找回密码
 registerss
搜索
查看: 46|回复: 0

洱海月 v0-07-0300 封包解析:ID 487 CGCharAllTitles(请求全部称号列表)

[复制链接]
  • 打卡等级:本地老炮
  • 打卡总天数:603
  • 打卡月天数:1
  • 打卡总奖励:600
  • 最近打卡:2026-10-03 06:32:28
Waylee 发表于 2026-4-12 19:16 | 显示全部楼层 |阅读模式 | Google Chrome | Windows 10

马上注册,查看网站隐藏内容!!

您需要 登录 才可以下载或查看,没有账号?registerss

×

CGCharAllTitles 是旧版客户端里用于请求角色全部称号列表的查询包。

当前版本中,这条包本身只携带一个对象 ID,但当前 Lua 场景服处理并不会使用这个字段,而是固定把“请求者自己”的全部称号列表整理成 GCCharAllTitles 回给客户端。

包信息

项目 内容
封包 ID 487
包名 CGCharAllTitles
方向 CG 客户端 -> 场景服
固定包长 4
直接回包 GCCharAllTitles
回包 ID 237
当前 Lua 入口 request:CGCharAllTitles()
当前场景服处理 scenecore:char_all_titles()
主要作用 请求当前角色全部称号数据并回传数值称号与字符串称号列表

当前 Game.exe 的虚函数结论为:

GetPacketID() = 487;
GetPacketSize() = 4;

包体结构

这条包是固定长度包,只有一个 uint32 字段。

偏移 长度 字段 类型 含义
0x00 0x04 target_obj_id uint32 客户端上传的目标对象 ID

当前实际行为 / 模式说明

  • 当前 Lua 请求入口是 request:CGCharAllTitles(),随后调用场景服 char_all_titles()。
  • 当前场景服处理函数签名是 scenecore:char_all_titles(who),只使用请求者对象 ID who,并没有读取包体里的 target_obj_id。
  • 因此在当前项目现状下,这条包虽然上传了一个对象 ID,但服务端实际固定回的是“当前请求角色自己的称号列表”。
  • 角色对象会调用 update_titles_to_client() 构造 GCCharAllTitles:
    • self.id_titles 作为数值称号列表
    • self.titles 作为字符串称号列表
  • 当前 Lua 中这两类列表的真实结构已经能直接确认:
    • id_titles 元素形如 { id = xxx }
    • titles 元素形如 { id = xxx, str = "xxx" }
  • GCCharAllTitles 在当前 Lua 发送时还会补齐两个数量字段:
    • m_nTitleId = #self.id_titles
    • m_nTitleStr = #self.titles
  • 当前 Game.exe 的 GCCharAllTitles 处理器还明确限制:
    • 数值称号数量最大 0x86,即 134
    • 字符串称号数量最大 0x10,即 16

关联回包结构

GCCharAllTitles 是变长回包,头部固定 6 字节,后面依次跟:

  • 12 * m_nTitleId 字节的数值称号数组
  • sum(13 + title_len) 字节的字符串称号数组

当前 Game.exe 的 GetPacketSize() 公式可归纳为:

size = 6 + 12 * title_id_count + Σ(13 + title_len);

GCCharAllTitles 头部结构

偏移 长度 字段 类型 含义
0x00 0x04 obj_id uint32 被回填称号列表的对象 ID
0x04 0x01 title_id_count uint8 数值称号数量,客户端最大接收 134
0x05 0x01 title_str_count uint8 字符串称号数量,客户端最大接收 16

数值称号单项结构

每个数值称号固定 12 字节。

偏移 长度 字段 类型 含义
+0x00 0x04 reserved uint32 当前 Lua 发送时固定写 0
+0x04 0x04 title_id uint32 数值称号 ID
+0x08 0x04 remain_time uint32 剩余时间,当前 Lua 默认写 0

字符串称号单项结构

每个字符串称号长度为 13 + title_len 字节。

