feat: RecompLauncher support (recomplauncher.json, make_game --game/--prepare) #1102
No reviewers
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
No milestone
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot!1102
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/recomplauncher-support"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Hi! This makes Hookshot work with RecompLauncher, which installs and updates recomps from their GitHub releases. Nothing changes for anyone who doesn't use it.
What players get (Linux AppImage and Windows)
.nup(or a folder withromfsandexefs), and the launcher builds the game for you with a progress bar, then starts it with Play.hookshot_options.ini, the same file the in-game menu writes.What's in it
recomplauncher.jsonat the repo root, andscripts/linux/appimage.shcopies it into the AppImage at/recomplauncher.json. It validates against the schema. A small test (tests/test_recomplauncher_json.py) checks that every settings key is a row of the in-game menu.Code change (its own commit,
nx2/make_game.py+tests/test_make_game_prepare.py): two new opt-in options.--game <.nup or folder>is the same as--nup, or--romfsand--exefs.--prepareprintsprogress 0.4 Textlines instead of the builder app's@@lines, builds into~/Games/Hookshotunless--outis given, and exits 0 on success.They only apply when those arguments are passed. Without them
make_game.py, the builder windows and the game behave exactly as before. The existing read, check and build code is reused as is.Windows (own commits):
HookshotBuilder.exe --cli <make_game options>and--play <folder>(builder/setup/setup.c,builder/HookshotBuilder/App.xaml.cs).--cliinstalls the builder the usual way but with no window, then runsmake_game.pywith the output on stdout/stderr and its result as the exit code.--playstartsbin\hookshot.exeand waits for it. The windows workflow also makesHookshot-<tag>-Windows-x64.zip(the setup besiderecomplauncher.json) and uploads it with the release. The setup and the builder start exactly as before unless those two arguments are passed.What doesn't change
The game, graphics, saves, config formats and the builder's own start are untouched. No game files are added.
How it was tested
recomplauncher.jsonvalidates against the published schema except for the newcheck.nup_build_id, which RecompLauncher's schema in #39 adds. Game-free tests cover the new options and that every settings key is a row of the in-game menu.HookshotBuilder.exe --cli --checkreported the supported version,--cli --preparebuilt the game in about 15 minutes (exit 0, orderedprogresslines), and--playstarted it. The Windows builder workflow compiles and publishes on GitHub's runner.nup_build_idreturnse0f3ccfa…for the real Ocarina of Time.nupand a different build for five other Switch 2 packages.Game-free source regressionsrun has one failure,tests/test_program_answer_domains.py(agpu/vkfixture,answers_inundeclared). It is not touched by this PR.For the maintainer
CI_RELEASE_WINDOWSis set.recomplauncher.json.recomplauncher.jsonhas"check": { "nup_build_id": "e0f3ccfa" }, so RecompLauncher refuses a.nup(or a folder withexefs/main) of another build before the build starts. It needs the launcher change in elripalda/RecompLauncher#39. A launcher without it ignores the field and checks nothing, as before. The published schema doesn't list the field until that is released, so schema validation may flag it until then.dumpslist: Redump doesn't cover Switch 2 packages, and no checksums are made up.Thanks, this is a tidy change and the opt-in story holds up: without
--game/--prepare,PREPAREstays False andsay()still prints the@@lines (the test covers that), the new--gamemapping only runs when passed, and the--cli/--playchecks insetup.c/App.xaml.csonly trigger on those exact first arguments. The new tests are picked up by thetests/test_*.pyglob inrun_all.py, so no registration is needed. The AppImage side needs no change either, sinceAppRunalready has--cliand--play <folder>. A few things I'd like fixed or decided before merging:1. Windows
--cli --preparefailures lose their message. In prepare modesay_preparewriteserror ...to stderr.Runner.Startforwards stderr throughLine(so it ends up on stdout in--cli), but only@@errorlines seterror. So on a failed buildCli()prints the generic "The build tools stopped without saying why" on stderr and exits 1, while the real reason went to stdout. A launcher that shows stderr will show the useless message. Either havesay_preparealso print somethingRunnerrecognises, or haveCliparseerrorlines too.2.
--checkis silent with--prepare.say("check", ...)falls throughsay_prepare, which only handles stage/progress/error/done, so--prepare --checkprints nothing. Probably fine since the manifest usesnup_build_idinstead, but then--prepareshouldn't claim to work with--check, orcheckshould be printed.3.
--gameis not validated. A missing.nuphitsos.stat(a.nup)and ends in a Python traceback (after~/Games/Hookshothas been created), and a folder withoutromfs/exefsfails later inside the copy. Since the path comes from an external launcher, a one-linefail("... not found")up front (and for the folder: bothromfsandexefsmust exist) would give RecompLauncher a cleanerrorline.4. Naming/overlap with #1026. #1026 (shaders prepared at the end of the build) adds
--no-prepare-shaders, the game's--prepare-shaders, andprepare_shaders()in the samemake_game.pytail, so "prepare" will mean two different things (build everything for the launcher vs. the shader step). The argparse flags don't collide (--prepareis an exact match), but I'd consider something like--launcher/--progress-lines. More concretely,show_preparedin #1026 passes@@stage/@@progresslines and the "shaders were not prepared" text straight throughprint, bypassingsay(), so in--preparemode those would reach the launcher as raw@@lines instead ofprogress <n> <text>. Whichever lands second needs to route that throughsay(). The two also edit the same hunk nearsay("done", out)andparse_args, so expect a rebase.5. #1179 (profiles/save import). It touches the builder/launcher (
MainWindow*,App.xaml,hookshot-launch,run_all.py). I didn't dig into its save layout, butrecomplauncher.jsonhardcodes the saves at{local}/hookshotand{home}/Games/Hookshot/user; if profiles move where saves live, the manifest needs updating. Worth cross-checking whichever merges second.Nits:
--play's parser insetup.conly handles one optionally-quoted path (fine for how a launcher passes it), and the{home}/Games/Hookshotdefault is hardcoded in the manifest, so a player who built somewhere else gets "No built game to start", which is at least a clear message. The Windows zip step and glob look right to me (dist/is the artifact root, and the tag-only release job is as described).CI: GitHub reports no checks on this branch, so I couldn't confirm a green run. I didn't build or run anything.
Thanks, good catches. Fixed in
2d27d08anda3859f1.--prepare,make_gamenow printserror <text>on stdout, and--clitakes that as the reason, saying it once on stdout and again on stderr (also for "build tools not found").--prepare --checknow prints itscheck ok|bad …line.--gameis checked inparse_argsbefore any folder is made: a path that doesn't exist, or a folder without bothromfsandexefs, is oneerrorline. Tests added.show_preparedthroughsay(); happy to rebase. I'd keep--prepareas the name: it matches thepreparestep inrecomplauncher.json, and the flags don't collide.The Python tests pass on Linux; the
App.xaml.cschange still needs a Windows build.Follow-up on the Windows side: HookshotBuilder at
a3859f1builds with .NET 8 (0 warnings, 0 errors), and--cli --preparefrom that build exits 1 with a singleerror …line on stdout and again on stderr for:.nupthat doesn't exist (error Your copy of the game was not found: …, and no output folder is made)romfs(error The folder … needs both a romfs and an exefs folder in it.)error The build tools were not found next to this program.)Not run: a full successful build, since there was no game copy on that machine.
Thanks, all the points are addressed at
a3859f1.--prepare,error <text>now goes to stdout, andCli()reuses that line as the reason (once on stdout, once on stderr), including the "tools not found" case. Thefailure == "cancelled"handling reads fine.checklines are printed in prepare mode, and covered bytest_error_and_check_lines_are_on_stdout.--gameis validated inparse_argsbefore any folder is made (missing path, or a folder without bothromfsandexefs), and--prepareis applied first so the failure comes out as a plainerrorline. The tests cover both and the non-prepare@@errorcase.--prepareas the name. Whichever of this and #1026 lands second needs to routeshow_preparedthroughsay(), as agreed.recomplauncher.jsonagainst #1179 if it lands first.No new issues in the delta. The
App.xaml.cschange I couldn't build, but your note about the .NET 8 build and the--cli --preparefailure runs covers it. GitHub shows no CI checks on this branch, and the PR is currently mergeable. I didn't build or run anything.