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

洱海月 v0-07-0300 封包解析:ID 200 CGTeamLeaderRetInvite(队长回复转交邀请审批)

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

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

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

×

CGTeamLeaderRetInvite 是旧版客户端里“队长回复转交邀请审批”的请求包。

当普通队员发起 CGTeamInvite,但自己不是当前队长时,世界服不会直接把邀请发给目标玩家,而是先给队长发送 GCTeamLeaderAskInvite。队长随后通过这条 CGTeamLeaderRetInvite 决定是否放行这次邀请。

包信息

项目 内容
封包 ID 200
包名 CGTeamLeaderRetInvite
方向 CG 客户端 -> 游戏服
固定包长 73
前置来包 GCTeamLeaderAskInvite
当前 Lua 入口 request:CGTeamLeaderRetInvite()
当前世界服处理 worldcore:char_ret_team_leader_invite()
主要作用 队长对“队员发起的邀请”作出同意或拒绝回复

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

GetPacketID() = 200;
GetPacketSize() = 73;
Read    = sub_1405C98F0;
Write   = sub_1405C99B0;
Execute = sub_140328A50;

包体结构

当前 Game.exe 与 Lua 协议定义都能确认,这条包固定为 73 字节。

偏移 长度 字段 类型 含义
0x00 0x01 return_type uint8 队长审批结果,当前 Lua 按 1 = 同意、0 = 拒绝 解释
0x01 0x04 source_guid int32 原始邀请发起者 GUID,也就是发起 CGTeamInvite 的队员
0x05 0x04 dest_guid int32 被邀请目标 GUID
0x09 0x20 guids[8] int32[8] 客户端附带的第一组 GUID 快照,当前 Lua 未消费
0x29 0x20 team_guids[8] int32[8] 客户端附带的第二组队伍 GUID 快照,当前 Lua 未消费

当前 Game.exe 的 Read / Write 顺序固定为:

read_u8(return_type);
read_i32(source_guid);
read_i32(dest_guid);
for (i = 0; i < 8; ++i)
    read_i32(guids[i]);
for (i = 0; i < 8; ++i)
    read_i32(team_guids[i]);

总长度正好是:

1 + 4 + 4 + 8*4 + 8*4 = 73

当前实际行为 / 模式说明

  • 当前 Lua 入口是 request:CGTeamLeaderRetInvite(),收到后会把“当前队长 GUID + 整包数据”转给世界服 char_ret_team_leader_invite()。
  • 当前世界服真正做业务判定的核心字段只有:
    • return_type
    • source_guid
    • dest_guid
  • 世界服会先用 leader_guid + source_guid + dest_guid 到 pending_team_leader_invites 里消费一条待处理审批上下文。
  • 如果找不到这条上下文,当前 Lua 会直接提示队长:队伍邀请已失效,请重新邀请。
  • 当前审批上下文有超时控制,超时时间是 300 秒。
  • return_type = 0 时:
    • 世界服不给目标玩家继续发邀请
    • 只给原始邀请发起者发送 GCTeamError
    • 错误码是 TEAM_ERROR_INVITELEADERREFUSE = 3
  • return_type = 1 时:
    • 世界服会先重新校验队长、发起邀请的队员、目标玩家和当前队伍状态
    • 校验通过后,再给目标玩家发送真正的 GCTeamAskInvite
    • 随后目标玩家还需要继续回复 CGTeamRetInvite,这次邀请才会真正进入最终入队链
  • 当前世界服还会额外校验这些状态:
    • 队长是否仍是该队队长
    • 发起邀请的队员是否还在同一队伍里
    • 目标玩家是否在线
    • 目标玩家是否已经有队伍
    • 队伍是否已满
    • 三方是否有人已在团里
  • guids[8] 和 team_guids[8] 在当前版本里会被客户端提交,但当前世界服处理函数没有使用这两组数组做校验或分支,因此现状里更像客户端附带的 GUID 快照参数。

