Files
mtgodot-poc/audit/contracts/social.chat-text-tail.md
T
shenandshen c93894313a fix: 装备属性面板避让逻辑 + 多项功能更新
- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧
- inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域
- 包含其他累积的功能开发和测试文件
2026-09-21 16:38:59 -07:00

18 KiB
Raw Blame History

social.chat_text_tail

Scope

审计公聊、队伍/公会/喊话频道、无 VID 系统消息、私聊收发和私聊窗口、忽略名单、聊天气泡、名字/公会/称号/等级尾标以及尾标的寿命、排布和死亡清理。对比重点是当前端是否复现 40250 的消息类型分支、服务器事件来源、私聊状态机、文本颜色/过滤/表情副作用、尾标覆盖规则和渲染布局;本地有同名 helper 或能显示文本不等于实现统一。

Reference call chain

  • UserInterface/PythonNetworkStreamPhaseGame.cpp
    • RecvChatPacket 校验聊天类型;CHAT_TYPE_COMMAND 进入 ServerCommand,不进入普通聊天和聊天尾标。
    • 有 VID 时,普通/队伍/公会/喊话/客户端私聊从 "名字: " 后取正文,执行表情解析、跨帝国文字转换和辱骂过滤;角色不存在时直接忽略;除 CHAT_TYPE_SHOUT 外注册 CPythonTextTail::RegisterChatTailPC 消息再进入 CPythonChat::AppendChat
    • 无 VID 时,NOTICE/BIG_NOTICE 分别进入 BINARY_SetTipMessage/BINARY_SetBigMessage,系统和喊话按专门分支处理,不是简单追加到同一聊天列表。
    • RecvWhisperPacket 将 mode、发送者和文本交给 OnRecvWhisper/错误/系统回调;私聊历史、按钮、闪烁和忽略名单由 CPythonChatuiwhisper.pygame.py 联动。
  • UserInterface/PythonNetworkStreamCommand.cpp
    • ServerCommand 作为 CHAT_TYPE_COMMAND 的二次命令总线,解析 cube、observer、StoneDetect、stamina、mobile、gift、情感动作和 dig_motion,并把副作用交给 UI、角色或效果管理器;命令不进入普通聊天尾标。
  • UserInterface/PythonChat.cpp / PythonChat.h
    • 普通聊天维护共享聊天行队列和多个 chat set,支持 view/edit/log 三种布局、滚动步长、最大行数、延迟追加、按频道颜色和清理。
    • 40250 颜色是 talking 白、info 淡红、notice/big notice 淡黄、party 青白、guild 淡紫、command/shout 青绿、whisper 绿色;私聊 mode 包含 chat、not-exist、target-blocked、sender-blocked、error、GM 和 system。
    • AppendWhisper 按目标名维护独立会话;IgnoreCharacter/IsIgnoreCharacter 只对目标名切换黑名单;InitWhisper/MakeWhisperButton 恢复已有会话。
  • UserInterface/PythonTextTail.cpp / InstanceBaseEffect.cpp
    • RegisterChatTailRegisterInfoTail 共用每 VID 一条尾标;聊天尾标为白色、bNameFlag=true,信息尾标为淡红、bNameFlag=false,新消息覆盖旧消息并重置 now + 5000ms
    • 聊天气泡会强制显示角色名字,并把名字尾标移动到气泡下方 17px;公会名、称号、等级按实际字体度量排在名字两侧/上下;角色死亡时 DetachTextTail
    • 公会名只在 guild id 非零时创建,名称查询失败回退 Noname;称号/等级受 EnablePKTitle、alignment grade、level 和挂马高度影响。
  • Client/Eternexus/root/game.py / uiwhisper.py
    • OnRecvWhisper 按官方 whisper mode 分流到 AppendWhisper、系统错误文本和界面 RecvWhisper 通知;聊天输入、好友/目标板和独立私聊窗口都能打开同一目标会话。
    • 私聊窗口发送只有网络请求成功后才应关闭/追加本地回显;忽略按钮通过 /ignore <name> 与服务端/客户端状态同步。

