CGUnEquip 是旧版客户端里用于请求卸下角色装备的固定长度封包。
包信息
| 项目 |
内容 |
| 封包 ID |
267 |
| 包名 |
CGUnEquip |
| 对应回包 |
GCUnEquipResult |
| 回包 ID |
165 |
| 作用 |
请求卸下指定装备位上的装备 |
包体结构
当前 Game.exe 的 GetPacketSize() 明确返回 4,Read/Write 也都是按 4 个连续字节处理。
| 偏移 |
长度 |
字段 |
类型 |
含义 |
0x00 |
0x01 |
equipPoint |
uint8 |
装备位,当前 Lua 实际只使用这个字段 |
0x01 |
0x01 |
bagIndex |
uint8 |
目标背包格位,常见值为 255,表示未指定固定格位 |
0x02 |
0x01 |
operationType |
uint8 |
卸装操作类型,普通卸装常见为 0,时装卸下到衣柜时可见 5 |
0x03 |
0x01 |
targetIndex |
uint8 |
目标索引,普通卸装常见为 0,时装模式下可携带衣柜槽位 |
总长度:
4 字节
当前实际行为 / 模式说明
- 当前 Lua 服务端入口是
request:CGUnEquip(),随后转到 scenecore:char_un_equip()。
- 当前 Lua 实际只读取
equipPoint,后 3 个字节没有参与普通卸装逻辑判定。
- 普通装备卸下时,目标容器是道具背包;若背包没有空位,当前 Lua 直接提示“背包空间不足。”,不会继续走成功回包。
HEQUIP_PROP_BAG 和 HEQUIP_MATERIAL_BOX 在当前 Lua 里分别对应“行囊”和“格箱”,卸下前会额外检查容量是否足够。
HEQUIP_FASHION 走时装分支,目标容器不是普通背包,而是易容阁衣柜;当前 Lua 以角色身上保存的 fashion_depot_index 为主要落点依据。
SHENBING 处于变身状态时,当前 Lua 会直接拒绝卸下并提示“请取消神兵状态再更卸下装备。”
按当前 Game.exe 构包点来看,这条包至少存在两种常见形态:
- 普通装备卸下:常见为
equipPoint, 255, 0, 0
- 时装卸下:可见为
16, 255, 5, fashion_depot_index
这说明 equipPoint 是稳定主字段,后 3 个字节更像附加控制参数。当前 Lua 服务端并没有依赖这些附加字节来决定普通卸装流程。
服务端落点
这条包在当前项目里的关键位置如下:
- 协议定义:
/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
关键代码
当前 Lua 协议定义
packet.CGUnEquip = {
xy_id = packet.XYID_CG_UN_EQUIP,
bis = function(self, buffer)
local stream = bistream.new()
stream:attach(buffer)
self.equipPoint = stream:readuchar()
self.bagIndex = stream:readuchar()
self.operationType = stream:readuchar()
self.targetIndex = stream:readuchar()
end
}
当前 Lua 请求入口
function request:CGUnEquip()
skynet.call(my_scene, "lua", "char_un_equip", my_obj_id, self)
end
当前 Lua 场景服处理
function scenecore:char_un_equip(obj_id, unequip)
local ret = packet_def.GCUnEquipResult.new()
local obj_me = self.objs[obj_id]
local equipPoint = unequip.equipPoint
local equip_container = obj_me:get_equip_container()
local equip = equip_container:get_item(equipPoint)
ret.equipPoint = equipPoint
...
end
当前 Game.exe 的读写结论
GetPacketID() = 267;
GetPacketSize() = 4;
Read(stream) {
read_u8(equipPoint);
read_u8(bagIndex);
read_u8(operationType);
read_u8(targetIndex);
}
结果值
当前 Game.exe 中,GCUnEquipResult 的客户端处理函数会按 result 分支处理:
| result |
含义 |
说明 |
1 |
卸下成功 |
客户端刷新装备位和目标格子 |
2 |
背包已满 |
客户端提示“背包已满!” |
3 |
目标位置已有物品 |
客户端提示“该位置已经有物品!” |
4 |
行囊无法卸下 |
客户端提示“你的行囊中存在物品,无法卸下” |
5 |
格箱无法卸下 |
客户端提示“你的格箱中存在物品,无法卸下” |
6 |
背包已满无法卸下 |
客户端提示“你的背包已满,无法卸下” |
7 |
背包已满无法卸下 |
客户端同样走“你的背包已满,无法卸下” |
不过从当前 Lua 实现来看,服务端主要稳定使用的是成功结果 1;很多失败场景已经直接改成服务端即时提示,而不是严格回落到旧客户端的全部 result 分支。
结论
CGUnEquip 这条包本质上就是“请求卸下指定装备位装备”的定长请求包。
当前项目里真正要记住的只有五点:
- 这条包的 ID 是
267。
- 包体长度固定是
4 字节。
- 当前 Lua 实际决定卸装逻辑的关键字段是第
1 字节 equipPoint。
- 普通装备卸下走背包,时装卸下走易容阁衣柜。
- 当前
Game.exe 证明后 3 个字节确实存在控制含义,但在当前 Lua 服务端里并不是普通卸装的核心判定依据。
|