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(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 DrawTranspiler(IEnumerable 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 list = new List(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 InternalUpdateTranspiler(IEnumerable 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 list = new List(); 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 _enableCargoStackShader; private static ConfigEntry _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("Rendering", "EnableCargoStackShader", true, "Enables cargo rendering with native stack height and side layer support up to 8 layers."); _enhancePileSorter = ((BaseUnityPlugin)this).Config.Bind("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 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)(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() : 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(), Position = position, PreTechs = preTechs, PreTechsImplicit = Array.Empty(), Items = items, ItemPoints = itemPoints, HashNeeded = hashNeeded, UnlockRecipes = Array.Empty(), UnlockFunctions = unlockFunctions, UnlockValues = unlockValues, Published = true, Level = 0, MaxLevel = 0, LevelCoef1 = 0, LevelCoef2 = 0, IsLabTech = true, PreTechsMax = false, AddItems = Array.Empty(), AddItemCounts = Array.Empty(), PropertyOverrideItems = Array.Empty(), PropertyItemCounts = Array.Empty() }; } 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 ResolveStationPilerTechs() { return (from tech in ((ProtoSet)(object)LDB.techs)?.dataArray ?? Array.Empty() where tech != null && tech.Published && tech.UnlockFunctions != null && tech.UnlockFunctions.Contains(29) orderby ((Proto)tech).ID select tech).ToList(); } private static int[] ResolveFreeTechIds(IEnumerable defaultIds) { HashSet hashSet = new HashSet(from tech in ((ProtoSet)(object)LDB.techs)?.dataArray ?? Array.Empty() where tech != null select ((Proto)tech).ID); List list = new List(); 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)(object)LDB.techs).OnAfterDeserialize(); TechProto[] dataArray = ((ProtoSet)(object)LDB.techs).dataArray; foreach (TechProto obj in dataArray) { if (obj != null) { obj.Preload(); } } dataArray = ((ProtoSet)(object)LDB.techs).dataArray; foreach (TechProto val in dataArray) { if (val != null) { val.PreTechsImplicit = (val.PreTechsImplicit ?? Array.Empty()).Except(val.PreTechs ?? Array.Empty()).ToArray(); val.UnlockRecipes = (val.UnlockRecipes ?? Array.Empty()).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)(object)LDB.techs).Select(num); if (val != null) { int num2 = 0; int num3 = Array.IndexOf(val.Items ?? Array.Empty(), 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(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("Assets/CargoInstancing8.shader"); if ((Object)(object)_cargoShader == (Object)null) { _cargoShader = ((IEnumerable)_shaderBundle.LoadAllAssets()).FirstOrDefault((Func)((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 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 enableCargoStackShader = _enableCargoStackShader; if ((enableCargoStackShader != null && enableCargoStackShader.Value) || _cargoStackRenderPatchDisabled) { return; } Cargo[] fieldValue = GetFieldValue(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 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(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(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(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(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(StationWindowFields.MinPilerSlider, window), GetFieldValue(StationWindowFields.MinPilerSliderFillImage, window), GetFieldValue(StationWindowFields.MinPilerValue, window), GetFieldValue(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(StationInspectorFields.MinPilerSlider, inspector), GetFieldValue(StationInspectorFields.MinPilerSliderFillImage, inspector), GetFieldValue(StationInspectorFields.MinPilerValue, inspector), GetFieldValue(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(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(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; } }