CGWGuildLeagueQuit 是当前版本已接入的一条同盟系统请求包,用于让当前帮会退出所在同盟。当前 Game.exe 可确认它的客户端完整包体固定为 4 字节;当前 Lua 主链也已接入,但实际处理逻辑并不读取这 4 字节,而是直接按发包者当前帮会与角色身份执行退出同盟流程。
包信息
| 项目 |
内容 |
| 封包 ID |
48 |
| 包名 |
CGWGuildLeagueQuit |
| 方向 |
Client -> Server |
| 相关回包 |
无专用回包 |
| 作用 |
请求当前帮会退出所在同盟 |
包体结构
当前 Game.exe 与当前 Lua 都能确认,这条包固定只有 1 个 int32 字段。
| 偏移 |
长度 |
字段 |
类型 |
含义 |
0x00 |
0x04 |
legacy_guid |
int32 |
旧链路遗留的 GUID 槽位;当前 Lua 会读入但不消费 |
当前客户端完整包长固定为:
4
当前实际行为
- 当前
Game.exe 中,CGWGuildLeagueQuit::GetPacketID() 返回 48,GetPacketSize() 返回 4。
- 当前
Game.exe 的 Read() / Write() 都只围绕对象偏移 +24 的 4 字节字段进行读写。
- 当前
Game.exe 的 Execute() 是通用返回桩,直接返回 2。
- 当前 Lua 协议定义
packet.CGWGuildLeagueQuit.bis() 只读取一个 int32 到 unknow_1。
- 当前请求入口链路已经接入:
request:CGWGuildLeagueQuit()
ma_guild:CGWGuildLeagueQuit(lq)
guildmanager_core:guild_league_quit(guid, guild_id, lq)
- 当前服务端真正使用的是会话侧的:
guid = self:get_guid()
guild_id = self:get_guild_id()
- 当前
guildmanager_core:guild_league_quit() 里并没有读取 lq 的任何字段,说明这 4 字节在现行 Lua 主链里是未消费的保留参数。
- 当前退出逻辑的实际约束是:
- 校验通过后,服务端会:
- 把当前帮会从同盟列表移除
- 把当前帮会的
confederate_id/confederate_name 清空
- 通过内部
multicast(..., "update_confederate_id", ...) 刷新本帮在线成员的同盟属性
- 如果退出者正好是盟主,则把盟主转给同盟列表中的第一个剩余帮会帮主;如果已无剩余帮会,则删除该同盟记录
- 当前主链没有构造
WG* 或 GC* 的专用结果包,因此应记为“无专用回包”。
- 当前脚本事件
/home/ubuntu/Game2/services/scripts/event/guildleague/guildleaguebase.lua 也能直接调用 .Guildmanager:guild_league_quit(guid, guild_id),进一步说明这条封包只是同一服务端逻辑的一种网络入口。
服务端落点
- 协议定义:
/home/ubuntu/Game2/services/game/packet.lua
- 请求入口:
/home/ubuntu/Game2/services/msgagent.lua
- MsgAgent 分发:
/home/ubuntu/Game2/msgagent_module/ma_guild.lua
- 实际退出同盟逻辑:
/home/ubuntu/Game2/services/guild/guildmanager_core.lua
- 复用同一逻辑的脚本路径:
/home/ubuntu/Game2/services/scripts/event/guildleague/guildleaguebase.lua
关键代码
当前 Lua 协议定义
packet.CGWGuildLeagueQuit = {
xy_id = packet.XYID_CGW_GUILD_LEAGUE_QUIT,
new = function()
local o = {}
setmetatable(o, { __index = packet.CGWGuildLeagueQuit })
o:ctor()
return o
end,
ctor = function(self)
end,
bis = function(self, buffer)
local stream = bistream.new()
stream:attach(buffer)
self.unknow_1 = stream:readint()
end
}
当前 Lua 请求链
function request:CGWGuildLeagueQuit()
ma_func:CGWGuildLeagueQuit(self)
end
function ma_guild:CGWGuildLeagueQuit(lq)
local guild_id = self:get_guild_id()
skynet.call(".Guildmanager", "lua", "guild_league_quit", self:get_guid(), guild_id, lq)
end
当前 Lua 实际处理逻辑
function guildmanager_core:guild_league_quit(guid, guild_id, lq)
local my_guild = self:get_guild_by_id(guild_id)
local chief = self:get_my_guild_info_in_guild(guid, guild_id)
assert(chief.position == define.GUILD_POSITION_CHIEFTAIN)
assert(my_guild.confederate_id ~= define.INVAILD_ID)
local league_id = my_guild.confederate_id
local league = self:get_guild_league_by_id(league_id)
local guild = self:get_guild_by_id(guild_id)
self:remove_guild_in_league_by_id(guild, league)
self:update_guild_confederate_id_and_name({id = define.INVAILD_ID, name = ""}, guild)
if league.chief_guid == guid then
local guilds = league.guilds
if #guilds > 0 then
guild = self:get_guild_by_id(guilds[1].id)
chief = self:find_cheif_in_guild(guild)
league.chief_guid = chief.guid
league.chief_name = chief.name
self:db_update_league_info(league)
else
self:db_remove_league(league)
end
self:reload_leagues()
end
end
当前 Game.exe 读写结论
GetPacketID() = 48;
GetPacketSize() = 4;
Read(stream) {
read_bytes(legacy_guid, 4);
}
Write(stream) {
write_bytes(legacy_guid, 4);
}
Execute() {
return 2;
}
旧 Server 仅作命名线索
Read(iStream) {
SocketInputStream::Read(iStream, &this->m_GUID, 4u);
}
Write(oStream) {
SocketOutputStream::Write(oStream, &this->m_GUID, 4u);
}
旧 Server 同名类把这 4 字节命名为 m_GUID,说明它历史上更像“玩家 GUID 槽位”。但旧 Server 的包 ID 是 344,且旧 Handler 会在转发前直接把该字段覆写成当前人物 GUID;当前版本 Lua 又完全不消费这 4 字节,所以本文只把它记为 legacy_guid,并以当前 Game.exe + Lua 链路为准。
结论
CGWGuildLeagueQuit 的当前包 ID 是 48,固定包长 4 字节。
- 当前客户端完整包体只有一个
int32 字段;结合旧 Server 命名,可把它视为遗留 GUID 槽位。
- 当前 Lua 主链已经接入这条请求,但实际退出同盟逻辑完全不读取该字段。
- 当前服务端真正依赖的是发包者自己的
guid 和当前 guild_id,并要求发包者必须是帮主且帮会已加入同盟。
- 当前处理完成后没有专用结果回包,主要是直接改同盟数据并刷新在线成员的同盟属性。