包信息
| 项目 |
内容 |
| PacketID |
584 |
| 包名 |
GCCooldownUpdate |
| 方向 |
服务端 -> 客户端 |
| 长度 |
10 + 12 * m_nNumCooldown |
| 主要用途 |
向客户端同步人物或珍兽的冷却池剩余时间 |
当前 Game.exe 已确认以下协议事实:
GetPacketID:0x1405ED0A0,返回 584
GetPacketSize:0x1405EF2C0,返回 10 + 12 * m_nNumCooldown
Read:0x140609F80
Write:0x14060A080
Execute:0x140609F70 -> 0x14033E790
包体结构
| 偏移 |
长度 |
字段 |
类型 |
含义 |
| 0 |
4 |
m_uHighSection |
uint32 |
冷却主体 GUID 高位段。人物冷却时为 0 |
| 4 |
4 |
m_uLowSection |
uint32 |
冷却主体 GUID 低位段。人物冷却时为 0 |
| 8 |
2 |
m_nNumCooldown |
uint16 |
冷却项数量。当前 Game.exe 只接受 1..40 |
| 10 + i*12 |
4 |
m_aCooldowns[i].m_nID |
int32 |
冷却池 ID |
| 14 + i*12 |
4 |
m_aCooldowns[i].m_nCooldown |
uint32 |
当前剩余冷却时长 |
| 18 + i*12 |
4 |
m_aCooldowns[i].m_nCooldownElapsed |
uint32 |
已经过的冷却时长 |
其中 i = 0 .. m_nNumCooldown - 1。
当前实际行为
GCCooldownUpdate 是服务端主动下发包,当前项目没有专门的上行请求包。
- 当前 Lua 只实现了
bos,没有实现 bis,说明这条包在现行链路里只负责下发,不负责回读。
- 当
m_uHighSection = 0 且 m_uLowSection = 0 时,客户端按“人物冷却”路径处理整组冷却项。
- 当这两个字段任意一个非
0 时,客户端会走“带 GUID 的冷却主体”路径。当前 Lua 实际只在珍兽冷却时写入宠物 GUID,因此这条分支目前对应的是珍兽冷却同步。
- 当前人物对象会在以下场景发送这条包:
set_cool_down() 设置单个冷却
update_cool_down_time() 减少单个冷却
send_cool_down_time() 批量同步当前冷却
challenge_refresh_skill_cool_down() 清空挑战技能冷却
challenge_restore_skill_cool_down() 恢复挑战前技能冷却
- 当前珍兽对象会在
pet:set_cool_down() 中给拥有者发送这条包,并把宠物 GUID 写入 m_uHighSection / m_uLowSection。
- 当前 Lua 发送时,所有冷却项都固定写
m_nCooldownElapsed = 0,也就是只同步“剩余时间”,不回填已经流逝的时长。
- 当前
Game.exe 最多按 40 项处理这条包;旧 Server 同类结构是 32 项,但本文以当前 Game.exe 的 40 项为准。
服务端落点
/home/ubuntu/Game2/services/game/packet.lua
- 定义
GCCooldownUpdate 的下行结构
/home/ubuntu/Game2/services/scene/obj/human.lua
set_cool_down()
update_cool_down_time()
send_cool_down_time()
challenge_refresh_skill_cool_down()
challenge_restore_skill_cool_down()
/home/ubuntu/Game2/services/scene/obj/pet.lua
set_cool_down() 给主人同步珍兽冷却
/home/ubuntu/Game2/lualib/define.lua
OTHER_SKILL_OR_STATUS_COOLDOWN = 10000
关键代码
packet.GCCooldownUpdate = {
xy_id = packet.XYID_GC_COLL_DOWN_UPDATE,
ctor = function(self)
self.m_uHighSection = 0
self.m_uLowSection = 0
self.m_nNumCooldown = 0
self.m_aCooldowns = {}
end,
bos = function(self)
local stream = bostream.new()
stream:writeuint(self.m_uHighSection)
stream:writeuint(self.m_uLowSection)
stream:writeushort(self.m_nNumCooldown)
for i = 1, self.m_nNumCooldown do
stream:writeint(self.m_aCooldowns[i].m_nID)
stream:writeuint(self.m_aCooldowns[i].m_nCooldown)
stream:writeuint(self.m_aCooldowns[i].m_nCooldownElapsed)
end
return stream:get()
end
}
function human:set_cool_down(id, cool_down_time)
local index = tonumber(id)
if index < define.OTHER_SKILL_OR_STATUS_COOLDOWN then
local msg = packet_def.GCCooldownUpdate.new()
msg.m_nNumCooldown = 1
msg.m_aCooldowns = {}
msg.m_aCooldowns[1] = {
m_nID = index,
m_nCooldown = cool_down_time,
m_nCooldownElapsed = 0
}
self:get_scene():send2client(self, msg)
end
end
function pet:set_cool_down(id, cool_down_time)
local owner = self:get_owner()
if owner then
local pet_guid = self:get_guid()
local msg = packet_def.GCCooldownUpdate.new()
msg.m_nNumCooldown = 1
msg.m_uHighSection = pet_guid.m_uHighSection
msg.m_uLowSection = pet_guid.m_uLowSection
msg.m_aCooldowns[1] = {
m_nID = tonumber(id),
m_nCooldown = cool_down_time,
m_nCooldownElapsed = 0
}
self:get_scene():send2client(owner, msg)
end
end
GetPacketSize() = 10 + 12 * m_nNumCooldown;
if (m_uHighSection == 0 && m_uLowSection == 0) {
apply_human_cooldowns(m_aCooldowns, m_nNumCooldown);
} else {
apply_guid_cooldowns(m_aCooldowns, m_nNumCooldown, guid64);
}
结论
GCCooldownUpdate 是当前版本的冷却时间同步回包,核心结构就是“冷却主体 GUID 分段 + 冷却项数量 + 冷却项数组”。
这条包当前已经可以按明确语义理解:m_uHighSection / m_uLowSection 用来区分冷却属于人物还是某个 GUID 主体,m_aCooldowns 里每项表示一个冷却池的剩余时间。现行 Lua 主链中,人物冷却用全 0 section,珍兽冷却用宠物 GUID section,且默认只同步剩余时间,不同步已流逝时间。
|