# client_phase_integration_system.gd —— 40250 客户端全状态机与全流程一体化集成系统 1:1 # 严格对照: # Client/Eternexus/root/networkmodule.py, interfacemodule.py, game.py # ClientVS22/source/UserInterface/PythonNetworkStream.h (PHASE_*) extends RefCounted const IntroLoginPhase = preload("res://intro_login_phase.gd") const IntroEmpirePhase = preload("res://intro_empire_phase.gd") const IntroSelectPhase = preload("res://intro_select_phase.gd") const IntroCreatePhase = preload("res://intro_create_phase.gd") const IntroLoadingPhase = preload("res://intro_loading_phase.gd") const MessengerSystem = preload("res://messenger_system.gd") const WhisperChatSystem = preload("res://whisper_chat_system.gd") const AtlasNavigationSystem = preload("res://atlas_navigation_system.gd") const EquipmentInspectSystem = preload("res://equipment_inspect_system.gd") const BgmJukeboxSystem = preload("res://bgm_jukebox_system.gd") # 官方 Phase 枚举 (PythonNetworkStream.h) enum ClientPhase { PHASE_OFFLINE, PHASE_LOGIN, PHASE_EMPIRE, PHASE_SELECT, PHASE_CREATE, PHASE_LOADING, PHASE_GAME } var current_phase: int = ClientPhase.PHASE_LOGIN # 阶段子模块实例 var login_phase: RefCounted = null var empire_phase: RefCounted = null var select_phase: RefCounted = null var create_phase: RefCounted = null var loading_phase: RefCounted = null # 游戏内核心交互模块实例 var messenger: RefCounted = null var whisper: RefCounted = null var atlas: RefCounted = null var equip_inspect: RefCounted = null var jukebox: RefCounted = null # 活跃角色数据 var active_character: Dictionary = {} var active_account: String = "" # 热键弹窗焦点栈 (用于 Escape 键自顶向下关闭) var dialog_focus_stack: Array = [] func _init() -> void: current_phase = ClientPhase.PHASE_LOGIN active_character = {} active_account = "" dialog_focus_stack.clear() # 初始化各阶段系统 login_phase = IntroLoginPhase.new() empire_phase = IntroEmpirePhase.new() select_phase = IntroSelectPhase.new() create_phase = IntroCreatePhase.new() loading_phase = IntroLoadingPhase.new() # 初始化游戏内交互系统 messenger = MessengerSystem.new() whisper = WhisperChatSystem.new() atlas = AtlasNavigationSystem.new() equip_inspect = EquipmentInspectSystem.new() jukebox = BgmJukeboxSystem.new() # 1. 登录跳转流 (Login -> Select / Empire) func process_login(account: String, password_input: String) -> Dictionary: var r = login_phase.attempt_login(account, password_input) if not r["success"]: return r active_account = account if r.get("has_characters", false): current_phase = ClientPhase.PHASE_SELECT r["next_phase"] = ClientPhase.PHASE_SELECT else: current_phase = ClientPhase.PHASE_EMPIRE r["next_phase"] = ClientPhase.PHASE_EMPIRE return r # 2. 阵营抉择流 (Empire -> Create) func process_empire_select(empire_id: int) -> Dictionary: if current_phase != ClientPhase.PHASE_EMPIRE: return { "success": false, "error": "NOT_IN_EMPIRE_PHASE" } empire_phase.select_empire(empire_id) var conf = empire_phase.confirm_empire_selection() current_phase = ClientPhase.PHASE_CREATE conf["next_phase"] = ClientPhase.PHASE_CREATE return conf # 3. 角色塑形流 (Create -> Select) func process_character_create(name: String, empire_id: int = 1) -> Dictionary: if current_phase != ClientPhase.PHASE_CREATE: return { "success": false, "error": "NOT_IN_CREATE_PHASE" } var r = create_phase.create_character(name, empire_id) if not r["success"]: return r # 存入角色选择大厅首个空槽位 select_phase.set_character_slot(0, r["character"]) current_phase = ClientPhase.PHASE_SELECT r["next_phase"] = ClientPhase.PHASE_SELECT return r # 4. 选择角色出战流 (Select -> Loading -> Game) func process_character_start(slot_idx: int) -> Dictionary: if current_phase != ClientPhase.PHASE_SELECT: return { "success": false, "error": "NOT_IN_SELECT_PHASE" } select_phase.select_slot(slot_idx) var r = select_phase.start_game() if not r["success"]: return r active_character = r["character"] # 启动过场加载 loading_phase.start_loading() current_phase = ClientPhase.PHASE_LOADING # 完成 4 阶段加载 for i in range(5): loading_phase.advance_loading_step() if loading_phase.is_completed(): current_phase = ClientPhase.PHASE_GAME jukebox.on_enter_map("metin2_map_a1") messenger.main_player_name = active_character.get("name", "Hero") whisper.main_player_name = active_character.get("name", "Hero") r["next_phase"] = ClientPhase.PHASE_GAME return r # 5. 全局热键路由与窗口调度 (1:1 interfacemodule.py) func handle_input_hotkey(key_name: String) -> Dictionary: if current_phase != ClientPhase.PHASE_GAME: return { "handled": false, "phase": current_phase } match key_name: "Alt+M": # 好友面板 var is_showing: bool = (dialog_focus_stack.has("MESSENGER")) if is_showing: dialog_focus_stack.erase("MESSENGER") return { "handled": true, "action": "CLOSE_MESSENGER" } else: dialog_focus_stack.append("MESSENGER") return { "handled": true, "action": "OPEN_MESSENGER" } "M": # Atlas 全景大地图 var visible = atlas.toggle_atlas() if visible: dialog_focus_stack.append("ATLAS") return { "handled": true, "action": "OPEN_ATLAS" } else: dialog_focus_stack.erase("ATLAS") return { "handled": true, "action": "CLOSE_ATLAS" } "Escape": # 自顶向下关闭弹窗或呼出系统菜单 if not dialog_focus_stack.is_empty(): var top_dialog = dialog_focus_stack.pop_back() if top_dialog == "ATLAS": atlas.hide_atlas() return { "handled": true, "action": "CLOSED_TOP_DIALOG", "dialog": top_dialog } else: return { "handled": true, "action": "OPEN_SYSTEM_MENU" } return { "handled": false } # 6. 登出游戏 (Game -> Select / Login) func logout_to_select() -> void: current_phase = ClientPhase.PHASE_SELECT active_character = {} dialog_focus_stack.clear() atlas.hide_atlas() jukebox.on_enter_map("intro_select") func logout_to_login() -> void: current_phase = ClientPhase.PHASE_LOGIN active_character = {} active_account = "" dialog_focus_stack.clear() jukebox.on_enter_map("intro_login")