mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-17 22:03:50 +02:00
Updates and fixes
This commit is contained in:
@@ -147,25 +147,6 @@ namespace VRCX
|
||||
VRCXVR.Instance.Restart();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of arrays containing information about the connected VR devices.
|
||||
/// Each sub-array contains the type of device and its current state
|
||||
/// </summary>
|
||||
/// <returns>An array of arrays containing information about the connected VR devices.</returns>
|
||||
public string[][] GetVRDevices()
|
||||
{
|
||||
return VRCXVR.Instance.GetDevices();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current CPU usage as a percentage.
|
||||
/// </summary>
|
||||
/// <returns>The current CPU usage as a percentage.</returns>
|
||||
public float CpuUsage()
|
||||
{
|
||||
return CpuMonitor.Instance.CpuUsage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves an image from the VRChat API and caches it for future use. The function will return the cached image if it already exists.
|
||||
/// </summary>
|
||||
@@ -352,19 +333,6 @@ namespace VRCX
|
||||
WinformThemer.DoFunny();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of milliseconds that the system has been running.
|
||||
/// </summary>
|
||||
/// <returns>The number of milliseconds that the system has been running.</returns>
|
||||
public double GetUptime()
|
||||
{
|
||||
using (var uptime = new PerformanceCounter("System", "System Up Time"))
|
||||
{
|
||||
uptime.NextValue();
|
||||
return TimeSpan.FromSeconds(uptime.NextValue()).TotalMilliseconds;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a color value derived from the given user ID.
|
||||
/// This is, essentially, and is used for, random colors.
|
||||
|
||||
62
Dotnet/AppApi/AppApiVr.cs
Normal file
62
Dotnet/AppApi/AppApiVr.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using CefSharp;
|
||||
|
||||
namespace VRCX
|
||||
{
|
||||
public class AppApiVr
|
||||
{
|
||||
public static readonly AppApiVr Instance;
|
||||
|
||||
static AppApiVr()
|
||||
{
|
||||
Instance = new AppApiVr();
|
||||
}
|
||||
|
||||
public void VrInit()
|
||||
{
|
||||
if (MainForm.Instance?.Browser != null && !MainForm.Instance.Browser.IsLoading && MainForm.Instance.Browser.CanExecuteJavascriptInMainFrame)
|
||||
MainForm.Instance.Browser.ExecuteScriptAsync("$app.vrInit", "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current CPU usage as a percentage.
|
||||
/// </summary>
|
||||
/// <returns>The current CPU usage as a percentage.</returns>
|
||||
public float CpuUsage()
|
||||
{
|
||||
return CpuMonitor.Instance.CpuUsage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of arrays containing information about the connected VR devices.
|
||||
/// Each sub-array contains the type of device and its current state
|
||||
/// </summary>
|
||||
/// <returns>An array of arrays containing information about the connected VR devices.</returns>
|
||||
public string[][] GetVRDevices()
|
||||
{
|
||||
return VRCXVR.Instance.GetDevices();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of milliseconds that the system has been running.
|
||||
/// </summary>
|
||||
/// <returns>The number of milliseconds that the system has been running.</returns>
|
||||
public double GetUptime()
|
||||
{
|
||||
using var uptime = new PerformanceCounter("System", "System Up Time");
|
||||
uptime.NextValue();
|
||||
return TimeSpan.FromSeconds(uptime.NextValue()).TotalMilliseconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current language of the operating system.
|
||||
/// </summary>
|
||||
/// <returns>The current language of the operating system.</returns>
|
||||
public string CurrentCulture()
|
||||
{
|
||||
return CultureInfo.CurrentCulture.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,51 +58,52 @@ namespace VRCX
|
||||
/// Starts the VRChat game process with the specified command-line arguments.
|
||||
/// </summary>
|
||||
/// <param name="arguments">The command-line arguments to pass to the VRChat game.</param>
|
||||
public void StartGame(string arguments)
|
||||
public bool StartGame(string arguments)
|
||||
{
|
||||
// try stream first
|
||||
try
|
||||
{
|
||||
using (var key = Registry.ClassesRoot.OpenSubKey(@"steam\shell\open\command"))
|
||||
using var key = Registry.ClassesRoot.OpenSubKey(@"steam\shell\open\command");
|
||||
// "C:\Program Files (x86)\Steam\steam.exe" -- "%1"
|
||||
var match = Regex.Match(key.GetValue(string.Empty) as string, "^\"(.+?)\\\\steam.exe\"");
|
||||
if (match.Success)
|
||||
{
|
||||
// "C:\Program Files (x86)\Steam\steam.exe" -- "%1"
|
||||
var match = Regex.Match(key.GetValue(string.Empty) as string, "^\"(.+?)\\\\steam.exe\"");
|
||||
if (match.Success)
|
||||
{
|
||||
var path = match.Groups[1].Value;
|
||||
// var _arguments = Uri.EscapeDataString(arguments);
|
||||
Process.Start(new ProcessStartInfo
|
||||
var path = match.Groups[1].Value;
|
||||
// var _arguments = Uri.EscapeDataString(arguments);
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
WorkingDirectory = path,
|
||||
FileName = $"{path}\\steam.exe",
|
||||
UseShellExecute = false,
|
||||
Arguments = $"-applaunch 438100 {arguments}"
|
||||
}).Close();
|
||||
return;
|
||||
}
|
||||
})
|
||||
?.Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
logger.Warn("Failed to start VRChat from Steam");
|
||||
}
|
||||
|
||||
// fallback
|
||||
try
|
||||
{
|
||||
using (var key = Registry.ClassesRoot.OpenSubKey(@"VRChat\shell\open\command"))
|
||||
using var key = Registry.ClassesRoot.OpenSubKey(@"VRChat\shell\open\command");
|
||||
// "C:\Program Files (x86)\Steam\steamapps\common\VRChat\launch.exe" "%1" %*
|
||||
var match = Regex.Match(key.GetValue(string.Empty) as string, "(?!\")(.+?\\\\VRChat.*)(!?\\\\launch.exe\")");
|
||||
if (match.Success)
|
||||
{
|
||||
// "C:\Program Files (x86)\Steam\steamapps\common\VRChat\launch.exe" "%1" %*
|
||||
var match = Regex.Match(key.GetValue(string.Empty) as string, "(?!\")(.+?\\\\VRChat.*)(!?\\\\launch.exe\")");
|
||||
if (match.Success)
|
||||
{
|
||||
var path = match.Groups[1].Value;
|
||||
StartGameFromPath(path, arguments);
|
||||
}
|
||||
var path = match.Groups[1].Value;
|
||||
return StartGameFromPath(path, arguments);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
logger.Warn("Failed to start VRChat from registry");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -116,7 +117,7 @@ namespace VRCX
|
||||
if (!path.EndsWith(".exe"))
|
||||
path = Path.Combine(path, "launch.exe");
|
||||
|
||||
if (!File.Exists(path))
|
||||
if (!path.EndsWith("launch.exe") || !File.Exists(path))
|
||||
return false;
|
||||
|
||||
Process.Start(new ProcessStartInfo
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using System;
|
||||
using CefSharp;
|
||||
|
||||
namespace VRCX
|
||||
{
|
||||
public static class Util
|
||||
public static class JavascriptBindings
|
||||
{
|
||||
public static void ApplyJavascriptBindings(IJavascriptObjectRepository repository)
|
||||
public static void ApplyAppJavascriptBindings(IJavascriptObjectRepository repository)
|
||||
{
|
||||
repository.NameConverter = null;
|
||||
repository.Register("AppApi", AppApi.Instance);
|
||||
@@ -17,5 +16,11 @@ namespace VRCX
|
||||
repository.Register("Discord", Discord.Instance);
|
||||
repository.Register("AssetBundleCacher", AssetBundleCacher.Instance);
|
||||
}
|
||||
|
||||
public static void ApplyVrJavascriptBindings(IJavascriptObjectRepository repository)
|
||||
{
|
||||
repository.NameConverter = null;
|
||||
repository.Register("AppApiVr", AppApiVr.Instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ namespace VRCX
|
||||
Browser.ShowDevTools();
|
||||
};
|
||||
|
||||
Util.ApplyJavascriptBindings(Browser.JavascriptObjectRepository);
|
||||
JavascriptBindings.ApplyAppJavascriptBindings(Browser.JavascriptObjectRepository);
|
||||
Browser.ConsoleMessage += (_, args) =>
|
||||
{
|
||||
jslogger.Debug(args.Message + " (" + args.Source + ":" + args.Line + ")");
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace VRCX
|
||||
Size = new System.Drawing.Size(width, height);
|
||||
RenderHandler = this;
|
||||
|
||||
Util.ApplyJavascriptBindings(JavascriptObjectRepository);
|
||||
JavascriptBindings.ApplyVrJavascriptBindings(JavascriptObjectRepository);
|
||||
}
|
||||
|
||||
public new void Dispose()
|
||||
|
||||
@@ -45,8 +45,8 @@ namespace VRCX
|
||||
Dock = DockStyle.Fill
|
||||
};
|
||||
|
||||
Util.ApplyJavascriptBindings(_browser1.JavascriptObjectRepository);
|
||||
Util.ApplyJavascriptBindings(_browser2.JavascriptObjectRepository);
|
||||
JavascriptBindings.ApplyVrJavascriptBindings(_browser1.JavascriptObjectRepository);
|
||||
JavascriptBindings.ApplyVrJavascriptBindings(_browser2.JavascriptObjectRepository);
|
||||
|
||||
panel1.Controls.Add(_browser1);
|
||||
panel2.Controls.Add(_browser2);
|
||||
|
||||
@@ -13,26 +13,41 @@ namespace VRCX
|
||||
{
|
||||
public class WorldDBManager
|
||||
{
|
||||
public static WorldDBManager Instance;
|
||||
public static readonly WorldDBManager Instance;
|
||||
private readonly HttpListener listener;
|
||||
private readonly WorldDatabase worldDB;
|
||||
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
private const string WorldDBServerUrl = "http://127.0.0.1:22500/";
|
||||
|
||||
private string lastError = null;
|
||||
private bool debugWorld = false;
|
||||
|
||||
public WorldDBManager(string url)
|
||||
static WorldDBManager()
|
||||
{
|
||||
Instance = new WorldDBManager();
|
||||
}
|
||||
|
||||
public WorldDBManager()
|
||||
{
|
||||
Instance = this;
|
||||
// http://localhost:22500
|
||||
listener = new HttpListener();
|
||||
listener.Prefixes.Add(url);
|
||||
listener.Prefixes.Add(WorldDBServerUrl);
|
||||
|
||||
worldDB = new WorldDatabase(Path.Combine(Program.AppDataDirectory, "VRCX-WorldData.db"));
|
||||
|
||||
}
|
||||
|
||||
public async Task Start()
|
||||
public void Init()
|
||||
{
|
||||
if (VRCXStorage.Instance.Get("VRCX_DisableWorldDatabase") == "true")
|
||||
{
|
||||
logger.Info("World database is disabled. Not starting.");
|
||||
return;
|
||||
}
|
||||
|
||||
Task.Run(Start);
|
||||
}
|
||||
|
||||
private async Task Start()
|
||||
{
|
||||
// typing this in vr gonna kms
|
||||
try
|
||||
@@ -223,9 +238,13 @@ namespace VRCX
|
||||
}
|
||||
|
||||
var worldOverride = request.QueryString["world"];
|
||||
if (worldOverride == "global")
|
||||
{
|
||||
TryInitializeWorld(worldOverride, out connectionKey);
|
||||
}
|
||||
if (worldOverride != null && worldId != worldOverride)
|
||||
{
|
||||
var allowed = worldDB.GetWorldAllowExternalRead(worldOverride);
|
||||
var allowed = worldDB.GetWorldAllowExternalRead(worldOverride) || worldOverride == "global";
|
||||
if (!allowed)
|
||||
{
|
||||
return ConstructSuccessResponse(null, connectionKey);
|
||||
@@ -262,9 +281,13 @@ namespace VRCX
|
||||
}
|
||||
|
||||
var worldOverride = request.QueryString["world"];
|
||||
if (worldOverride == "global")
|
||||
{
|
||||
TryInitializeWorld(worldOverride, out connectionKey);
|
||||
}
|
||||
if (worldOverride != null && worldId != worldOverride)
|
||||
{
|
||||
var allowed = worldDB.GetWorldAllowExternalRead(worldOverride);
|
||||
var allowed = worldDB.GetWorldAllowExternalRead(worldOverride) || worldOverride == "global";
|
||||
if (!allowed)
|
||||
{
|
||||
return ConstructSuccessResponse(null, connectionKey);
|
||||
@@ -319,9 +342,13 @@ namespace VRCX
|
||||
}
|
||||
|
||||
var worldOverride = request.QueryString["world"];
|
||||
if (worldOverride == "global")
|
||||
{
|
||||
TryInitializeWorld(worldOverride, out connectionKey);
|
||||
}
|
||||
if (worldOverride != null && worldId != worldOverride)
|
||||
{
|
||||
var allowed = worldDB.GetWorldAllowExternalRead(worldOverride);
|
||||
var allowed = worldDB.GetWorldAllowExternalRead(worldOverride) || worldOverride == "global";
|
||||
if (!allowed)
|
||||
{
|
||||
return ConstructSuccessResponse(null, connectionKey);
|
||||
@@ -526,8 +553,6 @@ namespace VRCX
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Make sure the connection key is a valid GUID. No point in doing anything else if it's not.
|
||||
if (!debugWorld && !Guid.TryParse(request.ConnectionKey, out Guid _))
|
||||
{
|
||||
@@ -539,6 +564,12 @@ namespace VRCX
|
||||
|
||||
// Get the world ID from the connection key
|
||||
string worldId = worldDB.GetWorldByConnectionKey(request.ConnectionKey);
|
||||
|
||||
// Global override
|
||||
if (request.ConnectionKey == "global")
|
||||
{
|
||||
worldId = "global";
|
||||
}
|
||||
|
||||
// World ID is null, which means the connection key is invalid (or someone just deleted a world from the DB while VRCX was running lol).
|
||||
if (worldId == null)
|
||||
|
||||
@@ -135,16 +135,14 @@ namespace VRCX
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
logger.Info("{0} Starting...", Version);
|
||||
|
||||
// I'll re-do this whole function eventually I swear
|
||||
var worldDBServer = new WorldDBManager("http://127.0.0.1:22500/");
|
||||
Task.Run(worldDBServer.Start);
|
||||
|
||||
|
||||
ProcessMonitor.Instance.Init();
|
||||
SQLiteLegacy.Instance.Init();
|
||||
VRCXStorage.Load();
|
||||
CpuMonitor.Instance.Init();
|
||||
Discord.Instance.Init();
|
||||
WorldDBManager.Instance.Init();
|
||||
WebApi.Instance.Init();
|
||||
LogWatcher.Instance.Init();
|
||||
AutoAppLaunchManager.Instance.Init();
|
||||
@@ -161,7 +159,7 @@ namespace VRCX
|
||||
AutoAppLaunchManager.Instance.Exit();
|
||||
LogWatcher.Instance.Exit();
|
||||
WebApi.Instance.Exit();
|
||||
worldDBServer.Stop();
|
||||
WorldDBManager.Instance.Stop();
|
||||
|
||||
Discord.Instance.Exit();
|
||||
CpuMonitor.Instance.Exit();
|
||||
|
||||
@@ -117,12 +117,12 @@
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CefSharp.OffScreen.NETCore" Version="120.1.80" />
|
||||
<PackageReference Include="CefSharp.WinForms.NETCore" Version="120.1.80" />
|
||||
<PackageReference Include="CefSharp.OffScreen.NETCore" Version="120.1.110" />
|
||||
<PackageReference Include="CefSharp.WinForms.NETCore" Version="120.1.110" />
|
||||
<PackageReference Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.6" />
|
||||
<PackageReference Include="NLog" Version="5.2.8" />
|
||||
<PackageReference Include="SharpDX.Direct3D11" Version="4.2.0" />
|
||||
<PackageReference Include="SharpDX.Mathematics" Version="4.2.0" />
|
||||
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.118" />
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
"LogWatcher": "readonly",
|
||||
"Discord": "readonly",
|
||||
"AppApi": "readonly",
|
||||
"AppApiVr": "readonly",
|
||||
"SharedVariable": "readonly",
|
||||
"WebApi": "readonly",
|
||||
"AssetBundleCacher": "readonly"
|
||||
|
||||
@@ -643,8 +643,8 @@ speechSynthesis.getVoices();
|
||||
options.N > 0
|
||||
? options.N > options.params.offset
|
||||
: options.N < 0
|
||||
? args.json.length
|
||||
: options.params.n === args.json.length)
|
||||
? args.json.length
|
||||
: options.params.n === args.json.length)
|
||||
) {
|
||||
this.bulk(options);
|
||||
} else if ('done' in options) {
|
||||
@@ -4684,7 +4684,7 @@ speechSynthesis.getVoices();
|
||||
}
|
||||
this.errorNoty = new Noty({
|
||||
type: 'error',
|
||||
text: `WebSocket Error: ${err}`
|
||||
text: escapeTag(`WebSocket Error: ${err}`)
|
||||
}).show();
|
||||
return;
|
||||
}
|
||||
@@ -14687,14 +14687,10 @@ speechSynthesis.getVoices();
|
||||
'VRCX_StartAtWindowsStartup',
|
||||
false
|
||||
);
|
||||
$app.data.isStartAsMinimizedState = false;
|
||||
$app.data.isCloseToTray = false;
|
||||
VRCXStorage.Get('VRCX_StartAsMinimizedState').then((result) => {
|
||||
$app.isStartAsMinimizedState = result === 'true';
|
||||
});
|
||||
VRCXStorage.Get('VRCX_CloseToTray').then((result) => {
|
||||
$app.isCloseToTray = result === 'true';
|
||||
});
|
||||
$app.data.isStartAsMinimizedState =
|
||||
(await VRCXStorage.Get('VRCX_StartAsMinimizedState')) === 'true';
|
||||
$app.data.isCloseToTray =
|
||||
(await VRCXStorage.Get('VRCX_CloseToTray')) === 'true';
|
||||
if (await configRepository.getBool('VRCX_CloseToTray')) {
|
||||
// move back to JSON
|
||||
$app.data.isCloseToTray =
|
||||
@@ -14702,6 +14698,8 @@ speechSynthesis.getVoices();
|
||||
VRCXStorage.Set('VRCX_CloseToTray', $app.data.isCloseToTray.toString());
|
||||
await configRepository.remove('VRCX_CloseToTray');
|
||||
}
|
||||
$app.data.disableWorldDatabase =
|
||||
(await VRCXStorage.Get('VRCX_DisableWorldDatabase')) === 'true';
|
||||
$app.methods.saveVRCXWindowOption = async function () {
|
||||
await configRepository.setBool(
|
||||
'VRCX_StartAtWindowsStartup',
|
||||
@@ -14712,6 +14710,10 @@ speechSynthesis.getVoices();
|
||||
this.isStartAsMinimizedState.toString()
|
||||
);
|
||||
VRCXStorage.Set('VRCX_CloseToTray', this.isCloseToTray.toString());
|
||||
VRCXStorage.Set(
|
||||
'VRCX_DisableWorldDatabase',
|
||||
this.disableWorldDatabase.toString()
|
||||
);
|
||||
AppApi.SetStartup(this.isStartAtWindowsStartup);
|
||||
};
|
||||
$app.data.photonEventOverlay = await configRepository.getBool(
|
||||
@@ -16662,6 +16664,16 @@ speechSynthesis.getVoices();
|
||||
D.isShowAvatar = true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
database
|
||||
.getUserStats(D.ref, inCurrentWorld)
|
||||
.then((ref1) => {
|
||||
if (ref1.userId === D.id) {
|
||||
D.lastSeen = ref1.created_at;
|
||||
D.joinCount = ref1.joinCount;
|
||||
D.timeSpent = ref1.timeSpent;
|
||||
}
|
||||
});
|
||||
}
|
||||
API.getRepresentedGroup({ userId }).then((args1) => {
|
||||
D.representedGroup = args1.json;
|
||||
@@ -19541,14 +19553,25 @@ speechSynthesis.getVoices();
|
||||
$app.launchOptionsDialog.visible = false;
|
||||
});
|
||||
|
||||
$app.methods.updateLaunchOptions = async function () {
|
||||
$app.methods.updateLaunchOptions = function () {
|
||||
var D = this.launchOptionsDialog;
|
||||
D.visible = false;
|
||||
D.launchArguments = String(D.launchArguments)
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
await configRepository.setString('launchArguments', D.launchArguments);
|
||||
await configRepository.setString(
|
||||
configRepository.setString('launchArguments', D.launchArguments);
|
||||
if (
|
||||
D.vrcLaunchPathOverride &&
|
||||
D.vrcLaunchPathOverride.endsWith('.exe') &&
|
||||
!D.vrcLaunchPathOverride.endsWith('launch.exe')
|
||||
) {
|
||||
this.$message({
|
||||
message:
|
||||
'Invalid path, you must enter VRChat folder or launch.exe',
|
||||
type: 'error'
|
||||
});
|
||||
return;
|
||||
}
|
||||
configRepository.setString(
|
||||
'vrcLaunchPathOverride',
|
||||
D.vrcLaunchPathOverride
|
||||
);
|
||||
@@ -19556,6 +19579,7 @@ speechSynthesis.getVoices();
|
||||
message: 'Updated launch options',
|
||||
type: 'success'
|
||||
});
|
||||
D.visible = false;
|
||||
};
|
||||
|
||||
$app.methods.showLaunchOptions = function () {
|
||||
@@ -20101,10 +20125,19 @@ speechSynthesis.getVoices();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
AppApi.StartGame(args.join(' '));
|
||||
this.$message({
|
||||
message: 'VRChat launched',
|
||||
type: 'success'
|
||||
AppApi.StartGame(args.join(' ')).then((result) => {
|
||||
if (!result) {
|
||||
this.$message({
|
||||
message:
|
||||
'Failed to find VRChat, set a custom path in launch options',
|
||||
type: 'error'
|
||||
});
|
||||
} else {
|
||||
this.$message({
|
||||
message: 'VRChat launched',
|
||||
type: 'success'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
console.log('Launch Game', args.join(' '), desktopMode);
|
||||
|
||||
@@ -407,6 +407,14 @@ html
|
||||
i.el-icon-warning
|
||||
span.extra(v-if="userDialog.timeSpent === 0") -
|
||||
span.extra(v-else) {{ userDialog.timeSpent | timeToText }}
|
||||
template(v-else)
|
||||
.x-friend-item(@click="showPreviousInstancesUserDialog(userDialog.ref)")
|
||||
.detail
|
||||
span.name {{ $t('dialog.user.info.play_time') }}
|
||||
el-tooltip(v-if="!hideTooltips" placement="top" style="margin-left:5px" :content="$t('dialog.user.info.accuracy_notice')")
|
||||
i.el-icon-warning
|
||||
span.extra(v-if="userDialog.timeSpent === 0") -
|
||||
span.extra(v-else) {{ userDialog.timeSpent | timeToText }}
|
||||
.x-friend-item(style="cursor:default")
|
||||
el-tooltip(placement="top")
|
||||
template(#content)
|
||||
@@ -1486,7 +1494,7 @@ html
|
||||
el-button(type="primary" size="small" @click="createGroupInstance()" :disabled="!newInstanceDialog.groupId") {{ $t('dialog.new_instance.create_instance') }}
|
||||
|
||||
//- dialog: launch options
|
||||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="launchOptionsDialog" :visible.sync="launchOptionsDialog.visible" :title="$t('dialog.launch_options.header')" width="500px")
|
||||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="launchOptionsDialog" :visible.sync="launchOptionsDialog.visible" :title="$t('dialog.launch_options.header')" width="600px")
|
||||
div(style="font-size:12px")
|
||||
| {{ $t('dialog.launch_options.description') }} #[br]
|
||||
| {{ $t('dialog.launch_options.example') }} #[el-tag(size="mini") --fps=144]
|
||||
|
||||
@@ -403,6 +403,10 @@
|
||||
"header": "Automatically Manage Cache When Closing VRChat",
|
||||
"description": "Auto delete old versions from cache"
|
||||
},
|
||||
"disable_local_world_persistence": {
|
||||
"header": "Disable Local World Persistence",
|
||||
"description": "Disable localhost webserver (requires restart)"
|
||||
},
|
||||
"remote_database": {
|
||||
"header": "Remote Avatar Database",
|
||||
"enable": "Enable",
|
||||
@@ -582,6 +586,7 @@
|
||||
"last_seen": "Last Seen",
|
||||
"join_count": "Join Count",
|
||||
"time_together": "Time Together",
|
||||
"play_time": "Play Time",
|
||||
"online_for": "Online For",
|
||||
"offline_for": "Offline For",
|
||||
"last_activity": "Last Activity",
|
||||
@@ -592,7 +597,7 @@
|
||||
"avatar_cloning": "Avatar Cloning",
|
||||
"avatar_cloning_allow": "Allowed",
|
||||
"avatar_cloning_deny": "Deny",
|
||||
"home_location": "Home Location",
|
||||
"home_location": "Home World",
|
||||
"id": "User ID",
|
||||
"id_tooltip": "Copy to clipboard",
|
||||
"copy_id": "Copy ID",
|
||||
|
||||
@@ -415,6 +415,11 @@ mixin settingsTab()
|
||||
div.options-container-item
|
||||
span.name(style="min-width:300px") {{ $t('view.settings.advanced.advanced.auto_cache_management.description') }}
|
||||
el-switch(v-model="autoSweepVRChatCache" @change="saveOpenVROption")
|
||||
//- Advanced | Disable local world database
|
||||
span.sub-header {{ $t('view.settings.advanced.advanced.disable_local_world_persistence.header') }}
|
||||
div.options-container-item
|
||||
span.name(style="min-width:300px") {{ $t('view.settings.advanced.advanced.disable_local_world_persistence.description') }}
|
||||
el-switch(v-model="disableWorldDatabase" @change="saveVRCXWindowOption")
|
||||
//- Advanced | Remote Avatar Database
|
||||
div.options-container
|
||||
span.header {{ $t('view.settings.advanced.advanced.remote_database.header') }}
|
||||
|
||||
@@ -20,7 +20,7 @@ Vue.component('marquee-text', MarqueeText);
|
||||
(async function () {
|
||||
var $app = null;
|
||||
|
||||
await CefSharp.BindObjectAsync('AppApi');
|
||||
await CefSharp.BindObjectAsync('AppApiVr');
|
||||
|
||||
Noty.overrideDefaults({
|
||||
animation: {
|
||||
@@ -50,6 +50,18 @@ Vue.component('marquee-text', MarqueeText);
|
||||
String(s).replace(/["&'<>]/gu, (c) => `&#${c.charCodeAt(0)};`);
|
||||
Vue.filter('escapeTag', escapeTag);
|
||||
|
||||
var escapeTagRecursive = (obj) => {
|
||||
if (typeof obj === 'string') {
|
||||
return escapeTag(obj);
|
||||
}
|
||||
if (typeof obj === 'object') {
|
||||
for (var key in obj) {
|
||||
obj[key] = escapeTagRecursive(obj[key]);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
var commaNumber = (n) =>
|
||||
String(Number(n) || 0).replace(/(\d)(?=(\d{3})+(?!\d))/gu, '$1,');
|
||||
Vue.filter('commaNumber', commaNumber);
|
||||
@@ -216,10 +228,7 @@ Vue.component('marquee-text', MarqueeText);
|
||||
watch: {},
|
||||
el: '#x-app',
|
||||
mounted() {
|
||||
workerTimers.setTimeout(
|
||||
() => AppApi.ExecuteAppFunction('vrInit', ''),
|
||||
1000
|
||||
);
|
||||
workerTimers.setTimeout(() => AppApiVr.VrInit(), 1000);
|
||||
if (this.appType === '1') {
|
||||
this.updateStatsLoop();
|
||||
}
|
||||
@@ -410,7 +419,7 @@ Vue.component('marquee-text', MarqueeText);
|
||||
.replace(',', '');
|
||||
|
||||
if (!this.config.hideCpuUsageFromFeed) {
|
||||
var cpuUsage = await AppApi.CpuUsage();
|
||||
var cpuUsage = await AppApiVr.CpuUsage();
|
||||
this.cpuUsage = cpuUsage.toFixed(0);
|
||||
}
|
||||
if (this.lastLocation.date !== 0) {
|
||||
@@ -429,7 +438,7 @@ Vue.component('marquee-text', MarqueeText);
|
||||
}
|
||||
|
||||
if (!this.config.hideDevicesFromFeed) {
|
||||
AppApi.GetVRDevices().then((devices) => {
|
||||
AppApiVr.GetVRDevices().then((devices) => {
|
||||
var deviceList = [];
|
||||
var baseStations = 0;
|
||||
devices.forEach((device) => {
|
||||
@@ -480,7 +489,7 @@ Vue.component('marquee-text', MarqueeText);
|
||||
this.devices = [];
|
||||
}
|
||||
if (this.config.pcUptimeOnFeed) {
|
||||
AppApi.GetUptime().then((uptime) => {
|
||||
AppApiVr.GetUptime().then((uptime) => {
|
||||
this.pcUptime = timeToText(uptime);
|
||||
});
|
||||
} else {
|
||||
@@ -494,7 +503,12 @@ Vue.component('marquee-text', MarqueeText);
|
||||
|
||||
$app.methods.playNoty = function (json) {
|
||||
var { noty, message, image } = JSON.parse(json);
|
||||
var message = escapeTag(message);
|
||||
if (typeof noty === 'undefined') {
|
||||
console.error('noty is undefined');
|
||||
return;
|
||||
}
|
||||
var noty = escapeTagRecursive(noty);
|
||||
var message = escapeTag(message) || '';
|
||||
var text = '';
|
||||
var img = '';
|
||||
if (image) {
|
||||
@@ -515,8 +529,8 @@ Vue.component('marquee-text', MarqueeText);
|
||||
noty.displayName
|
||||
}</strong> is in ${this.displayLocation(
|
||||
noty.location,
|
||||
escapeTag(noty.worldName),
|
||||
escapeTag(noty.groupName)
|
||||
noty.worldName,
|
||||
noty.groupName
|
||||
)}`;
|
||||
break;
|
||||
case 'Online':
|
||||
@@ -524,8 +538,8 @@ Vue.component('marquee-text', MarqueeText);
|
||||
if (noty.worldName) {
|
||||
locationName = ` to ${this.displayLocation(
|
||||
noty.location,
|
||||
escapeTag(noty.worldName),
|
||||
escapeTag(noty.groupName)
|
||||
noty.worldName,
|
||||
noty.groupName
|
||||
)}`;
|
||||
}
|
||||
text = `<strong>${noty.displayName}</strong> has logged in${locationName}`;
|
||||
@@ -534,16 +548,14 @@ Vue.component('marquee-text', MarqueeText);
|
||||
text = `<strong>${noty.displayName}</strong> has logged out`;
|
||||
break;
|
||||
case 'Status':
|
||||
text = `<strong>${noty.displayName}</strong> status is now <i>${
|
||||
noty.status
|
||||
}</i> ${escapeTag(noty.statusDescription)}`;
|
||||
text = `<strong>${noty.displayName}</strong> status is now <i>${noty.status}</i> ${noty.statusDescription}`;
|
||||
break;
|
||||
case 'invite':
|
||||
text = `<strong>${
|
||||
noty.senderUsername
|
||||
}</strong> has invited you to ${this.displayLocation(
|
||||
noty.details.worldId,
|
||||
escapeTag(noty.details.worldName)
|
||||
noty.details.worldName
|
||||
)}${message}`;
|
||||
break;
|
||||
case 'requestInvite':
|
||||
@@ -571,19 +583,19 @@ Vue.component('marquee-text', MarqueeText);
|
||||
text = `<strong>${noty.previousDisplayName}</strong> changed their name to ${noty.displayName}`;
|
||||
break;
|
||||
case 'group.announcement':
|
||||
text = escapeTag(noty.message);
|
||||
text = noty.message;
|
||||
break;
|
||||
case 'group.informative':
|
||||
text = escapeTag(noty.message);
|
||||
text = noty.message;
|
||||
break;
|
||||
case 'group.invite':
|
||||
text = escapeTag(noty.message);
|
||||
text = noty.message;
|
||||
break;
|
||||
case 'group.joinRequest':
|
||||
text = escapeTag(noty.message);
|
||||
text = noty.message;
|
||||
break;
|
||||
case 'group.queueReady':
|
||||
text = escapeTag(noty.message);
|
||||
text = noty.message;
|
||||
break;
|
||||
case 'PortalSpawn':
|
||||
if (noty.displayName) {
|
||||
@@ -591,33 +603,27 @@ Vue.component('marquee-text', MarqueeText);
|
||||
noty.displayName
|
||||
}</strong> has spawned a portal to ${this.displayLocation(
|
||||
noty.instanceId,
|
||||
escapeTag(noty.worldName),
|
||||
escapeTag(noty.groupName)
|
||||
noty.worldName,
|
||||
noty.groupName
|
||||
)}`;
|
||||
} else {
|
||||
text = 'User has spawned a portal';
|
||||
}
|
||||
break;
|
||||
case 'AvatarChange':
|
||||
text = `<strong>${
|
||||
noty.displayName
|
||||
}</strong> changed into avatar ${escapeTag(noty.name)}`;
|
||||
text = `<strong>${noty.displayName}</strong> changed into avatar ${noty.name}`;
|
||||
break;
|
||||
case 'ChatBoxMessage':
|
||||
text = `<strong>${noty.displayName}</strong> said ${escapeTag(
|
||||
noty.text
|
||||
)}`;
|
||||
text = `<strong>${noty.displayName}</strong> said ${noty.text}`;
|
||||
break;
|
||||
case 'Event':
|
||||
text = escapeTag(noty.data);
|
||||
text = noty.data;
|
||||
break;
|
||||
case 'External':
|
||||
text = escapeTag(noty.message);
|
||||
text = noty.message;
|
||||
break;
|
||||
case 'VideoPlay':
|
||||
text = `<strong>Now playing:</strong> ${escapeTag(
|
||||
noty.notyName
|
||||
)}`;
|
||||
text = `<strong>Now playing:</strong> ${noty.notyName}`;
|
||||
break;
|
||||
case 'BlockedOnPlayerJoined':
|
||||
text = `Blocked user <strong>${noty.displayName}</strong> has joined`;
|
||||
@@ -766,10 +772,10 @@ Vue.component('marquee-text', MarqueeText);
|
||||
this.hudTimeout = JSON.parse(json);
|
||||
};
|
||||
|
||||
$app.data.currentCulture = await AppApi.CurrentCulture();
|
||||
$app.data.currentCulture = await AppApiVr.CurrentCulture();
|
||||
|
||||
$app.methods.setDatetimeFormat = async function () {
|
||||
this.currentCulture = await AppApi.CurrentCulture();
|
||||
this.currentCulture = await AppApiVr.CurrentCulture();
|
||||
var formatDate = function (date) {
|
||||
if (!date) {
|
||||
return '';
|
||||
|
||||
Reference in New Issue
Block a user