Decompiled source of GlobalProliferatorSupply v2.3.0

GlobalProliferatorSupply.dll

Decompiled a week ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using BepInEx;
using BepInEx.Logging;
using CommonAPI;
using CommonAPI.Systems;
using HarmonyLib;
using UnityEngine;
using crecheng.DSPModSave;
using xiaoye97;

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

public static class C
{
	public const string GUID = "com.mandaobudao.globalproliferatorsupply";

	public const string NAME = "GlobalProliferatorSupply";

	public const string VERSION = "2.3.0";

	public const int ITEM_ID = 9600;

	public const int RECIPE_ID = 9601;

	public const int ORIG_STATION_ID = 2103;

	public const int PROLIF_MK1 = 1141;

	public const int PROLIF_MK2 = 1142;

	public const int PROLIF_MK3 = 1143;

	public const int SPRAYER_ITEM_ID = 1144;

	public const int SPRAYERS_PER_RECIPE = 100;

	public const int RECIPE_TIME = 600;

	public const int TOWER_MAX_ITEM_COUNT = 30000;

	public const float TINT_R = 0.2f;

	public const float TINT_G = 0.4f;

	public const float TINT_B = 1f;

	public const string TAB_ID = "gps:GlobalSupplyTab";

	public const string TAB_NAME = "全球供应";

	public const string TAB_ICON = "Icons/ItemRecipe/logistic-station";

	public const string LOG = "[GPS] ";

	public const string ITEM_NAME = "全球增产剂供应";

	public const string ITEM_DESC = "全球供应塔:仅可仓储与需求增产剂。塔内有增产剂库存时,本星球所有建筑的生产原料自动带上增产效果,无需喷涂机与传送带。";
}
[CommonAPISubmoduleDependency(new string[] { "TabSystem" })]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("com.mandaobudao.globalproliferatorsupply", "GlobalProliferatorSupply", "2.3.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInProcess("DSPGAME.exe")]
public class GPSPlugin : BaseUnityPlugin, IModCanSave
{
	internal static ManualLogSource Log;

	internal static int TabIndex = -1;

	private int tick;

	private static int summarySec;

	private static bool recipeEnsured;

	private static bool iconEnsured;

	private void Awake()
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Log.LogInfo((object)"[GPS] v2.3.0 加载中...");
		try
		{
			TabIndex = TabSystem.RegisterTab("gps:GlobalSupplyTab", new TabData("全球供应", "Icons/ItemRecipe/logistic-station"));
			Log.LogInfo((object)("[GPS] 分页「全球供应」索引=" + TabIndex));
		}
		catch (Exception ex)
		{
			Log.LogError((object)("[GPS] 分页注册失败: " + ex.Message));
		}
		LDBTool.PreAddDataAction = (Action)Delegate.Combine(LDBTool.PreAddDataAction, new Action(Registry.OnPreAddData));
		LDBTool.PostAddDataAction = (Action)Delegate.Combine(LDBTool.PostAddDataAction, new Action(Registry.OnPostAddData));
		Harmony h = new Harmony("com.mandaobudao.globalproliferatorsupply");
		PatchSafe(h, typeof(StationWindowPatches));
		PatchSafe(h, typeof(RecipeUnlockPatches));
		PatchSafe(h, typeof(PickerRestrictPatches));
		PatchSafe(h, typeof(FactorySprayPatch));
		PatchSafe(h, typeof(IconSetPatches));
		LogPatchInfo(typeof(FactorySystem), "GameTick");
		Log.LogInfo((object)"[GPS] v2.3.0 加载完成");
	}

	private static void PatchSafe(Harmony h, Type t)
	{
		try
		{
			h.CreateClassProcessor(t).Patch();
			Log.LogInfo((object)("[GPS] 补丁 " + t.Name + " 已应用"));
		}
		catch (Exception ex)
		{
			Log.LogError((object)("[GPS] 补丁 " + t.Name + " 失败: " + ex.Message));
		}
	}

	private static void LogPatchInfo(Type type, string name)
	{
		try
		{
			int num = 0;
			foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type))
			{
				if (!(declaredMethod.Name != name))
				{
					Patches patchInfo = Harmony.GetPatchInfo((MethodBase)declaredMethod);
					num += ((patchInfo != null) ? (patchInfo.Postfixes.Count + patchInfo.Prefixes.Count) : 0);
				}
			}
			Log.LogInfo((object)("[GPS] 补丁校验 " + type.Name + "." + name + " => " + num));
		}
		catch (Exception)
		{
		}
	}

	private void Update()
	{
		if (++tick < 60)
		{
			return;
		}
		tick = 0;
		if (!recipeEnsured && GameMain.history != null)
		{
			recipeEnsured = true;
			try
			{
				if (GameMain.history.recipeUnlocked != null)
				{
					GameMain.history.recipeUnlocked.Add(9601);
				}
				Log.LogInfo((object)"[GPS] 配方 9601 已强制解锁");
			}
			catch (Exception)
			{
			}
		}
		if (!iconEnsured && GameMain.iconSet != null && ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(9601) != null)
		{
			iconEnsured = true;
			try
			{
				IconSet iconSet = GameMain.iconSet;
				if (iconSet.recipeIconIndex == null || iconSet.recipeIconIndex.Length <= 9601 || iconSet.recipeIconIndex[9601] == 0)
				{
					FieldInfo field = typeof(IconSet).GetField("loaded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null)
					{
						field.SetValue(iconSet, false);
					}
					iconSet.Create();
					Log.LogInfo((object)"[GPS] 图集已重建以收录配方图标");
				}
				else
				{
					Log.LogInfo((object)("[GPS] 图集已包含配方图标 idx=" + iconSet.recipeIconIndex[9601]));
				}
				RecipeProto val = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(9601);
				Log.LogInfo((object)("[GPS] 配方状态:GridIndex=" + (val?.GridIndex ?? (-1)) + " 解锁=" + (GameMain.history != null && GameMain.history.RecipeUnlocked(9601)) + " 物品解锁=" + (GameMain.history != null && GameMain.history.ItemUnlocked(9600))));
			}
			catch (Exception ex2)
			{
				Log.LogWarning((object)("[GPS] 图集检查异常: " + ex2.Message));
			}
		}
		try
		{
			SupplyManager.Tick();
		}
		catch (Exception ex2)
		{
			Log.LogWarning((object)("[GPS] 无线供应异常: " + ex2.Message));
		}
		if (GameMain.history != null && ++summarySec >= 10)
		{
			summarySec = 0;
			Log.LogInfo((object)("[GPS] 累计喷涂=" + BuildingSpray.SprayCount + " 有料输入槽=" + BuildingSpray.ScanCount + " 活动塔=" + PlanetSpray.ActiveHubCount));
		}
	}

	public void Export(BinaryWriter w)
	{
		w.Write(1);
	}

	public void Import(BinaryReader r)
	{
		r.ReadInt32();
	}

	public void IntoOtherSave()
	{
	}
}
public static class Registry
{
	internal static int ModelId = -1;