Current call chain

  • EntityStore::mut_chatmut_whisper 和 parser 已保存 GC_CHAT/GC_WHISPER 为 chat queueM2Client 发出 chatwhisper_received 信号,基础 classic 动态包布局和长度限制存在;GC_WHISPER 缺少固定 type/name 字段时会拒绝,不再静默吞包。
  • project/ui/chat_ui.gd 只有四个本地 tab(全部/私聊/系统/战斗),按 Godot RichTextLabel 重建整段文本;公共输入支持普通、公会、队伍、喊话和 /w,但普通/喊话发送失败没有统一错误回显,私聊窗口也无视 client.whisper() 返回值而立即本地回显并关闭。
  • 当前入站私聊 _on_whisper 已按 40250 区分 0=CHAT1=NOT_EXIST2=TARGET_BLOCKED3=SENDER_BLOCKED4=ERROR5=GM0xFF=SYSTEM;1..4 的空文本会生成本地化错误兜底文案。live 会话已接入,颜色/字体和服务端错误正文仍未完整闭环。
  • project/whisper_chat_system.gd 实现了独立的本地 conversation/最小化/闪烁/忽略 helperChatUI.setup 现在把它接入 M2Client.whisper_received;live 私聊仍没有完整的独立窗口历史渲染、任务栏按钮、ignore 命令和发送结果状态。
  • project/chat_tail.gd 已复现单 VID 覆盖、5000ms 生命周期、聊天/信息颜色和名字跟随规则;project/net_world.gdLabel3D 气泡、名字和子标签实现,死亡/过期会清理节点。
  • project/text_tail.gdtext_tail_arrange.gdname_tail_layout.gd 已实现部分颜色、称号、等级、公会名、挂马高度和像素近似排布;但运行时仍是 Godot billboard/估算字符宽度,不是 40250 的 CGraphicText 实际字体度量和 CPythonTextTail 渲染对象。
  • ClassicParser::on_gc(GC_CHAT) 现按 40250 先拒绝非法 chat type,并在非系统消息的 VID 不存在于 EntityStore 时消费但不产生 chat eventlive project/net_world.gd::_on_chat 仍没有复现表情解析、跨帝国转换、辱骂过滤和无 VID NOTICE/BIG_NOTICE 专用 UI。

Branch matrix

场景 40250 当前端 结论
普通/队伍/公会聊天 解析类型、角色和前缀,过滤/表情后写聊天行,必要时注册气泡 基础 GC_CHAT queue、UI tab 和气泡存在 PARTIAL:过滤/表情/未知实体/真实显示布局缺失
喊话 公共聊天颜色和公共区显示,不能注册角色聊天尾标 当前写入公共 tabChatTail 也能保留,但 net_world 连接路径未证明按 ref 排除 PARTIAL
无 VID INFO/NOTICE/BIG_NOTICE 专用 tip/big notice 分支,按类型显示 统一塞入 System/All RichTextLabel,没有专用 tip/big notice GAP
COMMAND 进入 ServerCommand,不显示普通聊天/气泡 native 有部分 command 解析;非已识别 command 仍缺完整 side effect 矩阵 PARTIAL
表情/帝国文字/辱骂过滤 先解析表情或转换/过滤,再显示文本/动画 有发送表情 token,但没有入站 ParseEmoticon、帝国转换和辱骂过滤链 GAP
私聊正常收发 mode/name/text 进入独立目标会话,按钮/历史/通知联动 packet queue、独立输入和 live conversation 接入存在;窗口历史/按钮/通知仍不完整 PARTIAL
私聊错误/GM/system mode 0..5/0xFF 具有不同错误/字体/颜色和通知 mode 数值与错误/GM/system 分支已对齐;颜色、字体和 live 通知仍不等价 PARTIAL
忽略目标 IgnoreCharacter 按名称切换,收到私聊不进入会话并有服务端 ignore 命令 live ChatUI 收到普通/GM 私聊前经过会话 ignore 判断;仍无 UI 忽略按钮/服务端命令连接 PARTIAL
聊天气泡 每 VID 单槽覆盖,白/淡红,5000ms,聊天气泡强显名字并上移名字 17px 单槽、颜色、生命周期和本地布局 helper 存在 PARTIAL:实际字体/屏幕投影/已知实体和资源表现不同
名字/称号/等级/公会名 由角色同步、alignment/guild/item/挂马更新,死亡 detach,真实字体度量排布 快照+Label3D 子标签和近似字符宽度存在 PARTIAL:权威更新源和渲染度量不完全同链
换图/重连/死亡/重复消息 CPythonChat/TextTail 清理与重新注册,旧会话状态按客户端生命周期处理 本地节点过期/死亡清理存在;chat queue、私聊会话和重连恢复未端到端验证 PARTIAL

