diff --git a/dGame/dUtilities/Mail.cpp b/dGame/dUtilities/Mail.cpp index e2ffbf79..f333851d 100644 --- a/dGame/dUtilities/Mail.cpp +++ b/dGame/dUtilities/Mail.cpp @@ -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(playerMail.size()); // size - bitStream.Write(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(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(mail.timeSent); // expiration date - bitStream.Write(mail.timeSent);// send date - bitStream.Write(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); diff --git a/dGame/dUtilities/Mail.h b/dGame/dUtilities/Mail.h index 07c3e37f..6a78f47a 100644 --- a/dGame/dUtilities/Mail.h +++ b/dGame/dUtilities/Mail.h @@ -1,40 +1,185 @@ -#pragma once +#ifndef __MAIL_H__ +#define __MAIL_H__ + +#include #include "BitStream.h" #include "RakNetTypes.h" #include "dCommonVars.h" +template +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 header = LUHeader(eConnectionType::CLIENT, MessageType::Client::MAIL); + MailMessageID messageID; + }; + + struct Data { + MailLUHeader header; + uint32_t throttled = 0; + std::vector playerMail; + + Data() = delete; + Data(std::vector 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 data) { + this->Write>(data.header); + this->Write(static_cast(data.messageID)); + } + + template <> + inline void RakNet::BitStream::Write(Mail::Data data) { + + this->Write(data.header); + this->Write(data.throttled); + + this->Write(data.playerMail.size()); + this->Write(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(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(mail.timeSent); // expiration date + this->Write(mail.timeSent);// send date + this->Write(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 data) { + this->Write(data.header); + this->Write(static_cast(data.response)); + } + + template <> + inline void RakNet::BitStream::Write(Mail::Notification data) { + this->Write(data.header); + this->Write(data.notification); + this->Write(0); // unused + this->Write(0); // unused + this->Write(data.auctionID); + this->Write(0); // unused + this->Write(data.mailCount); + } + + template <> + inline void RakNet::BitStream::Write(Mail::AttachmentCollect data) { + this->Write(data.header); + this->Write(data.status); + this->Write(data.mailID); + } + + template <> + inline void RakNet::BitStream::Write(Mail::DeleteMail data) { + this->Write(data.header); + this->Write(data.status); + this->Write(data.mailID); + } + + template <> + inline void RakNet::BitStream::Write(Mail::Read data) { + this->Write(data.header); + this->Write(data.status); + this->Write(data.mailID); + } +} + +#endif // !__MAIL_H__ diff --git a/dNet/BitStreamUtils.h b/dNet/BitStreamUtils.h index 33fde564..d55df14a 100644 --- a/dNet/BitStreamUtils.h +++ b/dNet/BitStreamUtils.h @@ -2,11 +2,18 @@ #define __BITSTREAMUTILS__H__ #include "GeneralUtils.h" -#include "MessageIdentifiers.h" #include "BitStream.h" #include #include +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 +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 void WriteHeader(RakNet::BitStream& bitStream, eConnectionType connectionType, T internalPacketID) { @@ -53,7 +73,6 @@ namespace BitStreamUtils { bitStream.Write(static_cast(internalPacketID)); bitStream.Write(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 value) { + this->Write(value.messageID); + this->Write(value.connectionType); + this->Write(static_cast(value.internalPacketID)); + this->Write(0); + } + + template <> + inline void RakNet::BitStream::Write>(LUHeader value) { + this->Write(value.messageID); + this->Write(value.connectionType); + this->Write(static_cast(value.internalPacketID)); + this->Write(0); + } + + template <> + inline void RakNet::BitStream::Write>(LUHeader value) { + this->Write(value.messageID); + this->Write(value.connectionType); + this->Write(static_cast(value.internalPacketID)); + this->Write(0); + } + + template <> + inline void RakNet::BitStream::Write>(LUHeader value) { + this->Write(value.messageID); + this->Write(value.connectionType); + this->Write(static_cast(value.internalPacketID)); + this->Write(0); + } + + template <> + inline void RakNet::BitStream::Write>(LUHeader value) { + this->Write(value.messageID); + this->Write(value.connectionType); + this->Write(static_cast(value.internalPacketID)); + this->Write(0); + } }; #endif //!__BITSTREAMUTILS__H__ diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 6a596960..a467ac0f 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -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; }