	public static void OnPreAddData()
	{
		((ProtoSet<ItemProto>)(object)LDB.items).OnAfterDeserialize();
		((ProtoSet<RecipeProto>)(object)LDB.recipes).OnAfterDeserialize();
		((ProtoSet<ModelProto>)(object)LDB.models).OnAfterDeserialize();
		ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(2103);
		if (val == null)
		{
			GPSPlugin.Log.LogError((object)("[GPS] 找不到原版物品 " + 2103));
			return;
		}
		ModelProto val2 = ((ProtoSet<ModelProto>)(object)LDB.models).Select(val.ModelIndex);
		if (val2 == null)
		{
			GPSPlugin.Log.LogError((object)("[GPS] 找不到原版模型 " + val.ModelIndex));
			return;
		}
		ModelId = NextModelId();
		if (ModelId < 0)
		{
			GPSPlugin.Log.LogError((object)"[GPS] 无法分配模型 ID");
			return;
		}
		RegisterModel(val2, ModelId);
		RegisterItem(val, ModelId);
		RegisterRecipe(val);
		GPSPlugin.Log.LogInfo((object)("[GPS] 注册完成:模型=" + ModelId + " 物品=" + 9600 + " 配方=" + 9601));
	}

	public static void OnPostAddData()
	{
		((ProtoSet<ItemProto>)(object)LDB.items).OnAfterDeserialize();
		((ProtoSet<RecipeProto>)(object)LDB.recipes).OnAfterDeserialize();
		((ProtoSet<ModelProto>)(object)LDB.models).OnAfterDeserialize();
		PreloadItem(9600);
		PreloadRecipe(9601);
		FixupTextAndIcon();
		ItemProto.InitConstructableItems();
		ItemProto.InitItemIds();
		ItemProto.InitItemIndices();
		ItemProto.InitProductionMask();
		ModelProto.InitMaxModelIndex();
		ModelProto.InitModelIndices();
		ModelProto.InitModelOrders();
		try
		{
			FieldInfo field = typeof(UIBuildMenu).GetField("staticLoaded", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				field.SetValue(null, false);
			}
			UIBuildMenu.StaticLoad();
		}
		catch (Exception)
		{
		}
		try
		{
			PlanetFactory.PrefabDescByModelIndex = null;
			PlanetFactory.InitPrefabDescArray();
		}
		catch (Exception)
		{
		}
		GPSPlugin.Log.LogInfo((object)"[GPS] OnPostAddData 完成");
	}

