using System; using System.Diagnostics; using System.Reflection; using System.Runtime; using Barotrauma; using Microsoft.Xna.Framework; using HarmonyLib; namespace FastLoadMod { public class MemoryManager : IAssemblyPlugin { private static Harmony harmony; private static GCLatencyMode originalLatencyMode; private static bool isManagingMemory = false; private static Stopwatch pacemakerTimer = new Stopwatch(); private const double PACEMAKER_INTERVAL_MS = 50.0; public void Initialize() { harmony = new Harmony("com.fastload.memorymanager"); try { var updateMethod = typeof(GameMain).GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (updateMethod != null) { harmony.Patch(updateMethod, postfix: new HarmonyMethod(AccessTools.Method(typeof(MemoryManager), "PacemakerUpdate"))); } var generateMethod = typeof(Level).GetMethod("Generate", BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance); if (generateMethod != null) { harmony.Patch(generateMethod, prefix: new HarmonyMethod(AccessTools.Method(typeof(MemoryManager), "StartControlledBurn")), postfix: new HarmonyMethod(AccessTools.Method(typeof(MemoryManager), "EndControlledBurn"))); } DebugConsole.NewMessage("[EnLo] MemManager working.", Color.Lime); } catch (Exception ex) { DebugConsole.NewMessage($"[EnLo] Memory Manager Error: {ex.Message}", Color.Red); } } public void Dispose() { if (isManagingMemory) EndControlledBurn(); if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } } public void OnLoadCompleted() { } public void PreInitPatching() { } public static void StartControlledBurn() { if (!isManagingMemory) { originalLatencyMode = GCSettings.LatencyMode; GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency; isManagingMemory = true; pacemakerTimer.Restart(); } } public static void PacemakerUpdate() { if (!isManagingMemory) return; if (pacemakerTimer.Elapsed.TotalMilliseconds >= PACEMAKER_INTERVAL_MS) { GC.Collect(0, GCCollectionMode.Optimized, false, false); pacemakerTimer.Restart(); } } public static void EndControlledBurn() { if (isManagingMemory) { pacemakerTimer.Stop(); GCSettings.LatencyMode = originalLatencyMode; isManagingMemory = false; GC.Collect(2, GCCollectionMode.Forced, true, true); } } } }