3.聊天消息树协议设计
3.1 知识点
设计思路
聊天消息树(ChatInfoTree
)是一种通用的聊天传输格式,是客户端与服务器之间唯一的聊天协议载体。双端都有这些代码。通过消息树,你可以轻松地:
- 定义频道与目标:设置
ChatChannelType
、ChatChannelId
,并指定一个或多个接收目标Target
。 - 组织丰富内容:按顺序拼接任意类型的节点(文字、表情、链接、位置、打开 UI、装备信息等),每个节点都可携带交互事件。
- 自定义展示:客户端解析后,可根据节点类型自由渲染,支持富文本、高亮、点击跳转、地图定位等效果。
这种设计不仅让消息格式高度模块化、可扩展,还保证了客户端与服务器对协议的完全一致,使得新增节点类型、改动展示逻辑都能在不破坏兼容性的前提下平滑迭代。
消息树结构与属性定义图
classDiagram class ChatInfoTree { +int ChatChannelType +long ChatChannelId +long UnitId +string UserName +bool IsHaveLinkItem +long SystemBroadcastId +ListTarget +List Nodes } class ChatInfoNode { +int ChatNodeType +int ChatNodeEvent +string Content +string Color +byte[] Data } ChatInfoTree "1" o-- "*" ChatInfoNode : 包含
ChatInfoTree
ChatChannelType
:频道类型(世界 / 私聊 / 公会 / 跑马灯 / …)ChatChannelId
:频道 ID(对应组队、公会、地图等)UnitId
、UserName
:发送者身份IsHaveLinkItem
:是否包含可点击的物品或链接(可选)SystemBroadcastId
:系统广播配置 ID(可选)Target
:定向接收者列表(私聊或部分广播)Nodes
:按顺序存放的消息节点列表
ChatInfoNode
ChatNodeType
:节点类型(Text / Link / Image / OpenUI / Position / Item …)ChatNodeEvent
:点击或交互事件类型(ClickLink / OpenUI / Position / UseItem …)Content
:显示文本或简要描述Color
:自定义显示颜色(可选)Data
:序列化后的二进制参数(如链接地址、UI 名称、坐标结构等,可选)
面向对象类图
注意:可以直接在消息中传入ChatInfoTree,无需序列化反序列化ChatInfoTree。保证双端有共享聊天数协议即可。当然也可以序列化ChatInfoTree后再接受端再反序列化,这样传递的是字节数组。
classDiagram class ChatMessage { +ChatInfoTree Tree +byte[] Serialize() +$static$ ChatMessage Deserialize(byte[]) } class ChatInfoTree { +int ChannelType +long ChannelId +long SenderId +string SenderName +List~long~ TargetIds +List~ChatInfoNode~ Nodes +AddText(string)$ ChatInfoTree +AddLink(string, string)$ ChatInfoTree +AddImage(string)$ ChatInfoTree +AddOpenUI(string, string)$ ChatInfoTree +AddPosition(string, string, float, float, float)$ ChatInfoTree } class ChatInfoNode { +int NodeType +int EventType +string Content +string Color +byte[] Data } ChatMessage --> ChatInfoTree ChatInfoTree "1" o-- "*" ChatInfoNode : contains
- ChatMessage:负责整条消息的序列化与反序列化。
- ChatInfoTree:链式 API 构建各类节点,最终生成完整树结构。
- ChatInfoNode:仅存数据,无行为;所有“添加节点”的方法都由
ChatInfoTree
提供。
核心伪代码示例
// 客户端:构建一条世界聊天,带位置和超链接
var tree = new ChatInfoTree()
.AddText("我当前在:")
.AddPosition("龙之谷", "龙之谷地图", 120.5f, 75.2f, 0f)
.AddText(" 更多信息:")
.AddLink("点击前往官网", "https://game.example.com");
// 序列化并发送
var msg = new ChatMessage { Tree = tree };
await session.Call(new C2Chat_SendMessageRequest {
ChatInfoTree = msg.Serialize()
});
// 服务器端:解析并分发
var resp = await session.Call<Chat2C_Message>(req);
var chatMsg = ChatMessage.Deserialize(resp.ChatInfoTree);
foreach (var node in chatMsg.Tree.Nodes) {
switch ((ChatNodeType)node.NodeType) {
case ChatNodeType.Text:
Console.Write(node.Content);
break;
case ChatNodeType.Link:
// 渲染为可点击超链接
break;
case ChatNodeType.Position:
// 绑定地图跳转事件
break;
// ……
}
}
// 频道类型
[Flags]
public enum ChatChannelType {
None = 0,
World = 1 << 1,
Private = 1 << 2,
System = 1 << 3,
Broadcast = 1 << 4,
Notice = 1 << 5,
Team = 1 << 6,
Near = 1 << 7,
CurrentMap = 1 << 8,
All = World | Private | System | Broadcast | Notice | Team | Near,
Display = All | CurrentMap
}
// 节点交互事件
public enum ChatNodeEvent {
None = 0,
OpenUI = 1,
OpenLink = 2,
UseItem = 3,
Position = 4
}
// 节点类型
public enum ChatNodeType {
None = 0,
Position = 1,
OpenUI = 2,
Link = 3,
Item = 4,
Text = 5,
Image = 6
}
// 工厂扩展方法(部分示例)
public static class ChatNodeFactory {
public static ChatInfoTree AddendTextNode(this ChatInfoTree tree, string content) { … }
public static ChatInfoTree AddendLinkNode(this ChatInfoTree tree, string content, string link) { … }
public static ChatInfoTree AddendImageNode(this ChatInfoTree tree, string content) { … }
public static ChatInfoTree AddendOpenUINode(this ChatInfoTree tree, string content, string uiName) { … }
public static ChatInfoTree AddendPositionNode(this ChatInfoTree tree, string content, string mapName, float x, float y, float z) { … }
}
// 聊天树快捷入口
public static class ChatTreeFactory {
public static ChatInfoTree World(Scene s) => new() { Scene = s, ChatChannelType = (int)ChatChannelType.World };
public static ChatInfoTree Private(Scene s) => new() { Scene = s, ChatChannelType = (int)ChatChannelType.Private };
// … 其它频道 …
}
小结
- 统一格式:
ChatInfoTree
+ChatInfoNode
让所有聊天场景都走同一条协议路线。 - 链式易用:面向对象的链式 API,让客户端构建消息简单直观。
- 事件驱动:节点携带
ChatNodeEvent
,可在 UI 层或逻辑层自由绑定交互。 - 高度可扩展:新增节点类型或事件,只需扩展枚举和 Factory 方法,无需改动分发/渲染框架。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com