P07-01-WX: 仕上がった天候の機能の受入:自然天候・雨・嵐・世界樹と成人客のマナ霧・上部の表示と予報・保存と移行(マナ炉の産出 120 を除く。P07-01 の補助の作業。原単位への加算 0)

This commit is contained in:
Agent Control Runner
2026-10-24 07:08:23 +09:00
parent c50136017b
commit f99c881bca
11 changed files with 370 additions and 42 deletions
@@ -3,7 +3,10 @@ extends SceneTree
## P07-01 F7, reader phase (a separate engine process after the writer). Each
## handed-off save package is loaded into a fresh Runtime, must equal the writer's
## state at that minute, and must continue to the writer's uninterrupted final
## state, with every remaining 06:00 draw happening exactly once.
## state, with every remaining 06:00 draw happening exactly once. The fog scene
## (WX7) packages must also equal the writer's state one minute after each save,
## so the fog mana yield and the adult intimacy apply exactly once across the
## process boundary.
const Fixture := preload("res://tests/helpers/p07_weather_restart_fixture.gd")
@@ -20,6 +23,7 @@ func _run() -> void:
var handoff := _read_handoff()
if not handoff.is_empty():
_check_restarts(handoff)
_check_fog(handoff.get("fog", {}))
await process_frame
if _failures == 0:
print("PASS: %d checks" % _checks)
@@ -54,18 +58,7 @@ func _check_restarts(handoff: Dictionary) -> void:
for save: Variant in saves:
var minute := int((save as Dictionary).get("minute", -1))
var path := Fixture.READER_SAVE % minute
var directory := ProjectSettings.globalize_path(path)
DirAccess.make_dir_recursive_absolute(directory)
var files: Dictionary = (save as Dictionary).get("files", {})
var intact := not files.is_empty()
for name: String in files:
var bytes := Marshalls.base64_to_raw(str(files[name].get("base64", "")))
intact = intact and Fixture.sha256(bytes) == str(files[name].get("sha256", "")) and bytes.size() == int(files[name].get("bytes", -1))
var file := FileAccess.open(directory.path_join(name), FileAccess.WRITE)
if file != null:
file.store_buffer(bytes)
file.close()
_expect(intact, "save package at minute %d arrived byte-exact" % minute)
_expect(_write_package(save, path), "save package at minute %d arrived byte-exact" % minute)
var expected_state := Marshalls.base64_to_raw(str((save as Dictionary).get("state_base64", "")))
var fixture := fixtures.new_fixture(false)
var runtime: Variant = fixture[&"runtime"]
@@ -85,6 +78,50 @@ func _check_restarts(handoff: Dictionary) -> void:
SaveService.delete_save(path)
func _check_fog(fog: Dictionary) -> void:
var fixtures := Fixture.new(_expect)
_expect(int(fog.get("seed", -1)) == Fixture.FOG_SEED and int(fog.get("last_minute", -1)) == Fixture.FOG_LAST_MINUTE, "same fog scene and minute script")
var final_state := Marshalls.base64_to_raw(str(fog.get("straight_final_state_base64", "")))
_expect(not final_state.is_empty() and Fixture.sha256(final_state) == str(fog.get("straight_final_state_sha256", "")), "the writer's fog final state arrived intact")
var saves: Array = fog.get("saves", [])
_expect(saves.size() == Fixture.FOG_SAVE_MINUTES.size(), "every fog save package was handed off")
var after: Dictionary = fog.get("after_states", {})
for save: Variant in saves:
var minute := int((save as Dictionary).get("minute", -1))
var path := Fixture.FOG_READER_SAVE % minute
_expect(_write_package(save, path), "fog save package at minute %d arrived byte-exact" % minute)
var expected_state := Marshalls.base64_to_raw(str((save as Dictionary).get("state_base64", "")))
var next_row: Dictionary = after.get(str(minute + 1), {})
var next_state := Marshalls.base64_to_raw(str(next_row.get("base64", "")))
_expect(not next_state.is_empty() and Fixture.sha256(next_state) == str(next_row.get("sha256", "")), "the writer's state one minute after %d arrived intact" % minute)
var fixture := fixtures.new_fixture(false, Fixture.FOG_SEED)
var runtime: Variant = fixture[&"runtime"]
_expect(bool(runtime.load_from_path(path).get(&"ok", false)) and fixtures.state_bytes(runtime) == expected_state and fixture[&"clock"].absolute_minute == minute,
"the reader resumes the minute %d fog save exactly" % minute)
fixtures.play(fixture, minute, minute + 1, Callable())
_expect(fixtures.state_bytes(runtime) == next_state, "one minute after the minute %d fog save the reader equals the uninterrupted run (no double fog yield or intimacy)" % minute)
fixtures.play(fixture, minute + 1, Fixture.FOG_LAST_MINUTE, Callable())
_expect(fixtures.state_bytes(runtime) == final_state, "continuing the minute %d fog save reaches the uninterrupted final state" % minute)
fixtures.free_fixture(fixture)
SaveService.delete_save(path)
## Writes one handed-off save package byte for byte; true when every file matches its pin.
func _write_package(save: Dictionary, path: String) -> bool:
var directory := ProjectSettings.globalize_path(path)
DirAccess.make_dir_recursive_absolute(directory)
var files: Dictionary = save.get("files", {})
var intact := not files.is_empty()
for name: String in files:
var bytes := Marshalls.base64_to_raw(str(files[name].get("base64", "")))
intact = intact and Fixture.sha256(bytes) == str(files[name].get("sha256", "")) and bytes.size() == int(files[name].get("bytes", -1))
var file := FileAccess.open(directory.path_join(name), FileAccess.WRITE)
if file != null:
file.store_buffer(bytes)
file.close()
return intact
func _expect(condition: bool, message: String) -> void:
_checks += 1
if not condition: