Decompiled source of REPOPatch v1.0.0

off_grid.REPOPatch.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using REPOPatch.Features;
using REPOPatch.Patches;
using REPOPatch.Services;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("off_grid.REPOPatch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("REPOPatch")]
[assembly: AssemblyTitle("off_grid.REPOPatch")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace REPOPatch
{
	[BepInPlugin("off_grid.REPOPatch", "REPOPatch", "1.0.0")]
	public class REPOPatch : BaseUnityPlugin
	{
		internal static Harmony Harmony = new Harmony("off_grid.REPOPatch");

		internal static bool Patch_SendBufferFull = true;

		internal static int SBF_MaxQueuedStatUpdates = 2000;

		internal static int SBF_MaxSendsPerFlush = 25;

		internal static float SBF_FlushInterval = 0.08f;

		internal static bool SBF_DropWhenFull = true;

		public ConfigFile config;

		public static REPOPatch Instance { get; private set; } = null;


		internal static ManualLogSource Logger { get; private set; } = null;


		private void Setup()
		{
			if (Patch_SendBufferFull)
			{
				PunManagerPatch.EnablePatch();
			}
			Logger.LogInfo((object)"<--- Setup Finished --->");
		}

		private void NetworkSetup()
		{
			Logger.LogInfo((object)"<--- Network Finished --->");
		}

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			FileManager.InitializeConfig();
			Setup();
			NetworkSetup();
			Harmony.PatchAll();
			Logger.LogInfo((object)"off_grid.REPOPatch v1.0.0 has fully loaded!");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "off_grid.REPOPatch";

		public const string PLUGIN_NAME = "REPOPatch";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace REPOPatch.Services
{
	internal class Networking
	{
	}
	internal static class PhotonViewCache
	{
		private static readonly Dictionary<int, PhotonView> s_cache = new Dictionary<int, PhotonView>(1024);

		private static readonly object s_lock = new object();

		public static bool TryGet(int viewID, out PhotonView? pv)
		{
			lock (s_lock)
			{
				if (s_cache.TryGetValue(viewID, out pv))
				{
					if ((Object)(object)pv == (Object)null)
					{
						s_cache.Remove(viewID);
						pv = null;
						return false;
					}
					return true;
				}
			}
			pv = null;
			return false;
		}

		public static void Store(int viewID, PhotonView pv)
		{
			if ((Object)(object)pv == (Object)null)
			{
				return;
			}
			lock (s_lock)
			{
				s_cache[viewID] = pv;
			}
		}

		public static void Invalidate(int viewID)
		{
			lock (s_lock)
			{
				s_cache.Remove(viewID);
			}
		}

		public static void Clear()
		{
			lock (s_lock)
			{
				s_cache.Clear();
			}
		}
	}
	internal static class ListPool<T>
	{
		private const int MaxPoolSize = 256;

		private static readonly Stack<List<T>> s_pool = new Stack<List<T>>(64);

		private static readonly object s_lock = new object();

		public static List<T> Get(int capacity = 0)
		{
			lock (s_lock)
			{
				if (s_pool.Count > 0)
				{
					List<T> list = s_pool.Pop();
					if (capacity > list.Capacity)
					{
						list.Capacity = capacity;
					}
					list.Clear();
					return list;
				}
			}
			if (capacity <= 0)
			{
				return new List<T>();
			}
			return new List<T>(capacity);
		}

		public static void Release(List<T> list)
		{
			if (list == null)
			{
				return;
			}
			list.Clear();
			lock (s_lock)
			{
				if (s_pool.Count < 256)
				{
					s_pool.Push(list);
				}
			}
		}

		public static void ReleaseRange(IEnumerable<List<T>> lists)
		{
			if (lists == null)
			{
				return;
			}
			lock (s_lock)
			{
				foreach (List<T> list in lists)
				{
					if (list != null)
					{
						list.Clear();
						if (s_pool.Count < 256)
						{
							s_pool.Push(list);
						}
					}
				}
			}
		}
	}
	internal static class DictionaryPool<TKey, TValue>
	{
		private const int MaxPoolSize = 128;

		private static readonly Stack<Dictionary<TKey, TValue>> s_pool = new Stack<Dictionary<TKey, TValue>>(32);

		private static readonly object s_lock = new object();

		public static Dictionary<TKey, TValue> Get(int capacity = 0)
		{
			lock (s_lock)
			{
				if (s_pool.Count > 0)
				{
					Dictionary<TKey, TValue> dictionary = s_pool.Pop();
					dictionary.Clear();
					return dictionary;
				}
			}
			if (capacity <= 0)
			{
				return new Dictionary<TKey, TValue>();
			}
			return new Dictionary<TKey, TValue>(capacity);
		}

		public static void Release(Dictionary<TKey, TValue> d)
		{
			if (d == null)
			{
				return;
			}
			d.Clear();
			lock (s_lock)
			{
				if (s_pool.Count < 128)
				{
					s_pool.Push(d);
				}
			}
		}

		public static void ReleaseRange(IEnumerable<Dictionary<TKey, TValue>> items)
		{
			if (items == null)
			{
				return;
			}
			lock (s_lock)
			{
				foreach (Dictionary<TKey, TValue> item in items)
				{
					if (item != null)
					{
						item.Clear();
						if (s_pool.Count < 128)
						{
							s_pool.Push(item);
						}
					}
				}
			}
		}
	}
	internal static class PhotonHashtablePool
	{
		private const int MaxPoolSize = 256;

		private static readonly Stack<Hashtable> s_pool = new Stack<Hashtable>(64);

		private static readonly object s_lock = new object();

		public static Hashtable Get(int capacity = 0)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			lock (s_lock)
			{
				if (s_pool.Count > 0)
				{
					Hashtable val = s_pool.Pop();
					((Dictionary<object, object>)(object)val).Clear();
					return val;
				}
			}
			return new Hashtable();
		}

		public static void Release(Hashtable ht)
		{
			if (ht == null)
			{
				return;
			}
			((Dictionary<object, object>)(object)ht).Clear();
			lock (s_lock)
			{
				if (s_pool.Count < 256)
				{
					s_pool.Push(ht);
				}
			}
		}

		public static void ReleaseRange(IEnumerable<Hashtable> items)
		{
			if (items == null)
			{
				return;
			}
			lock (s_lock)
			{
				foreach (Hashtable item in items)
				{
					if (item != null)
					{
						((Dictionary<object, object>)(object)item).Clear();
						if (s_pool.Count < 256)
						{
							s_pool.Push(item);
						}
					}
				}
			}
		}
	}
	public class StatThrottler : MonoBehaviour
	{
		private struct Pending
		{
			public PunManager manager;

			public string dict;

			public string key;

			public int val;

			public Pending(PunManager m, string d, string k, int v)
			{
				manager = m;
				dict = d;
				key = k;
				val = v;
			}
		}

		[CompilerGenerated]
		private sealed class <FlushLoop>d__11 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public StatThrottler <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <FlushLoop>d__11(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ed: Expected O, but got Unknown
				//IL_0053: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				StatThrottler statThrottler = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (statThrottler.queue.Count > 0)
				{
					for (int i = 0; i < Math.Min(REPOPatch.SBF_MaxSendsPerFlush, statThrottler.queue.Count); i++)
					{
						Pending pending = statThrottler.queue.Dequeue();
						try
						{
							pending.manager.UpdateStatRPC(pending.dict, pending.key, pending.val, default(PhotonMessageInfo));
							if (!statThrottler.lastSent.TryGetValue(pending.dict, out Dictionary<string, int> value))
							{
								value = new Dictionary<string, int>();
								statThrottler.lastSent[pending.dict] = value;
							}
							value[pending.key] = pending.val;
						}
						catch (Exception arg)
						{
							REPOPatch.Logger.LogWarning((object)$"> StatThrottler send failed: {arg}");
						}
					}
					<>2__current = (object)new WaitForSeconds(REPOPatch.SBF_FlushInterval);
					<>1__state = 1;
					return true;
				}
				statThrottler.flushRoutine = null;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private readonly Queue<Pending> queue = new Queue<Pending>();

		private readonly Dictionary<string, Dictionary<string, int>> lastSent = new Dictionary<string, Dictionary<string, int>>();

		private Coroutine? flushRoutine;

		public static StatThrottler? Instance { get; private set; }

		public static StatThrottler CreateOrGet()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			if ((Object)(object)Instance != (Object)null)
			{
				return Instance;
			}
			Instance = Object.FindObjectOfType<StatThrottler>();
			if ((Object)(object)Instance != (Object)null)
			{
				return Instance;
			}
			GameObject val = new GameObject("StatThrottler");
			Object.DontDestroyOnLoad((Object)(object)val);
			Instance = val.AddComponent<StatThrottler>();
			return Instance;
		}

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}

		public void Enqueue(PunManager manager, string dict, string key, int value)
		{
			if ((Object)(object)manager == (Object)null || (lastSent.TryGetValue(dict, out Dictionary<string, int> value2) && value2.TryGetValue(key, out var value3) && value3 == value))
			{
				return;
			}
			if (queue.Count >= REPOPatch.SBF_MaxQueuedStatUpdates)
			{
				if (REPOPatch.SBF_DropWhenFull)
				{
					return;
				}
				queue.Dequeue();
			}
			queue.Enqueue(new Pending(manager, dict, key, value));
			if (flushRoutine == null)
			{
				flushRoutine = ((MonoBehaviour)this).StartCoroutine(FlushLoop());
			}
		}

		[IteratorStateMachine(typeof(<FlushLoop>d__11))]
		private IEnumerator FlushLoop()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <FlushLoop>d__11(0)
			{
				<>4__this = this
			};
		}

		public void FlushAllNow()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			while (queue.Count > 0)
			{
				Pending pending = queue.Dequeue();
				try
				{
					pending.manager.UpdateStatRPC(pending.dict, pending.key, pending.val, default(PhotonMessageInfo));
				}
				catch
				{
				}
			}
		}
	}
}
namespace REPOPatch.Patches
{
	[HarmonyPatch]
	internal static class PhotonAndCanvasPatches
	{
		private static readonly Dictionary<int, MaterialPropertyBlock> s_rendererBlocks = new Dictionary<int, MaterialPropertyBlock>();

