From b33fb66d2a7bebb618befa4647893e2ac9d2aa21 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 14 Aug 2015 22:14:26 +1000 Subject: [PATCH 01/16] Created a new branch to act as a submodule of common classes --- README.md | 35 -- client/base_scene.cpp | 105 ----- client/base_scene.hpp | 61 --- client/channels.hpp | 26 -- client/client_application.cpp | 284 ------------ client/client_application.hpp | 57 --- client/client_utilities/terminal_error.cpp | 23 - client/client_utilities/terminal_error.hpp | 31 -- client/client_utilities/text_util.cpp | 45 -- client/client_utilities/text_util.hpp | 33 -- client/entities/base_character.cpp | 83 ---- client/entities/base_character.hpp | 52 --- client/entities/base_monster.cpp | 46 -- client/entities/base_monster.hpp | 42 -- client/entities/entity.cpp | 63 --- client/entities/entity.hpp | 53 --- client/entities/local_character.cpp | 35 -- client/entities/local_character.hpp | 39 -- client/entities/makefile | 32 -- client/gameplay_scenes/makefile | 32 -- client/gameplay_scenes/world.hpp | 165 ------- client/gameplay_scenes/world_characters.cpp | 240 ---------- client/gameplay_scenes/world_chat.cpp | 39 -- client/gameplay_scenes/world_connections.cpp | 134 ------ client/gameplay_scenes/world_logic.cpp | 428 ------------------ client/gameplay_scenes/world_map.cpp | 118 ----- client/gameplay_scenes/world_monsters.cpp | 126 ------ client/main.cpp | 59 --- client/makefile | 60 --- client/menu_scenes/disconnected_screen.cpp | 118 ----- client/menu_scenes/disconnected_screen.hpp | 63 --- client/menu_scenes/lobby_menu.cpp | 306 ------------- client/menu_scenes/lobby_menu.hpp | 110 ----- client/menu_scenes/main_menu.cpp | 129 ------ client/menu_scenes/main_menu.hpp | 60 --- client/menu_scenes/makefile | 32 -- client/menu_scenes/options_menu.cpp | 102 ----- client/menu_scenes/options_menu.hpp | 58 --- client/menu_scenes/splash_screen.cpp | 53 --- client/menu_scenes/splash_screen.hpp | 44 -- client/scene_signal.hpp | 37 -- common/graphics/makefile | 32 -- common/makefile | 7 - copyright.txt | 15 - .../client_utilities => debugging}/makefile | 4 - {common/debugging => debugging}/timer.cpp | 0 {common/debugging => debugging}/timer.hpp | 0 .../character_defines.hpp | 0 {common/utilities => gameplay}/makefile | 4 - {common/graphics => graphics}/button.cpp | 0 {common/graphics => graphics}/button.hpp | 0 {common/graphics => graphics}/image.cpp | 0 {common/graphics => graphics}/image.hpp | 0 {common/debugging => graphics}/makefile | 4 - .../graphics => graphics}/sprite_sheet.cpp | 0 .../graphics => graphics}/sprite_sheet.hpp | 0 {common/graphics => graphics}/text_box.cpp | 0 {common/graphics => graphics}/text_box.hpp | 0 {common/graphics => graphics}/text_line.cpp | 0 {common/graphics => graphics}/text_line.hpp | 0 instructions.txt | 35 -- makefile | 38 +- {common/map => map}/makefile | 4 - {common/map => map}/region.cpp | 0 {common/map => map}/region.hpp | 0 {common/map => map}/region_api.cpp | 0 {common/map => map}/region_api.hpp | 0 {common/map => map}/region_pager_api.cpp | 0 {common/map => map}/region_pager_api.hpp | 0 {common/map => map}/region_pager_base.cpp | 0 {common/map => map}/region_pager_base.hpp | 0 {common/map => map}/region_pager_lua.cpp | 0 {common/map => map}/region_pager_lua.hpp | 0 {common/map => map}/tile_sheet.cpp | 0 {common/map => map}/tile_sheet.hpp | 0 {common/network => network}/makefile | 4 - .../packet_types/character_packet.cpp | 0 .../packet_types/character_packet.hpp | 0 .../packet_types/client_packet.cpp | 0 .../packet_types/client_packet.hpp | 0 .../network => network}/packet_types/makefile | 4 +- .../packet_types/monster_packet.cpp | 0 .../packet_types/monster_packet.hpp | 0 .../packet_types/region_packet.cpp | 0 .../packet_types/region_packet.hpp | 0 .../packet_types/serial_packet_base.cpp | 0 .../packet_types/serial_packet_base.hpp | 0 .../packet_types/server_packet.cpp | 0 .../packet_types/server_packet.hpp | 0 .../packet_types/text_packet.cpp | 0 .../packet_types/text_packet.hpp | 0 {common/network => network}/serial_packet.hpp | 0 .../serial_packet_type.hpp | 0 .../network => network}/serial_utility.cpp | 0 .../network => network}/serial_utility.hpp | 0 .../udp_network_utility.cpp | 0 .../udp_network_utility.hpp | 0 rsc/config.cfg | 33 -- rsc/graphics/interface/button.png | Bin 321 -> 0 bytes rsc/graphics/logos/krstudios.png | Bin 171445 -> 0 bytes rsc/graphics/sprites/aniflower.bmp | Bin 12342 -> 0 bytes rsc/graphics/sprites/coa2.bmp | Bin 73782 -> 0 bytes rsc/graphics/sprites/elliot2.bmp | Bin 73782 -> 0 bytes rsc/graphics/sprites/skume1.bmp | Bin 1041 -> 0 bytes rsc/graphics/sprites/skume2.bmp | Bin 784 -> 0 bytes rsc/graphics/tilesets/MishMash.bmp | Bin 1625142 -> 0 bytes rsc/graphics/tilesets/blank.bmp | Bin 786486 -> 0 bytes rsc/graphics/tilesets/dirt.bmp | Bin 110646 -> 0 bytes rsc/graphics/tilesets/grass.bmp | Bin 110646 -> 0 bytes rsc/graphics/tilesets/longgrass.bmp | Bin 110646 -> 0 bytes rsc/graphics/tilesets/overworld.bmp | Bin 786486 -> 0 bytes rsc/graphics/tilesets/sand.bmp | Bin 110646 -> 0 bytes rsc/graphics/tilesets/terrain.bmp | Bin 553014 -> 0 bytes rsc/graphics/tilesets/water.bmp | Bin 110646 -> 0 bytes rsc/scripts/door_utility.lua | 89 ---- rsc/scripts/map_maker.lua | 141 ------ rsc/scripts/map_saver.lua | 39 -- rsc/scripts/setup_server.lua | 61 --- rsc/scripts/setup_server.sql | 158 ------- server/accounts/account_data.cpp | 54 --- server/accounts/account_data.hpp | 56 --- server/accounts/account_manager.cpp | 279 ------------ server/accounts/account_manager.hpp | 62 --- server/accounts/makefile | 32 -- server/characters/character_api.cpp | 129 ------ server/characters/character_api.hpp | 27 -- server/characters/character_data.cpp | 38 -- server/characters/character_data.hpp | 48 -- server/characters/character_manager.cpp | 348 -------------- server/characters/character_manager.hpp | 67 --- server/characters/character_manager_api.cpp | 114 ----- server/characters/character_manager_api.hpp | 27 -- server/characters/makefile | 32 -- server/clients/client_data.cpp | 52 --- server/clients/client_data.hpp | 50 -- server/clients/client_manager.cpp | 108 ----- server/clients/client_manager.hpp | 62 --- server/clients/makefile | 32 -- server/entities/entity.cpp | 66 --- server/entities/entity.hpp | 56 --- server/entities/entity_api.cpp | 106 ----- server/entities/entity_api.hpp | 27 -- server/entities/makefile | 32 -- server/linit.cpp | 99 ---- server/main.cpp | 70 --- server/makefile | 64 --- server/monsters/makefile | 32 -- server/monsters/monster_api.cpp | 88 ---- server/monsters/monster_api.hpp | 27 -- server/monsters/monster_data.cpp | 55 --- server/monsters/monster_data.hpp | 57 --- server/monsters/monster_manager.cpp | 94 ---- server/monsters/monster_manager.hpp | 62 --- server/monsters/monster_manager_api.cpp | 80 ---- server/monsters/monster_manager_api.hpp | 27 -- server/rooms/makefile | 32 -- server/rooms/room_api.cpp | 159 ------- server/rooms/room_api.hpp | 27 -- server/rooms/room_data.cpp | 159 ------- server/rooms/room_data.hpp | 79 ---- server/rooms/room_manager.cpp | 209 --------- server/rooms/room_manager.hpp | 81 ---- server/rooms/room_manager_api.cpp | 125 ----- server/rooms/room_manager_api.hpp | 26 -- server/server_application.hpp | 129 ------ server/server_character_methods.cpp | 243 ---------- server/server_chat.cpp | 34 -- server/server_connections.cpp | 173 ------- server/server_data_queries.cpp | 97 ---- server/server_logic.cpp | 350 -------------- server/server_methods.cpp | 90 ---- server/server_utilities/makefile | 32 -- server/server_utilities/network_api.cpp | 80 ---- server/server_utilities/network_api.hpp | 27 -- server/server_utilities/server_utilities.cpp | 184 -------- server/server_utilities/server_utilities.hpp | 38 -- server/server_utilities/sql_tools.cpp | 50 -- server/server_utilities/sql_tools.hpp | 28 -- server/triggers/makefile | 32 -- server/triggers/trigger_api.cpp | 126 ------ server/triggers/trigger_api.hpp | 27 -- server/triggers/trigger_data.cpp | 58 --- server/triggers/trigger_data.hpp | 58 --- server/triggers/trigger_manager.cpp | 96 ---- server/triggers/trigger_manager.hpp | 61 --- server/triggers/trigger_manager_api.cpp | 148 ------ server/triggers/trigger_manager_api.hpp | 27 -- todo.txt | 26 -- .../utilities => utilities}/bounding_box.hpp | 0 .../config_utility.cpp | 0 .../config_utility.hpp | 0 .../utilities => utilities}/frame_rate.hpp | 0 .../utilities => utilities}/ip_operators.cpp | 0 .../utilities => utilities}/ip_operators.hpp | 0 {common/gameplay => utilities}/makefile | 4 - {common/utilities => utilities}/singleton.hpp | 0 {common/utilities => utilities}/vector2.hpp | 0 197 files changed, 15 insertions(+), 10089 deletions(-) delete mode 100644 client/base_scene.cpp delete mode 100644 client/base_scene.hpp delete mode 100644 client/channels.hpp delete mode 100644 client/client_application.cpp delete mode 100644 client/client_application.hpp delete mode 100644 client/client_utilities/terminal_error.cpp delete mode 100644 client/client_utilities/terminal_error.hpp delete mode 100644 client/client_utilities/text_util.cpp delete mode 100644 client/client_utilities/text_util.hpp delete mode 100644 client/entities/base_character.cpp delete mode 100644 client/entities/base_character.hpp delete mode 100644 client/entities/base_monster.cpp delete mode 100644 client/entities/base_monster.hpp delete mode 100644 client/entities/entity.cpp delete mode 100644 client/entities/entity.hpp delete mode 100644 client/entities/local_character.cpp delete mode 100644 client/entities/local_character.hpp delete mode 100644 client/entities/makefile delete mode 100644 client/gameplay_scenes/makefile delete mode 100644 client/gameplay_scenes/world.hpp delete mode 100644 client/gameplay_scenes/world_characters.cpp delete mode 100644 client/gameplay_scenes/world_chat.cpp delete mode 100644 client/gameplay_scenes/world_connections.cpp delete mode 100644 client/gameplay_scenes/world_logic.cpp delete mode 100644 client/gameplay_scenes/world_map.cpp delete mode 100644 client/gameplay_scenes/world_monsters.cpp delete mode 100644 client/main.cpp delete mode 100644 client/makefile delete mode 100644 client/menu_scenes/disconnected_screen.cpp delete mode 100644 client/menu_scenes/disconnected_screen.hpp delete mode 100644 client/menu_scenes/lobby_menu.cpp delete mode 100644 client/menu_scenes/lobby_menu.hpp delete mode 100644 client/menu_scenes/main_menu.cpp delete mode 100644 client/menu_scenes/main_menu.hpp delete mode 100644 client/menu_scenes/makefile delete mode 100644 client/menu_scenes/options_menu.cpp delete mode 100644 client/menu_scenes/options_menu.hpp delete mode 100644 client/menu_scenes/splash_screen.cpp delete mode 100644 client/menu_scenes/splash_screen.hpp delete mode 100644 client/scene_signal.hpp delete mode 100644 common/graphics/makefile delete mode 100644 common/makefile delete mode 100644 copyright.txt rename {client/client_utilities => debugging}/makefile (87%) rename {common/debugging => debugging}/timer.cpp (100%) rename {common/debugging => debugging}/timer.hpp (100%) rename {common/gameplay => gameplay}/character_defines.hpp (100%) rename {common/utilities => gameplay}/makefile (86%) rename {common/graphics => graphics}/button.cpp (100%) rename {common/graphics => graphics}/button.hpp (100%) rename {common/graphics => graphics}/image.cpp (100%) rename {common/graphics => graphics}/image.hpp (100%) rename {common/debugging => graphics}/makefile (86%) rename {common/graphics => graphics}/sprite_sheet.cpp (100%) rename {common/graphics => graphics}/sprite_sheet.hpp (100%) rename {common/graphics => graphics}/text_box.cpp (100%) rename {common/graphics => graphics}/text_box.hpp (100%) rename {common/graphics => graphics}/text_line.cpp (100%) rename {common/graphics => graphics}/text_line.hpp (100%) delete mode 100644 instructions.txt rename {common/map => map}/makefile (86%) rename {common/map => map}/region.cpp (100%) rename {common/map => map}/region.hpp (100%) rename {common/map => map}/region_api.cpp (100%) rename {common/map => map}/region_api.hpp (100%) rename {common/map => map}/region_pager_api.cpp (100%) rename {common/map => map}/region_pager_api.hpp (100%) rename {common/map => map}/region_pager_base.cpp (100%) rename {common/map => map}/region_pager_base.hpp (100%) rename {common/map => map}/region_pager_lua.cpp (100%) rename {common/map => map}/region_pager_lua.hpp (100%) rename {common/map => map}/tile_sheet.cpp (100%) rename {common/map => map}/tile_sheet.hpp (100%) rename {common/network => network}/makefile (87%) rename {common/network => network}/packet_types/character_packet.cpp (100%) rename {common/network => network}/packet_types/character_packet.hpp (100%) rename {common/network => network}/packet_types/client_packet.cpp (100%) rename {common/network => network}/packet_types/client_packet.hpp (100%) rename {common/network => network}/packet_types/makefile (88%) rename {common/network => network}/packet_types/monster_packet.cpp (100%) rename {common/network => network}/packet_types/monster_packet.hpp (100%) rename {common/network => network}/packet_types/region_packet.cpp (100%) rename {common/network => network}/packet_types/region_packet.hpp (100%) rename {common/network => network}/packet_types/serial_packet_base.cpp (100%) rename {common/network => network}/packet_types/serial_packet_base.hpp (100%) rename {common/network => network}/packet_types/server_packet.cpp (100%) rename {common/network => network}/packet_types/server_packet.hpp (100%) rename {common/network => network}/packet_types/text_packet.cpp (100%) rename {common/network => network}/packet_types/text_packet.hpp (100%) rename {common/network => network}/serial_packet.hpp (100%) rename {common/network => network}/serial_packet_type.hpp (100%) rename {common/network => network}/serial_utility.cpp (100%) rename {common/network => network}/serial_utility.hpp (100%) rename {common/network => network}/udp_network_utility.cpp (100%) rename {common/network => network}/udp_network_utility.hpp (100%) delete mode 100644 rsc/config.cfg delete mode 100644 rsc/graphics/interface/button.png delete mode 100644 rsc/graphics/logos/krstudios.png delete mode 100644 rsc/graphics/sprites/aniflower.bmp delete mode 100644 rsc/graphics/sprites/coa2.bmp delete mode 100644 rsc/graphics/sprites/elliot2.bmp delete mode 100644 rsc/graphics/sprites/skume1.bmp delete mode 100644 rsc/graphics/sprites/skume2.bmp delete mode 100644 rsc/graphics/tilesets/MishMash.bmp delete mode 100644 rsc/graphics/tilesets/blank.bmp delete mode 100644 rsc/graphics/tilesets/dirt.bmp delete mode 100644 rsc/graphics/tilesets/grass.bmp delete mode 100644 rsc/graphics/tilesets/longgrass.bmp delete mode 100644 rsc/graphics/tilesets/overworld.bmp delete mode 100644 rsc/graphics/tilesets/sand.bmp delete mode 100644 rsc/graphics/tilesets/terrain.bmp delete mode 100644 rsc/graphics/tilesets/water.bmp delete mode 100644 rsc/scripts/door_utility.lua delete mode 100644 rsc/scripts/map_maker.lua delete mode 100644 rsc/scripts/map_saver.lua delete mode 100644 rsc/scripts/setup_server.lua delete mode 100644 rsc/scripts/setup_server.sql delete mode 100644 server/accounts/account_data.cpp delete mode 100644 server/accounts/account_data.hpp delete mode 100644 server/accounts/account_manager.cpp delete mode 100644 server/accounts/account_manager.hpp delete mode 100644 server/accounts/makefile delete mode 100644 server/characters/character_api.cpp delete mode 100644 server/characters/character_api.hpp delete mode 100644 server/characters/character_data.cpp delete mode 100644 server/characters/character_data.hpp delete mode 100644 server/characters/character_manager.cpp delete mode 100644 server/characters/character_manager.hpp delete mode 100644 server/characters/character_manager_api.cpp delete mode 100644 server/characters/character_manager_api.hpp delete mode 100644 server/characters/makefile delete mode 100644 server/clients/client_data.cpp delete mode 100644 server/clients/client_data.hpp delete mode 100644 server/clients/client_manager.cpp delete mode 100644 server/clients/client_manager.hpp delete mode 100644 server/clients/makefile delete mode 100644 server/entities/entity.cpp delete mode 100644 server/entities/entity.hpp delete mode 100644 server/entities/entity_api.cpp delete mode 100644 server/entities/entity_api.hpp delete mode 100644 server/entities/makefile delete mode 100644 server/linit.cpp delete mode 100644 server/main.cpp delete mode 100644 server/makefile delete mode 100644 server/monsters/makefile delete mode 100644 server/monsters/monster_api.cpp delete mode 100644 server/monsters/monster_api.hpp delete mode 100644 server/monsters/monster_data.cpp delete mode 100644 server/monsters/monster_data.hpp delete mode 100644 server/monsters/monster_manager.cpp delete mode 100644 server/monsters/monster_manager.hpp delete mode 100644 server/monsters/monster_manager_api.cpp delete mode 100644 server/monsters/monster_manager_api.hpp delete mode 100644 server/rooms/makefile delete mode 100644 server/rooms/room_api.cpp delete mode 100644 server/rooms/room_api.hpp delete mode 100644 server/rooms/room_data.cpp delete mode 100644 server/rooms/room_data.hpp delete mode 100644 server/rooms/room_manager.cpp delete mode 100644 server/rooms/room_manager.hpp delete mode 100644 server/rooms/room_manager_api.cpp delete mode 100644 server/rooms/room_manager_api.hpp delete mode 100644 server/server_application.hpp delete mode 100644 server/server_character_methods.cpp delete mode 100644 server/server_chat.cpp delete mode 100644 server/server_connections.cpp delete mode 100644 server/server_data_queries.cpp delete mode 100644 server/server_logic.cpp delete mode 100644 server/server_methods.cpp delete mode 100644 server/server_utilities/makefile delete mode 100644 server/server_utilities/network_api.cpp delete mode 100644 server/server_utilities/network_api.hpp delete mode 100644 server/server_utilities/server_utilities.cpp delete mode 100644 server/server_utilities/server_utilities.hpp delete mode 100644 server/server_utilities/sql_tools.cpp delete mode 100644 server/server_utilities/sql_tools.hpp delete mode 100644 server/triggers/makefile delete mode 100644 server/triggers/trigger_api.cpp delete mode 100644 server/triggers/trigger_api.hpp delete mode 100644 server/triggers/trigger_data.cpp delete mode 100644 server/triggers/trigger_data.hpp delete mode 100644 server/triggers/trigger_manager.cpp delete mode 100644 server/triggers/trigger_manager.hpp delete mode 100644 server/triggers/trigger_manager_api.cpp delete mode 100644 server/triggers/trigger_manager_api.hpp delete mode 100644 todo.txt rename {common/utilities => utilities}/bounding_box.hpp (100%) rename {common/utilities => utilities}/config_utility.cpp (100%) rename {common/utilities => utilities}/config_utility.hpp (100%) rename {common/utilities => utilities}/frame_rate.hpp (100%) rename {common/utilities => utilities}/ip_operators.cpp (100%) rename {common/utilities => utilities}/ip_operators.hpp (100%) rename {common/gameplay => utilities}/makefile (86%) rename {common/utilities => utilities}/singleton.hpp (100%) rename {common/utilities => utilities}/vector2.hpp (100%) diff --git a/README.md b/README.md index de55c5e..9bc9e84 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,5 @@ -## Outline - -Tortuga is a 2D MMORPG featuring permadeath, with an emphasis on multiplayer cooperation, exploration and customization. The game runs on customizable public and private servers. - -This game is inspired by classic 2D RPGs (Final Fantasy, The Legend of Zelda), as well as more modern sandboxes and MMOs (Minecraft, EVE Online). This project is currently independently created and funded, with the goal of creating a game that will engage the players and inspire a large community. - -## Releases - -* The most recent stable build for Windows can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga-win.rar). -* The most recent stable build for Linux can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga-linux.tar). - -## Documentation - -* [Tortuga Wiki](https://github.com/Ratstail91/Tortuga/wiki) - Full documentation (incomplete) -* [Tortuga Bug Tracker](https://github.com/Ratstail91/Tortuga/issues) - A list of all known bugs and issues - -## External Dependencies - -* [SDL 2.0](http://www.libsdl.org/) - Simple DirectMedia Layer API -* [SDL_image 2.0](https://www.libsdl.org/projects/SDL_image/) - An SDL Extension for loading multiple image file formats -* [SDL_net 2.0](http://www.libsdl.org/projects/SDL_net/) - SDL's networking extension -* [SDL_ttf 2.0](https://www.libsdl.org/projects/SDL_ttf/) - An SDL extention for rendering fonts -* [lua 5.2](http://www.lua.org/) - The lua programming language -* [SQLite3](http://www.sqlite.org/) - A lightweight SQL database engine - -## Tools - -* [WinRAR](http://www.rarlab.com/) - A free archive tool; needed for Windows distribution -* [tar](http://www.gnu.org/software/tar/manual/) - The GNU archive tool; needed for Linux distribution -* [Dropbox](https://www.dropbox.com/) - For hosting and distribution - ## Copyright -(Future versions (to be determined) may be released under a modified version of the [Uplink Developer's License](http://www.introversion.co.uk/uplink/developer/license.html).) - -The current version of Tortuga is released under the [zlib license](http://en.wikipedia.org/wiki/Zlib_License). - Copyright (c) 2013-2015 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. diff --git a/client/base_scene.cpp b/client/base_scene.cpp deleted file mode 100644 index fc29fab..0000000 --- a/client/base_scene.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "base_scene.hpp" - -SDL_Renderer* BaseScene::rendererHandle = nullptr; - -BaseScene::BaseScene() { - //EMPTY -} - -BaseScene::~BaseScene() { - //EMPTY -} - -void BaseScene::RenderFrame(SDL_Renderer* renderer) { - //EMPTY -} - -void BaseScene::SetRenderer(SDL_Renderer* r) { - rendererHandle = r; -} - -SDL_Renderer* BaseScene::GetRenderer() { - return rendererHandle; -} - -void BaseScene::SetSceneSignal(SceneSignal signal) { - sceneSignal = signal; -} - -SceneSignal BaseScene::GetSceneSignal() { - return sceneSignal; -} - -//------------------------- -//frame phases -//------------------------- - -void BaseScene::FrameStart() { - //EMPTY -} - -void BaseScene::Update() { - //EMPTY -} - -void BaseScene::FrameEnd() { - //EMPTY -} - -//------------------------- -//input events -//------------------------- - -void BaseScene::QuitEvent() { - sceneSignal = SceneSignal::QUIT; -} - -void BaseScene::MouseMotion(SDL_MouseMotionEvent const& event) { - //EMPTY -} - -void BaseScene::MouseButtonDown(SDL_MouseButtonEvent const& event) { - //EMPTY -} - -void BaseScene::MouseButtonUp(SDL_MouseButtonEvent const& event) { - //EMPTY -} - -void BaseScene::MouseWheel(SDL_MouseWheelEvent const& event) { - //EMPTY -} - -void BaseScene::KeyDown(SDL_KeyboardEvent const& event) { - //preference as a default - switch(event.keysym.sym) { - case SDLK_ESCAPE: - QuitEvent(); - break; - } -} - -void BaseScene::KeyUp(SDL_KeyboardEvent const& event) { - //EMPTY -} diff --git a/client/base_scene.hpp b/client/base_scene.hpp deleted file mode 100644 index 0a7b225..0000000 --- a/client/base_scene.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "scene_signal.hpp" - -#include "SDL2/SDL.h" - -class BaseScene { -public: - BaseScene(); - virtual ~BaseScene(); - - virtual void RenderFrame(SDL_Renderer*); - static void SetRenderer(SDL_Renderer*); - SceneSignal GetSceneSignal(); - - //frame phases - virtual void FrameStart(); - virtual void Update(); - virtual void FrameEnd(); - - //input events - virtual void QuitEvent(); - virtual void MouseMotion(SDL_MouseMotionEvent const& event); - virtual void MouseButtonDown(SDL_MouseButtonEvent const& event); - virtual void MouseButtonUp(SDL_MouseButtonEvent const& event); - virtual void MouseWheel(SDL_MouseWheelEvent const& event); - virtual void KeyDown(SDL_KeyboardEvent const& event); - virtual void KeyUp(SDL_KeyboardEvent const& event); - - //TODO: joystick and controller events - -protected: - //control - static SDL_Renderer* GetRenderer(); - void SetSceneSignal(SceneSignal); - -private: - static SDL_Renderer* rendererHandle; - SceneSignal sceneSignal = SceneSignal::CONTINUE; -}; \ No newline at end of file diff --git a/client/channels.hpp b/client/channels.hpp deleted file mode 100644 index 362463a..0000000 --- a/client/channels.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -enum Channels { - SERVER = 0 -}; diff --git a/client/client_application.cpp b/client/client_application.cpp deleted file mode 100644 index a713248..0000000 --- a/client/client_application.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "client_application.hpp" - -#include "serial_packet.hpp" -#include "config_utility.hpp" - -#include -#include -#include -#include - -//------------------------- -//Public access members -//------------------------- - -void ClientApplication::Init(int argc, char* argv[]) { - std::cout << "Beginning " << argv[0] << std::endl; - - //load the prerequisites - ConfigUtility& config = ConfigUtility::GetSingleton(); - config.Load("rsc/config.cfg", false, argc, argv); - - //------------------------- - //create and check the window - //------------------------- - - int w = config.Int("client.screen.w"); - int h = config.Int("client.screen.h"); - int f = config.Bool("client.screen.f") ? SDL_WINDOW_FULLSCREEN : 0; - - window = SDL_CreateWindow(argv[0], SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w ? w : 800, h ? h : 600, f); - - if (!window) { - std::ostringstream msg; - msg << "Failed to create the window: " << SDL_GetError(); - throw(std::runtime_error(msg.str())); - } - - std::cout << "Initialized the window" << std::endl; - - //------------------------- - //create and check the renderer - //------------------------- - - renderer = SDL_CreateRenderer(window, -1, 0); - - if (!renderer) { - std::ostringstream msg; - msg << "Failed to create the renderer: " << SDL_GetError(); - throw(std::runtime_error(msg.str())); - } - - //screen scaling - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); - SDL_RenderSetLogicalSize(renderer, w, h); - - //set the hook for the renderer - BaseScene::SetRenderer(renderer); - - std::cout << "Initialized the renderer" << std::endl; - - //------------------------- - //Initialize the APIs - //------------------------- - - //initialize SDL_net - if (SDLNet_Init()) { - std::ostringstream msg; - msg << "Failed to initialize SDL_net: " << SDL_GetError(); - throw(std::runtime_error(msg.str())); - } - UDPNetworkUtility::GetSingleton().Open(0); - - std::cout << "Initialized SDL_net" << std::endl; - - //------------------------- - //debug output - //------------------------- - -#define DEBUG_OUTPUT_VAR(x) std::cout << "\t" << #x << ": " << x << std::endl; - - std::cout << "Internal sizes:" << std::endl; - - DEBUG_OUTPUT_VAR(NETWORK_VERSION); - 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_TILE_FOOTPRINT); - DEBUG_OUTPUT_VAR(REGION_SOLID_FOOTPRINT); - DEBUG_OUTPUT_VAR(PACKET_STRING_SIZE); - DEBUG_OUTPUT_VAR(PACKET_BUFFER_SIZE); - DEBUG_OUTPUT_VAR(MAX_PACKET_SIZE); - DEBUG_OUTPUT_VAR(static_cast(SerialPacketType::LAST)); - -#undef DEBUG_OUTPUT_VAR - - //------------------------- - //finalize the startup - //------------------------- - - std::cout << "Startup completed successfully" << std::endl; - - //------------------------- - //debugging - //------------------------- - - //... -} - -void ClientApplication::Proc() { - //load the first scene - ProcessSceneSignal(SceneSignal::FIRST); - - //fixed frame rate - typedef std::chrono::steady_clock Clock; - - Clock::time_point simTime = Clock::now(); - Clock::time_point realTime; - constexpr std::chrono::duration frameDelay(16); //~60FPS - - //the game loop continues until the scenes signal QUIT - while(activeScene->GetSceneSignal() != SceneSignal::QUIT) { - //switch scenes if necessary - if(activeScene->GetSceneSignal() != SceneSignal::CONTINUE) { - ProcessSceneSignal(activeScene->GetSceneSignal()); - continue; - } - - //update the current time - realTime = Clock::now(); - - //simulate the game or give the machine a break - if (simTime < realTime) { - while(simTime < realTime) { - //call the user defined functions - activeScene->FrameStart(); - ProcessEvents(); - activeScene->Update(); - activeScene->FrameEnd(); - - //step to the next frame - simTime += frameDelay; - } - } - else { - SDL_Delay(1); - } - - SDL_RenderClear(renderer); - activeScene->RenderFrame(renderer); - SDL_RenderPresent(renderer); - } - - //cleanup - ClearScene(); -} - -void ClientApplication::Quit() { - //clean up after the program - std::cout << "Shutting down" << std::endl; - UDPNetworkUtility::GetSingleton().Close(); - SDLNet_Quit(); - BaseScene::SetRenderer(nullptr); - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); - std::cout << "Clean exit" << std::endl; -} - -//------------------------- -//Scene management -//------------------------- - -void ClientApplication::ProcessEvents() { - SDL_Event event; - while(SDL_PollEvent(&event)) { - switch(event.type) { - case SDL_QUIT: - activeScene->QuitEvent(); - break; - - case SDL_MOUSEMOTION: - activeScene->MouseMotion(event.motion); - break; - - case SDL_MOUSEBUTTONDOWN: - activeScene->MouseButtonDown(event.button); - break; - - case SDL_MOUSEBUTTONUP: - activeScene->MouseButtonUp(event.button); - break; - - case SDL_MOUSEWHEEL: - activeScene->MouseWheel(event.wheel); - break; - - case SDL_KEYDOWN: - activeScene->KeyDown(event.key); - break; - - case SDL_KEYUP: - activeScene->KeyUp(event.key); - break; - - //TODO: joystick and controller events - - //window events are handled internally - case SDL_WINDOWEVENT: - switch(event.window.event) { - case SDL_WINDOWEVENT_RESIZED: - SDL_RenderSetLogicalSize(renderer, event.window.data1, event.window.data2); - break; - } - break; - } - } -} - -//Add the custom scene headers here -#include "splash_screen.hpp" -#include "main_menu.hpp" -#include "options_menu.hpp" -#include "lobby_menu.hpp" -#include "world.hpp" -#include "disconnected_screen.hpp" - -void ClientApplication::ProcessSceneSignal(SceneSignal signal) { - //BUG: #16 Resources are being reloaded between scenes - ClearScene(); - switch(signal) { - //add scene creation calls here - case SceneSignal::FIRST: - case SceneSignal::SPLASHSCREEN: - activeScene = new SplashScreen(); - break; - case SceneSignal::MAINMENU: - activeScene = new MainMenu(); - break; - case SceneSignal::OPTIONSMENU: - activeScene = new OptionsMenu(); - break; - case SceneSignal::LOBBYMENU: - activeScene = new LobbyMenu(&clientIndex, &accountIndex); - break; - case SceneSignal::WORLD: - activeScene = new World(&clientIndex, &accountIndex); - break; - case SceneSignal::DISCONNECTEDSCREEN: - activeScene = new DisconnectedScreen(); - break; - default: { - std::ostringstream msg; - msg << "Failed to recognize the scene signal: " << signal; - throw(std::logic_error(msg.str())); - } - } -} - -void ClientApplication::ClearScene() { - delete activeScene; - activeScene = nullptr; -} diff --git a/client/client_application.hpp b/client/client_application.hpp deleted file mode 100644 index 43c421d..0000000 --- a/client/client_application.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "base_scene.hpp" -#include "scene_signal.hpp" -#include "singleton.hpp" -#include "udp_network_utility.hpp" - -#include "SDL2/SDL.h" - -class ClientApplication: public Singleton { -public: - void Init(int argc, char* argv[]); - void Proc(); - void Quit(); - -private: - friend Singleton; - - ClientApplication() = default; - ~ClientApplication() = default; - - //scene management - void ProcessEvents(); - void ProcessSceneSignal(SceneSignal); - void ClearScene(); - - BaseScene* activeScene = nullptr; - - //TODO: build a "window" class? - SDL_Window* window = nullptr; - SDL_Renderer* renderer = nullptr; - - //shared parameters - int clientIndex = -1; - int accountIndex = -1; -}; \ No newline at end of file diff --git a/client/client_utilities/terminal_error.cpp b/client/client_utilities/terminal_error.cpp deleted file mode 100644 index b113807..0000000 --- a/client/client_utilities/terminal_error.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "terminal_error.hpp" - diff --git a/client/client_utilities/terminal_error.hpp b/client/client_utilities/terminal_error.hpp deleted file mode 100644 index 0735247..0000000 --- a/client/client_utilities/terminal_error.hpp +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include -#include - -class terminal_error: public std::runtime_error { -public: - explicit terminal_error(const std::string& str): runtime_error(str) {} - explicit terminal_error(const char* cstr): runtime_error(cstr) {} -}; diff --git a/client/client_utilities/text_util.cpp b/client/client_utilities/text_util.cpp deleted file mode 100644 index 6094d20..0000000 --- a/client/client_utilities/text_util.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "text_util.hpp" - -#include - -SDL_Texture* renderPlainText(SDL_Renderer* renderer, TTF_Font* font, std::string str, SDL_Color color) { - //make the surface (from SDL_ttf) - SDL_Surface* surface = TTF_RenderText_Solid(font, str.c_str(), color); - if (!surface) { - throw(std::runtime_error("Failed to create a TTF surface")); - } - - //convert to texture - SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface); - if (!texture) { - SDL_FreeSurface(surface); - throw(std::runtime_error("Failed to create a TTF texture")); - } - - //cleanup - SDL_FreeSurface(surface); - - //NOTE: free the texture yourself - return texture; -} \ No newline at end of file diff --git a/client/client_utilities/text_util.hpp b/client/client_utilities/text_util.hpp deleted file mode 100644 index db62286..0000000 --- a/client/client_utilities/text_util.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "SDL2/SDL.h" -#include "SDL2/SDL_ttf.h" - -#include - -constexpr SDL_Color COLOR_WHITE = {255, 255, 255, 255}; - -//TODO: some kind of persistent display widget -//TODO: I need a full suite of widgets -SDL_Texture* renderPlainText(SDL_Renderer*, TTF_Font*, std::string, SDL_Color color); \ No newline at end of file diff --git a/client/entities/base_character.cpp b/client/entities/base_character.cpp deleted file mode 100644 index becb773..0000000 --- a/client/entities/base_character.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "base_character.hpp" - -#include "config_utility.hpp" - -//------------------------- -//graphics -//------------------------- - -void BaseCharacter::CorrectSprite() { - //NOTE: These must correspond to the sprite sheet in use - if (motion.y > 0) { - sprite.SetIndexY(0); - } - else if (motion.y < 0) { - sprite.SetIndexY(1); - } - else if (motion.x > 0) { - sprite.SetIndexY(3); - } - else if (motion.x < 0) { - sprite.SetIndexY(2); - } - - //animation - if (motion != 0) { - sprite.SetDelay(0.1); - } - else { - sprite.SetDelay(0); - sprite.SetIndexX(0); - } -} - -//------------------------- -//metadata -//------------------------- - -int BaseCharacter::SetOwner(int i) { - return owner = i; -} - -int BaseCharacter::GetOwner() { - return owner; -} - -std::string BaseCharacter::SetHandle(std::string s) { - return handle = s; -} - -std::string BaseCharacter::GetHandle() const { - return handle; -} - -std::string BaseCharacter::SetAvatar(SDL_Renderer* const renderer, std::string s) { - avatar = s; - sprite.Load(renderer, ConfigUtility::GetSingleton()["dir.sprites"] + avatar, CHARACTER_CELLS_X, CHARACTER_CELLS_Y); - return avatar; -} - -std::string BaseCharacter::GetAvatar() const { - return avatar; -} \ No newline at end of file diff --git a/client/entities/base_character.hpp b/client/entities/base_character.hpp deleted file mode 100644 index 4dca687..0000000 --- a/client/entities/base_character.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -//components -#include "character_defines.hpp" -#include "entity.hpp" - -//std namespace -#include - -class BaseCharacter: public Entity { -public: - BaseCharacter() = default; - virtual ~BaseCharacter() = default; - - //graphics - void CorrectSprite(); - - //metadata - int SetOwner(int i); - int GetOwner(); - std::string SetHandle(std::string s); - std::string GetHandle() const; - std::string SetAvatar(SDL_Renderer* const, std::string s); - std::string GetAvatar() const; - -protected: - //metadata - int owner; - std::string handle; - std::string avatar; -}; diff --git a/client/entities/base_monster.cpp b/client/entities/base_monster.cpp deleted file mode 100644 index cda27f8..0000000 --- a/client/entities/base_monster.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "base_monster.hpp" - -#include "config_utility.hpp" - -void BaseMonster::CorrectSprite() { - //TODO: (9) BaseMonster::CorrectSprite() -} - -std::string BaseMonster::SetHandle(std::string s) { - return handle = s; -} - -std::string BaseMonster::GetHandle() const { - return handle; -} - -std::string BaseMonster::SetAvatar(SDL_Renderer* const renderer, std::string s) { - avatar = s; - sprite.Load(renderer, ConfigUtility::GetSingleton()["dir.sprites"] + avatar, 4, 1); - return avatar; -} - -std::string BaseMonster::GetAvatar() const { - return avatar; -} \ No newline at end of file diff --git a/client/entities/base_monster.hpp b/client/entities/base_monster.hpp deleted file mode 100644 index d99ee55..0000000 --- a/client/entities/base_monster.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "entity.hpp" - -class BaseMonster: public Entity { -public: - BaseMonster() = default; - virtual ~BaseMonster() = default; - - void CorrectSprite(); - - std::string SetHandle(std::string s); - std::string GetHandle() const; - std::string SetAvatar(SDL_Renderer* const, std::string s); - std::string GetAvatar() const; - -protected: - //metadata - std::string handle; - std::string avatar; -}; diff --git a/client/entities/entity.cpp b/client/entities/entity.cpp deleted file mode 100644 index e44bc4f..0000000 --- a/client/entities/entity.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "entity.hpp" - -void Entity::Update() { - origin += motion; - sprite.Update(0.016); -} - -void Entity::DrawTo(SDL_Renderer* const renderer, int camX, int camY) { - sprite.DrawTo(renderer, origin.x - camX, origin.y - camY); -} - -SpriteSheet* Entity::GetSprite() { - return &sprite; -} - -//------------------------- -//accessors & mutators -//------------------------- - -Vector2 Entity::SetOrigin(Vector2 v) { - return origin = v; -} - -Vector2 Entity::SetMotion(Vector2 v) { - return motion = v; -} - -BoundingBox Entity::SetBounds(BoundingBox b) { - return bounds = b; -} - -Vector2 Entity::GetOrigin() { - return origin; -} - -Vector2 Entity::GetMotion() { - return motion; -} - -BoundingBox Entity::GetBounds() { - return bounds; -} \ No newline at end of file diff --git a/client/entities/entity.hpp b/client/entities/entity.hpp deleted file mode 100644 index d0f712a..0000000 --- a/client/entities/entity.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "bounding_box.hpp" -#include "sprite_sheet.hpp" -#include "vector2.hpp" - -//The base class for all objects in the world -class Entity { -public: - virtual void Update(); - virtual void DrawTo(SDL_Renderer* const, int camX, int camY); - - SpriteSheet* GetSprite(); - - //accessors & mutators - Vector2 SetOrigin(Vector2 v); - Vector2 SetMotion(Vector2 v); - BoundingBox SetBounds(BoundingBox b); - - Vector2 GetOrigin(); - Vector2 GetMotion(); - BoundingBox GetBounds(); - -protected: - Entity() = default; - virtual ~Entity() = default; - - SpriteSheet sprite; - Vector2 origin; - Vector2 motion; - BoundingBox bounds; -}; diff --git a/client/entities/local_character.cpp b/client/entities/local_character.cpp deleted file mode 100644 index 16c1eff..0000000 --- a/client/entities/local_character.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "local_character.hpp" - -#include - -bool LocalCharacter::ProcessCollisionGrid(std::list boxList) { - for(auto& box : boxList) { - if (box.CheckOverlap(origin + bounds)) { - origin -= motion; - motion = {0, 0}; - return true; - } - } - return false; -} \ No newline at end of file diff --git a/client/entities/local_character.hpp b/client/entities/local_character.hpp deleted file mode 100644 index af7f5fa..0000000 --- a/client/entities/local_character.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "base_character.hpp" -#include "bounding_box.hpp" -#include "vector2.hpp" - -#include - -class LocalCharacter: public BaseCharacter { -public: - LocalCharacter() = default; - virtual ~LocalCharacter() = default; - - bool ProcessCollisionGrid(std::list); - -private: - //NOTE: NO MEMBERS -}; diff --git a/client/entities/makefile b/client/entities/makefile deleted file mode 100644 index 6d25c17..0000000 --- a/client/entities/makefile +++ /dev/null @@ -1,32 +0,0 @@ -#config -INCLUDES+=. .. ../../common/gameplay ../../common/graphics ../../common/utilities -LIBS+= -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=.. -OUT=$(addprefix $(OUTDIR)/,client.a) - -#targets -all: $(OBJ) $(OUT) - ar -crs $(OUT) $(OBJ) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/client/gameplay_scenes/makefile b/client/gameplay_scenes/makefile deleted file mode 100644 index 40fc4ee..0000000 --- a/client/gameplay_scenes/makefile +++ /dev/null @@ -1,32 +0,0 @@ -#config -INCLUDES+=. .. ../client_utilities ../entities ../../common/gameplay ../../common/graphics ../../common/map ../../common/network ../../common/network/packet_types ../../common/ui ../../common/utilities -LIBS+= -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=.. -OUT=$(addprefix $(OUTDIR)/,client.a) - -#targets -all: $(OBJ) $(OUT) - ar -crs $(OUT) $(OBJ) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/client/gameplay_scenes/world.hpp b/client/gameplay_scenes/world.hpp deleted file mode 100644 index 790cc2e..0000000 --- a/client/gameplay_scenes/world.hpp +++ /dev/null @@ -1,165 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -//maps -#include "region_pager_base.hpp" - -//utilities -#include "udp_network_utility.hpp" -#include "serial_packet.hpp" -#include "config_utility.hpp" - -//graphics -#include "image.hpp" -#include "button.hpp" -#include "tile_sheet.hpp" - -//common -#include "frame_rate.hpp" - -//client -#include "base_scene.hpp" -#include "base_monster.hpp" -#include "local_character.hpp" - -//STL -#include - -#include - -class World: public BaseScene { -public: - //Public access members - World(int* const argClientIndex, int* const argAccountIndex); - ~World(); - - void RenderFrame(SDL_Renderer* renderer) override; - -private: - //frame phases - void FrameStart() override; - void Update() override; - void FrameEnd() override; - - //input events - void MouseMotion(SDL_MouseMotionEvent const& event) override; - void MouseButtonDown(SDL_MouseButtonEvent const& event) override; - void MouseButtonUp(SDL_MouseButtonEvent const& event) override; - void MouseWheel(SDL_MouseWheelEvent const& event) override; - void KeyDown(SDL_KeyboardEvent const& event) override; - void KeyUp(SDL_KeyboardEvent const& event) override; - - //handle incoming traffic - void HandlePacket(SerialPacket* const); - - //heartbeat system - void hPing(ServerPacket* const); - void hPong(ServerPacket* const); - - void CheckHeartBeat(); - - //basic connections - void SendLogoutRequest(); - void SendDisconnectRequest(); - void SendAdminDisconnectForced(); - void SendAdminShutdownRequest(); - - void hLogoutResponse(ClientPacket* const); - void hDisconnectResponse(ClientPacket* const); - void hAdminDisconnectForced(ClientPacket* const); - - //map management - void SendRegionRequest(int roomIndex, int x, int y); - void hRegionContent(RegionPacket* const); - void UpdateMap(); - - //character management - void hCharacterUpdate(CharacterPacket* const); - void hCharacterCreate(CharacterPacket* const); - void hCharacterDelete(CharacterPacket* const); - void hQueryCharacterExists(CharacterPacket* const); - void hQueryCharacterStats(CharacterPacket* const); - void hQueryCharacterLocation(CharacterPacket* const); - void hCharacterMovement(CharacterPacket* const); - void hCharacterAttack(CharacterPacket* const); - void hCharacterDamage(CharacterPacket* const); - - //monster management - void hMonsterCreate(MonsterPacket* const); - void hMonsterDelete(MonsterPacket* const); - void hQueryMonsterExists(MonsterPacket* const); - void hQueryMonsterStats(MonsterPacket* const); - void hQueryMonsterLocation(MonsterPacket* const); - void hMonsterMovement(MonsterPacket* const); - void hMonsterAttack(MonsterPacket* const); - void hMonsterDamage(MonsterPacket* const); - - //chat - void hTextBroadcast(TextPacket* const); - void hTextSpeech(TextPacket* const); - void hTextWhisper(TextPacket* const); - - //general gameplay - void SendLocalCharacterMovement(); - std::list GenerateCollisionGrid(Entity*, int tileWidth, int tileHeight); - - //indexes - int& clientIndex; - int& accountIndex; - int characterIndex = -1; - int roomIndex = -1; - - //graphics - Image buttonImage; - TileSheet tileSheet; - - //map - RegionPagerBase regionPager; - - //UI - Button disconnectButton; - Button shutDownButton; - FrameRate fps; - - //the camera structure - struct { - int x = 0, y = 0; - int width = 0, height = 0; - int marginX = 0, marginY = 0; - } camera; - - //entities - std::map characterMap; - std::map monsterMap; - LocalCharacter* localCharacter = nullptr; - - //heartbeat - //TODO: (2) Heartbeat needs it's own utility - typedef std::chrono::steady_clock Clock; - Clock::time_point lastBeat = Clock::now(); - int attemptedBeats = 0; - - //ugly references; I hate this - ConfigUtility& config = ConfigUtility::GetSingleton(); - UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton(); -}; diff --git a/client/gameplay_scenes/world_characters.cpp b/client/gameplay_scenes/world_characters.cpp deleted file mode 100644 index 377bc05..0000000 --- a/client/gameplay_scenes/world_characters.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "world.hpp" - -#include "channels.hpp" - -#include -#include -#include -#include - -//------------------------- -//character management -//------------------------- - -//DOCS: preexisting characters will result in query responses -//DOCS: new characters will result in create messages -//DOCS: this client's character will exist in both (skipped) - -void World::hCharacterUpdate(CharacterPacket* const argPacket) { - //TODO: (1) Authentication - //NOTE: applies to the local character too - - //check that this character exists - std::map::iterator characterIt = characterMap.find(argPacket->characterIndex); - if (characterIt != characterMap.end()) { - //update the origin and motion, if there's a difference - if (characterIt->second.GetOrigin() != argPacket->origin) { - characterIt->second.SetOrigin(argPacket->origin); - } - if (characterIt->second.GetMotion() != argPacket->motion) { - characterIt->second.SetMotion(argPacket->motion); - characterIt->second.CorrectSprite(); //only correct the sprite if the motion changes - } - } -} - -void World::hCharacterCreate(CharacterPacket* const argPacket) { - //prevent double message - if (characterMap.find(argPacket->characterIndex) != characterMap.end()) { - std::ostringstream msg; - msg << "Double character creation event; "; - msg << "Index: " << argPacket->characterIndex << "; "; - msg << "Handle: " << argPacket->handle; - throw(std::runtime_error(msg.str())); - } - - //implicity create and retrieve the entity - BaseCharacter* character = &characterMap[argPacket->characterIndex]; - - //fill the character's info - character->SetHandle(argPacket->handle); - character->SetAvatar(argPacket->avatar); - character->SetOwner(argPacket->accountIndex); - character->SetOrigin(argPacket->origin); - character->SetMotion(argPacket->motion); - character->SetBounds(argPacket->bounds); - - character->CorrectSprite(); - - //check for this player's character - if (character->GetOwner() == accountIndex) { - localCharacter = static_cast(character); - - //focus the camera on this character's sprite - camera.marginX = (camera.width / 2 - localCharacter->GetSprite()->GetImage()->GetClipW() / 2); - camera.marginY = (camera.height/ 2 - localCharacter->GetSprite()->GetImage()->GetClipH() / 2); - - //focus on this character's info - characterIndex = argPacket->characterIndex; - roomIndex = argPacket->roomIndex; - - //query the world state (room) - CharacterPacket newPacket; - memset(&newPacket, 0, MAX_PACKET_SIZE); - newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS; - newPacket.roomIndex = roomIndex; - network.SendTo(Channels::SERVER, &newPacket); - newPacket.type = SerialPacketType::QUERY_MONSTER_EXISTS; - network.SendTo(Channels::SERVER, &newPacket); - } - - //debug - std::cout << "Character Create, total: " << characterMap.size() << std::endl; -} - -void World::hCharacterDelete(CharacterPacket* const argPacket) { - //ignore if this character doesn't exist - std::map::iterator characterIt = characterMap.find(argPacket->characterIndex); - if (characterIt == characterMap.end()) { - return; - } - - //check for this player's character - if ((*characterIt).second.GetOwner() == accountIndex) { - localCharacter = nullptr; - - //clear the camera - camera.marginX = 0; - camera.marginY = 0; - - //clear the room - roomIndex = -1; - regionPager.UnloadAll(); - characterMap.clear(); - monsterMap.clear(); - } - else { - //remove this character - characterMap.erase(characterIt); - } - - //debug - std::cout << "Character Delete, total: " << characterMap.size() << std::endl; -} - -void World::hQueryCharacterExists(CharacterPacket* const argPacket) { - //prevent a double message about this player's character -// if (argPacket->accountIndex == accountIndex) { -// return; -// } - - //ignore characters in a different room (sub-optimal) - if (argPacket->roomIndex != roomIndex) { - return; - } - - //implicitly construct the character if it doesn't exist - BaseCharacter* character = &characterMap[argPacket->characterIndex]; - - //set/update the character's info - character->SetOrigin(argPacket->origin); - character->SetMotion(argPacket->motion); - character->SetBounds({CHARACTER_BOUNDS_X, CHARACTER_BOUNDS_Y, CHARACTER_BOUNDS_WIDTH, CHARACTER_BOUNDS_HEIGHT}); - character->SetHandle(argPacket->handle); - character->SetAvatar(argPacket->avatar); - character->SetOwner(argPacket->accountIndex); - character->CorrectSprite(); - - //debug - std::cout << "Character Query, total: " << characterMap.size() << std::endl; -} - -void World::hQueryCharacterStats(CharacterPacket* const argPacket) { - //TODO: (9) World::hQueryCharacterStats() -} - -void World::hQueryCharacterLocation(CharacterPacket* const argPacket) { - //TODO: (9) World::hQueryCharacterLocation() -} - -void World::hCharacterMovement(CharacterPacket* const argPacket) { - //TODO: (1) Authentication - if (argPacket->characterIndex == characterIndex) { - return; - } - - //check that this character exists - std::map::iterator characterIt = characterMap.find(argPacket->characterIndex); - if (characterIt != characterMap.end()) { - //set the origin and motion - characterIt->second.SetOrigin(argPacket->origin); - characterIt->second.SetMotion(argPacket->motion); - characterIt->second.CorrectSprite(); - } -} - -void World::hCharacterAttack(CharacterPacket* const argPacket) { - //TODO: (9) World::hCharacterAttack() -} - -void World::hCharacterDamage(CharacterPacket* const argPacket) { - //TODO: (9) World::hCharacterDamage() -} - -//------------------------- -//player movement & collision -//------------------------- - -void World::SendLocalCharacterMovement() { - CharacterPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_MOVEMENT; - - newPacket.accountIndex = accountIndex; - newPacket.characterIndex = characterIndex; - newPacket.roomIndex = roomIndex; - newPacket.origin = localCharacter->GetOrigin(); - newPacket.motion = localCharacter->GetMotion(); - - network.SendTo(Channels::SERVER, &newPacket); -} - -std::list World::GenerateCollisionGrid(Entity* ptr, int tileWidth, int tileHeight) { - //prepare for collisions - BoundingBox wallBounds = {0, 0, tileWidth, tileHeight}; - std::list boxList; - - //NOTE: for loops were too dense to work with, so I've just used while loops - - //outer loop - wallBounds.x = snapToBase((double)wallBounds.w, ptr->GetOrigin().x); - while(wallBounds.x < (ptr->GetOrigin() + ptr->GetBounds()).x + ptr->GetBounds().w) { - //inner loop - wallBounds.y = snapToBase((double)wallBounds.h, ptr->GetOrigin().y); - while(wallBounds.y < (ptr->GetOrigin() + ptr->GetBounds()).y + ptr->GetBounds().h) { - //check to see if this tile is solid - if (regionPager.GetSolid(wallBounds.x / wallBounds.w, wallBounds.y / wallBounds.h)) { - //push onto the box set - boxList.push_front(wallBounds); - } - - //increment - wallBounds.y += wallBounds.h; - } - - //increment - wallBounds.x += wallBounds.w; - } - - return std::move(boxList); -} \ No newline at end of file diff --git a/client/gameplay_scenes/world_chat.cpp b/client/gameplay_scenes/world_chat.cpp deleted file mode 100644 index 09ac1bb..0000000 --- a/client/gameplay_scenes/world_chat.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "world.hpp" - -//------------------------- -//chat -//------------------------- - -void World::hTextBroadcast(TextPacket* const argPacket) { - //TODO: (9) World::hTextBroadcast() -} - -void World::hTextSpeech(TextPacket* const argPacket) { - //TODO: (9) World::hTextSpeech() -} - -void World::hTextWhisper(TextPacket* const argPacket) { - //TODO: (9) World::hTextWhisper() -} - diff --git a/client/gameplay_scenes/world_connections.cpp b/client/gameplay_scenes/world_connections.cpp deleted file mode 100644 index fb30f96..0000000 --- a/client/gameplay_scenes/world_connections.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "world.hpp" - -#include "channels.hpp" -#include "ip_operators.hpp" - -#include -#include -#include - -//------------------------- -//heartbeat system -//------------------------- - -void World::hPing(ServerPacket* const argPacket) { - ServerPacket newPacket; - newPacket.type = SerialPacketType::PONG; - network.SendTo(argPacket->srcAddress, &newPacket); -} - -void World::hPong(ServerPacket* const argPacket) { - if (*network.GetIPAddress(Channels::SERVER) != argPacket->srcAddress) { - throw(std::runtime_error("Heartbeat message received from an unknown source")); - } - attemptedBeats = 0; - lastBeat = Clock::now(); -} - -void World::CheckHeartBeat() { - //check the connection (heartbeat) - if (Clock::now() - lastBeat > std::chrono::seconds(3)) { - if (attemptedBeats > 2) { - //escape to the disconnect screen - SendDisconnectRequest(); - SetNextScene(SceneList::DISCONNECTEDSCREEN); - ConfigUtility::GetSingleton()["client.disconnectMessage"] = "Error: Lost connection to the server"; - } - else { - ServerPacket newPacket; - newPacket.type = SerialPacketType::PING; - network.SendTo(Channels::SERVER, &newPacket); - - attemptedBeats++; - lastBeat = Clock::now(); - } - } -} - -//------------------------- -//Connection control -//------------------------- - -void World::SendLogoutRequest() { - ClientPacket newPacket; - - //send a logout request - newPacket.type = SerialPacketType::LOGOUT_REQUEST; - newPacket.accountIndex = accountIndex; - - network.SendTo(Channels::SERVER, &newPacket); -} - -void World::SendDisconnectRequest() { - ClientPacket newPacket; - - //send a disconnect request - newPacket.type = SerialPacketType::DISCONNECT_REQUEST; - newPacket.clientIndex = clientIndex; - - network.SendTo(Channels::SERVER, &newPacket); -} - -void World::SendAdminDisconnectForced() { - //TODO: (9) World::SendAdminDisconnectForced() -} - -void World::SendAdminShutdownRequest() { - ClientPacket newPacket; - - //send a shutdown request - newPacket.type = SerialPacketType::ADMIN_SHUTDOWN_REQUEST; - newPacket.accountIndex = accountIndex; - - network.SendTo(Channels::SERVER, &newPacket); -} - -void World::hLogoutResponse(ClientPacket* const argPacket) { - if (localCharacter) { - characterMap.erase(characterIndex); - localCharacter = nullptr; - } - - accountIndex = -1; - characterIndex = -1; - - //reset the camera - camera.marginX = camera.marginY = 0; - - //because, why not? I guess... - SendDisconnectRequest(); -} - -void World::hDisconnectResponse(ClientPacket* const argPacket) { - hLogoutResponse(argPacket);//shortcut - SetNextScene(SceneList::DISCONNECTEDSCREEN); - ConfigUtility::GetSingleton()["client.disconnectMessage"] = "You have successfully logged out"; -} - -void World::hAdminDisconnectForced(ClientPacket* const argPacket) { - hDisconnectResponse(argPacket);//shortcut - SetNextScene(SceneList::DISCONNECTEDSCREEN); - ConfigUtility::GetSingleton()["client.disconnectMessage"] = "You have been forcibly disconnected by the server"; -} - diff --git a/client/gameplay_scenes/world_logic.cpp b/client/gameplay_scenes/world_logic.cpp deleted file mode 100644 index a75833e..0000000 --- a/client/gameplay_scenes/world_logic.cpp +++ /dev/null @@ -1,428 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "world.hpp" - -#include "channels.hpp" -#include "terminal_error.hpp" - -#include -#include -#include -#include -#include -#include - -//------------------------- -//Public access members -//------------------------- - -World::World(int* const argClientIndex, int* const argAccountIndex): - clientIndex(*argClientIndex), - accountIndex(*argAccountIndex) -{ - //setup the utility objects - buttonImage.LoadSurface(config["dir.interface"] + "button_menu.bmp"); - buttonImage.SetClipH(buttonImage.GetClipH()/3); - font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp"); - - //pass the utility objects - disconnectButton.SetImage(&buttonImage); - disconnectButton.SetFont(&font); - shutDownButton.SetImage(&buttonImage); - shutDownButton.SetFont(&font); - - //set the button positions - disconnectButton.SetX(50); - disconnectButton.SetY(50 + buttonImage.GetClipH() * 0); - shutDownButton.SetX(50); - shutDownButton.SetY(50 + buttonImage.GetClipH() * 1); - - //set the button texts - disconnectButton.SetText("Disconnect"); - shutDownButton.SetText("Shut Down"); - - //load the tilesheet - //TODO: (2) Tile size and tile sheet should be loaded elsewhere - tileSheet.Load(config["dir.tilesets"] + "overworld.bmp", 32, 32); - - //Send the character data - CharacterPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_LOAD; - strncpy(newPacket.handle, config["client.handle"].c_str(), PACKET_STRING_SIZE); - strncpy(newPacket.avatar, config["client.avatar"].c_str(), PACKET_STRING_SIZE); - newPacket.accountIndex = accountIndex; - network.SendTo(Channels::SERVER, &newPacket); - - //set the camera's values - camera.width = GetScreen()->w; - camera.height = GetScreen()->h; - - //debug - // -} - -World::~World() { - //unload the local data - characterMap.clear(); - monsterMap.clear(); -} - -//------------------------- -//Frame loop -//------------------------- - -void World::FrameStart() { - // -} - -void World::Update() { - //create and zero the buffer - SerialPacket* packetBuffer = reinterpret_cast(new char[MAX_PACKET_SIZE]); - memset(packetBuffer, 0, MAX_PACKET_SIZE); - - try { - //suck in and process all waiting packets - while(network.Receive(packetBuffer)) { - HandlePacket(packetBuffer); - } - } - catch(terminal_error& e) { - throw(e); - } - catch(std::exception& e) { - std::cerr << "HandlePacket Error: " << e.what() << std::endl; - } - - //free the buffer - delete reinterpret_cast(packetBuffer); - - //heartbeat system - CheckHeartBeat(); - - //update all entities - for (auto& it : characterMap) { - it.second.Update(); - } - for (auto& it : monsterMap) { - it.second.Update(); - } - - try { - //update the map - UpdateMap(); - } - catch(terminal_error& e) { - throw(e); - } - catch(std::exception& e) { - std::cerr << "UpdateMap Error: " << e.what() << std::endl; - } - - //skip the rest without a local character - if (!localCharacter) { - return; - } - - //get the collidable boxes - std::list boxList = GenerateCollisionGrid(localCharacter, tileSheet.GetTileW(), tileSheet.GetTileH()); - - //process the collisions - if (localCharacter->ProcessCollisionGrid(boxList)) { - localCharacter->CorrectSprite(); - SendLocalCharacterMovement(); - } - - //update the camera - camera.x = localCharacter->GetOrigin().x - camera.marginX; - camera.y = localCharacter->GetOrigin().y - camera.marginY; -} - -void World::FrameEnd() { - // -} - -void World::RenderFrame() { -// SDL_FillRect(GetScreen(), 0, 0); - Render(GetScreen()); - SDL_Flip(GetScreen()); - fps.Calculate(); -} - -void World::Render(SDL_Surface* const screen) { - //draw the map - for (std::list::iterator it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) { - tileSheet.DrawRegionTo(screen, &(*it), camera.x, camera.y); - - //debugging -// std::ostringstream msg; -// msg << it->GetX() << ", " << it->GetY(); -// font.DrawStringTo(msg.str(), screen, it->GetX() * tileSheet.GetImage()->GetClipW() - camera.x, it->GetY() * tileSheet.GetImage()->GetClipH() - camera.y); - } - - //draw the entities - for (auto& it : characterMap) { - //BUG: #29 Characters (and other entities) are drawn out of order - it.second.DrawTo(screen, camera.x, camera.y); - } - for (auto& it : monsterMap) { - it.second.DrawTo(screen, camera.x, camera.y); - } - - //draw UI - disconnectButton.DrawTo(screen); - shutDownButton.DrawTo(screen); - std::ostringstream msg; - msg << fps.GetFrameRate(); - font.DrawStringTo(msg.str(), screen, 0, 0); -} - -//------------------------- -//Event handlers -//------------------------- - -void World::QuitEvent() { - //two-step logout - SendDisconnectRequest(); - SetNextScene(SceneList::QUIT); -} - -void World::MouseMotion(SDL_MouseMotionEvent const& motion) { - disconnectButton.MouseMotion(motion); - shutDownButton.MouseMotion(motion); -} - -void World::MouseButtonDown(SDL_MouseButtonEvent const& button) { - disconnectButton.MouseButtonDown(button); - shutDownButton.MouseButtonDown(button); -} - -void World::MouseButtonUp(SDL_MouseButtonEvent const& button) { - if (disconnectButton.MouseButtonUp(button) == Button::State::HOVER && button.button == SDL_BUTTON_LEFT) { - SendLogoutRequest(); - } - if (shutDownButton.MouseButtonUp(button) == Button::State::HOVER && button.button == SDL_BUTTON_LEFT) { - SendAdminShutdownRequest(); - } -} - -void World::KeyDown(SDL_KeyboardEvent const& key) { - //hotkeys - switch(key.keysym.sym) { - case SDLK_ESCAPE: - //TODO: (3) the escape key should actually control menus and stuff - SendLogoutRequest(); - return; - } - - //character movement - if (!localCharacter) { - return; - } - Vector2 motion = localCharacter->GetMotion(); - switch(key.keysym.sym) { - case SDLK_w: - motion.y -= CHARACTER_WALKING_SPEED; - break; - case SDLK_a: - motion.x -= CHARACTER_WALKING_SPEED; - break; - case SDLK_s: - motion.y += CHARACTER_WALKING_SPEED; - break; - case SDLK_d: - motion.x += CHARACTER_WALKING_SPEED; - break; - default: - //DOCS: prevents wrong keys screwing with character movement - return; - } - //handle diagonals - if (motion.x != 0 && motion.y != 0) { - motion *= CHARACTER_WALKING_MOD; - } - //set the info - localCharacter->SetMotion(motion); - localCharacter->CorrectSprite(); - SendLocalCharacterMovement(); -} - -void World::KeyUp(SDL_KeyboardEvent const& key) { - //character movement - if (!localCharacter) { - return; - } - Vector2 motion = localCharacter->GetMotion(); - switch(key.keysym.sym) { - case SDLK_w: - motion.y = std::min(0.0, motion.y += CHARACTER_WALKING_SPEED); - break; - case SDLK_a: - motion.x = std::min(0.0, motion.x += CHARACTER_WALKING_SPEED); - break; - case SDLK_s: - motion.y = std::max(0.0, motion.y -= CHARACTER_WALKING_SPEED); - break; - case SDLK_d: - motion.x = std::max(0.0, motion.x -= CHARACTER_WALKING_SPEED); - break; - default: - //DOCS: prevents wrong keys screwing with character movement - return; - } - //BUGFIX: reset cardinal direction speed on key release - if (motion.x > 0) { - motion.x = CHARACTER_WALKING_SPEED; - } - else if (motion.x < 0) { - motion.x = -CHARACTER_WALKING_SPEED; - } - if (motion.y > 0) { - motion.y = CHARACTER_WALKING_SPEED; - } - else if (motion.y < 0) { - motion.y = -CHARACTER_WALKING_SPEED; - } - //handle diagonals - if (motion.x != 0 && motion.y != 0) { - motion *= CHARACTER_WALKING_MOD; - } - //set the info - localCharacter->SetMotion(motion); - localCharacter->CorrectSprite(); - SendLocalCharacterMovement(); -} - -//------------------------- -//Direct incoming traffic -//------------------------- - -void World::HandlePacket(SerialPacket* const argPacket) { - switch(argPacket->type) { - //heartbeat system - case SerialPacketType::PING: - hPing(static_cast(argPacket)); - break; - case SerialPacketType::PONG: - hPong(static_cast(argPacket)); - break; - - //game server connections - case SerialPacketType::LOGOUT_RESPONSE: - hLogoutResponse(static_cast(argPacket)); - break; - case SerialPacketType::DISCONNECT_RESPONSE: - hDisconnectResponse(static_cast(argPacket)); - break; - case SerialPacketType::ADMIN_DISCONNECT_FORCED: - hAdminDisconnectForced(static_cast(argPacket)); - break; - - //map management - case SerialPacketType::REGION_CONTENT: - hRegionContent(static_cast(argPacket)); - break; - - //character management - case SerialPacketType::CHARACTER_UPDATE: - hCharacterUpdate(static_cast(argPacket)); - break; - case SerialPacketType::CHARACTER_CREATE: - hCharacterCreate(static_cast(argPacket)); - break; - case SerialPacketType::CHARACTER_DELETE: - hCharacterDelete(static_cast(argPacket)); - break; - case SerialPacketType::QUERY_CHARACTER_EXISTS: - hQueryCharacterExists(static_cast(argPacket)); - break; - case SerialPacketType::QUERY_CHARACTER_STATS: - hQueryCharacterStats(static_cast(argPacket)); - break; - case SerialPacketType::QUERY_CHARACTER_LOCATION: - hQueryCharacterLocation(static_cast(argPacket)); - break; - case SerialPacketType::CHARACTER_MOVEMENT: - hCharacterMovement(static_cast(argPacket)); - break; - case SerialPacketType::CHARACTER_ATTACK: - hCharacterAttack(static_cast(argPacket)); - break; - case SerialPacketType::CHARACTER_DAMAGE: - hCharacterDamage(static_cast(argPacket)); - break; - - //monster management - case SerialPacketType::MONSTER_CREATE: - hMonsterCreate(static_cast(argPacket)); - break; - case SerialPacketType::MONSTER_DELETE: - hMonsterDelete(static_cast(argPacket)); - break; - case SerialPacketType::QUERY_MONSTER_EXISTS: - hQueryMonsterExists(static_cast(argPacket)); - break; - case SerialPacketType::QUERY_MONSTER_STATS: - hQueryMonsterStats(static_cast(argPacket)); - break; - case SerialPacketType::QUERY_MONSTER_LOCATION: - hQueryMonsterLocation(static_cast(argPacket)); - break; - case SerialPacketType::MONSTER_MOVEMENT: - hMonsterMovement(static_cast(argPacket)); - break; - case SerialPacketType::MONSTER_ATTACK: - hMonsterAttack(static_cast(argPacket)); - break; - case SerialPacketType::MONSTER_DAMAGE: - hMonsterDamage(static_cast(argPacket)); - break; - - //chat - case SerialPacketType::TEXT_BROADCAST: - hTextBroadcast(static_cast(argPacket)); - break; - case SerialPacketType::TEXT_SPEECH: - hTextSpeech(static_cast(argPacket)); - break; - case SerialPacketType::TEXT_WHISPER: - hTextWhisper(static_cast(argPacket)); - break; - - //general rejection messages - case SerialPacketType::REGION_REJECTION: - case SerialPacketType::CHARACTER_REJECTION: - case SerialPacketType::QUERY_REJECTION: - throw(terminal_error(static_cast(argPacket)->text)); - break; - case SerialPacketType::SHUTDOWN_REJECTION: - throw(std::runtime_error(static_cast(argPacket)->text)); - break; - - //errors - default: { - std::ostringstream msg; - msg << "Unknown SerialPacketType encountered in World: " << static_cast(argPacket->type); - throw(std::runtime_error(msg.str())); - } - break; - } -} \ No newline at end of file diff --git a/client/gameplay_scenes/world_map.cpp b/client/gameplay_scenes/world_map.cpp deleted file mode 100644 index 1265281..0000000 --- a/client/gameplay_scenes/world_map.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "world.hpp" - -#include "channels.hpp" - -#include - -//------------------------- -//static functions -//------------------------- - -static int regionChecksum(Region* const region) { - int sum = 0; - for(int i = 0; i < REGION_WIDTH; i++) { - for (int j = 0; j < REGION_HEIGHT; j++) { - for (int k = 0; k < REGION_DEPTH; k++) { - sum += region->GetTile(i, j, k); - } - } - } - return sum; -} - -//------------------------- -//map management -//------------------------- - -void World::SendRegionRequest(int roomIndex, int x, int y) { - RegionPacket packet; - - //pack the region's data - packet.type = SerialPacketType::REGION_REQUEST; - packet.roomIndex = roomIndex; - packet.x = x; - packet.y = y; - - network.SendTo(Channels::SERVER, &packet); -} - -void World::hRegionContent(RegionPacket* const argPacket) { - //checksum - if (regionChecksum(argPacket->region) == 0) { - std::ostringstream msg; - msg << "Received region checksum failed: " << argPacket->x << ", " << argPacket->y; - throw(std::runtime_error(msg.str())); - } - - //replace existing regions - regionPager.UnloadIf([&](Region const& region) -> bool { - return region.GetX() == argPacket->x && region.GetY() == argPacket->y; - }); - regionPager.PushRegion(argPacket->region); - - //clean up after the serial code - delete argPacket->region; - argPacket->region = nullptr; -} - -void World::UpdateMap() { - if (roomIndex == -1) { - return; - } - - //these represent the zone of regions that the client needs loaded, including the mandatory buffers (+1/-1) - int xStart = snapToBase(REGION_WIDTH, camera.x/tileSheet.GetTileW()) - REGION_WIDTH; - int xEnd = snapToBase(REGION_WIDTH, (camera.x+camera.width)/tileSheet.GetTileW()) + REGION_WIDTH; - - int yStart = snapToBase(REGION_HEIGHT, camera.y/tileSheet.GetTileH()) - REGION_HEIGHT; - int yEnd = snapToBase(REGION_HEIGHT, (camera.y+camera.height)/tileSheet.GetTileH()) + REGION_HEIGHT; - - //prune distant regions - regionPager.GetContainer()->remove_if([&](Region const& region) -> bool { - return region.GetX() < xStart || region.GetX() > xEnd || region.GetY() < yStart || region.GetY() > yEnd; - }); - - //request empty regions within this zone - for (int i = xStart; i <= xEnd; i += REGION_WIDTH) { - for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) { - Region* region = regionPager.FindRegion(i, j); - if (!region) { - //request absent region - SendRegionRequest(roomIndex, i, j); - } - else if (regionChecksum(region) == 0) { - //checksum failed - //NOTE: this patches bug #45, but does not resolve it - regionPager.UnloadIf([region](Region const& ref) -> bool { - //remove the erroneous region - return region == &ref; - }); - SendRegionRequest(roomIndex, i, j); - std::ostringstream msg; - msg << "Existing region checksum failed: " << roomIndex << ", " << i << ", " << j; - throw(std::runtime_error(msg.str())); - } - } - } -} \ No newline at end of file diff --git a/client/gameplay_scenes/world_monsters.cpp b/client/gameplay_scenes/world_monsters.cpp deleted file mode 100644 index ada5786..0000000 --- a/client/gameplay_scenes/world_monsters.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "world.hpp" - -#include "channels.hpp" - -#include -#include -#include - -//------------------------- -//monster management -//------------------------- - -void World::hMonsterCreate(MonsterPacket* const argPacket) { - //check for logic errors - if (monsterMap.find(argPacket->monsterIndex) != monsterMap.end()) { - std::ostringstream msg; - msg << "Double monster creation event; "; - msg << "Index: " << argPacket->monsterIndex << "; "; - msg << "Handle: " << argPacket->handle; - throw(std::runtime_error(msg.str())); - } - - //ignore monsters from other rooms - if (roomIndex != argPacket->roomIndex) { - //temporary error checking - std::ostringstream msg; - msg << "Monster from the wrong room received: "; - msg << "monsterIndex: " << argPacket->monsterIndex << ", roomIndex: " << argPacket->roomIndex; - throw(std::runtime_error(msg.str())); - } - - //implicitly create the element - BaseMonster* monster = &monsterMap[argPacket->monsterIndex]; - - //fill the monster's info - monster->SetHandle(argPacket->handle); - monster->SetAvatar(argPacket->avatar); - monster->SetBounds(argPacket->bounds); - monster->SetOrigin(argPacket->origin); - monster->SetMotion(argPacket->motion); - - //debug - std::cout << "Monster Create, total: " << monsterMap.size() << std::endl; -} - -void World::hMonsterDelete(MonsterPacket* const argPacket) { - //ignore if this monster doesn't exist - std::map::iterator monsterIt = monsterMap.find(argPacket->monsterIndex); - if (monsterIt == monsterMap.end()) { - return; - } - - //remove this monster - monsterMap.erase(monsterIt); - - //debug - std::cout << "Monster Delete, total: " << monsterMap.size() << std::endl; -} - -void World::hQueryMonsterExists(MonsterPacket* const argPacket) { - //ignore monsters in a different room (sub-optimal) - if (argPacket->roomIndex != roomIndex) { - return; - } - - //implicitly create the element - BaseMonster* monster = &monsterMap[argPacket->monsterIndex]; - - //fill the monster's info - monster->SetHandle(argPacket->handle); - monster->SetAvatar(argPacket->avatar); - monster->SetBounds(argPacket->bounds); - monster->SetOrigin(argPacket->origin); - monster->SetMotion(argPacket->motion); - - //debug - std::cout << "Monster Query, total: " << monsterMap.size() << std::endl; -} - -void World::hQueryMonsterStats(MonsterPacket* const argPacket) { - //TODO: (9) World::hQueryMonsterStats() -} - -void World::hQueryMonsterLocation(MonsterPacket* const argPacket) { - //TODO: (9) World::hQueryMonsterLocation() -} - -void World::hMonsterMovement(MonsterPacket* const argPacket) { - //ignore if this monster doesn't exist - std::map::iterator monsterIt = monsterMap.find(argPacket->monsterIndex); - if (monsterIt == monsterMap.end()) { - return; - } - - monsterIt->second.SetOrigin(argPacket->origin); - monsterIt->second.SetOrigin(argPacket->motion); -} - -void World::hMonsterAttack(MonsterPacket* const argPacket) { - //TODO: (9) World::hMonsterAttack() -} - -void World::hMonsterDamage(MonsterPacket* const argPacket) { - //TODO: (9) World::hMonsterDamage() -} \ No newline at end of file diff --git a/client/main.cpp b/client/main.cpp deleted file mode 100644 index 5afbd6e..0000000 --- a/client/main.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "client_application.hpp" - -//singletons -#include "config_utility.hpp" -#include "udp_network_utility.hpp" - -#include -#include - -using namespace std; - -int main(int argc, char* argv[]) { - try { - //create the singletons - ConfigUtility::CreateSingleton(); - UDPNetworkUtility::CreateSingleton(); - - //call the client's routines - ClientApplication::CreateSingleton(); - ClientApplication& app = ClientApplication::GetSingleton(); - - app.Init(argc, argv); - app.Proc(); - app.Quit(); - - //control the position of the app's destructor - ClientApplication::DeleteSingleton(); - - //delete the singletons - ConfigUtility::DeleteSingleton(); - UDPNetworkUtility::DeleteSingleton(); - } - catch(exception& e) { - cerr << "Fatal exception thrown: " << e.what() << endl; - return 1; - } - return 0; -} \ No newline at end of file diff --git a/client/makefile b/client/makefile deleted file mode 100644 index be625e2..0000000 --- a/client/makefile +++ /dev/null @@ -1,60 +0,0 @@ -#include directories -INCLUDES+=. client_utilities entities gameplay_scenes menu_scenes ../common/debugging ../common/gameplay ../common/graphics ../common/map ../common/network ../common/network/packet_types ../common/ui ../common/utilities - -#libraries -#the order of the $(LIBS) is important, at least for MinGW -LIBS+=client.a ../libcommon.a -lSDL_net -ifeq ($(OS),Windows_NT) - LIBS+=-lwsock32 -liphlpapi -lmingw32 -endif -LIBS+=-lSDL2main -lSDL2 -lSDL2_image -lSDL2_ttf - -#flags -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) -ifeq ($(shell uname), Linux) - #read data about the current install - CXXFLAGS+=$(shell sdl-config --cflags --static-libs) -endif - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=../out -OUT=$(addprefix $(OUTDIR)/,client) - -#targets -all: $(OBJ) $(OUT) - $(MAKE) -C client_utilities - $(MAKE) -C entities -# $(MAKE) -C gameplay_scenes -# $(MAKE) -C menu_scenes -# $(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< - -clean: -ifeq ($(OS),Windows_NT) - $(RM) *.o *.a *.exe -else ifeq ($(shell uname), Linux) - find . -type f -name *.o -exec rm -f -r -v {} \; - find . -type f -name *.a -exec rm -f -r -v {} \; - rm -f -v out/client out/server -endif - -rebuild: clean all diff --git a/client/menu_scenes/disconnected_screen.cpp b/client/menu_scenes/disconnected_screen.cpp deleted file mode 100644 index 0a5e655..0000000 --- a/client/menu_scenes/disconnected_screen.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "disconnected_screen.hpp" - -#include "channels.hpp" -#include "config_utility.hpp" -#include "udp_network_utility.hpp" - -#include - -//------------------------- -//Public access members -//------------------------- - -DisconnectedScreen::DisconnectedScreen() { - ConfigUtility& config = ConfigUtility::GetSingleton(); - - //setup the utility objects - //TODO: (1) resource tool, to prevent reloading like this - image.Load(GetRenderer(), config["dir.interface"] + "button.png"); - font = TTF_OpenFont(config["client.font"].c_str(), 12); - - //setup the button - backButton.SetBackgroundTexture(GetRenderer(), image.GetTexture()); - backButton.SetText(GetRenderer(), font, "Back", {255, 255, 255, 255}); - - //set the button positions - backButton.SetX(50); - backButton.SetY(50); - - //set the disconnection message text - textLine.SetText(GetRenderer(), font, config["client.disconnectMessage"], {255, 255, 255, 255}); - - //full reset - UDPNetworkUtility::GetSingleton().Unbind(Channels::SERVER); - - //auto return - startTick = std::chrono::steady_clock::now(); -} - -DisconnectedScreen::~DisconnectedScreen() { - TTF_CloseFont(font); -} - -//------------------------- -//Frame loop -//------------------------- - -void DisconnectedScreen::FrameStart() { - // -} - -void DisconnectedScreen::Update() { - if (std::chrono::steady_clock::now() - startTick > std::chrono::duration(10)) { - SetSceneSignal(SceneSignal::MAINMENU); - } - - //Eat incoming packets - while(UDPNetworkUtility::GetSingleton().Receive()); -} - -void DisconnectedScreen::FrameEnd() { - // -} - -void DisconnectedScreen::RenderFrame(SDL_Renderer* renderer) { - backButton.DrawTo(renderer); - textLine.DrawTo(renderer, 50, 50); -} - -//------------------------- -//Event handlers -//------------------------- - -void DisconnectedScreen::MouseMotion(SDL_MouseMotionEvent const& event) { - backButton.MouseMotion(event); -} - -void DisconnectedScreen::MouseButtonDown(SDL_MouseButtonEvent const& event) { - backButton.MouseButtonDown(event); -} - -void DisconnectedScreen::MouseButtonUp(SDL_MouseButtonEvent const& event) { - if (backButton.MouseButtonUp(event) == Button::State::RELEASED) { - SetSceneSignal(SceneSignal::MAINMENU); - } -} - -void DisconnectedScreen::KeyDown(SDL_KeyboardEvent const& event) { - switch(event.keysym.sym) { - case SDLK_ESCAPE: - SetSceneSignal(SceneSignal::MAINMENU); - break; - } -} - -void DisconnectedScreen::KeyUp(SDL_KeyboardEvent const& event) { - // -} diff --git a/client/menu_scenes/disconnected_screen.hpp b/client/menu_scenes/disconnected_screen.hpp deleted file mode 100644 index 5edf340..0000000 --- a/client/menu_scenes/disconnected_screen.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "base_scene.hpp" -#include "button.hpp" -#include "image.hpp" -#include "text_line.hpp" - -#include "SDL2/SDL_ttf.h" - -#include - -class DisconnectedScreen : public BaseScene { -public: - //Public access members - DisconnectedScreen(); - ~DisconnectedScreen(); - - void RenderFrame(SDL_Renderer* renderer) override; - -protected: - //frame phases - void FrameStart() override; - void Update() override; - void FrameEnd() override; - - //input events - void MouseMotion(SDL_MouseMotionEvent const& event) override; - void MouseButtonDown(SDL_MouseButtonEvent const& event) override; - void MouseButtonUp(SDL_MouseButtonEvent const& event) override; - void MouseWheel(SDL_MouseWheelEvent const& event) override; - void KeyDown(SDL_KeyboardEvent const& event) override; - void KeyUp(SDL_KeyboardEvent const& event) override; - - //graphics - Image image; - TTF_Font* font = nullptr; - Button backButton; - TextLine textLine; - - //auto return - std::chrono::steady_clock::time_point startTick; -}; diff --git a/client/menu_scenes/lobby_menu.cpp b/client/menu_scenes/lobby_menu.cpp deleted file mode 100644 index be12984..0000000 --- a/client/menu_scenes/lobby_menu.cpp +++ /dev/null @@ -1,306 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "lobby_menu.hpp" - -#include "channels.hpp" - -#include -#include - -//------------------------- -//Public access members -//------------------------- - -LobbyMenu::LobbyMenu(int* const argClientIndex, int* const argAccountIndex): - clientIndex(*argClientIndex), - accountIndex(*argAccountIndex) -{ - //preemptive reset - clientIndex = -1; - accountIndex = -1; - - //setup the utility objects - buttonImage.Load(GetRenderer(), config["dir.interface"] + "button.png"); - font = TTF_OpenFont(config["client.font"].c_str(), 12); - - //setup the buttons - searchButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); - searchButton.SetText(GetRenderer(), font, "Search", {255, 255, 255, 255}); - joinButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); - joinButton.SetText(GetRenderer(), font, "Join", {255, 255, 255, 255}); - backButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); - backButton.SetText(GetRenderer(), font, "Back", {255, 255, 255, 255}); - - //set the button positions (assumed) - searchButton.SetX(50); - searchButton.SetY(50); - joinButton.SetX(50); - joinButton.SetY(70); - backButton.SetX(50); - backButton.SetY(90); - - //pseudo-list selection - boundingBox = {300, 50, 200, 12}; - - //DEBUG: hacked together a highlight box - highlightImage.Create(GetRenderer(), 300, 12, {49, 150, 5, 255}); - - //Eat incoming packets - while(network.Receive()); - - //Initial broadcast - SendBroadcastRequest(); -} - -LobbyMenu::~LobbyMenu() { - TTF_CloseFont(font); -} - -//------------------------- -//Frame loop -//------------------------- - -void LobbyMenu::FrameStart() { - // -} - -void LobbyMenu::Update() { - //suck in and process all waiting packets - SerialPacket* packetBuffer = reinterpret_cast(new char[MAX_PACKET_SIZE]); - while(network.Receive(packetBuffer)) { - HandlePacket(packetBuffer); - } - delete reinterpret_cast(packetBuffer); -} - -void LobbyMenu::FrameEnd() { - // -} - -void LobbyMenu::RenderFrame(SDL_Renderer* renderer) { - //TODO: (2) I need a proper UI system for the entire client and the editor - - //UI - searchButton.DrawTo(renderer); - joinButton.DrawTo(renderer); - backButton.DrawTo(renderer); - - //TODO: (3) draw headers for the server list - //TODO: (3) ping/delay displayed in the server list - for (int i = 0; i < serverVector.size(); i++) { - //draw the selected server's highlight - if (selection == &serverVector[i]) { - highlightImage.DrawTo(renderer, boundingBox.x, boundingBox.y + boundingBox.h * i); - } - - //draw the server's info - serverVector[i].nameImage.DrawTo(renderer, boundingBox.x, boundingBox.y + boundingBox.h * i); - serverVector[i].playerCountImage.DrawTo(renderer, boundingBox.x, boundingBox.y + boundingBox.h * i); - } -} - -//------------------------- -//Event handlers -//------------------------- - -void LobbyMenu::MouseMotion(SDL_MouseMotionEvent const& event) { - searchButton.MouseMotion(event); - joinButton.MouseMotion(event); - backButton.MouseMotion(event); -} - -void LobbyMenu::MouseButtonDown(SDL_MouseButtonEvent const& event) { - searchButton.MouseButtonDown(event); - joinButton.MouseButtonDown(event); - backButton.MouseButtonDown(event); -} - -void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& event) { - if (searchButton.MouseButtonUp(event) == Button::State::RELEASED) { - SendBroadcastRequest(); - } - if (joinButton.MouseButtonUp(event) == Button::State::RELEASED && selection && selection->compatible) { - SendJoinRequest(); - } - if (backButton.MouseButtonUp(event) == Button::State::RELEASED) { - SetSceneSignal(SceneSignal::MAINMENU); - } - - //has the user selected a server on the list? - BoundingBox tmpBox = boundingBox; - tmpBox.h *= serverVector.size(); //within the list bounds - if (tmpBox.CheckOverlap({event.x, event.y})) { - //NOTE: this memory trick requires a vector - selection = &serverVector[(event.y - boundingBox.y)/boundingBox.h]; - } - else { - selection = nullptr; - } -} - -void LobbyMenu::MouseWheel(SDL_MouseWheelEvent const& event) { - // -} - -void LobbyMenu::KeyDown(SDL_KeyboardEvent const& event) { - switch(event.keysym.sym) { - case SDLK_ESCAPE: - SetSceneSignal(SceneSignal::MAINMENU); - break; - } -} - -void LobbyMenu::KeyUp(SDL_KeyboardEvent const& event) { - // -} - -//------------------------- -//Network handlers -//------------------------- - -void LobbyMenu::HandlePacket(SerialPacket* const argPacket) { - switch(argPacket->type) { - //responses - case SerialPacketType::BROADCAST_RESPONSE: - HandleBroadcastResponse(static_cast(argPacket)); - break; - case SerialPacketType::JOIN_RESPONSE: - HandleJoinResponse(static_cast(argPacket)); - break; - case SerialPacketType::LOGIN_RESPONSE: - HandleLoginResponse(static_cast(argPacket)); - break; - - //rejections - case SerialPacketType::JOIN_REJECTION: - HandleJoinRejection(static_cast(argPacket)); - break; - case SerialPacketType::LOGIN_REJECTION: - HandleLoginRejection(static_cast(argPacket)); - break; - - //handle errors - default: { - std::ostringstream msg; - msg << "Unknown SerialPacketType encountered in LobbyMenu: " << static_cast(argPacket->type); - throw(std::runtime_error( msg.str() )); - } - break; - } -} - -void LobbyMenu::HandleBroadcastResponse(ServerPacket* const argPacket) { - //extract the data - ServerInfo newServer; - - newServer.address = argPacket->srcAddress; - newServer.name = argPacket->name; - newServer.playerCount = argPacket->playerCount; - newServer.version = argPacket->version; - newServer.compatible = newServer.version == NETWORK_VERSION; - - //push - serverVector.push_back(newServer); - - //BUGFIX: since TextLine lacks the memory management of Image, I'll wait until after the line is in the vector to handle these - - //fancy colors - SDL_Color color; - if (newServer.compatible) { - color = {255, 255, 255, 255}; - } - else { - color = {255, 0, 0, 255}; - } - - //fancy itoa - auto itoa_base10 = [](int i) -> std::string { - char str[20]; - printf(str, "%d", i); - return std::string(str); - }; - - //text graphics - serverVector.back().nameImage.SetText(GetRenderer(), font, newServer.name, color); - serverVector.back().playerCountImage.SetText(GetRenderer(), font, itoa_base10(newServer.playerCount), color); -} - -void LobbyMenu::HandleJoinResponse(ClientPacket* const argPacket) { - //save the server's data - clientIndex = argPacket->clientIndex; - network.Bind(argPacket->srcAddress, Channels::SERVER); - - //request login data - SendLoginRequest(); -} - -void LobbyMenu::HandleLoginResponse(ClientPacket* const argPacket) { - if (argPacket->clientIndex != clientIndex) { - throw(std::runtime_error("Client index invalid during login")); - } - accountIndex = argPacket->accountIndex; - SetSceneSignal(SceneSignal::WORLD); -} - -void LobbyMenu::HandleJoinRejection(TextPacket* const argPacket) { - //TODO: (9) LobbyMenu::HandleJoinRejection() -} - -void LobbyMenu::HandleLoginRejection(TextPacket* const argPacket) { - //TODO: (9) LobbyMenu::HandleLoginRejection -} - -//------------------------- -//server control -//------------------------- - -void LobbyMenu::SendBroadcastRequest() { - //broadcast to the network, or a specific server - ClientPacket packet; - packet.type = SerialPacketType::BROADCAST_REQUEST; - network.SendTo(config["server.host"].c_str(), config.Int("server.port"), &packet); - - //reset the server list - serverVector.clear(); - selection = nullptr; -} - -void LobbyMenu::SendJoinRequest() { - //pack the packet - ClientPacket packet; - packet.type = SerialPacketType::JOIN_REQUEST; - - //join the selected server - network.SendTo(selection->address, &packet); - selection = nullptr; -} - -void LobbyMenu::SendLoginRequest() { - //NOTE: high cohesion - //TODO: have a separate login screen - ClientPacket packet; - packet.type = SerialPacketType::LOGIN_REQUEST; - packet.clientIndex = clientIndex; - strncpy(packet.username, config["client.username"].c_str(), PACKET_STRING_SIZE); - - network.SendTo(Channels::SERVER, &packet); -} diff --git a/client/menu_scenes/lobby_menu.hpp b/client/menu_scenes/lobby_menu.hpp deleted file mode 100644 index e591346..0000000 --- a/client/menu_scenes/lobby_menu.hpp +++ /dev/null @@ -1,110 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -//graphics & ui -#include "image.hpp" -#include "button.hpp" -#include "bounding_box.hpp" -#include "text_line.hpp" - -#include "SDL2/SDL_ttf.h" - -//utilities -#include "config_utility.hpp" -#include "udp_network_utility.hpp" -#include "serial_packet.hpp" - -//client -#include "base_scene.hpp" - -//STL -#include - -class LobbyMenu : public BaseScene { -public: - //Public access members - LobbyMenu(int* const argClientIndex, int* const argAccountIndex); - ~LobbyMenu(); - - void RenderFrame(SDL_Renderer* renderer) override; - -protected: - //frame phases - void FrameStart() override; - void Update() override; - void FrameEnd() override; - - //input events - void MouseMotion(SDL_MouseMotionEvent const& event) override; - void MouseButtonDown(SDL_MouseButtonEvent const& event) override; - void MouseButtonUp(SDL_MouseButtonEvent const& event) override; - void MouseWheel(SDL_MouseWheelEvent const& event) override; - void KeyDown(SDL_KeyboardEvent const& event) override; - void KeyUp(SDL_KeyboardEvent const& event) override; - - //Network handlers - void HandlePacket(SerialPacket* const); - void HandleBroadcastResponse(ServerPacket* const); - void HandleJoinResponse(ClientPacket* const); - void HandleLoginResponse(ClientPacket* const); - void HandleJoinRejection(TextPacket* const); - void HandleLoginRejection(TextPacket* const); - - //server control - void SendBroadcastRequest(); - void SendJoinRequest(); - void SendLoginRequest(); - - //shared parameters - ConfigUtility& config = ConfigUtility::GetSingleton(); - UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton(); - int& clientIndex; - int& accountIndex; - - //define the list object - struct ServerInfo { - //graphics - TextLine nameImage; - TextLine playerCountImage; - - //networking - IPaddress address; - std::string name; - int playerCount; - int version; - bool compatible; - }; - - //members - Image buttonImage; - Image highlightImage; - TTF_Font* font = nullptr; - Button searchButton; - Button joinButton; - Button backButton; - - std::vector serverVector; - ServerInfo* selection = nullptr; - - BoundingBox boundingBox; -}; diff --git a/client/menu_scenes/main_menu.cpp b/client/menu_scenes/main_menu.cpp deleted file mode 100644 index aac2d18..0000000 --- a/client/menu_scenes/main_menu.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "main_menu.hpp" - -#include "config_utility.hpp" - -//------------------------- -//Public access members -//------------------------- - -MainMenu::MainMenu() { - ConfigUtility& config = ConfigUtility::GetSingleton(); - - //setup the utility objects - buttonImage.Load(GetRenderer(), config["dir.interface"] + "button.png"); - font = TTF_OpenFont(config["client.font"].c_str(), 12); - - //setup the buttons - startButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); - startButton.SetText(GetRenderer(), font, "Start", {255, 255, 255, 255}); - optionsButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); - optionsButton.SetText(GetRenderer(), font, "Options", {255, 255, 255, 255}); - quitButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); - quitButton.SetText(GetRenderer(), font, "Quit", {255, 255, 255, 255}); - - //set the button positions - startButton.SetX(50); - startButton.SetY(50 + 20 * 0); - optionsButton.SetX(50); - optionsButton.SetY(50 + 20 * 1); - quitButton.SetX(50); - quitButton.SetY(50 + 20 * 2); - - //text box - textBox.PushLine(GetRenderer(), font, "Thanks for playing!", {255, 255, 255, 255}); - textBox.PushLine(GetRenderer(), font, "You can get the latest version at: ", {255, 255, 255, 255}); - textBox.PushLine(GetRenderer(), font, "krgamestudios.com", {255, 255, 255, 255}); - - //debug - // -} - -MainMenu::~MainMenu() { - TTF_CloseFont(font); -} - -//------------------------- -//Frame loop -//------------------------- - -void MainMenu::FrameStart() { - // -} - -void MainMenu::Update() { - // -} - -void MainMenu::FrameEnd() { - // -} - -void MainMenu::RenderFrame(SDL_Renderer* renderer) { - startButton.DrawTo(renderer); - optionsButton.DrawTo(renderer); - quitButton.DrawTo(renderer); - - textBox.DrawTo(renderer, 50, 50, 12); -} - -//------------------------- -//Event handlers -//------------------------- - -void MainMenu::MouseMotion(SDL_MouseMotionEvent const& event) { - startButton.MouseMotion(event); - optionsButton.MouseMotion(event); - quitButton.MouseMotion(event); -} - -void MainMenu::MouseButtonDown(SDL_MouseButtonEvent const& event) { - startButton.MouseButtonDown(event); - optionsButton.MouseButtonDown(event); - quitButton.MouseButtonDown(event); -} - -void MainMenu::MouseButtonUp(SDL_MouseButtonEvent const& event) { - //TODO: (2) Buttons should only register as "selected" when the left button is used - if (startButton.MouseButtonUp(event) == Button::State::RELEASED) { - SetSceneSignal(SceneSignal::LOBBYMENU); - } - if (optionsButton.MouseButtonUp(event) == Button::State::RELEASED) { - SetSceneSignal(SceneSignal::OPTIONSMENU); - } - if (quitButton.MouseButtonUp(event) == Button::State::RELEASED) { - QuitEvent(); - } -} - -void MainMenu::KeyDown(SDL_KeyboardEvent const& event) { - // -} - -void MainMenu::KeyUp(SDL_KeyboardEvent const& event) { - switch(event.keysym.sym) { - case SDLK_ESCAPE: - QuitEvent(); - break; - } -} diff --git a/client/menu_scenes/main_menu.hpp b/client/menu_scenes/main_menu.hpp deleted file mode 100644 index 272408c..0000000 --- a/client/menu_scenes/main_menu.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "base_scene.hpp" -#include "button.hpp" -#include "image.hpp" -#include "text_box.hpp" - -#include "SDL2/SDL_ttf.h" - -class MainMenu : public BaseScene { -public: - //Public access members - MainMenu(); - ~MainMenu(); - - void RenderFrame(SDL_Renderer* renderer) override; - -protected: - //frame phases - void FrameStart() override; - void Update() override; - void FrameEnd() override; - - //input events - void MouseMotion(SDL_MouseMotionEvent const& event) override; - void MouseButtonDown(SDL_MouseButtonEvent const& event) override; - void MouseButtonUp(SDL_MouseButtonEvent const& event) override; - void MouseWheel(SDL_MouseWheelEvent const& event) override; - void KeyDown(SDL_KeyboardEvent const& event) override; - void KeyUp(SDL_KeyboardEvent const& event) override; - - //members - Image buttonImage; - TTF_Font* font = nullptr; - Button startButton; - Button optionsButton; - Button quitButton; - TextBox textBox; -}; diff --git a/client/menu_scenes/makefile b/client/menu_scenes/makefile deleted file mode 100644 index f03de53..0000000 --- a/client/menu_scenes/makefile +++ /dev/null @@ -1,32 +0,0 @@ -#config -INCLUDES+=. .. ../client_utilities ../../common/graphics ../../common/map ../../common/network ../../common/network/packet_types ../../common/ui ../../common/utilities -LIBS+= -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=.. -OUT=$(addprefix $(OUTDIR)/,client.a) - -#targets -all: $(OBJ) $(OUT) - ar -crs $(OUT) $(OBJ) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/client/menu_scenes/options_menu.cpp b/client/menu_scenes/options_menu.cpp deleted file mode 100644 index 96863b3..0000000 --- a/client/menu_scenes/options_menu.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "options_menu.hpp" - -#include "config_utility.hpp" - -//------------------------- -//Public access members -//------------------------- - -OptionsMenu::OptionsMenu() { - ConfigUtility& config = ConfigUtility::GetSingleton(); - - //setup the utility objects - buttonImage.Load(GetRenderer(), config["dir.interface"] + "button.png"); - font = TTF_OpenFont(config["client.font"].c_str(), 12); - - //setup the button - backButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); - backButton.SetText(GetRenderer(), font, "Back", {255, 255, 255, 255}); - - //set the button positions - backButton.SetX(50); - backButton.SetY(50); - - //text line - textLine.SetText(GetRenderer(), font, "This code is fucking hard to refactor.", {255, 255, 255, 255}); -} - -OptionsMenu::~OptionsMenu() { - TTF_CloseFont(font); -} - -//------------------------- -//Frame loop -//------------------------- - -void OptionsMenu::FrameStart() { - // -} - -void OptionsMenu::Update() { - // -} - -void OptionsMenu::FrameEnd() { - // -} - -void OptionsMenu::RenderFrame(SDL_Renderer* renderer) { - backButton.DrawTo(renderer); - textLine.DrawTo(renderer, 50, 30); -} - -//------------------------- -//Event handlers -//------------------------- - -void OptionsMenu::MouseMotion(SDL_MouseMotionEvent const& event) { - backButton.MouseMotion(event); -} - -void OptionsMenu::MouseButtonDown(SDL_MouseButtonEvent const& event) { - backButton.MouseButtonDown(event); -} - -void OptionsMenu::MouseButtonUp(SDL_MouseButtonEvent const& event) { - if (backButton.MouseButtonUp(event) == Button::State::RELEASED) { - SetSceneSignal(SceneSignal::MAINMENU); - } -} - -void OptionsMenu::KeyDown(SDL_KeyboardEvent const& event) { - switch(event.keysym.sym) { - case SDLK_ESCAPE: - SetSceneSignal(SceneSignal::MAINMENU); - break; - } -} - -void OptionsMenu::KeyUp(SDL_KeyboardEvent const& event) { - // -} diff --git a/client/menu_scenes/options_menu.hpp b/client/menu_scenes/options_menu.hpp deleted file mode 100644 index 31507f6..0000000 --- a/client/menu_scenes/options_menu.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "button.hpp" -#include "image.hpp" -#include "text_line.hpp" - -#include "base_scene.hpp" - -//NOTE: The options screen needs to be USED -class OptionsMenu : public BaseScene { -public: - //Public access members - OptionsMenu(); - ~OptionsMenu(); - - void RenderFrame(SDL_Renderer* renderer) override; - -private: - //frame phases - void FrameStart() override; - void Update() override; - void FrameEnd() override; - - //input events - void MouseMotion(SDL_MouseMotionEvent const& event) override; - void MouseButtonDown(SDL_MouseButtonEvent const& event) override; - void MouseButtonUp(SDL_MouseButtonEvent const& event) override; - void MouseWheel(SDL_MouseWheelEvent const& event) override; - void KeyDown(SDL_KeyboardEvent const& event) override; - void KeyUp(SDL_KeyboardEvent const& event) override; - - //members - Image buttonImage; - TTF_Font* font = nullptr; - Button backButton; - TextLine textLine; -}; diff --git a/client/menu_scenes/splash_screen.cpp b/client/menu_scenes/splash_screen.cpp deleted file mode 100644 index 9fefd4a..0000000 --- a/client/menu_scenes/splash_screen.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "splash_screen.hpp" - -#include "config_utility.hpp" - -//------------------------- -//Public access members -//------------------------- - -SplashScreen::SplashScreen() { - logo.Load(GetRenderer(), ConfigUtility::GetSingleton()["dir.logos"] + "krstudios.png"); - startTick = std::chrono::steady_clock::now(); -} - -SplashScreen::~SplashScreen() { - // -} - -//------------------------- -//Frame loop -//------------------------- - -void SplashScreen::FrameStart() { - if (std::chrono::steady_clock::now() - startTick > std::chrono::duration(1)) { - SetSceneSignal(SceneSignal::MAINMENU); - } -} - -void SplashScreen::RenderFrame(SDL_Renderer* renderer) { - int w = 0, h = 0; - SDL_RenderGetLogicalSize(renderer, &w, &h); - logo.DrawTo(renderer, (w - logo.GetClipW()) / 2, (h - logo.GetClipH()) / 2); -} diff --git a/client/menu_scenes/splash_screen.hpp b/client/menu_scenes/splash_screen.hpp deleted file mode 100644 index 469c647..0000000 --- a/client/menu_scenes/splash_screen.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "base_scene.hpp" -#include "image.hpp" - -#include - -class SplashScreen : public BaseScene { -public: - //Public access members - SplashScreen(); - ~SplashScreen(); - - void RenderFrame(SDL_Renderer* renderer) override; - -private: - //Frame loop - void FrameStart() override; - - //members - std::chrono::steady_clock::time_point startTick; - Image logo; -}; diff --git a/client/scene_signal.hpp b/client/scene_signal.hpp deleted file mode 100644 index 2604ce4..0000000 --- a/client/scene_signal.hpp +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -enum SceneSignal { - //reserved members for internal use - QUIT = -1, - CONTINUE = 0, - FIRST = 1, - - //custom scenes - SPLASHSCREEN, - MAINMENU, - OPTIONSMENU, - LOBBYMENU, - WORLD, - DISCONNECTEDSCREEN, -}; \ No newline at end of file diff --git a/common/graphics/makefile b/common/graphics/makefile deleted file mode 100644 index 0d2afc1..0000000 --- a/common/graphics/makefile +++ /dev/null @@ -1,32 +0,0 @@ -#config -INCLUDES+=. ../map -LIBS+= -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=../.. -OUT=$(addprefix $(OUTDIR)/,libcommon.a) - -#targets -all: $(OBJ) $(OUT) - ar -crs $(OUT) $(OBJ) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/common/makefile b/common/makefile deleted file mode 100644 index dcfef9b..0000000 --- a/common/makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: - $(MAKE) -C debugging - $(MAKE) -C gameplay - $(MAKE) -C graphics - $(MAKE) -C map - $(MAKE) -C network - $(MAKE) -C utilities diff --git a/copyright.txt b/copyright.txt deleted file mode 100644 index 964147d..0000000 --- a/copyright.txt +++ /dev/null @@ -1,15 +0,0 @@ -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-2015 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/client/client_utilities/makefile b/debugging/makefile similarity index 87% rename from client/client_utilities/makefile rename to debugging/makefile index 803bbcf..e6bcb85 100644 --- a/client/client_utilities/makefile +++ b/debugging/makefile @@ -10,10 +10,6 @@ CXXSRC=$(wildcard *.cpp) OBJDIR=obj OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) -#output -OUTDIR=.. -OUT=$(addprefix $(OUTDIR)/,client.a) - #targets all: $(OBJ) $(OUT) ar -crs $(OUT) $(OBJ) diff --git a/common/debugging/timer.cpp b/debugging/timer.cpp similarity index 100% rename from common/debugging/timer.cpp rename to debugging/timer.cpp diff --git a/common/debugging/timer.hpp b/debugging/timer.hpp similarity index 100% rename from common/debugging/timer.hpp rename to debugging/timer.hpp diff --git a/common/gameplay/character_defines.hpp b/gameplay/character_defines.hpp similarity index 100% rename from common/gameplay/character_defines.hpp rename to gameplay/character_defines.hpp diff --git a/common/utilities/makefile b/gameplay/makefile similarity index 86% rename from common/utilities/makefile rename to gameplay/makefile index 104b518..e6bcb85 100644 --- a/common/utilities/makefile +++ b/gameplay/makefile @@ -10,10 +10,6 @@ CXXSRC=$(wildcard *.cpp) OBJDIR=obj OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) -#output -OUTDIR=../.. -OUT=$(addprefix $(OUTDIR)/,libcommon.a) - #targets all: $(OBJ) $(OUT) ar -crs $(OUT) $(OBJ) diff --git a/common/graphics/button.cpp b/graphics/button.cpp similarity index 100% rename from common/graphics/button.cpp rename to graphics/button.cpp diff --git a/common/graphics/button.hpp b/graphics/button.hpp similarity index 100% rename from common/graphics/button.hpp rename to graphics/button.hpp diff --git a/common/graphics/image.cpp b/graphics/image.cpp similarity index 100% rename from common/graphics/image.cpp rename to graphics/image.cpp diff --git a/common/graphics/image.hpp b/graphics/image.hpp similarity index 100% rename from common/graphics/image.hpp rename to graphics/image.hpp diff --git a/common/debugging/makefile b/graphics/makefile similarity index 86% rename from common/debugging/makefile rename to graphics/makefile index 104b518..e6bcb85 100644 --- a/common/debugging/makefile +++ b/graphics/makefile @@ -10,10 +10,6 @@ CXXSRC=$(wildcard *.cpp) OBJDIR=obj OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) -#output -OUTDIR=../.. -OUT=$(addprefix $(OUTDIR)/,libcommon.a) - #targets all: $(OBJ) $(OUT) ar -crs $(OUT) $(OBJ) diff --git a/common/graphics/sprite_sheet.cpp b/graphics/sprite_sheet.cpp similarity index 100% rename from common/graphics/sprite_sheet.cpp rename to graphics/sprite_sheet.cpp diff --git a/common/graphics/sprite_sheet.hpp b/graphics/sprite_sheet.hpp similarity index 100% rename from common/graphics/sprite_sheet.hpp rename to graphics/sprite_sheet.hpp diff --git a/common/graphics/text_box.cpp b/graphics/text_box.cpp similarity index 100% rename from common/graphics/text_box.cpp rename to graphics/text_box.cpp diff --git a/common/graphics/text_box.hpp b/graphics/text_box.hpp similarity index 100% rename from common/graphics/text_box.hpp rename to graphics/text_box.hpp diff --git a/common/graphics/text_line.cpp b/graphics/text_line.cpp similarity index 100% rename from common/graphics/text_line.cpp rename to graphics/text_line.cpp diff --git a/common/graphics/text_line.hpp b/graphics/text_line.hpp similarity index 100% rename from common/graphics/text_line.hpp rename to graphics/text_line.hpp diff --git a/instructions.txt b/instructions.txt deleted file mode 100644 index 85fcaf9..0000000 --- a/instructions.txt +++ /dev/null @@ -1,35 +0,0 @@ -This is the README for Tortuga's demo build. The source code is available at: - - https://github.com/Ratstail91/Tortuga - -The current build may have bugs, missing features, bugs masquerading as -features, etc. You can report a bug/feature here: - - https://github.com/Ratstail91/Tortuga/issues - -Please note that this game requires a functioning server to operate correctly. -Both a game server and game client are included in this package. - -------------------------- -Instructions For Setup -------------------------- - -1. To create a server, simply run server.exe - (a public server is provided by default) -2. To join a server, your player information must be input into rsc/config.cfg - (NOTE: This process will be streamlined later) -3. To change the config settings, open rsc/config.cfg -4. These settings must be unique for each player: - -* client.username -* client.handle - -5. There are currently two options for 'client.avatar': - -* client.avatar = elliot2.bmp #male -* client.avatar = coa2.bmp #female - -6. When you've correctly set these values, run client.exe, and select 'Start' - from the main menu; this displays the list of available servers. -7. Select the name of a server (default is 'Public') and select 'Join'. -8. Welcome to Tortuga, enjoy your stay. diff --git a/makefile b/makefile index efa122e..c5ac867 100644 --- a/makefile +++ b/makefile @@ -1,31 +1,19 @@ -#Windows 7: -#RM=del /y - -#Windows 8.1: -#RM=del /S - -OUTDIR=out +#output +export OUTDIR=.. +export OUT=$(addprefix $(OUTDIR)/,libcommon.a) all: $(OUTDIR) - $(MAKE) -C common -# $(MAKE) -C server - $(MAKE) -C client + $(MAKE) -C debugging + $(MAKE) -C gameplay + $(MAKE) -C graphics + $(MAKE) -C map + $(MAKE) -C network + $(MAKE) -C ui + $(MAKE) -C utilities debug: export CXXFLAGS+=-g debug: clean all -release: export CXXFLAGS+=-static-libgcc -static-libstdc++ -release: clean all package - -#For use on my machine ONLY -package: -ifeq ($(OS),Windows_NT) - rar a -r -ep Tortuga-win.rar $(OUTDIR)/*.exe $(OUTDIR)/*.dll - rar a -r Tortuga-win.rar rsc/* copyright.txt instructions.txt -else ifeq ($(shell uname), Linux) - tar -C $(OUTDIR) -zcvf Tortuga-linux.tar client server ../rsc ../copyright.txt ../instructions.txt -endif - $(OUTDIR): mkdir $(OUTDIR) @@ -33,9 +21,9 @@ clean: ifeq ($(OS),Windows_NT) $(RM) *.o *.a *.exe else ifeq ($(shell uname), Linux) - find . -type f -name '*.o' -exec rm -f -r -v {} \; - find . -type f -name '*.a' -exec rm -f -r -v {} \; - rm -f -v $(OUT) + find . -type f -name *.o -exec rm -f -r -v {} \; + find . -type f -name *.a -exec rm -f -r -v {} \; + rm -f -v out/client out/server endif rebuild: clean all diff --git a/common/map/makefile b/map/makefile similarity index 86% rename from common/map/makefile rename to map/makefile index 03a0db8..7e6b897 100644 --- a/common/map/makefile +++ b/map/makefile @@ -10,10 +10,6 @@ CXXSRC=$(wildcard *.cpp) OBJDIR=obj OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) -#output -OUTDIR=../.. -OUT=$(addprefix $(OUTDIR)/,libcommon.a) - #targets all: $(OBJ) $(OUT) ar -crs $(OUT) $(OBJ) diff --git a/common/map/region.cpp b/map/region.cpp similarity index 100% rename from common/map/region.cpp rename to map/region.cpp diff --git a/common/map/region.hpp b/map/region.hpp similarity index 100% rename from common/map/region.hpp rename to map/region.hpp diff --git a/common/map/region_api.cpp b/map/region_api.cpp similarity index 100% rename from common/map/region_api.cpp rename to map/region_api.cpp diff --git a/common/map/region_api.hpp b/map/region_api.hpp similarity index 100% rename from common/map/region_api.hpp rename to map/region_api.hpp diff --git a/common/map/region_pager_api.cpp b/map/region_pager_api.cpp similarity index 100% rename from common/map/region_pager_api.cpp rename to map/region_pager_api.cpp diff --git a/common/map/region_pager_api.hpp b/map/region_pager_api.hpp similarity index 100% rename from common/map/region_pager_api.hpp rename to map/region_pager_api.hpp diff --git a/common/map/region_pager_base.cpp b/map/region_pager_base.cpp similarity index 100% rename from common/map/region_pager_base.cpp rename to map/region_pager_base.cpp diff --git a/common/map/region_pager_base.hpp b/map/region_pager_base.hpp similarity index 100% rename from common/map/region_pager_base.hpp rename to map/region_pager_base.hpp diff --git a/common/map/region_pager_lua.cpp b/map/region_pager_lua.cpp similarity index 100% rename from common/map/region_pager_lua.cpp rename to map/region_pager_lua.cpp diff --git a/common/map/region_pager_lua.hpp b/map/region_pager_lua.hpp similarity index 100% rename from common/map/region_pager_lua.hpp rename to map/region_pager_lua.hpp diff --git a/common/map/tile_sheet.cpp b/map/tile_sheet.cpp similarity index 100% rename from common/map/tile_sheet.cpp rename to map/tile_sheet.cpp diff --git a/common/map/tile_sheet.hpp b/map/tile_sheet.hpp similarity index 100% rename from common/map/tile_sheet.hpp rename to map/tile_sheet.hpp diff --git a/common/network/makefile b/network/makefile similarity index 87% rename from common/network/makefile rename to network/makefile index f1d2063..3bcac3d 100644 --- a/common/network/makefile +++ b/network/makefile @@ -10,10 +10,6 @@ CXXSRC=$(wildcard *.cpp) OBJDIR=obj OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) -#output -OUTDIR=../.. -OUT=$(addprefix $(OUTDIR)/,libcommon.a) - #targets all: $(OBJ) $(OUT) ar -crs $(OUT) $(OBJ) diff --git a/common/network/packet_types/character_packet.cpp b/network/packet_types/character_packet.cpp similarity index 100% rename from common/network/packet_types/character_packet.cpp rename to network/packet_types/character_packet.cpp diff --git a/common/network/packet_types/character_packet.hpp b/network/packet_types/character_packet.hpp similarity index 100% rename from common/network/packet_types/character_packet.hpp rename to network/packet_types/character_packet.hpp diff --git a/common/network/packet_types/client_packet.cpp b/network/packet_types/client_packet.cpp similarity index 100% rename from common/network/packet_types/client_packet.cpp rename to network/packet_types/client_packet.cpp diff --git a/common/network/packet_types/client_packet.hpp b/network/packet_types/client_packet.hpp similarity index 100% rename from common/network/packet_types/client_packet.hpp rename to network/packet_types/client_packet.hpp diff --git a/common/network/packet_types/makefile b/network/packet_types/makefile similarity index 88% rename from common/network/packet_types/makefile rename to network/packet_types/makefile index 241fc55..3526e73 100644 --- a/common/network/packet_types/makefile +++ b/network/packet_types/makefile @@ -11,8 +11,8 @@ OBJDIR=obj OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) #output -OUTDIR=../../.. -OUT=$(addprefix $(OUTDIR)/,libcommon.a) +OUTDIR=../$(OUTDIR) +OUT=../$(OUT) #targets all: $(OBJ) $(OUT) diff --git a/common/network/packet_types/monster_packet.cpp b/network/packet_types/monster_packet.cpp similarity index 100% rename from common/network/packet_types/monster_packet.cpp rename to network/packet_types/monster_packet.cpp diff --git a/common/network/packet_types/monster_packet.hpp b/network/packet_types/monster_packet.hpp similarity index 100% rename from common/network/packet_types/monster_packet.hpp rename to network/packet_types/monster_packet.hpp diff --git a/common/network/packet_types/region_packet.cpp b/network/packet_types/region_packet.cpp similarity index 100% rename from common/network/packet_types/region_packet.cpp rename to network/packet_types/region_packet.cpp diff --git a/common/network/packet_types/region_packet.hpp b/network/packet_types/region_packet.hpp similarity index 100% rename from common/network/packet_types/region_packet.hpp rename to network/packet_types/region_packet.hpp diff --git a/common/network/packet_types/serial_packet_base.cpp b/network/packet_types/serial_packet_base.cpp similarity index 100% rename from common/network/packet_types/serial_packet_base.cpp rename to network/packet_types/serial_packet_base.cpp diff --git a/common/network/packet_types/serial_packet_base.hpp b/network/packet_types/serial_packet_base.hpp similarity index 100% rename from common/network/packet_types/serial_packet_base.hpp rename to network/packet_types/serial_packet_base.hpp diff --git a/common/network/packet_types/server_packet.cpp b/network/packet_types/server_packet.cpp similarity index 100% rename from common/network/packet_types/server_packet.cpp rename to network/packet_types/server_packet.cpp diff --git a/common/network/packet_types/server_packet.hpp b/network/packet_types/server_packet.hpp similarity index 100% rename from common/network/packet_types/server_packet.hpp rename to network/packet_types/server_packet.hpp diff --git a/common/network/packet_types/text_packet.cpp b/network/packet_types/text_packet.cpp similarity index 100% rename from common/network/packet_types/text_packet.cpp rename to network/packet_types/text_packet.cpp diff --git a/common/network/packet_types/text_packet.hpp b/network/packet_types/text_packet.hpp similarity index 100% rename from common/network/packet_types/text_packet.hpp rename to network/packet_types/text_packet.hpp diff --git a/common/network/serial_packet.hpp b/network/serial_packet.hpp similarity index 100% rename from common/network/serial_packet.hpp rename to network/serial_packet.hpp diff --git a/common/network/serial_packet_type.hpp b/network/serial_packet_type.hpp similarity index 100% rename from common/network/serial_packet_type.hpp rename to network/serial_packet_type.hpp diff --git a/common/network/serial_utility.cpp b/network/serial_utility.cpp similarity index 100% rename from common/network/serial_utility.cpp rename to network/serial_utility.cpp diff --git a/common/network/serial_utility.hpp b/network/serial_utility.hpp similarity index 100% rename from common/network/serial_utility.hpp rename to network/serial_utility.hpp diff --git a/common/network/udp_network_utility.cpp b/network/udp_network_utility.cpp similarity index 100% rename from common/network/udp_network_utility.cpp rename to network/udp_network_utility.cpp diff --git a/common/network/udp_network_utility.hpp b/network/udp_network_utility.hpp similarity index 100% rename from common/network/udp_network_utility.hpp rename to network/udp_network_utility.hpp diff --git a/rsc/config.cfg b/rsc/config.cfg deleted file mode 100644 index cf72bdc..0000000 --- a/rsc/config.cfg +++ /dev/null @@ -1,33 +0,0 @@ -#configuration of the programs - -#server specific settings -server.host = 255.255.255.255 -server.port = 21795 -server.name = local - -server.dbname = database.db - -#client specific settings -#client.screen.w = 800 -#client.screen.h = 600 -client.screen.f = false - -#TODO: change this based on platform? -client.font = /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf - -client.username = username -client.handle = handle -client.avatar = elliot2.bmp - -#directories -dir.logos = rsc/graphics/logos/ -dir.sprites = rsc/graphics/sprites/ -dir.tilesets = rsc/graphics/tilesets/ -dir.interface = rsc/graphics/interface/ -dir.scripts = rsc/scripts/ -dir.maps = rsc/maps/ - -#map system -map.savename = servermap - -#debugging diff --git a/rsc/graphics/interface/button.png b/rsc/graphics/interface/button.png deleted file mode 100644 index 867cd63df639db0c8892a31e6c2310820e652b01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 321 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 d(P<^j^+PS=>> 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 diff --git a/rsc/graphics/sprites/aniflower.bmp b/rsc/graphics/sprites/aniflower.bmp deleted file mode 100644 index fbc60f5b7c5737f2298f382ee800121b05e7d153..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12342 zcmeH}Jx&}!5QT@>nI$AbhXe#f$T4zii4*u9NDiF(Dg?x&z5o{>aqi5qCH#6`^R`qo zwAk({%R!^rR?p9V_4=#c5!auuE|>N13gbCG-|+c>&&hIz5r4S<{vAKOuq@BZ^E{@3 zX)zcv^7(|*6xPhuB@5ea_^Lj8hALJIy`08#@ZlTB-R}f_{E{{f)!A zLUp&~qfTG*!xH~9+?laXG#||GN>IMWaYatP>+B%k!9m;d2mQDbTRw_Lm5_Ej2~@Pj zj=-%MOXi&9Ksi9!D&j|#ApFOEX zbXWTPGoHeuxtfd5XZRXCb`*_dqA+q7vBV&sUneR&Ki0eD^9n|%2v<7%kb~q_5y&Bm z1mC80;g3zu=Yds;jQsRZ8{#uLOFK&)s~|@Uv2fPK$h#eI=Ev8G)rc!hK0;<55;$5u zuHZDJ%5Dk3bzN2Z6w#7xB^M$-Cf(#+cobQw0L;s8tFWh5xYnY_`X*e0R)Nz#&hEFY w9|qoiY~*5Ueg$Lryd{XQicu4hF^OV2&Oa#OD$dhsU>cYPrh#c-8W=S27YPS~bpQYW diff --git a/rsc/graphics/sprites/coa2.bmp b/rsc/graphics/sprites/coa2.bmp deleted file mode 100644 index bd7b3c0e68a27ce935b84bbda7a7f184e1556bcc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73782 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 Ia)1u}4>E?7uK)l5 diff --git a/rsc/graphics/sprites/elliot2.bmp b/rsc/graphics/sprites/elliot2.bmp deleted file mode 100644 index 89f66d82713f3ed60315c0f8ff1538aee2a954fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73782 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 L|0}`xwr%_m)tPtO diff --git a/rsc/graphics/sprites/skume1.bmp b/rsc/graphics/sprites/skume1.bmp deleted file mode 100644 index ae31c9a93d317d48da9e4db084b65cf505efef27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1041 zcmV+s1n&EZP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!Tzd z+%OP?&n_cCUeZ9GQbhu!l2nsQ0>oA1DGlT$K-#!?gd2lLOCtA=q)dIrK_}}h?d%L! zXFXgm*X!kES{`rPlSv7k01wYUYdl|b+46Y4pTpxP{)7bpWysqFrSPV0-kEl@N8Y63vK#7hGeJq1du-`jMF zevS6(2~aX0r0>0^fwZALr+~NlAmW@UrvC!=isLbl5R5|21nj9-6aK0Il*V34+6-%B zw13xQ3Z#ocQ}Y&{=USuq9iWu@Em(Nzb2*-ZJ--js_93rds(%e>Pb9i`1E4jZ)P%s( z@HIR_Anik{JJlx*gQYjMy2SzT7O{3d&rnzc@YW~bW&o_KUyGyxs0E+rb_;C?W|)Ah z0cdHywgIJD^7Cp!FvA4w8h|MCfi(cLOu$zGXdzr{Jdo6(4Z%zk@a{RlmT(VH5MLS~ zSZYB2d1!;iQHU~Mg6Tew2Gdp)q$ z(rXdq*UhyTCjc%ixi~I3viYs?=!Zuywpb>BHTm9+Zef1D5@wx%rT};w4_cTH?wT<1 z0#F4Y!g!z&uC2u*01f^o&Z2n)Ck7!8CN?2h_=2F`mly50A#PBWE8rjwd_{(SwpY-e5o#Row(NCZb44{FU{o`e~-lTl13wLNeN zKo6u1&tU+-%=(uA;1?q{!76f#)O<3l{+9rN7EOo}Rm+3Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!TuM~%UPOti)y8?Iwz%@U9Z>LxDJl_0Fuk5|dA=T`n0GLFwi$4e0B1@H@(7FgTI2NFG0cc)L`@#kE7{Kep*V)m6=lsXFfi(ug;H698 zZ%LM30I=4l{lxaNmiagP2&la~Y2c;HDV=}s(LMl8Xj|YJ0M~APG}I!Q9|??B1%Q#% z66iLhS;Eo)v~Iz%W#_`TdIU)4H!DDi5sdP+5vzP4=LRe zO`=AdqdC8N0l2x+76Q)zz<UO2+shB&_hVf z6W0o<)wZ7hq5y<;5hOw60;r)h00JIBs}JY`srFLyM+;y{Nf@31aL5NI=83d8t-99p zp9%n$C_zd1oVfrb)CRzT2b_n0pCkMkE$tR^9?l8?S_N}xEai$8!|(?ayKlwY1Qh20 O0000 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%0DwdVH2=sO-&PizB~XdGF(nI5?7>rf&4+)9 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 diff --git a/rsc/graphics/tilesets/blank.bmp b/rsc/graphics/tilesets/blank.bmp deleted file mode 100644 index 44b11c7863f0547b40c1550c7442547b48baa404..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 786486 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 zw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(L zXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuR zz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+! z>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_Uyp zFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~ zUT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870 zdcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw z!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3 zLoc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN z(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNny zoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xv zw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(L zXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuR zz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+! z>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_Uyp zFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~ zUT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870 zdcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw z!RwuRz0+Q3LofVagJ0L_^y_+|4cqSv_z#VN(_UypFSNnyoqD~~ zUT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870 zdcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw z!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3 zLoc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN z(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNny zoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xv zw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(L zXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuR zz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+! z>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_Uyp zFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~ zUT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870 zdcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw z!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3 zLoc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN z(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNny zoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xv zw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(L 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 zuXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZ zz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{ zd!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w} z>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz z2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C z4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8 zPJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d}) zck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0 zp$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO z^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9? zuXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZ zz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{ zd!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w} z>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz z2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C z4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8 zPJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d}) 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 z^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;) z7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~ zFSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0 zz20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ; z;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIs zX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+U zPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ- z+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20dr zw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV z^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;) z7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~ zFSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0 zz20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ; z;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIs zX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+U zPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ- z+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20dr zw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV z^-jIsX)m;)7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;) z7uw+UPQBh~FSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+UPQBh~ zFSMZ-+Tit0z20drw4oQ;;PpcV^-jIsX)m;)7uw+U^Qm9g>GTD9p$*&b z3;24SdcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(L zXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuR zz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+! z>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_Uyp zFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~ zUT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870 zdcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw z!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3 zLoc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN z(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNny zoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xv zw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(L zXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuR zz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+! z>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_Uyp zFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~ zUT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870 zdcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw z!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3 zLoc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN z(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNny zoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xv zw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(L zXhScw!RwuRz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuR zz0+Q3Loc+!>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+! z>z#VN(_UypFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>z#VN(_Uyp zFSNnyoqD~~UT8xvw8870dcD(LXhScw!RwuRz0+Q3Loc+!>*rIyuG8rY^g27wCmHY`-ty>vih& zPJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d}) zck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0 zp$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO z^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9? zuXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZ zz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{ zd!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w} z>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz z2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C z4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8 zPJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d}) zck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0 zp$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO z^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9? zuXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZ zz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{ zd!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w} z>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz z2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C z4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8 zPJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d}) zck1;{d!Y@z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z z&<3w}>h(^0p$)yz2CsMO^-g=C4ZY9?uXpP8PJ5vZz0d})ck1;{d!Y@z&<3w}>h(^0 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 zc)e4vciIbW=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxDZRmwIc)e4vciIbW z=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxDZRmwIc)e4vciIbW=!G_Ty;HAu z+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxDZRmwIc)e4vciIbW=!G_Ty;HAu+6!&yg*JG- zQ?Ga03vK9yHh8^LuXoxDZRmwIc)e4vciIbW=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9y zHh8^LuXoxDZRmwIc)e4vciIbW=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxD zZRmwIc)e4vciIbW=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxDZRmwIc)e4v zciIbW=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxDZRmwIc)e4vciIbW=!G_T zy;HAu+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxDZRmwIc)e4vciIbW=!G_Ty;HAu+6!&y zg*JG-Q?Ga03vK9yHh8^LuXoxDZRmwIc)e4vciIbW=!G_Ty;HAu+6!&yg*JG-Q?Ga0 z3vK9yHh8^LuXoxDZRmwIc)e4vciIbW=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9yHh8^L zuXoxDZRmwIc)e4vciIbW=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxDZRmwI zc)e4vciIbW=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxDZRmwIc)e4vciIbW z=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxDZRmwIc)e4vciIbW=!G_Ty;HAu z+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxDZRmwIc)e4vciIbW=!G_Ty;HAu+6!&yg*JG- zQ?Ga03vK9yHh8^LuXoxDZRmwIc)e4vciIbW=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9y zHh8^LuXoxDZRmwIc)e4vciIbW=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxD zZRmwIc)e4vciIbW=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxDZRmwIc)e4v zciIbW=!G_Ty;HAu+6!&yg*JG-Q?Ga03vK9yHh8^LuXoxDZRmwIc)e4vciIbW=!G_T cy;HAu+6!&yg*JG-Q?Ga03vK9yHh8_$A9ZJRF8}}l diff --git a/rsc/graphics/tilesets/dirt.bmp b/rsc/graphics/tilesets/dirt.bmp deleted file mode 100644 index 089ba2aed69991bf3ee8f86a2552aa4c6742f41c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 110646 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ǀ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 Kesj_9;Qs^UF5@i# diff --git a/rsc/graphics/tilesets/grass.bmp b/rsc/graphics/tilesets/grass.bmp deleted file mode 100644 index ac8c6e46e6e7dee769c2157f08930fbf94632706..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 110646 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 DiPYCg!c7uMGFa2b2*n4zmu{ES`b< zTMUzbVErd#9m>Z~_e-0W9;=}#)Q|^dJVZnM%i$+|G+axclD|A;t;}ZW>F2i!K3t!) z%W(X8^_iG=hOLbB^=Ebz{|>!4HCF$KESn1CMB0cU$JET`>;WA%^7 zvIQ<3VtqP0GBiu8vD1oqNsN&Vpw}{Vu+i}AZI74W@sb!Ln}rT$=wPGa*V`U1*~E_$ z&A=BElbL}Z`D2gLr$m-VXBmYrHT0xihU3rEKQZ4N>aZv3^E&@cVliN>{t;O=XKB@s zX1O4QNvqD~CD`$bw7nL7lxRhLB7f{r`j^P^NTN~rDwuMMvG}gZ8TDC`-}IP|j`^DV zwMi)jjMcvi&K4-3w;p6sT_t^(^;@%aB$ha*(Jv6q@{YkcZ-^fyGV?|Ga~7ZCqW)1C z+hg-Y0mqN*Vq4kZbXjNKkcr{A>J<(ncKS~67 zy%*9a@|QhO|AfqNAim0`++r*~X!Gi`=Ot^1`11)Lq6 zd-P$6(J;JF!-eppL_X1?{B;(xFob_p#`Z$^&gQ)Ov@C}V_;mV@0(emS9REX<96T_; zqHS1=crKNw_R=FAd_XygVG1&(hgGS4rQlWYqeLs}6Zy+_vaai&kQpw7|AP9gO0?;e zhA+5Zn>4Bc1M@5W(-!jR;rOagO4J@Su{ao-#qap!cf7(@#E%lK&R=J7Hk~hfPUJU= zgKf0y_$Byo{yOs1`m7#dkJH4YCwZ}+L+;le4%L`}`PI477CM^oH5-rYG(|(f=o2H6 zt9*mJ9DbB&MSUWF*<CM17%*IPwQOCuVeQ0 zIn6(9baXgS|Fm^X1h!HvLp!o5n#f~iWXCd)-yW}(Cq5~~nz}Q7l!#NT%U@^F5eD*) z;@BRAZ@^@X!hb=1Cgw+n)Z5tmb(BLHKT!V!p6(YtCsu6iKLlGM43>~t-jOXa_S_#o z>7${J@ZlfxTS_!apAs3*DEt@HXX^<2{bTRf{(U=<1NBe4=&!@&VI>?fEZYmF(VZ5c7zdn~8%BDC7S4 zr9>b8DZiyel)?4!bI;lWELDl;naH}{Hi{3`cOC5r^jMZo87wf;ZMa)awf_5Y9aQupNcpI>K1LRMkWO9E-dM zZFqjmP1!9|M0WiP3MZKIC!FfgtHfE$8DdxCe@bW6 z4ZHM|`Y5K<|ByapioFv4ejH~oqMhSk-E=m7b<>MZao$<~7dPrJj~O|g-~JY#*`GiG z-&Pf^uN&aY{{ghSGLZlP diff --git a/rsc/graphics/tilesets/overworld.bmp b/rsc/graphics/tilesets/overworld.bmp deleted file mode 100644 index d9cc0c6ebab8853254282098d12c584fdd467a29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 786486 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 zdZ(^;+85f;7uw)@r>=L}7uwJl+TePpu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^;+85f; z7uw)@r>=L}7uwJl+TePpu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^;+85f;7uw)@r>=L} z7uwJl+TePpu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^;+85f;7uw)@r>=L}7uwJl+TePp zu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^;+85f;7uw)@r>=L}7uwJl+TePpu6NoO+Rzu; z;CiR7ciI=)&==a^dZ(^;+85f;7uw)@r>=L}7uwJl+TePpu6NoO+Rzu;;CiR7ciI=) z&==a^dZ(^;+85f;7uw)@r>=L}7uwJl+TePpu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^; z+85f;7uw)@r>=L}7uwJl+TePpu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^;+85f;7uw)@ zr>=L}7uwJl+TePpu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^;+85f;7uw)@r>=L}7uwJl z+TePpu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^;+85f;7uw)@r>=L}7uwJl+TePpu6NoO z+Rzu;;CiR7ciI=)&==a^dZ(^;+85f;7uw)@r>=L}7uwJl+TePpu6NoO+Rzu;;CiR7 zciI=)&==a^dZ(^;+85f;7uw)@r>=L}7uwJl+TePpu6NoO+Rzu;;CiR7ciI=)&==a^ zdZ(^;+85f;7uw)@r>=L}7uwJl+TePpu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^;+85f; z7uw)@r>=L}7uwJl+TePpu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^;+85f;7uw)@r>=L} z7uwJl+TePpu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^;+85f;7uw)@r>=L}7uwJl+TePp zu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^;+85f;7uw)@r>=L}7uwJl+TePpu6NoO+Rzu; z;CiR7ciI=)&==a^dZ(^;+85f;7uw)@r>=L}7uwJl+TePpu6NoO+Rzu;;CiR7ciI=) z&==a^dZ(^;+85f;7uw)@r>=L}7uwJl+TePpu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^; z+85f;7uw)@r>=L}7uwJl+TePpu6NoO+Rzu;;CiR7ciI=)&==a^dZ(^;+85f;7uw)@ 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 zPF?S`FSMaAw88aGUGKCnw4pDw!SzmE@3b$pp)a(-^-f*yv@f)wFSNn+PF?S`FSMaA zw88aGUGKCnw4pDw!SzmE@3b$pp)a(-^-f*yv@f)wFSNn+PF?S`FSMaAw88aGUGKCn zw4pDw!SzmE@3b$pp)a(-^-f*yv@f)wFSNn+PF?S`FSMaAw88aGUGKCnw4pDw!SzmE z@3b$pp)a(-^-f*yv@f)wFSNn+PF?S`FSMaAw88aGUGKCnw4pDw!SzmE@3b$pp)a(- z^-f*yv@f)wFSNn+PF?S`FSMaAw88aGUGKCnw4pDw!SzmE@3b$pp)a(-^-f*yv@f)w zFSNn+PF?S`FSMaAw88aGUGKCnw4pDw!SzmE@3b$pp)a(-^-f*yv@f)wFSNn+PF?S` zFSMaAw88aGUGKCnw4pDw!SzmE@3b$pp)a(-^-f*yv@f)wFSNn+PF?S`FSMaAw88aG zUGKCnw4pDw!SzmE@3b$pp)a(-^-f*yv@f)wFSNn+PF?S`FSMaAw88aGUGKCnw4pDw z!SzmE@3b$pp)a(-^-f*yv@f)wFSNn+PF?S`FSMaAw88aGUGKCnw4pDw!SzmE@3b$p zp)a(-^-f*yv@f)wFSNn+PF?S`FSMaAw88aGUGKCnw4pDw!SzmE@3b$pp)a(-^-f*y zv@f)wFSNn+PF?S`FSMaAw88aGUGKCnw4pDw!SzmE@3b$pp)a(-^-f*yv@f)wFSNn+ zPF?S`FSMaAw88aGUGKCnw4pDw!SzmE@3b$pp)a(-^-f*yv@f)wFSNn+PF?S`FSMaA zw88aGUGKCnw4pDw!SzmE@3b$pp)a(-^-f*yv@f)wFSNn+PF?S`FSMaAw88aGUGKCn zw4pDw!SzmE@3b$pp)a(-^-f*yv@f)wFSNn+PF?S`FSMaAw88aGUGKCnw4pDw!SzmE z@3b$pp)a(-^-f*yv@f)wFSNn+PF?S`FSMaAw88aGUGKCnw4pDw!SzmE@3b$pp)a(- z^-f*yv@f)wFSNn+PF?S`FSMaAw88aGUGKCnw4pDw!SzmE@3b$pp)a(-^-f*yv@f)w zFSNn+PF?S`FSMaAw88aGUGKCnw4pDw!SzmE@3b$pp)a(-^-f*yv@f)wFSNn+PF?S` zFSMaAw88aGUGKCnw4pDw!SzmE@3b$pp)a(-^-f*yv@f)wFSNn+PF?S`FSMaAw88aG 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 zy;Ija?F((_3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija?F((_ z3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija?F((_3vF<{Q`bA~ z3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija?F((_3vF<{Q`bA~3vK8NZE(F) z*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija?F((_3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVa zaJ^I4JM9Z?=nHLdy;Ija?F((_3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z? z=nHLdy;Ija?F((_3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija z?F((_3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija?F((_3vF<{ zQ`bA~3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija?F((_3vF<{Q`bA~3vK8N zZE(F)*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija?F((_3vF<{Q`bA~3vK8NZE(F)*E{VC zZRiVaaJ^I4JM9Z?=nHLdy;Ija?F((_3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVaaJ^I4 zJM9Z?=nHLdy;Ija?F((_3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z?=nHLd zy;Ija?F((_3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija?F((_ z3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija?F((_3vF<{Q`bA~ z3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija?F((_3vF<{Q`bA~3vK8NZE(F) z*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija?F((_3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVa zaJ^I4JM9Z?=nHLdy;Ija?F((_3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z? z=nHLdy;Ija?F((_3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija z?F((_3vF<{Q`bA~3vK8NZE(F)*E{VCZRiVaaJ^I4JM9Z?=nHLdy;Ija?F((_3vF<{ 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 z>z($6HuQxyxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6HuQxy zxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6HuQxyxZbJjo%V$` z^o2IK-l^-I_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6HuQxyxZbJjo%V$`^o2IK-l^-I z_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6HuQxyxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld} zsq3Bgg*NnsHn`rY>z($6HuQxyxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld}sq3Bgg*Nns zHn`rY>z($6HuQxyxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6 zHuQxyxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6HuQxyxZbJj zo%V$`^o2IK-l^-I_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6HuQxyxZbJjo%V$`^o2IK z-l^-I_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6HuQxyxZbJjo%V$`^o2IK-l^-I_Jua| zg*Ld}sq3Bgg*NnsHn`rY>z($6HuQxyxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld}sq3Bg zg*NnsHn`rY>z($6HuQxyxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld}sq3Bgg*NnsHn`rY z>z($6HuQxyxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6HuQxy zxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6HuQxyxZbJjo%V$` z^o2IK-l^-I_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6HuQxyxZbJjo%V$`^o2IK-l^-I z_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6HuQxyxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld} zsq3Bgg*NnsHn`rY>z($6HuQxyxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld}sq3Bgg*Nns zHn`rY>z($6HuQxyxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6 zHuQxyxZbJjo%V$`^o2IK-l^-I_Jua|g*Ld}sq3Bgg*NnsHn`rY>z($6HuQxyxZbJj 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 z>UyVrp$&bZ4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Amcj|hleW49~p$)Eg>UyVrp$&bZ z4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Amcj|hleW49~p$)Eg>UyVrp$&bZ4X$_UdZ&G% z4Sk^vu6OEsr+uLfeW4Amcj|hleW49~p$)Eg>UyVrp$&bZ4X$_UdZ&G%4Sk^vu6OEs zr+uLfeW4Amcj|hleW49~p$)Eg>UyVrp$&bZ4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Am zcj|hleW49~p$)Eg>UyVrp$&bZ4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Amcj|hleW49~ zp$)Eg>UyVrp$&bZ4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Amcj|hleW49~p$)Eg>UyVr zp$&bZ4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Amcj|hleW49~p$)Eg>UyVrp$&bZ4X$_U zdZ&G%4Sk^vu6OEsr+uLfeW4Amcj|hleW49~p$)Eg>UyVrp$&bZ4X$_UdZ&G%4Sk^v zu6OEsr+uLfeW4Amcj|hleW49~p$)Eg>UyVrp$&bZ4X$_UdZ&G%4Sk^vu6OEsr+uLf zeW4Amcj|hleW49~p$)Eg>UyVrp$&bZ4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Amcj|hl zeW49~p$)Eg>UyVrp$&bZ4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Amcj|hleW49~p$)Eg z>UyVrp$&bZ4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Amcj|hleW49~p$)Eg>UyVrp$&bZ z4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Amcj|hleW49~p$)Eg>UyVrp$&bZ4X$_UdZ&G% z4Sk^vu6OEsr+uLfeW4Amcj|hleW49~p$)Eg>UyVrp$&bZ4X$_UdZ&G%4Sk^vu6OEs zr+uLfeW4Amcj|hleW49~p$)Eg>UyVrp$&bZ4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Am zcj|hleW49~p$)Eg>UyVrp$&bZ4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Amcj|hleW49~ zp$)Eg>UyVrp$&bZ4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Amcj|hleW49~p$)Eg>UyVr zp$&bZ4X$_UdZ&G%4Sk^vu6OEsr+uLfeW4Amcj|hleW49~p$)Eg>UyVrp$&bZ4X$_U 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 I>38t|0rS7;rvLx| diff --git a/rsc/graphics/tilesets/terrain.bmp b/rsc/graphics/tilesets/terrain.bmp deleted file mode 100644 index 0a39c74c88f031545124e48e0c2f01249ab064cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 553014 zcmeFaKdW}jw3u2_5XkcL2p{ZbEZeY+LbR-xF z(rD7LU*z(0{PsA{*yEXVR;^lVRjp^O_uYrx>yDZ=Yt*PwbIr5%KDWF7;eYfu|MkD{ z$6x>X8~mSt760dd_fo84yb{ky|BZe|M*W%P=r9q zKmBL4Yi-pYjFqbZ^!cCv_y2KlKBRU0M`l>={GEjdrYO?+83_UoFi%-RF;l31E0RUm z$Lqi|@Nd=+7kb*Sa~(@Ren8&nKe`J6*{etkjAuH7uga=gnI7+B=Pxt!rt2aU<1*Im z^=M|dsE=W3>!e{}nHh5OaI=22q~vdDyLFJJ2kJ+gI!_Ca^9NcD9|UN^=&w=lZ3=%|=0brc&-?dJ zcAmATc=_UB7N4x%f0Pf&T(8Xc#(7 ztI4$D;&C6!%Pl`_+4Aa()wdvSVMUBQV%X^CiNb z>{tl^tNG>3Ea2k%`e*Gp$P+&rWVF(JiLfU- zW`Z~YvVNbv8`c2<{`9BOcEa~hZa#?Y>Oa19A5)l&Z6)Jh9GK#>l~cxV!auP#%42T& zGf_Z?Dr>vU|Bfn6t*#$!1dy#LBb)v>XG_25+yUp4QhC`}axk&-y0M753 zpTe#!5rzhNp|4b$LiDX3?9QWspp1jt@IR1$LS)L-} z{_qrg^=l&l_o0PH_?>f5zc0B4>wx|GEIP(l3koeI47o}{fr8DxeaE`xRY4@>fea`kThyGY^H^`ngd)^&eB^t7JIeFAW`hRQW1b za;y7wk-}0t=#TOTfi{}UFIveMlecmP%3Az)UW*5E?$3v z9{RR&$!Hx-?slEQR6o$BKyRH90 zGhK4!#Iy8syXpKo#Toq~ISKOV6rsFQB!j)y(QYsP{j<@js{Z4ufTcEoQnqq5i+|&U zf9X7ezklg|1RXg5IS}F;YIcf0eYKpG3>OcqcmPru;v8yrihgYo4ubexer-hk+-`b( z>J%sSi{~&ndB3gx!w!R4fmY^5yy`!^BVLfoOc!?mg!_F2fB(jDgj@O3SIgOOaktVh zZQ&q{ud5$!H=SRnIImw+2Y{|v_U;A!?xAlR0p_zQ>DeQx`j2E21kJdt^1ecv5Al~b zA3lP=bKUpU-x16yUBNx|Q(ia)gX`*t+fC=!DW>Qb+b*D6*1Z$#dVhPZ!~S3R$^8cl z84OdAu5*9#g7q7qh=-WoXGs~bSeB(y{3AYebg@0d!+3^M|mjc7b`CGRfbly<^pmHAM zhWa7Qj}QzG!}I#JS77GwFn^y`d+p*E=O#GDuT}p3em9C&=b0RN??2@)R&Yt$1_61p zy-(pUuNY^4g#MQJC+cSjsp_WtFR!@86n=36OxN$^8Bfu#I)V6Bx8ZM9d?H7H`G>!M zpuaqV3Lt=BuV(cD6B3@npKq2&`_WGyaKCPm?tO|s&K&R{e^}*1=_k+>hlBh&Zz%7; z3G$FIonQI^u=^B#@aX+L)_>H6TFbxV@83V#R}MRXnHbViJw2hsT*axU@cXqA|LFJ2 zUFuIJzaTR4eqAkSSJc06K|E3a+eJ5i?a~*Hz;{b|{YUxmQRE5V_^bc;jvcI?L(s{@ z6k0J8-2eWP`|yYR?aS8eZS~_g64?QR`hz(dc9=PJl3yFG0Gr~Ga6ms-jgXJ?lg&+7 z!O!>iyHPY6Q72(~{~0_c)A%Wq=X!xaIC6u!Ywtm~v z^4s!z2?6Uw1he$F>gPOv&>xO)l0TD&gWQ?FC4NynRLy(BQ24e9!`7-I z-snFpq1Fc{W>sVEu;+U`U@iB2??p-o3q3zf`B2L}e;0qQ#<~0wgN>Y-`2PBr`jg2S zkx^&-X^}6AOS6MB`c=|S81O{?qGJs7pOfD|p|9%5dTT-gkMC*3!4?g}a$m@tkZ?VJ zu11Lm2=abU{ce$)bKW0k7WOSp`Y+B4fXfy>sbBRb!T=`nclwW-41s6zbBIrm7r6TV z3CH1Z^VC{3o~b1O`Ca@btrEuh zk*O`ToIvpm2KmFnz~31T@`GVK)3+O6<(Wmt82Cf9TGRIO;r^q8`=N;Wy@#i!a0KCT zz=P-fkMM^=;xKFT$W8PgP|j1_P`}%|iEpAGI-z7!ZBDqM{#FA~hY@IHZp6R(Psc9( zE=jvunfT=M{^Q=ZTxHH}`OCLBccHuKZ^`x>aeO!Z(B?c*WwxQ)UX3`I_}5p7|htIa30j^j7|qIu-O=@N41`6cH%%HM{hF zr5OM_x{?RgkGy)c{M`{TWd}#g9-lyw->lN02`tg2udRuGXKk6Qv041Ru#|i?_e>@p% zrTG$JPj;*XfYtorMaV-J6R>M`>}hlLXL&i|yZ5nccI>O>>KAj6{oMLl(7Ei`>4;zU;i}%b2)z8WM^-}}OAH^@@Z}p8oKYHwcc&3Hl z{=bR$oIkPkADylPLJi0q7~-qsPl$U?iEqN6Uxa={XSqOsUrB#fI$PiZ{n)~HSE(SF z#Xq!ubf~B6FFMBi-+!2}{hibJQqqlkN%XOoX!cpv#WXz6T*0UKWy?5_X-oYX*VD?B z&K6jzADg!LOTiDVA06}Q`aAu{KXO9<(G-@4sYuxV{$ZWqnG2Ou9%qvYar})4kyig< zGM>&u9C#4Cn7@1%MuMyLk7(%U$nCrNU&@BaC)N*5es29se{2`6&zQsUt^T8ObwFct z>p&#`UAkXCPAmLz{_>GadpRyWJCvvh?21@9IXYrTs!meQ7jXXQz&n^L-WbJ;R`)#R})DeG_d;t9L zm!`e-3j4@GWAUjl^r;Q}>Oa`MyaL40dHko;ITCydf9qY?8z1q+bNc@5-Mydh`}*ac z`L|48zjpDhi91p~`7pnebnp*Q}{ct z!>+09WIxjJXV<=i$rAI~`|YchNPvz%nEid~(>-y#!k_O(VIM!6L4FSLxsm+pKPUq~ z%Q)t}t101MBEB}v`qUr}3>WbC--z*99`L;W@f~+%-o*dD=HT9-W={(Y7t~K@cb^)> zpVi;$9{R!&@Js~-eD)1D`VUS$;*ZS9`JE{+=lpWJ4oPR~B!B;n*frY`*_m?vySCe# zTzc-oj>yiG>vy({HwAN-yb$pm%#n`B&J=il`03AEuV{Y)q0bCv#? zAbr>ngfz{DcrmQ{5B2DN0ZN7AL0oZ8zBB*Gt1+0951u2zpF!qXX&<@YLGkn|_`~3x z>nB|CbM+S;{+{pA2n#(`_g6zr+ zBJ*$;+uURqbD#zJa^TMW?vfp7HSF*sXQ}?*ivPP&ygJX`$i}x&qyO-tb<4VUg3!;y z?D*~9nSa-7GMG%GTK)`@EKOT_zXz0u(h9>n*H4gI4)3pjZ?_5gY(Bjf^y)wK2d_pp z3NGbfKSG{t?}PXcyeuP2+~?rW$nuMGTDLrSzvtD`BFT7A{XlcLUql|KKlGEm!vp=N zv`7UIKqwE*>H{exfcz=^=ii+c16<1fw32_~?!aLE_>zEGqViv}j1Tgw&O>=CF8+}4 zIR3p2hxuqb;h!eY`}dE0lamf$CWf?BPfsW@S8?h={Hn}#fS$mgbzA%}k2`?tm{p(J z6r2yOe->x6Zyfz|P$YcsKistSRL>!3r7^DW9QVJ!+hB^cbR=hi>puaEQ}nbvCEO6cEL z>uXlaZ_Do`^n(W-P%)gp-*U%?@=LbBd4EW?`u!?zVNp=#0Kgww)cS=;3BC&0^TU)6 zwcPW)7b(G4UCF=5ET5_?+E zuPI-ppulSW(j^(?GVZ3orJV68{+C;n_eFF3vSeMEui3msnSYqyB{?&(WE|tq;&X&s z9OK8@>H4$69FbAe{Sh-jATK{`Jl~guwREYKO!M!_pUp>v2MK4qq5e|*MExbdZh4kJ zVVCLrEI+6f^Q`*~%3H(x)PGB1h|lr|o(E>$f+}YdK#6i3D+oY)@no=-=1YV<*|8D; zmhuOGFl@*^;c?+jg!W7q81 zb7tx9$n&X|43{MA$&Qua%)p9|fN=2E5_}k7iqBR~8NUhtVT|HMY{`_tcPx@T_Jj*Qo?u;-jn#B()(F)AvUs|8iJPuf3 zt>=pOYg`*M=lUOZZyh|xLyaM!yh;TDGD#{qBr#rYa*N z{8%Vjfs!o;2lj%z9 zIIKS~bNC?sAazB3mKJRWC2VQ^Z^|eWq)p&({eU5Cfk?^b&7^fr($fcz<9Cam=#T3M zp6h=gpUa=g=kk|@y4s)eP&rs?8wn2T&pQrA2Kh&%A}4IhRpl0#Lg(?H!7Xyyv-sVj zC;H?1fpLV1{s(dnXYrTh2+rcql{x)>TSpj)x8!ZcH~ksey_2)a&n~g46A57#F5y>S zUd}Hck#m^SHY3mCcZ;6rkLw4<5hnT{$T^(FUy>s@i@#N<6Zu<57>u_R_Tzp1gIjmf z`uw~4L)hhTOMxNWR}5&9?oycbsX-hVuHg^XIYf}$;^yoZ$~1T-&ciM zpBlu0f%Vxs!gyS}m;9|+#RC}Mx04w-2ZyEpuuG=GsvOJ_k>~u*6nJueCTE&>LW1HY zRT&Hn9sb}ChGFeV{?69i=p_FI`ukg)(Vv+a@hdpPFNZ zi@!g`S*hK%X(w5Pf#2f+xAccyS|1f$9ym1|oCW#g_=7(f>eK-4DzHyE{-8e>=r zx&BRy4*Qdt83|W#m_P7fIK4hwM>rPGf8U9UjXgI?ktSE;k`CCUg884-V;K?oe z%eB`Te>z);pFq2Wc<8rbcKieBhWs6KIOT`EoBob?mo0o)|KLUk_y?JJgaiCoctL%3 zPH}#!rT;wh2!o0T;DG;ox8N?m=?I2Jr98$115Oblo5Mx?Bjz9{$h(RDP4SRD%m4mf z$NU-LoTVQ;+>URM1W)1bA7sibb^7Z+g?5lcb`cEL{~$Tj!WOMzxIU%n11TiHxAKa$ zFo3XJvn%*_`ID2S%|X_m7kXsSA73(#A#9LeN67j)wYjMn`at}Hgp2e`x1$8&AVr2upvm!k%NdUjU*VpA|d zeLLHTNa;_RxyuxVZzWlNL}xRC-~#Qj{`pr zbR77v{>lH1pa1Tk{y*bC|M>s>=ivuyLDJdfVN-wmcYj&>^T%HvX2_4=9|zVr!2ZMM zfAPQlUmAKl3f+c7_8jE{{5tQ{(&hv5t*dlbg>@r}2ym)Hiv(P*->=pJbQT_%a%RUt z{{iMHOa9US{?G6;h3dB=3H3AU?6?as_v@2Y6zV6J)+|Y%=lM|op~G%$A0wY{lRtG$ znq}oE-r~%*i(v|X-WU9N({&M^LOxu)`?_;YXO=~DtY1H^-ErOE@yf}WBmB8+6xrm@ zJ3b?FdH?Z?0G7i7tN}dzLWNZ@87K#UBmkln_#po^C6S$B(IrQbiCAf@#b%pdjS-txve`!8~Q~clDJty?-l3Jt*m!PFzJC+-XY8Ssa0YvM; z`{QrfhrWN%cKn}a^LhXKk2cK!7vaJDS2)fdXhB?fEB>YB;WlQxbn8C3i&=WVeHmfa zRdw*;`q6eBa!l>w7bk$zdi>7#O>?9FczYo(n+&GP_;=90f3R<>frNt8CoYx%YqrC{ zLp_CmQF)B`vuNu+t!|KD_5Jq6_$=6aEOF0{8HN2RAdU=fNpT2dUP`AK)k>LT1>nBgh z*X@(GFG;h~Mj&Q_ayH1;Fz6ve*k}sBI03RkpS>G)wSW54XgmDo(KB|HuT=;7j|(8C z3|%4szD4n)NJ!vNJYlG~Kv;es{)x4LGX}fD@ilZXQ9y_4gZ_6^X=-)-Xd?hOU-*DO z&e_uMId{OV`Yanu4u)2vz7*nlq0UaD!c(eBz(y3>5i@1G4+A-dC9Q&=<(D&OfR3O; zxgjWWAC~@{*?n_uP!)y}4-lqi-S42n>qehTvx z;b@eH`Ybxe>)Xbg%yyq?d`I!r++F_#Qvh*c05=>8G31kRW+LKC{9GO*WG0IH%7eEO_&j_CLND{)Id<2-w-&x8(Be*Y*aP_TXVA9pWf z*GWG^ghMW5LdKa^k-&y{hF*}}o?UHY{Vz%2d| zPTvdqeaSUAn1&%G3DCx(W4wO<@~N`JC@A1d{>0XQI+F5KD?-^mE2}+7tRv^CR^&4N z!)4G?t|Nzpaeod=3JWFRKK=)V8ba#0KRQ!jk!%4h z$8YXF+(j6Y#Urqk|5yzK%|4WDfdl%Fsq$4WX&07kfdl$GJGw~W)%Bx|06N-6req6% zX!q*Z!bPBS5Z6zPN1=Ew0LD}a_WjGy=C zm?~eTTkcCOXV2>|X&H2p!mH~?8$pAdA?QeLP01h8?$xh_i$F^`@OI#uGt?pMk1rGS5 zbIIfm&_*axq|Ne2vQ%FD+!>twS0eLyLf#C z4Sn0Zl3OHyjeqqYJX=?gF9i|l*P;9r!an;remT`zN!h(lFJvrk>DA9bRd z37T0#dNo{R2aoILcGLNFiZl8}auQ^tcK9>WLsE`^|7>)sSN~BBKrOH|mqn{;5unfg zCzGGT-@o*``O{a+*+=*v4&oKHLO-|TE))56ij(@qa~Pa_e_Nj}>@b)WXk~81t^dF) zUV)p27Y#>X+@GE^jvvI|zi}P;CjRu*au%BJ?|(Rmd?uK#U(U?s*D22H7u5lP-A~qM zzkBH0Mu7QjN_zH4-un;j(%&>%Ah^1B*rHW@FJZ_RPYZWdXG8mj;j(A$2r1GFn;X&aRt>Vfg5Zf*wwhRJ) zXV_~UUmrheIG)LN|71B0G9G<;ldmmh4LY6o2Qg@2S5d7*l>__tY;{eh>v0 z>DOL!`9(WRzX%6`_AP-Qmbgqq@U2(a-+AJNO2l-pKEO`laZ$UhlU$X0_@%qp1`pyZhM)B72@Ay~$LC3?( zrM}k(><`SB&OUe?f4JYL>&I~>-fu8R!+zOlcC&s&cqLfm58sOw_2cHO;HUEMM$z~X z>Li4wRA+wmpK=WDU>!d;s+&go{t0P&zkmE!9-VFk=ucGwSmkUeU>^dH z&?-l?0@v_|+V&$z+X#?s0oTu6oP3r)K|hAtWkj}eBwGMencNSewIe{Z0;~C3;upmq zTK}q+&{#AK-!@^Wv~BSE{YyI%xNlxasuKrD2+J`OQ zOZhW7BYp*k>!(G&D2`WP#r9!Jv?@Q;e^?m!pHe?` z8{+GxvGuoTbRPb*z5LaGuopM=iw4fN(?dKxUs#4`pd0{_0Nj>86cUFz!kzV(${%#U zuHUOj=0Bo-TsiR*^|u&qp3IW)qh4V+CB6?J`;2H zKnvnRT*Te@{VmAY)dJr^e-`PHAUF)~pdXT0KjX4>id*TIs&Q~z{cpX(e(m!1LhPBL z9fhH1>aOWktAVh|=&4`9unJgl3|kD36 zi%3-`NNKx*m-&y4w5bb53-Vz;MOYPvchKMJ8)`TJ{HK+< z5r6d`oW1-{;U08DU?zrqGR{mye2H7?apJJ)efYy$&>8xnuGilYR!+HE;Jf*sH9xd| z1nAKVUOz{@Tqb-!fcwoSg%zTDf ztp&i;bpHGzbRrOdLj{ExuG8NU)1Q+0_q^XMe$oA|uAg6qztuPX{OGa&;h7fxvl031 z8-Dd4e|-Y>_lWfnA{=rR6EY5*J`8M_3X$vi^NY}rxZu_L`%3z=Zo9CH2VSke!=J@V zWCz?wKaVDGZUSVH5;lm~jTdRt=^`GE_+{^J!gje7RvfYEkoXYV|7?sDLTgM@6Y~` z6Z(&)uslpf!dL&{MZ1!5?EgK*F&Pjc2uHg!fB7zq1j|FYCyo#JGoqoNQ!4BSU9;l@ z`pb>TS;|H}X1VG?^}`d*^~asRj6b#u`vjUZ_3A&m<+4IXf~7zB%Z%b9B%K`b2q1Y8 zfB7zq2g_4Pw!mKf;{rOFrM8ivWDD%o-`}Owyy$*;gt_`_w#kp z5b*K)?MNN>M<*h{LYdqFKl~kYFxBcF`mho3%rfW+-}t@%NKCj*4Oy#r;)g8@OE|<6 ztws#|Z5>bkD47W&3;-mEkWfo5=I^`?yQU`U-?i^xa&Vr*>;3PmePaEv!k=6JuK&AH z*vHRike@?*ZY00@56VETLx9z&%2Xe~o24IB2mphMFkhLX6}TsV|BV=*4Q?FvXMD$9 znYe{J_}|wIg^#PBr`NyhZ*>oS;Rtx9f&xDKhOPhLqSYDtKqbKrgQqk*@L4YD(`xp! z{QWm#*Q`6>&Jg=-%b#7_?M;^90bJ()reInGyITGP4IiBCgdF?&&F#3eoFmIbI~zgEy$=GI8GJY#jE+~3rD~+%b+KGW9vWCxhYSX0=t&%O6C^3mh4I{`Nv<7U6~zW zl(CC#ZnA6BwF>xbiIoXZCMdW|wpNYvV~Hmdi>C#ANh?QjPyV&}zZ=D?^X!dmd<$9s zk-Y%?z<_5!c+4}%&kKxNdL!MXvk-dXJ z{bw^Dnd8kzY#-*Rh!OxLism6Q30Tf`ViQc zZ{kn!dkOvEK?iuzn|JC7t@|x^d?^1D>z|s-TUZnfE_vVR7Ys@W31K;g2(t5oDkt2W zf04<*Hm%pd$@?vhdNjX_2R`W!7?!?YrTU{bReXwsc!J6?R^6X} ziq*lNan9h+_`+kEo%`KI$h)3$zvaF^{MWo+rTHEV_1UQ(P5JT?vqg{@CBz>s-vr24 zlMxV)W}m`eS~M6ey^;em2Vk#1g91jR<+-@R2sKOSAOym#b8qV^E zYWLPpd9w_vJ|(pUa0Kn!Aq-RGZ*h{4hw_U64m=prLp(iSSlTjB4gg62?#bUW3UQv| zp87koed?J1&QM}HGsU0P{3=dvG`;>y{R~d=NBSL{_rD|C#bcwx^Tdj{O9+M&-B5o^x#E6=1Ny}ifYS;e;OE*vj-fam9OieD4nD@8#fOM? zJjSo(n_w4z5SfR0yIuV351AH`%p4-v$Rp){wm`yx7DU>+@s}=jjJl8hmU71Z5*_c- zUvA-S8Smo9^1Man^vGU*Ups<#@n`Wl5;on%AJ&cxH~F)|9O-Pd$ zUtf4)A)cDWu*Kj4w4Hz$2tLlA%}1njx?AZl#ZS~<@=w3tu*-CQ)t-Y^_3pagpu9B< z`}!6a*MCc4h(qucf4~!%b$0iJ+i6N$%bWm0KB;`U7_>_{8)!AWl0W!^A*D)r=X4Sr zz-RUI2vhWDb5{5hc6pHhL3w9*hx+fx^QpQ1J2PJQ>Ml;;i(=pQG?MhEz@1PjA1uG#Tnev)vx69#;MKPc}EvDX29ERo3b z`aAM`N;?K{OusV&lO#XYWJcU$&clDl_;zvKg=JL_lKo34EFt*qQ9@rXG@DZ;xX0H@65pDDgRTr2b~alFyxbQ zW+LKCT%pH_G3&uw@w-J&^vCrRyVYm>&&-H~t31QcwPBa({8GrvoyZ@QZw{#h&x`AS zQ4 z2?R(85yd$r2E>IsAh3}n1Vtslv<|JN0@WbDTO_Iy9OI{qk}w31@w+Ss z*fQA54~D!&rd8wsKi6WRNIGCIe-^(P@hzalhr(GiraH1UB?bcWZ%PUYV#}c94?zsM zkf0>*EXh-?2v6s;66`@@Ny<~L$YuO)QA=kl-V%@aNA%+?d0&bt<9+?^jBv?=U>Wc8 zV^*{RCC_1g7eJD^{E|HmTv7*Tod@)ft5Rm(7b3ZJM{S-Wk7x;)R&J3QawPmoTtjAJ z_(XoU=;``#793&L{kk*458}U|K4r@;z%t8E2@Zgnd*82Jl9W90ej!-21Uy$h_^wDW zhqmC?M#Xor)AZH!FTf`l+q+Joo7Pw45&Vo&Msm;lf?al~4h+hX;=f7;(1+wQJ zk!*ou`gciE^2GZEm1qe_u5%Ii*$1)y_9(!=j6IRxEqc0soCP;H@qXPL;)(p3e7gSC z^;sTaB-nq^BwJwb`!%AW%$az<5FfVSDG(1O%J(jB&A3eH0IbDl{}cJ$qNnS}S#X4j z_v_{e&*B$h0JHeLTo=`6P`+!(cM!r{XAAGrze`3=p6GudXN&MN=0+r2*nDtsmNZrY z^9MX4;a?l@aDRTc2uFCdew<~lem6&0R}XOJenl9-EPnDVtj<73^Q@BFO7VudfIa`6qu1!116a5dn@E|-F z1Y@X!l$*){0a?)j58@C0V2E@5==aOb7R~Y}Gcz)a-%sIqB7f@$2jW!aI$JpFKd@bA zN#;kFIM5%;EqJJWSZ=|%KU*gB<4@tw7Cp={4@1jicw16^8keL}#a*I}RWgY|KX@O1J))5ZJH+S>|$UeMLXQ8%e*`l~I zOVHY4a5*@YDNt_YL1hAXyu_YNT&8)@mw3Fyo}Bqx{ve){5Abg;DHA-{(ccp9OPs32 zo?ITeze~yK!9IVV9BZAb#C`tFC1rvKH~CvfI2m^h0ZY=!E&9v3OV~OOB}Tw=I$J1B zfBy+U2?XLF0lqfSYUnw@Becr#wIU3_b4vb>Ih-Oxpw)1bUurY(wIU3_bASU$M?5lp zZJ^cAb27iS>uf{@5eBfyzsY=(Uq{HmwFTK4dJb?VVWe}4^HU$$RI*R{FP;u4|E8oX z5YSz;4ABKC6U_V(Ne5`vW&9maeCnS5xWW>{&sqML{0biPN6SmVVwj~L6~$dxTB@`u z{H6Z6LCF@F%im{Palc_l{2>dMf+zX||EMK^xS9sU>ng2@$adtP*J#ifT@g>5${Bd$%=O5?6 z)>tb690q0%o!|3?%S}nB91bV)mz$mpQte5S^UH%v?*Do6ABJDX0sgyk^U3-_QSslf z{z?j8?+Nv6ibukx{!;vE{&Lfw;Ew~pj{_qwuX5CX6mf99X}7yAKg#)aEdATR`^(aw zKmPLTc=dCZ9|ul2z#f9e;=M&JMF43bCo~^q{yOi}(&hv5t^0zva-M+x1LrAac4)aU z+~CN<4rgmB7lw8x;J&TptK*;Def8tJED>Ql1>S`xr4NuTHWQ2(L5 zt@k&$t>heMr2L2_Ii6t^BH8v*i5BkV*Fu4E(=20FMEepz|19QTj7RT!ITSmr~fN99oY@dp ziu+K(!0AKe@I#luyu=BSt9Rezhbp(x4M*IErG8(_le+(# zyXS;J7>3Z`{8^F<##$dTSvv-14v+DR6F{^cyg#NncsBb+_qzyf$N%Y(SpSh%4yYtt zhX*}5r{&oYaVlVzlLtdShMtyZL&T|kA#ljlaA|p97nh+;36^f%ClA6p{&e(**#UAw{goVaT+J zB~kKA3_;GBD4;_XWRzmEw!CU2N2{3JQKhM{1Pc}EfFLFeeW5l2V4Baia3Bmr=M+OH z$MZjhTW2pDOAdxsJ-k6duSEn$kgfh+1q8v)GXch0_k&-@gI!p{5q)+_8=$U6*iD{~|M)qmhT%~#2l zb?8AEEB#=|2|f$*2l1b;2cF#>IOflJB_)Hzl$XL;PT|Q4(Gmxm1z^6<0+&JNV5-!n zAeXPJPi+KnOusASp`6oaOMXwj9`kDOY~Alh_ppxSnV~!RRK&0TQ<_6RIn_y^$z=k9 z{o?VpNal|DN%EYqj{jsagd?2Pe^N}jTneQv+naL~Avo`UsZGK2{L;x|2L0LypmlsM zESHN-Ifw+#&HDHJE3w1_xPFhvcJXRBp~GO9GZhrbIXrLJJzGr=@pNqghgJIDwZN(; z@}H@M;0%W+{W+s2uZ0*F`Puu;@)Uv2rS+qY0OU!yDHyfOpTIey-#!R6lYeqE%nn+ZI*b4-=5B6Ex1wYeUTx3K3Q;CGS2zSl{9rxNy!Ch|M2 z_8Q^W!bL!009=p99k;qiXgGO@NC?(c@BIgoe0K~(gtLtEU!WleLv|G{)c>ka$OKi6 z+=u@_0mwR@Ymq+(glUN`#eJ4+fu;JfON(DR1(3Y7etaXUk_po35#pA9F2TJ!?Oy#_ zJ00jCoBCx%-88=bcbnN^^vs!i`;X-HK}Wp&XAA1{v}SL@zxVcaoD1~t)uw!j?0^gO zV~esmOQ%3bXKQMg{sSA0@E@Snalo(T6M^%${6~&YVVJwhNTk!0;&S``k-|O*3Ue|O z@XS*qk(=-jUVT2%mHG!oDlMzckt_9w-KA3?B#aDq>E}ixw8|ObKd)a5Q-H(+jOf?* zLu?nXKS2+D+q{xnB!7*6^&dQ`5ZYX7iIKw}&FTwNk&xhV;TE_Fznp1-`{-{e3~>mC zw=LOu9$Z|NhzNRMvl>ihVD* z6yyc*Iz<4UMuunc_b=TKdk25|YB~D||HDD(^Sb)scGLNFij(@qa~MFtnfh$?A9fhb z3bZme;;H}W)5~A6fKkaIGBRZSKZU=4qe>-#zqgBfxw%B|Up2)_Q zGksI8>Imi(mYm_oTHmz9=lR1a!Y=3e1EHK@d=|e>5w<(VFScDEY~2}lRP|bi{lD;& z`wtc}7^WiOd;jT(>`X!b$X88=p+EHz{?1+Z)#ll2^mhbfDytfgT%#YmP?8^HTx2J+ zqhEVhcxD;&gm0YsPxx&SN;>kSGXN~% zPl#jq2>#YB-(P=6Iq%~B{`(PD*N^tnMpOLBwCDN7xe2rv!I}5>yHUJ4&*VtzKS4Z( z__o1MhNfnXicjPSF#pW=j|32u&6AFm9i|KhP9NTrfAD5;kl$9nTjUoS@Bx3E zIp9Fv@;|KdVW>|{WoAZB>Tl61ev)7M0mSLx0KYFk)_>H6TFbxVukW95FVc|X<%y7w zIDfR(LFVCXjw6EpR>l#`@fJ@jKEm(UN<6;r2){ei(%FiS@UPatls}VS5Se(tu2vU4 zksqAC1@T;d$^LE>@4tWP3rD~+%b+KGJ_n(nCy3lr-^&eh= z3MSN&4?_-ySnD^aV$&)mgtba=5OS{P_sa!_wiWud%XEG*3ry56&Hz{d;qLreg+orb z-#~lKaFIVc@>7dcEL&=Mwu zCuUind@A{#{GsM?mKFNFe&+HA{TNQ<&*Y5Ey5FVzE%HTiy#*8f7pH?o{6)w3`Vb1= zHeuLWRm5NYhp!k<5n6;FlW9os9IV1mNXtW}g|%f`$hn?BS0fJ&B|+Os{n$th6a87O ze<^<^XJm>$E%HTiUGAd#SWr1O^X9i*SWY8?09;ydu?YV_0n=!Y9_ zk(&d2(jR9Q_AOTMYoocqWecCwFP;{d$lvKdYBB_#$^*(w@kl>rlrbxU)Z-;&o;DHgiPD!2u2D-mi=27IXQ*sVxG(;u+|$eSgBjz%LSj zJJ*kN79C^Y57BB(+sp0uFKw#phDG=gDh*dMo#gkDg8e0r;17kwArE+S{T=0x)31th zaC845^%tmr8s2Ik>M#PW%#C=}e{|REKjJ;LB`EGg1;v&Da=dZnB~FOtKFrB; z`OCN1yAZa!q5hWaY|cIPLzN$)l&#YIEdn{s;YUy~6rWKi=<7Z)@%Q2j-Oi@apwMPUtP=s?3%n;&gBm z{_rB?p=);h5&cp$LMkkk9Zu~h}z ztN+j(JWEePFeHazNak=PM+-x87%I)dNRIMDau_l#ya?q`gaHJ?Fbv5Yj^t=zNXD>~ z7lK?Rk`BoHn`^_84mqYmvJZo1@pz7cEfA8!uv|5gqlFR!)^xm%)$tpEc87x(A)5)H3)H{o(ed;ko)Zx<})8 zD|93-6ln6i`cLa}Spb~vUv$ZUVBh?E^5++!6OlQW`O^{8pK84zIzpM?cN7xl-ftE^ zmp@<74?iyyKJX{pZ>w+o`O#zl!!s?s^?wDv>OWZtdkCIEo)5z+{qO2vRXAP91j*g_ z^NY}rT&cgWq(961x~>0NJfuFce&F+?>tFi4t2hoHHeu+Q8~D|KSebaTIC1HUFvwTT zgBfFO2$Id?kKoTQ!e-P=oCfwHlQu#ycM{mK?^|!i*f8h{&re+b`Xie|^N5!ds z>Bva{&gKZ>9_-+!@R#qxNHAEz^M>FVe?~O)b0CJTlG6}kpyG}Uma<(QF!S%J zKS(WykJIm6WeK+a19Nn<1b7A;St<%5ftD)L0T1FY--Yp@OqlD>xPVS3CE>{*NhSE; z{g#?t-h=ALWeY!1f2-%{3rD~+6%_EU|+XWdKDgi*j4)Af;0MJtFYds%WL(g%n1OSh>u;&A7 zIFjGW@wf;{uA%2RRsw*>TiEk~H5|!r<-GL@`>$PSEIt*6KDB}0`%gG2Pm#6hbZj8L z3OEGyzv`3Oa)f&^4xT`T*$env@50{rT>X1@@8`SEAHUy@RA_r#{e+@@wEkB2(1(qH zXO=-v_{P?MavheDPIEv$`vb3_T)r9nIDhAL*fkaEkOx2J&#rw3lUo;YvHyLwEs>r0 z#rm1@H?6M`o`-1KLBmou4=^r`zDkxj>* zRX^0cdA}-#Px&taC7}M;E?zB2A2tLbO|v0h3{(FZ`O^)wm74oOtOEHX_(xui!JNJ) zJ}Z9)nP;WB2I33ucTl`*lRumCHWQpy_=jIs2oxRT)q;E~eE)=@XGU!O2bR{%$a%mtKs+r_K- z=nF@{Gs~bSeB<~26LudQ;?_pKY6jVI+V%Y7FUYRUe6$eR#WpuNDDmN3|98oD8He#) z{aMB@%>UgeUY%!eWaC>X^`G$DDBM0^FP88pU)EFjcfBTq$#SFgXOLuRniTdysh>+a z_j^EjmeJwQ$*ssS{Vlc}|7H01cAJpT=F@9Iul|!gRD^%D(U5=+6X%jZ90_4bYj{uo z124p6@@f5&i@-=~xKT-ZI#7 z9`W1qpMQ5+45b^bQl3snURwJcc_0Je{aKKKH5(Br^)mB{t5S@ z>&Wr)Mv#vh|8CcF>z}8N z?P6Bj5s&pBwg?$c0p&B~u=#k0(Pe2lW}n6HRrG^@69-Vqp|(}P4nj_-fA>nO9#{WV zep&yahkDB4+({_Rn+cNnBeydUvoA#2J^8(ae(<0JyxA%DTkiN!e!dIOs()%OZ(&go zJFOm@q7KO=2v}kBPl0Xq+ffT=a>GV{G|TUb`PH9 z$8u*AE>D4AXe=0pgVRaHeW+lI{LcJxCV+4joRPn%GMIXRGHcz{0$&O_g2 zBEQoLAK>Sy`?AmT(|kNdRf1#sv-l9vUdQ+)ey;u?G7lwN;DG*2i--s_;9(ipb{;I3 z@U28zo(&PFx(|QpQfbuP^tY5V9?Zw^fc|oe%*@CEek{pb%;jHNpILm4=s3sxnXW%8 z%n@mJa6o^D8Ej5Y>_Onovr`h%d|{^2MxJ&P{%jE<5bRQKtG^UKQGdxl{eHtP)A`rc zXHec6-lu+A3PT)%XVrgZCV9y(qX^g{Jkzm~5e)GhQL+Q1h1v)_k`dw)`GY?gV$+HI zCEG;)tRInC{3UsLBHmPZLdMAbhFzxfXE$;rDCclfe^A~T9^;n`C~<~k`aAM`3L72c z=R(&B?99L-4<`z%G^7$GhoRCOjN~XkB!{8W9E{{BKO~1C(}G21jtBz?$zd3hIULE+ z!jK$>NDJaQWSU4iAP|OOha8z5T1^GQFl1WTrOXjw03kUHLo$aWIa(N!!!RiC3`H0~ zAPmEh%;89m7J70=o=^D_@w7ll4nwSRW?&@XUrGLNCH|$f#m_ia3HaK)>WTcpqG$ON z#B=C(bmo3r#`5%<`hxuhu2KQ(|c4tkCZkt>D*Lbh^3zxPIbU{FxaMSTu{D&V*g2^RM$iDBm2yH;D;= zQ+Toh!z_oI1z>(iD}%_{6y^zY{dZ>I4mou4T&>f|gfam^T3617wa8&4Ke;?7AhL+x zEqbCquAex&cg+9Hj0i6%UmPNw>Lhp$8S)mL+}4K$v~@HY`%&)AK`b4BF5i=9CL*QShzIEQ6a4U%(&y!LXEC27eR%hb`LlCo?lrx}AfY{2!^G z)}dN)ykgLqPlw0>{jFVg#Y-_cIO2cUS0t??D**sG{83O}fQp0!j|;cJ9r%Mk7*Z{? zwPY*)o9Hhsn&MApW&{pT;U`Z?RR(pl1jyl!;<^4?N7xnb@CO0PEcNf&w3CcoN`CE5 zKy9A6=?@dIgk9Iyf-@{9f7mn+J?(M)`4(`%2l;b>{=CI3e=;*8v-nx7OY5_Bgah&X zW{vAVuw7@#EdR?b^nP_d{A2}`2#*8me*}NF=vn?;pg(Uh>wYscBeVEh6+4l?b%bN_ zmf#Q%`j73^Srz!h?mk4O4+Ac@U=9}YCoJg?$5)MK`i|qP#xpzor9TK_$rOIyI^Ze% zrG9QSg`ZS;7sRLVXJ$rb@l${KoT4Ahts@+cQ&_3lgVKL^qs~HXB!1s?6Ngo;EjD>t z3E&_3s%b6Xj9<*(@(1xvsb#{I`di{lVS~Y}f9@`Ue=a%B82ATIJ)V~NTSqtAzl+ni807aQz}zkb%i&)B{z0b9LML88S38Avki_=|9`t9BoN3wu#{_>k zEO!h+E-8az%iuozyZp(?ezcB1d7(#~gt+v_myF{~j!4Ph(a-zc+*ErF@{bdWnP8A# zt4jTv&ENq4=2@mBxYQ|xyGXSApg+6FnanMCU)m19ckI)KRTy^imF)Zq0wB&G4+3{M zHRVeJzjA(g;3f#e4Pk=dk7j8;^LKeAhRi?ClXZ%%!|zklUv9dZzufd>kf%FIa(=m+ z3=Ajr#d4nfhvAoTAirXKC0RfEC7QvIjG>AO`PX~myQ|=j=`Y2v<}Ww>3H~_n`#8W? zEHoCq%ML;gn~%St*PDjjXX!7+ujVf|{R#d!@Z-Rb19afu{Ga}9{QQgm?Z1p4$6?4R zPx$-)`M(ra{W_NZ?ce=n>CYd3`E|VdIm?d&CmisWq9)^w1wr*9VhquI*nbfDhyUb1 zVE(W3PAzRdAm6$#`iUpJb^mF#%tr!e8R^i95cyof2>Ck;4@_l#>O|c2A7Gxcgc_z$ z{Z=F_7}d|Lvx_kBdwrJmqkMqP`k$rtBAyTRA6cqbnEgTiGl89-m~Rs?o*I$?Pcn!Q zIlvk^fA-c1xy2cNZR+~-rt2bp9Ew@D*Q1$PBz$hxPwS+iU@**?xP?uA-V~k$;PLuV zL6-b^$7e(??>}xYZ-m$9=F@7LuY6Cy5?u%5j4(Mw?!$jgN$~jDpKEsCwF|C>S4QB& ztRInZzq|G-leI5E=4S*`N}~X38>vriI+x#RAxXmr0eX1sk3WC>@dp9Nhr_L*5||^xFywNP1GEUS(6^h;zq&&D`d9D1$*(I|;s56DIbr(!2LH7q zi)u=JiW5NkJ$Qet+i&)b?spN|j{nmmvHnA^bOqF)`x0Pt@PE1R?qs!wIR{hs=U-YL zvJrM=f0l0DCzr6*_uH2dW>=IGn{oSd2EE7nmdc| zidk1b+6X|GrE2HC)G+Rkb8hPQ}LeV56`>NJ**>nX6Q~n74cX9;a(CG{Ku^H z0AsdOoJ>|eGKHVTf3g_hgU$;FWa%+~PKqg)Qwg39fG@t^Qk#OS>qi>_=)QDWDqVpQ zf1Gnfzvo|xb>2>W#&+>)IHAK}m@^d=$T>VOT!k1tga4Qc{v*?WTt6}MJ^ncUGnL@x z0J{%|{W+s2ucbm>)5q^O%Tq+9xTt=#5db{lF52{%Kh7ztzJ6bF4fYc4)MwE#zFJUd zDPhP}3JMf#_Wcw5r}+v3Fd|DCQ5uFJf~hd;_p2!e@5X<)4A%K`SW;L>g}3rQDAZ6Q zSzXiXM;ifPi&^}l9oMfV7XX^cH!di|P!WKlW4!tgx{CkfnI0$h**9!||G{?fA3v&3 zDq)an@$9@`$mdTu8hP-15dYyaSm)1SNxty5_v<2sQAjGh74@Ty04DN_c9(vwS_*d6 z=UcCM{qi+4`076}A3v}Q^-0s9lMx1$AWL%uQ&`0V`YbV?q$0!3`H$5AkA|lonL!@^ zq(8@0`KsIAuZt9xb@UU%x%#ycz{L6#?Oy#_xCl@Wo`dz-YBl((@u@KMsSW(qfA~_! ze_pZo2MU&%0GQ z`Ci5hGJ+@9GEL8C@$bETI)EnuPQA{bz1ozoe~IXh7`e&)N~eH|2Vh10_(l`?omNK} z=hyOyfMtm%!C-ynt}+r)U)oOo`u?Fs@<&zb5z3Z$E@2r1a|wrhYArMIROAu-gICY9 z;Q0}M21P1OYI!MsBOlQp>PI>SR6L97hZ|)#a%7i3=k<$W3OHP!tp+mmZ8P%s>aYHT zGqN&iyRhmLaRrHe$W?l(|M1Ef_k7_y^Kafe&UF+0n^Kve3%axa;VfA*A`|t?8F5bG z*D22E7s*LL4dH-3lt==9e_Q>hANTK{jZXF6f1pY~6vG|@N%~h6;>>ZtWFAVHTZ|KT7i zFc}Uov3}&tTz;M6ynay~0KD-t?{B|*=-Wns`D{vh_DEj+2U7jJMZPi4DF)e5c{D^c z)RNYDpT*y~Zq`4}8}9eB{&WO$>Jk2jQ_xacy+S{?o6fIOOwlj4U4Vx=`Tq7=$JfV? z8jfeO9r@E|-|&0?DX*A8If=Iq5e9+1{}5{yXV)tC0T`K_V%#$^B?e$}GJ#mLzKT3l z1&qv-{GGd=!VePsO!TKC7*p8GeLL^Zbp5b`_v;6l=#Ti_2kkZ2AJNXzFTz1E>we#Q zh5bEQ-!=lCSq44f8>jxmR~Y(v1eO_|x<0=t7EGSyDwz+URgd6r-Lgvew*It~KgfSS zf=XzSe(g1vU$hhTi*pm;EVJtKyHQy4nHfy|2jcmo{=@EpC%X+B2%nrnewZZ#gUZp% zdw>4&il3st6c5jzs9#06NWZ+A$S+QS>H3{KW4@IW->+7y3BOx$sN^%>KWY~^1+hoG zhILpZur=}Ed?LuWmUFF!cjnJG3$;J`{eImd#%KBC%mHJIk@^X%e5fOU2S1vcc)#KV z$o*$Tzx*V?5`Vv(-|;N}wdr5|X?*td`wv%zrc_hCzJFv3fUqlZPndx7G6-|zkJgfh z{u5`m93kh&`Tbgn!?~#Zx7EMYpGE zf5*T255&8Enxr;N%mOtEOg+D<*hSW1feeS|+(V^Gx@hN-@OY_!6k z)%ut6XL3epY%WL@8xjIm`7w_AY>_XDOF*cK&M-{%>t{88(J==4&w=ls@CnEJ;)Md^ zhY5GeevWXmk5iQrSB|8v?;W$4Qa;@9$f$c<(&kVM3GX58pW7`ww3q7$^?`_(FNajpZyB zs#Np>dYYDF7Fa`od-D5RP+}eVCi+W}9;D!#`|pB*Ra7dNo9kCSqxc_P|J481E3E(Y zStOttC<3HRg=FG3#j)Hl(e<>d$kXSZ{N znc+giaMAq+*-*mbd0hQ0^5^3B>#bK<|M3okoL+~qRRx>%A3DY|({=0pVkNLLiD3oZ z@P$fn|5@Rlc7OixB9ucOmZzg9IzDZ@%%4(T2tLC9pqZ{dv3{Oj|I}Y}jIVy8hC`rX zE58|k??2o$yigeOJyO#E;QNL0aG#anuOTz>MCOC|!;4T3dESrvQ)NBAFP!{LY4 z4_|?&>u>c9H5>r`)5_e4zxoe5iTZ=w17HC#q9HqyO4@Vixfqa%2!=}LT2hIS`5Jzf zKfDES^H0~`>KlK4^w|IKObfsLe-rOH zf8tmFVP%%}iJ<&Mt+IFk^n+OiiJ9;5XYuD3p&#LSX^5;?tFhdj`9BYA0}*n=QO^QbmM$kygv0#F^B|4R1%CRjSLtn;`mwovSl1xE?S>4hvTpQqjmv{cGyaSV=w#m3|5CH8dsh9Z0G_VD)qnJb zBjA||3i#|Be)S)98`LLDR1taTfK3Jw<+B$l?yU(yu_<2>rv(l?$`A3S{N=l_D<~f( z>fa@xlMG4l`Bwh7)Uq}pRchs@A~&obmGRT{zx4|H$U$TAsW9}Z4V?N99Mcu!9oK8_ zfb|eEX?1?GPP|%f&fj_$_QvP>vv>D?K3mXD?zbZq9zL#q!YlA-{jKhy4;ul`EQ6l# zjbHso7fts1@HvVcV$AJ-v}@xy02OK!PBXqzGfHWY8m&)r}R_FuT=m3{`qy1m!3wu$sUBM(moEW(T|U@7iu} z^2hz(6fEDo9)v%xU-BI6x?i0|093#}baLP;`QLg)`x6L#W-v3Rz4sp;+>g&5f+O?P zv_c62ipw7Wt`#RD!T?-yL;lT|Vm#rDKjXWc$^4-IBeK0_9N)Qq^rk$t{#}1;7q1qi z4;zAzrr8iLhVT7{R}9~DzleDA;R~f%4w1tj#&bStm2-dokym3dM_$QY|MA9xE5^<82N=#1>kU#Q%xVdXggjjJ6#iYW z$zZbFEBzTHS(+w=x+Y20U2_U?UGCuh9#F0=u-&uj=YT)%@CyGA@bB$5A)n2s*MeUC zNB0ZBAE;$r=}G-`hEGn>YM&(oW<`Ps>xWZ#YU-Z+2VRzuCG@TIXJq-sIVbP;yjm5> z3A6@^{ANtAO;er06lA{1U0r2BJM6VKkW`dpwmi|A5|NOhtVxUFApH}iu+#Nv4 zjnt1X2{_cJW)Wv?kMNV^*RFro=iY|He6*eLPm|~M{Uh7CudWHeBlMif@*n?_!Vi}O z9{&5w860bgR^5kRmAMY!)bwZF7C+464&-Xgk-_@Zrq8W^zNgK;arDnYk+AANG>zut z8HNP-(gX<{%yj!%z#6|3QA0&=2^19AMpsf(*mW`gFTg?EufJe;zZo zi&-oKee(<0Jer1ji+;6#~ zb2`2`{}bzeT09J$-g!&FD@4hB7Uci zRUXVy{gg&Mnm?SnGYnI|N&SaUMAZxcf0&>+OGV}|j;A89QRRgAv-r#U-y3u{fXA03 z89%JUT?@yz@Jw!3-mj-^VhIlVJN&8^&fuEa#p8!vH!-o|4EdJ7>!5~h`Bg2Hb{tOBjN#m`#)c*aBa89hBa=VHA zIDXh-ZhZ!F4c%~P@L}J7BqM>h#;1lLA=MOrB((*&9X0IL-{RDXNT@C32@l98W_fnL zT++Z*8U}x`R{k(k5dbptiP?|yw~Rtu2fU&Fj%=Sg=D#zPc;fx8=I7nv$&CPXn^W$$ z)X(4)e(47Yw|R!YBiqG?9qAr}+`aSumRm@3C?O5G1%~=zgvXbjJXC}^A`C;ai5!3t zEpH8#5D3GN%g6akmk_+a{+4pZ;S7J^iHUw&!D_D)GNdHMF#}%7l*S-#w;Tf^|us;_{91T%s7;eAKou)nj>-pQ*;9nI-?;y zWc+db!5<8tjr9HJ>@58qc|JAQe`f|} z1@c7Lh(jI|PYtC3L8f5}*cWP*`}0KpU=hyi$8;-h=uZ&O;Vk_n`E-B6F4Otf)n`!N z8S-WMZ2ffP`P5whof%mDftL~t!4N;}IdlwS@WY_rBZBHbA(Q$a#2+krmi{1~Lzq9s z|B`&VKVg^Y{Ojs7DDMv;yMd=KzyXYdKW1 z*ciuC5iMavOFRdd3zf{FlEub2o{DJ6Ccj&>f*(pGW(B|NC!Xa`W<~^OnZ*w`@Dp~K z&cDw8pnP+P!yc&5^ZGZ1dBR-(of(*CY1I#A`GPPFUUgnxCMzGA!q4J&i=OC@>nEP& ze`ZDm7R};E!Q?IG@~b9S)MpmI8Ic|w^P2Z-Q&LEn>wihkE$9HA_@OPRtKbi3^~5YY z5|`*sJq{Ag^6AM8-jLrdlJbY@=UH@$lm5Fi!gKFev;uSaS#OK#Q<}%Y_4PlljhS=( z54)o>`Qz`GJYf(CjHr4UQ5qRARK)S)_}wCk$MZq{xPIV?{s(3bC-S3g@)mRX$+oUO zv;NHpB=N<$;QiVZlN09pANYB2Jn??vhYsj=7##73OToiKkz{ZM36b0qL>`v zs?fed@>BTTq9^*}`hj&>=lu`N96pHug8D2i+6=&IDio4PMW4&1MsLoBxQ{F!{ZejIseeU?WU2}&6J zahB9a3{o-6<3mi@SnDry;nj9dR{&*(s%1<&sj^8bMqCc)5c&`6}oI_QJ zSA~KOAO=67(o{JmIf7z1$*+wF=*$KFw9XacIA-6U!}`NUdxsPK4_o_15aWsgup>96 zCy2-yU@rs2713Hm{3l#7rtZw|7V#9%)sM5_2ov?YIl{B}MHs*={tN0eDBn9|z0G~U z_G-xa6a5e5;r(LI@rw2S!(>@Rz$Ls{K3y$y6uCct@CQR2;YYvUZ?))98ab>0B>>fg0#Cs{J|E*!gG=nuPqkemb>Vn=L&CzkNk)Sv_b z#hJ_@*NPKCVF1s$8-MTzLkj-Uulvmw&AQ*r%*ZT$Rr0#}Y#rf1TyF}GFaH5H^&i-- zvt*Y45;$dNWb72m$WTpDp^)AMQ6>#4Awdu+FZ*AfC;#+WE z-4v#j35*|@Lw|@hE7P)X$Rr_h?#AEp2XRV;=G*FTiKoxA^tX1I!rvjE!VePhsH(5= zr**W!_{jS;NOdetzMZN6&epmb@N)~?3x9A^JigzQB4Jib^8NA%x8?7c!>K##?}*o} zP0`=k=p=ui8RRGV>BH*!?408K6dk}3^l|}Uc%FHL;iUf~Tkv+&e|S1P*=;C*PfpPa zpCtpACbCqN<{;;u`ZvW-^uNE?F@H8WC+denZl@wgWEOw_AX8@Pu)kkZXa`AF z+;7-g2Lw<90roorRvMcRhYGqsTI+1Y9{C`DaA5C{r{2`xr^Rx2qvcPZq%})zBm6px zt}@(jYYWA-5WshA`J;s`0G@UFsdg5B>j-n>a1}r7pL3Z<*rwla-jrM5$&>1i7{L?w zl~;L0{)oY611|X)gvqLZP%%hO!~;(`)GBDkat?{h{9iKYz7gk0_6IrH|6Ts@rnpz& zALr2xI@>Y*<)*9o%S}%Pp?R?WPj1v-?l*Gye*0Ve%>Dun=xs&O>UCp#@gd8J5tbA3 zxfV~xuXjTV0Z!^K#joZsH~k6zIPm*8pjRxszidI?VUWpW_8*^OFS_0|NupYvh1x=g zRC1}m6t5+V_{&XyfHqxi{xAO+KLr2afBhfvqoGd`bCy_7uKjf^ z{oB9$%hI1e{_^X1^>daV2TnME*1;cj9&{C8wiI9jKE3()D$f2o@6^)f1M;o=qMvN< z^chc?&zoYzXFIf75-ykb+gW&E3VT5n#gm^RgZ=}|Q+Gx$a0dR( z`oTSNiK=Usq|ftwsQ<`GUJ9PN6uPa;Ql@|>D-D40a8pd+6c{+nwrdrDCo`Wx#+B(h zeTm1F43IZn7va88CH?F6dNi~Ap;z!tSLXMK+0G3z6HhJ4o{aEgx$6nEeg3@TGa{Gw zAKYU$nU}6R;zckMLC$(m`MM*fAHKr6V)GdiPC!-GxK~KqPL2f~ix(pg%0vy#wH9 zbN8IEi(kpy7f(j;B<4^@!%#c&Tz&mq4yr!CI03Z8gZIa>tJycY-$iIU{!fp@`cF3B zeHIpww}|kEmk5k0{4kS%SZM?bD%ledlqAI&!IYK|h{}PmlEnjnV9CFiCuy~vRyh!M{T?j&#R=g0J$`451AhC{ z=ri74h|4B}sWSc@Z1f))P6IKNlK{kuP%VbK8Xkc|r$QtLwcIm-KghqRJa~4Rpu-B# zz(rg4Y29tep!4he?~CzSX`rg<^`pHe@{1E7==Z66VhHy7{B9JDM#O}&&y>MP`0790 z6wlxoA}CJQr-bp9;S`^g&8HVL*D4>$PvM_l9z473q9>(4)3@#uQUmXf@^oJkIsJb7 zk~CZTLsgJORm?f2UmM}z`~lBNesKb1{XTm)EI(yJY!|OC#BUxw%d}nn$FC0;fuY2} zL!agC@Um#Hu$BnOe`k0E|HRrj=Fda{9V%Xs-_B+C+fk*d)%Bx|0CY_!>(e<~`aS0k z7)ORwy|w~nW68nLYSfoPJTKJQwIdzl5KsOfNQD&1VbIJe-W{IGXY%9t<;)o%PXL5z z#h^cDcHdn4@%!CWNZ(Xc9J-Sy>(d4Jjqr|+`Qw~@{hs+L%#%{5P7N#QM$s|8K7qW$ z5VtZn;$Odi@qWYQ@|Gb9z!M~xBAF1@BG^gO6w~g>f4&}O`Ey=L$#9eVEww4g+VJwD zY(%E$*G2#!6%NG-~8{Ome>sUw&-6_nz4Zr%2`T+f>V-$la z0O{0_LFOnyvjAAaIM;Ft5d{Gd^d*ciK~GO`yqf=HG0fF}QcSs=Zo8$7NI4z$1jn=d zFSRL%UGRf_xiz#=p0v571NyZQ0LjnuJLiag&%YAOLmpWs({Rqd^$P1Yp~GO9GZhrb zIXo}7=DrjoNxBYRw5}U*{BTI%BovP)e|(CBe2Pt5D}n^l3OLCH{AVhG^5*J4qbIM0 zHhB&p{1N}NJVm4p!Xy%4mVRvnFpEEMlD4nkmt2GOS_zczSJ5$Ezkm5u*+`auVPW=-2Od4>?K=PLyQ)7pbQm%| z0eQ20mVY-2h~_MPWwDL&zP?M|0BCx*gL--f0C}(67+?2KZk7Ji%#MS5_8b2C_n$Tc z9xPEw8q{s-g^BlC$q6>CIXz{A?x6qjG3cz5Q73+~J}+D9g%@YMPIc30Hjzox~%?w{^v95S>c0et{Sfgt3(LjcQ!)(r(iV+$7E zQ2(_vKsqFTMSWg#)vIjN-Rj>a#nh7%MLp;GccXxb`pQ1*--Q=}XV2%>J(FKGJv9t_ z>H+?9|HKuik^3RIBjPsCk>K5NnuuEBPJNvIYX^X@gRCuuMF=n$kfBot>+_ncUS-SN z5m)%R+W(Gzn-o7=pB;UwoiwQc`MQzSVAh%-$gE}nN_Cu|vQ8b;ci~0g>H2K^<{2)W zHk@8@^9W>eG2TmVD9-@ZZt)IDf^Uvmrn$* zozLa1awOut^qBnT_YdE=w?V8L0bo9uhi{*$yiLu81R-!^AP$!1)D86yww@e+%Kt%= z(r#XVeF``>9;E61*=V}{dH*U*0WY7=tqbJPZ<~$3yM5FAbN?hq8cl!Gju^J}n78!- z%+fX9%{L-&_Ji~v_WeHfd1w`ahSL{20=A(5hx9A&=G#_*v+&R854o`QME!Wvb^zN= z*EfqZ{uMb1k{t=!7l-r;~_(rHyBpw^Njv})7kNi{#^h2Zkc6A_Z@0WE<+^;PKGXTFswRL{~-}} zoT%TnC>zl<%|LVL9l4DYijo147?YBzZGu$wl6>Kpd#J}G^G@?Cg9$-D;G-p#+>hD5GDKWx_rkJELsK4x*=zfvy% zKPy4}bZQU3ul?J@-!=mHTuQ$8M857HTn*kBc1Q4!?aT_qW)uLX1xWEu96rN)>hHAs zp8j_XGez&LHd)Y}#EZ+LP4V3jxRND2%Ch%|@b5OL@d7LulKg7?(l z>GeJR?-S1jBKmS+itVDDD3GTU{o>JNw^q-fg9q zc|W4R?H}9Mogep_SRXY5ru%R4C7#~jt-EFTyVaE6KivYpeXHjINF+Jtfxz3Wdk8ac zMF5atI+Yp!(JFCNA|5Tt$)ZIK^pH?1lHaem|tm>f(oHVB<_E*h-?83pmNPpPN z>;l}e@w4C8YxfVUhD&K(YVG%rhACYa5dR(VJOnHkHZ!x5gEPf!bAkts!*}X;Tfvyr z%zxbfrS(~gzacWQzwNfq_QdnwTYx9}j}&TouU{Hp|FgUQ&NEy!#kYEo~yb;^jG`}j{fy3#QA93J;S6vv@b?j^|7 zd3`s!0<=}J;AQ_TB=_a}HGNif5thnC&gf@tp1&8x^Z(#8TuSRwf9@alif3)(+`Kvt z*|)2jBNntEYkOhSR9@1Yk}t@Vg3E%+vjO}1!*+9r*;*&qa467o17`z>w=sj6k_pYBpk>9* z26Ql(jXF4R7^)z%fwRL}IO~_j;`h%$JM;S|`{E=&Z2WDb;Wo*vQ-CHoMbIh0o%Q<& z1z+Uf^D|w4@SkCNF{}PdaUvg~zh(ZScz+bL>f>i6n0|g#9xfJ#!*82mDD5#={QgNU z-VCu3Jk*V0Up|Sr%2|R@AOawGfBofYyvTnxx}rW;`@d9wDNcmLllPhPvn75}{6o(_ zUwulwb%6{Q&T^Q@5L}n~bN|>-n;VeQVIzPiL7v2ku#iH-9+xod02A z^MgO``&z#=9{pQ%ZXW(TUjFC)N$D((cTNL~4^4iCMmi`zL2&?2mJk=nQ4Nr{kvHoP z2Z`ZF_+NES89&bd=bj&q>!Q_wg&h^={{XzBb6h8O-#5oUN$_LdS!~F@15I`Ud{oKk4}J zO=ZZVnI*xq(Pa6VWeH%poK^CdgrC*#uV9HWuV<4Tk|Mh%o3Be|)n{q4BU)`B)(loP z`A+|s$&PJ1!&&uFKOmZ>{HssXSL^fbuBg9u_4NX7=5QSi!)Ds+G}^;v(+Se7WzdKO zQXrk7zeq9VLV_-L2?S{p-l=b8wg6@@8Hc(J02_Ia|1F=!V=`}Q%bTH70pQQlA3lWT zFv*%PDO(fs1vo1|z^MT6nffg4EhA_2aekeD^#|J&=X`zCPZ6S)A)3GX79?QV-*0zC z-9LT9gtPYxr&g_~eceB7jTxM1hJGc;ER9rVfeH9!-uds zyovu+Z_8kJB+hBd-ReKs=16?v`RQtZuK%rj!wV;XKU>TP@w$KLb>19KKyUyBgy3v~ z9q(CAb!J&R&{TkSL;c|^*cm2;AN0RtY;~%86nwY(FFjM+k2^mU_H)m_{vX^P8-KUT zjl@F1rq0^^le$s5<@rp6BjMY~Kpu(@Evr0H0mBj^5PbiL{_;cEiC`6y`@1yHQS_YL+`ruq_~`Sm|E+uD|9|wF?01G9@yB(sV*%km7JGV-(f%MW2c@=pKzPWETJyn4P*{g>wT_F3mAw)uiS-T%ss z@%`U_AUyt^v++yGj&q0b)u(7_HxHGh`@|_M@5BYoq3o`O#=H3}Nu<|8kS1u()%up@ zIKUD)l6c+@1E%;t?q`eH^~6#l?G1u7L36IC|EgiUWotm*?dMkhuddIJ=vpEU zCJRui;|2o~cPc}s=GN!iT~R-BaJXkt80;bx(e1b9s_t)R~9G;q@IC-D1&r|yz zBxB5er9t*cKnmymM`ufa->psrO5MaiHne9wDVlM?XZinoQPhv0he3W0@qR%5x_@#E zQZcHRT6J@+WP&_I;N%@X<#i!J2x#WbvpR)Brg(l1+J-11*$1D+we5><=tEI_L^uKj`_zOqSOoM`+{f5`>A3m8bSBhy>0~``G!q6ij zfS*|jM%YV1fJ69sH(yzSvs3iLG#(mr#-Yu{5acF*ZHTX|GfUnjq!B__0;hDXBakf z#C89qk3;Y5Db?mABuLpCi0w!K*i|2-fAH%#PCH(oAJf$|5OfPtMkLcYHaoC+*GFSWilMy(21^jzaeBC_HMjreYs{1F+qAwcoG_JOZU^p&hIYUHxp){sgxTLWpQUGWk7>CP+ zbM>G4Ob(Lw>vK@#Qd(+wUHxBhju}q^1*G+y1aQ;9KYo6e#^#>S_vk-++YEdzpS>&S z>;CDk*}G+qiOA#tP}OF#yd&Ybs^bHOCi7?YU-(##EU{djJBc4z{$>s>prM|MJvv+;fO z&wo2x3ajwMxrZ){)W|Je%%ey*M2&!*1W?;jgV zYMo&4aDg}sST5|fnUzer?yNtY+bf1ip9)+d{;T7izmBe92f@RYg6+Ouf;-q4<$LOTgnq$)rviN-Io=*uKnKCg^WWvlDxN`EHGrHW z`bq&@tJFY{7Qh1&yz~#B+3~uVb?vD0{r+iVoma;(=DTSf1ouLjPBA;g6kikWrTYgdC78E|L)K0?3vUClo zN@US8?3y%Y%0|$Ft}qd$U_w|eeg~BmJk;;yt9bB(ljtWt+1Hd!Hh`@G9hcmo$-(lc_}A(d(24tEn|S+ykhfq< zQ-z4+S&Ar5j`A}!(n0xd4ee9(w+fZ`o$Iq>yQk6%`XaDjb`y}dkycp6GZ5;ry7fu_JGM1{(*NofWP$l$lQK@wqbPw0{mPr6#WA7| zQ!Y0ikcZ`9MFJ9M_HFvBRZ8&w{?<5fmm`P z9b7%1OY_SJIxQs@WYbms5Hh7DfU6paB`4BB^_LEp5y^s<5(~0vGl?g%RCX!=tl{v3 zks5+bg)f1%h)5P_#)SdkaF#(M@7G_JD3SOfHH`&;Z{>g0{6zn&`jlc~eTH48>w7E( z*r;M4I=n&tRTm zY)|pODn7kF!!FbHDa94%b8x;h)I(?I2jy%47@A*`=8ZthJ50&LY=#Iz-m%wH?eHmm zx6?*ID+eQppUlc6i@XzY)*%s$4XZLGpS4Z<2>qc%pXGlr&#*f}I(hRv)!$X|>Gc_Q znXcc}2%e}vINu+>P=BmW@xSk_XD8MtQmq_J{kcQD8~`D6H~~GIRl`DOL(W5qmNciJ z-BZ6yG^F`){>deE<~ixVDrmKXv{e8f(Jb`nPg$#9N<^ zq%6k$0HI|_(coA>X9MK0mZ>lyGn-&9X*Fma8OT@bcZu9OelYe~{>cUN=lyqO#Po4i zeUuf<)sNbB=SR=SLClaKZ@s0SMgkhkVJ%a~>wnxE%xCpEW?TM;-AT!J9b{>ep?C;fM2#B=+rtYEIb6$qd#6ZQ3c z9N-~m{%z;yxHp&+>l3MAce3Wqg%Hd`r-JPi1ZjfiKz41WLgU?hmN0cU{Vvg``%f+t z>)(|TPt;Gfl@-j@zxsS?`#5;#`9JPT=G^)#3m9_GFlT_Lr}zxxga;b$L;`rbwwX-> z-(0^-6vH3wKeH)Sn0S|ON)y`%V6`duO&eyIQCVmGJMzl#H&sJ|4S?*HoZxthX} zV7imT#)lA-Hp{rd0GY?n=MfL994ZzYS~BA9*w&R+J5F%eLIu)vVE}4G)RC4r93$A{ z&041v0l1dkq4gU=-tOzdH|TeXaLDeu#a@O+0`BQQx!@LimNDQp|6Lq0vQ~o~U(i=@ z0JHSb$s2FhWTO7y{HbAFwIzHS33%E6Q#O|5>*~|WVAAyP7))d!XV?{kV6f}vRD$={ z@A?lZf1Lm1Vk5}qWc|B1;#vJwZ~(LPQ-Q0`=ivO=VK+;wq;C-dIEO@f32_$6f7Zj2 zuhgpkmYG%mgSb}B#fZzJAIuXPL-`plgM&y2@`owR-$#F_PllNP^-tsS-YQY1JR6iN z@2C2^R3<_T&g*YAaiacK3diHtkbEO+{?r>B{P_~6>xcjkJBIOlVN8~--q09Ri8Kb zUvA;4I9Z>iGLc#O*t_(6Zl&--oO2bo{SkQ@0X=123BIu1&XQU6U)`b;Ny_BA1k#ww zI}vGM-b@AiSVQ?s5OQygh%}UWGo`o-nQf7dNJDc=e_0|IwwlHS()RT;n9 zh(ni5)ZeO4;`jHzWqx9PQuCc%Y)y7#)9?w}tmY8x$d>q$`I^3dvZgJ&vvOD-CbSFzH`L!L4pVw2adNpyeRj;_ zc2@oOH#*bbedSsHqqA&WN;FGdFtnO%13<@)dM)ir6nU!Q$Vt2%f-t}he7cF1CE zR(q5rMr#4Tpmq%r#YB3rXKoKpX-EsVG4##{Aq;TDLB(R`=Q$~IemSK(+28Xveid$B z0k0Yk45!zi=ci|bhff~b`!m&*hF|u-YW`~d)lGkczZLlJR3KmOaLM>BcbxCqx2u}- b{-SX|w1+mcBOKkg=w-Q&M=UrOizh%1R%3mxz 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 Pe38F*D&_wKQwRPZ%kb7f diff --git a/rsc/scripts/door_utility.lua b/rsc/scripts/door_utility.lua deleted file mode 100644 index 49f272d..0000000 --- a/rsc/scripts/door_utility.lua +++ /dev/null @@ -1,89 +0,0 @@ ---[[ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ ---]] - ---DOCS: a placeholder door utility - -local doorUtility = {} - -roomAPI = require("room") -regionPagerAPI = require("region_pager") - -triggerAPI = require("trigger") -triggerManagerAPI = require("trigger_manager") - -entityAPI = require("entity") -characterAPI = require("character") - -networkAPI = require("network") - -function doorUtility.createTrigger(handle, room, x, y, script) - local pager = roomAPI.GetPager(room) - - --place the indicator tile - regionPagerAPI.SetTile(pager, x / 32, y / 32, 0, mapMaker.dirt) - regionPagerAPI.SetTile(pager, x / 32, y / 32, 1, mapMaker.blank) - regionPagerAPI.SetTile(pager, x / 32, y / 32, 2, mapMaker.blank) - - --create the trigger object - triggerManagerAPI.Create( - roomAPI.GetTriggerMgr(room), handle, x, y, - 0, 0, 32, 32, --size of the tiles - script - ) -end - -function doorUtility.createDoorPair(handle, roomOne, Xone, Yone, roomTwo, Xtwo, Ytwo) - --create the scripts - local function scriptOne(entity) - if entityAPI.GetType(entity) ~= "character" then return end - - --move the character - characterAPI.SetRoom(entity, roomTwo) - characterAPI.SetOrigin(entity, Xtwo, Ytwo-16) - networkAPI.PumpCharacterUpdate(entity) - - --disable the other trigger - local triggerTwo = triggerManagerAPI.GetTrigger(roomAPI.GetTriggerMgr(roomTwo), handle) - triggerAPI.PushExclusionEntity(triggerTwo, entity) - end - - local function scriptTwo(entity) - if entityAPI.GetType(entity) ~= "character" then return end - - --move the character - characterAPI.SetRoom(entity, roomOne) - characterAPI.SetOrigin(entity, Xone, Yone-16) --NOTE: the 16 pixel margin for presentation - networkAPI.PumpCharacterUpdate(entity) - - --disable the other trigger - local triggerOne = triggerManagerAPI.GetTrigger(roomAPI.GetTriggerMgr(roomOne), handle) - triggerAPI.PushExclusionEntity(triggerOne, entity) - end - - --create the triggers proper - doorUtility.createTrigger(handle, roomOne, Xone, Yone, scriptOne) - doorUtility.createTrigger(handle, roomTwo, Xtwo, Ytwo, scriptTwo) -end - -return doorUtility \ No newline at end of file diff --git a/rsc/scripts/map_maker.lua b/rsc/scripts/map_maker.lua deleted file mode 100644 index 596570f..0000000 --- a/rsc/scripts/map_maker.lua +++ /dev/null @@ -1,141 +0,0 @@ ---[[ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ ---]] - ---DOCS: a placeholder map generator - -local regionAPI = require("region") - -local mapMaker = {} - ---utility functions -function mapMaker.Sqr(x) return x*x end -function mapMaker.Dist(x, y, i, j) return math.sqrt(mapMaker.Sqr(x - i) + mapMaker.Sqr(y - j)) end - ---tile macros, mapped to the tilesheet "overworld.bmp" -mapMaker.blank = 0 -mapMaker.water = 18 + 3 * 0 -mapMaker.sand = 18 + 3 * 1 -mapMaker.plains = 18 + 3 * 2 -mapMaker.grass = 18 + 3 * 3 -mapMaker.dirt = 18 + 3 * 4 - ---"edge" macros -mapMaker.edges = {} -mapMaker.edges.north = -16 -mapMaker.edges.south = 16 -mapMaker.edges.east = 1 -mapMaker.edges.west = -1 - ---TODO: (1) path system ---use these macros (mapped to "overworld.bmp" for now) to smooth the region's edges -function mapMaker.SmoothEdgesSimple(r) - --make and pad an array to use - local shiftArray = {} - for i = 1, regionAPI.GetWidth(r) do - shiftArray[i] = {} - for j = 1, regionAPI.GetHeight(r) do - shiftArray[i][j] = 0 - end - end - - --build the array - for i = 1, regionAPI.GetWidth(r) do - for j = 1, regionAPI.GetHeight(r) do - --if (not regionAPI edge) and (west tile < this tile), etc. - if i > 1 and regionAPI.GetTile(r, i - 1, j, 1) < regionAPI.GetTile(r, i, j, 1) then - shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.west - end - if j > 1 and regionAPI.GetTile(r, i, j - 1, 1) < regionAPI.GetTile(r, i, j, 1) then - shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.north - end - if i < regionAPI.GetWidth(r) and regionAPI.GetTile(r, i + 1, j, 1) < regionAPI.GetTile(r, i, j, 1) then - shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.east - end - if j < regionAPI.GetHeight(r) and regionAPI.GetTile(r, i, j + 1, 1) < regionAPI.GetTile(r, i, j, 1) then - shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.south - end - end - end - - --finally apply this - for i = 1, regionAPI.GetWidth(r) do - for j = 1, regionAPI.GetHeight(r) do - if shiftArray[i][j] ~= 0 then - regionAPI.SetTile(r, i, j, 2, regionAPI.GetTile(r, i, j, 1) + shiftArray[i][j]) - regionAPI.SetTile(r, i, j, 1, regionAPI.GetTile(r, i, j, 1) - 3) - end - end - end -end - ---custom generation systems here -function mapMaker.DebugIsland(r) - --debug - io.write("map_maker:DebugIsland(", regionAPI.GetX(r), ", ", regionAPI.GetY(r), ")\n") - - --basic distance check for each tile, placing an island around the world origin - for i = 1, regionAPI.GetWidth(r) do - for j = 1, regionAPI.GetHeight(r) do - local dist = mapMaker.Dist(0, 0, i + regionAPI.GetX(r) -1, j + regionAPI.GetY(r) -1) - if dist < 10 then - regionAPI.SetTile(r, i, j, 1, mapMaker.plains) - elseif dist < 12 then - regionAPI.SetTile(r, i, j, 1, mapMaker.sand) - else - regionAPI.SetTile(r, i, j, 1, mapMaker.water) - regionAPI.SetSolid(r, i, j, true) - end - end - end - - --examples of the smoothing function NOT working correctly - --[[ - for j = 1, regionAPI.GetHeight(r) do - regionAPI.SetTile(r, 3, j, 1, mapMaker.dirt) - regionAPI.SetTile(r, 4, j, 1, mapMaker.dirt) - - regionAPI.SetTile(r, 10, j, 1, mapMaker.dirt) - end - --]] - - --A generic edge system - mapMaker.SmoothEdgesSimple(r) -end - -function mapMaker.DebugGrassland(r) - --debug - io.write("map_maker:DebugGrassland(", regionAPI.GetX(r), ", ", regionAPI.GetY(r), ")\n") - - --all dirt - for i = 1, regionAPI.GetWidth(r) do - for j = 1, regionAPI.GetHeight(r) do - regionAPI.SetTile(r, i, j, 1, mapMaker.grass) - end - end - - --A generic edge system --- mapMaker.SmoothEdgesSimple(r) -end - -return mapMaker \ No newline at end of file diff --git a/rsc/scripts/map_saver.lua b/rsc/scripts/map_saver.lua deleted file mode 100644 index f2f4ea0..0000000 --- a/rsc/scripts/map_saver.lua +++ /dev/null @@ -1,39 +0,0 @@ ---[[ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ ---]] - -local region = require("region") - -local mapSaver = {} - -function mapSaver.Load(r) - --empty --- io.write("map_saver:Load(", region.GetX(r), ", ", region.GetY(r), ")\n") -end -function mapSaver.Save(r) - --empty --- io.write("map_saver:Save(", region.GetX(r), ", ", region.GetY(r), ")\n") -end - ---TODO: (3) create a flexible saving & loading system -return mapSaver \ No newline at end of file diff --git a/rsc/scripts/setup_server.lua b/rsc/scripts/setup_server.lua deleted file mode 100644 index 4cb4972..0000000 --- a/rsc/scripts/setup_server.lua +++ /dev/null @@ -1,61 +0,0 @@ ---[[ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ ---]] - ---DOCS: This script is run by the server on startup - -print("Lua script check") - ---requirements -roomManagerAPI = require("room_manager") -roomAPI = require("room") - -mapMaker = require("map_maker") -mapSaver = require("map_saver") - -doorUtility = require("door_utility") - ---test the room hooks -roomManagerAPI.SetOnCreate(function(room, index) - print("", "Creating room: ", roomAPI.GetName(room), index) - - roomAPI.SetOnTick(room, function(room) - roomAPI.ForEachCharacter(room, function(character) - -- - end) - end) -end) - -roomManagerAPI.SetOnUnload(function(room, index) - print("", "Unloading room: ", roomAPI.GetName(room), index) -end) - ---NOTE: room 0 is the first that the client asks for, therefore it must exist -local overworld, uidOne = roomManagerAPI.CreateRoom("overworld", "overworld.bmp") -roomAPI.Initialize(overworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugIsland, mapSaver.Save) - -local underworld, uidTwo = roomManagerAPI.CreateRoom("underworld", "overworld.bmp") -roomAPI.Initialize(underworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugGrassland, mapSaver.Save) - ---call the monstrosity -doorUtility.createDoorPair("pair 1", overworld, -64, -64, underworld, 64, 64) diff --git a/rsc/scripts/setup_server.sql b/rsc/scripts/setup_server.sql deleted file mode 100644 index 1ef5983..0000000 --- a/rsc/scripts/setup_server.sql +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ - -CREATE TABLE IF NOT EXISTS UserAccounts ( - uid INTEGER PRIMARY KEY AUTOINCREMENT, - username varchar(100) UNIQUE, --TODO: (3) Swap username for email address - - --server-client security --- passhash varchar(100), --- passsalt varchar(100), - - --server controls - blacklisted BIT DEFAULT 0, - whitelisted BIT DEFAULT 1, - mod BIT DEFAULT 0, - admin BIT DEFAULT 0 -); - -CREATE TABLE IF NOT EXISTS LiveCharacters ( - uid INTEGER PRIMARY KEY AUTOINCREMENT, - - --metadata - owner INTEGER REFERENCES Accounts(uid), - handle varchar(100) UNIQUE, - avatar varchar(100), - birth timestamp NOT NULL DEFAULT (datetime()), - - --physically exists in the world - roomIndex INTEGER DEFAULT 0, - originX INTEGER DEFAULT 0, - originY INTEGER DEFAULT 0, - boundsX INTEGER DEFAULT 0, - boundsY INTEGER DEFAULT 0, - boundsW INTEGER DEFAULT 0, - boundsH INTEGER DEFAULT 0 -); - -CREATE TABLE IF NOT EXISTS DeadCharacters ( - uid INTEGER PRIMARY KEY, - - --metadata - owner INTEGER REFERENCES Accounts(uid), - handle varchar(100), - avatar varchar(100), - birth timestamp NOT NULL -); - -CREATE TABLE IF NOT EXISTS LiveMonsters ( - uid INTEGER PRIMARY KEY AUTOINCREMENT, - - --metadata - handle varchar(100) UNIQUE, - avatar varchar(100), - - --actions --- script - - --physically exists in the world - roomIndex INTEGER DEFAULT 0, - originX INTEGER DEFAULT 0, - originY INTEGER DEFAULT 0, - boundsX INTEGER DEFAULT 0, - boundsY INTEGER DEFAULT 0, - boundsW INTEGER DEFAULT 0, - boundsH INTEGER DEFAULT 0 -); - -CREATE TABLE IF NOT EXISTS DeadMonsters ( - uid INTEGER PRIMARY KEY, - - --metadata - handle varchar(100) UNIQUE, - avatar varchar(100) -); - -------------------------- ---Utility tables -------------------------- - -CREATE TABLE IF NOT EXISTS StatisticSets ( - --metadata - uid INTEGER PRIMARY KEY AUTOINCREMENT, - - --general use statistics - level INTEGER DEFAULT 0, - exp INTEGER DEFAULT 0, - maxHP INTEGER DEFAULT 0, - health INTEGER DEFAULT 0, - maxMP INTEGER DEFAULT 0, - mana INTEGER DEFAULT 0, - attack INTEGER DEFAULT 0, - defence INTEGER DEFAULT 0, - intelligence INTEGER DEFAULT 0, - resistance INTEGER DEFAULT 0, - speed INTEGER DEFAULT 0, - accuracy REAL DEFAULT 0.0, - evasion REAL DEFAULT 0.0, - luck REAL DEFAULT 0.0 -); - -CREATE TABLE IF NOT EXISTS InWorldItems ( - --metadata - uid INTEGER PRIMARY KEY AUTOINCREMENT, - itemType INTEGER, - - --position in the world - roomIndex INTEGER DEFAULT 0, - originX INTEGER DEFAULT 0, - originY INTEGER DEFAULT 0, - - --unique information - stackSize INTEGER DEFAULT 0, - durability INTEGER DEFAULT 0, - stats INTEGER REFERENCES StatisticSets(uid) -); - -CREATE TABLE IF NOT EXISTS InventoryItems ( - --metadata - uid INTEGER PRIMARY KEY AUTOINCREMENT, - owner INTEGER REFERENCES Characters(uid), - itemType INTEGER, - - --unique information - stackSize INTEGER DEFAULT 0, - durability INTEGER DEFAULT 0, - stats INTEGER REFERENCES StatisticSets(uid) -); - -CREATE TABLE IF NOT EXISTS WornEquipment ( - --metadata - uid INTEGER PRIMARY KEY AUTOINCREMENT, - owner INTEGER REFERENCES Characters(uid), - itemType INTEGER, - - --unique information - durability INTEGER DEFAULT 0, - stats INTEGER REFERENCES StatisticSets(uid) - --attached script? -); diff --git a/server/accounts/account_data.cpp b/server/accounts/account_data.cpp deleted file mode 100644 index 0ee36b0..0000000 --- a/server/accounts/account_data.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "account_data.hpp" - -int AccountData::SetClientIndex(int i) { - return clientIndex = i; -} - -int AccountData::GetClientIndex() { - return clientIndex; -} - -std::string AccountData::SetUsername(std::string s) { - return username = s; -} - -std::string AccountData::GetUsername() { - return username; -} - -bool AccountData::GetBlackListed() { - return blackListed; -} - -bool AccountData::GetWhiteListed() { - return whiteListed; -} - -bool AccountData::GetModerator() { - return mod; -} - -bool AccountData::GetAdministrator() { - return admin; -} \ No newline at end of file diff --git a/server/accounts/account_data.hpp b/server/accounts/account_data.hpp deleted file mode 100644 index 2feecd8..0000000 --- a/server/accounts/account_data.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include - -class AccountData { -public: - AccountData() = default; - ~AccountData() = default; - - //accessors and mutators - int SetClientIndex(int i); - int GetClientIndex(); - - std::string SetUsername(std::string s); - std::string GetUsername(); - - //database stuff - bool GetBlackListed(); - bool GetWhiteListed(); - bool GetModerator(); - bool GetAdministrator(); - -private: - friend class AccountManager; - - int clientIndex; - std::string username; - //password/auth token - - //bit fields? - bool blackListed = false; - bool whiteListed = true; - bool mod = false; - bool admin = false; -}; diff --git a/server/accounts/account_manager.cpp b/server/accounts/account_manager.cpp deleted file mode 100644 index bf67d41..0000000 --- a/server/accounts/account_manager.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "account_manager.hpp" - -#include - -//------------------------- -//Define the queries -//------------------------- - -static const char* CREATE_USER_ACCOUNT = "INSERT INTO UserAccounts (username) VALUES (?);"; - -static const char* LOAD_USER_ACCOUNT = "SELECT " - "uid, " - "blacklisted, " - "whitelisted, " - "mod, " - "admin " - " FROM UserAccounts WHERE username = ?;"; - -static const char* SAVE_USER_ACCOUNT = "UPDATE OR FAIL UserAccounts SET " - "blacklisted = ?2, " - "whitelisted = ?3, " - "mod = ?4, " - "admin = ?5 " - "WHERE uid = ?1;"; - -static const char* DELETE_USER_ACCOUNT = "DELETE FROM UserAccounts WHERE uid = ?;"; - -static const char* COUNT_USER_ACCOUNT_RECORDS = "SELECT COUNT(*) FROM UserAccounts;"; - -//------------------------- -//Define the public methods -//------------------------- - -//TODO: (1) block blacklisted accounts -int AccountManager::Create(std::string username, int clientIndex) { - //create this user account, failing if it exists, leave this account in memory - sqlite3_stmt* statement = nullptr; - - //prep - if (sqlite3_prepare_v2(database, CREATE_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); - } - - //parameter - if (sqlite3_bind_text(statement, 1, username.c_str(), username.size() + 1, SQLITE_STATIC) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) ); - } - - //execute - if (sqlite3_step(statement) != SQLITE_DONE) { - //if this fails, than this account exists - sqlite3_finalize(statement); - return -1; - } - - sqlite3_finalize(statement); - - //load this account into memory - return Load(username, clientIndex); -} - -int AccountManager::Load(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; - - //prep - if (sqlite3_prepare_v2(database, LOAD_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); - } - - //parameter - if (sqlite3_bind_text(statement, 1, username.c_str(), username.size() + 1, SQLITE_STATIC) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) ); - } - - //execute - int ret = sqlite3_step(statement); - - //process the result - if (ret == SQLITE_ROW) { - //get the index - int uid = sqlite3_column_int(statement, 0); - - //check to see if this account is already loaded - if (elementMap.find(uid) != elementMap.end()) { - sqlite3_finalize(statement); - return -1; - } - - //extract the data into memory - AccountData& newAccount = elementMap[uid]; - newAccount.username = username; - newAccount.blackListed = sqlite3_column_int(statement, 1); - newAccount.whiteListed = sqlite3_column_int(statement, 2); - newAccount.mod = sqlite3_column_int(statement, 3); - newAccount.admin = sqlite3_column_int(statement, 4); - newAccount.clientIndex = clientIndex; - - //finish the routine - sqlite3_finalize(statement); - return uid; - } - - sqlite3_finalize(statement); - - if (ret == SQLITE_DONE) { - //create the non-existant account instead - return Create(username, clientIndex); - } - - throw(std::runtime_error(std::string() + "Unknown SQL error in LoadAccount: " + sqlite3_errmsg(database) )); -} - -int AccountManager::Save(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. - - //this method fails if this account is not loaded - if (elementMap.find(uid) == elementMap.end()) { - return -1; - } - - AccountData& account = elementMap[uid]; - sqlite3_stmt* statement = nullptr; - - //prep - if (sqlite3_prepare_v2(database, SAVE_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); - } - - //parameters - bool ret = false; - ret |= sqlite3_bind_int(statement, 1, uid) != SQLITE_OK; - ret |= sqlite3_bind_int(statement, 2, account.blackListed) != SQLITE_OK; - ret |= sqlite3_bind_int(statement, 3, account.whiteListed) != SQLITE_OK; - ret |= sqlite3_bind_int(statement, 4, account.mod) != SQLITE_OK; - ret |= sqlite3_bind_int(statement, 5, account.admin) != SQLITE_OK; - - //check for binding errors - if (ret) { - throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) ); - } - - //execute - if (sqlite3_step(statement) != SQLITE_DONE) { - //if this fails, than something went horribly wrong - sqlite3_finalize(statement); - throw( std::runtime_error(std::string() + "Unknown SQL error when saving an account: " + sqlite3_errmsg(database)) ); - } - - sqlite3_finalize(statement); - - //successful execution - return 0; -} - -void AccountManager::Unload(int uid) { - //save this user account, and then unload it - //NOTE: the associated characters are unloaded externally - Save(uid); - elementMap.erase(uid); -} - -void AccountManager::Delete(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; - - //prep - if (sqlite3_prepare_v2(database, DELETE_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); - } - - //parameter - if (sqlite3_bind_int(statement, 1, uid) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) ); - } - - //execute - if (sqlite3_step(statement) != SQLITE_DONE) { - //if this fails, than something went horribly wrong - sqlite3_finalize(statement); - throw( std::runtime_error(std::string() + "Unknown SQL error when deleting an account: " + sqlite3_errmsg(database)) ); - } - - //finish the routine - sqlite3_finalize(statement); - elementMap.erase(uid); -} - -void AccountManager::UnloadAll() { - for (auto& it : elementMap) { - Save(it.first); - } - elementMap.clear(); -} - -void AccountManager::UnloadIf(std::function)> fn) { - //replicate std::remove_if, using custom code - std::map::iterator it = elementMap.begin(); - while (it != elementMap.end()) { - if (fn(*it)) { - Save(it->first); - it = elementMap.erase(it); - } - else { - ++it; - } - } -} - -//------------------------- -//Define the accessors and mutators -//------------------------- - -AccountData* AccountManager::Get(int uid) { - std::map::iterator it = elementMap.find(uid); - - if (it == elementMap.end()) { - return nullptr; - } - - return &it->second; -} - -int AccountManager::GetLoadedCount() { - return elementMap.size(); -} - -int AccountManager::GetTotalCount() { - //a lot just to count something. - sqlite3_stmt* statement = nullptr; - - //prep - if (sqlite3_prepare_v2(database, COUNT_USER_ACCOUNT_RECORDS, -1, &statement, nullptr) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); - } - - //execute & retrieve the result - sqlite3_step(statement); - int ret = sqlite3_column_int(statement, 0); - - //finish the routine - sqlite3_finalize(statement); - return ret; -} - -std::map* AccountManager::GetContainer() { - return &elementMap; -} - -sqlite3* AccountManager::SetDatabase(sqlite3* db) { - return database = db; -} - -sqlite3* AccountManager::GetDatabase() { - return database; -} diff --git a/server/accounts/account_manager.hpp b/server/accounts/account_manager.hpp deleted file mode 100644 index 9a3ca45..0000000 --- a/server/accounts/account_manager.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "account_data.hpp" -#include "singleton.hpp" - -#include "sqlite3.h" - -#include -#include - -class AccountManager: public Singleton { -public: - //common public methods - int Create(std::string username, int clientIndex); - int Load(std::string username, int clientIndex); - int Save(int uid); - void Unload(int uid); - void Delete(int uid); - - void UnloadAll(); - void UnloadIf(std::function)> fn); - - //accessors and mutators - AccountData* Get(int uid); - int GetLoadedCount(); - int GetTotalCount(); - std::map* GetContainer(); - - sqlite3* SetDatabase(sqlite3* db); - sqlite3* GetDatabase(); - -private: - friend Singleton; - - AccountManager() = default; - ~AccountManager() = default; - - //members - std::map elementMap; - sqlite3* database = nullptr; -}; diff --git a/server/accounts/makefile b/server/accounts/makefile deleted file mode 100644 index 635dbd4..0000000 --- a/server/accounts/makefile +++ /dev/null @@ -1,32 +0,0 @@ -#config -INCLUDES+=. ../server_utilities ../../common/utilities -LIBS+= -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=.. -OUT=$(addprefix $(OUTDIR)/,server.a) - -#targets -all: $(OBJ) $(OUT) - ar -crs $(OUT) $(OBJ) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/server/characters/character_api.cpp b/server/characters/character_api.cpp deleted file mode 100644 index 99b2cfe..0000000 --- a/server/characters/character_api.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "character_api.hpp" - -#include "character_data.hpp" -#include "character_manager.hpp" -#include "entity_api.hpp" -#include "room_manager.hpp" -#include "server_utilities.hpp" - -#include - -static int setRoom(lua_State* L) { - //reverse engineer the character index - int characterIndex = -1; - CharacterData* character = static_cast(lua_touserdata(L, 1)); - CharacterManager& characterMgr = CharacterManager::GetSingleton(); - - for (auto& it : *characterMgr.GetContainer()) { - if (character == &it.second) { - characterIndex = it.first; - break; - } - } - - //error checking - if (characterIndex == -1) { - throw(std::runtime_error("Lua Error: Failed to find character index by reference")); - } - - //get the room index, depending on the parameter type - int roomIndex = -1; - RoomManager& roomMgr = RoomManager::GetSingleton(); - switch(lua_type(L, 2)) { - case LUA_TNUMBER: - roomIndex = lua_tointeger(L, 2); - break; - case LUA_TLIGHTUSERDATA: - //reverse engineer the room index - for (auto& it : *roomMgr.GetContainer()) { - if (lua_touserdata(L, 2) == &it.second) { - roomIndex = it.first; - break; - } - } - break; - } - - //error checking - if (roomIndex == -1) { - throw(std::runtime_error("Lua Error: Failed to find room index by reference")); - } - - //send the delete & create messages - pumpAndChangeRooms(character, roomIndex, characterIndex); - return 0; -} - -static int getOwner(lua_State* L) { - CharacterData* character = static_cast(lua_touserdata(L, 1)); - lua_pushinteger(L, character->GetOwner()); - return 1; -} - -static int getHandle(lua_State* L) { - CharacterData* character = static_cast(lua_touserdata(L, 1)); - lua_pushstring(L, character->GetHandle().c_str()); - return 1; -} - -static int getAvatar(lua_State* L) { - CharacterData* character = static_cast(lua_touserdata(L, 1)); - lua_pushstring(L, character->GetAvatar().c_str()); - return 1; -} - -static const luaL_Reg characterLib[] = { - {"SetRoom", setRoom}, -// {"GetOwner", getOwner}, //unusable without account API - {"GetHandle", getHandle}, - {"GetAvatar", getAvatar}, - {nullptr, nullptr} -}; - -LUAMOD_API int openCharacterAPI(lua_State* L) { - //get the parent table - luaL_requiref(L, TORTUGA_ENTITY_API, openEntityAPI, false); - - //the local table - luaL_newlib(L, characterLib); - - //merge the local table into the parent table - lua_pushnil(L); //first key - while(lua_next(L, -2)) { - //copy the key-value pair - lua_pushvalue(L, -2); - lua_pushvalue(L, -2); - - //push the copy to the parent table - lua_settable(L, -6); - - //pop the original value before continuing - lua_pop(L, 1); - } - - //remove the local table, leaving the expanded parent table - lua_pop(L, 1); - - return 1; -} \ No newline at end of file diff --git a/server/characters/character_api.hpp b/server/characters/character_api.hpp deleted file mode 100644 index c8534e7..0000000 --- a/server/characters/character_api.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "lua.hpp" - -#define TORTUGA_CHARACTER_API "character" -LUAMOD_API int openCharacterAPI(lua_State* L); diff --git a/server/characters/character_data.cpp b/server/characters/character_data.cpp deleted file mode 100644 index 3d9d728..0000000 --- a/server/characters/character_data.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "character_data.hpp" - -CharacterData::CharacterData(): Entity("character") { - //EMPTY -} - -int CharacterData::GetOwner() { - return owner; -} - -std::string CharacterData::GetHandle() { - return handle; -} - -std::string CharacterData::GetAvatar() { - return avatar; -} \ No newline at end of file diff --git a/server/characters/character_data.hpp b/server/characters/character_data.hpp deleted file mode 100644 index ba10705..0000000 --- a/server/characters/character_data.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -//components -#include "character_defines.hpp" -#include "entity.hpp" - -//std namespace -#include -#include - -class CharacterData: public Entity { -public: - CharacterData(); - ~CharacterData() = default; - - //database stuff - int GetOwner(); - std::string GetHandle(); - std::string GetAvatar(); - -private: - friend class CharacterManager; - - int owner = -1; - std::string handle; - std::string avatar; -}; diff --git a/server/characters/character_manager.cpp b/server/characters/character_manager.cpp deleted file mode 100644 index 0108b43..0000000 --- a/server/characters/character_manager.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "character_manager.hpp" - -#include "sqlite3.h" - -#include "character_defines.hpp" - -#include -#include -#include - -//------------------------- -//Define the queries -//------------------------- - -//NOTE: Programmer set variables are NOT zero-indexed -//NOTE: SQLite3 returned variables (i.e. loading) ARE zero-indexed - -static const char* CREATE_CHARACTER = "INSERT INTO LiveCharacters (" - "owner, " - "handle, " - "avatar, " - "boundsX, " - "boundsY, " - "boundsW, " - "boundsH" - ") VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7);"; - -static const char* LOAD_CHARACTER = "SELECT " - "uid, " - "owner, " - "handle, " - "avatar, " - "roomIndex, " - "originX, " - "originY, " - "boundsX, " - "boundsY, " - "boundsW, " - "boundsH " - "FROM LiveCharacters WHERE handle = ?;"; - -static const char* SAVE_CHARACTER = "UPDATE OR FAIL LiveCharacters SET " - "roomIndex = ?2, " - "originX = ?3, " - "originY = ?4, " - "boundsX = ?5, " - "boundsY = ?6, " - "boundsW = ?7, " - "boundsH = ?8 " - "WHERE uid = ?1;"; - -static const char* DELETE_CHARACTER = "DELETE FROM LiveCharacters WHERE uid = ?;"; - -static const char* COUNT_CHARACTER_RECORDS = "SELECT COUNT(*) FROM LiveCharacters;"; - -//------------------------- -//Define the methods -//------------------------- - -//NOTE: default baseStats as a parameter would be good for different beggining states or multiple classes -int CharacterManager::Create(int owner, std::string handle, std::string avatar) { - //Create the character, failing if it exists - sqlite3_stmt* statement = nullptr; - - //prep - if (sqlite3_prepare_v2(database, CREATE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); - } - - //parameters - bool ret = false; - ret |= sqlite3_bind_int(statement, 1, owner); - ret |= sqlite3_bind_text(statement, 2, handle.c_str(), handle.size() + 1, SQLITE_STATIC); - ret |= sqlite3_bind_text(statement, 3, avatar.c_str(), avatar.size() + 1, SQLITE_STATIC); - ret |= sqlite3_bind_int(statement, 4, CHARACTER_BOUNDS_X); - ret |= sqlite3_bind_int(statement, 5, CHARACTER_BOUNDS_Y); - ret |= sqlite3_bind_int(statement, 6, CHARACTER_BOUNDS_WIDTH); - ret |= sqlite3_bind_int(statement, 7, CHARACTER_BOUNDS_HEIGHT); - - //check for binding errors - if (ret) { - throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) ); - } - - //execute - if (sqlite3_step(statement) != SQLITE_DONE) { - //if this fails, than this character exists - sqlite3_finalize(statement); - return -1; - } - - sqlite3_finalize(statement); - - //load this character into memory - return Load(owner, handle, avatar); -} - -int CharacterManager::Load(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; - - //prep - if (sqlite3_prepare_v2(database, LOAD_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); - } - - //parameter - if (sqlite3_bind_text(statement, 1, handle.c_str(), handle.size() + 1, SQLITE_STATIC) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) ); - } - - //execute - int ret = sqlite3_step(statement); - - //process the result - if (ret == SQLITE_ROW) { - //get the index - int uid = sqlite3_column_int(statement, 0); - - //check to see if this character is already loaded - if (elementMap.find(uid) != elementMap.end()) { - sqlite3_finalize(statement); - return -1; - } - - //check the owner - if (owner != sqlite3_column_int(statement, 1)) { - sqlite3_finalize(statement); - //unload the already loaded character - Unload(uid); - return -2; - } - - //extract the data into memory - CharacterData& newChar = elementMap[uid]; - - //metadata - newChar.owner = owner; - newChar.handle = reinterpret_cast(sqlite3_column_text(statement, 2)); - newChar.avatar = reinterpret_cast(sqlite3_column_text(statement, 3)); - //Don't cache the birth - - //world origin - newChar.roomIndex = sqlite3_column_int(statement, 4); - newChar.origin.x = (double)sqlite3_column_int(statement, 5); - newChar.origin.y = (double)sqlite3_column_int(statement, 6); - //bounds - newChar.bounds.x = (int)sqlite3_column_int(statement, 7); - newChar.bounds.y = (int)sqlite3_column_int(statement, 8); - newChar.bounds.w = (int)sqlite3_column_int(statement, 9); - newChar.bounds.h = (int)sqlite3_column_int(statement, 10); - - //gameplay components: equipment, items, buffs, debuffs... - - //finish the routine - sqlite3_finalize(statement); - return uid; - } - - sqlite3_finalize(statement); - - if (ret == SQLITE_DONE) { - //create the non-existant character instead - return Create(owner, handle, avatar); - } - - throw(std::runtime_error(std::string() + "Unknown SQL error in LoadCharacter: " + sqlite3_errmsg(database) )); -} - -int CharacterManager::Save(int uid) { - //save this character from memory, replacing it if it exists in the database - //DOCS: To use this method, change the in-memory copy, and then call this function using that object's UID. - - //this method fails if this character is not loaded - if (elementMap.find(uid) == elementMap.end()) { - return -1; - } - - CharacterData& character = elementMap[uid]; - sqlite3_stmt* statement = nullptr; - - //prep - if (sqlite3_prepare_v2(database, SAVE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); - } - - //parameters - bool ret = false; - ret |= sqlite3_bind_int(statement, 1, uid) != SQLITE_OK; - ret |= sqlite3_bind_int(statement, 2, character.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; - ret |= sqlite3_bind_int(statement, 5, character.bounds.x) != SQLITE_OK; - ret |= sqlite3_bind_int(statement, 6, character.bounds.y) != SQLITE_OK; - ret |= sqlite3_bind_int(statement, 7, character.bounds.w) != SQLITE_OK; - ret |= sqlite3_bind_int(statement, 8, character.bounds.h) != SQLITE_OK; - - //gameplay components: equipment, items, buffs, debuffs... - - //check for binding errors - if (ret) { - throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) ); - } - - //execute - if (sqlite3_step(statement) != SQLITE_DONE) { - //if this fails, than something went horribly wrong - sqlite3_finalize(statement); - throw( std::runtime_error(std::string() + "Unknown SQL error when saving a character: " + sqlite3_errmsg(database)) ); - } - - sqlite3_finalize(statement); - - //successful execution - return 0; -} - -void CharacterManager::Unload(int uid) { - //save this character, then unload it - Save(uid); - elementMap.erase(uid); -} - -void CharacterManager::Delete(int uid) { - //TODO: when deleting a character, move it to an archive table - //delete this character from the database, then remove it from memory - sqlite3_stmt* statement = nullptr; - - //prep - if (sqlite3_prepare_v2(database, DELETE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); - } - - //parameter - if (sqlite3_bind_int(statement, 1, uid) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) ); - } - - //execute - if (sqlite3_step(statement) != SQLITE_DONE) { - //if this fails, than something went horribly wrong - sqlite3_finalize(statement); - throw( std::runtime_error(std::string() + "Unknown SQL error when deleting a character: " + sqlite3_errmsg(database)) ); - } - - //finish the routine - sqlite3_finalize(statement); - elementMap.erase(uid); -} - -void CharacterManager::UnloadAll() { - for (auto& it : elementMap) { - Save(it.first); - } - elementMap.clear(); -} - -void CharacterManager::UnloadIf(std::function)> fn) { - std::map::iterator it = elementMap.begin(); - while (it != elementMap.end()) { - if (fn(*it)) { - Save(it->first); - it = elementMap.erase(it); - } - else { - ++it; - } - } -} - -//------------------------- -//Define the accessors and mutators -//------------------------- - -CharacterData* CharacterManager::Get(int uid) { - std::map::iterator it = elementMap.find(uid); - - if (it == elementMap.end()) { - return nullptr; - } - - return &it->second; -} - -CharacterData* CharacterManager::Get(std::string handle) { - for (std::map::iterator it = elementMap.begin(); it != elementMap.end(); ++it) { - if (it->second.GetHandle() == handle) { - return &it->second; - } - } - return nullptr; -} - -int CharacterManager::GetLoadedCount() { - return elementMap.size(); -} - -int CharacterManager::GetTotalCount() { - //a lot just to count something. - sqlite3_stmt* statement = nullptr; - - //prep - if (sqlite3_prepare_v2(database, COUNT_CHARACTER_RECORDS, -1, &statement, nullptr) != SQLITE_OK) { - throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); - } - - //execute & retrieve the result - sqlite3_step(statement); - int ret = sqlite3_column_int(statement, 0); - - //finish the routine - sqlite3_finalize(statement); - return ret; -} - -std::map* CharacterManager::GetContainer() { - return &elementMap; -} - -sqlite3* CharacterManager::SetDatabase(sqlite3* db) { - return database = db; -} - -sqlite3* CharacterManager::GetDatabase() { - return database; -} diff --git a/server/characters/character_manager.hpp b/server/characters/character_manager.hpp deleted file mode 100644 index 2d1f3e4..0000000 --- a/server/characters/character_manager.hpp +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "character_data.hpp" -#include "singleton.hpp" - -#include "sqlite3.h" - -#include -#include - -class CharacterManager: public Singleton { -public: - //common public methods - int Create(int owner, std::string handle, std::string avatar); - int Load(int owner, std::string handle, std::string avatar); - int Save(int uid); - void Unload(int uid); - void Delete(int uid); - - void UnloadAll(); - void UnloadIf(std::function)> fn); - - //accessors and mutators - CharacterData* Get(int uid); - CharacterData* Get(std::string handle); - int GetLoadedCount(); - int GetTotalCount(); - std::map* GetContainer(); - - //API interface - sqlite3* SetDatabase(sqlite3* db); - sqlite3* GetDatabase(); - - //hooks - //TODO: character hooks - -private: - friend Singleton; - - CharacterManager() = default; - ~CharacterManager() = default; - - //members - std::map elementMap; - sqlite3* database = nullptr; -}; diff --git a/server/characters/character_manager_api.cpp b/server/characters/character_manager_api.cpp deleted file mode 100644 index a853f39..0000000 --- a/server/characters/character_manager_api.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "character_manager_api.hpp" - -#include "character_manager.hpp" - -#include -#include - -//TODO: (1) character hooks? - -static int setOnCreate(lua_State* L) { - //TODO: (9) setOnCreate() -} - -static int setOnLoad(lua_State* L) { - //TODO: (9) setOnLoad() -} - -static int setOnSave(lua_State* L) { - //TODO: (9) setOnSave() -} - -static int setOnUnload(lua_State* L) { - //TODO: (9) setOnUnload() -} - -static int setOnDelete(lua_State* L) { - //TODO: (9) setOnDelete() -} - -static int getCharacter(lua_State* L) { - //integer vs name - CharacterManager& characterMgr = CharacterManager::GetSingleton(); - CharacterData* characterData = nullptr; - - switch(lua_type(L, 1)) { - case LUA_TNUMBER: - characterData = characterMgr.Get(lua_tointeger(L, 1)); - break; - case LUA_TSTRING: - //access characters via their handles - characterData = characterMgr.Get(lua_tostring(L, 1)); - break; - } - - if (characterData) { - lua_pushlightuserdata(L, static_cast(characterData)); - } - else { - lua_pushnil(L); - } - - return 1; -} - -static int getLoadedCount(lua_State* L) { - CharacterManager& characterMgr = CharacterManager::GetSingleton(); - lua_pushinteger(L, characterMgr.GetLoadedCount()); - return 1; -} - -static int forEach(lua_State* L) { - CharacterManager& characterMgr = CharacterManager::GetSingleton(); - //pass each character to the given function - for (auto& it : *characterMgr.GetContainer()) { - lua_pushvalue(L, -1); - lua_pushlightuserdata(L, static_cast(&it.second)); - //call each iteration, throwing an exception if something happened - if (lua_pcall(L, 1, 0, 0) != LUA_OK) { - std::ostringstream os; - os << "Lua error: "; - os << lua_tostring(L, -1); - throw(std::runtime_error(os.str())); - } - } - return 0; -} - -static const luaL_Reg characterManagerLib[] = { -// {"SetOnCreate", setOnCreate}, -// {"SetOnLoad", setOnLoad}, -// {"SetOnSave", setOnSave}, -// {"SetOnUnload", setOnUnload}, -// {"SetOnDelete", setOnDelete}, - {"GetCharacter", getCharacter}, - {"GetLoadedCount", getLoadedCount}, - {"ForEach", forEach}, - {nullptr, nullptr} -}; - -LUAMOD_API int openCharacterManagerAPI(lua_State* L) { - luaL_newlib(L, characterManagerLib); - return 1; -} \ No newline at end of file diff --git a/server/characters/character_manager_api.hpp b/server/characters/character_manager_api.hpp deleted file mode 100644 index 166251e..0000000 --- a/server/characters/character_manager_api.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "lua.hpp" - -#define TORTUGA_CHARACTER_MANAGER_API "character_manager" -LUAMOD_API int openCharacterManagerAPI(lua_State* L); diff --git a/server/characters/makefile b/server/characters/makefile deleted file mode 100644 index ecf6192..0000000 --- a/server/characters/makefile +++ /dev/null @@ -1,32 +0,0 @@ -#config -INCLUDES+=. ../entities ../monsters ../rooms ../server_utilities ../triggers ../../common/gameplay ../../common/map ../../common/network ../../common/network/packet_types ../../common/utilities -LIBS+= -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=.. -OUT=$(addprefix $(OUTDIR)/,server.a) - -#targets -all: $(OBJ) $(OUT) - ar -crs $(OUT) $(OBJ) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/server/clients/client_data.cpp b/server/clients/client_data.cpp deleted file mode 100644 index 1a549a4..0000000 --- a/server/clients/client_data.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "client_data.hpp" - -ClientData::ClientData(IPaddress add) { - address = add; -} - -IPaddress ClientData::SetAddress(IPaddress add) { - return address = add; -} - -IPaddress ClientData::GetAddress() { - return address; -} - -ClientData::Clock::time_point ClientData::GetLastBeat() { - return lastBeat; -} - -int ClientData::GetAttempts() { - return attemptedBeats; -} - -int ClientData::IncrementAttempts() { - lastBeat = Clock::now(); - return attemptedBeats++; -} - -int ClientData::ResetAttempts() { - lastBeat = Clock::now(); - return attemptedBeats = 0; -} \ No newline at end of file diff --git a/server/clients/client_data.hpp b/server/clients/client_data.hpp deleted file mode 100644 index bcf7cc8..0000000 --- a/server/clients/client_data.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "SDL_net.h" - -#include - -class ClientData { -public: - typedef std::chrono::steady_clock Clock; - - ClientData() = default; - ClientData(IPaddress add); - ~ClientData() = default; - - IPaddress SetAddress(IPaddress add); - IPaddress GetAddress(); - - Clock::time_point GetLastBeat(); - - int GetAttempts(); - int IncrementAttempts(); - int ResetAttempts(); - -private: - IPaddress address = {0,0}; - - Clock::time_point lastBeat = Clock::now(); - int attemptedBeats = 0; -}; diff --git a/server/clients/client_manager.cpp b/server/clients/client_manager.cpp deleted file mode 100644 index 80d6942..0000000 --- a/server/clients/client_manager.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "client_manager.hpp" - -#include "ip_operators.hpp" -#include "udp_network_utility.hpp" - -#include - -std::list ClientManager::CheckConnections() { - //list of clients to disconnect - std::list returnList; - - for (auto& it : elementMap) { - //3 seconds between beats - if (ClientData::Clock::now() - it.second.GetLastBeat() > std::chrono::seconds(3)) { - ServerPacket newPacket; - newPacket.type = SerialPacketType::PING; - UDPNetworkUtility::GetSingleton().SendTo(it.second.GetAddress(), &newPacket); - it.second.IncrementAttempts(); - } - } - - for (auto& it : elementMap) { - if (it.second.GetAttempts() > 2) { - returnList.push_back(it.first); - } - } - - return returnList; -} - -void ClientManager::HandlePong(ServerPacket* const argPacket) { - //find and update the specified client - for (auto& it : elementMap) { - if (it.second.GetAddress() == argPacket->srcAddress) { - it.second.ResetAttempts(); - return; - } - } -} - -int ClientManager::Create(IPaddress add) { - ClientData& client = elementMap[counter]; - client.SetAddress(add); - return counter++; -} - -void ClientManager::Unload(int uid) { - elementMap.erase(uid); -} - -void ClientManager::UnloadAll() { - elementMap.clear(); -} - -void ClientManager::UnloadIf(std::function)> fn) { - std::map::iterator it = elementMap.begin(); - while (it != elementMap.end()) { - if (fn(*it)) { - it = elementMap.erase(it); - } - else { - ++it; - } - } -} - -ClientData* ClientManager::Get(int uid) { - std::map::iterator it = elementMap.find(uid); - - if (it == elementMap.end()) { - return nullptr; - } - - return &it->second; -} - -int ClientManager::GetLoadedCount() { - return elementMap.size(); -} - -int ClientManager::GetTotalCount() { - return elementMap.size(); -} - -std::map* ClientManager::GetContainer() { - return &elementMap; -} \ No newline at end of file diff --git a/server/clients/client_manager.hpp b/server/clients/client_manager.hpp deleted file mode 100644 index 7a7b930..0000000 --- a/server/clients/client_manager.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "client_data.hpp" -#include "server_packet.hpp" -#include "singleton.hpp" - -#include "SDL_net.h" - -#include -#include -#include - -class ClientManager: public Singleton { -public: - //methods - std::list CheckConnections(); - void HandlePong(ServerPacket* const argPacket); - - //common public methods - int Create(IPaddress); - void Unload(int uid); - - void UnloadAll(); - void UnloadIf(std::function)> fn); - - //accessors & mutators - ClientData* Get(int uid); - int GetLoadedCount(); - int GetTotalCount(); - std::map* GetContainer(); - -private: - friend Singleton; - - ClientManager() = default; - ~ClientManager() = default; - - //members - std::map elementMap; - int counter = 0; -}; diff --git a/server/clients/makefile b/server/clients/makefile deleted file mode 100644 index 1384da7..0000000 --- a/server/clients/makefile +++ /dev/null @@ -1,32 +0,0 @@ -#config -INCLUDES+=. ../server_utilities ../../common/network ../../common/network/packet_types ../../common/utilities -LIBS+= -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=.. -OUT=$(addprefix $(OUTDIR)/,server.a) - -#targets -all: $(OBJ) $(OUT) - ar -crs $(OUT) $(OBJ) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/server/entities/entity.cpp b/server/entities/entity.cpp deleted file mode 100644 index dd3249d..0000000 --- a/server/entities/entity.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "entity.hpp" - -Entity::Entity(const char* _type): type(_type) { - //EMPTY -} - -void Entity::Update() { - origin += motion; -} - -int Entity::SetRoomIndex(int i) { - return roomIndex = i; -} - -Vector2 Entity::SetOrigin(Vector2 v) { - return origin = v; -} - -Vector2 Entity::SetMotion(Vector2 v) { - return motion = v; -} - -BoundingBox Entity::SetBounds(BoundingBox b) { - return bounds = b; -} - -int Entity::GetRoomIndex() const { - return roomIndex; -} - -Vector2 Entity::GetOrigin() const { - return origin; -} - -Vector2 Entity::GetMotion() const { - return motion; -} - -BoundingBox Entity::GetBounds() const { - return bounds; -} - -const char* Entity::GetType() const { - return type; -} \ No newline at end of file diff --git a/server/entities/entity.hpp b/server/entities/entity.hpp deleted file mode 100644 index 8ed7889..0000000 --- a/server/entities/entity.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "bounding_box.hpp" -#include "vector2.hpp" - -#include - -//The base class for all objects in the world -class Entity { -public: - virtual void Update(); - - //accessors & mutators - int SetRoomIndex(int i); - Vector2 SetOrigin(Vector2 v); - Vector2 SetMotion(Vector2 v); - BoundingBox SetBounds(BoundingBox b); - - int GetRoomIndex() const; - Vector2 GetOrigin() const; - Vector2 GetMotion() const; - BoundingBox GetBounds() const; - - const char* GetType() const; - -protected: - Entity(const char* type); - virtual ~Entity() = default; - - int roomIndex = -1; - Vector2 origin = {0, 0}; - Vector2 motion = {0, 0}; - BoundingBox bounds = {0, 0, 0, 0}; - const char* type; -}; diff --git a/server/entities/entity_api.cpp b/server/entities/entity_api.cpp deleted file mode 100644 index 13bda83..0000000 --- a/server/entities/entity_api.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "entity_api.hpp" - -#include "entity.hpp" - -static int setRoomIndex(lua_State* L) { - Entity* entity = static_cast(lua_touserdata(L, 1)); - entity->SetRoomIndex(lua_tointeger(L, 2)); - return 0; -} - -static int setOrigin(lua_State* L) { - Entity* entity = static_cast(lua_touserdata(L, 1)); - entity->SetOrigin({lua_tonumber(L, 2), lua_tonumber(L, 3)}); - return 0; -} - -static int setMotion(lua_State* L) { - Entity* entity = static_cast(lua_touserdata(L, 1)); - entity->SetMotion({lua_tonumber(L, 2), lua_tonumber(L, 3)}); - return 0; -} - -static int setBounds(lua_State* L) { - Entity* entity = static_cast(lua_touserdata(L, 1)); - entity->SetBounds({ - lua_tointeger(L, 2), - lua_tointeger(L, 3), - lua_tointeger(L, 4), - lua_tointeger(L, 5) - }); - return 0; -} - -static int getRoomIndex(lua_State* L) { - Entity* entity = static_cast(lua_touserdata(L, 1)); - lua_pushinteger(L, entity->GetRoomIndex()); - return 1; -} - -static int getOrigin(lua_State* L) { - Entity* entity = static_cast(lua_touserdata(L, 1)); - lua_pushnumber(L, entity->GetOrigin().x); - lua_pushnumber(L, entity->GetOrigin().y); - return 2; -} - -static int getMotion(lua_State* L) { - Entity* entity = static_cast(lua_touserdata(L, 1)); - lua_pushnumber(L, entity->GetMotion().x); - lua_pushnumber(L, entity->GetMotion().y); - return 2; -} - -static int getBounds(lua_State* L) { - Entity* entity = static_cast(lua_touserdata(L, 1)); - lua_pushinteger(L, entity->GetBounds().x); - lua_pushinteger(L, entity->GetBounds().y); - lua_pushinteger(L, entity->GetBounds().w); - lua_pushinteger(L, entity->GetBounds().h); - return 4; -} - -static int getType(lua_State* L) { - Entity* entity = static_cast(lua_touserdata(L, 1)); - lua_pushstring(L, entity->GetType()); - return 1; -} - -static const luaL_Reg entityLib[] = { - {"SetRoomIndex", setRoomIndex}, - {"SetOrigin", setOrigin}, - {"SetMotion", setMotion}, - {"SetBounds", setBounds}, - {"GetRoomIndex", getRoomIndex}, - {"GetOrigin", getOrigin}, - {"GetMotion", getMotion}, - {"GetBounds", getBounds}, - {"GetType", getType}, - {nullptr, nullptr} -}; - -LUAMOD_API int openEntityAPI(lua_State* L) { - luaL_newlib(L, entityLib); - return 1; -} \ No newline at end of file diff --git a/server/entities/entity_api.hpp b/server/entities/entity_api.hpp deleted file mode 100644 index cfd5dec..0000000 --- a/server/entities/entity_api.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "lua.hpp" - -#define TORTUGA_ENTITY_API "entity" -LUAMOD_API int openEntityAPI(lua_State* L); diff --git a/server/entities/makefile b/server/entities/makefile deleted file mode 100644 index 1b92ad0..0000000 --- a/server/entities/makefile +++ /dev/null @@ -1,32 +0,0 @@ -#config -INCLUDES+=. ../../common/utilities -LIBS+= -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=.. -OUT=$(addprefix $(OUTDIR)/,server.a) - -#targets -all: $(OBJ) $(OUT) - ar -crs $(OUT) $(OBJ) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/server/linit.cpp b/server/linit.cpp deleted file mode 100644 index f1c05bb..0000000 --- a/server/linit.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* $Id: linit.c,v 1.32, modified - * Initialization of libraries for lua.c and other clients - * See Copyright Notice in lua.h - * - * If you embed Lua in your program and need to open the standard - * libraries, call luaL_openlibs in your program. If you need a - * different set of libraries, copy this file to your project and edit - * it to suit your needs. - * - * Modified for use in Tortuga, renamed to linit.cpp - * Modifications are released under the zlib license: - * - * Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#define linit_c -#define LUA_LIB - -#include "lua.hpp" - -#include "entity_api.hpp" -#include "character_api.hpp" -#include "character_manager_api.hpp" -#include "region_api.hpp" -#include "region_pager_api.hpp" -//#include "monster_api.hpp" -//#include "monster_manager_api.hpp" -#include "network_api.hpp" -#include "room_api.hpp" -#include "room_manager_api.hpp" -#include "trigger_api.hpp" -#include "trigger_manager_api.hpp" - -//these libs are loaded by lua.c and are readily available to any Lua program -static const luaL_Reg loadedlibs[] = { - //Standard libs - {"_G", luaopen_base}, - {LUA_LOADLIBNAME, luaopen_package}, - {LUA_COLIBNAME, luaopen_coroutine}, - {LUA_TABLIBNAME, luaopen_table}, - {LUA_IOLIBNAME, luaopen_io}, - {LUA_OSLIBNAME, luaopen_os}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_BITLIBNAME, luaopen_bit32}, - {LUA_MATHLIBNAME, luaopen_math}, - {LUA_DBLIBNAME, luaopen_debug}, - {NULL, NULL} -}; - -//these libs are preloaded and must be required before used -static const luaL_Reg preloadedlibs[] = { - {TORTUGA_ENTITY_API, openEntityAPI}, //required by derived classes - {TORTUGA_CHARACTER_API, openCharacterAPI}, - {TORTUGA_CHARACTER_MANAGER_API, openCharacterManagerAPI}, -// {TORTUGA_MONSTER_API, openMonsterAPI}, -// {TORTUGA_MONSTER_MANAGER_API, openMonsterManagerAPI}, - {TORTUGA_NETWORK_API, openNetworkAPI}, - {TORTUGA_REGION_API, openRegionAPI}, - {TORTUGA_REGION_PAGER_API, openRegionPagerAPI}, - {TORTUGA_ROOM_API, openRoomAPI}, - {TORTUGA_ROOM_MANAGER_API, openRoomManagerAPI}, - {TORTUGA_TRIGGER_API, openTriggerAPI}, - {TORTUGA_TRIGGER_MANAGER_API, openTriggerManagerAPI}, - {NULL, NULL} -}; - -LUALIB_API void luaL_openlibs (lua_State *L) { - const luaL_Reg *lib; - //call open functions from 'loadedlibs' and set results to global table - for (lib = loadedlibs; lib->func; lib++) { - luaL_requiref(L, lib->name, lib->func, 1); - lua_pop(L, 1); //remove lib - } - //add open functions from 'preloadedlibs' into 'package.preload' table - luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); - for (lib = preloadedlibs; lib->func; lib++) { - lua_pushcfunction(L, lib->func); - lua_setfield(L, -2, lib->name); - } - lua_pop(L, 1); //remove _PRELOAD table -} diff --git a/server/main.cpp b/server/main.cpp deleted file mode 100644 index a69dfb0..0000000 --- a/server/main.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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" - -//singletons -#include "account_manager.hpp" -#include "character_manager.hpp" -#include "client_manager.hpp" -#include "config_utility.hpp" -#include "room_manager.hpp" -#include "udp_network_utility.hpp" - -#include -#include - -using namespace std; - -int main(int argc, char* argv[]) { - try { - //create the singletons - AccountManager::CreateSingleton(); - CharacterManager::CreateSingleton(); - ClientManager::CreateSingleton(); - ConfigUtility::CreateSingleton(); - RoomManager::CreateSingleton(); - UDPNetworkUtility::CreateSingleton(); - - //call the server's routines - ServerApplication::CreateSingleton(); - ServerApplication& app = ServerApplication::GetSingleton(); - - app.Init(argc, argv); - app.Proc(); - app.Quit(); - - ServerApplication::DeleteSingleton(); - - //delete the singletons - AccountManager::DeleteSingleton(); - CharacterManager::DeleteSingleton(); - ClientManager::DeleteSingleton(); - ConfigUtility::DeleteSingleton(); - RoomManager::DeleteSingleton(); - UDPNetworkUtility::DeleteSingleton(); - } - catch(exception& e) { - cerr << "Fatal exception thrown: " << e.what() << endl; - return 1; - } - return 0; -} \ No newline at end of file diff --git a/server/makefile b/server/makefile deleted file mode 100644 index fd5b942..0000000 --- a/server/makefile +++ /dev/null @@ -1,64 +0,0 @@ -#include directories -INCLUDES+=SDL . accounts characters clients entities rooms server_utilities triggers ../common/debugging ../common/gameplay ../common/map ../common/network ../common/network/packet_types ../common/utilities - -#libraries -#the order of the $(LIBS) is important, at least for MinGW -LIBS+=server.a ../libcommon.a -lSDL_net -ifeq ($(OS),Windows_NT) - LIBS+=-lwsock32 -liphlpapi -lmingw32 -endif -LIBS+=-lSDLmain -lSDL -llua -lsqlite3 -ifeq ($(shell uname), Linux) - #I don't know what this does, but Ubuntu needs it (dynamic linking for lua) - LIBS+=-ldl -endif - -#flags -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=../out -OUT=$(addprefix $(OUTDIR)/,server) - -#targets -all: $(OBJ) $(OUT) - $(MAKE) -C accounts - $(MAKE) -C characters - $(MAKE) -C clients - $(MAKE) -C entities -# $(MAKE) -C monsters - $(MAKE) -C rooms - $(MAKE) -C server_utilities - $(MAKE) -C triggers - $(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< - -clean: -ifeq ($(OS),Windows_NT) - $(RM) *.o *.a *.exe -else ifeq ($(shell uname), Linux) - find . -type f -name *.o -exec rm -f -r -v {} \; - find . -type f -name *.a -exec rm -f -r -v {} \; - rm -f -v out/client out/server -endif - -rebuild: clean all diff --git a/server/monsters/makefile b/server/monsters/makefile deleted file mode 100644 index efc3852..0000000 --- a/server/monsters/makefile +++ /dev/null @@ -1,32 +0,0 @@ -#config -INCLUDES+=. ../entities ../server_utilities ../../common/gameplay ../../common/utilities -LIBS+= -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=.. -OUT=$(addprefix $(OUTDIR)/,server.a) - -#targets -all: $(OBJ) $(OUT) - ar -crs $(OUT) $(OBJ) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/server/monsters/monster_api.cpp b/server/monsters/monster_api.cpp deleted file mode 100644 index c5c4d93..0000000 --- a/server/monsters/monster_api.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "monster_api.hpp" - -#include "monster_data.hpp" - -#include "entity_api.hpp" - -static int setAvatar(lua_State* L) { - MonsterData* monster = static_cast(lua_touserdata(L, 1)); - monster->SetAvatar(lua_tostring(L, 2)); - //TODO: (1) send an update to the clients? - return 0; -} - -static int getAvatar(lua_State* L) { - MonsterData* monster = static_cast(lua_touserdata(L, 1)); - lua_pushstring(L, monster->GetAvatar().c_str()); - return 1; -} - -static int setScript(lua_State* L) { - MonsterData* monster = static_cast(lua_touserdata(L, 1)); - luaL_unref(L, LUA_REGISTRYINDEX, monster->GetScriptReference()); - monster->SetScriptReference(luaL_ref(L, LUA_REGISTRYINDEX)); - return 0; -} - -static int getScript(lua_State* L) { - MonsterData* monster = static_cast(lua_touserdata(L, 1)); - lua_pushinteger(L, monster->GetScriptReference()); - lua_gettable(L, LUA_REGISTRYINDEX); - return 1; -} - -static const luaL_Reg monsterLib[] = { - {"SetAvatar", setAvatar}, - {"GetAvatar", getAvatar}, - {"SetScript", setScript}, - {"GetScript", getScript}, - {nullptr, nullptr} -}; - -LUAMOD_API int openMonsterAPI(lua_State* L) { - //get the parent table - luaL_requiref(L, TORTUGA_ENTITY_API, openEntityAPI, false); - - //the local table - luaL_newlib(L, monsterLib); - - //merge the local table into the parent table - lua_pushnil(L); //first key - while(lua_next(L, -2)) { - //copy the key-value pair - lua_pushvalue(L, -2); - lua_pushvalue(L, -2); - - //push the copy to the parent table - lua_settable(L, -6); - - //pop the original value before continuing - lua_pop(L, 1); - } - - //remove the local table, leaving the expanded parent table - lua_pop(L, 1); - - return 1; -} \ No newline at end of file diff --git a/server/monsters/monster_api.hpp b/server/monsters/monster_api.hpp deleted file mode 100644 index 73d535d..0000000 --- a/server/monsters/monster_api.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "lua.hpp" - -#define TORTUGA_MONSTER_API "monster" -LUAMOD_API int openMonsterAPI(lua_State* L); diff --git a/server/monsters/monster_data.cpp b/server/monsters/monster_data.cpp deleted file mode 100644 index d2d6abf..0000000 --- a/server/monsters/monster_data.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "monster_data.hpp" - -MonsterData::MonsterData(std::string _avatar, int _scriptRef): - Entity("monster"), - avatar(_avatar), - scriptRef(_scriptRef) -{ - //EMPTY -} - -void MonsterData::Update() { - Entity::Update(); - //TODO: (0) call the script reference -} - -//------------------------- -//accessors & mutators -//------------------------- - -std::string MonsterData::SetAvatar(std::string s) { - return avatar = s; -} - -std::string MonsterData::GetAvatar() { - return avatar; -} - -int MonsterData::SetScriptReference(int i) { - return scriptRef = i; -} - -int MonsterData::GetScriptReference() { - return scriptRef; -} \ No newline at end of file diff --git a/server/monsters/monster_data.hpp b/server/monsters/monster_data.hpp deleted file mode 100644 index aac2d03..0000000 --- a/server/monsters/monster_data.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "entity.hpp" - -#include "lua.hpp" - -#include - -/* DOCS: Monster attributes, read more - * species (avatar, script) - * level - * health/mana - * permadeath/respawn -*/ - -class MonsterData: public Entity { -public: - MonsterData(std::string avatar, int scriptRef); - ~MonsterData() = default; - - virtual void Update(); - - //accessors & mutators - - std::string SetAvatar(std::string); - std::string GetAvatar(); - - int SetScriptReference(int); - int GetScriptReference(); - -private: - friend class MonsterManager; - - std::string avatar; - int scriptRef = LUA_NOREF; -}; diff --git a/server/monsters/monster_manager.cpp b/server/monsters/monster_manager.cpp deleted file mode 100644 index 7f9a11a..0000000 --- a/server/monsters/monster_manager.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "monster_manager.hpp" - -MonsterManager::MonsterManager() { - //EMPTY -} - -MonsterManager::~MonsterManager() { - UnloadAll(); -} - -int MonsterManager::Create(std::string avatar, int scriptRef) { - //implicitly create the new - elementMap.emplace(counter, MonsterData(avatar, scriptRef)); - - //TODO: do various things like saving to the database - return counter++; -} - -//TODO: (1) monster load, save - -void MonsterManager::Unload(int uid) { - elementMap.erase(uid); -} - -void MonsterManager::UnloadAll() { - elementMap.clear(); -} - -void MonsterManager::UnloadIf(std::function)> fn) { - std::map::iterator it = elementMap.begin(); - while (it != elementMap.end()) { - if (fn(*it)) { - it = elementMap.erase(it); - } - else { - ++it; - } - } -} - -MonsterData* MonsterManager::Get(int uid) { - std::map::iterator it = elementMap.find(uid); - - if (it == elementMap.end()) { - return nullptr; - } - - return &it->second; -} - -int MonsterManager::GetLoadedCount() { - return elementMap.size(); -} - -std::map* MonsterManager::GetContainer() { - return &elementMap; -} - -lua_State* MonsterManager::SetLuaState(lua_State* L) { - return lua = L; -} - -lua_State* MonsterManager::GetLuaState() { - return lua; -} - -sqlite3* MonsterManager::SetDatabase(sqlite3* db) { - return database = db; -} - -sqlite3* MonsterManager::GetDatabase() { - return database; -} diff --git a/server/monsters/monster_manager.hpp b/server/monsters/monster_manager.hpp deleted file mode 100644 index 76b8ffa..0000000 --- a/server/monsters/monster_manager.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "monster_data.hpp" - -#include "lua.hpp" -#include "sqlite3.h" - -#include -#include -#include - -class MonsterManager { -public: - MonsterManager(); - ~MonsterManager(); - - //common public methods - int Create(std::string avatar, int scriptRef); - void Unload(int uid); - - void UnloadAll(); - void UnloadIf(std::function)> fn); - - //accessors & mutators - MonsterData* Get(int uid); - int GetLoadedCount(); - std::map* GetContainer(); - - //hooks - lua_State* SetLuaState(lua_State* L); - lua_State* GetLuaState(); - sqlite3* SetDatabase(sqlite3* db); - sqlite3* GetDatabase(); - -private: - //members - std::map elementMap; - int counter = 0; - lua_State* lua = nullptr; - sqlite3* database = nullptr; -}; diff --git a/server/monsters/monster_manager_api.cpp b/server/monsters/monster_manager_api.cpp deleted file mode 100644 index 08be549..0000000 --- a/server/monsters/monster_manager_api.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "monster_manager_api.hpp" - -#include "monster_manager.hpp" - -static int create(lua_State* L) { - MonsterManager* mgr = static_cast(lua_touserdata(L, 1)); - int index = mgr->Create(lua_tostring(L, 2), lua_tointeger(L, 3)); - MonsterData* monster = mgr->Get(index); - lua_pushlightuserdata(L, static_cast(monster)); - lua_pushinteger(L, index); - return 2; -} - -//TOOD: this needs to take the userdata as a parameter too -static int unload(lua_State* L) { - MonsterManager* mgr = static_cast(lua_touserdata(L, 1)); - mgr->Unload(lua_tointeger(L, 2)); - return 0; -} - -static int unloadAll(lua_State* L) { - MonsterManager* mgr = static_cast(lua_touserdata(L, 1)); - mgr->UnloadAll(); - return 0; -} - -static int unloadIf(lua_State* L) { - MonsterManager* mgr = static_cast(lua_touserdata(L, 1)); - //TODO: unloadIf - return 0; -} - -static int get(lua_State* L) { - MonsterManager* mgr = static_cast(lua_touserdata(L, 1)); - MonsterData* monster = mgr->Get(lua_tointeger(L, 2)); - lua_pushlightuserdata(L, static_cast(monster)); - return 1; -} - -static int getLoadedCount(lua_State* L) { - MonsterManager* mgr = static_cast(lua_touserdata(L, 1)); - lua_pushinteger(L, mgr->GetLoadedCount()); - return 1; -} - -static const luaL_Reg monsterManagerLib[] = { - {"Create", create}, - {"Unload", unload}, - {"UnloadAll", unloadAll}, -// {"UnloadIf", unloadIf}, - {"Get", get}, - {"GetLoadedCount", getLoadedCount}, - {nullptr, nullptr} -}; - -LUAMOD_API int openMonsterManagerAPI(lua_State* L) { - luaL_newlib(L, monsterManagerLib); - return 1; -} \ No newline at end of file diff --git a/server/monsters/monster_manager_api.hpp b/server/monsters/monster_manager_api.hpp deleted file mode 100644 index 218246c..0000000 --- a/server/monsters/monster_manager_api.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "lua.hpp" - -#define TORTUGA_MONSTER_MANAGER_API "monster_manager" -LUAMOD_API int openMonsterManagerAPI(lua_State* L); diff --git a/server/rooms/makefile b/server/rooms/makefile deleted file mode 100644 index 048c575..0000000 --- a/server/rooms/makefile +++ /dev/null @@ -1,32 +0,0 @@ -#config -INCLUDES+=. ../characters ../entities ../monsters ../server_utilities ../triggers ../../common/gameplay ../../common/map ../../common/utilities -LIBS+= -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=.. -OUT=$(addprefix $(OUTDIR)/,server.a) - -#targets -all: $(OBJ) $(OUT) - ar -crs $(OUT) $(OBJ) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/server/rooms/room_api.cpp b/server/rooms/room_api.cpp deleted file mode 100644 index 9aad030..0000000 --- a/server/rooms/room_api.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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_api.hpp" - -#include "room_data.hpp" - -#include -#include - -static int setRoomName(lua_State* L) { - RoomData* room = reinterpret_cast(lua_touserdata(L, 1)); - room->SetName(lua_tostring(L, 2)); - return 0; -} - -static int getRoomName(lua_State* L) { - RoomData* room = reinterpret_cast(lua_touserdata(L, 1)); - lua_pushstring(L, room->GetName().c_str()); - return 1; -} - -static int setTilesetName(lua_State* L) { - RoomData* room = reinterpret_cast(lua_touserdata(L, 1)); - room->SetTileset(lua_tostring(L, 2)); - return 0; -} - -static int getTilesetName(lua_State* L) { - RoomData* room = reinterpret_cast(lua_touserdata(L, 1)); - lua_pushstring(L, room->GetTileset().c_str()); - return 1; -} - -static int getPager(lua_State* L) { - RoomData* room = reinterpret_cast(lua_touserdata(L, 1)); - lua_pushlightuserdata(L, reinterpret_cast(room->GetPager()) ); - return 1; -} - -/* -static int getMonsterMgr(lua_State* L) { - RoomData* room = reinterpret_cast(lua_touserdata(L, 1)); - lua_pushlightuserdata(L, reinterpret_cast(room->GetMonsterMgr()) ); - return 1; -} -*/ - -static int getTriggerMgr(lua_State* L) { - RoomData* room = reinterpret_cast(lua_touserdata(L, 1)); - lua_pushlightuserdata(L, reinterpret_cast(room->GetTriggerMgr()) ); - return 1; -} - -static int forEachCharacter(lua_State* L) { - RoomData* room = reinterpret_cast(lua_touserdata(L, 1)); - //pass each character to the given function - for (auto& it : *room->GetCharacterList()) { - lua_pushvalue(L, -1); - lua_pushlightuserdata(L, static_cast(it)); - //call each iteration, throwing an exception if something happened - if (lua_pcall(L, 1, 0, 0) != LUA_OK) { - std::ostringstream os; - os << "Lua error: "; - os << lua_tostring(L, -1); - throw(std::runtime_error(os.str())); - } - } - return 0; -} - -/* -static int forEachMonster(lua_State* L) { - RoomData* room = reinterpret_cast(lua_touserdata(L, 1)); - MonsterManager* monsterMgr = room->GetMonsterMgr(); - //pass each monster to the given function - for (auto& it : *monsterMgr->GetContainer()) { - lua_pushvalue(L, -1); - lua_pushlightuserdata(L, static_cast(&it.second)); - //call each iteration, throwing an exception if something happened - if (lua_pcall(L, 1, 0, 0) != LUA_OK) { - std::ostringstream os; - os << "Lua error: "; - os << lua_tostring(L, -1); - throw(std::runtime_error(os.str())); - } - } - return 0; -} -*/ - -static int setOnTick(lua_State* L) { - RoomData* room = reinterpret_cast(lua_touserdata(L, 1)); - luaL_unref(L, LUA_REGISTRYINDEX, room->GetTickReference()); - room->SetTickReference(luaL_ref(L, LUA_REGISTRYINDEX)); - return 0; -} - -static int getOnTick(lua_State* L) { - RoomData* room = reinterpret_cast(lua_touserdata(L, 1)); - lua_rawgeti(L, LUA_REGISTRYINDEX, room->GetTickReference()); - return 1; -} - -static int initialize(lua_State* L) { - RoomData* room = static_cast(lua_touserdata(L, 1)); - - //set the refs of these parameters (backwards, since it pops from the top of the stack) - room->GetPager()->SetUnloadReference(luaL_ref(L, LUA_REGISTRYINDEX)); - room->GetPager()->SetCreateReference(luaL_ref(L, LUA_REGISTRYINDEX)); - room->GetPager()->SetSaveReference(luaL_ref(L, LUA_REGISTRYINDEX)); - room->GetPager()->SetLoadReference(luaL_ref(L, LUA_REGISTRYINDEX)); - - //more parameters can be added here later - return 0; -} - -static const luaL_Reg roomLib[] = { - {"SetName", setRoomName}, - {"GetName", getRoomName}, - {"SetTileset", setTilesetName}, - {"GetTileset", getTilesetName}, - - {"GetPager",getPager}, -// {"GetMonsterMgr",getMonsterMgr}, - {"GetTriggerMgr",getTriggerMgr}, - - {"ForEachCharacter", forEachCharacter}, -// {"ForEachMonster", forEachMonster}, - - {"SetOnTick", setOnTick}, - {"GetOnTick", getOnTick}, - - {"Initialize", initialize}, - {nullptr, nullptr} -}; - -LUAMOD_API int openRoomAPI(lua_State* L) { - luaL_newlib(L, roomLib); - return 1; -} \ No newline at end of file diff --git a/server/rooms/room_api.hpp b/server/rooms/room_api.hpp deleted file mode 100644 index b3af811..0000000 --- a/server/rooms/room_api.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "lua.hpp" - -#define TORTUGA_ROOM_API "room" -LUAMOD_API int openRoomAPI(lua_State* L); diff --git a/server/rooms/room_data.cpp b/server/rooms/room_data.cpp deleted file mode 100644 index cb6e8e0..0000000 --- a/server/rooms/room_data.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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_data.hpp" - -#include -#include -#include -#include - -//TODO: (9) character collisions should be preformed client-side -void RoomData::RunFrame() { - //get the hook - lua_rawgeti(lua, LUA_REGISTRYINDEX, tickRef); - - if (!lua_isnil(lua, -1)) { - //call the tick function, with this as a parameter - lua_pushlightuserdata(lua, this); - if (lua_pcall(lua, 1, 0, 0) != LUA_OK) { - throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) )); - } - } - else { - lua_pop(lua, 1); - } - - //update the entities in the room - for (auto& it : characterList) { - it->Update(); - } - //TODO: (3) iterate through the monster map - //TODO: (3) trigger script for monsters - - //build a list of game entities - std::stack entityStack; - for (auto& it : characterList) { - entityStack.push(it); - } - //TODO: (3) push the monster entities - - //compare the triggers to the entities, using their real hitboxes - //NOTE: this stack solution should prevent problems when modifying the various lists - while(entityStack.size()) { - //get the entity & hitbox - Entity* entity = entityStack.top(); - BoundingBox entityBox = entity->GetBounds() + entity->GetOrigin(); - - //get the trigger pair & hitbox - for (auto& triggerPair : *triggerMgr.GetContainer()) { - BoundingBox triggerBox = triggerPair.second.GetBoundingBox() + triggerPair.second.GetOrigin(); - - //find all collisions - if (entityBox.CheckOverlap(triggerBox)) { - //skip members of the exclusion list - if (std::any_of(triggerPair.second.GetExclusionList()->begin(), triggerPair.second.GetExclusionList()->end(), [entity](Entity* ptr) -> bool { - return entity == ptr; - })) { - continue; - } - - //run the trigger script - lua_rawgeti(lua, LUA_REGISTRYINDEX, triggerPair.second.GetScriptReference()); - lua_pushlightuserdata(lua, entity); - - if (lua_pcall(lua, 1, 0, 0) != LUA_OK) { - //error - throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) )); - } - - //push to the exclusion list - triggerPair.second.GetExclusionList()->push_back(entity); - } - else { - //remove members of the exclusion list - //NOTE: characters in different rooms won't be removed, but that shouldn't be a problem - triggerPair.second.GetExclusionList()->remove_if([entity](Entity* ptr) -> bool { - return entity == ptr; - }); - } - } - - //next - entityStack.pop(); - } -} - -std::string RoomData::SetName(std::string s) { - return roomName = s; -} - -std::string RoomData::GetName() { - return roomName; -} - -std::string RoomData::SetTileset(std::string s) { - return tilesetName = s; -} - -std::string RoomData::GetTileset() { - return tilesetName; -} - -RegionPagerLua* RoomData::GetPager() { - return &pager; -} - -TriggerManager* RoomData::GetTriggerMgr() { - return &triggerMgr; -} - -std::list* RoomData::GetCharacterList() { - return &characterList; -} - -lua_State* RoomData::SetLuaState(lua_State* L) { - lua = L; - pager.SetLuaState(lua); - triggerMgr.SetLuaState(lua); - return lua; -} - -lua_State* RoomData::GetLuaState() { - return lua; -} - -sqlite3* RoomData::SetDatabase(sqlite3* db) { - database = db; - return database; -} - -sqlite3* RoomData::GetDatabase() { - return database; -} - -int RoomData::SetTickReference(int i) { - return tickRef = i; -} - -int RoomData::GetTickReference() { - return tickRef; -} \ No newline at end of file diff --git a/server/rooms/room_data.hpp b/server/rooms/room_data.hpp deleted file mode 100644 index 7cd11b2..0000000 --- a/server/rooms/room_data.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "character_data.hpp" -#include "region_pager_lua.hpp" -#include "trigger_manager.hpp" - -#include "lua.hpp" -#include "sqlite3.h" - -#include -#include - -class RoomData { -public: - RoomData() = default; - ~RoomData() = default; - - void RunFrame(); - - //accessors and mutators - std::string SetName(std::string); - std::string GetName(); - - std::string SetTileset(std::string); - std::string GetTileset(); - - RegionPagerLua* GetPager(); - TriggerManager* GetTriggerMgr(); - std::list* GetCharacterList(); - - //API interfaces - lua_State* SetLuaState(lua_State* L); - lua_State* GetLuaState(); - sqlite3* SetDatabase(sqlite3* db); - sqlite3* GetDatabase(); - - //hooks - int SetTickReference(int i); - int GetTickReference(); - //TODO: other triggers like player entry & exit, etc. - -private: - //metadata - std::string roomName; - std::string tilesetName; - - //members - RegionPagerLua pager; - TriggerManager triggerMgr; - std::list characterList; - - //API - lua_State* lua = nullptr; - sqlite3* database = nullptr; - - //hooks - int tickRef = LUA_NOREF; -}; diff --git a/server/rooms/room_manager.cpp b/server/rooms/room_manager.cpp deleted file mode 100644 index c974413..0000000 --- a/server/rooms/room_manager.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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" - -#include "room_api.hpp" - -#include - -//------------------------- -//public access methods -//------------------------- - -int RoomManager::Create(std::string roomName, std::string tileset) { - //create the room - RoomData* newRoom = &elementMap[counter]; //implicitly constructs the element - newRoom->SetName(roomName); - newRoom->SetTileset(tileset); - - newRoom->SetLuaState(lua); - newRoom->SetDatabase(database); - - //get the hook - lua_rawgeti(lua, LUA_REGISTRYINDEX, createRef); - - if(!lua_isnil(lua, -1)) { - lua_pushlightuserdata(lua, newRoom); - lua_pushinteger(lua, counter); - //call the function, 2 arg, 0 return - if (lua_pcall(lua, 2, 0, 0) != LUA_OK) { - throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) )); - } - } - - //finish the routine - return counter++; -} - -void RoomManager::UnloadAll() { - //get the hook - lua_rawgeti(lua, LUA_REGISTRYINDEX, unloadRef); - - if(!lua_isnil(lua, -1)) { - //pass each room to the hook - for (auto& it : elementMap) { - lua_pushvalue(lua, -1); //copy the hook - lua_pushlightuserdata(lua, &it.second); - lua_pushinteger(lua, it.first); - //call the function, 2 arg, 0 return - if (lua_pcall(lua, 2, 0, 0) != LUA_OK) { - throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) )); - } - } - } - - //pop the hook or nil - lua_pop(lua, 1); - - elementMap.clear(); -} - -void RoomManager::UnloadIf(std::function)> fn) { - //get the hook - lua_rawgeti(lua, LUA_REGISTRYINDEX, unloadRef); - - //get the element - std::map::iterator it = elementMap.begin(); - - //jenky pattern - while (it != elementMap.end()) { - if (fn(*it)) { - - if(!lua_isnil(lua, -1)) { - lua_pushvalue(lua, -1); //copy the hook - lua_pushlightuserdata(lua, &it->second); - lua_pushinteger(lua, it->first); - - //call the function, 2 arg, 0 return - if (lua_pcall(lua, 2, 0, 0) != LUA_OK) { - throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) )); - } - } - - it = elementMap.erase(it); - } - else { - ++it; - } - } - - //pop the hook or nil - lua_pop(lua, 1); -} - -void RoomManager::PushCharacter(CharacterData* character) { - if (!character) { - throw(std::runtime_error("Failed to push a null character to a room")); - } - - RoomData* room = Get(character->GetRoomIndex()); - - if (!room) { - throw(std::runtime_error("Failed to push an character to a non-existant room")); - } - - room->GetCharacterList()->push_back(character); -} - -void RoomManager::PopCharacter(CharacterData const* character) { - //NOTE: to pop an character from a room, the character must first exist - if (!character) { - throw(std::runtime_error("Failed to pop a null character to a room")); - } - - RoomData* room = Get(character->GetRoomIndex()); - - if (!room) { - throw(std::runtime_error("Failed to pop an character to a non-existant room")); - } - - room->GetCharacterList()->remove_if([character](CharacterData* ptr) { - return character == ptr; - }); -} - -RoomData* RoomManager::Get(int uid) { - std::map::iterator it = elementMap.find(uid); - - if (it == elementMap.end()) { - return nullptr; - } - - return &it->second; -} - -RoomData* RoomManager::Get(std::string name) { - for (std::map::iterator it = elementMap.begin(); it != elementMap.end(); ++it) { - if (it->second.GetName() == name) { - return &it->second; - } - } - return nullptr; -} - -int RoomManager::GetLoadedCount() { - return elementMap.size(); -} - -std::map* RoomManager::GetContainer() { - return &elementMap; -} - -lua_State* RoomManager::SetLuaState(lua_State* L) { - lua = L; - for (auto& it : elementMap) { - it.second.SetLuaState(lua); - } - return lua; -} - -lua_State* RoomManager::GetLuaState() { - return lua; -} - -sqlite3* RoomManager::SetDatabase(sqlite3* db) { - database = db; - for (auto& it : elementMap) { - it.second.SetDatabase(database); - } - return database; -} - -sqlite3* RoomManager::GetDatabase() { - return database; -} - -int RoomManager::SetCreateReference(int i) { - return createRef = i; -} - -int RoomManager::SetUnloadReference(int i) { - return unloadRef = i; -} - -int RoomManager::GetCreateReference() { - return createRef; -} - -int RoomManager::GetUnloadReference() { - return unloadRef; -} diff --git a/server/rooms/room_manager.hpp b/server/rooms/room_manager.hpp deleted file mode 100644 index af95d56..0000000 --- a/server/rooms/room_manager.hpp +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "character_data.hpp" -#include "room_data.hpp" -#include "singleton.hpp" - -#include "lua.hpp" -#include "sqlite3.h" - -#include -#include - -class RoomManager: public Singleton { -public: - //common public methods - int Create(std::string name, std::string tileset); - - void UnloadAll(); - void UnloadIf(std::function)> fn); - - void PushCharacter(CharacterData* character); - void PopCharacter(CharacterData const* character); - - //accessors and mutators - RoomData* Get(int uid); - RoomData* Get(std::string name); - int GetLoadedCount(); - std::map* GetContainer(); - - //API interfaces - lua_State* SetLuaState(lua_State* L); - lua_State* GetLuaState(); - sqlite3* SetDatabase(sqlite3* db); - sqlite3* GetDatabase(); - - //hooks - int SetCreateReference(int i); - int SetUnloadReference(int i); - - int GetCreateReference(); - int GetUnloadReference(); - -private: - friend Singleton; - - RoomManager() = default; - ~RoomManager() = default; - - //members - std::map elementMap; - int counter = 0; - - //API - lua_State* lua = nullptr; - sqlite3* database = nullptr; - - //hooks - int createRef = LUA_NOREF; - int unloadRef = LUA_NOREF; -}; diff --git a/server/rooms/room_manager_api.cpp b/server/rooms/room_manager_api.cpp deleted file mode 100644 index c0e88a6..0000000 --- a/server/rooms/room_manager_api.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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_api.hpp" - -#include "room_manager.hpp" - -int createRoom(lua_State* L) { - //create & get the room - RoomManager& roomMgr = RoomManager::GetSingleton(); - int uid = roomMgr.Create(lua_tostring(L, 1), lua_tostring(L, 2)); - RoomData* room = roomMgr.Get(uid); - - //TODO: initialization parameters here? - - //return room, uid - lua_pushlightuserdata(L, static_cast(room)); - lua_pushinteger(L, uid); //for debugging, mostly - - return 2; -} - -int unloadRoom(lua_State* L) { - RoomManager& roomMgr = RoomManager::GetSingleton(); - - switch(lua_type(L, 1)) { - case LUA_TNUMBER: { - //number - int uid = lua_tointeger(L, 1); - roomMgr.UnloadIf([uid](std::pair it){ - return it.first == uid; - }); - } - break; - case LUA_TSTRING: { - //name - std::string name = lua_tostring(L, 1); - roomMgr.UnloadIf([name](std::pair it){ - return it.second.GetName() == name; - }); - } - break; - case LUA_TLIGHTUSERDATA: { - //the room itself - std::string name = static_cast(lua_touserdata(L, 1))->GetName(); - roomMgr.UnloadIf([name](std::pair it){ - return it.second.GetName() == name; - }); - } - break; - } - return 0; -} - -int getRoom(lua_State* L) { - //integer vs name for getRoom() - RoomManager& roomMgr = RoomManager::GetSingleton(); - RoomData* room = nullptr; - - switch(lua_type(L, 1)) { - case LUA_TNUMBER: - //number - room = roomMgr.Get(lua_tointeger(L, 1)); - break; - case LUA_TSTRING: - //name - room = roomMgr.Get(lua_tostring(L, 1)); - break; - } - - if (room) { - lua_pushlightuserdata(L, static_cast(room)); - } - else { - lua_pushnil(L); - } - - return 1; -} - -static int setOnCreate(lua_State* L) { - RoomManager& roomMgr = RoomManager::GetSingleton(); - luaL_unref(L, LUA_REGISTRYINDEX, roomMgr.GetCreateReference()); - roomMgr.SetCreateReference(luaL_ref(L, LUA_REGISTRYINDEX)); - return 0; -} - -static int setOnUnload(lua_State* L) { - RoomManager& roomMgr = RoomManager::GetSingleton(); - luaL_unref(L, LUA_REGISTRYINDEX, roomMgr.GetUnloadReference()); - roomMgr.SetUnloadReference(luaL_ref(L, LUA_REGISTRYINDEX)); - return 0; -} - -static const luaL_Reg roomManagerLib[] = { - {"CreateRoom", createRoom}, - {"UnloadRoom", unloadRoom}, - {"GetRoom", getRoom}, - {"SetOnCreate", setOnCreate}, - {"SetOnUnload", setOnUnload}, - {nullptr, nullptr} -}; - -LUAMOD_API int openRoomManagerAPI(lua_State* L) { - luaL_newlib(L, roomManagerLib); - return 1; -} diff --git a/server/rooms/room_manager_api.hpp b/server/rooms/room_manager_api.hpp deleted file mode 100644 index 0606d83..0000000 --- a/server/rooms/room_manager_api.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once -#include "lua.hpp" - -#define TORTUGA_ROOM_MANAGER_API "room_manager" -LUAMOD_API int openRoomManagerAPI(lua_State* L); diff --git a/server/server_application.hpp b/server/server_application.hpp deleted file mode 100644 index 29ed8ff..0000000 --- a/server/server_application.hpp +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -//managers -#include "account_manager.hpp" -#include "character_manager.hpp" -#include "client_manager.hpp" -#include "room_manager.hpp" - -//utilities -#include "config_utility.hpp" -#include "udp_network_utility.hpp" - -//common utilities -#include "ip_operators.hpp" -#include "serial_packet.hpp" -#include "singleton.hpp" - -//server utilities -#include "server_utilities.hpp" - -//APIs -#include "lua.hpp" -#include "sqlite3.h" - -#include "SDL/SDL.h" - -//STL -#include -#include - -//The main application class -class ServerApplication: public Singleton { -public: - //public methods - void Init(int argc, char* argv[]); - void Proc(); - void Quit(); - -private: - friend Singleton; - - ServerApplication() = default; - ~ServerApplication() = default; - - //handle incoming traffic - void HandlePacket(SerialPacket* const); - - //heartbeat system - void hPing(ServerPacket* const); - void hPong(ServerPacket* const); - - //basic connections - void hBroadcastRequest(ServerPacket* const); - void hJoinRequest(ClientPacket* const); - void hLoginRequest(ClientPacket* const); - - //client disconnections - void hLogoutRequest(ClientPacket* const); - void hDisconnectRequest(ClientPacket* const); - - //server commands - void hAdminDisconnectForced(ClientPacket* const); - void hAdminShutdownRequest(ClientPacket* const); - - //data management - void hRegionRequest(RegionPacket* const); - void hQueryCharacterExists(CharacterPacket* const); - void hQueryCharacterStats(CharacterPacket* const); - void hQueryCharacterLocation(CharacterPacket* const); - void hQueryMonsterExists(MonsterPacket* const); - void hQueryMonsterStats(MonsterPacket* const); - void hQueryMonsterLocation(MonsterPacket* const); - - //character management - void hCharacterCreate(CharacterPacket* const); - void hCharacterDelete(CharacterPacket* const); - void hCharacterLoad(CharacterPacket* const); - void hCharacterUnload(CharacterPacket* const); - - //character movement - void hCharacterMovement(CharacterPacket* const); - void hCharacterAttack(CharacterPacket* const); - void hCharacterDamage(CharacterPacket* const); - - //chat - void hTextBroadcast(TextPacket* const); - void hTextSpeech(TextPacket* const); - void hTextWhisper(TextPacket* const); - - //utility methods - void SaveServerState(); - - //APIs and utilities - sqlite3* database = nullptr; - lua_State* luaState = nullptr; - - //ugly references; I hate this - ClientManager& clientMgr = ClientManager::GetSingleton(); - AccountManager& accountMgr = AccountManager::GetSingleton(); - CharacterManager& characterMgr = CharacterManager::GetSingleton(); - RoomManager& roomMgr = RoomManager::GetSingleton(); - - ConfigUtility& config = ConfigUtility::GetSingleton(); - UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton(); - - //misc - bool running = true; -}; diff --git a/server/server_character_methods.cpp b/server/server_character_methods.cpp deleted file mode 100644 index 4e85ee6..0000000 --- a/server/server_character_methods.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 -#include -#include - -//------------------------- -//Character Management -//------------------------- - -void ServerApplication::hCharacterCreate(CharacterPacket* const argPacket) { - int characterIndex = characterMgr.Create(argPacket->accountIndex, argPacket->handle, argPacket->avatar); - - if (characterIndex < 0) { - //build the error message - std::ostringstream msg; - msg << "Character already exists: " << argPacket->handle; - - //build & send the packet - TextPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_REJECTION; - strncpy(newPacket.text, msg.str().c_str(), PACKET_STRING_SIZE); - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); - - return; - } - - //push to the rooms - CharacterData* characterData = characterMgr.Get(characterIndex); - roomMgr.PushCharacter(characterData); - - //pump this character to all clients - CharacterPacket newPacket; - copyCharacterToPacket(&newPacket, characterIndex); - newPacket.type = SerialPacketType::CHARACTER_CREATE; - pumpPacketProximity(&newPacket, characterData->GetRoomIndex()); -} - -void ServerApplication::hCharacterDelete(CharacterPacket* const argPacket) { - //get the user's data - AccountData* accountData = accountMgr.Get(argPacket->accountIndex); - if (!accountData) { - return; - } - ClientData* clientData = clientMgr.Get(accountData->GetClientIndex()); - if (!clientData) { - return; - } - - //check for fraud - if (clientData->GetAddress() != argPacket->srcAddress) { - std::cerr << "Falsified character deletion detected targeting: " << argPacket->handle << std::endl; - return; - } - - //load the character into memory - int characterIndex = characterMgr.Load(argPacket->accountIndex, argPacket->handle, argPacket->avatar); - - if (characterIndex < 0) { - //build the error message - std::ostringstream msg; - msg << "Cannot delete this character"; - - //build & send the packet - TextPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_REJECTION; - strncpy(newPacket.text, msg.str().c_str(), PACKET_STRING_SIZE); - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); - - return; - } - - //pop from the rooms - CharacterData* characterData = characterMgr.Get(characterIndex); - roomMgr.PopCharacter(characterData); - - //pump character delete - CharacterPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_DELETE; - newPacket.characterIndex = characterIndex; - pumpPacketProximity(static_cast(&newPacket), characterData->GetRoomIndex()); - - //delete the character - characterMgr.Delete(characterIndex); -} - -void ServerApplication::hCharacterLoad(CharacterPacket* const argPacket) { - int characterIndex = characterMgr.Load(argPacket->accountIndex, argPacket->handle, argPacket->avatar); - - if (characterIndex < 0) { - //build the error message - std::ostringstream msg; - if (characterIndex == -1) { - msg << "Character already loaded: "; - } - if (characterIndex == -2) { - msg << "Character name is taken: "; - } - msg << argPacket->handle; - - //build & send the packet - TextPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_REJECTION; - strncpy(newPacket.text, msg.str().c_str(), PACKET_STRING_SIZE); - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); - - return; - } - - //push to the rooms - CharacterData* characterData = characterMgr.Get(characterIndex); - roomMgr.PushCharacter(characterData); - - //pump this character to all clients - CharacterPacket newPacket; - copyCharacterToPacket(&newPacket, characterIndex); - newPacket.type = SerialPacketType::CHARACTER_CREATE; - pumpPacketProximity(&newPacket, characterData->GetRoomIndex()); -} - -void ServerApplication::hCharacterUnload(CharacterPacket* const argPacket) { - //get the entries - CharacterData* characterData = characterMgr.Get(argPacket->characterIndex); - if (!characterData) { - return; - } - - AccountData* accountData = accountMgr.Get(characterData->GetOwner()); - if (!accountData) { - return; - } - - ClientData* clientData = clientMgr.Get(accountData->GetClientIndex()); - if (!clientData) { - return; - } - - //check for fraud - if (clientData->GetAddress() != argPacket->srcAddress) { - std::cerr << "Falsified character unload detected targeting: uid(" << argPacket->characterIndex << ")" << std::endl; - return; - } - - //pop from the rooms - roomMgr.PopCharacter(characterData); - - //pump character delete - CharacterPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_DELETE; - newPacket.characterIndex = argPacket->characterIndex; - pumpPacketProximity(static_cast(&newPacket), characterData->GetRoomIndex()); - - //unload the character - characterMgr.Unload(argPacket->characterIndex); -} - -//------------------------- -//character movement -//------------------------- - -//TODO: (2) Could replace this verbosity with a "verify" method, taking a client, account and character ptr as arguments - -void ServerApplication::hCharacterMovement(CharacterPacket* const argPacket) { - //get the specified objects - AccountData* accountData = accountMgr.Get(argPacket->accountIndex); - - if (!accountData) { - throw(std::runtime_error("Failed to move a character, missing account")); - } - - CharacterData* characterData = characterMgr.Get(argPacket->characterIndex); - - if (!characterData) { - throw(std::runtime_error("Failed to move a character, missing character")); - } - - //get this account's client - ClientData* clientData = clientMgr.Get(accountData->GetClientIndex()); - - //check for fraud - if (clientData->GetAddress() != argPacket->srcAddress) { - std::cerr << "Falsified set character motion targeting uid(" << argPacket->characterIndex << ")" << std::endl; - return; - } - - //check if allowed - if (characterData->GetOwner() != argPacket->accountIndex && !accountData->GetModerator() && !accountData->GetAdministrator()) { - //TODO: (3) send to the client? - std::cerr << "Failed to set character motion due to lack of permissions targeting uid(" << argPacket->characterIndex << ")" << std::endl; - return; - } - - //check if moving rooms - if (characterData->GetRoomIndex() != argPacket->roomIndex) { - //set the character's origin and motion - characterData->SetOrigin(argPacket->origin); - characterData->SetMotion(argPacket->motion); - - //send the delete & create messages - pumpAndChangeRooms(characterData, argPacket->roomIndex, argPacket->characterIndex); - } - //if not moving between rooms - else { - //set the character's origin and motion - characterData->SetOrigin(argPacket->origin); - characterData->SetMotion(argPacket->motion); - - //update the clients - CharacterPacket newPacket; - copyCharacterToPacket(&newPacket, argPacket->characterIndex); - newPacket.type = SerialPacketType::CHARACTER_MOVEMENT; - pumpPacketProximity(&newPacket, characterData->GetRoomIndex()); - } -} - -void ServerApplication::hCharacterAttack(CharacterPacket* const argPacket) { - //TODO: (9) ServerApplication::hCharacterAttack() -} - -void ServerApplication::hCharacterDamage(CharacterPacket* const argPacket) { - //TODO: (9) ServerApplication::hCharacterDamage() -} \ No newline at end of file diff --git a/server/server_chat.cpp b/server/server_chat.cpp deleted file mode 100644 index f5395f0..0000000 --- a/server/server_chat.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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" - -void ServerApplication::hTextBroadcast(TextPacket* const argPacket) { - //TODO: (9) ServerApplication::hTextBroadcast() -} - -void ServerApplication::hTextSpeech(TextPacket* const argPacket) { - //TODO: (9) ServerApplication::hTextSpeech() -} - -void ServerApplication::hTextWhisper(TextPacket* const argPacket) { - //TODO: (9) ServerApplication::hTextWhisper() -} diff --git a/server/server_connections.cpp b/server/server_connections.cpp deleted file mode 100644 index e88c1dd..0000000 --- a/server/server_connections.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 -#include -#include - -//------------------------- -//heartbeat system -//------------------------- - -void ServerApplication::hPing(ServerPacket* const argPacket) { - ServerPacket newPacket; - newPacket.type = SerialPacketType::PONG; - network.SendTo(argPacket->srcAddress, &newPacket); -} - -void ServerApplication::hPong(ServerPacket* const argPacket) { - clientMgr.HandlePong(argPacket); -} - -//------------------------- -//basic connections -//------------------------- - -void ServerApplication::hBroadcastRequest(ServerPacket* const argPacket) { - //send the server's data - ServerPacket newPacket; - - newPacket.type = SerialPacketType::BROADCAST_RESPONSE; - strncpy(newPacket.name, config["server.name"].c_str(), PACKET_STRING_SIZE); - newPacket.playerCount = characterMgr.GetLoadedCount(); - newPacket.version = NETWORK_VERSION; - - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); -} - -void ServerApplication::hJoinRequest(ClientPacket* const argPacket) { - //register the client - int clientIndex = clientMgr.Create(argPacket->srcAddress); - - //send the client their info - ClientPacket newPacket; - newPacket.type = SerialPacketType::JOIN_RESPONSE; - newPacket.clientIndex = clientIndex; - - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); - - //finished this routine - std::cout << "New join, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl; -} - -void ServerApplication::hLoginRequest(ClientPacket* const argPacket) { - //get the client data - ClientData* clientData = clientMgr.Get(argPacket->clientIndex); - - if (clientData == nullptr || clientData->GetAddress() != argPacket->srcAddress) { - std::cerr << "Falsified client index detected: " << argPacket->clientIndex << std::endl; - return; - } - - //load the user account - int accountIndex = accountMgr.Load(argPacket->username, argPacket->clientIndex); - - //Cannot load - if (accountIndex < 0) { - //build the message - std::ostringstream msg; - msg << "Account already loaded: " << argPacket->username; - - //build the packet - TextPacket newPacket; - newPacket.type = SerialPacketType::LOGIN_REJECTION; - strncpy(newPacket.text, msg.str().c_str(), PACKET_STRING_SIZE); - network.SendTo(clientData->GetAddress(), static_cast(&newPacket)); - - //log the error - std::cerr << "Error message sent: " << newPacket.text << std::endl; - return; - } - - //send the client their info - ClientPacket newPacket; - newPacket.type = SerialPacketType::LOGIN_RESPONSE; - newPacket.clientIndex = argPacket->clientIndex; - newPacket.accountIndex = accountIndex; - - network.SendTo(clientData->GetAddress(), static_cast(&newPacket)); - - //finished this routine - std::cout << "New login, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl; -} - -void ServerApplication::hLogoutRequest(ClientPacket* const argPacket) { - //get the account and client data - AccountData* accountData = accountMgr.Get(argPacket->accountIndex); - if (!accountData) { - return; - } - - ClientData* clientData = clientMgr.Get(accountData->GetClientIndex()); - if (!clientData) { - std::ostringstream msg; - msg << "No client found for an account: " << accountData->GetUsername(); - throw(std::logic_error(msg.str())); - } - - //check for fraud - if (clientData->GetAddress() != argPacket->srcAddress) { - std::cerr << "Falsified logout detected targeting: " << accountData->GetUsername() << std::endl; - return; - } - - //send the logout response - ClientPacket newPacket; - newPacket.type = SerialPacketType::LOGOUT_RESPONSE; - newPacket.accountIndex = argPacket->accountIndex; - - network.SendTo(clientData->GetAddress(), static_cast(&newPacket)); - - //save and unload this account and it's characters - fullAccountUnload(argPacket->accountIndex); - - //finished this routine - std::cout << "New logout, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl; -} - -void ServerApplication::hDisconnectRequest(ClientPacket* const argPacket) { - //get the client data - ClientData* clientData = clientMgr.Get(argPacket->clientIndex); - if (!clientData) { - return; - } - - //check for fraud - if (clientData->GetAddress() != argPacket->srcAddress) { - std::cerr << "Falsified disconnection detected targeting: " << argPacket->clientIndex << std::endl; - return; - } - - //send the disconnect response - ClientPacket newPacket; - newPacket.type = SerialPacketType::DISCONNECT_RESPONSE; - newPacket.clientIndex = argPacket->clientIndex; - - network.SendTo(clientData->GetAddress(), static_cast(&newPacket)); - - //unload the client, it's accounts, and their characters - fullClientUnload(argPacket->clientIndex); - - //finished this routine - std::cout << "New disconnection, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl; -} diff --git a/server/server_data_queries.cpp b/server/server_data_queries.cpp deleted file mode 100644 index 721925a..0000000 --- a/server/server_data_queries.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 -#include -#include - -//------------------------- -//Queries -//------------------------- - -void ServerApplication::hRegionRequest(RegionPacket* const argPacket) { - //get the region object, send a rejection on error - RoomData* room = roomMgr.Get(argPacket->roomIndex); - if (!room) { - //build the error message - std::ostringstream msg; - msg << "Failed to find Region (" << argPacket->roomIndex << "," << argPacket->x << "," << argPacket->y << "); "; - msg << "Room " << argPacket->roomIndex << " does not exist"; - - //build the packet - TextPacket newPacket; - newPacket.type = SerialPacketType::REGION_REJECTION; - strncpy(newPacket.text, msg.str().c_str(), PACKET_STRING_SIZE); - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); - - //log the error - std::cerr << "Error message sent: " << newPacket.text << std::endl; - return; - } - Region* region = room->GetPager()->GetRegion(argPacket->x, argPacket->y); - - //send the content - RegionPacket newPacket; - - newPacket.type = SerialPacketType::REGION_CONTENT; - newPacket.roomIndex = argPacket->roomIndex; - newPacket.x = argPacket->x; - newPacket.y = argPacket->y; - newPacket.region = region; - - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); -} - -void ServerApplication::hQueryCharacterExists(CharacterPacket* const argPacket) { - //respond with all character data - CharacterPacket newPacket; - - for (auto& it : *characterMgr.GetContainer()) { - if (argPacket->roomIndex != -1 && it.second.GetRoomIndex() != argPacket->roomIndex) { - continue; - } - copyCharacterToPacket(&newPacket, it.first); - newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS; - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); - } -} - -void ServerApplication::hQueryCharacterStats(CharacterPacket* const argPacket) { - //TODO: (9) ServerApplication::hQueryCharacterStats() -} - -void ServerApplication::hQueryCharacterLocation(CharacterPacket* const argPacket) { - //TODO: (9) ServerApplication::hQueryCharacterLocation() -} - -void ServerApplication::hQueryMonsterExists(MonsterPacket* const argPacket) { - //TODO: (9) ServerApplication::hQueryMonsterExists() -} - -void ServerApplication::hQueryMonsterStats(MonsterPacket* const argPacket) { - //TODO: (9) ServerApplication::hQueryMonsterStats() -} - -void ServerApplication::hQueryMonsterLocation(MonsterPacket* const argPacket) { - //TODO: (9) ServerApplication::hQueryMonsterLocation() -} diff --git a/server/server_logic.cpp b/server/server_logic.cpp deleted file mode 100644 index ed31f6f..0000000 --- a/server/server_logic.cpp +++ /dev/null @@ -1,350 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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" - -//utility functions -#include "sql_tools.hpp" - -//std & STL -#include -#include - #include -#include -#include -#include -#include - -//------------------------- -//public methods -//------------------------- - -//BUG: #35 The server fails without at least one room - -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 config settings - config.Load("rsc/config.cfg", false, argc, argv); - - //------------------------- - //Initialize the APIs - //------------------------- - - //Init SDL - if (SDL_Init(0)) { - std::ostringstream os; - os << "Failed to initialize SDL: " << SDL_GetError(); - throw(std::runtime_error(os.str())); - } - 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; - - //append config["dir.scripts"] to the module path - if (config["dir.scripts"].size() > 0) { - //get the original path - lua_getglobal(luaState, "package"); - lua_getfield(luaState, -1, "path"); - - //build & push the message - std::ostringstream path; - path << lua_tostring(luaState, -1) << ";" << config["dir.scripts"] << "?.lua"; - lua_pushstring(luaState, path.str().c_str()); - - //set the new path and clean up the stack - lua_setfield(luaState, -3, "path"); - lua_pop(luaState, 2); - - std::cout << "\tLua script directory appended" << std::endl; - } - - //------------------------- - //Setup the objects - //------------------------- - - //set the hooks - accountMgr.SetDatabase(database); - characterMgr.SetDatabase(database); - - roomMgr.SetLuaState(luaState); - roomMgr.SetDatabase(database); - - 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 - //------------------------- - -#define DEBUG_OUTPUT_VAR(x) std::cout << "\t" << #x << ": " << x << std::endl; - - std::cout << "Internal sizes:" << std::endl; - - DEBUG_OUTPUT_VAR(NETWORK_VERSION); - 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_TILE_FOOTPRINT); - DEBUG_OUTPUT_VAR(REGION_SOLID_FOOTPRINT); - DEBUG_OUTPUT_VAR(PACKET_STRING_SIZE); - DEBUG_OUTPUT_VAR(PACKET_BUFFER_SIZE); - DEBUG_OUTPUT_VAR(MAX_PACKET_SIZE); - DEBUG_OUTPUT_VAR(static_cast(SerialPacketType::LAST)); - -#undef DEBUG_OUTPUT_VAR - - //------------------------- - //finalize the startup - //------------------------- - - std::cout << "Startup completed successfully" << std::endl; - - //------------------------- - //debugging - //------------------------- - - //... -} - -void ServerApplication::Proc() { - //network buffer - SerialPacket* packetBuffer = reinterpret_cast(new char[MAX_PACKET_SIZE]); - memset(packetBuffer, 0, MAX_PACKET_SIZE); //zero the buffer - - //time system - typedef std::chrono::steady_clock Clock; - - Clock::time_point simTime = Clock::now(); - Clock::time_point realTime; - - while(running) { - //suck in the waiting packets & process them - while(network.Receive(packetBuffer)) { - try { - HandlePacket(packetBuffer); - } - catch(std::exception& e) { - std::cerr << "HandlePacket Error: " << e.what() << std::endl; - } - //reset the buffer - memset(packetBuffer, 0, MAX_PACKET_SIZE); - } - - //Check client connections - std::list disconnections = clientMgr.CheckConnections(); - for(auto const& it : disconnections) { - fullClientUnload(it); - std::cerr << "Client dropped: " << it << std::endl; - } - - //"tick" the internals - realTime = Clock::now(); - - if (simTime < realTime) { - while(simTime < realTime) { - for (auto& it : *roomMgr.GetContainer()) { - it.second.RunFrame(); - } - //~60 FPS - simTime += std::chrono::duration(16); - } - } - else { - //give the machine a break - SDL_Delay(10); - } - } - delete reinterpret_cast(packetBuffer); -} - -void ServerApplication::Quit() { - std::cout << "Shutting down" << std::endl; - - //save the server state - SaveServerState(); - - //close the managers - accountMgr.UnloadAll(); - characterMgr.UnloadAll(); - clientMgr.UnloadAll(); - 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) { - //heartbeat system - case SerialPacketType::PING: - hPing(static_cast(argPacket)); - break; - case SerialPacketType::PONG: - hPong(static_cast(argPacket)); - break; - - //client connections - case SerialPacketType::BROADCAST_REQUEST: - hBroadcastRequest(static_cast(argPacket)); - break; - case SerialPacketType::JOIN_REQUEST: - hJoinRequest(static_cast(argPacket)); - break; - case SerialPacketType::LOGIN_REQUEST: - hLoginRequest(static_cast(argPacket)); - break; - - //client disconnections - case SerialPacketType::LOGOUT_REQUEST: - hLogoutRequest(static_cast(argPacket)); - break; - case SerialPacketType::DISCONNECT_REQUEST: - hDisconnectRequest(static_cast(argPacket)); - break; - - //server commands - case SerialPacketType::ADMIN_DISCONNECT_FORCED: - hAdminDisconnectForced(static_cast(argPacket)); - break; - case SerialPacketType::ADMIN_SHUTDOWN_REQUEST: - hAdminShutdownRequest(static_cast(argPacket)); - break; - - //data management & queries - case SerialPacketType::REGION_REQUEST: - hRegionRequest(static_cast(argPacket)); - break; - case SerialPacketType::QUERY_CHARACTER_EXISTS: - hQueryCharacterExists(static_cast(argPacket)); - break; - case SerialPacketType::QUERY_CHARACTER_STATS: - hQueryCharacterStats(static_cast(argPacket)); - break; - case SerialPacketType::QUERY_CHARACTER_LOCATION: - hQueryCharacterLocation(static_cast(argPacket)); - break; - - case SerialPacketType::QUERY_MONSTER_EXISTS: - hQueryMonsterExists(static_cast(argPacket)); - break; - case SerialPacketType::QUERY_MONSTER_STATS: - hQueryMonsterStats(static_cast(argPacket)); - break; - case SerialPacketType::QUERY_MONSTER_LOCATION: - hQueryMonsterLocation(static_cast(argPacket)); - break; - - //character management - case SerialPacketType::CHARACTER_CREATE: - hCharacterCreate(static_cast(argPacket)); - break; - case SerialPacketType::CHARACTER_DELETE: - hCharacterDelete(static_cast(argPacket)); - break; - case SerialPacketType::CHARACTER_LOAD: - hCharacterLoad(static_cast(argPacket)); - break; - case SerialPacketType::CHARACTER_UNLOAD: - hCharacterUnload(static_cast(argPacket)); - break; - - //character movement - case SerialPacketType::CHARACTER_MOVEMENT: - hCharacterMovement(static_cast(argPacket)); - break; - case SerialPacketType::CHARACTER_ATTACK: - hCharacterAttack(static_cast(argPacket)); - break; - case SerialPacketType::CHARACTER_DAMAGE: - hCharacterDamage(static_cast(argPacket)); - break; - - //chat - case SerialPacketType::TEXT_BROADCAST: - hTextBroadcast(static_cast(argPacket)); - break; - case SerialPacketType::TEXT_SPEECH: - hTextSpeech(static_cast(argPacket)); - break; - case SerialPacketType::TEXT_WHISPER: - hTextWhisper(static_cast(argPacket)); - break; - - //handle errors - default: { - std::ostringstream msg; - msg << "Unknown SerialPacketType encountered in the server: "; - msg << static_cast(argPacket->type); - throw(std::runtime_error(msg.str())); - } - break; - } -} diff --git a/server/server_methods.cpp b/server/server_methods.cpp deleted file mode 100644 index d23c13b..0000000 --- a/server/server_methods.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 - #include -#include -#include - -//------------------------- -//server commands -//------------------------- - -void ServerApplication::hAdminDisconnectForced(ClientPacket* const argPacket) { - //TODO: (9) ServerApplication::hAdminDisconnectForced() -} - -void ServerApplication::hAdminShutdownRequest(ClientPacket* const argPacket) { - //get the account and client data - AccountData* accountData = accountMgr.Get(argPacket->accountIndex); - if (!accountData) { - return; - } - ClientData* clientData = clientMgr.Get(accountData->GetClientIndex()); - if (!clientData) { - std::ostringstream msg; - msg << "No client found for an account: " << accountData->GetUsername(); - throw(std::logic_error(msg.str())); - } - - //check for fraud - if (clientData->GetAddress() != argPacket->srcAddress) { - std::cerr << "Falsified server shutdown detected from: " << accountData->GetUsername() << std::endl; - return; - } - - //reject non-admin requests - if (accountData->GetAdministrator() != true) { - std::cerr << "Rejected server shutdown command from: " << accountData->GetUsername() << std::endl; - - //build the message - std::ostringstream msg; - msg << "Invalid admin status"; - - //build the packet - TextPacket newPacket; - newPacket.type = SerialPacketType::SHUTDOWN_REJECTION; - strncpy(newPacket.text, msg.str().c_str(), PACKET_STRING_SIZE); - - //send the rejection message - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); - - return; - } - - //end the server - running = false; - - //disconnect all clients - TextPacket newPacket; - newPacket.type = SerialPacketType::ADMIN_DISCONNECT_FORCED; - strncpy(newPacket.text, "Server shutdown", PACKET_STRING_SIZE); - pumpPacket(&newPacket); - - //finished this routine - std::cout << "Shutdown signal accepted" << std::endl; -} - -void ServerApplication::SaveServerState() { - //TODO: (3) Periodic mass server saves -} diff --git a/server/server_utilities/makefile b/server/server_utilities/makefile deleted file mode 100644 index 7a87443..0000000 --- a/server/server_utilities/makefile +++ /dev/null @@ -1,32 +0,0 @@ -#config -INCLUDES+=. ../accounts ../characters ../clients ../entities ../monsters ../rooms ../triggers ../../common/gameplay ../../common/map ../../common/network ../../common/network/packet_types ../../common/utilities -LIBS+= -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=.. -OUT=$(addprefix $(OUTDIR)/,server.a) - -#targets -all: $(OBJ) $(OUT) - ar -crs $(OUT) $(OBJ) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/server/server_utilities/network_api.cpp b/server/server_utilities/network_api.cpp deleted file mode 100644 index c1fe6ac..0000000 --- a/server/server_utilities/network_api.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "network_api.hpp" - -#include "character_data.hpp" -#include "character_manager.hpp" -#include "server_utilities.hpp" - -#include - -static int pumpCharacterUpdate(lua_State* L) { - CharacterData* characterData = static_cast(lua_touserdata(L, 1)); - - //determine the character's index - int index = -1; - for (auto const& it : *CharacterManager::GetSingleton().GetContainer()) { - if(characterData == &it.second) { - index = it.first; - break; - } - } - - //signal an error - if (index == -1) { - lua_pushboolean(L, false); - return 1; - } - - //fill the packet with all of this character's data - CharacterPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_UPDATE; - newPacket.characterIndex = index; - strncpy(newPacket.handle, characterData->GetHandle().c_str(), PACKET_STRING_SIZE); - strncpy(newPacket.avatar, characterData->GetAvatar().c_str(), PACKET_STRING_SIZE); - newPacket.accountIndex = characterData->GetOwner(); - newPacket.roomIndex = characterData->GetRoomIndex(); - newPacket.origin = characterData->GetOrigin(); - newPacket.motion = characterData->GetMotion(); - - //pump to the room - pumpPacketProximity(&newPacket, characterData->GetRoomIndex()); - - //signal success - lua_pushboolean(L, true); - return 1; -} - -static int pumpMonsterUpdate(lua_State* L) { - //TODO: (0) send the info about a specific monster instance -} - -static const luaL_Reg networkLib[] = { - {"PumpCharacterUpdate", pumpCharacterUpdate}, - {"PumpMonsterUpdate", pumpMonsterUpdate}, - {nullptr, nullptr} -}; - -LUAMOD_API int openNetworkAPI(lua_State* L) { - luaL_newlib(L, networkLib); - return 1; -} \ No newline at end of file diff --git a/server/server_utilities/network_api.hpp b/server/server_utilities/network_api.hpp deleted file mode 100644 index 62d8381..0000000 --- a/server/server_utilities/network_api.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "lua.hpp" - -#define TORTUGA_NETWORK_API "network" -LUAMOD_API int openNetworkAPI(lua_State* L); diff --git a/server/server_utilities/server_utilities.cpp b/server/server_utilities/server_utilities.cpp deleted file mode 100644 index 698ed29..0000000 --- a/server/server_utilities/server_utilities.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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_utilities.hpp" - -#include "account_manager.hpp" -#include "character_manager.hpp" -#include "client_manager.hpp" -#include "room_manager.hpp" -#include "udp_network_utility.hpp" - -#include - -//------------------------- -//manager unload functions -//------------------------- - -void fullClientUnload(int index) { - ClientManager::GetSingleton().UnloadIf([index](std::pair clientPair) -> bool { - //skip the wrong clients - if (clientPair.first != index) { - return false; - } - - AccountManager& accountMgr = AccountManager::GetSingleton(); - - //unload associated accounts - for (std::map::iterator it = accountMgr.GetContainer()->begin(); it != accountMgr.GetContainer()->end(); /* EMPTY */) { - if (it->second.GetClientIndex() == index) { - fullAccountUnload(it->first); - it = accountMgr.GetContainer()->begin(); - } - else { - ++it; - } - } - - //unload this client - return true; - }); -} - -void fullAccountUnload(int index) { - AccountManager::GetSingleton().UnloadIf([index](std::pair accountPair) -> bool { - //skip the wrong accounts - if (accountPair.first != index) { - return false; - } - - CharacterManager& characterMgr = CharacterManager::GetSingleton(); - - //unload associated characters - for (std::map::iterator it = characterMgr.GetContainer()->begin(); it != characterMgr.GetContainer()->end(); /* EMPTY */) { - if (it->second.GetOwner() == index) { - fullCharacterUnload(it->first); - it = characterMgr.GetContainer()->begin(); - } - else { - ++it; - } - } - - //unload this account - return true; - }); -} - -void fullCharacterUnload(int index) { - CharacterManager::GetSingleton().UnloadIf([index](std::pair characterPair) -> bool { - //skip the wrong characters - if (characterPair.first != index) { - return false; - } - - //pop from the rooms - RoomManager::GetSingleton().PopCharacter(&characterPair.second); - - //pump character unload - CharacterPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_DELETE; - newPacket.characterIndex = characterPair.first; - //NOTE: more character info as needed - - //TODO: proximity? - pumpPacketProximity(&newPacket, characterPair.second.GetRoomIndex()); - - //unload this character - return true; - }); -} - -//------------------------- -//utility functions -//------------------------- - -void pumpPacket(SerialPacket* const argPacket) { - for (auto& it : *ClientManager::GetSingleton().GetContainer()) { - UDPNetworkUtility::GetSingleton().SendTo(it.second.GetAddress(), argPacket); - } -} - -void pumpPacketProximity(SerialPacket* const argPacket, int roomIndex, Vector2 position, int distance) { - RoomData* roomData = RoomManager::GetSingleton().Get(roomIndex); - - if (!roomData) { - throw(std::runtime_error("Failed to pump to a non-existant room")); - } - - AccountData* accountData = nullptr; - ClientData* clientData = nullptr; - - for (auto& characterIt : *roomData->GetCharacterList()) { - if (distance == -1 || (characterIt->GetOrigin() - position).Length() <= distance) { - accountData = AccountManager::GetSingleton().Get(characterIt->GetOwner()); - clientData = ClientManager::GetSingleton().Get(accountData->GetClientIndex()); - UDPNetworkUtility::GetSingleton().SendTo(clientData->GetAddress(), argPacket); - } - } -} - -void copyCharacterToPacket(CharacterPacket* const packet, int characterIndex) { - CharacterData* characterData = CharacterManager::GetSingleton().Get(characterIndex); - if (!characterData) { - throw(std::runtime_error("Failed to copy a character to a packet")); - } - - copyCharacterToPacket(packet, characterData, characterIndex); -} - -void copyCharacterToPacket(CharacterPacket* const packet, CharacterData* const characterData, int characterIndex) { - //NOTE: keep this up to date when the character changes - packet->characterIndex = characterIndex; - strncpy(packet->handle, characterData->GetHandle().c_str(), PACKET_STRING_SIZE); - strncpy(packet->avatar, characterData->GetAvatar().c_str(), PACKET_STRING_SIZE); - packet->accountIndex = characterData->GetOwner(); - packet->roomIndex = characterData->GetRoomIndex(); - packet->origin = characterData->GetOrigin(); - packet->motion = characterData->GetMotion(); - packet->bounds = characterData->GetBounds(); -} - -void pumpAndChangeRooms(int characterIndex, int newRoomIndex) { - //get the character object - CharacterData* character = CharacterManager::GetSingleton().Get(characterIndex); - - //pass ownwards - pumpAndChangeRooms(character, newRoomIndex, characterIndex); -} - -void pumpAndChangeRooms(CharacterData* const characterData, int newRoomIndex, int characterIndex) { - //delete from the old room - CharacterPacket newPacket; - copyCharacterToPacket(&newPacket, characterData, characterIndex); - newPacket.type = SerialPacketType::CHARACTER_DELETE; - pumpPacketProximity(&newPacket, characterData->GetRoomIndex()); - - //move the character between rooms - RoomManager::GetSingleton().PopCharacter(characterData); - characterData->SetRoomIndex(newRoomIndex); - RoomManager::GetSingleton().PushCharacter(characterData); - - //create in the new room - copyCharacterToPacket(&newPacket, characterData, characterIndex); - newPacket.type = SerialPacketType::CHARACTER_CREATE; - pumpPacketProximity(&newPacket, characterData->GetRoomIndex()); -} \ No newline at end of file diff --git a/server/server_utilities/server_utilities.hpp b/server/server_utilities/server_utilities.hpp deleted file mode 100644 index 64035b7..0000000 --- a/server/server_utilities/server_utilities.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "character_data.hpp" -#include "serial_packet.hpp" -#include "vector2.hpp" - -void fullClientUnload(int index); -void fullAccountUnload(int index); -void fullCharacterUnload(int index); - -void pumpPacket(SerialPacket* const argPacket); -void pumpPacketProximity(SerialPacket* const argPacket, int roomIndex, Vector2 position = {0, 0}, int distance = -1); - -void copyCharacterToPacket(CharacterPacket* const packet, int characterIndex); -void copyCharacterToPacket(CharacterPacket* const packet, CharacterData* const characterData, int characterIndex); -void pumpAndChangeRooms(int characterIndex, int newRoomIndex); -void pumpAndChangeRooms(CharacterData* const characterData, int newRoomIndex, int characterIndex); diff --git a/server/server_utilities/sql_tools.cpp b/server/server_utilities/sql_tools.cpp deleted file mode 100644 index 78e1065..0000000 --- a/server/server_utilities/sql_tools.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "sql_tools.hpp" - -#include -#include -#include -#include - -int runSQLScript(sqlite3* db, std::string fname, int (*callback)(void*,int,char**,char**), void* argPtr) { - //load the file into a string - std::ifstream is(fname); - if (!is.is_open()) { - return -1; - } - std::string script; - getline(is, script, '\0'); - is.close(); - - //run the SQL loaded from the file - char* errmsg = nullptr; - int ret = sqlite3_exec(db, script.c_str(), callback, argPtr, &errmsg); - if (ret != SQLITE_OK) { - //handle any errors received from the SQL - std::ostringstream msg; - msg << "SQL Script Error " << ret << ": " << errmsg; - free(errmsg); - throw(std::runtime_error( msg.str() )); - } - return ret; -} \ No newline at end of file diff --git a/server/server_utilities/sql_tools.hpp b/server/server_utilities/sql_tools.hpp deleted file mode 100644 index 838bbba..0000000 --- a/server/server_utilities/sql_tools.hpp +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "sqlite3.h" - -#include - -int runSQLScript(sqlite3* db, std::string fname, int (*callback)(void*,int,char**,char**) = nullptr, void* argPtr = nullptr); diff --git a/server/triggers/makefile b/server/triggers/makefile deleted file mode 100644 index 16035a5..0000000 --- a/server/triggers/makefile +++ /dev/null @@ -1,32 +0,0 @@ -#config -INCLUDES+=. ../entities ../server_utilities ../../common/utilities -LIBS+= -CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) - -#source -CXXSRC=$(wildcard *.cpp) - -#objects -OBJDIR=obj -OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) - -#output -OUTDIR=.. -OUT=$(addprefix $(OUTDIR)/,server.a) - -#targets -all: $(OBJ) $(OUT) - ar -crs $(OUT) $(OBJ) - -$(OBJ): | $(OBJDIR) - -$(OUT): | $(OUTDIR) - -$(OBJDIR): - mkdir $(OBJDIR) - -$(OUTDIR): - mkdir $(OUTDIR) - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/server/triggers/trigger_api.cpp b/server/triggers/trigger_api.cpp deleted file mode 100644 index 8f9089a..0000000 --- a/server/triggers/trigger_api.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "trigger_api.hpp" - -#include "trigger_data.hpp" - -//hamdle -static int setHandle(lua_State* L) { - TriggerData* trigger = static_cast(lua_touserdata(L, 1)); - trigger->SetHandle(lua_tostring(L, 2)); - return 0; -} - -static int getHandle(lua_State* L) { - TriggerData* trigger = static_cast(lua_touserdata(L, 1)); - lua_pushstring(L, trigger->GetHandle().c_str()); - return 1; -} - -//origin -static int setOrigin(lua_State* L) { - TriggerData* trigger = static_cast(lua_touserdata(L, 1)); - trigger->SetOrigin(Vector2(lua_tonumber(L, 2), lua_tonumber(L, 3))); - return 0; -} - -static int getOrigin(lua_State* L) { - TriggerData* trigger = static_cast(lua_touserdata(L, 1)); - lua_pushnumber(L, trigger->GetOrigin().x); - lua_pushnumber(L, trigger->GetOrigin().y); - return 2; -} - -//bounds -static int setBoundingBox(lua_State* L) { - TriggerData* trigger = static_cast(lua_touserdata(L, 1)); - trigger->SetBoundingBox(BoundingBox( - lua_tonumber(L, 2), - lua_tonumber(L, 3), - lua_tonumber(L, 4), - lua_tonumber(L, 5) - )); - return 0; -} - -static int getBoundingBox(lua_State* L) { - TriggerData* trigger = static_cast(lua_touserdata(L, 1)); - lua_pushinteger(L, trigger->GetBoundingBox().x); - lua_pushinteger(L, trigger->GetBoundingBox().y); - lua_pushinteger(L, trigger->GetBoundingBox().w); - lua_pushinteger(L, trigger->GetBoundingBox().h); - return 4; -} - -//triggers -static int setReference(lua_State* L) { - TriggerData* trigger = static_cast(lua_touserdata(L, 1)); - luaL_unref(L, LUA_REGISTRYINDEX, trigger->GetScriptReference()); - trigger->SetScriptReference(luaL_ref(L, LUA_REGISTRYINDEX)); - return 0; -} - -static int getReference(lua_State* L) { - TriggerData* trigger = static_cast(lua_touserdata(L, 1)); - lua_pushinteger(L, trigger->GetScriptReference()); - lua_gettable(L, LUA_REGISTRYINDEX); - return 1; -} - -static int pushExclusionEntity(lua_State* L) { - TriggerData* trigger = static_cast(lua_touserdata(L, 1)); - trigger->GetExclusionList()->push_back(static_cast(lua_touserdata(L, 2))); - return 0; -} - -static int removeExclusionEntity(lua_State* L) { - TriggerData* trigger = static_cast(lua_touserdata(L, 1)); - Entity* entity = static_cast(lua_touserdata(L, 2)); - trigger->GetExclusionList()->remove_if([entity](Entity* ptr){ - return entity == ptr; - }); - return 0; -} - -static const luaL_Reg triggerLib[] = { - {"SetHandle", setHandle}, - {"GetHandle", getHandle}, - - {"SetOrigin",setOrigin}, - {"GetOrigin",getOrigin}, - - {"SetBounds",setBoundingBox}, - {"GetBounds",getBoundingBox}, - - {"SetScript",setReference}, - {"GetScript",getReference}, - - {"PushExclusionEntity", pushExclusionEntity}, - {"RemoveExclusionEntity", removeExclusionEntity}, - - {nullptr, nullptr} -}; - -LUAMOD_API int openTriggerAPI(lua_State* L) { - luaL_newlib(L, triggerLib); - return 1; -} \ No newline at end of file diff --git a/server/triggers/trigger_api.hpp b/server/triggers/trigger_api.hpp deleted file mode 100644 index 12f3e85..0000000 --- a/server/triggers/trigger_api.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "lua.hpp" - -#define TORTUGA_TRIGGER_API "trigger" -LUAMOD_API int openTriggerAPI(lua_State* L); diff --git a/server/triggers/trigger_data.cpp b/server/triggers/trigger_data.cpp deleted file mode 100644 index 32ce359..0000000 --- a/server/triggers/trigger_data.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "trigger_data.hpp" - -std::string TriggerData::SetHandle(std::string s) { - return handle = s; -} - -std::string TriggerData::GetHandle() const { - return handle; -} - -Vector2 TriggerData::SetOrigin(Vector2 v) { - return origin = v; -} - -Vector2 TriggerData::GetOrigin() { - return origin; -} - -BoundingBox TriggerData::SetBoundingBox(BoundingBox b) { - return bounds = b; -} - -BoundingBox TriggerData::GetBoundingBox() { - return bounds; -} - -int TriggerData::SetScriptReference(int i) { - return scriptRef = i; -} - -int TriggerData::GetScriptReference() { - return scriptRef; -} - -std::list* TriggerData::GetExclusionList() { - return &exclusionList; -} \ No newline at end of file diff --git a/server/triggers/trigger_data.hpp b/server/triggers/trigger_data.hpp deleted file mode 100644 index 36e9181..0000000 --- a/server/triggers/trigger_data.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "bounding_box.hpp" -#include "entity.hpp" -#include "vector2.hpp" - -#include "lua.hpp" - -#include -#include - -class TriggerData { -public: - TriggerData() = default; - ~TriggerData() = default; - - std::string SetHandle(std::string); - std::string GetHandle() const; - - Vector2 SetOrigin(Vector2 v); - Vector2 GetOrigin(); - - BoundingBox SetBoundingBox(BoundingBox b); - BoundingBox GetBoundingBox(); - - int SetScriptReference(int i); - int GetScriptReference(); - - std::list* GetExclusionList(); - -private: - std::string handle; - Vector2 origin; - BoundingBox bounds; - int scriptRef = LUA_NOREF; - std::list exclusionList; -}; diff --git a/server/triggers/trigger_manager.cpp b/server/triggers/trigger_manager.cpp deleted file mode 100644 index c6de249..0000000 --- a/server/triggers/trigger_manager.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "trigger_manager.hpp" - -TriggerManager::TriggerManager() { - //EMPTY -} - -TriggerManager::~TriggerManager() { - UnloadAll(); -} - -int TriggerManager::Create(std::string handle) { - //implicitly creates the element - TriggerData& triggerData = elementMap[counter]; - - triggerData.SetHandle(handle); - - return counter++; -} - -void TriggerManager::Unload(int uid) { - elementMap.erase(uid); -} - -void TriggerManager::UnloadAll() { - //TODO: save? - elementMap.clear(); -} - -void TriggerManager::UnloadIf(std::function)> fn) { - std::map::iterator it = elementMap.begin(); - while (it != elementMap.end()) { - if (fn(*it)) { - it = elementMap.erase(it); - } - else { - ++it; - } - } -} - -TriggerData* TriggerManager::Get(int uid) { - std::map::iterator it = elementMap.find(uid); - - if (it == elementMap.end()) { - return nullptr; - } - - return &it->second; -} - -TriggerData* TriggerManager::Get(std::string handle) { - for (std::map::iterator it = elementMap.begin(); it != elementMap.end(); ++it) { - if (it->second.GetHandle() == handle) { - return &it->second; - } - } - return nullptr; -} - -int TriggerManager::GetLoadedCount() { - return elementMap.size(); -} - -std::map* TriggerManager::GetContainer() { - return &elementMap; -} - -//hooks -lua_State* TriggerManager::SetLuaState(lua_State* L) { - return lua = L; -} - -lua_State* TriggerManager::GetLuaState() { - return lua; -} \ No newline at end of file diff --git a/server/triggers/trigger_manager.hpp b/server/triggers/trigger_manager.hpp deleted file mode 100644 index 067f9ec..0000000 --- a/server/triggers/trigger_manager.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "bounding_box.hpp" -#include "vector2.hpp" -#include "trigger_data.hpp" - -#include "lua.hpp" - -#include -#include -#include - -class TriggerManager { -public: - TriggerManager(); - ~TriggerManager(); - - //common public methods - int Create(std::string handle); - void Unload(int uid); - - void UnloadAll(); - void UnloadIf(std::function)> fn); - - //accessors & mutators - TriggerData* Get(int uid); - TriggerData* Get(std::string handle); - int GetLoadedCount(); - std::map* GetContainer(); - - //hooks - lua_State* SetLuaState(lua_State* L); - lua_State* GetLuaState(); - -private: - //members - std::map elementMap; - lua_State* lua = nullptr; - int counter = 0; -}; diff --git a/server/triggers/trigger_manager_api.cpp b/server/triggers/trigger_manager_api.cpp deleted file mode 100644 index 580ea5e..0000000 --- a/server/triggers/trigger_manager_api.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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 "trigger_manager_api.hpp" - -#include "trigger_manager.hpp" - -static int create(lua_State* L) { - //DOCS: params: create(triggerMgr, name[, originX, originY[, boundsX, boundsY, boundsW, boundsH]][, script]) - - //get the trigger manager - TriggerManager* mgr = static_cast(lua_touserdata(L, 1)); - - //create the trigger - int index = mgr->Create(lua_tostring(L, 2)); - TriggerData* triggerData = mgr->Get(index); - - //origin - if (lua_gettop(L) >= 4) { - triggerData->SetOrigin({lua_tonumber(L, 3), lua_tonumber(L, 4)}); //vectorX, vectorY - } - - //bounds - if (lua_gettop(L) >= 8) { - triggerData->SetBoundingBox({ - lua_tointeger(L, 5), //boundsX - lua_tointeger(L, 6), //boundsY - lua_tointeger(L, 7), //boundsW - lua_tointeger(L, 8) //boundsH - }); - } - - //if the parameter list isn't capped with a script, append a nil instead - if (lua_type(L, -1) != LUA_TFUNCTION) { - lua_pushnil(L); - } - - //set the script reference (may be nil) - triggerData->SetScriptReference(luaL_ref(L, LUA_REGISTRYINDEX)); - - //push to the scipts - lua_pushlightuserdata(L, static_cast(triggerData)); - lua_pushinteger(L, index); - - return 2; -} - -static int unload(lua_State* L) { - TriggerManager* mgr = static_cast(lua_touserdata(L, 1)); - int count = 0; //the number removed - - //based on the type - switch(lua_type(L, 2)) { - //unload this index - case LUA_TNUMBER: - mgr->UnloadIf([L, &count](std::pair it) -> bool { - if (it.first == lua_tointeger(L, 2)) { - count++; - return true; - } - else { - return false; - } - }); - break; - - //unload this name - case LUA_TSTRING: - mgr->UnloadIf([L, &count](std::pair it) -> bool { - if (it.second.GetHandle() == lua_tostring(L, 2)) { - count++; - return true; - } - else { - return false; - } - }); - break; - } - - //return the number removed - lua_pushinteger(L, count); - return 1; -} - -static int getTrigger(lua_State* L) { - TriggerManager* mgr = static_cast(lua_touserdata(L, 1)); - TriggerData* triggerData = nullptr; - - switch(lua_type(L, 2)) { - case LUA_TNUMBER: - triggerData = mgr->Get(lua_tointeger(L, 2)); - break; - case LUA_TSTRING: - triggerData = mgr->Get(lua_tostring(L, 2)); - break; - } - - if (triggerData) { - lua_pushlightuserdata(L, static_cast(triggerData)); - } - else { - lua_pushnil(L); - } - - return 1; -} - -static int forEach(lua_State* L) { - //TODO: (9) forEach() -} - -static int getLoadedCount(lua_State* L) { - TriggerManager* mgr = static_cast(lua_touserdata(L, 1)); - lua_pushinteger(L, mgr->GetLoadedCount()); - return 1; -} - -static const luaL_Reg triggerManagerLib[] = { - {"Create",create}, - {"Unload",unload}, - {"GetTrigger",getTrigger}, - {"GetCount",getLoadedCount}, - {nullptr, nullptr} -}; - -LUAMOD_API int openTriggerManagerAPI(lua_State* L) { - luaL_newlib(L, triggerManagerLib); - return 1; -} \ No newline at end of file diff --git a/server/triggers/trigger_manager_api.hpp b/server/triggers/trigger_manager_api.hpp deleted file mode 100644 index 2350b60..0000000 --- a/server/triggers/trigger_manager_api.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013-2015 - * - * 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. -*/ -#pragma once - -#include "lua.hpp" - -#define TORTUGA_TRIGGER_MANAGER_API "trigger_manager" -LUAMOD_API int openTriggerManagerAPI(lua_State* L); diff --git a/todo.txt b/todo.txt deleted file mode 100644 index 3bbb4dd..0000000 --- a/todo.txt +++ /dev/null @@ -1,26 +0,0 @@ -TODO: upgrade to lua 5.3 -TODO: upgrade to SDL 2.0 -TODO: Split config.cfg in two, one for the server and the client -TODO: Consistency for bounds names - -TODO: Account passwords (list) - * backbone account server OR - * social network login OR - * ... - * salts & hashes - * login screen prompting for username & password - -TODO: Features - * Make sure login errors are sent to the client - * Add the "home" parameter to the server's config file - * Waypoints, with positions and trigger zones (collision areas) for doors, monster spawns, etc. (trigger system) - * Fix shoddy movement - * Remove the big "Shut Down" button (currently broken...) - * Make a way for the server owner to control the server directly - * The TileSheet class should implement the surface itself - * Time delay for requesting region packets - * A proper logging system - * Fix the const-ness of accessors - * Add a screenshot of the game to README.md - * joystick/gamepad support - * add the tilesheet to the map system \ No newline at end of file diff --git a/common/utilities/bounding_box.hpp b/utilities/bounding_box.hpp similarity index 100% rename from common/utilities/bounding_box.hpp rename to utilities/bounding_box.hpp diff --git a/common/utilities/config_utility.cpp b/utilities/config_utility.cpp similarity index 100% rename from common/utilities/config_utility.cpp rename to utilities/config_utility.cpp diff --git a/common/utilities/config_utility.hpp b/utilities/config_utility.hpp similarity index 100% rename from common/utilities/config_utility.hpp rename to utilities/config_utility.hpp diff --git a/common/utilities/frame_rate.hpp b/utilities/frame_rate.hpp similarity index 100% rename from common/utilities/frame_rate.hpp rename to utilities/frame_rate.hpp diff --git a/common/utilities/ip_operators.cpp b/utilities/ip_operators.cpp similarity index 100% rename from common/utilities/ip_operators.cpp rename to utilities/ip_operators.cpp diff --git a/common/utilities/ip_operators.hpp b/utilities/ip_operators.hpp similarity index 100% rename from common/utilities/ip_operators.hpp rename to utilities/ip_operators.hpp diff --git a/common/gameplay/makefile b/utilities/makefile similarity index 86% rename from common/gameplay/makefile rename to utilities/makefile index 104b518..e6bcb85 100644 --- a/common/gameplay/makefile +++ b/utilities/makefile @@ -10,10 +10,6 @@ CXXSRC=$(wildcard *.cpp) OBJDIR=obj OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) -#output -OUTDIR=../.. -OUT=$(addprefix $(OUTDIR)/,libcommon.a) - #targets all: $(OBJ) $(OUT) ar -crs $(OUT) $(OBJ) diff --git a/common/utilities/singleton.hpp b/utilities/singleton.hpp similarity index 100% rename from common/utilities/singleton.hpp rename to utilities/singleton.hpp diff --git a/common/utilities/vector2.hpp b/utilities/vector2.hpp similarity index 100% rename from common/utilities/vector2.hpp rename to utilities/vector2.hpp From 68eddcfcbb94171212fa7702b411aa28ff3454eb Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 14 Aug 2015 22:42:48 +1000 Subject: [PATCH 02/16] Fixed a makefile --- makefile | 1 - network/packet_types/makefile | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/makefile b/makefile index c5ac867..12d7825 100644 --- a/makefile +++ b/makefile @@ -8,7 +8,6 @@ all: $(OUTDIR) $(MAKE) -C graphics $(MAKE) -C map $(MAKE) -C network - $(MAKE) -C ui $(MAKE) -C utilities debug: export CXXFLAGS+=-g diff --git a/network/packet_types/makefile b/network/packet_types/makefile index 3526e73..e6aff0a 100644 --- a/network/packet_types/makefile +++ b/network/packet_types/makefile @@ -10,13 +10,9 @@ CXXSRC=$(wildcard *.cpp) OBJDIR=obj OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) -#output -OUTDIR=../$(OUTDIR) -OUT=../$(OUT) - #targets all: $(OBJ) $(OUT) - ar -crs $(OUT) $(OBJ) + ar -crs ../$(OUT) $(OBJ) $(OBJ): | $(OBJDIR) From 6bcaf460b95d3da258545140b8c82fc508cb658b Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Tue, 18 Aug 2015 03:59:17 +1000 Subject: [PATCH 03/16] Reversed the display order of the lines --- graphics/text_box.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/text_box.cpp b/graphics/text_box.cpp index 4fdefa4..98275aa 100644 --- a/graphics/text_box.cpp +++ b/graphics/text_box.cpp @@ -34,7 +34,7 @@ TextBox::~TextBox() { void TextBox::DrawTo(SDL_Renderer* renderer, int posX, int posY, int pointSize) { for (std::list::iterator it = lineList.begin(); it != lineList.end(); it++) { it->DrawTo(renderer, posX, posY); - posY -= pointSize; + posY += pointSize; } } From 345980af5ed1080317bc671c852bb6e92c5d0ba1 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Thu, 20 Aug 2015 02:32:00 +1000 Subject: [PATCH 04/16] Changed an inclusion path I've also modified my local SDL_net install to ensure that it built with the correct version of SDL. Long story short: This worked me up way too much. --- network/packet_types/serial_packet_base.hpp | 2 +- network/udp_network_utility.hpp | 2 +- utilities/ip_operators.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/network/packet_types/serial_packet_base.hpp b/network/packet_types/serial_packet_base.hpp index 22ff75b..a2eafff 100644 --- a/network/packet_types/serial_packet_base.hpp +++ b/network/packet_types/serial_packet_base.hpp @@ -23,7 +23,7 @@ #include "serial_packet_type.hpp" -#include "SDL_net.h" +#include "SDL2/SDL_net.h" constexpr int PACKET_STRING_SIZE = 100; diff --git a/network/udp_network_utility.hpp b/network/udp_network_utility.hpp index d770244..6c48ac3 100644 --- a/network/udp_network_utility.hpp +++ b/network/udp_network_utility.hpp @@ -26,7 +26,7 @@ #include "singleton.hpp" //APIs -#include "SDL_net.h" +#include "SDL2/SDL_net.h" class UDPNetworkUtility : public Singleton { public: diff --git a/utilities/ip_operators.hpp b/utilities/ip_operators.hpp index 5e3c208..a3d5b62 100644 --- a/utilities/ip_operators.hpp +++ b/utilities/ip_operators.hpp @@ -21,7 +21,7 @@ */ #pragma once -#include "SDL_net.h" +#include "SDL2/SDL_net.h" //these should've come standard bool operator==(IPaddress lhs, IPaddress rhs); From 03e643a17a881f9ecc13c6b28db8fd9d1da23d16 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Thu, 20 Aug 2015 20:42:19 +1000 Subject: [PATCH 05/16] Updated network version tag --- network/serial_packet.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/serial_packet.hpp b/network/serial_packet.hpp index 54a0ffd..fbfb851 100644 --- a/network/serial_packet.hpp +++ b/network/serial_packet.hpp @@ -33,7 +33,7 @@ typedef SerialPacketBase SerialPacket; //DOCS: NETWORK_VERSION is used to discern compatible servers and clients -constexpr int NETWORK_VERSION = 20150304; +constexpr int NETWORK_VERSION = 20150820; union MaxPacket { CharacterPacket a; From 2dd2aead13f62a3658bdddb3777a383a19949c97 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 23 Aug 2015 01:52:03 +1000 Subject: [PATCH 06/16] Tweaked FPS implementation --- utilities/frame_rate.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/utilities/frame_rate.hpp b/utilities/frame_rate.hpp index 3a52c2f..31970db 100644 --- a/utilities/frame_rate.hpp +++ b/utilities/frame_rate.hpp @@ -28,16 +28,21 @@ public: typedef std::chrono::high_resolution_clock Clock; FrameRate() = default; + + //DOCS: for usage purposes, this returns -1 unless a new framerate value is set int Calculate() { frameCount++; if (Clock::now() - tick >= std::chrono::duration(1)) { lastFrameRate = frameCount; frameCount = 0; tick = Clock::now(); + return lastFrameRate; } - return lastFrameRate; + return -1; } + int GetFrameRate() { return lastFrameRate; } + private: int frameCount = 0; int lastFrameRate = 0; From 93a955caf97d62369f9f94ab4a4894b0b2ece308 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 23 Aug 2015 02:47:59 +1000 Subject: [PATCH 07/16] Removed commented code --- graphics/button.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/graphics/button.cpp b/graphics/button.cpp index 21b8b47..49c8502 100644 --- a/graphics/button.cpp +++ b/graphics/button.cpp @@ -85,9 +85,6 @@ void Button::SetText(SDL_Renderer* renderer, TTF_Font* font, std::string s, SDL_ //free the texture SDL_DestroyTexture(text); - - //DEBUG: testing -// image.SetClipH(image.GetClipH() * 3); } void Button::SetX(int x) { From 540f646209f579ab1941b221ceeb44fab9d4322a Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 23 Aug 2015 04:54:51 +1000 Subject: [PATCH 08/16] Added color macros for buttons --- graphics/button.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/graphics/button.hpp b/graphics/button.hpp index 71b8e02..e4887a8 100644 --- a/graphics/button.hpp +++ b/graphics/button.hpp @@ -27,6 +27,11 @@ #include +constexpr SDL_Color COLOR_WHITE = {255, 255, 255, 255}; +constexpr SDL_Color COLOR_RED = {255, 0, 0, 255}; +constexpr SDL_Color COLOR_ORANGE = {255, 127, 0, 255}; +constexpr SDL_Color COLOR_BLUE = {0, 0, 255, 255}; + class Button { public: enum State { From 0c1232ae3bfa2eeebd53699eca1d800254334add Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Mon, 24 Aug 2015 02:01:46 +1000 Subject: [PATCH 09/16] Fixed a graphical bug --- graphics/sprite_sheet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/sprite_sheet.cpp b/graphics/sprite_sheet.cpp index b0db04d..3d61f62 100644 --- a/graphics/sprite_sheet.cpp +++ b/graphics/sprite_sheet.cpp @@ -85,7 +85,7 @@ void SpriteSheet::Update(double delta) { } //modify area drawn clip.x = indexX * clip.w; - clip.y = indexX * clip.y; + clip.y = indexY * clip.h; } SDL_Texture* SpriteSheet::Load(SDL_Renderer* r, std::string fname, Uint16 cx, Uint16 cy) { From 37fadc6567d4acfdc6e8bebbc8914f2cbcac98f9 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Mon, 24 Aug 2015 14:26:32 +1000 Subject: [PATCH 10/16] Resolved bug #45 --- map/region_pager_base.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/map/region_pager_base.cpp b/map/region_pager_base.cpp index 857dabd..f041e89 100644 --- a/map/region_pager_base.cpp +++ b/map/region_pager_base.cpp @@ -34,7 +34,10 @@ Region::type_t RegionPagerBase::SetTile(int x, int y, int z, Region::type_t v) { } Region::type_t RegionPagerBase::GetTile(int x, int y, int z) { - Region* ptr = GetRegion(x, y); + Region* ptr = FindRegion(x, y); + if (!ptr) { + return 0; + } return ptr->GetTile(x - ptr->GetX(), y - ptr->GetY(), z); } @@ -44,7 +47,10 @@ bool RegionPagerBase::SetSolid(int x, int y, int b) { } bool RegionPagerBase::GetSolid(int x, int y) { - Region* ptr = GetRegion(x, y); + Region* ptr = FindRegion(x, y); + if (!ptr) { + return 0; + } return ptr->GetSolid(x - ptr->GetX(), y - ptr->GetY()); } From e7d3205a966e6a6d5370755cead42068aeda2143 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Mon, 24 Aug 2015 14:38:59 +1000 Subject: [PATCH 11/16] Comment tweak --- map/region_pager_base.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/map/region_pager_base.cpp b/map/region_pager_base.cpp index f041e89..49b8118 100644 --- a/map/region_pager_base.cpp +++ b/map/region_pager_base.cpp @@ -76,7 +76,6 @@ Region* RegionPagerBase::FindRegion(int x, int y) { } Region* RegionPagerBase::PushRegion(Region* const ptr) { - //BUG: #45 Some regions are occasionally losing their tile data regionList.push_front(*ptr); return ®ionList.front(); } From fd98749995cfd3f0c4f040878850e5f75d37cb56 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Thu, 3 Sep 2015 14:19:57 +1000 Subject: [PATCH 12/16] Added the scene template framework --- frameworks/network/makefile | 29 +++++ frameworks/scenes/application.cpp | 188 ++++++++++++++++++++++++++++ frameworks/scenes/application.hpp | 54 ++++++++ frameworks/scenes/base_scene.cpp | 105 ++++++++++++++++ frameworks/scenes/base_scene.hpp | 61 +++++++++ frameworks/scenes/example_scene.cpp | 83 ++++++++++++ frameworks/scenes/example_scene.hpp | 46 +++++++ frameworks/scenes/main.cpp | 43 +++++++ frameworks/scenes/makefile | 56 +++++++++ frameworks/scenes/scene_signal.hpp | 32 +++++ 10 files changed, 697 insertions(+) create mode 100644 frameworks/network/makefile create mode 100644 frameworks/scenes/application.cpp create mode 100644 frameworks/scenes/application.hpp create mode 100644 frameworks/scenes/base_scene.cpp create mode 100644 frameworks/scenes/base_scene.hpp create mode 100644 frameworks/scenes/example_scene.cpp create mode 100644 frameworks/scenes/example_scene.hpp create mode 100644 frameworks/scenes/main.cpp create mode 100644 frameworks/scenes/makefile create mode 100644 frameworks/scenes/scene_signal.hpp diff --git a/frameworks/network/makefile b/frameworks/network/makefile new file mode 100644 index 0000000..3bcac3d --- /dev/null +++ b/frameworks/network/makefile @@ -0,0 +1,29 @@ +#config +INCLUDES+=. packet_types ../gameplay ../map ../utilities +LIBS+= +CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) + +#source +CXXSRC=$(wildcard *.cpp) + +#objects +OBJDIR=obj +OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) + +#targets +all: $(OBJ) $(OUT) + ar -crs $(OUT) $(OBJ) + $(MAKE) -C packet_types + +$(OBJ): | $(OBJDIR) + +$(OUT): | $(OUTDIR) + +$(OBJDIR): + mkdir $(OBJDIR) + +$(OUTDIR): + mkdir $(OUTDIR) + +$(OBJDIR)/%.o: %.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/frameworks/scenes/application.cpp b/frameworks/scenes/application.cpp new file mode 100644 index 0000000..32b9906 --- /dev/null +++ b/frameworks/scenes/application.cpp @@ -0,0 +1,188 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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 "application.hpp" + +#include +#include +#include + +void Application::Init(int argc, char* argv[]) { + //create and check the window + window = SDL_CreateWindow( + "Example Caption", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + screenWidth, + screenHeight, + SDL_WINDOW_RESIZABLE); + + if (!window) { + std::ostringstream msg; + msg << "Failed to create the window: " << SDL_GetError(); + throw(std::runtime_error(msg.str())); + } + + //create and check the renderer + renderer = SDL_CreateRenderer(window, -1, 0); + + if (!renderer) { + std::ostringstream msg; + msg << "Failed to create the renderer: " << SDL_GetError(); + throw(std::runtime_error(msg.str())); + } + + //screen scaling + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); + SDL_RenderSetLogicalSize(renderer, 800, 600); + + //set the hook for the renderer + BaseScene::SetRenderer(renderer); +} + +void Application::Proc() { + //load the first scene + ProcessSceneSignal(SceneSignal::FIRST); + + //fixed frame rate + typedef std::chrono::steady_clock Clock; + + Clock::time_point simTime = Clock::now(); + Clock::time_point realTime; + constexpr std::chrono::duration frameDelay(16); //~60FPS + + //the game loop continues until the scenes signal QUIT + while(activeScene->GetSceneSignal() != SceneSignal::QUIT) { + //switch scenes if necessary + if(activeScene->GetSceneSignal() != SceneSignal::CONTINUE) { + ProcessSceneSignal(activeScene->GetSceneSignal()); + continue; + } + + //update the current time + realTime = Clock::now(); + + //simulate the game or give the machine a break + if (simTime < realTime) { + while(simTime < realTime) { + //call the user defined functions + activeScene->FrameStart(); + ProcessEvents(); + activeScene->Update(); + activeScene->FrameEnd(); + + //step to the next frame + simTime += frameDelay; + } + } + else { + SDL_Delay(1); + } + + SDL_RenderClear(renderer); + activeScene->RenderFrame(renderer); + SDL_RenderPresent(renderer); + } + + //cleanup + ClearScene(); +} + +void Application::Quit() { + //clean up after the program + BaseScene::SetRenderer(nullptr); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); +} + +//------------------------- +//Scene management +//------------------------- + +void Application::ProcessEvents() { + SDL_Event event; + while(SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_QUIT: + activeScene->QuitEvent(); + break; + + case SDL_MOUSEMOTION: + activeScene->MouseMotion(event.motion); + break; + + case SDL_MOUSEBUTTONDOWN: + activeScene->MouseButtonDown(event.button); + break; + + case SDL_MOUSEBUTTONUP: + activeScene->MouseButtonUp(event.button); + break; + + case SDL_MOUSEWHEEL: + activeScene->MouseWheel(event.wheel); + break; + + case SDL_KEYDOWN: + activeScene->KeyDown(event.key); + break; + + case SDL_KEYUP: + activeScene->KeyUp(event.key); + break; + + //TODO: joystick and controller events + + //window events are handled internally + case SDL_WINDOWEVENT: + switch(event.window.event) { + case SDL_WINDOWEVENT_RESIZED: + SDL_RenderSetLogicalSize(renderer, event.window.data1, event.window.data2); + break; + } + break; + } + } +} + +//Add the custom scene headers here +#include "example_scene.hpp" + +void Application::ProcessSceneSignal(SceneSignal signal) { + ClearScene(); + + switch(signal) { + case SceneSignal::FIRST: + case SceneSignal::EXAMPLE_SCENE: + activeScene = new ExampleScene(); + break; + default: { + std::ostringstream msg; + msg << "Failed to recognize the scene signal: " << signal; + throw(std::logic_error(msg.str())); + } + } +} + +void Application::ClearScene() { + delete activeScene; + activeScene = nullptr; +} \ No newline at end of file diff --git a/frameworks/scenes/application.hpp b/frameworks/scenes/application.hpp new file mode 100644 index 0000000..c927734 --- /dev/null +++ b/frameworks/scenes/application.hpp @@ -0,0 +1,54 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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. +*/ +#pragma once + +#include "base_scene.hpp" +#include "scene_signal.hpp" + +#include "SDL2/SDL.h" + +//TODO: do something with these +constexpr int screenWidth = 800; +constexpr int screenHeight = 600; + +//DOCS: The Application class handles scene switching, utilizing only one window +class Application { +public: + Application() = default; + ~Application() = default; + + void Init(int argc, char* argv[]); + void Proc(); + void Quit(); + +private: + //scene management + void ProcessEvents(); + void ProcessSceneSignal(SceneSignal); + void ClearScene(); + + BaseScene* activeScene = nullptr; + + //TODO: build a "window" class? + SDL_Window* window = nullptr; + SDL_Renderer* renderer = nullptr; +}; \ No newline at end of file diff --git a/frameworks/scenes/base_scene.cpp b/frameworks/scenes/base_scene.cpp new file mode 100644 index 0000000..f637710 --- /dev/null +++ b/frameworks/scenes/base_scene.cpp @@ -0,0 +1,105 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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 "base_scene.hpp" + +SDL_Renderer* BaseScene::rendererHandle = nullptr; + +BaseScene::BaseScene() { + //EMPTY +} + +BaseScene::~BaseScene() { + //EMPTY +} + +void BaseScene::RenderFrame(SDL_Renderer* renderer) { + //EMPTY +} + +void BaseScene::SetRenderer(SDL_Renderer* r) { + rendererHandle = r; +} + +SDL_Renderer* BaseScene::GetRenderer() { + return rendererHandle; +} + +void BaseScene::SetSceneSignal(SceneSignal signal) { + sceneSignal = signal; +} + +SceneSignal BaseScene::GetSceneSignal() { + return sceneSignal; +} + +//------------------------- +//frame phases +//------------------------- + +void BaseScene::FrameStart() { + //EMPTY +} + +void BaseScene::Update() { + //EMPTY +} + +void BaseScene::FrameEnd() { + //EMPTY +} + +//------------------------- +//input events +//------------------------- + +void BaseScene::QuitEvent() { + sceneSignal = SceneSignal::QUIT; +} + +void BaseScene::MouseMotion(SDL_MouseMotionEvent const& event) { + //EMPTY +} + +void BaseScene::MouseButtonDown(SDL_MouseButtonEvent const& event) { + //EMPTY +} + +void BaseScene::MouseButtonUp(SDL_MouseButtonEvent const& event) { + //EMPTY +} + +void BaseScene::MouseWheel(SDL_MouseWheelEvent const& event) { + //EMPTY +} + +void BaseScene::KeyDown(SDL_KeyboardEvent const& event) { + //preference as a default + switch(event.keysym.sym) { + case SDLK_ESCAPE: + QuitEvent(); + break; + } +} + +void BaseScene::KeyUp(SDL_KeyboardEvent const& event) { + //EMPTY +} diff --git a/frameworks/scenes/base_scene.hpp b/frameworks/scenes/base_scene.hpp new file mode 100644 index 0000000..96a4085 --- /dev/null +++ b/frameworks/scenes/base_scene.hpp @@ -0,0 +1,61 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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. +*/ +#pragma once + +#include "scene_signal.hpp" + +#include "SDL2/SDL.h" + +class BaseScene { +public: + BaseScene(); + virtual ~BaseScene(); + + virtual void RenderFrame(SDL_Renderer*); + static void SetRenderer(SDL_Renderer*); + SceneSignal GetSceneSignal(); + + //frame phases + virtual void FrameStart(); + virtual void Update(); + virtual void FrameEnd(); + + //input events + virtual void QuitEvent(); + virtual void MouseMotion(SDL_MouseMotionEvent const& event); + virtual void MouseButtonDown(SDL_MouseButtonEvent const& event); + virtual void MouseButtonUp(SDL_MouseButtonEvent const& event); + virtual void MouseWheel(SDL_MouseWheelEvent const& event); + virtual void KeyDown(SDL_KeyboardEvent const& event); + virtual void KeyUp(SDL_KeyboardEvent const& event); + + //TODO: joystick and controller events + +protected: + //control + static SDL_Renderer* GetRenderer(); + void SetSceneSignal(SceneSignal); + +private: + static SDL_Renderer* rendererHandle; + SceneSignal sceneSignal = SceneSignal::CONTINUE; +}; \ No newline at end of file diff --git a/frameworks/scenes/example_scene.cpp b/frameworks/scenes/example_scene.cpp new file mode 100644 index 0000000..33be9ab --- /dev/null +++ b/frameworks/scenes/example_scene.cpp @@ -0,0 +1,83 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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 "example_scene.hpp" + +ExampleScene::ExampleScene() { + // +} + +ExampleScene::~ExampleScene() { + // +} + +//------------------------- +//frame phases +//------------------------- + +void ExampleScene::FrameStart() { + // +} + +void ExampleScene::Update() { + // +} + +void ExampleScene::FrameEnd() { + // +} + +void ExampleScene::RenderFrame(SDL_Renderer* renderer) { + // +} + +//------------------------- +//input events +//------------------------- + +void ExampleScene::MouseMotion(SDL_MouseMotionEvent const& event) { + // +} + +void ExampleScene::MouseButtonDown(SDL_MouseButtonEvent const& event) { + // +} + +void ExampleScene::MouseButtonUp(SDL_MouseButtonEvent const& event) { + // +} + +void ExampleScene::MouseWheel(SDL_MouseWheelEvent const& event) { + // +} + +void ExampleScene::KeyDown(SDL_KeyboardEvent const& event) { + //preference as a default + switch(event.keysym.sym) { + case SDLK_ESCAPE: + QuitEvent(); + break; + } +} + +void ExampleScene::KeyUp(SDL_KeyboardEvent const& event) { + // +} diff --git a/frameworks/scenes/example_scene.hpp b/frameworks/scenes/example_scene.hpp new file mode 100644 index 0000000..2f18af1 --- /dev/null +++ b/frameworks/scenes/example_scene.hpp @@ -0,0 +1,46 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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. +*/ +#pragma once + +#include "base_scene.hpp" + +class ExampleScene : public BaseScene { +public: + ExampleScene(); + ~ExampleScene(); + + void RenderFrame(SDL_Renderer* renderer) override; + +private: + //frame phases + void FrameStart() override; + void Update() override; + void FrameEnd() override; + + //input events + void MouseMotion(SDL_MouseMotionEvent const& event) override; + void MouseButtonDown(SDL_MouseButtonEvent const& event) override; + void MouseButtonUp(SDL_MouseButtonEvent const& event) override; + void MouseWheel(SDL_MouseWheelEvent const& event) override; + void KeyDown(SDL_KeyboardEvent const& event) override; + void KeyUp(SDL_KeyboardEvent const& event) override; +}; diff --git a/frameworks/scenes/main.cpp b/frameworks/scenes/main.cpp new file mode 100644 index 0000000..90f7d67 --- /dev/null +++ b/frameworks/scenes/main.cpp @@ -0,0 +1,43 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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 "application.hpp" + +#include "SDL2/SDL.h" + +#include +#include + +int main(int argc, char** argv) { + std::cout << "Beginning " << argv[0] << std::endl; + try { + Application app; + app.Init(argc, argv); + app.Proc(); + app.Quit(); + } + catch(std::exception& e) { + std::cerr << "Fatal Error: " << e.what() << std::endl; + return 1; + } + std::cout << "Clean exit from " << argv[0] << std::endl; + return 0; +} \ No newline at end of file diff --git a/frameworks/scenes/makefile b/frameworks/scenes/makefile new file mode 100644 index 0000000..a8f0ea0 --- /dev/null +++ b/frameworks/scenes/makefile @@ -0,0 +1,56 @@ +#include directories +INCLUDES+=. + +#libraries +#the order of the $(LIBS) is important, at least for MinGW +LIBS+= +ifeq ($(OS),Windows_NT) + LIBS+=-lmingw32 +endif +LIBS+=-lSDL2main -lSDL2 + +#flags +CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) +ifeq ($(shell uname), Linux) + #read data about the current install + CXXFLAGS+=$(shell sdl-config --cflags --static-libs) +endif + +#source +CXXSRC=$(wildcard *.cpp) + +#objects +OBJDIR=obj +OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) + +#output +OUTDIR=out +OUT=$(addprefix $(OUTDIR)/,scenes) + +#targets +all: $(OBJ) $(OUT) + $(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS) + +$(OBJ): | $(OBJDIR) + +$(OUT): | $(OUTDIR) + +$(OBJDIR): + mkdir $(OBJDIR) + +$(OUTDIR): + mkdir $(OUTDIR) + +$(OBJDIR)/%.o: %.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +clean: +ifeq ($(OS),Windows_NT) + $(RM) *.o *.a *.exe +else ifeq ($(shell uname), Linux) + find . -type f -name '*.o' -exec rm -f -r -v {} \; + find . -type f -name '*.a' -exec rm -f -r -v {} \; + rm -f -v $(OUT) +endif + +rebuild: clean all diff --git a/frameworks/scenes/scene_signal.hpp b/frameworks/scenes/scene_signal.hpp new file mode 100644 index 0000000..49e0bcb --- /dev/null +++ b/frameworks/scenes/scene_signal.hpp @@ -0,0 +1,32 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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. +*/ +#pragma once + +enum SceneSignal { + //reserved members for internal use + QUIT = -1, + CONTINUE = 0, + FIRST = 1, + + //custom scenes + EXAMPLE_SCENE +}; \ No newline at end of file From f83f5f76c7f156237a84df9aea5a06439688a571 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Thu, 3 Sep 2015 14:23:59 +1000 Subject: [PATCH 13/16] tweaked .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 497ac38..ee3a5ac 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ Out/ release/ debug/ out/ +bin/ +common/ #Project generated files *.db From 3eafb57403e469cc3b7517fe89618095c352e2f1 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Thu, 3 Sep 2015 14:47:03 +1000 Subject: [PATCH 14/16] Fixed magic numbers for default screen size --- frameworks/scenes/application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/scenes/application.cpp b/frameworks/scenes/application.cpp index 32b9906..0b68fdd 100644 --- a/frameworks/scenes/application.cpp +++ b/frameworks/scenes/application.cpp @@ -52,7 +52,7 @@ void Application::Init(int argc, char* argv[]) { //screen scaling SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); - SDL_RenderSetLogicalSize(renderer, 800, 600); + SDL_RenderSetLogicalSize(renderer, screenWidth, screenHeight); //set the hook for the renderer BaseScene::SetRenderer(renderer); From 15cd3648a3ce9c63c4c9e901978eb7c4fe94896c Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 18 Mar 2016 21:09:02 +1100 Subject: [PATCH 15/16] Fixed minor networking issue --- network/packet_types/server_packet.cpp | 4 ++-- network/serial_packet.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/network/packet_types/server_packet.cpp b/network/packet_types/server_packet.cpp index 562d353..eefefbe 100644 --- a/network/packet_types/server_packet.cpp +++ b/network/packet_types/server_packet.cpp @@ -27,16 +27,16 @@ void serializeServer(void* buffer, ServerPacket* packet) { serialCopy(&buffer, &packet->type, sizeof(SerialPacketType)); //identify the server + serialCopy(&buffer, &packet->version, sizeof(int)); serialCopy(&buffer, packet->name, PACKET_STRING_SIZE); serialCopy(&buffer, &packet->playerCount, sizeof(int)); - serialCopy(&buffer, &packet->version, sizeof(int)); } void deserializeServer(void* buffer, ServerPacket* packet) { deserialCopy(&buffer, &packet->type, sizeof(SerialPacketType)); //identify the server + deserialCopy(&buffer, &packet->version, sizeof(int)); deserialCopy(&buffer, packet->name, PACKET_STRING_SIZE); deserialCopy(&buffer, &packet->playerCount, sizeof(int)); - deserialCopy(&buffer, &packet->version, sizeof(int)); } diff --git a/network/serial_packet.hpp b/network/serial_packet.hpp index fbfb851..4bf1d8a 100644 --- a/network/serial_packet.hpp +++ b/network/serial_packet.hpp @@ -33,7 +33,7 @@ typedef SerialPacketBase SerialPacket; //DOCS: NETWORK_VERSION is used to discern compatible servers and clients -constexpr int NETWORK_VERSION = 20150820; +constexpr int NETWORK_VERSION = 20160316; union MaxPacket { CharacterPacket a; From 49b15f4710e7fe33dc7c468589aa8c188dbdb4ec Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sat, 19 Mar 2016 06:10:32 +1100 Subject: [PATCH 16/16] Moved all folders into common/ --- .gitignore | 26 ------------------- README.md | 11 -------- {debugging => common/debugging}/makefile | 0 {debugging => common/debugging}/timer.cpp | 0 {debugging => common/debugging}/timer.hpp | 0 .../frameworks}/network/makefile | 0 .../frameworks}/scenes/application.cpp | 0 .../frameworks}/scenes/application.hpp | 0 .../frameworks}/scenes/base_scene.cpp | 0 .../frameworks}/scenes/base_scene.hpp | 0 .../frameworks}/scenes/example_scene.cpp | 0 .../frameworks}/scenes/example_scene.hpp | 0 .../frameworks}/scenes/main.cpp | 0 .../frameworks}/scenes/makefile | 0 .../frameworks}/scenes/scene_signal.hpp | 0 .../gameplay}/character_defines.hpp | 0 {gameplay => common/gameplay}/makefile | 0 {graphics => common/graphics}/button.cpp | 0 {graphics => common/graphics}/button.hpp | 0 {graphics => common/graphics}/image.cpp | 0 {graphics => common/graphics}/image.hpp | 0 {graphics => common/graphics}/makefile | 0 .../graphics}/sprite_sheet.cpp | 0 .../graphics}/sprite_sheet.hpp | 0 {graphics => common/graphics}/text_box.cpp | 0 {graphics => common/graphics}/text_box.hpp | 0 {graphics => common/graphics}/text_line.cpp | 0 {graphics => common/graphics}/text_line.hpp | 0 {map => common/map}/makefile | 0 {map => common/map}/region.cpp | 0 {map => common/map}/region.hpp | 0 {map => common/map}/region_api.cpp | 0 {map => common/map}/region_api.hpp | 0 {map => common/map}/region_pager_api.cpp | 0 {map => common/map}/region_pager_api.hpp | 0 {map => common/map}/region_pager_base.cpp | 0 {map => common/map}/region_pager_base.hpp | 0 {map => common/map}/region_pager_lua.cpp | 0 {map => common/map}/region_pager_lua.hpp | 0 {map => common/map}/tile_sheet.cpp | 0 {map => common/map}/tile_sheet.hpp | 0 {network => common/network}/makefile | 0 .../packet_types/character_packet.cpp | 0 .../packet_types/character_packet.hpp | 0 .../network}/packet_types/client_packet.cpp | 0 .../network}/packet_types/client_packet.hpp | 0 .../network}/packet_types/makefile | 0 .../network}/packet_types/monster_packet.cpp | 0 .../network}/packet_types/monster_packet.hpp | 0 .../network}/packet_types/region_packet.cpp | 0 .../network}/packet_types/region_packet.hpp | 0 .../packet_types/serial_packet_base.cpp | 0 .../packet_types/serial_packet_base.hpp | 0 .../network}/packet_types/server_packet.cpp | 0 .../network}/packet_types/server_packet.hpp | 0 .../network}/packet_types/text_packet.cpp | 0 .../network}/packet_types/text_packet.hpp | 0 {network => common/network}/serial_packet.hpp | 0 .../network}/serial_packet_type.hpp | 0 .../network}/serial_utility.cpp | 0 .../network}/serial_utility.hpp | 0 .../network}/udp_network_utility.cpp | 0 .../network}/udp_network_utility.hpp | 0 .../utilities}/bounding_box.hpp | 0 .../utilities}/config_utility.cpp | 0 .../utilities}/config_utility.hpp | 0 .../utilities}/frame_rate.hpp | 0 .../utilities}/ip_operators.cpp | 0 .../utilities}/ip_operators.hpp | 0 {utilities => common/utilities}/makefile | 0 {utilities => common/utilities}/singleton.hpp | 0 {utilities => common/utilities}/vector2.hpp | 0 72 files changed, 37 deletions(-) delete mode 100644 .gitignore delete mode 100644 README.md rename {debugging => common/debugging}/makefile (100%) rename {debugging => common/debugging}/timer.cpp (100%) rename {debugging => common/debugging}/timer.hpp (100%) rename {frameworks => common/frameworks}/network/makefile (100%) rename {frameworks => common/frameworks}/scenes/application.cpp (100%) rename {frameworks => common/frameworks}/scenes/application.hpp (100%) rename {frameworks => common/frameworks}/scenes/base_scene.cpp (100%) rename {frameworks => common/frameworks}/scenes/base_scene.hpp (100%) rename {frameworks => common/frameworks}/scenes/example_scene.cpp (100%) rename {frameworks => common/frameworks}/scenes/example_scene.hpp (100%) rename {frameworks => common/frameworks}/scenes/main.cpp (100%) rename {frameworks => common/frameworks}/scenes/makefile (100%) rename {frameworks => common/frameworks}/scenes/scene_signal.hpp (100%) rename {gameplay => common/gameplay}/character_defines.hpp (100%) rename {gameplay => common/gameplay}/makefile (100%) rename {graphics => common/graphics}/button.cpp (100%) rename {graphics => common/graphics}/button.hpp (100%) rename {graphics => common/graphics}/image.cpp (100%) rename {graphics => common/graphics}/image.hpp (100%) rename {graphics => common/graphics}/makefile (100%) rename {graphics => common/graphics}/sprite_sheet.cpp (100%) rename {graphics => common/graphics}/sprite_sheet.hpp (100%) rename {graphics => common/graphics}/text_box.cpp (100%) rename {graphics => common/graphics}/text_box.hpp (100%) rename {graphics => common/graphics}/text_line.cpp (100%) rename {graphics => common/graphics}/text_line.hpp (100%) rename {map => common/map}/makefile (100%) rename {map => common/map}/region.cpp (100%) rename {map => common/map}/region.hpp (100%) rename {map => common/map}/region_api.cpp (100%) rename {map => common/map}/region_api.hpp (100%) rename {map => common/map}/region_pager_api.cpp (100%) rename {map => common/map}/region_pager_api.hpp (100%) rename {map => common/map}/region_pager_base.cpp (100%) rename {map => common/map}/region_pager_base.hpp (100%) rename {map => common/map}/region_pager_lua.cpp (100%) rename {map => common/map}/region_pager_lua.hpp (100%) rename {map => common/map}/tile_sheet.cpp (100%) rename {map => common/map}/tile_sheet.hpp (100%) rename {network => common/network}/makefile (100%) rename {network => common/network}/packet_types/character_packet.cpp (100%) rename {network => common/network}/packet_types/character_packet.hpp (100%) rename {network => common/network}/packet_types/client_packet.cpp (100%) rename {network => common/network}/packet_types/client_packet.hpp (100%) rename {network => common/network}/packet_types/makefile (100%) rename {network => common/network}/packet_types/monster_packet.cpp (100%) rename {network => common/network}/packet_types/monster_packet.hpp (100%) rename {network => common/network}/packet_types/region_packet.cpp (100%) rename {network => common/network}/packet_types/region_packet.hpp (100%) rename {network => common/network}/packet_types/serial_packet_base.cpp (100%) rename {network => common/network}/packet_types/serial_packet_base.hpp (100%) rename {network => common/network}/packet_types/server_packet.cpp (100%) rename {network => common/network}/packet_types/server_packet.hpp (100%) rename {network => common/network}/packet_types/text_packet.cpp (100%) rename {network => common/network}/packet_types/text_packet.hpp (100%) rename {network => common/network}/serial_packet.hpp (100%) rename {network => common/network}/serial_packet_type.hpp (100%) rename {network => common/network}/serial_utility.cpp (100%) rename {network => common/network}/serial_utility.hpp (100%) rename {network => common/network}/udp_network_utility.cpp (100%) rename {network => common/network}/udp_network_utility.hpp (100%) rename {utilities => common/utilities}/bounding_box.hpp (100%) rename {utilities => common/utilities}/config_utility.cpp (100%) rename {utilities => common/utilities}/config_utility.hpp (100%) rename {utilities => common/utilities}/frame_rate.hpp (100%) rename {utilities => common/utilities}/ip_operators.cpp (100%) rename {utilities => common/utilities}/ip_operators.hpp (100%) rename {utilities => common/utilities}/makefile (100%) rename {utilities => common/utilities}/singleton.hpp (100%) rename {utilities => common/utilities}/vector2.hpp (100%) diff --git a/.gitignore b/.gitignore deleted file mode 100644 index ee3a5ac..0000000 --- a/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -#Editor generated files -*.sln -*.vcproj -*.suo -*.ncb -*.user - -#Directories -Release/ -Debug/ -Out/ -release/ -debug/ -out/ -bin/ -common/ - -#Project generated files -*.db -*.o -*.a -*.exe - -#Shell files -*.bat -*.sh diff --git a/README.md b/README.md deleted file mode 100644 index 9bc9e84..0000000 --- a/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## Copyright - -Copyright (c) 2013-2015 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/debugging/makefile b/common/debugging/makefile similarity index 100% rename from debugging/makefile rename to common/debugging/makefile diff --git a/debugging/timer.cpp b/common/debugging/timer.cpp similarity index 100% rename from debugging/timer.cpp rename to common/debugging/timer.cpp diff --git a/debugging/timer.hpp b/common/debugging/timer.hpp similarity index 100% rename from debugging/timer.hpp rename to common/debugging/timer.hpp diff --git a/frameworks/network/makefile b/common/frameworks/network/makefile similarity index 100% rename from frameworks/network/makefile rename to common/frameworks/network/makefile diff --git a/frameworks/scenes/application.cpp b/common/frameworks/scenes/application.cpp similarity index 100% rename from frameworks/scenes/application.cpp rename to common/frameworks/scenes/application.cpp diff --git a/frameworks/scenes/application.hpp b/common/frameworks/scenes/application.hpp similarity index 100% rename from frameworks/scenes/application.hpp rename to common/frameworks/scenes/application.hpp diff --git a/frameworks/scenes/base_scene.cpp b/common/frameworks/scenes/base_scene.cpp similarity index 100% rename from frameworks/scenes/base_scene.cpp rename to common/frameworks/scenes/base_scene.cpp diff --git a/frameworks/scenes/base_scene.hpp b/common/frameworks/scenes/base_scene.hpp similarity index 100% rename from frameworks/scenes/base_scene.hpp rename to common/frameworks/scenes/base_scene.hpp diff --git a/frameworks/scenes/example_scene.cpp b/common/frameworks/scenes/example_scene.cpp similarity index 100% rename from frameworks/scenes/example_scene.cpp rename to common/frameworks/scenes/example_scene.cpp diff --git a/frameworks/scenes/example_scene.hpp b/common/frameworks/scenes/example_scene.hpp similarity index 100% rename from frameworks/scenes/example_scene.hpp rename to common/frameworks/scenes/example_scene.hpp diff --git a/frameworks/scenes/main.cpp b/common/frameworks/scenes/main.cpp similarity index 100% rename from frameworks/scenes/main.cpp rename to common/frameworks/scenes/main.cpp diff --git a/frameworks/scenes/makefile b/common/frameworks/scenes/makefile similarity index 100% rename from frameworks/scenes/makefile rename to common/frameworks/scenes/makefile diff --git a/frameworks/scenes/scene_signal.hpp b/common/frameworks/scenes/scene_signal.hpp similarity index 100% rename from frameworks/scenes/scene_signal.hpp rename to common/frameworks/scenes/scene_signal.hpp diff --git a/gameplay/character_defines.hpp b/common/gameplay/character_defines.hpp similarity index 100% rename from gameplay/character_defines.hpp rename to common/gameplay/character_defines.hpp diff --git a/gameplay/makefile b/common/gameplay/makefile similarity index 100% rename from gameplay/makefile rename to common/gameplay/makefile diff --git a/graphics/button.cpp b/common/graphics/button.cpp similarity index 100% rename from graphics/button.cpp rename to common/graphics/button.cpp diff --git a/graphics/button.hpp b/common/graphics/button.hpp similarity index 100% rename from graphics/button.hpp rename to common/graphics/button.hpp diff --git a/graphics/image.cpp b/common/graphics/image.cpp similarity index 100% rename from graphics/image.cpp rename to common/graphics/image.cpp diff --git a/graphics/image.hpp b/common/graphics/image.hpp similarity index 100% rename from graphics/image.hpp rename to common/graphics/image.hpp diff --git a/graphics/makefile b/common/graphics/makefile similarity index 100% rename from graphics/makefile rename to common/graphics/makefile diff --git a/graphics/sprite_sheet.cpp b/common/graphics/sprite_sheet.cpp similarity index 100% rename from graphics/sprite_sheet.cpp rename to common/graphics/sprite_sheet.cpp diff --git a/graphics/sprite_sheet.hpp b/common/graphics/sprite_sheet.hpp similarity index 100% rename from graphics/sprite_sheet.hpp rename to common/graphics/sprite_sheet.hpp diff --git a/graphics/text_box.cpp b/common/graphics/text_box.cpp similarity index 100% rename from graphics/text_box.cpp rename to common/graphics/text_box.cpp diff --git a/graphics/text_box.hpp b/common/graphics/text_box.hpp similarity index 100% rename from graphics/text_box.hpp rename to common/graphics/text_box.hpp diff --git a/graphics/text_line.cpp b/common/graphics/text_line.cpp similarity index 100% rename from graphics/text_line.cpp rename to common/graphics/text_line.cpp diff --git a/graphics/text_line.hpp b/common/graphics/text_line.hpp similarity index 100% rename from graphics/text_line.hpp rename to common/graphics/text_line.hpp diff --git a/map/makefile b/common/map/makefile similarity index 100% rename from map/makefile rename to common/map/makefile diff --git a/map/region.cpp b/common/map/region.cpp similarity index 100% rename from map/region.cpp rename to common/map/region.cpp diff --git a/map/region.hpp b/common/map/region.hpp similarity index 100% rename from map/region.hpp rename to common/map/region.hpp diff --git a/map/region_api.cpp b/common/map/region_api.cpp similarity index 100% rename from map/region_api.cpp rename to common/map/region_api.cpp diff --git a/map/region_api.hpp b/common/map/region_api.hpp similarity index 100% rename from map/region_api.hpp rename to common/map/region_api.hpp diff --git a/map/region_pager_api.cpp b/common/map/region_pager_api.cpp similarity index 100% rename from map/region_pager_api.cpp rename to common/map/region_pager_api.cpp diff --git a/map/region_pager_api.hpp b/common/map/region_pager_api.hpp similarity index 100% rename from map/region_pager_api.hpp rename to common/map/region_pager_api.hpp diff --git a/map/region_pager_base.cpp b/common/map/region_pager_base.cpp similarity index 100% rename from map/region_pager_base.cpp rename to common/map/region_pager_base.cpp diff --git a/map/region_pager_base.hpp b/common/map/region_pager_base.hpp similarity index 100% rename from map/region_pager_base.hpp rename to common/map/region_pager_base.hpp diff --git a/map/region_pager_lua.cpp b/common/map/region_pager_lua.cpp similarity index 100% rename from map/region_pager_lua.cpp rename to common/map/region_pager_lua.cpp diff --git a/map/region_pager_lua.hpp b/common/map/region_pager_lua.hpp similarity index 100% rename from map/region_pager_lua.hpp rename to common/map/region_pager_lua.hpp diff --git a/map/tile_sheet.cpp b/common/map/tile_sheet.cpp similarity index 100% rename from map/tile_sheet.cpp rename to common/map/tile_sheet.cpp diff --git a/map/tile_sheet.hpp b/common/map/tile_sheet.hpp similarity index 100% rename from map/tile_sheet.hpp rename to common/map/tile_sheet.hpp diff --git a/network/makefile b/common/network/makefile similarity index 100% rename from network/makefile rename to common/network/makefile diff --git a/network/packet_types/character_packet.cpp b/common/network/packet_types/character_packet.cpp similarity index 100% rename from network/packet_types/character_packet.cpp rename to common/network/packet_types/character_packet.cpp diff --git a/network/packet_types/character_packet.hpp b/common/network/packet_types/character_packet.hpp similarity index 100% rename from network/packet_types/character_packet.hpp rename to common/network/packet_types/character_packet.hpp diff --git a/network/packet_types/client_packet.cpp b/common/network/packet_types/client_packet.cpp similarity index 100% rename from network/packet_types/client_packet.cpp rename to common/network/packet_types/client_packet.cpp diff --git a/network/packet_types/client_packet.hpp b/common/network/packet_types/client_packet.hpp similarity index 100% rename from network/packet_types/client_packet.hpp rename to common/network/packet_types/client_packet.hpp diff --git a/network/packet_types/makefile b/common/network/packet_types/makefile similarity index 100% rename from network/packet_types/makefile rename to common/network/packet_types/makefile diff --git a/network/packet_types/monster_packet.cpp b/common/network/packet_types/monster_packet.cpp similarity index 100% rename from network/packet_types/monster_packet.cpp rename to common/network/packet_types/monster_packet.cpp diff --git a/network/packet_types/monster_packet.hpp b/common/network/packet_types/monster_packet.hpp similarity index 100% rename from network/packet_types/monster_packet.hpp rename to common/network/packet_types/monster_packet.hpp diff --git a/network/packet_types/region_packet.cpp b/common/network/packet_types/region_packet.cpp similarity index 100% rename from network/packet_types/region_packet.cpp rename to common/network/packet_types/region_packet.cpp diff --git a/network/packet_types/region_packet.hpp b/common/network/packet_types/region_packet.hpp similarity index 100% rename from network/packet_types/region_packet.hpp rename to common/network/packet_types/region_packet.hpp diff --git a/network/packet_types/serial_packet_base.cpp b/common/network/packet_types/serial_packet_base.cpp similarity index 100% rename from network/packet_types/serial_packet_base.cpp rename to common/network/packet_types/serial_packet_base.cpp diff --git a/network/packet_types/serial_packet_base.hpp b/common/network/packet_types/serial_packet_base.hpp similarity index 100% rename from network/packet_types/serial_packet_base.hpp rename to common/network/packet_types/serial_packet_base.hpp diff --git a/network/packet_types/server_packet.cpp b/common/network/packet_types/server_packet.cpp similarity index 100% rename from network/packet_types/server_packet.cpp rename to common/network/packet_types/server_packet.cpp diff --git a/network/packet_types/server_packet.hpp b/common/network/packet_types/server_packet.hpp similarity index 100% rename from network/packet_types/server_packet.hpp rename to common/network/packet_types/server_packet.hpp diff --git a/network/packet_types/text_packet.cpp b/common/network/packet_types/text_packet.cpp similarity index 100% rename from network/packet_types/text_packet.cpp rename to common/network/packet_types/text_packet.cpp diff --git a/network/packet_types/text_packet.hpp b/common/network/packet_types/text_packet.hpp similarity index 100% rename from network/packet_types/text_packet.hpp rename to common/network/packet_types/text_packet.hpp diff --git a/network/serial_packet.hpp b/common/network/serial_packet.hpp similarity index 100% rename from network/serial_packet.hpp rename to common/network/serial_packet.hpp diff --git a/network/serial_packet_type.hpp b/common/network/serial_packet_type.hpp similarity index 100% rename from network/serial_packet_type.hpp rename to common/network/serial_packet_type.hpp diff --git a/network/serial_utility.cpp b/common/network/serial_utility.cpp similarity index 100% rename from network/serial_utility.cpp rename to common/network/serial_utility.cpp diff --git a/network/serial_utility.hpp b/common/network/serial_utility.hpp similarity index 100% rename from network/serial_utility.hpp rename to common/network/serial_utility.hpp diff --git a/network/udp_network_utility.cpp b/common/network/udp_network_utility.cpp similarity index 100% rename from network/udp_network_utility.cpp rename to common/network/udp_network_utility.cpp diff --git a/network/udp_network_utility.hpp b/common/network/udp_network_utility.hpp similarity index 100% rename from network/udp_network_utility.hpp rename to common/network/udp_network_utility.hpp diff --git a/utilities/bounding_box.hpp b/common/utilities/bounding_box.hpp similarity index 100% rename from utilities/bounding_box.hpp rename to common/utilities/bounding_box.hpp diff --git a/utilities/config_utility.cpp b/common/utilities/config_utility.cpp similarity index 100% rename from utilities/config_utility.cpp rename to common/utilities/config_utility.cpp diff --git a/utilities/config_utility.hpp b/common/utilities/config_utility.hpp similarity index 100% rename from utilities/config_utility.hpp rename to common/utilities/config_utility.hpp diff --git a/utilities/frame_rate.hpp b/common/utilities/frame_rate.hpp similarity index 100% rename from utilities/frame_rate.hpp rename to common/utilities/frame_rate.hpp diff --git a/utilities/ip_operators.cpp b/common/utilities/ip_operators.cpp similarity index 100% rename from utilities/ip_operators.cpp rename to common/utilities/ip_operators.cpp diff --git a/utilities/ip_operators.hpp b/common/utilities/ip_operators.hpp similarity index 100% rename from utilities/ip_operators.hpp rename to common/utilities/ip_operators.hpp diff --git a/utilities/makefile b/common/utilities/makefile similarity index 100% rename from utilities/makefile rename to common/utilities/makefile diff --git a/utilities/singleton.hpp b/common/utilities/singleton.hpp similarity index 100% rename from utilities/singleton.hpp rename to common/utilities/singleton.hpp diff --git a/utilities/vector2.hpp b/common/utilities/vector2.hpp similarity index 100% rename from utilities/vector2.hpp rename to common/utilities/vector2.hpp