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)
{
}
}
}