		private static readonly object s_lock = new object();

		private static readonly ConditionalWeakTable<object, Coroutine> s_wiggleCoroutines = new ConditionalWeakTable<object, Coroutine>();

		[HarmonyPatch(typeof(PhotonView), "OnDestroy")]
		[HarmonyPostfix]
		private static void PhotonView_OnDestroy_Postfix(PhotonView __instance)
		{
			try
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				int num = 0;
				try
				{
					num = __instance.ViewID;
				}
				catch
				{
					PropertyInfo property = typeof(PhotonView).GetProperty("ViewID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (property != null)
					{
						num = (int)property.GetValue(__instance);
					}
				}
				if (num > 0)
				{
					PhotonViewCache.Invalidate(num);
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(CanvasHandler), "SetMaterialAlpha")]
		[HarmonyPrefix]
		private static bool CanvasHandler_SetMaterialAlpha_Prefix(MeshRenderer renderer, float alpha)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)renderer == (Object)null)
				{
					return false;
				}
				int num = Shader.PropertyToID("_Color");
				int instanceID = ((Object)renderer).GetInstanceID();
				MaterialPropertyBlock value;
				lock (s_lock)
				{
					if (!s_rendererBlocks.TryGetValue(instanceID, out value))
					{
						value = new MaterialPropertyBlock();
						s_rendererBlocks[instanceID] = value;
					}
				}
				Color val = Color.white;
				try
				{
					Material sharedMaterial = ((Renderer)renderer).sharedMaterial;
					if ((Object)(object)sharedMaterial != (Object)null)
					{
						val = sharedMaterial.color;
					}
				}
				catch
				{
				}
				val.a = Mathf.Clamp01(alpha);
				value.SetColor(num, val);
				((Renderer)renderer).SetPropertyBlock(value);
				return false;
			}
			catch (Exception arg)
			{
				REPOPatch.Logger.LogWarning((object)$"> CanvasHandler SetMaterialAlpha exception: {arg}");
				return true;
			}
		}

		[HarmonyPatch(typeof(CanvasHandler), "StartWiggle")]
		[HarmonyPrefix]
		private static bool StartWiggle_Prefix(object __instance)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			try
			{
				Type type = __instance.GetType();
				FieldInfo fieldInfo = AccessTools.Field(type, "DustParticles");
				ParticleSystem val = (ParticleSystem)fieldInfo.GetValue(__instance);
				float num = (float)AccessTools.Field(type, "wiggleAmount").GetValue(__instance);
				FieldInfo fieldInfo2 = AccessTools.Field(type, "currentWiggleAmount");
				FieldInfo fieldInfo3 = AccessTools.Field(type, "isWiggling");
				if (s_wiggleCoroutines.TryGetValue(__instance, out Coroutine value) && value != null)
				{
					try
					{
						object obj = ((__instance is MonoBehaviour) ? __instance : null);
						if (obj != null)
						{
							((MonoBehaviour)obj).StopCoroutine(value);
						}
					}
					catch
					{
					}
					try
					{
						s_wiggleCoroutines.Remove(__instance);
					}
					catch
					{
					}
				}
				fieldInfo3.SetValue(__instance, true);
				try
				{
					if ((Object)(object)val != (Object)null && !val.isPlaying)
					{
						val.Play();
					}
				}
				catch
				{
				}
				fieldInfo2.SetValue(__instance, num);
				MethodInfo methodInfo = AccessTools.Method(type, "WiggleCoroutine", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					IEnumerator enumerator = (IEnumerator)methodInfo.Invoke(__instance, null);
					if (enumerator != null)
					{
						object obj5 = ((__instance is MonoBehaviour) ? __instance : null);
						Coroutine val2 = ((obj5 != null) ? ((MonoBehaviour)obj5).StartCoroutine(enumerator) : null);
						if (val2 != null)
						{
							try
							{
								s_wiggleCoroutines.Add(__instance, val2);
							}
							catch
							{
								try
								{
									s_wiggleCoroutines.Remove(__instance);
									s_wiggleCoroutines.Add(__instance, val2);
								}
								catch
								{
								}
							}
						}
					}
				}
				return false;
			}
			catch (Exception arg)
			{
				REPOPatch.Logger.LogWarning((object)$"> CanvasHandler StartWiggle prefix exception: {arg}");
				return true;
			}
		}

		[HarmonyPatch(typeof(CanvasHandler), "StopWiggle")]
		[HarmonyPrefix]
		private static bool StopWiggle_Prefix(object __instance)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			try
			{
				Type type = __instance.GetType();
				FieldInfo fieldInfo = AccessTools.Field(type, "DustParticles");
				ParticleSystem val = (ParticleSystem)fieldInfo.GetValue(__instance);
				FieldInfo fieldInfo2 = AccessTools.Field(type, "isWiggling");
				try
				{
					if ((Object)(object)val != (Object)null && val.isPlaying)
					{
						val.Stop();
					}
				}
				catch
				{
				}
				fieldInfo2.SetValue(__instance, false);
				if (s_wiggleCoroutines.TryGetValue(__instance, out Coroutine value) && value != null)
				{
					try
					{
						object obj2 = ((__instance is MonoBehaviour) ? __instance : null);
						if (obj2 != null)
						{
							((MonoBehaviour)obj2).StopCoroutine(value);
						}
					}
					catch
					{
					}
					try
					{
						s_wiggleCoroutines.Remove(__instance);
					}
					catch
					{
					}
				}
				return false;
			}
			catch (Exception arg)
			{
				REPOPatch.Logger.LogWarning((object)$"> CanvasHandler StopWiggle prefix exception: {arg}");
				return true;
			}
		}
	}
	[HarmonyPatch]
	public static class RenderTextureMain_Optimizations
	{
		[HarmonyPatch(typeof(RenderTextureMain), "SetRenderTexture")]
		[HarmonyPrefix]
		private static bool SetRenderTexture_Prefix(object __instance)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			try
			{
				Type type = __instance.GetType();
				FieldInfo fieldInfo = AccessTools.Field(type, "renderTexture");
				RenderTexture val = (RenderTexture)fieldInfo.GetValue(__instance);
				float num = (float)AccessTools.Field(type, "textureWidth").GetValue(__instance);
				float num2 = (float)AccessTools.Field(type, "textureHeight").GetValue(__instance);
				int num3 = (int)num;
				int num4 = (int)num2;
				if (((Texture)val).width != num3 || ((Texture)val).height != num4 || !val.IsCreated())
				{
					try
					{
						if (val.IsCreated())
						{
							val.Release();
						}
						((Texture)val).width = num3;
						((Texture)val).height = num4;
						val.Create();
					}
					catch (Exception arg)
					{
						REPOPatch.Logger.LogError((object)$"> Error resetting RenderTexture: {arg}");
						return true;
					}
				}
				else
				{
					REPOPatch.Logger.LogInfo((object)"> RenderTexture already has correct dimensions and is created.");
				}
				FieldInfo fieldInfo2 = AccessTools.Field(type, "cameras");
				if (fieldInfo2.GetValue(__instance) is IList list)
				{
					foreach (Camera item in list)
					{
						Camera val2 = item;
						try
						{
							val2.targetTexture = val;
							((Behaviour)val2).enabled = false;
							((Behaviour)val2).enabled = true;
						}
						catch (Exception arg2)
						{
							REPOPatch.Logger.LogError((object)$"> Error updating camera target texture: {arg2}");
						}
					}
				}
				return false;
			}
			catch (Exception arg3)
			{
				REPOPatch.Logger.LogWarning((object)$"> SetRenderTexture prefix exception: {arg3}");
				return true;
			}
		}
	}
	[HarmonyPatch]
	internal static class PunManagerAdvancedPatches
	{
		[HarmonyPatch(typeof(PunManager), "ConvertToHashtable")]
		[HarmonyPrefix]
		private static bool ConvertToHashtable_Prefix(object __instance, Dictionary<string, int> dictionary, ref Hashtable? __result)
		{
			try
			{
				if (dictionary == null)
				{
					__result = null;
					return false;
				}
				Hashtable val = PhotonHashtablePool.Get(dictionary.Count);
				foreach (KeyValuePair<string, int> item in dictionary)
				{
					((Dictionary<object, object>)(object)val).Add((object)item.Key, (object)item.Value);
				}
				__result = val;
				return false;
			}
			catch (Exception arg)
			{
				REPOPatch.Logger.LogWarning((object)$"> ConvertToHashtable prefix exception: {arg}");
				return true;
			}
		}

		[HarmonyPatch(typeof(PunManager), "SyncAllDictionaries")]
		[HarmonyPrefix]
		private static bool SyncAllDictionaries_Prefix(object __instance)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			try
			{
				Type type = __instance.GetType();
				FieldInfo fieldInfo = AccessTools.Field(type, "statsManager");
				FieldInfo fieldInfo2 = AccessTools.Field(type, "syncData");
				FieldInfo fieldInfo3 = AccessTools.Field(type, "photonView");
				object value = fieldInfo.GetValue(__instance);
				List<Hashtable> list = (List<Hashtable>)fieldInfo2.GetValue(__instance);
				PhotonView val = (PhotonView)fieldInfo3.GetValue(__instance);
				Type type2 = value.GetType();
				FieldInfo fieldInfo4 = AccessTools.Field(type2, "statsSynced");
				if (fieldInfo4 != null)
				{
					fieldInfo4.SetValue(value, true);
				}
				if (!SemiFunc.IsMultiplayer() || !PhotonNetwork.IsMasterClient)
				{
					REPOPatch.Logger.LogWarning((object)"> SyncAllDictionaries patch failed: Not in multiplayer, so not point in patching...");
					return false;
				}
				list.Clear();
				FieldInfo fieldInfo5 = AccessTools.Field(type2, "dictionaryOfDictionaries");
				Dictionary<string, Dictionary<string, int>> dictionary = (Dictionary<string, Dictionary<string, int>>)fieldInfo5.GetValue(value);
				if (dictionary == null || dictionary.Count == 0)
				{
					REPOPatch.Logger.LogError((object)"> SyncAllDictionaries patch failed: DAa!2");
					return false;
				}
				Hashtable val2 = PhotonHashtablePool.Get();
				int num = 0;
				int num2 = 0;
				int count = dictionary.Count;
				MethodInfo methodInfo = AccessTools.Method(__instance.GetType(), "ConvertToHashtable", new Type[1] { typeof(Dictionary<string, int>) }, (Type[])null);
				foreach (KeyValuePair<string, Dictionary<string, int>> item in dictionary)
				{
					Hashtable value2 = (Hashtable)methodInfo.Invoke(__instance, new object[1] { item.Value });
					((Dictionary<object, object>)(object)val2).Add((object)item.Key, (object)value2);
					num++;
					num2++;
					if (num > 3 || num2 == count)
					{
						list.Add(val2);
						val2 = PhotonHashtablePool.Get();
						num = 0;
					}
				}
				if (val2 != null && ((Dictionary<object, object>)(object)val2).Count == 0)
				{
					PhotonHashtablePool.Release(val2);
				}
				for (int i = 0; i < list.Count; i++)
				{
					bool flag = i == list.Count - 1;
					Hashtable val3 = list[i];
					try
					{
						val.RPC("ReceiveSyncData", (RpcTarget)1, new object[2] { val3, flag });
					}
					catch (Exception arg)
					{
						REPOPatch.Logger.LogWarning((object)$"> SyncAllDictionaries RPC send failed: {arg}");
					}
				}
				foreach (Hashtable item2 in list)
				{
					if (item2 == null)
					{
						continue;
					}
					List<Hashtable> list2 = ListPool<Hashtable>.Get(((Dictionary<object, object>)(object)item2).Count);
					DictionaryEntryEnumerator enumerator3 = item2.GetEnumerator();
					try
					{
						while (((DictionaryEntryEnumerator)(ref enumerator3)).MoveNext())
						{
							object? value3 = ((DictionaryEntryEnumerator)(ref enumerator3)).Current.Value;
							Hashtable val4 = (Hashtable)((value3 is Hashtable) ? value3 : null);
							if (val4 != null)
							{
								list2.Add(val4);
							}
						}
					}
					finally
					{
						((IDisposable)(DictionaryEntryEnumerator)(ref enumerator3)).Dispose();
					}
					foreach (Hashtable item3 in list2)
					{
						PhotonHashtablePool.Release(item3);
					}
					ListPool<Hashtable>.Release(list2);
					PhotonHashtablePool.Release(item2);
				}
				list.Clear();
				return false;
			}
			catch (Exception arg2)
			{
				REPOPatch.Logger.LogWarning((object)$"> SyncAllDictionaries prefix exception: {arg2}");
				return true;
			}
		}

		[HarmonyPatch(typeof(PunManager), "TruckPopulateItemVolumes")]
		[HarmonyPrefix]
		private static bool TruckPopulateItemVolumes_Prefix(object __instance)
		{
			try
			{
				Type type = __instance.GetType();
				FieldInfo fieldInfo = AccessTools.Field(type, "itemManager");
				object value = fieldInfo.GetValue(__instance);
				if (value == null)
				{
					REPOPatch.Logger.LogError((object)"> TruckPopulateItemVolumes patch failed: DAa!1");
					return true;
				}
				if (AccessTools.Field(value.GetType(), "spawnedItems")?.GetValue(value) is IList list)
				{
					list.Clear();
				}
				MethodInfo method = typeof(SemiFunc).GetMethod("IsNotMasterClient", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null && (bool)method.Invoke(null, null))
				{
					REPOPatch.Logger.LogError((object)"> TruckPopulateItemVolumes patch failed: DAa!2");
					return false;
				}
				FieldInfo fieldInfo2 = AccessTools.Field(value.GetType(), "itemVolumes");
				FieldInfo fieldInfo3 = AccessTools.Field(value.GetType(), "purchasedItems");
				List<object> list2 = fieldInfo2.GetValue(value) as List<object>;
				List<object> list3 = fieldInfo3.GetValue(value) as List<object>;
				int capacity = list2?.Count ?? 0;
				int capacity2 = list3?.Count ?? 0;
				List<object> list4 = ListPool<object>.Get(capacity);
				List<object> list5 = ListPool<object>.Get(capacity2);
				try
				{
					if (list2 != null)
					{
						list4.AddRange(list2);
					}
					if (list3 != null)
					{
						list5.AddRange(list3);
					}
					while (list4.Count > 0 && list5.Count > 0)
					{
						bool flag = false;
						for (int i = 0; i < list5.Count; i++)
						{
							object obj = list5[i];
							object obj2 = null;
							foreach (object item in list4)
							{
								try
								{
									Type type2 = item.GetType();
									FieldInfo field = type2.GetField("itemVolume", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									Type type3 = obj.GetType();
									FieldInfo field2 = type3.GetField("itemVolume", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									object obj3 = ((field != null) ? field.GetValue(item) : null);
									object obj4 = ((field2 != null) ? field2.GetValue(obj) : null);
									if (obj3 != null && obj4 != null && obj3.Equals(obj4))
									{
										obj2 = item;
										break;
									}
								}
								catch
								{
								}
							}
							if (obj2 != null)
							{
								MethodInfo method2 = type.GetMethod("SpawnItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
								if (method2 != null)
								{
									method2.Invoke(__instance, new object[2] { obj, obj2 });
								}
								list4.Remove(obj2);
								list5.RemoveAt(i);
								flag = true;
								break;
							}
						}
						if (!flag)
						{
							break;
						}
					}
					if (list2 != null)
					{
						foreach (object item2 in list2)
						{
							if (item2 == null)
							{
								continue;
							}
							try
							{
								FieldInfo field3 = item2.GetType().GetField("gameObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
								if (field3 != null)
								{
									object? value2 = field3.GetValue(item2);
									GameObject val = (GameObject)((value2 is GameObject) ? value2 : null);
									if ((Object)(object)val != (Object)null)
									{
										Object.Destroy((Object)(object)val);
									}
								}
							}
							catch
							{
							}
						}
					}
				}
				finally
				{
					ListPool<object>.Release(list4);
					ListPool<object>.Release(list5);
				}
				return false;
			}
			catch (Exception arg)
			{
				REPOPatch.Logger.LogWarning((object)$"> TruckPopulateItemVolumes pooled prefix exception: {arg}");
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(PunManager), "UpdateStat", new Type[]
	{
		typeof(string),
		typeof(string),
		typeof(int)
	})]
	internal static class PunManagerPatch
	{
		private static volatile bool _enabled;

		public static void EnablePatch()
		{
			_enabled = true;
			StatThrottler.CreateOrGet();
			REPOPatch.Logger.LogInfo((object)"> PunManagerPatch enabled.");
		}

		public static void DisablePatch()
		{
			_enabled = false;
			REPOPatch.Logger.LogInfo((object)"> PunManagerPatch disabled.");
		}

		public static bool IsEnabled()
		{
			return _enabled;
		}

		private static bool Prefix(PunManager __instance, string dictionaryName, string key, int value)
		{
			if (!_enabled)
			{
				return true;
			}
			try
			{
				StatThrottler statThrottler = StatThrottler.CreateOrGet();
				statThrottler.Enqueue(__instance, dictionaryName, key, value);
				return false;
			}
			catch (Exception arg)
			{
				REPOPatch.Logger.LogWarning((object)$"> PunManagerPatch Prefix exception: {arg}");
				return true;
			}
		}
	}
	[HarmonyPatch]
	internal static class PunManagerPoolsAndPhotonFindPatches
	{
		[HarmonyPatch(typeof(PhotonView), "Find", new Type[] { typeof(int) })]
		[HarmonyPrefix]
		private static bool PhotonView_Find_Prefix(int viewID, ref PhotonView __result)
		{
			if (viewID <= 0)
			{
				return true;
			}
			if (PhotonViewCache.TryGet(viewID, out PhotonView pv))
			{
				__result = pv;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(PhotonView), "Find", new Type[] { typeof(int) })]
		[HarmonyPostfix]
		private static void PhotonView_Find_Postfix(int viewID, PhotonView __result)
		{
			if ((Object)(object)__result != (Object)null && viewID > 0)
			{
				PhotonViewCache.Store(viewID, __result);
			}
		}

		[HarmonyPatch(typeof(PunManager), "ReceiveSyncData")]
		[HarmonyPrefix]
		private static bool ReceiveSyncData_Prefix(object __instance, Hashtable data, bool finalChunk, PhotonMessageInfo _info = default(PhotonMessageInfo))
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(SemiFunc), "MasterOnlyRPC", (Type[])null, (Type[])null);
				if (methodInfo != null && !(bool)methodInfo.Invoke(null, new object[1] { _info }))
				{
					REPOPatch.Logger.LogError((object)"> ReceiveSyncData patch failed: DAa!1");
					return false;
				}
				if (data == null || ((Dictionary<object, object>)(object)data).Count == 0)
				{
					REPOPatch.Logger.LogError((object)"> ReceiveSyncData patch failed: DAa!2");
					return false;
				}
				Type type = __instance.GetType();
				FieldInfo fieldInfo = AccessTools.Field(type, "statsManager");
				if (fieldInfo == null)
				{
					REPOPatch.Logger.LogError((object)"> ReceiveSyncData patch failed: DAa!3");
					return true;
				}
				object value = fieldInfo.GetValue(__instance);
				if (value == null)
				{
					REPOPatch.Logger.LogError((object)"> ReceiveSyncData patch failed: DAa!4");
					return true;
				}
				Type type2 = value.GetType();
				FieldInfo fieldInfo2 = AccessTools.Field(type2, "dictionaryOfDictionaries");
				if (fieldInfo2 == null)
				{
					REPOPatch.Logger.LogError((object)"> ReceiveSyncData patch failed: DAa!4");
					return true;
				}
				if (!(fieldInfo2.GetValue(value) is Dictionary<string, Dictionary<string, int>> dictionary))
				{
					REPOPatch.Logger.LogError((object)"> ReceiveSyncData patch failed: DAa!5");
					return true;
				}
				DictionaryEntryEnumerator enumerator = data.GetEnumerator();
				try
				{
					while (((DictionaryEntryEnumerator)(ref enumerator)).MoveNext())
					{
						DictionaryEntry current = ((DictionaryEntryEnumerator)(ref enumerator)).Current;
						if (!(current.Key is string key) || !dictionary.TryGetValue(key, out var value2) || value2 == null)
						{
							continue;
						}
						object? value3 = current.Value;
						Hashtable val = (Hashtable)((value3 is Hashtable) ? value3 : null);
						if (val == null)
						{
							continue;
						}
						DictionaryEntryEnumerator enumerator2 = val.GetEnumerator();
						try
						{
							while (((DictionaryEntryEnumerator)(ref enumerator2)).MoveNext())
							{
								DictionaryEntry current2 = ((DictionaryEntryEnumerator)(ref enumerator2)).Current;
								if (current2.Key is string key2 && current2.Value is int value4)
								{
									value2[key2] = value4;
								}
							}
						}
						finally
						{
							((IDisposable)(DictionaryEntryEnumerator)(ref enumerator2)).Dispose();
						}
					}
				}
				finally
				{
					((IDisposable)(DictionaryEntryEnumerator)(ref enumerator)).Dispose();
				}
				if (finalChunk)
				{
					AccessTools.Field(type2, "statsSynced")?.SetValue(value, true);
				}
				return false;
			}
			catch (Exception arg)
			{
				REPOPatch.Logger.LogWarning((object)$"> ReceiveSyncData prefix exception: {arg}");
				return true;
			}
		}

		[HarmonyPatch(typeof(PunManager), "ShopUpdateCost")]
		[HarmonyPrefix]
		private static bool ShopUpdateCost_Prefix(PunManager __instance)
		{
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ShopManager instance = ShopManager.instance;
				FieldInfo fieldInfo = AccessTools.Field(((object)instance).GetType(), "shoppingList");
				if (fieldInfo == null)
				{
					REPOPatch.Logger.LogError((object)"> ShopUpdateCost patch failed: DAa!1");
					return true;
				}
				if (!(fieldInfo.GetValue(instance) is IList list))
				{
					REPOPatch.Logger.LogError((object)"> ShopUpdateCost patch failed: DAa!2");
					return true;
				}
				object? obj = AccessTools.Field(typeof(PunManager), "photonView")?.GetValue(__instance);
				PhotonView val = (PhotonView)((obj is PhotonView) ? obj : null);
				Type typeFromHandle = typeof(ItemAttributes);
				FieldInfo fieldInfo2 = AccessTools.Field(typeFromHandle, "roomVolumeCheck");
				FieldInfo fieldInfo3 = AccessTools.Field(typeFromHandle, "value");
				if (fieldInfo2 == null || fieldInfo3 == null)
				{
					REPOPatch.Logger.LogError((object)"> ShopUpdateCost patch failed: DAa!3");
					return true;
				}
				Type fieldType = fieldInfo2.FieldType;
				MethodInfo methodInfo = AccessTools.Method(fieldType, "CheckSet", (Type[])null, (Type[])null);
				FieldInfo fieldInfo4 = AccessTools.Field(fieldType, "inExtractionPoint");
				if (fieldInfo4 == null)
				{
					REPOPatch.Logger.LogError((object)"> ShopUpdateCost patch failed: DAa!4");
					return true;
				}
				List<ItemAttributes> list2 = ListPool<ItemAttributes>.Get();
				try
				{
					int num = 0;
					foreach (object item in list)
					{
						ItemAttributes val2 = (ItemAttributes)((item is ItemAttributes) ? item : null);
						if ((Object)(object)val2 != (Object)null)
						{
							object value = fieldInfo2.GetValue(val2);
							methodInfo?.Invoke(value, null);
							if (!(bool)fieldInfo4.GetValue(value))
							{
								list2.Add(val2);
								continue;
							}
							int num2 = (int)fieldInfo3.GetValue(val2);
							num += num2;
						}
						else
						{
							list2.Add(val2);
						}
					}
					foreach (ItemAttributes item2 in list2)
					{
						list.Remove(item2);
					}
					if (SemiFunc.IsMasterClientOrSingleplayer())
					{
						if (SemiFunc.IsMultiplayer() && (Object)(object)val != (Object)null)
						{
							val.RPC("UpdateShoppingCostRPC", (RpcTarget)0, new object[1] { num });
						}
						else
						{
							__instance.UpdateShoppingCostRPC(num, default(PhotonMessageInfo));
						}
					}
					return false;
				}
				finally
				{
					ListPool<ItemAttributes>.Release(list2);
				}
			}
			catch (Exception arg)
			{
				REPOPatch.Logger.LogWarning((object)$"> ShopUpdateCost pool prefix exception: {arg}");
				return true;
			}
		}
	}
}
namespace REPOPatch.Modules
{
	public static class Helper
	{
	}
}
namespace REPOPatch.Features
{
	public static class Additions
	{
	}
	public static class FileManager
	{
		internal static ConfigEntry<T> BindConfig<T>(string Header, string Features, T Value, string? Info = "")
		{
			return REPOPatch.Instance.config.Bind<T>(Header, Features, Value, Info);
		}