	private static void RegisterModel(ModelProto srcModel, int id)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: 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_007c: 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_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Expected O, but got Unknown
		//IL_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		ModelProto val = new ModelProto();
		val.ObjectType = srcModel.ObjectType;
		val.RuinType = srcModel.RuinType;
		val.RendererType = srcModel.RendererType;
		val.HpMax = srcModel.HpMax;
		val.PrefabPath = srcModel.PrefabPath;
		val.Order = srcModel.Order;
		((Proto)val).ID = id;
		((Proto)val).Name = id.ToString();
		((Proto)val).SID = "";
		((Proto)val).sid = "";
		val.meshBounds = srcModel.meshBounds;
		PrefabDesc prefabDesc = srcModel.prefabDesc;
		GameObject val2 = ((prefabDesc != null && (Object)(object)prefabDesc.prefab != (Object)null) ? prefabDesc.prefab : Resources.Load<GameObject>(srcModel.PrefabPath));
		GameObject val3 = ((prefabDesc != null && (Object)(object)prefabDesc.colliderPrefab != (Object)null) ? prefabDesc.colliderPrefab : (string.IsNullOrEmpty(srcModel.PrefabPath) ? null : Resources.Load<GameObject>(srcModel.PrefabPath + "-cl")));
		if ((Object)(object)val2 == (Object)null)
		{
			GPSPlugin.Log.LogError((object)("[GPS] 模型 prefab 为空:PrefabPath=" + ((srcModel.PrefabPath == null) ? "null" : srcModel.PrefabPath)));
			return;
		}
		PrefabDesc val4 = (((Object)(object)val3 == (Object)null) ? new PrefabDesc(id, val2) : new PrefabDesc(id, val2, val3));
		if (prefabDesc != null)
		{
			val4.hasBuildCollider = prefabDesc.hasBuildCollider;
			val4.colliders = prefabDesc.colliders;
			val4.buildCollider = prefabDesc.buildCollider;
			val4.buildColliders = prefabDesc.buildColliders;
			val4.colliderPrefab = prefabDesc.colliderPrefab;
			val4.dragBuild = prefabDesc.dragBuild;
			val4.dragBuildDist = prefabDesc.dragBuildDist;
			val4.blueprintBoxSize = prefabDesc.blueprintBoxSize;
			val4.roughHeight = prefabDesc.roughHeight;
			val4.roughWidth = prefabDesc.roughWidth;
			val4.roughRadius = prefabDesc.roughRadius;
			val4.barHeight = prefabDesc.barHeight;
			val4.barWidth = prefabDesc.barWidth;
			val4.idleEnergyPerTick = prefabDesc.idleEnergyPerTick;
			val4.workEnergyPerTick = prefabDesc.workEnergyPerTick;
			val4.stationMaxDroneCount = prefabDesc.stationMaxDroneCount;
			val4.stationMaxEnergyAcc = prefabDesc.stationMaxEnergyAcc;
		}
		Color tint = default(Color);
		((Color)(ref tint))..ctor(0.2f, 0.4f, 1f, 1f);
		TintMaterials(val4, tint);
		val4.isStation = true;
		val4.isCollectStation = false;
		val4.isVeinCollector = false;
		val4.stationMaxItemCount = 30000;
		val4.stationMaxItemKinds = 1;
		val4.stationMaxShipCount = 0;
		val4.modelIndex = id;
		val.prefabDesc = val4;
		LDBTool.PreAddProto((Proto)(object)val);
		GPSPlugin.Log.LogInfo((object)("[GPS] 模型已注册:ID=" + id + " prefab=OK collider=" + (((Object)(object)val3 != (Object)null) ? "OK" : "null") + " hasBuildCollider=" + val4.hasBuildCollider));
	}

	private static void TintMaterials(PrefabDesc d, Color tint)
	{
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Expected O, but got Unknown
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Expected O, but got Unknown
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (d.lodMaterials != null)
			{
				for (int i = 0; i < d.lodMaterials.Length; i++)
				{
					Material[] array = d.lodMaterials[i];
					if (array == null)
					{
						continue;
					}
					for (int j = 0; j < array.Length; j++)
					{
						if (!((Object)(object)array[j] == (Object)null))
						{
							array[j] = new Material(array[j]);
							array[j].SetColor("_Color", tint);
						}
					}
				}
			}
			if (d.materials == null)
			{
				return;
			}
			for (int j = 0; j < d.materials.Length; j++)
			{
				if (!((Object)(object)d.materials[j] == (Object)null))
				{
					d.materials[j] = new Material(d.materials[j]);
					d.materials[j].SetColor("_Color", tint);
				}
			}
		}
		catch (Exception ex)
		{
			GPSPlugin.Log.LogWarning((object)("[GPS] 材质染色失败: " + ex.Message));
		}
	}

	private static void RegisterItem(ItemProto src, int modelId)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		ItemProto val = new ItemProto();
		((Proto)val).ID = 9600;
		((Proto)val).Name = "全球增产剂供应";
		((Proto)val).name = "全球增产剂供应";
		val.Description = "全球供应塔:仅可仓储与需求增产剂。塔内有增产剂库存时,本星球所有建筑的生产原料自动带上增产效果,无需喷涂机与传送带。";
		val.description = "全球供应塔:仅可仓储与需求增产剂。塔内有增产剂库存时,本星球所有建筑的生产原料自动带上增产效果,无需喷涂机与传送带。";
		val.Type = src.Type;
		val.StackSize = src.StackSize;
		val.GridIndex = ((GPSPlugin.TabIndex <= 0) ? 1 : GPSPlugin.TabIndex) * 1000 + 101;
		val.BuildIndex = FreeBuildIndex(src.BuildIndex);
		val.ModelIndex = modelId;
		val.ModelCount = 1;
		val.HpMax = src.HpMax;
		val.IsEntity = true;
		val.CanBuild = true;
		val.BuildMode = src.BuildMode;
		val.IconPath = src.IconPath;
		val.PreTechOverride = 0;
		val.UnlockKey = -1;
		val.Grade = 0;
		val.Upgrades = new int[0];
		val.prefabDesc = PrefabDesc.none;
		LDBTool.PreAddProto((Proto)(object)val);
		GPSPlugin.Log.LogInfo((object)("[GPS] 物品已注册:GridIndex=" + val.GridIndex + " BuildIndex=" + val.BuildIndex + " ModelIndex=" + modelId + " IconPath=" + val.IconPath));
	}

	private static void RegisterRecipe(ItemProto src)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Expected O, but got Unknown
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		int num = ResolveSprayerId();
		RecipeProto val = new RecipeProto();
		((Proto)val).ID = 9601;
		((Proto)val).Name = "全球增产剂供应";
		((Proto)val).name = "全球增产剂供应";
		val.Description = "全球供应塔:仅可仓储与需求增产剂。塔内有增产剂库存时,本星球所有建筑的生产原料自动带上增产效果,无需喷涂机与传送带。";
		val.Type = (ERecipeType)4;
		val.Handcraft = true;
		val.Explicit = true;
		val.TimeSpend = 600;
		val.Items = new int[2] { 2103, num };
		val.ItemCounts = new int[2] { 1, 100 };
		val.Results = new int[1] { 9600 };
		val.ResultCounts = new int[1] { 1 };
		val.GridIndex = ((GPSPlugin.TabIndex <= 0) ? 1 : GPSPlugin.TabIndex) * 1000 + 101;
		val.IconPath = src.IconPath;
		TechProto val2 = (val.preTech = FindRecipeFor(2103)?.preTech);
		if (val2 != null)
		{
			AppendRecipeToTech(val2);
		}
		LDBTool.PreAddProto((Proto)(object)val);
		GPSPlugin.Log.LogInfo((object)("[GPS] 配方已注册:GridIndex=" + val.GridIndex + " 材料=" + 2103 + "x1 + " + num + "x" + 100));
	}

	private static RecipeProto FindRecipeFor(int itemId)
	{
		RecipeProto[] dataArray = ((ProtoSet<RecipeProto>)(object)LDB.recipes).dataArray;
		foreach (RecipeProto val in dataArray)
		{
			if (val != null && val.Results != null && val.Results.Length != 0 && val.Results[0] == itemId)
			{
				return val;
			}
		}
		return null;
	}

	private static void AppendRecipeToTech(TechProto tech)
	{
		int[] unlockRecipes = tech.UnlockRecipes;
		if (unlockRecipes == null)
		{
			tech.UnlockRecipes = new int[1] { 9601 };
			return;
		}
		for (int i = 0; i < unlockRecipes.Length; i++)
		{
			if (unlockRecipes[i] == 9601)
			{
				return;
			}
		}
		int[] array = new int[unlockRecipes.Length + 1];
		Array.Copy(unlockRecipes, array, unlockRecipes.Length);
		array[unlockRecipes.Length] = 9601;
		tech.UnlockRecipes = array;
		GPSPlugin.Log.LogInfo((object)("[GPS] 已把配方加入科技 " + ((Proto)tech).ID + " 的解锁列表"));
	}

	private static int ResolveSprayerId()
	{
		ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
		foreach (ItemProto val in dataArray)
		{
			if (val != null && ((Proto)val).name != null)
			{
				string name = ((Proto)val).name;
				if (name.IndexOf("喷涂机", StringComparison.Ordinal) >= 0 || name.IndexOf("Spray Coater", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return ((Proto)val).ID;
				}
			}
		}
		return 1144;
	}

	private static int NextModelId()
	{
		ModelProto[] dataArray = ((ProtoSet<ModelProto>)(object)LDB.models).dataArray;
		int num = dataArray.Length + 64;
		int num2 = 0;
		for (int i = 0; i < dataArray.Length; i++)
		{
			if (dataArray[i] != null && ((Proto)dataArray[i]).ID > num2)
			{
				num2 = ((Proto)dataArray[i]).ID;
			}
		}
		int num3 = num2 + 1;
		if (num3 < num && ((ProtoSet<ModelProto>)(object)LDB.models).Select(num3) == null)
		{
			return num3;
		}
		for (int i = num - 1; i > 0; i--)
		{
			if (((ProtoSet<ModelProto>)(object)LDB.models).Select(i) == null)
			{
				return i;
			}
		}
		return -1;
	}

	private static int FreeBuildIndex(int origBuildIndex)
	{
		int num = origBuildIndex / 100;
		for (int i = 0; i <= 12; i++)
		{
			int num2 = num * 100 + i;
			bool flag = false;
			for (int j = 0; j < ((ProtoSet<ItemProto>)(object)LDB.items).dataArray.Length; j++)
			{
				ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray[j];
				if (val != null && ((Proto)val).ID != 9600 && val.BuildIndex == num2)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return num2;
			}
		}
		return origBuildIndex + 1;
	}

	internal static void FixupTextAndIcon()
	{
		ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(2103);
		ItemProto val2 = ((ProtoSet<ItemProto>)(object)LDB.items).Select(9600);
		if (val2 != null)
		{
			((Proto)val2).name = "全球增产剂供应";
			val2.description = "全球供应塔:仅可仓储与需求增产剂。塔内有增产剂库存时,本星球所有建筑的生产原料自动带上增产效果,无需喷涂机与传送带。";
			if (val != null)
			{
				if (val.DescFields != null)
				{
					val2.DescFields = (int[])val.DescFields.Clone();
				}
				CopySprite(val, val2);
			}
		}
		RecipeProto val3 = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(9601);
		if (val3 != null)
		{
			((Proto)val3).name = "全球增产剂供应";
			val3.description = "全球供应塔:仅可仓储与需求增产剂。塔内有增产剂库存时,本星球所有建筑的生产原料自动带上增产效果,无需喷涂机与传送带。";
			if (val != null)
			{
				CopySprite(val, val3);
			}
		}
	}

	private static void CopySprite(object src, object dst)
	{
		try
		{
			PropertyInfo property = src.GetType().GetProperty("iconSprite");
			Sprite val = (Sprite)((property != null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Type type = dst.GetType();
			PropertyInfo property2 = type.GetProperty("iconSprite");
			if (property2 != null && property2.CanWrite)
			{
				property2.SetValue(dst, val, null);
				return;
			}
			FieldInfo field = type.GetField("_iconSprite", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				field.SetValue(dst, val);
			}
		}
		catch (Exception)
		{
		}
	}

	private static void PreloadItem(int itemId)
	{
		ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
		for (int i = 0; i < dataArray.Length; i++)
		{
			if (dataArray[i] != null && ((Proto)dataArray[i]).ID == itemId)
			{
				try
				{
					dataArray[i].recipes = null;
					dataArray[i].rawMats = null;
					dataArray[i].Preload(i);
					return;
				}
				catch (Exception ex)
				{
					GPSPlugin.Log.LogWarning((object)("[GPS] 物品 Preload 失败: " + ex.Message));
					return;
				}
			}
		}
		GPSPlugin.Log.LogWarning((object)("[GPS] Preload 时找不到物品 " + itemId));
	}

	private static void PreloadRecipe(int recipeId)
	{
		RecipeProto[] dataArray = ((ProtoSet<RecipeProto>)(object)LDB.recipes).dataArray;
		for (int i = 0; i < dataArray.Length; i++)
		{
			if (dataArray[i] != null && ((Proto)dataArray[i]).ID == recipeId)
			{
				try
				{
					dataArray[i].Preload(i);
					break;
				}
				catch (Exception ex)
				{
					GPSPlugin.Log.LogWarning((object)("[GPS] 配方 Preload 失败: " + ex.Message));
					break;
				}
			}
		}
	}
}
internal static class R
{
	private static readonly Dictionary<string, FieldInfo> cache = new Dictionary<string, FieldInfo>();

	internal static FieldInfo Field(Type t, params string[] names)
	{
		foreach (string text in names)
		{
			string key = t.FullName + "." + text;
			if (cache.TryGetValue(key, out var value))
			{
				if (value != null)
				{
					return value;
				}
				continue;
			}
			value = t.GetField(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			cache[key] = value;
			if (value != null)
			{
				return value;
			}
		}
		return null;
	}
}
public static class StationWindowPatches
{
	private static bool diagOpen;

	private static bool diagRefresh;

	[HarmonyPostfix]
	[HarmonyPatch(typeof(UIStationWindow), "_OnOpen")]
	private static void OnOpen(UIStationWindow __instance)
	{
		if (!diagOpen)
		{
			diagOpen = true;
			GPSPlugin.Log.LogInfo((object)"[GPS] 诊断:_OnOpen 命中");
		}
		try
		{
			StationUI.OnOpen(__instance);
		}
		catch (Exception ex)
		{
			GPSPlugin.Log.LogWarning((object)("[GPS] OnOpen 异常: " + ex.Message));
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(UIStationWindow), "RefreshTrans")]
	private static void RefreshTrans(UIStationWindow __instance, StationComponent station)
	{
		if (!diagRefresh)
		{
			diagRefresh = true;
			GPSPlugin.Log.LogInfo((object)("[GPS] 诊断:RefreshTrans 命中,station=" + ((station == null) ? "null" : ("entityId=" + station.entityId))));
		}
		try
		{
			StationUI.OnRefresh(__instance, station);
		}
		catch (Exception ex)
		{
			GPSPlugin.Log.LogWarning((object)("[GPS] RefreshTrans 异常: " + ex.Message));
		}
	}

	[HarmonyPatch(typeof(UIStationWindow), "_OnClose")]
	[HarmonyPostfix]
	private static void OnClose()
	{
		StationUI.Clear();
	}
}
public static class RecipeUnlockPatches
{
	[HarmonyPostfix]
	[HarmonyPatch(typeof(GameHistoryData), "Init")]
	private static void Init(GameHistoryData __instance)
	{
		Unlock(__instance);
	}

	[HarmonyPatch(typeof(GameHistoryData), "SetForNewGame")]
	[HarmonyPostfix]
	private static void SetForNewGame(GameHistoryData __instance)
	{
		Unlock(__instance);
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(GameHistoryData), "RecipeUnlocked")]
	private static void RecipeUnlocked(int recipeId, ref bool __result)
	{
		if (!__result && recipeId == 9601)
		{
			__result = true;
		}
	}

	private static void Unlock(GameHistoryData h)
	{
		if (h != null && h.recipeUnlocked != null)
		{
			h.recipeUnlocked.Add(9601);
		}
	}
}
public static class PickerRestrictPatches
{
	private static readonly FieldInfo fIndex = typeof(UIItemPicker).GetField("indexArray", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly FieldInfo fProto = typeof(UIItemPicker).GetField("protoArray", BindingFlags.Instance | BindingFlags.NonPublic);

	private static bool loggedRestrict;

	private static bool loggedSkip;

	[HarmonyPrefix]
	[HarmonyPatch(typeof(UIItemPicker), "RefreshIcons")]
	private static bool RefreshIcons(UIItemPicker __instance)
	{
		if (!ShouldRestrict(__instance))
		{
			return true;
		}
		if (fIndex == null || fProto == null)
		{
			return true;
		}
		if (!loggedRestrict)
		{
			loggedRestrict = true;
			GPSPlugin.Log.LogInfo((object)"[GPS] 物品选取器已限制为三种增产剂");
		}
		uint[] array = fIndex.GetValue(__instance) as uint[];
		ItemProto[] array2 = fProto.GetValue(__instance) as ItemProto[];
		if (array == null || array2 == null)
		{
			return true;
		}
		Array.Clear(array, 0, array.Length);
		Array.Clear(array2, 0, array2.Length);
		IconSet iconSet = GameMain.iconSet;
		if (iconSet == null || iconSet.itemIconIndex == null)
		{
			return false;
		}
		int[] array3 = new int[3] { 1141, 1142, 1143 };
		int num = 0;
		for (int i = 0; i < array3.Length; i++)
		{
			if (num >= array2.Length)
			{
				break;
			}
			if (num >= array.Length)
			{
				break;
			}
			ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(array3[i]);
			if (val != null)
			{
				array[num] = ((((Proto)val).ID >= 0 && ((Proto)val).ID < iconSet.itemIconIndex.Length) ? iconSet.itemIconIndex[((Proto)val).ID] : 0u);
				array2[num] = val;
				num++;
			}
		}
		return false;
	}

	private static bool ShouldRestrict(UIItemPicker picker)
	{
		if ((Object)(object)picker == (Object)null)
		{
			return false;
		}
		if (!loggedSkip)
		{
			loggedSkip = true;
			GPSPlugin.Log.LogInfo((object)("[GPS] 诊断:RefreshIcons 命中,onReturn=" + ((picker.onReturn == null) ? "null" : ((picker.onReturn.Target == null) ? "no-target" : picker.onReturn.Target.GetType().Name))));
		}
		if (StationUI.RestrictPicker)
		{
			return true;
		}
		try
		{
			Action<ItemProto> onReturn = picker.onReturn;
			if (onReturn != null)
			{
				object? target = onReturn.Target;
				UIStationStorage val = (UIStationStorage)((target is UIStationStorage) ? target : null);
				if ((Object)(object)val != (Object)null && val.station != null && StationUI.IsOurTower(val.station.entityId))
				{
					return true;
				}
			}
		}
		catch (Exception)
		{
		}
		if (!loggedSkip)
		{
			loggedSkip = true;
			GPSPlugin.Log.LogInfo((object)"[GPS] 物品选取器未命中限制条件(将显示全部物品)");
		}
		return false;
	}
}
public static class IconSetPatches
{
	[HarmonyPatch(typeof(IconSet), "Create")]
	[HarmonyPrefix]
	private static void Create()
	{
		try
		{
			Registry.FixupTextAndIcon();
			ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(9600);
			RecipeProto val2 = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(9601);
			GPSPlugin.Log.LogInfo((object)("[GPS] 图集创建前修正:item.icon=" + ((val != null && (Object)(object)val.iconSprite != (Object)null) ? "OK" : "null") + " recipe.icon=" + ((val2 != null && (Object)(object)val2.iconSprite != (Object)null) ? "OK" : "null") + " name=" + ((val == null) ? "null" : ((Proto)val).name)));
		}
		catch (Exception)
		{
		}
	}
}
[HarmonyPatch]
public static class FactorySprayPatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		yield return AccessTools.Method(typeof(FactorySystem), "GameTick", (Type[])null, (Type[])null);
		yield return AccessTools.Method(typeof(FactorySystem), "GameTickLabResearchMode", (Type[])null, (Type[])null);
	}

	[HarmonyPostfix]
	private static void Postfix(FactorySystem __instance)
	{
		BuildingSpray.Tick(__instance);
	}
}
internal static class BuildingSpray
{
	internal static int SprayCount;

	internal static int ScanCount;

	private static bool logged;

	internal static void Tick(FactorySystem fs)
	{
		//IL_0086: 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_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		if (fs == null)
		{
			return;
		}
		PlanetFactory factory = fs.factory;
		if (factory == null)
		{
			return;
		}
		int planetId = factory.planetId;
		int num = PlanetSpray.Level(planetId);
		if (num <= 0)
		{
			return;
		}
		AssemblerComponent[] assemblerPool = fs.assemblerPool;
		int num2;
		if (assemblerPool != null)
		{
			num2 = fs.assemblerCursor;
			if (num2 > assemblerPool.Length)
			{
				num2 = assemblerPool.Length;
			}
			for (int i = 1; i < num2; i++)
			{
				AssemblerComponent val = assemblerPool[i];
				if (val.id == i)
				{
					TopUp(planetId, val.served, val.incServed, num);
				}
			}
		}
		LabComponent[] labPool = fs.labPool;
		if (labPool == null)
		{
			return;
		}
		num2 = fs.labCursor;
		if (num2 > labPool.Length)
		{
			num2 = labPool.Length;
		}
		for (int i = 1; i < num2; i++)
		{
			LabComponent val2 = labPool[i];
			if (val2.id == i)
			{
				TopUp(planetId, val2.served, val2.incServed, num);
			}
		}
	}

	private static void TopUp(int planetId, int[] served, int[] incServed, int lvl)
	{
		if (served == null || incServed == null)
		{
			return;
		}
		int num = ((served.Length < incServed.Length) ? served.Length : incServed.Length);
		for (int i = 0; i < num; i++)
		{
			int num2 = served[i];
			if (num2 <= 0)
			{
				continue;
			}
			int num3 = num2 * lvl;
			if (incServed[i] >= num3)
			{
				continue;
			}
			ScanCount++;
			int num4 = (num3 - incServed[i]) / lvl;
			if (num4 > 0)
			{
				int num5 = PlanetSpray.Take(planetId, num4);
				if (num5 <= 0)
				{
					break;
				}
				incServed[i] += num5 * lvl;
				SprayCount += num5;
				if (!logged)
				{
					logged = true;
					GPSPlugin.Log.LogInfo((object)("[GPS] 建筑喷涂生效:planet=" + planetId + " 原料槽=" + i + " 数量=" + num2 + " 本次=" + num5));
				}
			}
		}
	}
}
internal static class StationUI
{
	private static UIStationWindow current;

	private static StationComponent currentStation;

	internal static bool RestrictPicker
	{
		get
		{
			if ((Object)(object)current == (Object)null || currentStation == null)
			{
				return false;
			}
			if (!((Component)current).gameObject.activeInHierarchy)
			{
				return false;
			}
			return IsOurTower(currentStation.entityId);
		}
	}

	internal static StationComponent GetStation(UIStationWindow win)
	{
		if ((Object)(object)win == (Object)null)
		{
			return null;
		}
		try
		{
			FieldInfo fieldInfo = R.Field(typeof(UIStationWindow), "_stationId");
			if (fieldInfo == null)
			{
				return null;
			}
			int num = Convert.ToInt32(fieldInfo.GetValue(win));
			if (num <= 0 || win.transport == null || win.transport.stationPool == null)
			{
				return null;
			}
			if (num >= win.transport.stationPool.Length)
			{
				return null;
			}
			StationComponent val = win.transport.stationPool[num];
			if (val == null || val.id != num)
			{
				return null;
			}
			return val;
		}
		catch (Exception)
		{
			return null;
		}
	}

	internal static bool IsOurTower(int entityId)
	{
		return IsOurTower((GameMain.localPlanet != null) ? GameMain.localPlanet.factory : null, entityId);
	}

	internal static bool IsOurTower(PlanetFactory f, int entityId)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		if (f == null || f.entityPool == null)
		{
			return false;
		}
		if (entityId <= 0 || entityId >= f.entityPool.Length)
		{
			return false;
		}
		EntityData val = f.entityPool[entityId];
		return val.protoId == 9600 || (Registry.ModelId > 0 && val.modelIndex == Registry.ModelId);
	}

	internal static void Clear()
	{
		current = null;
		currentStation = null;
	}

	internal static void OnOpen(UIStationWindow win)
	{
		current = win;
		currentStation = GetStation(win);
	}

	internal static void OnRefresh(UIStationWindow win, StationComponent sc)
	{
		current = win;
		currentStation = sc;
	}
}
public static class PlanetSpray
{
	internal sealed class Hub
	{
		public int ItemId;

