Everything lived in one flat directory, so a diff gave no clue what area it touched and finding the file you wanted meant knowing its exact name. Twelve folders now, grouped by what a thing IS rather than what type it is - a vessel's definition, its component scenes and its upgrade resources sit together, because that is the set you read when you change one of them. buildings core controllers enemies logistics planets resources shaders surface ui vessels vfx world 332 files moved and every res:// reference rewritten - 306 files touched, including the autoload and main-scene paths in project.godot. Nothing renamed: this is purely where files sit, so the diff is a pile of pure moves and no behaviour is buried in it. ui_theme.tres, icon.svg and web_shell.html stay at the root, where Godot and the export preset expect them. Verified three ways, because a suite alone would not have caught all of it: the full 117 pass, the web export builds clean, and the game renders. The export is why that matters. The FIRST export after the move failed with "Attempt to open script 'res://GameState.gd'" - the old path - while project.godot on disk plainly said res://core/GameState.gd. That is this project's documented Android FUSE mtime trap: Godot served a cached copy of a file whose content had changed. A `touch` fixed it. Nothing in the test suite would have found that, because the suite runs from a copy on a native filesystem - the one place the bug cannot happen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
129 lines
4.7 KiB
GDScript
129 lines
4.7 KiB
GDScript
extends SceneTree
|
|
|
|
# Headless gameplay test: run with
|
|
# godot --headless -s res://tests/test_cargo_readout.gd
|
|
# Forgejo #15 (part 2 of #12): what the fleet is carrying has to be visible
|
|
# separately from what is banked.
|
|
#
|
|
# Since #14, ore is cargo until the fleet delivers it to the mothership. The
|
|
# banked readout does not move on pickup, so without a second readout mining
|
|
# looks broken - you gather ore and no number on screen changes.
|
|
#
|
|
# --headless has no GPU and draws no pixels, so this asserts on the two
|
|
# readouts' state, not on their appearance. tests/screenshot.sh covers
|
|
# whether they are legible.
|
|
#
|
|
# Verifies:
|
|
# 1. the banked readout keeps showing the BANK, not the total
|
|
# 2. the cargo readout shows the hold, and appears only while carrying
|
|
# 3. an empty hold hides it rather than parking a permanent 0 beside the
|
|
# real total
|
|
# 4. delivering moves the number from one readout to the other
|
|
# 5. the two are actually told apart on screen, rather than being the same
|
|
# number twice in the same colour at the same place
|
|
|
|
var game_state: Node
|
|
var scene: Node
|
|
var banked: Control
|
|
var cargo: Control
|
|
var stage: int = 0
|
|
var mothership_id: int = 0
|
|
var elapsed: float = 0.0
|
|
|
|
|
|
func _initialize() -> void:
|
|
game_state = root.get_node("GameState")
|
|
game_state.buildings.clear()
|
|
game_state.extractors.clear()
|
|
game_state.rocks = 42
|
|
game_state.fleet_cargo = 0
|
|
# Banking is a transfer TO the mothership now (#24), and a transfer needs
|
|
# a building to aim at. Only the record is required - the transfer
|
|
# primitives work off GameState, not off the spawned node - so this stays
|
|
# a display test rather than becoming one about the building system.
|
|
mothership_id = game_state.add_building(GameState.BUILDING_MOTHERSHIP, Vector2.ZERO)
|
|
scene = load("res://world/Main.tscn").instantiate()
|
|
root.add_child(scene)
|
|
|
|
|
|
func _process(delta: float) -> bool:
|
|
elapsed += delta
|
|
match stage:
|
|
0:
|
|
if elapsed < 0.2:
|
|
return false
|
|
# ResourceReadout builds its rows in _ready(), which for a -s
|
|
# entry-point script does not fire synchronously inside
|
|
# _initialize()'s add_child() - it is deferred to the first
|
|
# frame. Looking these up here, after the elapsed wait above,
|
|
# instead of right after add_child(), is what makes them non-null.
|
|
var readout: Node = scene.get_node("UI/ResourceReadout")
|
|
banked = readout.banked_number(GameState.RESOURCE_ORE)
|
|
cargo = readout.fleet_number(GameState.RESOURCE_ORE)
|
|
# --- 3. nothing carried -> no cargo readout -----------------
|
|
if cargo.visible:
|
|
print("TEST_CARGO_READOUT: FAIL (cargo readout showing with an empty hold)")
|
|
quit(1)
|
|
return true
|
|
if banked.amount != 42:
|
|
print("TEST_CARGO_READOUT: FAIL (banked readout shows %d, bank is 42)" % banked.amount)
|
|
quit(1)
|
|
return true
|
|
print("empty hold -> cargo readout hidden, banked shows %d" % banked.amount)
|
|
|
|
game_state.collect_cargo(7)
|
|
elapsed = 0.0
|
|
stage = 1
|
|
return false
|
|
1:
|
|
if elapsed < 0.2:
|
|
return false
|
|
# --- 1 + 2. carried and banked are separate numbers ---------
|
|
if not cargo.visible:
|
|
print("TEST_CARGO_READOUT: FAIL (carrying 7 and the cargo readout is hidden)")
|
|
quit(1)
|
|
return true
|
|
if cargo.amount != 7:
|
|
print("TEST_CARGO_READOUT: FAIL (cargo readout shows %d, hold is 7)" % cargo.amount)
|
|
quit(1)
|
|
return true
|
|
if banked.amount != 42:
|
|
print("TEST_CARGO_READOUT: FAIL (banked readout moved to %d on a pickup - it is showing the total, not the bank)" % banked.amount)
|
|
quit(1)
|
|
return true
|
|
print("carrying 7 -> cargo=%d banked=%d" % [cargo.amount, banked.amount])
|
|
|
|
# --- 5. genuinely distinguishable ---------------------------
|
|
if cargo.glow_color == banked.glow_color:
|
|
print("TEST_CARGO_READOUT: FAIL (both readouts drawn in the same colour)")
|
|
quit(1)
|
|
return true
|
|
if cargo.position == banked.position:
|
|
print("TEST_CARGO_READOUT: FAIL (both readouts in the same place)")
|
|
quit(1)
|
|
return true
|
|
print("distinct: colours %s vs %s, at %s vs %s" % [
|
|
cargo.glow_color, banked.glow_color, cargo.position, banked.position
|
|
])
|
|
|
|
# --- 4. delivery moves it across ----------------------------
|
|
game_state.transfer_to_building(mothership_id, game_state.fleet_cargo)
|
|
elapsed = 0.0
|
|
stage = 2
|
|
return false
|
|
2:
|
|
if elapsed < 0.2:
|
|
return false
|
|
if cargo.visible:
|
|
print("TEST_CARGO_READOUT: FAIL (cargo readout still showing after delivery)")
|
|
quit(1)
|
|
return true
|
|
if banked.amount != 49:
|
|
print("TEST_CARGO_READOUT: FAIL (banked shows %d after delivering 7 into 42)" % banked.amount)
|
|
quit(1)
|
|
return true
|
|
print("delivered -> cargo hidden, banked shows %d" % banked.amount)
|
|
print("TEST_CARGO_READOUT: PASS")
|
|
quit(0)
|
|
return true
|
|
return false
|