Decompiled source of VoidFleetCap v1.3.5

FleetCap.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace VoidFleetCap;

[BepInPlugin("aimod.VoidFleetCap", "VoidFleetCap", "1.3.5")]
public class Plugin : BaseUnityPlugin
{
	public const string GUID = "aimod.VoidFleetCap";

	public const string NAME = "VoidFleetCap";

	public const string VERSION = "1.3.5";

	internal static ManualLogSource Log;

	internal const int Slots = 48;

	private int tick;

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		try
		{
			Install();
		}
		catch (Exception ex)
		{
			Log.LogError((object)("install failed: " + ex));
		}
	}

	private void Install()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Expected O, but got Unknown
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Expected O, but got Unknown
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Expected O, but got Unknown
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Expected O, but got Unknown
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Expected O, but got Unknown
		Harmony h = new Harmony("aimod.VoidFleetCap");
		Type t = typeof(CombatModuleComponent);
		HarmonyMethod prep = new HarmonyMethod(typeof(Patches).GetMethod("Prep"));
		HarmonyMethod finish = new HarmonyMethod(typeof(Patches).GetMethod("Finish"));
		HarmonyMethod clamp = new HarmonyMethod(typeof(Patches).GetMethod("Clamp"));
		P("GameTick/clamp", delegate
		{
			h.Patch((MethodBase)t.GetMethod("GameTick", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), clamp, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		});
		P("Import", delegate
		{
			h.Patch((MethodBase)t.GetMethod("Import", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (HarmonyMethod)null, finish, (HarmonyMethod)null, (HarmonyMethod)null);
		});
		try
		{
			MethodInfo method = t.GetMethod("AutoReplenishAllFleets", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				h.Patch((MethodBase)method, new HarmonyMethod(typeof(Patches).GetMethod("ReplenishPrep")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method2 = t.GetMethod("ReplenishFleet", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method2 != null)
			{
				h.Patch((MethodBase)method2, new HarmonyMethod(typeof(Patches).GetMethod("ReplenishIndex")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("replenish patch: " + ex.Message));
		}
		MethodInfo[] methods = t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (!(methodInfo.Name != "Setup"))
			{
				MethodInfo mm = methodInfo;
				ParameterInfo[] parameters = methodInfo.GetParameters();
				string text = ((parameters.Length != 0) ? parameters[0].ParameterType.Name : "?");
				P("Setup(" + text + ")", delegate
				{
					h.Patch((MethodBase)mm, prep, finish, (HarmonyMethod)null, (HarmonyMethod)null);
				});
			}
		}
		P("UIMechaWindow._OnCreate/pageButtons", delegate
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			h.Patch((MethodBase)AccessTools.Method(typeof(UIMechaWindow), "_OnCreate", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches).GetMethod("PageButtons")), (HarmonyMethod)null, (HarmonyMethod)null);
		});
		P("TechProto.GetHashNeeded", delegate
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			h.Patch((MethodBase)AccessTools.Method(typeof(TechProto), "GetHashNeeded", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches).GetMethod("HashNeeded")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		});
		P("UIZS_FleetPanel.RefreshCompletely/entries", delegate
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			h.Patch((MethodBase)AccessTools.Method(typeof(UIZS_FleetPanel), "RefreshCompletely", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches).GetMethod("ZSFleetEntries")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		});
		Log.LogInfo((object)("1.3.5 installed, slots=" + 48 + " fleetTechMax=23 droneRateMax=20 droneDurabilityMax=30"));
		AppDomain.CurrentDomain.AssemblyLoad += delegate(object s, AssemblyLoadEventArgs e)
		{
			try
			{
				TcfvDroplets.Attach(e.LoadedAssembly, h);
			}
			catch (Exception)
			{
			}
		};
		Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
		foreach (Assembly asm in assemblies)
		{
			try
			{
				TcfvDroplets.Attach(asm, h);
			}
			catch (Exception)
			{
			}
		}
	}

	private static void P(string label, Action a)
	{
		try
		{
			a();
			Log.LogInfo((object)("  patched " + label));
		}
		catch (Exception ex)
		{
			Log.LogError((object)("  patch " + label + " failed: " + ex.Message));
		}
	}

	private void Update()
	{
		if (++tick % 60 != 0)
		{
			return;
		}
		try
		{
			TechCap.Apply();
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("tech: " + ex.Message));
		}
		try
		{
			FleetSync.Apply();
		}
		catch (Exception ex2)
		{
			Log.LogWarning((object)("sync: " + ex2.Message));
		}
	}
}
internal static class Patches
{
	public static void Prep(CombatModuleComponent __instance)
	{
		Cap.Shrink(__instance, 8);
	}

	public static void Finish(CombatModuleComponent __instance)
	{
		Cap.Expand(__instance);
	}

	public static void Clamp(CombatModuleComponent __instance)
	{
		Cap.Clamp(__instance);
	}

	public static void DropletGuard()
	{
		TcfvDroplets.Ensure();
	}

	public static void PageButtons(object __instance)
	{
		PageExpand.Run(__instance);
	}

	public static void ZSFleetEntries(UIZS_FleetPanel __instance)
	{
		ZSPanel.Fill(__instance);
	}

	public static void ReplenishPrep(CombatModuleComponent __instance)
	{
		try
		{
			Cap.Expand(__instance);
			Cap.Clamp(__instance);
		}
		catch (Exception)
		{
		}
	}

	public static bool ReplenishIndex(CombatModuleComponent __instance, int fleetIndex)
	{
		try
		{
			object value = AccessTools.Field(typeof(CombatModuleComponent), "moduleFleets").GetValue(__instance);
			if (!(value is Array array))
			{
				return true;
			}
			return fleetIndex >= 0 && fleetIndex < array.Length;
		}
		catch (Exception)
		{
			return true;
		}
	}

	public static bool HashNeeded(TechProto __instance, int levelRequest, ref long __result)
	{
		try
		{
			if (__instance == null)
			{
				return true;
			}
			if (!TechCap.BaseHash.TryGetValue(((Proto)__instance).ID, out var value))
			{
				return true;
			}
			if (!TechCap.BaseLevel.TryGetValue(((Proto)__instance).ID, out var value2))
			{
				return true;
			}
			int maxLevel = __instance.MaxLevel;
			int num = levelRequest;
			if (num > maxLevel)
			{
				num = maxLevel;
			}
			if (num < value2)
			{
				num = value2;
			}
			if (num <= value2)
			{
				__result = value;
				return false;
			}
			if (TechCap.Points.TryGetValue(((Proto)__instance).ID, out var value3) && value3 > 0)
			{
				double num2 = 1000000.0 * Math.Pow((double)num / 20.0, 3.0);
				long num3 = (long)Math.Round(num2 * 3600.0 / (double)value3);
				if (num3 < value)
				{
					num3 = value;
				}
				__result = num3;
				return false;
			}
			double num4 = (double)num / (double)value2;
			__result = (long)Math.Round((double)value * num4 * num4);
			return false;
		}
		catch (Exception)
		{
			return true;
		}
	}
}
internal static class Cap
{
	private static FieldInfo ff;

	private static FieldInfo fp;

	private static FieldInfo fCount;

	private static FieldInfo fProto;

	private static FieldInfo fIsSpace;

	private static MethodInfo mCreate;

	private static MethodInfo mSet2;

	private static MethodInfo mSet3;

	private static Type mSet3Type;

	private static FieldInfo fGround;

	private static FieldInfo fSmall;

	private static FieldInfo fLarge;

	private static bool logged;

	internal static int Slots => 48;

	private static void Fields()
	{
		if (ff != null)
		{
			return;
		}
		ff = typeof(CombatModuleComponent).GetField("moduleFleets", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		fp = typeof(CombatModuleComponent).GetField("moduleFleetPoses", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		fCount = typeof(CombatModuleComponent).GetField("fleetCount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		fIsSpace = typeof(CombatModuleComponent).GetField("isSpace", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (ff == null)
		{
			return;
		}
		Type elementType = ff.FieldType.GetElementType();
		fProto = elementType.GetField("protoId", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		mCreate = elementType.GetMethod("Create", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(int) }, null);
		MethodInfo[] methods = elementType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (!(methodInfo.Name != "SetItemId"))
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length == 2)
				{
					mSet2 = methodInfo;
				}
				else if (parameters.Length == 3)
				{
					mSet3 = methodInfo;
					mSet3Type = parameters[2].ParameterType;
				}
			}
		}
		fGround = typeof(ItemProto).GetField("kFighterGroundIds", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		fSmall = typeof(ItemProto).GetField("kFighterSpaceSmallIds", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		fLarge = typeof(ItemProto).GetField("kFighterSpaceLargeIds", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
	}

	internal static bool IsMecha(CombatModuleComponent c)
	{
		try
		{
			if (c == null || GameMain.mainPlayer == null)
			{
				return false;
			}
			Mecha mecha = GameMain.mainPlayer.mecha;
			if (mecha == null)
			{
				return false;
			}
			return c == mecha.groundCombatModule || c == mecha.spaceCombatModule;
		}
		catch (Exception)
		{
			return false;
		}
	}

	internal static void Shrink(CombatModuleComponent c, int len)
	{
		try
		{
			Fields();
			if (c != null && !(ff == null))
			{
				ResizeTo(ff, c, len);
				ResizeTo(fp, c, len);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("shrink: " + ex.Message));
		}
	}

	internal static void Expand(CombatModuleComponent c)
	{
		try
		{
			Fields();
			if (c != null && !(ff == null) && !(fp == null) && IsMecha(c))
			{
				ResizeTo(ff, c, Slots);
				ResizeTo(fp, c, Slots);
				FillFleets(c);
				FillPoses(c);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("expand: " + ex.Message));
		}
	}

	private static void FillFleets(CombatModuleComponent c)
	{
		if (!(ff.GetValue(c) is Array array) || fProto == null)
		{
			return;
		}
		object value = array.GetValue(0);
		if (value == null)
		{
			return;
		}
		int num = (int)fProto.GetValue(value);
		if (num == 0)
		{
			return;
		}
		bool space = fIsSpace != null && (bool)fIsSpace.GetValue(c);
		int ground = IdOf(fGround);
		int small = IdOf(fSmall);
		int large = IdOf(fLarge);
		int num2 = 0;
		for (int i = 1; i < array.Length; i++)
		{
			object value2 = array.GetValue(i);
			if (value2 != null && (int)fProto.GetValue(value2) == 0)
			{
				object obj = Make(num, space, ground, small, large);
				if (obj != null)
				{
					array.SetValue(obj, i);
					num2++;
				}
			}
		}
		if (!logged)
		{
			logged = true;
			Plugin.Log.LogInfo((object)("slots ready: len=" + array.Length + " made=" + num2));
		}
	}

	private static object Make(int protoId, bool space, int ground, int small, int large)
	{
		if (mCreate == null)
		{
			return null;
		}
		object obj = mCreate.Invoke(null, new object[1] { protoId });
		try
		{
			if (space)
			{
				if (mSet3 != null && small > 0)
				{
					mSet3.Invoke(obj, new object[3]
					{
						-1,
						small,
						Size(0)
					});
				}
				else if (mSet2 != null && small > 0)
				{
					mSet2.Invoke(obj, new object[2] { -1, small });
				}
				if (mSet3 != null && large > 0)
				{
					mSet3.Invoke(obj, new object[3]
					{
						-1,
						large,
						Size(1)
					});
				}
			}
			else if (ground > 0)
			{
				if (mSet2 != null)
				{
					mSet2.Invoke(obj, new object[2] { -1, ground });
				}
				else if (mSet3 != null)
				{
					mSet3.Invoke(obj, new object[3]
					{
						-1,
						ground,
						Size(0)
					});
				}
			}
		}
		catch (Exception)
		{
		}
		return obj;
	}

	private static object Size(int v)
	{
		if (mSet3Type == null)
		{
			return v;
		}
		try
		{
			return Enum.ToObject(mSet3Type, v);
		}
		catch (Exception)
		{
			return v;
		}
	}

	private static int IdOf(FieldInfo f)
	{
		try
		{
			if (f == null)
			{
				return 0;
			}
			if (!(f.GetValue(null) is int[] array) || array.Length == 0)
			{
				return 0;
			}
			return array[0];
		}
		catch (Exception)
		{
			return 0;
		}
	}

	private static void FillPoses(CombatModuleComponent c)
	{
		if (!(fp.GetValue(c) is Array { Length: >8 } array))
		{
			return;
		}
		for (int i = 8; i < array.Length; i++)
		{
			object value = array.GetValue(i % 8);
			if (value != null)
			{
				array.SetValue(value, i);
			}
		}
	}

	internal static void Clamp(CombatModuleComponent c)
	{
		try
		{
			Fields();
			if (c != null && !(ff == null) && !(fCount == null) && ff.GetValue(c) is Array array)
			{
				int num = (int)fCount.GetValue(c);
				if (num > array.Length)
				{
					fCount.SetValue(c, array.Length);
				}
			}
		}
		catch (Exception)
		{
		}
	}

	private static void ResizeTo(FieldInfo f, object o, int len)
	{
		if (f.GetValue(o) is Array array && array.Length != len)
		{
			Type elementType = array.GetType().GetElementType();
			int length = Math.Min(array.Length, len);
			Array array2 = Array.CreateInstance(elementType, len);
			Array.Copy(array, array2, length);
			f.SetValue(o, array2);
		}
	}
}
internal static class TcfvDroplets
{
	private static bool patched;

	private static Type type;

	private static FieldInfo fPool;

	private static FieldInfo fLen;

	private static FieldInfo fList;

	internal static void Attach(Assembly asm, Harmony h)
	{
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Expected O, but got Unknown
		if (patched || asm == null)
		{
			return;
		}
		string name;
		try
		{
			name = asm.GetName().Name;
		}
		catch (Exception)
		{
			return;
		}
		if (name != "DSP_Battle")
		{
			return;
		}
		Type type = asm.GetType("DSP_Battle.Droplets");
		if (type == null)
		{
			return;
		}
		TcfvDroplets.type = type;
		fPool = type.GetField("dropletPool", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		fLen = type.GetField("dropletArrayLength", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		fList = type.GetField("warpRushCharge", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		Ensure();
		MethodInfo methodInfo = null;
		MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo2 in methods)
		{
			if (methodInfo2.Name == "GameData_GameTick")
			{
				methodInfo = methodInfo2;
				break;
			}
		}
		if (methodInfo == null)
		{
			Plugin.Log.LogWarning((object)"DSP_Battle.Droplets: GameData_GameTick not found");
			return;
		}
		h.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Patches).GetMethod("DropletGuard")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		patched = true;
		Plugin.Log.LogInfo((object)"  patched DSP_Battle.Droplets.GameData_GameTick + dropletPool");
	}

	internal static void Ensure()
	{
		try
		{
			if (type == null || fPool == null || !(fPool.GetValue(null) is Array array))
			{
				return;
			}
			int num = 144;
			if (array.Length >= num)
			{
				return;
			}
			Type elementType = array.GetType().GetElementType();
			ConstructorInfo constructor = elementType.GetConstructor(new Type[1] { typeof(int) });
			Array array2 = Array.CreateInstance(elementType, num);
			Array.Copy(array, array2, array.Length);
			for (int i = array.Length; i < num; i++)
			{
				object value = ((constructor != null) ? constructor.Invoke(new object[1] { i }) : Activator.CreateInstance(elementType));
				array2.SetValue(value, i);
			}
			fPool.SetValue(null, array2);
			if (fLen != null)
			{
				fLen.SetValue(null, num);
			}
			if (fList != null && fList.GetValue(null) is IList list)
			{
				while (list.Count < num)
				{
					list.Add(0);
				}
			}
			Plugin.Log.LogInfo((object)("dropletPool expanded: " + array.Length + " -> " + num));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("dropletPool: " + ex.Message));
		}
	}
}
internal static class FleetSync
{
	internal const int VanillaLevel = 7;

	internal const int VanillaFleets = 8;

	private static int lastG = -1;

	private static int lastS = -1;

	private static FieldInfo ff;

	private static FieldInfo fFleetId;

	internal static void Apply()
	{
		if (GameMain.mainPlayer != null)
		{
			Mecha mecha = GameMain.mainPlayer.mecha;
			if (mecha != null)
			{
				Sync(mecha.groundCombatModule, TechCap.LevelOf("地面编队扩容"), "ground", ref lastG);
				Sync(mecha.spaceCombatModule, TechCap.LevelOf("太空编队扩容"), "space", ref lastS);
			}
		}
	}

	internal static int Pages(int squads)
	{
		return (squads - 1) / 4 + 1;
	}

	private static void Sync(CombatModuleComponent c, int level, string tag, ref int last)
	{
		if (c == null)
		{
			return;
		}
		Cap.Expand(c);
		if (level <= 7)
		{
			if (level != last)
			{
				Plugin.Log.LogInfo((object)(tag + " vanilla range, fleetCount=" + c.fleetCount + " (tech Lv" + level + ", " + Pages(c.fleetCount) + " pages)"));
			}
			last = level;
			return;
		}
		int num = 8 + 2 * (level - 7);
		if (num > 48)
		{
			num = 48;
		}
		if (num < 1)
		{
			num = 1;
		}
		int fleetCount = c.fleetCount;
		if (fleetCount != num)
		{
			if (fleetCount > num)
			{
				int num2 = ActiveFleets(c, num);
				if (num2 > 0)
				{
					if (level != last)
					{
						Plugin.Log.LogInfo((object)(tag + " fleetCount=" + fleetCount + " (tech Lv" + level + ", want " + num + ", " + num2 + " launched, keep)"));
					}
					last = level;
					return;
				}
			}
			c.fleetCount = num;
			Plugin.Log.LogInfo((object)(tag + " fleetCount: " + fleetCount + " -> " + num + " (tech Lv" + level + ", " + Pages(num) + " pages)"));
		}
		else if (level != last)
		{
			Plugin.Log.LogInfo((object)(tag + " fleetCount=" + fleetCount + " (tech Lv" + level + ", " + Pages(num) + " pages)"));
		}
		last = level;
	}

	private static int ActiveFleets(CombatModuleComponent c, int from)
	{
		try
		{
			if (ff == null)
			{
				ff = typeof(CombatModuleComponent).GetField("moduleFleets", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (ff == null)
			{
				return 0;
			}
			if (!(ff.GetValue(c) is Array array))
			{
				return 0;
			}
			int num = 0;
			for (int i = from; i < array.Length; i++)
			{
				object value = array.GetValue(i);
				if (value != null)
				{
					if (fFleetId == null)
					{
						fFleetId = value.GetType().GetField("fleetId", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					}
					if (!(fFleetId == null) && (int)fFleetId.GetValue(value) != 0)
					{
						num++;
					}
				}
			}
			return num;
		}
		catch (Exception)
		{
			return 0;
		}
	}
}
internal static class PageExpand
{
	internal const int Need = 12;

	internal static void Run(object window)
	{
		try
		{
			if (window == null)
			{
				return;
			}
			Type type = window.GetType();
			FieldInfo field = type.GetField("fleetPageButtons", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo field2 = type.GetField("fleetPageButton", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null || field2 == null)
			{
				return;
			}
			Array array = field.GetValue(window) as Array;
			object? value = field2.GetValue(window);
			Component val = (Component)((value is Component) ? value : null);
			if (array == null || (Object)(object)val == (Object)null || array.Length >= 12)
			{
				return;
			}
			Type elementType = array.GetType().GetElementType();
			Array array2 = Array.CreateInstance(elementType, 12);
			Array.Copy(array, array2, array.Length);
			Transform parent = val.transform.parent;
			for (int i = array.Length; i < 12; i++)
			{
				Component val2 = Object.Instantiate<Component>(val, parent);
				if ((Object)(object)val2 != (Object)null)
				{
					array2.SetValue(val2, i);
				}
			}
			field.SetValue(window, array2);
			Plugin.Log.LogInfo((object)("fleet page buttons: " + array.Length + " -> " + 12));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("pageButtons: " + ex.Message));
		}
	}
}
internal static class ZSPanel
{
	internal static void Fill(UIZS_FleetPanel p)
	{
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Expected O, but got Unknown
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Expected O, but got Unknown
		try
		{
			if ((Object)(object)p == (Object)null)
			{
				return;
			}
			Type typeFromHandle = typeof(UIZS_FleetPanel);
			FieldInfo fieldInfo = AccessTools.Field(typeFromHandle, "mecha");
			object obj = ((fieldInfo != null) ? fieldInfo.GetValue(p) : null);
			if (obj != null)
			{
				Type type = obj.GetType();
				CombatModuleComponent val = (CombatModuleComponent)AccessTools.Field(type, "groundCombatModule").GetValue(obj);
				CombatModuleComponent val2 = (CombatModuleComponent)AccessTools.Field(type, "spaceCombatModule").GetValue(obj);
				int num = 4;
				if (val != null && val.fleetCount > num)
				{
					num = val.fleetCount;
				}
				if (val2 != null && val2.fleetCount > num)
				{
					num = val2.fleetCount;
				}
				if (num > 48)
				{
					num = 48;
				}
				FillOne(typeFromHandle, p, "gFleetEntries", "groundFleetEntry", val, num);
				FillOne(typeFromHandle, p, "sFleetEntries", "SpaceFleetEntry", val2, num);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("zsPanel: " + ex.Message));
		}
	}

	private static void FillOne(Type t, UIZS_FleetPanel p, string listName, string tplName, CombatModuleComponent mod, int want)
	{
		FieldInfo fieldInfo = AccessTools.Field(t, listName);
		FieldInfo fieldInfo2 = AccessTools.Field(t, tplName);
		if (fieldInfo == null || fieldInfo2 == null || mod == null)
		{
			return;
		}
		IList list = fieldInfo.GetValue(p) as IList;
		object? value = fieldInfo2.GetValue(p);
		UIZS_FleetEntry val = (UIZS_FleetEntry)((value is UIZS_FleetEntry) ? value : null);
		if (list == null || (Object)(object)val == (Object)null)
		{
			return;
		}
		int num = 0;
		while (list.Count > want)
		{
			int index = list.Count - 1;
			object? obj = list[index];
			UIZS_FleetEntry val2 = (UIZS_FleetEntry)((obj is UIZS_FleetEntry) ? obj : null);
			list.RemoveAt(index);
			if ((Object)(object)val2 != (Object)null)
			{
				try
				{
					Object.Destroy((Object)(object)((Component)val2).gameObject);
				}
				catch (Exception)
				{
				}
			}
		}
		while (list.Count < want)
		{
			int count = list.Count;
			UIZS_FleetEntry val3 = Object.Instantiate<UIZS_FleetEntry>(val, ((Component)val).transform.parent);
			if ((Object)(object)val3 == (Object)null)
			{
				break;
			}
			((ManualBehaviour)val3)._Create();
			val3.fleetIndex = count;
			val3.fleetProtoId = ((count < mod.moduleFleets.Length) ? mod.moduleFleets[count].protoId : 0);
			val3.fleetPanel = p;
			try
			{
				((ManualBehaviour)val3)._Init((object)GameMain.data);
			}
			catch (Exception)
			{
			}
			list.Add(val3);
			num++;
		}
		if (num > 0)
		{
			Plugin.Log.LogInfo((object)(listName + " entries: +" + num + " -> " + list.Count));
		}
	}
}
internal static class TechCap
{
	private struct Target
	{
		public string Name;

		public int Tier;

		public int Max;
	}

	private static readonly Target[] Targets = new Target[4]
	{
		new Target
		{
			Name = "地面编队扩容",
			Tier = 7,
			Max = 23
		},
		new Target
		{
			Name = "太空编队扩容",
			Tier = 7,
			Max = 23
		},
		new Target
		{
			Name = "战斗无人机射速",
			Tier = 5,
			Max = 20
		},
		new Target
		{
			Name = "战斗无人机耐久",
			Tier = 5,
			Max = 30
		}
	};

	internal static readonly Dictionary<int, long> BaseHash = new Dictionary<int, long>();

	internal static readonly Dictionary<int, int> BaseLevel = new Dictionary<int, int>();

	internal static readonly Dictionary<int, int> Points = new Dictionary<int, int>();

	private static readonly Dictionary<string, TechProto> cache = new Dictionary<string, TechProto>();

	private static bool logged;

	internal static TechProto Find(string name, int tier)
	{
		TechProto[] array = (((Object)(object)LDB.techs != (Object)null) ? ((ProtoSet<TechProto>)(object)LDB.techs).dataArray : null);
		if (array == null)
		{
			return null;
		}
		TechProto val = null;
		TechProto[] array2 = array;
		foreach (TechProto val2 in array2)
		{
			if (val2 != null && !(((Proto)val2).name != name))
			{
				if (val2.Level == tier)
				{
					return val2;
				}
				if (val == null || val2.Level > val.Level)
				{
					val = val2;
				}
			}
		}
		return val;
	}

	private static Target TargetOf(string name)
	{
		Target[] targets = Targets;
		for (int i = 0; i < targets.Length; i++)
		{
			Target result = targets[i];
			if (result.Name == name)
			{
				return result;
			}
		}
		return new Target
		{
			Name = name,
			Tier = 7,
			Max = 23
		};
	}

	internal static TechProto Of(string name)
	{
		if (cache.TryGetValue(name, out var value) && value != null)
		{
			return value;
		}
		value = Find(name, TargetOf(name).Tier);
		if (value != null)
		{
			cache[name] = value;
		}
		return value;
	}

	internal static int IdOf(string name)
	{
		return ((Proto)(Of(name)?)).ID ?? 0;
	}

	internal static int LevelOf(string name)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		if (GameMain.history == null)
		{
			return -1;
		}
		TechProto val = Of(name);
		if (val == null)
		{
			return -1;
		}
		if (!GameMain.history.techStates.TryGetValue(((Proto)val).ID, out var value))
		{
			return 0;
		}
		return value.curLevel;
	}

	internal static void Apply()
	{
		//IL_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0508: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)LDB.techs == (Object)null || ((ProtoSet<TechProto>)(object)LDB.techs).dataArray == null)
		{
			return;
		}
		GameHistoryData history = GameMain.history;
		if (history == null)
		{
			return;
		}
		List<string> list = new List<string>();
		Target[] targets = Targets;
		for (int i = 0; i < targets.Length; i++)
		{
			Target target = targets[i];
			TechProto val = Find(target.Name, target.Tier);
			if (val == null)
			{
				list.Add(target.Name + ":NOTFOUND");
				continue;
			}
			if (val.Level != target.Tier)
			{
				string[] obj = new string[6] { target.Name, ":TIERMISS(want", null, null, null, null };
				int tier = target.Tier;
				obj[2] = tier.ToString();
				obj[3] = ",got";
				obj[4] = val.Level.ToString();
				obj[5] = ")";
				list.Add(string.Concat(obj));
			}
			if (!BaseHash.ContainsKey(((Proto)val).ID))
			{
				int num = Math.Max(1, val.Level);
				BaseLevel[((Proto)val).ID] = num;
				BaseHash[((Proto)val).ID] = val.GetHashNeeded(num);
				int num2 = 0;
				if (val.ItemPoints != null)
				{
					int[] itemPoints = val.ItemPoints;
					foreach (int num3 in itemPoints)
					{
						if (num3 > num2)
						{
							num2 = num3;
						}
					}
				}
				Points[((Proto)val).ID] = num2;
			}
			if (val.MaxLevel != target.Max)
			{
				val.MaxLevel = target.Max;
			}
			if (history.techStates != null && history.techStates.TryGetValue(((Proto)val).ID, out var value))
			{
				bool flag = false;
				if (value.maxLevel != target.Max)
				{
					value.maxLevel = target.Max;
					flag = true;
				}
				if (value.curLevel > target.Max)
				{
					value.curLevel = target.Max;
					flag = true;
				}
				if (flag)
				{
					history.techStates[((Proto)val).ID] = value;
				}
			}
			list.Add(target.Name + ":id" + ((Proto)val).ID + "/Lv" + val.Level + "/max" + val.MaxLevel + "/base" + BaseHash[((Proto)val).ID] + "@L" + BaseLevel[((Proto)val).ID] + "/pts" + (Points.ContainsKey(((Proto)val).ID) ? Points[((Proto)val).ID] : (-1)) + "/h" + val.GetHashNeeded(val.Level) + "->" + val.GetHashNeeded(target.Max) + "/cur" + CurLevel(((Proto)val).ID));
		}
		try
		{
			int num4 = 0;
			TechProto[] dataArray = ((ProtoSet<TechProto>)(object)LDB.techs).dataArray;
			foreach (TechProto val2 in dataArray)
			{
				if (val2 == null)
				{
					continue;
				}
				bool flag2 = false;
				Target[] targets2 = Targets;
				for (int l = 0; l < targets2.Length; l++)
				{
					Target target2 = targets2[l];
					if (target2.Name == ((Proto)val2).name && target2.Tier == val2.Level)
					{
						flag2 = true;
						break;
					}
				}
				if (!flag2 && history.techStates != null && history.techStates.TryGetValue(((Proto)val2).ID, out var value2) && value2.maxLevel > val2.MaxLevel)
				{
					value2.maxLevel = val2.MaxLevel;
					if (value2.curLevel > val2.MaxLevel)
					{
						value2.curLevel = val2.MaxLevel;
					}
					history.techStates[((Proto)val2).ID] = value2;
					if (num4 < 12)
					{
						Plugin.Log.LogInfo((object)("repair tech state: " + ((Proto)val2).name + " id" + ((Proto)val2).ID + " max " + value2.maxLevel + " cur " + value2.curLevel));
					}
					num4++;
				}
			}
			if (num4 > 0)
			{
				Plugin.Log.LogInfo((object)("repair tech state: " + num4 + " techs clamped back to vanilla max"));
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("repair: " + ex.Message));
		}
		if (!logged)
		{
			logged = true;
			Plugin.Log.LogInfo((object)("tech: " + string.Join(" | ", list.ToArray())));
			DumpLevels("地面编队扩容");
			DumpLevels("太空编队扩容");
			DumpLevels("战斗无人机射速");
			DumpLevels("战斗无人机耐久");
		}
	}

	private static string CurLevel(int id)
	{
		if (GameMain.history != null && GameMain.history.techStates.TryGetValue(id, out var value))
		{
			return value.curLevel + "/" + value.maxLevel;
		}
		return "?";
	}

	private static void DumpLevels(string name)
	{
		TechProto val = Of(name);
		if (val == null)
		{
			Plugin.Log.LogInfo((object)("levels " + name + ": NOTFOUND"));
			return;
		}
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.Append("levels ").Append(name).Append(" id")
			.Append(((Proto)val).ID)
			.Append(" max")
			.Append(val.MaxLevel)
			.Append(": ");
		int num = Math.Max(1, val.Level);
		int num2 = Math.Min(val.MaxLevel, num + 30);
		for (int i = num; i <= num2; i++)
		{
			stringBuilder.Append(i).Append("=").Append(val.GetHashNeeded(i));
			if (i != num2)
			{
				stringBuilder.Append(", ");
			}
		}
		Plugin.Log.LogInfo((object)stringBuilder.ToString());
	}
}