diff --git a/client/character.cpp b/client/character.cpp index eaa38d8..70ee4a9 100644 --- a/client/character.cpp +++ b/client/character.cpp @@ -21,14 +21,14 @@ */ #include "character.hpp" -void Character::Update(double delta) { +void Character::Update() { if (motion.x && motion.y) { - origin += motion * delta * CHARACTER_WALKING_MOD; + origin += motion * CHARACTER_WALKING_MOD; } else if (motion != 0) { - origin += motion * delta; + origin += motion; } - sprite.Update(delta); + sprite.Update(0.016); } void Character::DrawTo(SDL_Surface* const dest, int camX, int camY) { diff --git a/client/character.hpp b/client/character.hpp index bde4268..23924a4 100644 --- a/client/character.hpp +++ b/client/character.hpp @@ -40,7 +40,7 @@ public: Character() = default; ~Character() = default; - void Update(double delta); + void Update(); //graphics void DrawTo(SDL_Surface* const, int camX, int camY); diff --git a/client/client_application.cpp b/client/client_application.cpp index 16ad96c..75a9d9b 100644 --- a/client/client_application.cpp +++ b/client/client_application.cpp @@ -120,7 +120,6 @@ void ClientApplication::Proc() { //prepare the time system typedef std::chrono::steady_clock Clock; - std::chrono::duration delta(16); Clock::time_point simTime = Clock::now(); Clock::time_point realTime; @@ -138,8 +137,9 @@ void ClientApplication::Proc() { //simulate game time while (simTime < realTime) { //call each user defined function - activeScene->RunFrame(double(delta.count()) / std::chrono::duration::period::den); - simTime += delta; + activeScene->RunFrame(); + //~60 FPS + simTime += std::chrono::duration(16); } //draw the game to the screen diff --git a/client/scenes/base_scene.cpp b/client/scenes/base_scene.cpp index 48512ec..d4b7824 100644 --- a/client/scenes/base_scene.cpp +++ b/client/scenes/base_scene.cpp @@ -75,10 +75,10 @@ SceneList BaseScene::GetNextScene() const { //Frame loop //------------------------- -void BaseScene::RunFrame(double delta) { +void BaseScene::RunFrame() { FrameStart(); HandleEvents(); - Update(delta); + Update(); FrameEnd(); } @@ -86,6 +86,7 @@ void BaseScene::RenderFrame() { SDL_FillRect(screen, 0, 0); Render(screen); SDL_Flip(screen); + SDL_Delay(10); } //------------------------- diff --git a/client/scenes/base_scene.hpp b/client/scenes/base_scene.hpp index a4bfd88..d954ca0 100644 --- a/client/scenes/base_scene.hpp +++ b/client/scenes/base_scene.hpp @@ -40,13 +40,13 @@ public: SceneList GetNextScene() const; //Frame loop - virtual void RunFrame(double delta); + virtual void RunFrame(); virtual void RenderFrame(); protected: virtual void FrameStart() {} virtual void HandleEvents(); - virtual void Update(double delta) {} + virtual void Update() {} virtual void FrameEnd() {} virtual void Render(SDL_Surface* const screen) {} diff --git a/client/scenes/clean_up.cpp b/client/scenes/clean_up.cpp index 416a1c8..1be9e5c 100644 --- a/client/scenes/clean_up.cpp +++ b/client/scenes/clean_up.cpp @@ -80,22 +80,15 @@ CleanUp::~CleanUp() { //Frame loop //------------------------- -void CleanUp::Update(double delta) { +void CleanUp::Update() { if (std::chrono::steady_clock::now() - startTick > std::chrono::duration(10)) { - QuitEvent(); + SetNextScene(SceneList::MAINMENU); } //BUGFIX: Eat incoming packets while(network.Receive()); } -void CleanUp::RenderFrame() { - SDL_FillRect(GetScreen(), 0, 0); - Render(GetScreen()); - SDL_Flip(GetScreen()); - fps.Calculate(); -} - void CleanUp::Render(SDL_Surface* const screen) { backButton.DrawTo(screen); font.DrawStringTo("You have been disconnected.", screen, 50, 30); diff --git a/client/scenes/clean_up.hpp b/client/scenes/clean_up.hpp index ac39b44..a408d3d 100644 --- a/client/scenes/clean_up.hpp +++ b/client/scenes/clean_up.hpp @@ -30,12 +30,8 @@ #include "raster_font.hpp" #include "button.hpp" -//common -#include "frame_rate.hpp" - -#include "character.hpp" - //client +#include "character.hpp" #include "base_scene.hpp" //std namespace @@ -54,8 +50,7 @@ public: protected: //Frame loop - void Update(double delta); - void RenderFrame(); + void Update(); void Render(SDL_Surface* const); //Event handlers @@ -79,7 +74,6 @@ protected: //UI Button backButton; - FrameRate fps; //auto return std::chrono::steady_clock::time_point startTick; diff --git a/client/scenes/in_world.cpp b/client/scenes/in_world.cpp index b2de46c..f78103f 100644 --- a/client/scenes/in_world.cpp +++ b/client/scenes/in_world.cpp @@ -92,17 +92,17 @@ void InWorld::FrameStart() { // } -void InWorld::Update(double delta) { +void InWorld::Update() { //suck in and process all waiting packets - SerialPacket* packetBuffer = static_cast(malloc(MAX_PACKET_SIZE)); + SerialPacket* packetBuffer = reinterpret_cast(new char[MAX_PACKET_SIZE]); while(network.Receive(packetBuffer)) { HandlePacket(packetBuffer); } - free(static_cast(packetBuffer)); + delete reinterpret_cast(packetBuffer); //update the characters for (auto& it : characterMap) { - it.second.Update(delta); + it.second.Update(); } //check the map @@ -129,7 +129,7 @@ void InWorld::Update(double delta) { } if ((localCharacter->GetOrigin() + localCharacter->GetBounds()).CheckOverlap(wallBounds)) { - localCharacter->SetOrigin(localCharacter->GetOrigin() - (localCharacter->GetMotion() * delta)); + localCharacter->SetOrigin(localCharacter->GetOrigin() - (localCharacter->GetMotion())); localCharacter->SetMotion({0,0}); localCharacter->CorrectSprite(); SendPlayerUpdate(); diff --git a/client/scenes/in_world.hpp b/client/scenes/in_world.hpp index c72ff73..e263bc8 100644 --- a/client/scenes/in_world.hpp +++ b/client/scenes/in_world.hpp @@ -59,7 +59,7 @@ public: protected: //Frame loop void FrameStart(); - void Update(double delta); + void Update(); void FrameEnd(); void RenderFrame(); void Render(SDL_Surface* const); diff --git a/client/scenes/lobby_menu.cpp b/client/scenes/lobby_menu.cpp index d866159..80504c3 100644 --- a/client/scenes/lobby_menu.cpp +++ b/client/scenes/lobby_menu.cpp @@ -82,13 +82,13 @@ void LobbyMenu::FrameStart() { // } -void LobbyMenu::Update(double delta) { +void LobbyMenu::Update() { //suck in and process all waiting packets - SerialPacket* packetBuffer = static_cast(malloc(MAX_PACKET_SIZE)); + SerialPacket* packetBuffer = reinterpret_cast(new char[MAX_PACKET_SIZE]); while(network.Receive(packetBuffer)) { HandlePacket(packetBuffer); } - free(static_cast(packetBuffer)); + delete reinterpret_cast(packetBuffer); } void LobbyMenu::FrameEnd() { diff --git a/client/scenes/lobby_menu.hpp b/client/scenes/lobby_menu.hpp index 7020ac8..03160c2 100644 --- a/client/scenes/lobby_menu.hpp +++ b/client/scenes/lobby_menu.hpp @@ -47,7 +47,7 @@ public: protected: //Frame loop void FrameStart(); - void Update(double delta); + void Update(); void FrameEnd(); void Render(SDL_Surface* const); diff --git a/client/scenes/main_menu.cpp b/client/scenes/main_menu.cpp index ca82ef8..5aa431b 100644 --- a/client/scenes/main_menu.cpp +++ b/client/scenes/main_menu.cpp @@ -72,7 +72,7 @@ void MainMenu::FrameStart() { // } -void MainMenu::Update(double delta) { +void MainMenu::Update() { // } diff --git a/client/scenes/main_menu.hpp b/client/scenes/main_menu.hpp index 2dec3ae..9572499 100644 --- a/client/scenes/main_menu.hpp +++ b/client/scenes/main_menu.hpp @@ -37,7 +37,7 @@ public: protected: //Frame loop void FrameStart(); - void Update(double delta); + void Update(); void FrameEnd(); void Render(SDL_Surface* const); diff --git a/client/scenes/options_menu.cpp b/client/scenes/options_menu.cpp index 539cd44..7aa2493 100644 --- a/client/scenes/options_menu.cpp +++ b/client/scenes/options_menu.cpp @@ -59,7 +59,7 @@ void OptionsMenu::FrameStart() { // } -void OptionsMenu::Update(double delta) { +void OptionsMenu::Update() { // } diff --git a/client/scenes/options_menu.hpp b/client/scenes/options_menu.hpp index 8570644..5bb3eed 100644 --- a/client/scenes/options_menu.hpp +++ b/client/scenes/options_menu.hpp @@ -38,7 +38,7 @@ public: protected: //Frame loop void FrameStart(); - void Update(double delta); + void Update(); void FrameEnd(); void Render(SDL_Surface* const); diff --git a/client/scenes/splash_screen.cpp b/client/scenes/splash_screen.cpp index 2c3b233..5473d79 100644 --- a/client/scenes/splash_screen.cpp +++ b/client/scenes/splash_screen.cpp @@ -40,7 +40,7 @@ SplashScreen::~SplashScreen() { //Frame loop //------------------------- -void SplashScreen::Update(double delta) { +void SplashScreen::Update() { if (std::chrono::steady_clock::now() - startTick > std::chrono::duration(1)) { SetNextScene(SceneList::MAINMENU); } diff --git a/client/scenes/splash_screen.hpp b/client/scenes/splash_screen.hpp index 9d55c0c..c6440c1 100644 --- a/client/scenes/splash_screen.hpp +++ b/client/scenes/splash_screen.hpp @@ -36,7 +36,7 @@ public: protected: //Frame loop - void Update(double delta); + void Update(); void Render(SDL_Surface* const); //members diff --git a/common/gameplay/character_defines.hpp b/common/gameplay/character_defines.hpp index 43777e0..484fcfa 100644 --- a/common/gameplay/character_defines.hpp +++ b/common/gameplay/character_defines.hpp @@ -25,7 +25,7 @@ #include //the speeds that the characters move -constexpr double CHARACTER_WALKING_SPEED = 140.0; +constexpr double CHARACTER_WALKING_SPEED = 2.24; constexpr double CHARACTER_WALKING_MOD = 1.0/sqrt(2.0); //the bounds for the character objects, mapped to the default sprites diff --git a/copyright.txt b/copyright.txt new file mode 100644 index 0000000..08613f0 --- /dev/null +++ b/copyright.txt @@ -0,0 +1,15 @@ +Future versions (to be determined) may be released under a modified version of the Uplink Developer's License. + +The current version of Tortuga is released under the zlib license. + +Copyright (c) 2013, 2014 Kayne Ruse + +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. \ No newline at end of file diff --git a/makefile b/makefile index 3a5a667..8ae66e9 100644 --- a/makefile +++ b/makefile @@ -19,7 +19,12 @@ debug: export CXXFLAGS+=-g debug: clean all release: export CXXFLAGS+=-static-libgcc -static-libstdc++ -release: clean all +release: clean all package + +#For use on my machine ONLY +package: + rar a -r -ep Tortuga.rar out/*.exe out/*.dll + rar a -r Tortuga.rar rsc/* copyright.txt $(OUTDIR): mkdir $(OUTDIR) diff --git a/rsc/scripts/setup_server.lua b/rsc/scripts/setup_server.lua index e73d5f7..8b43720 100644 --- a/rsc/scripts/setup_server.lua +++ b/rsc/scripts/setup_server.lua @@ -17,6 +17,7 @@ tiles = { --custom generation systems here function islandGenerator(region) + io.write("Generating (", Region.GetX(region), ", ", Region.GetY(region), ")\n") for i = 1, Region.GetWidth(region) do for j = 1, Region.GetHeight(region) do local dist = math.dist(0, 0, i + Region.GetX(region) -1, j + Region.GetY(region) -1) diff --git a/server/accounts/account_manager.hpp b/server/accounts/account_manager.hpp index 7c6cc1f..2e631b5 100644 --- a/server/accounts/account_manager.hpp +++ b/server/accounts/account_manager.hpp @@ -23,16 +23,14 @@ #define ACCOUNTMANAGER_HPP_ #include "account_data.hpp" +#include "singleton.hpp" #include "sqlite3/sqlite3.h" #include -class AccountManager { +class AccountManager : public Singleton { public: - AccountManager() = default; - ~AccountManager() { UnloadAll(); }; - //public access methods int CreateAccount(std::string username, int clientIndex); int LoadAccount(std::string username, int clientIndex); @@ -50,6 +48,11 @@ public: sqlite3* GetDatabase(); private: + friend Singleton; + + AccountManager() = default; + ~AccountManager() = default; + std::map accountMap; sqlite3* database = nullptr; }; diff --git a/server/accounts/makefile b/server/accounts/makefile index 8d12afe..f24e1ba 100644 --- a/server/accounts/makefile +++ b/server/accounts/makefile @@ -1,5 +1,5 @@ #config -INCLUDES+=. +INCLUDES+=. ../../common/utilities LIBS+= CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) diff --git a/server/characters/character_manager.hpp b/server/characters/character_manager.hpp index 191fd4c..084d595 100644 --- a/server/characters/character_manager.hpp +++ b/server/characters/character_manager.hpp @@ -23,17 +23,15 @@ #define CHARACTERMANAGER_HPP_ #include "character_data.hpp" +#include "singleton.hpp" #include "sqlite3/sqlite3.h" #include #include -class CharacterManager { +class CharacterManager : public Singleton { public: - CharacterManager() = default; - ~CharacterManager() { UnloadAll(); }; - //public access methods int CreateCharacter(int owner, std::string handle, std::string avatar); int LoadCharacter(int owner, std::string handle, std::string avatar); @@ -53,6 +51,11 @@ public: sqlite3* GetDatabase(); private: + friend Singleton; + + CharacterManager() = default; + ~CharacterManager() = default; + std::map characterMap; sqlite3* database = nullptr; }; diff --git a/server/main.cpp b/server/main.cpp index 71ebb7c..8987d26 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -33,7 +33,10 @@ using namespace std; int main(int argc, char** argv) { try { //create the singletons + AccountManager::Create(); + CharacterManager::Create(); ConfigUtility::Create(); + RoomManager::Create(); UDPNetworkUtility::Create(); //call the server's routines @@ -47,7 +50,10 @@ int main(int argc, char** argv) { ServerApplication::Delete(); //delete the singletons + AccountManager::Delete(); + CharacterManager::Delete(); ConfigUtility::Delete(); + RoomManager::Delete(); UDPNetworkUtility::Delete(); } catch(exception& e) { diff --git a/server/rooms/makefile b/server/rooms/makefile index f4921ea..ea66828 100644 --- a/server/rooms/makefile +++ b/server/rooms/makefile @@ -1,5 +1,5 @@ #config -INCLUDES+=. ../mapgen ../mapgen/generators ../../common/map +INCLUDES+=. ../../common/map ../../common/utilities LIBS+= CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) diff --git a/server/rooms/room_manager.hpp b/server/rooms/room_manager.hpp index 50a2074..2f13893 100644 --- a/server/rooms/room_manager.hpp +++ b/server/rooms/room_manager.hpp @@ -23,18 +23,14 @@ #define ROOMMANAGER_HPP_ #include "room_data.hpp" +#include "singleton.hpp" #include "lua/lua.hpp" #include -#define ROOM_MANAGER_PSEUDOINDEX "RoomManager" - -class RoomManager { +class RoomManager : public Singleton { public: - RoomManager() = default; - ~RoomManager() = default; - //public access methods int CreateRoom(); void UnloadRoom(int uid); @@ -52,6 +48,11 @@ public: lua_State* GetLuaState() { return luaState; } private: + friend Singleton; + + RoomManager() = default; + ~RoomManager() = default; + std::map roomMap; lua_State* luaState = nullptr; int counter = 0; diff --git a/server/rooms/room_manager_api.cpp b/server/rooms/room_manager_api.cpp index c8f1b5c..02565b9 100644 --- a/server/rooms/room_manager_api.cpp +++ b/server/rooms/room_manager_api.cpp @@ -26,45 +26,24 @@ #include static int getRoom(lua_State* L) { - //get the room manager - lua_pushstring(L, ROOM_MANAGER_PSEUDOINDEX); - lua_gettable(L, LUA_REGISTRYINDEX); - RoomManager* roomMgr = reinterpret_cast(lua_touserdata(L, -1)); - - //push the room and return it - lua_pushlightuserdata(L, reinterpret_cast( roomMgr->GetRoom(lua_tointeger(L, -2)) )); + //find, push and return the room + RoomData* room = RoomManager::GetSingleton().GetRoom(lua_tointeger(L, -2)); + lua_pushlightuserdata(L, reinterpret_cast(room)); return 1; } static int createRoom(lua_State* L) { //TODO: check parameter count for the glue functions - //get the room manager - lua_pushstring(L, ROOM_MANAGER_PSEUDOINDEX); - lua_gettable(L, LUA_REGISTRYINDEX); - RoomManager* roomMgr = reinterpret_cast(lua_touserdata(L, -1)); - - //create the room - int uid = roomMgr->CreateRoom(); - - //TODO: any room parameters - - //return the new room - lua_pushlightuserdata(L, roomMgr->FindRoom(uid)); + //create, find and return the room + int uid = RoomManager::GetSingleton().CreateRoom(); + lua_pushlightuserdata(L, RoomManager::GetSingleton().FindRoom(uid)); return 1; } static int unloadRoom(lua_State* L) { - //get the room manager - lua_pushstring(L, ROOM_MANAGER_PSEUDOINDEX); - lua_gettable(L, LUA_REGISTRYINDEX); - RoomManager* roomMgr = reinterpret_cast(lua_touserdata(L, -1)); - - //TODO: any room parameters - //unload the specified room - roomMgr->UnloadRoom(lua_tointeger(L, -2)); - + RoomManager::GetSingleton().UnloadRoom(lua_tointeger(L, -2)); return 0; } diff --git a/server/server_application.hpp b/server/server_application.hpp index 17b6e41..372549b 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -92,13 +92,13 @@ private: std::map clientMap; //managers - AccountManager accountMgr; - CharacterManager characterMgr; - RoomManager roomMgr; + AccountManager& accountMgr = AccountManager::GetSingleton(); + CharacterManager& characterMgr = CharacterManager::GetSingleton(); + RoomManager& roomMgr = RoomManager::GetSingleton(); //misc bool running = true; - int clientUID = 0; + int clientIndex = 0; }; #endif diff --git a/server/server_logic.cpp b/server/server_logic.cpp new file mode 100644 index 0000000..e4e1f5f --- /dev/null +++ b/server/server_logic.cpp @@ -0,0 +1,233 @@ +/* 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" + +//for PACKET_BUFFER_SIZE +#include "serial.hpp" + +//utility functions +#include "sql_utility.hpp" +#include "utility.hpp" + +#include +#include +#include + +//------------------------- +//public methods +//------------------------- + +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 " << argv[0] << std::endl; + + //load the prerequisites + 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 + //------------------------- + + //set the hooks + accountMgr.SetDatabase(database); + characterMgr.SetDatabase(database); + + roomMgr.SetLuaState(luaState); + + std::cout << "Internal managers initialized" << 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 + //------------------------- + + //TODO: enable/disable these with a switch +#define DEBUG_OUTPUT_VAR(x) std::cout << "\t" << #x << ": " << x << std::endl; + + std::cout << "Internal sizes:" << std::endl; + + DEBUG_OUTPUT_VAR(sizeof(Region::type_t)); + DEBUG_OUTPUT_VAR(sizeof(Region)); + DEBUG_OUTPUT_VAR(REGION_WIDTH); + DEBUG_OUTPUT_VAR(REGION_HEIGHT); + DEBUG_OUTPUT_VAR(REGION_DEPTH); + DEBUG_OUTPUT_VAR(REGION_SOLID_FOOTPRINT); + DEBUG_OUTPUT_VAR(REGION_FOOTPRINT); + DEBUG_OUTPUT_VAR(PACKET_BUFFER_SIZE); + DEBUG_OUTPUT_VAR(MAX_PACKET_SIZE); + +#undef DEBUG_OUTPUT_VAR + + //------------------------- + //finalize the startup + //------------------------- + + std::cout << "Startup completed successfully" << std::endl; + + //------------------------- + //debugging + //------------------------- + + //... +} + +void ServerApplication::Proc() { + SerialPacket* packetBuffer = reinterpret_cast(new char[MAX_PACKET_SIZE]); + while(running) { + //suck in the waiting packets & process them + while(network.Receive(packetBuffer)) { + HandlePacket(packetBuffer); + } + //update the internals + //BUG: #30 Update the internals i.e. player positions + + //give the computer a break + SDL_Delay(10); + } + delete reinterpret_cast(packetBuffer); +} + +void ServerApplication::Quit() { + std::cout << "Shutting down" << std::endl; + + //close the managers + clientMap.clear(); + accountMgr.UnloadAll(); + characterMgr.UnloadAll(); + //TODO: unload combats + //TODO: unload enemies + roomMgr.UnloadAll(); + + //APIs + lua_close(luaState); + sqlite3_close_v2(database); + network.Close(); + SDLNet_Quit(); + SDL_Quit(); + + std::cout << "Clean exit" << std::endl; +} + +//------------------------- +//direct incoming traffic +//------------------------- + +void ServerApplication::HandlePacket(SerialPacket* const argPacket) { + switch(argPacket->type) { + //basic connections + case SerialPacketType::BROADCAST_REQUEST: + HandleBroadcastRequest(static_cast(argPacket)); + break; + case SerialPacketType::JOIN_REQUEST: + HandleJoinRequest(static_cast(argPacket)); + break; + case SerialPacketType::DISCONNECT: + HandleDisconnect(static_cast(argPacket)); + break; + case SerialPacketType::SHUTDOWN: + HandleShutdown(static_cast(argPacket)); + break; + + //map management + case SerialPacketType::REGION_REQUEST: + HandleRegionRequest(static_cast(argPacket)); + break; + + //combat management + //TODO: combat management + + //character management + case SerialPacketType::CHARACTER_NEW: + HandleCharacterNew(static_cast(argPacket)); + break; + case SerialPacketType::CHARACTER_DELETE: + HandleCharacterDelete(static_cast(argPacket)); + break; + case SerialPacketType::CHARACTER_UPDATE: + case SerialPacketType::CHARACTER_STATS_REQUEST: + HandleCharacterUpdate(static_cast(argPacket)); + break; + + //enemy management + //TODO: enemy management + + //mismanagement + case SerialPacketType::SYNCHRONIZE: + HandleSynchronize(static_cast(argPacket)); + break; + + //handle errors + default: { + std::string msg = "Unknown SerialPacketType encountered in the server: "; + msg += to_string_custom(static_cast(argPacket->type)); + throw(std::runtime_error(msg)); + } + break; + } +} \ No newline at end of file diff --git a/server/server_application.cpp b/server/server_methods.cpp similarity index 60% rename from server/server_application.cpp rename to server/server_methods.cpp index a3ae389..d993b83 100644 --- a/server/server_application.cpp +++ b/server/server_methods.cpp @@ -21,220 +21,7 @@ */ #include "server_application.hpp" -//for PACKET_BUFFER_SIZE -#include "serial.hpp" - -//utility functions -#include "sql_utility.hpp" -#include "utility.hpp" - -#include #include -#include - -//------------------------- -//public methods -//------------------------- - -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 " << argv[0] << std::endl; - - //load the prerequisites - 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 - //------------------------- - - //set the hooks - accountMgr.SetDatabase(database); - characterMgr.SetDatabase(database); - - roomMgr.SetLuaState(luaState); - - std::cout << "Internal managers set" << std::endl; - - //register the "globals" - lua_pushstring(luaState, ROOM_MANAGER_PSEUDOINDEX); - lua_pushlightuserdata(luaState, &roomMgr); - lua_settable(luaState, LUA_REGISTRYINDEX); - - std::cout << "Internal managers registered with 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 - //------------------------- - - //TODO: enable/disable these with a switch -#define DEBUG_OUTPUT_VAR(x) std::cout << "\t" << #x << ": " << x << std::endl; - - std::cout << "Internal sizes:" << std::endl; - - DEBUG_OUTPUT_VAR(sizeof(Region::type_t)); - DEBUG_OUTPUT_VAR(sizeof(Region)); - DEBUG_OUTPUT_VAR(REGION_WIDTH); - DEBUG_OUTPUT_VAR(REGION_HEIGHT); - DEBUG_OUTPUT_VAR(REGION_DEPTH); - DEBUG_OUTPUT_VAR(REGION_SOLID_FOOTPRINT); - DEBUG_OUTPUT_VAR(REGION_FOOTPRINT); - DEBUG_OUTPUT_VAR(PACKET_BUFFER_SIZE); - DEBUG_OUTPUT_VAR(MAX_PACKET_SIZE); - -#undef DEBUG_OUTPUT_VAR - - //------------------------- - //finalize the startup - //------------------------- - - std::cout << "Startup completed successfully" << std::endl; - - //------------------------- - //debugging - //------------------------- - - //... -} - -void ServerApplication::Proc() { - SerialPacket* packetBuffer = static_cast(malloc(MAX_PACKET_SIZE)); - while(running) { - //suck in the waiting packets & process them - while(network.Receive(packetBuffer)) { - HandlePacket(packetBuffer); - } - //update the internals - //BUG: #30 Update the internals i.e. player positions - - //give the computer a break - SDL_Delay(10); - } - free(static_cast(packetBuffer)); -} - -void ServerApplication::Quit() { - std::cout << "Shutting down" << std::endl; - - //close the managers - clientMap.clear(); - accountMgr.UnloadAll(); - characterMgr.UnloadAll(); - //TODO: unload combats - //TODO: unload enemies - roomMgr.UnloadAll(); - - //APIs - lua_close(luaState); - sqlite3_close_v2(database); - network.Close(); - SDLNet_Quit(); - SDL_Quit(); - - std::cout << "Clean exit" << std::endl; -} - -//------------------------- -//handle incoming traffic -//------------------------- - -void ServerApplication::HandlePacket(SerialPacket* const argPacket) { - switch(argPacket->type) { - //basic connections - case SerialPacketType::BROADCAST_REQUEST: - HandleBroadcastRequest(static_cast(argPacket)); - break; - case SerialPacketType::JOIN_REQUEST: - HandleJoinRequest(static_cast(argPacket)); - break; - case SerialPacketType::DISCONNECT: - HandleDisconnect(static_cast(argPacket)); - break; - case SerialPacketType::SHUTDOWN: - HandleShutdown(static_cast(argPacket)); - break; - - //map management - case SerialPacketType::REGION_REQUEST: - HandleRegionRequest(static_cast(argPacket)); - break; - - //combat management - //TODO: combat management - - //character management - case SerialPacketType::CHARACTER_NEW: - HandleCharacterNew(static_cast(argPacket)); - break; - case SerialPacketType::CHARACTER_DELETE: - HandleCharacterDelete(static_cast(argPacket)); - break; - case SerialPacketType::CHARACTER_UPDATE: - case SerialPacketType::CHARACTER_STATS_REQUEST: - HandleCharacterUpdate(static_cast(argPacket)); - break; - - //enemy management - //TODO: enemy management - - //mismanagement - case SerialPacketType::SYNCHRONIZE: - HandleSynchronize(static_cast(argPacket)); - break; - - //handle errors - default: - throw(std::runtime_error(std::string() + "Unknown SerialPacketType encountered in the server: " + to_string_custom(static_cast(argPacket->type)) )); - break; - } -} //------------------------- //basic connections @@ -259,7 +46,7 @@ void ServerApplication::HandleJoinRequest(ClientPacket* const argPacket) { //load the user account //TODO: handle passwords - int accountIndex = accountMgr.LoadAccount(argPacket->username, clientUID); + int accountIndex = accountMgr.LoadAccount(argPacket->username, clientIndex); if (accountIndex < 0) { //TODO: send rejection packet std::cerr << "Error: Account already loaded: " << accountIndex << std::endl; @@ -269,13 +56,13 @@ void ServerApplication::HandleJoinRequest(ClientPacket* const argPacket) { //send the client their info ClientPacket newPacket; newPacket.type = SerialPacketType::JOIN_RESPONSE; - newPacket.clientIndex = clientUID; + newPacket.clientIndex = clientIndex; newPacket.accountIndex = accountIndex; network.SendTo(&newClient.address, static_cast(&newPacket)); //finished this routine - clientMap[clientUID++] = newClient; + clientMap[clientIndex++] = newClient; std::cout << "New connection, " << clientMap.size() << " clients and " << accountMgr.GetContainer()->size() << " accounts total" << std::endl; } diff --git a/todo.txt b/todo.txt index f7a9491..284be85 100644 --- a/todo.txt +++ b/todo.txt @@ -1,43 +1,14 @@ TODO: encapsulate the data structures -TODO: The server's managers should be singletons too -TODO: Get the rooms working TODO: A proper logging system +TODO: Ping-pong and keep alive system TODO: Move the statistics into their own SQL table, instead of duplicating the structure a dozen times +TODO: Get the rooms working, even if only via hotkeys +TODO: Rejection messages +TODO: Fix shoddy movement TODO: make the whole thing more fault tolerant TODO: Authentication TODO: server is slaved to the client TODO: Time delay for requesting region packets TODO: command line parameters overriding config.cfg settings - ---Requirements-- - -The enemies need AI scripts -The scripts need to be able to generate other enemies (frog king). -The characters need a flag to show if they're in a combat instance or not, to signify of they should be unloaded client-side -On each game loop, the server should envoke each combat instance's update function - Each combat instance invokes each enemy's and character's update functions - These update functions increase the ATB guagues - if an ATB guage is full - than the stored command is executed - the players issue their commands during the build up - if there isn't a command ready, then the player is still choosing - for the enemies, the stored commands are driven by scripts, so when the enemies need to attack, their attached scripts are called. - after the commands are called, the ATB is reset to 0. - etc... - ---Enemy API-- - -enemyTables -- The global store of enemy tables. Only accessed by C++ code (unless you want to break something). - -enemy.new(parameters) -- return a new enemy object - -table.logic: the AI logic. If null, do nothing -table.ref: reference to the enemy itself, for use by API functions, set by constructor? - -combat -- the combat API -combat.new(mapIndex, x, y) -- return combat instance's index -combat.pushenemy(c, enemy) -- return the enemy's position -combat.popenemy(c, position) -- -