还有一个需要注意的历史命名细节:

  • 当前 Lua 常量名写的是 XYID_CG_TEAM_LEADER_RET_APPLY = 200
  • 但当前包类名和业务语义已经明确是 CGTeamLeaderRetInvite

也就是说,这条协议虽然沿用了旧的 RET_APPLY 常量名,但实际处理的是“队长回复转交邀请审批”。

服务端落点

  • 协议定义:
    • /home/ubuntu/Game2/services/game/packet.lua
  • 请求入口:
    • /home/ubuntu/Game2/services/msgagent.lua
  • 邀请转交与审批状态:
    • /home/ubuntu/Game2/services/world/worldcore.lua

关键代码

当前 Lua 协议定义

packet.CGTeamLeaderRetInvite = {
    xy_id = packet.XYID_CG_TEAM_LEADER_RET_APPLY,
    bis = function(self, buffer)
        local stream = bistream.new()
        stream:attach(buffer)
        self.return_type = stream:readuchar()
        self.source_guid = stream:readint()
        self.dest_guid = stream:readint()
        self.guids = {}
        for i = 1, 8 do
            self.guids[i] = stream:readint()
        end
        self.team_guids = {}
        for i = 1, 8 do
            self.team_guids[i] = stream:readint()
        end
    end
}

当前 Lua 请求入口

function request:CGTeamLeaderRetInvite()
    local my_guid = ma_func:get_guid()
    skynet.call(".world", "lua", "char_ret_team_leader_invite", my_guid, self)
end

当前世界服处理

function worldcore:char_ret_team_leader_invite(guid, ret)
    local leader = self:find_user(guid)
    if not leader or ret == nil then
        return
    end

    local source_guid = ret.source_guid
    local dest_guid = ret.dest_guid
    local agree_invite = parse_team_invite_reply(ret.return_type)
    local invite_ctx = self:consume_team_leader_invite_pending(guid, source_guid, dest_guid)
    if invite_ctx == nil then
        self:notify_client_tips(leader, TEAM_INVITE_INVALID_TIPS)
        return
    end

    if not agree_invite then
        local msg = packet_def.GCTeamError.new()
        msg.error_code = define.TEAM_ERROR.TEAM_ERROR_INVITELEADERREFUSE
        self:send2client(inviter, msg)
        return
    end

    local msg = packet_def.GCTeamAskInvite.new()
    msg.guid = source_guid
    msg.nickname = inviter.uinfo.name
    self:create_invite_info(msg, team:get_members())
    if self:send2client(accpter, msg) then
        self:add_team_invite_pending(source_guid, dest_guid, team_id, guid)
    end
end

当前 Game.exe 的读写与执行结论

GetPacketID() = 200;
GetPacketSize() = 73;

Read(stream) {
    read_u8(return_type);
    read_i32(source_guid);
    read_i32(dest_guid);
    for (i = 0; i < 8; ++i)
        read_i32(guids[i]);
    for (i = 0; i < 8; ++i)
        read_i32(team_guids[i]);
}

Write(stream) {
    write_u8(return_type);
    write_i32(source_guid);
    write_i32(dest_guid);
    for (i = 0; i < 8; ++i)
        write_i32(guids[i]);
    for (i = 0; i < 8; ++i)
        write_i32(team_guids[i]);
}

Execute() {
    return 2;
}

结论

CGTeamLeaderRetInvite 在当前旧版项目里的最终结论很明确:

  1. 这条包的 ID 是 200,固定长度 73。
  2. 它不是普通被邀请者的回复包,而是“队长对转交邀请作出的审批回复”。
  3. 当前世界服真正依赖的业务核心字段是 return_type、source_guid、dest_guid。
  4. return_type = 1 表示队长同意,服务端会继续给目标玩家发送真正的 GCTeamAskInvite。
  5. return_type = 0 表示队长拒绝,原始邀请发起者会收到 TEAM_ERROR_INVITELEADERREFUSE。
  6. 两组 8 元 GUID 数组在当前版本里会被客户端提交,但当前 Lua 主链没有消费它们做业务判定。
您需要登录后才可以回帖 登录 | registerss

本版积分规则

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

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

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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