From 6664f8a8bcce2042be42da724088e7307796eb99 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 6 Jun 2014 21:14:41 +1000 Subject: [PATCH 01/11] Renamed server_connections.cpp => network_handlers.cpp --- server/{server_connections.cpp => network_handlers.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename server/{server_connections.cpp => network_handlers.cpp} (100%) diff --git a/server/server_connections.cpp b/server/network_handlers.cpp similarity index 100% rename from server/server_connections.cpp rename to server/network_handlers.cpp From 310f701b0decae994ea3651f66448095b90f598b Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 6 Jun 2014 21:42:27 +1000 Subject: [PATCH 02/11] Began modulating ServerApplication, beginning with the accounts --- common/gameplay/sanity_check.cpp | 1 - {common/gameplay => server}/account_data.hpp | 0 ...unt_management.cpp => account_manager.cpp} | 42 +++++++++++--- server/account_manager.hpp | 55 +++++++++++++++++++ server/server_application.hpp | 8 +-- 5 files changed, 89 insertions(+), 17 deletions(-) rename {common/gameplay => server}/account_data.hpp (100%) rename server/{account_management.cpp => account_manager.cpp} (88%) create mode 100644 server/account_manager.hpp diff --git a/common/gameplay/sanity_check.cpp b/common/gameplay/sanity_check.cpp index 719db9f..22f1737 100644 --- a/common/gameplay/sanity_check.cpp +++ b/common/gameplay/sanity_check.cpp @@ -19,7 +19,6 @@ * 3. This notice may not be removed or altered from any source * distribution. */ -#include "account_data.hpp" #include "character_data.hpp" #include "client_data.hpp" #include "combat_data.hpp" diff --git a/common/gameplay/account_data.hpp b/server/account_data.hpp similarity index 100% rename from common/gameplay/account_data.hpp rename to server/account_data.hpp diff --git a/server/account_management.cpp b/server/account_manager.cpp similarity index 88% rename from server/account_management.cpp rename to server/account_manager.cpp index eb298d8..424c125 100644 --- a/server/account_management.cpp +++ b/server/account_manager.cpp @@ -19,9 +19,7 @@ * 3. This notice may not be removed or altered from any source * distribution. */ -#include "server_application.hpp" - -#include "sqlite3/sqlite3.h" +#include "account_manager.hpp" #include @@ -35,10 +33,10 @@ static const char* SAVE_USER_ACCOUNT = "UPDATE OR FAIL Accounts SET blacklisted static const char* DELETE_USER_ACCOUNT = "DELETE FROM Accounts WHERE uid = ?;"; //------------------------- -//Define the methods +//Define the public methods //------------------------- -int ServerApplication::CreateUserAccount(std::string username, int clientIndex) { +int AccountManager::CreateUserAccount(std::string username, int clientIndex) { //create this user account, failing if it exists, leave this account in memory sqlite3_stmt* statement = nullptr; @@ -65,7 +63,7 @@ int ServerApplication::CreateUserAccount(std::string username, int clientIndex) return LoadUserAccount(username, clientIndex); } -int ServerApplication::LoadUserAccount(std::string username, int clientIndex) { +int AccountManager::LoadUserAccount(std::string username, int clientIndex) { //load this user account, failing if it is in memory, creating it if it doesn't exist sqlite3_stmt* statement = nullptr; @@ -117,7 +115,7 @@ int ServerApplication::LoadUserAccount(std::string username, int clientIndex) { throw(std::runtime_error(std::string() + "Unknown SQL error in LoadUserAccount: " + sqlite3_errmsg(database) )); } -int ServerApplication::SaveUserAccount(int uid) { +int AccountManager::SaveUserAccount(int uid) { //save this user account 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. @@ -160,14 +158,14 @@ int ServerApplication::SaveUserAccount(int uid) { return 0; } -void ServerApplication::UnloadUserAccount(int uid) { +void AccountManager::UnloadUserAccount(int uid) { //save this user account, and then unload it //NOTE: the associated characters are unloaded externally SaveUserAccount(uid); accountMap.erase(uid); } -void ServerApplication::DeleteUserAccount(int uid) { +void AccountManager::DeleteUserAccount(int uid) { //delete a user account from the database, and remove it from memory //NOTE: the associated characters should be deleted externally sqlite3_stmt* statement = nullptr; @@ -193,3 +191,29 @@ void ServerApplication::DeleteUserAccount(int uid) { sqlite3_finalize(statement); accountMap.erase(uid); } + +//------------------------- +//Define the accessors and mutators +//------------------------- + +AccountData* AccountManager::GetAccount(int uid) { + std::map::iterator it = accountMap.find(uid); + + if (it == accountMap.end()) { + return nullptr; + } + + return &it->second; +} + +std::map* AccountManager::GetContainer() { + return &accountMap; +} + +sqlite3* AccountManager::SetDatabase(sqlite3* db) { + return database = db; +} + +sqlite3* AccountManager::GetDatabase() { + return database; +} \ No newline at end of file diff --git a/server/account_manager.hpp b/server/account_manager.hpp new file mode 100644 index 0000000..6d109ac --- /dev/null +++ b/server/account_manager.hpp @@ -0,0 +1,55 @@ +/* Copyright: (c) Kayne Ruse 2014 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef ACCOUNTMANAGER_HPP_ +#define ACCOUNTMANAGER_HPP_ + +#include "account_data.hpp" + +#include "sqlite3/sqlite3.h" + +#include + +class AccountManager { +public: + AccountManager() = default; + ~AccountManager() = default; + + //public access methods + int CreateUserAccount(std::string username, int clientIndex); + int LoadUserAccount(std::string username, int clientIndex); + int SaveUserAccount(int uid); + void UnloadUserAccount(int uid); + void DeleteUserAccount(int uid); + + //accessors and mutators + AccountData* GetAccount(int uid); + std::map* GetContainer(); + + sqlite3* SetDatabase(sqlite3* db); + sqlite3* GetDatabase(); + +private: + std::map accountMap; + sqlite3* database = nullptr; +}; + +#endif diff --git a/server/server_application.hpp b/server/server_application.hpp index cbc7511..87f34de 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -79,12 +79,7 @@ private: void PumpCharacterUnload(int uid); //Account management - int CreateUserAccount(std::string username, int clientIndex); - int LoadUserAccount(std::string username, int clientIndex); - int SaveUserAccount(int uid); - void UnloadUserAccount(int uid); - void DeleteUserAccount(int uid); - + //character management int CreateCharacter(int owner, std::string handle, std::string avatar); int LoadCharacter(int owner, std::string handle, std::string avatar); @@ -101,7 +96,6 @@ private: //server tables std::map clientMap; - std::map accountMap; std::map characterMap; std::map combatMap; std::map enemyMap; From 7fb458ddc14a16fbe10a09e13a09572991f8104c Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 6 Jun 2014 21:52:22 +1000 Subject: [PATCH 03/11] Refactored the character management into a separate class --- ...r_management.cpp => character_manager.cpp} | 38 +++++++++++-- server/character_manager.hpp | 55 +++++++++++++++++++ server/server_application.hpp | 5 -- 3 files changed, 87 insertions(+), 11 deletions(-) rename server/{character_management.cpp => character_manager.cpp} (91%) create mode 100644 server/character_manager.hpp diff --git a/server/character_management.cpp b/server/character_manager.cpp similarity index 91% rename from server/character_management.cpp rename to server/character_manager.cpp index 3991305..4064f5d 100644 --- a/server/character_management.cpp +++ b/server/character_manager.cpp @@ -19,7 +19,7 @@ * 3. This notice may not be removed or altered from any source * distribution. */ -#include "server_application.hpp" +#include "character_manager.hpp" #include "sqlite3/sqlite3.h" @@ -60,7 +60,7 @@ static const char* DELETE_CHARACTER = "DELETE FROM Characters WHERE uid = ?;"; //TODO: should statistics be stored separately? //TODO: default stats as a parameter? This would be good for differing beggining states or multiple classes -int ServerApplication::CreateCharacter(int owner, std::string handle, std::string avatar) { +int CharacterManager::CreateCharacter(int owner, std::string handle, std::string avatar) { //Create the character, failing if it exists sqlite3_stmt* statement = nullptr; @@ -93,7 +93,7 @@ int ServerApplication::CreateCharacter(int owner, std::string handle, std::strin return LoadCharacter(owner, handle, avatar); } -int ServerApplication::LoadCharacter(int owner, std::string handle, std::string avatar) { +int CharacterManager::LoadCharacter(int owner, std::string handle, std::string avatar) { //load the specified character, creating it if it doesn't exist //fail if it is already loaded, or does not belong to this account sqlite3_stmt* statement = nullptr; @@ -178,7 +178,7 @@ int ServerApplication::LoadCharacter(int owner, std::string handle, std::string throw(std::runtime_error(std::string() + "Unknown SQL error in LoadCharacter: " + sqlite3_errmsg(database) )); } -int ServerApplication::SaveCharacter(int uid) { +int CharacterManager::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. @@ -241,13 +241,13 @@ int ServerApplication::SaveCharacter(int uid) { return 0; } -void ServerApplication::UnloadCharacter(int uid) { +void CharacterManager::UnloadCharacter(int uid) { //save this character, then unload it SaveCharacter(uid); characterMap.erase(uid); } -void ServerApplication::DeleteCharacter(int uid) { +void CharacterManager::DeleteCharacter(int uid) { //delete this character from the database, then remove it from memory sqlite3_stmt* statement = nullptr; @@ -272,3 +272,29 @@ void ServerApplication::DeleteCharacter(int uid) { sqlite3_finalize(statement); characterMap.erase(uid); } + +//------------------------- +//Define the accessors and mutators +//------------------------- + +CharacterData* CharacterManager::GetCharacter(int uid) { + std::map::iterator it = characterMap.find(uid); + + if (it == characterMap.end()) { + return nullptr; + } + + return &it->second; +} + +std::map* CharacterManager::GetContainer() { + return &characterMap; +} + +sqlite3* CharacterManager::SetDatabase(sqlite3* db) { + return database = db; +} + +sqlite3* CharacterManager::GetDatabase() { + return database; +} \ No newline at end of file diff --git a/server/character_manager.hpp b/server/character_manager.hpp new file mode 100644 index 0000000..c334a7a --- /dev/null +++ b/server/character_manager.hpp @@ -0,0 +1,55 @@ +/* Copyright: (c) Kayne Ruse 2014 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef CHARACTERMANAGER_HPP_ +#define CHARACTERMANAGER_HPP_ + +#include "character_data.hpp" + +#include "sqlite3/sqlite3.h" + +#include + +class CharacterManager { +public: + CharacterManager() = default; + ~CharacterManager() = default; + + //public access methods + int CreateCharacter(int owner, std::string handle, std::string avatar); + int LoadCharacter(int owner, std::string handle, std::string avatar); + int SaveCharacter(int uid); + void UnloadCharacter(int uid); + void DeleteCharacter(int uid); + + //accessors and mutators + CharacterData* GetCharacter(int uid); + std::map* GetContainer(); + + sqlite3* SetDatabase(sqlite3* db); + sqlite3* GetDatabase(); + +private: + std::map characterMap; + sqlite3* database = nullptr; +}; + +#endif diff --git a/server/server_application.hpp b/server/server_application.hpp index 87f34de..6016d8f 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -81,11 +81,6 @@ private: //Account management //character management - int CreateCharacter(int owner, std::string handle, std::string avatar); - int LoadCharacter(int owner, std::string handle, std::string avatar); - int SaveCharacter(int uid); - void UnloadCharacter(int uid); - void DeleteCharacter(int uid); //TODO: combat management From 973a2be16b1ebcd390b752a7b3a75941978b51be Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 6 Jun 2014 22:11:05 +1000 Subject: [PATCH 04/11] Merged server_internals.cpp and network_handlers.cpp into server_application.cpp --- common/gameplay/sanity_check.cpp | 2 - {common/gameplay => server}/client_data.hpp | 0 {common/gameplay => server}/room_data.hpp | 0 ...rk_handlers.cpp => server_application.cpp} | 201 +++++++++++++++++- server/server_application.hpp | 7 +- server/server_internals.cpp | 190 ----------------- 6 files changed, 200 insertions(+), 200 deletions(-) rename {common/gameplay => server}/client_data.hpp (100%) rename {common/gameplay => server}/room_data.hpp (100%) rename server/{network_handlers.cpp => server_application.cpp} (56%) delete mode 100644 server/server_internals.cpp diff --git a/common/gameplay/sanity_check.cpp b/common/gameplay/sanity_check.cpp index 22f1737..8669811 100644 --- a/common/gameplay/sanity_check.cpp +++ b/common/gameplay/sanity_check.cpp @@ -20,10 +20,8 @@ * distribution. */ #include "character_data.hpp" -#include "client_data.hpp" #include "combat_data.hpp" #include "enemy_data.hpp" -#include "room_data.hpp" #include "statistics.hpp" /* DOCS: Sanity check, read more diff --git a/common/gameplay/client_data.hpp b/server/client_data.hpp similarity index 100% rename from common/gameplay/client_data.hpp rename to server/client_data.hpp diff --git a/common/gameplay/room_data.hpp b/server/room_data.hpp similarity index 100% rename from common/gameplay/room_data.hpp rename to server/room_data.hpp diff --git a/server/network_handlers.cpp b/server/server_application.cpp similarity index 56% rename from server/network_handlers.cpp rename to server/server_application.cpp index 047462f..8cd135f 100644 --- a/server/network_handlers.cpp +++ b/server/server_application.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* Copyright: (c) Kayne Ruse 2014 * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -21,11 +21,199 @@ */ #include "server_application.hpp" +#include "sql_utility.hpp" +#include "serial.hpp" + #include #include +#include //------------------------- -//Handle various network input +//Define the public members +//------------------------- + +void ServerApplication::Init(int argc, char** argv) { + //NOTE: I might need to rearrange the init process so that lua & SQL can interact with the map system as needed. + std::cout << "Beginning startup" << std::endl; + + //initial setup + config.Load("rsc\\config.cfg"); + + //------------------------- + //Initialize the APIs + //------------------------- + + //Init SDL + if (SDL_Init(0)) { + throw(std::runtime_error("Failed to initialize SDL")); + } + std::cout << "Initialized SDL" << std::endl; + + //Init SDL_net + if (SDLNet_Init()) { + throw(std::runtime_error("Failed to initialize SDL_net")); + } + network.Open(config.Int("server.port")); + std::cout << "Initialized SDL_net" << std::endl; + + //Init SQL + int ret = sqlite3_open_v2(config["server.dbname"].c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, nullptr); + if (ret != SQLITE_OK || !database) { + throw(std::runtime_error(std::string() + "Failed to initialize SQL: " + sqlite3_errmsg(database) )); + } + std::cout << "Initialized SQL" << std::endl; + + //Init lua + luaState = luaL_newstate(); + if (!luaState) { + throw(std::runtime_error("Failed to initialize lua")); + } + luaL_openlibs(luaState); + std::cout << "Initialized lua" << std::endl; + + //------------------------- + //Setup the objects + //------------------------- + + //setup the map object + regionPager.GetAllocator()->SetLuaState(luaState); + regionPager.GetFormat()->SetLuaState(luaState); + regionPager.GetFormat()->SetSaveDir(config["dir.maps"] + config["map.savename"]); + std::cout << "Prepared the map system" << std::endl; + + //push the pager onto the lua registry + lua_pushstring(luaState, "pager"); + lua_pushlightuserdata(luaState, reinterpret_cast(®ionPager)); + lua_settable(luaState, LUA_REGISTRYINDEX); + std::cout << "Registered the map system in lua" << std::endl; + + //------------------------- + //Run the startup scripts + //------------------------- + + //setup the database + if (runSQLScript(database, config["dir.scripts"] + "setup_server.sql")) { + throw(std::runtime_error("Failed to initialize SQL's setup script")); + } + std::cout << "Completed SQL's setup script" << std::endl; + + //run lua's startup script + if (luaL_dofile(luaState, (config["dir.scripts"] + "setup_server.lua").c_str())) { + throw(std::runtime_error(std::string() + "Failed to initialize lua's setup script: " + lua_tostring(luaState, -1) )); + } + std::cout << "Completed lua's setup script" << std::endl; + + //debug output + std::cout << "Internal sizes:" << std::endl; + std::cout << "\tsizeof(SerialPacket): " << sizeof(SerialPacket) << std::endl; + std::cout << "\tPACKET_BUFFER_SIZE: " << PACKET_BUFFER_SIZE << std::endl; + + //finalize the startup + std::cout << "Startup completed successfully" << std::endl; + + //debugging + // +} + +void ServerApplication::Proc() { + SerialPacket packet; + while(running) { + //suck in the waiting packets & process them + while(network.Receive(&packet)) { + HandlePacket(packet); + } + //update the internals + //TODO: update the internals i.e. player positions + //give the computer a break + SDL_Delay(10); + } +} + +void ServerApplication::Quit() { + std::cout << "Shutting down" << std::endl; + + //save the server state + for (auto& it : accountMap) { + SaveUserAccount(it.first); + } + for (auto& it : characterMap) { + SaveCharacter(it.first); + } + + //empty the members + accountMap.clear(); + characterMap.clear(); + regionPager.UnloadAll(); + + //APIs + lua_close(luaState); + sqlite3_close_v2(database); + network.Close(); + SDLNet_Quit(); + SDL_Quit(); + + std::cout << "Shutdown finished" << std::endl; +} + +//------------------------- +//Define the network switch +//------------------------- + +void ServerApplication::HandlePacket(SerialPacket packet) { + switch(packet.meta.type) { + //basic connections + case SerialPacketType::BROADCAST_REQUEST: + HandleBroadcastRequest(packet); + break; + case SerialPacketType::JOIN_REQUEST: + HandleJoinRequest(packet); + break; + case SerialPacketType::DISCONNECT: + HandleDisconnect(packet); + break; + case SerialPacketType::SHUTDOWN: + HandleShutdown(packet); + break; + + //map management + case SerialPacketType::REGION_REQUEST: + HandleRegionRequest(packet); + break; + + //combat management + //TODO: combat management + + //character management + case SerialPacketType::CHARACTER_NEW: + HandleCharacterNew(packet); + break; + case SerialPacketType::CHARACTER_DELETE: + HandleCharacterDelete(packet); + break; + case SerialPacketType::CHARACTER_UPDATE: + HandleCharacterUpdate(packet); + break; + case SerialPacketType::CHARACTER_STATS_REQUEST: + HandleCharacterUpdate(packet); + break; + + //enemy management + //TODO: enemy management + + //mismanagement + case SerialPacketType::SYNCHRONIZE: + HandleSynchronize(packet); + break; + + //handle errors + default: + throw(std::runtime_error(std::string() + "Unknown SerialPacketType encountered in the server: " + to_string_custom(int(packet.type)))); + break; + } +} + +//------------------------- +//Define the network handlers //------------------------- void ServerApplication::HandleBroadcastRequest(SerialPacket packet) { @@ -191,4 +379,11 @@ void ServerApplication::PumpCharacterUnload(int uid) { delPacket.meta.type = SerialPacket::Type::CHARACTER_DELETE; delPacket.characterInfo.characterIndex = uid; PumpPacket(delPacket); -} \ No newline at end of file +} + +//------------------------- +//Define the utility methods +//------------------------- + +//TODO: utility methods + diff --git a/server/server_application.hpp b/server/server_application.hpp index 6016d8f..3b24303 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -78,10 +78,8 @@ private: void PumpPacket(SerialPacket); void PumpCharacterUnload(int uid); - //Account management - - //character management - + //TODO: Account management + //TODO: character management //TODO: combat management //APIs @@ -91,7 +89,6 @@ private: //server tables std::map clientMap; - std::map characterMap; std::map combatMap; std::map enemyMap; diff --git a/server/server_internals.cpp b/server/server_internals.cpp deleted file mode 100644 index c5298fc..0000000 --- a/server/server_internals.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2014 - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. -*/ -#include "server_application.hpp" - -#include "sql_utility.hpp" -#include "serial.hpp" - -#include -#include -#include - -//------------------------- -//Define the public members -//------------------------- - -void ServerApplication::Init(int argc, char** argv) { - //NOTE: I might need to rearrange the init process so that lua & SQL can interact with the map system as needed. - std::cout << "Beginning startup" << std::endl; - - //initial setup - config.Load("rsc\\config.cfg"); - - //------------------------- - //Initialize the APIs - //------------------------- - - //Init SDL - if (SDL_Init(0)) { - throw(std::runtime_error("Failed to initialize SDL")); - } - std::cout << "Initialized SDL" << std::endl; - - //Init SDL_net - if (SDLNet_Init()) { - throw(std::runtime_error("Failed to initialize SDL_net")); - } - network.Open(config.Int("server.port")); - std::cout << "Initialized SDL_net" << std::endl; - - //Init SQL - int ret = sqlite3_open_v2(config["server.dbname"].c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, nullptr); - if (ret != SQLITE_OK || !database) { - throw(std::runtime_error(std::string() + "Failed to initialize SQL: " + sqlite3_errmsg(database) )); - } - std::cout << "Initialized SQL" << std::endl; - - //Init lua - luaState = luaL_newstate(); - if (!luaState) { - throw(std::runtime_error("Failed to initialize lua")); - } - luaL_openlibs(luaState); - std::cout << "Initialized lua" << std::endl; - - //------------------------- - //Setup the objects - //------------------------- - - //setup the map object - regionPager.GetAllocator()->SetLuaState(luaState); - regionPager.GetFormat()->SetLuaState(luaState); - regionPager.GetFormat()->SetSaveDir(config["dir.maps"] + config["map.savename"]); - std::cout << "Prepared the map system" << std::endl; - - //push the pager onto the lua registry - lua_pushstring(luaState, "pager"); - lua_pushlightuserdata(luaState, reinterpret_cast(®ionPager)); - lua_settable(luaState, LUA_REGISTRYINDEX); - std::cout << "Registered the map system in lua" << std::endl; - - //------------------------- - //Run the startup scripts - //------------------------- - - //setup the database - if (runSQLScript(database, config["dir.scripts"] + "setup_server.sql")) { - throw(std::runtime_error("Failed to initialize SQL's setup script")); - } - std::cout << "Completed SQL's setup script" << std::endl; - - //run lua's startup script - if (luaL_dofile(luaState, (config["dir.scripts"] + "setup_server.lua").c_str())) { - throw(std::runtime_error(std::string() + "Failed to initialize lua's setup script: " + lua_tostring(luaState, -1) )); - } - std::cout << "Completed lua's setup script" << std::endl; - - //debug output - std::cout << "Internal sizes:" << std::endl; - std::cout << "\tsizeof(SerialPacket): " << sizeof(SerialPacket) << std::endl; - std::cout << "\tPACKET_BUFFER_SIZE: " << PACKET_BUFFER_SIZE << std::endl; - - //finalize the startup - std::cout << "Startup completed successfully" << std::endl; - - //debugging - // -} - -void ServerApplication::Proc() { - SerialPacket packet; - while(running) { - //suck in the waiting packets & process them - while(network.Receive(&packet)) { - HandlePacket(packet); - } - //update the internals - //TODO: update the internals i.e. player positions - //give the computer a break - SDL_Delay(10); - } -} - -void ServerApplication::Quit() { - std::cout << "Shutting down" << std::endl; - - //save the server state - for (auto& it : accountMap) { - SaveUserAccount(it.first); - } - for (auto& it : characterMap) { - SaveCharacter(it.first); - } - - //empty the members - accountMap.clear(); - characterMap.clear(); - regionPager.UnloadAll(); - - //APIs - lua_close(luaState); - sqlite3_close_v2(database); - network.Close(); - SDLNet_Quit(); - SDL_Quit(); - - std::cout << "Shutdown finished" << std::endl; -} - -//------------------------- -//Define the uber switch -//------------------------- - -void ServerApplication::HandlePacket(SerialPacket packet) { - switch(packet.meta.type) { - case SerialPacket::Type::BROADCAST_REQUEST: - HandleBroadcastRequest(packet); - break; - case SerialPacket::Type::JOIN_REQUEST: - HandleJoinRequest(packet); - break; - case SerialPacket::Type::SYNCHRONIZE: - HandleSynchronize(packet); - break; - case SerialPacket::Type::DISCONNECT: - HandleDisconnect(packet); - break; - case SerialPacket::Type::SHUTDOWN: - HandleShutdown(packet); - break; - case SerialPacket::Type::CHARACTER_UPDATE: - HandleCharacterUpdate(packet); - break; - case SerialPacket::Type::REGION_REQUEST: - HandleRegionRequest(packet); - break; - //handle errors - default: - throw(std::runtime_error("Unknown SerialPacketType encountered")); - break; - } -} From 5c8572d8116b19710c57e6c8c0945890a5b1382d Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 6 Jun 2014 22:57:10 +1000 Subject: [PATCH 05/11] Rearranged the methods --- server/server_application.cpp | 96 ++++++++++++++++++++++------------- server/server_application.hpp | 62 +++++++++++----------- 2 files changed, 94 insertions(+), 64 deletions(-) diff --git a/server/server_application.cpp b/server/server_application.cpp index 8cd135f..12c8589 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -29,7 +29,7 @@ #include //------------------------- -//Define the public members +//public methods //------------------------- void ServerApplication::Init(int argc, char** argv) { @@ -75,17 +75,13 @@ void ServerApplication::Init(int argc, char** argv) { //Setup the objects //------------------------- - //setup the map object - regionPager.GetAllocator()->SetLuaState(luaState); - regionPager.GetFormat()->SetLuaState(luaState); - regionPager.GetFormat()->SetSaveDir(config["dir.maps"] + config["map.savename"]); - std::cout << "Prepared the map system" << std::endl; + accountMgr.SetDatabase(database); + characterMgr.SetDatabase(database); - //push the pager onto the lua registry - lua_pushstring(luaState, "pager"); - lua_pushlightuserdata(luaState, reinterpret_cast(®ionPager)); - lua_settable(luaState, LUA_REGISTRYINDEX); - std::cout << "Registered the map system in lua" << std::endl; + combatMgr.SetLuaState(luaState); + roomMgr.SetLuaState(luaState); + + std::cout << "Internal managers ready" << std::endl; //------------------------- //Run the startup scripts @@ -103,16 +99,21 @@ void ServerApplication::Init(int argc, char** argv) { } std::cout << "Completed lua's setup script" << std::endl; + //------------------------- //debug output + //------------------------- + std::cout << "Internal sizes:" << std::endl; - std::cout << "\tsizeof(SerialPacket): " << sizeof(SerialPacket) << std::endl; - std::cout << "\tPACKET_BUFFER_SIZE: " << PACKET_BUFFER_SIZE << std::endl; + std::cout << "\tTile Size: " << sizeof(Region::type_t) << std::endl; + std::cout << "\tRegion Format: " << REGION_WIDTH << ", " << REGION_HEIGHT << ", " << REGION_DEPTH << << std::endl; + std::cout << "\tRegion Content Footprint: " << REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) << std::endl; + std::cout << "\tPACKET_BUFFER_SIZE (max size): " << PACKET_BUFFER_SIZE << std::endl; + //------------------------- //finalize the startup - std::cout << "Startup completed successfully" << std::endl; + //------------------------- - //debugging - // + std::cout << "Startup completed successfully" << std::endl; } void ServerApplication::Proc() { @@ -156,7 +157,7 @@ void ServerApplication::Quit() { } //------------------------- -//Define the network switch +//handle incoming traffic //------------------------- void ServerApplication::HandlePacket(SerialPacket packet) { @@ -191,9 +192,7 @@ void ServerApplication::HandlePacket(SerialPacket packet) { HandleCharacterDelete(packet); break; case SerialPacketType::CHARACTER_UPDATE: - HandleCharacterUpdate(packet); - break; - case SerialPacketType::CHARACTER_STATS_REQUEST: + case SerialPacketType::CHARACTER_STATS_REQUEST: //TODO: ? HandleCharacterUpdate(packet); break; @@ -213,7 +212,7 @@ void ServerApplication::HandlePacket(SerialPacket packet) { } //------------------------- -//Define the network handlers +//basic connections //------------------------- void ServerApplication::HandleBroadcastRequest(SerialPacket packet) { @@ -344,6 +343,37 @@ void ServerApplication::HandleShutdown(SerialPacket packet) { std::cout << "Shutdown signal accepted" << std::endl; } +//------------------------- +//map management +//------------------------- + +void ServerApplication::HandleRegionRequest(SerialPacket packet) { + //TODO: this should be moved elsewhere + packet.meta.type = SerialPacket::Type::REGION_CONTENT; + packet.regionInfo.region = regionPager.GetRegion(packet.regionInfo.x, packet.regionInfo.y); + + //send the content + network.SendTo(&packet.meta.srcAddress, &packet); +} + +//------------------------- +//combat management +//------------------------- + +//TODO: combat management + +//------------------------- +//Character Management +//------------------------- + +void ServerApplication::HandleCharacterNew(SerialPacket) { + //TODO: fill this +} + +void ServerApplication::HandleCharacterDelete(SerialPacket) { + //TODO: fill this +} + void ServerApplication::HandleCharacterUpdate(SerialPacket packet) { //TODO: this should be moved elsewhere if (characterMap.find(packet.characterInfo.characterIndex) == characterMap.end()) { @@ -357,14 +387,17 @@ void ServerApplication::HandleCharacterUpdate(SerialPacket packet) { PumpPacket(packet); } -void ServerApplication::HandleRegionRequest(SerialPacket packet) { - //TODO: this should be moved elsewhere - packet.meta.type = SerialPacket::Type::REGION_CONTENT; - packet.regionInfo.region = regionPager.GetRegion(packet.regionInfo.x, packet.regionInfo.y); +//------------------------- +//enemy management +//------------------------- - //send the content - network.SendTo(&packet.meta.srcAddress, &packet); -} +//TODO: enemy management + +//------------------------- +//utility methods +//------------------------- + +//TODO: a function that only sends to characters in a certain proximity void ServerApplication::PumpPacket(SerialPacket packet) { //NOTE: I don't really like this, but it'll do for now @@ -380,10 +413,3 @@ void ServerApplication::PumpCharacterUnload(int uid) { delPacket.characterInfo.characterIndex = uid; PumpPacket(delPacket); } - -//------------------------- -//Define the utility methods -//------------------------- - -//TODO: utility methods - diff --git a/server/server_application.hpp b/server/server_application.hpp index 3b24303..aa761d3 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -24,22 +24,19 @@ //server specific stuff #include "client_data.hpp" -#include "account_data.hpp" -#include "character_data.hpp" -#include "combat_data.hpp" -#include "enemy_factory_generic.hpp" +#include "account_manager.hpp" +#include "character_manager.hpp" +#include "combat_manager.hpp" +#include "room_manager.hpp" //maps #include "map_allocator.hpp" #include "map_file_format.hpp" #include "region_pager.hpp" -//networking +//common utilities #include "udp_network_utility.hpp" - -//common #include "config_utility.hpp" -#include "vector2.hpp" //APIs #include "lua/lua.hpp" @@ -51,10 +48,9 @@ #include //The main application class -//TODO: modulate this god class class ServerApplication { public: - //standard functions + //public methods ServerApplication() = default; ~ServerApplication() = default; @@ -63,47 +59,55 @@ public: void Quit(); private: + //handle incoming traffic void HandlePacket(SerialPacket); - //handle incoming traffic + //basic connections void HandleBroadcastRequest(SerialPacket); void HandleJoinRequest(SerialPacket); - void HandleSynchronize(SerialPacket); void HandleDisconnect(SerialPacket); void HandleShutdown(SerialPacket); - void HandleCharacterUpdate(SerialPacket); + + //map management void HandleRegionRequest(SerialPacket); + //combat management + //TODO: combat management + + //character management + void HandleCharacterNew(SerialPacket); + void HandleCharacterDelete(SerialPacket); + void HandleCharacterUpdate(SerialPacket); + + //enemy management + //TODO: enemy management + + //mismanagement + void HandleSynchronize(SerialPacket); + + //utility methods //TODO: a function that only sends to characters in a certain proximity void PumpPacket(SerialPacket); void PumpCharacterUnload(int uid); - //TODO: Account management - //TODO: character management - //TODO: combat management - - //APIs - UDPNetworkUtility network; + //APIs and utilities sqlite3* database = nullptr; lua_State* luaState = nullptr; + UDPNetworkUtility network; + ConfigUtility config; //server tables std::map clientMap; - std::map combatMap; - std::map enemyMap; - //maps - //TODO: I need to handle multiple map objects - //TODO: Unload regions that are distant from any characters - RegionPager regionPager; - EnemyFactoryGeneric enemyFactory; + //managers + AccountManager accountMgr; + CharacterManager characterMgr; + CombatManager combatMgr; + RoomManager roomMgr; //misc bool running = true; - ConfigUtility config; int clientUID = 0; - int combatUID = 0; - int enemyUID = 0; }; #endif From 10e857ecd1aaeb7e4b7e550be4bc3f967e9e5789 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 6 Jun 2014 23:08:05 +1000 Subject: [PATCH 06/11] Added empty managers for CombatData, RoomData and EnemyData These are just placeholders for now, but I'll flesh them out later. I should note that the server's managers all build cleanly. --- server/combat_manager.cpp | 54 +++++++++++++++++++++++++++++++++++++++ server/combat_manager.hpp | 51 ++++++++++++++++++++++++++++++++++++ server/enemy_manager.cpp | 54 +++++++++++++++++++++++++++++++++++++++ server/enemy_manager.hpp | 51 ++++++++++++++++++++++++++++++++++++ server/room_manager.cpp | 54 +++++++++++++++++++++++++++++++++++++++ server/room_manager.hpp | 51 ++++++++++++++++++++++++++++++++++++ 6 files changed, 315 insertions(+) create mode 100644 server/combat_manager.cpp create mode 100644 server/combat_manager.hpp create mode 100644 server/enemy_manager.cpp create mode 100644 server/enemy_manager.hpp create mode 100644 server/room_manager.cpp create mode 100644 server/room_manager.hpp diff --git a/server/combat_manager.cpp b/server/combat_manager.cpp new file mode 100644 index 0000000..be4f9ac --- /dev/null +++ b/server/combat_manager.cpp @@ -0,0 +1,54 @@ +/* Copyright: (c) Kayne Ruse 2014 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "combat_manager.hpp" + +//------------------------- +//public access methods +//------------------------- + +//TODO + +//------------------------- +//accessors and mutators +//------------------------- + +CombatData* CombatManager::GetCombat(int uid) { + std::map::iterator it = combatMap.find(uid); + + if (it == combatMap.end()) { + return nullptr; + } + + return &it->second; +} + +std::map* CombatManager::GetContainer() { + return &combatMap; +} + +lua_State* CombatManager::SetLuaState(lua_State* L) { + return luaState = L; +} + +lua_State* CombatManager::GetLuaState() { + return luaState; +} diff --git a/server/combat_manager.hpp b/server/combat_manager.hpp new file mode 100644 index 0000000..77573ab --- /dev/null +++ b/server/combat_manager.hpp @@ -0,0 +1,51 @@ +/* Copyright: (c) Kayne Ruse 2014 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef COMBATMANAGER_HPP_ +#define COMBATMANAGER_HPP_ + +#include "combat_data.hpp" + +#include "lua/lua.hpp" + +#include + +class CombatManager { +public: + CombatManager() = default; + ~CombatManager() = default; + + //public access methods + //TODO + + //accessors and mutators + CombatData* GetCombat(int uid); + std::map* GetContainer(); + + lua_State* SetLuaState(lua_State*); + lua_State* GetLuaState(); + +private: + std::map combatMap; + lua_State* luaState = nullptr; +}; + +#endif \ No newline at end of file diff --git a/server/enemy_manager.cpp b/server/enemy_manager.cpp new file mode 100644 index 0000000..2b49d3d --- /dev/null +++ b/server/enemy_manager.cpp @@ -0,0 +1,54 @@ +/* Copyright: (c) Kayne Ruse 2014 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "enemy_manager.hpp" + +//------------------------- +//public access methods +//------------------------- + +//TODO + +//------------------------- +//accessors and mutators +//------------------------- + +EnemyData* EnemyManager::GetEnemy(int uid) { + std::map::iterator it = enemyMap.find(uid); + + if (it == enemyMap.end()) { + return nullptr; + } + + return &it->second; +} + +std::map* EnemyManager::GetContainer() { + return &enemyMap; +} + +lua_State* EnemyManager::SetLuaState(lua_State* L) { + return luaState = L; +} + +lua_State* EnemyManager::GetLuaState() { + return luaState; +} diff --git a/server/enemy_manager.hpp b/server/enemy_manager.hpp new file mode 100644 index 0000000..dae86ad --- /dev/null +++ b/server/enemy_manager.hpp @@ -0,0 +1,51 @@ +/* Copyright: (c) Kayne Ruse 2014 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef ENEMYMANAGER_HPP_ +#define ENEMYMANAGER_HPP_ + +#include "enemy_data.hpp" + +#include "lua/lua.hpp" + +#include + +class EnemyManager { +public: + EnemyManager() = default; + ~EnemyManager() = default; + + //public access methods + //TODO + + //accessors and mutators + EnemyData* GetEnemy(int uid); + std::map* GetContainer(); + + lua_State* SetLuaState(lua_State*); + lua_State* GetLuaState(); + +private: + std::map enemyMap; + lua_State* luaState = nullptr; +}; + +#endif \ No newline at end of file diff --git a/server/room_manager.cpp b/server/room_manager.cpp new file mode 100644 index 0000000..3cb43dd --- /dev/null +++ b/server/room_manager.cpp @@ -0,0 +1,54 @@ +/* Copyright: (c) Kayne Ruse 2014 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "room_manager.hpp" + +//------------------------- +//public access methods +//------------------------- + +//TODO + +//------------------------- +//accessors and mutators +//------------------------- + +RoomData* RoomManager::GetRoom(int uid) { + std::map::iterator it = roomMap.find(uid); + + if (it == roomMap.end()) { + return nullptr; + } + + return &it->second; +} + +std::map* RoomManager::GetContainer() { + return &roomMap; +} + +lua_State* RoomManager::SetLuaState(lua_State* L) { + return luaState = L; +} + +lua_State* RoomManager::GetLuaState() { + return luaState; +} diff --git a/server/room_manager.hpp b/server/room_manager.hpp new file mode 100644 index 0000000..9b1dfc6 --- /dev/null +++ b/server/room_manager.hpp @@ -0,0 +1,51 @@ +/* Copyright: (c) Kayne Ruse 2014 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#ifndef ROOMMANAGER_HPP_ +#define ROOMMANAGER_HPP_ + +#include "room_data.hpp" + +#include "lua/lua.hpp" + +#include + +class RoomManager { +public: + RoomManager() = default; + ~RoomManager() = default; + + //public access methods + //TODO + + //accessors and mutators + RoomData* GetRoom(int uid); + std::map* GetContainer(); + + lua_State* SetLuaState(lua_State*); + lua_State* GetLuaState(); + +private: + std::map roomMap; + lua_State* luaState = nullptr; +}; + +#endif \ No newline at end of file From 170096b5db9bf5a0293254813652f7c667336ffa Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 6 Jun 2014 23:34:38 +1000 Subject: [PATCH 07/11] Server is nearly done, only server_application.cpp is failing --- client/makefile | 2 +- server/account_manager.cpp | 10 ++++++++++ server/account_manager.hpp | 4 ++-- server/character_manager.cpp | 10 ++++++++++ server/character_manager.hpp | 4 ++-- server/makefile | 2 +- server/server_application.cpp | 14 +------------- server/server_application.hpp | 6 ++++-- 8 files changed, 31 insertions(+), 21 deletions(-) diff --git a/client/makefile b/client/makefile index bba3c67..947b822 100644 --- a/client/makefile +++ b/client/makefile @@ -1,5 +1,5 @@ #config -INCLUDES+=. ../common/gameplay ../common/graphics ../common/map ../common/network ../common/ui ../common/utilities +INCLUDES+=. ../common/gameplay ../common/graphics ../common/map ../common/network ../common/network/packet ../common/network/serial ../common/ui ../common/utilities LIBS+=../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) -DGRAPHICS diff --git a/server/account_manager.cpp b/server/account_manager.cpp index 424c125..4a9bdc4 100644 --- a/server/account_manager.cpp +++ b/server/account_manager.cpp @@ -36,6 +36,16 @@ static const char* DELETE_USER_ACCOUNT = "DELETE FROM Accounts WHERE uid = ?;"; //Define the public methods //------------------------- +AccountManager::AccountManager() { + // +} + +AccountManager::~AccountManager() { + for (auto& it : accountMap) { + SaveUserAccount(it.first); + } +} + int AccountManager::CreateUserAccount(std::string username, int clientIndex) { //create this user account, failing if it exists, leave this account in memory sqlite3_stmt* statement = nullptr; diff --git a/server/account_manager.hpp b/server/account_manager.hpp index 6d109ac..10ba8a3 100644 --- a/server/account_manager.hpp +++ b/server/account_manager.hpp @@ -30,8 +30,8 @@ class AccountManager { public: - AccountManager() = default; - ~AccountManager() = default; + AccountManager(); + ~AccountManager(); //public access methods int CreateUserAccount(std::string username, int clientIndex); diff --git a/server/character_manager.cpp b/server/character_manager.cpp index 4064f5d..1192788 100644 --- a/server/character_manager.cpp +++ b/server/character_manager.cpp @@ -58,6 +58,16 @@ static const char* DELETE_CHARACTER = "DELETE FROM Characters WHERE uid = ?;"; //Define the methods //------------------------- +CharacterManager::CharacterManager() { + // +} + +CharacterManager::~CharacterManager() { + for (auto& it : characterMap) { + SaveCharacter(it.first); + } +} + //TODO: should statistics be stored separately? //TODO: default stats as a parameter? This would be good for differing beggining states or multiple classes int CharacterManager::CreateCharacter(int owner, std::string handle, std::string avatar) { diff --git a/server/character_manager.hpp b/server/character_manager.hpp index c334a7a..97b3a18 100644 --- a/server/character_manager.hpp +++ b/server/character_manager.hpp @@ -30,8 +30,8 @@ class CharacterManager { public: - CharacterManager() = default; - ~CharacterManager() = default; + CharacterManager(); + ~CharacterManager(); //public access methods int CreateCharacter(int owner, std::string handle, std::string avatar); diff --git a/server/makefile b/server/makefile index 901f8a6..7c733ea 100644 --- a/server/makefile +++ b/server/makefile @@ -1,5 +1,5 @@ #config -INCLUDES+=. ../common/gameplay ../common/map ../common/network ../common/script ../common/utilities +INCLUDES+=. ../common/gameplay ../common/map ../common/network ../common/network/packet ../common/network/serial ../common/script ../common/utilities LIBS+=../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua -lsqlite3 CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) diff --git a/server/server_application.cpp b/server/server_application.cpp index 12c8589..24c71cc 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -80,6 +80,7 @@ void ServerApplication::Init(int argc, char** argv) { combatMgr.SetLuaState(luaState); roomMgr.SetLuaState(luaState); + enemyMgr.SetLuaState(luaState); std::cout << "Internal managers ready" << std::endl; @@ -133,19 +134,6 @@ void ServerApplication::Proc() { void ServerApplication::Quit() { std::cout << "Shutting down" << std::endl; - //save the server state - for (auto& it : accountMap) { - SaveUserAccount(it.first); - } - for (auto& it : characterMap) { - SaveCharacter(it.first); - } - - //empty the members - accountMap.clear(); - characterMap.clear(); - regionPager.UnloadAll(); - //APIs lua_close(luaState); sqlite3_close_v2(database); diff --git a/server/server_application.hpp b/server/server_application.hpp index aa761d3..cab0e1f 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -23,10 +23,11 @@ #define SERVERAPPLICATION_HPP_ //server specific stuff -#include "client_data.hpp" #include "account_manager.hpp" #include "character_manager.hpp" +#include "client_data.hpp" #include "combat_manager.hpp" +#include "enemy_manager.hpp" #include "room_manager.hpp" //maps @@ -96,13 +97,14 @@ private: UDPNetworkUtility network; ConfigUtility config; - //server tables + //simple tables std::map clientMap; //managers AccountManager accountMgr; CharacterManager characterMgr; CombatManager combatMgr; + EnemyManager enemyMgr; RoomManager roomMgr; //misc From cac273da5e21ec9a9173eb625909231b8c40f3d9 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sat, 7 Jun 2014 01:14:54 +1000 Subject: [PATCH 08/11] Partial rewrite of server_application.cpp I've also fixed some other issues along the way. However, the next step requires support for multiple rooms. Finally. --- common/network/packet/serial_packet_base.hpp | 3 +- server/account_manager.cpp | 20 +- server/account_manager.hpp | 10 +- server/character_manager.cpp | 12 ++ server/character_manager.hpp | 3 + server/server_application.cpp | 192 +++++++++---------- server/server_application.hpp | 22 +-- 7 files changed, 131 insertions(+), 131 deletions(-) diff --git a/common/network/packet/serial_packet_base.hpp b/common/network/packet/serial_packet_base.hpp index 16279c8..760e54a 100644 --- a/common/network/packet/serial_packet_base.hpp +++ b/common/network/packet/serial_packet_base.hpp @@ -30,6 +30,7 @@ #include "SDL/SDL_net.h" +#define NETWORK_VERSION 20140607 #define PACKET_STRING_SIZE 100 struct SerialPacketBase { @@ -39,7 +40,7 @@ struct SerialPacketBase { typedef SerialPacketType Type; - virtual ~SerialPacketBase(); + virtual ~SerialPacketBase() {}; }; typedef SerialPacketBase SerialPacket; diff --git a/server/account_manager.cpp b/server/account_manager.cpp index 4a9bdc4..2a5a968 100644 --- a/server/account_manager.cpp +++ b/server/account_manager.cpp @@ -42,11 +42,11 @@ AccountManager::AccountManager() { AccountManager::~AccountManager() { for (auto& it : accountMap) { - SaveUserAccount(it.first); + SaveAccount(it.first); } } -int AccountManager::CreateUserAccount(std::string username, int clientIndex) { +int AccountManager::CreateAccount(std::string username, int clientIndex) { //create this user account, failing if it exists, leave this account in memory sqlite3_stmt* statement = nullptr; @@ -70,10 +70,10 @@ int AccountManager::CreateUserAccount(std::string username, int clientIndex) { sqlite3_finalize(statement); //load this account into memory - return LoadUserAccount(username, clientIndex); + return LoadAccount(username, clientIndex); } -int AccountManager::LoadUserAccount(std::string username, int clientIndex) { +int AccountManager::LoadAccount(std::string username, int clientIndex) { //load this user account, failing if it is in memory, creating it if it doesn't exist sqlite3_stmt* statement = nullptr; @@ -119,13 +119,13 @@ int AccountManager::LoadUserAccount(std::string username, int clientIndex) { if (ret == SQLITE_DONE) { //create the non-existant account instead - return CreateUserAccount(username, clientIndex); + return CreateAccount(username, clientIndex); } - throw(std::runtime_error(std::string() + "Unknown SQL error in LoadUserAccount: " + sqlite3_errmsg(database) )); + throw(std::runtime_error(std::string() + "Unknown SQL error in LoadAccount: " + sqlite3_errmsg(database) )); } -int AccountManager::SaveUserAccount(int uid) { +int AccountManager::SaveAccount(int uid) { //save this user account 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. @@ -168,14 +168,14 @@ int AccountManager::SaveUserAccount(int uid) { return 0; } -void AccountManager::UnloadUserAccount(int uid) { +void AccountManager::UnloadAccount(int uid) { //save this user account, and then unload it //NOTE: the associated characters are unloaded externally - SaveUserAccount(uid); + SaveAccount(uid); accountMap.erase(uid); } -void AccountManager::DeleteUserAccount(int uid) { +void AccountManager::DeleteAccount(int uid) { //delete a user account from the database, and remove it from memory //NOTE: the associated characters should be deleted externally sqlite3_stmt* statement = nullptr; diff --git a/server/account_manager.hpp b/server/account_manager.hpp index 10ba8a3..5bf3841 100644 --- a/server/account_manager.hpp +++ b/server/account_manager.hpp @@ -34,11 +34,11 @@ public: ~AccountManager(); //public access methods - int CreateUserAccount(std::string username, int clientIndex); - int LoadUserAccount(std::string username, int clientIndex); - int SaveUserAccount(int uid); - void UnloadUserAccount(int uid); - void DeleteUserAccount(int uid); + int CreateAccount(std::string username, int clientIndex); + int LoadAccount(std::string username, int clientIndex); + int SaveAccount(int uid); + void UnloadAccount(int uid); + void DeleteAccount(int uid); //accessors and mutators AccountData* GetAccount(int uid); diff --git a/server/character_manager.cpp b/server/character_manager.cpp index 1192788..34310c9 100644 --- a/server/character_manager.cpp +++ b/server/character_manager.cpp @@ -283,6 +283,18 @@ void CharacterManager::DeleteCharacter(int uid) { characterMap.erase(uid); } +void CharacterManager::UnloadCharacterIf(std::function::iterator)> f) { + //save this character, then unload it if the parameter returns true + for (std::map::iterator it = characterMap.begin(); it != characterMap.end(); /* EMPTY */ ) { + if (f(it)) { + SaveCharacter(it->first); + it = characterMap.erase(it); + continue; + } + it++; + } +} + //------------------------- //Define the accessors and mutators //------------------------- diff --git a/server/character_manager.hpp b/server/character_manager.hpp index 97b3a18..812d337 100644 --- a/server/character_manager.hpp +++ b/server/character_manager.hpp @@ -27,6 +27,7 @@ #include "sqlite3/sqlite3.h" #include +#include class CharacterManager { public: @@ -40,6 +41,8 @@ public: void UnloadCharacter(int uid); void DeleteCharacter(int uid); + void UnloadCharacterIf(std::function::iterator)> f); + //accessors and mutators CharacterData* GetCharacter(int uid); std::map* GetContainer(); diff --git a/server/server_application.cpp b/server/server_application.cpp index 24c71cc..7ef5f45 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -106,7 +106,7 @@ void ServerApplication::Init(int argc, char** argv) { std::cout << "Internal sizes:" << std::endl; std::cout << "\tTile Size: " << sizeof(Region::type_t) << std::endl; - std::cout << "\tRegion Format: " << REGION_WIDTH << ", " << REGION_HEIGHT << ", " << REGION_DEPTH << << std::endl; + std::cout << "\tRegion Format: " << REGION_WIDTH << ", " << REGION_HEIGHT << ", " << REGION_DEPTH << std::endl; std::cout << "\tRegion Content Footprint: " << REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) << std::endl; std::cout << "\tPACKET_BUFFER_SIZE (max size): " << PACKET_BUFFER_SIZE << std::endl; @@ -122,7 +122,7 @@ void ServerApplication::Proc() { while(running) { //suck in the waiting packets & process them while(network.Receive(&packet)) { - HandlePacket(packet); + HandlePacket(&packet); } //update the internals //TODO: update the internals i.e. player positions @@ -148,25 +148,25 @@ void ServerApplication::Quit() { //handle incoming traffic //------------------------- -void ServerApplication::HandlePacket(SerialPacket packet) { - switch(packet.meta.type) { +void ServerApplication::HandlePacket(SerialPacket* const argPacket) { + switch(argPacket->type) { //basic connections case SerialPacketType::BROADCAST_REQUEST: - HandleBroadcastRequest(packet); + HandleBroadcastRequest(dynamic_cast(argPacket)); break; case SerialPacketType::JOIN_REQUEST: - HandleJoinRequest(packet); + HandleJoinRequest(dynamic_cast(argPacket)); break; case SerialPacketType::DISCONNECT: - HandleDisconnect(packet); + HandleDisconnect(dynamic_cast(argPacket)); break; case SerialPacketType::SHUTDOWN: - HandleShutdown(packet); + HandleShutdown(dynamic_cast(argPacket)); break; //map management case SerialPacketType::REGION_REQUEST: - HandleRegionRequest(packet); + HandleRegionRequest(dynamic_cast(argPacket)); break; //combat management @@ -174,14 +174,14 @@ void ServerApplication::HandlePacket(SerialPacket packet) { //character management case SerialPacketType::CHARACTER_NEW: - HandleCharacterNew(packet); + HandleCharacterNew(dynamic_cast(argPacket)); break; case SerialPacketType::CHARACTER_DELETE: - HandleCharacterDelete(packet); + HandleCharacterDelete(dynamic_cast(argPacket)); break; case SerialPacketType::CHARACTER_UPDATE: case SerialPacketType::CHARACTER_STATS_REQUEST: //TODO: ? - HandleCharacterUpdate(packet); + HandleCharacterUpdate(dynamic_cast(argPacket)); break; //enemy management @@ -189,12 +189,12 @@ void ServerApplication::HandlePacket(SerialPacket packet) { //mismanagement case SerialPacketType::SYNCHRONIZE: - HandleSynchronize(packet); + HandleSynchronize(dynamic_cast(argPacket)); break; //handle errors default: - throw(std::runtime_error(std::string() + "Unknown SerialPacketType encountered in the server: " + to_string_custom(int(packet.type)))); + throw(std::runtime_error(std::string() + "Unknown SerialPacketType encountered in the server: " + to_string_custom(int(argPacket->type)))); break; } } @@ -203,129 +203,82 @@ void ServerApplication::HandlePacket(SerialPacket packet) { //basic connections //------------------------- -void ServerApplication::HandleBroadcastRequest(SerialPacket packet) { - //pack the server's data - packet.meta.type = SerialPacket::Type::BROADCAST_RESPONSE; - packet.serverInfo.networkVersion = NETWORK_VERSION; - snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str()); - packet.serverInfo.playerCount = characterMap.size(); +void ServerApplication::HandleBroadcastRequest(SerialPacket* const argPacket) { + //send the server's data + ServerPacket newPacket; - //bounce this packet - network.SendTo(&packet.meta.srcAddress, &packet); + newPacket.type = SerialPacketType::BROADCAST_RESPONSE; + snprintf(newPacket.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str()); + newPacket.playerCount = characterMgr.GetContainer()->size(); + newPacket.version = NETWORK_VERSION; + + network.SendTo(&argPacket->srcAddress, dynamic_cast(&newPacket)); } -void ServerApplication::HandleJoinRequest(SerialPacket packet) { +void ServerApplication::HandleJoinRequest(ClientPacket* const argPacket) { //create the new client ClientData newClient; - newClient.address = packet.meta.srcAddress; + newClient.address = argPacket->srcAddress; //load the user account - int accountIndex = LoadUserAccount(packet.clientInfo.username, clientUID); + //TODO: handle passwords + int accountIndex = accountMgr.LoadAccount(argPacket->username, clientUID); if (accountIndex < 0) { //TODO: send rejection packet std::cerr << "Error: Account already loaded: " << accountIndex << std::endl; return; } - //load the new character - int characterIndex = LoadCharacter(accountIndex, packet.clientInfo.handle, packet.clientInfo.avatar); - if (characterIndex < 0) { - //TODO: send rejection packet - std::cerr << "Error: Character already loaded: " << characterIndex << std::endl; - UnloadUserAccount(accountIndex); - return; - } - //send the client their info - packet.meta.type = SerialPacket::Type::JOIN_RESPONSE; - packet.clientInfo.clientIndex = clientUID; - packet.clientInfo.accountIndex = accountIndex; - packet.clientInfo.characterIndex = characterIndex; + ClientPacket newPacket; + newPacket.type = SerialPacketType::JOIN_RESPONSE; + newPacket.clientIndex = clientUID; + newPacket.accountIndex = accountIndex; - //bounce this packet - network.SendTo(&newClient.address, &packet); + network.SendTo(&newClient.address, dynamic_cast(&newPacket)); - //reference to prevent multiple lookups - //TODO: I need a way to pack structures unto packets more easily - //NOTE: this chunk of code is similar to HandleSynchronize - CharacterData& character = characterMap[characterIndex]; - - //send the new character to all clients - packet.meta.type = SerialPacket::Type::CHARACTER_NEW; - packet.characterInfo.characterIndex = characterIndex; - strncpy(packet.characterInfo.handle, character.handle.c_str(), PACKET_STRING_SIZE); - strncpy(packet.characterInfo.avatar, character.avatar.c_str(), PACKET_STRING_SIZE); - packet.characterInfo.mapIndex = character.mapIndex; - packet.characterInfo.origin = character.origin; - packet.characterInfo.motion = character.motion; - packet.characterInfo.stats = character.stats; - - PumpPacket(packet); - - //TODO: don't send anything to a certain client until they send the OK (the sync packet? or ignore client side?) //finished this routine clientMap[clientUID++] = newClient; - std::cout << "Connect, total: " << clientMap.size() << std::endl; + std::cout << "New connection, " << clientMap.size() << " clients and " << accountMgr.GetContainer()->size() << " accounts total" << std::endl; } -void ServerApplication::HandleSynchronize(SerialPacket packet) { - //TODO: compensate for large distances - - //send all the server's data to this client - SerialPacket newPacket; - - //characters - newPacket.meta.type = SerialPacket::Type::CHARACTER_UPDATE; - for (auto& it : characterMap) { - //TODO: update this for the expanded CharacterData structure - newPacket.characterInfo.characterIndex = it.first; - snprintf(newPacket.characterInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str()); - snprintf(newPacket.characterInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str()); - newPacket.characterInfo.mapIndex = it.second.mapIndex; - newPacket.characterInfo.origin = it.second.origin; - newPacket.characterInfo.motion = it.second.motion; - newPacket.characterInfo.stats = it.second.stats; - - network.SendTo(&clientMap[packet.clientInfo.clientIndex].address, &newPacket); - } -} - -void ServerApplication::HandleDisconnect(SerialPacket packet) { +void ServerApplication::HandleDisconnect(ClientPacket* const argPacket) { //TODO: authenticate who is disconnecting/kicking //forward to the specified client - network.SendTo(&clientMap[accountMap[packet.clientInfo.accountIndex].clientIndex].address, &packet); + network.SendTo( + &clientMap[ accountMgr.GetAccount(argPacket->accountIndex)->clientIndex ].address, + dynamic_cast(argPacket) + ); - //unload client and server-side characters - for (std::map::iterator it = characterMap.begin(); it != characterMap.end(); /* EMPTY */ ) { - if (it->second.owner == packet.clientInfo.accountIndex) { + //save and unload this account's characters + //pump the unload message to all remaining clients + characterMgr.UnloadCharacterIf([&](std::map::iterator it) -> bool { + if (argPacket->accountIndex == it->second.owner) { PumpCharacterUnload(it->first); - SaveCharacter(it->first); - it = characterMap.erase(it); //efficient - continue; + return true; } - else { - ++it; - } - } + return false; + }); //erase the in-memory stuff - clientMap.erase(accountMap[packet.clientInfo.accountIndex].clientIndex); - UnloadUserAccount(packet.clientInfo.accountIndex); + clientMap.erase(accountMgr.GetAccount(argPacket->accountIndex)->clientIndex); + accountMgr.UnloadAccount(argPacket->accountIndex); //finished this routine - std::cout << "Disconnect, total: " << clientMap.size() << std::endl; + std::cout << "Disconnection, " << clientMap.size() << " clients and " << accountMgr.GetContainer()->size() << " accounts total" << std::endl; } -void ServerApplication::HandleShutdown(SerialPacket packet) { +void ServerApplication::HandleShutdown(SerialPacket* const argPacket) { //TODO: authenticate who is shutting the server down //end the server running = false; //disconnect all clients - packet.meta.type = SerialPacket::Type::DISCONNECT; - PumpPacket(packet); + SerialPacket newPacket; + newPacket.type = SerialPacketType::DISCONNECT; + PumpPacket(&newPacket); //finished this routine std::cout << "Shutdown signal accepted" << std::endl; @@ -335,13 +288,18 @@ void ServerApplication::HandleShutdown(SerialPacket packet) { //map management //------------------------- -void ServerApplication::HandleRegionRequest(SerialPacket packet) { - //TODO: this should be moved elsewhere - packet.meta.type = SerialPacket::Type::REGION_CONTENT; - packet.regionInfo.region = regionPager.GetRegion(packet.regionInfo.x, packet.regionInfo.y); +void ServerApplication::HandleRegionRequest(RegionPacket* const argPacket) { + RegionPacket newPacket; + + newPacket.type = SerialPacketType::REGION_CONTENT; + newPacket.roomIndex = argPacket->roomIndex; + newPacket.x = argPacket->x; + newPacket.y = argPacket->y; + + newPacket.region = roomMgr.GetRoom(argPacket->roomIndex)->GetPager()->GetRegion(argPacket->x, argPacket->y); //send the content - network.SendTo(&packet.meta.srcAddress, &packet); + network.SendTo(&argPacket->srcAddress, dynamic_cast(argPacket)); } //------------------------- @@ -381,6 +339,32 @@ void ServerApplication::HandleCharacterUpdate(SerialPacket packet) { //TODO: enemy management +//------------------------- +//mismanagement +//------------------------- + +void ServerApplication::HandleSynchronize(SerialPacket packet) { + //TODO: compensate for large distances + + //send all the server's data to this client + SerialPacket newPacket; + + //characters + newPacket.meta.type = SerialPacket::Type::CHARACTER_UPDATE; + for (auto& it : characterMap) { + //TODO: update this for the expanded CharacterData structure + newPacket.characterInfo.characterIndex = it.first; + snprintf(newPacket.characterInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str()); + snprintf(newPacket.characterInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str()); + newPacket.characterInfo.mapIndex = it.second.mapIndex; + newPacket.characterInfo.origin = it.second.origin; + newPacket.characterInfo.motion = it.second.motion; + newPacket.characterInfo.stats = it.second.stats; + + network.SendTo(&clientMap[packet.clientInfo.clientIndex].address, &newPacket); + } +} + //------------------------- //utility methods //------------------------- diff --git a/server/server_application.hpp b/server/server_application.hpp index cab0e1f..a0cb9b3 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -61,34 +61,34 @@ public: private: //handle incoming traffic - void HandlePacket(SerialPacket); + void HandlePacket(SerialPacket* const); //basic connections - void HandleBroadcastRequest(SerialPacket); - void HandleJoinRequest(SerialPacket); - void HandleDisconnect(SerialPacket); - void HandleShutdown(SerialPacket); + void HandleBroadcastRequest(SerialPacket* const); + void HandleJoinRequest(ClientPacket* const); + void HandleDisconnect(ClientPacket* const); + void HandleShutdown(SerialPacket* const); //map management - void HandleRegionRequest(SerialPacket); + void HandleRegionRequest(RegionPacket* const); //combat management //TODO: combat management //character management - void HandleCharacterNew(SerialPacket); - void HandleCharacterDelete(SerialPacket); - void HandleCharacterUpdate(SerialPacket); + void HandleCharacterNew(SerialPacket* const); + void HandleCharacterDelete(SerialPacket* const); + void HandleCharacterUpdate(SerialPacket* const); //enemy management //TODO: enemy management //mismanagement - void HandleSynchronize(SerialPacket); + void HandleSynchronize(SerialPacket* const); //utility methods //TODO: a function that only sends to characters in a certain proximity - void PumpPacket(SerialPacket); + void PumpPacket(SerialPacket* const); void PumpCharacterUnload(int uid); //APIs and utilities From 63be0ee70d3e9c236d06e05557bda876fe8b42d7 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sat, 7 Jun 2014 02:12:40 +1000 Subject: [PATCH 09/11] The server is building, but still needs work There is some missing character creation/unloading code, and there are a few other issues highlighted by TODO tags, see below. In general, 'mapIndex' has been renamed to 'roomIndex'. Multiple rooms have not been fully implemented yet, but I'm working on it. Other issues: * FileFormat needs to be changed to MapLoader * Server's character movement is still slaved to the clients The client does not build. --- common/gameplay/character_data.hpp | 2 +- common/map/map_file_format.hpp | 2 + common/map/region.hpp | 6 +- common/script/map_api.cpp | 2 + rsc/scripts/setup_server.sql | 2 +- server/character_manager.cpp | 6 +- server/room_data.hpp | 16 ++++-- server/room_manager.hpp | 1 + server/server_application.cpp | 91 +++++++++++++++++++----------- server/server_application.hpp | 13 ++--- 10 files changed, 85 insertions(+), 56 deletions(-) diff --git a/common/gameplay/character_data.hpp b/common/gameplay/character_data.hpp index ff129b2..361788b 100644 --- a/common/gameplay/character_data.hpp +++ b/common/gameplay/character_data.hpp @@ -45,7 +45,7 @@ struct CharacterData { std::string avatar; //world position - int mapIndex = 0; + int roomIndex = 0; Vector2 origin = {0.0,0.0}; Vector2 motion = {0.0,0.0}; Vector2 bounds = {0.0,0.0}; diff --git a/common/map/map_file_format.hpp b/common/map/map_file_format.hpp index 92f0c8d..75f5204 100644 --- a/common/map/map_file_format.hpp +++ b/common/map/map_file_format.hpp @@ -28,6 +28,8 @@ #include +//TODO: I'm unhappy with using this system, there needs to be a way to handle saving/loading better + class DummyFormat { public: void Load(Region** const, int x, int y); diff --git a/common/map/region.hpp b/common/map/region.hpp index 560161b..4c0d2cd 100644 --- a/common/map/region.hpp +++ b/common/map/region.hpp @@ -22,9 +22,9 @@ #ifndef REGION_HPP_ #define REGION_HPP_ -#define REGION_WIDTH 20 -#define REGION_HEIGHT 20 -#define REGION_DEPTH 3 +constexpr int REGION_WIDTH = 20; +constexpr int REGION_HEIGHT = 20; +constexpr int REGION_DEPTH = 3; class Region { public: diff --git a/common/script/map_api.cpp b/common/script/map_api.cpp index 9ecfea4..0bcaf80 100644 --- a/common/script/map_api.cpp +++ b/common/script/map_api.cpp @@ -27,6 +27,8 @@ #include "region_pager.hpp" //NOTE: When operating on a region, setTile() & getTile() *are not* zero indexed, but when operating on the entire map they *are* zero indexed. +//TODO: enforce all possible parameter counts +//TODO: update the map API to handle multiple rooms static int setTile(lua_State* L) { if (lua_gettop(L) == 5) { diff --git a/rsc/scripts/setup_server.sql b/rsc/scripts/setup_server.sql index 04a6aab..88d0a82 100644 --- a/rsc/scripts/setup_server.sql +++ b/rsc/scripts/setup_server.sql @@ -23,7 +23,7 @@ CREATE TABLE IF NOT EXISTS Characters ( birth timestamp NOT NULL DEFAULT (datetime()), --position - mapIndex INTEGER DEFAULT 0, + roomIndex INTEGER DEFAULT 0, originX INTEGER DEFAULT 0, originY INTEGER DEFAULT 0, diff --git a/server/character_manager.cpp b/server/character_manager.cpp index 34310c9..5767e60 100644 --- a/server/character_manager.cpp +++ b/server/character_manager.cpp @@ -33,7 +33,7 @@ static const char* CREATE_CHARACTER = "INSERT INTO Characters (owner, handle, av static const char* LOAD_CHARACTER = "SELECT * FROM Characters WHERE handle = ?;"; static const char* SAVE_CHARACTER = "UPDATE OR FAIL Characters SET " - "mapIndex = ?2," + "roomIndex = ?2," "originX = ?3," "originY = ?4," "level = ?5," @@ -148,7 +148,7 @@ int CharacterManager::LoadCharacter(int owner, std::string handle, std::string a //Don't cache the birth //world origin - newChar.mapIndex = sqlite3_column_int(statement, 5); + newChar.roomIndex = sqlite3_column_int(statement, 5); newChar.origin.x = (double)sqlite3_column_int(statement, 6); newChar.origin.y = (double)sqlite3_column_int(statement, 7); @@ -208,7 +208,7 @@ int CharacterManager::SaveCharacter(int uid) { //parameters bool ret = false; ret |= sqlite3_bind_int(statement, 1, uid) != SQLITE_OK; - ret |= sqlite3_bind_int(statement, 2, character.mapIndex) != SQLITE_OK; + ret |= sqlite3_bind_int(statement, 2, character.roomIndex) != SQLITE_OK; ret |= sqlite3_bind_int(statement, 3, (int)character.origin.x) != SQLITE_OK; ret |= sqlite3_bind_int(statement, 4, (int)character.origin.y) != SQLITE_OK; diff --git a/server/room_data.hpp b/server/room_data.hpp index 6826314..c436d54 100644 --- a/server/room_data.hpp +++ b/server/room_data.hpp @@ -22,6 +22,11 @@ #ifndef ROOMDATA_HPP_ #define ROOMDATA_HPP_ +//map system +#include "map_allocator.hpp" +#include "map_file_format.hpp" +#include "region_pager.hpp" + struct RoomData { enum class RoomType { OVERWORLD, @@ -31,11 +36,12 @@ struct RoomData { CAVES, }; - /* TODO: more - * "multiple rooms system" using this structure - * Pager - * collision map - */ + //members + RegionPager pager; + RoomType type; + + //TODO: collision map + //TODO: NPCs? }; #endif diff --git a/server/room_manager.hpp b/server/room_manager.hpp index 9b1dfc6..2caadaa 100644 --- a/server/room_manager.hpp +++ b/server/room_manager.hpp @@ -35,6 +35,7 @@ public: //public access methods //TODO + //TODO: setup the pagers and functors of each room object //accessors and mutators RoomData* GetRoom(int uid); diff --git a/server/server_application.cpp b/server/server_application.cpp index 7ef5f45..836af2b 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -174,14 +174,14 @@ void ServerApplication::HandlePacket(SerialPacket* const argPacket) { //character management case SerialPacketType::CHARACTER_NEW: - HandleCharacterNew(dynamic_cast(argPacket)); + HandleCharacterNew(dynamic_cast(argPacket)); break; case SerialPacketType::CHARACTER_DELETE: - HandleCharacterDelete(dynamic_cast(argPacket)); + HandleCharacterDelete(dynamic_cast(argPacket)); break; case SerialPacketType::CHARACTER_UPDATE: case SerialPacketType::CHARACTER_STATS_REQUEST: //TODO: ? - HandleCharacterUpdate(dynamic_cast(argPacket)); + HandleCharacterUpdate(dynamic_cast(argPacket)); break; //enemy management @@ -189,7 +189,7 @@ void ServerApplication::HandlePacket(SerialPacket* const argPacket) { //mismanagement case SerialPacketType::SYNCHRONIZE: - HandleSynchronize(dynamic_cast(argPacket)); + HandleSynchronize(dynamic_cast(argPacket)); break; //handle errors @@ -296,7 +296,7 @@ void ServerApplication::HandleRegionRequest(RegionPacket* const argPacket) { newPacket.x = argPacket->x; newPacket.y = argPacket->y; - newPacket.region = roomMgr.GetRoom(argPacket->roomIndex)->GetPager()->GetRegion(argPacket->x, argPacket->y); + newPacket.region = roomMgr.GetRoom(argPacket->roomIndex)->pager.GetRegion(argPacket->x, argPacket->y); //send the content network.SendTo(&argPacket->srcAddress, dynamic_cast(argPacket)); @@ -312,25 +312,46 @@ void ServerApplication::HandleRegionRequest(RegionPacket* const argPacket) { //Character Management //------------------------- -void ServerApplication::HandleCharacterNew(SerialPacket) { +void ServerApplication::HandleCharacterNew(CharacterPacket* const argPacket) { //TODO: fill this } -void ServerApplication::HandleCharacterDelete(SerialPacket) { +void ServerApplication::HandleCharacterDelete(CharacterPacket* const argPacket) { //TODO: fill this } -void ServerApplication::HandleCharacterUpdate(SerialPacket packet) { - //TODO: this should be moved elsewhere - if (characterMap.find(packet.characterInfo.characterIndex) == characterMap.end()) { - throw(std::runtime_error("Cannot update a non-existant character")); +void ServerApplication::HandleCharacterUpdate(CharacterPacket* const argPacket) { + CharacterData* character = characterMgr.GetCharacter(argPacket->characterIndex); + + //make a new character if this one doesn't exist + if (!character) { + //this isn't normal + std::cerr << "Warning: HandleCharacterUpdate() is passing to HandleCharacterNew()" << std::endl; + HandleCharacterNew(argPacket); + return; } - //TODO: the server needs it's own movement system too - characterMap[packet.characterInfo.characterIndex].origin = packet.characterInfo.origin; - characterMap[packet.characterInfo.characterIndex].motion = packet.characterInfo.motion; + /* TODO: rewrite this design flaw, read more + * Slaving the client to the server here is a terrible idea, instead there + * needs to be a utility function to update and send the server-side character + * to the clients. + * + * Other things to consider include functionality to reequip the character, + * apply status effects and to change the stats as well. These should all be + * handled server-side. + */ + character->roomIndex = argPacket->roomIndex; + character->origin = argPacket->origin; + character->motion = argPacket->motion; - PumpPacket(packet); + character->stats = argPacket->stats; + + //TODO: equipment + //TODO: items + //TODO: buffs + //TODO: debuffs + + PumpPacket(argPacket); } //------------------------- @@ -343,26 +364,29 @@ void ServerApplication::HandleCharacterUpdate(SerialPacket packet) { //mismanagement //------------------------- -void ServerApplication::HandleSynchronize(SerialPacket packet) { +void ServerApplication::HandleSynchronize(ClientPacket* const argPacket) { //TODO: compensate for large distances + //TODO: I quite dislike this function //send all the server's data to this client - SerialPacket newPacket; + CharacterPacket characterPacket; //characters - newPacket.meta.type = SerialPacket::Type::CHARACTER_UPDATE; - for (auto& it : characterMap) { + characterPacket.type = SerialPacketType::CHARACTER_UPDATE; + for (auto& it : *characterMgr.GetContainer()) { //TODO: update this for the expanded CharacterData structure - newPacket.characterInfo.characterIndex = it.first; - snprintf(newPacket.characterInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str()); - snprintf(newPacket.characterInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str()); - newPacket.characterInfo.mapIndex = it.second.mapIndex; - newPacket.characterInfo.origin = it.second.origin; - newPacket.characterInfo.motion = it.second.motion; - newPacket.characterInfo.stats = it.second.stats; + characterPacket.characterIndex = it.first; + snprintf(characterPacket.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str()); + snprintf(characterPacket.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str()); + characterPacket.roomIndex = it.second.roomIndex; + characterPacket.origin = it.second.origin; + characterPacket.motion = it.second.motion; + characterPacket.stats = it.second.stats; - network.SendTo(&clientMap[packet.clientInfo.clientIndex].address, &newPacket); + network.SendTo(&clientMap[argPacket->clientIndex].address, dynamic_cast(&characterPacket)); } + + //TODO: more } //------------------------- @@ -371,17 +395,16 @@ void ServerApplication::HandleSynchronize(SerialPacket packet) { //TODO: a function that only sends to characters in a certain proximity -void ServerApplication::PumpPacket(SerialPacket packet) { - //NOTE: I don't really like this, but it'll do for now +void ServerApplication::PumpPacket(SerialPacket* const argPacket) { for (auto& it : clientMap) { - network.SendTo(&it.second.address, &packet); + network.SendTo(&it.second.address, argPacket); } } void ServerApplication::PumpCharacterUnload(int uid) { //delete the client-side character(s) - SerialPacket delPacket; - delPacket.meta.type = SerialPacket::Type::CHARACTER_DELETE; - delPacket.characterInfo.characterIndex = uid; - PumpPacket(delPacket); + CharacterPacket newPacket; + newPacket.type = SerialPacketType::CHARACTER_DELETE; + newPacket.characterIndex = uid; + PumpPacket(dynamic_cast(&newPacket)); } diff --git a/server/server_application.hpp b/server/server_application.hpp index a0cb9b3..05168df 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -30,11 +30,6 @@ #include "enemy_manager.hpp" #include "room_manager.hpp" -//maps -#include "map_allocator.hpp" -#include "map_file_format.hpp" -#include "region_pager.hpp" - //common utilities #include "udp_network_utility.hpp" #include "config_utility.hpp" @@ -76,15 +71,15 @@ private: //TODO: combat management //character management - void HandleCharacterNew(SerialPacket* const); - void HandleCharacterDelete(SerialPacket* const); - void HandleCharacterUpdate(SerialPacket* const); + void HandleCharacterNew(CharacterPacket* const); + void HandleCharacterDelete(CharacterPacket* const); + void HandleCharacterUpdate(CharacterPacket* const); //enemy management //TODO: enemy management //mismanagement - void HandleSynchronize(SerialPacket* const); + void HandleSynchronize(ClientPacket* const); //utility methods //TODO: a function that only sends to characters in a certain proximity From ee2ac0b7a9ae854c072ab0c6fc417131d02ea98f Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 8 Jun 2014 00:36:05 +1000 Subject: [PATCH 10/11] Created MAX_PACKET_SIZE --- common/network/packet/serial_packet.hpp | 10 ++++++++++ server/server_application.cpp | 21 ++++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/common/network/packet/serial_packet.hpp b/common/network/packet/serial_packet.hpp index 7b7137f..44198aa 100644 --- a/common/network/packet/serial_packet.hpp +++ b/common/network/packet/serial_packet.hpp @@ -31,4 +31,14 @@ //NOTE: SerialPacket is defined in serial_packet_base.hpp +union MaxPacket { + CharacterPacket a; + ClientPacket b; + CombatPacket c; + EnemyPacket d; + RegionPacket e; + ServerPacket f; +}; +constexpr int MAX_PACKET_SIZE = sizeof(MaxPacket); + #endif diff --git a/server/server_application.cpp b/server/server_application.cpp index 836af2b..f4dd348 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -115,14 +115,29 @@ void ServerApplication::Init(int argc, char** argv) { //------------------------- std::cout << "Startup completed successfully" << std::endl; + + //------------------------- + //debugging + //------------------------- + + std::cout << "Debugging dump:" << std::endl; + std::cout << "\tMAX_PACKET_SIZE:\t\t" << MAX_PACKET_SIZE << std::endl; + std::cout << "\tsizeof(SerialPacket):\t\t" << sizeof(SerialPacket) << std::endl; + std::cout << "\tsizeof(CharacterPacket):\t" << sizeof(CharacterPacket) << std::endl; + std::cout << "\t\tsizeof(Statistics):\t" << sizeof(Statistics) << std::endl; + std::cout << "\tsizeof(ClientPacket):\t\t" << sizeof(ClientPacket) << std::endl; + std::cout << "\tsizeof(CombatPacket):\t\t" << sizeof(CombatPacket) << std::endl; + std::cout << "\tsizeof(EnemyPacket):\t\t" << sizeof(EnemyPacket) << std::endl; + std::cout << "\tsizeof(RegionPacket):\t\t" << sizeof(RegionPacket) << std::endl; + std::cout << "\tsizeof(ServerPacket):\t\t" << sizeof(ServerPacket) << std::endl; } void ServerApplication::Proc() { - SerialPacket packet; + char packetBuffer[MAX_PACKET_SIZE]; while(running) { //suck in the waiting packets & process them - while(network.Receive(&packet)) { - HandlePacket(&packet); + while(network.Receive(reinterpret_cast(packetBuffer))) { + HandlePacket(reinterpret_cast(packetBuffer)); } //update the internals //TODO: update the internals i.e. player positions From 5175a4e40d45037012473393b7d407b1ac5bf1f4 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 8 Jun 2014 02:51:12 +1000 Subject: [PATCH 11/11] Fleshed out and rewrote some code Fleshed out HandleCharacterNew() and HandleCharacterDelete(), and rewrote HandleSynchronize(). --- server/character_manager.cpp | 1 - server/server_application.cpp | 91 +++++++++++++++++++++++++++-------- server/server_application.hpp | 1 + todo.txt | 11 +++-- 4 files changed, 81 insertions(+), 23 deletions(-) diff --git a/server/character_manager.cpp b/server/character_manager.cpp index 5767e60..0a1d4d7 100644 --- a/server/character_manager.cpp +++ b/server/character_manager.cpp @@ -68,7 +68,6 @@ CharacterManager::~CharacterManager() { } } -//TODO: should statistics be stored separately? //TODO: default stats as a parameter? This would be good for differing beggining states or multiple classes int CharacterManager::CreateCharacter(int owner, std::string handle, std::string avatar) { //Create the character, failing if it exists diff --git a/server/server_application.cpp b/server/server_application.cpp index f4dd348..44467a0 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -195,7 +195,7 @@ void ServerApplication::HandlePacket(SerialPacket* const argPacket) { HandleCharacterDelete(dynamic_cast(argPacket)); break; case SerialPacketType::CHARACTER_UPDATE: - case SerialPacketType::CHARACTER_STATS_REQUEST: //TODO: ? + case SerialPacketType::CHARACTER_STATS_REQUEST: HandleCharacterUpdate(dynamic_cast(argPacket)); break; @@ -328,11 +328,52 @@ void ServerApplication::HandleRegionRequest(RegionPacket* const argPacket) { //------------------------- void ServerApplication::HandleCharacterNew(CharacterPacket* const argPacket) { - //TODO: fill this + int characterIndex = characterMgr.CreateCharacter(argPacket->accountIndex, argPacket->handle, argPacket->avatar); + + if (characterIndex == -1) { + //TODO: rejection packet + std::cerr << "Warning: Character already loaded" << std::endl; + return; + } + + if (characterIndex == -2) { + //TODO: rejection packet + std::cerr << "Warning: Character already exists" << std::endl; + return; + } + + //send this new character to all clients + CharacterPacket newPacket; + newPacket.type = SerialPacketType::CHARACTER_NEW; + CopyCharacterToPacket(&newPacket, characterIndex); + PumpPacket(&newPacket); } void ServerApplication::HandleCharacterDelete(CharacterPacket* const argPacket) { - //TODO: fill this + //NOTE: Disconnecting only unloads a character, this explicitly deletes it + + //Authenticate the owner is doing this + int characterIndex = characterMgr.LoadCharacter(argPacket->accountIndex, argPacket->handle, argPacket->avatar); + + //if this is not your character + if (characterIndex == -2) { + //TODO: rejection packet + std::cerr << "Warning: Character cannot be deleted" << std::endl; + + //unload an unneeded character + if (characterIndex != -1) { + characterMgr.UnloadCharacter(characterIndex); + } + return; + } + + //delete it + characterMgr.DeleteCharacter(characterIndex); + + //TODO: success packet + + //Unload this character from all clients + PumpCharacterUnload(characterIndex); } void ServerApplication::HandleCharacterUpdate(CharacterPacket* const argPacket) { @@ -381,27 +422,22 @@ void ServerApplication::HandleCharacterUpdate(CharacterPacket* const argPacket) void ServerApplication::HandleSynchronize(ClientPacket* const argPacket) { //TODO: compensate for large distances - //TODO: I quite dislike this function + //NOTE: I quite dislike this function - //send all the server's data to this client - CharacterPacket characterPacket; + //send all of the server's data to this client + ClientData& client = clientMap[argPacket->clientIndex]; + + //send all characters + CharacterPacket newPacket; + newPacket.type = SerialPacketType::CHARACTER_UPDATE; - //characters - characterPacket.type = SerialPacketType::CHARACTER_UPDATE; for (auto& it : *characterMgr.GetContainer()) { - //TODO: update this for the expanded CharacterData structure - characterPacket.characterIndex = it.first; - snprintf(characterPacket.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str()); - snprintf(characterPacket.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str()); - characterPacket.roomIndex = it.second.roomIndex; - characterPacket.origin = it.second.origin; - characterPacket.motion = it.second.motion; - characterPacket.stats = it.second.stats; - - network.SendTo(&clientMap[argPacket->clientIndex].address, dynamic_cast(&characterPacket)); + newPacket.characterIndex = it.first; + CopyCharacterToPacket(&newPacket, it.first); + network.SendTo(&client.address, dynamic_cast(&newPacket)); } - //TODO: more + //TODO: more in HandleSynchronize() } //------------------------- @@ -423,3 +459,20 @@ void ServerApplication::PumpCharacterUnload(int uid) { newPacket.characterIndex = uid; PumpPacket(dynamic_cast(&newPacket)); } + +void ServerApplication::CopyCharacterToPacket(CharacterPacket* const packet, int characterIndex) { + CharacterData* character = characterMgr.GetCharacter(characterIndex); + if (!character) { + throw(std::runtime_error("Failed to copy a character to a packet")); + } + + //TODO: keep this up to date when the character changes + packet->characterIndex = characterIndex; + snprintf(packet->handle, PACKET_STRING_SIZE, "%s", character->handle.c_str()); + snprintf(packet->avatar, PACKET_STRING_SIZE, "%s", character->avatar.c_str()); + packet->accountIndex = character->owner; + packet->roomIndex = character->roomIndex; + packet->origin = character->origin; + packet->motion = character->motion; + packet->stats = character->stats; +} \ No newline at end of file diff --git a/server/server_application.hpp b/server/server_application.hpp index 05168df..ca2129b 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -85,6 +85,7 @@ private: //TODO: a function that only sends to characters in a certain proximity void PumpPacket(SerialPacket* const); void PumpCharacterUnload(int uid); + void CopyCharacterToPacket(CharacterPacket* const packet, int characterIndex); //APIs and utilities sqlite3* database = nullptr; diff --git a/todo.txt b/todo.txt index fa7d60d..605e60a 100644 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,11 @@ -TODO: Modulate this god class -TODO: Segment SerialPacket? -TODO: Not all structures in common/gameplay are needed by the client +TODO: MapLoader, in place of FileFormat +TODO: Get the rooms working +TODO: update the map API to handle multiple rooms + +TODO: Rejection packets +TODO: Authentication +TODO: server is slaved to the client + TODO: I need to keep the documentation up to date. Namely, the GDD is getting out of date. TODO: I completely forgot about status ailments TODO: Time delay for requesting region packets