找回密码
 registerss
搜索
查看: 16|回复: 0

洱海月 v0-07-0300 封包解析:ID 508 CGCGWPacket(帮会城战与同盟复合请求)

[复制链接]
  • 打卡等级:本地老炮
  • 打卡总天数:603
  • 打卡月天数:1
  • 打卡总奖励:600
  • 最近打卡:2026-10-03 06:32:28
Waylee 发表于 2026-4-14 12:55 | 显示全部楼层 |阅读模式 | Google Chrome | Windows 10

马上注册,查看网站隐藏内容!!

您需要 登录 才可以下载或查看,没有账号?registerss

×

CGCGWPacket 是当前版本里承载帮会城市、帮会宣战、同盟踢人等功能的复合请求包。它不是固定业务单包,而是由 type(uint8) + payload_length(uint32) + payload 组成的总包头,再按 type 分发到不同子结构。

包信息

项目 内容
封包 ID 508
包名 CGCGWPacket
方向 CG 客户端 -> 游戏服
包长规则 动态包长,5 + payload_length
当前 Lua 状态 现役协议;msgagent 已接入多个 type 分支
专用回包 无专用回包;按分支可能返回 GCWGCPacket 或提示消息
作用 承载帮会城市申请/查询/操作、同盟踢人、帮会宣战等复合请求

当前 Game.exe 可确认:

CGCGWPacket::GetPacketID()   = 508;
CGCGWPacket::GetPacketSize() = payload_length + 5;
CGCGWPacket::Read()          = read(type, 1) + read(payload_length, 4) + read(payload, payload_length);
CGCGWPacket::Write()         = write(type, 1) + write(payload_length, 4) + write(payload, payload_length);
CGCGWPacket::Execute()       = 0;

包体结构

总包头固定为 1 + 4 字节,后面紧跟 payload_length 指定的子载荷。以下偏移都以 payload 起始位置为基准。

总包头

偏移 长度 字段 类型 含义
0x00 0x01 type uint8 复合请求类型
0x01 0x04 payload_length uint32 子载荷长度
0x05 n payload bytes[n] 按 type 解释的子结构

type = 1 城市申请,payload_length = 40

偏移 长度 字段 类型 含义
0x00 0x04 city_enter_group uint32 城市入驻目标组
0x04 0x04 guid int32 客户端附带的角色标识,当前 Lua 不消费
0x08 0x04 reserved_1 int32 当前客户端填 0,Lua 不消费
0x0C 0x1A name char[26] 城市名
0x26 0x02 padding_1 bytes[2] 客户端尾部补零,当前 Lua 未读取

type = 2 城市信息查询,payload_length = 4

偏移 长度 字段 类型 含义
0x00 0x02 scene_id int16 查询场景或兼容占位值
0x02 0x01 m_Type uint8 查询类别
0x03 0x01 m_BldIdx uint8 建筑索引

当前 Lua 已接入的查询类别:

  • m_Type = 1:城市基础/管理信息
  • m_Type = 2:研究基础信息
  • m_Type = 3:研究详情
  • m_Type = 4:城市商店信息
  • m_Type = 5:商线列表

当前客户端部分基础查询仍会发 m_Type = 0,Lua 在 guild_city_ask_info() 中会把 scene_id > 0 且 m_BldIdx = 0 的分支归一化成 m_Type = 1。

type = 3 且 payload_length = 34,野外帮战申请

偏移 长度 字段 类型 含义
0x00 0x20 reserved_1 bytes[32] 当前 Lua 与服务端主逻辑均未消费的前置数据
0x20 0x02 tar_guild_id int16 目标帮会 ID

type = 3 且 payload_length = 52,城市操作

偏移 长度 字段 类型 含义
0x00 0x01 m_Opt uint8 操作类型
0x01 0x01 m_BuildIdx uint8 建筑索引
0x02 0x02 m_Reserved uint16 保留字段
0x04 0x04 m_ItemIdx uint32 配方/商品/条目索引
0x08 0x04 m_PriceMoney uint32 金币价格字段
0x0C 0x04 m_Money uint32 金币字段
0x10 0x04 m_TicketValue uint32 票券值字段
0x14 0x04 m_uSourceSceneID uint32 来源场景 ID
0x18 0x04 m_uProductValue uint32 产出值字段
0x1C 0x04 m_Serial uint32 序号字段
0x20 0x02 m_TargetGuildID int16 目标帮会 ID
0x22 0x02 m_TargetReserved int16 目标保留字段
0x24 0x04 m_PriceTicketValue uint32 票券价格字段
0x28 0x08 m_ItemGUID bytes[8] 物品 GUID 原始字节
0x30 0x04 m_CurrencyType int32 货币类型

