From 3a55a9b66f83663302b366d67c75a620f8bd0cad Mon Sep 17 00:00:00 2001 From: Gent Date: Fri, 6 Nov 2020 20:50:17 -0500 Subject: [PATCH] Add email structs and functions to DB Mutex locks included --- src/Database.cpp | 170 +++++++++++++++++++++++++++++++++++++++++++++++ src/Database.hpp | 34 ++++++++++ 2 files changed, 204 insertions(+) diff --git a/src/Database.cpp b/src/Database.cpp index 300fb89..73ff2e4 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -98,6 +98,29 @@ auto db = make_storage("database.db", make_column("PlayerAId", &Database::Buddyship::PlayerAId), make_column("PlayerBId", &Database::Buddyship::PlayerBId), make_column("Status", &Database::Buddyship::Status) + ), + make_table("EmailData", + make_column("PlayerId", &Database::EmailData::PlayerId), + make_column("MsgIndex", &Database::EmailData::MsgIndex), + make_column("ReadFlag", &Database::EmailData::ReadFlag), + make_column("ItemFlag", &Database::EmailData::ItemFlag), + make_column("SenderId", &Database::EmailData::SenderId), + make_column("SenderFirstName", &Database::EmailData::SenderFirstName, collate_nocase()), + make_column("SenderLastName", &Database::EmailData::SenderLastName, collate_nocase()), + make_column("SubjectLine", &Database::EmailData::SubjectLine), + make_column("MsgBody", &Database::EmailData::MsgBody), + make_column("Taros", &Database::EmailData::Taros), + make_column("SendTime", &Database::EmailData::SendTime), + make_column("DeleteTime", &Database::EmailData::DeleteTime) + ), + make_table("EmailItems", + make_column("PlayerId", &Database::EmailItem::PlayerId), + make_column("MsgIndex", &Database::EmailItem::MsgIndex), + make_column("Slot", &Database::EmailItem::Slot), + make_column("Id", &Database::EmailItem::Id), + make_column("Type", &Database::EmailItem::Type), + make_column("Opt", &Database::EmailItem::Opt), + make_column("TimeLimit", &Database::EmailItem::TimeLimit) ) ); @@ -743,4 +766,151 @@ int Database::getNumBuddies(Player* player) { return buddies.size() > 50 ? 50 : buddies.size(); } +// email +int Database::getUnreadEmailCount(int playerID) { + std::lock_guard lock(dbCrit); + + auto emailData = db.get_all( + where(c(&Database::EmailData::PlayerId) == playerID && c(&Database::EmailData::ReadFlag) == 0) + ); + + return emailData.size(); +} + +std::vector Database::getEmails(int playerID, int page) { + std::lock_guard lock(dbCrit); + + std::vector emails; + + auto emailData = db.get_all( + where(c(&Database::EmailData::PlayerId) == playerID), + order_by(&Database::EmailData::MsgIndex).desc(), + limit(5 * (page - 1), 5) + ); + + int i = 0; + for (Database::EmailData email : emailData) { + emails.push_back(email); + i++; + } + + return emails; +} + +Database::EmailData Database::getEmail(int playerID, int index) { + std::lock_guard lock(dbCrit); + + auto emailData = db.get_all( + where(c(&Database::EmailData::PlayerId) == playerID && c(&Database::EmailData::MsgIndex) == index) + ); + + if (emailData.size() > 1) + std::cout << "[WARN] Duplicate emails detected (player " << playerID << ", index " << index << ")" << std::endl; + + return emailData.at(0); +} + +sItemBase* Database::getEmailAttachments(int playerID, int index) { + std::lock_guard lock(dbCrit); + + sItemBase* items = new sItemBase[4]; + for (int i = 0; i < 4; i++) + items[i] = { 0, 0, 0, 0 }; // zero out items + + auto attachments = db.get_all( + where(c(&Database::EmailItem::PlayerId) == playerID && c(&Database::EmailItem::MsgIndex) == index) + ); + + if (attachments.size() > 4) + std::cout << "[WARN] Email has too many attachments (player " << playerID << ", index " << index << ")" << std::endl; + + for (Database::EmailItem& item : attachments) { + items[item.Slot - 1] = { item.Type, item.Id, item.Opt, item.TimeLimit }; + } + + return items; +} + +void Database::updateEmailContent(EmailData* data) { + std::lock_guard lock(dbCrit); + + db.begin_transaction(); + + db.remove_all( + where(c(&Database::EmailData::PlayerId) == data->PlayerId && c(&Database::EmailData::MsgIndex) == data->MsgIndex) + ); + db.insert(*data); + + db.commit(); +} + +void Database::deleteEmailAttachments(int playerID, int index, int slot) { + std::lock_guard lock(dbCrit); + + db.begin_transaction(); + + if (slot == -1) { // delete all + db.remove_all( + where(c(&Database::EmailItem::PlayerId) == playerID && c(&Database::EmailItem::MsgIndex) == index) + ); + } else { // delete single by comparing slot num + db.remove_all( + where(c(&Database::EmailItem::PlayerId) == playerID && c(&Database::EmailItem::MsgIndex) == index + && c(&Database::EmailItem::Slot) == slot) + ); + } + + db.commit(); +} + +void Database::deleteEmails(int playerID, int64_t* indices) { + std::lock_guard lock(dbCrit); + + db.begin_transaction(); + + for (int i = 0; i < 5; i++) { + db.remove_all( + where(c(&Database::EmailData::PlayerId) == playerID && c(&Database::EmailData::MsgIndex) == indices[i]) + ); // no need to check if the index is 0, since an email will never have index < 1 + } + + db.commit(); +} + +int Database::getNextEmailIndex(int playerID) { + std::lock_guard lock(dbCrit); + + auto emailData = db.get_all( + where(c(&Database::EmailData::PlayerId) == playerID), + order_by(&Database::EmailData::MsgIndex).desc(), + limit(1) + ); + + return (emailData.size() > 0 ? emailData.at(0).MsgIndex + 1 : 1); +} + +void Database::sendEmail(EmailData* data, std::vector attachments) { + std::lock_guard lock(dbCrit); + + db.begin_transaction(); + + db.insert(*data); // add email data to db + // add email attachments to db email inventory + int slot = 1; + for (sItemBase item : attachments) { + EmailItem dbItem = { + data->PlayerId, + data->MsgIndex, + slot, + item.iType, + item.iID, + item.iOpt, + item.iTimeLimit + }; + db.insert(dbItem); + } + + db.commit(); +} + #pragma endregion ShardServer diff --git a/src/Database.hpp b/src/Database.hpp index ce82080..516c561 100644 --- a/src/Database.hpp +++ b/src/Database.hpp @@ -84,6 +84,29 @@ namespace Database { int PlayerBId; int16_t Status; }; + struct EmailData { + int PlayerId; + int MsgIndex; + int32_t ReadFlag; + int32_t ItemFlag; + int SenderId; + std::string SenderFirstName; + std::string SenderLastName; + std::string SubjectLine; + std::string MsgBody; + int Taros; + uint64_t SendTime; + uint64_t DeleteTime; + }; + struct EmailItem { + int PlayerId; + int MsgIndex; + int Slot; + int16_t Type; + int16_t Id; + int32_t Opt; + int32_t TimeLimit; + }; #pragma endregion DatabaseStructs @@ -138,4 +161,15 @@ namespace Database { // parsing blobs void appendBlob(std::vector*blob, int64_t input); int64_t blobToInt64(std::vector::iterator it); + + // email + int getUnreadEmailCount(int playerID); + std::vector getEmails(int playerID, int page); + EmailData getEmail(int playerID, int index); + sItemBase* getEmailAttachments(int playerID, int index); + void updateEmailContent(EmailData* data); + void deleteEmailAttachments(int playerID, int index, int slot); + void deleteEmails(int playerID, int64_t* indices); + int getNextEmailIndex(int playerID); + void sendEmail(EmailData* data, std::vector attachments); }