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;
}
}