extends Node # 玩家任务书状态与后端任务接口的唯一入口。 signal board_changed(board: Dictionary) signal board_failed(message: String) signal reward_claimed(task_id: String, wallet: Dictionary) var _board: Dictionary = {} var _loading_board: bool = false var _account_generation: int = -1 func _ready() -> void: var auth_manager := get_node_or_null("/root/AuthManager") if auth_manager != null and auth_manager.has_signal("auth_state_changed"): var callback := Callable(self, "_on_auth_state_changed") if not auth_manager.is_connected("auth_state_changed", callback): auth_manager.connect("auth_state_changed", callback) call_deferred("_refresh_after_ready") func get_board() -> Dictionary: return _board.duplicate(true) func is_loaded() -> bool: return not _board.is_empty() func refresh_board() -> void: if not _is_authenticated() or _loading_board: return var api := _api_client() if api == null: board_failed.emit("任务服务不可用") return _loading_board = true _account_generation = _current_account_generation() api.call("get_json", "/tasks/board", Callable(self, "_on_board_response").bind(_account_generation), true) func report_activity(activity: String, target_id: String = "") -> void: if not _is_authenticated(): return var api := _api_client() if api == null: return var payload := {"activity": activity} if not target_id.strip_edges().is_empty(): payload["target_id"] = target_id.strip_edges() var request_generation := _current_account_generation() api.call("post_json", "/tasks/activities", payload, Callable(self, "_on_activity_response").bind(request_generation), true) func claim_task(task_id: String) -> void: if task_id.strip_edges().is_empty() or not _is_authenticated(): return var api := _api_client() if api == null: board_failed.emit("任务服务不可用") return var request_generation := _current_account_generation() api.call("post_json", "/tasks/%s/claim" % task_id.uri_encode(), {}, Callable(self, "_on_claim_response").bind(task_id, request_generation), true) func _refresh_after_ready() -> void: if _is_authenticated(): refresh_board() func _on_auth_state_changed(is_authenticated: bool, _user: Dictionary) -> void: if not is_authenticated: _board.clear() _loading_board = false _account_generation = -1 board_changed.emit({}) return refresh_board() func _on_board_response(success: bool, response: Dictionary, error_info: Dictionary, request_generation: int) -> void: if request_generation != _current_account_generation(): return _loading_board = false if not success: board_failed.emit(str(error_info.get("message", "任务书读取失败"))) return _apply_board_response(response) func _on_activity_response(success: bool, response: Dictionary, _error_info: Dictionary, request_generation: int) -> void: if not success or request_generation != _current_account_generation(): return _apply_board_response(response) func _on_claim_response(success: bool, response: Dictionary, error_info: Dictionary, task_id: String, request_generation: int) -> void: if request_generation != _current_account_generation(): return if not success: board_failed.emit(str(error_info.get("message", "奖励领取失败"))) return var data_variant: Variant = response.get("data", {}) if not (data_variant is Dictionary): board_failed.emit("任务奖励响应格式错误") return var data: Dictionary = data_variant as Dictionary var board_variant: Variant = data.get("board", {}) if board_variant is Dictionary: _apply_board(board_variant as Dictionary) var wallet_variant: Variant = data.get("wallet", {}) if wallet_variant is Dictionary: var wallet: Dictionary = wallet_variant as Dictionary var player_state := get_node_or_null("/root/PlayerStateManager") if player_state != null and player_state.has_method("apply_wallet"): player_state.call("apply_wallet", wallet) reward_claimed.emit(task_id, wallet.duplicate(true)) func _apply_board_response(response: Dictionary) -> void: var data_variant: Variant = response.get("data", {}) if data_variant is Dictionary: _apply_board(data_variant as Dictionary) else: board_failed.emit("任务书响应格式错误") func _apply_board(board: Dictionary) -> void: _board = board.duplicate(true) board_changed.emit(get_board()) func _api_client() -> Node: return get_node_or_null("/root/ApiClient") func _is_authenticated() -> bool: var auth_manager := get_node_or_null("/root/AuthManager") return auth_manager != null and auth_manager.has_method("is_authenticated") and bool(auth_manager.call("is_authenticated")) func _current_account_generation() -> int: var auth_manager := get_node_or_null("/root/AuthManager") return int(auth_manager.call("get_account_generation")) if auth_manager != null and auth_manager.has_method("get_account_generation") else 0