完善客户端功能并同步差距文档

This commit is contained in:
shenlei
2026-09-03 18:40:01 +09:00
parent f93a172296
commit 13ccb8d02d
135 changed files with 21881 additions and 1259 deletions
+109
View File
@@ -0,0 +1,109 @@
# chat_tail —— §8.8 头顶「聊天 / 信息」尾标 1:1CPythonTextTail::RegisterChatTail /
# RegisterInfoTail 的纯静态镜像(与 name_color.gd / text_tail.gd 同套路)。
#
# REF 40250/ClientVS22/source/UserInterface/PythonTextTail.cpp
# :16 c_TextTail_Chat_Color = D3DXCOLOR(1,1,1,1) —— 普通聊天气泡=白
# :17 c_TextTail_Info_Color = D3DXCOLOR(1, 0.785f, 0.785f, 1) —— 信息气泡=淡红
# :26 gs_TextTail_LivingTime = 5000 —— TEXTTAIL_LIVINGTIME_CONTROL
# :28 TextTail_GetLivingTime() assert(gs_TextTail_LivingTime > 1000)
# :34 TextTail_SetLivingTime(livingTime)
# :581 RegisterChatTail(vid, szChat)m_ChatTailMap 已有该 vid → 改文本 + Color=Chat +
# LivingTime = now + GetLivingTime() + bNameFlag=TRUE,直接 return
# 否则新建(高度 = 角色高 + 10),LivingTime = now + GetLivingTime()bNameFlag=TRUE
# SetOutline(true)VERTICAL_ALIGN_BOTTOM,插入 m_ChatTailMap
# :624 RegisterInfoTail(vid, szChat):同上,但 Color=Info、bNameFlag=FALSE
# :328 UpdateAllTextTail:遍历 m_ChatTailMapLivingTime < now 即 DeleteTextTail + erase
# (每 vid 只有一条 chat/info 尾标,chat 与 info 共用同一张 m_ChatTailMap
# :74 UpdateAllTextTailchat 尾标若 bNameFlag → ShowCharacterTextTail(vid)(名字也一起顶出来)
# :105 UpdateShowingTextTailchat 尾标若 bNameFlag → 名字尾标 y = chatTail.y - 17(名字挪到气泡下方)
# :684 IsChatTextTail(vid)m_ChatTailMap.find(vid) != end
#
# REF 40250/ClientVS22/source/UserInterface/PythonNetworkStreamPhaseGame.cpp
# :1301 CHAT_TYPE_COMMAND → ServerCommand,提前 return(不进尾标)
# :1321 TALKING/PARTY/GUILD/SHOUT/WHISPERline = strchr(buf,':') ? p + 2 : buf(去掉 "名字: " 前缀)
# :1363 INFO/NOTICE/BIG_NOTICE/defaultline = buf(原样)
# :1372 if (CHAT_TYPE_SHOUT != kChat.type) RegisterChatTail(kChat.dwVID, line);
# → 带 VID 的聊天里,除 SHOUT / COMMAND 外都进「聊天尾标」;RegisterInfoTail 仅
# game.py:930 / :936 技能 / 射击错误尾标显式调。
#
# seam ⑨:参考端聊天尾标由 Render() 与名字尾标同屏排布(气泡在上、名字下移 17px,bNameFlag 决定
# 名字是否强制显示);本移植是 net_world 里名字 Label3D 与 "bubble" Label3D 各自 billboard 并存,
# 名字不强制顶出、不随气泡下移——差异记入 §8.8。
extends RefCounted
const CHAT_COLOR := Color(1.0, 1.0, 1.0)
const INFO_COLOR := Color(1.0, 0.785, 0.785)
const LIVING_TIME_DEFAULT := 5000 # msgs_TextTail_LivingTime
const LIVING_TIME_MIN := 1000 # assert 下界(TextTail_GetLivingTime
const HEIGHT_ADD := 10.0 # 角色高 + 10RegisterChatTail 新建分支)
# CHAT_TYPE_*Packet.h:1410 enum EChatType
const CT_TALKING := 0
const CT_INFO := 1
const CT_NOTICE := 2
const CT_PARTY := 3
const CT_GUILD := 4
const CT_COMMAND := 5
const CT_SHOUT := 6
const CT_WHISPER := 7
const CT_BIG_NOTICE := 8
static var _living_time := LIVING_TIME_DEFAULT
static func set_living_time(ms: int) -> void:
# TextTail_SetLivingTime —— 参考端不在此断言(断言在 GetLivingTime
_living_time = ms
static func living_time() -> int:
# TextTail_GetLivingTimeassert(gs_TextTail_LivingTime > 1000)
assert(_living_time > LIVING_TIME_MIN)
return _living_time
static func strip_name_prefix(raw: String) -> String:
# strchr(buf, ':') ? p + 2 : buf —— 有冒号则取 ": " 之后正文,否则整串原样
var i := raw.find(":")
return raw.substr(i + 2) if i != -1 else raw
static func line_for_tail(chat_type: int, raw: String) -> String:
# RecvChatPacket 的 switchTALKING/PARTY/GUILD/SHOUT/WHISPER 去前缀;其余原样
match chat_type:
CT_TALKING, CT_PARTY, CT_GUILD, CT_SHOUT, CT_WHISPER:
return strip_name_prefix(raw)
_:
return raw
static func wants_chat_tail(chat_type: int) -> bool:
# RecvChatPacketCOMMAND 提前 returnSHOUT 显式排除;其余带 VID 聊天都进尾标
return chat_type != CT_SHOUT and chat_type != CT_COMMAND
static func _register(tails: Dictionary, vid: int, text: String, now_ms: int, col: Color, name_flag: bool) -> Dictionary:
var e := {
"text": text,
"color": col,
"name_flag": name_flag,
"living_time": now_ms + living_time(),
}
tails[vid] = e
return e
static func register_chat(tails: Dictionary, vid: int, text: String, now_ms: int) -> Dictionary:
# CPythonTextTail::RegisterChatTail —— 白 + bNameFlag TRUE,已存在则原地替换
return _register(tails, vid, text, now_ms, CHAT_COLOR, true)
static func register_info(tails: Dictionary, vid: int, text: String, now_ms: int) -> Dictionary:
# CPythonTextTail::RegisterInfoTail —— 淡红 + bNameFlag FALSE,与 chat 共用同一张表
return _register(tails, vid, text, now_ms, INFO_COLOR, false)
static func is_chat_text_tail(tails: Dictionary, vid: int) -> bool:
# CPythonTextTail::IsChatTextTail
return tails.has(vid)
static func expire(tails: Dictionary, now_ms: int) -> Array:
# UpdateAllTextTailLivingTime < now 即删除;返回被清掉的 vid 列表
var dead: Array = []
for vid in tails.keys():
if int(tails[vid].get("living_time", 0)) < now_ms:
dead.append(vid)
for vid in dead:
tails.erase(vid)
return dead