fix(net): 修复 40250 进入游戏时的收包错位
- GC_ITEM_DEL(20) 按 40250 旧结构为 42 字节,GC_REFINE_INFORMATION(95) 为 59 字节 - 公会标记连接接受 GC_MARK_DIFF_DATA(101),按 1 字节消费 - GUILD_SUBHEADER_GC_SKILL_INFO 服务器声明 22 字节但实际只写 21 字节, 按实际长度分帧,修复 "unknown GC header 200 (last: 75,20)" 断线 - 会话测试的 quest info 包改为 40250 按 flag 定长的格式,新增对应分帧测试 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ft3kXpNdLbKEfg5uDLfqVF
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace mtnet::classic;
|
||||
@@ -248,6 +249,46 @@ int main() {
|
||||
CHECK(s.outgoing_pending() == 0, "unknown header does not resync into trailing bytes");
|
||||
}
|
||||
|
||||
// ------------------------------------------- GC_GUILD SKILL_INFO short write
|
||||
{
|
||||
// guild.cpp CGuild::SendSkillInfoPacket: size = 4 + 6 + GUILD_SKILL_COUNT (22)
|
||||
// but only skill_point + abySkill[12] + power(2) + max_power(2) follow the
|
||||
// head (21 bytes). LoginMember sends it right before SendEnemyGuild's
|
||||
// TPacketGCGuildName (size 20 = 0x14), which is how a real login desynced
|
||||
// into "unknown GC header 200 (last: 75,20)".
|
||||
ClassicStream s;
|
||||
std::string err;
|
||||
s.on_error = [&](const std::string &e) { err = e; };
|
||||
std::vector<std::pair<uint8_t, std::vector<uint8_t>>> got;
|
||||
s.on_packet = [&](uint8_t h, const uint8_t *body, uint32_t len) {
|
||||
got.push_back({h, std::vector<uint8_t>(body, body + len)});
|
||||
return true;
|
||||
};
|
||||
std::vector<uint8_t> skill = {HDR_GC_GUILD, 22, 0, 12, 3};
|
||||
for (uint8_t i = 0; i < 12; ++i) {
|
||||
skill.push_back(static_cast<uint8_t>(i + 1));
|
||||
}
|
||||
skill.insert(skill.end(), {0x10, 0x00, 0x20, 0x00}); // power 16, max_power 32
|
||||
CHECK(skill.size() == 21, "server SKILL_INFO writes 21 bytes");
|
||||
std::vector<uint8_t> name = {HDR_GC_GUILD, 20, 0, 16, 0x2A, 0, 0, 0};
|
||||
const char gname[12] = "Wolves";
|
||||
name.insert(name.end(), gname, gname + sizeof(gname));
|
||||
CHECK(name.size() == 20, "TPacketGCGuildName is 20 bytes");
|
||||
std::vector<uint8_t> wire = skill;
|
||||
wire.insert(wire.end(), name.begin(), name.end());
|
||||
s.feed(wire.data(), wire.size());
|
||||
CHECK(err.empty(), "guild skill info + guild name: no framing error");
|
||||
CHECK(got.size() == 2, "guild skill info + guild name: two packets delivered");
|
||||
if (got.size() == 2) {
|
||||
CHECK(got[0].second.size() == 1 + 17 && got[0].second[0] == 12 &&
|
||||
got[0].second[1] == 3 && got[0].second[16] == 0x20,
|
||||
"skill info body = subheader + 17 bytes");
|
||||
CHECK(got[1].first == HDR_GC_GUILD && got[1].second.size() == 17 &&
|
||||
got[1].second[0] == 16 && got[1].second[1] == 0x2A,
|
||||
"guild name packet framed intact after skill info");
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------- rejected handler
|
||||
{
|
||||
ClassicStream s;
|
||||
|
||||
Reference in New Issue
Block a user