Capture current source, content data, tests, asset licenses, and original-specification traceability. Original implementation remains incomplete. The accepted matching UI generation passed 154 suites and 12,253 checks, with eight rendered staff-contract screens reviewed. Latest native Windows and full-original acceptance remain outstanding.
120 lines
6.3 KiB
GDScript
120 lines
6.3 KiB
GDScript
extends "res://tests/ui/test_first_operating_day.gd"
|
|
## Two-process natural opening/three-close debug flow. The Python runner supplies
|
|
## an isolated slot and evidence directory; never use ordinary player saves.
|
|
var _handoff_done := false
|
|
|
|
func _run() -> void:
|
|
if OS.get_environment("THE_TREE_OPENING_RESTART_SLOT").is_empty():
|
|
push_error("Restart runner must supply its isolated save slot")
|
|
quit(1)
|
|
return
|
|
if "--read" not in OS.get_cmdline_user_args():
|
|
await super._run()
|
|
return
|
|
_clock = root.get_node("GameClock")
|
|
_runtime = root.get_node("SimulationRuntime")
|
|
var state: Variant = root.get_node("GameState")
|
|
_clock.reset(1, 6, 0)
|
|
state.reset()
|
|
_runtime.initialize(_clock, state, 424242)
|
|
_clock.set_paused(true)
|
|
root.size = Vector2i(1440, 810)
|
|
_main = load("res://scenes/main/main.tscn").instantiate()
|
|
_main.set("manual_save_path", OS.get_environment("THE_TREE_OPENING_RESTART_SLOT"))
|
|
root.add_child(_main)
|
|
_runtime.configure_save_policy({&"enabled": false, &"daily_checkpoint_enabled": false})
|
|
await process_frame
|
|
await process_frame
|
|
_guide = _main.find_child("InnOpeningGuide", true, false)
|
|
_ledger = _main.find_child("OperatingLedgerPanel", true, false)
|
|
_load_handoff()
|
|
await _continue_to_third_close()
|
|
var expected: Variant = JSON.parse_string(FileAccess.get_file_as_string(_evidence_path("expected.json")))
|
|
_expect(expected is Dictionary, "previous process retained expected continuation evidence")
|
|
if expected is Dictionary:
|
|
_expect(_gameplay_digest() == expected.get("gameplay_digest"), "fresh process reproduces full gameplay snapshot through third close")
|
|
_expect(JSON.stringify(_runtime.operations_coordinator.get_day_summaries()) == expected.get("closes_json"), "all three financial reports exactly match uninterrupted continuation")
|
|
await _capture_restart("restarted-third-close")
|
|
if _failures == 0:
|
|
SaveService.delete_save(OS.get_environment("THE_TREE_OPENING_RESTART_SLOT"))
|
|
super._finish()
|
|
|
|
func _finish() -> void:
|
|
if _failures > 0 or _handoff_done:
|
|
super._finish()
|
|
return
|
|
_handoff_done = true
|
|
_main.set("manual_save_path", OS.get_environment("THE_TREE_OPENING_RESTART_SLOT"))
|
|
var selected_id: StringName = _runtime.facility_service.get_instances()[0].instance_id
|
|
_main.call("_on_facility_selected", selected_id)
|
|
var selection_file := FileAccess.open(_evidence_path("selection.json"), FileAccess.WRITE)
|
|
selection_file.store_string(JSON.stringify({"id": String(selected_id)}))
|
|
selection_file.close()
|
|
var found_save := false
|
|
for node: Node in _main.find_children("*", "Button", true, false):
|
|
if node.text == "保存":
|
|
node.pressed.emit()
|
|
found_save = true
|
|
break
|
|
_expect(found_save, "save through the normal dashboard button")
|
|
_load_handoff()
|
|
await _capture_restart("saved-second-morning")
|
|
await _continue_to_third_close()
|
|
var file := FileAccess.open(_evidence_path("expected.json"), FileAccess.WRITE)
|
|
_expect(file != null, "continuation evidence can be retained")
|
|
if file != null:
|
|
file.store_string(JSON.stringify({"gameplay_digest": _gameplay_digest(), "closes_json": JSON.stringify(_runtime.operations_coordinator.get_day_summaries())}, "\t") + "\n")
|
|
file.close()
|
|
await _capture_restart("uninterrupted-third-close")
|
|
super._finish()
|
|
|
|
func _load_handoff() -> void:
|
|
var menu := _main.find_child("SaveLoadMenu", true, false) as MenuButton
|
|
_expect(menu != null and not menu.disabled, "normal load menu is available")
|
|
if menu != null and not menu.disabled:
|
|
menu.get_popup().id_pressed.emit(0)
|
|
_expect(_clock.absolute_minute == 1920, "disk load restores the second morning at08:00")
|
|
_expect(_guide.get_progress().get(&"stage") == &"complete", "restarted UI recognizes completed opening")
|
|
var selection: Dictionary = JSON.parse_string(FileAccess.get_file_as_string(_evidence_path("selection.json")))
|
|
_expect(String(_main.get("_selected_entity_id")) == selection["id"], "disk load restores the facility selected when saving")
|
|
_expect(_main.get("_selected_entity_kind") == &"facility", "disk load restores the selection type")
|
|
_expect(String(_main.get("world_preview").selected_entity_id) == selection["id"], "disk load restores the selected facility highlight")
|
|
|
|
func _continue_to_third_close() -> void:
|
|
await _advance(4320 - _clock.absolute_minute)
|
|
_expect(_clock.absolute_minute == 4320, "natural operation reaches third midnight")
|
|
var summaries: Array = _runtime.operations_coordinator.get_day_summaries()
|
|
_expect(summaries.size() == 3, "three calendar closes exist exactly once")
|
|
for summary: Dictionary in summaries:
|
|
_expect(summary.get(&"balanced", false), "every operating close reconciles with the ledger")
|
|
var report: Dictionary = _runtime.get_operations_report()
|
|
_expect(not report.get(&"runtime_failure_latched", true), "no simulation failure after multi-day continuation")
|
|
_expect(_ledger.get_report().get(&"selected_close") == summaries.back(), "dashboard presents latest third-day report")
|
|
var detail: String = _ledger.get("_facility_label").text
|
|
_expect(not detail.contains("facility_"), "completed infrastructure has human-readable ledger names")
|
|
for definition_id: StringName in [&"guest_stairs", &"guest_corridor"]:
|
|
var definition: FacilityDefinition = _runtime.definition_registry.get_facility(definition_id)
|
|
_expect(detail.contains(definition.display_name), "ledger identifies charged infrastructure: %s" % definition.display_name)
|
|
|
|
func _gameplay_digest() -> String:
|
|
var snapshot: Dictionary = _runtime.create_snapshot()
|
|
# SAVE_LOADED contains measured elapsed time, which differs by process.
|
|
# Preserve ID counters, RNG streams and every other gameplay subsystem.
|
|
snapshot[&"systems"][&"runtime"].erase(&"domain_events")
|
|
var phase := "read" if "--read" in OS.get_cmdline_user_args() else "write"
|
|
var evidence := FileAccess.open(_evidence_path(phase + "-gameplay.json"), FileAccess.WRITE)
|
|
if evidence != null:
|
|
evidence.store_string(JSON.stringify(snapshot, "\t") + "\n")
|
|
evidence.close()
|
|
return SimulationDigest.compute(snapshot)
|
|
|
|
func _evidence_path(name: String) -> String:
|
|
return OS.get_environment("THE_TREE_OPENING_RESTART_OUTPUT").path_join(name)
|
|
|
|
func _capture_restart(name: String) -> void:
|
|
if DisplayServer.get_name() == "headless": return
|
|
_main.call("_refresh_dashboard")
|
|
await process_frame
|
|
await RenderingServer.frame_post_draw
|
|
_expect(root.get_texture().get_image().save_png(_evidence_path(name + ".png")) == OK, "capture restart flow: " + name)
|