Decompiled source of DSP MolecularHub v0.1.9
BepInEx\plugins\DSP-MolecularHub\DSP-MolecularHub.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Logging; using CommonAPI; using CommonAPI.Systems; using CommonAPI.Systems.ModLocalization; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("DSP-MolecularHub")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("分子装配枢纽 — 8 配方槽 + 槽间内部直连总线")] [assembly: AssemblyFileVersion("0.1.9.0")] [assembly: AssemblyInformationalVersion("0.1.9")] [assembly: AssemblyProduct("DSP-MolecularHub")] [assembly: AssemblyTitle("DSP-MolecularHub")] [assembly: AssemblyVersion("0.1.9.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DSPMolecularHub { internal static class CompatProbe { private static bool installed; private static bool selfTestDone; private static int frames; private static DateTime startedUtc = DateTime.MinValue; public static void Install() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown if (installed) { return; } installed = true; try { Type type = AccessTools.TypeByName("CommonAPI.Patches.ProtoSet_Patch"); if (type == null) { Plugin.Log.LogWarning("[compat-probe] 未找到 CommonAPI.Patches.ProtoSet_Patch(CommonAPI 未安装?),跳过"); return; } MethodInfo methodInfo = AccessTools.Method(type, "ChangeSelectDefault", (Type[])null, (Type[])null); if (methodInfo == null) { Plugin.Log.LogWarning("[compat-probe] 未找到 ChangeSelectDefault,跳过"); return; } new Harmony("org.xcm.dsp.molecularhub.compatprobe").Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(CompatProbe), "SkipBrokenPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.Log.LogInfo("[compat-probe] 已停用 CommonAPI 的 Select 后缀 ChangeSelectDefault(它在 0.10.35.29151 上无条件抛 NRE;本环境没有移除任何原版 proto,停用无副作用)"); } catch (Exception ex) { Plugin.Log.LogError("[compat-probe] 安装失败:" + ex); } } public static bool SkipBrokenPostfix() { return false; } public static void SelfTest() { if (selfTestDone) { return; } if (startedUtc == DateTime.MinValue) { startedUtc = DateTime.UtcNow; } if (frames++ % 30 != 0) { return; } double totalSeconds = (DateTime.UtcNow - startedUtc).TotalSeconds; bool flag = false; try { flag = GameMain.data != null; } catch { } if (!flag && totalSeconds < 10.0) { return; } int num = 0; ItemProto val = null; ItemProto val2 = null; RecipeProto val3 = null; try { val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(1001); } catch { num++; } try { val2 = ((ProtoSet<ItemProto>)(object)LDB.items).Select(HubConst.RuntimeItemId); } catch { num++; } try { val3 = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(HubConst.RuntimeRecipeId); } catch { num++; } if (val2 == null && totalSeconds < 60.0) { return; } selfTestDone = true; try { Plugin.Log.LogInfo("[compat-probe] Select 自检:异常 " + num + " 次(关键指标,应为 0);铁块1001=" + ((val == null) ? "null" : "ok") + ";枢纽物品" + HubConst.RuntimeItemId + "=" + ((val2 == null) ? "null" : "ok") + ";枢纽配方" + HubConst.RuntimeRecipeId + "=" + ((val3 == null) ? "null" : "ok") + ";游戏内=" + flag + ",用时 " + (int)totalSeconds + "s"); } catch (Exception ex) { Plugin.Log.LogError("[compat-probe] 自检输出失败:" + ex); } } } internal static class DiagProbe { private const int MaxTracked = 4; private const int MaxInserters = 8; private const int MaxAnimLines = 400; private const int MaxInsLines = 240; private const int MaxNeedsLines = 120; private static readonly int[] trackEnt = new int[4]; private static readonly long[] trackSig = new long[4]; private static readonly int[] trackFrame = new int[4]; private static readonly string[] trackText = new string[4]; private static int trackN; private static int trackedHub = -1; private static readonly int[] insEnt = new int[8]; private static readonly long[] insSig = new long[8]; private static readonly int[] insFrame = new int[8]; private static readonly string[] insText = new string[8]; private static int insN; private static int prevNeedsRef; private static long prevNeedsHash; private static int needsFrame; private static bool needsInited; private static int animLogged; private static int insLogged; private static int needsLogged; private static bool statsLogged; private static int tickFrame = -1; private static int errorLogged; private static readonly StringBuilder sb = new StringBuilder(512); public static void Tick() { try { if ((!HotTune.ProbeAnim && !HotTune.ProbeIns && !HotTune.ProbeStats) || GameMain.localPlanet == null) { return; } PlanetFactory factory = GameMain.localPlanet.factory; if (factory == null || factory.factorySystem == null || factory.entityPool == null) { return; } int frameCount = Time.frameCount; if (frameCount == tickFrame) { return; } tickFrame = frameCount; HubComponent hubComponent = FindHub(factory); if (hubComponent != null && hubComponent.entityId > 0) { if (HotTune.ProbeStats && !statsLogged) { statsLogged = true; DumpStats(factory, hubComponent); } if (HotTune.ProbeAnim) { ProbeAnim(factory, hubComponent, frameCount); } if (HotTune.ProbeIns) { ProbeInserter(factory, hubComponent, frameCount); } } } catch (Exception ex) { if (errorLogged < 5) { errorLogged++; Plugin.Log.LogWarning("[probe] 采样失败:" + ex.Message); } } } private static HubComponent FindHub(PlanetFactory pf) { List<HubComponent> all = HubRegistry.All; if (all == null) { return null; } for (int i = 0; i < all.Count; i++) { HubComponent hubComponent = all[i]; if (hubComponent != null && hubComponent.Factory == pf && hubComponent.entityId > 0) { return hubComponent; } } return null; } private static void ProbeAnim(PlanetFactory pf, HubComponent hub, int frame) { if (trackedHub != hub.entityId || trackN <= 0) { RebuildTracking(pf, hub); } if (trackN <= 0) { return; } for (int i = 0; i < trackN; i++) { int num = trackEnt[i]; if (num <= 0 || num >= pf.entityCursor) { continue; } long num2 = EntSig(pf, num); if (num2 != trackSig[i] || trackFrame[i] == 0) { int value = ((trackFrame[i] > 0) ? (frame - trackFrame[i]) : 0); trackSig[i] = num2; trackFrame[i] = frame; trackText[i] = EntText(pf, num); if (animLogged < 400) { animLogged++; sb.Length = 0; sb.Append("[probe-anim] +").Append(value).Append("f ") .Append(trackText[i]); Plugin.Log.LogInfo(sb.ToString()); } } } } private static void RebuildTracking(PlanetFactory pf, HubComponent hub) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: 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_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) trackedHub = hub.entityId; trackN = 0; for (int i = 0; i < 4; i++) { trackEnt[i] = 0; trackSig[i] = 0L; trackFrame[i] = 0; trackText[i] = null; } trackEnt[trackN++] = hub.entityId; Vector3 pos = pf.entityPool[hub.entityId].pos; float num = float.MaxValue; float num2 = float.MaxValue; float num3 = float.MaxValue; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = Mathf.Min(pf.entityCursor, pf.entityPool.Length); for (int j = 1; j < num7; j++) { if (trackN >= 4) { break; } if (j == hub.entityId) { continue; } EntityData val = pf.entityPool[j]; if (val.id <= 0 || val.protoId <= 0) { continue; } float num8 = val.pos.x - pos.x; float num9 = val.pos.y - pos.y; float num10 = val.pos.z - pos.z; float num11 = num8 * num8 + num9 * num9 + num10 * num10; if (!(num11 > 900f)) { if (num11 < num) { num3 = num2; num6 = num5; num2 = num; num5 = num4; num = num11; num4 = j; } else if (num11 < num2) { num3 = num2; num6 = num5; num2 = num11; num5 = j; } else if (num11 < num3) { num3 = num11; num6 = j; } } } if (num4 > 0) { trackEnt[trackN++] = num4; } if (num5 > 0) { trackEnt[trackN++] = num5; } if (num6 > 0) { trackEnt[trackN++] = num6; } } private static int F2I(float f) { return BitConverter.ToInt32(BitConverter.GetBytes(f), 0); } private static long H(long h, long v) { return h * 31 + v; } private static long EntSig(PlanetFactory pf, int eid) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) SignData val = pf.entitySignPool[eid]; AnimData val2 = pf.entityAnimPool[eid]; long h = 17L; h = H(h, val.signType); h = H(h, val.iconType); h = H(h, val.iconId0); h = H(h, F2I(val.count0)); h = H(h, val2.state); h = H(h, F2I(val2.power * 100f)); EntityData val3 = pf.entityPool[eid]; if (val3.assemblerId > 0 && val3.assemblerId < pf.factorySystem.assemblerPool.Length) { AssemblerComponent val4 = pf.factorySystem.assemblerPool[val3.assemblerId]; h = H(h, val4.recipeId); h = H(h, val4.replicating ? 1 : 0); } if (val3.inserterId > 0 && pf.factorySystem.inserterPool != null && val3.inserterId < pf.factorySystem.inserterPool.Length) { InserterComponent val5 = pf.factorySystem.inserterPool[val3.inserterId]; h = H(h, (long)val5.stage); h = H(h, val5.itemId); h = H(h, val5.pickTarget); h = H(h, val5.insertTarget); h = H(h, val5.careNeeds ? 1 : 0); h = H(h, val5.filter); } if (val3.powerConId > 0 && pf.powerSystem != null && pf.powerSystem.consumerPool != null && val3.powerConId < pf.powerSystem.consumerPool.Length) { PowerConsumerComponent val6 = pf.powerSystem.consumerPool[val3.powerConId]; h = H(h, val6.requiredEnergy); h = H(h, val6.networkId); } return h; } private static string EntText(PlanetFactory pf, int eid) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Expected I4, but got Unknown //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0388: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) EntityData val = pf.entityPool[eid]; SignData val2 = pf.entitySignPool[eid]; AnimData val3 = pf.entityAnimPool[eid]; sb.Length = 0; sb.Append("e=").Append(eid).Append(" proto=") .Append(val.protoId); sb.Append(" sign=").Append(val2.signType).Append('/') .Append(val2.iconType) .Append('/') .Append(val2.iconId0); sb.Append("/c").Append(val2.count0.ToString("0")); sb.Append(" anim[st=").Append(val3.state).Append(" p=") .Append(val3.power.ToString("0.00")) .Append(" t=") .Append(val3.time.ToString("0.00")) .Append(" pre=") .Append(val3.prepare_length.ToString("0.0")) .Append(" wl=") .Append(val3.working_length.ToString("0.0")) .Append(']'); if (val.assemblerId > 0 && val.assemblerId < pf.factorySystem.assemblerPool.Length) { AssemblerComponent val4 = pf.factorySystem.assemblerPool[val.assemblerId]; sb.Append(" asm[pool=").Append(val.assemblerId).Append(" r=") .Append(val4.recipeId) .Append(val4.replicating ? " WORK" : " idle") .Append(" t=") .Append(val4.time) .Append(']'); } if (val.inserterId > 0 && pf.factorySystem.inserterPool != null && val.inserterId < pf.factorySystem.inserterPool.Length) { InserterComponent val5 = pf.factorySystem.inserterPool[val.inserterId]; sb.Append(" ins[pool=").Append(val.inserterId).Append(" st=") .Append((int)val5.stage) .Append(" item=") .Append(val5.itemId) .Append(" pick=") .Append(val5.pickTarget) .Append(" put=") .Append(val5.insertTarget) .Append(" care=") .Append(val5.careNeeds ? 1 : 0) .Append(" filter=") .Append(val5.filter) .Append(']'); } if (val.powerConId > 0 && pf.powerSystem != null && pf.powerSystem.consumerPool != null && val.powerConId < pf.powerSystem.consumerPool.Length) { PowerConsumerComponent val6 = pf.powerSystem.consumerPool[val.powerConId]; sb.Append(" pc[req=").Append(val6.requiredEnergy).Append(" work=") .Append(val6.workEnergyPerTick) .Append(" idle=") .Append(val6.idleEnergyPerTick) .Append(" net=") .Append(val6.networkId); int networkId = val6.networkId; if (pf.powerSystem.netPool != null && networkId >= 0 && networkId < pf.powerSystem.netPool.Length && pf.powerSystem.netPool[networkId] != null) { PowerNetwork val7 = pf.powerSystem.netPool[networkId]; sb.Append(" ratio=").Append(val7.consumerRatio.ToString("0.000")).Append(" reqE=") .Append(val7.energyRequired) .Append(" servedE=") .Append(val7.energyServed); } if (pf.powerSystem.networkServes != null && networkId >= 0 && networkId < pf.powerSystem.networkServes.Length) { sb.Append(" serves=").Append(pf.powerSystem.networkServes[networkId].ToString("0.00")); } sb.Append(']'); } return sb.ToString(); } private static void ProbeInserter(PlanetFactory pf, HubComponent hub, int frame) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) FactorySystem factorySystem = pf.factorySystem; if (factorySystem.inserterPool == null) { return; } int entityId = hub.entityId; int num = 0; int num2 = Mathf.Min(factorySystem.inserterCursor, factorySystem.inserterPool.Length); for (int i = 1; i < num2; i++) { if (num >= 8) { break; } InserterComponent val = factorySystem.inserterPool[i]; if (val.id == i && val.insertTarget == entityId) { insEnt[num] = i; num++; } } if (num != insN) { insN = num; for (int j = 0; j < 8; j++) { if (j >= insN) { insSig[j] = 0L; insFrame[j] = 0; insText[j] = null; } } } for (int k = 0; k < insN; k++) { int num3 = insEnt[k]; if (num3 <= 0 || num3 >= factorySystem.inserterCursor) { continue; } InserterComponent ins = factorySystem.inserterPool[num3]; long num4 = InsSig(pf, ins); if (num4 != insSig[k] || insFrame[k] == 0) { int value = ((insFrame[k] > 0) ? (frame - insFrame[k]) : 0); insSig[k] = num4; insFrame[k] = frame; insText[k] = InsText(pf, num3, ins); if (insLogged < 240) { insLogged++; sb.Length = 0; sb.Append("[probe-ins] +").Append(value).Append("f ") .Append(insText[k]); Plugin.Log.LogInfo(sb.ToString()); } } } if (pf.entityNeeds == null || entityId <= 0 || entityId >= pf.entityNeeds.Length) { return; } int[] array = pf.entityNeeds[entityId]; int interfacePoolId = hub.InterfacePoolId; int[] array2 = ((interfacePoolId > 0 && interfacePoolId < factorySystem.assemblerPool.Length) ? factorySystem.assemblerPool[interfacePoolId].needs : null); int num5 = ((array != null) ? RuntimeHelpers.GetHashCode(array) : 0); long num6 = 0L; if (array != null) { for (int l = 0; l < array.Length && l < 6; l++) { num6 = H(num6, array[l]); } } if (needsInited && num5 == prevNeedsRef && num6 == prevNeedsHash) { return; } int value2 = (needsInited ? (frame - needsFrame) : 0); needsInited = true; prevNeedsRef = num5; prevNeedsHash = num6; needsFrame = frame; if (needsLogged >= 120) { return; } needsLogged++; sb.Length = 0; sb.Append("[probe-needs] +").Append(value2).Append("f ref=") .Append(num5.ToString("x8")) .Append(" sameAsIface=") .Append(array == array2) .Append(" len=") .Append((array != null) ? array.Length : (-1)) .Append(" val=["); if (array != null) { for (int m = 0; m < array.Length && m < 6; m++) { if (m > 0) { sb.Append(','); } sb.Append(array[m]); } } sb.Append("] ifacePool=").Append(interfacePoolId); Plugin.Log.LogInfo(sb.ToString()); } private static long InsSig(PlanetFactory pf, InserterComponent ins) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) long h = 17L; h = H(h, ins.entityId); h = H(h, ins.careNeeds ? 1 : 0); h = H(h, ins.filter); h = H(h, ins.pickTarget); h = H(h, ins.insertTarget); if (ins.entityId > 0 && ins.entityId < pf.entitySignPool.Length) { SignData val = pf.entitySignPool[ins.entityId]; h = H(h, val.signType); h = H(h, val.iconType); h = H(h, val.iconId0); } return h; } private static string InsText(PlanetFactory pf, int poolId, InserterComponent ins) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected I4, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) sb.Length = 0; sb.Append("pool=").Append(poolId).Append(" ent=") .Append(ins.entityId) .Append(" care=") .Append(ins.careNeeds ? 1 : 0) .Append(" filter=") .Append(ins.filter) .Append(" item=") .Append(ins.itemId) .Append(" stage=") .Append((int)ins.stage) .Append(" pick=") .Append(ins.pickTarget) .Append(" put=") .Append(ins.insertTarget) .Append(" typed=") .Append(ins.insertTargetTypedId.ToString("x8")); if (ins.entityId > 0 && ins.entityId < pf.entitySignPool.Length) { SignData val = pf.entitySignPool[ins.entityId]; sb.Append(" sign=").Append(val.signType).Append('/') .Append(val.iconType) .Append('/') .Append(val.iconId0); } return sb.ToString(); } private static void DumpPools(PlanetFactory pf, HubComponent hub) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) FactorySystem factorySystem = pf.factorySystem; int entityId = hub.entityId; sb.Length = 0; sb.Append("[probe-slots] hub=").Append(entityId).Append(" iface=") .Append(hub.InterfacePoolId) .Append(" slots:"); for (int i = 0; i < 8; i++) { int slotPoolId = hub.GetSlotPoolId(i); if (slotPoolId > 0 && slotPoolId < factorySystem.assemblerPool.Length) { AssemblerComponent val = factorySystem.assemblerPool[slotPoolId]; int value = ((val.entityId > 0 && val.entityId < pf.entityPool.Length) ? pf.entityPool[val.entityId].protoId : (-1)); sb.Append(" [").Append(i).Append("]池") .Append(slotPoolId) .Append(":e") .Append(val.entityId) .Append(":p") .Append(value) .Append(":r") .Append(val.recipeId); } } Plugin.Log.LogInfo(sb.ToString()); DumpPool("assembler", factorySystem, "assemblerPool", "assemblerCursor", pf, entityId); DumpPool("lab", factorySystem, "labPool", "labCursor", pf, entityId); DumpPool("miner", factorySystem, "minerPool", "minerCursor", pf, entityId); DumpPool("ejector", factorySystem, "ejectorPool", "ejectorCursor", pf, entityId); DumpPool("silo", factorySystem, "siloPool", "siloCursor", pf, entityId); DumpPool("fractionator", factorySystem, "fractionatorPool", "fractionatorCursor", pf, entityId); if (pf.powerSystem != null) { DumpPool("gen", pf.powerSystem, "genPool", "genCursor", pf, entityId); } DumpEntity(pf, entityId); DumpOwners(pf, entityId); if (factorySystem.inserterPool == null) { return; } int num = Mathf.Min(factorySystem.inserterCursor, factorySystem.inserterPool.Length); int num2 = 0; for (int j = 1; j < num; j++) { if (num2 >= 8) { break; } InserterComponent val2 = factorySystem.inserterPool[j]; if (val2.id == j && val2.insertTarget == entityId) { num2++; DumpEntity(pf, val2.entityId); DumpOwners(pf, val2.entityId); } } } private static void DumpPool(string tag, object holder, string poolField, string cursorField, PlanetFactory pf, int hubEntity) { if (holder == null) { return; } try { Type type = holder.GetType(); FieldInfo field = type.GetField(poolField, BindingFlags.Instance | BindingFlags.Public); if (field == null) { Plugin.Log.LogWarning("[probe-pool] 找不到字段 " + poolField); } else { if (!(field.GetValue(holder) is Array { Length: var num } array)) { return; } FieldInfo field2 = type.GetField(cursorField, BindingFlags.Instance | BindingFlags.Public); if (field2 != null && field2.FieldType == typeof(int)) { int num2 = (int)field2.GetValue(holder); if (num2 > 0) { num = num2; } } int num3 = Mathf.Min(num, array.Length); sb.Length = 0; sb.Append("[probe-pool] ").Append(tag).Append(" cursor=") .Append(num) .Append(':'); int num4 = 0; for (int i = 1; i < num3; i++) { if (num4 >= 120) { break; } object value = array.GetValue(i); if (value == null) { continue; } Type type2 = value.GetType(); FieldInfo field3 = type2.GetField("id"); FieldInfo field4 = type2.GetField("entityId"); FieldInfo field5 = type2.GetField("recipeId"); if (((field3 != null) ? ((int)field3.GetValue(value)) : (-1)) == i) { int num5 = ((field4 != null) ? ((int)field4.GetValue(value)) : (-1)); int value2 = ((num5 > 0 && num5 < pf.entityPool.Length && pf.entityPool[num5].id > 0) ? pf.entityPool[num5].protoId : (-1)); sb.Append(" i").Append(i).Append(":e") .Append(num5) .Append(":p") .Append(value2); if (field5 != null) { sb.Append(":r").Append((int)field5.GetValue(value)); } if (num5 == hubEntity) { sb.Append("<<HUB"); } num4++; } } if (num4 == 0) { sb.Append(" (空)"); } Plugin.Log.LogInfo(sb.ToString()); } } catch (Exception ex) { Plugin.Log.LogWarning("[probe-pool] " + tag + " dump 失败:" + ex.Message); } } private static void DumpEntity(PlanetFactory pf, int eid) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) try { if (eid <= 0 || eid >= pf.entityPool.Length) { return; } EntityData val = pf.entityPool[eid]; if (val.id <= 0) { return; } sb.Length = 0; sb.Append("[probe-entity] e=").Append(eid).Append(" proto=") .Append(val.protoId) .Append(" model=") .Append(val.modelIndex) .Append(" fields:"); FieldInfo[] fields = typeof(EntityData).GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { if (!(fieldInfo.FieldType != typeof(int))) { int num = (int)fieldInfo.GetValue(val); if (num != 0) { sb.Append(' ').Append(fieldInfo.Name).Append('=') .Append(num); } } } Plugin.Log.LogInfo(sb.ToString()); } catch (Exception ex) { Plugin.Log.LogWarning("[probe-entity] dump 失败:" + ex.Message); } } private static void DumpOwners(PlanetFactory pf, int eid) { try { FactorySystem factorySystem = pf.factorySystem; sb.Length = 0; sb.Append("[probe-owners] e=").Append(eid); if (eid > 0 && eid < pf.entityPool.Length) { sb.Append(" proto=").Append(pf.entityPool[eid].protoId); } sb.Append(" owners:"); string[] array = new string[6] { "asm", "lab", "miner", "ejector", "silo", "gen" }; foreach (string text in array) { string name = text switch { "silo" => "siloPool", "ejector" => "ejectorPool", "miner" => "minerPool", "lab" => "labPool", "asm" => "assemblerPool", _ => "genPool", }; object obj = ((text == "gen" && pf.powerSystem != null) ? ((object)pf.powerSystem) : ((object)factorySystem)); FieldInfo field = obj.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public); if (field == null || !(field.GetValue(obj) is Array array2)) { continue; } for (int j = 1; j < array2.Length; j++) { object value = array2.GetValue(j); if (value != null) { Type type = value.GetType(); FieldInfo field2 = type.GetField("id"); FieldInfo field3 = type.GetField("entityId"); if (!(field2 == null) && !(field3 == null) && (int)field2.GetValue(value) == j && (int)field3.GetValue(value) == eid) { FieldInfo field4 = type.GetField("recipeId"); sb.Append(' ').Append(text).Append(j) .Append(":r") .Append((field4 != null) ? ((int)field4.GetValue(value)) : (-1)); } } } } Plugin.Log.LogInfo(sb.ToString()); } catch (Exception ex) { Plugin.Log.LogWarning("[probe-owners] dump 失败:" + ex.Message); } } private static void DumpStats(PlanetFactory pf, HubComponent hub) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) try { FactorySystem factorySystem = pf.factorySystem; int entityId = hub.entityId; DumpPools(pf, hub); sb.Length = 0; sb.Append("[probe-stats] hub=").Append(entityId).Append(" iface=") .Append(hub.InterfacePoolId) .Append(" cursor=") .Append(factorySystem.assemblerCursor) .Append(" slots=["); for (int i = 0; i < 8; i++) { if (i > 0) { sb.Append(','); } sb.Append(hub.GetSlotPoolId(i)); } sb.Append("] sameEntity=["); int num = Mathf.Min(factorySystem.assemblerCursor, factorySystem.assemblerPool.Length); for (int j = 1; j < num; j++) { AssemblerComponent val = factorySystem.assemblerPool[j]; if (val.id == j && val.entityId == entityId) { sb.Append(j).Append(":r").Append(val.recipeId) .Append(val.replicating ? ":W" : ":I") .Append(":cc") .Append(val.cycleCount) .Append(":pc") .Append(val.pcId) .Append(":n") .Append((val.needs == null) ? (-1) : val.needs.Length) .Append(":s") .Append((val.served == null) ? (-1) : val.served.Length) .Append(' '); } } sb.Append(']'); Plugin.Log.LogInfo(sb.ToString()); int powerConId = pf.entityPool[entityId].powerConId; if (powerConId > 0 && pf.powerSystem != null && powerConId < pf.powerSystem.consumerPool.Length) { PowerConsumerComponent val2 = pf.powerSystem.consumerPool[powerConId]; sb.Length = 0; sb.Append("[probe-stats] power pc=").Append(powerConId).Append(" entity=") .Append(val2.entityId) .Append(" net=") .Append(val2.networkId) .Append(" req=") .Append(val2.requiredEnergy) .Append(" work=") .Append(val2.workEnergyPerTick) .Append(" idle=") .Append(val2.idleEnergyPerTick); int networkId = val2.networkId; if (pf.powerSystem.netPool != null && networkId >= 0 && networkId < pf.powerSystem.netPool.Length && pf.powerSystem.netPool[networkId] != null) { PowerNetwork val3 = pf.powerSystem.netPool[networkId]; sb.Append(" ratio=").Append(val3.consumerRatio.ToString("0.000000")).Append(" genRatio=") .Append(val3.generaterRatio.ToString("0.000000")) .Append(" reqE=") .Append(val3.energyRequired) .Append(" servedE=") .Append(val3.energyServed) .Append(" capE=") .Append(val3.energyCapacity) .Append(" consumers=") .Append((val3.consumers != null) ? val3.consumers.Count : (-1)); } Plugin.Log.LogInfo(sb.ToString()); } if (GameMain.statistics == null || GameMain.statistics.production == null || GameMain.statistics.production.factoryStatPool == null || pf.index < 0 || pf.index >= GameMain.statistics.production.factoryStatPool.Length) { return; } FactoryProductionStat val4 = GameMain.statistics.production.factoryStatPool[pf.index]; if (val4 == null) { return; } sb.Length = 0; sb.Append("[probe-stats] stat fields: "); FieldInfo[] fields = typeof(FactoryProductionStat).GetFields(BindingFlags.Instance | BindingFlags.Public); for (int k = 0; k < fields.Length; k++) { object obj = null; try { obj = fields[k].GetValue(val4); } catch { } Array array = obj as Array; sb.Append(fields[k].Name).Append('=').Append((array != null) ? ("arr" + array.Length) : ((obj == null) ? "null" : obj.ToString())) .Append(' '); } Plugin.Log.LogInfo(sb.ToString()); sb.Length = 0; sb.Append("[probe-stats] stat reg: productCursor=").Append(val4.productCursor); int[] array2 = new int[8] { 1101, 1102, 1104, 1201, 1202, 1203, 1204, 1301 }; foreach (int num2 in array2) { int value = ((val4.productRegister != null && num2 < val4.productRegister.Length) ? val4.productRegister[num2] : (-1)); int value2 = ((val4.consumeRegister != null && num2 < val4.consumeRegister.Length) ? val4.consumeRegister[num2] : (-1)); sb.Append(' ').Append(num2).Append(":p") .Append(value) .Append("/c") .Append(value2); } Plugin.Log.LogInfo(sb.ToString()); sb.Length = 0; sb.Append("[probe-stats] productPool:"); int num3 = 0; if (val4.productPool != null) { for (int m = 1; m < val4.productCursor && m < val4.productPool.Length; m++) { if (num3 >= 24) { break; } ProductStat val5 = val4.productPool[m]; if (val5 != null && val5.itemId > 0 && (val5.productionCount != 0 || val5.consumptionCount != 0 || !(val5.refProductSpeed <= 0f) || !(val5.refConsumeSpeed <= 0f))) { sb.Append(" [i").Append(val5.itemId).Append(" prod") .Append(val5.productionCount) .Append("/cons") .Append(val5.consumptionCount) .Append("/refP") .Append(val5.refProductSpeed.ToString("0.0")) .Append("/refC") .Append(val5.refConsumeSpeed.ToString("0.0")) .Append("/sto") .Append(val5.storageCount) .Append(']'); num3++; } } } sb.Append(" nonzero=").Append(num3); Plugin.Log.LogInfo(sb.ToString()); } catch (Exception ex) { if (errorLogged < 5) { errorLogged++; Plugin.Log.LogWarning("[probe-stats] dump 失败:" + ex.Message); } } } } internal static class EntityCustom { private const string KeyCustomId = "customId"; private const string KeyCustomType = "customType"; private static readonly FieldInfo CustomIdField = typeof(EntityData).GetField("customId", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo CustomTypeField = typeof(EntityData).GetField("customType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); public static bool ReflectionAvailable { get { if (CustomIdField != null) { return CustomTypeField != null; } return false; } } public static int GetCustomId(EntityData entity) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (CustomIdField != null) { return (int)CustomIdField.GetValue(entity); } try { return EntityDataExtensions.GetProperty<int>(ref entity, "customId"); } catch { return 0; } } public static int GetCustomType(EntityData entity) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (CustomTypeField != null) { return (int)CustomTypeField.GetValue(entity); } try { return EntityDataExtensions.GetProperty<int>(ref entity, "customType"); } catch { return 0; } } } internal static class HotTune { public static bool TickEnabled = true; public static bool VanillaDrive = true; public static bool Rebalance = true; public static bool Chain = true; public static int HoldMul = 4; public static int HoldFloor = 4; public static int ProductCap = 60; public static int ChainReserve = 4; public static bool ExportIntermediates = true; public static int SlotSpeedInt = 10000; public static int BusCap = 2000; public static int RequestMul = 4; public static int RequestFloor = 50; public static bool InsertFix = true; public static bool CopyPaste = true; public static bool AnimFix = true; public static bool PowerFix = false; public static bool ProbeAnim = false; public static bool ProbeIns = false; public static bool ProbeStats = false; private static DateTime lastWriteUtc = DateTime.MinValue; private static DateTime nextPollUtc = DateTime.MinValue; private static bool firstPoll = true; private static bool absentLogged; public static string FilePath => Path.Combine(Plugin.PluginDir, "hot-tune.txt"); public static void Poll() { DateTime utcNow = DateTime.UtcNow; if (utcNow < nextPollUtc) { return; } nextPollUtc = utcNow.AddMilliseconds(250.0); try { if (!File.Exists(FilePath)) { if (!absentLogged) { absentLogged = true; Plugin.Log.LogTune("[hot-tune] 未发现 " + FilePath + " —— 使用编译期默认值;写入该文件即可在线调参,无需重启游戏。"); } return; } DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(FilePath); if (firstPoll || !(lastWriteTimeUtc == lastWriteUtc)) { lastWriteUtc = lastWriteTimeUtc; bool first = firstPoll; firstPoll = false; Apply(File.ReadAllLines(FilePath), first); } } catch (Exception ex) { Plugin.Log.LogWarning("[hot-tune] 读取失败:" + ex.Message); } } private static void Apply(string[] lines, bool first) { List<string> list = new List<string>(); List<string> list2 = new List<string>(); for (int i = 0; i < lines.Length; i++) { string text = lines[i]; if (text == null) { continue; } text = text.Trim(); if (text.Length == 0 || text[0] == '#' || text[0] == ';') { continue; } int num = text.IndexOf('='); if (num <= 0) { continue; } string text2 = text.Substring(0, num).Trim().ToLowerInvariant(); string text3 = text.Substring(num + 1).Trim(); if (text3.Length == 0) { continue; } bool v; int v2; switch (text2) { case "tick": if (TryBool(text3, out v) && v != TickEnabled) { TickEnabled = v; list.Add("tick=" + (v ? 1 : 0)); } break; case "debug": if (TryBool(text3, out v) && v != HubWindow.DebugEnabled) { HubWindow.DebugEnabled = v; list.Add("debug=" + (v ? 1 : 0)); } break; case "drive": if (TryDrive(text3, out v) && v != VanillaDrive) { VanillaDrive = v; list.Add("drive=" + (v ? "vanilla" : "mod")); } break; case "rebalance": if (TryBool(text3, out v) && v != Rebalance) { Rebalance = v; list.Add("rebalance=" + (v ? 1 : 0)); } break; case "chain": if (TryBool(text3, out v) && v != Chain) { Chain = v; list.Add("chain=" + (v ? 1 : 0)); } break; case "holdmul": if (TryInt(text3, out v2) && v2 > 0 && v2 != HoldMul) { HoldMul = v2; list.Add("holdMul=" + v2); } break; case "holdfloor": if (TryInt(text3, out v2) && v2 >= 0 && v2 != HoldFloor) { HoldFloor = v2; list.Add("holdFloor=" + v2); } break; case "productcap": if (TryInt(text3, out v2) && v2 > 0 && v2 != ProductCap) { ProductCap = v2; list.Add("productCap=" + v2); } break; case "chainreserve": if (TryInt(text3, out v2) && v2 > 0 && v2 != ChainReserve) { ChainReserve = v2; list.Add("chainReserve=" + v2); } break; case "exportintermediates": if (TryBool(text3, out v) && v != ExportIntermediates) { ExportIntermediates = v; list.Add("exportIntermediates=" + (v ? 1 : 0)); } break; case "slotspeed": if (TryInt(text3, out v2) && v2 > 0 && v2 != SlotSpeedInt) { SlotSpeedInt = v2; list.Add("slotSpeed=" + v2); } break; case "buscap": if (TryInt(text3, out v2) && v2 > 0 && v2 != BusCap) { BusCap = v2; list.Add("busCap=" + v2); } break; case "requestmul": if (TryInt(text3, out v2) && v2 > 0 && v2 != RequestMul) { RequestMul = v2; list.Add("requestMul=" + v2); } break; case "requestfloor": if (TryInt(text3, out v2) && v2 >= 0 && v2 != RequestFloor) { RequestFloor = v2; list.Add("requestFloor=" + v2); } break; case "animfix": if (TryBool(text3, out v) && v != AnimFix) { AnimFix = v; list.Add("animFix=" + (v ? 1 : 0)); } break; case "copypaste": if (TryBool(text3, out v) && v != CopyPaste) { CopyPaste = v; list.Add("copypaste=" + (v ? 1 : 0)); } break; case "powerfix": if (TryBool(text3, out v) && v != PowerFix) { PowerFix = v; list.Add("powerFix=" + (v ? 1 : 0)); } break; case "probeanim": if (TryBool(text3, out v) && v != ProbeAnim) { ProbeAnim = v; list.Add("probeAnim=" + (v ? 1 : 0)); } break; case "probeins": if (TryBool(text3, out v) && v != ProbeIns) { ProbeIns = v; list.Add("probeIns=" + (v ? 1 : 0)); } break; case "probestats": if (TryBool(text3, out v) && v != ProbeStats) { ProbeStats = v; list.Add("probeStats=" + (v ? 1 : 0)); } break; case "insertfix": case "stackfix": if (TryBool(text3, out v) && v != InsertFix) { InsertFix = v; list.Add("insertfix=" + (v ? 1 : 0)); } break; default: list2.Add(text2); break; } } string text4 = string.Format("tick={0} debug={1} drive={2} rebalance={3} chain={4} holdMul={5} holdFloor={6} productCap={7} chainReserve={8} exportIntermediates={9} slotSpeed={10} busCap={11} requestMul={12} requestFloor={13} animFix={14} powerFix={15} probeAnim={16} probeIns={17} probeStats={18} copypaste={19}", TickEnabled ? 1 : 0, HubWindow.DebugEnabled ? 1 : 0, VanillaDrive ? "vanilla" : "mod", Rebalance ? 1 : 0, Chain ? 1 : 0, HoldMul, HoldFloor, ProductCap, ChainReserve, ExportIntermediates ? 1 : 0, SlotSpeedInt, BusCap, RequestMul, RequestFloor, AnimFix ? 1 : 0, PowerFix ? 1 : 0, ProbeAnim ? 1 : 0, ProbeIns ? 1 : 0, ProbeStats ? 1 : 0, CopyPaste ? 1 : 0); if (first) { Plugin.Log.LogTune("[hot-tune] 已加载 " + FilePath + " -> " + text4); } else if (list.Count > 0) { Plugin.Log.LogInfo("[hot-tune] 在线更新(无需重启游戏):" + string.Join(", ", list.ToArray()) + " | 当前 " + text4); } if (list2.Count > 0) { Plugin.Log.LogInfo("[hot-tune] 忽略未知键:" + string.Join(", ", list2.ToArray())); } } private static bool TryInt(string s, out int v) { return int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out v); } private static bool TryBool(string s, out bool v) { v = false; if (s == "1" || s.Equals("true", StringComparison.OrdinalIgnoreCase) || s.Equals("on", StringComparison.OrdinalIgnoreCase)) { v = true; return true; } if (s == "0" || s.Equals("false", StringComparison.OrdinalIgnoreCase) || s.Equals("off", StringComparison.OrdinalIgnoreCase)) { v = false; return true; } return false; } private static bool TryDrive(string s, out bool vanilla) { vanilla = false; if (s.Equals("vanilla", StringComparison.OrdinalIgnoreCase)) { vanilla = true; return true; } if (s.Equals("mod", StringComparison.OrdinalIgnoreCase)) { vanilla = false; return true; } return TryBool(s, out vanilla); } } internal sealed class HubComponent { public int entityId; private int[] bus = new int[12000]; private readonly object busLock = new object(); private readonly int[] sorterNeeds = new int[16]; private int sorterNeedCount; private int insertFixLogCount; private int[] slotIds = new int[8]; private readonly int[] lastSeenRecipe = new int[8]; private readonly int[] uiReqTypes = new int[48]; private int uiReqTypeCount; private readonly int[] uiUnadvExternalIds = new int[16]; private int uiUnadvExternalCount; private int uiExternalInputCount; private int uiAllInputCount; private int hubPcId; private PlanetFactory factory; private readonly int[] servedSnapshot = new int[48]; private static readonly int[] TempRegister = new int[12000]; private int lastSignFirst = -1; private int signLogCount; private int exportOverflowLogCount; private int needsChangeLogCount; private int probeTick; private int ttsTicks; private int ifaceProbeTick; private readonly int[] lastProbeTime = new int[8]; private int feedRotation; private readonly int[] needsCache = new int[6]; private readonly int[] hubInputIds = new int[6]; private readonly int[] candIds = new int[48]; private readonly int[] candCount = new int[48]; private readonly int[] candStock = new int[48]; private readonly int[] candUsed = new int[48]; private readonly int[] candExcluded = new int[48]; private int lastInternalExcludedHash; private readonly int[] wantTicks = new int[12000]; private readonly int[] encIds = new int[48]; private int lastEncCount; private int lastExcludedHash; private int needsAssertFailCount; private readonly int[] starvedTicks = new int[12000]; private readonly int[] starvedNow = new int[12000]; private bool inputMapDirty; private RecipeExecuteData interfaceRecipeOld; private int cachedInterfaceId; private RecipeExecuteData interfaceRecipe; private readonly int[] slotLastProduced = new int[6]; private readonly int[] lastCycle = new int[8]; private readonly bool[] cycleInit = new bool[8]; private readonly int[] outTaken = new int[12000]; private float hubAnimTime; private bool hubAnimInit; private int hubNormFrame = -1; private int hubNormErrorCount; private int consumeShortLogCount; private int producedLossLogCount; public PlanetFactory Factory => factory; public int AdvertisedCount { get { if (hubInputIds == null) { return 0; } int i; for (i = 0; i < hubInputIds.Length && hubInputIds[i] > 0; i++) { } return i; } } public int ExternalInputTypeCount => uiExternalInputCount; public int AllInputTypeCount => uiAllInputCount; public int WorkingSlotCount { get { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) int num = 0; FactorySystem val = ((factory != null) ? factory.factorySystem : null); if (val == null) { return 0; } for (int i = 0; i < slotIds.Length; i++) { if (TryGetSlotRef(val, i, out var slot) && slot.recipeId != 0 && slot.replicating) { num++; } } return num; } } public int OccupiedSlotCount { get { int num = 0; for (int i = 0; i < 8; i++) { if (GetSlotRecipe(i) != 0) { num++; } } return num; } } public int InterfacePoolId { get { try { return (factory != null) ? InterfaceSlotId() : (-1); } catch { return -1; } } } public int GetBusCount(int itemId) { if (bus == null || itemId <= 0 || itemId >= bus.Length) { return 0; } return bus[itemId]; } public int GetAdvertisedItem(int index) { if (hubInputIds == null || index < 0 || index >= hubInputIds.Length) { return 0; } return hubInputIds[index]; } public int GetHubStock(int itemId) { return HubBuffered(itemId); } public int CollectProducts(int[] items, int[] counts, int max) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) if (items == null || counts == null || max <= 0) { return 0; } if (items.Length < max || counts.Length < max) { return 0; } EnsureBus(); FactorySystem val = ((factory != null) ? factory.factorySystem : null); int num = 0; if (val != null) { for (int i = 0; i < slotIds.Length; i++) { if (!TryGetSlotRef(val, i, out var slot) || slot.recipeExecuteData == null || slot.produced == null) { continue; } int[] products = slot.recipeExecuteData.products; if (products == null) { continue; } int num2 = Mathf.Min(products.Length, slot.produced.Length); for (int j = 0; j < num2; j++) { int num3 = products[j]; if (num3 <= 0) { continue; } int num4 = -1; for (int k = 0; k < num; k++) { if (items[k] == num3) { num4 = k; break; } } if (num4 < 0) { if (num >= max) { continue; } num4 = num; items[num4] = num3; counts[num4] = 0; num++; } counts[num4] += slot.produced[j]; } } } for (int l = 0; l < num; l++) { int num5 = items[l]; if (num5 > 0 && bus != null && num5 < bus.Length) { counts[l] += bus[num5]; } } for (int m = num; m < max; m++) { items[m] = 0; counts[m] = 0; } return num; } public int RequiredInputTypeCount() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) uiReqTypeCount = 0; FactorySystem val = ((factory != null) ? factory.factorySystem : null); if (val == null) { return 0; } for (int i = 0; i < slotIds.Length; i++) { if (!TryGetSlotRef(val, i, out var slot) || slot.recipeExecuteData == null || slot.recipeExecuteData.requires == null) { continue; } int[] requires = slot.recipeExecuteData.requires; foreach (int num in requires) { if (num > 0 && IndexOf(uiReqTypes, uiReqTypeCount, num) < 0) { if (uiReqTypeCount >= uiReqTypes.Length) { break; } uiReqTypes[uiReqTypeCount++] = num; } } } return uiReqTypeCount; } public int FillUnadvertisedInputs(int[] items, int max) { if (items == null || max <= 0) { return 0; } int num = RequiredInputTypeCount(); int num2 = 0; for (int i = 0; i < num; i++) { if (num2 >= max) { break; } int num3 = uiReqTypes[i]; if (!Contains(hubInputIds, hubInputIds.Length, num3)) { items[num2++] = num3; } } return num2; } public int FillRequiredInputs(int[] items, int max) { if (items == null || max <= 0) { return 0; } int num = RequiredInputTypeCount(); int num2 = 0; for (int i = 0; i < hubInputIds.Length; i++) { if (num2 >= max) { break; } int num3 = hubInputIds[i]; if (num3 > 0 && IndexOf(uiReqTypes, num, num3) >= 0 && !Contains(items, num2, num3)) { items[num2++] = num3; } } for (int j = 0; j < num; j++) { if (num2 >= max) { break; } int num4 = uiReqTypes[j]; if (!Contains(items, num2, num4)) { items[num2++] = num4; } } return num2; } public bool IsAdvertisedItem(int itemId) { if (itemId > 0) { return Contains(hubInputIds, hubInputIds.Length, itemId); } return false; } public int GetUnadvertisedExternalInputs(int[] items, int max) { if (items == null || max <= 0) { return 0; } int num = Mathf.Min(uiUnadvExternalCount, max); for (int i = 0; i < num; i++) { items[i] = uiUnadvExternalIds[i]; } return num; } public int TakeProductStock(int itemId, int max) { //IL_0045: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if (itemId <= 0 || max <= 0) { return 0; } EnsureBus(); FactorySystem val = ((factory != null) ? factory.factorySystem : null); int num = 0; if (val != null) { for (int i = 0; i < slotIds.Length; i++) { if (num >= max) { break; } if (!TryGetSlotRef(val, i, out var slot) || slot.recipeExecuteData == null || slot.produced == null) { continue; } int[] products = slot.recipeExecuteData.products; if (products == null) { continue; } bool flag = false; int num2 = Mathf.Min(products.Length, slot.produced.Length); for (int j = 0; j < num2; j++) { if (num >= max) { break; } if (products[j] == itemId && slot.produced[j] > 0) { int num3 = Mathf.Min(slot.produced[j], max - num); slot.produced[j] -= num3; num += num3; flag = true; } } if (flag) { WriteSlot(val, i, ref slot); } } } if (num < max && bus != null && itemId < bus.Length) { lock (busLock) { int num4 = Mathf.Min(bus[itemId], max - num); if (num4 > 0) { bus[itemId] -= num4; num += num4; } } } return num; } public int TakeStock(int itemId, int max) { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) if (itemId <= 0 || max <= 0 || bus == null || itemId >= bus.Length) { return 0; } int num = 0; lock (busLock) { int num2 = Mathf.Min(bus[itemId], max); if (num2 > 0) { bus[itemId] -= num2; num += num2; } } FactorySystem val = ((factory != null) ? factory.factorySystem : null); if (val == null || num >= max) { return num; } int num3 = InterfaceSlotId(); if (num3 > 0 && num3 < val.assemblerPool.Length && hubInputIds != null) { AssemblerComponent val2 = val.assemblerPool[num3]; if (val2.served != null) { for (int i = 0; i < hubInputIds.Length && i < val2.served.Length; i++) { if (num >= max) { break; } if (hubInputIds[i] == itemId && val2.served[i] > 0) { int num4 = Mathf.Min(val2.served[i], max - num); val2.served[i] -= num4; if (val2.served[i] == 0 && val2.incServed != null && i < val2.incServed.Length) { val2.incServed[i] = 0; } num += num4; } } val.assemblerPool[num3] = val2; } } if (num >= max) { return num; } for (int j = 0; j < 8; j++) { if (num >= max) { break; } if (!TryGetSlotRef(val, j, out var slot) || slot.recipeExecuteData == null || slot.served == null) { continue; } int[] requires = slot.recipeExecuteData.requires; if (requires == null) { continue; } bool flag = false; for (int k = 0; k < requires.Length && k < slot.served.Length; k++) { if (num >= max) { break; } if (requires[k] == itemId && slot.served[k] > 0) { int num5 = Mathf.Min(slot.served[k], max - num); slot.served[k] -= num5; if (slot.served[k] == 0 && slot.incServed != null && k < slot.incServed.Length) { slot.incServed[k] = 0; } num += num5; flag = true; } } if (flag) { WriteSlot(val, j, ref slot); } } return num; } public void GiveBack(int itemId, int count) { if (itemId <= 0 || count <= 0 || bus == null || itemId >= bus.Length) { return; } lock (busLock) { int num = HotTune.BusCap - bus[itemId]; if (num > 0) { bus[itemId] += Mathf.Min(num, count); } } } public bool IsHubInputItem(int itemId) { if (itemId <= 0) { return false; } for (int i = 0; i < sorterNeedCount; i++) { if (sorterNeeds[i] == itemId) { return true; } } return false; } public void RebuildSorterNeeds() { int num = 0; for (int i = 0; i < hubInputIds.Length; i++) { if (num >= sorterNeeds.Length) { break; } int num2 = hubInputIds[i]; if (num2 <= 0) { continue; } bool flag = false; for (int j = 0; j < num; j++) { if (sorterNeeds[j] == num2) { flag = true; break; } } if (!flag) { sorterNeeds[num++] = num2; } } for (int k = 0; k < 8; k++) { if (num >= sorterNeeds.Length) { break; } int slotRecipe = GetSlotRecipe(k); if (slotRecipe <= 0) { continue; } RecipeProto val = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(slotRecipe); if (val == null || val.Items == null) { continue; } for (int l = 0; l < val.Items.Length; l++) { if (num >= sorterNeeds.Length) { break; } int num3 = val.Items[l]; if (num3 <= 0) { continue; } bool flag2 = false; for (int m = 0; m < num; m++) { if (sorterNeeds[m] == num3) { flag2 = true; break; } } if (!flag2) { sorterNeeds[num++] = num3; } } } for (int n = num; n < sorterNeeds.Length; n++) { sorterNeeds[n] = 0; } sorterNeedCount = num; } public void BindEntityNeeds() { if (factory == null || entityId <= 0) { return; } try { int num = InterfaceSlotId(); if (num > 0 && factory.entityPool[entityId].assemblerId != num) { factory.entityPool[entityId].assemblerId = num; } int[][] entityNeeds = factory.entityNeeds; if (entityNeeds != null && entityId < entityNeeds.Length) { entityNeeds[entityId] = sorterNeeds; } } catch { } } public int TryInsertBusItem(int itemId, int count) { if (itemId <= 0 || count <= 0 || itemId >= 12000) { return 0; } EnsureBus(); if (itemId >= bus.Length) { return 0; } lock (busLock) { if (HotTune.BusCap - bus[itemId] < count) { return 0; } bus[itemId] += count; return count; } } public void NoteInsertFix(int itemId, int accepted) { if (insertFixLogCount < 20) { insertFixLogCount++; Plugin.Log.LogInfo(string.Format("[insertfix] 分拣器投料短路:item={0} x{1} → {2}(entity {3})", itemId, accepted, (accepted > 0) ? "已进内部总线" : "总线满拒收", entityId)); } } public void Init(PlanetFactory planet) { factory = planet; EnsureBus(); if (planet.factorySystem == null) { return; } hubPcId = planet.entityPool[entityId].powerConId; LogInitDiag("F1-前(创建槽位前)"); if (InterfaceSlotId() <= 0) { int num = planet.factorySystem.NewAssemblerComponent(entityId, 10000); if (num > 0) { planet.entityPool[entityId].assemblerId = num; cachedInterfaceId = num; Plugin.Log.LogInfo("[问题3] 接口位组件缺失,已补建 assemblerId=" + num + "(实体 " + entityId + ")"); } } SetupHubInterfaceSlot(); ReuseExistingSlots(); for (int i = 0; i < 8; i++) { EnsureSlot(i); } ApplyHubEnergyDeclaration(); LogInitDiag("F1-后(槽位创建并恢复 assemblerId 后)"); if ((Object)(object)HubWindow.Instance != (Object)null) { HubWindow.Instance.LogSlotIds(this); } Plugin.Log.LogInfo($"枢纽组件就绪:实体 {entityId},pcId={hubPcId},接口位 assemblerId={planet.entityPool[entityId].assemblerId},槽位 {8} 个。"); } public void OnAdded(PrebuildData data, PlanetFactory planet) { Init(planet); } public void OnRemoved(PlanetFactory planet) { FactorySystem val = planet?.factorySystem; int num = 0; try { num = InterfaceSlotId(); } catch { } try { RefundAllToPlayer(val); } catch (Exception ex) { Plugin.Log.LogWarning("拆除枢纽退还物品失败(部分物品可能丢失):" + ex.Message); } if (val != null && slotIds != null) { for (int i = 0; i < slotIds.Length; i++) { if (slotIds[i] > 0) { val.RemoveAssemblerComponent(slotIds[i]); slotIds[i] = 0; } } } if (val != null && num > 0 && num < val.assemblerPool.Length && val.assemblerPool[num].id == num) { val.RemoveAssemblerComponent(num); } try { if (factory != null && factory.entityPool != null && entityId > 0 && entityId < factory.entityPool.Length) { factory.entityPool[entityId].assemblerId = 0; } } catch { } cachedInterfaceId = 0; if (bus != null) { Array.Clear(bus, 0, bus.Length); } factory = null; } public void Free() { factory = null; hubPcId = 0; if (slotIds != null) { Array.Clear(slotIds, 0, slotIds.Length); } if (bus != null) { Array.Clear(bus, 0, bus.Length); } } private static void GiveToPlayer(Player player, int itemId, int count, int objId) { if (player == null || itemId <= 0 || count <= 0) { return; } try { int num = player.TryAddItemToPackage(itemId, count, 0, true, objId, false); if (num > 0) { UIItemup.Up(itemId, num); } } catch (Exception ex) { Plugin.Log.LogWarning("退还物品失败 item=" + itemId + ":" + ex.Message); } } private void RefundAllToPlayer(FactorySystem fs) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) Player mainPlayer = GameMain.mainPlayer; if (mainPlayer == null || fs == null) { return; } int objId = entityId; if (slotIds != null) { for (int i = 0; i < slotIds.Length; i++) { int num = slotIds[i]; if (num > 0 && num < fs.assemblerPool.Length) { try { fs.TakeBackItems_Assembler(mainPlayer, num); } catch (Exception ex) { Plugin.Log.LogWarning("退还槽位 " + i + " 缓存失败:" + ex.Message); } } } } int num2 = InterfaceSlotId(); if (num2 > 0 && num2 < fs.assemblerPool.Length && hubInputIds != null) { AssemblerComponent val = fs.assemblerPool[num2]; if (val.served != null) { int num3 = Mathf.Min(val.served.Length, hubInputIds.Length); bool flag = false; for (int j = 0; j < num3; j++) { int num4 = val.served[j]; int num5 = hubInputIds[j]; if (num4 > 0 && num5 > 0) { GiveToPlayer(mainPlayer, num5, num4, objId); val.served[j] = 0; if (val.incServed != null && j < val.incServed.Length) { val.incServed[j] = 0; } flag = true; } } if (flag) { fs.assemblerPool[num2] = val; } } } EnsureBus(); if (bus == null) { return; } lock (busLock) { for (int k = 1; k < bus.Length; k++) { int num6 = bus[k]; if (num6 > 0) { GiveToPlayer(mainPlayer, k, num6, objId); bus[k] = 0; } } } } private void EnsureBus() { if (bus == null || bus.Length < 12000) { bus = new int[12000]; } } private void RefreshHubSign() { if (factory == null || entityId <= 0 || !IsAlive()) { return; } SignData[] entitySignPool = factory.entitySignPool; if (entitySignPool == null || entityId >= entitySignPool.Length) { return; } int num = 0; int num2 = 0; for (int i = 0; i < 8; i++) { int slotRecipe = GetSlotRecipe(i); if (slotRecipe != 0) { if (num == 0) { num = slotRecipe; } num2++; } } if (entitySignPool[entityId].signType != 0) { if (signLogCount < 120) { signLogCount++; Plugin.Log.LogInfo("[sign] 枢纽实体 signType=" + entitySignPool[entityId].signType + " → 压制为 0(隐藏)"); } entitySignPool[entityId].signType = 0u; } if (entitySignPool[entityId].count0 != (float)num2 || lastSignFirst != num) { lastSignFirst = num; entitySignPool[entityId].iconType = ((num > 0) ? 2u : 0u); entitySignPool[entityId].iconId0 = (uint)num; entitySignPool[entityId].count0 = num2; } } private void EnsureSlot(int index) { if (factory == null || factory.factorySystem == null) { return; } FactorySystem factorySystem = factory.factorySystem; if (index < 0 || index >= 8) { return; } int num = slotIds[index]; if (num > 0 && num < factorySystem.assemblerPool.Length && factorySystem.assemblerPool[num].id == num && factorySystem.assemblerPool[num].entityId == entityId) { return; } int num2 = InterfaceSlotId(); int assemblerId = factory.entityPool[entityId].assemblerId; num = factorySystem.NewAssemblerComponent(entityId, 10000); if (num <= 0) { Plugin.Log.LogError($"枢纽槽位 {index} 分配 assemblerPool 组件失败(返回 {num}),该槽位本次不可用。"); return; } if (num2 > 0 && num2 < factorySystem.assemblerPool.Length && factorySystem.assemblerPool[num2].id == num2) { factory.entityPool[entityId].assemblerId = num2; cachedInterfaceId = num2; } else { factory.entityPool[entityId].assemblerId = assemblerId; } factorySystem.assemblerPool[num].pcId = hubPcId; slotIds[index] = num; } private void ReuseExistingSlots() { FactorySystem val = ((factory != null) ? factory.factorySystem : null); if (val == null) { return; } int num = InterfaceSlotId(); if (num <= 0) { return; } int num2 = 16; int[] array = new int[num2]; int num3 = 0; int num4 = Mathf.Min(val.assemblerCursor, val.assemblerPool.Length); for (int i = 1; i < num4; i++) { if (num3 >= num2) { break; } if (val.assemblerPool[i].id == i && val.assemblerPool[i].entityId == entityId && i != num) { array[num3++] = i; } } if (num3 == 0) { return; } Array.Sort(array, 0, num3); int num5 = 0; for (int j = 0; j < 8 && j < num3; j++) { if (slotIds[j] <= 0) { slotIds[j] = array[j]; num5++; } } if (num5 > 0) { Plugin.Log.LogInfo($"[F1] 复用读档里已存在的槽位组件 {num5} 个(避免每次读档重复创建导致 pool 膨胀)。"); } } private void LogInitDiag(string tag) { //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_03a5: Unknown result type (might be due to invalid IL or missing references) try { FactorySystem val = ((factory != null) ? factory.factorySystem : null); if (val == null) { Plugin.Log.LogInfo("[F1] " + tag + ":factorySystem=null"); return; } int assemblerId = factory.entityPool[entityId].assemblerId; StringBuilder stringBuilder = new StringBuilder(320); stringBuilder.Append("[F1] ").Append(tag).Append(":entityPool.assemblerId=") .Append(assemblerId) .Append(",assemblerCursor=") .Append(val.assemblerCursor) .Append(",slotIds=["); for (int i = 0; i < 8; i++) { if (i > 0) { stringBuilder.Append(','); } stringBuilder.Append(slotIds[i]); } stringBuilder.Append("],slotRecipes=["); for (int j = 0; j < 8; j++) { if (j > 0) { stringBuilder.Append(','); } stringBuilder.Append(GetSlotRecipe(j)); } stringBuilder.Append(']'); stringBuilder.Append(",同实体组件=["); bool flag = true; int num = Mathf.Min(val.assemblerCursor, val.assemblerPool.Length); for (int k = 1; k < num; k++) { if (val.assemblerPool[k].id == k && val.assemblerPool[k].entityId == entityId) { if (!flag) { stringBuilder.Append(','); } flag = false; stringBuilder.Append(k).Append(':').Append(val.assemblerPool[k].recipeId) .Append(':') .Append((val.assemblerPool[k].served == null) ? (-1) : val.assemblerPool[k].served.Length); } } stringBuilder.Append(']'); int value = -1; int num2 = Mathf.Min(val.assemblerCursor, val.assemblerPool.Length); for (int l = 1; l < num2; l++) { if (val.assemblerPool[l].id == l && val.assemblerPool[l].entityId == entityId && l != assemblerId && val.assemblerPool[l].recipeId == 0 && val.assemblerPool[l].served == null) { value = l; break; } } if (assemblerId > 0 && assemblerId < val.assemblerPool.Length && val.assemblerPool[assemblerId].id == assemblerId) { AssemblerComponent val2 = val.assemblerPool[assemblerId]; stringBuilder.Append(",接口有效性:id=").Append(assemblerId).Append(" recipeId=") .Append(val2.recipeId) .Append(" entityId=") .Append(val2.entityId) .Append(" servedLen=") .Append((val2.served == null) ? (-1) : val2.served.Length) .Append(" needsLen=") .Append((val2.needs == null) ? (-1) : val2.needs.Length) .Append(" assemblerId字段=") .Append(factory.entityPool[entityId].assemblerId) .Append(" entityNeeds同引用="); bool value2 = false; try { int[][] entityNeeds = factory.entityNeeds; value2 = entityNeeds != null && entityId > 0 && entityId < entityNeeds.Length && entityNeeds[entityId] == val2.needs; } catch { } stringBuilder.Append(value2); } stringBuilder.Append(",原生装配候选(recipeId=0且served=null)=").Append(value); bool flag2 = false; for (int m = 0; m < 8; m++) { if (slotIds[m] == assemblerId) { flag2 = true; } } stringBuilder.Append(",接口位与槽位冲突=").Append(flag2); if (flag2) { Plugin.Log.LogInfo(stringBuilder.ToString()); } else { Plugin.Log.LogInfo(stringBuilder.ToString()); } } catch (Exception ex) { Plugin.Log.LogInfo("[F1] 诊断日志失败:" + ex.Message); } } public int GetSlotRecipe(int index) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!TryGetSlotRef((factory != null) ? factory.factorySystem : null, index, out var slot)) { return 0; } return slot.recipeId; } public void SetSlotRecipe(int index, int recipeId, bool refund = true) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (factory == null || index < 0 || index >= 8) { return; } EnsureSlot(index); FactorySystem factorySystem = factory.factorySystem; int num = slotIds[index]; if (num <= 0 || num >= factorySystem.assemblerPool.Length) { return; } if (recipeId > 0) { RecipeProto val = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(recipeId); if (val == null || !HubConst.IsRecipeTypeAllowed(val.Type)) { Plugin.Log.LogInfo(string.Format("分子装配枢纽拒绝配方 {0}(类型 {1}):分馏/研究/光子存储类配方需要专用机器逻辑,其它类型(含 MOD 扩展类型)都允许。", recipeId, (val != null) ? ((object)Unsafe.As<ERecipeType, ERecipeType>(ref val.Type)/*cast due to .constrained prefix*/).ToString() : "null")); return; } } int recipeId2 = factorySystem.assemblerPool[num].recipeId; if (recipeId2 == recipeId) { lastSeenRecipe[index] = recipeId; return; } if (refund && recipeId2 > 0) { Player mainPlayer = GameMain.mainPlayer; if (mainPlayer != null) { try { factorySystem.TakeBackItems_Assembler(mainPlayer, num); } catch (Exception ex) { Plugin.Log.LogWarning("退还槽位缓存物品失败:" + ex.Message); } } } ((AssemblerComponent)(ref factorySystem.assemblerPool[num])).SetRecipe(recipeId, factory.entitySignPool); factorySystem.assemblerPool[num].pcId = hubPcId; if (factorySystem.assemblerPool[num].served != null) { Array.Clear(factorySystem.assemblerPool[num].served, 0, factorySystem.assemblerPool[num].served.Length); } if (factorySystem.assemblerPool[num].incServed != null) { Array.Clear(factorySystem.assemblerPool[num].incServed, 0, factorySystem.assemblerPool[num].incServed.Length); } if (factorySystem.assemblerPool[num].produced != null) { Array.Clear(factorySystem.assemblerPool[num].produced, 0, factorySystem.assemblerPool[num].produced.Length); } factorySystem.assemblerPool[num].time = 0; if (recipeId == 0) { for (int i = 0; i < hubInputIds.Length; i++) { hubInputIds[i] = 0; } } interfaceRecipe = null; inputMapDirty = true; lastSeenRecipe[index] = recipeId; Plugin.Log.LogInfo($"SetSlotRecipe:槽位 {index}(assemblerPool id={num})设为配方 {recipeId},回读 {factorySystem.assemblerPool[num].recipeId},已清空输入缓冲"); RefreshHubSign(); } public int GetSlotPoolId(int index) { if (slotIds == null || index < 0 || index >= slotIds.Length) { return -1; } return slotIds[index]; } public bool IsAlive() { if (factory == null || factory.entityPool == null) { return false; } if (entityId <= 0 || entityId >= factory.entityPool.Length) { return false; } if (factory.entityPool[entityId].id != entityId) { return false; } try { ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select((int)factory.entityPool[entityId].protoId); return val != null && ((Proto)val).ID == HubConst.RuntimeItemId; } catch { return false; } } public bool TryGetSlot(int index, out AssemblerComponent slot) { return TryGetSlotRef((factory != null) ? factory.factorySystem : null, index, out slot); } private bool TryGetSlotRef(FactorySystem fs, int index, out AssemblerComponent slot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) slot = default(AssemblerComponent); if (fs == null || slotIds == null || index < 0 || index >= slotIds.Length) { return false; } int num = slotIds[index]; if (num <= 0 || fs.assemblerPool == null || num >= fs.assemblerPool.Length) { return false; } if (fs.assemblerPool[num].id != num) { return false; } slot = fs.assemblerPool[num]; return true; } public int InternalUpdate(float power, PlanetFactory planet) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) factory = planet; FactorySystem factorySystem = planet.factorySystem; if (factorySystem == null) { return 0; } FactoryProductionStat val = ((GameMain.statistics != null) ? GameMain.statistics.production.factoryStatPool[planet.index] : null); int[] array = ((val != null) ? val.productRegister : TempRegister); int[] array2 = ((val != null) ? val.consumeRegister : TempRegister); int num = 0; for (int i = 0; i < 8; i++) { if (TryGetSlotRef(factorySystem, i, out var slot) && slot.recipeId != 0 && slot.recipeExecuteData != null) { num++; PushToBus(factorySystem, i, ref slot); FeedFromBus(factorySystem, i, ref slot); slot.speed = HotTune.SlotSpeedInt; slot.speedOverride = HotTune.SlotSpeedInt; ((AssemblerComponent)(ref slot)).InternalUpdate(power, array, array2); FeedFromBus(factorySystem, i, ref slot); SnapshotServed(i, ref slot); } } RefreshHubSign(); return (num > 0) ? 1 : 0; } private void PushToBus(FactorySystem fs, int index, ref AssemblerComponent slot) { int[] requires = slot.recipeExecuteData.requires; int[] requireCounts = slot.recipeExecuteData.requireCounts; if (slot.served == null) { return; } int num = ((!HotTune.Rebalance) ? ServedHoldSize(requireCounts) : 0); for (int i = 0; i < requires.Length && i < slot.served.Length; i++) { int num2 = (HotTune.Rebalance ? ServedHoldSizeAt(requireCounts, i) : num); int num3 = slot.served[i] - num2; if (num3 <= 0) { continue; } int num4 = requires[i]; if (num4 <= 0 || num4 >= bus.Length) { continue; } lock (busLock) { if (bus[num4] + num3 > HotTune.BusCap) { num3 = Mathf.Max(0, HotTune.BusCap - bus[num4]); } if (num3 <= 0) { continue; } bus[num4] += num3; goto IL_00e3; } IL_00e3: slot.served[i] -= num3; if (slot.served[i] == 0) { slot.incServed[i] = 0; } } WriteSlot(fs, index, ref slot); } private void FeedFromBus(FactorySystem fs, int index, ref AssemblerComponent slot) { int[] requires = slot.recipeExecuteData.requires; int[] requireCounts = slot.recipeExecuteData.requireCounts; if (slot.served == null) { return; } int num = ((!HotTune.Rebalance) ? ServedHoldSize(requireCounts) : 0); for (int i = 0; i < requires.Length && i < slot.served.Length; i++) { int num2 = requires[i]; if (num2 <= 0 || num2 >= bus.Length) { continue; } int num3 = (HotTune.Rebalance ? ServedHoldSizeAt(requireCounts, i) : num) - slot.served[i]; if (num3 <= 0) { continue; } int num4 = Mathf.Min(num3, bus[num2]); if (HotTune.Rebalance && num4 > 0) { int num5 = ((i >= requireCounts.Length || requireCounts[i] <= 0) ? 1 : requireCounts[i]); num4 = Mathf.Min(num4, num5); } if (num4 <= 0) { continue; } lock (busLock) { if (num4 > bus[num2]) { num4 = bus[num2]; } if (num4 <= 0) { continue; } bus[num2] -= num4; goto IL_010f; } IL_010f: slot.served[i] += num4; } WriteSlot(fs, index, ref slot); } private void FeedAllFromBusFair(FactorySystem fs) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) int num = 8; bool[] array = new bool[num]; for (int i = 0; i < num; i++) { int num2 = -1; float num3 = -1f; for (int j = 0; j < num; j++) { int num4 = (feedRotation + j) % num; if (!array[num4] && TryGetSlotRef(fs, num4, out var slot) && slot.recipeId != 0 && slot.recipeExecuteData != null) { float num5 = SlotDeficitScore(ref slot); if (num5 > num3) { num3 = num5; num2 = num4; } } } if (num2 < 0) { break; } array[num2] = true; if (TryGetSlotRef(fs, num2, out var slot2)) { FeedFromBus(fs, num2, ref slot2); } } feedRotation = (feedRotation + 1) % num; } private static float SlotDeficitScore(ref AssemblerComponent slot) { int[] requires = slot.recipeExecuteData.requires; int[] requireCounts = slot.recipeExecuteData.requireCounts; if (requires == null || requireCounts == null || slot.served == null) { return 0f; } float num = 0f; for (int i = 0; i < requires.Length && i < requireCounts.Length && i < slot.served.Length; i++) { int num2 = ServedHoldSizeAt(requireCounts, i); if (num2 > 0) { int num3 = num2 - slot.served[i]; if (num3 > 0) { num += (float)num3 / (float)num2; } } } return num; } private static int ServedHoldSize(int[] requireCounts) { int num = 1; for (int i = 0; i < requireCounts.Length; i++) { if (requireCounts[i] > num) { num = requireCounts[i]; } } return Mathf.Max(num * 20, 60); } private static int ServedHoldSizeAt(int[] requireCounts, int k) { int num = ((k >= requireCounts.Length) ? 1 : requireCounts[k]); if (num < 1) { num = 1; } return Mathf.Max(num * HotTune.HoldMul, HotTune.HoldFloor); } private bool IsInternalProduct(int itemId) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) FactorySystem val = ((factory != null) ? factory.factorySystem : null); if (val == null) { return false; } for (int i = 0; i < 8; i++) { if (!TryGetSlotRef(val, i, out var slot) || slot.recipeId == 0 || slot.recipeExecuteData == null) { continue; } int[] products = slot.recipeExecuteData.products; if (products == null) { continue; } for (int j = 0; j < products.Length; j++) { if (products[j] == itemId) { return true; } } } return false; } private bool IsInternalNeed(int itemId) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) FactorySystem val = ((factory != null) ? factory.factorySystem : null); if (val == null) { return false; } for (int i = 0; i < 8; i++) { if (!TryGetSlotRef(val, i, out var slot) || slot.recipeId == 0 || slot.recipeExecuteData == null) { continue; } int[] requires = slot.recipeExecuteData.requires; if (requires == null) { continue; } for (int j = 0; j < requires.Length; j++) { if (requires[j] == itemId) { return true; } } } return false; } private int InternalDemand(int itemId) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) FactorySystem val = ((factory != null) ? factory.factorySystem : null); if (val == null) { return 0; } int num = 0; for (int i = 0; i < 8; i++) { if (!TryGetSlotRef(val, i, out var slot) || slot.recipeId == 0 || slot.recipeExecuteData == null) { continue; } int[] requires = slot.recipeExecuteData.requires; int[] requireCounts = slot.recipeExecuteData.requireCounts; if (requires == null || requireCounts == null) { continue; } for (int j = 0; j < requires.Length && j < requireCounts.Length; j++) { if (requires[j] == itemId) { num += ((requireCounts[j] <= 0) ? 1 : requireCounts[j]); } } } return num; } private int PushProductsToBus(FactorySystem fs, int index, ref AssemblerComponent slot) { if (slot.produced == null || slot.recipeExecuteData == null) { return 0; } int[] products = slot.recipeExecuteData.products; if (products == null) { return 0; } int num = 0; for (int i = 0; i < products.Length && i < slot.produced.Length; i++) { int num2 = products[i]; if (num2 <= 0 || num2 >= bus.Length) { continue; } int num3 = slot.produced[i]; if (num3 > 0 && IsInternalNeed(num2)) { int num4 = Mathf.Min(HotTune.BusCap, HotTune.ProductCap) - bus[num2]; int num5 = Mathf.Min(num3, num4); if (num5 > 0) { bus[num2] += num5; slot.produced[i] -= num5; num += num5; } } } if (num > 0) { WriteSlot(fs, index, ref slot); } return num; } private void WriteSlot(FactorySystem fs, int index, ref AssemblerComponent slot) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) int num = slotIds[index]; if (num > 0 && fs.assemblerPool != null && num < fs.assemblerPool.Length) { fs.assemblerPool[num] = slot; } } private void SnapshotServed(int slotIndex, ref AssemblerComponent slot) { int num = slotIndex * 6; for (int i = 0; i < 6; i++) { servedSnapshot[num + i] = ((slot.served != null && i < slot.served.Length) ? slot.served[i] : 0); } } public int GetServedSnapshot(int slotIndex, int itemIndex) { int num = slotIndex * 6 + itemIndex; if (num < 0 || num >= servedSnapshot.Length) { return 0; } return servedSnapshot[num]; } public void ApplyHubEnergyDeclaration() { if (factory == null) { return; } if (hubPcId <= 0) { hubPcId = factory.entityPool[entityId].powerConId; } if (hubPcId > 0) { PowerConsumerComponent[] consumerPool = factory.powerSystem.consumerPool; if (consumerPool != null && hubPcId < consumerPool.Length && consumerPool[hubPcId].id == hubPcId) { consumerPool[hubPcId].workEnergyPerTick = 360000L; consumerPool[hubPcId].idleEnergyPerTick = 7200L; } } } public void UpdatePowerState(ref PowerConsumerComponent component) { if (hubPcId <= 0 && factory != null) { hubPcId = factory.entityPool[entityId].powerConId; } component.workEnergyPerTick = 360000L; component.idleEnergyPerTick = 7200L; } public int[] UpdateNeeds() { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) EnsureBus(); for (int i = 0; i < needsCache.Length; i++) { needsCache[i] = 0; } FactorySystem val = ((factory != null) ? factory.factorySystem : null); if (val == null) { return needsCache; } Array.Clear(candIds, 0, candIds.Length); Array.Clear(ca