GCRaidError 是当前团队系统的通用失败通知包。服务端只下发一个 error_code,客户端再按错误码索引本地提示文本并弹出对应错误信息。
它不是某个单独请求的专用回包,而是多个 CGRaid* 请求在失败分支上的共用下行协议。
包信息
| 项目 |
内容 |
| 封包 ID |
1249 |
| 包名 |
GCRaidError |
| 方向 |
GC 游戏服 -> 客户端 |
| 包长 |
1 |
| 当前 Lua 协议定义 |
/home/ubuntu/Game2/services/game/packet.lua |
| 主要服务端落点 |
/home/ubuntu/Game2/services/world/worldcore.lua、/home/ubuntu/Game2/lualib/define.lua |
| 主要作用 |
团队流程失败时向客户端返回错误码,由客户端映射为本地化错误提示 |
当前 Game.exe 可直接确认:
GetPacketID() = 1249;
GetPacketSize() = 1;
Read() = sub_1405FDB70;
Write() = sub_1405C67A0;
Execute() = sub_14061D660 -> sub_14008A400;
包体结构
| 偏移 |
长度 |
字段 |
类型 |
含义 |
0x00 |
0x01 |
error_code |
uint8 |
团队错误码;客户端据此选择对应提示文本 |
当前实际行为
- 当前 Lua
bos() 只写出 1 个字节,包体没有附带 GUID、名字、队伍编号等额外参数。
- 当前
Game.exe 的 Read() / Write() 也只读写 1 个字节,客户端与 Lua 结构完全一致。
- 客户端
Execute() 会先校验 error_code <= 0x2C,再用 off_1408D2DE0[error_code] 取本地提示文本键,并投递到 UI 提示通道。
- 当前 Lua 的
define.RAID_ERROR 已经给出绝大多数错误码的明确名字,因此这条包的唯一字段可以直接命名为 error_code,不需要使用 unknow_x。
worldcore.lua 中的现役发送点覆盖团队申请、邀请、踢人、职位任命、队伍位置调整、成员加入失败等多类失败场景,说明它是团队系统的共用错误回包。
- 客户端文本表保留了
0..44 共 45 个槽位;当前 Lua 明确使用到 0..42,其中 7、23、24、37、38、39、40 仍是保留位。
当前版本里较常见的错误码如下:
| 值 |
Lua 常量 |
含义 |
常见触发场景 |
0 |
RAID_ERROR_INVITEDESTHASRAID |
邀请对象已经加入团队 |
邀请目标已在其他团队 |
1 |
RAID_ERROR_INVITEDHASINRAID |
被邀请玩家已在你的团队中 |
重复邀请本团成员 |
2 |
RAID_ERROR_INVITEDTARGETNOTONLINE |
邀请目标不在线 |
邀请离线角色 |
3 |
RAID_ERROR_RAID_NOTEXIST_OR_LEADEROUT |
团队不存在或团长已离团 |
回应旧邀请、旧申请时目标团队失效 |
4 |
RAID_ERROR_INVITEREFUSE |
对方拒绝邀请 |
被邀请方拒绝加入 |
5 |
RAID_ERROR_FULL |
团队已满 |
团队已满后的通用失败提示 |
6 |
RAID_ERROR_FULL_CANTINVITE |
团队已满,无法继续邀请 |
邀请入口失败 |
8 |
RAID_ERROR_KICKNOTLEADER |
只有团长或助理才能踢人 |
普通成员尝试踢人 |
9 |
RAID_ERROR_KICKLEADER |
不能踢出团长 |
助理尝试踢团长 |
10 |
RAID_ERROR_KICK_ASSISTANT |
不能踢出同职位助理 |
助理互踢 |
11 |
RAID_ERROR_TARGET_IN_OTHERRAID |
目标已在其他团队 |
申请或邀请通过时目标已先加入他团 |
13 |
RAID_ERROR_APPLYLEADERREFUSE |
团长拒绝入团申请 |
申请入团被拒 |
15 |
RAID_ERROR_APPOINTSOURNOLEADER |
团长已换人 |
回应旧邀请时来源职位变化 |
16 |
RAID_ERROR_NOT_IN_RAID |
当前角色不在团队中 |
大量团队操作前置校验失败 |
17 |
RAID_ERROR_TARGET_NOT_IN_YOUR_RAID |
目标不在你的团队中 |
踢人、任命时目标已不在本团 |
19 |
RAID_ERROR_NOT_LEADER |
当前角色已不是团长 |
任命、审批等仅团长操作失败 |
20 |
RAID_ERROR_ASSISTANT_MAX |
助理人数已满 |
任命助理超过上限 |
21 |
RAID_ERROR_APPOINT_FAIL |
任命失败 |
目标职位未变化或无法完成任命 |
25 |
RAID_ERROR_FULL_CANTAPPLY |
团队已满,无法加入 |
申请入团失败 |
31 |
RAID_ERROR_ADDMEMFAILED |
添加成员失败 |
申请通过后成员状态异常 |
32 |
RAID_ERROR_ADDMEMFAILED_INVITEERR |
邀请人异常,加入失败 |
邀请链路异常 |
33 |
RAID_ERROR_CHANGE_POISTION_1 |
调整团员位置失败 |
换位时找不到原成员位置 |
41 |
RAID_RESERVER_8 |
你已经加入一支队伍了 |
枚举名仍是保留写法,但语义已明确 |
42 |
RAID_ERROR_NUMBER |
对方已经加入一支队伍了 |
目标已在普通队伍中,不能继续组团队 |
服务端落点
- 协议定义位于
/home/ubuntu/Game2/services/game/packet.lua,当前结构只有 error_code:uint8。
- 错误码枚举位于
/home/ubuntu/Game2/lualib/define.lua 的 define.RAID_ERROR。
- 主发送链位于
/home/ubuntu/Game2/services/world/worldcore.lua,典型入口包括:
char_ret_raid_apply
char_ret_raid_invite
char_invite_raid
char_raid_kick
char_raid_appoint
- 团队位置调整与成员加入失败分支
- 这条包没有绑定单一上行请求,多个
CGRaid* 包都会在失败时复用它。
关键代码
当前 Lua 协议定义
packet.GCRaidError = {
xy_id = packet.XYID_GCRaidError,
new = function(o)
o = o or {}
setmetatable(o, {__index = packet.GCRaidError})
o:ctor()
return o
end,
ctor = function(self) self.error_code = 0 end,
bis = function(self, buffer)
end,
bos = function(self)
local stream = bostream.new()
stream:writeuchar(self.error_code)
return stream:get()
end
}
当前 Game.exe 读写实现
__int64 __fastcall Read(__int64 packet, __int64 stream)
{
sub_1403F9B00(stream, (char *)(packet + 24), 1u);
return 1;
}
__int64 __fastcall Write(__int64 packet, __int64 stream)
{
(*(void (__fastcall **)(__int64, __int64, __int64))(*(_QWORD *)stream + 8LL))(stream, packet + 24, 1);
return 1;
}
当前客户端执行逻辑
if ( packet->error_code > 0x2C )
tThrowAssertException("...\\GCRaidErrorHandler.cpp", 122, "FALSE");
text_key = off_1408D2DE0[packet->error_code];
PushUIMessage(133, text_key);
结论
GCRaidError(1249) 在当前版本中已经可以明确判定为团队系统的通用错误通知包,完整包体只有一个 error_code:uint8。当前 Lua 与当前 Game.exe 的结构、长度和执行方式完全一致,字段命名也已经足够明确。
这条包的重点不在包体长度,而在错误码语义。现役 Lua 已经为大部分错误码提供了稳定命名,客户端则负责把错误码映射为本地提示文本,因此本文不需要借助旧 Server 就可以给出当前版本的最终结论。
|