40250 classic: expand CHARACTER_NAME_MAX_LEN to 64 for full UTF-8 Chinese names

This commit is contained in:
shen
2026-09-19 19:50:40 -07:00
parent 21462cddca
commit 0dafa9f5ff
3 changed files with 51 additions and 51 deletions
+23 -23
View File
@@ -31,7 +31,7 @@
namespace mtnet::classic {
// ------------------------------------------------------------------ constants
inline constexpr int CHARACTER_NAME_MAX_LEN = 24; // common/length.h -> name[25]
inline constexpr int CHARACTER_NAME_MAX_LEN = 64; // common/length.h -> name[65]
inline constexpr int GUILD_NAME_MAX_LEN = 12; // -> guild_name[13]
inline constexpr int GUILD_GRADE_NAME_MAX_LEN = 8;
inline constexpr int GUILD_COMMENT_MAX_LEN = 50;
@@ -373,8 +373,8 @@ struct SimplePlayer { // TSimplePlayer (common/tables.h) == client TSimplePlayer
uint16_t port;
uint8_t skill_group;
};
// 4 + 25 + 1 + 1 + 4 + 4 + 2 + 1 + 2 + 4 + 8 + 4 + 2 + 1
static_assert(sizeof(SimplePlayer) == 63);
// 4 + 65 + 1 + 1 + 4 + 4 + 2 + 1 + 2 + 4 + 8 + 4 + 2 + 1
static_assert(sizeof(SimplePlayer) == 103);
// --- control / handshake ---
struct Blank { uint8_t header; };
@@ -439,9 +439,9 @@ struct GCLoginSuccessT { // packet_login_success — 40250 sends the NEWSLOT (N=
};
using GCLoginSuccess = GCLoginSuccessT<PLAYER_PER_ACCOUNT>; // header 32
using GCLoginSuccess3 = GCLoginSuccessT<PLAYER_PER_ACCOUNT3>; // header 6 (legacy)
// 1 + 63*N + 4*N + 13*N + 4 + 4
static_assert(sizeof(GCLoginSuccess) == 1 + 63 * 4 + 4 * 4 + 13 * 4 + 4 + 4); // 329
static_assert(sizeof(GCLoginSuccess3) == 1 + 63 * 3 + 4 * 3 + 13 * 3 + 4 + 4); // 249
// 1 + 103*N + 4*N + 13*N + 4 + 4
static_assert(sizeof(GCLoginSuccess) == 1 + sizeof(SimplePlayer) * 4 + 4 * 4 + 13 * 4 + 4 + 4); // 489
static_assert(sizeof(GCLoginSuccess3) == 1 + sizeof(SimplePlayer) * 3 + 4 * 3 + 13 * 3 + 4 + 4); // 369
struct GCLoginFailure { uint8_t header; char status[LOGIN_STATUS_MAX_LEN + 1]; };
static_assert(sizeof(GCLoginFailure) == 10);
@@ -487,7 +487,7 @@ struct CGPlayerCreate { // command_player_create — note `job` is WORD here
uint8_t shape;
uint8_t con, intel, str, dex;
};
static_assert(sizeof(CGPlayerCreate) == 1 + 1 + 25 + 2 + 1 + 4);
static_assert(sizeof(CGPlayerCreate) == 1 + 1 + (CHARACTER_NAME_MAX_LEN + 1) + 2 + 1 + 4); // 74
struct CGPlayerDelete { uint8_t header; uint8_t index; char private_code[PRIVATE_CODE_LENGTH]; };
static_assert(sizeof(CGPlayerDelete) == 10);
@@ -497,7 +497,7 @@ struct CGChangeName {
uint8_t index;
char name[CHARACTER_NAME_MAX_LEN + 1];
};
static_assert(sizeof(CGChangeName) == 27);
static_assert(sizeof(CGChangeName) == 1 + 1 + (CHARACTER_NAME_MAX_LEN + 1)); // 67
struct CGEmpire { uint8_t header; uint8_t empire; };
static_assert(sizeof(CGEmpire) == 2);
@@ -524,10 +524,10 @@ struct CGClientVersion2 {
static_assert(sizeof(CGClientVersion2) == 67);
struct GCPlayerCreateSuccess { uint8_t header; uint8_t account_slot; SimplePlayer player; };
static_assert(sizeof(GCPlayerCreateSuccess) == 2 + 63);
static_assert(sizeof(GCPlayerCreateSuccess) == 2 + sizeof(SimplePlayer)); // 105
struct GCPlayerCreateFailure { uint8_t header; uint8_t type; };
struct GCChangeNameNotice { uint8_t header; uint32_t pid; char name[CHARACTER_NAME_MAX_LEN + 1]; };
static_assert(sizeof(GCPlayerCreateFailure) == 2 && sizeof(GCChangeNameNotice) == 30);
static_assert(sizeof(GCPlayerCreateFailure) == 2 && sizeof(GCChangeNameNotice) == 1 + 4 + (CHARACTER_NAME_MAX_LEN + 1)); // 70
struct GCPlayerDeleteSuccess { uint8_t header; uint8_t account_index; };
static_assert(sizeof(GCPlayerDeleteSuccess) == 2);
@@ -568,7 +568,7 @@ struct GCMainCharacter { // packet.h:1043 (== client TPacketGCMainCharacter2_EMP
uint8_t empire;
uint8_t skill_group;
};
static_assert(sizeof(GCMainCharacter) == 1 + 4 + 2 + 25 + 12 + 1 + 1);
static_assert(sizeof(GCMainCharacter) == 1 + 4 + 2 + (CHARACTER_NAME_MAX_LEN + 1) + 12 + 1 + 1); // 86
// SUPPORT_BGM variants emitted by CHARACTER::MainCharacterPacket when the
// map has a configured background track. The BGM field is not needed by the
@@ -595,7 +595,7 @@ struct GCMainCharacter4BGM {
uint8_t empire;
uint8_t skill_group;
};
static_assert(sizeof(GCMainCharacter3BGM) == 71 && sizeof(GCMainCharacter4BGM) == 75);
static_assert(sizeof(GCMainCharacter3BGM) == 111 && sizeof(GCMainCharacter4BGM) == 115);
// --- spawn / despawn / move ---
struct GCCharacterAdd { // packet_add_char (server) — no name/parts
@@ -632,7 +632,7 @@ struct GCCharacterAdd2 { // packet_add_char2 — name + parts + guild
uint32_t mount_vnum;
};
static_assert(sizeof(GCCharacterAdd2) ==
1 + 4 + 25 + 4 + 12 + 1 + 2 + 8 + 1 + 1 + 1 + 8 + 1 + 4 + 2 + 1 + 4);
1 + 4 + (CHARACTER_NAME_MAX_LEN + 1) + 4 + 12 + 1 + 2 + 8 + 1 + 1 + 1 + 8 + 1 + 4 + 2 + 1 + 4); // 120
struct GCCharacterDel { uint8_t header; uint32_t vid; };
static_assert(sizeof(GCCharacterDel) == 5);
@@ -993,7 +993,7 @@ struct GCDragonSoulRefine {
ItemPos pos;
};
static_assert(sizeof(GCAttack) == 10 && sizeof(GCItemUse) == 16 &&
sizeof(GCItemOwnership) == 30 && sizeof(GCOwnership) == 9 && sizeof(GCMount) == 18 &&
sizeof(GCItemOwnership) == 70 && sizeof(GCOwnership) == 9 && sizeof(GCMount) == 18 &&
sizeof(GCCreateFly) == 10 && sizeof(GCFlyTargeting) == 17 &&
sizeof(GCPvp) == 10 && sizeof(GCDuelStart) == 3 && sizeof(GCShopSign) == 38 &&
sizeof(GCSkillGroup) == 2 && sizeof(GCSpecialEffect) == 6 && sizeof(GCSpecificEffect) == 133 &&
@@ -1002,12 +1002,12 @@ static_assert(sizeof(GCAttack) == 10 && sizeof(GCItemUse) == 16 &&
sizeof(GCObserverAdd) == 9 && sizeof(GCObserverMove) == 9 &&
sizeof(GCObserverRemove) == 5 && sizeof(GCTime) == 5 && sizeof(GCChannel) == 2 &&
sizeof(GCDungeonHead) == 1 && sizeof(GCNPCPositionHead) == 2 &&
sizeof(NPCPosition34) == 34 && sizeof(LandPacketElement24) == 24 &&
sizeof(NPCPosition34) == 74 && sizeof(LandPacketElement24) == 24 &&
sizeof(GCTargetCreate43) == 43 && sizeof(GCTargetUpdate13) == 13 &&
sizeof(GCTargetDelete5) == 5 && sizeof(GCLoverInfo) == 27 &&
sizeof(GCTargetDelete5) == 5 && sizeof(GCLoverInfo) == 67 &&
sizeof(GCLovePointUpdate) == 2 && sizeof(GCDigMotion) == 10 &&
sizeof(EquipmentItem38) == 38 && sizeof(GCViewEquip) == 1221 &&
sizeof(GCChangeName) == 30 && sizeof(GCRefineMaterial) == 8 &&
sizeof(GCChangeName) == 70 && sizeof(GCRefineMaterial) == 8 &&
sizeof(GCRefineInfo) == 60 && sizeof(GCDragonSoulRefine) == 5);
// packet_char_additional_info (header 136) — fills a spawned entity's name/parts/...
@@ -1023,7 +1023,7 @@ struct GCCharAddInfo {
uint8_t pk_mode;
uint32_t mount_vnum;
};
static_assert(sizeof(GCCharAddInfo) == 1 + 4 + 25 + 8 + 1 + 4 + 4 + 2 + 1 + 4); // 54
static_assert(sizeof(GCCharAddInfo) == 1 + 4 + (CHARACTER_NAME_MAX_LEN + 1) + 8 + 1 + 4 + 4 + 2 + 1 + 4); // 94
// --- GC skills / quickslots ---
struct PlayerSkill3 { // TPlayerSkill (common/tables.h) — time_t is 32-bit on the -m32 server
@@ -1064,7 +1064,7 @@ struct GCWhisperHead { // packet_whisper (header 34) — + text
uint8_t type;
char name_from[CHARACTER_NAME_MAX_LEN + 1];
};
static_assert(sizeof(GCWhisperHead) == 1 + 2 + 1 + 25); // 29
static_assert(sizeof(GCWhisperHead) == 1 + 2 + 1 + (CHARACTER_NAME_MAX_LEN + 1)); // 69
struct SyncPosElement { uint32_t vid; int32_t x, y; };
static_assert(sizeof(SyncPosElement) == 12);
@@ -1133,7 +1133,7 @@ struct GCPartyRemove { uint8_t header; uint32_t pid; }; // hea
struct GCPartyLink { uint8_t header; uint32_t pid; uint32_t vid; }; // header 91
struct GCPartyUnlink { uint8_t header; uint32_t pid; uint32_t vid; }; // header 92
struct GCPartyParameter { uint8_t header; uint8_t distribute_mode; }; // header 83
static_assert(sizeof(GCPartyInvite) == 5 && sizeof(GCPartyAdd) == 30 &&
static_assert(sizeof(GCPartyInvite) == 5 && sizeof(GCPartyAdd) == 70 &&
sizeof(GCPartyUpdate) == 21 && sizeof(GCPartyRemove) == 5 && sizeof(GCPartyLink) == 9 &&
sizeof(GCPartyParameter) == 2);
@@ -1288,11 +1288,11 @@ struct GuildInvite17 {
uint32_t guild_id;
char guild_name[GUILD_NAME_MAX_LEN + 1];
};
static_assert(sizeof(GuildMember38) == 38 && sizeof(GuildInfo35) == 35 &&
static_assert(sizeof(GuildMember38) == 78 && sizeof(GuildInfo35) == 35 &&
sizeof(GuildGrade10) == 10 && sizeof(GuildWar10) == 10 &&
sizeof(GuildWarPoint12) == 12 && sizeof(GuildWarPair8) == 8 &&
sizeof(GuildName16) == 16 && sizeof(GuildSkill17) == 17 &&
sizeof(GuildComment80) == 80 && sizeof(GuildInvite17) == 17);
sizeof(GuildComment80) == 120 && sizeof(GuildInvite17) == 17);
// CGuild::SendSkillInfoPacket() (guild.cpp) announces
// `size = sizeof(pack) + 6 + GUILD_SKILL_COUNT` (22) but writes only
@@ -1306,7 +1306,7 @@ inline constexpr int GUILD_SKILL_INFO_PACKET_SIZE = 4 + sizeof(GuildSkill17); //
struct CGChatHead { uint8_t header; uint16_t length; uint8_t type; }; // + char szChat[]
static_assert(sizeof(CGChatHead) == 4);
struct CGWhisper { uint8_t header; uint16_t size; char name_to[CHARACTER_NAME_MAX_LEN + 1]; };
static_assert(sizeof(CGWhisper) == 28);
static_assert(sizeof(CGWhisper) == 1 + 2 + (CHARACTER_NAME_MAX_LEN + 1)); // 68
struct GCChatHead { // packet_chatting — + text
uint8_t header;
+12 -12
View File
@@ -31,11 +31,11 @@ int main() {
// --- struct sizes (redundant with static_assert, but explicit) ---
CHECK(sizeof(Handshake) == 13, "sizeof Handshake");
CHECK(sizeof(CGText) == 1, "sizeof CG_TEXT base");
CHECK(sizeof(SimplePlayer) == 63, "sizeof SimplePlayer");
CHECK(sizeof(GCMainCharacter) == 46, "sizeof GCMainCharacter");
CHECK(sizeof(GCMainCharacter3BGM) == 71 && sizeof(GCMainCharacter4BGM) == 75,
CHECK(sizeof(SimplePlayer) == 103, "sizeof SimplePlayer");
CHECK(sizeof(GCMainCharacter) == 86, "sizeof GCMainCharacter");
CHECK(sizeof(GCMainCharacter3BGM) == 111 && sizeof(GCMainCharacter4BGM) == 115,
"sizeof main-character BGM variants");
CHECK(sizeof(GCCharacterAdd2) == 80 && sizeof(GCCharacterUpdate) == 35,
CHECK(sizeof(GCCharacterAdd2) == 120 && sizeof(GCCharacterUpdate) == 35,
"sizeof character add/update variants");
CHECK(sizeof(GCFishing) == 7, "sizeof GC_FISHING");
CHECK(sizeof(GCWarpClassic) == 15, "sizeof classic GC_WARP");
@@ -43,7 +43,7 @@ int main() {
"sizeof auth success packets");
CHECK(sizeof(GCPasspodFailed) == 130 && sizeof(GCXTrapRequest) == 129 && sizeof(GCHSRequest) == 403,
"sizeof optional security packets");
CHECK(sizeof(GCLoginSuccess) == 329, "sizeof GCLoginSuccess (NEWSLOT, 4 players)");
CHECK(sizeof(GCLoginSuccess) == 489, "sizeof GCLoginSuccess (NEWSLOT, 4 players)");
CHECK(sizeof(GCPoints) == 1 + 255 * 4, "sizeof GCPoints");
CHECK(sizeof(GCPointChange) == 17, "sizeof GCPointChange (int header quirk)");
CHECK(sizeof(CGMove) == 16, "sizeof CGMove");
@@ -55,16 +55,16 @@ int main() {
// --- size-table lookup (body size, no trailing seq byte) ---
CHECK(packet_size_gc(HDR_GC_PHASE) == 2, "gc size PHASE");
CHECK(packet_size_gc(HDR_GC_MAIN_CHARACTER) == 46, "gc size MAIN_CHARACTER");
CHECK(packet_size_gc(HDR_GC_MAIN_CHARACTER) == 86, "gc size MAIN_CHARACTER");
CHECK(packet_size_gc(HDR_GC_WARP) == sizeof(GCWarpClassic), "gc size WARP");
CHECK(packet_size_gc(HDR_GC_MAIN_CHARACTER3_BGM) == 71 &&
packet_size_gc(HDR_GC_MAIN_CHARACTER4_BGM_VOL) == 75, "gc size MAIN_CHARACTER BGM");
CHECK(packet_size_gc(HDR_GC_CHARACTER_ADD2) == 80 &&
CHECK(packet_size_gc(HDR_GC_MAIN_CHARACTER3_BGM) == 111 &&
packet_size_gc(HDR_GC_MAIN_CHARACTER4_BGM_VOL) == 115, "gc size MAIN_CHARACTER BGM");
CHECK(packet_size_gc(HDR_GC_CHARACTER_ADD2) == 120 &&
packet_size_gc(HDR_GC_CHARACTER_UPDATE2) == 35, "gc size character variants");
CHECK(packet_size_gc(HDR_GC_FISHING) == 7, "gc size FISHING");
CHECK(packet_size_gc(HDR_GC_AUTH_SUCCESS) == 6 &&
packet_size_gc(HDR_GC_XTRAP_CS1_REQUEST) == 129, "gc size auth/security");
CHECK(packet_size_gc(HDR_GC_LOGIN_SUCCESS_NEWSLOT) == 329, "gc size LOGIN_SUCCESS_NEWSLOT");
CHECK(packet_size_gc(HDR_GC_LOGIN_SUCCESS_NEWSLOT) == 489, "gc size LOGIN_SUCCESS_NEWSLOT");
CHECK(packet_size_gc(HDR_GC_CHARACTER_POINTS) == 1021, "gc size CHARACTER_POINTS");
CHECK(packet_size_gc(HDR_GC_EXCHANGE) == 47, "gc size EXCHANGE");
CHECK(packet_size_gc(HDR_GC_SAFEBOX_MONEY_CHANGE) == 5, "gc size SAFEBOX_MONEY_CHANGE");
@@ -121,8 +121,8 @@ int main() {
CHECK(buf[0] == 113, "wire byte 0 == header");
// header(1) vid(4) race(2) name(25) -> x at offset 32
int32_t x_wire;
std::memcpy(&x_wire, buf + 1 + 4 + 2 + 25, 4);
CHECK(x_wire == 100000, "wire x at offset 32");
std::memcpy(&x_wire, buf + 1 + 4 + 2 + (CHARACTER_NAME_MAX_LEN + 1), 4);
CHECK(x_wire == 100000, "wire x at offset");
GCMainCharacter rt{};
std::memcpy(&rt, buf, sizeof(rt));