偏移 长度 字段 类型 含义
+0x00 0x04 title_id uint32 字符串称号类型 ID
+0x04 0x01 title_len uint8 称号字符串长度
+0x05 0x04 reserved_1 uint32 当前 Lua 发送时固定写 0
+0x09 0x04 reserved_2 uint32 当前 Lua 发送时固定写 0
+0x0D n title_str char[n] GBK 字符串内容

服务端落点

这条包在当前项目里的关键位置如下:

  • 协议定义:
    • /home/ubuntu/Game2/services/game/packet.lua
  • 请求入口:
    • /home/ubuntu/Game2/services/msgagent.lua
  • 场景服处理:
    • /home/ubuntu/Game2/services/scene/scenecore.lua
  • 角色称号回包构造:
    • /home/ubuntu/Game2/services/scene/obj/human.lua
  • 脚本侧称号派发入口:
    • /home/ubuntu/Game2/lualib/script_base.lua

关键代码

当前 Lua 协议定义

packet.CGCharAllTitles = {
    xy_id = packet.XYID_CG_CHAR_ALL_TITLES,
    ctor = function(self) self.m_objID = 0 end,
    bis = function(self, buffer)
        local stream = bistream.new()
        stream:attach(buffer)
        self.m_objID = stream:readuint()
    end
}

当前 Lua 请求入口与场景服处理

function request:CGCharAllTitles()
    skynet.call(my_scene, "lua", "char_all_titles", my_obj_id, self)
end

function scenecore:char_all_titles(who)
    local obj_me = self:get_obj_by_id(who)
    obj_me:update_titles_to_client()
end

这里可以直接看出:当前场景服没有使用 self.m_objID,而是固定把请求者 who 的称号列表发回客户端。

当前角色称号回包构造

function human:update_titles_to_client()
    local msg = packet_def.GCCharAllTitles.new()
    msg.m_objID = self:get_obj_id()
    msg.m_nTitleId = #self.id_titles
    msg.m_TitleIdList = self.id_titles
    msg.m_nTitleStr = #self.titles
    msg.m_TitleStrList = self.titles
    self:get_scene():send2client(self, msg)
end

当前称号列表真实数据结构

function human:add_id_title(id)
    table.insert(self.id_titles, { id = id })
end

function human:set_title(id, titlestr)
    local title = { id = id, str = titlestr }
    table.insert(self.titles, title)
end

当前 Game.exe 关键结论

CGCharAllTitles::Read/Write 都只处理一个 uint32:

Read : read(a1 + 24, 4);
Write: write(a1 + 24, 4);
GetPacketSize() = 4;

GCCharAllTitles 则是变长回包:

GetPacketID() = 237;
GetPacketSize() = 6 + 12 * title_id_count + Σ(13 + title_len);

客户端处理器 GCCharAllTitlesHandler.cpp 还能进一步确认:

  • title_id_count <= 134
  • title_str_count <= 16
  • 数值称号项按三段 uint32 读取
  • 字符串称号项按 uint32 + uint8 + uint32 + uint32 + char[n] 读取

结论

CGCharAllTitles 在当前旧版项目中可以明确归类为“请求全部称号列表”的固定 4 字节查询包。

它的包体确实带有一个 target_obj_id,但当前 Lua 服务端并不使用这个字段,实际行为是:

  • 固定回当前请求角色自己的称号列表
  • 回包 GCCharAllTitles 同时带回数值称号与字符串称号两套数据

因此,这条包在当前项目中的最终用途应当直接写成:

“请求当前角色全部称号数据并同步到客户端称号缓存”。

您需要登录后才可以回帖 登录 | registerss

本版积分规则

QQ|手机版|雪舞知识库 ( 浙ICP备15015590号-1 | 萌ICP备20232229号|浙公网安备33048102000118号 )|天天打卡

GMT+8, 2026-10-4 11:26 , Processed in 0.065705 second(s), 26 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表