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

19 KiB

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

  • (2026-04-21 16:36Z) Read repository rules, Windows rules, PLANS.md, CODE.md, and current Godot project files.
  • (2026-04-21 16:36Z) Verified that the Godot project currently lives in godot/project.godot, not at the repository root.
  • (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.
  • (2026-04-21 16:52Z) Implemented root scene, placeholder scene, smoke scene, input actions, and debug boot code.
  • (2026-04-21 16:52Z) Ran formatting for touched C# files with jb cleanupcode --build=False.
  • (2026-04-21 16:52Z) Validated with .NET build, Godot solution build, and headless smoke boot.
  • (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.