wire: guild packets and DisplayGuildCreateBox as structs

The guild packets of the 1.10.64 client (docs/Guilds.md) as Serialize/Deserialize structs, laid out the way the client's
packet handlers read them: GUILD_CREATE_RESPONSE, GUILD_INVITE, GUILD_INVITE_INITIAL_RESPONSE, _FINAL_RESPONSE,
_CONFIRM, GUILD_ADD_PLAYER, GUILD_REMOVE_PLAYER, GUILD_LOGIN_LOGOUT and GUILD_DATA (ClientPackets), the world packet
TMP_GUILD_CREATE the create box sends, the chat packets the client sends through its world (GUILD_INVITE,
GUILD_INVITE_RESPONSE, GUILD_LEAVE, GUILD_GET_ALL), DLU's world <-> chat packets (GUILD_CREATE, GUILD_KICK,
GUILD_GET_STATUS as the chat server's guild update to a world, and GUILD_SET_RANK and GUILD_DISBAND appended to
MessageType::Chat after CREATE_TEAM) and the game message DisplayGuildCreateBox (626). Fixed-size names always keep a
NUL, since the client reads them as C strings. Enums eGuildCreateResponse, eGuildInviteResponse,
eGuildInviteFinalResponse, eGuildRank and eGuildLeaveReason. Nothing sends them yet.

Check: GuildPacketsTests compares every packet with the bytes at the client's offsets. Nothing to check in game.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-29 05:40:53 -05:00
parent 88ebdf685e
commit 130f3566cc
14 changed files with 905 additions and 0 deletions

View File

@@ -74,5 +74,7 @@ namespace MessageType {
UPDATE_FREE_TRIAL_STATUS,
// CUSTOM DLU MESSAGE ID FOR INTERNAL USE
CREATE_TEAM,
GUILD_SET_RANK, // world -> chat: /gpromote, /gdemote, /gleader
GUILD_DISBAND, // world -> chat: /gdisband
};
}

View File

@@ -0,0 +1,14 @@
#ifndef EGUILDCREATERESPONSE_H
#define EGUILDCREATERESPONSE_H
#include <cstdint>
// MSG_CLIENT_GUILD_CREATE_RESPONSE's result (docs/Guilds.md)
enum class eGuildCreateResponse : uint8_t {
CREATED, // "MSG_GUILD_GUILD_NAME_CREATED", then the client asks for the guild's data
BAD_NAME, // "MSG_GUILD_GUILD_NAME_CANT_BE_USED"
EXISTS, // "MSG_GUILD_GUILD_NAME_ALREADY_IN_USE"
FAILED, // anything else: "MSG_GUILD_GUILD_COULD_NOT_BE_CREATED"
};
#endif // EGUILDCREATERESPONSE_H

View File

@@ -0,0 +1,23 @@
#ifndef EGUILDINVITERESPONSE_H
#define EGUILDINVITERESPONSE_H
#include <cstdint>
// MSG_CLIENT_GUILD_INVITE_INITIAL_RESPONSE's code: what happened to the invite the player sent (docs/Guilds.md)
enum class eGuildInviteResponse : uint8_t {
SENT, // "MSG_GUILD_GUILD_INVITE_SENT_TO_NAME"
NOT_ONLINE, // "MSG_GENERIC_NAME_IS_NOT_ONLINE"
ALREADY_IN_GUILD, // "MSG_GUILD_NAME_IS_ALREADY_IN_A_GUILD"
INVITE_PENDING, // "MSG_GUILD_NAME_ALREADY_HAS_A_GUILD_INVITE_PENDING"
FAILED, // anything else: "MSG_GUILD_COULD_NOT_INVITE_NAME"
};
// MSG_CLIENT_GUILD_INVITE_FINAL_RESPONSE's code: the invited player's answer, told to the inviter
enum class eGuildInviteFinalResponse : uint8_t {
JOINED, // "MSG_GUILD_NAME_HAS_JOINED_THE_GUILD"
DECLINED, // "MSG_GUILD_NAME_DECLINED_YOUR_INVITATION"
NOT_ONLINE, // "MSG_GENERIC_NAME_IS_NOT_ONLINE"
FAILED, // anything else: "CLIENTMSG_COULD_NOT_INVITE_NAME"
};
#endif // EGUILDINVITERESPONSE_H

View File

@@ -0,0 +1,21 @@
#ifndef EGUILDRANK_H
#define EGUILDRANK_H
#include <cstdint>
// A guild member's rank, as the client names it in the guild list (0 and anything above 4: no name)
enum class eGuildRank : uint8_t {
NONE,
LEADER,
OFFICER,
VETERAN,
RECRUIT,
};
// MSG_CLIENT_GUILD_REMOVE_PLAYER's reason
enum class eGuildLeaveReason : uint8_t {
LEFT,
KICKED,
};
#endif // EGUILDRANK_H