当前 Lua 已接入的 m_Opt:

  • 1:建筑升级
  • 2:取消当前建造
  • 4:新建建筑
  • 5:建筑降级
  • 6:拆除建筑
  • 7:研究
  • 8:取消研究
  • 10:城市商店购买
  • 11:城市商店交货
  • 12:创建商线
  • 13:取消商线

type = 7 同盟踢人,payload_length = 4

偏移 长度 字段 类型 含义
0x00 0x02 reserved_1 int16 客户端 GuildLeague::FireGuild 第一参数,当前 Lua 未消费
0x02 0x02 kick_guild_id int16 被踢出的帮会 ID

type = 11 帮会宣战,payload_length = 8

偏移 长度 字段 类型 含义
0x00 0x04 initiate_or_accept uint32 当前 Lua 使用 0=发起宣战、1=接受宣战
0x04 0x02 my_guild_id int16 当前帮会 ID
0x06 0x02 tar_guild_id int16 目标帮会 ID

type = 12 帮会城市整数参数请求,payload_length = 2

偏移 长度 字段 类型 含义
0x00 0x02 guild_id int16 当前客户端直接写入的帮会 ID;Lua 分支未读取,转而重新从场景取值

当前 Game.exe 里还能看到未被现役 Lua 主链接入的旧分支,例如:

  • type = 4,payload_length = 28
  • type = 6,payload_length = 112

当前实际行为

  • type = 1:提交城市申请。msgagent 会先检查角色是否满足占城条件,再补写当前会话的 guild_id,最后调用 .Guildmanager:city_apply();成功后扣除占城消耗。
  • type = 2:查询帮会城市信息。请求会转给 .Dynamicscenemanager:guild_city_ask_info(),结果再拆成一个或多个 GCWGCPacket 回给客户端。
  • type = 3 且为 city_opt:城市操作主分支。m_Opt = 11 走场景服 agent_command_guild_city_shop_sell(),其余操作走 .Dynamicscenemanager:guild_city_opt()。
  • type = 3 且为 guild_wild_war:野外帮战宣战。服务端先检查本帮扩张值是否达到 100,再调用 .Guildmanager:guild_wild_war()。
  • type = 7:同盟踢人。当前 Game.exe 真实子载荷是 int16 + int16,但现役 Lua 分支仍按原始字节处理,只取 self.data[3] 作为 kick_guild_id 传给 ma_guild:guild_league_kick()。
  • type = 11:帮会宣战/应战。请求直接转给 .Guildmanager:guild_war()。
  • type = 12:请求帮会城市整数参数。当前 Lua 会重新获取当前帮会 ID,调用 .Guildmanager:get_guild_int_nums(),成功后回发 GCWGCPacket(type=12)。
  • 其他 type:当前 Lua 只会把原始字节读入 self.data,msgagent 没有现役处理分支。

服务端落点

  • 协议定义:/home/ubuntu/Game2/services/game/packet.lua
  • 请求入口:/home/ubuntu/Game2/services/msgagent.lua
  • 帮会模块:/home/ubuntu/Game2/msgagent_module/ma_guild.lua
  • 城市查询/操作:/home/ubuntu/Game2/lualib/dynamicscenemanager_core.lua
  • 帮会/同盟/宣战处理:/home/ubuntu/Game2/services/guild/guildmanager_core.lua
  • 场景服特殊处理:/home/ubuntu/Game2/services/scene/scenecore.lua

关键代码

当前 Game.exe 总包读写

__int64 __fastcall CGCGWPacket_Read(__int64 packet, __int64 stream)
{
    read(stream, packet + 24, 1);
    read(stream, packet + 28, 4);
    read(stream, packet + 32, *(unsigned int *)(packet + 28));
    return 1;
}