		public int Level;

		public int PerItem;

		public int Remaining;

		public int Consumed;

		public int Debt;
	}

	private static readonly ConcurrentDictionary<int, Hub> hubs = new ConcurrentDictionary<int, Hub>();

	private static bool reported;

	internal static int ActiveHubCount
	{
		get
		{
			int num = 0;
			foreach (KeyValuePair<int, Hub> hub in hubs)
			{
				if (hub.Value != null && hub.Value.Level > 0)
				{
					num++;
				}
			}
			return num;
		}
	}

	internal static Hub ResolveHub(int planetId)
	{
		if (planetId >= 0 && hubs.TryGetValue(planetId, out var value) && value.Level > 0)
		{
			return value;
		}
		Hub hub = null;
		int num = 0;
		foreach (KeyValuePair<int, Hub> hub2 in hubs)
		{
			if (hub2.Value != null && hub2.Value.Level > 0)
			{
				hub = hub2.Value;
				num++;
			}
		}
		return (num == 1) ? hub : null;
	}

	internal static int Level(int planetId)
	{
		return ResolveHub(planetId)?.Level ?? 0;
	}

	internal static int Take(int planetId, int n)
	{
		Hub hub = ResolveHub(planetId);
		if (hub == null || n <= 0)
		{
			return 0;
		}
		return TakeQuota(hub, n);
	}

