169 lines
8.8 KiB
GDScript
169 lines
8.8 KiB
GDScript
extends SceneTree
|
|
|
|
const BattleService = preload("res://p10_3/deep_channels_battle_service.gd")
|
|
const Controller = preload("res://p10_3/runtime_controller.gd")
|
|
const Fixture = preload("res://tests/p10_3/deep_channels_fixture.gd")
|
|
const Main = preload("res://main.gd")
|
|
const P102Controller = preload("res://p10_2/runtime_controller.gd")
|
|
const P102Save = preload("res://p10_2/save_v8_service.gd")
|
|
const SaveV9 = preload("res://p10_3/save_v9_service.gd")
|
|
|
|
const VIEWPORT := Vector2i(844, 390)
|
|
|
|
var experience
|
|
var failures: Array[String] = []
|
|
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("run_test")
|
|
|
|
|
|
func run_test() -> void:
|
|
root.size = VIEWPORT
|
|
root.content_scale_mode = Window.CONTENT_SCALE_MODE_CANVAS_ITEMS
|
|
root.content_scale_aspect = Window.CONTENT_SCALE_ASPECT_EXPAND
|
|
root.content_scale_size = VIEWPORT
|
|
experience = Controller.new()
|
|
experience.persistence_enabled = false
|
|
experience.battle_auto_advance = false
|
|
experience.locale = "zh_CN"
|
|
experience.size = Vector2(VIEWPORT)
|
|
experience.configure_entry(Fixture.new().migrated_snapshot())
|
|
root.add_child(experience)
|
|
await settle_frames(12)
|
|
|
|
expect(experience.p103_mode, "Save v9 activates the P10.3 runtime")
|
|
expect(experience.screen == Controller.P103_SCREEN_MARKET, "Market 5 resumes as the first deep-channel screen")
|
|
expect(experience.find_child("P103DeepFerry", true, false) != null, "Market 5 renders the deep-channel ferry workspace")
|
|
expect(experience.find_children("P102RouteTarget_*", "Button", true, false).size() == 3, "Market 5 exposes three route posts")
|
|
|
|
var starting_order: Array = Array(experience.region_market.state.current_run.deployed_recruit_ids).duplicate()
|
|
if starting_order.size() >= 2:
|
|
experience._commit_line_drag(String(starting_order[-1]), String(starting_order[0]))
|
|
await settle_frames()
|
|
expect(experience.region_market.state.current_run.deployed_recruit_ids != starting_order, "deployment drag commits an atomic new order")
|
|
|
|
await clear_round(5, 0, "channel_thread_adjacent", "P103ChannelThread")
|
|
expect(experience.screen == Controller.P103_SCREEN_MARKET, "Round 5 settlement opens Market 6")
|
|
await clear_round(6, 1, "safe_index_advanced", "P103SafeIndexPulse")
|
|
|
|
expect(experience.screen == Controller.P103_SCREEN_ARTIFACT, "Round 6 settlement opens the Artifact shrine")
|
|
expect(experience.find_children("P103ArtifactTarget_*", "Button", true, false).size() == 3, "Artifact shrine exposes three opposed laws")
|
|
expect(experience.find_child("P103ArtifactShrine", true, false) != null, "Artifact choice remains inside the ferry world")
|
|
experience.choose_p103_artifact("AR-012")
|
|
await settle_frames()
|
|
|
|
expect(experience.screen == Controller.P103_SCREEN_PROMOTION, "Artifact choice opens the eligible promotion anvil")
|
|
expect(experience.find_children("P103PromotionTarget_*", "Button", true, false).size() == 2, "promotion anvil exposes two deterministic branches")
|
|
expect(experience.find_child("P103PromotionAnvil", true, false) != null, "promotion choice remains inside the ferry world")
|
|
experience.choose_p103_promotion("PF-A13")
|
|
await settle_frames()
|
|
|
|
expect(experience.screen == Controller.P103_SCREEN_MARKET, "promotion returns to playable Market 7")
|
|
await clear_round(7, 2, "long_company_opening", "P103ArtifactPulse")
|
|
|
|
var run: Dictionary = experience.region_market.state.current_run
|
|
expect(experience.screen == Controller.P103_SCREEN_MARKET_8, "Round 7 settlement reaches visible Market 8")
|
|
expect(run.phase == "market_8" and run.market_index == 8 and run.cleared_rounds == 7, "Market 8 is the exact continuation boundary")
|
|
expect(run.active_artifact_ids == ["AR-012"], "Market 8 visibly preserves Long Company")
|
|
expect(_company_has_profession(run, "PF-A13"), "Market 8 visibly preserves Fieldmender")
|
|
expect(experience.find_child("P103DeepFerry", true, false) != null, "Market 8 preserves the restored ferry")
|
|
var encoded: Dictionary = SaveV9.new().encode_snapshot(experience.region_market.state.snapshot(), 50)
|
|
var decoded: Dictionary = SaveV9.new().decode_text(String(encoded.get("text", "")), 50)
|
|
expect(encoded.ok and decoded.ok and decoded.snapshot == experience.region_market.state.snapshot(), "visible Market 8 roundtrips through Save v9")
|
|
var market_eight_snapshot: Dictionary = experience.region_market.state.snapshot()
|
|
|
|
experience.queue_free()
|
|
await settle_frames(18)
|
|
var game = Main.new()
|
|
game.auto_boot = false
|
|
game.p100_persistence_enabled = false
|
|
root.add_child(game)
|
|
await settle_frames()
|
|
game.p102_experience = P102Controller.new()
|
|
game.p102_experience.persistence_enabled = false
|
|
game.p102_experience.size = Vector2(VIEWPORT)
|
|
game.p102_experience.configure_entry(Fixture.new().p102_market_5_snapshot())
|
|
game.add_child(game.p102_experience)
|
|
await settle_frames(12)
|
|
expect(is_instance_valid(game.p103_handoff_button), "main exposes one Continue Deep Channels command on stable P10.2 Market 5")
|
|
if is_instance_valid(game.p103_handoff_button):
|
|
game.p103_handoff_button.emit_signal(&"pressed")
|
|
await settle_frames(12)
|
|
expect(is_instance_valid(game.p103_experience), "main hands stable P10.2 Market 5 to the P10.3 runtime")
|
|
if is_instance_valid(game.p103_experience):
|
|
expect(game.p103_experience.p103_mode and int(game.p103_experience.region_market.state.current_run.market_index) == 5, "main handoff migrates into exact P10.3 Market 5")
|
|
game.queue_free()
|
|
await settle_frames(18)
|
|
|
|
_cleanup_save_files()
|
|
var p102_path := ProjectSettings.globalize_path("user://aetherbound_guild_p10_2.json")
|
|
var p103_path := ProjectSettings.globalize_path("user://aetherbound_guild_p10_3.json")
|
|
var wrote_v8 := P102Save.new().write_slot(p102_path, Fixture.new().p102_market_5_snapshot(), 60, "")
|
|
var wrote_v9 := SaveV9.new().write_slot(p103_path, market_eight_snapshot, 61, "")
|
|
expect(wrote_v8.ok and wrote_v9.ok, "resume priority fixture writes valid Save v8 and Save v9 slots")
|
|
var resumed = Main.new()
|
|
resumed.auto_boot = true
|
|
resumed.p100_experience_enabled = true
|
|
resumed.p100_persistence_enabled = true
|
|
root.add_child(resumed)
|
|
await settle_frames(18)
|
|
expect(is_instance_valid(resumed.p103_experience), "main prioritizes Save v9 when Save v8 also exists")
|
|
expect(not is_instance_valid(resumed.p102_experience), "Save v9 priority does not mount the older P10.2 runtime")
|
|
if is_instance_valid(resumed.p103_experience):
|
|
expect(resumed.p103_experience.screen == Controller.P103_SCREEN_MARKET_8, "Save v9 priority restores exact Market 8")
|
|
resumed.queue_free()
|
|
await settle_frames(45)
|
|
_cleanup_save_files()
|
|
if failures.is_empty():
|
|
print("ABG_P10_3_CONTINUOUS_RUNTIME_OK markets=5,6,7,8 rounds=5,6,7 artifact=AR-012 promotion=PF-A13 order=drag widow=event_bound sluice=event_bound artifact_effect=event_bound ferry=world_first save_v9=stable main=handoff resume=v9_priority")
|
|
quit(0)
|
|
else:
|
|
for failure in failures:
|
|
push_error(failure)
|
|
quit(1)
|
|
|
|
|
|
func clear_round(market_index: int, risk: int, event_kind: String, effect_node: String) -> void:
|
|
expect(int(experience.region_market.state.current_run.market_index) == market_index, "Round %d starts at its matching Market" % market_index)
|
|
var route: Dictionary = experience.region_market.state.current_run.market_board.battle_offers[risk]
|
|
var plan_id := String(BattleService.PREFERRED_PLAN[String(route.route_id)])
|
|
experience.tap_region_route(String(route.offer_id))
|
|
experience.commit_region_route()
|
|
await settle_frames()
|
|
expect(experience.screen == Controller.P103_SCREEN_PLAN, "Round %d opens the four-plan workspace" % market_index)
|
|
expect(experience.find_children("P102PlanTarget_*", "Button", true, false).size() == 4, "Round %d presents four direct plan targets" % market_index)
|
|
experience.choose_region_plan(plan_id)
|
|
experience.advance_region_battle_ticks(999)
|
|
await settle_frames()
|
|
expect(experience.screen == Controller.P103_SCREEN_BATTLE and experience.region_battle_complete, "Round %d reaches its visible result" % market_index)
|
|
expect(int(experience.region_event_counts.get(event_kind, 0)) == 1, "Round %d consumes %s exactly once" % [market_index, event_kind])
|
|
expect(experience.find_child(effect_node, true, false) != null, "Round %d binds %s to a world effect" % [market_index, event_kind])
|
|
experience.settle_region_battle()
|
|
await settle_frames()
|
|
|
|
|
|
func _company_has_profession(run: Dictionary, profession_id: String) -> bool:
|
|
for recruit_id in run.company:
|
|
if String(run.recruit_records[recruit_id].profession_id) == profession_id:
|
|
return true
|
|
return false
|
|
|
|
|
|
func _cleanup_save_files() -> void:
|
|
for save_name in ["user://aetherbound_guild_p10_2.json", "user://aetherbound_guild_p10_3.json"]:
|
|
for suffix in ["", ".bak", ".candidate"]:
|
|
var path := ProjectSettings.globalize_path(save_name + suffix)
|
|
if FileAccess.file_exists(path):
|
|
DirAccess.remove_absolute(path)
|
|
|
|
|
|
func settle_frames(count := 5) -> void:
|
|
for _index in count:
|
|
await process_frame
|
|
|
|
|
|
func expect(condition: bool, message: String) -> void:
|
|
if not condition:
|
|
failures.append("P10.3 continuous runtime: %s" % message)
|