__int64 __fastcall CGCGWPacket_Write(__int64 packet, __int64 stream)
{
    write(stream, packet + 24, 1);
    write(stream, packet + 28, 4);
    write(stream, packet + 32, *(unsigned int *)(packet + 28));
    return 1;
}

当前 Lua 总包解析

packet.CGCGWPacket = {
    xy_id = packet.XYID_CG_CGW_PACKET,
    bis = function(self, buffer)
        local stream = bistream.new()
        stream:attach(buffer)
        self.type = stream:readuchar()
        local len = stream:readuint()
        if self.type == 1 then
            self.city_apply = packet.CGWPacket_CityApply.new()
            self.city_apply:bis(stream)
        elseif self.type == 2 then
            self.city_ask_info = packet.CGWPacket_CityAskInfo.new()
            self.city_ask_info:bis(stream)
        elseif self.type == 3 then
            if len == 0x22 then
                self.guild_wild_war = packet.CGWPacket_GuildWildWar.new()
                self.guild_wild_war:bis(stream)
            else
                self.city_opt = packet.CGWPacket_CityOpt.new()
                self.city_opt:bis(stream)
            end
        elseif self.type == 11 then
            self.guild_war = packet.CGWPacket_GuildWar.new()
            self.guild_war:bis(stream)
        else
            self.data = {}
            for i = 1, len do
                self.data[i] = stream:readuchar()
            end
        end
    end
}

当前 Lua 请求分发

function request:CGCGWPacket()
    local my_guid = ma_func:get_guid()
    if self.type == 1 then
        ...
        result = skynet.call(".Guildmanager", "lua", "city_apply", my_guid, city_apply)
    elseif self.type == 2 then
        ...
        local ok, result = pcall(skynet.call, ".Dynamicscenemanager", "lua", "guild_city_ask_info", my_guid, guild_id, self.city_ask_info)
        ...
    elseif self.type == 3 then
        if self.city_opt then
            ...
            local ok, result = pcall(skynet.call, ".Dynamicscenemanager", "lua", "guild_city_opt", my_guid, guild_id, self.city_opt)
            ...
        else
            ...
            skynet.call(".Guildmanager", "lua", "guild_wild_war", my_guid, self.guild_wild_war)
        end
    elseif self.type == 7 then
        local kick_guild_id = self.data[3]
        ma_func:guild_league_kick(kick_guild_id)
    elseif self.type == 11 then
        skynet.call(".Guildmanager", "lua", "guild_war", my_guid, self.guild_war)
    elseif self.type == 12 then
        ...
        local msg = packet_def.GCWGCPacket.new()
        msg.type = 12
        msg.wgc_int_nums = params
        Net:send(msg)
    end
end

当前客户端可确认的 type = 7 与 type = 12 发包

// GuildLeague::FireGuild(parameter1, parameter2)
word payload[0] = parameter1;
word payload[1] = parameter2;
type = 7;
payload_length = 4;

// ConfraternityCount
word payload[0] = current_guild_id;
type = 12;
payload_length = 2;

结论

  1. CGCGWPacket(508) 是一个复合请求总包,真正的包长规则是 5 + payload_length,不是固定长度。
  2. 当前 Lua 主链实际接入的是 type = 1/2/3/7/11/12 六类业务,其中 type = 3 又按 payload_length 拆成 34 字节的野外帮战申请和 52 字节的城市操作。
  3. type = 7 与 type = 12 已能从当前 Game.exe 明确确认出真实子载荷,分别是 int16 + int16 与单个 int16;其中 type = 7 的现役 Lua 仍只取到了第二个 int16 的低字节。
  4. 当前城市查询与城市操作分支不会回单一专用结果包,而是按返回内容拆成多个 GCWGCPacket 子包回给客户端。
  5. Game.exe 里还能看到 type = 4、type = 6 等旧分支,但当前 Lua msgagent 没有现役处理逻辑,不应当作当前服务端稳定功能使用。
您需要登录后才可以回帖 登录 | registerss

本版积分规则

QQ|手机版|雪舞知识库 ( 浙ICP备15015590号-1 | 萌ICP备20232229号|浙公网安备33048102000118号 )|天天打卡

GMT+8, 2026-10-4 11:26 , Processed in 0.062060 second(s), 26 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表