88 lines
2.5 KiBLFS
C#
Executable File
88 lines
2.5 KiBLFS
C#
Executable File
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);
|
|
}
|
|
}
|
|
}
|
|
}
|