SavePaths ported verbatim from Theriapolis.Game/Platform/. Same OS
directories as MonoGame (%LOCALAPPDATA%\Theriapolis\Saves on
Windows, ~/Library/Application Support/Theriapolis/Saves on macOS,
$XDG_DATA_HOME/Theriapolis/saves on Linux) so saves round-trip
across the two builds without migration.
PlayScreen save layer. Wired PlayerReputation + Flags + QuestEngine
+ QuestContext + _killedByChunk + _pendingEncounterRestore in
_Ready, even though M7.3 doesn't actively drive any of those —
they're round-trip-required, so a save written by the MonoGame
build with non-empty rep/flags/quest state loads here and re-saves
without data loss. SaveTo/BuildHeader/CaptureBody/ApplyRestoredBody
are field-for-field ports of the MonoGame methods (Phase 5 M3 + M5,
Phase 6 M2 + M4); CaptureBody flushes the streamer first so chunk
deltas land in the store before serialisation. HandleChunkLoaded
now honours _killedByChunk so a killed spawn stays dead across
chunk reload + save round-trip.
F5 quicksaves to the autosave slot. Save-flash toast (bottom-center
Label, fade-out via Modulate.A) confirms each write.
_Ready branches on session.PendingRestore: when set (load path),
calls ApplyRestoredBody and skips the new-game spawn; otherwise
spawns at the Tier-1 anchor with the M6 character. The
mid-combat encounter snapshot is captured on save but the push to
CombatHUDScreen is the M8 stub (logs a console diagnostic).
SaveLoadScreen — load-only slot picker. Header-only deserialise
per row (SaveCodec.DeserializeHeaderOnly reads just the JSON
prefix, body untouched), so opening the picker is cheap even with
many large saves. Slot label matches MonoGame's SlotLabel() format
exactly. Incompatible / unreadable rows render disabled with the
reason inline.
TitleScreen Continue. Enable-gate replaced — was "user://character.json
exists" (M7.1 placeholder), now scans SavesDir for *.trps + checks
SaveCodec.IsCompatible. OnContinue swaps to SaveLoadScreen instead
of the print stub. Manual play-test loop confirmed: F5 in run #1,
quit, relaunch, Continue → Autosave row → progress bar → PlayScreen
with character restored at saved tile.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Lands the M7 plan's first two sub-milestones on port/godot.
theriapolis-rpg-implementation-plan-godot-port-m7.md is the design
doc (six screens collapse to four scenes + a camera mode, with
per-screen behavioural contracts and a six-step sub-milestone
breakdown).
M7.1 — WorldGenProgressScreen + GameSession autoload + wizard
hand-off rewrite. GameSession holds the cross-scene state that
outlives any single screen: seed, post-worldgen Ctx, pending
character (from the M6 wizard) and pending save snapshot (for
M7.3's load path). Wizard forwards StepReview.CharacterConfirmed
upward, and TitleScreen swaps to the progress screen instead of
just printing the build summary. The progress screen runs the
23-stage pipeline on a background thread, drives a ProgressBar
from ctx.ProgressCallback, and writes the full exception trace to
user://worldgen_error.log on failure. Escape cancels at the next
stage boundary and returns to title.
M7.2 — PlayScreen with a walking character. Extracted
WorldRenderNode from the M2+M4 WorldView demo so PlayScreen and
WorldView mount the same renderer (biome image + polylines +
bridges + settlement dots + tactical chunk lifecycle + PanZoomCamera
+ per-frame layer visibility + line-width counter-scaling).
PlayScreen owns the streamer (M7.3 save needs it), composes
ContentResolver + ActorManager + WorldClock + AnchorRegistry +
PlayerController, spawns the player at the Tier-1 anchor, and
wires resident + non-resident NPC spawning from chunk-load events
with allegiance-tinted markers.
PlayerController ported engine-agnostic to Theriapolis.Godot/Input/.
Takes pre-resolved dx/dy/dt/isTactical/isFocused instead of poking
MonoGame InputManager + Camera2D, so the arithmetic that advances
PlayerActor.Position and WorldClock.InGameSeconds is bit-identical
to the MonoGame version — saves round-trip cleanly.
Click-to-travel in world-map mode (camera zoom <
TacticalRenderZoomMin), WASD step in tactical mode with axis-
separated motion + encumbrance + sub-second clock carry. HUD
overlay top-left shows HP/AC/seed/tile/biome/view-mode/time. Esc
returns to title (M7.4 replaces this with a pause menu).
Namespace gotcha: Theriapolis.GodotHost.Input shadows the engine's
Godot.Input static class for any file under the GodotHost
namespace tree. Files needing keyboard polls (WorldView,
PlayScreen) fully qualify as Godot.Input.IsKeyPressed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>