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

洱海月 v0-07-0300 封包解析:ID 644 GCTeamAskApply(队长入队申请提示)

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

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

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

×

GCTeamAskApply 是当前队伍申请链里发给目标队长的提示包。申请者执行 CGTeamApply 后,世界服不会直接让其入队,而是先把申请者的基础信息和角色预览发给队长,由队长客户端弹出审批提示,再通过 CGTeamRetApply 决定是否同意。

当前 Temp_Release_v0-07-0300 里,这条协议既保留在 Game.exe,也确实被 /home/ubuntu/Game2/services/world/worldcore.lua 发送。它的主体结构是“双 GUID + 双名字 + 单人预览信息 + 尾部 token”,其中单人预览块与 GCTeamAskInvite 使用的是同一套外观预览序列化思路。

包信息

项目 内容
封包 ID 644
包名 GCTeamAskApply
方向 GC 服务端 -> 队长客户端
前置来源 CGTeamApply
后续回复 CGTeamRetApply
当前 Lua 协议定义 已定义
当前 Lua 发送点 /home/ubuntu/Game2/services/world/worldcore.lua
主要作用 把“某玩家申请加入当前队伍”的审批提示与申请者预览信息发给队长

当前 Game.exe 的虚函数结论为:

GCTeamAskApply
GetPacketID()   = 644;
GetPacketSize() = 33 + source_name_size + dest_name_size + (detail_flag ? 92 : 0);
Read            = 0x140609830;
Write           = 0x140609BC0;
Execute thunk   = 0x140609820 -> sub_14033F2B0;

包体结构

这条包是“固定头 + 双变长名字 + 单人预览块 + 固定尾”的变长结构。

当前 Game.exe 的 GetPacketSize() 公式为:

33 + source_name_size + dest_name_size + (detail_flag ? 92 : 0)

包体主结构如下:

偏移 长度 字段 类型 含义
0x00 0x04 source_guid int32 申请入队者 GUID
0x04 0x04 dest_guid int32 当前队长 GUID
0x08 0x01 source_name_size uint8 申请者名字长度
0x09 0x01 dest_name_size uint8 队长名字长度
0x0A source_name_size source_name char[n] 申请者名字
0x0A+n dest_name_size dest_name char[m] 队长名字
0x0A+n+m 0x04 menpai int32 申请者门派
... 0x02 sceneid int16 申请者当前场景 ID
... 0x04 level int32 申请者等级
... 0x01 detail_flag uint8 是否附带完整外观预览
... 0x02 model int16 申请者模型 ID
... 0x04 preview_param_1 int32 角色预览附加参数;当前 Lua 默认 2
... 0x02 preview_param_2 int16 角色预览附加参数;当前 Lua 默认 -1
... 0x5C appearance_preview byte[92] 仅当 detail_flag != 0 时写入的完整外观预览
... 0x04 apply_token uint32 申请上下文 token;当前 Lua 默认写 39344113

appearance_preview 结构

当 detail_flag != 0 时,后面会继续写入 92 字节外观数据:

顺序 长度 字段 类型 含义
1 0x0A weapon int32 + int32 + uint16 武器外观三元组
2 0x0A cap int32 + int32 + uint16 帽子外观三元组
3 0x0A armour int32 + int32 + uint16 衣服外观三元组
4 0x0A cuff int32 + int32 + uint16 护腕外观三元组
5 0x0A foot int32 + int32 + uint16 鞋子外观三元组
6 0x04 face_style int32 脸型
7 0x04 hair_style int32 发型
8 0x04 hair_color int32 发色
9 0x12 fashion int32 * 4 + uint16 时装外观组合
10 0x02 exterior_back_id uint16 背饰 ID
11 0x02 exterior_head_id uint16 头饰 ID
12 0x04 exterior_back_pos int32 背饰位置参数
13 0x04 exterior_head_pos int32 头饰位置参数

当前 Game.exe 读取名字时接受 1..30 字节长度;当前 Lua 发送时使用 < 0x1E 限制,因此实际项目里名字通常应控制在 29 字节以内。

当前实际行为

当前实际业务链如下:

  1. 玩家发起 CGTeamApply。
  2. 世界服在 /home/ubuntu/Game2/services/world/worldcore.lua 里检查申请者、目标玩家和目标队伍状态。
  3. 校验通过后,世界服找到目标队长,构造 GCTeamAskApply 发给队长。
  4. 队长客户端收到后,生成一条本地待审批申请,并显示 GCTeamAskApplyhandler_Info_Someone_Apply_Team 提示。
  5. 队长后续再通过 CGTeamRetApply 决定是否同意。

