调整聊天插件(功能服与跨服通信)
上一篇的地图插件是单服逻辑。这一篇用官方聊天插件(neteaseChat)讲跨服通信——世界频道要把消息发到所有服务器,必须经过**功能服(Service)**中转。
功能服(Service)是什么
功能服连接所有游戏服/大厅服和数据库,能拿到全服信息、处理全服操作。判断要不要用功能服:
- 本地频道(只在当前服)→ 不需要功能服
- 世界频道(发到所有服)→ 必须经功能服转发
所以聊天插件有两个 Mod:neteaseChat(客户端+服务端,跑在游戏/大厅服)和 neteaseChatService(跑在功能服)。
三端结构
| Mod | System 类 | 职责 |
|---|---|---|
| 客户端 | ChatClientSystem | UI 显示、按钮响应、本地消息缓存 |
| 服务端 | ChatServerSystem | 各节点通信、事件响应 |
| 功能服 | ChatServiceSystem | 跨服消息转发 |
每端还有一个 ChatManager 管理各频道消息。频道用服务器 id 区分:本地频道 = 服务器 id,世界频道 = 0。
初始化流程
- 各端 system 初始化:Server 创建本地+世界频道;Client 创建 UIMgr;Service 监听
NetGameCommonConfChangeEvent,为每个 game/lobby 服建一个频道 - 客户端 UI 就绪:客户端响应
UiInitFinished,创建聊天界面,向服务端发ClientUiInitFinished - 服务端回传玩家信息:服务端拿到玩家 uid/昵称,发
ModConfigResponseFromServerEvent(配置)和TellYourPlayerUidAndSidEvent(uid/服务器 id)给客户端 - 客户端据此创建本地/世界频道
世界消息的完整流转
一条世界频道消息,从发送到所有玩家看到,经过这些节点(看清楚事件名在各端间接力):
客户端发送
└─ PlayerChatFromClientEvent ──▶ 服务端
└─ RequestToService(ChatFromServerEvent) ──▶ 功能服
└─ 插入频道,世界频道则遍历所有服
└─ newChatFromServiceEvent ──▶ 各服务端
└─ newChatFromServerEvent ──▶ 各客户端
└─ 定时刷新 LocalNewChatRecord ──▶ Chat UI 显示关键几段代码:
python
# 功能服:世界频道消息发给所有服务器
def TellServerNewChat(self, chatDict):
if self.mChatChannel != chatConsts.ALL_SERVER_CHANNEL:
self.system.NotifyToServerNode(self.mChatChannel, "newChatFromServiceEvent", chatDict)
else:
for serverid in self.system.GetCommonConfig():
self.system.NotifyToServerNode(serverid, "newChatFromServiceEvent", chatDict)python
# 服务端:收到后广播给本服所有客户端
def TellClientNewChat(self, chatDict):
self.system.BroadcastToAllClient("newChatFromServerEvent", chatDict)跨服通信的三个关键 API
RequestToService(服务端→功能服)、NotifyToServerNode(功能服→指定服务端)、BroadcastToAllClient(服务端→本服全部客户端)。跨服逻辑基本都是这三者的组合。
微调实战:聊天前缀加服务器类型
需求:每条消息前面加上发送者所在的服务器类型前缀。改动点在功能服 neteaseChatService——它是消息的中转站,在转发时给 chatDict 加上服务器类型字段,客户端显示时读取即可。这样不管本地还是世界频道,前缀都统一由功能服注入,避免各服务端各写一套。
学到这里,你已经能读懂并二次开发官方插件了。接下来看开发技巧与性能优化,让你的网络服跑得又稳又快。回到基岩版网络游戏首页。