	private static int TakeQuota(Hub h, int n)
	{
		int i;
		for (i = 0; i < n; i++)
		{
			if (Interlocked.Decrement(ref h.Remaining) < 0)
			{
				Interlocked.Increment(ref h.Remaining);
				break;
			}
		}
		if (i > 0)
		{
			Interlocked.Add(ref h.Consumed, i);
		}
		return i;
	}

	internal static void Sync(PlanetFactory factory, List<StationComponent> towers)
	{
		if (factory == null)
		{
			return;
		}
		Hub orAdd = hubs.GetOrAdd(factory.planetId, (int param0) => new Hub());
		int num = 0;
		int num2 = 0;
		if (towers != null)
		{
			for (int num3 = 0; num3 < towers.Count; num3++)
			{
				StationStore[] storage = towers[num3].storage;
				if (storage == null)
				{
					continue;
				}
				for (int num4 = 0; num4 < storage.Length; num4++)
				{
					int itemId = storage[num4].itemId;
					if ((itemId == 1141 || itemId == 1142 || itemId == 1143) && storage[num4].count > 0)
					{
						if (num == 0)
						{
							num = itemId;
						}
						if (itemId == num)
						{
							num2 += storage[num4].count;
						}
					}
				}
			}
		}
		int num5 = 0;
		int num6 = 0;
		if (num != 0)
		{
			ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(num);
			if (val != null)
			{
				num5 = val.Ability;
				num6 = val.HpMax;
			}
		}
		if (num5 <= 0 || num6 <= 0)
		{
			orAdd.Level = 0;
			orAdd.Remaining = 0;
			orAdd.ItemId = 0;
			return;
		}
		int num7 = Interlocked.Exchange(ref orAdd.Consumed, 0);
		if (orAdd.ItemId != num)
		{
			orAdd.ItemId = num;
			orAdd.Debt = 0;
		}
		orAdd.Debt += num7;
		int num8 = orAdd.Debt / num6;
		orAdd.Debt -= num8 * num6;
		if (num8 > 0 && towers != null)
		{
			DeductItems(towers, num, num8);
		}
		int num9 = 0;
		if (towers != null)
		{
			for (int num3 = 0; num3 < towers.Count; num3++)
			{
				StationStore[] storage = towers[num3].storage;
				if (storage == null)
				{
					continue;
				}
				for (int num4 = 0; num4 < storage.Length; num4++)
				{
					if (storage[num4].itemId == num && storage[num4].count > 0)
					{
						num9 += storage[num4].count;
					}
				}
			}
		}
		orAdd.Level = num5;
		orAdd.PerItem = num6;
		int num10 = num9 * num6 - orAdd.Debt;
		if (num10 < 0)
		{
			num10 = 0;
		}
		Interlocked.Exchange(ref orAdd.Remaining, num10);
		if (!reported)
		{
			reported = true;
			GPSPlugin.Log.LogInfo((object)("[GPS] 全星球增殖已启用:planet=" + factory.planetId + " 增产剂=" + num + " 等级=" + num5 + " 每份可喷=" + num6 + " 库存=" + num9 + " 可用次数=" + num10));
		}
	}

