Decompiled source of zzInfinity v1.0.1

zzInfinity.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace zzInfinity;

[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("zz.zzInfinity", "zz无限", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	public const string PluginGUID = "zz.zzInfinity";

	public const string PluginName = "zz无限";

	public const string PluginVersion = "1.0.0";

	public static Plugin Instance;

	public static ManualLogSource Logger;

	public static Harmony HarmonyInstance;

	public static ConfigEntry<float> AssemblerSpeedMult;

	public static ConfigEntry<float> SmelterSpeedMult;

	public static ConfigEntry<float> ChemicalSpeedMult;

	public static ConfigEntry<float> RefinerySpeedMult;

	public static ConfigEntry<float> ColliderSpeedMult;

	public static ConfigEntry<bool> BeltDoubleSpeed;

	public static ConfigEntry<float> PoleCoverMult;

	public static ConfigEntry<float> PoleConnectMult;

	public static ConfigEntry<float> PowerGenMult;

	public static ConfigEntry<bool> EnableStackingTechExt;

	public static ConfigEntry<float> StackingTechCostMult;

	private bool _applied;

	private bool _gameLoaded;

	private int _waitFrames;

	private bool _ldbPostFired;

	private int _ldbPostFrames;

	private void Awake()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		Instance = this;
		Logger = ((BaseUnityPlugin)this).Logger;
		HarmonyInstance = new Harmony("zz.zzInfinity");
		Logger.LogInfo((object)"zz无限 启动 v1.0.0");
		InitConfig();
		HarmonyInstance.PatchAll(typeof(Patches));
		HarmonyInstance.PatchAll(typeof(InfiniteTech));
		InfiniteTech.ManualPatchOptionalGetters();
		try
		{
			Type type = Type.GetType("xiaoye97.LDBTool, LDBTool");
			if (!(type != null))
			{
				return;
			}
			FieldInfo field = type.GetField("PostAddDataAction", BindingFlags.Static | BindingFlags.Public);
			if (field != null)
			{
				Action a = (Action)field.GetValue(null);
				a = (Action)Delegate.Combine(a, (Action)delegate
				{
					_ldbPostFired = true;
					_ldbPostFrames = 0;
				});
				field.SetValue(null, a);
				Logger.LogInfo((object)"已订阅 LDBTool.PostAddDataAction");
			}
		}
		catch
		{
		}
	}

	private void InitConfig()
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Expected O, but got Unknown
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Expected O, but got Unknown
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Expected O, but got Unknown
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Expected O, but got Unknown
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Expected O, but got Unknown
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Expected O, but got Unknown
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Expected O, but got Unknown
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Expected O, but got Unknown
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Expected O, but got Unknown
		//IL_0239: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Expected O, but got Unknown
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: Expected O, but got Unknown
		AssemblerSpeedMult = ((BaseUnityPlugin)this).Config.Bind<float>("01-制造台", "速度倍率", 2f, new ConfigDescription("制造台 Mk.I / II / III 的工作速度倍率。范围 0(无加成) ~ 100(100倍);1 = 原版默认;默认 = 2倍。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[0]));
		SmelterSpeedMult = ((BaseUnityPlugin)this).Config.Bind<float>("02-熔炉类", "速度倍率", 2f, new ConfigDescription("熔炉、电弧熔炉、位面熔炉的工作速度倍率。范围 0(无加成) ~ 100(100倍);1 = 原版默认;默认 = 2倍。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[0]));
		ChemicalSpeedMult = ((BaseUnityPlugin)this).Config.Bind<float>("03-化工厂", "速度倍率", 2f, new ConfigDescription("化工厂的工作速度倍率。范围 0(无加成) ~ 100(100倍);1 = 原版默认;默认 = 2倍。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[0]));
		RefinerySpeedMult = ((BaseUnityPlugin)this).Config.Bind<float>("04-精炼厂", "速度倍率", 2f, new ConfigDescription("原油精炼厂的工作速度倍率。范围 0(无加成) ~ 100(100倍);1 = 原版默认;默认 = 2倍。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[0]));
		ColliderSpeedMult = ((BaseUnityPlugin)this).Config.Bind<float>("05-粒子对撞机", "速度倍率", 2f, new ConfigDescription("粒子对撞机的工作速度倍率。范围 0(无加成) ~ 100(100倍);1 = 原版默认;默认 = 2倍。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[0]));
		BeltDoubleSpeed = ((BaseUnityPlugin)this).Config.Bind<bool>("06-传送带", "启用2倍速度", true, new ConfigDescription("关闭 = 原版速度(3种传送带);开启 = 相对原版提升至2倍。\n游戏硬上限 60 格/秒 不会突破。", (AcceptableValueBase)null, new object[0]));
		PoleCoverMult = ((BaseUnityPlugin)this).Config.Bind<float>("07-电线杆", "覆盖范围倍率", 2f, new ConfigDescription("特斯拉塔/无线输电塔/卫星配电站 等电力节点的 覆盖半径 × 倍率。范围 1 – 10,默认 2×。\n【安全说明】仅对新放置的建筑生效;已建造的电线杆不会自动升级,避免电网每帧重新计算导致的归零跳动。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), new object[0]));
		PoleConnectMult = ((BaseUnityPlugin)this).Config.Bind<float>("07-电线杆", "连接距离倍率", 2f, new ConfigDescription("电力节点之间的 可连线最大距离 × 倍率。范围 1 – 10,默认 2×。\n【安全说明】仅对新放置的建筑生效;已建造的电线杆不会自动升级,避免电网每帧重新计算导致的归零跳动。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), new object[0]));
		PowerGenMult = ((BaseUnityPlugin)this).Config.Bind<float>("08-发电设施", "发电力倍率", 2f, new ConfigDescription("火力/地热/燃油/太阳能/风力/射线接收/聚变发电站 等 每tick产能量 × 倍率。\n范围 0 – 100。默认 2×。\n【安全说明】仅对新放置的建筑生效;已建造的电线杆不会自动升级,避免电网每帧重新计算导致的归零跳动。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[0]));
		EnableStackingTechExt = ((BaseUnityPlugin)this).Config.Bind<bool>("20-运输站集装科技", "启用上限扩展", true, new ConfigDescription("开启后运输站集装物流科技最大等级从原版扩展到 50 级;\n到达 50 级后研究按钮显示 MAX 无法点击;每级科研点消耗递增 1.3×(可调)。", (AcceptableValueBase)null, new object[0]));
		StackingTechCostMult = ((BaseUnityPlugin)this).Config.Bind<float>("20-运输站集装科技", "消耗递增倍率", 1.3f, new ConfigDescription("集装科技 2 级及以上,每级科研点消耗相对原版再乘 (倍率)^(level-1)。\n默认 1.3 = 2级×1.3,3级×1.69,...;填 1.0 保持原版消耗。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), new object[0]));
		((BaseUnityPlugin)this).Config.SettingChanged += delegate
		{
			if (_applied)
			{
				MultiplierApplier.ApplyAllMultipliers();
			}
		};
	}

	public static float GetSpeedMultiplier(MultiplierApplier.BuildingCategory category)
	{
		switch (category)
		{
		case MultiplierApplier.BuildingCategory.Assembler:
			return AssemblerSpeedMult.Value;
		case MultiplierApplier.BuildingCategory.Smelter:
			return SmelterSpeedMult.Value;
		case MultiplierApplier.BuildingCategory.ChemicalPlant:
			return ChemicalSpeedMult.Value;
		case MultiplierApplier.BuildingCategory.Refinery:
			return RefinerySpeedMult.Value;
		case MultiplierApplier.BuildingCategory.Collider:
			return ColliderSpeedMult.Value;
		case MultiplierApplier.BuildingCategory.Belt:
			if (!BeltDoubleSpeed.Value)
			{
				return 1f;
			}
			return 2f;
		default:
			return 1f;
		}
	}

	private void Update()
	{
		if (!_applied)
		{
			if (_ldbPostFired)
			{
				_ldbPostFrames++;
				if (_ldbPostFrames >= 300)
				{
					ApplyNow("LDBToolPost 300帧延迟");
				}
				return;
			}
			_waitFrames++;
			if (_waitFrames < 1800 || (Object)(object)LDB.items == (Object)null || ((ProtoSet<ItemProto>)(object)LDB.items).dataArray == null || ((ProtoSet<ItemProto>)(object)LDB.items).dataArray.Length < 500)
			{
				return;
			}
			ApplyNow("备用轮询 30秒");
		}
		if (_applied && !_gameLoaded && GameMain.data != null && GameMain.data.factoryCount > 0)
		{
			_gameLoaded = true;
			MultiplierApplier.OnGameLoaded();
		}
		else if (_gameLoaded && (GameMain.data == null || GameMain.data.factoryCount == 0))
		{
			_gameLoaded = false;
		}
	}

	private void ApplyNow(string source)
	{
		try
		{
			MultiplierApplier.CaptureOriginals();
			MultiplierApplier.ApplyAllMultipliers();
			InfiniteTech.Initialize();
			_applied = true;
			Logger.LogInfo((object)("zz无限 倍率已应用(来源:" + source + ")"));
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("应用倍率失败: " + ex.Message + "\n" + ex.StackTrace));
			_applied = true;
		}
	}

	private void OnDestroy()
	{
		if (HarmonyInstance != null)
		{
			HarmonyInstance.UnpatchSelf();
		}
	}
}
public static class MultiplierApplier
{
	public enum BuildingCategory
	{
		Unknown,
		Assembler,
		Smelter,
		ChemicalPlant,
		Refinery,
		Collider,
		Belt,
		PowerNode,
		PowerGenerator
	}

	private static readonly Dictionary<int, int> OrigAssembler = new Dictionary<int, int>();

	private static readonly Dictionary<int, int> OrigBelt = new Dictionary<int, int>();

	private static readonly Dictionary<int, BuildingCategory> CatOf = new Dictionary<int, BuildingCategory>();

	private static readonly List<FieldInfo> PoleFields = new List<FieldInfo>();

	private static readonly List<FieldInfo> GenFields = new List<FieldInfo>();

	private static readonly Dictionary<int, Dictionary<string, float>> OrigPole = new Dictionary<int, Dictionary<string, float>>();

	private static readonly Dictionary<int, Dictionary<string, float>> OrigGen = new Dictionary<int, Dictionary<string, float>>();

	private static bool _captured;

	private static bool _fieldCacheBuilt;

	private static void BuildFieldCache()
	{
		if (_fieldCacheBuilt)
		{
			return;
		}
		_fieldCacheBuilt = true;
		if ((Object)(object)LDB.items == (Object)null || ((ProtoSet<ItemProto>)(object)LDB.items).dataArray == null)
		{
			return;
		}
		Type type = null;
		ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
		foreach (ItemProto val in dataArray)
		{
			if (val != null && val.prefabDesc != null)
			{
				type = ((object)val.prefabDesc).GetType();
				break;
			}
		}
		if (type == null)
		{
			return;
		}
		string[] array = new string[9] { "powerConnectDistance", "powerCoverRadius", "poleCoverRadius", "poleConnectDistance", "coverRadius", "connectDistance", "wirelessMaxPower", "wirelessPower", "wirelessChargePower" };
		string[] array2 = new string[9] { "powerGenEnergyPerTick", "generatorEnergyPerTick", "genEnergyPerTick", "solarEnergyPerTick", "energyPerTickGen", "generateEnergyPerTick", "powerEnergyPerTick", "fuelEnergyPerTick", "energyPerTick" };
		string[] array3 = array;
		foreach (string name in array3)
		{
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null && (field.FieldType == typeof(float) || field.FieldType == typeof(long) || field.FieldType == typeof(double)))
			{
				PoleFields.Add(field);
			}
		}
		string[] array4 = array2;
		foreach (string name2 in array4)
		{
			FieldInfo field2 = type.GetField(name2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field2 != null && (field2.FieldType == typeof(float) || field2.FieldType == typeof(long) || field2.FieldType == typeof(double) || field2.FieldType == typeof(int)))
			{
				GenFields.Add(field2);
			}
		}
		string text = "";
		foreach (FieldInfo poleField in PoleFields)
		{
			text = text + poleField.Name + " ";
		}
		Plugin.Logger.LogInfo((object)("zz无限 电线杆候选字段: " + text));
		text = "";
		foreach (FieldInfo genField in GenFields)
		{
			text = text + genField.Name + " ";
		}
		Plugin.Logger.LogInfo((object)("zz无限 发电候选字段: " + text));
	}

	public static void CaptureOriginals()
	{
		if (_captured)
		{
			return;
		}
		BuildFieldCache();
		if ((Object)(object)LDB.items == (Object)null || ((ProtoSet<ItemProto>)(object)LDB.items).dataArray == null)
		{
			return;
		}
		ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
		foreach (ItemProto val in dataArray)
		{
			if (val == null || val.prefabDesc == null)
			{
				continue;
			}
			PrefabDesc prefabDesc = val.prefabDesc;
			if (prefabDesc.isAssembler && prefabDesc.assemblerSpeed > 0)
			{
				OrigAssembler[((Proto)val).ID] = prefabDesc.assemblerSpeed;
			}
			if (prefabDesc.beltSpeed > 0)
			{
				OrigBelt[((Proto)val).ID] = prefabDesc.beltSpeed;
			}
			Dictionary<string, float> dictionary;
			if (PoleFields.Count > 0)
			{
				dictionary = null;
				foreach (FieldInfo poleField in PoleFields)
				{
					float num = FieldToFloat(poleField, prefabDesc);
					if (num > 0f)
					{
						if (dictionary == null)
						{
							dictionary = new Dictionary<string, float>();
						}
						dictionary[poleField.Name] = num;
					}
				}
				if (dictionary != null)
				{
					OrigPole[((Proto)val).ID] = dictionary;
				}
			}
			if (GenFields.Count <= 0)
			{
				continue;
			}
			dictionary = null;
			foreach (FieldInfo genField in GenFields)
			{
				float num2 = FieldToFloat(genField, prefabDesc);
				if (num2 > 0f)
				{
					if (dictionary == null)
					{
						dictionary = new Dictionary<string, float>();
					}
					dictionary[genField.Name] = num2;
				}
			}
			if (dictionary != null)
			{
				OrigGen[((Proto)val).ID] = dictionary;
			}
		}
		_captured = true;
		Plugin.Logger.LogInfo((object)("zz无限 捕获原版: 制造类=" + OrigAssembler.Count + ", 传送带=" + OrigBelt.Count + ", 电线杆类=" + OrigPole.Count + ", 发电设施=" + OrigGen.Count));
	}

	public static void ApplyAllMultipliers()
	{
		if ((Object)(object)LDB.items == (Object)null || ((ProtoSet<ItemProto>)(object)LDB.items).dataArray == null)
		{
			return;
		}
		if (!_captured)
		{
			CaptureOriginals();
		}
		CatOf.Clear();
		int num = 0;
		ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
		foreach (ItemProto val in dataArray)
		{
			if (val == null)
			{
				continue;
			}
			PrefabDesc prefabDesc = val.prefabDesc;
			if (prefabDesc == null)
			{
				continue;
			}
			int iD = ((Proto)val).ID;
			BuildingCategory buildingCategory = Classify(prefabDesc, iD);
			if (buildingCategory != BuildingCategory.Unknown)
			{
				CatOf[iD] = buildingCategory;
			}
			bool flag = false;
			if (OrigAssembler.ContainsKey(iD))
			{
				float speedMultiplier = Plugin.GetSpeedMultiplier(buildingCategory);
				int num2 = (int)((float)OrigAssembler[iD] * speedMultiplier);
				if (num2 < 0)
				{
					num2 = 0;
				}
				if (prefabDesc.assemblerSpeed != num2)
				{
					prefabDesc.assemblerSpeed = num2;
					flag = true;
				}
			}
			if (OrigBelt.ContainsKey(iD))
			{
				float speedMultiplier2 = Plugin.GetSpeedMultiplier(BuildingCategory.Belt);
				int num3 = (int)((float)OrigBelt[iD] * speedMultiplier2);
				if (num3 < 0)
				{
					num3 = 0;
				}
				if (prefabDesc.beltSpeed != num3)
				{
					prefabDesc.beltSpeed = num3;
					flag = true;
				}
			}
			if (OrigPole.TryGetValue(iD, out var value))
			{
				float value2 = Plugin.PoleConnectMult.Value;
				float value3 = Plugin.PoleCoverMult.Value;
				foreach (FieldInfo poleField in PoleFields)
				{
					if (value.TryGetValue(poleField.Name, out var value4))
					{
						float num4 = ((poleField.Name.Contains("Cover") || poleField.Name.Contains("Radius")) ? value3 : value2);
						float num5 = value4 * num4;
						if (num5 < 0f)
						{
							num5 = 0f;
						}
						if (SetField(poleField, prefabDesc, num5))
						{
							flag = true;
						}
					}
				}
				if (buildingCategory == BuildingCategory.Unknown)
				{
					CatOf[iD] = BuildingCategory.PowerNode;
				}
			}
			if (OrigGen.TryGetValue(iD, out var value5))
			{
				float value6 = Plugin.PowerGenMult.Value;
				foreach (FieldInfo genField in GenFields)
				{
					if (value5.TryGetValue(genField.Name, out var value7))
					{
						float num6 = value7 * value6;
						if (num6 < 0f)
						{
							num6 = 0f;
						}
						if (SetField(genField, prefabDesc, num6))
						{
							flag = true;
						}
					}
				}
				if (buildingCategory == BuildingCategory.Unknown)
				{
					CatOf[iD] = BuildingCategory.PowerGenerator;
				}
			}
			if (flag)
			{
				num++;
			}
		}
		Plugin.Logger.LogInfo((object)("zz无限 倍率已应用: 影响建筑 " + num + " 个"));
	}

	public static void OnGameLoaded()
	{
	}

	public static BuildingCategory GetCategory(int protoId)
	{
		if (CatOf.TryGetValue(protoId, out var value))
		{
			return value;
		}
		return BuildingCategory.Unknown;
	}

	private static BuildingCategory Classify(PrefabDesc d, int id)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected I4, but got Unknown
		if (OrigPole.ContainsKey(id))
		{
			return BuildingCategory.PowerNode;
		}
		if (OrigGen.ContainsKey(id))
		{
			return BuildingCategory.PowerGenerator;
		}
		if (d.beltSpeed > 0)
		{
			return BuildingCategory.Belt;
		}
		if (!d.isAssembler)
		{
			return BuildingCategory.Unknown;
		}
		int num = (int)d.assemblerRecipeType;
		if ((num & 2) != 0)
		{
			return BuildingCategory.Smelter;
		}
		if ((num & 4) != 0)
		{
			return BuildingCategory.ChemicalPlant;
		}
		if ((num & 8) != 0)
		{
			return BuildingCategory.Refinery;
		}
		if ((num & 0x10) != 0 || num == 5)
		{
			return BuildingCategory.Collider;
		}
		return BuildingCategory.Assembler;
	}

	private static float FieldToFloat(FieldInfo f, object inst)
	{
		object value = f.GetValue(inst);
		if (value == null)
		{
			return 0f;
		}
		if (f.FieldType == typeof(float))
		{
			return (float)value;
		}
		if (f.FieldType == typeof(double))
		{
			return (float)(double)value;
		}
		if (f.FieldType == typeof(long))
		{
			return (long)value;
		}
		if (f.FieldType == typeof(int))
		{
			return (int)value;
		}
		return 0f;
	}

	private static bool SetField(FieldInfo f, object inst, float newValue)
	{
		float num = FieldToFloat(f, inst);
		if (num - newValue < 1E-05f && newValue - num < 1E-05f)
		{
			return false;
		}
		if (f.FieldType == typeof(float))
		{
			f.SetValue(inst, newValue);
		}
		else if (f.FieldType == typeof(double))
		{
			f.SetValue(inst, (double)newValue);
		}
		else if (f.FieldType == typeof(long))
		{
			f.SetValue(inst, (long)newValue);
		}
		else if (f.FieldType == typeof(int))
		{
			f.SetValue(inst, (int)newValue);
		}
		return true;
	}
}
public static class Patches
{
}
public static class InfiniteTech
{
	private static bool _inited;

	private static int _stationTechId;

	public static void Initialize()
	{
		if (_inited)
		{
			return;
		}
		_inited = true;
		if (!Plugin.EnableStackingTechExt.Value)
		{
			return;
		}
		try
		{
			Find();
			if (_stationTechId != 0)
			{
				SetMax(_stationTechId, 50);
			}
			Plugin.Logger.LogInfo((object)("zz无限 集装科技扩展: 目标ID=" + _stationTechId + ", 上限=50级"));
		}
		catch (Exception ex)
		{
			Plugin.Logger.LogError((object)("初始化集装科技扩展失败: " + ex.Message));
		}
	}

	private static void Find()
	{
		if ((Object)(object)LDB.techs == (Object)null || ((ProtoSet<TechProto>)(object)LDB.techs).dataArray == null)
		{
			return;
		}
		int num = -1;
		int num2 = 0;
		TechProto[] dataArray = ((ProtoSet<TechProto>)(object)LDB.techs).dataArray;
		foreach (TechProto val in dataArray)
		{
			if (val == null || ((Proto)val).name == null)
			{
				continue;
			}
			string name = ((Proto)val).name;
			if (name.IndexOf("分拣", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("sorter", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("爪子", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("claw", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				num2++;
				continue;
			}
			bool flag = name.IndexOf("station", StringComparison.OrdinalIgnoreCase) >= 0 && (name.IndexOf("pile", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("container", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("logistics", StringComparison.OrdinalIgnoreCase) >= 0);
			bool flag2 = name.IndexOf("运输站", StringComparison.Ordinal) >= 0 || name.IndexOf("集装物流", StringComparison.Ordinal) >= 0 || (name.IndexOf("集装", StringComparison.Ordinal) >= 0 && name.IndexOf("物流", StringComparison.Ordinal) >= 0);
			if ((flag || flag2) && val.MaxLevel >= num)
			{
				num = val.MaxLevel;
				_stationTechId = ((Proto)val).ID;
			}
		}
		Plugin.Logger.LogInfo((object)("zz无限 集装科技查找: 候选目标ID=" + _stationTechId + " MaxLevel=" + num + " 已排除分拣器/爪子类科技=" + num2));
	}

	private static void SetMax(int id, int cap)
	{
		TechProto val = ((ProtoSet<TechProto>)(object)LDB.techs).Select(id);
		if (val != null)
		{
			Plugin.Logger.LogInfo((object)("zz无限 科技 " + id + " MaxLevel: " + val.MaxLevel + " → " + cap));
			val.MaxLevel = cap;
		}
	}

	[HarmonyPatch(typeof(GameHistoryData), "UnlockTech")]
	[HarmonyPostfix]
	public static void UnlockTech_Postfix(GameHistoryData __instance, int techId)
	{
		if (!_inited || !Plugin.EnableStackingTechExt.Value || techId != _stationTechId)
		{
			return;
		}
		try
		{
			int num = 50;
			TechProto val = ((ProtoSet<TechProto>)(object)LDB.techs).Select(techId);
			if (val != null)
			{
				num = val.MaxLevel;
			}
			Traverse val2 = Traverse.Create((object)__instance);
			Traverse val3 = val2.Field("techStates");
			if (!val3.FieldExists())
			{
				return;
			}
			Dictionary<int, object> value = val3.GetValue<Dictionary<int, object>>();
			if (value != null && value.TryGetValue(techId, out var value2) && value2 != null)
			{
				Traverse val4 = Traverse.Create(value2);
				int value3 = val4.Field("curLevel").GetValue<int>();
				int num2 = Math.Min(value3 + 1, num);
				val4.Field("curLevel").SetValue((object)num2);
				val4.Field("maxLevel").SetValue((object)num);
				Traverse val5 = val2.Field("stationPilerLevel");
				if (val5.FieldExists())
				{
					val5.SetValue((object)(val5.GetValue<int>() + 1));
				}
				if (num2 == 1 || num2 % 10 == 0 || num2 == num)
				{
					Plugin.Logger.LogInfo((object)("zz无限 集装科技研究: 等级 " + value3 + " → " + num2 + "/" + num));
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Logger.LogWarning((object)("集装研究后处理失败: " + ex.Message));
		}
	}

	public static void ManualPatchOptionalGetters()
	{
		Harmony harmonyInstance = Plugin.HarmonyInstance;
		if (harmonyInstance != null)
		{
			TryPatchM(harmonyInstance, typeof(GameHistoryData), "GetStationPilerLevel", typeof(InfiniteTech).GetMethod("GetStationPilerLevel_Postfix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
			TryPatchPropGet(harmonyInstance, typeof(GameHistoryData), "stationPilerLevel", typeof(InfiniteTech).GetMethod("stationPilerLevel_Getter_Postfix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
			TryPatchMArgs(harmonyInstance, typeof(TechProto), "GetHashNeeded", new Type[1] { typeof(int) }, typeof(InfiniteTech).GetMethod("HashNeeded_Postfix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
			Plugin.Logger.LogInfo((object)"zz无限 手动补丁完成");
		}
	}

	private static void TryPatchM(Harmony h, Type type, string methodName, MethodInfo postfix)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Expected O, but got Unknown
		try
		{
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(method == null))
			{
				h.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(postfix), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}
		catch
		{
		}
	}

	private static void TryPatchMArgs(Harmony h, Type type, string methodName, Type[] args, MethodInfo postfix)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Expected O, but got Unknown
		try
		{
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, args, null);
			if (!(method == null))
			{
				h.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(postfix), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}
		catch
		{
		}
	}

	private static void TryPatchPropGet(Harmony h, Type type, string prop, MethodInfo postfix)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Expected O, but got Unknown
		try
		{
			PropertyInfo property = type.GetProperty(prop, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(property == null))
			{
				MethodInfo getMethod = property.GetGetMethod(nonPublic: true);
				if (!(getMethod == null))
				{
					h.Patch((MethodBase)getMethod, (HarmonyMethod)null, new HarmonyMethod(postfix), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}
		catch
		{
		}
	}

	public static void GetStationPilerLevel_Postfix(GameHistoryData __instance, ref int __result)
	{
		if (!_inited || !Plugin.EnableStackingTechExt.Value)
		{
			return;
		}
		try
		{
			Traverse val = Traverse.Create((object)__instance).Field("stationPilerLevel");
			if (val.FieldExists())
			{
				int value = val.GetValue<int>();
				if (value != __result)
				{
					__result = value;
				}
			}
		}
		catch
		{
		}
	}

	public static void stationPilerLevel_Getter_Postfix(GameHistoryData __instance, ref int __result)
	{
		if (!_inited || !Plugin.EnableStackingTechExt.Value)
		{
			return;
		}
		try
		{
			Traverse val = Traverse.Create((object)__instance).Field("stationPilerLevel");
			if (val.FieldExists())
			{
				int value = val.GetValue<int>();
				if (value != __result)
				{
					__result = value;
				}
			}
		}
		catch
		{
		}
	}

	public static void HashNeeded_Postfix(TechProto __instance, int level, ref long __result)
	{
		if (!_inited || !Plugin.EnableStackingTechExt.Value || __instance == null || ((Proto)__instance).ID != _stationTechId || level <= 1)
		{
			return;
		}
		float value = Plugin.StackingTechCostMult.Value;
		if (!(value <= 1f))
		{
			double num = Math.Pow(value, level - 1);
			long num2 = (long)Math.Round((double)__result * num);
			if (num2 > 0)
			{
				__result = num2;
			}
		}
	}
}