CGAskItemInfo 是客户端向游戏服请求某个背包格详细物品信息的定长请求包。
当前版本里,这条包结构非常简单,只有一个背包格索引和一个请求回显标识。服务端收到后会从角色道具背包中取出对应格子的物品原始数据,并通过 GCItemInfo 回传。
包信息
| 项目 |
内容 |
| 封包 ID |
210 |
| 包名 |
CGAskItemInfo |
| 方向 |
CG 客户端 -> 游戏服 |
| 包长 |
6 |
| 当前 Lua 协议定义 |
/home/ubuntu/Game2/services/game/packet.lua |
| 当前服务端入口 |
/home/ubuntu/Game2/services/msgagent.lua |
| 当前场景处理 |
/home/ubuntu/Game2/services/scene/scenecore.lua 的 ask_item_info() |
| 主要作用 |
请求查询指定背包格物品详情,并等待 GCItemInfo 回包 |
当前 Game.exe 可直接确认:
GetPacketID() = 210;
GetPacketSize() = 6;
Read() = sub_1405C2170;
Write() = sub_1405C21C0;
Execute() = sub_140328170;
包体结构
| 偏移 |
长度 |
字段 |
类型 |
含义 |
0x00 |
0x02 |
bagIndex |
uint16 |
当前角色道具背包格索引 |
0x02 |
0x04 |
askid |
uint32 |
请求回显标识,服务端会原样回填到 GCItemInfo.askid |
总长度固定为:
2 + 4 = 6
当前实际行为 / 模式说明
- 当前 Lua 服务端收到
CGAskItemInfo 后,会直接把请求转交场景层 ask_item_info() 处理。
- 场景层会先创建一条
GCItemInfo 回包,并把请求里的:
原样带回响应。
obj:get_prop_bag():get_item(bag_index)
从当前角色的道具背包中读取该格物品。
- 如果该格没有物品,当前实现会构造一个空
item_cls.new() 占位数据,并把 GCItemInfo.unknow_1 置为 define.INVAILD_ID,表示该格为空。
- 如果该格存在物品,则回包中会带上
copy_item_raw_data_with_lock_state(item) 的完整道具原始数据。
- 这条包本身不负责修改物品状态,只负责查询并回传详情。
因此,CGAskItemInfo 在当前版本里的实际定位,就是“客户端查询背包格物品信息”的轻量请求包。
服务端落点
- 协议定义:
/home/ubuntu/Game2/services/game/packet.lua
- 请求入口:
/home/ubuntu/Game2/services/msgagent.lua
- 场景处理:
/home/ubuntu/Game2/services/scene/scenecore.lua
当前 Lua 转发关系非常直接:
function request:CGAskItemInfo()
skynet.call(my_scene, "lua", "ask_item_info", my_obj_id, self)
end
场景层核心处理如下:
function scenecore:ask_item_info(whos, ask)
local ret = packet_def.GCItemInfo.new()
ret.askid = ask.askid
ret.bagIndex = ask.bagIndex
ret.unknow_1 = 0
ret.unknow_2 = 0
local obj = self.objs[whos]
obj:refresh_locked_item_unlock_state(false)
local item = obj:get_prop_bag():get_item(ask.bagIndex) or item_cls.new()
local raw_data = obj:copy_item_raw_data_with_lock_state(item)
ret.item = raw_data
if item:get_index() == define.INVAILD_ID then
ret.unknow_1 = define.INVAILD_ID
end
self:send2client(obj, ret)
end
关键代码
当前 Lua 协议定义
packet.CGAskItemInfo = {
xy_id = packet.XYID_CG_ASK_ITEM_INFO,
ctor = function(self) end,
bis = function(self, buffer)
local stream = bistream.new()
stream:attach(buffer)
self.bagIndex = stream:readushort()
self.askid = stream:readuint()
end,
bos = function(self)
local stream = bostream.new()
stream:writeushort(self.bagIndex)
stream:writeuint(self.askid)
return stream:get()
end
}
当前 Game.exe 关键结论
当前客户端包类的读写顺序与 Lua 完全一致:
Read(stream) {
read_u16(bagIndex);
read_u32(askid);
return 1;
}
Write(stream) {
write_u16(bagIndex);
write_u32(askid);
return 1;
}
GetPacketSize() {
return 6;
}
Execute() {
return 2;
}
其中 Read() 在当前 Game.exe 里对应两次固定长度读取:
read(stream, this + 0x18, 2);
read(stream, this + 0x1C, 4);
这与当前 Lua 的 ushort + uint32 完全对齐。
结论
CGAskItemInfo 在当前 Temp_Release_v0-07-0300 里的最终结论可以直接收敛为:
- 这是一条固定长度
6 字节的客户端请求包。
- 包体只有两个字段:
bagIndex 用于定位当前角色道具背包中的目标格子。
askid 是请求回显标识,服务端会原样带回到 GCItemInfo.askid,用于客户端侧做请求响应对应。
- 当前真实业务处理在
scenecore:ask_item_info(),作用是查询背包格物品详情,不负责消耗、移动或修改物品。
- 当前
Game.exe 与当前 Lua 对这条包的结构判断完全一致,不需要借助旧 Server 作为结论依据。