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
+32 -2
View File
@@ -276,8 +276,9 @@ func _legacy_controls(writer: Dictionary, reader: Dictionary) -> void:
## Approved later save migrations applied when an older save is loaded, each
## checked against its own contract and then mapped into `expected` in place:
## A06 starts a fresh finite Mana reserve at the restored boundary, and P14-03
## raises the elevator snapshot from v1 to v2 with every other field unchanged.
## A06 starts a fresh finite Mana reserve at the restored boundary, P14-03
## raises the elevator snapshot from v1 to v2 with every other field unchanged,
## and P07-01 A13 migrates the weather snapshot and adds the weather stream.
func _approved_runtime_migrations(expected: Dictionary, reader: Dictionary) -> Dictionary:
var old: Dictionary = expected[&"systems"][&"runtime"]
var now: Dictionary = reader[&"systems"][&"runtime"]
@@ -322,6 +323,35 @@ func _approved_runtime_migrations(expected: Dictionary, reader: Dictionary) -> D
old[&"economy"] = economy
fields.append("economy_A12_empty_fund_accounts")
proof["economy_A12"] = {"added_accounts": added.keys(), "only_accounts_added": only_accounts_added}
# P07-01 A13 (SPEC section 5.2): a save from before natural weather keeps its
# weather and pending schedule, counts every day whose 06:00 has passed as
# drawn (no past draw), holds no rain extension, and starts the weather
# stream from the world seed; every other field stays byte-identical.
var old_weather: Variant = old.get(&"weather")
var now_weather: Variant = now.get(&"weather")
if old_weather is Dictionary and int(old_weather.get(&"version", 0)) == 1 and now_weather is Dictionary and int(now_weather.get(&"version", 0)) == 2:
var weather_minute := int(old_weather[&"minute"])
var last_draw_day := floori(weather_minute / 1440.0) - (0 if posmod(weather_minute, 1440) > 360 else 1)
var migrated: Dictionary = (old_weather as Dictionary).duplicate(true)
migrated[&"version"] = 2
migrated[&"natural"] = {&"last_draw_day": last_draw_day, &"today": {}}
migrated[&"rain_holds"] = {}
var only_natural_state_added: bool = migrated == now_weather
ok = ok and only_natural_state_added
old[&"weather"] = (now_weather as Dictionary).duplicate(true)
fields.append("weather_v1_to_v2_A13")
proof["weather_A13"] = {"last_draw_day": last_draw_day, "only_natural_state_added": only_natural_state_added}
var old_streams: Variant = old.get(&"rng_streams")
var now_streams: Variant = now.get(&"rng_streams")
if old_streams is Dictionary and now_streams is Dictionary and not (old_streams as Dictionary).has("weather") and (now_streams as Dictionary).has("weather"):
var seeded: Dictionary = DeterministicRng.from_root_seed(int(old[&"world_seed"]), &"weather").snapshot()
var others: Dictionary = (now_streams as Dictionary).duplicate(true)
others.erase("weather")
var only_weather_stream_added: bool = now_streams["weather"] == seeded and var_to_bytes(others) == var_to_bytes(old_streams)
ok = ok and only_weather_stream_added
old[&"rng_streams"] = (now_streams as Dictionary).duplicate(true)
fields.append("rng_streams_weather_from_world_seed_A13")
proof["rng_streams_A13"] = {"only_weather_stream_added": only_weather_stream_added}
if not fields.is_empty():
# Saves keep the Runtime's own key order, so the mapped tree follows it.
ok = ok and old.size() == now.size()