Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PhotonV4ServerVoiceFix v2.1.1
PhotonVoiceFix.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Photon.Realtime; using Photon.Voice; using Photon.Voice.Unity; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] [BepInPlugin("com.gil.photonvoicefix", "Photon Voice Fix", "2.1.1")] public class VoiceFixPlugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry<bool> ForceSequenced; internal static ConfigEntry<bool> LogStats; private void Awake() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_0176: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ForceSequenced = ((BaseUnityPlugin)this).Config.Bind<bool>("Fix", "ForceSequencedDelivery", true, "Send voice frames as Unreliable/Reliable instead of the Unsequenced modes Photon Server v4 doesn't support."); LogStats = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogVoiceStats", true, "Log voice frames sent/received every 5 seconds while in a room."); Harmony val = new Harmony("com.gil.photonvoicefix"); val.Patch((MethodBase)AccessTools.Method(typeof(VoiceConnection), "Init", (Type[])null, (Type[])null), new HarmonyMethod(typeof(VoicePatches), "InitPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(LoadBalancingTransport), "SendFrame", (Type[])null, (Type[])null), new HarmonyMethod(typeof(VoicePatches), "SendFramePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(LoadBalancingTransport2), "buildFrameMessage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(VoicePatches), "BuildFramePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(LoadBalancingTransport2), "onEventActionVoiceClient", (Type[])null, (Type[])null), new HarmonyMethod(typeof(VoicePatches), "OnEventPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.PropertySetter(typeof(LocalVoice), "TransmitEnabled"), new HarmonyMethod(typeof(VoicePatches), "TransmitPrefix", (Type[])null), new HarmonyMethod(typeof(VoicePatches), "TransmitPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)("VoiceFix 2.1.1 active (ForceSequencedDelivery=" + ForceSequenced.Value + ")")); } } public static class VoicePatches { private static readonly FieldInfo cppCompat = AccessTools.Field(typeof(VoiceConnection), "cppCompatibilityMode"); private static readonly object statsLock = new object(); private static readonly Stopwatch statsTimer = Stopwatch.StartNew(); private static int framesSent; private static int infoEvents; private static readonly Dictionary<int, int> framesFrom = new Dictionary<int, int>(); public static void InitPrefix(VoiceConnection __instance) { if (VoiceFixPlugin.ForceSequenced.Value) { cppCompat.SetValue(__instance, true); VoiceFixPlugin.Log.LogInfo((object)("Forced sequenced voice delivery on " + ((Object)__instance).name)); } } public static void SendFramePrefix() { lock (statsLock) { framesSent++; } MaybeFlushStats(); } public static void BuildFramePostfix(LoadBalancingTransport2 __instance, ref object __result) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 object obj = __result; ByteArraySlice val = (ByteArraySlice)((obj is ByteArraySlice) ? obj : null); if (val != null && (int)((PhotonPeer)((LoadBalancingClient)__instance).LoadBalancingPeer).SerializationProtocolType == 0) { byte[] array = new byte[val.Count]; Buffer.BlockCopy(val.Buffer, val.Offset, array, 0, val.Count); val.Release(); __result = array; } } public static void OnEventPrefix(EventData ev) { lock (statsLock) { if (ev.Code == 203) { framesFrom.TryGetValue(ev.Sender, out var value); framesFrom[ev.Sender] = value + 1; } else if (ev.Code == 202) { infoEvents++; } } MaybeFlushStats(); } public static void TransmitPrefix(LocalVoice __instance, out bool __state) { __state = __instance.TransmitEnabled; } public static void TransmitPostfix(LocalVoice __instance, bool __state) { if (__instance.TransmitEnabled != __state) { VoiceFixPlugin.Log.LogInfo((object)("[Voice] transmit " + (__instance.TransmitEnabled ? "ON" : "OFF"))); } } private static void MaybeFlushStats() { if (!VoiceFixPlugin.LogStats.Value) { return; } string text; lock (statsLock) { if (statsTimer.ElapsedMilliseconds < 5000) { return; } statsTimer.Reset(); statsTimer.Start(); StringBuilder stringBuilder = new StringBuilder("[Voice] last 5s: sent=" + framesSent + " infoEvents=" + infoEvents + " recv="); if (framesFrom.Count == 0) { stringBuilder.Append("none"); } foreach (KeyValuePair<int, int> item in framesFrom) { stringBuilder.Append("actor").Append(item.Key).Append(':') .Append(item.Value) .Append(' '); } text = stringBuilder.ToString(); framesSent = 0; infoEvents = 0; framesFrom.Clear(); } VoiceFixPlugin.Log.LogInfo((object)text); } }