包信息
| 项目 |
内容 |
| 封包 ID |
163 |
| 包名 |
GCBoxItemList |
| 方向 |
GC 服务端 -> 客户端 |
| 包长 |
动态 |
| 直接发送 |
场景服 |
| 主要关联交互 |
GCNewItemBox / CGPickBoxItem / GCPickResult |
| 主要作用 |
打开场景物品箱或采集点后,把箱内物品列表一次性下发给客户端 |
当前 Game.exe 可直接确认:
GetPacketID():sub_1405ECD90,返回 163
GetPacketSize():sub_1405EEC10,固定头 7 字节,再逐项累加 ItemInfo 长度
Read():sub_1405FFF10
Write():sub_1405FFFB0
Execute():sub_1405FFF00 -> sub_140333950
包体结构
| 偏移 |
长度 |
字段 |
类型 |
含义 |
0x00 |
0x04 |
m_objID |
uint32 |
场景中 itembox 对象 ID |
0x04 |
0x01 |
size |
uint8 |
本次下发的物品条目数,读写时都会限制最大 10 |
0x05 |
0x02 |
item_box_type |
int16 |
物品箱类型;当前 Lua 仅确认 -1 掉落箱、0 生长点箱 |
0x07 |
动态 |
item_list |
ItemInfo[size] |
按顺序序列化的物品条目列表 |
当前 Game.exe 与 Lua 的读写顺序完全一致:
read(m_objID, 4);
read(size, 1);
read(item_box_type, 2);
for (i = 0; i < size; ++i)
read(ItemInfo[i]);
stream:writeuint(self.m_objID)
stream:writeuchar(self.size)
stream:writeshort(self.item_box_type)
for i = 1, self.size do
packet.ItemInfo.bos(self.item_list[i], stream)
end
需要单独注意两点:
size 在客户端 Read() 和服务端 bos() 中都会被裁到 10,不是纯粹的信任字段。
item_list 不是固定长度尾部。GetPacketSize() 先取固定头 7 字节,再通过 sub_1405B3BA0() 逐项累计每个 ItemInfo 的实际序列化长度,因此整包长度取决于具体物品类型。
当前实际行为
- 当前 Lua 发送点有两条主链:
/home/ubuntu/Game2/services/scene/scenecore.lua 的 char_open_box_item():玩家主动打开场景物品箱时下发列表。
/home/ubuntu/Game2/services/scene/ability/generic_gather.lua 的 on_proc_success():采集成功后,如果目标是 itembox 且内部有物品,则直接下发列表。
- 两条主链都会从
itembox 的容器里读取原始物品数据,逐项执行 item:copy_raw_data() 后塞进 msg.item_list。
- 当前
itembox 容器在 /home/ubuntu/Game2/services/scene/obj/itembox.lua 初始化时固定 init(10, {}, define.CONTAINER_INDEX.ITEM_BOX),因此 size <= 10 不只是网络层限制,也符合当前场景箱体容器容量。
item_box_type 当前服务端枚举只有两种:
define.ITEMBOX_TYPE.ITYPE_DROPBOX = -1
define.ITEMBOX_TYPE.ITYPE_GROWPOINT = 0
- 客户端
Execute() 的实际行为不是简单缓存包体,而是:
- 通过
m_objID 找到场景里的箱体对象
- 清理当前物品箱展示
- 按
size 遍历 item_list
- 为每个条目解析物品模板、复制
ItemInfo 原始数据并挂到界面槽位
- 在当前交互对象仍然有效时刷新开箱界面状态
这说明 GCBoxItemList 的定位是“展示箱内可拾取内容”,而不是“执行拾取结果”;真正拾取单个条目的成功或失败,由 GCPickResult 承担。
服务端落点
/home/ubuntu/Game2/services/game/packet.lua
- 定义
packet.GCBoxItemList
bis() / bos() 都按 m_objID -> size -> item_box_type -> item_list 顺序处理
/home/ubuntu/Game2/services/scene/scenecore.lua
char_open_box_item() 构造并发送 GCBoxItemList
/home/ubuntu/Game2/services/scene/ability/generic_gather.lua
on_proc_success() 在采集型箱体上直接发送 GCBoxItemList
/home/ubuntu/Game2/services/scene/obj/itembox.lua
- 初始化
itembox 容器容量为 10
- 提供
get_item_box_type() 作为 item_box_type 来源
/home/ubuntu/Game2/lualib/define.lua
关键代码
packet.GCBoxItemList = {
xy_id = packet.XYID_GC_ITEM_BOX_LIST,
bis = function(self, buffer)
local stream = bistream.new()
stream:attach(buffer)
self.m_objID = stream:readuint()
self.size = stream:readuchar()
self.size = self.size > 10 and 10 or self.size
self.item_box_type = stream:readshort()
self.item_list = {}
for i = 1, self.size do
local item = packet.ItemInfo.new()
item:bis(stream)
self.item_list[i] = item
end
end,
bos = function(self)
local stream = bostream.new()
stream:writeuint(self.m_objID)
stream:writeuchar(self.size)
self.size = self.size > 10 and 10 or self.size
stream:writeshort(self.item_box_type)
for i = 1, self.size do
packet.ItemInfo.bos(self.item_list[i], stream)
end
return stream:get()
end
}
local msg = packet_def.GCBoxItemList.new()
local container = obj_box:get_container()
local list = {}
local item_list = container:get_item_data()
for i = 0, container:get_size() do
local item = item_list[i]
if item then
table.insert(list, item:copy_raw_data())
end
end
msg.m_objID = box_item.m_objID
msg.size = #list
msg.item_list = list
msg.item_box_type = obj_box:get_item_box_type()
self:send2client(me, msg)
__int64 __fastcall sub_1405EEC10(__int64 a1)
{
unsigned int total = 7;
for (int i = 0; i < *(unsigned __int8 *)(a1 + 32); ++i)
total += sub_1405B3BA0(a1 + 36 + 188LL * i);
return total;
}
结论
GCBoxItemList 是当前 Temp_Release_v0-07-0300 里用于“打开场景物品箱内容列表”的动态回包。它的固定头很小,只有 m_objID + size + item_box_type 共 7 字节,真正的大头在后面的 ItemInfo[size] 变长数组。
从当前 Lua 和 Game.exe 的一致证据看,这条包的实际语义已经很明确:
- 它只负责告诉客户端“这个箱子里现在有哪些物品”
- 它不负责单个物品的拾取结算
- 它当前最多承载
10 个条目
item_box_type 在当前服务端只稳定出现掉落箱 -1 和生长点箱 0
因此,GCBoxItemList 最准确的理解不是“通用物品列表包”,而是“绑定具体场景 itembox 对象的开箱内容同步包”。