	private static void DeductItems(List<StationComponent> towers, int itemId, int items)
	{
		for (int i = 0; i < towers.Count; i++)
		{
			if (items <= 0)
			{
				break;
			}
			StationStore[] storage = towers[i].storage;
			if (storage == null)
			{
				continue;
			}
			for (int j = 0; j < storage.Length; j++)
			{
				if (items <= 0)
				{
					break;
				}
				if (storage[j].itemId == itemId && storage[j].count > 0)
				{
					int num = Math.Min(items, storage[j].count);
					ref StationStore reference = ref storage[j];
					reference.count -= num;
					items -= num;
				}
			}
		}
	}
}
public static class SupplyManager
{
	public static void Tick()
	{
		GameData data = GameMain.data;
		if (data == null || data.factories == null)
		{
			return;
		}
		int num = data.factoryCount;
		if (num <= 0 || num > data.factories.Length)
		{
			num = data.factories.Length;
		}
		for (int i = 0; i < num; i++)
		{
			PlanetFactory val = data.factories[i];
			if (val == null || val.transport == null)
			{
				continue;
			}
			List<StationComponent> list = null;
			StationComponent[] stationPool = val.transport.stationPool;
			if (stationPool != null)
			{
				for (int j = 1; j < stationPool.Length; j++)
				{
					StationComponent val2 = stationPool[j];
					if (val2 != null && val2.id == j && val2.storage != null && StationUI.IsOurTower(val, val2.entityId) && HasDemandProliferator(val2))
					{
						if (list == null)
						{
							list = new List<StationComponent>();
						}
						list.Add(val2);
					}
				}
			}
			PlanetSpray.Sync(val, list);
		}
	}

	private static bool HasDemandProliferator(StationComponent sc)
	{
		StationStore[] storage = sc.storage;
		if (storage == null)
		{
			return false;
		}
		for (int i = 0; i < storage.Length; i++)
		{
			int itemId = storage[i].itemId;
			if ((itemId == 1141 || itemId == 1142 || itemId == 1143) && storage[i].count > 0)
			{
				return true;
			}
		}
		return false;
	}
}