		internal static void InitializeConfig()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			string text = Path.Combine(Paths.ConfigPath, "DAa Mods/REPOPatch");
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			REPOPatch.Instance.config = new ConfigFile(Path.Combine(text, "config.cfg"), true);
			if (BindConfig("Version", "Current Version", "").Value != "1.0.0")
			{
				REPOPatch.Instance.config.Clear();
			}
			DefineConfig();
			REPOPatch.Logger.LogWarning((object)"< Config initialized >");
		}

		internal static void DefineConfig()
		{
			BindConfig("Version", "Current Version", "1.0.0", "Autoupdates the config / lets the mod know what version of config it is.");
			REPOPatch.Patch_SendBufferFull = BindConfig("BufferThrottler", "SendBufferFull", Value: true, "Patches SendBufferFull error.").Value;
			REPOPatch.SBF_MaxQueuedStatUpdates = BindConfig("BufferThrottler", "MaxQueuedStatUpdates", 2000, "Maximum queued stat updates before drops/eviction occur.").Value;
			REPOPatch.SBF_MaxSendsPerFlush = BindConfig("BufferThrottler", "MaxSendsPerFlush", 25, "How many stat updates to send per flush batch.").Value;
			REPOPatch.SBF_FlushInterval = BindConfig("BufferThrottler", "FlushInterval", 0.08f, "Seconds to wait between flush batches.").Value;
			REPOPatch.SBF_DropWhenFull = BindConfig("BufferThrottler", "DropWhenFull", Value: true, "If true, drop new updates when queue is full; if false, oldest updates are evicted.").Value;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}