using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("EndlessResources")] [assembly: AssemblyDescription("Dyson Sphere Program BepInEx mod. All planet vein sources (ore, oil, Icarus, ILS / PLS vein collector) and source ILS / PLS storage stay non-depleting.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("EndlessResources")] [assembly: AssemblyCopyright("Copyright (c) 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("00000000-0000-0000-0000-000000000000")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = "")] [assembly: AssemblyVersion("1.0.0.0")] namespace EndlessResources; internal sealed class PluginConfig { public readonly ConfigEntry EnableMinerPatchFlag; public readonly ConfigEntry EnableOilPatchFlag; public readonly ConfigEntry EnableIcarusPatchFlag; public readonly ConfigEntry EnableILSVeinCollectionFlag; public readonly ConfigEntry EnableILSSourceFlag; public readonly ConfigEntry EnablePlanetMinerFastCompatFlag; public readonly ConfigEntry DebugLog; public PluginConfig(ConfigFile config) { EnableMinerPatchFlag = config.Bind("General", "EnableMinerPatchFlag", true, "Restore vein amount after miner extract (ore). When true, regular miners cannot deplete a vein. The ILS / PLS vein collector (which uses the same MinerComponent) is also covered."); EnableOilPatchFlag = config.Bind("General", "EnableOilPatchFlag", true, "Restore vein amount after oil extractor. When true, oil extractors cannot deplete an oil seep."); EnableIcarusPatchFlag = config.Bind("General", "EnableIcarusPatchFlag", true, "Restore vein amount after Icarus hand-mining (right-click a resource node). When true, the player can hand-mine indefinitely."); EnableILSVeinCollectionFlag = config.Bind("General", "EnableILSVeinCollectionFlag", true, "Keep the ILS / PLS collector miner's productCount full. When true, the ILS / PLS vein collector can pull from the miner every tick without waiting for the next InternalUpdate cycle. Note: the vein amount itself is covered by EnableMinerPatchFlag (the ILS / PLS uses a regular MinerComponent under the hood)."); EnableILSSourceFlag = config.Bind("General", "EnableILSSourceFlag", true, "Restore the source ILS / PLS storage after each dispatch. When true, the source station's storage buffer is restored to its pre-dispatch value, so the station can ship indefinitely."); EnablePlanetMinerFastCompatFlag = config.Bind("General", "EnablePlanetMinerFastCompatFlag", true, "Compatibility layer for PlanetMinerFast (DysonSphereMods). PlanetMinerFast bypasses MinerComponent.InternalUpdate and does its own vein mining in its own slow-tick handler, so Patch A does not cover it. When this flag is true, EndlessResources detects PlanetMinerFast via reflection and patches its OnSlowTick method with a snapshot (prefix) + restore (postfix) pair, so the station vein is also restored to its pre-call amount. If PlanetMinerFast is not installed, this flag is a no-op. Set to false to disable the compat layer (the station will then deplete the vein via PlanetMinerFast as normal)."); DebugLog = config.Bind("Diagnostics", "DebugLog", false, "Enable verbose diagnostic logging. Off by default; toggle on for first-run verification. Prints category-tagged lines ([config], [patch], [error]) to the BepInEx console."); } } internal static class EndlessResourcesLog { private static ManualLogSource logger; private static ConfigEntry debugEntry; public static void Init(ManualLogSource src, ConfigEntry debug) { logger = src; debugEntry = debug; } public static void Info(string msg) { if (debugEntry != null && debugEntry.Value && logger != null) { logger.LogInfo((object)("[EndlessResources] " + msg)); } } public static void Warn(string msg) { if (logger != null) { logger.LogWarning((object)("[EndlessResources] " + msg)); } } public static void Error(string msg) { if (logger != null) { logger.LogError((object)("[EndlessResources] " + msg)); } } public static bool IsDebugEnabled() { if (debugEntry != null) { return debugEntry.Value; } return false; } } [HarmonyPatch(typeof(PlayerAction_Mine), "GameTick")] internal static class IcarusPatch { internal sealed class Snapshot { public int veinId; public int amount; public short groupIndex; public long groupAmount; } private static bool firstFireLogged = true; private static void Prefix(PlayerAction_Mine __instance, long timei, ref Snapshot __state) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) try { if (!Plugin.Config.EnableIcarusPatchFlag.Value || __instance == null) { return; } PlanetFactory val = GameMain.localPlanet?.factory; if (val == null || val.veinPool == null || val.veinGroups == null) { return; } int miningId = __instance.miningId; if (miningId <= 0 || miningId >= val.veinPool.Length) { return; } VeinData val2 = val.veinPool[miningId]; if (val2.id != 0) { __state = new Snapshot { veinId = miningId, amount = val2.amount, groupIndex = val2.groupIndex }; if (val2.groupIndex > 0 && val2.groupIndex < val.veinGroups.Length) { __state.groupAmount = val.veinGroups[val2.groupIndex].amount; } } } catch (Exception ex) { EndlessResourcesLog.Error("Patch B (Icarus) prefix threw: " + ex); } } [HarmonyPriority(600)] private static void Postfix(PlayerAction_Mine __instance, long timei, ref Snapshot __state) { try { if (__state == null || __state.veinId == 0 || !Plugin.Config.EnableIcarusPatchFlag.Value) { return; } PlanetFactory val = GameMain.localPlanet?.factory; if (val == null || val.veinPool == null || val.veinGroups == null) { return; } int veinId = __state.veinId; if (veinId > 0 && veinId < val.veinPool.Length && val.veinPool[veinId].id != 0 && val.veinPool[veinId].amount != __state.amount) { val.veinPool[veinId].amount = __state.amount; int groupIndex = __state.groupIndex; if (groupIndex > 0 && groupIndex < val.veinGroups.Length) { val.veinGroups[groupIndex].amount = __state.groupAmount; } if (firstFireLogged && EndlessResourcesLog.IsDebugEnabled()) { EndlessResourcesLog.Info("[patch] Patch B (Icarus) fired: vein " + veinId + " restored to " + __state.amount); firstFireLogged = false; } } } catch (Exception ex) { EndlessResourcesLog.Error("Patch B (Icarus) postfix threw: " + ex); } } } [HarmonyPatch(typeof(MinerComponent), "InternalUpdate")] internal static class MinerPatch { internal sealed class Snapshot { public int[] veinIds; public int[] amounts; public short[] groupIndices; public long[] groupAmounts; } [HarmonyPriority(700)] private static void Prefix(MinerComponent __instance, PlanetFactory factory, VeinData[] veinPool, float power, float miningRate, float miningSpeed, int[] productRegister, ref Snapshot __state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) try { if (__instance.veins == null || __instance.veins.Length == 0 || factory == null || factory.veinPool == null || factory.veinGroups == null) { return; } bool flag = (int)__instance.type == 3; if ((flag && !Plugin.Config.EnableOilPatchFlag.Value) || (!flag && !Plugin.Config.EnableMinerPatchFlag.Value)) { return; } int num = __instance.veins.Length; __state = new Snapshot { veinIds = new int[num], amounts = new int[num], groupIndices = new short[num], groupAmounts = new long[num] }; for (int i = 0; i < num; i++) { int num2 = __instance.veins[i]; if (num2 <= 0 || num2 >= factory.veinPool.Length) { continue; } VeinData val = factory.veinPool[num2]; if (val.id != 0) { __state.veinIds[i] = num2; __state.amounts[i] = val.amount; __state.groupIndices[i] = val.groupIndex; if (val.groupIndex > 0 && val.groupIndex < factory.veinGroups.Length) { __state.groupAmounts[i] = factory.veinGroups[val.groupIndex].amount; } } } } catch (Exception ex) { EndlessResourcesLog.Error("Patch A (Miner) prefix threw: " + ex); } } [HarmonyPriority(700)] private unsafe static void Postfix(MinerComponent __instance, PlanetFactory factory, VeinData[] veinPool, float power, float miningRate, float miningSpeed, int[] productRegister, ref Snapshot __state) { try { if (__state == null || __state.veinIds == null || factory == null || factory.veinPool == null || factory.veinGroups == null) { return; } int num = 0; for (int i = 0; i < __state.veinIds.Length; i++) { int num2 = __state.veinIds[i]; if (num2 > 0 && num2 < factory.veinPool.Length && factory.veinPool[num2].id != 0) { factory.veinPool[num2].amount = __state.amounts[i]; int num3 = __state.groupIndices[i]; if (num3 > 0 && num3 < factory.veinGroups.Length) { factory.veinGroups[num3].amount = __state.groupAmounts[i]; } num++; } } if (num <= 0 || !EndlessResourcesLog.IsDebugEnabled()) { return; } int num4 = 0; int num5 = 0; for (int j = 0; j < __state.veinIds.Length; j++) { if (__state.veinIds[j] > 0) { num4 = __state.veinIds[j]; num5 = __state.amounts[j]; break; } } EndlessResourcesLog.Info("[patch] Patch A fired: type=" + ((object)(*(EMinerType*)(&__instance.type))/*cast due to .constrained prefix*/).ToString() + ", miner.veins.len=" + __state.veinIds.Length + ", restored=" + num + ", firstVid=" + num4 + ", firstAmt=" + num5); } catch (Exception ex) { EndlessResourcesLog.Error("Patch A (Miner) postfix threw: " + ex); } } } internal static class PlanetMinerFastCompat { private static bool _applied = false; private static bool _loggedNotDetected = false; private static Harmony _storedHarmony = null; private static readonly Dictionary _veinSnapshots = new Dictionary(); private static readonly Dictionary _groupSnapshots = new Dictionary(); public static void Apply(Harmony harmony) { _storedHarmony = harmony; TryApply(); } public static void Retry() { if (_storedHarmony == null) { EndlessResourcesLog.Warn("[compat] Retry called before Apply; skipping."); } else { TryApply(); } } private static void TryApply() { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_00da: Expected O, but got Unknown if (_applied) { return; } try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { type = assemblies[i].GetType("PlanetMinerFast.PlanetMinerFastPlugin", throwOnError: false); if (type != null) { break; } } if (type == null) { if (!_loggedNotDetected) { EndlessResourcesLog.Info("[compat] PlanetMinerFast not detected yet; will retry on Start."); _loggedNotDetected = true; } return; } _loggedNotDetected = false; MethodInfo method = type.GetMethod("OnSlowTick", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { EndlessResourcesLog.Warn("[compat] PlanetMinerFast detected but OnSlowTick method not found; skipping compat patch."); return; } MethodInfo method2 = typeof(PlanetMinerFastCompat).GetMethod("SnapshotPrefix", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method3 = typeof(PlanetMinerFastCompat).GetMethod("RestorePostfix", BindingFlags.Static | BindingFlags.NonPublic); _storedHarmony.Patch((MethodBase)method, new HarmonyMethod(method2), new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _applied = true; EndlessResourcesLog.Info("[compat] PlanetMinerFast detected; applied snapshot/restore patch on PlanetMinerFastPlugin.OnSlowTick."); } catch (Exception ex) { EndlessResourcesLog.Error("[compat] Failed to apply PlanetMinerFast compat patch: " + ex); } } private static void SnapshotPrefix() { try { if (GameMain.data == null || GameMain.data.factories == null) { return; } _veinSnapshots.Clear(); _groupSnapshots.Clear(); PlanetFactory[] factories = GameMain.data.factories; foreach (PlanetFactory val in factories) { if (val == null || val.veinPool == null) { continue; } int[] array = new int[val.veinPool.Length]; for (int j = 0; j < val.veinPool.Length; j++) { array[j] = val.veinPool[j].amount; } _veinSnapshots[val.index] = array; if (val.veinGroups != null) { long[] array2 = new long[val.veinGroups.Length]; for (int k = 0; k < val.veinGroups.Length; k++) { array2[k] = val.veinGroups[k].amount; } _groupSnapshots[val.index] = array2; } } } catch (Exception ex) { EndlessResourcesLog.Error("[compat] SnapshotPrefix threw: " + ex); } } private static void RestorePostfix() { try { if (GameMain.data == null || GameMain.data.factories == null) { return; } int num = 0; int num2 = 0; PlanetFactory[] factories = GameMain.data.factories; foreach (PlanetFactory val in factories) { if (val == null || val.veinPool == null) { continue; } if (_veinSnapshots.TryGetValue(val.index, out var value) && value.Length == val.veinPool.Length) { for (int j = 0; j < val.veinPool.Length; j++) { if (val.veinPool[j].id != 0 && val.veinPool[j].amount != value[j]) { val.veinPool[j].amount = value[j]; num++; } } } if (val.veinGroups == null || !_groupSnapshots.TryGetValue(val.index, out var value2) || value2.Length != val.veinGroups.Length) { continue; } for (int k = 0; k < val.veinGroups.Length; k++) { if (val.veinGroups[k].amount != value2[k]) { val.veinGroups[k].amount = value2[k]; num2++; } } } if ((num > 0 || num2 > 0) && EndlessResourcesLog.IsDebugEnabled()) { EndlessResourcesLog.Info("[compat] PlanetMinerFast restore: " + num + " veins, " + num2 + " groups."); } _veinSnapshots.Clear(); _groupSnapshots.Clear(); } catch (Exception ex) { EndlessResourcesLog.Error("[compat] RestorePostfix threw: " + ex); } } } [HarmonyPatch(typeof(StationComponent), "DetermineDispatch")] internal static class StationDispatchPatch { internal sealed class Snapshot { public StationStore[] storage; } private static bool firstFireLogged = true; [HarmonyPriority(600)] private static void Prefix(StationComponent __instance, float shipSailSpeed, float shipWarpSpeed, int shipCarries, int priorityIndex, StationComponent[] gStationPool, FactoryProductionStat[] factoryStatPool, PlanetFactory[] factories, GalaxyData galaxy, TrafficStatistics tstat, ref Snapshot __state) { try { if (Plugin.Config.EnableILSSourceFlag.Value && __instance != null && __instance.storage != null) { StationStore[] storage = __instance.storage; StationStore[] array = (StationStore[])(object)new StationStore[storage.Length]; Array.Copy(storage, array, storage.Length); __state = new Snapshot { storage = array }; } } catch (Exception ex) { EndlessResourcesLog.Error("Patch D (Station dispatch) prefix threw: " + ex); } } [HarmonyPriority(600)] private static void Postfix(StationComponent __instance, float shipSailSpeed, float shipWarpSpeed, int shipCarries, int priorityIndex, StationComponent[] gStationPool, FactoryProductionStat[] factoryStatPool, PlanetFactory[] factories, GalaxyData galaxy, TrafficStatistics tstat, ref Snapshot __state) { try { if (__state == null || __state.storage == null || !Plugin.Config.EnableILSSourceFlag.Value || __instance == null) { return; } StationStore[] storage = __state.storage; if (__instance.storage == null || __instance.storage.Length != storage.Length) { return; } bool flag = false; for (int i = 0; i < storage.Length; i++) { if (__instance.storage[i].count != storage[i].count || __instance.storage[i].inc != storage[i].inc || __instance.storage[i].localOrder != storage[i].localOrder || __instance.storage[i].remoteOrder != storage[i].remoteOrder) { __instance.storage[i].count = storage[i].count; __instance.storage[i].inc = storage[i].inc; __instance.storage[i].localOrder = storage[i].localOrder; __instance.storage[i].remoteOrder = storage[i].remoteOrder; flag = true; } } if (flag && firstFireLogged && EndlessResourcesLog.IsDebugEnabled()) { EndlessResourcesLog.Info("[patch] Patch D (Station dispatch) fired: first storage restoration. slots=" + storage.Length); firstFireLogged = false; } } catch (Exception ex) { EndlessResourcesLog.Error("Patch D (Station dispatch) postfix threw: " + ex); } } } [HarmonyPatch(typeof(StationComponent), "UpdateVeinCollection")] internal static class StationVeinCollectionPatch { internal sealed class Snapshot { public int minerId; public int productCount; } private static bool firstFireLogged = true; private static void Prefix(StationComponent __instance, PlanetFactory factory, int[] productRegister, ref Snapshot __state) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) try { if (!Plugin.Config.EnableILSVeinCollectionFlag.Value || __instance == null || factory == null || factory.factorySystem == null) { return; } MinerComponent[] minerPool = factory.factorySystem.minerPool; if (minerPool != null) { int minerId = __instance.minerId; if (minerId > 0 && minerId < minerPool.Length) { MinerComponent val = minerPool[minerId]; __state = new Snapshot { minerId = minerId, productCount = val.productCount }; } } } catch (Exception ex) { EndlessResourcesLog.Error("Patch C (Station vein collection) prefix threw: " + ex); } } [HarmonyPriority(600)] private static void Postfix(StationComponent __instance, PlanetFactory factory, int[] productRegister, ref Snapshot __state) { try { if (__state == null || !Plugin.Config.EnableILSVeinCollectionFlag.Value || factory == null || factory.factorySystem == null) { return; } MinerComponent[] minerPool = factory.factorySystem.minerPool; if (minerPool != null && __state.minerId > 0 && __state.minerId < minerPool.Length && minerPool[__state.minerId].productCount != __state.productCount) { minerPool[__state.minerId].productCount = __state.productCount; if (firstFireLogged && EndlessResourcesLog.IsDebugEnabled()) { EndlessResourcesLog.Info("[patch] Patch C (Station vein collection) fired: miner " + __state.minerId + " productCount restored to " + __state.productCount); firstFireLogged = false; } } } catch (Exception ex) { EndlessResourcesLog.Error("Patch C (Station vein collection) postfix threw: " + ex); } } } [BepInPlugin("com.zicarius.EndlessResources", "EndlessResources", "1.0.0")] [BepInProcess("DSPGAME.exe")] public sealed class Plugin : BaseUnityPlugin { public const string GUID = "com.zicarius.EndlessResources"; public const string NAME = "EndlessResources"; public const string VERSION = "1.0.0"; internal static PluginConfig Config; private static Harmony _harmony; private void Awake() { //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown Config = new PluginConfig(((BaseUnityPlugin)this).Config); EndlessResourcesLog.Init(((BaseUnityPlugin)this).Logger, Config.DebugLog); EndlessResourcesLog.Info("[config] Loaded with config: miner=" + Config.EnableMinerPatchFlag.Value + ", oil=" + Config.EnableOilPatchFlag.Value + ", icarus=" + Config.EnableIcarusPatchFlag.Value + ", ils_vein=" + Config.EnableILSVeinCollectionFlag.Value + ", ils_source=" + Config.EnableILSSourceFlag.Value + ", planetminerfast=" + Config.EnablePlanetMinerFastCompatFlag.Value + ", debug=" + Config.DebugLog.Value); try { _harmony = new Harmony("com.zicarius.EndlessResources"); _harmony.PatchAll(typeof(Plugin).Assembly); int num = 0; Type[] types = typeof(Plugin).Assembly.GetTypes(); for (int i = 0; i < types.Length; i++) { if (types[i].GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Length != 0) { num++; } } EndlessResourcesLog.Info("[patch] Applied " + num + " Harmony patches: MinerPatch, IcarusPatch, StationVeinCollectionPatch, StationDispatchPatch."); if (Config.EnablePlanetMinerFastCompatFlag.Value) { PlanetMinerFastCompat.Apply(_harmony); } } catch (Exception ex) { EndlessResourcesLog.Error("Harmony PatchAll failed: " + ex); } DumpTargetMethodSignatures(); } private static void DumpTargetMethodSignatures() { string[][] array = new string[4][] { new string[2] { "MinerComponent", "InternalUpdate" }, new string[2] { "PlayerAction_Mine", "GameTick" }, new string[2] { "StationComponent", "UpdateVeinCollection" }, new string[2] { "StationComponent", "DetermineDispatch" } }; foreach (string[] array2 in array) { try { Type type = AccessTools.TypeByName(array2[0]); if (type == null) { EndlessResourcesLog.Warn("[diag] Type not found: " + array2[0]); continue; } MethodInfo methodInfo = AccessTools.Method(type, array2[1], (Type[])null, (Type[])null); if (methodInfo == null) { EndlessResourcesLog.Warn("[diag] Method not found: " + array2[0] + "." + array2[1]); continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("[diag] ").Append(array2[0]).Append(".") .Append(array2[1]) .Append("("); for (int j = 0; j < parameters.Length; j++) { if (j > 0) { stringBuilder.Append(", "); } stringBuilder.Append(parameters[j].ParameterType.Name).Append(" ").Append(parameters[j].Name); } stringBuilder.Append(")"); EndlessResourcesLog.Info(stringBuilder.ToString()); } catch (Exception ex) { EndlessResourcesLog.Error("[diag] Failed to inspect " + array2[0] + "." + array2[1] + ": " + ex.Message); } } } private void Start() { if (Config.EnablePlanetMinerFastCompatFlag.Value) { PlanetMinerFastCompat.Retry(); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _harmony = null; } }