diff --git a/AppApi.cs b/AppApi.cs index 707508c3..467c353f 100644 --- a/AppApi.cs +++ b/AppApi.cs @@ -403,14 +403,6 @@ namespace VRCX return ""; } - public string DeserializeVrcEvent(string base64Data) - { - byte[] bytes = Convert.FromBase64String(base64Data); - var deserialization = new VRCEventDeserialization(); - var eventData = deserialization.DeserializeData(bytes); - return System.Text.Json.JsonSerializer.Serialize(eventData); - } - public string CustomCssPath() { var output = String.Empty; diff --git a/IPCClient.cs b/IPCClient.cs index 409d9817..27bc4ba6 100644 --- a/IPCClient.cs +++ b/IPCClient.cs @@ -17,10 +17,7 @@ namespace VRCX { private NamedPipeServerStream _ipcServer; private byte[] _recvBuffer = new byte[1024 * 8]; - private string _currentPacket; - private VRCEventDeserialization.EventEntry _eventEntry; - private readonly VRCEventDeserialization eventDeserialization = new VRCEventDeserialization(); public IPCClient(NamedPipeServerStream ipcServer) { @@ -55,34 +52,6 @@ namespace VRCX if (string.IsNullOrEmpty(packet)) continue; - var eventData = System.Text.Json.JsonSerializer.Deserialize(packet); - if (eventData.type == "OnEvent" && eventData.OnEventData.Code == 6) - { - var byteArray = Convert.FromBase64String(eventData.OnEventData.Parameters[245].ToString()); - _eventEntry = eventDeserialization.DeserializeData(byteArray); - if (VRCEventDeserialization.ignoreEvents.Contains(_eventEntry.EventType)) - continue; - - _eventEntry.type = "VRCEvent"; - _eventEntry.dt = eventData.dt; - _eventEntry.senderId = eventData.OnEventData.Sender; - var jsonData = System.Text.Json.JsonSerializer.Serialize(_eventEntry); - MainForm.Instance.Browser.ExecuteScriptAsync("$app.ipcEvent", jsonData); - continue; - } - else if (eventData.type == "OnEvent" && eventData.OnEventData.Code == 7) - { - _eventEntry = new VRCEventDeserialization.EventEntry - { - type = "Event7", - dt = eventData.dt, - senderId = eventData.OnEventData.Sender - }; - var jsonData = System.Text.Json.JsonSerializer.Serialize(_eventEntry); - MainForm.Instance.Browser.ExecuteScriptAsync("$app.ipcEvent", jsonData); - continue; - } - MainForm.Instance.Browser.ExecuteScriptAsync("$app.ipcEvent", packet); } diff --git a/VRCEventDeserialization.cs b/VRCEventDeserialization.cs deleted file mode 100644 index 208419ce..00000000 --- a/VRCEventDeserialization.cs +++ /dev/null @@ -1,269 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Numerics; -using System.Text; - -namespace VRCX -{ - internal class VRCEventDeserialization - { - private byte[] byteData; - private int byteOffset; - - private static readonly Dictionary DataType = new Dictionary { - {2, typeof(byte)}, - {3, typeof(double)}, - {4, typeof(float)}, - {5, typeof(int)}, - {6, typeof(short)}, - {7, typeof(long)}, - {8, typeof(bool)}, - {9, typeof(string)}, - {10, typeof(object[])}, - {11, typeof(IList)}, - {100, typeof(Vector2)}, - {101, typeof(Vector3)}, - {102, typeof(Vector4)}, - {103, typeof(Quaternion)} - }; - - public class EventEntry - { - public string type { get; set; } - public string dt { get; set; } - public int senderId { get; set; } - - - public int Type { get; set; } - public string EventType { get; set; } - public object Data { get; set; } - } - public class EventData - { - public string dt { get; set; } - public string type { get; set; } - public EventDataContainer OnEventData { get; set; } - public OperationContainer OnOperationResponseData { get; set; } - } - - public class EventDataContainer - { - public byte Code { get; set; } - public int Sender { get; set; } - public Dictionary Parameters { get; set; } - public byte SenderKey { get; set; } - public byte CustomDataKey { get; set; } - } - public class OperationContainer - { - public byte OperationCode { get; set; } - public short ReturnCode { get; set; } - public string DebugMessage { get; set; } - public Dictionary Parameters { get; set; } - } - - public static readonly List ignoreEvents = new List - { - "ReceiveVoiceStatsSyncRPC", - "initUSpeakSenderRPC", - "SanityCheck", - "UdonSyncRunProgramAsRPC", - "InformOfBadConnection", - "SetTimerRPC", - "IncrementPortalPlayerCountRPC", - "PlayEffect", - "PlayEmoteRPC", - "CancelRPC", - "_SendOnSpawn", - "RefreshAvatar", - "InternalApplyOverrideRPC" - }; - - private byte DeserializeByte() - { - return byteData[byteOffset++]; - } - - private int DeserializeInt() - { - int output = BitConverter.ToInt32(byteData, byteOffset); - byteOffset += 4; - return output; - } - - private short DeserializeShort() - { - short output = BitConverter.ToInt16(byteData, byteOffset); - byteOffset += 2; - return output; - } - - private string DeserializeString() - { - short stringLength = DeserializeShort(); - string output = Encoding.UTF8.GetString(byteData, byteOffset, stringLength); - byteOffset += stringLength; - return output; - } - - private bool DeserializeBool() - { - bool output = BitConverter.ToBoolean(byteData, byteOffset); - byteOffset++; - return output; - } - - private float DeserializeFloat() - { - float output = BitConverter.ToSingle(byteData, byteOffset); - byteOffset += 4; - return output; - } - - private double DeserializeDouble() - { - double output = BitConverter.ToDouble(byteData, byteOffset); - byteOffset += 8; - return output; - } - - private object DeserializeTypeArray() - { - short length = DeserializeShort(); - byte typeCode = DeserializeByte(); - var output = Array.CreateInstance(DataType[typeCode], length); - for (var i = 0; i < length; i++) - { - output.SetValue(DeserializeBytes(typeCode), i); - } - return output; - } - - private object[] DeserializeObjectArray() - { - short length = DeserializeShort(); - object[] output = new object[length]; - for (var i = 0; i < output.Length; i++) - { - output[i] = DeserializeBytes(); - } - return output; - } - - private long DeserializeInt64() - { - long output = BitConverter.ToInt64(byteData, byteOffset); - byteOffset += 8; - return output; - } - - private Vector2 DeserializeVector2() - { - return new Vector2(DeserializeFloat(), DeserializeFloat()); - } - - private Vector3 DeserializeVector3() - { - return new Vector3(DeserializeFloat(), DeserializeFloat(), DeserializeFloat()); - } - - private Vector4 DeserializeVector4() - { - return new Vector4(DeserializeFloat(), DeserializeFloat(), DeserializeFloat(), DeserializeFloat()); - } - - private Quaternion DeserializeQuaternion() - { - return new Quaternion(DeserializeFloat(), DeserializeFloat(), DeserializeFloat(), DeserializeFloat()); - } - - private object DeserializeBytes(byte type = 0) - { - if (type == 0) - { - type = DeserializeByte(); - } - switch (type) - { - case 1: - return null; - - case 2: - return DeserializeByte(); - - case 3: - return DeserializeDouble(); - - case 4: - return DeserializeFloat(); - - case 5: - return DeserializeInt(); - - case 6: - return DeserializeShort(); - - case 7: - return DeserializeInt64(); - - case 8: - return DeserializeBool(); - - case 9: - return DeserializeString(); - - case 10: - return DeserializeObjectArray(); - - case 11: - return DeserializeTypeArray(); - - case 100: - return DeserializeVector2(); - - case 101: - return DeserializeVector3(); - - case 102: - return DeserializeVector4(); - - case 103: - return DeserializeQuaternion(); - - default: - throw new Exception("Ignoring data type: " + type); - } - } - - public EventEntry DeserializeData(byte[] bytes) - { - EventEntry eventEntry = new EventEntry(); - byteOffset = 0; - byteData = bytes; - byte type = DeserializeByte(); - if (type == 106) - { - byteOffset += 8; - int length = DeserializeShort(); - byteOffset += length; - eventEntry.Type = DeserializeByte(); - byteOffset += 10; - eventEntry.EventType = DeserializeString(); - byteOffset += 5; - eventEntry.Data = null; - if (byteData.Length > byteOffset + 3) - { - byteData = (byte[])DeserializeTypeArray(); - byteOffset = 0; - eventEntry.Data = DeserializeBytes(); - } - } - else - { - throw new Exception("Unexpected type: " + type); - } - return eventEntry; - } - } -} \ No newline at end of file diff --git a/VRCX.csproj b/VRCX.csproj index eab8d9c1..6fd0497a 100644 --- a/VRCX.csproj +++ b/VRCX.csproj @@ -87,7 +87,6 @@ - diff --git a/html/src/app.js b/html/src/app.js index 4408a955..04e1524f 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -8727,9 +8727,7 @@ speechSynthesis.getVoices(); }; $app.methods.parsePhotonEvent = function (data, gameLogDate) { - if (data.Code === 226) { - // nothing - } else if (data.Code === 253) { + if (data.Code === 253) { // SetUserProperties this.parsePhotonUser( data.Parameters[253], @@ -8922,21 +8920,22 @@ speechSynthesis.getVoices(); } }; - $app.methods.parseVRCEvent = function (eventData) { + $app.methods.parseVRCEvent = function (json) { // VRC Event - var senderId = eventData.senderId; - var datetime = eventData.dt; + var datetime = json.dt; + var eventData = json.VRCEventData; + var senderId = eventData.Sender; if (this.debugPhotonLogging) { - console.log('VrcEvent:', eventData); + console.log('VrcEvent:', json); } if ( - eventData.EventType === '_InstantiateObject' && + eventData.EventName === '_InstantiateObject' && eventData.Data[0] === 'Portals/PortalInternalDynamic' ) { this.lastPortalId = eventData.Data[3]; return; } else if ( - eventData.EventType === '_DestroyObject' && + eventData.EventName === '_DestroyObject' && this.lastPortalList.has(eventData.Data[0]) ) { var portalId = eventData.Data[0]; @@ -8949,7 +8948,7 @@ speechSynthesis.getVoices(); created_at: datetime }); return; - } else if (eventData.EventType === 'ConfigurePortal') { + } else if (eventData.EventName === 'ConfigurePortal') { var instanceId = `${eventData.Data[0]}:${eventData.Data[1]}`; if (this.lastPortalId) { this.lastPortalList.set( @@ -8967,24 +8966,24 @@ speechSynthesis.getVoices(); this.parsePhotonPortalSpawn(datetime, instanceId, ref1); } return; - } else if (eventData.Type > 34) { + } else if (eventData.EventType > 34) { var entry = { created_at: datetime, type: 'Event', - data: `${displayName} called non existent RPC ${eventData.Type}` + data: `${displayName} called non existent RPC ${eventData.EventType}` }; this.addPhotonEventToGameLog(entry); } - if (eventData.Type === 14) { - if (eventData.EventType === 'ChangeVisibility') { + if (eventData.EventType === 14) { + if (eventData.EventName === 'ChangeVisibility') { if (eventData.Data[0] === true) { var text = 'EnableCamera'; } else if (eventData.Data[0] === false) { var text = 'DisableCamera'; } - } else if (eventData.EventType === 'ReloadAvatarNetworkedRPC') { + } else if (eventData.EventName === 'ReloadAvatarNetworkedRPC') { var text = 'AvatarReset'; - } else if (eventData.EventType === 'SpawnEmojiRPC') { + } else if (eventData.EventName === 'SpawnEmojiRPC') { var text = `SpawnEmoji ${this.photonEmojis[eventData.Data]}`; } else { var eventVrc = ''; @@ -8994,7 +8993,7 @@ speechSynthesis.getVoices(); '$1:' )}`; } - var text = `${eventData.EventType}${eventVrc}`; + var text = `${eventData.EventName}${eventVrc}`; } this.addEntryPhotonEvent({ photonId: senderId, @@ -9003,9 +9002,9 @@ speechSynthesis.getVoices(); created_at: datetime }); } else { - var eventType = ''; - if (eventData.EventType) { - eventType = ` ${JSON.stringify(eventData.EventType).replace( + var eventName = ''; + if (eventData.EventName) { + eventName = ` ${JSON.stringify(eventData.EventName).replace( /"([^(")"]+)":/g, '$1:' )}`; @@ -9013,8 +9012,8 @@ speechSynthesis.getVoices(); if (this.debugPhotonLogging) { var displayName = this.getDisplayNameFromPhotonId(senderId); var feed = `RPC ${displayName} ${ - this.photonEventType[eventData.Type] - }${eventType}`; + this.photonEventType[eventData.EventType] + }${eventName}`; console.log('VrcRpc:', feed); } } @@ -18842,6 +18841,9 @@ speechSynthesis.getVoices(); $app.data.ipcEnabled = false; $app.methods.ipcEvent = function (json) { + if (!this.friendLogInitStatus) { + return; + } try { var data = JSON.parse(json); } catch { @@ -18856,8 +18858,8 @@ speechSynthesis.getVoices(); data.OnEventData ); } - this.photonEventPulse(); this.parsePhotonEvent(data.OnEventData, data.dt); + this.photonEventPulse(); break; case 'OnOperationResponse': if (this.debugPhotonLogging) { @@ -18874,17 +18876,23 @@ speechSynthesis.getVoices(); this.photonEventPulse(); break; case 'VRCEvent': - this.photonEventPulse(); this.parseVRCEvent(data); + this.photonEventPulse(); break; - case 'Event7': - this.photonEvent7List.set(data.senderId, data.dt); + case 'Event7List': + for (var [id, dt] of Object.entries(data.Event7List)) { + this.photonEvent7List.set(parseInt(id, 10), dt); + } break; case 'Ping': if (!this.photonLoggingEnabled) { this.photonLoggingEnabled = true; configRepository.setBool('VRCX_photonLoggingEnabled', true); } + if (!this.companionUpdateReminder && data.version < '1.1.0') { + // check version + this.promptCompanionUpdateReminder(); + } this.ipcEnabled = true; this.ipcTimeout = 60; // 30secs break; @@ -18892,9 +18900,21 @@ speechSynthesis.getVoices(); AppApi.FocusWindow(); this.eventLaunchCommand(data.command); break; + default: + console.log('IPC:', data); } }; + $app.data.companionUpdateReminder = false; + + $app.methods.promptCompanionUpdateReminder = function () { + this.$alert( + 'An update is required for it to function properly.', + 'VRCX Companion mod is out of date' + ); + this.companionUpdateReminder = true; + }; + $app.data.photonEventCount = 0; $app.data.photonEventIcon = false;