using System; using System.Collections; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using UnityEngine; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace Erskine.LethalWringer; [BepInPlugin("Erskine.LethalWringer", "LethalWringer", "1.0.1")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry cEnabled; internal static ConfigEntry cSweepOnOrbit; internal static ConfigEntry cInterval; internal static ConfigEntry cPeriodicOrbit; internal static ConfigEntry cRunGC; internal static ConfigEntry cLog; private void Awake() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; cEnabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Master switch. Wrings unused assets out of memory during a run so RAM stops creeping up."); cSweepOnOrbit = ((BaseUnityPlugin)this).Config.Bind("General", "SweepOnReturnToOrbit", true, "Run one cleanup each time you get back to orbit after leaving a moon. This is the big, cheap one: the whole moon just unloaded, so there's the most memory to reclaim, and a hitch in orbit costs you nothing. Recommended on."); cInterval = ((BaseUnityPlugin)this).Config.Bind("General", "IntervalMinutes", 10f, new ConfigDescription("How often the periodic cleanup runs, in minutes. This is the safety net for long stays on one moon. Lower = tighter RAM but more frequent frame hitches.", (AcceptableValueBase)(object)new AcceptableValueRange(2f, 60f), new object[0])); cPeriodicOrbit = ((BaseUnityPlugin)this).Config.Bind("General", "PeriodicAlsoRunsInOrbit", false, "By default the periodic timer only ticks while you're landed on a moon (where RAM climbs). Turn this on to also tick in orbit. Usually unnecessary if SweepOnReturnToOrbit is on."); cRunGC = ((BaseUnityPlugin)this).Config.Bind("General", "AlsoCollectGarbage", false, "Also force a managed garbage collection after unloading. A little more RAM freed, a bigger hitch. Off by default."); cLog = ((BaseUnityPlugin)this).Config.Bind("General", "LogEachRun", true, "Print a line each cleanup showing the managed heap before/after."); GameObject val = new GameObject("LethalWringerRunner"); ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)val); val.AddComponent(); Log.LogInfo((object)("LethalWringer 1.0.0 active. Periodic every " + cInterval.Value + " min; sweep-on-return-to-orbit=" + cSweepOnOrbit.Value + ".")); } } public class WringerRunner : MonoBehaviour { private float timer; private bool running; private bool wasLanded; private bool sawStart; private void Update() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if (!Plugin.cEnabled.Value) { return; } StartOfRound instance = StartOfRound.Instance; if ((Object)instance == (Object)null) { timer = 0f; wasLanded = false; sawStart = false; return; } bool shipHasLanded = instance.shipHasLanded; if (sawStart && Plugin.cSweepOnOrbit.Value && wasLanded && !shipHasLanded && !running) { ((MonoBehaviour)this).StartCoroutine(Wring("returned to orbit", 3f)); } wasLanded = shipHasLanded; sawStart = true; if (!shipHasLanded && !Plugin.cPeriodicOrbit.Value) { timer = 0f; return; } timer += Time.deltaTime; float num = Mathf.Max(2f, Plugin.cInterval.Value) * 60f; if (timer >= num && !running) { timer = 0f; ((MonoBehaviour)this).StartCoroutine(Wring("periodic", 0f)); } } private IEnumerator Wring(string why, float delay) { running = true; if (delay > 0f) { yield return (object)new WaitForSeconds(delay); } long before = GC.GetTotalMemory(forceFullCollection: false); AsyncOperation op = Resources.UnloadUnusedAssets(); while (op != null && !op.isDone) { yield return null; } if (Plugin.cRunGC.Value) { GC.Collect(); } if (Plugin.cLog.Value) { long totalMemory = GC.GetTotalMemory(forceFullCollection: false); Plugin.Log.LogInfo((object)("[LethalWringer] wrung (" + why + "): managed heap " + before / 1048576 + "MB -> " + totalMemory / 1048576 + "MB.")); } timer = 0f; running = false; } }