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 在当前旧版项目里的最终结论很明确:
- 这条包的 ID 是
200,固定长度 73。
- 它不是普通被邀请者的回复包,而是“队长对转交邀请作出的审批回复”。
- 当前世界服真正依赖的业务核心字段是
return_type、source_guid、dest_guid。
return_type = 1 表示队长同意,服务端会继续给目标玩家发送真正的 GCTeamAskInvite。
return_type = 0 表示队长拒绝,原始邀请发起者会收到 TEAM_ERROR_INVITELEADERREFUSE。
- 两组 8 元 GUID 数组在当前版本里会被客户端提交,但当前 Lua 主链没有消费它们做业务判定。