Decompiled source of AssemblerVerticalConstruction v1.1.13

AssemblerVerticalConstruction.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using crecheng.DSPModSave;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AssemblerVerticalConstruction")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AssemblerVerticalConstruction")]
[assembly: AssemblyCopyright("Copyright lltcggie  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("5678B572-A4A6-488A-8229-BE42EB9AEFE3")]
[assembly: AssemblyFileVersion("1.1.13.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.1.13.0")]
namespace AssemblerVerticalConstruction;

public class AssemblerComponentEx
{
	public const int DefaultProductTransferStack = 9;

	public const int DefaultProductBufferStack = 9;

	private const int InputSlotCount = 6;

	public int[][] assemblerNextIds = new int[384][];

	private long[][] assemblerInputReceivedTicks = new long[384][];

	private int[][] assemblerInputReceivedCounts = new int[384][];

	public int assemblerCapacity = 384;

	public int transfarCount = 6;

	private int productTransferStack = 9;

	private int productBufferStack = 9;

	public int ProductTransferStack
	{
		get
		{
			return productTransferStack;
		}
		set
		{
			productTransferStack = Math.Max(1, value);
		}
	}

	public int ProductBufferStack
	{
		get
		{
			return productBufferStack;
		}
		set
		{
			productBufferStack = Math.Max(1, value);
		}
	}

	public void SetCargoStackLimit(int stack)
	{
		int val = (ProductTransferStack = Math.Max(1, stack));
		ProductBufferStack = Math.Max(9, val);
	}

	public void SetAssemblerCapacity(int newCapacity)
	{
		if (newCapacity > assemblerNextIds.Length)
		{
			int[][] array = assemblerNextIds;
			long[][] array2 = assemblerInputReceivedTicks;
			int[][] array3 = assemblerInputReceivedCounts;
			assemblerNextIds = new int[newCapacity][];
			assemblerInputReceivedTicks = new long[newCapacity][];
			assemblerInputReceivedCounts = new int[newCapacity][];
			if (array != null)
			{
				Array.Copy(array, assemblerNextIds, array.Length);
				Array.Copy(array2, assemblerInputReceivedTicks, array2.Length);
				Array.Copy(array3, assemblerInputReceivedCounts, array3.Length);
			}
			assemblerCapacity = newCapacity;
		}
	}

	public void EnsureAssemblerArray(int factoryIndex, int requiredCapacity)
	{
		EnsureFactoryIndex(factoryIndex);
		int[] array = assemblerNextIds[factoryIndex];
		long[] array2 = assemblerInputReceivedTicks[factoryIndex];
		int[] array3 = assemblerInputReceivedCounts[factoryIndex];
		if (array == null || array.Length < requiredCapacity || array2 == null || array2.Length < array.Length || array3 == null || array3.Length < array.Length * 6)
		{
			int val = ((array != null) ? array.Length : 0);
			int num = Math.Max(Math.Max(requiredCapacity, val), 256);
			int[] array4 = new int[num];
			if (array != null)
			{
				Array.Copy(array, array4, array.Length);
			}
			assemblerNextIds[factoryIndex] = array4;
			long[] array5 = new long[num];
			if (array2 != null)
			{
				Array.Copy(array2, array5, array2.Length);
			}
			assemblerInputReceivedTicks[factoryIndex] = array5;
			int[] array6 = new int[num * 6];
			if (array3 != null)
			{
				Array.Copy(array3, array6, array3.Length);
			}
			assemblerInputReceivedCounts[factoryIndex] = array6;
		}
	}

	public void ClearAssemblerArray(int factoryIndex, int requiredCapacity)
	{
		EnsureAssemblerArray(factoryIndex, requiredCapacity);
		Array.Clear(assemblerNextIds[factoryIndex], 0, assemblerNextIds[factoryIndex].Length);
		Array.Clear(assemblerInputReceivedTicks[factoryIndex], 0, assemblerInputReceivedTicks[factoryIndex].Length);
		Array.Clear(assemblerInputReceivedCounts[factoryIndex], 0, assemblerInputReceivedCounts[factoryIndex].Length);
	}

	public int GetNextId(int index, int assemblerId)
	{
		if (index >= assemblerNextIds.Length)
		{
			return 0;
		}
		if (assemblerNextIds[index] == null || assemblerId >= assemblerNextIds[index].Length)
		{
			return 0;
		}
		return assemblerNextIds[index][assemblerId];
	}

	public int[] GetNextIds(int factoryIndex)
	{
		if (factoryIndex < 0 || factoryIndex >= assemblerNextIds.Length)
		{
			return null;
		}
		return assemblerNextIds[factoryIndex];
	}

	public static void FindRecipeIdForBuild(FactorySystem factorySystem, int assemblerId)
	{
		int entityId = factorySystem.assemblerPool[assemblerId].entityId;
		if (entityId == 0)
		{
			return;
		}
		int num = entityId;
		bool flag = default(bool);
		int num2 = default(int);
		int num3 = default(int);
		do
		{
			factorySystem.factory.ReadObjectConn(num, 14, ref flag, ref num2, ref num3);
			num = num2;
			if (num > 0)
			{
				int assemblerId2 = factorySystem.factory.entityPool[num].assemblerId;
				if (assemblerId2 > 0 && factorySystem.assemblerPool[assemblerId2].id == assemblerId2 && factorySystem.assemblerPool[assemblerId2].recipeId > 0)
				{
					((AssemblerComponent)(ref factorySystem.assemblerPool[assemblerId])).SetRecipe(factorySystem.assemblerPool[assemblerId2].recipeId, factorySystem.factory.entitySignPool);
					SyncForceAccModeFromSource(factorySystem, assemblerId, assemblerId2);
					return;
				}
			}
		}
		while (num != 0);
		num = entityId;
		do
		{
			factorySystem.factory.ReadObjectConn(num, 15, ref flag, ref num2, ref num3);
			num = num2;
			if (num > 0)
			{
				int assemblerId3 = factorySystem.factory.entityPool[num].assemblerId;
				if (assemblerId3 > 0 && factorySystem.assemblerPool[assemblerId3].id == assemblerId3 && factorySystem.assemblerPool[assemblerId3].recipeId > 0)
				{
					((AssemblerComponent)(ref factorySystem.assemblerPool[assemblerId])).SetRecipe(factorySystem.assemblerPool[assemblerId3].recipeId, factorySystem.factory.entitySignPool);
					SyncForceAccModeFromSource(factorySystem, assemblerId, assemblerId3);
					break;
				}
			}
		}
		while (num != 0);
	}

	private static void SyncForceAccModeFromSource(FactorySystem factorySystem, int targetAssemblerId, int sourceAssemblerId)
	{
		ref AssemblerComponent reference = ref factorySystem.assemblerPool[targetAssemblerId];
		ref AssemblerComponent reference2 = ref factorySystem.assemblerPool[sourceAssemblerId];
		if (reference.recipeExecuteData != null && reference.recipeExecuteData.productive)
		{
			reference.forceAccMode = reference2.forceAccMode;
		}
	}

	public void SetAssemblerInsertTarget(PlanetFactory __instance, int assemblerId, int nextEntityId)
	{
		int index = __instance.factorySystem.factory.index;
		EnsureAssemblerArray(index, assemblerId + 1);
		if (assemblerId != 0 && __instance.factorySystem.assemblerPool[assemblerId].id == assemblerId)
		{
			if (nextEntityId == 0)
			{
				assemblerNextIds[index][assemblerId] = 0;
				return;
			}
			int assemblerId2 = __instance.entityPool[nextEntityId].assemblerId;
			assemblerNextIds[index][assemblerId] = assemblerId2;
			FindRecipeIdForBuild(__instance.factorySystem, assemblerId);
		}
	}

	public void UnsetAssemblerInsertTarget(PlanetFactory __instance, int assemblerId, int assemblerRemoveId)
	{
		int index = __instance.factorySystem.factory.index;
		EnsureAssemblerArray(index, Math.Max(assemblerId, assemblerRemoveId) + 1);
		int[] array = assemblerNextIds[index];
		if (assemblerRemoveId > 0 && assemblerRemoveId < array.Length)
		{
			Interlocked.Exchange(ref array[assemblerRemoveId], 0);
		}
		if (assemblerId > 0 && assemblerId < array.Length && array[assemblerId] == assemblerRemoveId)
		{
			Interlocked.CompareExchange(ref array[assemblerId], 0, assemblerRemoveId);
		}
	}

	public void SetAssemblerNext(int index, int assemblerId, int nextId)
	{
		EnsureAssemblerArray(index, assemblerId + 1);
		assemblerNextIds[index][assemblerId] = nextId;
	}

	public void RebuildAssemblerRelation(PlanetFactory factory, int assemblerId)
	{
		RebuildAssemblerRelation(factory, assemblerId, synchronizeRecipe: true);
	}

	internal void RebuildAssemblerRelation(PlanetFactory factory, int assemblerId, bool synchronizeRecipe)
	{
		if (factory == null || factory.factorySystem == null || assemblerId <= 0)
		{
			return;
		}
		FactorySystem factorySystem = factory.factorySystem;
		AssemblerComponent[] assemblerPool = factorySystem.assemblerPool;
		if (assemblerId >= assemblerPool.Length || assemblerPool[assemblerId].id != assemblerId)
		{
			return;
		}
		int entityId = assemblerPool[assemblerId].entityId;
		if (entityId <= 0)
		{
			return;
		}
		int index = factory.index;
		EnsureAssemblerArray(index, assemblerId + 1);
		bool flag = default(bool);
		int num = default(int);
		int num2 = default(int);
		factory.ReadObjectConn(entityId, 15, ref flag, ref num, ref num2);
		int nextId = 0;
		if (flag && num > 0 && num < factory.entityPool.Length)
		{
			int assemblerId2 = factory.entityPool[num].assemblerId;
			if (assemblerId2 > 0 && assemblerId2 < assemblerPool.Length && assemblerPool[assemblerId2].id == assemblerId2)
			{
				nextId = assemblerId2;
			}
		}
		SetAssemblerNext(index, assemblerId, nextId);
		factory.ReadObjectConn(entityId, 14, ref flag, ref num, ref num2);
		if (num > 0 && num < factory.entityPool.Length)
		{
			int assemblerId3 = factory.entityPool[num].assemblerId;
			if (assemblerId3 > 0 && assemblerId3 < assemblerPool.Length && assemblerPool[assemblerId3].id == assemblerId3)
			{
				SetAssemblerNext(index, assemblerId3, assemblerId);
			}
		}
		if (synchronizeRecipe)
		{
			FindRecipeIdForBuild(factorySystem, assemblerId);
		}
	}

	public void UpdateOutputToNext(PlanetFactory factory, int planeIndex, int assemblerId, AssemblerComponent[] assemblerPool, int assemblerNextId, long transferTick, bool useMutex)
	{
		if (assemblerId <= 0 || assemblerNextId <= 0 || assemblerId >= assemblerPool.Length || assemblerNextId >= assemblerPool.Length)
		{
			ClearAssemblerNextIfMatches(planeIndex, assemblerId, assemblerNextId);
		}
		else if (useMutex)
		{
			int entityId = assemblerPool[assemblerId].entityId;
			int entityId2 = assemblerPool[assemblerNextId].entityId;
			if (entityId > 0 && entityId2 > 0)
			{
				lock (factory.entityMutexs[entityId])
				{
					lock (factory.entityMutexs[entityId2])
					{
						UpdateOutputToNextInner(factory, planeIndex, assemblerId, assemblerNextId, assemblerPool, transferTick);
						return;
					}
				}
			}
			ClearAssemblerNextIfMatches(planeIndex, assemblerId, assemblerNextId);
		}
		else
		{
			UpdateOutputToNextInner(factory, planeIndex, assemblerId, assemblerNextId, assemblerPool, transferTick);
		}
	}

	private void UpdateOutputToNextInner(PlanetFactory factory, int planeIndex, int assemblerId, int assemblerNextId, AssemblerComponent[] assemblerPool, long transferTick)
	{
		ref AssemblerComponent reference = ref assemblerPool[assemblerId];
		ref AssemblerComponent reference2 = ref assemblerPool[assemblerNextId];
		if (reference.id != assemblerId || reference2.id != assemblerNextId)
		{
			ClearAssemblerNextIfMatches(planeIndex, assemblerId, assemblerNextId);
			return;
		}
		bool flag = default(bool);
		int num = default(int);
		int num2 = default(int);
		factory.ReadObjectConn(reference.entityId, 15, ref flag, ref num, ref num2);
		if (!flag || num != reference2.entityId)
		{
			int newNextId = 0;
			if (flag && num > 0 && num < factory.entityPool.Length)
			{
				int assemblerId2 = factory.entityPool[num].assemblerId;
				if (assemblerId2 > 0 && assemblerId2 < assemblerPool.Length && assemblerPool[assemblerId2].id == assemblerId2)
				{
					newNextId = assemblerId2;
				}
			}
			ReplaceAssemblerNextIfMatches(planeIndex, assemblerId, assemblerNextId, newNextId);
		}
		else
		{
			if (reference.recipeId <= 0 || reference.recipeId != reference2.recipeId || reference.served == null || reference2.served == null || reference.recipeExecuteData == null || reference2.recipeExecuteData == null)
			{
				return;
			}
			RecipeExecuteData recipeExecuteData = reference.recipeExecuteData;
			RecipeExecuteData recipeExecuteData2 = reference2.recipeExecuteData;
			int timeSpend = recipeExecuteData2.timeSpend;
			if (timeSpend <= 0)
			{
				return;
			}
			int num3 = Math.Max(2, reference2.speedOverride * 180 / timeSpend + 1);
			int[] served = reference.served;
			int[] incServed = reference.incServed;
			int[] served2 = reference2.served;
			int[] incServed2 = reference2.incServed;
			int[] requireCounts = recipeExecuteData2.requireCounts;
			long[] array = assemblerInputReceivedTicks[planeIndex];
			int[] array2 = assemblerInputReceivedCounts[planeIndex];
			int num4 = assemblerId * 6;
			int num5 = assemblerNextId * 6;
			bool flag2 = array[assemblerId] == transferTick;
			bool flag3 = array[assemblerNextId] == transferTick;
			bool flag4 = false;
			int num6 = served.Length;
			for (int i = 0; i < num6; i++)
			{
				int num7 = served[i];
				int num8 = requireCounts[i] * num3 - served2[i];
				int num9 = (flag2 ? array2[num4 + i] : 0);
				int num10 = num7 - num9;
				if (num8 > 0 && num10 > 0)
				{
					ref int reference3 = ref incServed[i];
					int num11 = Math.Min(num10, num8);
					if (reference3 <= 0)
					{
						reference3 = 0;
					}
					int num12 = split_inc_level(ref served[i], ref reference3, num11);
					if (served[i] == 0)
					{
						reference3 = 0;
					}
					served2[i] += num11;
					incServed2[i] += num11 * num12;
					if (!flag3)
					{
						array[assemblerNextId] = transferTick;
						array2[num5] = 0;
						array2[num5 + 1] = 0;
						array2[num5 + 2] = 0;
						array2[num5 + 3] = 0;
						array2[num5 + 4] = 0;
						array2[num5 + 5] = 0;
						flag3 = true;
					}
					array2[num5 + i] += num11;
					flag4 = true;
				}
			}
			if (flag4)
			{
				((AssemblerComponent)(ref reference)).UpdateNeeds();
				((AssemblerComponent)(ref reference2)).UpdateNeeds();
			}
			int num13 = productTransferStack;
			int num14 = productBufferStack;
			int[] productCounts = recipeExecuteData.productCounts;
			int[] produced = reference.produced;
			int[] produced2 = reference2.produced;
			int num15 = productCounts.Length;
			for (int j = 0; j < num15; j++)
			{
				int num16 = productCounts[j];
				int num17 = num16 * num14 - produced[j];
				int num18 = produced2[j];
				if (num17 > 0 && num18 > 0)
				{
					int val = num16 * num13;
					int num19 = Math.Min(num17, Math.Min(val, num18));
					produced[j] += num19;
					produced2[j] -= num19;
				}
			}
		}
	}

	private void EnsureFactoryIndex(int factoryIndex)
	{
		if (factoryIndex >= assemblerNextIds.Length)
		{
			int num = assemblerNextIds.Length;
			while (factoryIndex >= num)
			{
				num *= 2;
			}
			SetAssemblerCapacity(num);
		}
	}

	private void ClearAssemblerNextIfMatches(int index, int assemblerId, int expectedNextId)
	{
		ReplaceAssemblerNextIfMatches(index, assemblerId, expectedNextId, 0);
	}

	private void ReplaceAssemblerNextIfMatches(int index, int assemblerId, int expectedNextId, int newNextId)
	{
		if (index >= 0 && index < assemblerNextIds.Length)
		{
			int[] array = assemblerNextIds[index];
			if (array != null && assemblerId > 0 && assemblerId < array.Length && array[assemblerId] == expectedNextId)
			{
				Interlocked.CompareExchange(ref array[assemblerId], newNextId, expectedNextId);
			}
		}
	}

	private int split_inc_level(ref int n, ref int m, int p)
	{
		if (n <= 0)
		{
			return 0;
		}
		int num = m / n;
		int num2 = m - num * n;
		n -= p;
		int num3 = num2 - n;
		m -= ((num3 > 0) ? (num * p + num3) : (num * p));
		return num;
	}
}
[BepInPlugin("lltcggie.DSP.plugin.AssemblerVerticalConstruction", "AssemblerVerticalConstruction", "1.1.13")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[ModSaveSettings(/*Could not decode attribute arguments.*/)]
public class AssemblerVerticalConstruction : BaseUnityPlugin, IModCanSave
{
	public static readonly int CurrentSavedataVersion = 4;

	private const string FractionateEverythingGuid = "com.menglei.dsp.fe";

	private static readonly Version FractionateEverythingStackingVersion = new Version(2, 3, 0);

	private const int FractionateEverythingStackLimit = 20;

	private const string StackLimitNotice = " This is only an upper limit; the actual height is also restricted by the game's construction range, so tall buildings may stop below this value. Requires restart. / 此值仅为上限,实际高度还受游戏建造范围限制,高层建筑可能达不到该层数;需要重启。";

	private static ManualLogSource _logger;

	public static ManualLogSource Logger => _logger;

	private AssemblerVerticalConstruction()
	{
		_logger = ((BaseUnityPlugin)this).Logger;
	}

	public void Awake()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Expected O, but got Unknown
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Expected O, but got Unknown
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Expected O, but got Unknown
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Expected O, but got Unknown
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Expected O, but got Unknown
		AcceptableValueRange<int> val = new AcceptableValueRange<int>(2, 32);
		ConfigEntry<int> obj = ((BaseUnityPlugin)this).Config.Bind<int>("Stack Limits", "AssemblerMaxStackCount", 12, new ConfigDescription("Maximum assembler stack count at the highest vertical construction technology level. This is only an upper limit; the actual height is also restricted by the game's construction range, so tall buildings may stop below this value. Requires restart. / 此值仅为上限,实际高度还受游戏建造范围限制,高层建筑可能达不到该层数;需要重启。", (AcceptableValueBase)(object)val, Array.Empty<object>()));
		ConfigEntry<int> val2 = ((BaseUnityPlugin)this).Config.Bind<int>("Stack Limits", "SmelterMaxStackCount", 14, new ConfigDescription("Maximum smelter stack count at the highest vertical construction technology level. This is only an upper limit; the actual height is also restricted by the game's construction range, so tall buildings may stop below this value. Requires restart. / 此值仅为上限,实际高度还受游戏建造范围限制,高层建筑可能达不到该层数;需要重启。", (AcceptableValueBase)(object)val, Array.Empty<object>()));
		ConfigEntry<int> val3 = ((BaseUnityPlugin)this).Config.Bind<int>("Stack Limits", "ChemicalPlantMaxStackCount", 9, new ConfigDescription("Maximum chemical plant stack count at the highest vertical construction technology level. This is only an upper limit; the actual height is also restricted by the game's construction range, so tall buildings may stop below this value. Requires restart. / 此值仅为上限,实际高度还受游戏建造范围限制,高层建筑可能达不到该层数;需要重启。", (AcceptableValueBase)(object)val, Array.Empty<object>()));
		ConfigEntry<int> val4 = ((BaseUnityPlugin)this).Config.Bind<int>("Stack Limits", "OilRefineryMaxStackCount", 5, new ConfigDescription("Maximum oil refinery stack count at the highest vertical construction technology level. This is only an upper limit; the actual height is also restricted by the game's construction range, so tall buildings may stop below this value. Requires restart. / 此值仅为上限,实际高度还受游戏建造范围限制,高层建筑可能达不到该层数;需要重启。", (AcceptableValueBase)(object)val, Array.Empty<object>()));
		ConfigEntry<int> val5 = ((BaseUnityPlugin)this).Config.Bind<int>("Stack Limits", "ParticleColliderMaxStackCount", 4, new ConfigDescription("Maximum miniature particle collider stack count at the highest vertical construction technology level. This is only an upper limit; the actual height is also restricted by the game's construction range, so tall buildings may stop below this value. Requires restart. / 此值仅为上限,实际高度还受游戏建造范围限制,高层建筑可能达不到该层数;需要重启。", (AcceptableValueBase)(object)val, Array.Empty<object>()));
		RemoveLegacyResetConfig();
		AssemblerPatches.ApplyMaxStackCounts(obj.Value, val2.Value, val3.Value, val4.Value, val5.Value);
		ApplyKnownModCompatibility();
		Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
	}

	private void RemoveLegacyResetConfig()
	{
		string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
		if (!File.Exists(configFilePath) || File.ReadAllText(configFilePath).IndexOf("IsResetNextIds", StringComparison.Ordinal) < 0)
		{
			return;
		}
		bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
		try
		{
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("config", "IsResetNextIds", false, "Obsolete internal repair option.");
			((BaseUnityPlugin)this).Config.Remove(((ConfigEntryBase)val).Definition);
			((BaseUnityPlugin)this).Config.Save();
		}
		finally
		{
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
		}
	}

	public void Import(BinaryReader binaryReader)
	{
		if ((Object)(object)DSPGame.Game == (Object)null)
		{
			return;
		}
		int num = binaryReader.ReadInt32() * -1;
		if (num < CurrentSavedataVersion)
		{
			Logger.LogInfo((object)$"Old save data version: read {num} current {CurrentSavedataVersion}");
			Logger.LogInfo((object)"ResetNextIds");
			AssemblerPatches.ResetNextIds();
			return;
		}
		if (num != CurrentSavedataVersion)
		{
			Logger.LogWarning((object)$"Invalid save data version: read {num} current {CurrentSavedataVersion}");
			Logger.LogInfo((object)"ResetNextIds");
			AssemblerPatches.ResetNextIds();
			return;
		}
		int num2 = binaryReader.ReadInt32();
		if (num2 > AssemblerPatches.assemblerComponentEx.assemblerCapacity)
		{
			AssemblerPatches.assemblerComponentEx.SetAssemblerCapacity(num2);
		}
		for (int i = 0; i < num2; i++)
		{
			int num3 = binaryReader.ReadInt32();
			for (int j = 0; j < num3; j++)
			{
				int nextId = binaryReader.ReadInt32();
				AssemblerPatches.assemblerComponentEx.SetAssemblerNext(i, j, nextId);
			}
		}
	}

	public void Export(BinaryWriter binaryWriter)
	{
		if ((Object)(object)DSPGame.Game == (Object)null)
		{
			return;
		}
		binaryWriter.Write(CurrentSavedataVersion * -1);
		binaryWriter.Write(AssemblerPatches.assemblerComponentEx.assemblerCapacity);
		for (int i = 0; i < AssemblerPatches.assemblerComponentEx.assemblerCapacity; i++)
		{
			if (AssemblerPatches.assemblerComponentEx.assemblerNextIds[i] != null)
			{
				binaryWriter.Write(AssemblerPatches.assemblerComponentEx.assemblerNextIds[i].Length);
				for (int j = 0; j < AssemblerPatches.assemblerComponentEx.assemblerNextIds[i].Length; j++)
				{
					binaryWriter.Write(AssemblerPatches.assemblerComponentEx.assemblerNextIds[i][j]);
				}
			}
			else
			{
				binaryWriter.Write(0);
			}
		}
	}

	public void IntoOtherSave()
	{
		if (!((Object)(object)DSPGame.Game == (Object)null) && !DSPGame.IsMenuDemo)
		{
			Logger.LogInfo((object)"ResetNextIds");
			AssemblerPatches.ResetNextIds();
		}
	}

	private static void ApplyKnownModCompatibility()
	{
		if (Chainloader.PluginInfos.TryGetValue("com.menglei.dsp.fe", out var value))
		{
			Version version = value.Metadata.Version;
			if (!(version == null) && !(version < FractionateEverythingStackingVersion))
			{
				AssemblerVerticalConstructionCompat.SetCargoStackLimit(20);
				Logger.LogInfo((object)$"Detected FractionateEverything {version}; set stacked product transfer/buffer stack limit to {20}.");
			}
		}
	}
}
public static class AssemblerVerticalConstructionCompat
{
	public static int ProductTransferStack
	{
		get
		{
			return AssemblerPatches.assemblerComponentEx.ProductTransferStack;
		}
		set
		{
			AssemblerPatches.assemblerComponentEx.ProductTransferStack = value;
		}
	}

	public static int ProductBufferStack
	{
		get
		{
			return AssemblerPatches.assemblerComponentEx.ProductBufferStack;
		}
		set
		{
			AssemblerPatches.assemblerComponentEx.ProductBufferStack = value;
		}
	}

	public static void SetCargoStackLimit(int stack)
	{
		AssemblerPatches.assemblerComponentEx.SetCargoStackLimit(stack);
	}

	public static void RebuildAssemblerRelation(PlanetFactory factory, int assemblerId)
	{
		AssemblerPatches.RebuildAssemblerRelation(factory, assemblerId);
	}

	public static void RebuildFactoryRelations(PlanetFactory factory)
	{
		AssemblerPatches.RebuildFactoryRelations(factory);
	}

	public static void RebuildAllRelations()
	{
		AssemblerPatches.ResetNextIds();
	}
}
[HarmonyPatch]
internal class AssemblerPatches
{
	private class ModelSetting
	{
		public bool multiLevelAllowPortsOrSlots;

		public List<int> multiLevelAlternativeIds;

		public List<bool> multiLevelAlternativeYawTransposes;

		public Vector3 lapJoint;

		public int[] multiLevelMaxBuildCount;

		public ModelSetting(bool multiLevelAllowPortsOrSlots, List<int> multiLevelAlternativeIds, List<bool> multiLevelAlternativeYawTransposes, Vector3 lapJoint, int[] multiLevelMaxBuildCount)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			this.multiLevelAllowPortsOrSlots = multiLevelAllowPortsOrSlots;
			this.multiLevelAlternativeIds = multiLevelAlternativeIds;
			this.multiLevelAlternativeYawTransposes = multiLevelAlternativeYawTransposes;
			this.lapJoint = lapJoint;
			this.multiLevelMaxBuildCount = multiLevelMaxBuildCount;
		}
	}

	private static readonly ModelSetting AssemblerSetting = new ModelSetting(multiLevelAllowPortsOrSlots: false, new List<int> { 2303, 2304, 2305, 2318 }, new List<bool> { false, false, false, false }, new Vector3(0f, 5.05f, 0f), new int[7] { 2, 4, 6, 8, 10, 11, 12 });

	private static readonly ModelSetting SmelterSetting = new ModelSetting(multiLevelAllowPortsOrSlots: false, new List<int> { 2302, 2315, 2319, 6230 }, new List<bool> { false, false, false, false }, new Vector3(0f, 4.3f, 0f), new int[7] { 2, 4, 6, 8, 10, 12, 14 });

	private static readonly ModelSetting ChemicalPlantSetting = new ModelSetting(multiLevelAllowPortsOrSlots: false, new List<int> { 2309, 2317 }, new List<bool> { false, false }, new Vector3(0f, 6.85f, 0f), new int[7] { 2, 4, 5, 6, 7, 8, 9 });

	private static readonly ModelSetting OilRefinerySetting = new ModelSetting(multiLevelAllowPortsOrSlots: false, new List<int> { 2308 }, new List<bool> { false }, new Vector3(0f, 11.8f, 0f), new int[7] { 1, 2, 2, 3, 3, 4, 5 });

	private static readonly ModelSetting MiniatureParticleColliderSetting = new ModelSetting(multiLevelAllowPortsOrSlots: false, new List<int> { 2310 }, new List<bool> { false }, new Vector3(0f, 15.2f, 0f), new int[7] { 1, 2, 2, 3, 3, 3, 4 });

	private static readonly Dictionary<int, ModelSetting> ModelSettingDict = new Dictionary<int, ModelSetting>
	{
		{ 2303, AssemblerSetting },
		{ 2304, AssemblerSetting },
		{ 2305, AssemblerSetting },
		{ 2318, AssemblerSetting },
		{ 2302, SmelterSetting },
		{ 2315, SmelterSetting },
		{ 2319, SmelterSetting },
		{ 6230, SmelterSetting },
		{ 2309, ChemicalPlantSetting },
		{ 2317, ChemicalPlantSetting },
		{ 2308, OilRefinerySetting },
		{ 2310, MiniatureParticleColliderSetting }
	};

	public static AssemblerComponentEx assemblerComponentEx = new AssemblerComponentEx();

	public static void ApplyMaxStackCounts(int assembler, int smelter, int chemicalPlant, int oilRefinery, int particleCollider)
	{
		ApplyMaxStackCount(AssemblerSetting, assembler);
		ApplyMaxStackCount(SmelterSetting, smelter);
		ApplyMaxStackCount(ChemicalPlantSetting, chemicalPlant);
		ApplyMaxStackCount(OilRefinerySetting, oilRefinery);
		ApplyMaxStackCount(MiniatureParticleColliderSetting, particleCollider);
	}

	private static void ApplyMaxStackCount(ModelSetting setting, int maxStackCount)
	{
		int[] multiLevelMaxBuildCount = setting.multiLevelMaxBuildCount;
		int num = multiLevelMaxBuildCount.Length - 1;
		for (int i = 0; i < num; i++)
		{
			if (multiLevelMaxBuildCount[i] > maxStackCount)
			{
				multiLevelMaxBuildCount[i] = maxStackCount;
			}
		}
		multiLevelMaxBuildCount[num] = maxStackCount;
	}

	public static void RebuildAssemblerRelation(PlanetFactory factory, int assemblerId)
	{
		assemblerComponentEx.RebuildAssemblerRelation(factory, assemblerId);
	}

	public static void RebuildFactoryRelations(PlanetFactory factory)
	{
		if (factory == null || factory.factorySystem == null)
		{
			return;
		}
		FactorySystem factorySystem = factory.factorySystem;
		AssemblerComponent[] assemblerPool = factorySystem.assemblerPool;
		int index = factory.index;
		int requiredCapacity = assemblerPool.Length;
		assemblerComponentEx.ClearAssemblerArray(index, requiredCapacity);
		int[] array = assemblerComponentEx.assemblerNextIds[index];
		int[] array2 = new int[array.Length];
		int assemblerCursor = factorySystem.assemblerCursor;
		bool flag = default(bool);
		int num = default(int);
		int num2 = default(int);
		for (int i = 1; i < assemblerCursor; i++)
		{
			if (assemblerPool[i].id != i)
			{
				continue;
			}
			int entityId = assemblerPool[i].entityId;
			if (entityId <= 0)
			{
				continue;
			}
			factory.ReadObjectConn(entityId, 15, ref flag, ref num, ref num2);
			if (flag && num > 0 && num < factory.entityPool.Length)
			{
				int assemblerId = factory.entityPool[num].assemblerId;
				if (assemblerId > 0 && assemblerId < assemblerPool.Length && assemblerPool[assemblerId].id == assemblerId)
				{
					array[i] = assemblerId;
					array2[assemblerId] = i;
				}
			}
		}
		for (int j = 1; j < assemblerCursor; j++)
		{
			if (array2[j] == 0 && assemblerPool[j].id == j)
			{
				for (int num3 = array[j]; num3 != 0; num3 = array[num3])
				{
					AssemblerComponentEx.FindRecipeIdForBuild(factorySystem, num3);
				}
			}
		}
	}

	public static void ResetNextIds()
	{
		for (int i = 0; i < GameMain.data.factories.Length; i++)
		{
			if (GameMain.data.factories[i] != null)
			{
				RebuildFactoryRelations(GameMain.data.factories[i]);
			}
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(ItemProto), "Preload")]
	private static void PreloadPatch(ItemProto __instance, int _index)
	{
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		ModelProto val = LDB.models.modelArray[__instance.ModelIndex];
		if (val == null || val.prefabDesc == null || !val.prefabDesc.isAssembler || !ModelSettingDict.TryGetValue(((Proto)__instance).ID, out var value))
		{
			return;
		}
		LDB.models.modelArray[__instance.ModelIndex].prefabDesc.multiLevel = true;
		LDB.models.modelArray[__instance.ModelIndex].prefabDesc.multiLevelAllowPortsOrSlots = value.multiLevelAllowPortsOrSlots;
		LDB.models.modelArray[__instance.ModelIndex].prefabDesc.lapJoint = value.lapJoint;
		int num = value.multiLevelAlternativeIds.FindIndex((int item) => item == ((Proto)__instance).ID);
		if (num >= 0)
		{
			int[] array = new int[value.multiLevelAlternativeIds.Count - 1];
			bool[] array2 = new bool[value.multiLevelAlternativeIds.Count - 1];
			int num2 = 0;
			for (int num3 = 0; num3 < value.multiLevelAlternativeIds.Count; num3++)
			{
				if (num3 != num)
				{
					array[num2] = value.multiLevelAlternativeIds[num3];
					array2[num2] = value.multiLevelAlternativeYawTransposes[num3];
					num2++;
				}
			}
			LDB.models.modelArray[__instance.ModelIndex].prefabDesc.multiLevelAlternativeIds = array;
			LDB.models.modelArray[__instance.ModelIndex].prefabDesc.multiLevelAlternativeYawTransposes = array2;
		}
		else
		{
			LDB.models.modelArray[__instance.ModelIndex].prefabDesc.multiLevelAlternativeIds = value.multiLevelAlternativeIds.ToArray();
			LDB.models.modelArray[__instance.ModelIndex].prefabDesc.multiLevelAlternativeYawTransposes = value.multiLevelAlternativeYawTransposes.ToArray();
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(FactorySystem), "SetAssemblerCapacity")]
	private static bool SetAssemblerCapacityPatch(FactorySystem __instance, int newCapacity)
	{
		int index = __instance.factory.index;
		assemblerComponentEx.EnsureAssemblerArray(index, newCapacity);
		return true;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(PlanetFactory), "ApplyInsertTarget")]
	public static bool ApplyInsertTargetPatch(PlanetFactory __instance, int entityId, int insertTarget, int slotId, int offset)
	{
		if (entityId != 0)
		{
			if (insertTarget < 0)
			{
				Assert.CannotBeReached();
				insertTarget = 0;
			}
			else
			{
				bool flag = default(bool);
				int num = default(int);
				int num2 = default(int);
				__instance.ReadObjectConn(entityId, 15, ref flag, ref num, ref num2);
				if (!flag || num != insertTarget)
				{
					int num3 = insertTarget;
					insertTarget = entityId;
					entityId = num3;
				}
				int assemblerId = __instance.entityPool[entityId].assemblerId;
				if (assemblerId > 0 && __instance.entityPool[insertTarget].assemblerId > 0)
				{
					assemblerComponentEx.SetAssemblerInsertTarget(__instance, assemblerId, insertTarget);
				}
			}
		}
		return true;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(PlanetFactory), "ApplyEntityDisconnection")]
	public static bool ApplyEntityDisconnectionPatch(PlanetFactory __instance, int otherEntityId, int removingEntityId, int otherSlotId, int removingSlotId)
	{
		if (otherEntityId == 0)
		{
			return true;
		}
		int assemblerId = __instance.entityPool[otherEntityId].assemblerId;
		if (assemblerId > 0)
		{
			int assemblerId2 = __instance.entityPool[removingEntityId].assemblerId;
			if (assemblerId2 > 0)
			{
				assemblerComponentEx.UnsetAssemblerInsertTarget(__instance, assemblerId, assemblerId2);
			}
		}
		return true;
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(PlanetFactory), "CreateEntityLogicComponents")]
	public static void CreateEntityLogicComponentsPatch(PlanetFactory __instance, int entityId, PrefabDesc desc, int prebuildId)
	{
		if (entityId != 0 && desc.isAssembler)
		{
			int assemblerId = __instance.entityPool[entityId].assemblerId;
			assemblerComponentEx.RebuildAssemblerRelation(__instance, assemblerId);
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(GameLogic), "FactorySystemLabOutputToNext")]
	public static void AssemblerOutputToNextPatch(PlanetFactory[] ___factories, int ___factoryCount, long ___timei)
	{
		UpdateAssemblerOutputToNext(___factories, ___factoryCount, 0, 1, ___timei + 1, useMutex: false);
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(GameLogic), "FactorySystemLabOutputToNext_Parallel")]
	public static void AssemblerOutputToNextParallelPatch(int threadOrdinal, int threadCount, PlanetFactory[] ___factories, int ___factoryCount, long ___timei)
	{
		UpdateAssemblerOutputToNext(___factories, ___factoryCount, threadOrdinal, threadCount, ___timei + 1, useMutex: true);
	}

	private static void UpdateAssemblerOutputToNext(PlanetFactory[] factories, int factoryCount, int threadOrdinal, int threadCount, long transferTick, bool useMutex)
	{
		if (factoryCount <= 0 || threadCount <= 0)
		{
			return;
		}
		for (int i = 0; i < factoryCount; i++)
		{
			PlanetFactory val = factories[i];
			FactorySystem factorySystem = val.factorySystem;
			AssemblerComponent[] assemblerPool = factorySystem.assemblerPool;
			int assemblerCursor = factorySystem.assemblerCursor;
			int index = val.index;
			int[] nextIds = assemblerComponentEx.GetNextIds(index);
			if (nextIds == null)
			{
				continue;
			}
			int num = assemblerCursor - 1;
			int num2 = 1 + num * threadOrdinal / threadCount;
			int num3 = 1 + num * (threadOrdinal + 1) / threadCount;
			if (num3 > nextIds.Length)
			{
				num3 = nextIds.Length;
			}
			for (int j = num2; j < num3; j++)
			{
				int num4 = nextIds[j];
				if (num4 > 0)
				{
					assemblerComponentEx.UpdateOutputToNext(val, index, j, assemblerPool, num4, transferTick, useMutex);
				}
			}
		}
	}

	public static void SyncAssemblerFunctions(FactorySystem factorySystem, Player player, int assemblerId)
	{
		int entityId = factorySystem.assemblerPool[assemblerId].entityId;
		if (entityId == 0)
		{
			return;
		}
		int num = entityId;
		bool flag = default(bool);
		int num2 = default(int);
		int num3 = default(int);
		do
		{
			factorySystem.factory.ReadObjectConn(num, 14, ref flag, ref num2, ref num3);
			num = num2;
			if (num <= 0)
			{
				continue;
			}
			int assemblerId2 = factorySystem.factory.entityPool[num].assemblerId;
			if (assemblerId2 <= 0 || factorySystem.assemblerPool[assemblerId2].id != assemblerId2)
			{
				continue;
			}
			if (factorySystem.assemblerPool[assemblerId].recipeId > 0)
			{
				if (factorySystem.assemblerPool[assemblerId2].recipeId != factorySystem.assemblerPool[assemblerId].recipeId)
				{
					factorySystem.TakeBackItems_Assembler(player, assemblerId2);
					((AssemblerComponent)(ref factorySystem.assemblerPool[assemblerId2])).SetRecipe(factorySystem.assemblerPool[assemblerId].recipeId, factorySystem.factory.entitySignPool);
				}
			}
			else if (factorySystem.assemblerPool[assemblerId2].recipeId != 0)
			{
				factorySystem.TakeBackItems_Assembler(player, assemblerId2);
				((AssemblerComponent)(ref factorySystem.assemblerPool[assemblerId2])).SetRecipe(0, factorySystem.factory.entitySignPool);
			}
		}
		while (num != 0);
		num = entityId;
		bool flag2 = default(bool);
		int num4 = default(int);
		int num5 = default(int);
		do
		{
			factorySystem.factory.ReadObjectConn(num, 15, ref flag2, ref num4, ref num5);
			num = num4;
			if (num <= 0)
			{
				continue;
			}
			int assemblerId3 = factorySystem.factory.entityPool[num].assemblerId;
			if (assemblerId3 <= 0 || factorySystem.assemblerPool[assemblerId3].id != assemblerId3)
			{
				continue;
			}
			if (factorySystem.assemblerPool[assemblerId].recipeId > 0)
			{
				if (factorySystem.assemblerPool[assemblerId3].recipeId != factorySystem.assemblerPool[assemblerId].recipeId)
				{
					factorySystem.TakeBackItems_Assembler(factorySystem.factory.gameData.mainPlayer, assemblerId3);
					((AssemblerComponent)(ref factorySystem.assemblerPool[assemblerId3])).SetRecipe(factorySystem.assemblerPool[assemblerId].recipeId, factorySystem.factory.entitySignPool);
				}
			}
			else if (factorySystem.assemblerPool[assemblerId3].recipeId != 0)
			{
				factorySystem.TakeBackItems_Assembler(factorySystem.factory.gameData.mainPlayer, assemblerId3);
				((AssemblerComponent)(ref factorySystem.assemblerPool[assemblerId3])).SetRecipe(0, factorySystem.factory.entitySignPool);
			}
		}
		while (num != 0);
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(UIAssemblerWindow), "OnRecipeResetClick")]
	public static void OnRecipeResetClickPatch(UIAssemblerWindow __instance)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		if (__instance.assemblerId != 0 && __instance.factory != null && __instance.factorySystem.assemblerPool[__instance.assemblerId].id == __instance.assemblerId)
		{
			SyncAssemblerFunctions(__instance.factorySystem, __instance.player, __instance.assemblerId);
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(UIAssemblerWindow), "OnRecipePickerReturn")]
	public static void OnRecipePickerReturnPatch(UIAssemblerWindow __instance)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		if (__instance.assemblerId != 0 && __instance.factory != null && __instance.factorySystem.assemblerPool[__instance.assemblerId].id == __instance.assemblerId)
		{
			SyncAssemblerFunctions(__instance.factorySystem, __instance.player, __instance.assemblerId);
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(UIAssemblerWindow), "OnIncSwitchClick")]
	public static void OnIncSwitchClickPatch(UIAssemblerWindow __instance)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		if (__instance.assemblerId != 0 && __instance.factory != null && __instance.factorySystem.assemblerPool[__instance.assemblerId].id == __instance.assemblerId)
		{
			SyncForceAccMode(__instance.factorySystem, __instance.assemblerId);
		}
	}

	public static void SyncForceAccMode(FactorySystem factorySystem, int assemblerId)
	{
		int entityId = factorySystem.assemblerPool[assemblerId].entityId;
		if (entityId == 0)
		{
			return;
		}
		bool forceAccMode = factorySystem.assemblerPool[assemblerId].forceAccMode;
		int num = entityId;
		bool flag = default(bool);
		int num2 = default(int);
		int num3 = default(int);
		do
		{
			factorySystem.factory.ReadObjectConn(num, 14, ref flag, ref num2, ref num3);
			num = num2;
			if (num <= 0)
			{
				continue;
			}
			int assemblerId2 = factorySystem.factory.entityPool[num].assemblerId;
			if (assemblerId2 > 0 && factorySystem.assemblerPool[assemblerId2].id == assemblerId2)
			{
				RecipeExecuteData recipeExecuteData = factorySystem.assemblerPool[assemblerId2].recipeExecuteData;
				if (recipeExecuteData != null && recipeExecuteData.productive)
				{
					factorySystem.assemblerPool[assemblerId2].forceAccMode = forceAccMode;
				}
			}
		}
		while (num != 0);
		num = entityId;
		bool flag2 = default(bool);
		int num4 = default(int);
		int num5 = default(int);
		do
		{
			factorySystem.factory.ReadObjectConn(num, 15, ref flag2, ref num4, ref num5);
			num = num4;
			if (num <= 0)
			{
				continue;
			}
			int assemblerId3 = factorySystem.factory.entityPool[num].assemblerId;
			if (assemblerId3 > 0 && factorySystem.assemblerPool[assemblerId3].id == assemblerId3)
			{
				RecipeExecuteData recipeExecuteData2 = factorySystem.assemblerPool[assemblerId3].recipeExecuteData;
				if (recipeExecuteData2 != null && recipeExecuteData2.productive)
				{
					factorySystem.assemblerPool[assemblerId3].forceAccMode = forceAccMode;
				}
			}
		}
		while (num != 0);
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(BuildingParameters), "PasteToFactoryObject")]
	public static void PasteToFactoryObjectPatch(BuildingParameters __instance, int objectId, PlanetFactory factory, bool __result)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Invalid comparison between Unknown and I4
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		if (__result && objectId > 0 && (int)__instance.type == 5)
		{
			int assemblerId = factory.entityPool[objectId].assemblerId;
			if (assemblerId > 0 && factory.factorySystem.assemblerPool[assemblerId].id == assemblerId && factory.factorySystem.assemblerPool[assemblerId].recipeId == __instance.recipeId)
			{
				SyncAssemblerFunctions(factory.factorySystem, factory.gameData.mainPlayer, assemblerId);
				SyncForceAccMode(factory.factorySystem, assemblerId);
				assemblerComponentEx.RebuildAssemblerRelation(factory, assemblerId, synchronizeRecipe: false);
			}
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(BuildTool_Click), "CheckBuildConditions")]
	public static void CheckBuildConditionsPatch(BuildTool_Click __instance, ref bool __result)
	{
		//IL_0031: 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_0142: Invalid comparison between Unknown and I4
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		if (((BuildTool)__instance).buildPreviews.Count == 0)
		{
			return;
		}
		GameHistoryData history = ((BuildTool)__instance).actionBuild.history;
		bool flag = true;
		bool flag2 = default(bool);
		int num5 = default(int);
		int num6 = default(int);
		for (int i = 0; i < ((BuildTool)__instance).buildPreviews.Count; i++)
		{
			BuildPreview val = ((BuildTool)__instance).buildPreviews[i];
			if ((int)val.condition != 0 || !val.desc.isAssembler || !val.desc.multiLevel)
			{
				continue;
			}
			int iD = ((Proto)val.item).ID;
			if (!ModelSettingDict.TryGetValue(iD, out var value))
			{
				continue;
			}
			int num = history.storageLevel - 2;
			if (num >= value.multiLevelMaxBuildCount.Length)
			{
				continue;
			}
			int num2 = value.multiLevelMaxBuildCount[num];
			int num3 = value.multiLevelMaxBuildCount[6];
			int num4 = 0;
			if (val.inputObjId != 0)
			{
				((BuildTool)__instance).factory.ReadObjectConn(val.inputObjId, 14, ref flag2, ref num5, ref num6);
				while (num5 != 0)
				{
					num4++;
					((BuildTool)__instance).factory.ReadObjectConn(num5, 14, ref flag2, ref num5, ref num6);
				}
			}
			if (num2 >= 2 && num4 >= num2 - 1)
			{
				flag = num2 >= num3;
				val.condition = (EBuildCondition)40;
			}
		}
		for (int j = 0; j < ((BuildTool)__instance).buildPreviews.Count; j++)
		{
			BuildPreview val2 = ((BuildTool)__instance).buildPreviews[j];
			if ((int)val2.condition == 40)
			{
				((BuildTool)__instance).actionBuild.model.cursorState = -1;
				((BuildTool)__instance).actionBuild.model.cursorText = val2.conditionText;
				if (!flag)
				{
					BuildModel model = ((BuildTool)__instance).actionBuild.model;
					model.cursorText += Localization.Translate("垂直建造可升级");
				}
				if (!VFInput.onGUI)
				{
					UICursor.SetCursor((ECursor)6);
				}
				__result = false;
				break;
			}
		}
	}
}