From 80a26341b124ac6ccaa538f6df0fc720da69ac30 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 11 May 2014 20:13:27 +1000 Subject: [PATCH] Finished the character management, but it needs testing. --- server/character_data.hpp | 1 + server/server_account_management.cpp | 1 + server/server_application.hpp | 6 +- server/server_character_management.cpp | 80 +++++++++++++++++++++++--- 4 files changed, 77 insertions(+), 11 deletions(-) diff --git a/server/character_data.hpp b/server/character_data.hpp index dc94e7d..f31e185 100644 --- a/server/character_data.hpp +++ b/server/character_data.hpp @@ -30,6 +30,7 @@ struct CharacterData { //metadata + int owner; std::string handle; std::string avatar; diff --git a/server/server_account_management.cpp b/server/server_account_management.cpp index 87fbbdd..761c1e5 100644 --- a/server/server_account_management.cpp +++ b/server/server_account_management.cpp @@ -162,6 +162,7 @@ void ServerApplication::UnloadUserAccount(int uid) { //save this user account, and then unload it SaveUserAccount(uid); accountMap.erase(uid); + //TODO: unload this account's characters? } void ServerApplication::DeleteUserAccount(int uid) { diff --git a/server/server_application.hpp b/server/server_application.hpp index b27fb64..1b0cd60 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -87,9 +87,9 @@ private: //TODO: character management int CreateCharacter(int owner, std::string handle, std::string avatar); int LoadCharacter(int owner, std::string handle, std::string avatar); - void SaveCharacter(); - void UnloadCharacter(); - void DeleteCharacter(); + int SaveCharacter(int uid); + void UnloadCharacter(int uid); + void DeleteCharacter(int uid); //TODO: combat systems diff --git a/server/server_character_management.cpp b/server/server_character_management.cpp index 3039c1b..d13d5eb 100644 --- a/server/server_character_management.cpp +++ b/server/server_character_management.cpp @@ -31,8 +31,8 @@ static const char* CREATE_CHARACTER = "INSERT INTO PlayerCharacters (owner, handle, avatar) VALUES (?, ?, ?);"; static const char* LOAD_CHARACTER = "SELECT * FROM PlayerCharacters WHERE handle = ?;"; -//static const char* SAVE_CHARACTER = ";"; -//static const char* DELETE_CHARACTER = ";"; +static const char* SAVE_CHARACTER = "INSERT OR REPLACE INTO PlayerCharacters (uid, owner, mapIndex, positionX, positionY) VALUES (?, ?, ?, ?, ?);"; +static const char* DELETE_CHARACTER = "DELETE FROM PlayerCharacters WHERE uid = ?;"; //------------------------- //Define the methods @@ -151,14 +151,78 @@ int ServerApplication::LoadCharacter(int owner, std::string handle, std::string throw(std::runtime_error(std::string() + "Unknown SQL error in LoadCharacter: " + sqlite3_errmsg(database) )); } -void ServerApplication::SaveCharacter() { - //TODO: save this character +int ServerApplication::SaveCharacter(int uid) { + //save this character from memory, replacing it if it exists in the database + //DOCS: To use this method, change the in-memory copy, and then call this function using that object's UID. + + //this method fails if this character is not loaded + if (characterMap.find(uid) == characterMap.end()) { + return -1; + } + + CharacterData& character = characterMap[uid]; + sqlite3_stmt* statement = nullptr; + + //prep + if (sqlite3_prepare_v2(database, SAVE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) { + throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); + } + + //parameters + bool ret = false; + ret |= sqlite3_bind_int(statement, 1, uid) != SQLITE_OK; + ret |= sqlite3_bind_int(statement, 2, character.owner) != SQLITE_OK; + ret |= sqlite3_bind_int(statement, 3, character.mapIndex) != SQLITE_OK; + ret |= sqlite3_bind_int(statement, 4, (int)character.position.x) != SQLITE_OK; + ret |= sqlite3_bind_int(statement, 5, (int)character.position.y) != SQLITE_OK; + //TODO: stats, etc. + + //check for binding errors + if (ret) { + throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) ); + } + + //execute + if (sqlite3_step(statement) != SQLITE_DONE) { + //if this fails, than something went horribly wrong + sqlite3_finalize(statement); + throw( std::runtime_error(std::string() + "Unknown SQL error when saving an account: " + sqlite3_errmsg(database)) ); + } + + sqlite3_finalize(statement); + + //successful execution + return 0; } -void ServerApplication::UnloadCharacter() { - //TODO: save this character, then unload it +void ServerApplication::UnloadCharacter(int uid) { + //save this character, then unload it + SaveCharacter(uid); + characterMap.erase(uid); } -void ServerApplication::DeleteCharacter() { - //TODO: delete this character, then remove it from memory +void ServerApplication::DeleteCharacter(int uid) { + //delete this character from the database, then remove it from memory + sqlite3_stmt* statement = nullptr; + + //prep + if (sqlite3_prepare_v2(database, DELETE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) { + throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); + } + + //parameter + if (sqlite3_bind_int(statement, 1, uid) != SQLITE_OK) { + throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) ); + } + + //execute + if (sqlite3_step(statement) != SQLITE_DONE) { + //if this fails, than something went horribly wrong + sqlite3_finalize(statement); + throw( std::runtime_error(std::string() + "Unknown SQL error when deleting an account: " + sqlite3_errmsg(database)) ); + } + + //finish the routine + sqlite3_finalize(statement); + characterMap.erase(uid); }