Decompiled source of StackingEnhancement v0.1.0

BepInEx\plugins\StackingEnhancement\StackingEnhancement.dll

Decompiled 19 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CommonAPI;
using CommonAPI.Systems.ModLocalization;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;
using xiaoye97;

[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: AssemblyVersion("0.0.0.0")]
namespace StackingEnhancement;

[BepInPlugin("com.komonad.dsp.stackingenhancement", "堆叠增强", "0.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[CommonAPISubmoduleDependency(new string[] { "LocalizationModule", "ProtoRegistry" })]
public class Plugin : BaseUnityPlugin
{
	private static class StationWindowFields
	{
		public static readonly FieldInfo EventLock = AccessTools.Field(typeof(UIStationWindow), "event_lock");

		public static readonly FieldInfo Transport = AccessTools.Field(typeof(UIStationWindow), "transport");

		public static readonly FieldInfo StationId = AccessTools.Field(typeof(UIStationWindow), "_stationId");

		public static readonly FieldInfo MinPilerSlider = AccessTools.Field(typeof(UIStationWindow), "minPilerSlider");

		public static readonly FieldInfo MinPilerSliderFillImage = AccessTools.Field(typeof(UIStationWindow), "minPilerSliderFillImage");

		public static readonly FieldInfo MinPilerValue = AccessTools.Field(typeof(UIStationWindow), "minPilerValue");

		public static readonly FieldInfo TechPilerCheck = AccessTools.Field(typeof(UIStationWindow), "techPilerCheck");
	}

	private static class StationInspectorFields
	{
		public static readonly FieldInfo EventLock = AccessTools.Field(typeof(UIControlPanelStationInspector), "event_lock");

		public static readonly FieldInfo Transport = AccessTools.Field(typeof(UIControlPanelStationInspector), "transport");

		public static readonly FieldInfo StationId = AccessTools.Field(typeof(UIControlPanelStationInspector), "_stationId");

		public static readonly FieldInfo MinPilerSlider = AccessTools.Field(typeof(UIControlPanelStationInspector), "minPilerSlider");

		public static readonly FieldInfo MinPilerSliderFillImage = AccessTools.Field(typeof(UIControlPanelStationInspector), "minPilerSliderFillImage");

		public static readonly FieldInfo MinPilerValue = AccessTools.Field(typeof(UIControlPanelStationInspector), "minPilerValue");

		public static readonly FieldInfo TechPilerCheck = AccessTools.Field(typeof(UIControlPanelStationInspector), "techPilerCheck");
	}

	private static class CargoContainerFields
	{
		public static readonly FieldInfo CargoPool = AccessTools.Field(typeof(CargoContainer), "cargoPool");

		public static readonly FieldInfo Cursor = AccessTools.Field(typeof(CargoContainer), "cursor");

		public static readonly FieldInfo PoolCapacity = AccessTools.Field(typeof(CargoContainer), "poolCapacity");

		public static readonly FieldInfo CargoMatInst = AccessTools.Field(typeof(CargoContainer), "cargoMatInst");
	}

	private static class CargoContainerMethods
	{
		public static readonly MethodInfo Expand2x = AccessTools.Method(typeof(CargoContainer), "Expand2x", (Type[])null, (Type[])null);
	}

	[HarmonyPatch]
	private static class GameDataPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameData), "SetForNewGame")]
		private static void SetForNewGamePostfix(GameData __instance)
		{
			EnsureTechStates(__instance?.history);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameData), "Import")]
		private static void ImportPostfix(GameData __instance)
		{
			EnsureTechStates(__instance?.history);
		}
	}

	[HarmonyPatch(typeof(UIStationWindow))]
	private static class UIStationWindowPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("OnStationIdChange")]
		private static void OnStationIdChangePostfix(UIStationWindow __instance)
		{
			RefreshPilerUi(__instance);
		}

		[HarmonyPrefix]
		[HarmonyPatch("OnMinPilerValueChange")]
		private static bool OnMinPilerValueChangePrefix(UIStationWindow __instance, float value)
		{
			ApplyFixedPilerCount(__instance, value);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch("OnTechPilerClick")]
		private static bool OnTechPilerClickPrefix(UIStationWindow __instance)
		{
			ApplyTechPilerToggle(__instance);
			return false;
		}
	}

	[HarmonyPatch(typeof(UIControlPanelStationInspector))]
	private static class UIControlPanelStationInspectorPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("OnStationIdChange")]
		private static void OnStationIdChangePostfix(UIControlPanelStationInspector __instance)
		{
			RefreshPilerUi(__instance);
		}

		[HarmonyPrefix]
		[HarmonyPatch("OnMinPilerValueChange")]
		private static bool OnMinPilerValueChangePrefix(UIControlPanelStationInspector __instance, float value)
		{
			ApplyFixedPilerCount(__instance, value);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch("OnTechPilerClick")]
		private static bool OnTechPilerClickPrefix(UIControlPanelStationInspector __instance)
		{
			ApplyTechPilerToggle(__instance);
			return false;
		}
	}

	[HarmonyPatch(typeof(CargoContainer), "Draw")]
	private static class CargoContainerPatch
	{
		[HarmonyPrefix]
		private static void DrawPrefix(CargoContainer __instance)
		{
			_cargoRenderDrawCount = 0;
			if (!_cargoStackRenderPatchDisabled)
			{
				try
				{
					EnsureCargoRenderCapacity(__instance);
				}
				catch (Exception arg)
				{
					_cargoStackRenderPatchDisabled = true;
					ManualLogSource logger = _logger;
					if (logger != null)
					{
						logger.LogWarning((object)$"Cargo stack render patch disabled: {arg}");
					}
				}
			}
			if (_cargoShaderDrawPatchDisabled)
			{
				return;
			}
			try
			{
				ApplyCargoShader(GetFieldValue<Material>(CargoContainerFields.CargoMatInst, __instance));
			}
			catch (Exception arg2)
			{
				_cargoShaderDrawPatchDisabled = true;
				ManualLogSource logger2 = _logger;
				if (logger2 != null)
				{
					logger2.LogWarning((object)$"Cargo shader draw patch disabled: {arg2}");
				}
			}
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> DrawTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Expected O, but got Unknown
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Expected O, but got Unknown
			MethodInfo objB = AccessTools.Method(typeof(ComputeBuffer), "SetData", new Type[4]
			{
				typeof(Array),
				typeof(int),
				typeof(int),
				typeof(int)
			}, (Type[])null);
			MethodInfo methodInfo = AccessTools.Method(typeof(Plugin), "UploadCargoRenderData", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), "GetCargoRenderDrawCount", (Type[])null, (Type[])null);
			FieldInfo cursor = CargoContainerFields.Cursor;
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < list.Count; i++)
			{
				CodeInstruction val = list[i];
				if ((val.opcode == OpCodes.Call || val.opcode == OpCodes.Callvirt) && object.Equals(val.operand, objB))
				{
					list[i] = new CodeInstruction(OpCodes.Call, (object)methodInfo)
					{
						labels = val.labels,
						blocks = val.blocks
					};
					num++;
				}
				else if (val.opcode == OpCodes.Ldfld && object.Equals(val.operand, cursor) && i + 1 < list.Count && list[i + 1].opcode == OpCodes.Stelem_I4)
				{
					list[i] = new CodeInstruction(OpCodes.Call, (object)methodInfo2)
					{
						labels = val.labels,
						blocks = val.blocks
					};
					num2++;
				}
			}
			if (num != 1 || num2 != 1)
			{
				Debug.LogWarning((object)string.Format("[{0}] Unexpected CargoContainer.Draw patch shape. Replaced uploads={1}, drawCounts={2}.", "堆叠增强", num, num2));
			}
			return list;
		}
	}

	[HarmonyPatch(typeof(PilerComponent), "InternalUpdate")]
	private static class PilerComponentPatch
	{
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> InternalUpdateTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			int num = 0;
			int num2 = 0;
			List<CodeInstruction> list = new List<CodeInstruction>();
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Ldc_I4_4)
				{
					num++;
					list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Plugin), "GetMaxPilerStack", (Type[])null, (Type[])null)));
				}
				else if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num3 && Math.Abs(num3 - 4f) < 0.001f)
				{
					num2++;
					list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Plugin), "GetMaxPilerStackFloat", (Type[])null, (Type[])null)));
				}
				else
				{
					list.Add(instruction);
				}
			}
			if (num != 3 || num2 != 1)
			{
				Debug.LogWarning((object)string.Format("[{0}] Unexpected PilerComponent.InternalUpdate patch shape. Replaced int4={1}, float4={2}.", "堆叠增强", num, num2));
			}
			return list;
		}
	}

	[HarmonyPatch(typeof(InserterComponent), "InternalUpdate_Bidirectional")]
	private static class InserterBidirectionalPatch
	{
		private static byte _savedStackOutput;

		[HarmonyPrepare]
		private static bool Prepare()
		{
			return _enhancePileSorter?.Value ?? false;
		}

		[HarmonyPrefix]
		private static void Prefix(ref InserterComponent __instance)
		{
			_savedStackOutput = __instance.stackOutput;
			int maxPilerStack = GetMaxPilerStack();
			if (maxPilerStack > __instance.stackOutput)
			{
				__instance.stackOutput = (byte)maxPilerStack;
			}
		}

		[HarmonyFinalizer]
		private static void Finalizer(ref InserterComponent __instance)
		{
			__instance.stackOutput = _savedStackOutput;
		}
	}

	public const string ModGuid = "com.komonad.dsp.stackingenhancement";

	public const string ModName = "堆叠增强";

	public const string Version = "0.1.0";

	private const int DefaultPilerStack = 4;

	private const int MaxPilerStack = 8;

	private const float TallCargoUpperBlockOffset = 0.4f;

	private const string ShaderBundleFileName = "stacking-enhancement-shaders";

	private const string CargoShaderAssetPath = "Assets/CargoInstancing8.shader";

	private const string CargoShaderName = "VF Shaders/Batching/Cargo Instancing 8";

	private const int FunctionStationPilerLevel = 29;

	private const int ItemUniverseMatrix = 6006;

	private const int FallbackPreTechLogisticsPiler = 1607;

	private const string FallbackTechIconPath = "Icons/Tech/1607";

	private static readonly int[] DefaultTechIds = new int[4] { 9442, 9443, 9444, 9445 };

	private static readonly int[] LegacyStationStackTechIds = new int[4] { 9446, 9447, 9448, 9449 };

	private static readonly long[] EnhancementHashNeededByLevel = new long[4] { 115200000L, 144000000L, 172800000L, 201600000L };

	private static int[] _techIds = (int[])DefaultTechIds.Clone();

	private static int _stationAnchorTechId = 1607;

	private static ManualLogSource _logger;

	private static AssetBundle _shaderBundle;

	private static Shader _cargoShader;

	private static Shader _originalCargoShader;

	private static bool _cargoShaderLoadAttempted;

	private static bool _cargoShaderAppliedLogged;

	private static bool _cargoShaderDrawPatchDisabled;

	private static bool _cargoStackRenderPatchDisabled;

	private static Cargo[] _cargoRenderBuffer = (Cargo[])(object)new Cargo[128];

	private static int _cargoRenderDrawCount;

	private static ConfigEntry<bool> _enableCargoStackShader;

	private static ConfigEntry<bool> _enhancePileSorter;

	private static readonly Color SliderAutoNormalColor = new Color(1f, 1f, 1f, 0.1f);

	private static readonly Color SliderAutoHighlightColor = new Color(1f, 1f, 1f, 0.2f);

	private static readonly Color SliderFixedNormalColor = new Color(1f, 1f, 1f, 0.5f);

	private static readonly Color SliderFixedHighlightColor = new Color(1f, 1f, 1f, 1f);

	private void Awake()
	{
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		_logger = ((BaseUnityPlugin)this).Logger;
		_enableCargoStackShader = ((BaseUnityPlugin)this).Config.Bind<bool>("Rendering", "EnableCargoStackShader", true, "Enables cargo rendering with native stack height and side layer support up to 8 layers.");
		_enhancePileSorter = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "EnhancePileSorter", false, "When enabled, pile sorters output stacks matching the Stacking Enhancement tech level instead of the default 4-layer cap.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"堆叠增强 loaded.");
		RegisterLocalizations();
		LDBTool.PreAddDataAction = (Action)Delegate.Combine(LDBTool.PreAddDataAction, new Action(RegisterProtos));
		LDBTool.PostAddDataAction = (Action)Delegate.Combine(LDBTool.PostAddDataAction, new Action(PostAddData));
		new Harmony("com.komonad.dsp.stackingenhancement").PatchAll();
		LogPatchStatus();
	}

	private void OnDestroy()
	{
		LDBTool.PreAddDataAction = (Action)Delegate.Remove(LDBTool.PreAddDataAction, new Action(RegisterProtos));
		LDBTool.PostAddDataAction = (Action)Delegate.Remove(LDBTool.PostAddDataAction, new Action(PostAddData));
		if ((Object)(object)_shaderBundle != (Object)null)
		{
			_shaderBundle.Unload(false);
			_shaderBundle = null;
			_cargoShader = null;
			_cargoShaderLoadAttempted = false;
			_cargoShaderAppliedLogged = false;
			_cargoShaderDrawPatchDisabled = false;
			_cargoStackRenderPatchDisabled = false;
		}
	}

	private void RegisterProtos()
	{
		List<TechProto> list = ResolveStationPilerTechs();
		_techIds = ResolveFreeTechIds(DefaultTechIds);
		_stationAnchorTechId = ((list.Count > 0) ? ((Proto)list[list.Count - 1]).ID : 1607);
		int preTechId = _stationAnchorTechId;
		for (int i = 0; i < _techIds.Length; i++)
		{
			int stackLevel = 4 + i + 1;
			TechProto obj = CreateStackingTech(_techIds[i], stackLevel, preTechId, i);
			LDBTool.PreAddProto((Proto)(object)obj);
			preTechId = ((Proto)obj).ID;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Registered stacking enhancement techs: ids={0}, anchor={1}", string.Join(",", _techIds), _stationAnchorTechId));
	}

	private static void RegisterLocalizations()
	{
		for (int i = 5; i <= 8; i++)
		{
			LocalizationModule.RegisterTranslation(TechNameKey(i), $"Stacking Enhancement {i}", $"堆叠增强 {i} 层", "");
			LocalizationModule.RegisterTranslation(TechDescriptionKey(i), $"Improves logistics station cargo output stacking to {i} layers. Automatic pilers can also combine cargo up to {i} layers, while pile sorters keep their normal stacking limits.", $"将物流运输站输出货物堆叠上限提升至 {i} 层,并允许自动集装机生成最高 {i} 层货物。", "");
			LocalizationModule.RegisterTranslation(TechConclusionKey(i), $"Logistics station cargo output stacking has been improved to {i} layers. Automatic pilers can now output cargo stacks up to {i} layers.", $"物流运输站输出货物堆叠已提升至 {i} 层。自动集装机现在可以输出最高 {i} 层货物。", "");
		}
	}

	private void PostAddData()
	{
		RefreshTechProtoLinks();
		EnsureTechStates(GameMain.history);
		ApplyCargoShader(null);
	}

	private static TechProto CreateStackingTech(int techId, int stackLevel, int preTechId, int index)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		TechProto anchorTech = ((ProtoSet<TechProto>)(object)LDB.techs).Select(_stationAnchorTechId);
		return CreateBaseTech(techId, TechNameKey(stackLevel), TechDescriptionKey(stackLevel), TechConclusionKey(stackLevel), GetTechPosition(anchorTech, index), GetIconPath(anchorTech), GetIconTag(anchorTech), (preTechId <= 0) ? Array.Empty<int>() : new int[1] { preTechId }, new int[1] { 6006 }, new int[1] { 1 }, EnhancementHashNeededByLevel[Math.Min(index, EnhancementHashNeededByLevel.Length - 1)], new int[1] { 29 }, new double[1] { 1.0 });
	}

	private static TechProto CreateBaseTech(int techId, string name, string description, string conclusion, Vector2 position, string iconPath, string iconTag, int[] preTechs, int[] items, int[] itemPoints, long hashNeeded, int[] unlockFunctions, double[] unlockValues)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: 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_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: 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_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: 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)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: 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_0076: 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_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: 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_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: 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_00bb: 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_00cd: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Expected O, but got Unknown
		return new TechProto
		{
			ID = techId,
			Name = name,
			Desc = description,
			Conclusion = conclusion,
			IconPath = iconPath,
			IconTag = iconTag,
			IsHiddenTech = false,
			PreItem = Array.Empty<int>(),
			Position = position,
			PreTechs = preTechs,
			PreTechsImplicit = Array.Empty<int>(),
			Items = items,
			ItemPoints = itemPoints,
			HashNeeded = hashNeeded,
			UnlockRecipes = Array.Empty<int>(),
			UnlockFunctions = unlockFunctions,
			UnlockValues = unlockValues,
			Published = true,
			Level = 0,
			MaxLevel = 0,
			LevelCoef1 = 0,
			LevelCoef2 = 0,
			IsLabTech = true,
			PreTechsMax = false,
			AddItems = Array.Empty<int>(),
			AddItemCounts = Array.Empty<int>(),
			PropertyOverrideItems = Array.Empty<int>(),
			PropertyItemCounts = Array.Empty<int>()
		};
	}

	private static Vector2 GetTechPosition(TechProto anchorTech, int index)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//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_0030: 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)
		Vector2 val = (Vector2)(((??)anchorTech?.Position) ?? new Vector2(41f, 33f));
		return new Vector2(val.x + 4f + (float)index * 4f, val.y);
	}

	private static string GetIconPath(TechProto anchorTech)
	{
		if (!string.IsNullOrEmpty(anchorTech?.IconPath))
		{
			return anchorTech.IconPath;
		}
		return "Icons/Tech/1607";
	}

	private static string GetIconTag(TechProto anchorTech)
	{
		if (!string.IsNullOrEmpty(anchorTech?.IconTag))
		{
			return anchorTech.IconTag;
		}
		return "ddzq";
	}

	private static List<TechProto> ResolveStationPilerTechs()
	{
		return (from tech in ((ProtoSet<TechProto>)(object)LDB.techs)?.dataArray ?? Array.Empty<TechProto>()
			where tech != null && tech.Published && tech.UnlockFunctions != null && tech.UnlockFunctions.Contains(29)
			orderby ((Proto)tech).ID
			select tech).ToList();
	}

	private static int[] ResolveFreeTechIds(IEnumerable<int> defaultIds)
	{
		HashSet<int> hashSet = new HashSet<int>(from tech in ((ProtoSet<TechProto>)(object)LDB.techs)?.dataArray ?? Array.Empty<TechProto>()
			where tech != null
			select ((Proto)tech).ID);
		List<int> list = new List<int>();
		foreach (int defaultId in defaultIds)
		{
			int i;
			for (i = defaultId; hashSet.Contains(i); i++)
			{
			}
			hashSet.Add(i);
			list.Add(i);
		}
		return list.ToArray();
	}

	private static void RefreshTechProtoLinks()
	{
		((ProtoSet<TechProto>)(object)LDB.techs).OnAfterDeserialize();
		TechProto[] dataArray = ((ProtoSet<TechProto>)(object)LDB.techs).dataArray;
		foreach (TechProto obj in dataArray)
		{
			if (obj != null)
			{
				obj.Preload();
			}
		}
		dataArray = ((ProtoSet<TechProto>)(object)LDB.techs).dataArray;
		foreach (TechProto val in dataArray)
		{
			if (val != null)
			{
				val.PreTechsImplicit = (val.PreTechsImplicit ?? Array.Empty<int>()).Except(val.PreTechs ?? Array.Empty<int>()).ToArray();
				val.UnlockRecipes = (val.UnlockRecipes ?? Array.Empty<int>()).Distinct().ToArray();
				val.Preload2();
			}
		}
	}

	private static void EnsureTechStates(GameHistoryData history)
	{
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		if (history?.techStates == null)
		{
			return;
		}
		int[] techIds = _techIds;
		foreach (int num in techIds)
		{
			if (history.techStates.ContainsKey(num))
			{
				continue;
			}
			TechProto val = ((ProtoSet<TechProto>)(object)LDB.techs).Select(num);
			if (val != null)
			{
				int num2 = 0;
				int num3 = Array.IndexOf(val.Items ?? Array.Empty<int>(), 6006);
				if (num3 >= 0 && val.ItemPoints != null && num3 < val.ItemPoints.Length)
				{
					num2 = val.ItemPoints[num3];
				}
				history.techStates.Add(num, new TechState(false, val.Level, val.MaxLevel, 0L, val.GetHashNeeded(val.Level), num2));
			}
		}
		SyncStationPilerLevelFromUnlockedTechs(history);
	}

	public static int GetMaxPilerStack()
	{
		int val = GameMain.history?.stationPilerLevel ?? 4;
		return Math.Min(8, Math.Max(4, val));
	}

	public static float GetMaxPilerStackFloat()
	{
		return GetMaxPilerStack();
	}

	private static int GetStationOutputStackLevel(GameHistoryData history)
	{
		int val = history?.stationPilerLevel ?? 1;
		return Math.Min(8, Math.Max(1, val));
	}

	private static void SyncStationPilerLevelFromUnlockedTechs(GameHistoryData history)
	{
		if (history?.techStates != null)
		{
			int stationPilerLevel = history.stationPilerLevel;
			stationPilerLevel = Math.Max(stationPilerLevel, GetHighestUnlockedStackLevel(history, _techIds));
			stationPilerLevel = Math.Max(stationPilerLevel, GetHighestUnlockedStackLevel(history, LegacyStationStackTechIds));
			stationPilerLevel = Math.Min(8, stationPilerLevel);
			if (stationPilerLevel > history.stationPilerLevel)
			{
				history.stationPilerLevel = stationPilerLevel;
			}
		}
	}

	private static int GetHighestUnlockedStackLevel(GameHistoryData history, int[] techIds)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		for (int i = 0; i < techIds.Length; i++)
		{
			if (history.techStates.TryGetValue(techIds[i], out var value) && value.unlocked)
			{
				num = Math.Max(num, 4 + i + 1);
			}
		}
		return num;
	}

	private static string TechNameKey(int stackLevel)
	{
		return $"StackingEnhancement.Tech.{stackLevel}.Name";
	}

	private static string TechDescriptionKey(int stackLevel)
	{
		return $"StackingEnhancement.Tech.{stackLevel}.Description";
	}

	private static string TechConclusionKey(int stackLevel)
	{
		return $"StackingEnhancement.Tech.{stackLevel}.Conclusion";
	}

	private static T GetFieldValue<T>(FieldInfo field, object instance) where T : class
	{
		return field?.GetValue(instance) as T;
	}

	private static bool GetBoolFieldValue(FieldInfo field, object instance)
	{
		object obj = field?.GetValue(instance);
		bool flag = default(bool);
		int num;
		if (obj is bool)
		{
			flag = (bool)obj;
			num = 1;
		}
		else
		{
			num = 0;
		}
		return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
	}

	private static int GetIntFieldValue(FieldInfo field, object instance)
	{
		object obj = field?.GetValue(instance);
		if (obj is int)
		{
			return (int)obj;
		}
		return 0;
	}

	private static void SetBoolFieldValue(FieldInfo field, object instance, bool value)
	{
		field?.SetValue(instance, value);
	}

	private static void LogPatchStatus()
	{
		Patches patchInfo = Harmony.GetPatchInfo((MethodBase)AccessTools.Method(typeof(CargoContainer), "Draw", (Type[])null, (Type[])null));
		int valueOrDefault = (patchInfo?.Prefixes?.Count((Patch patch) => patch.owner == "com.komonad.dsp.stackingenhancement")).GetValueOrDefault();
		int valueOrDefault2 = (patchInfo?.Postfixes?.Count((Patch patch) => patch.owner == "com.komonad.dsp.stackingenhancement")).GetValueOrDefault();
		int valueOrDefault3 = (patchInfo?.Finalizers?.Count((Patch patch) => patch.owner == "com.komonad.dsp.stackingenhancement")).GetValueOrDefault();
		int valueOrDefault4 = (patchInfo?.Transpilers?.Count((Patch patch) => patch.owner == "com.komonad.dsp.stackingenhancement")).GetValueOrDefault();
		ManualLogSource logger = _logger;
		if (logger != null)
		{
			logger.LogInfo((object)$"CargoContainer.Draw patches: prefix={valueOrDefault}, postfix={valueOrDefault2}, finalizer={valueOrDefault3}, transpiler={valueOrDefault4}");
		}
	}

	private static Shader LoadCargoShader()
	{
		if ((Object)(object)_cargoShader != (Object)null)
		{
			return _cargoShader;
		}
		if (_cargoShaderLoadAttempted)
		{
			return null;
		}
		_cargoShaderLoadAttempted = true;
		string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty, "stacking-enhancement-shaders");
		if (!File.Exists(text))
		{
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogWarning((object)("Cargo shader bundle missing: " + text));
			}
			return null;
		}
		_shaderBundle = AssetBundle.LoadFromFile(text);
		if ((Object)(object)_shaderBundle == (Object)null)
		{
			ManualLogSource logger2 = _logger;
			if (logger2 != null)
			{
				logger2.LogWarning((object)("Failed to load cargo shader bundle: " + text));
			}
			return null;
		}
		_cargoShader = _shaderBundle.LoadAsset<Shader>("Assets/CargoInstancing8.shader");
		if ((Object)(object)_cargoShader == (Object)null)
		{
			_cargoShader = ((IEnumerable<Shader>)_shaderBundle.LoadAllAssets<Shader>()).FirstOrDefault((Func<Shader, bool>)((Shader shader) => (Object)(object)shader != (Object)null && ((Object)shader).name == "VF Shaders/Batching/Cargo Instancing 8"));
		}
		if ((Object)(object)_cargoShader == (Object)null)
		{
			ManualLogSource logger3 = _logger;
			if (logger3 != null)
			{
				logger3.LogWarning((object)("Cargo shader asset missing in bundle: " + text));
			}
		}
		else
		{
			ManualLogSource logger4 = _logger;
			if (logger4 != null)
			{
				logger4.LogInfo((object)("Loaded cargo shader: " + ((Object)_cargoShader).name));
			}
		}
		return _cargoShader;
	}

	private static void ApplyCargoShader(Material material)
	{
		Shader val = LoadCargoShader();
		Material val2 = Configs.builtin?.cargoMat;
		ConfigEntry<bool> enableCargoStackShader = _enableCargoStackShader;
		if (enableCargoStackShader == null || !enableCargoStackShader.Value)
		{
			if ((Object)(object)_originalCargoShader != (Object)null)
			{
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.shader != (Object)(object)_originalCargoShader)
				{
					val2.shader = _originalCargoShader;
				}
				if ((Object)(object)material != (Object)null && (Object)(object)material.shader != (Object)(object)_originalCargoShader)
				{
					material.shader = _originalCargoShader;
				}
			}
		}
		else
		{
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.shader != (Object)(object)val)
			{
				if ((Object)(object)_originalCargoShader == (Object)null)
				{
					_originalCargoShader = val2.shader;
				}
				val2.shader = val;
			}
			if ((Object)(object)material != (Object)null && (Object)(object)material.shader != (Object)(object)val)
			{
				material.shader = val;
			}
			if (!_cargoShaderAppliedLogged && (Object)(object)val2 != (Object)null)
			{
				_cargoShaderAppliedLogged = true;
				ManualLogSource logger = _logger;
				if (logger != null)
				{
					logger.LogInfo((object)("Applied cargo shader: " + ((Object)val).name));
				}
			}
		}
	}

	private static void EnsureCargoRenderCapacity(CargoContainer container)
	{
		ConfigEntry<bool> enableCargoStackShader = _enableCargoStackShader;
		if ((enableCargoStackShader != null && enableCargoStackShader.Value) || _cargoStackRenderPatchDisabled)
		{
			return;
		}
		Cargo[] fieldValue = GetFieldValue<Cargo[]>(CargoContainerFields.CargoPool, container);
		int intFieldValue = GetIntFieldValue(CargoContainerFields.Cursor, container);
		if (fieldValue == null || intFieldValue <= 0)
		{
			return;
		}
		int cargoCount = Math.Min(intFieldValue, fieldValue.Length);
		int num = CalculateCargoRenderCount(fieldValue, cargoCount);
		while (GetIntFieldValue(CargoContainerFields.PoolCapacity, container) < num)
		{
			if (CargoContainerMethods.Expand2x == null)
			{
				throw new MissingMethodException("CargoContainer", "Expand2x");
			}
			CargoContainerMethods.Expand2x.Invoke(container, null);
		}
	}

	private static void UploadCargoRenderData(ComputeBuffer buffer, Array source, int managedBufferStartIndex, int computeBufferStartIndex, int count)
	{
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: 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)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: 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)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: 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_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		ConfigEntry<bool> enableCargoStackShader = _enableCargoStackShader;
		if ((enableCargoStackShader != null && enableCargoStackShader.Value) || _cargoStackRenderPatchDisabled || !(source is Cargo[] array))
		{
			_cargoRenderDrawCount = count;
			buffer.SetData(source, managedBufferStartIndex, computeBufferStartIndex, count);
			return;
		}
		int num = Math.Min(count, array.Length - managedBufferStartIndex);
		if (num <= 0)
		{
			_cargoRenderDrawCount = 0;
			buffer.SetData(source, managedBufferStartIndex, computeBufferStartIndex, count);
			return;
		}
		int num2 = CalculateCargoRenderCount(array, num, managedBufferStartIndex);
		if (num2 <= count)
		{
			_cargoRenderDrawCount = count;
			buffer.SetData(source, managedBufferStartIndex, computeBufferStartIndex, count);
			return;
		}
		if (num2 > buffer.count - computeBufferStartIndex)
		{
			_cargoStackRenderPatchDisabled = true;
			_cargoRenderDrawCount = count;
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogWarning((object)$"Cargo stack render patch disabled: renderCount={num2}, bufferCount={buffer.count}, uploadOffset={computeBufferStartIndex}");
			}
			buffer.SetData(source, managedBufferStartIndex, computeBufferStartIndex, count);
			return;
		}
		EnsureCargoRenderBufferCapacity(num2);
		int num3 = 0;
		int num4 = managedBufferStartIndex + num;
		for (int i = managedBufferStartIndex; i < num4; i++)
		{
			Cargo val = array[i];
			int stack = val.stack;
			if (val.item <= 0 || stack <= 4 || stack > 8)
			{
				_cargoRenderBuffer[num3++] = val;
				continue;
			}
			Cargo val2 = val;
			val2.stack = 4;
			_cargoRenderBuffer[num3++] = val2;
			Cargo val3 = val;
			val3.stack = (byte)(stack - 4);
			ref Vector3 position = ref val3.position;
			position += val3.rotation * new Vector3(0f, 0.4f, 0f);
			_cargoRenderBuffer[num3++] = val3;
		}
		_cargoRenderDrawCount = num3;
		buffer.SetData((Array)_cargoRenderBuffer, 0, computeBufferStartIndex, num3);
	}

	private static int GetCargoRenderDrawCount(CargoContainer container)
	{
		if (_cargoRenderDrawCount <= 0)
		{
			return GetIntFieldValue(CargoContainerFields.Cursor, container);
		}
		return _cargoRenderDrawCount;
	}

	private static int CalculateCargoRenderCount(Cargo[] cargos, int cargoCount, int startIndex = 0)
	{
		//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)
		int num = cargoCount;
		int num2 = Math.Min(cargos.Length, startIndex + cargoCount);
		for (int i = startIndex; i < num2; i++)
		{
			Cargo val = cargos[i];
			int stack = val.stack;
			if (val.item > 0 && stack > 4 && stack <= 8)
			{
				num++;
			}
		}
		return num;
	}

	private static void EnsureCargoRenderBufferCapacity(int capacity)
	{
		if (_cargoRenderBuffer.Length < capacity)
		{
			int newSize = Math.Max(capacity, _cargoRenderBuffer.Length * 2);
			Array.Resize(ref _cargoRenderBuffer, newSize);
		}
	}

	private static void ApplyFixedPilerCount(UIStationWindow window, float value)
	{
		StationComponent stationComponent = GetStationComponent(window);
		Image fieldValue = GetFieldValue<Image>(StationWindowFields.TechPilerCheck, window);
		if (stationComponent != null && !GetBoolFieldValue(StationWindowFields.EventLock, window) && (fieldValue == null || !((Behaviour)fieldValue).enabled))
		{
			stationComponent.pilerCount = ClampStationPilerCount(Mathf.RoundToInt(value), GameMain.history);
			RefreshPilerUi(window);
		}
	}

	private static void ApplyFixedPilerCount(UIControlPanelStationInspector inspector, float value)
	{
		StationComponent stationComponent = GetStationComponent(inspector);
		Image fieldValue = GetFieldValue<Image>(StationInspectorFields.TechPilerCheck, inspector);
		if (stationComponent != null && !GetBoolFieldValue(StationInspectorFields.EventLock, inspector) && (fieldValue == null || !((Behaviour)fieldValue).enabled))
		{
			stationComponent.pilerCount = ClampStationPilerCount(Mathf.RoundToInt(value), GameMain.history);
			RefreshPilerUi(inspector);
		}
	}

	private static void ApplyTechPilerToggle(UIStationWindow window)
	{
		StationComponent stationComponent = GetStationComponent(window);
		if (stationComponent != null && !GetBoolFieldValue(StationWindowFields.EventLock, window))
		{
			Image fieldValue = GetFieldValue<Image>(StationWindowFields.TechPilerCheck, window);
			bool flag = fieldValue == null || !((Behaviour)fieldValue).enabled;
			stationComponent.pilerCount = ((!flag) ? GetStationOutputStackLevel(GameMain.history) : 0);
			RefreshPilerUi(window);
		}
	}

	private static void ApplyTechPilerToggle(UIControlPanelStationInspector inspector)
	{
		StationComponent stationComponent = GetStationComponent(inspector);
		if (stationComponent != null && !GetBoolFieldValue(StationInspectorFields.EventLock, inspector))
		{
			Image fieldValue = GetFieldValue<Image>(StationInspectorFields.TechPilerCheck, inspector);
			bool flag = fieldValue == null || !((Behaviour)fieldValue).enabled;
			stationComponent.pilerCount = ((!flag) ? GetStationOutputStackLevel(GameMain.history) : 0);
			RefreshPilerUi(inspector);
		}
	}

	private static void RefreshPilerUi(UIStationWindow window)
	{
		StationComponent stationComponent = GetStationComponent(window);
		if (stationComponent != null)
		{
			bool boolFieldValue = GetBoolFieldValue(StationWindowFields.EventLock, window);
			SetBoolFieldValue(StationWindowFields.EventLock, window, value: true);
			RefreshPilerUi(stationComponent, GetFieldValue<Slider>(StationWindowFields.MinPilerSlider, window), GetFieldValue<Image>(StationWindowFields.MinPilerSliderFillImage, window), GetFieldValue<Text>(StationWindowFields.MinPilerValue, window), GetFieldValue<Image>(StationWindowFields.TechPilerCheck, window));
			SetBoolFieldValue(StationWindowFields.EventLock, window, boolFieldValue);
		}
	}

	private static void RefreshPilerUi(UIControlPanelStationInspector inspector)
	{
		StationComponent stationComponent = GetStationComponent(inspector);
		if (stationComponent != null)
		{
			bool boolFieldValue = GetBoolFieldValue(StationInspectorFields.EventLock, inspector);
			SetBoolFieldValue(StationInspectorFields.EventLock, inspector, value: true);
			RefreshPilerUi(stationComponent, GetFieldValue<Slider>(StationInspectorFields.MinPilerSlider, inspector), GetFieldValue<Image>(StationInspectorFields.MinPilerSliderFillImage, inspector), GetFieldValue<Text>(StationInspectorFields.MinPilerValue, inspector), GetFieldValue<Image>(StationInspectorFields.TechPilerCheck, inspector));
			SetBoolFieldValue(StationInspectorFields.EventLock, inspector, boolFieldValue);
		}
	}

	private static void RefreshPilerUi(StationComponent station, Slider slider, Image sliderFillImage, Text valueText, Image techPilerCheck)
	{
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: 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_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: 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_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		int stationOutputStackLevel = GetStationOutputStackLevel(GameMain.history);
		if (station.pilerCount > stationOutputStackLevel)
		{
			station.pilerCount = stationOutputStackLevel;
		}
		bool flag = station.pilerCount == 0;
		if ((Object)(object)slider != (Object)null)
		{
			slider.maxValue = stationOutputStackLevel;
			slider.value = (flag ? stationOutputStackLevel : station.pilerCount);
			((Selectable)slider).interactable = !flag;
			ColorBlock colors = ((Selectable)slider).colors;
			((ColorBlock)(ref colors)).normalColor = (flag ? SliderAutoNormalColor : SliderFixedNormalColor);
			((ColorBlock)(ref colors)).highlightedColor = (flag ? SliderAutoHighlightColor : SliderFixedHighlightColor);
			((ColorBlock)(ref colors)).pressedColor = (flag ? SliderAutoHighlightColor : SliderFixedHighlightColor);
			((Selectable)slider).colors = colors;
		}
		if ((Object)(object)sliderFillImage != (Object)null)
		{
			((Graphic)sliderFillImage).color = (flag ? SliderAutoNormalColor : SliderFixedNormalColor);
		}
		if ((Object)(object)techPilerCheck != (Object)null)
		{
			((Behaviour)techPilerCheck).enabled = flag;
		}
		if ((Object)(object)valueText != (Object)null)
		{
			valueText.text = (flag ? stationOutputStackLevel : station.pilerCount).ToString();
		}
	}

	private static int ClampStationPilerCount(int value, GameHistoryData history)
	{
		return Math.Min(GetStationOutputStackLevel(history), Math.Max(1, value));
	}

	private static StationComponent GetStationComponent(UIStationWindow window)
	{
		PlanetTransport fieldValue = GetFieldValue<PlanetTransport>(StationWindowFields.Transport, window);
		int intFieldValue = GetIntFieldValue(StationWindowFields.StationId, window);
		if ((Object)(object)window == (Object)null || fieldValue == null || fieldValue.stationPool == null || intFieldValue <= 0 || intFieldValue >= fieldValue.stationPool.Length)
		{
			return null;
		}
		StationComponent val = fieldValue.stationPool[intFieldValue];
		if (val == null || val.id != intFieldValue)
		{
			return null;
		}
		return val;
	}

	private static StationComponent GetStationComponent(UIControlPanelStationInspector inspector)
	{
		PlanetTransport fieldValue = GetFieldValue<PlanetTransport>(StationInspectorFields.Transport, inspector);
		int intFieldValue = GetIntFieldValue(StationInspectorFields.StationId, inspector);
		if ((Object)(object)inspector == (Object)null || fieldValue == null || fieldValue.stationPool == null || intFieldValue <= 0 || intFieldValue >= fieldValue.stationPool.Length)
		{
			return null;
		}
		StationComponent val = fieldValue.stationPool[intFieldValue];
		if (val == null || val.id != intFieldValue)
		{
			return null;
		}
		return val;
	}
}