diff --git a/dDatabase/GameDatabase/ITables/IMail.h b/dDatabase/GameDatabase/ITables/IMail.h index 239f3cf2..b076a706 100644 --- a/dDatabase/GameDatabase/ITables/IMail.h +++ b/dDatabase/GameDatabase/ITables/IMail.h @@ -24,6 +24,9 @@ public: // Get the number of unread mail for the given character id. virtual uint32_t GetUnreadMailCount(const uint32_t characterId) = 0; + // Get the number of mail for a given character id. + virtual uint32_t GetMailCount(const uint32_t characterId) = 0; + // Mark the given mail as read. virtual void MarkMailRead(const uint64_t mailId) = 0; diff --git a/dDatabase/GameDatabase/MySQL/MySQLDatabase.h b/dDatabase/GameDatabase/MySQL/MySQLDatabase.h index 13f84e9a..9d725762 100644 --- a/dDatabase/GameDatabase/MySQL/MySQLDatabase.h +++ b/dDatabase/GameDatabase/MySQL/MySQLDatabase.h @@ -89,6 +89,7 @@ public: std::vector GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override; std::optional GetMail(const uint64_t mailId) override; uint32_t GetUnreadMailCount(const uint32_t characterId) override; + uint32_t GetMailCount(const uint32_t characterId) override; void MarkMailRead(const uint64_t mailId) override; void DeleteMail(const uint64_t mailId) override; void ClaimMailItem(const uint64_t mailId) override; diff --git a/dDatabase/GameDatabase/MySQL/Tables/Mail.cpp b/dDatabase/GameDatabase/MySQL/Tables/Mail.cpp index 74acb54f..b8735adf 100644 --- a/dDatabase/GameDatabase/MySQL/Tables/Mail.cpp +++ b/dDatabase/GameDatabase/MySQL/Tables/Mail.cpp @@ -71,6 +71,16 @@ uint32_t MySQLDatabase::GetUnreadMailCount(const uint32_t characterId) { return res->getInt("number_unread"); } +uint32_t MySQLDatabase::GetMailCount(const uint32_t characterId) { + auto res = ExecuteSelect("SELECT COUNT(*) AS mail_count FROM mail WHERE receiver_id=?;", characterId); + + if (!res->next()) { + return 0; + } + + return res->getInt("mail_count"); +} + void MySQLDatabase::MarkMailRead(const uint64_t mailId) { ExecuteUpdate("UPDATE mail SET was_read=1 WHERE id=? LIMIT 1;", mailId); } diff --git a/dDatabase/GameDatabase/SQLite/SQLiteDatabase.h b/dDatabase/GameDatabase/SQLite/SQLiteDatabase.h index 4112f87d..601c852a 100644 --- a/dDatabase/GameDatabase/SQLite/SQLiteDatabase.h +++ b/dDatabase/GameDatabase/SQLite/SQLiteDatabase.h @@ -87,6 +87,7 @@ public: std::vector GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override; std::optional GetMail(const uint64_t mailId) override; uint32_t GetUnreadMailCount(const uint32_t characterId) override; + uint32_t GetMailCount(const uint32_t characterId) override; void MarkMailRead(const uint64_t mailId) override; void DeleteMail(const uint64_t mailId) override; void ClaimMailItem(const uint64_t mailId) override; diff --git a/dDatabase/GameDatabase/SQLite/Tables/Mail.cpp b/dDatabase/GameDatabase/SQLite/Tables/Mail.cpp index edd4b672..3513aef7 100644 --- a/dDatabase/GameDatabase/SQLite/Tables/Mail.cpp +++ b/dDatabase/GameDatabase/SQLite/Tables/Mail.cpp @@ -70,6 +70,16 @@ uint32_t SQLiteDatabase::GetUnreadMailCount(const uint32_t characterId) { return res.getIntField("number_unread"); } +uint32_t SQLiteDatabase::GetMailCount(const uint32_t characterId) { + auto [_, res] = ExecuteSelect("SELECT COUNT(*) AS mail_count FROM mail WHERE receiver_id=?;", characterId); + + if (res.eof()) { + return 0; + } + + return res.getIntField("mail_count"); +} + void SQLiteDatabase::MarkMailRead(const uint64_t mailId) { ExecuteUpdate("UPDATE mail SET was_read=1 WHERE id=?;", mailId); } @@ -81,3 +91,4 @@ void SQLiteDatabase::ClaimMailItem(const uint64_t mailId) { void SQLiteDatabase::DeleteMail(const uint64_t mailId) { ExecuteDelete("DELETE FROM mail WHERE id=?;", mailId); } + diff --git a/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.h b/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.h index 59f7fe08..a46e3f79 100644 --- a/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.h +++ b/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.h @@ -66,6 +66,7 @@ class TestSQLDatabase : public GameDatabase { std::vector GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override; std::optional GetMail(const uint64_t mailId) override; uint32_t GetUnreadMailCount(const uint32_t characterId) override; + uint32_t GetMailCount(const uint32_t characterId) override; void MarkMailRead(const uint64_t mailId) override; void DeleteMail(const uint64_t mailId) override; void ClaimMailItem(const uint64_t mailId) override; diff --git a/dGame/dUtilities/Mail.cpp b/dGame/dUtilities/Mail.cpp index 0a93ced0..7e167941 100644 --- a/dGame/dUtilities/Mail.cpp +++ b/dGame/dUtilities/Mail.cpp @@ -81,56 +81,64 @@ namespace Mail { } else if (GeneralUtils::CaseInsensitiveStringCompare(mailInfo.recipient, character->GetName()) || receiverID->id == character->GetID()) { response.status = eSendResponse::CannotMailSelf; } else { - uint32_t mailCost = Game::zoneManager->GetWorldConfig().mailBaseFee; - uint32_t stackSize = 0; - - auto inventoryComponent = player->GetComponent(); - Item* item = nullptr; - - bool hasAttachment = mailInfo.itemID != 0 && mailInfo.itemCount > 0; - - if (hasAttachment) { - item = inventoryComponent->FindItemById(mailInfo.itemID); - if (item) { - mailCost += (item->GetInfo().baseValue * Game::zoneManager->GetWorldConfig().mailPercentAttachmentFee); - mailInfo.itemLOT = item->GetLot(); - } - } - - if (hasAttachment && !item) { - response.status = eSendResponse::AttachmentNotFound; - } else if (player->GetCharacter()->GetCoins() - mailCost < 0) { - response.status = eSendResponse::NotEnoughCoins; + // check if recipient mailbox is full + if (Database::Get()->GetMailCount(receiverID->id) >= 20) { + // There is no Mailbox full response, so we will do this instead + response.status = eSendResponse::UnknownError; + // send system chat message to player + ChatPackets::SendSystemMessage(player->GetSystemAddress(), u"Recipient's mailbox is full. Please try again later."); } else { - bool removeSuccess = true; - // Remove coins and items from the sender - player->GetCharacter()->SetCoins(player->GetCharacter()->GetCoins() - mailCost, eLootSourceType::MAIL); - if (inventoryComponent && hasAttachment && item) { - removeSuccess = inventoryComponent->RemoveItem(mailInfo.itemLOT, mailInfo.itemCount, INVALID, true); - auto* missionComponent = player->GetComponent(); - if (missionComponent && removeSuccess) missionComponent->Progress(eMissionTaskType::GATHER, mailInfo.itemLOT, LWOOBJID_EMPTY, "", -mailInfo.itemCount); + uint32_t mailCost = Game::zoneManager->GetWorldConfig().mailBaseFee; + uint32_t stackSize = 0; + + auto inventoryComponent = player->GetComponent(); + Item* item = nullptr; + + bool hasAttachment = mailInfo.itemID != 0 && mailInfo.itemCount > 0; + + if (hasAttachment) { + item = inventoryComponent->FindItemById(mailInfo.itemID); + if (item) { + mailCost += (item->GetInfo().baseValue * Game::zoneManager->GetWorldConfig().mailPercentAttachmentFee); + mailInfo.itemLOT = item->GetLot(); + } } - // we passed all the checks, now we can actully send the mail - if (removeSuccess) { - mailInfo.senderId = character->GetID(); - mailInfo.senderUsername = character->GetName(); - mailInfo.receiverId = receiverID->id; - mailInfo.itemSubkey = LWOOBJID_EMPTY; - - //clear out the attachementID - mailInfo.itemID = 0; - - Database::Get()->InsertNewMail(mailInfo); - response.status = eSendResponse::Success; - character->SaveXMLToDatabase(); - } else { + if (hasAttachment && !item) { response.status = eSendResponse::AttachmentNotFound; + } else if (player->GetCharacter()->GetCoins() - mailCost < 0) { + response.status = eSendResponse::NotEnoughCoins; + } else { + bool removeSuccess = true; + // Remove coins and items from the sender + player->GetCharacter()->SetCoins(player->GetCharacter()->GetCoins() - mailCost, eLootSourceType::MAIL); + if (inventoryComponent && hasAttachment && item) { + removeSuccess = inventoryComponent->RemoveItem(mailInfo.itemLOT, mailInfo.itemCount, INVALID, true); + auto* missionComponent = player->GetComponent(); + if (missionComponent && removeSuccess) missionComponent->Progress(eMissionTaskType::GATHER, mailInfo.itemLOT, LWOOBJID_EMPTY, "", -mailInfo.itemCount); + } + + // we passed all the checks, now we can actully send the mail + if (removeSuccess) { + mailInfo.senderId = character->GetID(); + mailInfo.senderUsername = character->GetName(); + mailInfo.receiverId = receiverID->id; + mailInfo.itemSubkey = LWOOBJID_EMPTY; + + //clear out the attachementID + mailInfo.itemID = 0; + + Database::Get()->InsertNewMail(mailInfo); + response.status = eSendResponse::Success; + character->SaveXMLToDatabase(); + } else { + response.status = eSendResponse::AttachmentNotFound; + } } } + } else { + response.status = eSendResponse::SenderAccountIsMuted; } - } else { - response.status = eSendResponse::SenderAccountIsMuted; } LOG("Finished send with status %s", StringifiedEnum::ToString(response.status).data()); response.Send(sysAddr);