完善客户端功能并同步差距文档
This commit is contained in:
+77
-11
@@ -9,6 +9,8 @@
|
||||
# 消费 M2Client:chat / whisper / item_picked_up。按类型分到 全部 / 私聊 / 系统 / 战斗 标签。
|
||||
extends Node
|
||||
|
||||
const Locale = preload("res://locale.gd")
|
||||
|
||||
# EChatType (wire.h)
|
||||
const T_TALKING := 0
|
||||
const T_INFO := 1
|
||||
@@ -42,9 +44,15 @@ var _tab := 0
|
||||
var _tab_btns := []
|
||||
var _max_lines := 200
|
||||
var _buffers := {} # tab -> Array[String]
|
||||
var _locale: RefCounted
|
||||
var _proto: Node
|
||||
var _fishing_active := false
|
||||
|
||||
func setup(m2client: Node, parent: Node) -> void:
|
||||
func setup(m2client: Node, parent: Node, assets_root := "") -> void:
|
||||
client = m2client
|
||||
if assets_root != "":
|
||||
_locale = Locale.new()
|
||||
_locale.setup(assets_root, "en")
|
||||
_build(parent)
|
||||
if client:
|
||||
if client.has_signal("chat"):
|
||||
@@ -56,6 +64,20 @@ func setup(m2client: Node, parent: Node) -> void:
|
||||
if client.has_signal("fishing_event"):
|
||||
client.fishing_event.connect(_on_fishing_event)
|
||||
|
||||
func set_proto(item_proto: Node) -> void:
|
||||
_proto = item_proto
|
||||
|
||||
func _loc(key: String, fallback: String, args: Array = []) -> String:
|
||||
if _locale and _locale.has(key):
|
||||
return _locale.t(key, args)
|
||||
return fallback % args if not args.is_empty() else fallback
|
||||
|
||||
func on_fishing_feedback(code: String) -> void:
|
||||
if code == "FISHING_WRONG_PLACE":
|
||||
var s := _loc("FISHING_WRONG_PLACE", "You cannot go fishing here.")
|
||||
_append(2, T_INFO, s)
|
||||
_append(3, T_INFO, s)
|
||||
|
||||
func focus_input() -> void:
|
||||
if _input:
|
||||
_input.grab_focus()
|
||||
@@ -70,6 +92,15 @@ func start_whisper(name: String) -> void:
|
||||
func is_typing() -> bool:
|
||||
return _input != null and _input.has_focus()
|
||||
|
||||
# game.py ToggleChatLogWindow hides/shows the complete chat log while keeping
|
||||
# the accumulated channel buffers. Enter can still focus the input afterward.
|
||||
func toggle_log() -> void:
|
||||
if _root:
|
||||
_root.visible = not _root.visible
|
||||
|
||||
func is_log_visible() -> bool:
|
||||
return _root != null and _root.visible
|
||||
|
||||
# --- 建 UI --------------------------------------------------------------
|
||||
|
||||
func _build(parent: Node) -> void:
|
||||
@@ -187,16 +218,51 @@ func _on_pickup(vnum: int, count: int, from: String) -> void:
|
||||
_append(3, T_INFO, s)
|
||||
|
||||
func _on_fishing_event(subheader: int, info: int, _dir: int) -> void:
|
||||
var s := ""
|
||||
if subheader == FISHING_SUCCESS:
|
||||
s = "鱼钩命中"
|
||||
elif subheader == FISHING_FAIL:
|
||||
s = "钓鱼失败"
|
||||
elif subheader == FISHING_FISH:
|
||||
s = "捕获物品 #%d" % info if info != 0 else "没有捕获到物品"
|
||||
if s != "":
|
||||
_append(2, T_INFO, s)
|
||||
_append(3, T_INFO, s)
|
||||
# RecvFishing only calls a UI callback for FAIL and FISH. SUCCESS is an
|
||||
# animation transition; the later FISH event decides notify vs success
|
||||
# from the actor's IsFishing() state.
|
||||
if subheader == 0: # FISHING_START
|
||||
_fishing_active = true
|
||||
return
|
||||
if subheader == 2: # FISHING_REACT
|
||||
_fishing_active = true
|
||||
return
|
||||
if subheader == FISHING_FAIL:
|
||||
_fishing_active = false
|
||||
var fail := _loc("FISHING_FAILURE", "You lost the Bait.")
|
||||
_append(2, T_INFO, fail)
|
||||
_append(3, T_INFO, fail)
|
||||
return
|
||||
if subheader != FISHING_FISH:
|
||||
if subheader == FISHING_SUCCESS:
|
||||
_fishing_active = false
|
||||
elif subheader == 1: # FISHING_STOP
|
||||
_fishing_active = false
|
||||
return
|
||||
if info == 0:
|
||||
var unknown := _loc("FISHING_UNKNOWN", "Something has taken the bait but you can't see what it is.")
|
||||
_append(2, T_INFO, unknown)
|
||||
_append(3, T_INFO, unknown)
|
||||
return
|
||||
var item: Dictionary = _proto.item(info) if _proto and _proto.has_method("item") else {}
|
||||
# ClientVS22 silently ignores a fish event when item_proto has no record.
|
||||
if item.is_empty():
|
||||
return
|
||||
var name := String(item.get("locale_name", item.get("name", "")))
|
||||
if name == "":
|
||||
name = "#%d" % info
|
||||
var is_fish := int(item.get("type", -1)) == 12 # CItemData::ITEM_TYPE_FISH
|
||||
var key := ""
|
||||
var fallback := ""
|
||||
if _fishing_active:
|
||||
key = "FISHING_NOTIFY1" if is_fish else "FISHING_NOTIFY2"
|
||||
fallback = "It looks like %s is hooked." if is_fish else "It looks like %s is on the hook."
|
||||
else:
|
||||
key = "FISHING_SUCCESS1" if is_fish else "FISHING_SUCCESS2"
|
||||
fallback = "You captured %s!" if is_fish else "You have pulled %s out of the water!"
|
||||
var s := _loc(key, fallback, [name])
|
||||
_append(2, T_INFO, s)
|
||||
_append(3, T_INFO, s)
|
||||
|
||||
# --- 追加行 --------------------------------------------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user