GCMonsterSpeak 是当前怪物/NPC 在场景里说话时使用的广播包。它把发言对象 ID 和一段变长文本一起发给附近客户端,用于显示怪物对白气泡或相关表现。
当前 Lua 协议与当前 Game.exe 的长度规则一致:包头 5 字节,后面跟随 text_len 字节正文。
包信息
| 项目 |
内容 |
| 封包 ID |
93 |
| 包名 |
GCMonsterSpeak |
| 方向 |
GC 游戏服 -> 客户端 |
| 包长 |
5 + text_len |
| 当前 Lua 协议定义 |
/home/ubuntu/Game2/services/game/packet.lua |
| 主要服务端落点 |
/home/ubuntu/Game2/lualib/script_base.lua |
| 主要作用 |
广播怪物或 NPC 的一句场景对白 |
当前 Game.exe 可直接确认:
GetPacketID() = 93;
GetPacketSize() = 5 + text_len;
包体结构
| 偏移 |
长度 |
字段 |
类型 |
含义 |
0x00 |
0x04 |
monster_obj_id |
int32 |
发言对象 ID |
0x04 |
0x01 |
text_len |
uint8 |
实际文本长度 |
0x05 |
text_len |
speak_content |
char[text_len] |
对白正文 |
当前实际行为
- 当前 Lua
MonsterNewTalk() 会构造 GCMonsterSpeak,把 m_objID 设为发言怪物 ID,再把 speek_content 广播到场景。
- 当前
packet.lua 在写包前会先把文本从 UTF-8 转成 GBK,然后把长度裁到最大 63 字节。
- 因此,虽然协议本身是变长文本包,但当前现役 Lua 发送链会主动限制单条对白正文不超过
63 字节。
- 当前
Game.exe 的长度公式 5 + text_len 和 Lua 的 1 字节长度写法完全一致。
服务端落点
- 协议定义:
/home/ubuntu/Game2/services/game/packet.lua
- 主要广播入口:
/home/ubuntu/Game2/lualib/script_base.lua
当前 Lua 的现役调用非常直接:
function script_base:MonsterNewTalk(selfId, str)
local msg = packet_def.GCMonsterSpeak.new()
msg.m_objID = selfId
msg.speek_content = str
monster:get_scene():broadcast(monster, msg, false)
end
关键代码
当前 Lua 写包逻辑
stream:writeint(self.m_objID)
self.speek_content = gbk.fromutf8(self.speek_content)
local len = string.len(self.speek_content)
len = len >= 0x40 and 63 or len
stream:writeuchar(len)
stream:write(self.speek_content, len)
当前 Game.exe 关键结论
GetPacketSize() {
return 5 + text_len;
}
结论
GCMonsterSpeak(93) 是当前场景怪物对白广播包,完整结构已经可以稳定命名为 monster_obj_id + text_len + speak_content。它的协议本体是标准的 1 字节长度前缀文本结构,而当前 Lua 现役发送链额外把正文限制在 63 字节以内。
这条包的字段和行为都能由当前 Lua 服务端与当前 Game.exe 直接确认,不需要借助旧 Server 来补名。
|