Proposal: "Download Demo Project" in the Project Manager
Milestone: Demo & polish (D4, last) · Status: ✅ done ·
Depends on: Demo project (the thing downloaded), Release (publish.yml) ·
Related: Project icons
Problem
Section titled “Problem”A new user of a released editor has no game to look at: New Project creates a near-empty template, and the Demo lives only in the source repository. Godot’s Project Manager offers an asset-library demo download; ours should offer the Demo in one click.
- A Download Demo Project button in the Project Manager that fetches the Demo matching the editor’s version, unpacks it into a folder the user chooses, points it at the engine, adds it to Recent Projects and opens it.
- No new NuGet packages (BCL
HttpClient+System.IO.Compression). - Works from a release build and from a development build.
Non-goals
Section titled “Non-goals”- A general asset/template library.
- Downloading or installing the engine itself. Like New Project, the Demo builds against an engine checkout
(
TemplateLocator.FindEngineCheckout,MAINFRAME_ENGINE_PATH); NuGet distribution is a separate proposal. - Updating an already-downloaded Demo in place.
Release side
Section titled “Release side”publish.yml gains a step after the editor packages are built and before gh release create (line 128):
git lfs pull --include="Examples/Demo/**"(the job otherwise excludesExamples/**, lines 72/83).- Zip
Examples/Demowithoutbin/,obj/,.vs/,*.user→release/MainframeEngine.Demo-v${VERSION}.zip, with the top-level folder inside the zip namedMainframeEngine.Demo/. - Copy it to
release/MainframeEngine.Demo.zip(stable name for “latest”). - Both files are attached by the existing
gh release create "v${VERSION}" release/*.
A build/package-demo.sh script does steps 2–3 so just publish-local can produce the same zip locally.
docs/design/release.md lists the new assets.
Editor side
Section titled “Editor side”- An icon button (download glyph, tooltip “Download Demo Project” — icons over text, per editor convention) in the
Project Manager toolbar next to New / Open Folder (
project_manager.rml,ProjectManager.cs:55-78events). - It opens a Download Demo dialog (
Content/Editor/download_demo.rml,Src/UI/DownloadDemoDialog.cs, built likeNewProjectDialog):- destination parent folder (default: the New Project dialog’s default parent), folder name
MainframeEngine.Demo(validated with the same rules asNewProjectRequest; an existing non-empty folder is an error); - shows the engine checkout the Demo will use, or the same “no engine checkout” error New Project shows;
- Download → progress bar (bytes / total from
Content-Length), status line, Cancel; - on failure: the error and a Retry button; nothing is left behind.
- destination parent folder (default: the New Project dialog’s default parent), folder name
Flow (Src/Projects/DemoDownloader.cs)
Section titled “Flow (Src/Projects/DemoDownloader.cs)”- URL.
https://github.com/Mainframe-Games/mainframe-engine/releases/download/v{EngineInfo.Version}/MainframeEngine.Demo-v{EngineInfo.Version}.zipfor release builds. Development builds (EngineInfo.Version == "0.0.0-dev", seeEngineInfo.cs) usehttps://github.com/Mainframe-Games/mainframe-engine/releases/latest/download/MainframeEngine.Demo.zipand the dialog notes that the latest release’s Demo may not match a development engine. The base URL is a constant in one place (DemoDownloader.ReleasesBaseUrl) so a fork changes one line. - Download with one shared
HttpClient(user agentMainframeEngine-Editor/{version}), streamed to a temp file under~/.mainframe/downloads/, with progress reported to the dialog on the main thread and aCancellationToken. HTTP 404 → “This editor version has no published demo” message. - Extract to a temp folder next to the destination with a zip-slip guard: every entry’s full path must stay inside the temp folder; symlink entries are rejected; total uncompressed size is capped at 1 GiB.
- Validate: exactly one top-level folder containing
project.mfprojthat loads withProjectSettingsFormat, a*.Desktop/*.Desktop.csproj, or*.Launcherfrom before the rename (GameProjectLayout) andContent/Scenes/. - Point at the engine: rewrite
MainframeEnginePathin the Demo’sDirectory.Build.propstoGameProjectLayout.RealPath(engineCheckout)— the same value New Project passes as--engine-path(ProjectCreator.cs:192). The rewrite edits only that property (XML, preserving the rest of the file). - Move into place (atomic directory move from the temp folder to the destination), delete the temp zip and folder.
RecentProjects.TouchandWorkspace.Commands.OpenProject(destination)— the same path New Project’sFinishuses (NewProjectDialog.cs:236). Opening builds the game as for any project.
Cancellation or any failure deletes the temp zip and temp folder; the destination is never partially written.
Testing
Section titled “Testing”All in Tests/MainframeEngine.Editor.Tests, no network:
- URL builder: release version → tagged asset URL;
0.0.0-dev→ latest URL. - Extraction from a zip built in the test: happy path; zip-slip entry (
../x) rejected; absolute entry rejected; size cap; missingproject.mfprojrejected; two top-level folders rejected. Directory.Build.propsrewrite: replaces onlyMainframeEnginePath, keeps other properties and comments; path with spaces.- Downloader with an injected
HttpMessageHandler: progress callbacks, 404 message, cancellation cleans up. build/package-demo.shis run in the CItemplatejob and the resulting zip goes through the same validation code (a small test entry point or--validate-demo-zipeditor QA flag), so a broken Demo zip fails CI before release.
Acceptance
Section titled “Acceptance”- In a released editor with an engine checkout available, Download Demo → Download produces a folder that opens, builds and plays with no manual edits, and appears in Recent Projects with its icon (Project icons).
- The release for
vX.Y.ZhasMainframeEngine.Demo-vX.Y.Z.zipandMainframeEngine.Demo.zipwith real LFS content (no pointer files). - Cancel and failures leave no files behind.
docs/design/editor.md#projectsanddocs/design/release.mdupdated.
Task list
Section titled “Task list”build/package-demo.sh,publish.ymlstep,just publish-local, CI zip validation.DemoDownloader(URL, download, extract, validate, rewrite, move) + tests.- Dialog + Project Manager button, wiring to Recent Projects / Open; docs.