Add console_command action: run dev-console commands over the HTTP API - #119
Open
SamPease wants to merge 1 commit into
Open
Add console_command action: run dev-console commands over the HTTP API#119SamPease wants to merge 1 commit into
SamPease wants to merge 1 commit into
Conversation
Constructs a MegaCrit.Sts2.Core.DevConsole.DevConsole directly and calls
ProcessCommand(string) on it, bypassing the console's UI panel entirely.
Exposes the game's full first-party dev-console command set (heal, damage,
block, energy, card, draw, applypower, fight <encounter_id>, unlock,
achievement, ...) over the existing localhost API - useful for reaching
precise states (exact HP/block/hand/statuses, or jumping straight into a
named encounter) beyond what's reachable through legal play alone.
Usage: POST /api/v1/singleplayer {"action": "console_command", "command": "heal 999"}
(requires a run in progress, same as every other action.)
Task-returning commands (e.g. fight) are fired via TaskHelper.RunSafely,
matching the game's own console (DevConsoleUI's ProcessCommand call site) -
not awaited synchronously. That matters: awaiting synchronously deadlocked
the whole mod when a task-returning command needed the main thread to keep
pumping to complete, since this handler already runs on the main thread via
RunOnMainThread. Confirmed live by calling `fight` while another combat was
already in progress before landing on the fire-and-forget fix.
There was a problem hiding this comment.
Pull request overview
Adds a new singleplayer HTTP action that lets clients execute first-party STS2 dev-console commands directly against the live run state, enabling precise scenario setup via the existing localhost API.
Changes:
- Add a new
"console_command"action dispatch in the singleplayer action switch. - Implement
ExecuteConsoleCommandto callDevConsole.ProcessCommand(string)and fire-and-forget any returned task viaTaskHelper.RunSafely.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+164
to
+166
| var devConsole = new MegaCrit.Sts2.Core.DevConsole.DevConsole(shouldAllowDebugCommands: true); | ||
| var result = devConsole.ProcessCommand(command); | ||
|
|
Comment on lines
88
to
91
| "crystal_sphere_click_cell" => ExecuteCrystalSphereClickCell(data), | ||
| "crystal_sphere_proceed" => ExecuteCrystalSphereProceed(), | ||
| "console_command" => ExecuteConsoleCommand(data), | ||
| _ => Error($"Unknown action: {action}") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a
console_commandaction that constructs aMegaCrit.Sts2.Core.DevConsole.DevConsoledirectly and calls
ProcessCommand(string)on it, bypassing the console's UI panelentirely. This exposes the game's full first-party dev-console command set (
heal,damage,block,energy,card,draw,applypower,fight <encounter_id>,unlock,achievement, ...) over the existing localhost API.(Requires a run in progress, same as every other action.)
Motivation: I'm using this mod as a ground-truth oracle for a personal project that
differential-tests a from-scratch combat simulator. Legal play alone can't reach a lot
of the precise/edge-case states I need to test against (exact HP thresholds, specific
status stacks, specific encounters without map RNG) — the dev console can construct
these directly. Seemed generically useful beyond my own use case, so opening this
rather than keeping it as a private patch.
A real bug found and fixed along the way
Task-returning commands (e.g.
fight) need to be fired viaTaskHelper.RunSafely,matching the game's own console (
DevConsoleUI'sProcessCommandcall site) — notawaited synchronously. I initially awaited the task directly
(
result.task.GetAwaiter().GetResult()), which deadlocked the entire mod: this handleralready runs on the main thread via
RunOnMainThread, andfight's task itself needsthe main thread to keep pumping to complete. Confirmed live — calling
fightwhileanother combat was already in progress hung the whole HTTP server, not just that
request, until switching to fire-and-forget.
Verification note
maincurrently doesn't compile against the latest installed STS2 (v0.109.0) due tothe pre-existing
IsPlayPhase/InventoryAPI breakage tracked in #114/#116/#117, so Icouldn't build-verify this diff directly against unpatched
main. I did build andextensively live-verify this exact change (including finding and fixing the deadlock
above) on top of #117's branch, which does compile and run against v0.108.0 and
v0.109.0. This diff doesn't touch any of the lines #117 changes — it's a new method
plus one new switch case — so it should apply and build cleanly on
mainonce #117 (oran equivalent fix) lands. Happy to rebase/re-verify against
maindirectly once that'sin, or against whatever base you'd prefer.