当前 Lua 的发送字段也很直接:

  • source_guid = 申请者 GUID
  • dest_guid = 队长 GUID
  • source_name = 申请者名字
  • dest_name = 队长名字
  • uinfo = 申请者 uinfo 的副本
  • fill_team_preview_detail() 会固定把 detail_flag 置为 1,并补齐武器、帽子、衣服、护腕、鞋子、时装、发型、背饰、头饰等预览字段

当前客户端 Execute() 的关键结论有三点:

  1. 它会把 source_guid、source_name、申请者预览块和 apply_token 组装成本地申请项。
  2. 它会显示 GCTeamAskApplyhandler_Info_Someone_Apply_Team,并额外触发一次本地后续流程 sub_140378380(2)。
  3. 当前观察到的执行逻辑里并没有实际使用 dest_guid 和 dest_name 参与后续分支。

因此,这条包的真正核心是“把申请者是谁、长什么样、能不能展示预览”交给队长客户端,而不是直接完成入队。

服务端落点

当前项目里与这条协议直接相关的落点如下:

  • 协议定义:
    • /home/ubuntu/Game2/services/game/packet.lua
  • 申请入口转发:
    • /home/ubuntu/Game2/services/msgagent.lua
  • 世界服发送审批提示:
    • /home/ubuntu/Game2/services/world/worldcore.lua
  • 队长后续回应处理:
    • /home/ubuntu/Game2/services/world/worldcore.lua

关键代码

当前 Lua 协议定义

packet.GCTeamAskApply = {
    xy_id = packet.XYID_GC_TEAM_ASK_APPLY,
    bos = function(self)
        local stream = bostream.new()
        stream:writeint(self.source_guid)
        stream:writeint(self.dest_guid)
        ...
        stream:writeuint(uinfo.menpai)
        stream:writeushort(uinfo.sceneid)
        stream:writeuint(uinfo.level)
        stream:writeuchar(uinfo.detail_flag or 0)
        stream:writeushort(uinfo.model)
        stream:writeint(uinfo.unknow_1 or 2)
        stream:writeshort(uinfo.unknow_2 or -1)
        if uinfo.detail_flag ~= 0 then
            stream:writeint(uinfo.weapon[define.WG_KEY_A])
            ...
            stream:writeint(uinfo.exterior_head_pos or 0)
        end
        stream:writeuint(uinfo.unknow_15 or 39344113)
        return stream:get()
    end
}

当前 Lua 发送位置

local msg = packet_def.GCTeamAskApply.new()
msg.source_guid = guid
msg.dest_guid = leader_guid
msg.source_name = me.uinfo.name
msg.dest_name = leader.uinfo.name
msg.uinfo = table.clone(me.uinfo)
fill_team_preview_detail(msg.uinfo, me.uinfo)
self:send2client(leader, msg)

当前 Game.exe 的读写结论

GetPacketID() = 644;
GetPacketSize() = 33 + source_name_size + dest_name_size + (detail_flag ? 92 : 0);

Read(stream) {
    read_i32(source_guid);
    read_i32(dest_guid);
    read_u8(source_name_size);
    read_u8(dest_name_size);
    read_char_n(source_name, source_name_size);
    read_char_n(dest_name, dest_name_size);
    read_i32(menpai);
    read_i16(sceneid);
    read_i32(level);
    read_u8(detail_flag);
    read_i16(model);
    read_i32(preview_param_1);
    read_i16(preview_param_2);
    if (detail_flag)
        read_bytes(92);
    read_u32(apply_token);
}

当前 Game.exe 的执行结论

Execute() {
    if (client_ctx_ready) {
        cache_pending_apply(source_guid, source_name, preview_info, apply_token);
        show_text("GCTeamAskApplyhandler_Info_Someone_Apply_Team");
        sub_140378380(2);
    }
    return 0;
}

结论

GCTeamAskApply 在当前 Temp_Release_v0-07-0300 项目里的结论可以直接收敛为:

  1. 这条包的 ID 是 644。
  2. 它是发给队长的入队申请提示包,不是最终入队结果包。
  3. 当前 Game.exe 与 Lua 都确认它是变长结构,长度公式为 33 + source_name_size + dest_name_size + (detail_flag ? 92 : 0)。
  4. 包里真正关键的是申请者 GUID、申请者名字、申请者预览信息,以及尾部 apply_token。
  5. 当前 Lua 发送时会固定补全 detail_flag = 1 的完整 92 字节外观预览块。
  6. 当前客户端执行逻辑会缓存申请项并弹出“有人申请入队”的提示,后续真正是否入队仍取决于 CGTeamRetApply。
您需要登录后才可以回帖 登录 | registerss

本版积分规则

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

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

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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