Decompiled source of PhotonV4ServerVoiceFix v2.1.1

PhotonVoiceFix.dll

Decompiled a month ago
using 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);
	}
}