Implementation-equivalence matrix

项目 状态 证据/限制
Preconditions PARTIAL native 长度/阶段边界存在;缺入站 actor/type/name、ignore、输入门控和真实 UI 状态前置条件
Branch structure PARTIAL 普通/私聊/尾标主干和 live ignore 分支存在,但无 VID notice、表情/过滤和完整私聊通知分支
Algorithms/formulas PARTIAL 5000ms 生命周期和 17px 名字偏移有静态镜像;频道颜色、前缀、字符宽度、会话/通知算法存在明确差异
State transition order GAP 参考是网络回包→过滤/表情/尾标→聊天/窗口/提示;当前 conversation 已随 live signal 更新,但本地回显/窗口通知和服务端结果顺序仍不同
Constants/units PARTIAL EChatType 和尾标 5000ms/17px/颜色部分存在;多个公共/私聊颜色与 40250 不同,字体宽度是 7px 估算
Timing/event sources PARTIAL 气泡过期和 UI 信号存在;延迟聊天、真实服务器命令、重连/后台通知和私聊闪烁未接通
Resource/data sources GAP 40250 使用角色/公会/本地化/字体资源及服务器消息;当前标题本地化可注入但 chat 文本/颜色/宽度多为脚本常量和 Godot 默认字体
Protocol side effects PARTIAL classic CG_CHAT/CG_WHISPER 与 GC queue 有;入站类型副作用、SendSequence/错误文案、ignore 命令和 notice/big notice UI 未完整复现
Interruption/failure/cleanup GAP 私聊发送失败仍本地显示并关闭;会话/忽略/聊天行重连清理、未知 VID、重复/乱序回包和专用提示清理缺端到端证据

Regression evidence

  • project/chat_test.gd:公共/私聊输入路由、拾取/钓鱼消息、气泡和名字/子标签排布通过;使用 fake client,未验证真实 GC_CHAT 分支和发送失败。
  • project/chat_tail_test.gdRegisterChatTail/RegisterInfoTail、单 VID 覆盖和 5000ms 生命周期通过。
  • project/text_tail_test.gdproject/text_tail_arrange_test.gdproject/name_tail_layout_test.gdproject/guild_mark_tail_test.gd:静态颜色、称号/等级、公会名、排列和 guild mark 通过;未验证真实字体资源和 C++ 尾标对象。
  • project/test_whisper_chat_parity.gd:26/26 通过,覆盖会话、闪烁、忽略和历史;project/chat_test.gd 另验证 live ChatUI 的普通/GM 入站信号进入同一 conversation。
  • project/chat_mobile_ui_test.gdproject/test_chat_hyperlink_dice_parity.gd:移动聊天窗口、私聊输入和额外链接/dice helper 通过;不能证明 40250 的入站消息分支。
  • build/extension/net_entity_testbuild/extension/net_classic_session_testGC_CHAT/GC_WHISPER 解析和发送包基础通过;session 回归覆盖未知 VID、非法 type、已知 VID 的 chat event 矩阵;project/chat_test.gd 另覆盖 whisper mode 1/5/0xFF 的错误、GM、system 显示映射,但仍没有完整 0..5/0xFF live 回调、失败回显和重连测试。

