First pass

This commit is contained in:
Aaron Kimbre 2025-01-08 14:01:09 -06:00
parent 23551d4ed8
commit 6cd1310460
4 changed files with 336 additions and 98 deletions

View File

@ -94,7 +94,7 @@ void Mail::SendMail(const LWOOBJID sender, const std::string& senderName, LWOOBJ
SendNotification(sysAddr, 1); //Show the "one new mail" message
}
void Mail::HandleMailStuff(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* entity) {
void Mail::HandleMail(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* entity) {
int mailStuffID = 0;
packet.Read(mailStuffID);
@ -142,7 +142,7 @@ void Mail::HandleSendMail(RakNet::BitStream& packet, const SystemAddress& sysAdd
u"This character has restricted mail access."
);
Mail::SendSendResponse(sysAddr, Mail::MailSendResponse::AccountIsMuted);
Mail::SendSendResponse(sysAddr, Mail::MailSendResponse::SenderAccountIsMuted);
return;
}
@ -243,50 +243,9 @@ void Mail::HandleSendMail(RakNet::BitStream& packet, const SystemAddress& sysAdd
void Mail::HandleDataRequest(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* player) {
auto playerMail = Database::Get()->GetMailForPlayer(player->GetCharacter()->GetID(), 20);
RakNet::BitStream bitStream;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::MAIL);
bitStream.Write(int(MailMessageID::MailData));
bitStream.Write(int(0)); // throttled
bitStream.Write<uint16_t>(playerMail.size()); // size
bitStream.Write<uint16_t>(0);
for (const auto& mail : playerMail) {
bitStream.Write(mail.id); //MailID
const LUWString subject(mail.subject, 50);
bitStream.Write(subject); //subject
const LUWString body(mail.body, 400);
bitStream.Write(body); //body
const LUWString sender(mail.senderUsername, 32);
bitStream.Write(sender); //sender
bitStream.Write(uint32_t(0)); // packing
bitStream.Write(uint64_t(0)); // attachedCurrency
bitStream.Write(mail.itemID); //Attachment ID
LOT lot = mail.itemLOT;
if (lot <= 0) bitStream.Write(LOT(-1));
else bitStream.Write(lot);
bitStream.Write(uint32_t(0)); // packing
bitStream.Write(mail.itemSubkey); // Attachment subKey
bitStream.Write<uint16_t>(mail.itemCount); // Attachment count
bitStream.Write(uint8_t(0)); // subject type (used for auction)
bitStream.Write(uint8_t(0)); // packing
bitStream.Write(uint32_t(0)); // packing
bitStream.Write<uint64_t>(mail.timeSent); // expiration date
bitStream.Write<uint64_t>(mail.timeSent);// send date
bitStream.Write<uint8_t>(mail.wasRead); //was read
bitStream.Write(uint8_t(0)); // isLocalized
bitStream.Write(uint16_t(0)); // packing
bitStream.Write(uint32_t(0)); // packing
}
Mail::Data data = Mail::Data(playerMail);
bitStream.Write(data);
Game::server->Send(bitStream, sysAddr, false);
}
@ -348,46 +307,28 @@ void Mail::HandleNotificationRequest(const SystemAddress& sysAddr, uint32_t obje
void Mail::SendSendResponse(const SystemAddress& sysAddr, MailSendResponse response) {
RakNet::BitStream bitStream;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::MAIL);
bitStream.Write(int(MailMessageID::SendResponse));
bitStream.Write(int(response));
Mail::Response data = Mail::Response(response);
bitStream.Write(data);
Game::server->Send(bitStream, sysAddr, false);
}
void Mail::SendNotification(const SystemAddress& sysAddr, int mailCount) {
RakNet::BitStream bitStream;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::MAIL);
uint64_t messageType = 2;
uint64_t s1 = 0;
uint64_t s2 = 0;
uint64_t s3 = 0;
uint64_t s4 = 0;
bitStream.Write(messageType);
bitStream.Write(s1);
bitStream.Write(s2);
bitStream.Write(s3);
bitStream.Write(s4);
bitStream.Write(mailCount);
bitStream.Write(int(0)); //Unknown
Mail::Notification data = Mail::Notification(MailNotification::NewMail, mailCount);
Game::server->Send(bitStream, sysAddr, false);
}
void Mail::SendAttachmentRemoveConfirm(const SystemAddress& sysAddr, uint64_t mailID) {
RakNet::BitStream bitStream;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::MAIL);
bitStream.Write(int(MailMessageID::AttachmentCollectConfirm));
bitStream.Write(int(0)); //unknown
bitStream.Write(mailID);
AttachmentCollect data = AttachmentCollect(MailRemoveAttachment::Success, mailID);
bitStream.Write(data);
Game::server->Send(bitStream, sysAddr, false);
}
void Mail::SendDeleteConfirm(const SystemAddress& sysAddr, uint64_t mailID, LWOOBJID playerID) {
RakNet::BitStream bitStream;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::MAIL);
bitStream.Write(int(MailMessageID::MailDeleteConfirm));
bitStream.Write(int(0)); //unknown
bitStream.Write(mailID);
DeleteMail data = DeleteMail(MailDeleteResponse::Success, mailID);
bitStream.Write(data);
Game::server->Send(bitStream, sysAddr, false);
Database::Get()->DeleteMail(mailID);
@ -395,10 +336,8 @@ void Mail::SendDeleteConfirm(const SystemAddress& sysAddr, uint64_t mailID, LWOO
void Mail::SendReadConfirm(const SystemAddress& sysAddr, uint64_t mailID) {
RakNet::BitStream bitStream;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::MAIL);
bitStream.Write(int(MailMessageID::MailReadConfirm));
bitStream.Write(int(0)); //unknown
bitStream.Write(mailID);
Read data = Read(MailReadResponse::Success, mailID);
bitStream.Write(data);
Game::server->Send(bitStream, sysAddr, false);
Database::Get()->MarkMailRead(mailID);

View File

@ -1,40 +1,185 @@
#pragma once
#ifndef __MAIL_H__
#define __MAIL_H__
#include <cstdint>
#include "BitStream.h"
#include "RakNetTypes.h"
#include "dCommonVars.h"
template <typename T>
struct LUHeader;
class Entity;
namespace Mail {
enum class MailMessageID {
Send = 0x00,
SendResponse = 0x01,
DataRequest = 0x03,
MailData = 0x04,
AttachmentCollect = 0x05,
AttachmentCollectConfirm = 0x06,
MailDelete = 0x07,
MailDeleteConfirm = 0x08,
MailRead = 0x09,
MailReadConfirm = 0x0a,
NotificationRequest = 0x0b
enum class MailMessageID : uint32_t {
Send = 0,
SendResponse,
Notification,
DataRequest,
MailData,
AttachmentCollect,
AttachmentCollectConfirm,
MailDelete,
MailDeleteConfirm,
MailRead,
MailReadConfirm,
NotificationRequest,
AuctionCreate,
AuctionCreationResponse,
AuctionCancel,
AuctionCancelResponse,
AuctionList,
AuctionListResponse,
AuctionBid,
AuctionBidResponse,
UnknownError
};
enum class MailSendResponse {
enum class MailSendResponse : uint32_t {
Success = 0,
NotEnoughCoins,
AttachmentNotFound,
ItemCannotBeMailed,
CannotMailSelf,
RecipientNotFound,
DifferentFaction,
Unknown,
RecipientDifferentFaction,
UnHandled7,
ModerationFailure,
AccountIsMuted,
UnknownFailure,
SenderAccountIsMuted,
UnHandled10,
RecipientIsIgnored,
UnknownFailure3,
RecipientIsFTP
UnHandled12,
RecipientIsFTP,
UnknownError
};
enum class MailDeleteResponse : uint32_t {
Success = 0,
HasAttachements,
NotFoud,
Throttled,
UnknownError
};
enum class MailRemoveAttachment : uint32_t {
Success = 0,
AttachmentNotFound,
NoSpaceInInventory,
MailNotFound,
Throttled,
UnknownError
};
enum class MailNotification : uint32_t {
NewMail = 0,
UnHandled,
AuctionWon,
AuctionSold,
AuctionOutbided,
AuctionExpired,
AuctionCancelled,
AuctionUpdated,
UnknownError
};
enum class MailReadResponse : uint32_t {
Success = 0,
UnknownError
};
struct MailInfo {
uint64_t id;
std::string senderUsername;
std::string recipient;
std::string subject;
std::string body;
uint32_t senderId;
uint32_t receiverId;
uint32_t itemCount;
uint32_t itemID;
LOT itemLOT;
LWOOBJID itemSubkey;
};
struct MailLUHeader {
LUHeader<MessageType::Client> header = LUHeader<MessageType::Client>(eConnectionType::CLIENT, MessageType::Client::MAIL);
MailMessageID messageID;
};
struct Data {
MailLUHeader header;
uint32_t throttled = 0;
std::vector<IMail::MailInfo> playerMail;
Data() = delete;
Data(std::vector<IMail::MailInfo> mailData) {
this->header.messageID = MailMessageID::MailData;
this->playerMail = mailData;
}
};
struct Response {
MailLUHeader header;
MailSendResponse response;
Response() = delete;
Response(MailSendResponse response) {
this->header.messageID = MailMessageID::SendResponse;
this->response = response;
}
};
struct Notification {
MailLUHeader header;
MailNotification notification;
LWOOBJID auctionID = 0;
uint32_t mailCount = 0;
Notification() = delete;
Notification(MailNotification notification, uint32_t mailCount, LWOOBJID auctionID = LWOOBJID_EMPTY) {
this->header.messageID = MailMessageID::Notification;
this->notification = notification;
this->auctionID = auctionID;
this->mailCount = mailCount;
}
};
struct AttachmentCollect {
MailLUHeader header;
MailRemoveAttachment status;
uint64_t mailID;
AttachmentCollect() = delete;
AttachmentCollect(MailRemoveAttachment status, uint64_t mailID) {
this->header.messageID = MailMessageID::AttachmentCollect;
this->status = status;
this->mailID = mailID;
}
};
struct DeleteMail {
MailLUHeader header;
MailDeleteResponse status;
uint64_t mailID;
DeleteMail() = delete;
DeleteMail(MailDeleteResponse status, uint64_t mailID) {
this->status = status;
this->mailID = mailID;
}
};
struct Read {
MailLUHeader header;
MailReadResponse status;
uint64_t mailID;
Read() = delete;
Read(MailReadResponse status, uint64_t mailID) {
this->status = status;
this->mailID = mailID;
}
};
const std::string ServerName = "Darkflame Universe";
@ -79,7 +224,7 @@ namespace Mail {
const SystemAddress& sysAddr
);
void HandleMailStuff(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* entity);
void HandleMail(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* entity);
void HandleSendMail(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* entity);
void HandleDataRequest(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* player);
void HandleAttachmentCollect(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* player);
@ -93,3 +238,98 @@ namespace Mail {
void SendDeleteConfirm(const SystemAddress& sysAddr, uint64_t mailID, LWOOBJID playerID);
void SendReadConfirm(const SystemAddress& sysAddr, uint64_t mailID);
};
namespace RakNet {
template <>
inline void RakNet::BitStream::Write<Mail::MailLUHeader>(Mail::MailLUHeader data) {
this->Write<LUHeader<MessageType::Client>>(data.header);
this->Write<uint32_t>(static_cast<uint32_t>(data.messageID));
}
template <>
inline void RakNet::BitStream::Write<Mail::Data>(Mail::Data data) {
this->Write<Mail::MailLUHeader>(data.header);
this->Write(data.throttled);
this->Write<uint16_t>(data.playerMail.size());
this->Write<uint16_t>(0); // packing
for (auto& mail : data.playerMail) {
this->Write(mail.id);
const LUWString subject(mail.subject, 50);
this->Write(subject);
const LUWString body(mail.body, 400);
this->Write(body);
const LUWString sender(mail.senderUsername, 32);
this->Write(sender);
this->Write(uint32_t(0)); // packing
this->Write(uint64_t(0)); // attachedCurrency
this->Write(mail.itemID);
LOT lot = mail.itemLOT;
if (lot <= 0) this->Write(LOT(-1));
else this->Write(lot);
this->Write(uint32_t(0)); // packing
this->Write(mail.itemSubkey);
this->Write<uint16_t>(mail.itemCount);
this->Write(uint8_t(0)); // subject type (used for auction)
this->Write(uint8_t(0)); // packing
this->Write(uint32_t(0)); // packing
this->Write<uint64_t>(mail.timeSent); // expiration date
this->Write<uint64_t>(mail.timeSent);// send date
this->Write<uint8_t>(mail.wasRead); // was read
this->Write(uint8_t(0)); // isLocalized
this->Write(uint16_t(0)); // packing
this->Write(uint32_t(0)); // packing
}
}
template <>
inline void RakNet::BitStream::Write<Mail::Response>(Mail::Response data) {
this->Write<Mail::MailLUHeader>(data.header);
this->Write<uint32_t>(static_cast<uint32_t>(data.response));
}
template <>
inline void RakNet::BitStream::Write<Mail::Notification>(Mail::Notification data) {
this->Write<Mail::MailLUHeader>(data.header);
this->Write(data.notification);
this->Write<uint64_t>(0); // unused
this->Write<uint64_t>(0); // unused
this->Write(data.auctionID);
this->Write<uint64_t>(0); // unused
this->Write(data.mailCount);
}
template <>
inline void RakNet::BitStream::Write<Mail::AttachmentCollect>(Mail::AttachmentCollect data) {
this->Write<Mail::MailLUHeader>(data.header);
this->Write(data.status);
this->Write(data.mailID);
}
template <>
inline void RakNet::BitStream::Write<Mail::DeleteMail>(Mail::DeleteMail data) {
this->Write<Mail::MailLUHeader>(data.header);
this->Write(data.status);
this->Write(data.mailID);
}
template <>
inline void RakNet::BitStream::Write<Mail::Read>(Mail::Read data) {
this->Write<Mail::MailLUHeader>(data.header);
this->Write(data.status);
this->Write(data.mailID);
}
}
#endif // !__MAIL_H__

View File

@ -2,11 +2,18 @@
#define __BITSTREAMUTILS__H__
#include "GeneralUtils.h"
#include "MessageIdentifiers.h"
#include "BitStream.h"
#include <string>
#include <algorithm>
namespace MessageType {
enum class Auth : uint32_t;
enum class Client : uint32_t;
enum class Server : uint32_t;
enum class World : uint32_t;
enum class Master : uint32_t;
}
enum class eConnectionType : uint16_t;
struct LUString {
@ -45,6 +52,19 @@ struct LUWString {
};
};
template <typename T>
struct LUHeader {
MessageID messageID;
eConnectionType connectionType;
T internalPacketID;
LUHeader(eConnectionType connectionType, T internalPacketID, MessageID messageID = ID_USER_PACKET_ENUM) {
this->messageID = messageID;
this->connectionType = connectionType;
this->internalPacketID = internalPacketID;
};
};
namespace BitStreamUtils {
template<typename T>
void WriteHeader(RakNet::BitStream& bitStream, eConnectionType connectionType, T internalPacketID) {
@ -53,7 +73,6 @@ namespace BitStreamUtils {
bitStream.Write(static_cast<uint32_t>(internalPacketID));
bitStream.Write<uint8_t>(0);
}
}
namespace RakNet {
@ -100,6 +119,46 @@ namespace RakNet {
value.string.resize(value.size);
this->Write(value.string);
}
template <>
inline void RakNet::BitStream::Write<LUHeader<MessageType::Auth>>(LUHeader<MessageType::Auth> value) {
this->Write<MessageID>(value.messageID);
this->Write<eConnectionType>(value.connectionType);
this->Write<uint32_t>(static_cast<uint32_t>(value.internalPacketID));
this->Write<uint8_t>(0);
}
template <>
inline void RakNet::BitStream::Write<LUHeader<MessageType::Client>>(LUHeader<MessageType::Client> value) {
this->Write<MessageID>(value.messageID);
this->Write<eConnectionType>(value.connectionType);
this->Write<uint32_t>(static_cast<uint32_t>(value.internalPacketID));
this->Write<uint8_t>(0);
}
template <>
inline void RakNet::BitStream::Write<LUHeader<MessageType::Server>>(LUHeader<MessageType::Server> value) {
this->Write<MessageID>(value.messageID);
this->Write<eConnectionType>(value.connectionType);
this->Write<uint32_t>(static_cast<uint32_t>(value.internalPacketID));
this->Write<uint8_t>(0);
}
template <>
inline void RakNet::BitStream::Write<LUHeader<MessageType::World>>(LUHeader<MessageType::World> value) {
this->Write<MessageID>(value.messageID);
this->Write<eConnectionType>(value.connectionType);
this->Write<uint32_t>(static_cast<uint32_t>(value.internalPacketID));
this->Write<uint8_t>(0);
}
template <>
inline void RakNet::BitStream::Write<LUHeader<MessageType::Master>>(LUHeader<MessageType::Master> value) {
this->Write<MessageID>(value.messageID);
this->Write<eConnectionType>(value.connectionType);
this->Write<uint32_t>(static_cast<uint32_t>(value.internalPacketID));
this->Write<uint8_t>(0);
}
};
#endif //!__BITSTREAMUTILS__H__

View File

@ -1189,7 +1189,7 @@ void HandlePacket(Packet* packet) {
// FIXME: Change this to the macro to skip the header...
LWOOBJID space;
bitStream.Read(space);
Mail::HandleMailStuff(bitStream, packet->systemAddress, UserManager::Instance()->GetUser(packet->systemAddress)->GetLastUsedChar()->GetEntity());
Mail::HandleMail(bitStream, packet->systemAddress, UserManager::Instance()->GetUser(packet->systemAddress)->GetLastUsedChar()->GetEntity());
break;
}