feat: add taskbook onboarding UI

This commit is contained in:
ANG-Server
2026-07-22 00:45:59 +08:00
parent bb91ccea21
commit 9a3248abd6
15 changed files with 598 additions and 2 deletions

View File

@@ -107,6 +107,7 @@ const HUD_FRIEND_LIST_TOGGLE = "hud_friend_list_toggle"
const HUD_SETTINGS_REQUESTED = "hud_settings_requested"
const HUD_BACKPACK_TOGGLE = "hud_backpack_toggle"
const HUD_MAP_TOGGLE = "hud_map_toggle"
const HUD_TASK_BOOK_REQUESTED = "hud_task_book_requested"
# ============================================================================
# 商城事件

View File

@@ -0,0 +1,128 @@
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

View File

@@ -0,0 +1 @@
uid://byurfu7d8qyfb