Files
zfxaction26_1/SLICE1.MD
2026-04-21 18:54:38 +02:00

330 lines
19 KiB
Markdown

# Build the Godot Project Shell
This ExecPlan is a living document. The sections `Progress`, `Surprises & Discoveries`, `Decision Log`, and `Outcomes & Retrospective` must be kept up to date as work proceeds.
This plan follows `PLANS.md` in the repository root. It is intentionally self-contained so a developer with only this repository and this file can implement Slice 1 without reading prior chat history.
## Purpose / Big Picture
After this slice, the repository will contain a bootable Godot 4 .NET project shell for the side-scrolling shooter. A developer will be able to build the C# project, start the Godot project, see a root scene load a normal placeholder scene, and boot directly into a smoke test scene through a debug boot mode. This gives later slices a stable place to add content, input, debug tools, and test harnesses without first repairing project setup.
The observable result is small but concrete: from `D:\Code\zfxaction26_1`, `dotnet build SideScrollerGame.sln` succeeds, `.\godot --headless --path godot --build-solutions --quit` succeeds, and `.\godot --headless --path godot -- --debug-boot=smoke` starts the root scene, loads the smoke scene, prints a short confirmation line, and exits with code 0.
## Progress
- [x] (2026-04-21 16:36Z) Read repository rules, Windows rules, `PLANS.md`, `CODE.md`, and current Godot project files.
- [x] (2026-04-21 16:36Z) Verified that the Godot project currently lives in `godot/project.godot`, not at the repository root.
- [x] (2026-04-21 16:36Z) Verified that `SideScrollerGame.sln` and `godot/SideScrollerGame.Godot.csproj` currently build with `dotnet build SideScrollerGame.sln` after the user's fixes.
- [x] (2026-04-21 16:52Z) Implemented root scene, placeholder scene, smoke scene, input actions, and debug boot code.
- [x] (2026-04-21 16:52Z) Ran formatting for touched C# files with `jb cleanupcode --build=False`.
- [x] (2026-04-21 16:52Z) Validated with .NET build, Godot solution build, and headless smoke boot.
- [x] (2026-04-21 16:52Z) Commit the completed slice.
## Surprises & Discoveries
- Observation: The current Godot project is under the `godot/` subdirectory. The repository-root wrapper is still used from `D:\Code\zfxaction26_1`, but commands must pass `--path godot`.
Evidence: `rg --files godot` lists `godot/project.godot` and `godot/SideScrollerGame.Godot.csproj`.
- Observation: A prior `.\godot --headless --path godot --build-solutions` command was observed to keep running without `--quit`.
Evidence: the process command line was `--headless --path godot --build-solutions`, and it had to be stopped. This plan uses `--build-solutions --quit` for validation.
- Observation: Running `dotnet build SideScrollerGame.sln` and `dotnet build godot\SideScrollerGame.Godot.csproj` at the same time can race on the same Godot temp assembly.
Evidence: the parallel build attempt failed with `CS2012: Cannot open ... SideScrollerGame.Godot.dll for writing`. A serial `dotnet build SideScrollerGame.sln` immediately afterward succeeded.
- Observation: `godot/project.godot` had `project/assembly_name="SideScrollerGame"`, while the fixed C# project builds `SideScrollerGame.Godot.dll`.
Evidence: the first smoke boot did not instantiate C# scripts, and `.\godot --headless --path godot --quit` reported that `GameRoot.cs` and `DebugOverlay.cs` classes could not be found. Updating the Godot assembly name to `SideScrollerGame.Godot` fixed script loading.
- Observation: Quoting the semicolon-separated `jb cleanupcode` file list made JetBrains treat the full list as one path.
Evidence: `jb cleanupcode --build=False "file1;file2;..."` exited with "No items were found to cleanup." Running `jb cleanupcode --build=False file1 file2 ...` formatted all touched C# files.
## Decision Log
- Decision: Keep `godot/project.godot` as the canonical Godot project entrypoint for this slice.
Rationale: The current repository already has the Godot project under `godot/`, the user explicitly corrected that it is not missing, and moving it would create unnecessary churn before gameplay exists.
Date/Author: 2026-04-21 / Codex.
- Decision: Implement Slice 1 as a minimal boot shell with placeholder scenes, not gameplay systems.
Rationale: `CODE.md` defines Slice 1 as the project shell. Later slices depend on stable project loading, input actions, debug boot mode, and a reliable smoke test.
Date/Author: 2026-04-21 / Codex.
- Decision: Use C# scripts for root boot, debug settings, overlay, and smoke exit behavior.
Rationale: This is a Godot .NET project, and later slices need reusable C# debug services and typed state. Keeping this in C# avoids replacing GDScript glue later.
Date/Author: 2026-04-21 / Codex.
- Decision: Parse debug boot settings from Godot user arguments such as `--debug-boot=smoke` and `--seed=12345`, with project settings as fallback.
Rationale: Command-line boot modes make sandbox and smoke testing fast without editor interaction. Project setting fallback keeps editor boot predictable.
Date/Author: 2026-04-21 / Codex.
- Decision: Match `godot/project.godot`'s .NET assembly name to the existing C# project output, `SideScrollerGame.Godot`.
Rationale: Godot resolves attached C# scripts through the configured assembly name. The project already builds `SideScrollerGame.Godot.dll`, and changing the Godot setting avoids touching the user's fixed `.csproj`.
Date/Author: 2026-04-21 / Codex.
## Outcomes & Retrospective
Implemented a bootable Godot project shell under `godot/`. Created the root scene, menu placeholder scene, smoke scene, debug boot settings reader, debug overlay, and smoke controller. Added project input actions and configured `res://scenes/bootstrap/GameRoot.tscn` as the main scene.
Validation completed:
dotnet build SideScrollerGame.sln
Build succeeded.
0 Warning(s)
0 Error(s)
.\godot --headless --path godot --build-solutions --quit
Exited successfully.
.\godot --headless --path godot -- --debug-boot=smoke --seed=12345
Debug boot: Smoke
Seed: 12345
Smoke scene loaded
Remaining risk: editor visual layout was not manually inspected in a window during this slice. The headless boot path and script loading are validated.
## Context and Orientation
The repository root is `D:\Code\zfxaction26_1`. The Godot project root is `D:\Code\zfxaction26_1\godot`. The wrapper `D:\Code\zfxaction26_1\godot.cmd` launches the local Godot 4.5.1 .NET executable, so commands are run from the repository root as `.\godot --path godot ...`.
Current important files are:
- `godot/project.godot`: the Godot project configuration. It currently has project name, C# feature flags, icon, and .NET assembly name, but no main scene and no input actions.
- `godot/SideScrollerGame.Godot.csproj`: the C# project for Godot scripts. It currently targets `net8.0` and uses `Godot.NET.Sdk/4.5.1`.
- `SideScrollerGame.sln`: the Visual Studio solution. It currently contains the Godot C# project and builds successfully after the user's fixes.
- `CODE.md`: the broader implementation plan. Its Slice 1 section asks for a project shell, root scene, input actions, smoke scene, debug boot mode, deterministic seed setting, and visible build/version label.
- `DESIGN.md`: the design document. It has user modifications and must not be touched by this slice.
There are currently no tracked scenes or gameplay scripts under `godot/scenes/` or `godot/scripts/`. This slice creates those directories and the minimal files needed to boot.
Definitions used in this plan:
- A root scene is the first Godot scene loaded by the project. It owns scene switching and debug boot selection.
- A placeholder scene is a simple visible scene used before real menu or gameplay exists.
- A smoke scene is a tiny scene used to prove the project can start. In headless mode it exits automatically with code 0 so it can be used by scripts and CI.
- Headless mode means Godot runs without opening a window. It is used for build and smoke validation.
- Debug boot mode means a developer can start the project directly in a specific scene by passing a command-line argument instead of clicking through menus.
## Plan of Work
First, create the scene and script folders under `godot/` so the project follows the planned layout without touching unrelated files. Add `godot/scripts/debug/DebugBootMode.cs`, an enum with at least `Menu` and `Smoke`. Add `godot/scripts/debug/DebugSettings.cs`, a small settings reader that parses `OS.GetCmdlineUserArgs()` for `--debug-boot=<value>` and `--seed=<integer>`, then falls back to Godot project settings `application/run/debug_boot_mode` and `application/run/debug_seed`.
Next, add `godot/scripts/bootstrap/GameRoot.cs`. This script should extend `Godot.Node`, read `DebugSettings` in `_Ready`, instantiate either the menu placeholder scene or smoke scene, and add it as a child. It should also create or update a debug overlay label so the screen shows the active boot mode, seed, current scene id, and whether debug mode is active. The root script should expose scene paths or `PackedScene` exports so a designer can change them in the Godot editor later.
Then add `godot/scripts/debug/DebugOverlay.cs`. It should extend `CanvasLayer` or `Control`, contain a `Label`, and expose a method like `SetStatus(DebugSettings settings, string loadedSceneId)`. Keep it simple: it only needs to show text in the top-left corner. Later slices will extend the overlay with mission time, enemies, projectiles, and hero state.
Then add `godot/scripts/menu/MenuPlaceholder.cs` and `godot/scripts/debug/SmokeSceneController.cs`. The menu placeholder should show a label such as `SideScrollerGame - Menu Placeholder` and a short debug instruction such as `Run with -- --debug-boot=smoke for smoke scene`. The smoke controller should show a simple placeholder hero shape or label. If the display server is headless, it should print `Smoke scene loaded` and quit successfully after one idle frame. In a normal window, it should stay visible.
Next, create the scene files:
- `godot/scenes/bootstrap/GameRoot.tscn`
- `godot/scenes/menu/MenuPlaceholder.tscn`
- `godot/scenes/debug/SmokeScene.tscn`
The root scene should be a `Node` with the `GameRoot.cs` script attached and a child `DebugOverlay`. The menu placeholder should be a `Control` or `Node2D` with a label and the `MenuPlaceholder.cs` script attached. The smoke scene should be a `Node2D` with a label or simple `Polygon2D` hero placeholder and the `SmokeSceneController.cs` script attached.
Finally, update `godot/project.godot`. Add `config/main_scene="res://scenes/bootstrap/GameRoot.tscn"` under `[application]`. Add input map entries for `move_up`, `move_down`, `move_left`, `move_right`, `fire_primary`, `fire_secondary`, `fire_special`, `pause_game`, `debug_overlay`, and `quick_restart`. Add project settings for default debug boot mode and seed. Keep the existing project name, features, icon, and .NET assembly name.
Do not edit `DESIGN.md`. Do not revert the user's current `SideScrollerGame.sln` or `godot/SideScrollerGame.Godot.csproj` changes. If those files must be touched during implementation, read the current content first and make only the minimal required edits.
## Concrete Steps
Run all commands from `D:\Code\zfxaction26_1`.
1. Confirm the current state before editing:
git status --short
rg --files godot
dotnet build SideScrollerGame.sln
Expected result: `git status --short` may show user changes to `DESIGN.md`, `SideScrollerGame.sln`, and `godot/SideScrollerGame.Godot.csproj`. `rg --files godot` should show the current Godot project files. `dotnet build SideScrollerGame.sln` should end with `Build succeeded`.
2. Create directories:
godot/scenes/bootstrap
godot/scenes/menu
godot/scenes/debug
godot/scripts/bootstrap
godot/scripts/menu
godot/scripts/debug
3. Add the C# scripts listed in the Plan of Work. Use 4 spaces for indentation. Use nullable reference types where practical. Keep one primary public type per file. Follow the repository type member order from `AGENTS.md`: nested types, constructors, disposable implementation, methods, properties, static members, events, fields.
4. Add the three scene files and attach the scripts. Prefer simple Godot built-in nodes and the existing `godot/icon.svg` for any placeholder image. No imported art is required for this slice.
5. Update `godot/project.godot` to set the main scene, input actions, and default debug settings. Use Godot's existing text format and preserve existing settings.
6. Format touched C# files:
jb cleanupcode --build=False godot\scripts\bootstrap\GameRoot.cs;godot\scripts\debug\DebugBootMode.cs;godot\scripts\debug\DebugSettings.cs;godot\scripts\debug\DebugOverlay.cs;godot\scripts\debug\SmokeSceneController.cs;godot\scripts\menu\MenuPlaceholder.cs
If `jb cleanupcode` is unavailable, record the exact error in `Surprises & Discoveries`, keep formatting manually consistent, and continue validation.
7. Validate the project:
dotnet build SideScrollerGame.sln
.\godot --headless --path godot --build-solutions --quit
.\godot --headless --path godot -- --debug-boot=smoke --seed=12345
Expected result: the .NET build succeeds, the Godot build exits, and the smoke boot prints a line containing `Smoke scene loaded` and exits with code 0.
8. Check the diff:
git status --short
git diff -- godot/project.godot godot/scenes godot/scripts SLICE1.MD
Expected result: the slice diff only includes the intended project shell files. User changes in `DESIGN.md`, `SideScrollerGame.sln`, or `godot/SideScrollerGame.Godot.csproj` must not be reverted.
9. Commit this slice after validation:
git add godot/project.godot godot/scenes godot/scripts SLICE1.MD
git commit -m "Add Godot project shell"
## Validation and Acceptance
This slice is accepted when the following observable behaviors are true.
Building from the repository root succeeds:
dotnet build SideScrollerGame.sln
The expected final lines include:
Build succeeded.
0 Warning(s)
0 Error(s)
Godot can build the C# solution and exit:
.\godot --headless --path godot --build-solutions --quit
The command should exit without a stuck Godot process. If it prints Godot warnings that do not fail the process, record them in this plan.
The project can boot through its main scene into the smoke scene:
.\godot --headless --path godot -- --debug-boot=smoke --seed=12345
The expected output includes:
Smoke scene loaded
Debug boot: Smoke
Seed: 12345
Opening the editor should show the project and root scene:
.\godot --editor --path godot
In the editor, `res://scenes/bootstrap/GameRoot.tscn` should be the configured main scene. Running it without arguments should show the menu placeholder and debug/version label. Running it with `-- --debug-boot=smoke` should show the smoke placeholder in a window or exit automatically in headless mode.
There is no automated unit test required for this slice because no pure gameplay rules exist yet. The smoke scene is the automated project-start test.
## Idempotence and Recovery
The implementation is additive and safe to repeat. Creating directories that already exist should do nothing. Re-running the validation commands should produce the same result.
If scene files are malformed, open the project with `.\godot --editor --path godot`, let Godot report the scene load error, and repair the smallest affected scene file. Do not delete unrelated files. If Godot generates `.uid` files for new scenes or scripts, keep them if Godot requires them; otherwise do not hand-edit generated IDs.
If `.\godot --headless --path godot --build-solutions --quit` hangs, stop only the stuck Godot process, record the command and process details in `Surprises & Discoveries`, and validate with `dotnet build SideScrollerGame.sln` plus the smoke boot command. Do not use broad process-kill commands that could stop an editor session the user is actively using.
If user changes appear in files outside this slice, leave them untouched. If a user change conflicts with `godot/project.godot`, read the file and merge only the needed main scene, input map, and debug setting entries.
## Artifacts and Notes
Current verification before implementation:
dotnet build SideScrollerGame.sln
Determining projects to restore...
All projects are up-to-date for restore.
SideScrollerGame.Godot -> D:\Code\zfxaction26_1\godot\.godot\mono\temp\bin\Debug\SideScrollerGame.Godot.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Current Godot project files before implementation:
godot\SideScrollerGame.Godot.csproj
godot\project.godot
godot\icon.svg.import
godot\icon.svg
Current dirty files before implementation:
M DESIGN.md
M SideScrollerGame.sln
M godot/SideScrollerGame.Godot.csproj
Those modified files are user work. This slice must not revert them.
## Interfaces and Dependencies
The project uses Godot 4.5.1 .NET through `Godot.NET.Sdk/4.5.1` and targets `net8.0` for desktop builds. Scripts should use the `Godot` C# namespace and partial Godot classes where required by the engine.
At the end of this slice, these C# types should exist:
In `godot/scripts/debug/DebugBootMode.cs`:
namespace SideScrollerGame.Debug;
public enum DebugBootMode
{
Menu,
Smoke
}
In `godot/scripts/debug/DebugSettings.cs`:
namespace SideScrollerGame.Debug;
public sealed class DebugSettings
{
public DebugBootMode BootMode { get; }
public int Seed { get; }
public static DebugSettings Load();
}
`DebugSettings.Load()` must read user command-line arguments first, then fall back to project settings. Unknown boot modes should fall back to `Menu` and print a Godot warning.
In `godot/scripts/bootstrap/GameRoot.cs`:
namespace SideScrollerGame.Bootstrap;
public partial class GameRoot : Node
{
public override void _Ready();
public void LoadBootScene(DebugBootMode bootMode);
}
`GameRoot` must instantiate `res://scenes/menu/MenuPlaceholder.tscn` for `Menu` and `res://scenes/debug/SmokeScene.tscn` for `Smoke`.
In `godot/scripts/debug/DebugOverlay.cs`:
namespace SideScrollerGame.Debug;
public partial class DebugOverlay : CanvasLayer
{
public void SetStatus(DebugSettings settings, string loadedSceneId);
}
The overlay should be visible by default in non-release builds. It should be small, top-left, and not block input.
In `godot/scripts/debug/SmokeSceneController.cs`:
namespace SideScrollerGame.Debug;
public partial class SmokeSceneController : Node2D
{
public override void _Ready();
}
In headless mode, the smoke controller should print confirmation and call `GetTree().Quit(0)` after at least one idle frame.
In `godot/scripts/menu/MenuPlaceholder.cs`:
namespace SideScrollerGame.Menu;
public partial class MenuPlaceholder : Control
{
public override void _Ready();
}
The menu placeholder may only set label text in this slice. Real menu behavior belongs to a later slice.
Revision note 2026-04-21: Created this ExecPlan from current repository state. The plan keeps `godot/project.godot` as the project entrypoint, incorporates the user's fixed solution and C# project state, and scopes Slice 1 to a bootable Godot shell with debug boot and smoke validation.