Deep audit round 2026-09-21

Fresh regression results

  • godot --headless --path project --script chat_test.gdchat_tail_test.gdtext_tail_test.gdtext_tail_arrange_test.gd:均退出码 0;公共/私聊路由、气泡覆盖、5000ms 生命周期、颜色和尾标排布通过,但使用的是脚本/fake client 与近似字体度量。
  • godot --headless --path project --script name_tail_layout_test.gdguild_mark_tail_test.gd:均退出码 0;名字/公会标记和尾标布局 helper 通过。
  • godot --headless --path project --script test_whisper_chat_parity.gd:退出码 0,26/26 通过;覆盖独立的 WhisperChatSystem 会话、闪烁、忽略和历史;chat_test.gd 已补 live ChatUI 入站网络状态验证。
  • godot --headless --path project --script chat_mobile_ui_test.gdtest_chat_hyperlink_dice_parity.gd:均退出码 0;移动 UI、链接/骰子 helper 通过。
  • build/extension/net_entity_testbuild/extension/net_classic_session_test:均退出码 0GC_CHAT/GC_WHISPER 基础解析和发送包通过,未覆盖完整消息分支矩阵。

Static parity findings

  • 40250 RecvWhisperPacket 的 mode 是 0=CHAT1=NOT_EXIST2=TARGET_BLOCKED3=SENDER_BLOCKED4=ERROR5=GM0xFF=SYSTEM;当前 ChatUI::_on_whisper1 显示为系统、2 显示为 GM,且其余错误/屏蔽分支没有对应 UI 语义。
  • 当前 ChatUIclient.whisper() 返回前就本地追加回显并关闭私聊窗口;网络发送失败时仍显示成功,违背 40250 的请求结果驱动状态转换。
  • WhisperChatSystem 已有独立会话/忽略/闪烁实现,live ChatUI 现在把普通/GM M2Client.whisper_received 接入该状态源;独立窗口渲染、任务栏按钮和服务端 ignore 命令仍未闭环。
  • 40250 RecvChatPacket 对未知 VID 的普通消息直接忽略,并处理表情、跨帝国转换、辱骂过滤以及无 VID 的 NOTICE/BIG_NOTICE 专用提示;当前 _on_chat 对未知 VID 仍能显示原文,NOTICE/BIG_NOTICE 统一进入 RichTextLabel,未接专用提示和过滤链。
  • 40250 聊天气泡/尾标依赖 CGraphicText 实际字体、角色/公会/称号/等级权威同步并在死亡时 detach;当前 Label3D/脚本近似布局虽有局部测试,但没有真实字体资源、网络更新和重连/死亡/重复消息端到端证据。

Active command-bus source review

  • 本轮逐项核对 PythonNetworkStreamCommand.cpp 与当前 EntityStore::apply_server_commandM2Client::poll 信号链:当前端已经覆盖 cube、observer、StoneDetect、stamina、mobile、gift、combo、block mode、lover、password/refine/private-shop 以及 emotion/dig 的主要事件枚举,net_entity_test 对其中一组事件通过。
  • 仍存在参考语义差异:40250 未识别/参数数量错误命令会走日志或特定 UI 回调;当前端对命令的统一 token/参数校验、效果资源创建、所有 emotion/observer/gift 回调和命令失败清理没有完整矩阵。ClientCommand() 在参考版本本身返回 false,不能把当前端已有 server-command helper 测试解释为完整 GM/命令 parity。

Round conclusion

本轮仍为 PARTIAL:已按 40250 收口 native GC_CHAT 的非法类型/未知 VID 丢弃分支,修正 ChatUI 的 whisper mode 映射与空错误文案兜底,并把 live 普通/GM whisper 接入独立会话和 ignore 判断;窗口通知、NOTICE 分支、表情/过滤/跨帝国文字和真实尾标渲染仍未与 40250 统一。

