From 36999392cffecc098a57bc2fbec6b33f6d1b5b0e Mon Sep 17 00:00:00 2001 From: John Celendro Date: Tue, 17 Jun 2025 01:12:53 +0800 Subject: [PATCH 1/4] Created a "simple name arg" flag in command so it's easier to type in the display name of cards. Added commands to trigger events, add enhancers, and modify the current node. --- Stoker.Base/Builder/CommandBuilder.cs | 11 +++ Stoker.Base/Commands/CardCommandFactory.cs | 25 ++++-- Stoker.Base/Commands/EventCommandFactory.cs | 85 ++++++++++++++++++ Stoker.Base/Commands/NodeCommandFactory.cs | 86 +++++++++++++++++++ Stoker.Base/Commands/RelicCommandFactory.cs | 36 ++++++-- Stoker.Base/Commands/UpgradeCommandFactory.cs | 85 ++++++++++++++++++ Stoker.Base/Impl/Command.cs | 8 ++ Stoker.Base/Stoker.Base.csproj | 6 +- Stoker.Plugin/Plugin.cs | 3 + Stoker.Plugin/Stoker.Plugin.csproj | 4 + 10 files changed, 334 insertions(+), 15 deletions(-) create mode 100644 Stoker.Base/Commands/EventCommandFactory.cs create mode 100644 Stoker.Base/Commands/NodeCommandFactory.cs create mode 100644 Stoker.Base/Commands/UpgradeCommandFactory.cs diff --git a/Stoker.Base/Builder/CommandBuilder.cs b/Stoker.Base/Builder/CommandBuilder.cs index 180a710..8cfc1e0 100644 --- a/Stoker.Base/Builder/CommandBuilder.cs +++ b/Stoker.Base/Builder/CommandBuilder.cs @@ -53,6 +53,17 @@ public ArgumentBuilder WithArgument(string name){ return new ArgumentBuilder(this, argument); } + public ArgumentBuilder WithSimpleNameArg() + { + var argument = new Argument + { + Name = "name" + }; + _command.AddArgument(argument); + _command.simpleNameArg = true; + return new ArgumentBuilder(this, argument); + } + /// /// Adds an option to the command. /// diff --git a/Stoker.Base/Commands/CardCommandFactory.cs b/Stoker.Base/Commands/CardCommandFactory.cs index b986a7f..5357a97 100644 --- a/Stoker.Base/Commands/CardCommandFactory.cs +++ b/Stoker.Base/Commands/CardCommandFactory.cs @@ -4,6 +4,7 @@ using Stoker.Base.Extension; using Stoker.Base.Impl; using Stoker.Base.Interfaces; +using System.Reflection; using TrainworksReloaded.Base; using TrainworksReloaded.Core; using TrainworksReloaded.Core.Enum; @@ -21,9 +22,23 @@ public static ICommand Create() .WithDescription("Manage cards") .WithSubCommand("add") .WithDescription("Add a card to the deck") - .WithArgument("name") + .WithSimpleNameArg() .WithDescription("The name of the card to add") - .WithSuggestions(() => [.. Railend.GetContainer().GetInstance>().GetAllIdentifiers(RegisterIdentifierType.ReadableID).Select(c => c.ToString())]) + .WithSuggestions(() => + { + Type type = typeof(CheatManager); + FieldInfo field = type.GetField("allGameData", BindingFlags.NonPublic | BindingFlags.Static); + + if (field != null) + { + AllGameData allGameData = field.GetValue(null) as AllGameData; + if (allGameData != null) + { + return allGameData.GetAllCardData().Select(s => s.Cheat_GetNameEnglish()).ToArray(); + } + } + return []; + }) .WithParser((xs) => xs) .Parent() .SetHandler((args) => @@ -120,7 +135,7 @@ public static ICommand Create() .Parent() .WithOption("page-size") .WithDescription("The number of cards to list per page") - .WithDefaultValue("10") + .WithDefaultValue("50") .WithAliases("ps") .WithParser((xs) => int.Parse(xs)) .Parent() @@ -135,14 +150,14 @@ public static ICommand Create() throw new Exception("Invalid --page option"); if (options["page-size"] is not int pageSize) throw new Exception("Invalid --page-size option"); - var cards = Railend.GetContainer().GetInstance>().GetAllIdentifiers(RegisterIdentifierType.ReadableID); + var cards = Railend.GetContainer().GetInstance>(); var startIndex = (page - 1) * pageSize; var endIndex = startIndex + pageSize; var pageCards = cards.Skip(startIndex).Take(pageSize); LoggerLazy.Value.Log("Cards:"); foreach (var card in pageCards) { - LoggerLazy.Value.Log($" {card}"); + LoggerLazy.Value.Log($"{card.Value.Cheat_GetNameEnglish()} : {card.Value.name}"); } return Task.CompletedTask; }) diff --git a/Stoker.Base/Commands/EventCommandFactory.cs b/Stoker.Base/Commands/EventCommandFactory.cs new file mode 100644 index 0000000..344faf2 --- /dev/null +++ b/Stoker.Base/Commands/EventCommandFactory.cs @@ -0,0 +1,85 @@ +using HarmonyLib; +using ShinyShoe.Loading; +using Stoker.Base.Builder; +using Stoker.Base.Extension; +using Stoker.Base.Impl; +using Stoker.Base.Interfaces; +using System.Reflection; +using TrainworksReloaded.Base; +using TrainworksReloaded.Core; +using TrainworksReloaded.Core.Enum; +using TrainworksReloaded.Core.Interfaces; + +namespace Stoker.Base.Commands +{ + public class EventCommandFactory + { + private static Lazy LoggerLazy { get; set; } = new(() => Railend.GetContainer().GetInstance()); + + public static ICommand Create() + { + var command = new CommandBuilder("event") + .WithDescription("Manage events") + .WithSubCommand("trigger") + .WithDescription("Trigger an event") + .WithSimpleNameArg() + .WithDescription("The name of the event to trigger") + .WithSuggestions(() => + { + Type type = typeof(CheatManager); + FieldInfo field = type.GetField("allGameData", BindingFlags.NonPublic | BindingFlags.Static); + + if (field != null) + { + AllGameData allGameData = field.GetValue(null) as AllGameData; + if (allGameData != null) + { + return allGameData.GetAllStoryEventData().Select(s => s.name).ToArray(); + } + } + return []; + }) + .WithParser((xs) => xs) + .Parent() + .SetHandler((args) => + { + var arguments = args.Arguments; + if (!arguments.ContainsKey("name")) + throw new Exception("Missing argument"); + if (arguments["name"] is not string eventName) + throw new Exception("Invalid argument"); + if (string.IsNullOrEmpty(eventName)) + throw new Exception("Empty argument"); + LoggerLazy.Value.Log($"Trigerring event: {eventName}"); + AccessTools.Method(typeof(CheatManager), "Command_StartEvent").Invoke(null, [eventName]); + return Task.CompletedTask; + }) + .UseHelpMiddleware() + .Parent() + .WithSubCommand("list") + .WithDescription("List all events") + .SetHandler((args) => + { + Type type = typeof(CheatManager); + FieldInfo field = type.GetField("allGameData", BindingFlags.NonPublic | BindingFlags.Static); + + if (field != null) + { + AllGameData allGameData = field.GetValue(null) as AllGameData; + if (allGameData != null) + { + List names = allGameData.GetAllStoryEventData().Select(s => s.name).ToList(); + names.Sort(); + names.ForEach(s => LoggerLazy.Value.Log(s)); + } + } + return Task.CompletedTask; + }) + .UseHelpMiddleware() + .Parent() + .UseHelpMiddleware() + .Build(); + return command; + } + } +} diff --git a/Stoker.Base/Commands/NodeCommandFactory.cs b/Stoker.Base/Commands/NodeCommandFactory.cs new file mode 100644 index 0000000..5bbb7df --- /dev/null +++ b/Stoker.Base/Commands/NodeCommandFactory.cs @@ -0,0 +1,86 @@ +using HarmonyLib; +using Stoker.Base.Builder; +using Stoker.Base.Extension; +using Stoker.Base.Interfaces; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using TrainworksReloaded.Core; + +namespace Stoker.Base.Commands +{ + public class NodeCommandFactory + { + private static Lazy LoggerLazy { get; set; } = new(() => Railend.GetContainer().GetInstance()); + + public static ICommand Create() + { + var command = new CommandBuilder("node") + .WithDescription("Manage nodes") + .WithSubCommand("next") + .WithDescription("Move to the next node") + .SetHandler((args) => + { + LoggerLazy.Value.Log($"Moving to next node"); + AccessTools.Method(typeof(CheatManager), "Command_NextNode").Invoke(null, []); + return Task.CompletedTask; + }) + .UseHelpMiddleware() + .Parent() + .WithSubCommand("prev") + .WithDescription("Move to the previous node") + .SetHandler((args) => + { + LoggerLazy.Value.Log($"Moving to previous node"); + AccessTools.Method(typeof(CheatManager), "Command_PreviousNode").Invoke(null, []); + return Task.CompletedTask; + }) + .UseHelpMiddleware() + .Parent() + .WithSubCommand("final") + .WithDescription("Move to the final node") + .SetHandler((args) => + { + LoggerLazy.Value.Log($"Moving to final node"); + AccessTools.Method(typeof(CheatManager), "Command_FinalNode").Invoke(null, []); + return Task.CompletedTask; + }) + .UseHelpMiddleware() + .Parent() + .WithSubCommand("tfb") + .WithDescription("Move to tfb") + .SetHandler((args) => + { + LoggerLazy.Value.Log($"Moving to tfb"); + AccessTools.Method(typeof(CheatManager), "Command_JumpToTFB").Invoke(null, []); + return Task.CompletedTask; + }) + .UseHelpMiddleware() + .Parent() + .WithSubCommand("reset") + .WithDescription("Reset node") + .SetHandler((args) => + { + LoggerLazy.Value.Log($"Resetting node"); + AccessTools.Method(typeof(CheatManager), "Command_ResetNode").Invoke(null, []); + return Task.CompletedTask; + }) + .UseHelpMiddleware() + .Parent() + .WithSubCommand("side") + .WithDescription("Change to the other side of the node") + .SetHandler((args) => + { + LoggerLazy.Value.Log($"Changing to the other side of the node"); + AccessTools.Method(typeof(CheatManager), "Command_ChangeSides").Invoke(null, []); + return Task.CompletedTask; + }) + .UseHelpMiddleware() + .Parent() + .UseHelpMiddleware() + .Build(); + return command; + } + } +} diff --git a/Stoker.Base/Commands/RelicCommandFactory.cs b/Stoker.Base/Commands/RelicCommandFactory.cs index b54aa82..4be7ed8 100644 --- a/Stoker.Base/Commands/RelicCommandFactory.cs +++ b/Stoker.Base/Commands/RelicCommandFactory.cs @@ -3,6 +3,7 @@ using Stoker.Base.Builder; using Stoker.Base.Extension; using Stoker.Base.Interfaces; +using System.Reflection; using TrainworksReloaded.Core; using TrainworksReloaded.Core.Enum; using TrainworksReloaded.Core.Interfaces; @@ -18,12 +19,27 @@ public static ICommand Create() .WithDescription("Manage relics") .WithSubCommand("add") .WithDescription("Add a relic to the deck") - .WithArgument("name") + .WithSimpleNameArg() .WithDescription("The name of the relic to add") - .WithSuggestions(() => [.. Railend.GetContainer().GetInstance>().GetAllIdentifiers(RegisterIdentifierType.ReadableID).Select(c => c.ToString())]) + .WithSuggestions(() => + { + Type type = typeof(CheatManager); + FieldInfo field = type.GetField("allGameData", BindingFlags.NonPublic | BindingFlags.Static); + + if (field != null) + { + AllGameData allGameData = field.GetValue(null) as AllGameData; + if (allGameData != null) + { + return allGameData.GetAllCollectableRelicData().Select(s => s.Cheat_GetNameEnglish()).ToArray(); + } + } + return []; + }) .WithParser((xs) => xs) .Parent() - .SetHandler((args) => { + .SetHandler((args) => + { var arguments = args.Arguments; if (!arguments.ContainsKey("name")) throw new Exception("Missing argument"); @@ -41,10 +57,11 @@ public static ICommand Create() .WithDescription("Remove a relic from the deck") .WithArgument("name") .WithDescription("The name of the relic to remove") - .WithSuggestions(() => [.. Railend.GetContainer().GetInstance>().GetAllIdentifiers(RegisterIdentifierType.ReadableID).Select(c => c.ToString())]) + .WithSuggestions(() => [.. Railend.GetContainer().GetInstance>().Select(c => c.Value.name)]) .WithParser((xs) => xs) .Parent() - .SetHandler((args) => { + .SetHandler((args) => + { var arguments = args.Arguments; if (!arguments.ContainsKey("name")) throw new Exception("Missing argument"); @@ -68,11 +85,12 @@ public static ICommand Create() .Parent() .WithOption("page-size") .WithDescription("The number of relics to list per page") - .WithDefaultValue("10") + .WithDefaultValue("50") .WithAliases("ps") .WithParser((xs) => int.Parse(xs)) .Parent() - .SetHandler((args) => { + .SetHandler((args) => + { var options = args.Options; if (!options.ContainsKey("page")) throw new Exception("Missing --page option"); @@ -82,14 +100,14 @@ public static ICommand Create() throw new Exception("Invalid --page option"); if (options["page-size"] is not int pageSize) throw new Exception("Invalid --page-size option"); - var relics = Railend.GetContainer().GetInstance>().GetAllIdentifiers(RegisterIdentifierType.ReadableID); + var relics = Railend.GetContainer().GetInstance>(); var startIndex = (page - 1) * pageSize; var endIndex = startIndex + pageSize; var pageRelics = relics.Skip(startIndex).Take(pageSize); LoggerLazy.Value.Log("Relics:"); foreach (var relic in pageRelics) { - LoggerLazy.Value.Log($" {relic}"); + LoggerLazy.Value.Log($"{relic.Value.Cheat_GetNameEnglish()} : {relic.Value.name}"); } return Task.CompletedTask; }) diff --git a/Stoker.Base/Commands/UpgradeCommandFactory.cs b/Stoker.Base/Commands/UpgradeCommandFactory.cs new file mode 100644 index 0000000..2237cf5 --- /dev/null +++ b/Stoker.Base/Commands/UpgradeCommandFactory.cs @@ -0,0 +1,85 @@ +using HarmonyLib; +using ShinyShoe.Loading; +using Stoker.Base.Builder; +using Stoker.Base.Extension; +using Stoker.Base.Impl; +using Stoker.Base.Interfaces; +using System.Reflection; +using TrainworksReloaded.Base; +using TrainworksReloaded.Core; +using TrainworksReloaded.Core.Enum; +using TrainworksReloaded.Core.Interfaces; + +namespace Stoker.Base.Commands +{ + public class UpgradeCommandFactory + { + private static Lazy LoggerLazy { get; set; } = new(() => Railend.GetContainer().GetInstance()); + + public static ICommand Create() + { + var command = new CommandBuilder("upgrade") + .WithDescription("Manage ugprades") + .WithSubCommand("card") + .WithDescription("Apply an upgrade to a card") + .WithSimpleNameArg() + .WithDescription("The name of the upgrade to apply") + .WithSuggestions(() => + { + Type type = typeof(CheatManager); + FieldInfo field = type.GetField("allGameData", BindingFlags.NonPublic | BindingFlags.Static); + + if (field != null) + { + AllGameData allGameData = field.GetValue(null) as AllGameData; + if (allGameData != null) + { + return allGameData.GetAllEnhancerData().Select(e => e.Cheat_GetNameEnglish()).ToArray(); + } + } + return []; + }) + .WithParser((xs) => xs) + .Parent() + .SetHandler((args) => + { + var arguments = args.Arguments; + if (!arguments.ContainsKey("name")) + throw new Exception("Missing argument"); + if (arguments["name"] is not string upgradeName) + throw new Exception("Invalid argument"); + if (string.IsNullOrEmpty(upgradeName)) + throw new Exception("Empty argument"); + LoggerLazy.Value.Log($"Applying upgrade: {upgradeName}"); + AccessTools.Method(typeof(CheatManager), "Command_UpgradeCard").Invoke(null, [upgradeName]); + return Task.CompletedTask; + }) + .UseHelpMiddleware() + .Parent() + .WithSubCommand("list") + .WithDescription("List all upgrades") + .SetHandler((args) => + { + Type type = typeof(CheatManager); + FieldInfo field = type.GetField("allGameData", BindingFlags.NonPublic | BindingFlags.Static); + + if (field != null) + { + AllGameData allGameData = field.GetValue(null) as AllGameData; + if (allGameData != null) + { + List names = allGameData.GetAllEnhancerData().Select(s => s.Cheat_GetNameEnglish() + " : " + s.name).ToList(); + names.Sort(); + names.ForEach(s => LoggerLazy.Value.Log(s)); + } + } + return Task.CompletedTask; + }) + .UseHelpMiddleware() + .Parent() + .UseHelpMiddleware() + .Build(); + return command; + } + } +} diff --git a/Stoker.Base/Impl/Command.cs b/Stoker.Base/Impl/Command.cs index 06a8109..0f9389c 100644 --- a/Stoker.Base/Impl/Command.cs +++ b/Stoker.Base/Impl/Command.cs @@ -11,6 +11,7 @@ public class Command : ICommand public List Options { get; set; } = []; public List SubCommands { get; set; } = []; public Func? Handler { get; set; } = null; + public bool simpleNameArg { get; set; } = false; IEnumerable ICommand.Arguments => Arguments; @@ -39,6 +40,13 @@ private HandlerArgs ParseArgs(string[] args) var argumentIndex = 0; var processedOptions = new HashSet(); + //No need to parse just accept the string with spaces for easy logical name input + if(simpleNameArg) + { + handlerArgs.Arguments.Add("name", string.Join(" ", args)); + return handlerArgs; + } + //Add default values for all options with a default value foreach (var option in Options) { diff --git a/Stoker.Base/Stoker.Base.csproj b/Stoker.Base/Stoker.Base.csproj index bc28d68..cf86bb9 100644 --- a/Stoker.Base/Stoker.Base.csproj +++ b/Stoker.Base/Stoker.Base.csproj @@ -10,6 +10,10 @@ - + + + + + diff --git a/Stoker.Plugin/Plugin.cs b/Stoker.Plugin/Plugin.cs index 8777b87..f6f093b 100644 --- a/Stoker.Plugin/Plugin.cs +++ b/Stoker.Plugin/Plugin.cs @@ -44,6 +44,9 @@ public void Awake() rootCommandExecutor.TryAddCommand(RelicCommandFactory.Create()); rootCommandExecutor.TryAddCommand(HandCommandFactory.Create()); rootCommandExecutor.TryAddCommand(PyreCommandFactory.Create()); + rootCommandExecutor.TryAddCommand(EventCommandFactory.Create()); + rootCommandExecutor.TryAddCommand(UpgradeCommandFactory.Create()); + rootCommandExecutor.TryAddCommand(NodeCommandFactory.Create()); // Need to reload save to see changes Railend.ConfigurePreAction(c => { diff --git a/Stoker.Plugin/Stoker.Plugin.csproj b/Stoker.Plugin/Stoker.Plugin.csproj index 88e940d..7a1e19f 100644 --- a/Stoker.Plugin/Stoker.Plugin.csproj +++ b/Stoker.Plugin/Stoker.Plugin.csproj @@ -20,4 +20,8 @@ + + + + From 150b42548e01407aa9c8eb3d1efe8dedf29c8251 Mon Sep 17 00:00:00 2001 From: John Celendro Date: Wed, 18 Jun 2025 14:02:23 +0800 Subject: [PATCH 2/4] Allow full relic and card name when removing relics/cards --- Stoker.Base/Commands/CardCommandFactory.cs | 24 ++++++++++++++----- Stoker.Base/Commands/EventCommandFactory.cs | 13 ++++------ Stoker.Base/Commands/RelicCommandFactory.cs | 23 ++++++++++++++---- Stoker.Base/Commands/UpgradeCommandFactory.cs | 13 ++++------ 4 files changed, 44 insertions(+), 29 deletions(-) diff --git a/Stoker.Base/Commands/CardCommandFactory.cs b/Stoker.Base/Commands/CardCommandFactory.cs index 5357a97..3b4b87c 100644 --- a/Stoker.Base/Commands/CardCommandFactory.cs +++ b/Stoker.Base/Commands/CardCommandFactory.cs @@ -2,10 +2,8 @@ using ShinyShoe.Loading; using Stoker.Base.Builder; using Stoker.Base.Extension; -using Stoker.Base.Impl; using Stoker.Base.Interfaces; using System.Reflection; -using TrainworksReloaded.Base; using TrainworksReloaded.Core; using TrainworksReloaded.Core.Enum; using TrainworksReloaded.Core.Interfaces; @@ -31,10 +29,10 @@ public static ICommand Create() if (field != null) { - AllGameData allGameData = field.GetValue(null) as AllGameData; + AllGameData? allGameData = field.GetValue(null) as AllGameData; if (allGameData != null) { - return allGameData.GetAllCardData().Select(s => s.Cheat_GetNameEnglish()).ToArray(); + return [.. allGameData.GetAllCardData().Select(s => s.Cheat_GetNameEnglish())]; } } return []; @@ -105,9 +103,23 @@ public static ICommand Create() .Parent() .WithSubCommand("remove") .WithDescription("Remove a card from the deck") - .WithArgument("name") + .WithSimpleNameArg() .WithDescription("The name of the card to remove") - .WithSuggestions(() => [.. Railend.GetContainer().GetInstance>().GetAllIdentifiers(RegisterIdentifierType.ReadableID).Select(c => c.ToString())]) + .WithSuggestions(() => + { + Type type = typeof(CheatManager); + FieldInfo field = type.GetField("saveManager", BindingFlags.NonPublic | BindingFlags.Static); + + if (field != null) + { + SaveManager? saveManager = field.GetValue(null) as SaveManager; + if (saveManager != null) + { + return [.. saveManager.GetDeckState().Select(s => s.GetTitleKey().LocalizeEnglish(true, null))]; + } + } + return []; + }) .WithParser((xs) => xs) .Parent() .SetHandler((args) => diff --git a/Stoker.Base/Commands/EventCommandFactory.cs b/Stoker.Base/Commands/EventCommandFactory.cs index 344faf2..8299ed0 100644 --- a/Stoker.Base/Commands/EventCommandFactory.cs +++ b/Stoker.Base/Commands/EventCommandFactory.cs @@ -1,14 +1,9 @@ using HarmonyLib; -using ShinyShoe.Loading; using Stoker.Base.Builder; using Stoker.Base.Extension; -using Stoker.Base.Impl; using Stoker.Base.Interfaces; using System.Reflection; -using TrainworksReloaded.Base; using TrainworksReloaded.Core; -using TrainworksReloaded.Core.Enum; -using TrainworksReloaded.Core.Interfaces; namespace Stoker.Base.Commands { @@ -31,10 +26,10 @@ public static ICommand Create() if (field != null) { - AllGameData allGameData = field.GetValue(null) as AllGameData; + AllGameData? allGameData = field.GetValue(null) as AllGameData; if (allGameData != null) { - return allGameData.GetAllStoryEventData().Select(s => s.name).ToArray(); + return [.. allGameData.GetAllStoryEventData().Select(s => s.name)]; } } return []; @@ -65,10 +60,10 @@ public static ICommand Create() if (field != null) { - AllGameData allGameData = field.GetValue(null) as AllGameData; + AllGameData? allGameData = field.GetValue(null) as AllGameData; if (allGameData != null) { - List names = allGameData.GetAllStoryEventData().Select(s => s.name).ToList(); + List names = [.. allGameData.GetAllStoryEventData().Select(s => s.name)]; names.Sort(); names.ForEach(s => LoggerLazy.Value.Log(s)); } diff --git a/Stoker.Base/Commands/RelicCommandFactory.cs b/Stoker.Base/Commands/RelicCommandFactory.cs index 4be7ed8..aba0442 100644 --- a/Stoker.Base/Commands/RelicCommandFactory.cs +++ b/Stoker.Base/Commands/RelicCommandFactory.cs @@ -5,7 +5,6 @@ using Stoker.Base.Interfaces; using System.Reflection; using TrainworksReloaded.Core; -using TrainworksReloaded.Core.Enum; using TrainworksReloaded.Core.Interfaces; namespace Stoker.Base.Commands; @@ -28,10 +27,10 @@ public static ICommand Create() if (field != null) { - AllGameData allGameData = field.GetValue(null) as AllGameData; + AllGameData? allGameData = field.GetValue(null) as AllGameData; if (allGameData != null) { - return allGameData.GetAllCollectableRelicData().Select(s => s.Cheat_GetNameEnglish()).ToArray(); + return [.. allGameData.GetAllCollectableRelicData().Select(s => s.Cheat_GetNameEnglish())]; } } return []; @@ -55,9 +54,23 @@ public static ICommand Create() .Parent() .WithSubCommand("remove") .WithDescription("Remove a relic from the deck") - .WithArgument("name") + .WithSimpleNameArg() .WithDescription("The name of the relic to remove") - .WithSuggestions(() => [.. Railend.GetContainer().GetInstance>().Select(c => c.Value.name)]) + .WithSuggestions(() => + { + Type type = typeof(CheatManager); + FieldInfo field = type.GetField("saveManager", BindingFlags.NonPublic | BindingFlags.Static); + + if (field != null) + { + SaveManager? saveManager = field.GetValue(null) as SaveManager; + if (saveManager != null) + { + return [.. saveManager.GetAllRelics().Select(s => s.GetSourceRelicData().Cheat_GetNameEnglish())]; + } + } + return []; + }) .WithParser((xs) => xs) .Parent() .SetHandler((args) => diff --git a/Stoker.Base/Commands/UpgradeCommandFactory.cs b/Stoker.Base/Commands/UpgradeCommandFactory.cs index 2237cf5..7caf84b 100644 --- a/Stoker.Base/Commands/UpgradeCommandFactory.cs +++ b/Stoker.Base/Commands/UpgradeCommandFactory.cs @@ -1,14 +1,9 @@ using HarmonyLib; -using ShinyShoe.Loading; using Stoker.Base.Builder; using Stoker.Base.Extension; -using Stoker.Base.Impl; using Stoker.Base.Interfaces; using System.Reflection; -using TrainworksReloaded.Base; using TrainworksReloaded.Core; -using TrainworksReloaded.Core.Enum; -using TrainworksReloaded.Core.Interfaces; namespace Stoker.Base.Commands { @@ -31,10 +26,10 @@ public static ICommand Create() if (field != null) { - AllGameData allGameData = field.GetValue(null) as AllGameData; + AllGameData? allGameData = field.GetValue(null) as AllGameData; if (allGameData != null) { - return allGameData.GetAllEnhancerData().Select(e => e.Cheat_GetNameEnglish()).ToArray(); + return [.. allGameData.GetAllEnhancerData().Select(e => e.Cheat_GetNameEnglish())]; } } return []; @@ -65,10 +60,10 @@ public static ICommand Create() if (field != null) { - AllGameData allGameData = field.GetValue(null) as AllGameData; + AllGameData? allGameData = field.GetValue(null) as AllGameData; if (allGameData != null) { - List names = allGameData.GetAllEnhancerData().Select(s => s.Cheat_GetNameEnglish() + " : " + s.name).ToList(); + List names = [.. allGameData.GetAllEnhancerData().Select(s => s.Cheat_GetNameEnglish() + " : " + s.name)]; names.Sort(); names.ForEach(s => LoggerLazy.Value.Log(s)); } From 7dcfa76cfd2be022de3d1e2dc8ee231285dde802 Mon Sep 17 00:00:00 2001 From: John Celendro Date: Fri, 20 Jun 2025 13:54:19 +0800 Subject: [PATCH 3/4] Fixed card and relic list to show all cards/relics. Changed upgrade command to "add" and changed list to only show logical names. --- Stoker.Base/Commands/CardCommandFactory.cs | 29 ++++++++++++++----- Stoker.Base/Commands/RelicCommandFactory.cs | 26 ++++++++++++----- Stoker.Base/Commands/UpgradeCommandFactory.cs | 4 +-- 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/Stoker.Base/Commands/CardCommandFactory.cs b/Stoker.Base/Commands/CardCommandFactory.cs index 3b4b87c..5d34526 100644 --- a/Stoker.Base/Commands/CardCommandFactory.cs +++ b/Stoker.Base/Commands/CardCommandFactory.cs @@ -162,15 +162,30 @@ public static ICommand Create() throw new Exception("Invalid --page option"); if (options["page-size"] is not int pageSize) throw new Exception("Invalid --page-size option"); - var cards = Railend.GetContainer().GetInstance>(); - var startIndex = (page - 1) * pageSize; - var endIndex = startIndex + pageSize; - var pageCards = cards.Skip(startIndex).Take(pageSize); - LoggerLazy.Value.Log("Cards:"); - foreach (var card in pageCards) + + + Type type = typeof(CheatManager); + FieldInfo field = type.GetField("allGameData", BindingFlags.NonPublic | BindingFlags.Static); + + if (field != null) { - LoggerLazy.Value.Log($"{card.Value.Cheat_GetNameEnglish()} : {card.Value.name}"); + AllGameData? allGameData = field.GetValue(null) as AllGameData; + if (allGameData != null) + { + List cards = allGameData.GetAllCardData().ToList(); + cards.FindAll(c => c.IsUnitAbility()).ForEach(c => cards.Remove(c)); // Remove unit abilities + cards.Sort((x, y) => string.Compare(x.Cheat_GetNameEnglish(), y.Cheat_GetNameEnglish(), StringComparison.OrdinalIgnoreCase)); + var startIndex = (page - 1) * pageSize; + var endIndex = startIndex + pageSize; + var pageCards = cards.Skip(startIndex).Take(pageSize); + LoggerLazy.Value.Log("Cards:"); + foreach (var card in pageCards) + { + LoggerLazy.Value.Log($"{card.Cheat_GetNameEnglish()}"); + } + } } + return Task.CompletedTask; }) .UseHelpMiddleware() diff --git a/Stoker.Base/Commands/RelicCommandFactory.cs b/Stoker.Base/Commands/RelicCommandFactory.cs index aba0442..9ff9949 100644 --- a/Stoker.Base/Commands/RelicCommandFactory.cs +++ b/Stoker.Base/Commands/RelicCommandFactory.cs @@ -113,14 +113,26 @@ public static ICommand Create() throw new Exception("Invalid --page option"); if (options["page-size"] is not int pageSize) throw new Exception("Invalid --page-size option"); - var relics = Railend.GetContainer().GetInstance>(); - var startIndex = (page - 1) * pageSize; - var endIndex = startIndex + pageSize; - var pageRelics = relics.Skip(startIndex).Take(pageSize); - LoggerLazy.Value.Log("Relics:"); - foreach (var relic in pageRelics) + + Type type = typeof(CheatManager); + FieldInfo field = type.GetField("allGameData", BindingFlags.NonPublic | BindingFlags.Static); + + if (field != null) { - LoggerLazy.Value.Log($"{relic.Value.Cheat_GetNameEnglish()} : {relic.Value.name}"); + AllGameData? allGameData = field.GetValue(null) as AllGameData; + if (allGameData != null) + { + List relics = allGameData.GetAllCollectableRelicData().ToList(); + relics.Sort((a, b) => string.Compare(a.Cheat_GetNameEnglish(), b.Cheat_GetNameEnglish(), StringComparison.OrdinalIgnoreCase)); + var startIndex = (page - 1) * pageSize; + var endIndex = startIndex + pageSize; + var pageRelics = relics.Skip(startIndex).Take(pageSize); + LoggerLazy.Value.Log("Relics:"); + foreach (var relic in pageRelics) + { + LoggerLazy.Value.Log($"{relic.Cheat_GetNameEnglish()}"); + } + } } return Task.CompletedTask; }) diff --git a/Stoker.Base/Commands/UpgradeCommandFactory.cs b/Stoker.Base/Commands/UpgradeCommandFactory.cs index 7caf84b..9b01778 100644 --- a/Stoker.Base/Commands/UpgradeCommandFactory.cs +++ b/Stoker.Base/Commands/UpgradeCommandFactory.cs @@ -15,7 +15,7 @@ public static ICommand Create() { var command = new CommandBuilder("upgrade") .WithDescription("Manage ugprades") - .WithSubCommand("card") + .WithSubCommand("add") .WithDescription("Apply an upgrade to a card") .WithSimpleNameArg() .WithDescription("The name of the upgrade to apply") @@ -63,7 +63,7 @@ public static ICommand Create() AllGameData? allGameData = field.GetValue(null) as AllGameData; if (allGameData != null) { - List names = [.. allGameData.GetAllEnhancerData().Select(s => s.Cheat_GetNameEnglish() + " : " + s.name)]; + List names = [.. allGameData.GetAllEnhancerData().Select(s => s.Cheat_GetNameEnglish())]; names.Sort(); names.ForEach(s => LoggerLazy.Value.Log(s)); } From b17621955d9250a8abea115c1a3c6def14bd268a Mon Sep 17 00:00:00 2001 From: John Celendro Date: Fri, 20 Jun 2025 13:58:07 +0800 Subject: [PATCH 4/4] Disabled xcopy. --- Stoker.Base/Stoker.Base.csproj | 4 ++-- Stoker.Plugin/Stoker.Plugin.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Stoker.Base/Stoker.Base.csproj b/Stoker.Base/Stoker.Base.csproj index cf86bb9..52816a5 100644 --- a/Stoker.Base/Stoker.Base.csproj +++ b/Stoker.Base/Stoker.Base.csproj @@ -13,7 +13,7 @@ - + diff --git a/Stoker.Plugin/Stoker.Plugin.csproj b/Stoker.Plugin/Stoker.Plugin.csproj index 7a1e19f..8d19263 100644 --- a/Stoker.Plugin/Stoker.Plugin.csproj +++ b/Stoker.Plugin/Stoker.Plugin.csproj @@ -21,7 +21,7 @@ - +