using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CommonAPI;
using CommonAPI.Systems.ModLocalization;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;
using xiaoye97;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace StackingEnhancement;
[BepInPlugin("com.komonad.dsp.stackingenhancement", "堆叠增强", "0.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[CommonAPISubmoduleDependency(new string[] { "LocalizationModule", "ProtoRegistry" })]
public class Plugin : BaseUnityPlugin
{
private static class StationWindowFields
{
public static readonly FieldInfo EventLock = AccessTools.Field(typeof(UIStationWindow), "event_lock");
public static readonly FieldInfo Transport = AccessTools.Field(typeof(UIStationWindow), "transport");
public static readonly FieldInfo StationId = AccessTools.Field(typeof(UIStationWindow), "_stationId");
public static readonly FieldInfo MinPilerSlider = AccessTools.Field(typeof(UIStationWindow), "minPilerSlider");
public static readonly FieldInfo MinPilerSliderFillImage = AccessTools.Field(typeof(UIStationWindow), "minPilerSliderFillImage");
public static readonly FieldInfo MinPilerValue = AccessTools.Field(typeof(UIStationWindow), "minPilerValue");
public static readonly FieldInfo TechPilerCheck = AccessTools.Field(typeof(UIStationWindow), "techPilerCheck");
}
private static class StationInspectorFields
{
public static readonly FieldInfo EventLock = AccessTools.Field(typeof(UIControlPanelStationInspector), "event_lock");
public static readonly FieldInfo Transport = AccessTools.Field(typeof(UIControlPanelStationInspector), "transport");
public static readonly FieldInfo StationId = AccessTools.Field(typeof(UIControlPanelStationInspector), "_stationId");
public static readonly FieldInfo MinPilerSlider = AccessTools.Field(typeof(UIControlPanelStationInspector), "minPilerSlider");
public static readonly FieldInfo MinPilerSliderFillImage = AccessTools.Field(typeof(UIControlPanelStationInspector), "minPilerSliderFillImage");
public static readonly FieldInfo MinPilerValue = AccessTools.Field(typeof(UIControlPanelStationInspector), "minPilerValue");
public static readonly FieldInfo TechPilerCheck = AccessTools.Field(typeof(UIControlPanelStationInspector), "techPilerCheck");
}
private static class CargoContainerFields
{
public static readonly FieldInfo CargoPool = AccessTools.Field(typeof(CargoContainer), "cargoPool");
public static readonly FieldInfo Cursor = AccessTools.Field(typeof(CargoContainer), "cursor");
public static readonly FieldInfo PoolCapacity = AccessTools.Field(typeof(CargoContainer), "poolCapacity");
public static readonly FieldInfo CargoMatInst = AccessTools.Field(typeof(CargoContainer), "cargoMatInst");
}
private static class CargoContainerMethods
{
public static readonly MethodInfo Expand2x = AccessTools.Method(typeof(CargoContainer), "Expand2x", (Type[])null, (Type[])null);
}
[HarmonyPatch]
private static class GameDataPatch
{
[HarmonyPostfix]
[HarmonyPatch(typeof(GameData), "SetForNewGame")]
private static void SetForNewGamePostfix(GameData __instance)
{
EnsureTechStates(__instance?.history);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(GameData), "Import")]
private static void ImportPostfix(GameData __instance)
{
EnsureTechStates(__instance?.history);
}
}
[HarmonyPatch(typeof(UIStationWindow))]
private static class UIStationWindowPatch
{
[HarmonyPostfix]
[HarmonyPatch("OnStationIdChange")]
private static void OnStationIdChangePostfix(UIStationWindow __instance)
{
RefreshPilerUi(__instance);
}
[HarmonyPrefix]
[HarmonyPatch("OnMinPilerValueChange")]
private static bool OnMinPilerValueChangePrefix(UIStationWindow __instance, float value)
{
ApplyFixedPilerCount(__instance, value);
return false;
}
[HarmonyPrefix]
[HarmonyPatch("OnTechPilerClick")]
private static bool OnTechPilerClickPrefix(UIStationWindow __instance)
{
ApplyTechPilerToggle(__instance);
return false;
}
}
[HarmonyPatch(typeof(UIControlPanelStationInspector))]
private static class UIControlPanelStationInspectorPatch
{
[HarmonyPostfix]
[HarmonyPatch("OnStationIdChange")]
private static void OnStationIdChangePostfix(UIControlPanelStationInspector __instance)
{
RefreshPilerUi(__instance);
}
[HarmonyPrefix]
[HarmonyPatch("OnMinPilerValueChange")]
private static bool OnMinPilerValueChangePrefix(UIControlPanelStationInspector __instance, float value)
{
ApplyFixedPilerCount(__instance, value);
return false;
}
[HarmonyPrefix]
[HarmonyPatch("OnTechPilerClick")]
private static bool OnTechPilerClickPrefix(UIControlPanelStationInspector __instance)
{
ApplyTechPilerToggle(__instance);
return false;
}
}
[HarmonyPatch(typeof(CargoContainer), "Draw")]
private static class CargoContainerPatch
{
[HarmonyPrefix]
private static void DrawPrefix(CargoContainer __instance)
{
_cargoRenderDrawCount = 0;
if (!_cargoStackRenderPatchDisabled)
{
try
{
EnsureCargoRenderCapacity(__instance);
}
catch (Exception arg)
{
_cargoStackRenderPatchDisabled = true;
ManualLogSource logger = _logger;
if (logger != null)
{
logger.LogWarning((object)$"Cargo stack render patch disabled: {arg}");
}
}
}
if (_cargoShaderDrawPatchDisabled)
{
return;
}
try
{
ApplyCargoShader(GetFieldValue<Material>(CargoContainerFields.CargoMatInst, __instance));
}
catch (Exception arg2)
{
_cargoShaderDrawPatchDisabled = true;
ManualLogSource logger2 = _logger;
if (logger2 != null)
{
logger2.LogWarning((object)$"Cargo shader draw patch disabled: {arg2}");
}
}
}
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> DrawTranspiler(IEnumerable<CodeInstruction> instructions)
{
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_0108: Expected O, but got Unknown
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_0177: Unknown result type (might be due to invalid IL or missing references)
//IL_0189: Expected O, but got Unknown
MethodInfo objB = AccessTools.Method(typeof(ComputeBuffer), "SetData", new Type[4]
{
typeof(Array),
typeof(int),
typeof(int),
typeof(int)
}, (Type[])null);
MethodInfo methodInfo = AccessTools.Method(typeof(Plugin), "UploadCargoRenderData", (Type[])null, (Type[])null);
MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), "GetCargoRenderDrawCount", (Type[])null, (Type[])null);
FieldInfo cursor = CargoContainerFields.Cursor;
List<CodeInstruction> list = new List<CodeInstruction>(instructions);
int num = 0;
int num2 = 0;
for (int i = 0; i < list.Count; i++)
{
CodeInstruction val = list[i];
if ((val.opcode == OpCodes.Call || val.opcode == OpCodes.Callvirt) && object.Equals(val.operand, objB))
{
list[i] = new CodeInstruction(OpCodes.Call, (object)methodInfo)
{
labels = val.labels,
blocks = val.blocks
};
num++;
}
else if (val.opcode == OpCodes.Ldfld && object.Equals(val.operand, cursor) && i + 1 < list.Count && list[i + 1].opcode == OpCodes.Stelem_I4)
{
list[i] = new CodeInstruction(OpCodes.Call, (object)methodInfo2)
{
labels = val.labels,
blocks = val.blocks
};
num2++;
}
}
if (num != 1 || num2 != 1)
{
Debug.LogWarning((object)string.Format("[{0}] Unexpected CargoContainer.Draw patch shape. Replaced uploads={1}, drawCounts={2}.", "堆叠增强", num, num2));
}
return list;
}
}
[HarmonyPatch(typeof(PilerComponent), "InternalUpdate")]
private static class PilerComponentPatch
{
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> InternalUpdateTranspiler(IEnumerable<CodeInstruction> instructions)
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Expected O, but got Unknown
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Expected O, but got Unknown
int num = 0;
int num2 = 0;
List<CodeInstruction> list = new List<CodeInstruction>();
foreach (CodeInstruction instruction in instructions)
{
if (instruction.opcode == OpCodes.Ldc_I4_4)
{
num++;
list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Plugin), "GetMaxPilerStack", (Type[])null, (Type[])null)));
}
else if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num3 && Math.Abs(num3 - 4f) < 0.001f)
{
num2++;
list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Plugin), "GetMaxPilerStackFloat", (Type[])null, (Type[])null)));
}
else
{
list.Add(instruction);
}
}
if (num != 3 || num2 != 1)
{
Debug.LogWarning((object)string.Format("[{0}] Unexpected PilerComponent.InternalUpdate patch shape. Replaced int4={1}, float4={2}.", "堆叠增强", num, num2));
}
return list;
}
}
[HarmonyPatch(typeof(InserterComponent), "InternalUpdate_Bidirectional")]
private static class InserterBidirectionalPatch
{
private static byte _savedStackOutput;
[HarmonyPrepare]
private static bool Prepare()
{
return _enhancePileSorter?.Value ?? false;
}
[HarmonyPrefix]
private static void Prefix(ref InserterComponent __instance)
{
_savedStackOutput = __instance.stackOutput;
int maxPilerStack = GetMaxPilerStack();
if (maxPilerStack > __instance.stackOutput)
{
__instance.stackOutput = (byte)maxPilerStack;
}
}
[HarmonyFinalizer]
private static void Finalizer(ref InserterComponent __instance)
{
__instance.stackOutput = _savedStackOutput;
}
}
public const string ModGuid = "com.komonad.dsp.stackingenhancement";
public const string ModName = "堆叠增强";
public const string Version = "0.1.0";
private const int DefaultPilerStack = 4;
private const int MaxPilerStack = 8;
private const float TallCargoUpperBlockOffset = 0.4f;
private const string ShaderBundleFileName = "stacking-enhancement-shaders";
private const string CargoShaderAssetPath = "Assets/CargoInstancing8.shader";
private const string CargoShaderName = "VF Shaders/Batching/Cargo Instancing 8";
private const int FunctionStationPilerLevel = 29;
private const int ItemUniverseMatrix = 6006;
private const int FallbackPreTechLogisticsPiler = 1607;
private const string FallbackTechIconPath = "Icons/Tech/1607";
private static readonly int[] DefaultTechIds = new int[4] { 9442, 9443, 9444, 9445 };
private static readonly int[] LegacyStationStackTechIds = new int[4] { 9446, 9447, 9448, 9449 };
private static readonly long[] EnhancementHashNeededByLevel = new long[4] { 115200000L, 144000000L, 172800000L, 201600000L };
private static int[] _techIds = (int[])DefaultTechIds.Clone();
private static int _stationAnchorTechId = 1607;
private static ManualLogSource _logger;
private static AssetBundle _shaderBundle;
private static Shader _cargoShader;
private static Shader _originalCargoShader;
private static bool _cargoShaderLoadAttempted;
private static bool _cargoShaderAppliedLogged;
private static bool _cargoShaderDrawPatchDisabled;
private static bool _cargoStackRenderPatchDisabled;
private static Cargo[] _cargoRenderBuffer = (Cargo[])(object)new Cargo[128];
private static int _cargoRenderDrawCount;
private static ConfigEntry<bool> _enableCargoStackShader;
private static ConfigEntry<bool> _enhancePileSorter;
private static readonly Color SliderAutoNormalColor = new Color(1f, 1f, 1f, 0.1f);
private static readonly Color SliderAutoHighlightColor = new Color(1f, 1f, 1f, 0.2f);
private static readonly Color SliderFixedNormalColor = new Color(1f, 1f, 1f, 0.5f);
private static readonly Color SliderFixedHighlightColor = new Color(1f, 1f, 1f, 1f);
private void Awake()
{
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
_logger = ((BaseUnityPlugin)this).Logger;
_enableCargoStackShader = ((BaseUnityPlugin)this).Config.Bind<bool>("Rendering", "EnableCargoStackShader", true, "Enables cargo rendering with native stack height and side layer support up to 8 layers.");
_enhancePileSorter = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "EnhancePileSorter", false, "When enabled, pile sorters output stacks matching the Stacking Enhancement tech level instead of the default 4-layer cap.");
((BaseUnityPlugin)this).Logger.LogInfo((object)"堆叠增强 loaded.");
RegisterLocalizations();
LDBTool.PreAddDataAction = (Action)Delegate.Combine(LDBTool.PreAddDataAction, new Action(RegisterProtos));
LDBTool.PostAddDataAction = (Action)Delegate.Combine(LDBTool.PostAddDataAction, new Action(PostAddData));
new Harmony("com.komonad.dsp.stackingenhancement").PatchAll();
LogPatchStatus();
}
private void OnDestroy()
{
LDBTool.PreAddDataAction = (Action)Delegate.Remove(LDBTool.PreAddDataAction, new Action(RegisterProtos));
LDBTool.PostAddDataAction = (Action)Delegate.Remove(LDBTool.PostAddDataAction, new Action(PostAddData));
if ((Object)(object)_shaderBundle != (Object)null)
{
_shaderBundle.Unload(false);
_shaderBundle = null;
_cargoShader = null;
_cargoShaderLoadAttempted = false;
_cargoShaderAppliedLogged = false;
_cargoShaderDrawPatchDisabled = false;
_cargoStackRenderPatchDisabled = false;
}
}
private void RegisterProtos()
{
List<TechProto> list = ResolveStationPilerTechs();
_techIds = ResolveFreeTechIds(DefaultTechIds);
_stationAnchorTechId = ((list.Count > 0) ? ((Proto)list[list.Count - 1]).ID : 1607);
int preTechId = _stationAnchorTechId;
for (int i = 0; i < _techIds.Length; i++)
{
int stackLevel = 4 + i + 1;
TechProto obj = CreateStackingTech(_techIds[i], stackLevel, preTechId, i);
LDBTool.PreAddProto((Proto)(object)obj);
preTechId = ((Proto)obj).ID;
}
((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Registered stacking enhancement techs: ids={0}, anchor={1}", string.Join(",", _techIds), _stationAnchorTechId));
}
private static void RegisterLocalizations()
{
for (int i = 5; i <= 8; i++)
{
LocalizationModule.RegisterTranslation(TechNameKey(i), $"Stacking Enhancement {i}", $"堆叠增强 {i} 层", "");
LocalizationModule.RegisterTranslation(TechDescriptionKey(i), $"Improves logistics station cargo output stacking to {i} layers. Automatic pilers can also combine cargo up to {i} layers, while pile sorters keep their normal stacking limits.", $"将物流运输站输出货物堆叠上限提升至 {i} 层,并允许自动集装机生成最高 {i} 层货物。", "");
LocalizationModule.RegisterTranslation(TechConclusionKey(i), $"Logistics station cargo output stacking has been improved to {i} layers. Automatic pilers can now output cargo stacks up to {i} layers.", $"物流运输站输出货物堆叠已提升至 {i} 层。自动集装机现在可以输出最高 {i} 层货物。", "");
}
}
private void PostAddData()
{
RefreshTechProtoLinks();
EnsureTechStates(GameMain.history);
ApplyCargoShader(null);
}
private static TechProto CreateStackingTech(int techId, int stackLevel, int preTechId, int index)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
TechProto anchorTech = ((ProtoSet<TechProto>)(object)LDB.techs).Select(_stationAnchorTechId);
return CreateBaseTech(techId, TechNameKey(stackLevel), TechDescriptionKey(stackLevel), TechConclusionKey(stackLevel), GetTechPosition(anchorTech, index), GetIconPath(anchorTech), GetIconTag(anchorTech), (preTechId <= 0) ? Array.Empty<int>() : new int[1] { preTechId }, new int[1] { 6006 }, new int[1] { 1 }, EnhancementHashNeededByLevel[Math.Min(index, EnhancementHashNeededByLevel.Length - 1)], new int[1] { 29 }, new double[1] { 1.0 });
}
private static TechProto CreateBaseTech(int techId, string name, string description, string conclusion, Vector2 position, string iconPath, string iconTag, int[] preTechs, int[] items, int[] itemPoints, long hashNeeded, int[] unlockFunctions, double[] unlockValues)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Expected O, but got Unknown
return new TechProto
{
ID = techId,
Name = name,
Desc = description,
Conclusion = conclusion,
IconPath = iconPath,
IconTag = iconTag,
IsHiddenTech = false,
PreItem = Array.Empty<int>(),
Position = position,
PreTechs = preTechs,
PreTechsImplicit = Array.Empty<int>(),
Items = items,
ItemPoints = itemPoints,
HashNeeded = hashNeeded,
UnlockRecipes = Array.Empty<int>(),
UnlockFunctions = unlockFunctions,
UnlockValues = unlockValues,
Published = true,
Level = 0,
MaxLevel = 0,
LevelCoef1 = 0,
LevelCoef2 = 0,
IsLabTech = true,
PreTechsMax = false,
AddItems = Array.Empty<int>(),
AddItemCounts = Array.Empty<int>(),
PropertyOverrideItems = Array.Empty<int>(),
PropertyItemCounts = Array.Empty<int>()
};
}
private static Vector2 GetTechPosition(TechProto anchorTech, int index)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
Vector2 val = (Vector2)(((??)anchorTech?.Position) ?? new Vector2(41f, 33f));
return new Vector2(val.x + 4f + (float)index * 4f, val.y);
}
private static string GetIconPath(TechProto anchorTech)
{
if (!string.IsNullOrEmpty(anchorTech?.IconPath))
{
return anchorTech.IconPath;
}
return "Icons/Tech/1607";
}
private static string GetIconTag(TechProto anchorTech)
{
if (!string.IsNullOrEmpty(anchorTech?.IconTag))
{
return anchorTech.IconTag;
}
return "ddzq";
}
private static List<TechProto> ResolveStationPilerTechs()
{
return (from tech in ((ProtoSet<TechProto>)(object)LDB.techs)?.dataArray ?? Array.Empty<TechProto>()
where tech != null && tech.Published && tech.UnlockFunctions != null && tech.UnlockFunctions.Contains(29)
orderby ((Proto)tech).ID
select tech).ToList();
}
private static int[] ResolveFreeTechIds(IEnumerable<int> defaultIds)
{
HashSet<int> hashSet = new HashSet<int>(from tech in ((ProtoSet<TechProto>)(object)LDB.techs)?.dataArray ?? Array.Empty<TechProto>()
where tech != null
select ((Proto)tech).ID);
List<int> list = new List<int>();
foreach (int defaultId in defaultIds)
{
int i;
for (i = defaultId; hashSet.Contains(i); i++)
{
}
hashSet.Add(i);
list.Add(i);
}
return list.ToArray();
}
private static void RefreshTechProtoLinks()
{
((ProtoSet<TechProto>)(object)LDB.techs).OnAfterDeserialize();
TechProto[] dataArray = ((ProtoSet<TechProto>)(object)LDB.techs).dataArray;
foreach (TechProto obj in dataArray)
{
if (obj != null)
{
obj.Preload();
}
}
dataArray = ((ProtoSet<TechProto>)(object)LDB.techs).dataArray;
foreach (TechProto val in dataArray)
{
if (val != null)
{
val.PreTechsImplicit = (val.PreTechsImplicit ?? Array.Empty<int>()).Except(val.PreTechs ?? Array.Empty<int>()).ToArray();
val.UnlockRecipes = (val.UnlockRecipes ?? Array.Empty<int>()).Distinct().ToArray();
val.Preload2();
}
}
}
private static void EnsureTechStates(GameHistoryData history)
{
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
if (history?.techStates == null)
{
return;
}
int[] techIds = _techIds;
foreach (int num in techIds)
{
if (history.techStates.ContainsKey(num))
{
continue;
}
TechProto val = ((ProtoSet<TechProto>)(object)LDB.techs).Select(num);
if (val != null)
{
int num2 = 0;
int num3 = Array.IndexOf(val.Items ?? Array.Empty<int>(), 6006);
if (num3 >= 0 && val.ItemPoints != null && num3 < val.ItemPoints.Length)
{
num2 = val.ItemPoints[num3];
}
history.techStates.Add(num, new TechState(false, val.Level, val.MaxLevel, 0L, val.GetHashNeeded(val.Level), num2));
}
}
SyncStationPilerLevelFromUnlockedTechs(history);
}
public static int GetMaxPilerStack()
{
int val = GameMain.history?.stationPilerLevel ?? 4;
return Math.Min(8, Math.Max(4, val));
}
public static float GetMaxPilerStackFloat()
{
return GetMaxPilerStack();
}
private static int GetStationOutputStackLevel(GameHistoryData history)
{
int val = history?.stationPilerLevel ?? 1;
return Math.Min(8, Math.Max(1, val));
}
private static void SyncStationPilerLevelFromUnlockedTechs(GameHistoryData history)
{
if (history?.techStates != null)
{
int stationPilerLevel = history.stationPilerLevel;
stationPilerLevel = Math.Max(stationPilerLevel, GetHighestUnlockedStackLevel(history, _techIds));
stationPilerLevel = Math.Max(stationPilerLevel, GetHighestUnlockedStackLevel(history, LegacyStationStackTechIds));
stationPilerLevel = Math.Min(8, stationPilerLevel);
if (stationPilerLevel > history.stationPilerLevel)
{
history.stationPilerLevel = stationPilerLevel;
}
}
}
private static int GetHighestUnlockedStackLevel(GameHistoryData history, int[] techIds)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
int num = 0;
for (int i = 0; i < techIds.Length; i++)
{
if (history.techStates.TryGetValue(techIds[i], out var value) && value.unlocked)
{
num = Math.Max(num, 4 + i + 1);
}
}
return num;
}
private static string TechNameKey(int stackLevel)
{
return $"StackingEnhancement.Tech.{stackLevel}.Name";
}
private static string TechDescriptionKey(int stackLevel)
{
return $"StackingEnhancement.Tech.{stackLevel}.Description";
}
private static string TechConclusionKey(int stackLevel)
{
return $"StackingEnhancement.Tech.{stackLevel}.Conclusion";
}
private static T GetFieldValue<T>(FieldInfo field, object instance) where T : class
{
return field?.GetValue(instance) as T;
}
private static bool GetBoolFieldValue(FieldInfo field, object instance)
{
object obj = field?.GetValue(instance);
bool flag = default(bool);
int num;
if (obj is bool)
{
flag = (bool)obj;
num = 1;
}
else
{
num = 0;
}
return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
}
private static int GetIntFieldValue(FieldInfo field, object instance)
{
object obj = field?.GetValue(instance);
if (obj is int)
{
return (int)obj;
}
return 0;
}
private static void SetBoolFieldValue(FieldInfo field, object instance, bool value)
{
field?.SetValue(instance, value);
}
private static void LogPatchStatus()
{
Patches patchInfo = Harmony.GetPatchInfo((MethodBase)AccessTools.Method(typeof(CargoContainer), "Draw", (Type[])null, (Type[])null));
int valueOrDefault = (patchInfo?.Prefixes?.Count((Patch patch) => patch.owner == "com.komonad.dsp.stackingenhancement")).GetValueOrDefault();
int valueOrDefault2 = (patchInfo?.Postfixes?.Count((Patch patch) => patch.owner == "com.komonad.dsp.stackingenhancement")).GetValueOrDefault();
int valueOrDefault3 = (patchInfo?.Finalizers?.Count((Patch patch) => patch.owner == "com.komonad.dsp.stackingenhancement")).GetValueOrDefault();
int valueOrDefault4 = (patchInfo?.Transpilers?.Count((Patch patch) => patch.owner == "com.komonad.dsp.stackingenhancement")).GetValueOrDefault();
ManualLogSource logger = _logger;
if (logger != null)
{
logger.LogInfo((object)$"CargoContainer.Draw patches: prefix={valueOrDefault}, postfix={valueOrDefault2}, finalizer={valueOrDefault3}, transpiler={valueOrDefault4}");
}
}
private static Shader LoadCargoShader()
{
if ((Object)(object)_cargoShader != (Object)null)
{
return _cargoShader;
}
if (_cargoShaderLoadAttempted)
{
return null;
}
_cargoShaderLoadAttempted = true;
string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty, "stacking-enhancement-shaders");
if (!File.Exists(text))
{
ManualLogSource logger = _logger;
if (logger != null)
{
logger.LogWarning((object)("Cargo shader bundle missing: " + text));
}
return null;
}
_shaderBundle = AssetBundle.LoadFromFile(text);
if ((Object)(object)_shaderBundle == (Object)null)
{
ManualLogSource logger2 = _logger;
if (logger2 != null)
{
logger2.LogWarning((object)("Failed to load cargo shader bundle: " + text));
}
return null;
}
_cargoShader = _shaderBundle.LoadAsset<Shader>("Assets/CargoInstancing8.shader");
if ((Object)(object)_cargoShader == (Object)null)
{
_cargoShader = ((IEnumerable<Shader>)_shaderBundle.LoadAllAssets<Shader>()).FirstOrDefault((Func<Shader, bool>)((Shader shader) => (Object)(object)shader != (Object)null && ((Object)shader).name == "VF Shaders/Batching/Cargo Instancing 8"));
}
if ((Object)(object)_cargoShader == (Object)null)
{
ManualLogSource logger3 = _logger;
if (logger3 != null)
{
logger3.LogWarning((object)("Cargo shader asset missing in bundle: " + text));
}
}
else
{
ManualLogSource logger4 = _logger;
if (logger4 != null)
{
logger4.LogInfo((object)("Loaded cargo shader: " + ((Object)_cargoShader).name));
}
}
return _cargoShader;
}
private static void ApplyCargoShader(Material material)
{
Shader val = LoadCargoShader();
Material val2 = Configs.builtin?.cargoMat;
ConfigEntry<bool> enableCargoStackShader = _enableCargoStackShader;
if (enableCargoStackShader == null || !enableCargoStackShader.Value)
{
if ((Object)(object)_originalCargoShader != (Object)null)
{
if ((Object)(object)val2 != (Object)null && (Object)(object)val2.shader != (Object)(object)_originalCargoShader)
{
val2.shader = _originalCargoShader;
}
if ((Object)(object)material != (Object)null && (Object)(object)material.shader != (Object)(object)_originalCargoShader)
{
material.shader = _originalCargoShader;
}
}
}
else
{
if ((Object)(object)val == (Object)null)
{
return;
}
if ((Object)(object)val2 != (Object)null && (Object)(object)val2.shader != (Object)(object)val)
{
if ((Object)(object)_originalCargoShader == (Object)null)
{
_originalCargoShader = val2.shader;
}
val2.shader = val;
}
if ((Object)(object)material != (Object)null && (Object)(object)material.shader != (Object)(object)val)
{
material.shader = val;
}
if (!_cargoShaderAppliedLogged && (Object)(object)val2 != (Object)null)
{
_cargoShaderAppliedLogged = true;
ManualLogSource logger = _logger;
if (logger != null)
{
logger.LogInfo((object)("Applied cargo shader: " + ((Object)val).name));
}
}
}
}
private static void EnsureCargoRenderCapacity(CargoContainer container)
{
ConfigEntry<bool> enableCargoStackShader = _enableCargoStackShader;
if ((enableCargoStackShader != null && enableCargoStackShader.Value) || _cargoStackRenderPatchDisabled)
{
return;
}
Cargo[] fieldValue = GetFieldValue<Cargo[]>(CargoContainerFields.CargoPool, container);
int intFieldValue = GetIntFieldValue(CargoContainerFields.Cursor, container);
if (fieldValue == null || intFieldValue <= 0)
{
return;
}
int cargoCount = Math.Min(intFieldValue, fieldValue.Length);
int num = CalculateCargoRenderCount(fieldValue, cargoCount);
while (GetIntFieldValue(CargoContainerFields.PoolCapacity, container) < num)
{
if (CargoContainerMethods.Expand2x == null)
{
throw new MissingMethodException("CargoContainer", "Expand2x");
}
CargoContainerMethods.Expand2x.Invoke(container, null);
}
}
private static void UploadCargoRenderData(ComputeBuffer buffer, Array source, int managedBufferStartIndex, int computeBufferStartIndex, int count)
{
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Unknown result type (might be due to invalid IL or missing references)
//IL_018d: Unknown result type (might be due to invalid IL or missing references)
//IL_018f: Unknown result type (might be due to invalid IL or missing references)
ConfigEntry<bool> enableCargoStackShader = _enableCargoStackShader;
if ((enableCargoStackShader != null && enableCargoStackShader.Value) || _cargoStackRenderPatchDisabled || !(source is Cargo[] array))
{
_cargoRenderDrawCount = count;
buffer.SetData(source, managedBufferStartIndex, computeBufferStartIndex, count);
return;
}
int num = Math.Min(count, array.Length - managedBufferStartIndex);
if (num <= 0)
{
_cargoRenderDrawCount = 0;
buffer.SetData(source, managedBufferStartIndex, computeBufferStartIndex, count);
return;
}
int num2 = CalculateCargoRenderCount(array, num, managedBufferStartIndex);
if (num2 <= count)
{
_cargoRenderDrawCount = count;
buffer.SetData(source, managedBufferStartIndex, computeBufferStartIndex, count);
return;
}
if (num2 > buffer.count - computeBufferStartIndex)
{
_cargoStackRenderPatchDisabled = true;
_cargoRenderDrawCount = count;
ManualLogSource logger = _logger;
if (logger != null)
{
logger.LogWarning((object)$"Cargo stack render patch disabled: renderCount={num2}, bufferCount={buffer.count}, uploadOffset={computeBufferStartIndex}");
}
buffer.SetData(source, managedBufferStartIndex, computeBufferStartIndex, count);
return;
}
EnsureCargoRenderBufferCapacity(num2);
int num3 = 0;
int num4 = managedBufferStartIndex + num;
for (int i = managedBufferStartIndex; i < num4; i++)
{
Cargo val = array[i];
int stack = val.stack;
if (val.item <= 0 || stack <= 4 || stack > 8)
{
_cargoRenderBuffer[num3++] = val;
continue;
}
Cargo val2 = val;
val2.stack = 4;
_cargoRenderBuffer[num3++] = val2;
Cargo val3 = val;
val3.stack = (byte)(stack - 4);
ref Vector3 position = ref val3.position;
position += val3.rotation * new Vector3(0f, 0.4f, 0f);
_cargoRenderBuffer[num3++] = val3;
}
_cargoRenderDrawCount = num3;
buffer.SetData((Array)_cargoRenderBuffer, 0, computeBufferStartIndex, num3);
}
private static int GetCargoRenderDrawCount(CargoContainer container)
{
if (_cargoRenderDrawCount <= 0)
{
return GetIntFieldValue(CargoContainerFields.Cursor, container);
}
return _cargoRenderDrawCount;
}
private static int CalculateCargoRenderCount(Cargo[] cargos, int cargoCount, int startIndex = 0)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
int num = cargoCount;
int num2 = Math.Min(cargos.Length, startIndex + cargoCount);
for (int i = startIndex; i < num2; i++)
{
Cargo val = cargos[i];
int stack = val.stack;
if (val.item > 0 && stack > 4 && stack <= 8)
{
num++;
}
}
return num;
}
private static void EnsureCargoRenderBufferCapacity(int capacity)
{
if (_cargoRenderBuffer.Length < capacity)
{
int newSize = Math.Max(capacity, _cargoRenderBuffer.Length * 2);
Array.Resize(ref _cargoRenderBuffer, newSize);
}
}
private static void ApplyFixedPilerCount(UIStationWindow window, float value)
{
StationComponent stationComponent = GetStationComponent(window);
Image fieldValue = GetFieldValue<Image>(StationWindowFields.TechPilerCheck, window);
if (stationComponent != null && !GetBoolFieldValue(StationWindowFields.EventLock, window) && (fieldValue == null || !((Behaviour)fieldValue).enabled))
{
stationComponent.pilerCount = ClampStationPilerCount(Mathf.RoundToInt(value), GameMain.history);
RefreshPilerUi(window);
}
}
private static void ApplyFixedPilerCount(UIControlPanelStationInspector inspector, float value)
{
StationComponent stationComponent = GetStationComponent(inspector);
Image fieldValue = GetFieldValue<Image>(StationInspectorFields.TechPilerCheck, inspector);
if (stationComponent != null && !GetBoolFieldValue(StationInspectorFields.EventLock, inspector) && (fieldValue == null || !((Behaviour)fieldValue).enabled))
{
stationComponent.pilerCount = ClampStationPilerCount(Mathf.RoundToInt(value), GameMain.history);
RefreshPilerUi(inspector);
}
}
private static void ApplyTechPilerToggle(UIStationWindow window)
{
StationComponent stationComponent = GetStationComponent(window);
if (stationComponent != null && !GetBoolFieldValue(StationWindowFields.EventLock, window))
{
Image fieldValue = GetFieldValue<Image>(StationWindowFields.TechPilerCheck, window);
bool flag = fieldValue == null || !((Behaviour)fieldValue).enabled;
stationComponent.pilerCount = ((!flag) ? GetStationOutputStackLevel(GameMain.history) : 0);
RefreshPilerUi(window);
}
}
private static void ApplyTechPilerToggle(UIControlPanelStationInspector inspector)
{
StationComponent stationComponent = GetStationComponent(inspector);
if (stationComponent != null && !GetBoolFieldValue(StationInspectorFields.EventLock, inspector))
{
Image fieldValue = GetFieldValue<Image>(StationInspectorFields.TechPilerCheck, inspector);
bool flag = fieldValue == null || !((Behaviour)fieldValue).enabled;
stationComponent.pilerCount = ((!flag) ? GetStationOutputStackLevel(GameMain.history) : 0);
RefreshPilerUi(inspector);
}
}
private static void RefreshPilerUi(UIStationWindow window)
{
StationComponent stationComponent = GetStationComponent(window);
if (stationComponent != null)
{
bool boolFieldValue = GetBoolFieldValue(StationWindowFields.EventLock, window);
SetBoolFieldValue(StationWindowFields.EventLock, window, value: true);
RefreshPilerUi(stationComponent, GetFieldValue<Slider>(StationWindowFields.MinPilerSlider, window), GetFieldValue<Image>(StationWindowFields.MinPilerSliderFillImage, window), GetFieldValue<Text>(StationWindowFields.MinPilerValue, window), GetFieldValue<Image>(StationWindowFields.TechPilerCheck, window));
SetBoolFieldValue(StationWindowFields.EventLock, window, boolFieldValue);
}
}
private static void RefreshPilerUi(UIControlPanelStationInspector inspector)
{
StationComponent stationComponent = GetStationComponent(inspector);
if (stationComponent != null)
{
bool boolFieldValue = GetBoolFieldValue(StationInspectorFields.EventLock, inspector);
SetBoolFieldValue(StationInspectorFields.EventLock, inspector, value: true);
RefreshPilerUi(stationComponent, GetFieldValue<Slider>(StationInspectorFields.MinPilerSlider, inspector), GetFieldValue<Image>(StationInspectorFields.MinPilerSliderFillImage, inspector), GetFieldValue<Text>(StationInspectorFields.MinPilerValue, inspector), GetFieldValue<Image>(StationInspectorFields.TechPilerCheck, inspector));
SetBoolFieldValue(StationInspectorFields.EventLock, inspector, boolFieldValue);
}
}
private static void RefreshPilerUi(StationComponent station, Slider slider, Image sliderFillImage, Text valueText, Image techPilerCheck)
{
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
int stationOutputStackLevel = GetStationOutputStackLevel(GameMain.history);
if (station.pilerCount > stationOutputStackLevel)
{
station.pilerCount = stationOutputStackLevel;
}
bool flag = station.pilerCount == 0;
if ((Object)(object)slider != (Object)null)
{
slider.maxValue = stationOutputStackLevel;
slider.value = (flag ? stationOutputStackLevel : station.pilerCount);
((Selectable)slider).interactable = !flag;
ColorBlock colors = ((Selectable)slider).colors;
((ColorBlock)(ref colors)).normalColor = (flag ? SliderAutoNormalColor : SliderFixedNormalColor);
((ColorBlock)(ref colors)).highlightedColor = (flag ? SliderAutoHighlightColor : SliderFixedHighlightColor);
((ColorBlock)(ref colors)).pressedColor = (flag ? SliderAutoHighlightColor : SliderFixedHighlightColor);
((Selectable)slider).colors = colors;
}
if ((Object)(object)sliderFillImage != (Object)null)
{
((Graphic)sliderFillImage).color = (flag ? SliderAutoNormalColor : SliderFixedNormalColor);
}
if ((Object)(object)techPilerCheck != (Object)null)
{
((Behaviour)techPilerCheck).enabled = flag;
}
if ((Object)(object)valueText != (Object)null)
{
valueText.text = (flag ? stationOutputStackLevel : station.pilerCount).ToString();
}
}
private static int ClampStationPilerCount(int value, GameHistoryData history)
{
return Math.Min(GetStationOutputStackLevel(history), Math.Max(1, value));
}
private static StationComponent GetStationComponent(UIStationWindow window)
{
PlanetTransport fieldValue = GetFieldValue<PlanetTransport>(StationWindowFields.Transport, window);
int intFieldValue = GetIntFieldValue(StationWindowFields.StationId, window);
if ((Object)(object)window == (Object)null || fieldValue == null || fieldValue.stationPool == null || intFieldValue <= 0 || intFieldValue >= fieldValue.stationPool.Length)
{
return null;
}
StationComponent val = fieldValue.stationPool[intFieldValue];
if (val == null || val.id != intFieldValue)
{
return null;
}
return val;
}
private static StationComponent GetStationComponent(UIControlPanelStationInspector inspector)
{
PlanetTransport fieldValue = GetFieldValue<PlanetTransport>(StationInspectorFields.Transport, inspector);
int intFieldValue = GetIntFieldValue(StationInspectorFields.StationId, inspector);
if ((Object)(object)inspector == (Object)null || fieldValue == null || fieldValue.stationPool == null || intFieldValue <= 0 || intFieldValue >= fieldValue.stationPool.Length)
{
return null;
}
StationComponent val = fieldValue.stationPool[intFieldValue];
if (val == null || val.id != intFieldValue)
{
return null;
}
return val;
}
}