Active EterLib text-render review

  • EterLib/GrpText.cpp/GrpTextInstance.cpp/TextBar.cpp/TextTag.cpp 以及 GrpFontTexture.cppGrpMarkInstance.cpp 共同负责真实字体资源、字宽/行数/字符位置、光标/描边/颜色、标记和池化对象生命周期;这正是 40250 聊天气泡、名字/公会/称号尾标的渲染基础。
  • 当前 Label3DRichTextLabel 和脚本宽度估算已覆盖局部可见结果,但没有复用同等字体纹理度量、字符定位、mark 生命周期和资源失败分支。已有布局测试使用 helper/fake client,不能替代真实字体资源与网络角色更新。
  • 因此本轮完成上述 EterLib 文本核心静态核对;尾标的单槽/5000ms/17px 行为仍有镜像证据,但渲染资源和清理链不一致,合同继续为 PARTIAL

Active UserInterface chat and text-tail review

  • InsultChecker.cpp/h 维护可清空/追加的禁词集合,按 locale-aware case-insensitive 比较处理多字节字符;FilterInsult* 替换完整词,IsInsultIn 只报告命中,不能用 ASCII find 近似替代。
  • PythonChatModule.cpp 暴露 chat set 的创建、位置/高度/步长/模式、延迟消息、忽略角色、whisper 会话、whisper 清理和 item hyperlink 解析;hyperlink 通过 CItemManager 查 item 数据,不是只显示原字符串。
  • PythonTextTailModule.cpp 的生产顺序是 UpdateAllTextTailUpdateShowingTextTailRegisterCharacterTextTailRegisterChatTail/RegisterInfoTail、标题/拾取/排列和投影位置查询;Pick、隐藏/显示和角色删除清理是同一状态机的一部分。
  • 当前端聊天/尾标 helper 已有局部测试,live ChatUI 已将普通/GM whisper 接入独立会话和 ignore 判断;仍未形成 locale 禁词、多字节边界、chat-set 排列、item hyperlink、未知/删除 VID、投影失败和真实字体资源的同一调用链,已有 Godot 宽度估算和本地文本状态不能证明 40250 等价,合同保持 PARTIAL

Implementation fix round 2026-09-22

  • project/ui/chat_ui.gd 已按 PythonChat.h/game.py 修正 whisper mode1..4 作为错误系统消息,5 作为 GM0xFF 作为 system;空错误正文使用本地化兜底文案。
  • extension/src/net/classic/classic_parser.cpp 已按 RecvWhisperPacket 的固定头前置条件,将缺少 type/name 的 GC_WHISPER body 从静默成功改为失败;net_classic_session_test 增加对应直接 parser 回归。
  • project/chat_test.gdproject/test_whisper_chat_parity.gdproject/chat_mobile_ui_test.gdproject/test_chat_hyperlink_dice_parity.gd 与 native session 回归通过;live conversation/ignore 接入已有证据,完整通知/颜色、忽略命令和公共聊天副作用仍未闭环。

Static review evidence

已将 InsultChecker.cpp/hPythonChatModule.cppPythonTextTailModule.cpp 纳入 active source 证据;这些文件对应的过滤、chat-set、whisper、hyperlink、尾标更新和拾取分支仍记录为实现差异或未验证分支。

Status

PARTIAL。当前端已有聊天协议骨架、公共输入、私聊基础发送、聊天气泡和名字尾标的可测试镜像,但并非与 40250 统一实现:live 私聊已接入独立会话,但窗口历史/任务栏通知/服务端 ignore 命令仍未闭环;公共颜色/notice 分支不一致、入站表情/过滤/跨帝国文本缺失,且尾标渲染仍使用 Godot billboard 与宽度估算。本轮已修正 whisper mode 映射、空错误文案、截断 whisper 拒绝逻辑并接通 live conversation/ignore 判断,其他差异继续保持 PARTIAL。