mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 02:43:44 +00:00
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>
651 lines
21 KiB
C++
651 lines
21 KiB
C++
/*
|
|
* Darkflame Universe
|
|
* Copyright 2018
|
|
*/
|
|
|
|
#include "ChatPackets.h"
|
|
#include "RakNetTypes.h"
|
|
#include "BitStream.h"
|
|
#include "Game.h"
|
|
#include "BitStreamUtils.h"
|
|
#include "dServer.h"
|
|
#include "ServiceType.h"
|
|
#include "MessageType/Chat.h"
|
|
|
|
namespace {
|
|
// A zone ID as three fields: map (u16), instance (u16), clone (u32)
|
|
void WriteZone(RakNet::BitStream& bitStream, const LWOZONEID& zoneID) {
|
|
bitStream.Write(zoneID.GetMapID());
|
|
bitStream.Write(zoneID.GetInstanceID());
|
|
bitStream.Write(zoneID.GetCloneID());
|
|
}
|
|
|
|
bool ReadZone(RakNet::BitStream& bitStream, LWOZONEID& zoneID) {
|
|
LWOMAPID mapID{};
|
|
LWOINSTANCEID instanceID{};
|
|
LWOCLONEID cloneID{};
|
|
VALIDATE_READ(bitStream.Read(mapID));
|
|
VALIDATE_READ(bitStream.Read(instanceID));
|
|
VALIDATE_READ(bitStream.Read(cloneID));
|
|
zoneID = LWOZONEID(mapID, instanceID, cloneID);
|
|
return true;
|
|
}
|
|
|
|
// The LUWString fills the rest of the stream (a message whose length isn't in the packet)
|
|
bool ReadRemainingWString(RakNet::BitStream& bitStream, LUWString& value) {
|
|
value.size = static_cast<uint32_t>(BITS_TO_BYTES(bitStream.GetNumberOfUnreadBits()) / sizeof(char16_t));
|
|
return value.size == 0 || bitStream.Read(value);
|
|
}
|
|
|
|
// Player and team packets from the client all start with the player's object ID and 4 unused bytes
|
|
bool ReadPlayerHeader(RakNet::BitStream& bitStream, LWOOBJID& playerID, uint32_t& unknown) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(bitStream.Read(unknown));
|
|
return true;
|
|
}
|
|
}
|
|
|
|
namespace ChatPackets {
|
|
void LoginSessionNotify::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, playerName);
|
|
WriteZone(bitStream, zoneID);
|
|
bitStream.Write(muteExpire);
|
|
bitStream.Write(gmLevel);
|
|
// Only on a resync, so every other one is byte for byte what it always was
|
|
if (resync) bitStream.Write<uint8_t>(1);
|
|
}
|
|
|
|
bool LoginSessionNotify::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, playerName, MAX_NAME_LENGTH));
|
|
VALIDATE_READ(ReadZone(bitStream, zoneID));
|
|
VALIDATE_READ(bitStream.Read(muteExpire));
|
|
VALIDATE_READ(bitStream.Read(gmLevel));
|
|
uint8_t resyncValue{};
|
|
resync = bitStream.GetNumberOfUnreadBits() >= 8 && bitStream.Read(resyncValue) && resyncValue != 0;
|
|
return true;
|
|
}
|
|
|
|
void UnexpectedDisconnect::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
}
|
|
|
|
bool UnexpectedDisconnect::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
return true;
|
|
}
|
|
|
|
void GMLevelUpdate::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(gmLevel);
|
|
}
|
|
|
|
bool GMLevelUpdate::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(bitStream.Read(gmLevel));
|
|
return true;
|
|
}
|
|
|
|
void GMMute::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(expire);
|
|
}
|
|
|
|
bool GMMute::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(bitStream.Read(expire));
|
|
return true;
|
|
}
|
|
|
|
void Announcement::Serialize(RakNet::BitStream& bitStream) const {
|
|
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, title);
|
|
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, message);
|
|
}
|
|
|
|
bool Announcement::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, title));
|
|
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, message));
|
|
return true;
|
|
}
|
|
|
|
void CreateTeam::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(leaderID);
|
|
bitStream.Write<uint64_t>(members.size());
|
|
for (const auto member : members) bitStream.Write(member);
|
|
WriteZone(bitStream, zoneID);
|
|
}
|
|
|
|
bool CreateTeam::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(leaderID));
|
|
uint64_t count{};
|
|
VALIDATE_READ(bitStream.Read(count));
|
|
if (count > MAX_MEMBERS) return false;
|
|
members.resize(count);
|
|
for (auto& member : members) VALIDATE_READ(bitStream.Read(member));
|
|
VALIDATE_READ(ReadZone(bitStream, zoneID));
|
|
return true;
|
|
}
|
|
|
|
void TeamUpdate::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(teamID);
|
|
bitStream.Write(deleteTeam);
|
|
if (deleteTeam) return;
|
|
bitStream.Write(lootFlag);
|
|
bitStream.Write<uint8_t>(members.size());
|
|
for (const auto member : members) bitStream.Write(member);
|
|
}
|
|
|
|
bool TeamUpdate::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(teamID));
|
|
VALIDATE_READ(bitStream.Read(deleteTeam));
|
|
if (deleteTeam) return true;
|
|
VALIDATE_READ(bitStream.Read(lootFlag));
|
|
uint8_t count{};
|
|
VALIDATE_READ(bitStream.Read(count));
|
|
members.resize(count);
|
|
for (auto& member : members) VALIDATE_READ(bitStream.Read(member));
|
|
return true;
|
|
}
|
|
|
|
void AchievementNotify::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write<uint64_t>(0); // Packing
|
|
bitStream.Write<uint32_t>(0); // Packing
|
|
bitStream.Write<uint8_t>(0); // Packing
|
|
bitStream.Write(earnerName);
|
|
bitStream.Write<uint64_t>(0); // Packing / No way to know meaning because of not enough data.
|
|
bitStream.Write<uint32_t>(0); // Packing / No way to know meaning because of not enough data.
|
|
bitStream.Write<uint16_t>(0); // Packing / No way to know meaning because of not enough data.
|
|
bitStream.Write<uint8_t>(0); // Packing / No way to know meaning because of not enough data.
|
|
bitStream.Write(missionEmailID);
|
|
bitStream.Write(earningPlayerID);
|
|
bitStream.Write(targetPlayerName);
|
|
}
|
|
|
|
bool AchievementNotify::Deserialize(RakNet::BitStream& bitStream) {
|
|
bitStream.IgnoreBytes(13);
|
|
VALIDATE_READ(bitStream.Read(earnerName));
|
|
bitStream.IgnoreBytes(15);
|
|
VALIDATE_READ(bitStream.Read(missionEmailID));
|
|
VALIDATE_READ(bitStream.Read(earningPlayerID));
|
|
VALIDATE_READ(bitStream.Read(targetPlayerName));
|
|
return true;
|
|
}
|
|
|
|
void MailNotify::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(receiverID);
|
|
}
|
|
|
|
bool MailNotify::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(receiverID));
|
|
return true;
|
|
}
|
|
|
|
void ShowAllRequest::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(requestor);
|
|
bitStream.Write(displayZoneData);
|
|
bitStream.Write(displayIndividualPlayers);
|
|
}
|
|
|
|
bool ShowAllRequest::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(requestor));
|
|
VALIDATE_READ(bitStream.Read(displayZoneData));
|
|
VALIDATE_READ(bitStream.Read(displayIndividualPlayers));
|
|
return true;
|
|
}
|
|
|
|
void FindPlayerRequest::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(requestor);
|
|
bitStream.Write(playerName);
|
|
}
|
|
|
|
bool FindPlayerRequest::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(requestor));
|
|
VALIDATE_READ(bitStream.Read(playerName));
|
|
return true;
|
|
}
|
|
|
|
void GetFriendsList::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
}
|
|
|
|
bool GetFriendsList::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
return true;
|
|
}
|
|
|
|
void AddFriendRequest::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(friendName);
|
|
bitStream.Write(isBestFriendRequest);
|
|
}
|
|
|
|
bool AddFriendRequest::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(friendName));
|
|
VALIDATE_READ(bitStream.Read(isBestFriendRequest));
|
|
return true;
|
|
}
|
|
|
|
void AddFriendResponse::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(responseCode);
|
|
bitStream.Write(friendName);
|
|
}
|
|
|
|
bool AddFriendResponse::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(responseCode));
|
|
VALIDATE_READ(bitStream.Read(friendName));
|
|
return true;
|
|
}
|
|
|
|
void RemoveFriend::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(friendName);
|
|
}
|
|
|
|
bool RemoveFriend::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(friendName));
|
|
return true;
|
|
}
|
|
|
|
void GetIgnoreList::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
}
|
|
|
|
bool GetIgnoreList::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
return true;
|
|
}
|
|
|
|
void AddIgnore::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(playerName);
|
|
}
|
|
|
|
bool AddIgnore::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(playerName));
|
|
return true;
|
|
}
|
|
|
|
void RemoveIgnore::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(playerName);
|
|
}
|
|
|
|
bool RemoveIgnore::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(playerName));
|
|
return true;
|
|
}
|
|
|
|
void GeneralChatMessage::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(chatChannel);
|
|
bitStream.Write(messageLength);
|
|
bitStream.Write(senderName);
|
|
bitStream.Write(senderID);
|
|
bitStream.Write(sourceID);
|
|
bitStream.Write(senderGMLevel);
|
|
bitStream.Write(message);
|
|
}
|
|
|
|
bool GeneralChatMessage::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(chatChannel));
|
|
VALIDATE_READ(bitStream.Read(messageLength));
|
|
if (messageLength > MAX_MESSAGE_LENGTH) return false;
|
|
VALIDATE_READ(bitStream.Read(senderName));
|
|
VALIDATE_READ(bitStream.Read(senderID));
|
|
VALIDATE_READ(bitStream.Read(sourceID));
|
|
VALIDATE_READ(bitStream.Read(senderGMLevel));
|
|
message = LUWString(messageLength);
|
|
if (messageLength != 0) VALIDATE_READ(bitStream.Read(message));
|
|
return true;
|
|
}
|
|
|
|
void PrivateChatMessage::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(chatChannel);
|
|
bitStream.Write(messageLength);
|
|
bitStream.Write(senderName);
|
|
bitStream.Write(senderID);
|
|
bitStream.Write(sourceID);
|
|
bitStream.Write(senderGMLevel);
|
|
bitStream.Write(receiverName);
|
|
bitStream.Write(receiverGMLevel);
|
|
bitStream.Write(responseCode);
|
|
bitStream.Write(message);
|
|
}
|
|
|
|
bool PrivateChatMessage::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(chatChannel));
|
|
VALIDATE_READ(bitStream.Read(messageLength));
|
|
if (messageLength > MAX_MESSAGE_LENGTH) return false;
|
|
VALIDATE_READ(bitStream.Read(senderName));
|
|
VALIDATE_READ(bitStream.Read(senderID));
|
|
VALIDATE_READ(bitStream.Read(sourceID));
|
|
VALIDATE_READ(bitStream.Read(senderGMLevel));
|
|
VALIDATE_READ(bitStream.Read(receiverName));
|
|
VALIDATE_READ(bitStream.Read(receiverGMLevel));
|
|
VALIDATE_READ(bitStream.Read(responseCode));
|
|
message = LUWString(messageLength);
|
|
if (messageLength != 0) VALIDATE_READ(bitStream.Read(message));
|
|
return true;
|
|
}
|
|
|
|
void TeamInvite::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(invitedPlayer);
|
|
}
|
|
|
|
bool TeamInvite::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(invitedPlayer));
|
|
return true;
|
|
}
|
|
|
|
void TeamInviteResponse::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(declined);
|
|
bitStream.Write(leaderID);
|
|
}
|
|
|
|
bool TeamInviteResponse::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(declined));
|
|
VALIDATE_READ(bitStream.Read(leaderID));
|
|
return true;
|
|
}
|
|
|
|
void TeamLeave::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
}
|
|
|
|
bool TeamLeave::Deserialize(RakNet::BitStream& bitStream) {
|
|
return ReadPlayerHeader(bitStream, playerID, unknown);
|
|
}
|
|
|
|
void TeamKick::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(kickedPlayer);
|
|
}
|
|
|
|
bool TeamKick::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(kickedPlayer));
|
|
return true;
|
|
}
|
|
|
|
void TeamSetLeader::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(promotedPlayer);
|
|
}
|
|
|
|
bool TeamSetLeader::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(promotedPlayer));
|
|
return true;
|
|
}
|
|
|
|
void TeamSetLoot::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(lootFlag);
|
|
}
|
|
|
|
bool TeamSetLoot::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(lootFlag));
|
|
return true;
|
|
}
|
|
|
|
void TeamGetStatus::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
}
|
|
|
|
bool TeamGetStatus::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
return true;
|
|
}
|
|
|
|
void RequestMinimumChatMode::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(chatChannel);
|
|
}
|
|
|
|
bool RequestMinimumChatMode::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(chatChannel));
|
|
return true;
|
|
}
|
|
|
|
void RequestMinimumChatModePrivate::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(chatChannel);
|
|
bitStream.Write(recipientName);
|
|
}
|
|
|
|
bool RequestMinimumChatModePrivate::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(ReadPlayerHeader(bitStream, playerID, unknown));
|
|
VALIDATE_READ(bitStream.Read(chatChannel));
|
|
VALIDATE_READ(bitStream.Read(recipientName));
|
|
return true;
|
|
}
|
|
}
|
|
|
|
namespace ChatPackets::Client {
|
|
void GeneralChatMessage::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(chatChannel);
|
|
bitStream.Write<uint32_t>(message.size());
|
|
bitStream.Write(senderName);
|
|
bitStream.Write(senderID);
|
|
bitStream.Write(sourceID);
|
|
bitStream.Write(senderGMLevel);
|
|
bitStream.Write(message);
|
|
bitStream.Write<uint16_t>(0); // terminator
|
|
}
|
|
|
|
bool GeneralChatMessage::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(unknown));
|
|
VALIDATE_READ(bitStream.Read(chatChannel));
|
|
uint32_t length{};
|
|
VALIDATE_READ(bitStream.Read(length));
|
|
if (length > MAX_MESSAGE_LENGTH) return false;
|
|
VALIDATE_READ(bitStream.Read(senderName));
|
|
VALIDATE_READ(bitStream.Read(senderID));
|
|
VALIDATE_READ(bitStream.Read(sourceID));
|
|
VALIDATE_READ(bitStream.Read(senderGMLevel));
|
|
message.resize(length);
|
|
if (length != 0) VALIDATE_READ(bitStream.ReadBits(reinterpret_cast<unsigned char*>(message.data()), BYTES_TO_BITS(length * sizeof(char16_t)), true));
|
|
uint16_t terminator{};
|
|
VALIDATE_READ(bitStream.Read(terminator));
|
|
return true;
|
|
}
|
|
|
|
void PrivateChatMessage::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(chatChannel);
|
|
bitStream.Write(messageLength);
|
|
bitStream.Write(senderName);
|
|
bitStream.Write(senderID);
|
|
bitStream.Write(sourceID);
|
|
bitStream.Write(senderGMLevel);
|
|
bitStream.Write(receiverName);
|
|
bitStream.Write(receiverGMLevel);
|
|
bitStream.Write(responseCode);
|
|
bitStream.Write(message);
|
|
}
|
|
|
|
bool PrivateChatMessage::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(bitStream.Read(chatChannel));
|
|
VALIDATE_READ(bitStream.Read(messageLength));
|
|
VALIDATE_READ(bitStream.Read(senderName));
|
|
VALIDATE_READ(bitStream.Read(senderID));
|
|
VALIDATE_READ(bitStream.Read(sourceID));
|
|
VALIDATE_READ(bitStream.Read(senderGMLevel));
|
|
VALIDATE_READ(bitStream.Read(receiverName));
|
|
VALIDATE_READ(bitStream.Read(receiverGMLevel));
|
|
VALIDATE_READ(bitStream.Read(responseCode));
|
|
VALIDATE_READ(ReadRemainingWString(bitStream, message));
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void ChatPackets::SendSystemMessage(const SystemAddress& sysAddr, const std::string& message, const bool broadcast) {
|
|
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(message), broadcast);
|
|
}
|
|
|
|
void ChatPackets::SendSystemMessage(const SystemAddress& sysAddr, const std::u16string& message, const bool broadcast) {
|
|
Client::GeneralChatMessage chatMessage;
|
|
chatMessage.chatChannel = 4;
|
|
chatMessage.senderName = LUWString("", 33);
|
|
chatMessage.message = message;
|
|
|
|
RakNet::BitStream bitStream;
|
|
chatMessage.WritePacket(bitStream);
|
|
// A message with an address goes only to that client (so Wincent's announcement works)
|
|
Game::server->Send(bitStream, sysAddr, sysAddr == UNASSIGNED_SYSTEM_ADDRESS);
|
|
}
|
|
|
|
void ChatPackets::RoutedFromClient::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(senderID);
|
|
for (const auto byte : data) bitStream.Write(byte);
|
|
}
|
|
|
|
bool ChatPackets::RoutedFromClient::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(senderID));
|
|
data.resize(BITS_TO_BYTES(bitStream.GetNumberOfUnreadBits()));
|
|
if (!data.empty()) VALIDATE_READ(bitStream.ReadBits(data.data(), BYTES_TO_BITS(data.size()), true));
|
|
return true;
|
|
}
|
|
|
|
// ---- Guilds ----
|
|
|
|
void ChatPackets::GuildInvite::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(invitedPlayer);
|
|
}
|
|
|
|
bool ChatPackets::GuildInvite::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(bitStream.Read(unknown));
|
|
VALIDATE_READ(bitStream.Read(invitedPlayer));
|
|
return true;
|
|
}
|
|
|
|
void ChatPackets::GuildInviteResponse::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(declined);
|
|
}
|
|
|
|
bool ChatPackets::GuildInviteResponse::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(bitStream.Read(unknown));
|
|
VALIDATE_READ(bitStream.Read(declined));
|
|
return true;
|
|
}
|
|
|
|
void ChatPackets::GuildLeave::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
}
|
|
|
|
bool ChatPackets::GuildLeave::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(bitStream.Read(unknown));
|
|
return true;
|
|
}
|
|
|
|
void ChatPackets::GuildGetAll::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
}
|
|
|
|
bool ChatPackets::GuildGetAll::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(bitStream.Read(unknown));
|
|
return true;
|
|
}
|
|
|
|
void ChatPackets::GuildCreate::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(guildName);
|
|
}
|
|
|
|
bool ChatPackets::GuildCreate::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(bitStream.Read(guildName));
|
|
return true;
|
|
}
|
|
|
|
void ChatPackets::GuildKick::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(unknown);
|
|
bitStream.Write(kickedPlayer);
|
|
}
|
|
|
|
bool ChatPackets::GuildKick::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(bitStream.Read(unknown));
|
|
VALIDATE_READ(bitStream.Read(kickedPlayer));
|
|
return true;
|
|
}
|
|
|
|
void ChatPackets::GuildSetRank::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(targetPlayer);
|
|
bitStream.Write(rank);
|
|
}
|
|
|
|
bool ChatPackets::GuildSetRank::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(bitStream.Read(targetPlayer));
|
|
VALIDATE_READ(bitStream.Read(rank));
|
|
return true;
|
|
}
|
|
|
|
void ChatPackets::GuildDisband::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
}
|
|
|
|
bool ChatPackets::GuildDisband::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
return true;
|
|
}
|
|
|
|
void ChatPackets::GuildStatus::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(characterID);
|
|
bitStream.Write(guildID);
|
|
bitStream.Write(guildName);
|
|
}
|
|
|
|
bool ChatPackets::GuildStatus::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(characterID));
|
|
VALIDATE_READ(bitStream.Read(guildID));
|
|
VALIDATE_READ(bitStream.Read(guildName));
|
|
return true;
|
|
}
|