Preserve production code, regression fixtures, audio assets and provenance, test infrastructure, and the original-completion plan and progress ledger. Final game and Windows acceptance remain pending; excluded local artifacts and native experiments are not part of this snapshot.
74 lines
3.7 KiB
GDScript
74 lines
3.7 KiB
GDScript
extends SceneTree
|
|
const FixtureCleanup := preload("res://tests/helpers/ui_audio_fixture_cleanup.gd")
|
|
var checks := 0
|
|
var failures := 0
|
|
func _initialize() -> void: call_deferred("run")
|
|
func expect(ok: bool, message: String) -> void:
|
|
checks += 1
|
|
if not ok:
|
|
failures += 1
|
|
push_error(message)
|
|
func run() -> void:
|
|
root.gui_embed_subwindows = true
|
|
root.size = Vector2i(1280,720)
|
|
var runtime: Variant = root.get_node("SimulationRuntime")
|
|
var clock: Variant = root.get_node("GameClock")
|
|
clock.reset(1,6,0)
|
|
root.get_node("GameState").reset()
|
|
runtime.initialize(clock,root.get_node("GameState"),424242)
|
|
clock.set_paused(true)
|
|
runtime.configure_save_policy({&"enabled": false})
|
|
var main: Control = load("res://scenes/main/main.tscn").instantiate()
|
|
root.add_child(main)
|
|
await process_frame
|
|
runtime.configure_save_policy({&"enabled": false})
|
|
for initial: GuestRuntime in runtime.guest_service.get_guests():
|
|
initial.state = GuestRuntime.State.LEAVING
|
|
runtime.guest_service.despawn_guest(initial.guest_id,clock.absolute_minute)
|
|
main.guest_count_label.pressed.emit()
|
|
await process_frame
|
|
var panel: GuestObservationPanel = main.guest_observer.find_child("GuestObservationPanel", true, false)
|
|
expect(main.guest_observer.visible and panel.guests.disabled, "HUD opens an empty observer without inventing visitors")
|
|
var service: GuestService = runtime.guest_service
|
|
var definition: GuestDefinition = service.get_definitions()[0]
|
|
var guest := service.spawn_guest(&"observer_guest", definition.guest_type_id, clock.absolute_minute, {&"wallet_gold": 500, &"needs": {&"hunger": 90, &"sleep": 70}, &"planned_exit_at": clock.absolute_minute+1000})
|
|
panel.refresh()
|
|
expect(panel.selected_guest_id == guest.guest_id and not panel.guests.disabled, "new real visitor appears in the observer")
|
|
expect(panel.bars[&"hunger"].value == 90 and "食欲" in panel.priority_label.text, "bars and highest need match actual state")
|
|
var before := SimulationDigest.compute(runtime.create_snapshot())
|
|
for frame: int in 3: panel.refresh()
|
|
expect(before == SimulationDigest.compute(runtime.create_snapshot()), "observing never changes the simulation")
|
|
guest.needs[&"sleep"] = 100
|
|
panel.refresh()
|
|
expect(panel.bars[&"sleep"].value == 100 and "睡眠欲" in panel.priority_label.text, "observer refreshes after needs change")
|
|
for state: int in GuestRuntime.State.values():
|
|
guest.state = state
|
|
panel.refresh()
|
|
expect(not panel.details.text.is_empty(), "every real state has a label")
|
|
guest.state = GuestRuntime.State.DECIDING
|
|
var saved := service.create_snapshot()
|
|
service.begin_leaving(guest.guest_id,clock.absolute_minute+1,&"TEST")
|
|
service.despawn_guest(guest.guest_id,clock.absolute_minute+2)
|
|
panel.refresh()
|
|
expect(panel.guests.disabled and panel.selected_guest_id.is_empty(), "despawn removes stale selection")
|
|
expect(service.restore_snapshot(saved), "guest snapshot restores")
|
|
panel.refresh()
|
|
expect(panel.selected_guest_id == &"observer_guest" and panel.bars[&"sleep"].value == 100, "read model follows restored service objects")
|
|
main.guest_observer.hide()
|
|
main.guest_count_label.pressed.emit()
|
|
await process_frame
|
|
expect(main.guest_observer.visible and clock.paused, "reopening preserves pause state")
|
|
main._refresh_dashboard()
|
|
if OS.get_environment("THE_TREE_GUEST_CAPTURE") == "1":
|
|
await process_frame
|
|
await RenderingServer.frame_post_draw
|
|
root.get_texture().get_image().save_png("res://artifacts/guest-ai-2026-09-29/observer.png")
|
|
var _audio_cleanup_final: Dictionary = await FixtureCleanup.free_owner_and_wait(self, main)
|
|
if not bool(_audio_cleanup_final.get(&"passed", false)):
|
|
push_error("Ordinary fixture audio cleanup failed: %s" % str(_audio_cleanup_final))
|
|
quit(96)
|
|
return
|
|
await process_frame
|
|
print("Guest observer: %d checks, %d failures" % [checks, failures])
|
|
quit(failures)
|