Decompiled source of DSP MolecularHub v0.1.9

BepInEx\plugins\DSP-MolecularHub\DSP-MolecularHub.dll

Decompiled 2 days ago
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