using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using GTFO.API;
using Gear;
using HarmonyLib;
using IRF;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using MemoryLeakFix.Handler;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MemoryLeakFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e92aa57d27a40c3524a9c956d68eee9faf40aee2")]
[assembly: AssemblyProduct("MemoryLeakFix")]
[assembly: AssemblyTitle("MemoryLeakFix")]
[assembly: AssemblyVersion("1.0.0.0")]
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;
}
}
}
namespace MemoryLeakFix
{
[BepInPlugin("Dinorush.MemoryLeakFix", "MemoryLeakFix", "1.2.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal sealed class EntryPoint : BasePlugin
{
public const string MODNAME = "MemoryLeakFix";
public override void Load()
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
((BasePlugin)this).Log.LogMessage((object)"Loading MemoryLeakFix");
new Harmony("MemoryLeakFix").PatchAll();
((BasePlugin)this).Log.LogMessage((object)"Loaded MemoryLeakFix");
LevelAPI.OnLevelCleanup += OnLevelCleanup;
AssetAPI.OnStartupAssetsLoaded += OnAssetsLoaded;
}
private void OnLevelCleanup()
{
Decay.s_poolHandle.Clear();
FallingObjectHandler.Clear();
}
private void OnAssetsLoaded()
{
FallingObjectHandler.Current.EnsureInit();
}
}
}
namespace MemoryLeakFix.Utils
{
internal static class DinoLogger
{
private static ManualLogSource logger = Logger.CreateLogSource("MemoryLeakFix");
public static void Log(string format, params object[] args)
{
Log(string.Format(format, args));
}
public static void Log(string str)
{
if (logger != null)
{
logger.Log((LogLevel)8, (object)str);
}
}
public static void Warning(string format, params object[] args)
{
Warning(string.Format(format, args));
}
public static void Warning(string str)
{
if (logger != null)
{
logger.Log((LogLevel)4, (object)str);
}
}
public static void Error(string format, params object[] args)
{
Error(string.Format(format, args));
}
public static void Error(string str)
{
if (logger != null)
{
logger.Log((LogLevel)2, (object)str);
}
}
public static void Debug(string format, params object[] args)
{
Debug(string.Format(format, args));
}
public static void Debug(string str)
{
if (logger != null)
{
logger.Log((LogLevel)32, (object)str);
}
}
}
}
namespace MemoryLeakFix.Patches
{
[HarmonyPatch]
internal static class DecayPatches
{
private const float DecayClearDelay = 5f;
[HarmonyPatch(typeof(Decay), "Initialize", new Type[]
{
typeof(SkinnedMeshRenderer),
typeof(List<InstancedRenderFeature>)
})]
[HarmonyPostfix]
private static void AddEndCallback(Decay __instance)
{
Decay __instance2 = __instance;
Decay obj = __instance2;
obj.OnDecaySafeToDespawnRenderer += Action.op_Implicit((Action)delegate
{
((MonoBehaviour)__instance2).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(DelayedClear(__instance2)));
});
}
private static IEnumerator DelayedClear(Decay __instance)
{
yield return (object)new WaitForSeconds(5f);
if ((Object)(object)__instance.m_particles != (Object)null)
{
__instance.m_particles.Stop(true, (ParticleSystemStopBehavior)0);
}
__instance.m_playing = true;
}
}
[HarmonyPatch]
internal static class FallingPatches
{
[HarmonyPatch(typeof(GlueClusterGrenadeInstance), "Start")]
[HarmonyPostfix]
private static void GlueGrenadeSpawn(GlueClusterGrenadeInstance __instance)
{
FallingObjectHandler.AddObject(((Component)__instance).gameObject);
}
[HarmonyPatch(typeof(GlowstickInstance), "Setup")]
[HarmonyPostfix]
private static void GlowstickSpawn(GlowstickInstance __instance)
{
FallingObjectHandler.AddObject(((Component)__instance).gameObject);
}
[HarmonyPatch(typeof(FogRepellerInstance), "Start")]
[HarmonyPostfix]
private static void FogRepellerSpawn(FogRepellerInstance __instance)
{
FallingObjectHandler.AddObject(((Component)__instance).gameObject);
}
[HarmonyPatch(typeof(GlueGunProjectile), "Awake")]
[HarmonyPostfix]
private static void GlueGunSpawn(GlueGunProjectile __instance)
{
GlueGunProjectile __instance2 = __instance;
FallingObjectHandler.AddObject(((Component)__instance2).gameObject, delegate(GameObject go)
{
ProjectileManager.WantToDestroyGlue(go.GetComponent<GlueGunProjectile>().SyncID);
}, () => __instance2.m_sound == null);
}
[HarmonyPatch(typeof(BulletWeapon), "DropMagazine")]
[HarmonyWrapSafe]
[HarmonyPostfix]
private static void DropMag(BulletWeapon __instance)
{
Pool magDropPool = __instance.m_magDropPool;
if (magDropPool != null)
{
FallingObjectHandler.AddPool(magDropPool);
FallingObjectHandler.AddObject((magDropPool.m_freeInstances.Count > 0) ? magDropPool.m_freeInstances.First.Value : magDropPool.m_usedInstances.First.Value, (Action<GameObject>?)magDropPool.Return, (Func<bool>?)null);
}
}
}
[HarmonyPatch]
internal static class SoundPatches
{
[HarmonyPatch(typeof(GlueGunProjectile), "SyncDestroy")]
[HarmonyPrefix]
private static void GlueGunSpawn(GlueGunProjectile __instance)
{
__instance.m_sound.Recycle();
}
[HarmonyPatch(typeof(ProjectileBase), "Collision")]
[HarmonyPostfix]
private static void ProjectileDestroy(ProjectileBase __instance)
{
__instance.m_soundPlayer.Recycle();
}
[HarmonyPatch(typeof(StrikerBigTentacle), "OnDead")]
[HarmonyPostfix]
private static void BigTentacleDead(StrikerBigTentacle __instance)
{
__instance.m_tipSound.Recycle();
}
}
}
namespace MemoryLeakFix.Handler
{
internal sealed class FallingObjectHandler : MonoBehaviour
{
private static readonly Action<GameObject> BasicDestroy;
private const int MaxSteps = 20;
private const float UpdateInterval = 1f;
private readonly LinkedList<(GameObject? go, Action<GameObject> destroyFunc, Func<bool>? checkFunc)> _objects = new LinkedList<(GameObject, Action<GameObject>, Func<bool>)>();
private readonly Dictionary<IntPtr, Pool> _pools = new Dictionary<IntPtr, Pool>();
private float _nextUpdateTime;
private LinkedListNode<(GameObject? go, Action<GameObject> destroyFunc, Func<bool>? checkFunc)>? _currentNode;
public static FallingObjectHandler Current { get; private set; }
static FallingObjectHandler()
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected O, but got Unknown
BasicDestroy = delegate(GameObject go)
{
Object.Destroy((Object)(object)go);
};
ClassInjector.RegisterTypeInIl2Cpp<FallingObjectHandler>();
GameObject val = new GameObject("MemoryLeakFix_FallingObjectHandler");
Object.DontDestroyOnLoad((Object)val);
Current = val.AddComponent<FallingObjectHandler>();
}
public void EnsureInit()
{
}
public void Awake()
{
Current = this;
}
public static void AddObject(GameObject go, Action<GameObject>? destroyFunc = null, Func<bool>? checkFunc = null)
{
Current._objects.AddLast((go, destroyFunc ?? BasicDestroy, checkFunc));
}
public static void AddPool(Pool pool)
{
Current._pools.TryAdd(((Il2CppObjectBase)pool).Pointer, pool);
}
private void Update()
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
if (Clock.Time < _nextUpdateTime)
{
return;
}
if (_currentNode == null)
{
_currentNode = _objects.First;
}
for (int i = 0; i < 20 && _currentNode != null; _currentNode = _currentNode.Next, i++)
{
GameObject item = _currentNode.Value.go;
if ((Object)(object)item != (Object)null)
{
if (!(item.transform.position.y < -10000f))
{
Func<bool>? item2 = _currentNode.Value.checkFunc;
if (item2 == null || !item2())
{
goto IL_00a6;
}
}
_currentNode.Value.destroyFunc(item);
_objects.Remove(_currentNode);
continue;
}
goto IL_00a6;
IL_00a6:
if ((Object)(object)item == (Object)null || !item.active)
{
_objects.Remove(_currentNode);
}
}
if (_currentNode == null)
{
_nextUpdateTime = Clock.Time + 1f;
}
}
private void OnClear()
{
KeyValuePair<IntPtr, Pool>[] array = _pools.ToArray();
for (int i = 0; i < array.Length; i++)
{
KeyValuePair<IntPtr, Pool> keyValuePair = array[i];
var (key, val2) = (KeyValuePair<IntPtr, Pool>)(ref keyValuePair);
if (val2 == null)
{
_pools.Remove(key);
}
else if (val2.m_usedInstances.Count > 0)
{
GameObject[] array2 = (GameObject[])(object)new GameObject[val2.m_usedInstances.Count];
LinkedListNode<GameObject> val3 = val2.m_usedInstances.First;
int num = 0;
while (num < val2.m_usedInstances.Count)
{
array2[num] = val3.Value;
num++;
val3 = val3.Next;
}
GameObject[] array3 = array2;
foreach (GameObject val4 in array3)
{
val2.Return(val4);
}
}
}
_objects.Clear();
_currentNode = null;
}
public static void Clear()
{
Current.OnClear();
}
}
}