3.聊天消息树协议设计
3.1 设计思路
聊天消息树(ChatInfoTree)是一种通用的聊天传输格式,是客户端与服务器之间唯一的聊天协议载体。双端都有这些代码。通过消息树,你可以轻松地:
- 定义频道与目标:设置
ChatChannelType、ChatChannelId,并指定一个或多个接收目标Target。 - 组织丰富内容:按顺序拼接任意类型的节点(文字、表情、链接、位置、打开 UI、装备信息等),每个节点都可携带交互事件。
- 自定义展示:客户端解析后,可根据节点类型自由渲染,支持富文本、高亮、点击跳转、地图定位等效果。
这种设计不仅让消息格式高度模块化、可扩展,还保证了客户端与服务器对协议的完全一致,使得新增节点类型、改动展示逻辑都能在不破坏兼容性的前提下平滑迭代。
3.2 消息树结构与属性定义图
classDiagram
class ChatInfoTree {
+int ChatChannelType
+long ChatChannelId
+long UnitId
+string UserName
+bool IsHaveLinkItem
+long SystemBroadcastId
+List Target
+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 名称、坐标结构等,可选)
3.3 面向对象类图
注意:可以直接在消息中传入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提供。
3.4 核心伪代码示例
// 客户端:构建一条世界聊天,带位置和超链接
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 };
// … 其它频道 …
}
3.5 小结
- 统一格式:
ChatInfoTree+ChatInfoNode让所有聊天场景都走同一条协议路线。 - 链式易用:面向对象的链式 API,让客户端构建消息简单直观。
- 事件驱动:节点携带
ChatNodeEvent,可在 UI 层或逻辑层自由绑定交互。 - 高度可扩展:新增节点类型或事件,只需扩展枚举和 Factory 方法,无需改动分发/渲染框架。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com