From 872425640dcf2cf054b1aae07e015a9352f30fdb Mon Sep 17 00:00:00 2001 From: Gent S Date: Wed, 25 Nov 2020 19:15:30 -0500 Subject: [PATCH] Prevent DB players from occupying same slot --- src/CNLoginServer.cpp | 27 ++++++++++++++------------- src/Database.cpp | 10 ++++++++++ src/Database.hpp | 1 + 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/CNLoginServer.cpp b/src/CNLoginServer.cpp index 4bfb398..6fff764 100644 --- a/src/CNLoginServer.cpp +++ b/src/CNLoginServer.cpp @@ -214,6 +214,17 @@ void CNLoginServer::nameCheck(CNSocket* sock, CNPacketData* data) { loginSessions[sock].lastHeartbeat = getTime(); } +void invalidCharacter(CNSocket* sock) { + INITSTRUCT(sP_LS2CL_REP_SHARD_SELECT_FAIL, fail); + fail.iErrorCode = 2; + sock->sendPacket((void*)&fail, P_LS2CL_REP_SHARD_SELECT_FAIL, sizeof(sP_LS2CL_REP_SHARD_SELECT_FAIL)); + + DEBUGLOG( + std::cout << "Login Server: Selected character error" << std::endl; + ) + return; +} + void CNLoginServer::nameSave(CNSocket* sock, CNPacketData* data) { if (data->size != sizeof(sP_CL2LS_REQ_SAVE_CHAR_NAME)) return; @@ -224,9 +235,10 @@ void CNLoginServer::nameSave(CNSocket* sock, CNPacketData* data) { int errorCode = 0; if (!CNLoginServer::isCharacterNameGood(U16toU8(save->szFirstName), U16toU8(save->szLastName))) { errorCode = 4; - } - else if (!Database::isNameFree(U16toU8(save->szFirstName), U16toU8(save->szLastName))) { + } else if (!Database::isNameFree(U16toU8(save->szFirstName), U16toU8(save->szLastName))) { errorCode = 1; + } else if (!Database::isSlotFree(loginSessions[sock].userID, save->iSlotNum)) { + return invalidCharacter(sock); } if (errorCode != 0) { @@ -260,17 +272,6 @@ void CNLoginServer::nameSave(CNSocket* sock, CNPacketData* data) { ) } -void invalidCharacter(CNSocket* sock) { - INITSTRUCT(sP_LS2CL_REP_SHARD_SELECT_FAIL, fail); - fail.iErrorCode = 2; - sock->sendPacket((void*)&fail, P_LS2CL_REP_SHARD_SELECT_FAIL, sizeof(sP_LS2CL_REP_SHARD_SELECT_FAIL)); - - DEBUGLOG( - std::cout << "Login Server: Selected character error" << std::endl; - ) - return; -} - bool validateCharacterCreation(sP_CL2LS_REQ_CHAR_CREATE* character) { // all the values have been determined from analyzing client code and xdt diff --git a/src/Database.cpp b/src/Database.cpp index 422c3ab..c02048a 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -208,6 +208,16 @@ bool Database::isNameFree(std::string firstName, std::string lastName) { .empty()); } +bool Database::isSlotFree(int accountId, int slotNum) { + std::lock_guard lock(dbCrit); + + return + (db.get_all + (where((c(&DbPlayer::AccountID) == accountId) + and (c(&DbPlayer::slot) == slotNum))) + .empty()); +} + int Database::createCharacter(sP_CL2LS_REQ_SAVE_CHAR_NAME* save, int AccountID) { std::lock_guard lock(dbCrit); diff --git a/src/Database.hpp b/src/Database.hpp index bb69743..d1b4c77 100644 --- a/src/Database.hpp +++ b/src/Database.hpp @@ -121,6 +121,7 @@ namespace Database { std::unique_ptr findAccount(std::string login); bool validateCharacter(int characterID, int userID); bool isNameFree(std::string firstName, std::string lastName); + bool isSlotFree(int accountId, int slotNum); // called after chosing name, returns ID int createCharacter(sP_CL2LS_REQ_SAVE_CHAR_NAME* save, int AccountID); // called after finishing creation