├── html
├── .gitignore
├── src
│ ├── constants.js
│ ├── blank.png
│ ├── service
│ │ ├── webapi.js
│ │ ├── sqlite.js
│ │ └── gamelog.js
│ ├── security.js
│ ├── repository
│ │ ├── config.js
│ │ └── shared.js
│ ├── vr.scss
│ ├── app.dark.scss
│ └── app.scss
├── images
│ ├── base_status_off.png
│ ├── invalid_status.png
│ ├── other_status_off.png
│ ├── base_status_error.png
│ ├── base_status_ready.png
│ ├── headset_status_off.png
│ ├── other_status_error.png
│ ├── other_status_ready.png
│ ├── tracker_status_off.png
│ ├── base_status_ready_low.png
│ ├── base_status_searching.gif
│ ├── base_status_standby.png
│ ├── controller_status_off.png
│ ├── headset_status_error.png
│ ├── headset_status_ready.png
│ ├── other_status_standby.png
│ ├── tracker_status_ready.png
│ ├── base_status_ready_alert.png
│ ├── controller_status_error.png
│ ├── controller_status_ready.png
│ ├── headset_status_standby.png
│ ├── other_status_ready_low.png
│ ├── other_status_searching.gif
│ ├── tracker_status_standby.png
│ ├── controller_status_standby.png
│ ├── headset_status_ready_alert.png
│ ├── headset_status_ready_low.png
│ ├── headset_status_searching.gif
│ ├── other_status_ready_alert.png
│ ├── tracker_status_ready_alert.png
│ ├── tracker_status_ready_low.png
│ ├── tracker_status_searching.gif
│ ├── base_status_searching_alert.gif
│ ├── controller_status_ready_low.png
│ ├── controller_status_searching.gif
│ ├── other_status_searching_alert.gif
│ ├── controller_status_ready_alert.png
│ ├── headset_status_searching_alert.gif
│ ├── tracker_status_searching_alert.gif
│ └── controller_status_searching_alert.gif
├── package.json
├── .eslintrc.js
└── webpack.config.js
├── VRCX.ico
├── AssetBundleCacher
├── AssetBundleCacher_Data
│ ├── app.info
│ ├── data.unity3d
│ ├── Resources
│ │ └── unity default resources
│ ├── boot.config
│ └── il2cpp_data
│ │ ├── etc
│ │ └── mono
│ │ │ ├── browscap.ini
│ │ │ ├── 2.0
│ │ │ ├── Browsers
│ │ │ │ └── Compat.browser
│ │ │ ├── settings.map
│ │ │ └── web.config
│ │ │ ├── 4.0
│ │ │ ├── Browsers
│ │ │ │ └── Compat.browser
│ │ │ └── settings.map
│ │ │ ├── 4.5
│ │ │ ├── Browsers
│ │ │ │ └── Compat.browser
│ │ │ └── settings.map
│ │ │ └── config
│ │ ├── Metadata
│ │ └── global-metadata.dat
│ │ └── Resources
│ │ └── mscorlib.dll-resources.dat
├── GameAssembly.dll
├── AssetBundleCacher.exe
├── WinPixEventRuntime.dll
└── README.md
├── VRChatRPC
├── VRChatRPC.dll
└── README.txt
├── OpenVR
├── win32
│ └── openvr_api.dll
└── win64
│ └── openvr_api.dll
├── librsync.net
├── Blake2Sharp.dll
├── librsync.net.dll
└── README.md
├── make-junction.cmd
├── App.config
├── Properties
├── Settings.settings
├── Settings.Designer.cs
├── AssemblyInfo.cs
├── Resources.Designer.cs
└── Resources.resx
├── make-zip-7z.cmd
├── make-zip.cmd
├── NoopDragHandler.cs
├── WinApi.cs
├── Util.cs
├── .github
└── workflows
│ └── github_actions.yml
├── VRCX.sln
├── LICENSE
├── Program.cs
├── JsonSerializer.cs
├── VRChatRPC.cs
├── VRForm.cs
├── SharedVariable.cs
├── CefService.cs
├── CpuMonitor.cs
├── .gitattributes
├── VRCXStorage.cs
├── MainForm.Designer.cs
├── VRForm.Designer.cs
├── SQLite.cs
├── README.md
├── .gitignore
├── MainForm.cs
├── VRForm.resx
├── Discord.cs
├── MainForm.resx
├── OffScreenBrowser.cs
├── VRCX.csproj
└── WebApi.cs
/html/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
3 |
--------------------------------------------------------------------------------
/VRCX.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/VRCX.ico
--------------------------------------------------------------------------------
/html/src/constants.js:
--------------------------------------------------------------------------------
1 | export var appVersion = 'VRCX 2021.05.26.1';
2 |
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/app.info:
--------------------------------------------------------------------------------
1 | UnityTools
2 | AssetBundleCacher
--------------------------------------------------------------------------------
/html/src/blank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/src/blank.png
--------------------------------------------------------------------------------
/VRChatRPC/VRChatRPC.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/VRChatRPC/VRChatRPC.dll
--------------------------------------------------------------------------------
/OpenVR/win32/openvr_api.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/OpenVR/win32/openvr_api.dll
--------------------------------------------------------------------------------
/OpenVR/win64/openvr_api.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/OpenVR/win64/openvr_api.dll
--------------------------------------------------------------------------------
/VRChatRPC/README.txt:
--------------------------------------------------------------------------------
1 | it grabs some data from VRChat process.. use at own risk.
2 |
3 | by pypy (mina#5656)
--------------------------------------------------------------------------------
/librsync.net/Blake2Sharp.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/librsync.net/Blake2Sharp.dll
--------------------------------------------------------------------------------
/librsync.net/librsync.net.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/librsync.net/librsync.net.dll
--------------------------------------------------------------------------------
/html/images/base_status_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/base_status_off.png
--------------------------------------------------------------------------------
/html/images/invalid_status.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/invalid_status.png
--------------------------------------------------------------------------------
/html/images/other_status_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/other_status_off.png
--------------------------------------------------------------------------------
/AssetBundleCacher/GameAssembly.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/AssetBundleCacher/GameAssembly.dll
--------------------------------------------------------------------------------
/html/images/base_status_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/base_status_error.png
--------------------------------------------------------------------------------
/html/images/base_status_ready.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/base_status_ready.png
--------------------------------------------------------------------------------
/html/images/headset_status_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/headset_status_off.png
--------------------------------------------------------------------------------
/html/images/other_status_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/other_status_error.png
--------------------------------------------------------------------------------
/html/images/other_status_ready.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/other_status_ready.png
--------------------------------------------------------------------------------
/html/images/tracker_status_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/tracker_status_off.png
--------------------------------------------------------------------------------
/html/images/base_status_ready_low.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/base_status_ready_low.png
--------------------------------------------------------------------------------
/html/images/base_status_searching.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/base_status_searching.gif
--------------------------------------------------------------------------------
/html/images/base_status_standby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/base_status_standby.png
--------------------------------------------------------------------------------
/html/images/controller_status_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/controller_status_off.png
--------------------------------------------------------------------------------
/html/images/headset_status_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/headset_status_error.png
--------------------------------------------------------------------------------
/html/images/headset_status_ready.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/headset_status_ready.png
--------------------------------------------------------------------------------
/html/images/other_status_standby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/other_status_standby.png
--------------------------------------------------------------------------------
/html/images/tracker_status_ready.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/tracker_status_ready.png
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/AssetBundleCacher/AssetBundleCacher.exe
--------------------------------------------------------------------------------
/html/images/base_status_ready_alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/base_status_ready_alert.png
--------------------------------------------------------------------------------
/html/images/controller_status_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/controller_status_error.png
--------------------------------------------------------------------------------
/html/images/controller_status_ready.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/controller_status_ready.png
--------------------------------------------------------------------------------
/html/images/headset_status_standby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/headset_status_standby.png
--------------------------------------------------------------------------------
/html/images/other_status_ready_low.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/other_status_ready_low.png
--------------------------------------------------------------------------------
/html/images/other_status_searching.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/other_status_searching.gif
--------------------------------------------------------------------------------
/html/images/tracker_status_standby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/tracker_status_standby.png
--------------------------------------------------------------------------------
/AssetBundleCacher/WinPixEventRuntime.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/AssetBundleCacher/WinPixEventRuntime.dll
--------------------------------------------------------------------------------
/html/images/controller_status_standby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/controller_status_standby.png
--------------------------------------------------------------------------------
/html/images/headset_status_ready_alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/headset_status_ready_alert.png
--------------------------------------------------------------------------------
/html/images/headset_status_ready_low.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/headset_status_ready_low.png
--------------------------------------------------------------------------------
/html/images/headset_status_searching.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/headset_status_searching.gif
--------------------------------------------------------------------------------
/html/images/other_status_ready_alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/other_status_ready_alert.png
--------------------------------------------------------------------------------
/html/images/tracker_status_ready_alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/tracker_status_ready_alert.png
--------------------------------------------------------------------------------
/html/images/tracker_status_ready_low.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/tracker_status_ready_low.png
--------------------------------------------------------------------------------
/html/images/tracker_status_searching.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/tracker_status_searching.gif
--------------------------------------------------------------------------------
/html/images/base_status_searching_alert.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/base_status_searching_alert.gif
--------------------------------------------------------------------------------
/html/images/controller_status_ready_low.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/controller_status_ready_low.png
--------------------------------------------------------------------------------
/html/images/controller_status_searching.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/controller_status_searching.gif
--------------------------------------------------------------------------------
/html/images/other_status_searching_alert.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/other_status_searching_alert.gif
--------------------------------------------------------------------------------
/html/images/controller_status_ready_alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/controller_status_ready_alert.png
--------------------------------------------------------------------------------
/html/images/headset_status_searching_alert.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/headset_status_searching_alert.gif
--------------------------------------------------------------------------------
/html/images/tracker_status_searching_alert.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/tracker_status_searching_alert.gif
--------------------------------------------------------------------------------
/html/images/controller_status_searching_alert.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/html/images/controller_status_searching_alert.gif
--------------------------------------------------------------------------------
/make-junction.cmd:
--------------------------------------------------------------------------------
1 | mklink /J "%~dp0\bin\x64\Debug\html" "%~dp0\html\dist"
2 | mklink /J "%~dp0\bin\x64\Release\html" "%~dp0\html\dist"
3 | pause
4 |
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/data.unity3d:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/AssetBundleCacher/AssetBundleCacher_Data/data.unity3d
--------------------------------------------------------------------------------
/librsync.net/README.md:
--------------------------------------------------------------------------------
1 | # librsync.net
2 |
3 | Source code is available here: [https://github.com/braddodson/librsync.net](https://github.com/braddodson/librsync.net)
4 |
--------------------------------------------------------------------------------
/AssetBundleCacher/README.md:
--------------------------------------------------------------------------------
1 | # Asset Bundle Cacher
2 |
3 | Source code is available here: [https://github.com/ZettaiVR/AssetBundleCacher](https://github.com/ZettaiVR/AssetBundleCacher)
4 |
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/Resources/unity default resources:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/AssetBundleCacher/AssetBundleCacher_Data/Resources/unity default resources
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/boot.config:
--------------------------------------------------------------------------------
1 | gfx-enable-native-gfx-jobs=
2 | wait-for-native-debugger=0
3 | scripting-runtime-version=latest
4 | vr-enabled=0
5 | hdr-display-enabled=0
6 |
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/il2cpp_data/etc/mono/browscap.ini:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/AssetBundleCacher/AssetBundleCacher_Data/il2cpp_data/etc/mono/browscap.ini
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/il2cpp_data/Metadata/global-metadata.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/AssetBundleCacher/AssetBundleCacher_Data/il2cpp_data/Metadata/global-metadata.dat
--------------------------------------------------------------------------------
/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/il2cpp_data/Resources/mscorlib.dll-resources.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmfunc/VRCX/master/AssetBundleCacher/AssetBundleCacher_Data/il2cpp_data/Resources/mscorlib.dll-resources.dat
--------------------------------------------------------------------------------
/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/make-zip-7z.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 | for /f %%a in ('powershell -Command "Get-Date -format yyyyMMdd"') do set TODAY=%%a
4 | set ZIP_NAME=VRCX_%TODAY%.zip
5 | echo %ZIP_NAME%
6 | rem using 7-Zip (https://www.7-zip.org)
7 | cd "%~dp0\bin\x64\Release"
8 | "C:\Program Files\7-Zip\7z.exe" a -tzip %ZIP_NAME% * -mx=7 -xr0!cache -xr0!userdata -xr0!*.log -xr0!VRCX.json -xr0!VRCX.sqlite3
9 | cd "%~dp0"
10 | move "%~dp0\bin\x64\Release\%ZIP_NAME%" "%~dp0"
11 | pause
12 |
--------------------------------------------------------------------------------
/make-zip.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 | for /f %%a in ('powershell -Command "Get-Date -format yyyyMMdd"') do set TODAY=%%a
4 | set ZIP_NAME=VRCX_%TODAY%.zip
5 | echo %ZIP_NAME%
6 | rem using bandizip (https://www.bandisoft.com/bandizip)
7 | cd "%~dp0\bin\x64\Release"
8 | bz c -l:9 -r -storeroot:yes -ex:"cache;userdata;*.log;VRCX.json;VRCX.sqlite3" -cmt:"https://github.com/pypy-vrc/VRCX" %ZIP_NAME% *
9 | cd "%~dp0"
10 | move "%~dp0\bin\x64\Release\%ZIP_NAME%" "%~dp0"
11 | pause
12 |
--------------------------------------------------------------------------------
/html/src/service/webapi.js:
--------------------------------------------------------------------------------
1 | // requires binding of WebApi
2 |
3 | class WebApiService {
4 | clearCookies() {
5 | return WebApi.ClearCookies();
6 | }
7 |
8 | execute(options) {
9 | return new Promise((resolve, reject) => {
10 | WebApi.Execute(options, (err, response) => {
11 | if (err !== null) {
12 | reject(err);
13 | return;
14 | }
15 | resolve(response);
16 | });
17 | });
18 | }
19 | }
20 |
21 | var self = new WebApiService();
22 | window.webApiService = self;
23 |
24 | export {
25 | self as default,
26 | WebApiService
27 | };
28 |
--------------------------------------------------------------------------------
/NoopDragHandler.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) 2019 pypy. All rights reserved.
2 | //
3 | // This work is licensed under the terms of the MIT license.
4 | // For a copy, see .
5 |
6 | using System.Collections.Generic;
7 | using CefSharp;
8 | using CefSharp.Enums;
9 |
10 | namespace VRCX
11 | {
12 | public class NoopDragHandler : IDragHandler
13 | {
14 | bool IDragHandler.OnDragEnter(IWebBrowser chromiumWebBrowser, IBrowser browser, IDragData dragData, DragOperationsMask mask)
15 | {
16 | return true;
17 | }
18 |
19 | void IDragHandler.OnDraggableRegionsChanged(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IList regions)
20 | {
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/html/src/service/sqlite.js:
--------------------------------------------------------------------------------
1 | // requires binding of SQLite
2 |
3 | class SQLiteService {
4 | execute(callback, sql, args = null) {
5 | return new Promise((resolve, reject) => {
6 | SQLite.Execute((err, data) => {
7 | if (err !== null) {
8 | reject(err);
9 | } else if (data === null) {
10 | resolve();
11 | } else {
12 | callback(data);
13 | }
14 | }, sql, args);
15 | });
16 | }
17 |
18 | executeNonQuery(sql, args = null) {
19 | return SQLite.ExecuteNonQuery(sql, args);
20 | }
21 | }
22 |
23 | var self = new SQLiteService();
24 | window.sqliteService = self;
25 |
26 | export {
27 | self as default,
28 | SQLiteService
29 | };
30 |
--------------------------------------------------------------------------------
/WinApi.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) 2019 pypy. All rights reserved.
2 | //
3 | // This work is licensed under the terms of the MIT license.
4 | // For a copy, see .
5 |
6 | using System;
7 | using System.Runtime.InteropServices;
8 |
9 | namespace VRCX
10 | {
11 | public static class WinApi
12 | {
13 | [DllImport("kernel32.dll", SetLastError = false)]
14 | public static extern void CopyMemory(IntPtr destination, IntPtr source, uint length);
15 |
16 | [DllImport("user32.dll", SetLastError = true)]
17 | public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
18 |
19 | [DllImport("user32.dll", SetLastError = true)]
20 | public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Util.cs:
--------------------------------------------------------------------------------
1 | using CefSharp;
2 |
3 | namespace VRCX
4 | {
5 | public static class Util
6 | {
7 | public static void ApplyJavascriptBindings(IJavascriptObjectRepository repository)
8 | {
9 | repository.NameConverter = null;
10 | repository.Register("AppApi", AppApi.Instance, true);
11 | repository.Register("SharedVariable", SharedVariable.Instance, false);
12 | repository.Register("WebApi", WebApi.Instance, true);
13 | repository.Register("VRCXStorage", VRCXStorage.Instance, false);
14 | repository.Register("SQLite", SQLite.Instance, true);
15 | repository.Register("LogWatcher", LogWatcher.Instance, true);
16 | repository.Register("Discord", Discord.Instance, true);
17 | repository.Register("AssetBundleCacher", AssetBundleCacher.Instance, true);
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.github/workflows/github_actions.yml:
--------------------------------------------------------------------------------
1 | name: VRCX
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | build_dotnet:
13 | runs-on: windows-latest
14 |
15 | steps:
16 | - uses: actions/checkout@v2
17 | - name: Setup Nuget.exe
18 | uses: nuget/setup-nuget@v1
19 | - name: Restore packages
20 | run: nuget restore VRCX.sln
21 | - name: Setup MSBuild.exe
22 | uses: microsoft/setup-msbuild@v1.0.2
23 | - name: Build with MSBuild
24 | run: msbuild VRCX.sln -p:Configuration=Release -p:Platform=x64
25 |
26 | build_node:
27 | runs-on: ubuntu-latest
28 | defaults:
29 | run:
30 | working-directory: html
31 |
32 | steps:
33 | - uses: actions/checkout@v2
34 | - name: Use Node.js ${{ matrix.node-version }}
35 | uses: actions/setup-node@v1
36 | with:
37 | node-version: ${{ matrix.node-version }}
38 | - name: Restore dependencies
39 | run: npm ci
40 | - name: Build
41 | run: npm run production
42 |
--------------------------------------------------------------------------------
/VRCX.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.168
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VRCX", "VRCX.csproj", "{D9F66F2E-3ED9-4D53-A6AC-ADCC1513562A}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Release|x64 = Release|x64
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {D9F66F2E-3ED9-4D53-A6AC-ADCC1513562A}.Debug|x64.ActiveCfg = Debug|x64
15 | {D9F66F2E-3ED9-4D53-A6AC-ADCC1513562A}.Debug|x64.Build.0 = Debug|x64
16 | {D9F66F2E-3ED9-4D53-A6AC-ADCC1513562A}.Release|x64.ActiveCfg = Release|x64
17 | {D9F66F2E-3ED9-4D53-A6AC-ADCC1513562A}.Release|x64.Build.0 = Release|x64
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {797D384F-D118-4CBB-9450-17949F9EFCA4}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 pypy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace VRCX.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
6 | // 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
7 | // 이러한 특성 값을 변경하세요.
8 | [assembly: AssemblyTitle("VRCX")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("VRCX")]
13 | [assembly: AssemblyCopyright("pypy")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
18 | // 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
19 | // 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
20 | [assembly: ComVisible(false)]
21 |
22 | // 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
23 | [assembly: Guid("d9f66f2e-3ed9-4d53-a6ac-adcc1513562a")]
24 |
25 | // 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
26 | //
27 | // 주 버전
28 | // 부 버전
29 | // 빌드 번호
30 | // 수정 버전
31 | //
32 | // 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호가 자동으로
33 | // 지정되도록 할 수 있습니다.
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/html/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "dev": "webpack --config webpack.config.js --mode development",
5 | "watch": "webpack --config webpack.config.js --mode development --watch",
6 | "prod": "webpack --config webpack.config.js --mode production",
7 | "development": "npm run dev",
8 | "production": "npm run prod"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/pypy-vrc/VRCX.git"
13 | },
14 | "keywords": [
15 | "vrchat"
16 | ],
17 | "author": "pypy ",
18 | "license": "MIT",
19 | "bugs": {
20 | "url": "https://github.com/pypy-vrc/VRCX/issues"
21 | },
22 | "homepage": "https://github.com/pypy-vrc/VRCX#readme",
23 | "devDependencies": {
24 | "animate.css": "^4.1.1",
25 | "copy-webpack-plugin": "^9.0.0",
26 | "css-loader": "^5.2.6",
27 | "element-ui": "^2.15.2",
28 | "famfamfam-flags": "^1.0.0",
29 | "file-loader": "^6.2.0",
30 | "html-webpack-plugin": "^5.3.1",
31 | "mini-css-extract-plugin": "^1.6.0",
32 | "normalize.css": "^8.0.1",
33 | "noty": "^3.2.0-beta-deprecated",
34 | "pug": "^3.0.2",
35 | "pug-plain-loader": "^1.1.0",
36 | "raw-loader": "^4.0.2",
37 | "sass": "^1.35.1",
38 | "sass-loader": "^12.1.0",
39 | "terser-webpack-plugin": "^5.1.3",
40 | "url-loader": "^4.1.1",
41 | "vue": "^2.6.14",
42 | "vue-data-tables": "^3.4.5",
43 | "vue-lazyload": "^1.3.3",
44 | "vue-swatches": "^2.1.1",
45 | "vuejs-toggle-switch": "^1.3.3",
46 | "webpack": "^5.39.0",
47 | "webpack-cli": "^4.7.2"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/il2cpp_data/etc/mono/2.0/Browsers/Compat.browser:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/il2cpp_data/etc/mono/4.0/Browsers/Compat.browser:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/il2cpp_data/etc/mono/4.5/Browsers/Compat.browser:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) 2019 pypy. All rights reserved.
2 | //
3 | // This work is licensed under the terms of the MIT license.
4 | // For a copy, see .
5 |
6 | using System;
7 | using System.Windows.Forms;
8 |
9 | namespace VRCX
10 | {
11 | public class Program
12 | {
13 | public static string BaseDirectory { get; private set; }
14 |
15 | static Program()
16 | {
17 | BaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
18 | }
19 |
20 | [STAThread]
21 | private static void Main()
22 | {
23 | try
24 | {
25 | Run();
26 | }
27 | catch (Exception e)
28 | {
29 | MessageBox.Show(e.ToString(), "PLEASE REPORT TO PYPY", MessageBoxButtons.OK, MessageBoxIcon.Error);
30 | Environment.Exit(0);
31 | }
32 | }
33 |
34 | private static void Run()
35 | {
36 | Application.EnableVisualStyles();
37 | Application.SetCompatibleTextRenderingDefault(false);
38 |
39 | SQLite.Instance.Init();
40 | VRCXStorage.Load();
41 | CpuMonitor.Instance.Init();
42 | Discord.Instance.Init();
43 | WebApi.Instance.Init();
44 | LogWatcher.Instance.Init();
45 |
46 | CefService.Instance.Init();
47 | VRCXVR.Instance.Init();
48 | Application.Run(new MainForm());
49 | WebApi.Instance.SaveCookies();
50 | VRCXVR.Instance.Exit();
51 | CefService.Instance.Exit();
52 |
53 | LogWatcher.Instance.Exit();
54 | WebApi.Instance.Exit();
55 |
56 | Discord.Instance.Exit();
57 | CpuMonitor.Instance.Exit();
58 | VRCXStorage.Save();
59 | SQLite.Instance.Exit();
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/JsonSerializer.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) 2019 pypy. All rights reserved.
2 | //
3 | // This work is licensed under the terms of the MIT license.
4 | // For a copy, see .
5 |
6 | using Newtonsoft.Json;
7 | using System.IO;
8 | using System.Text;
9 |
10 | namespace VRCX
11 | {
12 | public static class JsonSerializer
13 | {
14 | public static void Serialize(string path, T obj)
15 | {
16 | try
17 | {
18 | using (var file = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
19 | using (var stream = new StreamWriter(file, Encoding.UTF8))
20 | using (var writer = new JsonTextWriter(stream))
21 | {
22 | var serializer = Newtonsoft.Json.JsonSerializer.CreateDefault();
23 | serializer.Formatting = Formatting.Indented;
24 | serializer.Serialize(writer, obj, typeof(T));
25 | }
26 | }
27 | catch
28 | {
29 | }
30 | }
31 |
32 | public static bool Deserialize(string path, ref T obj) where T : new()
33 | {
34 | try
35 | {
36 | using (var file = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
37 | using (var stream = new StreamReader(file, Encoding.UTF8))
38 | using (var reader = new JsonTextReader(stream))
39 | {
40 | var o = Newtonsoft.Json.JsonSerializer.CreateDefault().Deserialize(reader);
41 | if (o == null)
42 | {
43 | o = new T();
44 | }
45 | obj = o;
46 | return true;
47 | }
48 | }
49 | catch
50 | {
51 | }
52 | return false;
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/VRChatRPC.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) 2019 pypy. All rights reserved.
2 | //
3 | // This work is licensed under the terms of the MIT license.
4 | // For a copy, see .
5 |
6 | using System;
7 | using System.Runtime.InteropServices;
8 | using System.Text;
9 |
10 | namespace VRCX
11 | {
12 | public class VRChatRPC
13 | {
14 | public static readonly VRChatRPC Instance;
15 |
16 | [DllImport("VRChatRPC", CallingConvention = CallingConvention.Cdecl)]
17 | private static extern bool VRChatRPC_000();
18 |
19 | [DllImport("VRChatRPC", CallingConvention = CallingConvention.Cdecl)]
20 | private static extern int VRChatRPC_001([Out] byte[] data, int size);
21 |
22 | [DllImport("VRChatRPC", CallingConvention = CallingConvention.Cdecl)]
23 | private static extern IntPtr VRChatRPC_002();
24 |
25 | static VRChatRPC()
26 | {
27 | Instance = new VRChatRPC();
28 | }
29 |
30 | public bool Update()
31 | {
32 | return VRChatRPC_000();
33 | }
34 |
35 | public string GetAuthSessionTicket()
36 | {
37 | var a = new byte[1024];
38 | var n = VRChatRPC_001(a, 1024);
39 | return BitConverter.ToString(a, 0, n).Replace("-", string.Empty);
40 | }
41 |
42 | public string GetPersonaName()
43 | {
44 | var ptr = VRChatRPC_002();
45 | if (ptr != IntPtr.Zero)
46 | {
47 | int n = 0;
48 | while (Marshal.ReadByte(ptr, n) != 0)
49 | {
50 | ++n;
51 | }
52 | if (n > 0)
53 | {
54 | var a = new byte[n];
55 | Marshal.Copy(ptr, a, 0, a.Length);
56 | return Encoding.UTF8.GetString(a);
57 | }
58 | }
59 | return string.Empty;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/html/src/security.js:
--------------------------------------------------------------------------------
1 | const defaultAESKey = new TextEncoder().encode(
2 | 'https://github.com/pypy-vrc/VRCX'
3 | )
4 |
5 | const hexToUint8Array = (hexStr) => {
6 | const r = hexStr.match(/.{1,2}/g)
7 | if (!r) return null
8 | return new Uint8Array(r.map((b) => parseInt(b, 16)))
9 | }
10 |
11 | const uint8ArrayToHex = (arr) =>
12 | arr.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '')
13 |
14 | function stdAESKey(key) {
15 | const tKey = new TextEncoder().encode(key)
16 | let sk = tKey
17 | if (key.length < 32) {
18 | sk = new Uint8Array(32)
19 | sk.set(tKey)
20 | sk.set(defaultAESKey.slice(key.length, 32), key.length)
21 | }
22 | return sk.slice(0, 32)
23 | }
24 |
25 | async function encrypt(plaintext, key) {
26 | let iv = window.crypto.getRandomValues(new Uint8Array(12))
27 | let sharedKey = await window.crypto.subtle.importKey(
28 | 'raw',
29 | stdAESKey(key),
30 | { name: 'AES-GCM', length: 256 },
31 | true,
32 | ['encrypt']
33 | )
34 | let cipher = await window.crypto.subtle.encrypt(
35 | { name: 'AES-GCM', iv },
36 | sharedKey,
37 | new TextEncoder().encode(plaintext)
38 | )
39 | let ciphertext = new Uint8Array(cipher)
40 | let encrypted = new Uint8Array(iv.length + ciphertext.byteLength)
41 | encrypted.set(iv, 0)
42 | encrypted.set(ciphertext, iv.length)
43 | return uint8ArrayToHex(encrypted)
44 | }
45 |
46 | async function decrypt(ciphertext, key) {
47 | let text = hexToUint8Array(ciphertext)
48 | if (!text) return ''
49 | let sharedKey = await window.crypto.subtle.importKey(
50 | 'raw',
51 | stdAESKey(key),
52 | { name: 'AES-GCM', length: 256 },
53 | true,
54 | ['decrypt']
55 | )
56 | let plaintext = await window.crypto.subtle.decrypt(
57 | { name: 'AES-GCM', iv: text.slice(0, 12) },
58 | sharedKey,
59 | text.slice(12)
60 | )
61 | return new TextDecoder().decode(new Uint8Array(plaintext))
62 | }
63 |
64 | export default {
65 | decrypt,
66 | encrypt,
67 | }
68 |
--------------------------------------------------------------------------------
/VRForm.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) 2019 pypy. All rights reserved.
2 | //
3 | // This work is licensed under the terms of the MIT license.
4 | // For a copy, see .
5 |
6 | using System.IO;
7 | using System.Windows.Forms;
8 | using CefSharp;
9 | using CefSharp.WinForms;
10 |
11 | namespace VRCX
12 | {
13 | public partial class VRForm : Form
14 | {
15 | public static VRForm Instance;
16 | private ChromiumWebBrowser _browser1;
17 | private ChromiumWebBrowser _browser2;
18 |
19 | public VRForm()
20 | {
21 | Instance = this;
22 | InitializeComponent();
23 |
24 | _browser1 = new ChromiumWebBrowser(
25 | Path.Combine(Program.BaseDirectory, "html/vr.html?1")
26 | )
27 | {
28 | DragHandler = new NoopDragHandler(),
29 | BrowserSettings =
30 | {
31 | DefaultEncoding = "UTF-8",
32 | },
33 | Dock = DockStyle.Fill
34 | };
35 |
36 | _browser2 = new ChromiumWebBrowser(
37 | Path.Combine(Program.BaseDirectory, "html/vr.html?2")
38 | )
39 | {
40 | DragHandler = new NoopDragHandler(),
41 | BrowserSettings =
42 | {
43 | DefaultEncoding = "UTF-8",
44 | },
45 | Dock = DockStyle.Fill
46 | };
47 |
48 | Util.ApplyJavascriptBindings(_browser1.JavascriptObjectRepository);
49 | Util.ApplyJavascriptBindings(_browser2.JavascriptObjectRepository);
50 |
51 | panel1.Controls.Add(_browser1);
52 | panel2.Controls.Add(_browser2);
53 | }
54 |
55 | private void button_refresh_Click(object sender, System.EventArgs e)
56 | {
57 | _browser1.ExecuteScriptAsync("location.reload()");
58 | _browser2.ExecuteScriptAsync("location.reload()");
59 | VRCXVR.Instance.Refresh();
60 | }
61 |
62 | private void button_devtools_Click(object sender, System.EventArgs e)
63 | {
64 | _browser1.ShowDevTools();
65 | _browser2.ShowDevTools();
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/SharedVariable.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) 2020 pypy. All rights reserved.
2 | //
3 | // This work is licensed under the terms of the MIT license.
4 | // For a copy, see .
5 |
6 | using System.Collections.Generic;
7 | using System.Threading;
8 |
9 | namespace VRCX
10 | {
11 | public class SharedVariable
12 | {
13 | public static readonly SharedVariable Instance;
14 | private readonly ReaderWriterLockSlim m_MapLock;
15 | private readonly Dictionary m_Map;
16 |
17 | static SharedVariable()
18 | {
19 | Instance = new SharedVariable();
20 | }
21 |
22 | public SharedVariable()
23 | {
24 | m_MapLock = new ReaderWriterLockSlim();
25 | m_Map = new Dictionary();
26 | }
27 |
28 | public void Clear()
29 | {
30 | m_MapLock.EnterWriteLock();
31 | try
32 | {
33 | m_Map.Clear();
34 | }
35 | finally
36 | {
37 | m_MapLock.ExitWriteLock();
38 | }
39 | }
40 |
41 | public string Get(string key)
42 | {
43 | m_MapLock.EnterReadLock();
44 | try
45 | {
46 | if (m_Map.TryGetValue(key, out string value) == true)
47 | {
48 | return value;
49 | }
50 | }
51 | finally
52 | {
53 | m_MapLock.ExitReadLock();
54 | }
55 |
56 | return null;
57 | }
58 |
59 | public void Set(string key, string value)
60 | {
61 | m_MapLock.EnterWriteLock();
62 | try
63 | {
64 | m_Map[key] = value;
65 | }
66 | finally
67 | {
68 | m_MapLock.ExitWriteLock();
69 | }
70 | }
71 |
72 | public bool Remove(string key)
73 | {
74 | m_MapLock.EnterWriteLock();
75 | try
76 | {
77 | return m_Map.Remove(key);
78 | }
79 | finally
80 | {
81 | m_MapLock.ExitWriteLock();
82 | }
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/CefService.cs:
--------------------------------------------------------------------------------
1 | using CefSharp;
2 | using CefSharp.WinForms;
3 | using System;
4 | using System.IO;
5 |
6 | namespace VRCX
7 | {
8 | public class CefService
9 | {
10 | public static readonly CefService Instance;
11 |
12 | static CefService()
13 | {
14 | Instance = new CefService();
15 | }
16 |
17 | internal void Init()
18 | {
19 | var cefSettings = new CefSettings
20 | {
21 | CachePath = Path.Combine(Program.BaseDirectory, "cache"),
22 | UserDataPath = Path.Combine(Program.BaseDirectory, "userdata"),
23 | IgnoreCertificateErrors = true,
24 | LogSeverity = LogSeverity.Disable,
25 | WindowlessRenderingEnabled = true,
26 | PersistSessionCookies = true,
27 | PersistUserPreferences = true
28 | };
29 |
30 | /*cefSettings.RegisterScheme(new CefCustomScheme
31 | {
32 | SchemeName = "vrcx",
33 | DomainName = "app",
34 | SchemeHandlerFactory = new FolderSchemeHandlerFactory(Application.StartupPath + "/../../../html")
35 | });*/
36 |
37 | cefSettings.CefCommandLineArgs.Add("ignore-certificate-errors");
38 | cefSettings.CefCommandLineArgs.Add("disable-plugins");
39 | cefSettings.CefCommandLineArgs.Add("disable-spell-checking");
40 | cefSettings.CefCommandLineArgs.Add("disable-pdf-extension");
41 | cefSettings.CefCommandLineArgs.Add("disable-extensions");
42 | cefSettings.CefCommandLineArgs["autoplay-policy"] = "no-user-gesture-required";
43 | // cefSettings.CefCommandLineArgs.Add("allow-universal-access-from-files");
44 | cefSettings.CefCommandLineArgs.Add("disable-web-security");
45 | cefSettings.SetOffScreenRenderingBestPerformanceArgs();
46 |
47 | CefSharpSettings.WcfEnabled = true; // TOOD: REMOVE THIS LINE YO
48 | CefSharpSettings.ShutdownOnExit = false;
49 |
50 | // Enable High-DPI support on Windows 7 or newer
51 | Cef.EnableHighDPISupport();
52 |
53 | if (Cef.Initialize(cefSettings) == false)
54 | {
55 | throw new Exception("Cef.Initialize()");
56 | }
57 | }
58 |
59 | internal void Exit()
60 | {
61 | Cef.Shutdown();
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/CpuMonitor.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) 2019 pypy. All rights reserved.
2 | //
3 | // This work is licensed under the terms of the MIT license.
4 | // For a copy, see .
5 |
6 | using System.Diagnostics;
7 | using System.Threading;
8 |
9 | namespace VRCX
10 | {
11 | public class CpuMonitor
12 | {
13 | public static readonly CpuMonitor Instance;
14 | public float CpuUsage;
15 | private PerformanceCounter _performanceCounter;
16 | private Timer _timer;
17 |
18 | static CpuMonitor()
19 | {
20 | Instance = new CpuMonitor();
21 | }
22 |
23 | public CpuMonitor()
24 | {
25 | try
26 | {
27 | _performanceCounter = new PerformanceCounter(
28 | "Processor Information",
29 | "% Processor Utility",
30 | "_Total",
31 | true
32 | );
33 | }
34 | catch
35 | {
36 | }
37 |
38 | // fallback
39 | if (_performanceCounter == null)
40 | {
41 | try
42 | {
43 | _performanceCounter = new PerformanceCounter(
44 | "Processor",
45 | "% Processor Time",
46 | "_Total",
47 | true
48 | );
49 | }
50 | catch
51 | {
52 | }
53 | }
54 |
55 | _timer = new Timer(TimerCallback, null, -1, -1);
56 | }
57 |
58 | internal void Init()
59 | {
60 | _timer.Change(1000, 1000);
61 | }
62 |
63 | internal void Exit()
64 | {
65 | lock (this)
66 | {
67 | _timer.Change(-1, -1);
68 | _performanceCounter?.Dispose();
69 | }
70 | }
71 |
72 | private void TimerCallback(object state)
73 | {
74 | lock (this)
75 | {
76 | try
77 | {
78 | if (_performanceCounter != null)
79 | {
80 | CpuUsage = _performanceCounter.NextValue();
81 | }
82 | }
83 | catch
84 | {
85 | }
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/html/src/service/gamelog.js:
--------------------------------------------------------------------------------
1 | // requires binding of LogWatcher
2 |
3 | //
4 | var contextMap = new Map();
5 |
6 | function parseRawGameLog(dt, type, args) {
7 | var gameLog = {
8 | dt,
9 | type
10 | };
11 |
12 | switch (type) {
13 | case 'location':
14 | gameLog.location = args[0];
15 | gameLog.worldName = args[1];
16 | break;
17 |
18 | case 'player-joined':
19 | gameLog.userDisplayName = args[0];
20 | gameLog.userType = args[1];
21 | break;
22 |
23 | case 'player-left':
24 | gameLog.userDisplayName = args[0];
25 | break;
26 |
27 | case 'notification':
28 | gameLog.json = args[0];
29 | break;
30 |
31 | case 'portal-spawn':
32 | gameLog.userDisplayName = args[0];
33 | break;
34 |
35 | case 'event':
36 | gameLog.event = args[0];
37 | break;
38 |
39 | case 'video-play':
40 | gameLog.videoURL = args[0];
41 | gameLog.displayName = args[1];
42 | break;
43 |
44 | default:
45 | break;
46 | }
47 |
48 | return gameLog;
49 | }
50 |
51 | class GameLogService {
52 | async poll() {
53 | var rawGameLogs = await LogWatcher.Get();
54 | var gameLogs = [];
55 | var now = Date.now();
56 |
57 | for (var [fileName, dt, type, ...args] of rawGameLogs) {
58 | var context = contextMap.get(fileName);
59 | if (typeof context === 'undefined') {
60 | context = {
61 | updatedAt: null,
62 |
63 | // location
64 | location: null
65 | };
66 | contextMap.set(fileName, context);
67 | }
68 |
69 | var gameLog = parseRawGameLog(dt, type, args);
70 |
71 | switch (gameLog.type) {
72 | case 'location':
73 | context.location = gameLog.location;
74 | break;
75 |
76 | default:
77 | break;
78 | }
79 |
80 | context.updatedAt = now;
81 |
82 | gameLogs.push(gameLog);
83 | }
84 |
85 | return gameLogs;
86 | }
87 |
88 | async reset() {
89 | await LogWatcher.Reset();
90 | contextMap.clear();
91 | }
92 | }
93 |
94 | var self = new GameLogService();
95 | window.gameLogService = self;
96 |
97 | export {
98 | self as default,
99 | GameLogService as LogWatcherService
100 | };
101 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/html/src/repository/config.js:
--------------------------------------------------------------------------------
1 | import sqliteService from '../service/sqlite.js';
2 | import sharedRepository, { SharedRepository } from './shared.js';
3 |
4 | var dirtyKeySet = new Set();
5 |
6 | function transformKey(key) {
7 | return `config:${String(key).toLowerCase()}`;
8 | }
9 |
10 | async function syncLoop() {
11 | if (dirtyKeySet.size > 0) {
12 | try {
13 | await sqliteService.executeNonQuery('BEGIN');
14 | try {
15 | for (var key of dirtyKeySet) {
16 | var value = sharedRepository.getString(key);
17 | if (value === null) {
18 | await sqliteService.executeNonQuery(
19 | 'DELETE FROM configs WHERE `key` = @key',
20 | {
21 | '@key': key
22 | }
23 | );
24 | } else {
25 | await sqliteService.executeNonQuery(
26 | 'INSERT OR REPLACE INTO configs (`key`, `value`) VALUES (@key, @value)',
27 | {
28 | '@key': key,
29 | '@value': value
30 | }
31 | );
32 | }
33 | }
34 | dirtyKeySet.clear();
35 | } finally {
36 | await sqliteService.executeNonQuery('COMMIT');
37 | }
38 | } catch (err) {
39 | console.error(err);
40 | }
41 | }
42 | setTimeout(syncLoop, 100);
43 | }
44 |
45 | class ConfigRepository extends SharedRepository {
46 | async init() {
47 | await sqliteService.executeNonQuery(
48 | 'CREATE TABLE IF NOT EXISTS configs (`key` TEXT PRIMARY KEY, `value` TEXT)'
49 | );
50 | await sqliteService.execute(
51 | ([key, value]) => sharedRepository.setString(key, value),
52 | 'SELECT `key`, `value` FROM configs'
53 | );
54 | syncLoop();
55 | }
56 |
57 | remove(key) {
58 | key = transformKey(key);
59 | sharedRepository.remove(key);
60 | dirtyKeySet.add(key);
61 | }
62 |
63 | getString(key, defaultValue = null) {
64 | key = transformKey(key);
65 | return sharedRepository.getString(key, defaultValue);
66 | }
67 |
68 | setString(key, value) {
69 | key = transformKey(key);
70 | value = String(value);
71 | sharedRepository.setString(key, value);
72 | dirtyKeySet.add(key);
73 | }
74 | }
75 |
76 | var self = new ConfigRepository();
77 | window.configRepository = self;
78 |
79 | export {
80 | self as default,
81 | ConfigRepository
82 | };
83 |
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/il2cpp_data/etc/mono/2.0/settings.map:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 |
26 |
48 |
49 |
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/il2cpp_data/etc/mono/4.0/settings.map:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 |
26 |
48 |
49 |
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/il2cpp_data/etc/mono/4.5/settings.map:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 |
26 |
48 |
49 |
--------------------------------------------------------------------------------
/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace VRCX.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VRCX.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/html/src/repository/shared.js:
--------------------------------------------------------------------------------
1 | // requires binding of SharedVariable
2 |
3 | function transformKey(key) {
4 | return String(key).toLowerCase();
5 | }
6 |
7 | class SharedRepository {
8 | remove(key) {
9 | key = transformKey(key);
10 | return SharedVariable.Remove(key);
11 | }
12 |
13 | getString(key, defaultValue = null) {
14 | key = transformKey(key);
15 | var value = SharedVariable.Get(key);
16 | if (value === null) {
17 | return defaultValue;
18 | }
19 | return value;
20 | }
21 |
22 | setString(key, value) {
23 | key = transformKey(key);
24 | value = String(value);
25 | SharedVariable.Set(key, value);
26 | }
27 |
28 | getBool(key, defaultValue = null) {
29 | var value = this.getString(key, null);
30 | if (value === null) {
31 | return defaultValue;
32 | }
33 | return value === 'true';
34 | }
35 |
36 | setBool(key, value) {
37 | this.setString(key, value ? 'true' : 'false');
38 | }
39 |
40 | getInt(key, defaultValue = null) {
41 | var value = this.getString(key, null);
42 | if (value === null) {
43 | return defaultValue;
44 | }
45 | value = parseInt(value, 10);
46 | if (isNaN(value) === true) {
47 | return defaultValue;
48 | }
49 | return value;
50 | }
51 |
52 | setInt(key, value) {
53 | this.setString(key, value);
54 | }
55 |
56 | getFloat(key, defaultValue = null) {
57 | var value = this.getString(key, null);
58 | if (value === null) {
59 | return defaultValue;
60 | }
61 | value = parseFloat(value);
62 | if (isNaN(value) === true) {
63 | return defaultValue;
64 | }
65 | return value;
66 | }
67 |
68 | setFloat(key, value) {
69 | this.setString(key, value);
70 | }
71 |
72 | getObject(key, defaultValue = null) {
73 | var value = this.getString(key, null);
74 | if (value === null) {
75 | return defaultValue;
76 | }
77 | try {
78 | value = JSON.parse(value);
79 | } catch (err) {
80 | }
81 | if (value !== Object(value)) {
82 | return defaultValue;
83 | }
84 | return value;
85 | }
86 |
87 | setObject(key, value) {
88 | this.setString(key, JSON.stringify(value));
89 | }
90 |
91 | getArray(key, defaultValue = null) {
92 | var value = this.getObject(key, null);
93 | if (Array.isArray(value) === false) {
94 | return defaultValue;
95 | }
96 | return value;
97 | }
98 |
99 | setArray(key, value) {
100 | this.setObject(key, value);
101 | }
102 | }
103 |
104 | var self = new SharedRepository();
105 | window.sharedRepository = self;
106 |
107 | export {
108 | self as default,
109 | SharedRepository
110 | };
111 |
--------------------------------------------------------------------------------
/html/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | browser: true,
5 | commonjs: true,
6 | es2020: true
7 | },
8 | parserOptions: {
9 | sourceType: 'module',
10 | impliedStrict: true
11 | },
12 | globals: {
13 | CefSharp: 'readonly',
14 | VRCX: 'readonly',
15 | VRCXStorage: 'readonly',
16 | SQLite: 'readonly',
17 | LogWatcher: 'readonly',
18 | Discord: 'readonly',
19 | AppApi: 'readonly',
20 | SharedVariable: 'readonly',
21 | WebApi: 'readonly'
22 | },
23 | extends: 'eslint:all',
24 | rules: {
25 | 'array-bracket-newline': 0,
26 | 'array-element-newline': 0,
27 | 'block-scoped-var': 0,
28 | camelcase: 0,
29 | 'capitalized-comments': 0,
30 | 'class-methods-use-this': 0,
31 | complexity: 0,
32 | 'func-names': 0,
33 | 'func-style': 0,
34 | 'function-call-argument-newline': 0,
35 | 'guard-for-in': 0,
36 | 'id-length': 0,
37 | indent: 0,
38 | 'linebreak-style': 0,
39 | 'lines-around-comment': 0,
40 | 'max-depth': 0,
41 | 'max-len': 0,
42 | 'max-lines': 0,
43 | 'max-lines-per-function': 0,
44 | 'max-statements': 0,
45 | 'multiline-comment-style': 0,
46 | 'multiline-ternary': 0,
47 | 'newline-per-chained-call': 0,
48 | 'new-cap': 0,
49 | 'no-await-in-loop': 0,
50 | 'no-bitwise': 0,
51 | 'no-console': 0,
52 | 'no-continue': 0,
53 | 'no-control-regex': 0,
54 | 'no-empty': [
55 | 'error',
56 | {
57 | allowEmptyCatch: true
58 | }
59 | ],
60 | 'no-extra-parens': 0,
61 | 'no-invalid-this': 0,
62 | 'no-magic-numbers': 0,
63 | 'no-mixed-operators': 0,
64 | 'no-negated-condition': 0,
65 | 'no-param-reassign': 0,
66 | 'no-plusplus': 0,
67 | 'no-redeclare': 0,
68 | 'no-ternary': 0,
69 | 'no-underscore-dangle': 0,
70 | 'no-var': 0,
71 | 'no-warning-comments': 0,
72 | 'object-curly-spacing': [
73 | 'error',
74 | 'always'
75 | ],
76 | 'object-property-newline': 0,
77 | 'one-var': 0,
78 | 'padded-blocks': 0,
79 | 'prefer-arrow-callback': 0,
80 | 'prefer-destructuring': 0,
81 | 'prefer-named-capture-group': 0,
82 | quotes: [
83 | 'error',
84 | 'single',
85 | {
86 | avoidEscape: true
87 | }
88 | ],
89 | 'quote-props': 0,
90 | 'require-unicode-regexp': 0,
91 | 'sort-imports': 0,
92 | 'sort-keys': 0,
93 | 'sort-vars': 0,
94 | 'space-before-function-paren': [
95 | 'error',
96 | {
97 | named: 'never'
98 | }
99 | ],
100 | strict: 0,
101 | 'vars-on-top': 0,
102 | 'wrap-regex': 0
103 | }
104 | };
105 |
--------------------------------------------------------------------------------
/AssetBundleCacher/AssetBundleCacher_Data/il2cpp_data/etc/mono/config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/VRCXStorage.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) 2019 pypy. All rights reserved.
2 | //
3 | // This work is licensed under the terms of the MIT license.
4 | // For a copy, see .
5 |
6 | using System;
7 | using System.Collections.Generic;
8 | using System.IO;
9 | using System.Threading;
10 |
11 | namespace VRCX
12 | {
13 | public class VRCXStorage
14 | {
15 | public static readonly VRCXStorage Instance;
16 | private static readonly ReaderWriterLockSlim m_Lock = new ReaderWriterLockSlim();
17 | private static Dictionary m_Storage = new Dictionary();
18 | private static string m_JsonPath = Path.Combine(Program.BaseDirectory, "VRCX.json");
19 | private static bool m_Dirty;
20 |
21 | static VRCXStorage()
22 | {
23 | Instance = new VRCXStorage();
24 | }
25 |
26 | public static void Load()
27 | {
28 | m_Lock.EnterWriteLock();
29 | try
30 | {
31 | JsonSerializer.Deserialize(m_JsonPath, ref m_Storage);
32 | m_Dirty = false;
33 | }
34 | finally
35 | {
36 | m_Lock.ExitWriteLock();
37 | }
38 | }
39 |
40 | public static void Save()
41 | {
42 | m_Lock.EnterReadLock();
43 | try
44 | {
45 | if (m_Dirty)
46 | {
47 | JsonSerializer.Serialize(m_JsonPath, m_Storage);
48 | m_Dirty = false;
49 | }
50 | }
51 | finally
52 | {
53 | m_Lock.ExitReadLock();
54 | }
55 | }
56 |
57 | public void Flush()
58 | {
59 | Save();
60 | }
61 |
62 | public void Clear()
63 | {
64 | m_Lock.EnterWriteLock();
65 | try
66 | {
67 | if (m_Storage.Count > 0)
68 | {
69 | m_Storage.Clear();
70 | m_Dirty = true;
71 | }
72 | }
73 | finally
74 | {
75 | m_Lock.ExitWriteLock();
76 | }
77 | }
78 |
79 | public bool Remove(string key)
80 | {
81 | m_Lock.EnterWriteLock();
82 | try
83 | {
84 | var result = m_Storage.Remove(key);
85 | if (result)
86 | {
87 | m_Dirty = true;
88 | }
89 | return result;
90 | }
91 | finally
92 | {
93 | m_Lock.ExitWriteLock();
94 | }
95 | }
96 |
97 | public string Get(string key)
98 | {
99 | m_Lock.EnterReadLock();
100 | try
101 | {
102 | return m_Storage.TryGetValue(key, out string value)
103 | ? value
104 | : string.Empty;
105 | }
106 | finally
107 | {
108 | m_Lock.ExitReadLock();
109 | }
110 | }
111 |
112 | public void Set(string key, string value)
113 | {
114 | m_Lock.EnterWriteLock();
115 | try
116 | {
117 | m_Storage[key] = value;
118 | m_Dirty = true;
119 | }
120 | finally
121 | {
122 | m_Lock.ExitWriteLock();
123 | }
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/html/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const CopyPlugin = require('copy-webpack-plugin');
3 | const HtmlWebpackPlugin = require('html-webpack-plugin');
4 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
5 | const TerserPlugin = require('terser-webpack-plugin');
6 |
7 | module.exports = {
8 | entry: {
9 | app: [
10 | './src/app.js',
11 | './src/app.scss'
12 | ],
13 | 'app.dark': './src/app.dark.scss',
14 | vr: [
15 | './src/vr.js',
16 | './src/vr.scss'
17 | ]
18 | },
19 | output: {
20 | filename: '[name].js',
21 | library: {
22 | type: 'window'
23 | }
24 | },
25 | module: {
26 | rules: [
27 | {
28 | test: /\.pug$/,
29 | oneOf: [
30 | {
31 | resourceQuery: /^\?vue/,
32 | use: 'pug-plain-loader'
33 | },
34 | {
35 | use: ['raw-loader', 'pug-plain-loader']
36 | }
37 | ]
38 | },
39 | {
40 | test: /\.s?css$/,
41 | use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
42 | },
43 | {
44 | test: /\.(eot|png|svg|ttf|woff)/,
45 | use: {
46 | loader: 'url-loader',
47 | options: {
48 | limit: false,
49 | name: 'assets/[name].[ext]'
50 | }
51 | }
52 | }
53 | ]
54 | },
55 | resolve: {
56 | extensions: ['.css', '.js', '.scss'],
57 | alias: {
58 | vue: path.join(
59 | __dirname,
60 | './node_modules/vue/dist/vue.common.prod.js'
61 | )
62 | }
63 | },
64 | performance: {
65 | hints: false
66 | },
67 | devtool: 'inline-source-map',
68 | target: ['web', 'es2020'],
69 | stats: {
70 | preset: 'errors-only',
71 | builtAt: true,
72 | timings: true
73 | },
74 | plugins: [
75 | new MiniCssExtractPlugin({
76 | filename: '[name].css'
77 | }),
78 | new HtmlWebpackPlugin({
79 | filename: 'index.html',
80 | template: './src/index.pug',
81 | inject: false,
82 | minify: false
83 | }),
84 | new HtmlWebpackPlugin({
85 | filename: 'vr.html',
86 | template: './src/vr.pug',
87 | inject: false,
88 | minify: false
89 | }),
90 | new CopyPlugin({
91 | patterns: [
92 | // assets
93 | {
94 | from: './images/',
95 | to: './images/'
96 | },
97 | // // vscode-codicons
98 | // {
99 | // from: './node_modules/vscode-codicons/dist/codicon.css',
100 | // to: 'vendor/vscode-codicons/'
101 | // },
102 | // {
103 | // from: './node_modules/vscode-codicons/dist/codicon.ttf',
104 | // to: 'vendor/vscode-codicons/'
105 | // },
106 | // // fontawesome
107 | // {
108 | // from: './node_modules/@fortawesome/fontawesome-free/webfonts/',
109 | // to: 'vendor/fontawesome/webfonts/'
110 | // },
111 | // {
112 | // from: './node_modules/@fortawesome/fontawesome-free/css/all.min.css',
113 | // to: 'vendor/fontawesome/css/'
114 | // },
115 | // // element-plus
116 | // {
117 | // from: './node_modules/element-plus/lib/theme-chalk/fonts/',
118 | // to: 'vendor/element-plus/lib/theme-chalk/fonts/'
119 | // },
120 | // {
121 | // from: './node_modules/element-plus/lib/theme-chalk/index.css',
122 | // to: 'vendor/element-plus/lib/theme-chalk/'
123 | // }
124 | ]
125 | })
126 | ],
127 | optimization: {
128 | minimizer: [
129 | new TerserPlugin({
130 | extractComments: false
131 | })
132 | ]
133 | }
134 | };
135 |
--------------------------------------------------------------------------------
/MainForm.Designer.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) 2019 pypy. All rights reserved.
2 | //
3 | // This work is licensed under the terms of the MIT license.
4 | // For a copy, see .
5 |
6 | namespace VRCX
7 | {
8 | partial class MainForm
9 | {
10 | ///
11 | /// 필수 디자이너 변수입니다.
12 | ///
13 | private System.ComponentModel.IContainer components = null;
14 |
15 | ///
16 | /// 사용 중인 모든 리소스를 정리합니다.
17 | ///
18 | /// 관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.
19 | protected override void Dispose(bool disposing)
20 | {
21 | if (disposing && (components != null))
22 | {
23 | components.Dispose();
24 | }
25 | base.Dispose(disposing);
26 | }
27 |
28 | #region Windows Form 디자이너에서 생성한 코드
29 |
30 | ///
31 | /// 디자이너 지원에 필요한 메서드입니다.
32 | /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
33 | ///
34 | private void InitializeComponent()
35 | {
36 | this.components = new System.ComponentModel.Container();
37 | this.TrayMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
38 | this.TrayMenu_Open = new System.Windows.Forms.ToolStripMenuItem();
39 | this.TrayMenu_Separator = new System.Windows.Forms.ToolStripSeparator();
40 | this.TrayMenu_Quit = new System.Windows.Forms.ToolStripMenuItem();
41 | this.TrayIcon = new System.Windows.Forms.NotifyIcon(this.components);
42 | this.TrayMenu.SuspendLayout();
43 | this.SuspendLayout();
44 | //
45 | // TrayMenu
46 | //
47 | this.TrayMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
48 | this.TrayMenu_Open,
49 | this.TrayMenu_Separator,
50 | this.TrayMenu_Quit});
51 | this.TrayMenu.Name = "TrayMenu";
52 | this.TrayMenu.Size = new System.Drawing.Size(132, 54);
53 | //
54 | // TrayMenu_Open
55 | //
56 | this.TrayMenu_Open.Name = "TrayMenu_Open";
57 | this.TrayMenu_Open.Size = new System.Drawing.Size(131, 22);
58 | this.TrayMenu_Open.Text = "Open";
59 | this.TrayMenu_Open.Click += new System.EventHandler(this.TrayMenu_Open_Click);
60 | //
61 | // TrayMenu_Separator
62 | //
63 | this.TrayMenu_Separator.Name = "TrayMenu_Separator";
64 | this.TrayMenu_Separator.Size = new System.Drawing.Size(128, 6);
65 | //
66 | // TrayMenu_Quit
67 | //
68 | this.TrayMenu_Quit.Name = "TrayMenu_Quit";
69 | this.TrayMenu_Quit.Size = new System.Drawing.Size(131, 22);
70 | this.TrayMenu_Quit.Text = "Quit VRCX";
71 | this.TrayMenu_Quit.Click += new System.EventHandler(this.TrayMenu_Quit_Click);
72 | //
73 | // TrayIcon
74 | //
75 | this.TrayIcon.ContextMenuStrip = this.TrayMenu;
76 | this.TrayIcon.Text = "VRCX";
77 | this.TrayIcon.Visible = true;
78 | this.TrayIcon.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.TrayIcon_MouseDoubleClick);
79 | //
80 | // MainForm
81 | //
82 | this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
83 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
84 | this.ClientSize = new System.Drawing.Size(842, 561);
85 | this.MinimumSize = new System.Drawing.Size(320, 240);
86 | this.Name = "MainForm";
87 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
88 | this.Text = "VRCX";
89 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
90 | this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainForm_FormClosed);
91 | this.Load += new System.EventHandler(this.MainForm_Load);
92 | this.Move += new System.EventHandler(this.MainForm_Move);
93 | this.Resize += new System.EventHandler(this.MainForm_Resize);
94 | this.TrayMenu.ResumeLayout(false);
95 | this.ResumeLayout(false);
96 |
97 | }
98 |
99 | #endregion
100 |
101 | private System.Windows.Forms.ContextMenuStrip TrayMenu;
102 | private System.Windows.Forms.ToolStripMenuItem TrayMenu_Open;
103 | private System.Windows.Forms.ToolStripSeparator TrayMenu_Separator;
104 | private System.Windows.Forms.ToolStripMenuItem TrayMenu_Quit;
105 | private System.Windows.Forms.NotifyIcon TrayIcon;
106 | }
107 | }
--------------------------------------------------------------------------------
/VRForm.Designer.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) 2019 pypy. All rights reserved.
2 | //
3 | // This work is licensed under the terms of the MIT license.
4 | // For a copy, see .
5 |
6 | namespace VRCX
7 | {
8 | partial class VRForm
9 | {
10 | ///
11 | /// 필수 디자이너 변수입니다.
12 | ///
13 | private System.ComponentModel.IContainer components = null;
14 |
15 | ///
16 | /// 사용 중인 모든 리소스를 정리합니다.
17 | ///
18 | /// 관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.
19 | protected override void Dispose(bool disposing)
20 | {
21 | if (disposing && (components != null))
22 | {
23 | components.Dispose();
24 | }
25 | base.Dispose(disposing);
26 | }
27 |
28 | #region Windows Form 디자이너에서 생성한 코드
29 |
30 | ///
31 | /// 디자이너 지원에 필요한 메서드입니다.
32 | /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
33 | ///
34 | private void InitializeComponent()
35 | {
36 | this.components = new System.ComponentModel.Container();
37 | this.timer = new System.Windows.Forms.Timer(this.components);
38 | this.panel1 = new System.Windows.Forms.Panel();
39 | this.panel2 = new System.Windows.Forms.Panel();
40 | this.button_refresh = new System.Windows.Forms.Button();
41 | this.button_devtools = new System.Windows.Forms.Button();
42 | this.SuspendLayout();
43 | //
44 | // panel1
45 | //
46 | this.panel1.Location = new System.Drawing.Point(0, 0);
47 | this.panel1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
48 | this.panel1.Name = "panel1";
49 | this.panel1.Size = new System.Drawing.Size(731, 768);
50 | this.panel1.TabIndex = 0;
51 | //
52 | // panel2
53 | //
54 | this.panel2.Location = new System.Drawing.Point(740, 0);
55 | this.panel2.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
56 | this.panel2.Name = "panel2";
57 | this.panel2.Size = new System.Drawing.Size(731, 768);
58 | this.panel2.TabIndex = 1;
59 | //
60 | // button_refresh
61 | //
62 | this.button_refresh.Location = new System.Drawing.Point(17, 777);
63 | this.button_refresh.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
64 | this.button_refresh.Name = "button_refresh";
65 | this.button_refresh.Size = new System.Drawing.Size(107, 34);
66 | this.button_refresh.TabIndex = 27;
67 | this.button_refresh.Text = "Refresh";
68 | this.button_refresh.UseVisualStyleBackColor = true;
69 | this.button_refresh.Click += new System.EventHandler(this.button_refresh_Click);
70 | //
71 | // button_devtools
72 | //
73 | this.button_devtools.Location = new System.Drawing.Point(133, 777);
74 | this.button_devtools.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
75 | this.button_devtools.Name = "button_devtools";
76 | this.button_devtools.Size = new System.Drawing.Size(107, 34);
77 | this.button_devtools.TabIndex = 27;
78 | this.button_devtools.Text = "DevTools";
79 | this.button_devtools.UseVisualStyleBackColor = true;
80 | this.button_devtools.Click += new System.EventHandler(this.button_devtools_Click);
81 | //
82 | // VRForm
83 | //
84 | this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F);
85 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
86 | this.ClientSize = new System.Drawing.Size(1483, 830);
87 | this.Controls.Add(this.button_devtools);
88 | this.Controls.Add(this.button_refresh);
89 | this.Controls.Add(this.panel2);
90 | this.Controls.Add(this.panel1);
91 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
92 | this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
93 | this.MaximizeBox = false;
94 | this.Name = "VRForm";
95 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
96 | this.Text = "VR";
97 | this.ResumeLayout(false);
98 |
99 | }
100 |
101 | #endregion
102 |
103 | private System.Windows.Forms.Timer timer;
104 | private System.Windows.Forms.Panel panel1;
105 | private System.Windows.Forms.Panel panel2;
106 | private System.Windows.Forms.Button button_refresh;
107 | private System.Windows.Forms.Button button_devtools;
108 | }
109 | }
--------------------------------------------------------------------------------
/SQLite.cs:
--------------------------------------------------------------------------------
1 | using CefSharp;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Data.SQLite;
5 | using System.IO;
6 | using System.Threading;
7 |
8 | namespace VRCX
9 | {
10 | public class SQLite
11 | {
12 | public static readonly SQLite Instance;
13 | private readonly ReaderWriterLockSlim m_ConnectionLock;
14 | private readonly SQLiteConnection m_Connection;
15 |
16 | static SQLite()
17 | {
18 | Instance = new SQLite();
19 | }
20 |
21 | public SQLite()
22 | {
23 | m_ConnectionLock = new ReaderWriterLockSlim();
24 |
25 | var dataSource = Path.Combine(Program.BaseDirectory, "VRCX.sqlite3");
26 | m_Connection = new SQLiteConnection($"Data Source=\"{dataSource}\";Version=3;PRAGMA locking_mode=NORMAL;PRAGMA busy_timeout=5000", true);
27 | }
28 |
29 | internal void Init()
30 | {
31 | m_Connection.Open();
32 | }
33 |
34 | internal void Exit()
35 | {
36 | m_Connection.Close();
37 | m_Connection.Dispose();
38 | }
39 |
40 | public void Execute(IJavascriptCallback callback, string sql, IDictionary args = null)
41 | {
42 | try
43 | {
44 | m_ConnectionLock.EnterReadLock();
45 | try
46 | {
47 | using (var command = new SQLiteCommand(sql, m_Connection))
48 | {
49 | if (args != null)
50 | {
51 | foreach (var arg in args)
52 | {
53 | command.Parameters.Add(new SQLiteParameter(arg.Key, arg.Value));
54 | }
55 | }
56 | using (var reader = command.ExecuteReader())
57 | {
58 | while (reader.Read() == true)
59 | {
60 | var values = new object[reader.FieldCount];
61 | reader.GetValues(values);
62 | if (callback.CanExecute == true)
63 | {
64 | callback.ExecuteAsync(null, values);
65 | }
66 | }
67 | }
68 | }
69 | if (callback.CanExecute == true)
70 | {
71 | callback.ExecuteAsync(null, null);
72 | }
73 | }
74 | finally
75 | {
76 | m_ConnectionLock.ExitReadLock();
77 | }
78 | }
79 | catch (Exception e)
80 | {
81 | if (callback.CanExecute == true)
82 | {
83 | callback.ExecuteAsync(e.Message, null);
84 | }
85 | }
86 |
87 | callback.Dispose();
88 | }
89 |
90 | public void Execute(Action