Decompiled source of AssemblerVerticalConstruction v1.1.4

AssemblerVerticalConstruction.dll

Decompiled 9 months 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 BepInEx;
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("0.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.1.0.0")]
namespace AssemblerVerticalConstruction;

public class AssemblerComponentEx
{
	public int[][] assemblerNextIds = new int[384][];

	public int assemblerCapacity = 384;

	public int transfarCount = 6;

	public void SetAssemblerCapacity(int newCapacity)
	{
		int[][] array = assemblerNextIds;
		assemblerNextIds = new int[newCapacity][];
		if (array != null)
		{
			Array.Copy(array, assemblerNextIds, (newCapacity <= assemblerCapacity) ? newCapacity : assemblerCapacity);
		}
		assemblerCapacity = newCapacity;
	}

	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 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);
					return;
				}
			}
		}
		while (num != 0);
		num = entityId;
		do
		{
			factorySystem.factory.ReadObjectConn(num, 14, 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);
					break;
				}
			}
		}
		while (num != 0);
	}

	public void SetAssemblerInsertTarget(PlanetFactory __instance, int assemblerId, int nextEntityId)
	{
		int index = __instance.factorySystem.factory.index;
		if (index >= assemblerNextIds.Length)
		{
			SetAssemblerCapacity(assemblerCapacity * 2);
		}
		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;
		if (assemblerId != 0 && __instance.factorySystem.assemblerPool[assemblerId].id == assemblerId)
		{
			assemblerNextIds[index][assemblerId] = 0;
		}
	}

	public void SetAssemblerNext(int index, int assemblerId, int nextId)
	{
		if (index >= assemblerNextIds.Length)
		{
			SetAssemblerCapacity(assemblerCapacity * 2);
		}
		if (assemblerNextIds[index] == null || assemblerId >= assemblerNextIds[index].Length)
		{
			int[] array = assemblerNextIds[index];
			int num = assemblerId * 2;
			num = ((num > 256) ? num : 256);
			assemblerNextIds[index] = new int[num];
			if (array != null)
			{
				int num2 = array.Length;
				Array.Copy(array, assemblerNextIds[index], (num <= num2) ? num : num2);
			}
		}
		assemblerNextIds[index][assemblerId] = nextId;
	}

	public void UpdateOutputToNext(PlanetFactory factory, int planeIndex, int assemblerId, AssemblerComponent[] assemblerPool, int assemblerNextId, bool useMutex)
	{
		if (useMutex)
		{
			int entityId = assemblerPool[assemblerId].entityId;
			int entityId2 = assemblerPool[assemblerNextId].entityId;
			lock (factory.entityMutexs[entityId])
			{
				lock (factory.entityMutexs[entityId2])
				{
					UpdateOutputToNextInner(assemblerId, assemblerNextId, assemblerPool);
					return;
				}
			}
		}
		UpdateOutputToNextInner(assemblerId, assemblerNextId, assemblerPool);
	}

	private void UpdateOutputToNextInner(int assemblerId, int assemblerNextId, AssemblerComponent[] assemblerPool)
	{
		ref AssemblerComponent reference = ref assemblerPool[assemblerId];
		if (reference.served == null)
		{
			return;
		}
		ref AssemblerComponent reference2 = ref assemblerPool[assemblerNextId];
		int num = reference2.speedOverride * 180 / reference2.timeSpend + 1;
		int num2 = reference.served.Length;
		for (int i = 0; i < num2; i++)
		{
			int num3 = reference.served[i];
			int num4 = reference2.requireCounts[i] * num - reference2.served[i];
			if (num4 > 0 && num3 > 0)
			{
				ref int reference3 = ref reference.incServed[i];
				int num5 = Math.Min(num3, num4);
				if (reference3 <= 0)
				{
					reference3 = 0;
				}
				int num6 = split_inc_level(ref reference.served[i], ref reference3, num5);
				if (reference.served[i] == 0)
				{
					reference3 = 0;
				}
				reference2.served[i] += num5;
				reference2.incServed[i] += num5 * num6;
			}
		}
		int num7 = reference.productCounts.Length;
		for (int j = 0; j < num7; j++)
		{
			int num8 = reference.productCounts[j] * 9;
			if (reference.produced[j] < num8 && reference2.produced[j] > 0)
			{
				int num9 = Math.Min(transfarCount, reference2.produced[j]);
				reference.produced[j] += num9;
				reference2.produced[j] -= num9;
			}
		}
	}

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

	public static ConfigEntry<bool> IsResetNextIds;

	private static ManualLogSource _logger;

	public static ManualLogSource Logger => _logger;

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

	~AssemblerVerticalConstruction()
	{
		try
		{
			if (IsResetNextIds.Value)
			{
				IsResetNextIds.Value = false;
				((BaseUnityPlugin)this).Config.Save();
			}
		}
		finally
		{
			((object)this).Finalize();
		}
	}

	public void Awake()
	{
		Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
		IsResetNextIds = ((BaseUnityPlugin)this).Config.Bind<bool>("config", "IsResetNextIds", false, "true if building overlay relationships must be recalculated when loading save data. This value is always reset to false when the game is closed.");
	}

	public void Import(BinaryReader binaryReader)
	{
		if ((Object)(object)DSPGame.Game == (Object)null)
		{
			return;
		}
		if (IsResetNextIds.Value)
		{
			Logger.LogInfo((object)"ResetNextIds");
			AssemblerPatches.ResetNextIds();
			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();
		}
	}
}
[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 }, new List<bool> { 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 },
		{ 2309, ChemicalPlantSetting },
		{ 2317, ChemicalPlantSetting },
		{ 2308, OilRefinerySetting },
		{ 2310, MiniatureParticleColliderSetting }
	};

	public static AssemblerComponentEx assemblerComponentEx = new AssemblerComponentEx();

	public static void ResetNextIds()
	{
		bool flag = default(bool);
		int num4 = default(int);
		int num5 = default(int);
		for (int i = 0; i < GameMain.data.factories.Length; i++)
		{
			if (GameMain.data.factories[i] == null)
			{
				continue;
			}
			FactorySystem factorySystem = GameMain.data.factories[i].factorySystem;
			if (factorySystem == null)
			{
				continue;
			}
			int index = factorySystem.factory.index;
			int[] array = new int[assemblerComponentEx.assemblerNextIds[index].Length];
			int value = Traverse.Create((object)factorySystem).Field("assemblerCapacity").GetValue<int>();
			for (int j = 1; j < value; j++)
			{
				int num = j;
				int entityId = factorySystem.assemblerPool[num].entityId;
				if (entityId == 0)
				{
					continue;
				}
				int num2 = entityId;
				do
				{
					int num3 = num2;
					factorySystem.factory.ReadObjectConn(num2, 15, ref flag, ref num4, ref num5);
					num2 = num4;
					if (num2 > 0)
					{
						int assemblerId = factorySystem.factory.entityPool[num3].assemblerId;
						int assemblerId2 = factorySystem.factory.entityPool[num2].assemblerId;
						if (assemblerId2 > 0 && factorySystem.assemblerPool[assemblerId2].id == assemblerId2)
						{
							assemblerComponentEx.SetAssemblerNext(index, assemblerId, assemblerId2);
							array[assemblerId2] = assemblerId;
						}
					}
				}
				while (num2 != 0);
			}
			int num6 = array.Length;
			for (int k = 1; k < num6; k++)
			{
				int num7 = array[k];
				if (num7 == 0 && factorySystem.assemblerPool[num7].id == num7)
				{
					for (int nextId = assemblerComponentEx.GetNextId(index, k); nextId != 0; nextId = assemblerComponentEx.GetNextId(index, nextId))
					{
						AssemblerComponentEx.FindRecipeIdForBuild(factorySystem, nextId);
					}
				}
			}
		}
	}

	[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 i = 0; i < value.multiLevelAlternativeIds.Count; i++)
			{
				if (i != num)
				{
					array[num2] = value.multiLevelAlternativeIds[i];
					array2[num2] = value.multiLevelAlternativeYawTransposes[i];
					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;
		if (index > assemblerComponentEx.assemblerNextIds.Length)
		{
			assemblerComponentEx.SetAssemblerCapacity(assemblerComponentEx.assemblerCapacity * 2);
		}
		int value = Traverse.Create((object)__instance).Field("assemblerCapacity").GetValue<int>();
		int[] array = assemblerComponentEx.assemblerNextIds[index];
		assemblerComponentEx.assemblerNextIds[index] = new int[newCapacity];
		if (array != null)
		{
			Array.Copy(array, assemblerComponentEx.assemblerNextIds[index], (newCapacity <= value) ? newCapacity : value);
		}
		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.FindRecipeIdForBuild(__instance.factorySystem, assemblerId);
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(FactorySystem), "GameTick", new Type[]
	{
		typeof(long),
		typeof(bool)
	})]
	public static void GameTickPatch(FactorySystem __instance, long time, bool isActive)
	{
		PerformanceMonitor.BeginSample((ECpuWorkEntry)14);
		PlanetFactory factory = __instance.factory;
		int index = factory.index;
		AssemblerComponent[] assemblerPool = __instance.assemblerPool;
		int assemblerCursor = __instance.assemblerCursor;
		for (int i = 1; i < assemblerCursor; i++)
		{
			if (assemblerPool[i].id == i)
			{
				int nextId = assemblerComponentEx.GetNextId(index, i);
				if (nextId > 0)
				{
					assemblerComponentEx.UpdateOutputToNext(factory, index, i, assemblerPool, nextId, useMutex: false);
				}
			}
		}
		PerformanceMonitor.EndSample((ECpuWorkEntry)14);
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(FactorySystem), "GameTick", new Type[]
	{
		typeof(long),
		typeof(bool),
		typeof(int),
		typeof(int),
		typeof(int)
	})]
	public static void GameTickPatch(FactorySystem __instance, long time, bool isActive, int _usedThreadCnt, int _curThreadIdx, int _minimumMissionCnt)
	{
		PlanetFactory factory = __instance.factory;
		int index = factory.index;
		AssemblerComponent[] assemblerPool = __instance.assemblerPool;
		int assemblerCursor = __instance.assemblerCursor;
		int num = default(int);
		int num2 = default(int);
		if (!WorkerThreadExecutor.CalculateMissionIndex(1, assemblerCursor - 1, _usedThreadCnt, _curThreadIdx, _minimumMissionCnt, ref num, ref num2))
		{
			return;
		}
		int num3 = num;
		bool useMutex = num3 == 1;
		int nextId = assemblerComponentEx.GetNextId(index, num3);
		if (assemblerPool[num3].id == num3 && nextId > 0)
		{
			assemblerComponentEx.UpdateOutputToNext(factory, index, num3, assemblerPool, nextId, useMutex);
		}
		for (num3 = num + 1; num3 < num2 - 1; num3++)
		{
			nextId = assemblerComponentEx.GetNextId(index, num3);
			if (assemblerPool[num3].id == num3 && nextId > 0)
			{
				assemblerComponentEx.UpdateOutputToNext(factory, index, num3, assemblerPool, nextId, useMutex: false);
			}
		}
		num3 = num2 - 1;
		if (num3 != num)
		{
			useMutex = num3 == 1;
			nextId = assemblerComponentEx.GetNextId(index, num3);
			if (assemblerPool[num3].id == num3 && nextId > 0)
			{
				assemblerComponentEx.UpdateOutputToNext(factory, index, num3, assemblerPool, nextId, 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(BuildingParameters), "PasteToFactoryObject")]
	public static void PasteToFactoryObjectPatch(BuildingParameters __instance, int objectId, PlanetFactory factory)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Invalid comparison between Unknown and I4
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		if (objectId <= 0)
		{
			return;
		}
		int assemblerId = factory.entityPool[objectId].assemblerId;
		if (assemblerId != 0 && (int)__instance.type == 5 && factory.factorySystem.assemblerPool[assemblerId].recipeId == __instance.recipeId)
		{
			ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select((int)factory.entityPool[objectId].protoId);
			if (val != null && val.prefabDesc != null)
			{
				SyncAssemblerFunctions(factory.factorySystem, factory.gameData.mainPlayer, assemblerId);
			}
		}
	}

	[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)39;
			}
		}
		for (int j = 0; j < ((BuildTool)__instance).buildPreviews.Count; j++)
		{
			BuildPreview val2 = ((BuildTool)__instance).buildPreviews[j];
			if ((int)val2.condition == 39)
			{
				((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;
			}
		}
	}
}