mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-22 16:23:50 +02:00
Refactor IPC
This commit is contained in:
21
AppApi.cs
21
AppApi.cs
@@ -9,7 +9,6 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Pipes;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
@@ -346,12 +345,20 @@ namespace VRCX
|
|||||||
|
|
||||||
public void IPCAnnounceStart()
|
public void IPCAnnounceStart()
|
||||||
{
|
{
|
||||||
var ipcClient = new NamedPipeClientStream(".", "vrcx-ipc", PipeDirection.InOut);
|
IPCServer.Send(new IPCPacket
|
||||||
ipcClient.Connect();
|
{
|
||||||
if (!ipcClient.IsConnected)
|
Type = "VRCXLaunch"
|
||||||
return;
|
});
|
||||||
var buffer = Encoding.UTF8.GetBytes("{\"type\":\"VRCXLaunch\"}" + (char)0x00);
|
}
|
||||||
ipcClient.BeginWrite(buffer, 0, buffer.Length, IPCClient.OnSend, ipcClient);
|
|
||||||
|
public void SendIpc(string type, string data)
|
||||||
|
{
|
||||||
|
IPCServer.Send(new IPCPacket
|
||||||
|
{
|
||||||
|
Type = "VrcxMessage",
|
||||||
|
MsgType = type,
|
||||||
|
Data = data
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExecuteAppFunction(string function, string json)
|
public void ExecuteAppFunction(string function, string json)
|
||||||
|
|||||||
52
IPCClient.cs
52
IPCClient.cs
@@ -4,23 +4,33 @@
|
|||||||
// This work is licensed under the terms of the MIT license.
|
// This work is licensed under the terms of the MIT license.
|
||||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||||
|
|
||||||
using CefSharp;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.IO.Pipes;
|
using System.IO.Pipes;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using CefSharp;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace VRCX
|
namespace VRCX
|
||||||
{
|
{
|
||||||
internal class IPCClient
|
internal class IPCClient
|
||||||
{
|
{
|
||||||
private NamedPipeServerStream _ipcServer;
|
private static readonly UTF8Encoding noBomEncoding = new UTF8Encoding(false, false);
|
||||||
private byte[] _recvBuffer = new byte[1024 * 8];
|
private readonly NamedPipeServerStream _ipcServer;
|
||||||
|
private readonly byte[] _recvBuffer = new byte[1024 * 8];
|
||||||
|
private readonly MemoryStream memoryStream;
|
||||||
|
private readonly byte[] packetBuffer = new byte[1024 * 1024];
|
||||||
|
private readonly Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer();
|
||||||
private string _currentPacket;
|
private string _currentPacket;
|
||||||
|
|
||||||
public IPCClient(NamedPipeServerStream ipcServer)
|
public IPCClient(NamedPipeServerStream ipcServer)
|
||||||
{
|
{
|
||||||
|
memoryStream = new MemoryStream(packetBuffer);
|
||||||
|
serializer.Culture = CultureInfo.InvariantCulture;
|
||||||
|
serializer.Formatting = Formatting.None;
|
||||||
|
|
||||||
_ipcServer = ipcServer;
|
_ipcServer = ipcServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +39,28 @@ namespace VRCX
|
|||||||
_ipcServer.BeginRead(_recvBuffer, 0, _recvBuffer.Length, OnRead, _ipcServer);
|
_ipcServer.BeginRead(_recvBuffer, 0, _recvBuffer.Length, OnRead, _ipcServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task Send(IPCPacket ipcPacket)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
using (var streamWriter = new StreamWriter(memoryStream, noBomEncoding, 65535, true))
|
||||||
|
using (var writer = new JsonTextWriter(streamWriter))
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, ipcPacket);
|
||||||
|
streamWriter.Write((char)0x00);
|
||||||
|
streamWriter.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
var length = (int)memoryStream.Position;
|
||||||
|
_ipcServer?.BeginWrite(packetBuffer, 0, length, OnSend, null);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
IPCServer.Clients.Remove(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnRead(IAsyncResult asyncResult)
|
private void OnRead(IAsyncResult asyncResult)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -37,6 +69,7 @@ namespace VRCX
|
|||||||
|
|
||||||
if (bytesRead <= 0)
|
if (bytesRead <= 0)
|
||||||
{
|
{
|
||||||
|
IPCServer.Clients.Remove(this);
|
||||||
_ipcServer.Close();
|
_ipcServer.Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -69,7 +102,14 @@ namespace VRCX
|
|||||||
public static void OnSend(IAsyncResult asyncResult)
|
public static void OnSend(IAsyncResult asyncResult)
|
||||||
{
|
{
|
||||||
var ipcClient = (NamedPipeClientStream)asyncResult.AsyncState;
|
var ipcClient = (NamedPipeClientStream)asyncResult.AsyncState;
|
||||||
ipcClient.EndWrite(asyncResult);
|
ipcClient?.EndWrite(asyncResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Close(IAsyncResult asyncResult)
|
||||||
|
{
|
||||||
|
var ipcClient = (NamedPipeClientStream)asyncResult.AsyncState;
|
||||||
|
ipcClient?.EndWrite(asyncResult);
|
||||||
|
ipcClient?.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
9
IPCPacket.cs
Normal file
9
IPCPacket.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace VRCX
|
||||||
|
{
|
||||||
|
public class IPCPacket
|
||||||
|
{
|
||||||
|
public string Type { get; set; }
|
||||||
|
public string Data { get; set; }
|
||||||
|
public string MsgType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
19
IPCServer.cs
19
IPCServer.cs
@@ -5,13 +5,16 @@
|
|||||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO.Pipes;
|
using System.IO.Pipes;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace VRCX
|
namespace VRCX
|
||||||
{
|
{
|
||||||
class IPCServer
|
internal class IPCServer
|
||||||
{
|
{
|
||||||
public static readonly IPCServer Instance;
|
public static readonly IPCServer Instance;
|
||||||
|
public static readonly List<IPCClient> Clients = new List<IPCClient>();
|
||||||
|
|
||||||
static IPCServer()
|
static IPCServer()
|
||||||
{
|
{
|
||||||
@@ -23,10 +26,18 @@ namespace VRCX
|
|||||||
new IPCServer().CreateIPCServer();
|
new IPCServer().CreateIPCServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task Send(IPCPacket ipcPacket)
|
||||||
|
{
|
||||||
|
foreach (var client in Clients)
|
||||||
|
{
|
||||||
|
await client.Send(ipcPacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void CreateIPCServer()
|
public void CreateIPCServer()
|
||||||
{
|
{
|
||||||
var ipcServer = new NamedPipeServerStream("vrcx-ipc", PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
|
var ipcServer = new NamedPipeServerStream("vrcx-ipc", PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
|
||||||
ipcServer.BeginWaitForConnection(asyncResult => DoAccept(asyncResult), ipcServer);
|
ipcServer.BeginWaitForConnection(DoAccept, ipcServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DoAccept(IAsyncResult asyncResult)
|
private void DoAccept(IAsyncResult asyncResult)
|
||||||
@@ -42,7 +53,9 @@ namespace VRCX
|
|||||||
Console.WriteLine(e);
|
Console.WriteLine(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
new IPCClient(ipcServer).BeginRead();
|
var ipcClient = new IPCClient(ipcServer);
|
||||||
|
Clients.Add(ipcClient);
|
||||||
|
ipcClient.BeginRead();
|
||||||
CreateIPCServer();
|
CreateIPCServer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ namespace VRCX
|
|||||||
|
|
||||||
public static void ArgsCheck()
|
public static void ArgsCheck()
|
||||||
{
|
{
|
||||||
string[] args = Environment.GetCommandLineArgs();
|
var args = Environment.GetCommandLineArgs();
|
||||||
processList = Process.GetProcessesByName("VRCX");
|
processList = Process.GetProcessesByName("VRCX");
|
||||||
|
|
||||||
bool isDebug = false;
|
var isDebug = false;
|
||||||
Debug.Assert(isDebug = true);
|
Debug.Assert(isDebug = true);
|
||||||
|
|
||||||
foreach (string arg in args)
|
foreach (var arg in args)
|
||||||
{
|
{
|
||||||
if (arg.Contains("--gpufix"))
|
if (arg.Contains("--gpufix"))
|
||||||
Program.GPUFix = true;
|
Program.GPUFix = true;
|
||||||
@@ -40,7 +40,7 @@ namespace VRCX
|
|||||||
Program.LaunchDebug = true;
|
Program.LaunchDebug = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (processList.Length > 1 && String.IsNullOrEmpty(LaunchCommand))
|
if (processList.Length > 1 && string.IsNullOrEmpty(LaunchCommand))
|
||||||
{
|
{
|
||||||
var result = MessageBox.Show("VRCX is already running, start another instance?", "VRCX", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
var result = MessageBox.Show("VRCX is already running, start another instance?", "VRCX", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||||||
if (result == DialogResult.Yes)
|
if (result == DialogResult.Yes)
|
||||||
@@ -63,7 +63,7 @@ namespace VRCX
|
|||||||
if (ipcClient.IsConnected)
|
if (ipcClient.IsConnected)
|
||||||
{
|
{
|
||||||
var buffer = Encoding.UTF8.GetBytes($"{{\"type\":\"LaunchCommand\",\"command\":\"{LaunchCommand}\"}}" + (char)0x00);
|
var buffer = Encoding.UTF8.GetBytes($"{{\"type\":\"LaunchCommand\",\"command\":\"{LaunchCommand}\"}}" + (char)0x00);
|
||||||
ipcClient.BeginWrite(buffer, 0, buffer.Length, IPCClient.OnSend, ipcClient);
|
ipcClient.BeginWrite(buffer, 0, buffer.Length, IPCClient.Close, ipcClient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@@ -160,6 +160,7 @@
|
|||||||
<None Include="App.config" />
|
<None Include="App.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="IPCPacket.cs" />
|
||||||
<Content Include="VRCX.ico">
|
<Content Include="VRCX.ico">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
|||||||
@@ -2583,7 +2583,15 @@ speechSynthesis.getVoices();
|
|||||||
};
|
};
|
||||||
this.cachedAvatars.set(ref.id, ref);
|
this.cachedAvatars.set(ref.id, ref);
|
||||||
} else {
|
} else {
|
||||||
|
var {unityPackages} = ref;
|
||||||
Object.assign(ref, json);
|
Object.assign(ref, json);
|
||||||
|
if (
|
||||||
|
json.unityPackages.length > 0 &&
|
||||||
|
unityPackages.length > 0 &&
|
||||||
|
!json.unityPackages.assetUrl
|
||||||
|
) {
|
||||||
|
ref.unityPackages = unityPackages;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ref.name = $app.replaceBioSymbols(ref.name);
|
ref.name = $app.replaceBioSymbols(ref.name);
|
||||||
ref.description = $app.replaceBioSymbols(ref.description);
|
ref.description = $app.replaceBioSymbols(ref.description);
|
||||||
@@ -10774,10 +10782,24 @@ speechSynthesis.getVoices();
|
|||||||
}
|
}
|
||||||
if (block === row.block && mute === row.mute) {
|
if (block === row.block && mute === row.mute) {
|
||||||
// no change
|
// no change
|
||||||
type = '';
|
if (type) {
|
||||||
|
this.addEntryPhotonEvent({
|
||||||
|
photonId,
|
||||||
|
text: `Moderation ${text}`,
|
||||||
|
type: 'Moderation',
|
||||||
|
color: 'yellow',
|
||||||
|
created_at: gameLogDate
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (text) {
|
this.moderationAgainstTable.forEach((item) => {
|
||||||
|
if (item.userId === ref.id && item.type === type) {
|
||||||
|
removeFromArray(this.moderationAgainstTable, item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (type) {
|
||||||
this.addEntryPhotonEvent({
|
this.addEntryPhotonEvent({
|
||||||
photonId,
|
photonId,
|
||||||
text: `Moderation ${text}`,
|
text: `Moderation ${text}`,
|
||||||
@@ -10785,8 +10807,6 @@ speechSynthesis.getVoices();
|
|||||||
color: 'yellow',
|
color: 'yellow',
|
||||||
created_at: gameLogDate
|
created_at: gameLogDate
|
||||||
});
|
});
|
||||||
}
|
|
||||||
if (type) {
|
|
||||||
var noty = {
|
var noty = {
|
||||||
created_at: new Date().toJSON(),
|
created_at: new Date().toJSON(),
|
||||||
userId: ref.id,
|
userId: ref.id,
|
||||||
@@ -10800,12 +10820,9 @@ speechSynthesis.getVoices();
|
|||||||
displayName: ref.displayName,
|
displayName: ref.displayName,
|
||||||
type
|
type
|
||||||
};
|
};
|
||||||
this.moderationAgainstTable.forEach((item) => {
|
|
||||||
if (item.userId === ref.id && item.type === type) {
|
|
||||||
removeFromArray(this.moderationAgainstTable, item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.moderationAgainstTable.push(entry);
|
this.moderationAgainstTable.push(entry);
|
||||||
|
}
|
||||||
|
if (block || mute || block !== row.block || mute !== row.mute) {
|
||||||
this.updateSharedFeed(true);
|
this.updateSharedFeed(true);
|
||||||
}
|
}
|
||||||
if (block || mute) {
|
if (block || mute) {
|
||||||
@@ -10816,7 +10833,7 @@ speechSynthesis.getVoices();
|
|||||||
block,
|
block,
|
||||||
mute
|
mute
|
||||||
});
|
});
|
||||||
} else {
|
} else if (row.block || row.mute) {
|
||||||
database.deleteModeration(ref.id);
|
database.deleteModeration(ref.id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -14875,6 +14892,9 @@ speechSynthesis.getVoices();
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (this.ipcEnabled) {
|
||||||
|
AppApi.SendIpc('ShowUserDialog', userId);
|
||||||
|
}
|
||||||
API.getCachedUser({
|
API.getCachedUser({
|
||||||
userId
|
userId
|
||||||
})
|
})
|
||||||
@@ -21617,6 +21637,8 @@ speechSynthesis.getVoices();
|
|||||||
this.ipcEnabled = true;
|
this.ipcEnabled = true;
|
||||||
this.ipcTimeout = 60; // 30secs
|
this.ipcTimeout = 60; // 30secs
|
||||||
break;
|
break;
|
||||||
|
case 'MsgPing':
|
||||||
|
break;
|
||||||
case 'LaunchCommand':
|
case 'LaunchCommand':
|
||||||
AppApi.FocusWindow();
|
AppApi.FocusWindow();
|
||||||
this.eventLaunchCommand(data.command);
|
this.eventLaunchCommand(data.command);
|
||||||
@@ -21644,10 +21666,22 @@ speechSynthesis.getVoices();
|
|||||||
$app.data.customUserTags = new Map();
|
$app.data.customUserTags = new Map();
|
||||||
|
|
||||||
$app.methods.addCustomTag = function (data) {
|
$app.methods.addCustomTag = function (data) {
|
||||||
this.customUserTags.set(data.UserId, {
|
if (data.Tag) {
|
||||||
tag: data.Tag,
|
this.customUserTags.set(data.UserId, {
|
||||||
|
tag: data.Tag,
|
||||||
|
colour: data.TagColour
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.customUserTags.delete(data.UserId);
|
||||||
|
}
|
||||||
|
var feedUpdate = {
|
||||||
|
userId: data.UserId,
|
||||||
colour: data.TagColour
|
colour: data.TagColour
|
||||||
});
|
};
|
||||||
|
AppApi.ExecuteVrOverlayFunction(
|
||||||
|
'updateHudFeedTag',
|
||||||
|
JSON.stringify(feedUpdate)
|
||||||
|
);
|
||||||
var ref = API.cachedUsers.get(data.UserId);
|
var ref = API.cachedUsers.get(data.UserId);
|
||||||
if (typeof ref !== 'undefined') {
|
if (typeof ref !== 'undefined') {
|
||||||
ref.$customTag = data.Tag;
|
ref.$customTag = data.Tag;
|
||||||
|
|||||||
@@ -726,6 +726,15 @@ Vue.component('marquee-text', MarqueeText);
|
|||||||
this.cleanHudFeed();
|
this.cleanHudFeed();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$app.methods.updateHudFeedTag = function (json) {
|
||||||
|
var ref = JSON.parse(json);
|
||||||
|
this.hudFeed.forEach((item) => {
|
||||||
|
if (item.userId === ref.userId) {
|
||||||
|
item.colour = ref.colour;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
$app.data.hudTimeout = [];
|
$app.data.hudTimeout = [];
|
||||||
|
|
||||||
$app.methods.updateHudTimeout = function (json) {
|
$app.methods.updateHudTimeout = function (json) {
|
||||||
|
|||||||
Reference in New Issue
Block a user