Sync player data to DB when trading and sending emails

This commit is contained in:
dongresource 2022-12-05 22:29:23 +01:00
parent eb8e54c1f0
commit 9b3e856a05
5 changed files with 67 additions and 31 deletions

View File

@ -276,7 +276,7 @@ static void emailSend(CNSocket* sock, CNPacketData* data) {
0 // DeleteTime (unimplemented) 0 // DeleteTime (unimplemented)
}; };
if (!Database::sendEmail(&email, attachments)) { if (!Database::sendEmail(&email, attachments, plr)) {
plr->money += cost; // give money back plr->money += cost; // give money back
// give items back // give items back
while (!attachments.empty()) { while (!attachments.empty()) {

View File

@ -1,5 +1,6 @@
#include "Trading.hpp" #include "Trading.hpp"
#include "PlayerManager.hpp" #include "PlayerManager.hpp"
#include "db/Database.hpp"
using namespace Trading; using namespace Trading;
@ -269,6 +270,8 @@ static void tradeConfirm(CNSocket* sock, CNPacketData* data) {
otherSock->sendPacket(msg, P_FE2CL_GM_REP_PC_ANNOUNCE); otherSock->sendPacket(msg, P_FE2CL_GM_REP_PC_ANNOUNCE);
return; return;
} }
Database::commitTrade(plr, plr2);
} }
static void tradeConfirmCancel(CNSocket* sock, CNPacketData* data) { static void tradeConfirmCancel(CNSocket* sock, CNPacketData* data) {

View File

@ -78,7 +78,9 @@ namespace Database {
// getting players // getting players
void getPlayer(Player* plr, int id); void getPlayer(Player* plr, int id);
bool _updatePlayer(Player *player);
void updatePlayer(Player *player); void updatePlayer(Player *player);
void commitTrade(Player *plr1, Player *plr2);
// buddies // buddies
int getNumBuddies(Player* player); int getNumBuddies(Player* player);
@ -98,7 +100,7 @@ namespace Database {
void deleteEmailAttachments(int playerID, int index, int slot); void deleteEmailAttachments(int playerID, int index, int slot);
void deleteEmails(int playerID, int64_t* indices); void deleteEmails(int playerID, int64_t* indices);
int getNextEmailIndex(int playerID); int getNextEmailIndex(int playerID);
bool sendEmail(EmailData* data, std::vector<sItemBase> attachments); bool sendEmail(EmailData* data, std::vector<sItemBase> attachments, Player *sender);
// racing // racing
RaceRanking getTopRaceRanking(int epID, int playerID); RaceRanking getTopRaceRanking(int epID, int playerID);

View File

@ -152,7 +152,8 @@ void Database::updateEmailContent(EmailData* data) {
sqlite3_step(stmt); sqlite3_step(stmt);
int attachmentsCount = sqlite3_column_int(stmt, 0); int attachmentsCount = sqlite3_column_int(stmt, 0);
data->ItemFlag = (data->Taros > 0 || attachmentsCount > 0) ? 1 : 0; // set attachment flag dynamically // set attachment flag dynamically
data->ItemFlag = (data->Taros > 0 || attachmentsCount > 0) ? 1 : 0;
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
@ -265,7 +266,7 @@ int Database::getNextEmailIndex(int playerID) {
return (index > 0 ? index + 1 : 1); return (index > 0 ? index + 1 : 1);
} }
bool Database::sendEmail(EmailData* data, std::vector<sItemBase> attachments) { bool Database::sendEmail(EmailData* data, std::vector<sItemBase> attachments, Player *sender) {
std::lock_guard<std::mutex> lock(dbCrit); std::lock_guard<std::mutex> lock(dbCrit);
sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL); sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
@ -330,6 +331,13 @@ bool Database::sendEmail(EmailData* data, std::vector<sItemBase> attachments) {
sqlite3_reset(stmt); sqlite3_reset(stmt);
} }
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
if (!_updatePlayer(sender)) {
std::cout << "[WARN] Database: Failed to save player to database: " << sqlite3_errmsg(db) << std::endl;
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
return false;
}
sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL); sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
return true; return true;
} }

View File

@ -285,11 +285,13 @@ void Database::getPlayer(Player* plr, int id) {
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
} }
void Database::updatePlayer(Player *player) { /*
std::lock_guard<std::mutex> lock(dbCrit); * Low-level function to save a player to DB.
* Must be run in a SQL transaction and with dbCrit locked.
sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL); * The caller manages the transacstion, so if this function returns false,
* the caller must roll it back.
*/
bool Database::_updatePlayer(Player *player) {
const char* sql = R"( const char* sql = R"(
UPDATE Players UPDATE Players
SET SET
@ -336,10 +338,8 @@ void Database::updatePlayer(Player *player) {
sqlite3_bind_int(stmt, 21, player->iID); sqlite3_bind_int(stmt, 21, player->iID);
if (sqlite3_step(stmt) != SQLITE_DONE) { if (sqlite3_step(stmt) != SQLITE_DONE) {
std::cout << "[WARN] Database: Failed to save player to database: " << sqlite3_errmsg(db) << std::endl;
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL); return false;
return;
} }
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
@ -375,10 +375,8 @@ void Database::updatePlayer(Player *player) {
rc = sqlite3_step(stmt); rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) { if (rc != SQLITE_DONE) {
std::cout << "[WARN] Database: Failed to save player to database: " << sqlite3_errmsg(db) << std::endl;
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return; return false;
} }
sqlite3_reset(stmt); sqlite3_reset(stmt);
} }
@ -395,10 +393,8 @@ void Database::updatePlayer(Player *player) {
sqlite3_bind_int(stmt, 6, player->Inven[i].iTimeLimit); sqlite3_bind_int(stmt, 6, player->Inven[i].iTimeLimit);
if (sqlite3_step(stmt) != SQLITE_DONE) { if (sqlite3_step(stmt) != SQLITE_DONE) {
std::cout << "[WARN] Database: Failed to save player to database: " << sqlite3_errmsg(db) << std::endl;
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return; return false;
} }
sqlite3_reset(stmt); sqlite3_reset(stmt);
} }
@ -415,10 +411,8 @@ void Database::updatePlayer(Player *player) {
sqlite3_bind_int(stmt, 6, player->Bank[i].iTimeLimit); sqlite3_bind_int(stmt, 6, player->Bank[i].iTimeLimit);
if (sqlite3_step(stmt) != SQLITE_DONE) { if (sqlite3_step(stmt) != SQLITE_DONE) {
std::cout << "[WARN] Database: Failed to save player to database: " << sqlite3_errmsg(db) << std::endl;
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return; return false;
} }
sqlite3_reset(stmt); sqlite3_reset(stmt);
} }
@ -451,10 +445,8 @@ void Database::updatePlayer(Player *player) {
sqlite3_bind_int(stmt, 4, player->QInven[i].iID); sqlite3_bind_int(stmt, 4, player->QInven[i].iID);
if (sqlite3_step(stmt) != SQLITE_DONE) { if (sqlite3_step(stmt) != SQLITE_DONE) {
std::cout << "[WARN] Database: Failed to save player to database: " << sqlite3_errmsg(db) << std::endl;
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return; return false;
} }
sqlite3_reset(stmt); sqlite3_reset(stmt);
} }
@ -487,10 +479,8 @@ void Database::updatePlayer(Player *player) {
sqlite3_bind_int(stmt, 4, player->Nanos[i].iStamina); sqlite3_bind_int(stmt, 4, player->Nanos[i].iStamina);
if (sqlite3_step(stmt) != SQLITE_DONE) { if (sqlite3_step(stmt) != SQLITE_DONE) {
std::cout << "[WARN] Database: Failed to save player to database: " << sqlite3_errmsg(db) << std::endl;
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return; return false;
} }
sqlite3_reset(stmt); sqlite3_reset(stmt);
} }
@ -524,14 +514,47 @@ void Database::updatePlayer(Player *player) {
sqlite3_bind_int(stmt, 5, player->RemainingNPCCount[i][2]); sqlite3_bind_int(stmt, 5, player->RemainingNPCCount[i][2]);
if (sqlite3_step(stmt) != SQLITE_DONE) { if (sqlite3_step(stmt) != SQLITE_DONE) {
std::cout << "[WARN] Database: Failed to save player to database: " << sqlite3_errmsg(db) << std::endl;
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return; return false;
} }
sqlite3_reset(stmt); sqlite3_reset(stmt);
} }
sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return true;
}
void Database::updatePlayer(Player *player) {
std::lock_guard<std::mutex> lock(dbCrit);
sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
if (!_updatePlayer(player)) {
std::cout << "[WARN] Database: Failed to save player to database: " << sqlite3_errmsg(db) << std::endl;
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
return;
}
sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
}
void Database::commitTrade(Player *plr1, Player *plr2) {
std::lock_guard<std::mutex> lock(dbCrit);
sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
if (!_updatePlayer(plr1)) {
std::cout << "[WARN] Database: Failed to save player to database: " << sqlite3_errmsg(db) << std::endl;
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
return;
}
if (!_updatePlayer(plr2)) {
std::cout << "[WARN] Database: Failed to save player to database: " << sqlite3_errmsg(db) << std::endl;
sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
return;
}
sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
} }