diff --git a/CheatEnabler/CheatEnabler.cs b/CheatEnabler/CheatEnabler.cs index d7c3a6e..6e0c7da 100644 --- a/CheatEnabler/CheatEnabler.cs +++ b/CheatEnabler/CheatEnabler.cs @@ -1,6 +1,6 @@ -using System.Reflection; +using System; +using System.Reflection; using BepInEx; -using CheatEnabler.Functions; using CheatEnabler.Patches; using HarmonyLib; using UXAssist.Common; @@ -83,19 +83,22 @@ public class CheatEnabler : BaseUnityPlugin "Mecha and Drones/Fleets invincible"); CombatPatch.BuildingsInvincibleEnabled = Config.Bind("Battle", "BuildingsInvincible", false, "Buildings invincible"); - } - private void Start() { UIConfigWindow.Init(); - Util.GetTypesInNamespace(Assembly.GetExecutingAssembly(), "CheatEnabler.Patches") - .Do(type => type.GetMethod("Init")?.Invoke(null, null)); - PlayerFunctions.Init(); - DysonSphereFunctions.Init(); + _patches = Util.GetTypesFiltered(Assembly.GetExecutingAssembly(), + t => string.Equals(t.Namespace, "CheatEnabler.Patches", StringComparison.Ordinal) || string.Equals(t.Namespace, "CheatEnabler.Functions", StringComparison.Ordinal)); + _patches?.Do(type => type.GetMethod("Init")?.Invoke(null, null)); + } + + private Type[] _patches; + + private void Start() + { + _patches?.Do(type => type.GetMethod("Start")?.Invoke(null, null)); } private void OnDestroy() { - Util.GetTypesInNamespace(Assembly.GetExecutingAssembly(), "CheatEnabler.Patches") - .Do(type => type.GetMethod("Uninit")?.Invoke(null, null)); + _patches?.Do(type => type.GetMethod("Uninit")?.Invoke(null, null)); } private void Update() @@ -103,4 +106,4 @@ public class CheatEnabler : BaseUnityPlugin if (VFInput.inputing) return; FactoryPatch.OnUpdate(); } -} +} \ No newline at end of file diff --git a/CheatEnabler/Patches/CombatPatch.cs b/CheatEnabler/Patches/CombatPatch.cs index 1203b05..64d9d17 100644 --- a/CheatEnabler/Patches/CombatPatch.cs +++ b/CheatEnabler/Patches/CombatPatch.cs @@ -16,6 +16,10 @@ public static class CombatPatch { MechaInvincibleEnabled.SettingChanged += (_, _) => MechaInvincible.Enable(MechaInvincibleEnabled.Value); BuildingsInvincibleEnabled.SettingChanged += (_, _) => BuildingsInvincible.Enable(BuildingsInvincibleEnabled.Value); + } + + public static void Start() + { MechaInvincible.Enable(MechaInvincibleEnabled.Value); BuildingsInvincible.Enable(BuildingsInvincibleEnabled.Value); } diff --git a/CheatEnabler/Patches/DysonSpherePatch.cs b/CheatEnabler/Patches/DysonSpherePatch.cs index a393aea..de07851 100644 --- a/CheatEnabler/Patches/DysonSpherePatch.cs +++ b/CheatEnabler/Patches/DysonSpherePatch.cs @@ -7,7 +7,7 @@ using UXAssist.Common; namespace CheatEnabler.Patches; -public static class DysonSpherePatch +public class DysonSpherePatch: PatchImpl { public static ConfigEntry SkipBulletEnabled; public static ConfigEntry SkipAbsorbEnabled; @@ -17,8 +17,6 @@ public static class DysonSpherePatch public static ConfigEntry OverclockSiloEnabled; private static bool _instantAbsorb; - private static Harmony _dysonSpherePatch; - public static void Init() { SkipBulletEnabled.SettingChanged += (_, _) => SkipBulletPatch.Enable(SkipBulletEnabled.Value); @@ -27,19 +25,22 @@ public static class DysonSpherePatch EjectAnywayEnabled.SettingChanged += (_, _) => EjectAnywayPatch.Enable(EjectAnywayEnabled.Value); OverclockEjectorEnabled.SettingChanged += (_, _) => OverclockEjector.Enable(OverclockEjectorEnabled.Value); OverclockSiloEnabled.SettingChanged += (_, _) => OverclockSilo.Enable(OverclockSiloEnabled.Value); + } + + public static void Start() + { SkipBulletPatch.Enable(SkipBulletEnabled.Value); SkipAbsorbPatch.Enable(SkipAbsorbEnabled.Value); QuickAbsorbPatch.Enable(QuickAbsorbEnabled.Value); EjectAnywayPatch.Enable(EjectAnywayEnabled.Value); OverclockEjector.Enable(OverclockEjectorEnabled.Value); OverclockSilo.Enable(OverclockSiloEnabled.Value); - _dysonSpherePatch ??= Harmony.CreateAndPatchAll(typeof(DysonSpherePatch)); + Enable(true); } public static void Uninit() { - _dysonSpherePatch?.UnpatchSelf(); - _dysonSpherePatch = null; + Enable(false); SkipBulletPatch.Enable(false); SkipAbsorbPatch.Enable(false); QuickAbsorbPatch.Enable(false); diff --git a/CheatEnabler/Patches/FactoryPatch.cs b/CheatEnabler/Patches/FactoryPatch.cs index 13706bd..3fc29e3 100644 --- a/CheatEnabler/Patches/FactoryPatch.cs +++ b/CheatEnabler/Patches/FactoryPatch.cs @@ -10,7 +10,7 @@ using UXAssist.Common; namespace CheatEnabler.Patches; -public static class FactoryPatch +public class FactoryPatch: PatchImpl { public static ConfigEntry ImmediateEnabled; public static ConfigEntry ArchitectModeEnabled; @@ -30,13 +30,11 @@ public static class FactoryPatch public static ConfigEntry GreaterPowerUsageInLogisticsEnabled; public static ConfigEntry ControlPanelRemoteLogisticsEnabled; - private static Harmony _factoryPatch; private static PressKeyBind _noConditionKey; private static PressKeyBind _noCollisionKey; public static void Init() { - if (_factoryPatch != null) return; _noConditionKey = KeyBindings.RegisterKeyBinding(new BuiltinKey { key = new CombineKey(0, 0, ECombineKeyAction.OnceClick, true), @@ -55,10 +53,13 @@ public static class FactoryPatch ); I18N.Add("KEYToggleNoCondition", "Toggle No Condition Build", "切换无条件建造"); I18N.Add("KEYToggleNoCollision", "Toggle No Collision", "切换无碰撞"); - I18N.Add("NoConditionOn", "No condition build is enabled!", "无条件建造已启用"); - I18N.Add("NoConditionOff", "No condition build is disabled!", "无条件建造已禁用"); - I18N.Add("NoCollisionOn", "No collision is enabled!", "无碰撞已启用"); - I18N.Add("NoCollisionOff", "No collision is disabled!", "无碰撞已禁用"); + I18N.Add("NoConditionOn", "No condition build is enabled!", "无条件建造已开启"); + I18N.Add("NoConditionOff", "No condition build is disabled!", "无条件建造已关闭"); + I18N.Add("NoCollisionOn", "No collision is enabled!", "无碰撞已开启"); + I18N.Add("NoCollisionOff", "No collision is disabled!", "无碰撞已关闭"); + I18N.Add("Build without condition is enabled!", "!!Build without condition is enabled!!", "!!无条件建造已开启!!"); + I18N.Add("No collision is enabled!", "!!No collision is enabled!!", "!!无碰撞已开启!!"); + ImmediateEnabled.SettingChanged += (_, _) => ImmediateBuild.Enable(ImmediateEnabled.Value); ArchitectModeEnabled.SettingChanged += (_, _) => ArchitectMode.Enable(ArchitectModeEnabled.Value); NoConditionEnabled.SettingChanged += (_, _) => NoConditionBuild.Enable(NoConditionEnabled.Value); @@ -73,6 +74,10 @@ public static class FactoryPatch WindTurbinesPowerGlobalCoverageEnabled.SettingChanged += (_, _) => WindTurbinesPowerGlobalCoverage.Enable(WindTurbinesPowerGlobalCoverageEnabled.Value); GreaterPowerUsageInLogisticsEnabled.SettingChanged += (_, _) => GreaterPowerUsageInLogistics.Enable(GreaterPowerUsageInLogisticsEnabled.Value); ControlPanelRemoteLogisticsEnabled.SettingChanged += (_, _) => ControlPanelRemoteLogistics.Enable(ControlPanelRemoteLogisticsEnabled.Value); + } + + public static void Start() + { ImmediateBuild.Enable(ImmediateEnabled.Value); ArchitectMode.Enable(ArchitectModeEnabled.Value); NoConditionBuild.Enable(NoConditionEnabled.Value); @@ -85,7 +90,7 @@ public static class FactoryPatch BoostGeothermalPower.Enable(BoostGeothermalPowerEnabled.Value); GreaterPowerUsageInLogistics.Enable(GreaterPowerUsageInLogisticsEnabled.Value); ControlPanelRemoteLogistics.Enable(ControlPanelRemoteLogisticsEnabled.Value); - _factoryPatch = Harmony.CreateAndPatchAll(typeof(FactoryPatch)); + Enable(true); GameLogic.OnGameBegin += GameMain_Begin_Postfix_For_ImmBuild; GameLogic.OnDataLoaded += () => WindTurbinesPowerGlobalCoverage.Enable(WindTurbinesPowerGlobalCoverageEnabled.Value); } @@ -93,8 +98,7 @@ public static class FactoryPatch public static void Uninit() { GameLogic.OnGameBegin -= GameMain_Begin_Postfix_For_ImmBuild; - _factoryPatch?.UnpatchSelf(); - _factoryPatch = null; + Enable(false); ImmediateBuild.Enable(false); ArchitectMode.Enable(false); NoConditionBuild.Enable(false); @@ -136,6 +140,7 @@ public static class FactoryPatch var obj = coll.gameObject; if (obj == null) return; obj.gameObject.SetActive(!NoCollisionEnabled.Value); + GameMain.data?.warningSystem?.UpdateCriticalWarningText(); } public static void ArrivePlanet(PlanetFactory factory) @@ -193,13 +198,23 @@ public static class FactoryPatch private static IEnumerable WarningSystem_hasCriticalWarning_Transpiler(IEnumerable instructions, ILGenerator generator) { var matcher = new CodeMatcher(instructions, generator); + var label1 = generator.DefineLabel(); + var label2 = generator.DefineLabel(); matcher.End().MatchBack(false, new CodeMatch(OpCodes.Ret) - ); + ).RemoveInstructions(1); matcher.InsertAndAdvance( - new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(FactoryPatch), nameof(NoConditionEnabled))), + new CodeInstruction(OpCodes.Brfalse, label1), + new CodeInstruction(OpCodes.Ldc_I4_1), + new CodeInstruction(OpCodes.Ret), + new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(FactoryPatch), nameof(NoConditionEnabled))).WithLabels(label1), new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(ConfigEntry), nameof(ConfigEntry.Value))), - new CodeInstruction(OpCodes.Or) + new CodeInstruction(OpCodes.Brfalse, label2), + new CodeInstruction(OpCodes.Ldc_I4_1), + new CodeInstruction(OpCodes.Ret), + new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(FactoryPatch), nameof(NoCollisionEnabled))).WithLabels(label2), + new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(ConfigEntry), nameof(ConfigEntry.Value))), + new CodeInstruction(OpCodes.Ret) ); return matcher.InstructionEnumeration(); } @@ -211,61 +226,54 @@ public static class FactoryPatch var matcher = new CodeMatcher(instructions, generator); matcher.MatchForward(false, new CodeMatch(OpCodes.Ldarg_0), - new CodeMatch(OpCodes.Ldstr), + new CodeMatch(OpCodes.Ldstr, ""), new CodeMatch(OpCodes.Call, AccessTools.PropertySetter(typeof(WarningSystem), nameof(WarningSystem.criticalWarningTexts))) ); matcher.Repeat(m => { var label1 = generator.DefineLabel(); - var label2 = generator.DefineLabel(); - m.Advance(1).Labels.Add(label1); - m.InsertAndAdvance( - new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(FactoryPatch), nameof(NoConditionEnabled))), - new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(ConfigEntry), nameof(ConfigEntry.Value))), - new CodeInstruction(OpCodes.Brfalse, label1), - new CodeInstruction(OpCodes.Ldstr, "Build without condition is enabled!"), - new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Localization), nameof(Localization.Translate), [typeof(string)])), - new CodeInstruction(OpCodes.Ldstr, "\r\n"), - new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(string), nameof(string.Concat), [typeof(string), typeof(string)])), - new CodeInstruction(OpCodes.Call, AccessTools.PropertySetter(typeof(WarningSystem), nameof(WarningSystem.criticalWarningTexts))) + m.Advance(1).RemoveInstructions(2).InsertAndAdvance( + Transpilers.EmitDelegate((WarningSystem w) => + { + if (NoConditionEnabled.Value) + { + CheatEnabler.Logger.LogDebug("A"); + w.criticalWarningTexts = "Build without condition is enabled!".Translate() + "\r\n"; + } + else if (NoCollisionEnabled.Value) + { + CheatEnabler.Logger.LogDebug("B"); + w.criticalWarningTexts = "No collision is enabled!".Translate() + "\r\n"; + } + CheatEnabler.Logger.LogDebug("C"); + } + ) ); - if (m.InstructionAt(2).opcode == OpCodes.Ret) + if (m.Opcode == OpCodes.Ret) { m.InsertAndAdvance( new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(WarningSystem), nameof(WarningSystem.onCriticalWarningTextChanged))), - new CodeInstruction(OpCodes.Brfalse_S, label2), + new CodeInstruction(OpCodes.Brfalse_S, label1), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(WarningSystem), nameof(WarningSystem.onCriticalWarningTextChanged))), new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Action), nameof(Action.Invoke))) ); + m.Labels.Add(label1); } - m.InsertAndAdvance( - new CodeInstruction(OpCodes.Br, label2) - ).Advance(2).Labels.Add(label2); }); return matcher.InstructionEnumeration(); } - private static class ImmediateBuild + private class ImmediateBuild: PatchImpl { - private static Harmony _immediatePatch; - - public static void Enable(bool enable) + protected override void OnEnable() { - if (enable) + var factory = GameMain.mainPlayer?.factory; + if (factory != null) { - if (_immediatePatch != null) return; - var factory = GameMain.mainPlayer?.factory; - if (factory != null) - { - ArrivePlanet(factory); - } - _immediatePatch = Harmony.CreateAndPatchAll(typeof(ImmediateBuild)); - return; + ArrivePlanet(factory); } - _immediatePatch?.UnpatchSelf(); - _immediatePatch = null; } [HarmonyTranspiler] @@ -369,19 +377,16 @@ public static class FactoryPatch } } - private static class NoConditionBuild + private class NoConditionBuild: PatchImpl { - private static Harmony _noConditionPatch; - public static void Enable(bool on) + protected override void OnEnable() + { + GameMain.data?.warningSystem?.UpdateCriticalWarningText(); + } + + protected override void OnDisable() { GameMain.data?.warningSystem?.UpdateCriticalWarningText(); - if (on) - { - _noConditionPatch ??= Harmony.CreateAndPatchAll(typeof(NoConditionBuild)); - return; - } - _noConditionPatch?.UnpatchSelf(); - _noConditionPatch = null; } [HarmonyTranspiler, HarmonyPriority(Priority.Last)] @@ -460,9 +465,8 @@ public static class FactoryPatch } } - public static class BeltSignalGenerator + public class BeltSignalGenerator: PatchImpl { - private static Harmony _beltSignalPatch; private static Dictionary[] _signalBelts; private static Dictionary _portalFrom; private static Dictionary> _portalTo; @@ -480,18 +484,15 @@ public static class FactoryPatch public float[] SourceProgress; } - public static void Enable(bool on) + protected override void OnEnable() + { + InitSignalBelts(); + GameLogic.OnGameBegin += GameMain_Begin_Postfix; + } + + protected override void OnDisable() { - if (on) - { - InitSignalBelts(); - _beltSignalPatch ??= Harmony.CreateAndPatchAll(typeof(BeltSignalGenerator)); - GameLogic.OnGameBegin += GameMain_Begin_Postfix; - return; - } GameLogic.OnGameBegin -= GameMain_Begin_Postfix; - _beltSignalPatch?.UnpatchSelf(); - _beltSignalPatch = null; _initialized = false; _signalBelts = null; _signalBeltsCapacity = 0; diff --git a/CheatEnabler/Patches/GamePatch.cs b/CheatEnabler/Patches/GamePatch.cs index ccb30e3..c3f9ea9 100644 --- a/CheatEnabler/Patches/GamePatch.cs +++ b/CheatEnabler/Patches/GamePatch.cs @@ -19,6 +19,10 @@ public static class GamePatch DevShortcutsEnabled.SettingChanged += (_, _) => DevShortcuts.Enable(DevShortcutsEnabled.Value); AbnormalDisablerEnabled.SettingChanged += (_, _) => AbnormalDisabler.Enable(AbnormalDisablerEnabled.Value); UnlockTechEnabled.SettingChanged += (_, _) => UnlockTech.Enable(UnlockTechEnabled.Value); + } + + public static void Start() + { DevShortcuts.Enable(DevShortcutsEnabled.Value); AbnormalDisabler.Enable(AbnormalDisablerEnabled.Value); UnlockTech.Enable(UnlockTechEnabled.Value); diff --git a/CheatEnabler/Patches/PlanetPatch.cs b/CheatEnabler/Patches/PlanetPatch.cs index 986294b..7799b9a 100644 --- a/CheatEnabler/Patches/PlanetPatch.cs +++ b/CheatEnabler/Patches/PlanetPatch.cs @@ -15,6 +15,10 @@ public static class PlanetPatch { WaterPumpAnywhereEnabled.SettingChanged += (_, _) => WaterPumperPatch.Enable(WaterPumpAnywhereEnabled.Value); TerraformAnywayEnabled.SettingChanged += (_, _) => TerraformAnyway.Enable(TerraformAnywayEnabled.Value); + } + + public static void Start() + { WaterPumperPatch.Enable(WaterPumpAnywhereEnabled.Value); TerraformAnyway.Enable(TerraformAnywayEnabled.Value); } diff --git a/CheatEnabler/Patches/PlayerPatch.cs b/CheatEnabler/Patches/PlayerPatch.cs index c719ee7..b97ed7e 100644 --- a/CheatEnabler/Patches/PlayerPatch.cs +++ b/CheatEnabler/Patches/PlayerPatch.cs @@ -15,6 +15,10 @@ public static class PlayerPatch { InstantTeleportEnabled.SettingChanged += (_, _) => InstantTeleport.Enable(InstantTeleportEnabled.Value); WarpWithoutSpaceWarpersEnabled.SettingChanged += (_, _) => WarpWithoutSpaceWarpers.Enable(WarpWithoutSpaceWarpersEnabled.Value); + } + + public static void Start() + { InstantTeleport.Enable(InstantTeleportEnabled.Value); WarpWithoutSpaceWarpers.Enable(WarpWithoutSpaceWarpersEnabled.Value); } diff --git a/CheatEnabler/Patches/ResourcePatch.cs b/CheatEnabler/Patches/ResourcePatch.cs index 9ced6f0..a7cdcd6 100644 --- a/CheatEnabler/Patches/ResourcePatch.cs +++ b/CheatEnabler/Patches/ResourcePatch.cs @@ -15,6 +15,10 @@ public static class ResourcePatch { InfiniteResourceEnabled.SettingChanged += (_, _) => InfiniteResource.Enable(InfiniteResourceEnabled.Value); FastMiningEnabled.SettingChanged += (_, _) => FastMining.Enable(FastMiningEnabled.Value); + } + + public static void Start() + { InfiniteResource.Enable(InfiniteResourceEnabled.Value); FastMining.Enable(FastMiningEnabled.Value); } diff --git a/CheatEnabler/UIConfigWindow.cs b/CheatEnabler/UIConfigWindow.cs index ec11512..b07062d 100644 --- a/CheatEnabler/UIConfigWindow.cs +++ b/CheatEnabler/UIConfigWindow.cs @@ -36,7 +36,6 @@ public static class UIConfigWindow I18N.Add("Finish build immediately", "Finish build immediately", "建造秒完成"); I18N.Add("Architect mode", "Architect mode", "建筑师模式"); I18N.Add("Build without condition", "Build without condition check", "无条件建造"); - I18N.Add("Build without condition is enabled!", "!!Build without condition is enabled!!", "!!无条件建造已开启!!"); I18N.Add("No collision", "No collision", "无碰撞"); I18N.Add("Belt signal generator", "Belt signal generator", "传送带信号物品生成"); I18N.Add("Belt signal alt format", "Belt signal alt format", "传送带信号替换格式"); diff --git a/UXAssist/Common/GameLogic.cs b/UXAssist/Common/GameLogic.cs index c305950..1f37673 100644 --- a/UXAssist/Common/GameLogic.cs +++ b/UXAssist/Common/GameLogic.cs @@ -3,24 +3,12 @@ using HarmonyLib; namespace UXAssist.Common; -public static class GameLogic +public class GameLogic: PatchImpl { - private static Harmony _harmony; public static Action OnDataLoaded; public static Action OnGameBegin; public static Action OnGameEnd; - public static void Init() - { - _harmony ??= Harmony.CreateAndPatchAll(typeof(GameLogic)); - } - - public static void Uninit() - { - _harmony?.UnpatchSelf(); - _harmony = null; - } - [HarmonyPostfix] [HarmonyPatch(typeof(VFPreload), nameof(VFPreload.InvokeOnLoadWorkEnded))] public static void VFPreload_InvokeOnLoadWorkEnded_Postfix() diff --git a/UXAssist/Common/PatchImpl.cs b/UXAssist/Common/PatchImpl.cs index b666105..206bc26 100644 --- a/UXAssist/Common/PatchImpl.cs +++ b/UXAssist/Common/PatchImpl.cs @@ -1,7 +1,15 @@ -using HarmonyLib; +using System; +using System.Reflection; +using HarmonyLib; namespace UXAssist.Common; +[AttributeUsage(AttributeTargets.Class, Inherited = false)] +public class PatchImplGuidAttribute(string guid) : Attribute +{ + public string Guid { get; } = guid; +} + public class PatchImpl where T : new() { private static T Instance { get; } = new(); @@ -17,7 +25,8 @@ public class PatchImpl where T : new() } if (enable) { - thisInstance._patch ??= Harmony.CreateAndPatchAll(typeof(T)); + var guid = typeof(T).GetCustomAttribute()?.Guid; + thisInstance._patch ??= Harmony.CreateAndPatchAll(typeof(T), guid); thisInstance.OnEnable(); return; } @@ -26,7 +35,7 @@ public class PatchImpl where T : new() thisInstance._patch = null; } - protected static Harmony GetPatch() => (Instance as PatchImpl)?._patch; + public static Harmony GetHarmony() => (Instance as PatchImpl)?._patch; protected virtual void OnEnable() { } protected virtual void OnDisable() { } diff --git a/UXAssist/Common/Util.cs b/UXAssist/Common/Util.cs index f36e3ec..db8d386 100644 --- a/UXAssist/Common/Util.cs +++ b/UXAssist/Common/Util.cs @@ -8,11 +8,13 @@ namespace UXAssist.Common; public static class Util { - public static Type[] GetTypesInNamespace(Assembly assembly, string nameSpace) + public static Type[] GetTypesFiltered(Assembly assembly, Func predicate) { - return assembly.GetTypes().Where(t => string.Equals(t.Namespace, nameSpace, StringComparison.Ordinal)).ToArray(); + return assembly.GetTypes().Where(predicate).ToArray(); } + public static Type[] GetTypesInNamespace(Assembly assembly, string nameSpace) => GetTypesFiltered(assembly, t => string.Equals(t.Namespace, nameSpace, StringComparison.Ordinal)); + public static byte[] LoadEmbeddedResource(string path, Assembly assembly = null) { if (assembly == null) diff --git a/UXAssist/ModsCompat/BulletTimeWrapper.cs b/UXAssist/ModsCompat/BulletTimeWrapper.cs index 787c977..b6f482c 100644 --- a/UXAssist/ModsCompat/BulletTimeWrapper.cs +++ b/UXAssist/ModsCompat/BulletTimeWrapper.cs @@ -35,7 +35,6 @@ public static class BulletTimeWrapper matcher.MatchForward(false, new CodeMatch(OpCodes.Ldstr, "Increase game speed (max 4x)") ).Set(OpCodes.Ldstr, "Increase game speed (max 10x)"); - UXAssist.Logger.LogDebug($"Patched IngameUI.Init @ {matcher.Pos}"); return matcher.InstructionEnumeration(); } @@ -45,7 +44,6 @@ public static class BulletTimeWrapper matcher.MatchForward(false, new CodeMatch(OpCodes.Ldc_R8, 240.0) ).Set(OpCodes.Ldc_R8, 600.0); - UXAssist.Logger.LogDebug($"Patched IngameUI.OnSpeedButtonClick @ {matcher.Pos}"); return matcher.InstructionEnumeration(); } diff --git a/UXAssist/Patches/DysonSpherePatch.cs b/UXAssist/Patches/DysonSpherePatch.cs index 30a3fad..d7493ee 100644 --- a/UXAssist/Patches/DysonSpherePatch.cs +++ b/UXAssist/Patches/DysonSpherePatch.cs @@ -7,19 +7,18 @@ using UXAssist.Common; namespace UXAssist.Patches; -public static class DysonSpherePatch +public class DysonSpherePatch: PatchImpl { public static ConfigEntry StopEjectOnNodeCompleteEnabled; public static ConfigEntry OnlyConstructNodesEnabled; public static ConfigEntry AutoConstructMultiplier; - private static Harmony _dysonSpherePatch; private static FieldInfo _totalNodeSpInfo, _totalFrameSpInfo, _totalCpInfo; public static void Init() { I18N.Add("[UXAssist] No node to fill", "[UXAssist] No node to fill", "[UXAssist] 无可建造节点"); - _dysonSpherePatch ??= Harmony.CreateAndPatchAll(typeof(DysonSpherePatch)); + Enable(true); StopEjectOnNodeCompleteEnabled.SettingChanged += (_, _) => StopEjectOnNodeComplete.Enable(StopEjectOnNodeCompleteEnabled.Value); OnlyConstructNodesEnabled.SettingChanged += (_, _) => OnlyConstructNodes.Enable(OnlyConstructNodesEnabled.Value); StopEjectOnNodeComplete.Enable(StopEjectOnNodeCompleteEnabled.Value); @@ -33,8 +32,7 @@ public static class DysonSpherePatch { StopEjectOnNodeComplete.Enable(false); OnlyConstructNodes.Enable(false); - _dysonSpherePatch?.UnpatchSelf(); - _dysonSpherePatch = null; + Enable(false); } public static void InitCurrentDysonSphere(int index) diff --git a/UXAssist/Patches/FactoryPatch.cs b/UXAssist/Patches/FactoryPatch.cs index 8244857..d11b9ea 100644 --- a/UXAssist/Patches/FactoryPatch.cs +++ b/UXAssist/Patches/FactoryPatch.cs @@ -12,7 +12,7 @@ using UXAssist.Common; namespace UXAssist.Patches; -public static class FactoryPatch +public class FactoryPatch: PatchImpl { public static ConfigEntry UnlimitInteractiveEnabled; public static ConfigEntry RemoveSomeConditionEnabled; @@ -29,8 +29,6 @@ public static class FactoryPatch public static ConfigEntry BeltSignalsForBuyOutEnabled; private static PressKeyBind _doNotRenderEntitiesKey; - private static Harmony _factoryPatch; - public static void Init() { _doNotRenderEntitiesKey = KeyBindings.RegisterKeyBinding(new BuiltinKey @@ -71,11 +69,13 @@ public static class FactoryPatch DragBuildPowerPoles.Enable(DragBuildPowerPolesEnabled.Value); BeltSignalsForBuyOut.Enable(BeltSignalsForBuyOutEnabled.Value); - _factoryPatch ??= Harmony.CreateAndPatchAll(typeof(FactoryPatch)); + Enable(true); } public static void Uninit() { + Enable(false); + RemoveSomeConditionBuild.Enable(false); UnlimitInteractive.Enable(false); NightLight.Enable(false); @@ -90,9 +90,6 @@ public static class FactoryPatch DragBuildPowerPoles.Enable(false); BeltSignalsForBuyOut.Enable(false); BeltSignalsForBuyOut.UninitPersist(); - - _factoryPatch?.UnpatchSelf(); - _factoryPatch = null; } public static void OnUpdate() @@ -1324,7 +1321,7 @@ public static class FactoryPatch private static void UnfixProto() { - if (GetPatch() == null || OldDragBuild.Count < 3 || DSPGame.IsMenuDemo) return; + if (GetHarmony() == null || OldDragBuild.Count < 3 || DSPGame.IsMenuDemo) return; var i = 0; foreach (var id in PowerPoleIds) { diff --git a/UXAssist/Patches/GamePatch.cs b/UXAssist/Patches/GamePatch.cs index 53cf869..226f4d1 100644 --- a/UXAssist/Patches/GamePatch.cs +++ b/UXAssist/Patches/GamePatch.cs @@ -9,7 +9,7 @@ using UXAssist.Common; namespace UXAssist.Patches; -public static class GamePatch +public class GamePatch: PatchImpl { private const string GameWindowClass = "UnityWndClass"; private static string _gameWindowTitle = "Dyson Sphere Program"; @@ -50,8 +50,6 @@ public static class GamePatch } } - private static Harmony _gamePatch; - public static void Init() { // Get profile name from command line arguments, and set window title accordingly @@ -104,19 +102,18 @@ public static class GamePatch MouseCursorScaleUp.Enable(MouseCursorScaleUpMultiplier.Value > 1); // AutoSaveOpt.Enable(AutoSaveOptEnabled.Value); ConvertSavesFromPeace.Enable(ConvertSavesFromPeaceEnabled.Value); - _gamePatch ??= Harmony.CreateAndPatchAll(typeof(GamePatch)); + Enable(true); } public static void Uninit() { + Enable(false); LoadLastWindowRect.Enable(false); EnableWindowResize.Enable(false); MouseCursorScaleUp.reload = false; MouseCursorScaleUp.Enable(false); // AutoSaveOpt.Enable(false); ConvertSavesFromPeace.Enable(false); - _gamePatch?.UnpatchSelf(); - _gamePatch = null; } private static void RefreshSavePath() @@ -341,21 +338,11 @@ public static class GamePatch } /* - private static class AutoSaveOpt + private class AutoSaveOpt: PatchImpl { - private static Harmony _patch; - - public static void Enable(bool on) + protected override void OnEnable() { - if (on) - { - Directory.CreateDirectory(GameConfig.gameSaveFolder + "AutoSaves/"); - _patch ??= Harmony.CreateAndPatchAll(typeof(AutoSaveOpt)); - return; - } - - _patch?.UnpatchSelf(); - _patch = null; + Directory.CreateDirectory(GameConfig.gameSaveFolder + "AutoSaves/"); } [HarmonyPrefix] diff --git a/UXAssist/UXAssist.cs b/UXAssist/UXAssist.cs index f0ee42d..737bed2 100644 --- a/UXAssist/UXAssist.cs +++ b/UXAssist/UXAssist.cs @@ -29,11 +29,10 @@ public class UXAssist : BaseUnityPlugin, IModCanSave private static bool _configWinInitialized; private static MyConfigWindow _configWin; - private static Harmony _patch; - private static Harmony _persistPatch; private static bool _initialized; private static PressKeyBind _toggleKey; private static ConfigFile _dummyConfig; + private Type[] _patches; #region IModCanSave private const ushort ModSaveVersion = 1; @@ -152,47 +151,46 @@ public class UXAssist : BaseUnityPlugin, IModCanSave DysonSpherePatch.AutoConstructMultiplier = Config.Bind("DysonSphere", "AutoConstructMultiplier", 1, "Dyson Sphere auto-construct speed multiplier"); I18N.Init(); - } - - private void Start() - { I18N.Add("UXAssist Config", "UXAssist Config", "UX助手设置"); I18N.Add("KEYOpenUXAssistConfigWindow", "Open UXAssist Config Window", "打开UX助手设置面板"); I18N.Add("KEYToggleAutoCruise", "Toggle auto-cruise", "切换自动巡航"); - // UI Patch - _patch ??= Harmony.CreateAndPatchAll(typeof(UXAssist), PluginInfo.PLUGIN_GUID); - _persistPatch ??= Harmony.CreateAndPatchAll(typeof(Persist)); + // UI Patches + UIPatch.Enable(true); - GameLogic.Init(); + // Persistant Patches + Persist.Enable(true); + GameLogic.Enable(true); MyWindowManager.Init(); UIConfigWindow.Init(); - Common.Util.GetTypesInNamespace(Assembly.GetExecutingAssembly(), "UXAssist.Patches") - .Do(type => type.GetMethod("Init")?.Invoke(null, null)); + _patches = Common.Util.GetTypesInNamespace(Assembly.GetExecutingAssembly(), "UXAssist.Patches"); + _patches?.Do(type => type.GetMethod("Init")?.Invoke(null, null)); - ModsCompat.AuxilaryfunctionWrapper.Init(_patch); - ModsCompat.BulletTimeWrapper.Init(_patch); + var patch = UIPatch.GetHarmony(); + ModsCompat.AuxilaryfunctionWrapper.Init(patch); + ModsCompat.BulletTimeWrapper.Init(patch); I18N.Apply(); I18N.OnInitialized += RecreateConfigWindow; - + } + + private void Start() + { + _patches?.Do(type => type.GetMethod("Start")?.Invoke(null, null)); LogisticsPatch.Start(); } private void OnDestroy() { - Common.Util.GetTypesInNamespace(Assembly.GetExecutingAssembly(), "UXAssist.Patches") - .Do(type => type.GetMethod("Uninit")?.Invoke(null, null)); + _patches?.Do(type => type.GetMethod("Uninit")?.Invoke(null, null)); MyWindowManager.Uninit(); - GameLogic.Uninit(); - _patch?.UnpatchSelf(); - _patch = null; - _persistPatch?.UnpatchSelf(); - _persistPatch = null; + GameLogic.Enable(false); + Persist.Enable(false); + UIPatch.Enable(false); } private void Update() @@ -245,66 +243,90 @@ public class UXAssist : BaseUnityPlugin, IModCanSave if (wasActive) ToggleConfigWindow(); } - // Add config button to main menu - [HarmonyPostfix, HarmonyPatch(typeof(UIRoot), nameof(UIRoot.OpenMainMenuUI))] - public static void UIRoot_OpenMainMenuUI_Postfix() + [PatchImplGuid(PluginInfo.PLUGIN_GUID)] + private class UIPatch: PatchImpl { - if (_initialized) return; + private static GameObject _buttonOnPlanetGlobe; + + // Add config button to main menu + [HarmonyPostfix, HarmonyPatch(typeof(UIRoot), nameof(UIRoot.OpenMainMenuUI))] + public static void UIRoot_OpenMainMenuUI_Postfix() { - var mainMenu = UIRoot.instance.uiMainMenu; - var src = mainMenu.newGameButton; - var parent = src.transform.parent; - var btn = Instantiate(src, parent); - btn.name = "button-cheatenabler-config"; - var l = btn.text.GetComponent(); - if (l != null) + if (_initialized) return; { - l.stringKey = "UXAssist Config"; - l.translation = "UXAssist Config".Translate(); + var mainMenu = UIRoot.instance.uiMainMenu; + var src = mainMenu.newGameButton; + var parent = src.transform.parent; + var btn = Instantiate(src, parent); + btn.name = "button-cheatenabler-config"; + var l = btn.text.GetComponent(); + if (l != null) + { + l.stringKey = "UXAssist Config"; + l.translation = "UXAssist Config".Translate(); + } + + btn.text.text = "UXAssist Config".Translate(); + btn.text.fontSize = btn.text.fontSize * 7 / 8; + I18N.OnInitialized += () => { btn.text.text = "UXAssist Config".Translate(); }; + var vec = ((RectTransform)mainMenu.exitButton.transform).anchoredPosition3D; + var vec2 = ((RectTransform)mainMenu.creditsButton.transform).anchoredPosition3D; + var transform1 = (RectTransform)btn.transform; + transform1.anchoredPosition3D = new Vector3(vec.x, vec.y + (vec.y - vec2.y) * 2, vec.z); + btn.button.onClick.RemoveAllListeners(); + btn.button.onClick.AddListener(ToggleConfigWindow); } - btn.text.text = "UXAssist Config".Translate(); - btn.text.fontSize = btn.text.fontSize * 7 / 8; - I18N.OnInitialized += () => { btn.text.text = "UXAssist Config".Translate(); }; - var vec = ((RectTransform)mainMenu.exitButton.transform).anchoredPosition3D; - var vec2 = ((RectTransform)mainMenu.creditsButton.transform).anchoredPosition3D; - var transform1 = (RectTransform)btn.transform; - transform1.anchoredPosition3D = new Vector3(vec.x, vec.y + (vec.y - vec2.y) * 2, vec.z); - btn.button.onClick.RemoveAllListeners(); - btn.button.onClick.AddListener(ToggleConfigWindow); + { + var panel = UIRoot.instance.uiGame.planetGlobe; + var src = panel.button2; + var sandboxMenu = UIRoot.instance.uiGame.sandboxMenu; + var icon = sandboxMenu.categoryButtons[6].transform.Find("icon")?.GetComponent()?.sprite; + var b = Instantiate(src, src.transform.parent); + _buttonOnPlanetGlobe = b.gameObject; + var rect = (RectTransform)_buttonOnPlanetGlobe.transform; + var btn = _buttonOnPlanetGlobe.GetComponent(); + var img = _buttonOnPlanetGlobe.transform.Find("button-2/icon")?.GetComponent(); + if (img != null) + { + img.sprite = icon; + } + + if (_buttonOnPlanetGlobe != null && btn != null) + { + _buttonOnPlanetGlobe.name = "open-uxassist-config"; + rect.localScale = new Vector3(0.6f, 0.6f, 0.6f); + rect.anchoredPosition3D = new Vector3(64f, -5f, 0f); + b.onClick.RemoveAllListeners(); + btn.onClick += _ => { ToggleConfigWindow(); }; + btn.tips.tipTitle = "UXAssist Config"; + I18N.OnInitialized += () => { btn.tips.tipTitle = "UXAssist Config".Translate(); }; + btn.tips.tipText = null; + btn.tips.corner = 9; + btn.tips.offset = new Vector2(-20f, -20f); + _buttonOnPlanetGlobe.SetActive(true); + } + } + _initialized = true; } + + [HarmonyPostfix] + [HarmonyPatch(typeof(UIPlanetGlobe), nameof(UIPlanetGlobe.DistributeButtons))] + private static void UIPlanetGlobe_DistributeButtons_Postfix(UIPlanetGlobe __instance) { - var panel = UIRoot.instance.uiGame.planetGlobe; - var src = panel.button2; - var sandboxMenu = UIRoot.instance.uiGame.sandboxMenu; - var icon = sandboxMenu.categoryButtons[6].transform.Find("icon")?.GetComponent()?.sprite; - var b = Instantiate(src, src.transform.parent); - var panelButtonGo = b.gameObject; - var rect = (RectTransform)panelButtonGo.transform; - var btn = panelButtonGo.GetComponent(); - var img = panelButtonGo.transform.Find("button-2/icon")?.GetComponent(); - if (img != null) + if (_buttonOnPlanetGlobe == null) return; + var rect = (RectTransform)_buttonOnPlanetGlobe.transform; + if (__instance.dysonSphereSystemUnlocked || __instance.logisticsSystemUnlocked) { - img.sprite = icon; - } - if (panelButtonGo != null && btn != null) - { - panelButtonGo.name = "open-uxassist-config"; - rect.localScale = new Vector3(0.6f, 0.6f, 0.6f); rect.anchoredPosition3D = new Vector3(64f, -5f, 0f); - b.onClick.RemoveAllListeners(); - btn.onClick += _ => { ToggleConfigWindow(); }; - btn.tips.tipTitle = "UXAssist Config"; - I18N.OnInitialized += () => { btn.tips.tipTitle = "UXAssist Config".Translate(); }; - btn.tips.tipText = null; - btn.tips.corner = 9; - btn.tips.offset = new Vector2(-20f, -20f); - panelButtonGo.SetActive(true); + } + else + { + rect.anchoredPosition3D = new Vector3(128f, -100f, 0f); } } - _initialized = true; } - private static class Persist + private class Persist: PatchImpl { // Check for noModifier while pressing hotkeys on build bar [HarmonyTranspiler]