CGPlayerShopAcquireShopList 是当前 Temp_Release_v0-07-0300 中用于请求玩家商店列表的空包协议。当前 Game.exe 可以明确确认这条请求包没有包体字段;Lua 服务端收到后,会直接返回 GCPlayerShopAcquireShopList(578) 店铺列表数据。
包信息
| 项目 |
内容 |
| 封包 ID |
27 |
| 包名 |
CGPlayerShopAcquireShopList |
| 对应回包 |
GCPlayerShopAcquireShopList(578) |
| 作用 |
请求当前玩家商店列表 |
当前 Game.exe 的虚函数结论为:
CGPlayerShopAcquireShopList
GetPacketID() = 0x1405EFE80 -> 27;
GetPacketSize() = 0x14046FDC0 -> 0;
Read = 0x1400BFC70;
Write = 0x1400BFC70;
Execute thunk = 0x1405FDBD0 -> 0x140328DE0;
包体结构
当前 Game.exe 中这是一条空包,请求体长度为 0。
| 偏移 |
长度 |
字段 |
类型 |
含义 |
- |
0 |
(无) |
- |
当前请求包无包体字段 |
当前实际行为
- 当前
Game.exe 明确保留了 CGPlayerShopAcquireShopList,并将其定义为空包。
- Lua 消息服收到这条请求后,会转发到场景服的
char_player_shop_acquire_shop_list。
- 当前场景服不会读取任何请求字段,而是直接组装
GCPlayerShopAcquireShopList 回包。
- 该回包在当前请求链路中包含:
npc_id = define.INVAILD_ID
com_factor = playershopmanager:get_com_factor()
shop_infos = playershopmanager:get_shop_infos({ human = human })
- 因此当前这条请求的真实效果是:向客户端回发“当前所有已挂牌玩家店铺列表”。
playershopmanager:get_shop_infos() 在当前实现里会遍历全部 player_shops,只保留 is_listed_player_shop(shop) 的店铺。
- 如果传入当前玩家对象,还会先同步该玩家的收藏店铺状态,再写入每个店铺条目的
is_in_favor。
- 同一条
GCPlayerShopAcquireShopList 回包还会被 NPC 脚本层复用:
DispatchPlayerShopList() 会下发 npc_id = targetId 的普通店铺列表
DispatchPlayerShopSaleOutList() 会下发售出店铺列表,并额外设置 unknow = 1
- 从当前
Game.exe 可确认 GCPlayerShopAcquireShopList 的长度公式是 13 + shop_num * 256,说明每个 shop_info 条目在协议层是固定 256 字节块。
服务端落点
- 协议定义:
/home/ubuntu/Game2/services/game/packet.lua
- 请求入口:
/home/ubuntu/Game2/services/msgagent.lua
- 场景处理:
/home/ubuntu/Game2/services/scene/scenecore.lua
- 列表组装:
/home/ubuntu/Game2/lualib/playershopmanager.lua
- NPC 脚本复用:
/home/ubuntu/Game2/lualib/script_base.lua
关键代码
当前 Game.exe 请求包结构
__int64 sub_1400BFC70()
{
return 1;
}
当前 Lua 请求入口
function request:CGPlayerShopAcquireShopList()
skynet.call(my_scene, "lua", "char_player_shop_acquire_shop_list", my_obj_id, self)
end
当前 Lua 场景处理
function scenecore:char_player_shop_acquire_shop_list(who, psa)
local obj_me = self.objs[who]
send_player_shop_acquire_shop_list(self, obj_me)
end
当前 Lua 回包组装
local function send_player_shop_acquire_shop_list(scene, human)
local msg = packet_def.GCPlayerShopAcquireShopList.new()
msg.npc_id = define.INVAILD_ID
msg.com_factor = playershopmanager:get_com_factor()
msg.shop_infos = playershopmanager:get_shop_infos({ human = human })
scene:send2client(human, msg)
end
当前 Lua 店铺信息来源
function playershopmanager:get_shop_infos(opts)
opts = opts or {}
local human = opts.human
if human then
...
human:update_favorite_shop_guids(valid_shop_guids)
end
local shop_infos = {}
for i, shop in ipairs(self.player_shops) do
if is_listed_player_shop(shop)
and (not opts.only_on_sale or shop:get_status() == shop.STATUS.STATUS_PLAYER_SHOP_ON_SALE) then
table.insert(shop_infos, build_shop_info(shop, i, opts.sale_out_list, human))
end
end
return shop_infos
end
结论
CGPlayerShopAcquireShopList 的封包 ID 是 27,当前 Game.exe 中固定长度为 0,属于空包请求。
- 当前 Lua 服务端不会从请求体读取任何参数,而是直接进入玩家商店列表回包流程。
- 这条请求的主回包是
GCPlayerShopAcquireShopList(578),当前请求链路下会返回全量已挂牌店铺列表、当前商会系数和收藏状态。
- 当前
GCPlayerShopAcquireShopList 在协议层是动态长度包,长度公式为 13 + shop_num * 256。
- 因此这条包应归类为玩家商店列表刷新请求,而不是携带筛选条件的业务参数包。
|