GCRedEnvelope 是红包系统的客户端同步包。当前 Temp_Release_v0-07-0300 的现役 /home/ubuntu/Game2 Lua 服务端没有接入这条协议,但当前 Game.exe 仍保留完整的红包消息提示、列表刷新、历史记录展示与 Lua 查询接口,因此这条包仍然具备明确的客户端行为价值。
包信息
| 项目 |
内容 |
| 封包 ID |
1113 |
| 包名 |
GCRedEnvelope |
| 方向 |
GC 服务端 -> 客户端 |
| 对应请求 |
当前 /home/ubuntu/Game2 主链未找到现役对应请求 |
| 包长 |
变长;按 packet_type 分支 |
| 当前 Lua 状态 |
当前项目未实现、未发送、未定义该包 |
| 主要作用 |
同步红包消息提示、红包列表数据、红包历史记录数据 |
包体结构
这条包的网络结构由“通用包头 + 分支包体”组成。当前客户端可确认的有效分支为 packet_type = 1 / 2 / 3 / 5。
1. 通用包头
| 偏移 |
长度 |
字段 |
类型 |
含义 |
0x00 |
0x01 |
packet_type |
uint8 |
分支类型;当前客户端可确认处理 1 / 2 / 3 / 5 |
0x01 |
0x04 |
reserved_header_1 |
int32 |
通用头字段;当前 Execute() 未直接消费 |
0x05 |
0x04 |
reserved_header_2 |
int32 |
通用头字段;当前 Execute() 未直接消费 |
2. 主消息条目 message_entry
单条主消息条目的网络序列化固定 78 字节。客户端内部缓存该条目时按 79 字节步长排列,多出的 1 字节只存在于内存布局,不在网络包体中。
| 偏移 |
长度 |
字段 |
类型 |
含义 |
+0x00 |
0x04 |
entry_id |
int32 |
条目 ID;客户端 Lua 查询接口会直接返回 |
+0x04 |
0x1E |
display_name |
char[30] |
显示字符串;当前红包消息界面与查询接口都会直接使用 |
+0x22 |
0x04 |
reserved_metric_1 |
int32 |
当前会进入列表 / 历史界面参数,但语义不足以稳定命名 |
+0x26 |
0x04 |
reserved_metric_2 |
int32 |
当前会进入红包消息事件参数,但语义不足以稳定命名 |
+0x2A |
0x04 |
limit_type |
int32 |
本地资格校验类型;0 不校验,1/2 会触发角色属性匹配判断 |
+0x2E |
0x04 |
limit_value |
int32 |
与 limit_type 配套的校验值 |
+0x32 |
0x04 |
reserved_metric_3 |
int32 |
当前会进入红包消息 / 历史界面参数,但语义不足以稳定命名 |
+0x36 |
0x04 |
reserved_metric_4 |
int32 |
当前会进入历史界面参数,但语义不足以稳定命名 |
+0x3A |
0x04 |
reserved_metric_5 |
int32 |
当前会进入历史界面参数,但语义不足以稳定命名 |
+0x3E |
0x04 |
reserved_metric_6 |
int32 |
客户端查询接口会与 reserved_metric_9 做相等比较 |
+0x42 |
0x04 |
reserved_metric_7 |
int32 |
当前会进入历史界面参数,但语义不足以稳定命名 |
+0x46 |
0x04 |
reserved_metric_8 |
int32 |
当前会进入列表 / 首条消息 / 历史界面参数 |
+0x4A |
0x04 |
reserved_metric_9 |
int32 |
客户端查询接口会与 reserved_metric_6 做相等比较 |
3. 历史记录条目 log_entry
单条历史记录条目的网络序列化固定 38 字节。客户端内部缓存该条目时按 39 字节步长排列,多出的 1 字节同样只存在于内存布局,不在网络包体中。
| 偏移 |
长度 |
字段 |
类型 |
含义 |
+0x00 |
0x04 |
player_guid |
uint32 |
玩家 GUID;当前客户端会与本角色 GUID 比对 |
+0x04 |
0x1E |
player_name |
char[30] |
玩家名字;Lua 查询接口会直接返回 |
+0x22 |
0x04 |
player_value |
int32 |
当前角色命中该日志时,会被当作个人结果值带入历史界面 |
4. 分支包体
packet_type = 1 / 2 使用同一条网络布局:
| 偏移 |
长度 |
字段 |
类型 |
含义 |
0x09 |
0x04 |
context_id |
int32 |
当前会被缓存到“首条红包消息槽”,并参与历史界面参数 |
0x0D |
0x04 |
entry_count |
int32 |
主消息条目数量;客户端循环上限 100 |
0x11 |
0x04 |
ui_arg |
int32 |
当前会直接传入红包消息事件 |
0x15 |
0x4E * entry_count |
message_list |
message_entry[entry_count] |
主消息条目数组 |
对应网络长度:
21 + 78 * entry_count
packet_type = 3 的网络布局:
| 偏移 |
长度 |
字段 |
类型 |
含义 |
0x09 |
0x04 |
entry_count |
int32 |
主消息条目数量;客户端循环上限 100 |
0x0D |
0x56 * entry_count |
message_query_list |
{ message_entry, extra_arg_b, extra_arg_a }[entry_count] |
每条消息后附带两个 int32 扩展值;Lua 查询接口会把两者一并返回 |
对应网络长度:
13 + 86 * entry_count
packet_type = 5 的网络布局:
| 偏移 |
长度 |
字段 |
类型 |
含义 |
0x09 |
0x04 |
context_id |
int32 |
历史界面参数之一 |
0x0D |
0x04 |
entry_count |
int32 |
主消息条目数量;客户端循环上限 100 |
0x11 |
0x4E * entry_count |
message_list |
message_entry[entry_count] |
主消息条目数组;当前历史界面只直接消费首条 |
0x11 + 0x4E * entry_count |
0x04 |
log_count |
int32 |
历史记录数量;客户端循环上限 100 |
0x15 + 0x4E * entry_count |
0x26 * log_count |
log_list |
log_entry[log_count] |
红包历史记录数组 |
对应网络长度:
21 + 78 * entry_count + 38 * log_count
当前实际行为
GetPacketID() 返回 1113。
- 当前客户端把
packet_type 作为主分支开关,只能明确确认 1 / 2 / 3 / 5 四类值。
packet_type = 1:
当前 Read() / Write() 结构与 packet_type = 2 相同,但 Execute() 直接返回,不触发可见界面逻辑。
packet_type = 2:
当前客户端会做一次本地节流与资格校验,通过后只缓存首条消息,再触发红包消息事件。虽然包体允许携带 entry_count 个 message_entry,但当前 Execute() 实际只直接消费第一条。
packet_type = 2 的资格校验规则已经可以坐实:
当 limit_type = 0 时不做限制;当 limit_type = 1 或 2 时,客户端会把 limit_value 与当前角色属性做一次本地匹配,不通过则不弹出红包提示。
packet_type = 3:
当前客户端会清空红包列表缓存,逐条写入 message_entry + extra_arg_a + extra_arg_b 的查询结果,再触发红包列表刷新事件。
packet_type = 5:
当前客户端会清空红包历史缓存,逐条写入 log_entry。如果某条 log_entry.player_guid 与本角色 GUID 相同,则其 player_value 会被当作“当前角色对应的个人结果值”带入红包历史界面。
packet_type = 5 虽然也会读取 message_list,但当前历史界面实际只直接消费首条主消息记录,其余重点在 log_list。
- 当前客户端还暴露了 4 个红包 Lua 接口:
Lua_GetFirstRedEnvelopeMsg
Lua_GetRedEnvelopeDataByIndex
Lua_GetRedEnvelopeLogDataByIndex
Lua_RefreshRedEnvelopeMsgData
- 这 4 个接口可以进一步坐实以下事实:
context_id、entry_id、display_name、player_guid、player_name、player_value 都已经被当前客户端实际读取和使用。
服务端落点
当前 /home/ubuntu/Game2 主链未找到 GCRedEnvelope 的协议定义、序列化实现、发送点或业务处理落点,已确认的检查范围包括:
/home/ubuntu/Game2/services/game/packet.lua
/home/ubuntu/Game2/services/msgagent.lua
/home/ubuntu/Game2/services/scene
/home/ubuntu/Game2/services/world
/home/ubuntu/Game2/lualib
当前结论是:Temp_Release_v0-07-0300 现役 Lua 服务端没有接入这条红包协议,本文结构与行为判断以当前 Game.exe 客户端链路为准。
关键代码
当前 Game.exe 的分支读写结论
common_header {
uint8 packet_type;
int32 reserved_header_1;
int32 reserved_header_2;
}
type_1_or_2 {
int32 context_id;
int32 entry_count;
int32 ui_arg;
message_entry message_list[entry_count];
}
type_3 {
int32 entry_count;
struct {
message_entry entry;
int32 extra_arg_b;
int32 extra_arg_a;
} message_query_list[entry_count];
}
type_5 {
int32 context_id;
int32 entry_count;
message_entry message_list[entry_count];
int32 log_count;
log_entry log_list[log_count];
}
当前 packet_type = 2 的核心执行逻辑
if (packet_type == 2) {
if (节流未通过) {
return 2;
}
if (limit_type == 0 || 本地资格校验通过(limit_type, limit_value)) {
cache_first_red_envelope(context_id, message_list[0]);
fire_ui_event(1164, display_name, reserved_metric_2, limit_type, reserved_metric_3, ui_arg);
}
return 2;
}
当前客户端 Lua 查询接口可确认的读取结果
Lua_GetFirstRedEnvelopeMsg()
-> success_flag, context_id, entry_id, reserved_metric_8, limit_type, limit_value, reserved_metric_3
Lua_GetRedEnvelopeDataByIndex(idx)
-> success_flag, entry_id, reserved_metric_8, limit_type, limit_value,
reserved_metric_1, reserved_metric_3, reserved_metric_4,
extra_arg_a, extra_arg_b, (reserved_metric_6 == reserved_metric_9), display_name
Lua_GetRedEnvelopeLogDataByIndex(idx)
-> success_flag, player_value, player_name
结论
GCRedEnvelope(1113) 不是单一固定格式,而是一条按 packet_type 分支解析的红包同步包。
- 当前
Game.exe 已能稳定确认它至少覆盖三类实际业务用途:红包提示、红包列表、红包历史记录。
packet_type = 1 与 packet_type = 2 共享同一网络结构,但当前客户端只对 packet_type = 2 执行有效提示逻辑。
context_id、entry_id、display_name、player_guid、player_name、player_value 已经有足够证据命名;其余数值字段虽然会进入界面和 Lua 接口,但语义仍不足以安全细化,保留 reserved_* 更稳妥。
- 当前
/home/ubuntu/Game2 现役 Lua 服务端没有接入这条协议,因此这篇文档应视为客户端保留协议的正式结构说明。