Files
mtgodot-poc/project/test_client_phase_integration_parity.gd
T
shenandshen 66d217b313 feat(client): 完成40250客户端核心功能1:1对齐与桥梁高度采样修复
- 桥梁与静态物体高度采样修复:
  - 严格对齐 40250 CMapOutdoor::GetHeight 与 CAttributeInstance::GetHeight
  - 解析 .mdatr 中的 AttributeHeight 网格,使用 is_in_triangle_2d 准确计算桥面多边形平面方程
  - sample_height 查询邻近区块并返回 fMAX(fObjectHeight, fTerrainHeight),彻底解决走上桥面穿透掉入水底/河床的问题
  - 新增 test_bridge_height_parity.gd 自动化对拍测试
- 40250 怪物击杀经验动效:
  - 1:1 实现 FLY_EXP(0) / FLY_HP / FLY_SP 粒子轨迹与爆炸吸附
- 40250 客户端全系统功能对齐(Batches 1-31):
  - 包含公会、交易、骑乘、变身、钓鱼、采矿、商城、信件、结婚、地牢等 134 套对拍系统与自动化回归测试
- 文档沉淀:
  - 新增 docs/CLIENT-PARITY-AUDIT-AND-FIX-GUIDE.md 客户端对拍缺陷发现与修复工程指南
2026-09-19 08:51:25 -07:00

124 lines
5.5 KiB
GDScript

# test_client_phase_integration_parity.gd —— 40250 客户端全状态机一体化回归测试
extends SceneTree
const SystemClass = preload("res://client_phase_integration_system.gd")
var _passed: int = 0
var _failed: int = 0
func _assert(cond: bool, msg: String) -> void:
if cond:
_passed += 1
print(" [PASS] %s" % msg)
else:
_failed += 1
printerr(" [FAIL] %s" % msg)
func _init() -> void:
print("\n=== Running test_client_phase_integration_parity (Batch 30 Direction 3) ===")
_test_fresh_account_full_lifecycle_flow()
_test_existing_account_direct_select_flow()
_test_in_game_hotkey_and_focus_stack()
_test_logout_transitions()
print("\n=== Result: %d Passed, %d Failed ===" % [_passed, _failed])
if _failed == 0:
print("ALL TESTS PASSED!\n")
else:
printerr("SOME TESTS FAILED!\n")
quit(0 if _failed == 0 else 1)
func _test_fresh_account_full_lifecycle_flow() -> void:
print("\n--- Test 1: Fresh Account Full Lifecycle (Login -> Empire -> Create -> Select -> Loading -> Game) ---")
var client = SystemClass.new()
_assert(client.current_phase == SystemClass.ClientPhase.PHASE_LOGIN, "Starts in PHASE_LOGIN")
# Register temporary fresh account
client.login_phase.registered_accounts["newbie"] = { "password": "123", "has_characters": false }
# 1. Login
var r_log = client.process_login("newbie", "123")
_assert(r_log["success"] == true, "Login succeeded")
_assert(client.current_phase == SystemClass.ClientPhase.PHASE_EMPIRE, "Transitions to PHASE_EMPIRE for new account")
# 2. Select Empire (Jinno = 3)
var r_emp = client.process_empire_select(3)
_assert(r_emp["success"] == true, "Empire selection confirmed")
_assert(client.current_phase == SystemClass.ClientPhase.PHASE_CREATE, "Transitions to PHASE_CREATE")
# 3. Create Character
var r_cr = client.process_character_create("NewKnight", 3)
_assert(r_cr["success"] == true, "Created NewKnight successfully")
_assert(client.current_phase == SystemClass.ClientPhase.PHASE_SELECT, "Transitions to PHASE_SELECT")
# 4. Start Game
var r_st = client.process_character_start(0)
_assert(r_st["success"] == true, "Started game from slot 0")
_assert(client.current_phase == SystemClass.ClientPhase.PHASE_GAME, "Transitions through Loading to PHASE_GAME")
_assert(client.active_character["name"] == "NewKnight", "Active character is NewKnight")
_assert(client.jukebox.is_playing == true, "BGM jukebox actively playing in-game music")
func _test_existing_account_direct_select_flow() -> void:
print("\n--- Test 2: Existing Account Direct to Character Select ---")
var client = SystemClass.new()
# Login with existing account (admin has characters)
var r_log = client.process_login("admin", "password")
_assert(r_log["success"] == true, "Admin logged in")
_assert(client.current_phase == SystemClass.ClientPhase.PHASE_SELECT, "Existing account transitions directly to PHASE_SELECT")
func _test_in_game_hotkey_and_focus_stack() -> void:
print("\n--- Test 3: In-Game Hotkey Management & Escape Stack ---")
var client = SystemClass.new()
client.login_phase.registered_accounts["hero"] = { "password": "123", "has_characters": false }
client.process_login("hero", "123")
client.process_empire_select(1)
client.process_character_create("HeroPlayer", 1)
client.process_character_start(0)
_assert(client.current_phase == SystemClass.ClientPhase.PHASE_GAME, "In PHASE_GAME")
# 1. Alt+M opens Messenger
var h_msg = client.handle_input_hotkey("Alt+M")
_assert(h_msg["action"] == "OPEN_MESSENGER", "Alt+M opens messenger")
_assert(client.dialog_focus_stack.has("MESSENGER"), "MESSENGER pushed to stack")
# 2. M opens Atlas
var h_atlas = client.handle_input_hotkey("M")
_assert(h_atlas["action"] == "OPEN_ATLAS", "M opens atlas")
_assert(client.atlas.is_atlas_visible == true, "Atlas is visible")
_assert(client.dialog_focus_stack[client.dialog_focus_stack.size() - 1] == "ATLAS", "ATLAS on top of stack")
# 3. First Escape closes top dialog (ATLAS)
var esc1 = client.handle_input_hotkey("Escape")
_assert(esc1["action"] == "CLOSED_TOP_DIALOG" and esc1["dialog"] == "ATLAS", "Escape popped ATLAS")
_assert(client.atlas.is_atlas_visible == false, "Atlas is hidden")
# 4. Second Escape closes MESSENGER
var esc2 = client.handle_input_hotkey("Escape")
_assert(esc2["action"] == "CLOSED_TOP_DIALOG" and esc2["dialog"] == "MESSENGER", "Escape popped MESSENGER")
# 5. Third Escape on empty stack opens System Menu
var esc3 = client.handle_input_hotkey("Escape")
_assert(esc3["action"] == "OPEN_SYSTEM_MENU", "Escape opens System Menu when stack is empty")
func _test_logout_transitions() -> void:
print("\n--- Test 4: Logout Transitions ---")
var client = SystemClass.new()
client.login_phase.registered_accounts["user"] = { "password": "123", "has_characters": false }
client.process_login("user", "123")
client.process_empire_select(1)
client.process_character_create("UserChar", 1)
client.process_character_start(0)
# Logout to Select
client.logout_to_select()
_assert(client.current_phase == SystemClass.ClientPhase.PHASE_SELECT, "Logged out to PHASE_SELECT")
_assert(client.active_character.is_empty(), "Active character cleared")
_assert(client.jukebox.current_track == "characterselect.mp3", "Switched BGM to character select theme")
# Logout to Login
client.logout_to_login()
_assert(client.current_phase == SystemClass.ClientPhase.PHASE_LOGIN, "Logged out to PHASE_LOGIN")
_assert(client.active_account.is_empty(), "Active account cleared")
_assert(client.jukebox.current_track == "enter_the_east.mp3", "Switched BGM to login theme")