Remove the one-way ore API superseded by the transfer menu
The loose end from #24. withdraw_to_fleet, unload_into_building and deliver_cargo were the old one-way moves behind "Load ore" and "Store ore here"; every one of them is a special case of transfer_to_building / transfer_to_fleet, and none had a caller left outside tests. The cargo_delivered signal had no listeners at all. Not just tidying: unload_into_building routed through deposit_to_building, which does NOT special-case the mothership - it writes b.stock, while building_holdings() returns `rocks` for a mothership and ignores stock entirely. So unload_into_building( mothership_id) would have parked ore in a field nothing reads, with no error. Nothing called it that way, but it is a plausibly-named function sitting there to be reached for later. transfer_to_building handles it. CARGO_LOAD_BATCH stays - the transfer menu's batch buttons use it; only its role as withdraw_to_fleet's default argument is gone. The #24 note expected folding these in to be costly for test_cargo_readout, which places no buildings. It is not: the transfer primitives work off GameState records rather than spawned nodes, so a single add_building() in setup is enough and it stays a display test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
fe1c721d64
commit
b6427b080d
27 changed files with 1085 additions and 275 deletions
|
|
@ -5,29 +5,28 @@ extends SceneTree
|
|||
# Every press in the ship crafter must say what happened. Reported twice from
|
||||
# play-testing as "the buttons do nothing".
|
||||
#
|
||||
# There is no silent-failure path left to press: storing with an empty hold,
|
||||
# ordering something the crafter cannot pay for yet, and storing successfully
|
||||
# all report. The queue in particular is invisible by nature - an order that
|
||||
# cannot be afforded is accepted and waits (#16), which looks exactly like a
|
||||
# dead button unless it says so.
|
||||
# The queue is invisible by nature - an order that cannot be afforded is
|
||||
# accepted and waits (#16), which looks exactly like a dead button unless it
|
||||
# says so.
|
||||
#
|
||||
# Verifies:
|
||||
# 1. storing with an empty hold explains where ore comes from
|
||||
# 2. ordering against an empty stock says it is queued AND how much more
|
||||
# 1. ordering against an empty stock says it is queued AND how much more
|
||||
# ore the building needs
|
||||
# 3. a successful store reports the amount
|
||||
# 4. the message survives the per-frame status refresh - it used to be
|
||||
# 2. the message survives the per-frame status refresh - it used to be
|
||||
# overwritten on the very next frame, which is what made a working
|
||||
# button look dead
|
||||
# 5. the message is the FIRST line, not buried under the standing state
|
||||
# 6. the panel is opened the way the GAME opens it - park the fleet on the
|
||||
# crafter and press the action button - and every button then works
|
||||
# 3. the message is the FIRST line, not buried under the standing state
|
||||
# 4. the panel is opened the way the GAME opens it - park the fleet on the
|
||||
# crafter and press the action button - and its buttons then work
|
||||
#
|
||||
# Point 6 exists because this test used to set craft_building_id by hand.
|
||||
# Point 4 exists because this test used to set craft_building_id by hand.
|
||||
# That skipped the one step that was actually broken: opening the panel
|
||||
# stopped recording WHICH crafter, so every handler bailed out at its `== 0`
|
||||
# guard while the panel still opened. Reported four times as "the buttons do
|
||||
# nothing", and invisible to every test that set the id itself.
|
||||
#
|
||||
# Storing ore used to be tested here too. It moved out of this panel entirely
|
||||
# in #24 - see test_resource_transfer.gd.
|
||||
|
||||
var game_state: Node
|
||||
var scene: Node
|
||||
|
|
@ -44,7 +43,11 @@ func _initialize() -> void:
|
|||
game_state.extractors.clear()
|
||||
game_state.transporters.clear()
|
||||
game_state.reset_progression()
|
||||
game_state.unlocked = ["shipyards", "coordination", "wing"]
|
||||
# Every capacity node, so the interceptor button stays available for the
|
||||
# real-tap checks below. A full fleet correctly DISABLES it, and a
|
||||
# disabled button not reacting to a tap is not the bug those checks are
|
||||
# looking for.
|
||||
game_state.unlocked = ["shipyards", "coordination", "wing", "squadron", "armada"]
|
||||
game_state.rocks = 100
|
||||
game_state.fleet_cargo = 0
|
||||
game_state.vessels_owed.clear()
|
||||
|
|
@ -104,17 +107,7 @@ func _process(delta: float) -> bool:
|
|||
return true
|
||||
print("panel opened from the building, bound to crafter %d" % controller.craft_building_id)
|
||||
|
||||
# --- 1. store with an empty hold ----------------------------
|
||||
controller._on_store_ore()
|
||||
var empty_msg: String = _first_line()
|
||||
if "carrying nothing" not in empty_msg:
|
||||
print("got: %s" % empty_msg)
|
||||
print("TEST_CRAFTER_FEEDBACK: FAIL (storing with an empty hold said nothing useful)")
|
||||
quit(1)
|
||||
return true
|
||||
print("empty hold -> %s" % empty_msg)
|
||||
|
||||
# --- 2. order against an empty stock ------------------------
|
||||
# --- 1. order against an empty stock ------------------------
|
||||
controller._on_craft_interceptor()
|
||||
var queued_msg: String = _first_line()
|
||||
if "queued" not in queued_msg.to_lower() or "more ore" not in queued_msg:
|
||||
|
|
@ -127,71 +120,47 @@ func _process(delta: float) -> bool:
|
|||
quit(1)
|
||||
return true
|
||||
print("unaffordable order -> %s" % queued_msg)
|
||||
|
||||
# --- 3. a successful store ----------------------------------
|
||||
game_state.withdraw_to_fleet(30)
|
||||
controller._on_store_ore()
|
||||
var stored_msg: String = _first_line()
|
||||
if "Stored" not in stored_msg:
|
||||
print("got: %s" % stored_msg)
|
||||
print("TEST_CRAFTER_FEEDBACK: FAIL (a successful store did not report)")
|
||||
quit(1)
|
||||
return true
|
||||
print("successful store -> %s" % stored_msg)
|
||||
elapsed = 0.0
|
||||
stage = 2
|
||||
return false
|
||||
2:
|
||||
# --- 4 + 5. it survives the refresh, and stays first --------
|
||||
# --- 2 + 3. it survives the refresh, and stays first --------
|
||||
if elapsed < 0.5:
|
||||
return false
|
||||
controller._refresh_craft_status()
|
||||
var still: String = _first_line()
|
||||
if "Stored" not in still:
|
||||
if "queued" not in still.to_lower():
|
||||
print("first line half a second later: %s" % still)
|
||||
print("TEST_CRAFTER_FEEDBACK: FAIL (the message was overwritten by the per-frame refresh)")
|
||||
quit(1)
|
||||
return true
|
||||
print("half a second later, still first: %s" % still)
|
||||
|
||||
# --- 6. a REAL tap, through the input path ------------------
|
||||
# --- 4. a REAL tap, through the input path ------------------
|
||||
# Everything above calls the handlers directly, which is how a
|
||||
# whole class of bug kept getting missed: the crafter logic was
|
||||
# fine and the BUTTON was inert, blocked by a modal guard. This
|
||||
# taps the control the way a touch does.
|
||||
game_state.withdraw_to_fleet(20)
|
||||
var stock_before: int = game_state.building_stock(crafter_id)
|
||||
var store_button: Control = scene.get_node("UI/CraftMenu/StoreOreButton")
|
||||
for pressed in [true, false]:
|
||||
var ev: InputEventScreenTouch = InputEventScreenTouch.new()
|
||||
ev.pressed = pressed
|
||||
ev.position = store_button.size / 2.0
|
||||
store_button._gui_input(ev)
|
||||
if game_state.building_stock(crafter_id) <= stock_before:
|
||||
print("stock %d -> %d after tapping Store ore" % [
|
||||
stock_before, game_state.building_stock(crafter_id)
|
||||
var queued_before: int = game_state.pending_orders(crafter_id)
|
||||
_tap(scene.get_node("UI/CraftMenu/InterceptorButton"))
|
||||
if game_state.pending_orders(crafter_id) <= queued_before:
|
||||
print("orders %d -> %d after tapping Interceptor" % [
|
||||
queued_before, game_state.pending_orders(crafter_id)
|
||||
])
|
||||
print("TEST_CRAFTER_FEEDBACK: FAIL (tapping the store button did nothing)")
|
||||
print("TEST_CRAFTER_FEEDBACK: FAIL (tapping the interceptor button did nothing)")
|
||||
quit(1)
|
||||
return true
|
||||
print("real tap on Store ore moved %d ore into the crafter" % [
|
||||
game_state.building_stock(crafter_id) - stock_before
|
||||
])
|
||||
print("real tap on Interceptor queued another order")
|
||||
|
||||
# And the same tap must still work after the build menu has been
|
||||
# opened and closed, which used to block every button forever.
|
||||
controller._on_build_pressed()
|
||||
controller._show_building_info(GameState.BUILDING_SHIP_CRAFTER)
|
||||
scene.get_node("UI/BuildMenu").visible = false
|
||||
game_state.withdraw_to_fleet(10)
|
||||
var stock_mid: int = game_state.building_stock(crafter_id)
|
||||
for pressed2 in [true, false]:
|
||||
var ev2: InputEventScreenTouch = InputEventScreenTouch.new()
|
||||
ev2.pressed = pressed2
|
||||
ev2.position = store_button.size / 2.0
|
||||
store_button._gui_input(ev2)
|
||||
if game_state.building_stock(crafter_id) <= stock_mid:
|
||||
print("TEST_CRAFTER_FEEDBACK: FAIL (store button dead after the build menu was opened and closed)")
|
||||
var queued_mid: int = game_state.pending_orders(crafter_id)
|
||||
_tap(scene.get_node("UI/CraftMenu/InterceptorButton"))
|
||||
if game_state.pending_orders(crafter_id) <= queued_mid:
|
||||
print("TEST_CRAFTER_FEEDBACK: FAIL (craft button dead after the build menu was opened and closed)")
|
||||
quit(1)
|
||||
return true
|
||||
print("still works after opening and closing the build menu")
|
||||
|
|
|
|||
Loading…
Reference in a new issue