Decompiled source of DSPProliferatorTweak v1.2.1

DSPProliferatorTweak.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[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 Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace DSPProliferatorTweak
{
	internal static class IncCeilingTranspiler
	{
		private static readonly FieldInfo CargoIncTableField = AccessTools.Field(typeof(Cargo), "incTable");

		private static readonly FieldInfo CeilingField = AccessTools.Field(typeof(ProliferatorTweakPlugin), "IncLevelAggregationCeiling");

		internal static readonly MethodInfo AssemblerSplitInc = AccessTools.Method(typeof(AssemblerComponent), "split_inc_level", (Type[])null, (Type[])null);

		internal static readonly MethodInfo LabSplitInc = AccessTools.Method(typeof(LabComponent), "split_inc_level", (Type[])null, (Type[])null);

		internal static IEnumerable<CodeInstruction> ReplaceTenBeforeSplitInc(IEnumerable<CodeInstruction> instructions, MethodInfo splitMethod)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = FindCallIndex(list, splitMethod);
			if (num < 0)
			{
				return list;
			}
			int num2 = Math.Max(0, num - 48);
			for (int num3 = num - 1; num3 >= num2; num3--)
			{
				if (IsLdcI4S10(list[num3]))
				{
					CodeInstruction val = list[num3];
					CodeInstruction val2 = new CodeInstruction(OpCodes.Ldsfld, (object)CeilingField);
					foreach (Label label in val.labels)
					{
						val2.labels.Add(label);
					}
					foreach (ExceptionBlock block in val.blocks)
					{
						val2.blocks.Add(block);
					}
					list[num3] = val2;
					break;
				}
			}
			return list;
		}

		internal static IEnumerable<CodeInstruction> ReplaceTenBeforeCargoIncTableRead(IEnumerable<CodeInstruction> instructions)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			for (int num = list.Count - 1; num >= 0; num--)
			{
				if (!(list[num].opcode != OpCodes.Ldsfld) && list[num].operand == CargoIncTableField)
				{
					int num2 = Math.Max(0, num - 20);
					for (int num3 = num - 1; num3 >= num2; num3--)
					{
						if (IsLdcI4S10(list[num3]))
						{
							CodeInstruction val = list[num3];
							CodeInstruction val2 = new CodeInstruction(OpCodes.Ldsfld, (object)CeilingField);
							foreach (Label label in val.labels)
							{
								val2.labels.Add(label);
							}
							foreach (ExceptionBlock block in val.blocks)
							{
								val2.blocks.Add(block);
							}
							list[num3] = val2;
							return list;
						}
					}
				}
			}
			return list;
		}

		private static int FindCallIndex(List<CodeInstruction> list, MethodInfo splitMethod)
		{
			for (int i = 0; i < list.Count; i++)
			{
				if ((!(list[i].opcode != OpCodes.Call) || !(list[i].opcode != OpCodes.Callvirt)) && list[i].operand is MethodInfo methodInfo && methodInfo == splitMethod)
				{
					return i;
				}
			}
			return -1;
		}

		private static bool IsLdcI4S10(CodeInstruction c)
		{
			if (c.opcode != OpCodes.Ldc_I4_S)
			{
				return false;
			}
			object operand = c.operand;
			if (!(operand is sbyte b))
			{
				if (operand is byte b2)
				{
					return b2 == 10;
				}
				return false;
			}
			return b == 10;
		}
	}
	[HarmonyPatch(typeof(AssemblerComponent), "InternalUpdate")]
	internal static class AssemblerIncCeilingPatch
	{
		[HarmonyTranspiler]
		internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return IncCeilingTranspiler.ReplaceTenBeforeSplitInc(instructions, IncCeilingTranspiler.AssemblerSplitInc);
		}
	}
	[HarmonyPatch(typeof(LabComponent), "InternalUpdateAssemble")]
	internal static class LabIncCeilingPatch
	{
		[HarmonyTranspiler]
		internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return IncCeilingTranspiler.ReplaceTenBeforeSplitInc(instructions, IncCeilingTranspiler.LabSplitInc);
		}
	}
	[HarmonyPatch(typeof(SpraycoaterComponent), "InternalUpdate")]
	internal static class SpraycoaterIncCeilingPatch
	{
		[HarmonyTranspiler]
		internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return IncCeilingTranspiler.ReplaceTenBeforeCargoIncTableRead(instructions);
		}
	}
	[HarmonyPatch(typeof(GameMain), "Start")]
	internal static class GameMainStartGenesisPatch
	{
		[HarmonyPostfix]
		internal static void Postfix()
		{
			ProliferatorTweakPlugin.NotifyGameStarted();
		}
	}
	[HarmonyPatch(typeof(ItemProto), "GetPropValue", new Type[]
	{
		typeof(int),
		typeof(StringBuilder),
		typeof(int)
	})]
	internal static class ItemProtoTooltipGuard
	{
		[HarmonyPrefix]
		internal static void Prefix(ItemProto __instance)
		{
			int ability = __instance.Ability;
			if (ability > 0 && (Cargo.incTable == null || ability >= Cargo.incTable.Length))
			{
				ProliferatorTweakPlugin.Instance?.EnsureCargoCoversAbilityIndex(ability);
			}
		}
	}
	[BepInPlugin("DSP.Kawaayi.ProliferatorTweak", "DSP Proliferator Tweak", "1.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class ProliferatorTweakPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "DSP.Kawaayi.ProliferatorTweak";

		public const string PluginName = "DSP Proliferator Tweak";

		public const string PluginVersion = "1.2.0";

		public static int IncLevelAggregationCeiling = 10;

		private const int VanillaTableLength = 11;

		private const int DefaultCustomSlot = 11;

		private ConfigEntry<int> _customAbilitySlot;

		private ConfigEntry<int> _slotIncTenths;

		private ConfigEntry<int> _slotAccTenths;

		private ConfigEntry<int> _slotPowerTenths;

		private ConfigEntry<bool> _patchGenesisProliferator;

		private ConfigEntry<int> _genesisItemId;

		private ConfigEntry<bool> _setGenesisSprayTimesHpMax;

		private ConfigEntry<int> _genesisSprayTimesHpMax;

		private int[]? _vanillaInc;

		private int[]? _vanillaAcc;

		private int[]? _vanillaPower;

		private double[]? _vanillaIncMilli;

		private double[]? _vanillaAccMilli;

		private double[]? _vanillaPowerRatio;

		private int[]? _vanillaIncFastNum;

		private byte[]? _vanillaFastIncArrow;

		private Harmony? _harmony;

		public static ProliferatorTweakPlugin? Instance { get; private set; }

		private void Awake()
		{
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Expected O, but got Unknown
			Instance = this;
			_customAbilitySlot = ((BaseUnityPlugin)this).Config.Bind<int>("CustomSlot", "AbilityIndex", 11, "自定义增产档位下标(与 ItemProto.Ability 一致)。原版合法为 1~10;默认 11 表示在 Cargo 表末尾新增一档。若 ≤10 则只覆盖该格数据、不扩容表。");
			_slotIncTenths = ((BaseUnityPlugin)this).Config.Bind<int>("CustomSlot", "ExtraOutputTenths", 250, "该下标「额外产出」千分比×10 的整数(与原版 Cargo.incTable 一致):250 表示 +25.0%。");
			_slotAccTenths = ((BaseUnityPlugin)this).Config.Bind<int>("CustomSlot", "SpeedBonusTenths", 1000, "该下标「制造速度」千分比×10:1000 表示 +100.0%。");
			_slotPowerTenths = ((BaseUnityPlugin)this).Config.Bind<int>("CustomSlot", "ExtraPowerCostTenths", 1500, "该下标「额外耗电」千分比×10:1500 表示 +150.0%(可按需改)。");
			_patchGenesisProliferator = ((BaseUnityPlugin)this).Config.Bind<bool>("GenesisBook", "SetGenesisItemAbility", true, "若为 true:尝试把创世之书物品 ItemProto.Ability 改为上面的自定义下标(默认物品 ID 1143)。");
			_genesisItemId = ((BaseUnityPlugin)this).Config.Bind<int>("GenesisBook", "ItemId", 1143, "要改 Ability 的物品 ID(默认创世增产剂 1143)。");
			_setGenesisSprayTimesHpMax = ((BaseUnityPlugin)this).Config.Bind<bool>("GenesisBook", "SetItemSprayTimesHpMax", true, "若为 true:把该物品的 ItemProto.HpMax 设为下方数值。喷涂机用 HpMax 作为每次喷涂的「次数」基准(与物品说明里喷涂次数一致)。");
			_genesisSprayTimesHpMax = ((BaseUnityPlugin)this).Config.Bind<int>("GenesisBook", "SprayTimesHpMax", 60, new ConfigDescription("喷涂次数(写入 ItemProto.HpMax)。原版 Mk.I/II/III 增产约 12/24/60 量级,可按需调大。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 99999), Array.Empty<object>()));
			_customAbilitySlot.SettingChanged += delegate
			{
				FullApply();
			};
			_slotIncTenths.SettingChanged += delegate
			{
				FullApply();
			};
			_slotAccTenths.SettingChanged += delegate
			{
				FullApply();
			};
			_slotPowerTenths.SettingChanged += delegate
			{
				FullApply();
			};
			_patchGenesisProliferator.SettingChanged += delegate
			{
				FullApply();
			};
			_genesisItemId.SettingChanged += delegate
			{
				FullApply();
			};
			_setGenesisSprayTimesHpMax.SettingChanged += delegate
			{
				FullApply();
			};
			_genesisSprayTimesHpMax.SettingChanged += delegate
			{
				FullApply();
			};
			SnapshotVanilla();
			_harmony = new Harmony("DSP.Kawaayi.ProliferatorTweak");
			_harmony.PatchAll(typeof(ProliferatorTweakPlugin).Assembly);
			FullApply();
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} v{1}:下标={2} 增产‰×10={3} 加速‰×10={4} 耗电‰×10={5};喷涂HpMax={6}", "DSP Proliferator Tweak", "1.2.0", _customAbilitySlot.Value, _slotIncTenths.Value, _slotAccTenths.Value, _slotPowerTenths.Value, _setGenesisSprayTimesHpMax.Value ? _genesisSprayTimesHpMax.Value.ToString() : "不改"));
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Instance = null;
		}

		internal static void NotifyGameStarted()
		{
			Instance?.ApplyGenesisItemOnly();
		}

		private void FullApply()
		{
			ApplyCargoTablesAndCeiling();
			ApplyGenesisItemOnly();
		}

		internal void EnsureCargoCoversAbilityIndex(int abilityIndex)
		{
			if (_vanillaInc != null && abilityIndex >= 0 && Cargo.incTable != null && abilityIndex >= Cargo.incTable.Length)
			{
				int value = _customAbilitySlot.Value;
				if (value >= 0 && value <= 63)
				{
					int needLen = Math.Max(11, Math.Max(value + 1, abilityIndex + 1));
					EnsureTableLengths(needLen);
					IncLevelAggregationCeiling = Math.Max(IncLevelAggregationCeiling, Math.Max(10, Math.Max(value, abilityIndex)));
					WriteCustomSlotValues();
				}
			}
		}

		private void ApplyGenesisItemOnly()
		{
			if ((!_patchGenesisProliferator.Value && !_setGenesisSprayTimesHpMax.Value) || (Object)(object)LDB.items == (Object)null)
			{
				return;
			}
			int value = _genesisItemId.Value;
			int value2 = _customAbilitySlot.Value;
			ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(value);
			if (val != null && ((Proto)val).ID == value)
			{
				if (_patchGenesisProliferator.Value)
				{
					val.Ability = value2;
				}
				if (_setGenesisSprayTimesHpMax.Value)
				{
					val.HpMax = _genesisSprayTimesHpMax.Value;
				}
			}
		}

		private void ApplyCargoTablesAndCeiling()
		{
			if (_vanillaInc != null)
			{
				int value = _customAbilitySlot.Value;
				if (value < 0 || value > 63)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)$"AbilityIndex={value} 超出安全范围,已忽略。");
					return;
				}
				int needLen = Math.Max(11, value + 1);
				EnsureTableLengths(needLen);
				IncLevelAggregationCeiling = Math.Max(10, value);
				WriteCustomSlotValues();
			}
		}

		private void WriteCustomSlotValues()
		{
			if (_vanillaInc != null && Cargo.incTable != null)
			{
				int value = _customAbilitySlot.Value;
				if (value >= 0 && value < Cargo.incTable.Length)
				{
					int num = Math.Max(0, _slotIncTenths.Value);
					int num2 = Math.Max(0, _slotAccTenths.Value);
					int num3 = Math.Max(0, _slotPowerTenths.Value);
					Cargo.incTable[value] = num;
					Cargo.accTable[value] = num2;
					Cargo.powerTable[value] = num3;
					Cargo.incTableMilli[value] = (double)num * 0.001;
					Cargo.accTableMilli[value] = (double)num2 * 0.001;
					Cargo.powerTableRatio[value] = 1.0 + (double)num3 * 0.001;
				}
			}
		}

		private void EnsureTableLengths(int needLen)
		{
			if (_vanillaInc != null && _vanillaAcc != null && _vanillaPower != null && _vanillaIncMilli != null && _vanillaAccMilli != null && _vanillaPowerRatio != null && _vanillaIncFastNum != null && _vanillaFastIncArrow != null && Cargo.incTable.Length < needLen)
			{
				Cargo.incTable = GrowArray(_vanillaInc, Cargo.incTable, needLen);
				Cargo.accTable = GrowArray(_vanillaAcc, Cargo.accTable, needLen);
				Cargo.powerTable = GrowArray(_vanillaPower, Cargo.powerTable, needLen);
				Cargo.incTableMilli = GrowArray(_vanillaIncMilli, Cargo.incTableMilli, needLen);
				Cargo.accTableMilli = GrowArray(_vanillaAccMilli, Cargo.accTableMilli, needLen);
				Cargo.powerTableRatio = GrowArray(_vanillaPowerRatio, Cargo.powerTableRatio, needLen);
				Cargo.incFastDivisionNumerator = GrowArray(_vanillaIncFastNum, Cargo.incFastDivisionNumerator, needLen);
				Cargo.fastIncArrowTable = GrowArray(_vanillaFastIncArrow, Cargo.fastIncArrowTable, needLen);
			}
		}

		private static int[] GrowArray(int[] snapshot, int[] current, int needLen)
		{
			if (current.Length >= needLen)
			{
				return current;
			}
			int[] array = new int[needLen];
			Array.Copy(snapshot, array, snapshot.Length);
			int num = snapshot[^1];
			for (int i = snapshot.Length; i < needLen; i++)
			{
				array[i] = num;
			}
			return array;
		}

		private static double[] GrowArray(double[] snapshot, double[] current, int needLen)
		{
			if (current.Length >= needLen)
			{
				return current;
			}
			double[] array = new double[needLen];
			Array.Copy(snapshot, array, snapshot.Length);
			double num = snapshot[^1];
			for (int i = snapshot.Length; i < needLen; i++)
			{
				array[i] = num;
			}
			return array;
		}

		private static byte[] GrowArray(byte[] snapshot, byte[] current, int needLen)
		{
			if (current.Length >= needLen)
			{
				return current;
			}
			byte[] array = new byte[needLen];
			Array.Copy(snapshot, array, snapshot.Length);
			byte b = snapshot[^1];
			for (int i = snapshot.Length; i < needLen; i++)
			{
				array[i] = b;
			}
			return array;
		}

		private void SnapshotVanilla()
		{
			_vanillaInc = (int[])Cargo.incTable.Clone();
			_vanillaAcc = (int[])Cargo.accTable.Clone();
			_vanillaPower = (int[])Cargo.powerTable.Clone();
			_vanillaIncMilli = (double[])Cargo.incTableMilli.Clone();
			_vanillaAccMilli = (double[])Cargo.accTableMilli.Clone();
			_vanillaPowerRatio = (double[])Cargo.powerTableRatio.Clone();
			_vanillaIncFastNum = (int[])Cargo.incFastDivisionNumerator.Clone();
			_vanillaFastIncArrow = (byte[])Cargo.fastIncArrowTable.Clone();
		}
	}
}