CGAuctionSearch 是客户端向元宝交易市场提交搜索条件的请求包,用于分页查询寄售中的珍兽、道具或装备。
包信息
| 项目 |
内容 |
| 封包 ID |
054 |
| 包名 |
CGAuctionSearch |
| 方向 |
客户端 -> 游戏服 |
| 长度 |
变长 |
| 对应回包 |
GCAuctionSearch |
| 回包 ID |
704 |
| 作用 |
按类型、分类、排序、关键字和页码查询元宝市场列表 |
包体结构
当前 Game.exe 的 GetPacketSize() 返回 name_len + 12,Lua 协议定义也按同样顺序解析。
| 偏移 |
长度 |
字段 |
类型 |
含义 |
0x00 |
0x01 |
type |
int8 |
搜索大类;当前服务端直接拿它匹配 ybmarket.type |
0x01 |
0x04 |
sub_type |
uint32 |
分类筛选编码,当前会拆成三级子类条件 |
0x05 |
0x01 |
order |
uint8 |
排序方式 |
0x06 |
0x04 |
name_len |
uint32 |
关键字字节长度 |
0x0A |
name_len |
name |
char[name_len] |
搜索关键字,当前 Lua 按 GBK 转 UTF-8 |
0x0A + name_len |
0x02 |
page |
int16 |
页码,当前每页固定 10 条 |
总长度:
12 + name_len 字节
当前实际行为
Game.exe 中 sub_1405EC2D0() 直接返回 54,sub_140202700() 返回 name_len + 12,可确认当前客户端类的包 ID 与变长公式。
Game.exe 中 sub_1405C76A0() 依次读取 1 + 4 + 1 + 4 + name_len + 2 字节,与 Lua 的 type / sub_type / order / name / page 完全一致。
- 当前 Lua 入口
request:CGAuctionSearch() 直接把整包转发给 .Ybexchange:search(self),然后立即构造 GCAuctionSearch 回包。
- 当前搜索默认条件是
{ type = request.type, status = "on_sale" }。
- 当
request.name ~= "" 时,搜索条件会被改写成 { item_name = { $regex = request.name }, status = "on_sale" },原本的 type 过滤会被覆盖掉。
- 当前
sub_type 会被拆成三段:first = sub_type // 10000、second = (sub_type % 10000) // 100、last = sub_type % 100;每段只要不是 0 或 1,就会附加到 query_tbl["sub_type.1/2/3"]。
- 当前排序值只有 4 种显式分支:
1:价格从低到高
2:价格从高到低
3:名称从小到大
4:名称从大到小
- 当前页码直接参与
skip = (request.page - 1) * 10 计算,没有在服务端做范围钳制。
- 当前回包
GCAuctionSearch 会写回 msg.type = self.type、msg.order = self.order、msg.cur_page_num = self.page,但 msg.sub_type 被硬编码成 117,并不会回传请求里的真实 sub_type。
- 当前
GCAuctionSearch.bos() 里,type == 1 走珍兽详情序列化,其他类型统一走 ItemInfo 序列化。因此从当前服务端逻辑推断,type = 1 对应珍兽,非 1 对应物品/装备。
服务端落点
- 协议定义:
/home/ubuntu/Game2/services/game/packet.lua
- 请求入口:
/home/ubuntu/Game2/services/msgagent.lua
- 交易市场服务入口:
/home/ubuntu/Game2/services/ybexchange/ybexchange.lua
- 交易市场搜索逻辑:
/home/ubuntu/Game2/services/ybexchange/ybexchange_core.lua
关键代码
客户端 Game.exe 关键方法:
__int64 sub_1405EC2D0()
{
return 54;
}
__int64 __fastcall sub_140202700(__int64 a1)
{
return *(unsigned int *)(a1 + 36) + 12LL;
}
__int64 __fastcall sub_1405C76A0(__int64 a1, __int64 a2)
{
sub_1403F9B00(a2, (char *)(a1 + 24), 1u);
sub_1403F9B00(a2, (char *)(a1 + 28), 4u);
sub_1403F9B00(a2, (char *)(a1 + 32), 1u);
sub_1403F9B00(a2, (char *)(a1 + 36), 4u);
sub_1403F9B00(a2, (char *)(a1 + 40), *(_DWORD *)(a1 + 36));
sub_1403F9B00(a2, (char *)(a1 + 104), 2u);
return 1;
}
当前 Lua 协议与请求入口:
packet.CGAuctionSearch = {
xy_id = packet.XYID_CG_AUCTION_SEARCH,
bis = function(self, buffer)
local stream = bistream.new()
stream:attach(buffer)
self.type = stream:readchar()
self.sub_type = stream:readuint()
self.order = stream:readuchar()
local len = stream:readuint()
self.name = stream:read(len)
self.name = gbk.toutf8(self.name)
self.page = stream:readshort()
end
}
function request:CGAuctionSearch()
local result = skynet.call(".Ybexchange", "lua", "search", self)
local msg = packet_def.GCAuctionSearch.new()
msg.type = self.type
msg.sub_type = 117
msg.order = self.order
msg.cur_page_num = self.page
msg.page_total = result.page_total
msg.merchandise_list = result.merchandise_list
Net:send(msg)
end
当前交易市场搜索逻辑:
function ybexchange_core:search(request)
local query_tbl = {type = request.type, status = "on_sale"}
if request.name ~= "" then
query_tbl = {["item_name"] = {["$regex"] = request.name}, status = "on_sale"}
end
self:trans_search_sub_type(request, query_tbl)
if request.order == 1 then
sorter = {["price"] = 1}
elseif request.order == 2 then
sorter = {["price"] = -1}
elseif request.order == 3 then
sorter = {["item_name"] = 1}
elseif request.order == 4 then
sorter = {["item_name"] = -1}
end
local skip = (request.page - 1) * 10
...
end
结论
CGAuctionSearch 是当前元宝市场的变长搜索请求包,结构稳定为 type + sub_type + order + name_len + name + page,总长公式为 12 + name_len。
当前版本最需要记住的不是字段名本身,而是三条实际行为:
name 非空时会覆盖默认的 type 条件,搜索会退化成“按名称 + 状态 + 子类”的组合查询。
sub_type 在服务端被拆成三级分类条件,而回包阶段却被硬编码成 117,不会原样带回。
page 和 order 当前都直接信任客户端输入,服务端只按固定每页 10 条做分页计算。