refactor(m4c): rename GameFlow coordinator to Main, move to scenes/Main.tscn

The entry-point coordinator read as an internal name ("GameFlow" buried in
scenes/flow/), so it wasn't obvious THIS is the scene that boots first — the
title screen looked like the entry point. Renamed to the Godot-conventional
Main (scenes/Main.tscn + scripts/main.gd) so the boot scene is self-evident.
TitleScreen is unchanged and still shown BY Main as its first screen.

Also drops the hand-written gd_scene uid (now matches sibling scenes) —
closes the Minor review finding. Full suite 327/327 green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-15 05:16:32 -05:00
parent 5a9f39ea48
commit d553213563
9 changed files with 14 additions and 27 deletions

View File

@@ -13,26 +13,13 @@ config_version=5
config/name="coc-rpg"
config/description="AI-driven single-player party RPG. Code owns state. AI owns text."
config/version="0.01-alpha"
run/main_scene="res://scenes/flow/GameFlow.tscn"
run/main_scene="res://scenes/Main.tscn"
config/features=PackedStringArray("4.7")
[display]
; The DESIGN CANVAS stays 1920x1080 — the mockups (§16) are authored there, and every
; .tscn's offsets are in those coordinates. It is a logical canvas, not a demand on the
; monitor: canvas_items + keep scales it uniformly into whatever window it is given, so
; the UI never reflows, it only gets smaller. Nothing below changes a layout number.
window/size/viewport_width=1920
window/size/viewport_height=1080
; The WINDOW is what the laptop has to fit, and it is a different question. 1600x900 was
; larger than a 1600x900 laptop's *usable* area once the WM took its panel and titlebar,
; so the window manager clamped it to 1589x752 and the run came up pillarboxed. 1280x720
; is 16:9 and fits any laptop this ships to; the window is resizable (Godot's default),
; and canvas_items rescales the canvas live on every resize.
window/size/window_width_override=1280
window/size/window_height_override=720
window/size/resizable=true
window/stretch/mode="canvas_items"
; keep = letterbox rather than distort or reflow. This IS Godot 4's default, so the editor
; prunes the line whenever it rewrites this file — that is cosmetic, not a behaviour change.
window/stretch/aspect="keep"

6
client/scenes/Main.tscn Normal file
View File

@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3]
[ext_resource type="Script" path="res://scripts/main.gd" id="1"]
[node name="Main" type="Node"]
script = ExtResource("1")

View File

@@ -1,6 +0,0 @@
[gd_scene load_steps=2 format=3 uid="uid://coc_gameflow"]
[ext_resource type="Script" path="res://scripts/ui/flow/game_flow.gd" id="1"]
[node name="GameFlow" type="Node"]
script = ExtResource("1")

View File

@@ -1,4 +1,4 @@
class_name GameFlow
class_name Main
extends Node
## The single home for the game's screen sequence: Title → Creation → Shell.
## Script-first by design — a pure coordinator with no Control layout, so ADR 0001's
@@ -88,6 +88,6 @@ func _start_campaign(creation: Dictionary) -> void:
if not result.get("ok", false):
# Unreachable via the UI (the CTA gates on validate), but §2 forbids trusting
# the caller and §13 forbids surfacing an error. Log and stay put.
push_error("GameFlow: construct rejected a creation: %s" % str(result.get("errors", [])))
push_error("Main: construct rejected a creation: %s" % str(result.get("errors", [])))
return
_show_shell(result["log"], result["state"])

View File

@@ -0,0 +1 @@
uid://du7rwup648n60

View File

@@ -1 +0,0 @@
uid://cy0r08ct0jugt

View File

@@ -1 +0,0 @@
uid://buyyn7tbjctb

View File

@@ -1,6 +1,6 @@
extends "res://addons/gut/test.gd"
const SCENE := "res://scenes/flow/GameFlow.tscn"
const SCENE := "res://scenes/Main.tscn"
const ContentDB = preload("res://scripts/content/content_db.gd")
const FakeTransport = preload("res://tests/doubles/fake_transport.gd")
const DmResponse = preload("res://scripts/net/dm_response.gd")
@@ -31,7 +31,7 @@ func _creation() -> Dictionary:
func test_boots_into_the_title():
var flow := _flow()
assert_true(flow._current is TitleScreen, "GameFlow opens on the title")
assert_true(flow._current is TitleScreen, "Main opens on the title")
func test_new_game_shows_creation():
@@ -53,7 +53,7 @@ func _assert_stays_on_creation(bad: Dictionary, why: String) -> void:
var flow := _flow()
flow._current.emit_signal("menu_activated", &"new_game")
# Drive the REAL signal with an invalid dict. The CTA gates this out via the UI,
# but §2 forbids GameFlow trusting the caller and §13 forbids surfacing an error.
# but §2 forbids Main trusting the caller and §13 forbids surfacing an error.
flow._current.emit_signal("creation_confirmed", bad)
assert_false(flow._current is MainWindowShell, "a failed construct never reaches the shell (§13): %s" % why)
assert_true(flow._current is CharacterCreation, "the player stays on the valid creation screen: %s" % why)

View File

@@ -0,0 +1 @@
uid://17abdh3almry