diff --git a/client/channels.hpp b/client/channels.hpp index 2fe04a7..431b877 100644 --- a/client/channels.hpp +++ b/client/channels.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/client/client_application.cpp b/client/client_application.cpp index 2725314..f2dcd8a 100644 --- a/client/client_application.cpp +++ b/client/client_application.cpp @@ -1,11 +1,11 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 ClientApplications, and to alter it and redistribute it + * 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 @@ -49,7 +49,7 @@ void ClientApplication::Init(int argc, char* argv[]) { //load the prerequisites ConfigUtility& config = ConfigUtility::GetSingleton(); - config.Load("rsc/config.cfg", argc, argv); + config.Load("rsc/config.cfg", false, argc, argv); //------------------------- //Initialize the APIs @@ -178,7 +178,7 @@ void ClientApplication::LoadScene(SceneList sceneIndex) { activeScene = new OptionsMenu(); break; case SceneList::LOBBYMENU: - activeScene = new LobbyMenu(&clientIndex, &accountIndex); //TODO: can I use the ConfigUtility for these parameters? + activeScene = new LobbyMenu(&clientIndex, &accountIndex); break; case SceneList::INWORLD: activeScene = new InWorld(&clientIndex, &accountIndex); diff --git a/client/client_application.hpp b/client/client_application.hpp index 7e99458..6f6fc0b 100644 --- a/client/client_application.hpp +++ b/client/client_application.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/network/packet_types/serial_statistics.hpp b/client/client_utilities/terminal_error.cpp similarity index 77% rename from common/network/packet_types/serial_statistics.hpp rename to client/client_utilities/terminal_error.cpp index 2f4243f..b113807 100644 --- a/common/network/packet_types/serial_statistics.hpp +++ b/client/client_utilities/terminal_error.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -19,12 +19,5 @@ * 3. This notice may not be removed or altered from any source * distribution. */ -#ifndef SERIALSTATISTICS_HPP_ -#define SERIALSTATISTICS_HPP_ +#include "terminal_error.hpp" -#include "statistics.hpp" - -void serializeStatistics(void** buffer, Statistics* stats); -void deserializeStatistics(void** buffer, Statistics* stats); - -#endif \ No newline at end of file diff --git a/client/client_utilities/terminal_error.hpp b/client/client_utilities/terminal_error.hpp new file mode 100644 index 0000000..8a7216b --- /dev/null +++ b/client/client_utilities/terminal_error.hpp @@ -0,0 +1,34 @@ +/* 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. +*/ +#ifndef TERMINALERROR_HPP_ +#define TERMINALERROR_HPP_ + +#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) {} +}; + +#endif diff --git a/client/entities/base_character.cpp b/client/entities/base_character.cpp new file mode 100644 index 0000000..c0e3f99 --- /dev/null +++ b/client/entities/base_character.cpp @@ -0,0 +1,83 @@ +/* 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.SetYIndex(0); + } + else if (motion.y < 0) { + sprite.SetYIndex(1); + } + else if (motion.x > 0) { + sprite.SetYIndex(3); + } + else if (motion.x < 0) { + sprite.SetYIndex(2); + } + + //animation + if (motion != 0) { + sprite.SetDelay(0.1); + } + else { + sprite.SetDelay(0); + sprite.SetXIndex(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(std::string s) { + avatar = s; + sprite.LoadSurface(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/renderable/base_character.hpp b/client/entities/base_character.hpp similarity index 74% rename from client/renderable/base_character.hpp rename to client/entities/base_character.hpp index 1531ba3..cd38a6a 100644 --- a/client/renderable/base_character.hpp +++ b/client/entities/base_character.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -24,12 +24,12 @@ //components #include "character_defines.hpp" -#include "renderable.hpp" +#include "entity.hpp" //std namespace #include -class BaseCharacter : public Renderable { +class BaseCharacter: public Entity { public: BaseCharacter() = default; virtual ~BaseCharacter() = default; @@ -38,14 +38,14 @@ public: void CorrectSprite(); //metadata - int SetOwner(int i) { return owner = i; } - int GetOwner() { return owner; } - std::string SetHandle(std::string s) { return handle = s; } - std::string GetHandle() const { return handle; } - std::string SetAvatar(std::string s) { return avatar = s; } - std::string GetAvatar() const { return avatar; } + int SetOwner(int i); + int GetOwner(); + std::string SetHandle(std::string s); + std::string GetHandle() const; + std::string SetAvatar(std::string s); + std::string GetAvatar() const; -private: +protected: //metadata int owner; std::string handle; diff --git a/client/renderable/base_monster.cpp b/client/entities/base_monster.cpp similarity index 95% rename from client/renderable/base_monster.cpp rename to client/entities/base_monster.cpp index e6350c4..2eaa513 100644 --- a/client/renderable/base_monster.cpp +++ b/client/entities/base_monster.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/client/renderable/base_monster.hpp b/client/entities/base_monster.hpp similarity index 90% rename from client/renderable/base_monster.hpp rename to client/entities/base_monster.hpp index 15cea7d..c9b7bb3 100644 --- a/client/renderable/base_monster.hpp +++ b/client/entities/base_monster.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -22,14 +22,14 @@ #ifndef BASEMONSTER_HPP_ #define BASEMONSTER_HPP_ -#include "renderable.hpp" +#include "entity.hpp" -class BaseMonster { +class BaseMonster: public Entity { public: BaseMonster() = default; virtual ~BaseMonster() = default; -private: +protected: // }; diff --git a/client/entities/entity.cpp b/client/entities/entity.cpp new file mode 100644 index 0000000..da67f27 --- /dev/null +++ b/client/entities/entity.cpp @@ -0,0 +1,63 @@ +/* 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_Surface* const dest, int camX, int camY) { + sprite.DrawTo(dest, 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/renderable/renderable.hpp b/client/entities/entity.hpp similarity index 63% rename from client/renderable/renderable.hpp rename to client/entities/entity.hpp index d78cde2..77b5c1c 100644 --- a/client/renderable/renderable.hpp +++ b/client/entities/entity.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -19,37 +19,37 @@ * 3. This notice may not be removed or altered from any source * distribution. */ -#ifndef RENDERABLE_HPP_ -#define RENDERABLE_HPP_ +#ifndef ENTITY_HPP_ +#define ENTITY_HPP_ #include "bounding_box.hpp" #include "sprite_sheet.hpp" #include "vector2.hpp" -class Renderable { +//The base class for all objects in the world +class Entity { public: - Renderable() = default; - virtual ~Renderable() = default; - virtual void Update(); virtual void DrawTo(SDL_Surface* const, int camX, int camY); - SpriteSheet* GetSprite() { return &sprite; } + SpriteSheet* GetSprite(); - //position - Vector2 SetOrigin(Vector2 v) { return origin = v; } - Vector2 GetOrigin() const { return origin; } - Vector2 SetMotion(Vector2 v) { return motion = v; } - Vector2 GetMotion() const { return motion; } + //accessors & mutators + Vector2 SetOrigin(Vector2 v); + Vector2 SetMotion(Vector2 v); + BoundingBox SetBounds(BoundingBox b); - //collision - BoundingBox SetBounds(BoundingBox b) { return bounds = b; } - BoundingBox GetBounds() { return bounds; } + Vector2 GetOrigin(); + Vector2 GetMotion(); + BoundingBox GetBounds(); + +protected: + Entity() = default; + virtual ~Entity() = default; -protected: //TODO: should be private SpriteSheet sprite; - Vector2 origin = {0, 0}; - Vector2 motion = {0, 0}; + Vector2 origin; + Vector2 motion; BoundingBox bounds; }; diff --git a/client/renderable/local_character.cpp b/client/entities/local_character.cpp similarity index 75% rename from client/renderable/local_character.cpp rename to client/entities/local_character.cpp index 211a6bc..16c1eff 100644 --- a/client/renderable/local_character.cpp +++ b/client/entities/local_character.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -21,3 +21,15 @@ */ #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/renderable/local_character.hpp b/client/entities/local_character.hpp similarity index 72% rename from client/renderable/local_character.hpp rename to client/entities/local_character.hpp index 37e90de..a462ddc 100644 --- a/client/renderable/local_character.hpp +++ b/client/entities/local_character.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -23,22 +23,20 @@ #define LOCALCHARACTER_HPP_ #include "base_character.hpp" -#include "statistics.hpp" +#include "bounding_box.hpp" +#include "vector2.hpp" -class LocalCharacter : public BaseCharacter { +#include + +class LocalCharacter: public BaseCharacter { public: LocalCharacter() = default; - ~LocalCharacter() = default; + virtual ~LocalCharacter() = default; - int SetRoomIndex(int i) { return roomIndex = i; } - int GetRoomIndex() { return roomIndex; } - - Statistics* GetBaseStats() { return &baseStats; } + bool ProcessCollisionGrid(std::list); private: - int roomIndex = -1; - Statistics baseStats; - //TODO: weapons, armour, buffs, debuffs, etc. + //NOTE: NO MEMBERS }; -#endif +#endif \ No newline at end of file diff --git a/client/renderable/makefile b/client/entities/makefile similarity index 100% rename from client/renderable/makefile rename to client/entities/makefile diff --git a/client/main.cpp b/client/main.cpp index 2115115..1278f91 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 @@ -36,7 +36,7 @@ int main(int argc, char* argv[]) { ConfigUtility::CreateSingleton(); UDPNetworkUtility::CreateSingleton(); - //call the server's routines + //call the client's routines ClientApplication::CreateSingleton(); ClientApplication& app = ClientApplication::GetSingleton(); diff --git a/client/makefile b/client/makefile index 39c104f..68ce8d9 100644 --- a/client/makefile +++ b/client/makefile @@ -1,5 +1,5 @@ #include directories -INCLUDES+=. client_utilities renderable scenes ../common/debugging ../common/gameplay ../common/graphics ../common/map ../common/network ../common/network/packet_types ../common/ui ../common/utilities +INCLUDES+=. client_utilities entities 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 @@ -26,8 +26,8 @@ OUT=$(addprefix $(OUTDIR)/,client) #targets all: $(OBJ) $(OUT) $(MAKE) -C client_utilities + $(MAKE) -C entities $(MAKE) -C scenes - $(MAKE) -C renderable $(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS) $(OBJ): | $(OBJDIR) diff --git a/client/scene_list.hpp b/client/scene_list.hpp index 82895cd..475e5bb 100644 --- a/client/scene_list.hpp +++ b/client/scene_list.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/client/scenes/base_scene.cpp b/client/scenes/base_scene.cpp index d4b7824..ba62b4c 100644 --- a/client/scenes/base_scene.cpp +++ b/client/scenes/base_scene.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/client/scenes/base_scene.hpp b/client/scenes/base_scene.hpp index d954ca0..453ab75 100644 --- a/client/scenes/base_scene.hpp +++ b/client/scenes/base_scene.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/client/scenes/disconnected_screen.cpp b/client/scenes/disconnected_screen.cpp index 7d95293..d3c0fb3 100644 --- a/client/scenes/disconnected_screen.cpp +++ b/client/scenes/disconnected_screen.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/client/scenes/disconnected_screen.hpp b/client/scenes/disconnected_screen.hpp index 453dad8..a735289 100644 --- a/client/scenes/disconnected_screen.hpp +++ b/client/scenes/disconnected_screen.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/client/scenes/in_world.cpp b/client/scenes/in_world.cpp index bea05c3..7dff310 100644 --- a/client/scenes/in_world.cpp +++ b/client/scenes/in_world.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 @@ -23,12 +23,25 @@ #include "channels.hpp" #include "utility.hpp" -#include "config_utility.hpp" +#include "terminal_error.hpp" #include #include #include #include +#include + +//------------------------- +//these should've come standard +//------------------------- + +bool operator==(IPaddress lhs, IPaddress rhs) { + return lhs.host == rhs.host && lhs.port == rhs.port; +} + +bool operator!=(IPaddress lhs, IPaddress rhs) { + return !(lhs == rhs); +} //------------------------- //Public access members @@ -38,8 +51,6 @@ InWorld::InWorld(int* const argClientIndex, int* const argAccountIndex): clientIndex(*argClientIndex), accountIndex(*argAccountIndex) { - ConfigUtility& config = ConfigUtility::GetSingleton(); - //setup the utility objects buttonImage.LoadSurface(config["dir.interface"] + "button_menu.bmp"); buttonImage.SetClipH(buttonImage.GetClipH()/3); @@ -62,27 +73,36 @@ InWorld::InWorld(int* const argClientIndex, int* const argAccountIndex): shutDownButton.SetText("Shut Down"); //load the tilesheet - //TODO: add the tilesheet to the map system? + //TODO: add the tilesheet to the map system //TODO: Tile size and tile sheet should be loaded elsewhere tileSheet.Load(config["dir.tilesets"] + "overworld.bmp", 32, 32); - //send this player's character info + //Send the character data + //TODO: login scene, prompt, etc. CharacterPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_NEW; + 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); - //request a sync - RequestSynchronize(); + //query the world state + memset(&newPacket, 0, MAX_PACKET_SIZE); + newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS; + network.SendTo(Channels::SERVER, &newPacket); + + //set the camera's values + camera.width = GetScreen()->w; + camera.height = GetScreen()->h; //debug // } InWorld::~InWorld() { - // + //unload the local data + characterMap.clear(); + monsterMap.clear(); } //------------------------- @@ -94,69 +114,57 @@ void InWorld::FrameStart() { } void InWorld::Update() { - //suck in and process all waiting packets + //create and zero the buffer SerialPacket* packetBuffer = reinterpret_cast(new char[MAX_PACKET_SIZE]); - while(network.Receive(packetBuffer)) { - HandlePacket(packetBuffer); + 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); - //update the characters + //heartbeat system + CheckHeartBeat(); + + //update all entities for (auto& it : characterMap) { it.second.Update(); } + for (auto& it : monsterMap) { + it.second.Update(); + } - //check the map + //update the map UpdateMap(); - //skip the rest + //skip the rest without a local character if (!localCharacter) { return; } - //check for collisions with the map - BoundingBox wallBounds = {0, 0, tileSheet.GetTileW(), tileSheet.GetTileH()}; - const int xCount = localCharacter->GetBounds().w / wallBounds.w + 1; - const int yCount = localCharacter->GetBounds().h / wallBounds.h + 1; + //get the collidable boxes + std::list boxList = GenerateCollisionGrid(localCharacter, tileSheet.GetTileW(), tileSheet.GetTileH()); - for (int i = -1; i <= xCount; ++i) { - for (int j = -1; j <= yCount; ++j) { - //set the wall's position - wallBounds.x = wallBounds.w * i + snapToBase((double)wallBounds.w, localCharacter->GetOrigin().x); - wallBounds.y = wallBounds.h * j + snapToBase((double)wallBounds.h, localCharacter->GetOrigin().y); - - if (!regionPager.GetSolid(wallBounds.x / wallBounds.w, wallBounds.y / wallBounds.h)) { - continue; - } - - if ((localCharacter->GetOrigin() + localCharacter->GetBounds()).CheckOverlap(wallBounds)) { - localCharacter->SetOrigin(localCharacter->GetOrigin() - (localCharacter->GetMotion())); - localCharacter->SetMotion({0,0}); - localCharacter->CorrectSprite(); - SendPlayerUpdate(); - } - } + //process the collisions + if (localCharacter->ProcessCollisionGrid(boxList)) { + localCharacter->CorrectSprite(); + SendLocalCharacterMotion(); } - //update the camera (following the player) + //update the camera camera.x = localCharacter->GetOrigin().x - camera.marginX; camera.y = localCharacter->GetOrigin().y - camera.marginY; - - //check the connection - if (Clock::now() - lastBeat > std::chrono::seconds(3)) { - if (attemptedBeats > 2) { - RequestDisconnect(); - SetNextScene(SceneList::DISCONNECTEDSCREEN); - ConfigUtility::GetSingleton()["client.disconnectMessage"] = "Error: Lost connection to the server"; - } - - ServerPacket newPacket; - newPacket.type = SerialPacketType::PING; - network.SendTo(Channels::SERVER, &newPacket); - - attemptedBeats++; - lastBeat = Clock::now(); - } } void InWorld::FrameEnd() { @@ -164,7 +172,7 @@ void InWorld::FrameEnd() { } void InWorld::RenderFrame() { -// SDL_FillRect(GetScreen(), 0, 0); + SDL_FillRect(GetScreen(), 0, 0); Render(GetScreen()); SDL_Flip(GetScreen()); fps.Calculate(); @@ -176,10 +184,13 @@ void InWorld::Render(SDL_Surface* const screen) { tileSheet.DrawRegionTo(screen, &(*it), camera.x, camera.y); } - //draw characters + //draw the entities for (auto& it : characterMap) { - //BUG: #29 drawing order according to Y origin - //TODO: use a list of renderable objects + //TODO: depth ordering + it.second.DrawTo(screen, camera.x, camera.y); + } + for (auto& it : monsterMap) { + //TODO: depth ordering it.second.DrawTo(screen, camera.x, camera.y); } @@ -194,8 +205,8 @@ void InWorld::Render(SDL_Surface* const screen) { //------------------------- void InWorld::QuitEvent() { - //exit the game AND the server - RequestDisconnect(); + //two-step logout + SendDisconnectRequest(); SetNextScene(SceneList::QUIT); } @@ -211,110 +222,167 @@ void InWorld::MouseButtonDown(SDL_MouseButtonEvent const& button) { void InWorld::MouseButtonUp(SDL_MouseButtonEvent const& button) { if (disconnectButton.MouseButtonUp(button) == Button::State::HOVER && button.button == SDL_BUTTON_LEFT) { - RequestDisconnect(); + SendLogoutRequest(); } if (shutDownButton.MouseButtonUp(button) == Button::State::HOVER && button.button == SDL_BUTTON_LEFT) { - RequestShutDown(); + SendShutdownRequest(); } } void InWorld::KeyDown(SDL_KeyboardEvent const& key) { - if (!localCharacter) { - return; - } - //hotkeys switch(key.keysym.sym) { case SDLK_ESCAPE: - RequestDisconnect(); - break; - } - - //player movement - Vector2 motion = localCharacter->GetMotion(); - switch(key.keysym.sym) { - case SDLK_LEFT: - motion.x -= CHARACTER_WALKING_SPEED; - break; - case SDLK_RIGHT: - motion.x += CHARACTER_WALKING_SPEED; - break; - case SDLK_UP: - motion.y -= CHARACTER_WALKING_SPEED; - break; - case SDLK_DOWN: - motion.y += CHARACTER_WALKING_SPEED; - break; - default: - return; - } - localCharacter->SetMotion(motion); - localCharacter->CorrectSprite(); - SendPlayerUpdate(); -} - -void InWorld::KeyUp(SDL_KeyboardEvent const& key) { - if (!localCharacter) { + //TODO: the escape key should actually control menus and stuff + SendLogoutRequest(); return; } - //player movement + //character movement + if (!localCharacter) { + return; + } Vector2 motion = localCharacter->GetMotion(); switch(key.keysym.sym) { - //NOTE: The use of min/max here are to prevent awkward movements - case SDLK_LEFT: - motion.x = std::min(motion.x + CHARACTER_WALKING_SPEED, 0.0); + case SDLK_w: + motion.y -= CHARACTER_WALKING_SPEED; break; - case SDLK_RIGHT: - motion.x = std::max(motion.x - CHARACTER_WALKING_SPEED, 0.0); + case SDLK_a: + motion.x -= CHARACTER_WALKING_SPEED; break; - case SDLK_UP: - motion.y = std::min(motion.y + CHARACTER_WALKING_SPEED, 0.0); + case SDLK_s: + motion.y += CHARACTER_WALKING_SPEED; break; - case SDLK_DOWN: - motion.y = std::max(motion.y - CHARACTER_WALKING_SPEED, 0.0); + 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(); - SendPlayerUpdate(); + SendLocalCharacterMotion(); +} + +void InWorld::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(); + SendLocalCharacterMotion(); } //------------------------- -//Network handlers +//Basic connections //------------------------- void InWorld::HandlePacket(SerialPacket* const argPacket) { switch(argPacket->type) { + //heartbeat system case SerialPacketType::PING: HandlePing(static_cast(argPacket)); break; case SerialPacketType::PONG: HandlePong(static_cast(argPacket)); break; - case SerialPacketType::DISCONNECT: - HandleDisconnect(static_cast(argPacket)); + + //game server connections + case SerialPacketType::LOGOUT_RESPONSE: + HandleLogoutResponse(static_cast(argPacket)); break; - case SerialPacketType::CHARACTER_NEW: - HandleCharacterNew(static_cast(argPacket)); + case SerialPacketType::DISCONNECT_RESPONSE: + HandleDisconnectResponse(static_cast(argPacket)); + break; + case SerialPacketType::DISCONNECT_FORCED: + HandleDisconnectForced(static_cast(argPacket)); + break; + + //map management + case SerialPacketType::REGION_CONTENT: + HandleRegionContent(static_cast(argPacket)); + break; + + //character management + case SerialPacketType::CHARACTER_CREATE: + HandleCharacterCreate(static_cast(argPacket)); break; case SerialPacketType::CHARACTER_DELETE: HandleCharacterDelete(static_cast(argPacket)); break; - case SerialPacketType::CHARACTER_UPDATE: - HandleCharacterUpdate(static_cast(argPacket)); + case SerialPacketType::QUERY_CHARACTER_EXISTS: + HandleCharacterQueryExists(static_cast(argPacket)); break; + + //character movement + case SerialPacketType::CHARACTER_SET_ROOM: + HandleCharacterSetRoom(static_cast(argPacket)); + break; + case SerialPacketType::CHARACTER_SET_ORIGIN: + HandleCharacterSetOrigin(static_cast(argPacket)); + break; + case SerialPacketType::CHARACTER_SET_MOTION: + HandleCharacterSetMotion(static_cast(argPacket)); + break; + + //rejection messages + case SerialPacketType::REGION_REJECTION: case SerialPacketType::CHARACTER_REJECTION: - HandleCharacterRejection(static_cast(argPacket)); + throw(terminal_error(static_cast(argPacket)->text)); break; - case SerialPacketType::REGION_CONTENT: - HandleRegionContent(static_cast(argPacket)); + case SerialPacketType::SHUTDOWN_REJECTION: + throw(std::runtime_error(static_cast(argPacket)->text)); break; - //handle errors - default: - throw(std::runtime_error(std::string() + "Unknown SerialPacketType encountered in InWorld: " + to_string_custom(static_cast(argPacket->type)) )); + + //errors + default: { + std::ostringstream msg; + msg << "Unknown SerialPacketType encountered in InWorld: " << static_cast(argPacket->type); + throw(std::runtime_error(msg.str())); + } break; } } @@ -326,97 +394,109 @@ void InWorld::HandlePing(ServerPacket* const argPacket) { } void InWorld::HandlePong(ServerPacket* const argPacket) { - if (network.GetIPAddress(Channels::SERVER)->host != argPacket->srcAddress.host) { + if (*network.GetIPAddress(Channels::SERVER) != argPacket->srcAddress) { throw(std::runtime_error("Heartbeat message received from an unknown source")); } - attemptedBeats = 0; lastBeat = Clock::now(); } -void InWorld::HandleDisconnect(ClientPacket* const argPacket) { - //TODO: More needed in the disconnection - SetNextScene(SceneList::DISCONNECTEDSCREEN); - ConfigUtility::GetSingleton()["client.disconnectMessage"] = "You have been disconnected"; +//------------------------- +//Connection control +//------------------------- + +void InWorld::SendLogoutRequest() { + ClientPacket newPacket; + + //send a logout request + newPacket.type = SerialPacketType::LOGOUT_REQUEST; + newPacket.accountIndex = accountIndex; + + network.SendTo(Channels::SERVER, &newPacket); } -void InWorld::HandleCharacterNew(CharacterPacket* const argPacket) { - if (characterMap.find(argPacket->characterIndex) != characterMap.end()) { - throw(std::runtime_error("Cannot create duplicate characters")); - } +void InWorld::SendDisconnectRequest() { + ClientPacket newPacket; - //create the character object - BaseCharacter& newCharacter = characterMap[argPacket->characterIndex]; + //send a disconnect request + newPacket.type = SerialPacketType::DISCONNECT_REQUEST; + newPacket.clientIndex = clientIndex; - //fill out the character's members - newCharacter.SetHandle(argPacket->handle); - newCharacter.SetAvatar(argPacket->avatar); - - newCharacter.GetSprite()->LoadSurface(ConfigUtility::GetSingleton()["dir.sprites"] + newCharacter.GetAvatar(), 4, 4); - - newCharacter.SetOrigin(argPacket->origin); - newCharacter.SetMotion(argPacket->motion); - newCharacter.SetBounds({ - CHARACTER_BOUNDS_X, - CHARACTER_BOUNDS_Y, - CHARACTER_BOUNDS_WIDTH, - CHARACTER_BOUNDS_HEIGHT - }); - -// (*newCharacter.GetBaseStats()) = argPacket->stats; - - //bookkeeping code - newCharacter.CorrectSprite(); - - //catch this client's player object - if (argPacket->accountIndex == accountIndex && !localCharacter) { - characterIndex = argPacket->characterIndex; - localCharacter = &newCharacter; - - //setup the camera - camera.width = GetScreen()->w; - camera.height = GetScreen()->h; - - //center on the player's character - camera.marginX = (GetScreen()->w / 2 - localCharacter->GetSprite()->GetImage()->GetClipW() / 2); - camera.marginY = (GetScreen()->h / 2 - localCharacter->GetSprite()->GetImage()->GetClipH() / 2); - } + network.SendTo(Channels::SERVER, &newPacket); } -void InWorld::HandleCharacterDelete(CharacterPacket* const argPacket) { - //TODO: authenticate when own character is being deleted (linked to a TODO in the server) +void InWorld::SendShutdownRequest() { + ClientPacket newPacket; - //catch this client's player object - if (argPacket->characterIndex == characterIndex) { - characterIndex = -1; + //send a shutdown request + newPacket.type = SerialPacketType::SHUTDOWN_REQUEST; + newPacket.accountIndex = accountIndex; + + network.SendTo(Channels::SERVER, &newPacket); +} + +void InWorld::HandleLogoutResponse(ClientPacket* const argPacket) { + if (localCharacter) { + characterMap.erase(characterIndex); localCharacter = nullptr; } - characterMap.erase(argPacket->characterIndex); + accountIndex = -1; + characterIndex = -1; + + //reset the camera + camera.marginX = camera.marginY = 0; + + //because, why not? I guess... + SendDisconnectRequest(); } -void InWorld::HandleCharacterUpdate(CharacterPacket* const argPacket) { - if (characterMap.find(argPacket->characterIndex) == characterMap.end()) { - HandleCharacterNew(argPacket); - return; - } - - BaseCharacter& character = characterMap[argPacket->characterIndex]; - - //other characters moving - if (argPacket->characterIndex != characterIndex) { - character.SetOrigin(argPacket->origin); - character.SetMotion(argPacket->motion); - character.CorrectSprite(); - } -} - -void InWorld::HandleCharacterRejection(TextPacket* const argPacket) { - RequestDisconnect(); +void InWorld::HandleDisconnectResponse(ClientPacket* const argPacket) { + HandleLogoutResponse(argPacket);//shortcut SetNextScene(SceneList::DISCONNECTEDSCREEN); - ConfigUtility& config = ConfigUtility::GetSingleton(); - config["client.disconnectMessage"] = "Error: "; - config["client.disconnectMessage"] += argPacket->text; + ConfigUtility::GetSingleton()["client.disconnectMessage"] = "You have successfully logged out"; +} + +void InWorld::HandleDisconnectForced(ClientPacket* const argPacket) { + HandleDisconnectResponse(argPacket);//shortcut + SetNextScene(SceneList::DISCONNECTEDSCREEN); + ConfigUtility::GetSingleton()["client.disconnectMessage"] = "You have been forcibly disconnected by the server"; +} + +void InWorld::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(); + } + } +} + +//------------------------- +//map management +//------------------------- + +void InWorld::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 InWorld::HandleRegionContent(RegionPacket* const argPacket) { @@ -429,82 +509,11 @@ void InWorld::HandleRegionContent(RegionPacket* const argPacket) { argPacket->region = nullptr; } -//------------------------- -//Server control -//------------------------- - -void InWorld::RequestSynchronize() { - ClientPacket newPacket; - - //request a sync - newPacket.type = SerialPacketType::SYNCHRONIZE; - newPacket.clientIndex = clientIndex; - newPacket.accountIndex = accountIndex; - - //TODO: location, range for sync request - - network.SendTo(Channels::SERVER, &newPacket); -} - -void InWorld::SendPlayerUpdate() { - CharacterPacket newPacket; - - //pack the packet - newPacket.type = SerialPacketType::CHARACTER_UPDATE; - - newPacket.characterIndex = characterIndex; - //NOTE: omitting the handle and avatar here - newPacket.accountIndex = accountIndex; - newPacket.roomIndex = 0; //TODO: room index - newPacket.origin = localCharacter->GetOrigin(); - newPacket.motion = localCharacter->GetMotion(); -// newPacket.stats = *localCharacter->GetBaseStats(); - - //TODO: gameplay components: equipment, items, buffs, debuffs - - network.SendTo(Channels::SERVER, &newPacket); -} - -void InWorld::RequestDisconnect() { - ClientPacket newPacket; - - //send a disconnect request - newPacket.type = SerialPacketType::DISCONNECT; - newPacket.clientIndex = clientIndex; - newPacket.accountIndex = accountIndex; - - network.SendTo(Channels::SERVER, &newPacket); -} - -void InWorld::RequestShutDown() { - ClientPacket newPacket; - - //send a shutdown request - newPacket.type = SerialPacketType::SHUTDOWN; - newPacket.clientIndex = clientIndex; - newPacket.accountIndex = accountIndex; - - network.SendTo(Channels::SERVER, &newPacket); -} - -void InWorld::RequestRegion(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); -} - -//------------------------- -//Utilities -//------------------------- - -//TODO: convert this into a more generic function?; using parameters for the bounds void InWorld::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; @@ -513,27 +522,234 @@ void InWorld::UpdateMap() { int yEnd = snapToBase(REGION_HEIGHT, (camera.y+camera.height)/tileSheet.GetTileH()) + REGION_HEIGHT; //prune distant regions - for (std::list::iterator it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); /* EMPTY */) { - //check if the region is outside of this area - if (it->GetX() < xStart || it->GetX() > xEnd || it->GetY() < yStart || it->GetY() > yEnd) { - - //clunky, but the alternative was time consuming - int tmpX = it->GetX(); - int tmpY = it->GetY(); - ++it; - - regionPager.UnloadRegion(tmpX, tmpY); - continue; - } - ++it; - } + 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) { if (!regionPager.FindRegion(i, j)) { - RequestRegion(0, i, j); + SendRegionRequest(roomIndex, i, j); } } } } + +//------------------------- +//entity management +//------------------------- + +//NOTE: preexisting characters will result in query responses +//NOTE: new characters will result in create messages +//NOTE: this client's character will exist in both (skipped) + +void InWorld::HandleCharacterCreate(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->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(); + + //check for this player's character + if (character->GetOwner() == accountIndex) { + localCharacter = static_cast(character); + + //focus the camera on this character + 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; + } + + //debug + std::cout << "Create, total: " << characterMap.size() << std::endl; +} + +void InWorld::HandleCharacterDelete(CharacterPacket* const argPacket) { + //ignore if this character doesn't exist + std::map::iterator characterIt = characterMap.find(argPacket->characterIndex); + if (characterIt == characterMap.end()) { + //debug + std::cout << "Ignoring character deletion" << std::endl; + 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; + } + + //remove this character + characterMap.erase(characterIt); + + //debug + std::cout << "Delete, total: " << characterMap.size() << std::endl; +} + +void InWorld::HandleCharacterQueryExists(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 << "Query, total: " << characterMap.size() << std::endl; +} + +void InWorld::HandleCharacterSetRoom(CharacterPacket* const argPacket) { + //someone else's character + if (argPacket->characterIndex != characterIndex) { + characterMap.erase(argPacket->characterIndex); + return; + } + + //this character is moving between rooms + roomIndex = argPacket->roomIndex; + + //set the character's info + localCharacter->SetOrigin(argPacket->origin); + localCharacter->SetMotion(argPacket->motion); + localCharacter->CorrectSprite(); + + //clear the old room's data + regionPager.UnloadAll(); + monsterMap.clear(); + + //use the jenky pattern for std::map to skip this player's character + for (std::map::iterator it = characterMap.begin(); it != characterMap.end(); /* EMPTY */ ) { + if (it->first != characterIndex) { + it = characterMap.erase(it); + } + else { + ++it; + } + } + + //request the info on characters in this room + CharacterPacket newPacket; + newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS; + newPacket.roomIndex = roomIndex; + network.SendTo(Channels::SERVER, &newPacket); +} + +void InWorld::HandleCharacterSetOrigin(CharacterPacket* const argPacket) { + //TODO: 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 InWorld::HandleCharacterSetMotion(CharacterPacket* const argPacket) { + //TODO: 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(); + } +} + +//------------------------- +//player movement +//------------------------- + +//TODO: add a "movement" packet type +void InWorld::SendLocalCharacterMotion() { + CharacterPacket newPacket; + newPacket.type = SerialPacketType::CHARACTER_SET_MOTION; + + newPacket.accountIndex = accountIndex; + newPacket.characterIndex = characterIndex; + newPacket.roomIndex = roomIndex; + newPacket.origin = localCharacter->GetOrigin(); + newPacket.motion = localCharacter->GetMotion(); + + network.SendTo(Channels::SERVER, &newPacket); +} + +std::list InWorld::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/scenes/in_world.hpp b/client/scenes/in_world.hpp index 7f2e078..7ce1288 100644 --- a/client/scenes/in_world.hpp +++ b/client/scenes/in_world.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 @@ -25,9 +25,10 @@ //maps #include "region_pager_base.hpp" -//networking +//utilities #include "udp_network_utility.hpp" #include "serial_packet.hpp" +#include "config_utility.hpp" //graphics #include "image.hpp" @@ -38,12 +39,10 @@ //common #include "frame_rate.hpp" -#include "base_character.hpp" -#include "base_monster.hpp" -#include "local_character.hpp" - //client #include "base_scene.hpp" +#include "base_monster.hpp" +#include "local_character.hpp" //STL #include @@ -72,34 +71,44 @@ protected: void KeyDown(SDL_KeyboardEvent const&); void KeyUp(SDL_KeyboardEvent const&); - //Network handlers + //Basic connections void HandlePacket(SerialPacket* const); void HandlePing(ServerPacket* const); void HandlePong(ServerPacket* const); - void HandleDisconnect(ClientPacket* const); - void HandleCharacterNew(CharacterPacket* const); - void HandleCharacterDelete(CharacterPacket* const); - void HandleCharacterUpdate(CharacterPacket* const); - void HandleCharacterRejection(TextPacket* const); + + //Connection control + void SendLogoutRequest(); + void SendDisconnectRequest(); + void SendShutdownRequest(); + + void HandleLogoutResponse(ClientPacket* const); + void HandleDisconnectResponse(ClientPacket* const); + void HandleDisconnectForced(ClientPacket* const); + + void CheckHeartBeat(); + + //map management + void SendRegionRequest(int roomIndex, int x, int y); void HandleRegionContent(RegionPacket* const); - - //Server control - void RequestSynchronize(); - void SendPlayerUpdate(); - void RequestDisconnect(); - void RequestShutDown(); - void RequestRegion(int roomIndex, int x, int y); - - //utilities void UpdateMap(); - //singleton shortcut - UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton(); + //character management + void HandleCharacterCreate(CharacterPacket* const); + void HandleCharacterDelete(CharacterPacket* const); + void HandleCharacterQueryExists(CharacterPacket* const); + void HandleCharacterSetRoom(CharacterPacket* const); + void HandleCharacterSetOrigin(CharacterPacket* const); + void HandleCharacterSetMotion(CharacterPacket* const); + + //player movement + void SendLocalCharacterMotion(); + std::list GenerateCollisionGrid(Entity*, int tileWidth, int tileHeight); //indexes int& clientIndex; int& accountIndex; int characterIndex = -1; + int roomIndex = -1; //graphics Image buttonImage; @@ -121,16 +130,20 @@ protected: int marginX = 0, marginY = 0; } camera; - //game components - BaseCharacter* localCharacter = nullptr; + //entities std::map characterMap; std::map monsterMap; + LocalCharacter* localCharacter = nullptr; //heartbeat - //TODO: This needs it's own utility, for both InWorld and InCombat + //TODO: 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(); }; #endif diff --git a/client/scenes/lobby_menu.cpp b/client/scenes/lobby_menu.cpp index c679f96..0776242 100644 --- a/client/scenes/lobby_menu.cpp +++ b/client/scenes/lobby_menu.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 @@ -190,15 +190,25 @@ void LobbyMenu::KeyUp(SDL_KeyboardEvent const& key) { 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: throw(std::runtime_error(std::string() + "Unknown SerialPacketType encountered in LobbyMenu: " + to_string_custom(static_cast(argPacket->type)) )); @@ -222,9 +232,19 @@ void LobbyMenu::HandleBroadcastResponse(ServerPacket* const argPacket) { } void LobbyMenu::HandleJoinResponse(ClientPacket* const argPacket) { + //save the server's data clientIndex = argPacket->clientIndex; - accountIndex = argPacket->accountIndex; 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; SetNextScene(SceneList::INWORLD); } @@ -232,6 +252,10 @@ void LobbyMenu::HandleJoinRejection(TextPacket* const argPacket) { //TODO: Better output for join rejection } +void LobbyMenu::HandleLoginRejection(TextPacket* const argPacket) { + //TODO: Better output for login rejection +} + //------------------------- //server control //------------------------- @@ -251,9 +275,18 @@ void LobbyMenu::SendJoinRequest() { //pack the packet ClientPacket packet; packet.type = SerialPacketType::JOIN_REQUEST; - strncpy(packet.username, config["client.username"].c_str(), PACKET_STRING_SIZE); //join the selected server network.SendTo(selection->address, &packet); selection = nullptr; } + +void LobbyMenu::SendLoginRequest() { + //NOTE: high cohesion + 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/scenes/lobby_menu.hpp b/client/scenes/lobby_menu.hpp index 1959c56..067af8c 100644 --- a/client/scenes/lobby_menu.hpp +++ b/client/scenes/lobby_menu.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 @@ -63,11 +63,14 @@ protected: 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(); diff --git a/client/scenes/main_menu.cpp b/client/scenes/main_menu.cpp index 5aa431b..2be7c93 100644 --- a/client/scenes/main_menu.cpp +++ b/client/scenes/main_menu.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/client/scenes/main_menu.hpp b/client/scenes/main_menu.hpp index 9572499..d3e7f74 100644 --- a/client/scenes/main_menu.hpp +++ b/client/scenes/main_menu.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/client/scenes/makefile b/client/scenes/makefile index 7a59128..c11a607 100644 --- a/client/scenes/makefile +++ b/client/scenes/makefile @@ -1,5 +1,5 @@ #config -INCLUDES+=. .. ../renderable ../../common/gameplay ../../common/graphics ../../common/map ../../common/network ../../common/network/packet_types ../../common/ui ../../common/utilities +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)) diff --git a/client/scenes/options_menu.cpp b/client/scenes/options_menu.cpp index 7aa2493..f06b798 100644 --- a/client/scenes/options_menu.cpp +++ b/client/scenes/options_menu.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/client/scenes/options_menu.hpp b/client/scenes/options_menu.hpp index 5bb3eed..bb15569 100644 --- a/client/scenes/options_menu.hpp +++ b/client/scenes/options_menu.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/client/scenes/splash_screen.cpp b/client/scenes/splash_screen.cpp index 5473d79..5399efd 100644 --- a/client/scenes/splash_screen.cpp +++ b/client/scenes/splash_screen.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/client/scenes/splash_screen.hpp b/client/scenes/splash_screen.hpp index c6440c1..a8bec1b 100644 --- a/client/scenes/splash_screen.hpp +++ b/client/scenes/splash_screen.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/debugging/timer.cpp b/common/debugging/timer.cpp index 29d107a..b99ee10 100644 --- a/common/debugging/timer.cpp +++ b/common/debugging/timer.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -39,7 +39,7 @@ void Timer::Stop() { std::ostream& operator<<(std::ostream& os, Timer& t) { os << t.GetName() << ": "; - os << std::chrono::duration_cast(t.GetTime()).count(); - os << "ms"; + os << std::chrono::duration_cast(t.GetTime()).count(); + os << "us"; return os; } diff --git a/common/debugging/timer.hpp b/common/debugging/timer.hpp index dfafec9..847f585 100644 --- a/common/debugging/timer.hpp +++ b/common/debugging/timer.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -34,8 +34,8 @@ public: Timer(std::string s); ~Timer() = default; - inline void Start(); - inline void Stop(); + void Start(); + void Stop(); //accessors and mutators Clock::duration GetTime() { return timeSpan; } diff --git a/common/gameplay/character_defines.hpp b/common/gameplay/character_defines.hpp index d5ca3b6..7b0d7d6 100644 --- a/common/gameplay/character_defines.hpp +++ b/common/gameplay/character_defines.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -35,4 +35,8 @@ constexpr int CHARACTER_BOUNDS_Y = 16; constexpr int CHARACTER_BOUNDS_WIDTH = 32; constexpr int CHARACTER_BOUNDS_HEIGHT = 32; +//the character's sprite format +constexpr int CHARACTER_CELLS_X = 4; +constexpr int CHARACTER_CELLS_Y = 4; + #endif diff --git a/common/graphics/image.cpp b/common/graphics/image.cpp index 3b4f99b..4089814 100644 --- a/common/graphics/image.cpp +++ b/common/graphics/image.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/graphics/image.hpp b/common/graphics/image.hpp index 462e565..709490d 100644 --- a/common/graphics/image.hpp +++ b/common/graphics/image.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/graphics/sprite_sheet.cpp b/common/graphics/sprite_sheet.cpp index 7726484..93c1984 100644 --- a/common/graphics/sprite_sheet.cpp +++ b/common/graphics/sprite_sheet.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/graphics/sprite_sheet.hpp b/common/graphics/sprite_sheet.hpp index 8ecaa5b..ea28a86 100644 --- a/common/graphics/sprite_sheet.hpp +++ b/common/graphics/sprite_sheet.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/map/map_system_api.cpp b/common/map/map_system_api.cpp new file mode 100644 index 0000000..9e908ad --- /dev/null +++ b/common/map/map_system_api.cpp @@ -0,0 +1,77 @@ +/* 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 "map_system_api.hpp" + +//all map API headers +#include "region_api.hpp" +#include "region_pager_api.hpp" +#include "tile_sheet_api.hpp" + +//macros +#include "region.hpp" + +//useful "globals" +static int getRegionWidth(lua_State* L) { + lua_pushinteger(L, REGION_WIDTH); + return 1; +} + +static int getRegionHeight(lua_State* L) { + lua_pushinteger(L, REGION_HEIGHT); + return 1; +} + +static int getRegionDepth(lua_State* L) { + lua_pushinteger(L, REGION_DEPTH); + return 1; +} + +//This mimics linit.c to create a nested collection of all map modules. +static const luaL_Reg funcs[] = { + //synonyms + {"GetRegionWidth", getRegionWidth}, + {"GetRegionHeight", getRegionHeight}, + {"GetRegionDepth", getRegionDepth}, + {nullptr, nullptr} +}; + +static const luaL_Reg libs[] = { + {"Region", openRegionAPI}, + {"RegionPager", openRegionPagerAPI}, +// {"TileSheet", openTileSheetAPI}, + {nullptr, nullptr} +}; + +int openMapSystemAPI(lua_State* L) { + //create the table + luaL_newlibtable(L, libs); + + //push the "global" functions + luaL_setfuncs(L, funcs, 0); + + //push the substable + for (const luaL_Reg* lib = libs; lib->func; lib++) { + lib->func(L); + lua_setfield(L, -2, lib->name); + } + return 1; +} \ No newline at end of file diff --git a/client/renderable/renderable.cpp b/common/map/map_system_api.hpp similarity index 76% rename from client/renderable/renderable.cpp rename to common/map/map_system_api.hpp index 46d319d..d01c276 100644 --- a/client/renderable/renderable.cpp +++ b/common/map/map_system_api.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -19,13 +19,16 @@ * 3. This notice may not be removed or altered from any source * distribution. */ -#include "renderable.hpp" +#ifndef MAPSYSTEMAPI_HPP_ +#define MAPSYSTEMAPI_APP_ -void Renderable::Update() { - origin += motion; - sprite.Update(0.016); -} +#if defined(__MINGW32__) + #include "lua/lua.hpp" +#else + #include "lua.hpp" +#endif -void Renderable::DrawTo(SDL_Surface* const dest, int camX, int camY) { - sprite.DrawTo(dest, origin.x - camX, origin.y - camY); -} \ No newline at end of file +#define TORTUGA_MAP_SYSTEM_API "map_system" +LUAMOD_API int openMapSystemAPI(lua_State* L); + +#endif \ No newline at end of file diff --git a/common/map/region.cpp b/common/map/region.cpp index ea1f402..229c350 100644 --- a/common/map/region.cpp +++ b/common/map/region.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/map/region.hpp b/common/map/region.hpp index 55e7e9f..5e2f882 100644 --- a/common/map/region.hpp +++ b/common/map/region.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/map/region_api.cpp b/common/map/region_api.cpp index 0ccb880..1749f49 100644 --- a/common/map/region_api.cpp +++ b/common/map/region_api.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/map/region_api.hpp b/common/map/region_api.hpp index babbb4f..aae8b29 100644 --- a/common/map/region_api.hpp +++ b/common/map/region_api.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -28,7 +28,7 @@ #include "lua.hpp" #endif -#define TORTUGA_REGION_NAME "Region" +#define TORTUGA_REGION_NAME "region" LUAMOD_API int openRegionAPI(lua_State* L); #endif diff --git a/common/map/region_pager_api.cpp b/common/map/region_pager_api.cpp index 73019d1..d7a38e9 100644 --- a/common/map/region_pager_api.cpp +++ b/common/map/region_pager_api.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/map/region_pager_api.hpp b/common/map/region_pager_api.hpp index b4f8c7b..2476a95 100644 --- a/common/map/region_pager_api.hpp +++ b/common/map/region_pager_api.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -28,7 +28,7 @@ #include "lua.hpp" #endif -#define TORTUGA_REGION_PAGER_NAME "RegionPager" +#define TORTUGA_REGION_PAGER_NAME "region_pager" LUAMOD_API int openRegionPagerAPI(lua_State* L); #endif diff --git a/common/map/region_pager_base.cpp b/common/map/region_pager_base.cpp index c046bdc..d20b346 100644 --- a/common/map/region_pager_base.cpp +++ b/common/map/region_pager_base.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/map/region_pager_base.hpp b/common/map/region_pager_base.hpp index 53bb097..c6d6b3d 100644 --- a/common/map/region_pager_base.hpp +++ b/common/map/region_pager_base.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/map/region_pager_lua.cpp b/common/map/region_pager_lua.cpp index d8fb538..8fb0dfc 100644 --- a/common/map/region_pager_lua.cpp +++ b/common/map/region_pager_lua.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -23,6 +23,17 @@ #include +RegionPagerLua::~RegionPagerLua() { + //unload all regions + UnloadAll(); + //clear any stored functions + luaL_unref(lua, LUA_REGISTRYINDEX, loadRef); + luaL_unref(lua, LUA_REGISTRYINDEX, saveRef); + luaL_unref(lua, LUA_REGISTRYINDEX, createRef); + luaL_unref(lua, LUA_REGISTRYINDEX, unloadRef); +} + +//return the loaded region, or nullptr on failure Region* RegionPagerLua::LoadRegion(int x, int y) { //get the pager's function from the registry lua_rawgeti(lua, LUA_REGISTRYINDEX, loadRef); @@ -54,6 +65,7 @@ Region* RegionPagerLua::LoadRegion(int x, int y) { } } +//return the saved region, or nullptr on failure Region* RegionPagerLua::SaveRegion(int x, int y) { //get the pager's function from the registry lua_rawgeti(lua, LUA_REGISTRYINDEX, saveRef); @@ -88,6 +100,7 @@ Region* RegionPagerLua::SaveRegion(int x, int y) { } } +//return the created region, or nullptr on failure Region* RegionPagerLua::CreateRegion(int x, int y) { if (FindRegion(x, y)) { throw(std::logic_error("Cannot overwrite an existing region")); @@ -116,6 +129,7 @@ Region* RegionPagerLua::CreateRegion(int x, int y) { return ®ionList.front(); } +//no return void RegionPagerLua::UnloadRegion(int x, int y) { //get the pager's function from the registry lua_rawgeti(lua, LUA_REGISTRYINDEX, unloadRef); diff --git a/common/map/region_pager_lua.hpp b/common/map/region_pager_lua.hpp index d23260f..203715b 100644 --- a/common/map/region_pager_lua.hpp +++ b/common/map/region_pager_lua.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -35,7 +35,7 @@ class RegionPagerLua : public RegionPagerBase { public: RegionPagerLua() = default; - ~RegionPagerLua() = default; + ~RegionPagerLua(); //region manipulation Region* LoadRegion(int x, int y) override; diff --git a/common/map/tile_sheet.cpp b/common/map/tile_sheet.cpp index 819d709..6f47337 100644 --- a/common/map/tile_sheet.cpp +++ b/common/map/tile_sheet.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/map/tile_sheet.hpp b/common/map/tile_sheet.hpp index f9bf8ea..6ad94ea 100644 --- a/common/map/tile_sheet.hpp +++ b/common/map/tile_sheet.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/map/tile_sheet_api.cpp b/common/map/tile_sheet_api.cpp index 5ee280f..141f200 100644 --- a/common/map/tile_sheet_api.cpp +++ b/common/map/tile_sheet_api.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/map/tile_sheet_api.hpp b/common/map/tile_sheet_api.hpp index 385a4b2..3cdd0e5 100644 --- a/common/map/tile_sheet_api.hpp +++ b/common/map/tile_sheet_api.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -28,8 +28,7 @@ #include "lua.hpp" #endif - -#define TORTUGA_TILE_SHEET_NAME "TileSheet" +#define TORTUGA_TILE_SHEET_NAME "tile_sheet" LUAMOD_API int openTileSheetAPI(lua_State* L); #endif diff --git a/common/network/packet_types/character_packet.cpp b/common/network/packet_types/character_packet.cpp index 7f6620c..98083f3 100644 --- a/common/network/packet_types/character_packet.cpp +++ b/common/network/packet_types/character_packet.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -23,8 +23,6 @@ #include "serial_utility.hpp" -#include "serial_statistics.hpp" - void serializeCharacter(void* buffer, CharacterPacket* packet) { serialCopy(&buffer, &packet->type, sizeof(SerialPacketType)); @@ -43,9 +41,6 @@ void serializeCharacter(void* buffer, CharacterPacket* packet) { serialCopy(&buffer, &packet->motion.x, sizeof(double)); serialCopy(&buffer, &packet->motion.y, sizeof(double)); - //stats structure - serializeStatistics(&buffer, &packet->stats); - //gameplay components: equipment, items, buffs, debuffs... } @@ -67,8 +62,5 @@ void deserializeCharacter(void* buffer, CharacterPacket* packet) { deserialCopy(&buffer, &packet->motion.x, sizeof(double)); deserialCopy(&buffer, &packet->motion.y, sizeof(double)); - //stats structure - deserializeStatistics(&buffer, &packet->stats); - //gameplay components: equipment, items, buffs, debuffs... } diff --git a/common/network/packet_types/character_packet.hpp b/common/network/packet_types/character_packet.hpp index 5d94c16..9b7dfde 100644 --- a/common/network/packet_types/character_packet.hpp +++ b/common/network/packet_types/character_packet.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 @@ -25,7 +25,6 @@ #include "serial_packet_base.hpp" #include "vector2.hpp" -#include "statistics.hpp" struct CharacterPacket : SerialPacketBase { //identify the character @@ -35,15 +34,13 @@ struct CharacterPacket : SerialPacketBase { //the owner int accountIndex; + //TODO: Authentication token? //location int roomIndex; Vector2 origin; Vector2 motion; - //gameplay - Statistics stats; - //gameplay components: equipment, items, buffs, debuffs... }; diff --git a/common/network/packet_types/client_packet.cpp b/common/network/packet_types/client_packet.cpp index 77da2e0..a0c6617 100644 --- a/common/network/packet_types/client_packet.cpp +++ b/common/network/packet_types/client_packet.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/network/packet_types/client_packet.hpp b/common/network/packet_types/client_packet.hpp index bd19c02..32efb06 100644 --- a/common/network/packet_types/client_packet.hpp +++ b/common/network/packet_types/client_packet.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/network/packet_types/region_packet.cpp b/common/network/packet_types/region_packet.cpp index b6b983a..4ac1471 100644 --- a/common/network/packet_types/region_packet.cpp +++ b/common/network/packet_types/region_packet.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/network/packet_types/region_packet.hpp b/common/network/packet_types/region_packet.hpp index 0c4d717..3020262 100644 --- a/common/network/packet_types/region_packet.hpp +++ b/common/network/packet_types/region_packet.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/network/packet_types/serial_packet_base.cpp b/common/network/packet_types/serial_packet_base.cpp index c8803b0..d90b868 100644 --- a/common/network/packet_types/serial_packet_base.cpp +++ b/common/network/packet_types/serial_packet_base.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/network/packet_types/serial_packet_base.hpp b/common/network/packet_types/serial_packet_base.hpp index 364e645..711fce2 100644 --- a/common/network/packet_types/serial_packet_base.hpp +++ b/common/network/packet_types/serial_packet_base.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/network/packet_types/serial_statistics.cpp b/common/network/packet_types/serial_statistics.cpp deleted file mode 100644 index fae799e..0000000 --- a/common/network/packet_types/serial_statistics.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2014 - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. -*/ -#include "serial_statistics.hpp" - -#include "serial_utility.hpp" - -void serializeStatistics(void** buffer, Statistics* stats) { - //integers - serialCopy(buffer, &stats->level, sizeof(int)); - serialCopy(buffer, &stats->exp, sizeof(int)); - serialCopy(buffer, &stats->maxHP, sizeof(int)); - serialCopy(buffer, &stats->health, sizeof(int)); - serialCopy(buffer, &stats->maxMP, sizeof(int)); - serialCopy(buffer, &stats->mana, sizeof(int)); - serialCopy(buffer, &stats->attack, sizeof(int)); - serialCopy(buffer, &stats->defence, sizeof(int)); - serialCopy(buffer, &stats->intelligence, sizeof(int)); - serialCopy(buffer, &stats->resistance, sizeof(int)); - serialCopy(buffer, &stats->speed, sizeof(int)); - - //floats - serialCopy(buffer, &stats->accuracy, sizeof(float)); - serialCopy(buffer, &stats->evasion, sizeof(float)); - serialCopy(buffer, &stats->luck, sizeof(float)); -} - -void deserializeStatistics(void** buffer, Statistics* stats) { - //integers - deserialCopy(buffer, &stats->level, sizeof(int)); - deserialCopy(buffer, &stats->exp, sizeof(int)); - deserialCopy(buffer, &stats->maxHP, sizeof(int)); - deserialCopy(buffer, &stats->health, sizeof(int)); - deserialCopy(buffer, &stats->maxMP, sizeof(int)); - deserialCopy(buffer, &stats->mana, sizeof(int)); - deserialCopy(buffer, &stats->attack, sizeof(int)); - deserialCopy(buffer, &stats->defence, sizeof(int)); - deserialCopy(buffer, &stats->intelligence, sizeof(int)); - deserialCopy(buffer, &stats->resistance, sizeof(int)); - deserialCopy(buffer, &stats->speed, sizeof(int)); - - //floats - deserialCopy(buffer, &stats->accuracy, sizeof(float)); - deserialCopy(buffer, &stats->evasion, sizeof(float)); - deserialCopy(buffer, &stats->luck, sizeof(float)); -} diff --git a/common/network/packet_types/server_packet.cpp b/common/network/packet_types/server_packet.cpp index 85ec493..562d353 100644 --- a/common/network/packet_types/server_packet.cpp +++ b/common/network/packet_types/server_packet.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/network/packet_types/server_packet.hpp b/common/network/packet_types/server_packet.hpp index 3de5a2d..169946e 100644 --- a/common/network/packet_types/server_packet.hpp +++ b/common/network/packet_types/server_packet.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/network/packet_types/text_packet.cpp b/common/network/packet_types/text_packet.cpp index fbe0d9f..56a9836 100644 --- a/common/network/packet_types/text_packet.cpp +++ b/common/network/packet_types/text_packet.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/network/packet_types/text_packet.hpp b/common/network/packet_types/text_packet.hpp index 8dfbe22..0e793b6 100644 --- a/common/network/packet_types/text_packet.hpp +++ b/common/network/packet_types/text_packet.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/network/serial_packet.hpp b/common/network/serial_packet.hpp index 7dd6c81..5d609f3 100644 --- a/common/network/serial_packet.hpp +++ b/common/network/serial_packet.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 @@ -33,7 +33,7 @@ typedef SerialPacketBase SerialPacket; //DOCS: NETWORK_VERSION is used to discern compatible servers and clients -constexpr int NETWORK_VERSION = 20140909; +constexpr int NETWORK_VERSION = 20141227; union MaxPacket { CharacterPacket a; diff --git a/common/network/serial_packet_type.hpp b/common/network/serial_packet_type.hpp index 1c517a8..c4e9842 100644 --- a/common/network/serial_packet_type.hpp +++ b/common/network/serial_packet_type.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 @@ -27,6 +27,7 @@ * valid data, but it will still be carried in that packet's format. */ +//TODO: This needs to be smoothed out enum class SerialPacketType { //default: there is something wrong NONE = 0, @@ -37,30 +38,37 @@ enum class SerialPacketType { //------------------------- //heartbeat - PING, - PONG, + PING = 1, + PONG = 2, //Used for finding available servers - BROADCAST_REQUEST, - BROADCAST_RESPONSE, + BROADCAST_REQUEST = 3, + BROADCAST_RESPONSE = 4, //------------------------- //ClientPacket - // client index, account index, character index + // client index, account index, username //------------------------- //Connecting to a server as a client - JOIN_REQUEST, - JOIN_RESPONSE, - - //client requests all information from the server - SYNCHRONIZE, + JOIN_REQUEST = 5, + JOIN_RESPONSE = 6, //disconnect from the server - DISCONNECT, + DISCONNECT_REQUEST = 7, + DISCONNECT_RESPONSE = 8, + DISCONNECT_FORCED = 9, + + //load the account + LOGIN_REQUEST = 10, + LOGIN_RESPONSE = 11, + + //unload the account + LOGOUT_REQUEST = 12, + LOGOUT_RESPONSE = 13, //shut down the server - SHUTDOWN, + SHUTDOWN_REQUEST = 14, //------------------------- //RegionPacket @@ -68,24 +76,35 @@ enum class SerialPacketType { //------------------------- //map data - REGION_REQUEST, - REGION_CONTENT, + REGION_REQUEST = 15, //NOTE: technically a query + REGION_CONTENT = 16, //------------------------- //CharacterPacket - // handle, avatar, character index, account index, - // room index, origin, motion + // character index, + // handle, avatar, + // account index (owner), + // room index, origin, motion, // statistics //------------------------- - //controlling characters - CHARACTER_NEW, - CHARACTER_DELETE, - CHARACTER_UPDATE, + //character management + CHARACTER_CREATE = 17, + CHARACTER_DELETE = 18, + CHARACTER_LOAD = 19, + CHARACTER_UNLOAD = 20, - //authentication, character index => character stats - CHARACTER_STATS_REQUEST, - CHARACTER_STATS_RESPONSE, + //find out info from the server + QUERY_CHARACTER_EXISTS = 21, + QUERY_CHARACTER_STATS = 22, + QUERY_CHARACTER_LOCATION = 23, + + //set the info in the server + CHARACTER_SET_ROOM = 24, + CHARACTER_SET_ORIGIN = 25, + CHARACTER_SET_MOTION = 26, + + //TODO: enemy management //------------------------- //TextPacket @@ -93,18 +112,20 @@ enum class SerialPacketType { //------------------------- //general speech - TEXT_BROADCAST, + TEXT_BROADCAST = 27, //rejection/error messages - SHUTDOWN_REJECTION, - JOIN_REJECTION, - CHARACTER_REJECTION, + JOIN_REJECTION = 28, + LOGIN_REJECTION = 29, + REGION_REJECTION = 30, + CHARACTER_REJECTION = 31, + SHUTDOWN_REJECTION = 32, //------------------------- //not used //------------------------- - LAST + LAST = 33 }; #endif \ No newline at end of file diff --git a/common/network/serial_utility.cpp b/common/network/serial_utility.cpp index 6572887..a0d2c61 100644 --- a/common/network/serial_utility.cpp +++ b/common/network/serial_utility.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -54,26 +54,38 @@ void serializePacket(void* buffer, SerialPacketBase* packet) { break; case SerialPacketType::JOIN_REQUEST: case SerialPacketType::JOIN_RESPONSE: - case SerialPacketType::SYNCHRONIZE: - case SerialPacketType::DISCONNECT: - case SerialPacketType::SHUTDOWN: + case SerialPacketType::DISCONNECT_REQUEST: + case SerialPacketType::DISCONNECT_RESPONSE: + case SerialPacketType::DISCONNECT_FORCED: + case SerialPacketType::LOGIN_REQUEST: + case SerialPacketType::LOGIN_RESPONSE: + case SerialPacketType::LOGOUT_REQUEST: + case SerialPacketType::LOGOUT_RESPONSE: + case SerialPacketType::SHUTDOWN_REQUEST: serializeClient(buffer, static_cast(packet)); break; case SerialPacketType::REGION_REQUEST: case SerialPacketType::REGION_CONTENT: serializeRegion(buffer, static_cast(packet)); break; - case SerialPacketType::CHARACTER_NEW: + case SerialPacketType::CHARACTER_CREATE: case SerialPacketType::CHARACTER_DELETE: - case SerialPacketType::CHARACTER_UPDATE: - case SerialPacketType::CHARACTER_STATS_REQUEST: - case SerialPacketType::CHARACTER_STATS_RESPONSE: + case SerialPacketType::CHARACTER_LOAD: + case SerialPacketType::CHARACTER_UNLOAD: + case SerialPacketType::QUERY_CHARACTER_EXISTS: + case SerialPacketType::QUERY_CHARACTER_STATS: + case SerialPacketType::QUERY_CHARACTER_LOCATION: + case SerialPacketType::CHARACTER_SET_ROOM: + case SerialPacketType::CHARACTER_SET_ORIGIN: + case SerialPacketType::CHARACTER_SET_MOTION: serializeCharacter(buffer, static_cast(packet)); break; case SerialPacketType::TEXT_BROADCAST: case SerialPacketType::JOIN_REJECTION: - case SerialPacketType::SHUTDOWN_REJECTION: + case SerialPacketType::LOGIN_REJECTION: + case SerialPacketType::REGION_REJECTION: case SerialPacketType::CHARACTER_REJECTION: + case SerialPacketType::SHUTDOWN_REJECTION: serializeText(buffer, static_cast(packet)); break; } @@ -93,26 +105,38 @@ void deserializePacket(void* buffer, SerialPacketBase* packet) { break; case SerialPacketType::JOIN_REQUEST: case SerialPacketType::JOIN_RESPONSE: - case SerialPacketType::SYNCHRONIZE: - case SerialPacketType::DISCONNECT: - case SerialPacketType::SHUTDOWN: + case SerialPacketType::DISCONNECT_REQUEST: + case SerialPacketType::DISCONNECT_RESPONSE: + case SerialPacketType::DISCONNECT_FORCED: + case SerialPacketType::LOGIN_REQUEST: + case SerialPacketType::LOGIN_RESPONSE: + case SerialPacketType::LOGOUT_REQUEST: + case SerialPacketType::LOGOUT_RESPONSE: + case SerialPacketType::SHUTDOWN_REQUEST: deserializeClient(buffer, static_cast(packet)); break; case SerialPacketType::REGION_REQUEST: case SerialPacketType::REGION_CONTENT: deserializeRegion(buffer, static_cast(packet)); break; - case SerialPacketType::CHARACTER_NEW: + case SerialPacketType::CHARACTER_CREATE: case SerialPacketType::CHARACTER_DELETE: - case SerialPacketType::CHARACTER_UPDATE: - case SerialPacketType::CHARACTER_STATS_REQUEST: - case SerialPacketType::CHARACTER_STATS_RESPONSE: + case SerialPacketType::CHARACTER_LOAD: + case SerialPacketType::CHARACTER_UNLOAD: + case SerialPacketType::QUERY_CHARACTER_EXISTS: + case SerialPacketType::QUERY_CHARACTER_STATS: + case SerialPacketType::QUERY_CHARACTER_LOCATION: + case SerialPacketType::CHARACTER_SET_ROOM: + case SerialPacketType::CHARACTER_SET_ORIGIN: + case SerialPacketType::CHARACTER_SET_MOTION: deserializeCharacter(buffer, static_cast(packet)); break; case SerialPacketType::TEXT_BROADCAST: case SerialPacketType::JOIN_REJECTION: - case SerialPacketType::SHUTDOWN_REJECTION: + case SerialPacketType::LOGIN_REJECTION: + case SerialPacketType::REGION_REJECTION: case SerialPacketType::CHARACTER_REJECTION: + case SerialPacketType::SHUTDOWN_REJECTION: deserializeText(buffer, static_cast(packet)); break; } diff --git a/common/network/serial_utility.hpp b/common/network/serial_utility.hpp index 829c904..0d3e9c0 100644 --- a/common/network/serial_utility.hpp +++ b/common/network/serial_utility.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/network/udp_network_utility.cpp b/common/network/udp_network_utility.cpp index e677854..c069b27 100644 --- a/common/network/udp_network_utility.cpp +++ b/common/network/udp_network_utility.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/network/udp_network_utility.hpp b/common/network/udp_network_utility.hpp index eef3de3..a162d89 100644 --- a/common/network/udp_network_utility.hpp +++ b/common/network/udp_network_utility.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/ui/button.cpp b/common/ui/button.cpp index 59b0ae2..c794c09 100644 --- a/common/ui/button.cpp +++ b/common/ui/button.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/ui/button.hpp b/common/ui/button.hpp index 2fe2faa..b1d6ff1 100644 --- a/common/ui/button.hpp +++ b/common/ui/button.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/ui/menu_bar.cpp b/common/ui/menu_bar.cpp index 2670e32..45358cc 100644 --- a/common/ui/menu_bar.cpp +++ b/common/ui/menu_bar.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/ui/menu_bar.hpp b/common/ui/menu_bar.hpp index e4dd392..ddbb250 100644 --- a/common/ui/menu_bar.hpp +++ b/common/ui/menu_bar.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/ui/raster_font.cpp b/common/ui/raster_font.cpp index 5005f7f..8b48fd2 100644 --- a/common/ui/raster_font.cpp +++ b/common/ui/raster_font.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/ui/raster_font.hpp b/common/ui/raster_font.hpp index c3c1ddd..25fa39a 100644 --- a/common/ui/raster_font.hpp +++ b/common/ui/raster_font.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/utilities/bounding_box.hpp b/common/utilities/bounding_box.hpp index ac7daf2..baf9917 100644 --- a/common/utilities/bounding_box.hpp +++ b/common/utilities/bounding_box.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/utilities/config_utility.cpp b/common/utilities/config_utility.cpp index fedf7e0..832680e 100644 --- a/common/utilities/config_utility.cpp +++ b/common/utilities/config_utility.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 @@ -27,13 +27,13 @@ #include #include -void ConfigUtility::Load(std::string fname, int argc, char* argv[]) { +void ConfigUtility::Load(std::string fname, bool skipMissingFile, int argc, char* argv[]) { //clear the stored configuration configMap.clear(); //use the default file if (argc < 2) { - configMap = Read(fname); + configMap = Read(fname, skipMissingFile); return; } @@ -47,7 +47,9 @@ void ConfigUtility::Load(std::string fname, int argc, char* argv[]) { for (int i = 1; i < argc; ++i) { //read from a specified config file if (!strncmp(argv[i], "-config=", 8)) { - redirectedFile = Read(argv[i] + 8); + //older specified files take precedence + table_t tmp = Read(argv[i] + 8, skipMissingFile); + redirectedFile.insert(tmp.begin(), tmp.end()); redirectUsed = true; continue; } @@ -73,18 +75,21 @@ void ConfigUtility::Load(std::string fname, int argc, char* argv[]) { //finally, construct the final config table if (!redirectUsed) { - redirectedFile = Read(fname); + redirectedFile = Read(fname, skipMissingFile); } configMap.insert(cmdLineParams.begin(), cmdLineParams.end()); configMap.insert(redirectedFile.begin(), redirectedFile.end()); } -ConfigUtility::table_t ConfigUtility::Read(std::string fname) { +ConfigUtility::table_t ConfigUtility::Read(std::string fname, bool skipMissingFile) { //read in and return this file's data table_t retTable; std::ifstream is(fname); if (!is.is_open()) { + if (skipMissingFile) { + return {}; //empty table + } std::ostringstream os; os << "Failed to open a config file: " << fname; throw(std::runtime_error( os.str() )); @@ -143,7 +148,7 @@ ConfigUtility::table_t ConfigUtility::Read(std::string fname) { //load in any subordinate config files if (retTable.find("config.next") != retTable.end()) { - table_t subTable = Read(retTable["config.next"]); + table_t subTable = Read(retTable["config.next"], skipMissingFile); retTable.insert(subTable.begin(), subTable.end()); } diff --git a/common/utilities/config_utility.hpp b/common/utilities/config_utility.hpp index fd6fb99..a63ed17 100644 --- a/common/utilities/config_utility.hpp +++ b/common/utilities/config_utility.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 @@ -27,9 +27,9 @@ #include #include -class ConfigUtility : public Singleton { +class ConfigUtility: public Singleton { public: - void Load(std::string fname, int argc = 0, char* argv[] = nullptr); + void Load(std::string fname, bool skipMissingFile = false, int argc = 0, char* argv[] = nullptr); //convert to a type std::string& String(std::string); @@ -47,10 +47,7 @@ private: friend Singleton; - ConfigUtility() = default; - ~ConfigUtility() = default; - - table_t Read(std::string fname); + table_t Read(std::string fname, bool skipMissingFile); table_t configMap; }; diff --git a/common/utilities/frame_rate.hpp b/common/utilities/frame_rate.hpp index f9b0a6d..e9899ac 100644 --- a/common/utilities/frame_rate.hpp +++ b/common/utilities/frame_rate.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/utilities/singleton.hpp b/common/utilities/singleton.hpp index 1754b84..ee9fbb0 100644 --- a/common/utilities/singleton.hpp +++ b/common/utilities/singleton.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/common/utilities/utility.cpp b/common/utilities/utility.cpp index 6f9e171..64b135b 100644 --- a/common/utilities/utility.cpp +++ b/common/utilities/utility.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/utilities/utility.hpp b/common/utilities/utility.hpp index 2cec21f..53cb426 100644 --- a/common/utilities/utility.hpp +++ b/common/utilities/utility.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 diff --git a/common/utilities/vector2.hpp b/common/utilities/vector2.hpp index 57c716c..00f4a06 100644 --- a/common/utilities/vector2.hpp +++ b/common/utilities/vector2.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 @@ -92,6 +92,10 @@ public: return ret; } + //unary operators + Vector2 operator-() { return {-x, -y}; } + + //comparison operators bool operator==(Vector2 v) { return (x == v.x && y == v.y); } bool operator!=(Vector2 v) { return (x != v.x || y != v.y); } diff --git a/rsc/scripts/map_maker.lua b/rsc/scripts/map_maker.lua index 3c1ca18..ca9ebc8 100644 --- a/rsc/scripts/map_maker.lua +++ b/rsc/scripts/map_maker.lua @@ -1,3 +1,5 @@ +local mapSystem = require "map_system" + local mapMaker = {} --utility functions @@ -19,16 +21,16 @@ mapMaker.dirt = 18 + 3 * 4 --custom generation systems here function mapMaker.debugIsland(region) - for i = 1, Region.GetWidth(region) do - for j = 1, Region.GetHeight(region) do - local dist = mapMaker.dist(0, 0, i + Region.GetX(region) -1, j + Region.GetY(region) -1) + for i = 1, mapSystem.Region.GetWidth(region) do + for j = 1, mapSystem.Region.GetHeight(region) do + local dist = mapMaker.dist(0, 0, i + mapSystem.Region.GetX(region) -1, j + mapSystem.Region.GetY(region) -1) if dist < 10 then - Region.SetTile(region, i, j, 1, mapMaker.plains) + mapSystem.Region.SetTile(region, i, j, 1, mapMaker.plains) elseif dist < 12 then - Region.SetTile(region, i, j, 1, mapMaker.sand) + mapSystem.Region.SetTile(region, i, j, 1, mapMaker.sand) else - Region.SetTile(region, i, j, 1, mapMaker.water) - Region.SetSolid(region, i, j, true) + mapSystem.Region.SetTile(region, i, j, 1, mapMaker.water) + mapSystem.Region.SetSolid(region, i, j, true) end end end diff --git a/rsc/scripts/map_saver.lua b/rsc/scripts/map_saver.lua index e69de29..0d7431f 100644 --- a/rsc/scripts/map_saver.lua +++ b/rsc/scripts/map_saver.lua @@ -0,0 +1,9 @@ +local mapSaver = {} +function mapSaver.Load(region) + --empty +end +function mapSaver.Save(region) + --empty +end +--TODO: create a flexible saving & loading system +return mapSaver \ No newline at end of file diff --git a/rsc/scripts/setup_room.lua b/rsc/scripts/setup_room.lua deleted file mode 100644 index e69de29..0000000 diff --git a/rsc/scripts/setup_server.lua b/rsc/scripts/setup_server.lua index 78a9b32..7ac5afc 100644 --- a/rsc/scripts/setup_server.lua +++ b/rsc/scripts/setup_server.lua @@ -2,11 +2,31 @@ print("Lua script check") mapMaker = require "map_maker" mapSaver = require "map_saver" +roomSystem = require "room_system" ---BUG: #35 The server fails without at least one room ---TODO: Create rooms with names? -newRoom = RoomManager.CreateRoom("overworld", "overworld.bmp") -pager = Room.GetPager(newRoom) -RegionPager.SetOnCreate(pager, mapMaker.debugIsland) +local function dumpTable(t) + print(t) + for k, v in pairs(t) do + print("",k, v) + end +end + +--create the overworld, set it's generator, loader & saver +--[[ +local t = { + "overworld.bmp", --tileset name + mapSaver.load, --load function + mapSaver.save, --save function + mapMaker.debugIsland, --create function + mapSaver.save --unload function +}]] + +dumpTable(roomSystem) +dumpTable(roomSystem.RoomManager) +dumpTable(roomSystem.Room) + +--NOTE: room 0 is the first that the client asks for, therefore it must exist +local overworld, uid = roomSystem.RoomManager.CreateRoom("overworld") +roomSystem.Room.Initialize(overworld, "overworld.bmp", mapSaver.Load, mapSaver.Save, mapMaker.debugIsland, mapSaver.Save) print("Finished the lua script") diff --git a/rsc/scripts/setup_server.sql b/rsc/scripts/setup_server.sql index 80da6fe..e7e9c63 100644 --- a/rsc/scripts/setup_server.sql +++ b/rsc/scripts/setup_server.sql @@ -1,3 +1,5 @@ +--TODO: An archive table of all dead characters + CREATE TABLE IF NOT EXISTS Accounts ( uid INTEGER PRIMARY KEY AUTOINCREMENT, username varchar(100) UNIQUE, diff --git a/server/accounts/account_data.cpp b/server/accounts/account_data.cpp new file mode 100644 index 0000000..0ee36b0 --- /dev/null +++ b/server/accounts/account_data.cpp @@ -0,0 +1,54 @@ +/* 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 index d7fb022..c40f281 100644 --- a/server/accounts/account_data.hpp +++ b/server/accounts/account_data.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -30,17 +30,17 @@ public: ~AccountData() = default; //accessors and mutators - int SetClientIndex(int i) { return clientIndex = i; } - int GetClientIndex() { return clientIndex; } + int SetClientIndex(int i); + int GetClientIndex(); - std::string SetUsername(std::string s) { return username = s; } - std::string GetUsername() { return username; } + std::string SetUsername(std::string s); + std::string GetUsername(); //database stuff - bool GetBlackListed() { return blackListed; } - bool GetWhiteListed() { return whiteListed; } - bool GetModerator() { return mod; } - bool GetAdministrator() { return admin; } + bool GetBlackListed(); + bool GetWhiteListed(); + bool GetModerator(); + bool GetAdministrator(); private: friend class AccountManager; @@ -49,6 +49,7 @@ private: std::string username; //TODO: password + //bit fields? bool blackListed = false; bool whiteListed = true; bool mod = false; diff --git a/server/accounts/account_manager.cpp b/server/accounts/account_manager.cpp index fccf530..84e7d06 100644 --- a/server/accounts/account_manager.cpp +++ b/server/accounts/account_manager.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/server/accounts/account_manager.hpp b/server/accounts/account_manager.hpp index 9520839..9e6e550 100644 --- a/server/accounts/account_manager.hpp +++ b/server/accounts/account_manager.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/server/client_data.cpp b/server/characters/character_data.cpp similarity index 78% rename from server/client_data.cpp rename to server/characters/character_data.cpp index 56eddc6..c0549d6 100644 --- a/server/client_data.cpp +++ b/server/characters/character_data.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -19,14 +19,16 @@ * 3. This notice may not be removed or altered from any source * distribution. */ -#include "client_data.hpp" +#include "character_data.hpp" -int ClientData::IncrementAttempts() { - lastBeat = Clock::now(); - return attemptedBeats++; +int CharacterData::GetOwner() { + return owner; } -int ClientData::ResetAttempts() { - lastBeat = Clock::now(); - return attemptedBeats = 0; +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 index edc3d01..873bfa4 100644 --- a/server/characters/character_data.hpp +++ b/server/characters/character_data.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -24,45 +24,28 @@ //components #include "character_defines.hpp" -#include "vector2.hpp" -#include "statistics.hpp" +#include "entity.hpp" //std namespace #include #include -class CharacterData { +class CharacterData: public Entity { public: CharacterData() = default; ~CharacterData() = default; - //location and movement - int SetRoomIndex(int i) { return roomIndex = i; } - Vector2 SetOrigin(Vector2 v) { return origin = v; } - Vector2 SetMotion(Vector2 v) { return motion = v; } - - int GetRoomIndex() { return roomIndex; } - Vector2 GetOrigin() { return origin; } - Vector2 GetMotion() { return motion; } - //accessors and mutators - Statistics* GetBaseStats() { return &baseStats; } + //... //database stuff - int GetOwner() { return owner; } - std::string GetHandle() { return handle; } - std::string GetAvatar() { return avatar; } + int GetOwner(); + std::string GetHandle(); + std::string GetAvatar(); private: friend class CharacterManager; - //world position - int roomIndex = 0; - Vector2 origin = {0.0,0.0}; - Vector2 motion = {0.0,0.0}; - - Statistics baseStats; - int owner; std::string handle; std::string avatar; diff --git a/server/characters/character_manager.cpp b/server/characters/character_manager.cpp index 13d7efa..53edc9c 100644 --- a/server/characters/character_manager.cpp +++ b/server/characters/character_manager.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -110,6 +110,8 @@ int CharacterManager::Load(int owner, std::string handle, std::string avatar) { //check the owner if (owner != sqlite3_column_int(statement, 1)) { sqlite3_finalize(statement); + //unload the already loaded character + Unload(uid); return -2; } diff --git a/server/characters/character_manager.hpp b/server/characters/character_manager.hpp index d8b2b80..fadf54c 100644 --- a/server/characters/character_manager.hpp +++ b/server/characters/character_manager.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/server/characters/makefile b/server/characters/makefile index 7133d20..7e666d5 100644 --- a/server/characters/makefile +++ b/server/characters/makefile @@ -1,5 +1,5 @@ #config -INCLUDES+=. ../server_utilities ../../common/gameplay ../../common/utilities +INCLUDES+=. ../entities ../server_utilities ../../common/gameplay ../../common/utilities LIBS+= CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) diff --git a/server/clients/client_data.cpp b/server/clients/client_data.cpp new file mode 100644 index 0000000..1a549a4 --- /dev/null +++ b/server/clients/client_data.cpp @@ -0,0 +1,52 @@ +/* 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/client_data.hpp b/server/clients/client_data.hpp similarity index 80% rename from server/client_data.hpp rename to server/clients/client_data.hpp index 0af85ed..18b93ef 100644 --- a/server/client_data.hpp +++ b/server/clients/client_data.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -26,21 +26,20 @@ #include -//TODO: ClientManager? class ClientData { public: typedef std::chrono::steady_clock Clock; ClientData() = default; - ClientData(IPaddress add): address(add) {} + ClientData(IPaddress add); ~ClientData() = default; - IPaddress SetAddress(IPaddress add) { return address = add; } - IPaddress GetAddress() { return address; } + IPaddress SetAddress(IPaddress add); + IPaddress GetAddress(); - Clock::time_point GetLastBeat() { return lastBeat; } + Clock::time_point GetLastBeat(); - int GetAttempts() { return attemptedBeats; } + int GetAttempts(); int IncrementAttempts(); int ResetAttempts(); diff --git a/server/clients/client_manager.cpp b/server/clients/client_manager.cpp new file mode 100644 index 0000000..87604f6 --- /dev/null +++ b/server/clients/client_manager.cpp @@ -0,0 +1,109 @@ +/* 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 "udp_network_utility.hpp" + +#include + +int ClientManager::CheckConnections() { + 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) { + int ret = it.first; +// elementMap.erase(it.first); + return ret; + } + } + + return -1; +} + +void ClientManager::HandlePong(ServerPacket* const argPacket) { + //find and update the specified client + for (auto& it : elementMap) { + if (it.second.GetAddress().host == argPacket->srcAddress.host && + it.second.GetAddress().port == argPacket->srcAddress.port + ) { + 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); + //TODO: ? disconnect, unload characters, notify other clients + } + 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 new file mode 100644 index 0000000..4e0b0d1 --- /dev/null +++ b/server/clients/client_manager.hpp @@ -0,0 +1,70 @@ +/* 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. +*/ +#ifndef CLIENTMANAGER_HPP_ +#define CLIENTMANAGER_HPP_ + +#include "client_data.hpp" +#include "manager_interface.hpp" +#include "server_packet.hpp" +#include "singleton.hpp" + +#include "SDL/SDL_net.h" + +#include + +class ClientManager: + public Singleton, + public ManagerInterface +{ +public: + //methods + int CheckConnections(); + void HandlePong(ServerPacket* const argPacket); + + //common public methods + int Create(IPaddress) override; + void Unload(int uid) override; + + void UnloadAll() override; + void UnloadIf(std::function)> fn) override; + + //accessors & mutators + ClientData* Get(int uid) override; + int GetLoadedCount() override; + int GetTotalCount() override; + std::map* GetContainer() override; + +private: + friend Singleton; + + ClientManager() = default; + ~ClientManager() = default; + + //EMPTY + int Load(IPaddress) override { return -1; } + int Save(int uid) override { return -1; } + void Delete(int uid) override { return; } + + int counter = 0; +}; + +#endif \ No newline at end of file diff --git a/server/clients/makefile b/server/clients/makefile new file mode 100644 index 0000000..4eb98bd --- /dev/null +++ b/server/clients/makefile @@ -0,0 +1,37 @@ +#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 $@ $< + +clean: + $(RM) *.o *.a *.exe + +rebuild: clean all diff --git a/server/doors/door_data.cpp b/server/doors/door_data.cpp new file mode 100644 index 0000000..c03f5a2 --- /dev/null +++ b/server/doors/door_data.cpp @@ -0,0 +1,38 @@ +/* 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 "door_data.hpp" + +std::string DoorData::SetRoomName(std::string s) { + return roomName = s; +} + +Vector2 DoorData::SetDestPosition(Vector2 v) { + return destPosition = v; +} + +std::string DoorData::GetRoomName() { + return roomName; +} + +Vector2 DoorData::GetDestPosition() { + return destPosition; +} diff --git a/client/renderable/base_character.cpp b/server/doors/door_data.hpp similarity index 65% rename from client/renderable/base_character.cpp rename to server/doors/door_data.hpp index ad31e92..fbd009d 100644 --- a/client/renderable/base_character.cpp +++ b/server/doors/door_data.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -19,29 +19,31 @@ * 3. This notice may not be removed or altered from any source * distribution. */ -#include "base_character.hpp" +#ifndef DOORDATA_HPP_ +#define DOORDATA_HPP_ -void BaseCharacter::CorrectSprite() { - //NOTE: These must correspond to the sprite sheet in use - if (motion.y > 0) { - sprite.SetYIndex(0); - } - else if (motion.y < 0) { - sprite.SetYIndex(1); - } - else if (motion.x > 0) { - sprite.SetYIndex(3); - } - else if (motion.x < 0) { - sprite.SetYIndex(2); - } +#include "entity.hpp" +#include "vector2.hpp" - //animation - if (motion != 0) { - sprite.SetDelay(0.1); - } - else { - sprite.SetDelay(0); - sprite.SetXIndex(0); - } -} +#include + +class DoorData: public Entity { +public: + DoorData() = default; + ~DoorData() = default; + + //accessors & mutators + std::string SetRoomName(std::string); + Vector2 SetDestPosition(Vector2); + + std::string GetRoomName(); + Vector2 GetDestPosition(); + +private: + friend class DoorManager; + + std::string roomName; + Vector2 destPosition; +}; + +#endif \ No newline at end of file diff --git a/server/doors/door_manager.cpp b/server/doors/door_manager.cpp new file mode 100644 index 0000000..f2c3ebe --- /dev/null +++ b/server/doors/door_manager.cpp @@ -0,0 +1,66 @@ +/* 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 "door_manager.hpp" + +int DoorManager::Create(std::string, Vector2) { + //TODO +} + +int DoorManager::Load(std::string, Vector2) { + //TODO +} + +int DoorManager::Save(int uid) { + //TODO +} + +void DoorManager::Unload(int uid) { + //TODO +} + +void DoorManager::Delete(int uid) { + //TODO +} + +void DoorManager::UnloadAll() { + //TODO +} + +void DoorManager::UnloadIf(std::function)> fn) { + //TODO +} + +DoorData* DoorManager::Get(int uid) { + //TODO +} + +int DoorManager::GetLoadedCount() { + //TODO +} + +int DoorManager::GetTotalCount() { + //TODO +} + +std::map* DoorManager::GetContainer() { + //TODO +} diff --git a/server/doors/door_manager.hpp b/server/doors/door_manager.hpp new file mode 100644 index 0000000..908da7d --- /dev/null +++ b/server/doors/door_manager.hpp @@ -0,0 +1,61 @@ +/* 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. +*/ +#ifndef DOORMANAGER_HPP_ +#define DOORMANAGER_HPP_ + +#include "door_data.hpp" +#include "manager_interface.hpp" +#include "singleton.hpp" +#include "vector2.hpp" + +#include +#include + +class DoorManager: + public Singleton, + public ManagerInterface +{ +public: + //common public methods + int Create(std::string, Vector2) override; + int Load(std::string, Vector2) override; + int Save(int uid) override; + void Unload(int uid) override; + void Delete(int uid) override; + + void UnloadAll() override; + void UnloadIf(std::function)> fn) override; + + //accessors & mutators + DoorData* Get(int uid) override; + int GetLoadedCount() override; + int GetTotalCount() override; + std::map* GetContainer() override; + +private: + friend Singleton; + + DoorManager() = default; + ~DoorManager() = default; +}; + +#endif \ No newline at end of file diff --git a/server/doors/makefile b/server/doors/makefile new file mode 100644 index 0000000..3585271 --- /dev/null +++ b/server/doors/makefile @@ -0,0 +1,37 @@ +#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 $@ $< + +clean: + $(RM) *.o *.a *.exe + +rebuild: clean all diff --git a/server/entities/entity.cpp b/server/entities/entity.cpp new file mode 100644 index 0000000..fcfa8aa --- /dev/null +++ b/server/entities/entity.cpp @@ -0,0 +1,46 @@ +/* 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" + +int Entity::SetRoomIndex(int i) { + return roomIndex = i; +} + +Vector2 Entity::SetOrigin(Vector2 v) { + return origin = v; +} + +Vector2 Entity::SetMotion(Vector2 v) { + return motion = v; +} + +int Entity::GetRoomIndex() { + return roomIndex; +} + +Vector2 Entity::GetOrigin() { + return origin; +} + +Vector2 Entity::GetMotion() { + return motion; +} \ No newline at end of file diff --git a/server/entities/entity.hpp b/server/entities/entity.hpp new file mode 100644 index 0000000..e110e80 --- /dev/null +++ b/server/entities/entity.hpp @@ -0,0 +1,48 @@ +/* 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. +*/ +#ifndef ENTITY_HPP_ +#define ENTITY_HPP_ + +#include "vector2.hpp" + +//The base class for all objects in the world +class Entity { +public: + //accessors & mutators + int SetRoomIndex(int i); + Vector2 SetOrigin(Vector2 v); + Vector2 SetMotion(Vector2 v); + + int GetRoomIndex(); + Vector2 GetOrigin(); + Vector2 GetMotion(); + +protected: + Entity() = default; + ~Entity() = default; + + int roomIndex = -1; + Vector2 origin; + Vector2 motion; +}; + +#endif \ No newline at end of file diff --git a/server/entities/makefile b/server/entities/makefile new file mode 100644 index 0000000..f24e1ba --- /dev/null +++ b/server/entities/makefile @@ -0,0 +1,37 @@ +#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 $@ $< + +clean: + $(RM) *.o *.a *.exe + +rebuild: clean all diff --git a/server/linit.cpp b/server/linit.cpp index cec8779..1030490 100644 --- a/server/linit.cpp +++ b/server/linit.cpp @@ -10,7 +10,7 @@ * Modified for use in Tortuga, renamed to linit.cpp * Modifications are released under the zlib license: * - * Copyright: (c) Kayne Ruse 2014 + * 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 @@ -40,11 +40,8 @@ #include "lua.hpp" #endif -#include "region_api.hpp" -#include "region_pager_api.hpp" -#include "tile_sheet_api.hpp" -#include "room_api.hpp" -#include "room_manager_api.hpp" +#include "map_system_api.hpp" +#include "room_system_api.hpp" //these libs are loaded by lua.c and are readily available to any Lua program static const luaL_Reg loadedlibs[] = { @@ -59,20 +56,14 @@ static const luaL_Reg loadedlibs[] = { {LUA_BITLIBNAME, luaopen_bit32}, {LUA_MATHLIBNAME, luaopen_math}, {LUA_DBLIBNAME, luaopen_debug}, - - //Tortuga's API - {TORTUGA_REGION_NAME, openRegionAPI}, - {TORTUGA_REGION_PAGER_NAME, openRegionPagerAPI}, - {TORTUGA_TILE_SHEET_NAME, openTileSheetAPI}, - {TORTUGA_ROOM_NAME, openRoomAPI}, - {TORTUGA_ROOM_MANAGER_NAME, openRoomManagerAPI}, - {NULL, NULL} }; //these libs are preloaded and must be required before used static const luaL_Reg preloadedlibs[] = { + {TORTUGA_MAP_SYSTEM_API, openMapSystemAPI}, + {TORTUGA_ROOM_SYSTEM_API, openRoomSystemAPI}, {NULL, NULL} }; diff --git a/server/main.cpp b/server/main.cpp index fdd4894..a132c96 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 @@ -24,7 +24,10 @@ //singletons #include "account_manager.hpp" #include "character_manager.hpp" +#include "client_manager.hpp" #include "config_utility.hpp" +#include "door_manager.hpp" +#include "monster_manager.hpp" #include "room_manager.hpp" #include "udp_network_utility.hpp" @@ -38,7 +41,10 @@ int main(int argc, char* argv[]) { //create the singletons AccountManager::CreateSingleton(); CharacterManager::CreateSingleton(); + ClientManager::CreateSingleton(); ConfigUtility::CreateSingleton(); + DoorManager::CreateSingleton(); + MonsterManager::CreateSingleton(); RoomManager::CreateSingleton(); UDPNetworkUtility::CreateSingleton(); @@ -55,7 +61,10 @@ int main(int argc, char* argv[]) { //delete the singletons AccountManager::DeleteSingleton(); CharacterManager::DeleteSingleton(); + ClientManager::DeleteSingleton(); ConfigUtility::DeleteSingleton(); + DoorManager::DeleteSingleton(); + MonsterManager::DeleteSingleton(); RoomManager::DeleteSingleton(); UDPNetworkUtility::DeleteSingleton(); } diff --git a/server/makefile b/server/makefile index b4a33a1..b798e8b 100644 --- a/server/makefile +++ b/server/makefile @@ -1,5 +1,5 @@ #include directories -INCLUDES+=. accounts characters rooms server_utilities ../common/debugging ../common/gameplay ../common/map ../common/network ../common/network/packet_types ../common/utilities +INCLUDES+=. accounts characters clients doors entities monsters rooms server_utilities ../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 @@ -27,6 +27,10 @@ OUT=$(addprefix $(OUTDIR)/,server) all: $(OBJ) $(OUT) $(MAKE) -C accounts $(MAKE) -C characters + $(MAKE) -C clients + $(MAKE) -C doors + $(MAKE) -C entities + $(MAKE) -C monsters $(MAKE) -C rooms $(MAKE) -C server_utilities $(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS) diff --git a/server/monsters/makefile b/server/monsters/makefile new file mode 100644 index 0000000..7e666d5 --- /dev/null +++ b/server/monsters/makefile @@ -0,0 +1,37 @@ +#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 $@ $< + +clean: + $(RM) *.o *.a *.exe + +rebuild: clean all diff --git a/server/monsters/monster_data.cpp b/server/monsters/monster_data.cpp new file mode 100644 index 0000000..7fda714 --- /dev/null +++ b/server/monsters/monster_data.cpp @@ -0,0 +1,38 @@ +/* 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" + +std::string MonsterData::SetAvatar(std::string s) { + return avatar = s; +} + +int MonsterData::SetScriptReference(int i) { + return scriptRef = i; +} + +std::string MonsterData::GetAvatar() { + return avatar; +} + +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 new file mode 100644 index 0000000..034cebb --- /dev/null +++ b/server/monsters/monster_data.hpp @@ -0,0 +1,47 @@ +/* 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. +*/ +#ifndef MONSTERDATA_HPP_ +#define MONSTERDATA_HPP_ + +#include "entity.hpp" + +#include + +class MonsterData: public Entity { +public: + MonsterData() = default; + ~MonsterData() = default; + + std::string SetAvatar(std::string); + int SetScriptReference(int); + + std::string GetAvatar(); + int GetScriptReference(); + +private: + friend class MonsterManager; + + std::string avatar; + int scriptRef; +}; + +#endif \ No newline at end of file diff --git a/server/monsters/monster_manager.cpp b/server/monsters/monster_manager.cpp new file mode 100644 index 0000000..dd88668 --- /dev/null +++ b/server/monsters/monster_manager.cpp @@ -0,0 +1,82 @@ +/* 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" + +int MonsterManager::Create(std::string) { + //TODO +} + +int MonsterManager::Load(std::string) { + //TODO +} + +int MonsterManager::Save(int uid) { + //TODO +} + +void MonsterManager::Unload(int uid) { + //TODO +} + +void MonsterManager::Delete(int uid) { + //TODO +} + +void MonsterManager::UnloadAll() { + //TODO +} + +void MonsterManager::UnloadIf(std::function)> fn) { + //TODO +} + +MonsterData* MonsterManager::Get(int uid) { + //TODO +} + +int MonsterManager::GetLoadedCount() { + //TODO +} + +int MonsterManager::GetTotalCount() { + //TODO +} + +std::map* MonsterManager::GetContainer() { + //TODO +} + +sqlite3* MonsterManager::SetDatabase(sqlite3* db) { + //TODO +} + +sqlite3* MonsterManager::GetDatabase() { + //TODO +} + +lua_State* MonsterManager::SetLuaState(lua_State* L) { + //TODO +} + +lua_State* MonsterManager::GetLuaState() { + //TODO +} diff --git a/server/monsters/monster_manager.hpp b/server/monsters/monster_manager.hpp new file mode 100644 index 0000000..de19e2c --- /dev/null +++ b/server/monsters/monster_manager.hpp @@ -0,0 +1,77 @@ +/* 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. +*/ +#ifndef MONSTERMANAGER_HPP_ +#define MONSTERMANAGER_HPP_ + +#include "manager_interface.hpp" +#include "monster_data.hpp" +#include "singleton.hpp" + +#ifdef __unix__ + #include "lua.hpp" + #include "sqlite3.h" +#else + #include "lua/lua.hpp" + #include "sqlite3/sqlite3.h" +#endif + +#include +#include + +class MonsterManager: + public Singleton, + public ManagerInterface +{ +public: + //common public methods + int Create(std::string) override; + int Load(std::string) override; + int Save(int uid) override; + void Unload(int uid) override; + void Delete(int uid) override; + + void UnloadAll() override; + void UnloadIf(std::function)> fn) override; + + //accessors & mutators + MonsterData* Get(int uid) override; + int GetLoadedCount() override; + int GetTotalCount() override; + std::map* GetContainer() override; + + //hooks + sqlite3* SetDatabase(sqlite3* db); + sqlite3* GetDatabase(); + lua_State* SetLuaState(lua_State* L); + lua_State* GetLuaState(); + +private: + friend Singleton; + + MonsterManager() = default; + ~MonsterManager() = default; + + sqlite3* database = nullptr; + lua_State* lua = nullptr; +}; + +#endif \ No newline at end of file diff --git a/server/rooms/makefile b/server/rooms/makefile index 4b00d80..514e483 100644 --- a/server/rooms/makefile +++ b/server/rooms/makefile @@ -1,5 +1,5 @@ #config -INCLUDES+=. ../server_utilities ../../common/map ../../common/utilities +INCLUDES+=. ../entities ../server_utilities ../../common/map ../../common/utilities LIBS+= CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) diff --git a/server/rooms/room_api.cpp b/server/rooms/room_api.cpp index bc8b1a1..b40d123 100644 --- a/server/rooms/room_api.cpp +++ b/server/rooms/room_api.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -23,12 +23,6 @@ #include "room_data.hpp" -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 setRoomName(lua_State* L) { RoomData* room = reinterpret_cast(lua_touserdata(L, 1)); room->SetRoomName(lua_tostring(L, 2)); @@ -53,12 +47,34 @@ static int getTilesetName(lua_State* L) { 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 initialize(lua_State* L) { + //set the members of the given room + RoomData* room = static_cast(lua_touserdata(L, 1)); + room->SetRoomName(lua_tostring(L, 2)); + + //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[] = { {"GetPager",getPager}, {"SetRoomName", setRoomName}, {"GetRoomName", getRoomName}, {"SetTileset", setTilesetName}, {"GetTileset", getTilesetName}, + {"Initialize", initialize}, {nullptr, nullptr} }; diff --git a/server/rooms/room_api.hpp b/server/rooms/room_api.hpp index 5a1a0c2..a091fd3 100644 --- a/server/rooms/room_api.hpp +++ b/server/rooms/room_api.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -28,7 +28,7 @@ #include "lua.hpp" #endif -#define TORTUGA_ROOM_NAME "Room" +#define TORTUGA_ROOM_API "room" LUAMOD_API int openRoomAPI(lua_State* L); #endif diff --git a/server/rooms/room_data.cpp b/server/rooms/room_data.cpp new file mode 100644 index 0000000..5b7ec8f --- /dev/null +++ b/server/rooms/room_data.cpp @@ -0,0 +1,46 @@ +/* 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" + +std::string RoomData::SetRoomName(std::string s) { + return roomName = s; +} + +std::string RoomData::GetRoomName() { + return roomName; +} + +std::string RoomData::SetTilesetName(std::string s) { + return tilesetName = s; +} + +std::string RoomData::GetTilesetName() { + return tilesetName; +} + +RegionPagerLua* RoomData::GetPager() { + return &pager; +} + +std::list* RoomData::GetEntityList() { + return &entityList; +} diff --git a/server/rooms/room_data.hpp b/server/rooms/room_data.hpp index 046b119..c3668fc 100644 --- a/server/rooms/room_data.hpp +++ b/server/rooms/room_data.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -22,9 +22,16 @@ #ifndef ROOMDATA_HPP_ #define ROOMDATA_HPP_ -//map system +#include "entity.hpp" #include "region_pager_lua.hpp" +#if defined(__MINGW32__) + #include "lua/lua.hpp" +#else + #include "lua.hpp" +#endif + +#include #include class RoomData { @@ -33,23 +40,24 @@ public: ~RoomData() = default; //accessors and mutators - RegionPagerLua* GetPager() { return &pager; } + std::string SetRoomName(std::string s); + std::string GetRoomName(); - std::string SetRoomName(std::string s) { return roomName = s; } - std::string GetRoomName() { return roomName; } + std::string SetTilesetName(std::string s); + std::string GetTilesetName(); - std::string SetTilesetName(std::string s) { return tilesetName = s; } - std::string GetTilesetName() { return tilesetName; } + RegionPagerLua* GetPager(); + std::list* GetEntityList(); private: friend class RoomManager; //members - RegionPagerLua pager; std::string roomName; std::string tilesetName; - //TODO: pass the room name & tileset name to the clients - //TODO: lua references i.e. create, unload, etc. + + RegionPagerLua pager; + std::list entityList; }; #endif diff --git a/server/rooms/room_manager.cpp b/server/rooms/room_manager.cpp index a697201..2d190c9 100644 --- a/server/rooms/room_manager.cpp +++ b/server/rooms/room_manager.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -29,25 +29,16 @@ //public access methods //------------------------- -int RoomManager::Create() { +int RoomManager::Create(std::string roomName) { //create the room RoomData* newRoom = &elementMap[counter]; //implicitly constructs the element + newRoom->SetRoomName(roomName); newRoom->pager.SetLuaState(lua); //finish the routine return counter++; } -int RoomManager::Load() { - //TODO: RoomManager::Load() - return -1; -} - -int RoomManager::Save(int uid) { - //TODO: RoomManager::Save(uid) - return -1; -} - void RoomManager::Unload(int uid) { //find the room std::map::iterator it = elementMap.find(uid); @@ -59,12 +50,6 @@ void RoomManager::Unload(int uid) { elementMap.erase(uid); } -void RoomManager::Delete(int uid) { - //TODO: RoomManager::Delete(int uid) - //NOTE: aliased to RoomManager::Unload(int uid) - Unload(uid); -} - void RoomManager::UnloadAll() { elementMap.clear(); } diff --git a/server/rooms/room_manager.hpp b/server/rooms/room_manager.hpp index dc75548..e5ae344 100644 --- a/server/rooms/room_manager.hpp +++ b/server/rooms/room_manager.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -34,15 +34,12 @@ class RoomManager: public Singleton, - public ManagerInterface + public ManagerInterface { public: //common public methods - int Create() override; - int Load() override; - int Save(int uid) override; + int Create(std::string) override; void Unload(int uid) override; - void Delete(int uid) override; void UnloadAll() override; void UnloadIf(std::function)> fn) override; @@ -63,6 +60,10 @@ private: RoomManager() = default; ~RoomManager() = default; + int Load(std::string) override { return -1; } + int Save(int uid) override { return -1; } + void Delete(int uid) override { } + lua_State* lua = nullptr; int counter = 0; }; diff --git a/server/rooms/room_manager_api.cpp b/server/rooms/room_manager_api.cpp index ab4d6d9..0a22f46 100644 --- a/server/rooms/room_manager_api.cpp +++ b/server/rooms/room_manager_api.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -24,16 +24,12 @@ #include "room_manager.hpp" int createRoom(lua_State* L) { + //create & get the room RoomManager& roomMgr = RoomManager::GetSingleton(); - int uid = roomMgr.Create(); + int uid = roomMgr.Create(lua_tostring(L, 1)); RoomData* room = roomMgr.Get(uid); - //setup the room - //TODO: room parameters only set via lua, fix this - room->SetRoomName(lua_tostring(L, 1)); - room->SetTilesetName(lua_tostring(L, 2)); - //return room, uid lua_pushlightuserdata(L, static_cast(room)); lua_pushinteger(L, uid); @@ -48,13 +44,30 @@ int unloadRoom(lua_State* L) { return 0; } +int getRoom(lua_State* L) { + //TODO: integer vs name for getRoom() + RoomManager& roomMgr = RoomManager::GetSingleton(); + + RoomData* room = roomMgr.Get(lua_tointeger(L, 1)); + + if (room) { + lua_pushlightuserdata(L, static_cast(room)); + } + else { + lua_pushnil(L); + } + + return 1; +} + static const luaL_Reg roomManagerLib[] = { {"CreateRoom", createRoom}, {"UnloadRoom", unloadRoom}, + {"GetRoom", getRoom}, {nullptr, nullptr} }; LUAMOD_API int openRoomManagerAPI(lua_State* L) { luaL_newlib(L, roomManagerLib); return 1; -} \ No newline at end of file +} diff --git a/server/rooms/room_manager_api.hpp b/server/rooms/room_manager_api.hpp index d8d7b75..bbee066 100644 --- a/server/rooms/room_manager_api.hpp +++ b/server/rooms/room_manager_api.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -28,7 +28,7 @@ #include "lua.hpp" #endif -#define TORTUGA_ROOM_MANAGER_NAME "RoomManager" +#define TORTUGA_ROOM_MANAGER_API "room_manager" LUAMOD_API int openRoomManagerAPI(lua_State* L); -#endif +#endif \ No newline at end of file diff --git a/server/rooms/room_system_api.cpp b/server/rooms/room_system_api.cpp new file mode 100644 index 0000000..0d6fa1a --- /dev/null +++ b/server/rooms/room_system_api.cpp @@ -0,0 +1,55 @@ +/* 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_system_api.hpp" + +//all room API headers +#include "room_api.hpp" +#include "room_manager_api.hpp" + +//useful "globals" +//... + +//This mimics linit.c to create a nested collection of all room modules. +static const luaL_Reg funcs[] = { + {nullptr, nullptr} +}; + +static const luaL_Reg libs[] = { + {"Room", openRoomAPI}, + {"RoomManager", openRoomManagerAPI}, + {nullptr, nullptr} +}; + +int openRoomSystemAPI(lua_State* L) { + //create the table + luaL_newlibtable(L, libs); + + //push the "global" functions + luaL_setfuncs(L, funcs, 0); + + //push the substable + for (const luaL_Reg* lib = libs; lib->func; lib++) { + lib->func(L); + lua_setfield(L, -2, lib->name); + } + return 1; +} diff --git a/common/gameplay/statistics.hpp b/server/rooms/room_system_api.hpp similarity index 71% rename from common/gameplay/statistics.hpp rename to server/rooms/room_system_api.hpp index 71020ae..7a8284a 100644 --- a/common/gameplay/statistics.hpp +++ b/server/rooms/room_system_api.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -19,24 +19,16 @@ * 3. This notice may not be removed or altered from any source * distribution. */ -#ifndef STATISTICS_HPP_ -#define STATISTICS_HPP_ +#ifndef ROOMSYSTEMAPI_HPP_ +#define ROOMSYSTEMAPI_HPP_ -struct Statistics { - int level = 0; - int exp = 0; - int maxHP = 0; - int health = 0; - int maxMP = 0; - int mana = 0; - int attack = 0; - int defence = 0; - int intelligence = 0; - int resistance = 0; - int speed = 0; - float accuracy = 0.0; - float evasion = 0.0; - float luck = 0.0; -}; +#if defined(__MINGW32__) + #include "lua/lua.hpp" +#else + #include "lua.hpp" +#endif + +#define TORTUGA_ROOM_SYSTEM_API "room_system" +LUAMOD_API int openRoomSystemAPI(lua_State* L); #endif \ No newline at end of file diff --git a/server/server_application.hpp b/server/server_application.hpp index ee27742..37b33bc 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 +/* 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 @@ -22,16 +22,20 @@ #ifndef SERVERAPPLICATION_HPP_ #define SERVERAPPLICATION_HPP_ -//server specific stuff, mostly managers -#include "client_data.hpp" +//managers #include "account_manager.hpp" #include "character_manager.hpp" +#include "client_manager.hpp" +#include "door_manager.hpp" +#include "monster_manager.hpp" #include "room_manager.hpp" -//common utilities -#include "udp_network_utility.hpp" -#include "serial_packet.hpp" +//utilities #include "config_utility.hpp" +#include "udp_network_utility.hpp" + +//common utilities +#include "serial_packet.hpp" #include "singleton.hpp" //APIs @@ -49,6 +53,10 @@ #include #include +//global utility functions +bool operator==(IPaddress lhs, IPaddress rhs); +bool operator!=(IPaddress lhs, IPaddress rhs); + //The main application class class ServerApplication: public Singleton { public: @@ -66,50 +74,64 @@ private: //handle incoming traffic void HandlePacket(SerialPacket* const); - //basic connections + //heartbeat sustem void HandlePing(ServerPacket* const); void HandlePong(ServerPacket* const); + + //basic connections void HandleBroadcastRequest(ServerPacket* const); void HandleJoinRequest(ClientPacket* const); - void HandleDisconnect(ClientPacket* const); - void HandleShutdown(ClientPacket* const); + void HandleLoginRequest(ClientPacket* const); - //map management + //client disconnections + void HandleLogoutRequest(ClientPacket* const); + void HandleDisconnectRequest(ClientPacket* const); + + //server commands + void HandleDisconnectForced(ClientPacket* const); + void HandleShutdownRequest(ClientPacket* const); + + //data management void HandleRegionRequest(RegionPacket* const); + void HandleCharacterExists(CharacterPacket* const); + + void SaveServerState(); + void FullClientUnload(int index); + void FullAccountUnload(int index); + void FullCharacterUnload(int index); //character management - void HandleCharacterNew(CharacterPacket* const); + void HandleCharacterCreate(CharacterPacket* const); void HandleCharacterDelete(CharacterPacket* const); - void HandleCharacterUpdate(CharacterPacket* const); + void HandleCharacterLoad(CharacterPacket* const); + void HandleCharacterUnload(CharacterPacket* const); - //mismanagement - void HandleSynchronize(ClientPacket* const); + //character movement + void HandleCharacterSetRoom(CharacterPacket* const); + void HandleCharacterSetOrigin(CharacterPacket* const); + void HandleCharacterSetMotion(CharacterPacket* const); //utility methods - void CheckClientConnections(); - //TODO: a function that only sends to characters in a certain proximity - void CleanupLostConnection(int index); void PumpPacket(SerialPacket* const); - void PumpCharacterUnload(int uid); void CopyCharacterToPacket(CharacterPacket* const packet, int characterIndex); //APIs and utilities sqlite3* database = nullptr; lua_State* luaState = nullptr; - UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton(); - ConfigUtility& config = ConfigUtility::GetSingleton(); - //simple tables - std::map clientMap; - - //managers + //ugly references; I hate this AccountManager& accountMgr = AccountManager::GetSingleton(); CharacterManager& characterMgr = CharacterManager::GetSingleton(); + ClientManager& clientMgr = ClientManager::GetSingleton(); + DoorManager& doorMgr = DoorManager::GetSingleton(); + MonsterManager& monsterMgr = MonsterManager::GetSingleton(); RoomManager& roomMgr = RoomManager::GetSingleton(); + ConfigUtility& config = ConfigUtility::GetSingleton(); + UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton(); + //misc bool running = true; - int clientIndex = 0; }; #endif diff --git a/server/server_character_methods.cpp b/server/server_character_methods.cpp new file mode 100644 index 0000000..018db97 --- /dev/null +++ b/server/server_character_methods.cpp @@ -0,0 +1,287 @@ +/* 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 + +//------------------------- +//Character Management +//------------------------- + +void ServerApplication::HandleCharacterCreate(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; + } + + //pump this character to all clients + CharacterPacket newPacket; + CopyCharacterToPacket(&newPacket, characterIndex); + newPacket.type = SerialPacketType::CHARACTER_CREATE; + PumpPacket(&newPacket); +} + +void ServerApplication::HandleCharacterDelete(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; + } + + //delete the character + characterMgr.Delete(characterIndex); + + //pump character delete + CharacterPacket newPacket; + newPacket.type = SerialPacketType::CHARACTER_DELETE; + newPacket.characterIndex = characterIndex; + PumpPacket(static_cast(&newPacket)); +} + +void ServerApplication::HandleCharacterLoad(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 == -1) { + 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; + } + + //pump this character to all clients + CharacterPacket newPacket; + CopyCharacterToPacket(&newPacket, characterIndex); + newPacket.type = SerialPacketType::CHARACTER_CREATE; + PumpPacket(&newPacket); +} + +void ServerApplication::HandleCharacterUnload(CharacterPacket* const argPacket) { + //get the entries + CharacterData* characterData = characterMgr.Get(argPacket->characterIndex); + if (!characterData) { + return; + } + + AccountData* accountData = accountMgr.Get(characterData->GetOwner()); + if (!accountData) { + return; //TODO: logic_error + } + + ClientData* clientData = clientMgr.Get(accountData->GetClientIndex()); + if (!clientData) { + return; //TODO: logic_error + } + + //check for fraud + if (clientData->GetAddress() != argPacket->srcAddress) { + std::cerr << "Falsified character unload detected targeting: uid(" << argPacket->characterIndex << ")" << std::endl; + return; + } + + //unload the character + characterMgr.Unload(argPacket->characterIndex); + + //pump character delete + CharacterPacket newPacket; + newPacket.type = SerialPacketType::CHARACTER_DELETE; + newPacket.characterIndex = argPacket->characterIndex; + PumpPacket(static_cast(&newPacket)); +} + +//------------------------- +//character movement +//------------------------- + +//TODO: ? Could replace this verbosity with a "verify" method, taking a client, account and character ptr as arguments + +void ServerApplication::HandleCharacterSetRoom(CharacterPacket* const argPacket) { + //get the specified objects + AccountData* accountData = accountMgr.Get(argPacket->accountIndex); + CharacterData* characterData = characterMgr.Get(argPacket->characterIndex); + + if (!accountData || !characterData) { + throw(std::runtime_error("Failed to set character room, missing data")); + } + + //get this account's client + ClientData* clientData = clientMgr.Get(accountData->GetClientIndex()); + + //check for fraud + if (clientData->GetAddress() != argPacket->srcAddress) { + std::cerr << "Falsified set character origin targeting uid(" << argPacket->characterIndex << ")" << std::endl; + return; + } + + //check if allowed + if (characterData->GetOwner() != argPacket->accountIndex && !accountData->GetModerator() && !accountData->GetAdministrator()) { + //TODO: send to the client? + std::cerr << "Failed to set character room due to lack of permissions targeting uid(" << argPacket->characterIndex << ")" << std::endl; + return; + } + + //set the character's room, zero it's origin, zero it's motion + //TODO: Set the origin here + characterData->SetRoomIndex(argPacket->roomIndex); + characterData->SetOrigin({0, 0}); + characterData->SetMotion({0, 0}); + + //update the clients + CharacterPacket newPacket; + CopyCharacterToPacket(&newPacket, argPacket->characterIndex); + newPacket.type = SerialPacketType::CHARACTER_SET_ROOM; + PumpPacket(&newPacket); +} + +void ServerApplication::HandleCharacterSetOrigin(CharacterPacket* const argPacket) { + //get the specified objects + AccountData* accountData = accountMgr.Get(argPacket->accountIndex); + CharacterData* characterData = characterMgr.Get(argPacket->characterIndex); + + if (!accountData || !characterData) { + throw(std::runtime_error("Failed to set character origin, missing data")); + } + + //get this account's client + ClientData* clientData = clientMgr.Get(accountData->GetClientIndex()); + + //check for fraud + if (clientData->GetAddress() != argPacket->srcAddress) { + std::cerr << "Falsified set character origin targeting uid(" << argPacket->characterIndex << ")" << std::endl; + return; + } + + //check if allowed + if (characterData->GetOwner() != argPacket->accountIndex && !accountData->GetModerator() && !accountData->GetAdministrator()) { + //TODO: send to the client? + std::cerr << "Failed to set character origin due to lack of permissions targeting uid(" << argPacket->characterIndex << ")" << std::endl; + return; + } + + //set the character's origin, zero it's motion + characterData->SetOrigin(argPacket->origin); + characterData->SetMotion({0, 0}); + + //update the clients + CharacterPacket newPacket; + CopyCharacterToPacket(&newPacket, argPacket->characterIndex); + newPacket.type = SerialPacketType::CHARACTER_SET_ORIGIN; + PumpPacket(&newPacket); +} + +void ServerApplication::HandleCharacterSetMotion(CharacterPacket* const argPacket) { + //get the specified objects + AccountData* accountData = accountMgr.Get(argPacket->accountIndex); + + if (!accountData) { + std::ostringstream msg; + msg << "Failed to set character motion, missing account: Index " << argPacket->accountIndex << "; "; + msg << "Number of accounts loaded: " << accountMgr.GetContainer()->size(); + throw(std::runtime_error(msg.str())); + } + + CharacterData* characterData = characterMgr.Get(argPacket->characterIndex); + + if (!characterData) { + std::ostringstream msg; + msg << "Failed to set character motion, missing character: Index " << argPacket->characterIndex << "; "; + msg << "Number of characters loaded: " << characterMgr.GetContainer()->size(); + throw(std::runtime_error(msg.str())); + } + + //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: send to the client? + std::cerr << "Failed to set character motion due to lack of permissions targeting uid(" << argPacket->characterIndex << ")" << std::endl; + return; + } + + //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_SET_MOTION; + PumpPacket(&newPacket); +} diff --git a/server/server_connections.cpp b/server/server_connections.cpp new file mode 100644 index 0000000..12ceda0 --- /dev/null +++ b/server/server_connections.cpp @@ -0,0 +1,176 @@ +/* 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 + +//------------------------- +//heartbeat system +//------------------------- + +void ServerApplication::HandlePing(ServerPacket* const argPacket) { + ServerPacket newPacket; + newPacket.type = SerialPacketType::PONG; + network.SendTo(argPacket->srcAddress, &newPacket); +} + +void ServerApplication::HandlePong(ServerPacket* const argPacket) { + clientMgr.HandlePong(argPacket); +} + +//------------------------- +//basic connections +//------------------------- + +void ServerApplication::HandleBroadcastRequest(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::HandleJoinRequest(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::HandleLoginRequest(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::HandleLogoutRequest(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::HandleDisconnectRequest(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; +} + +void ServerApplication::HandleDisconnectForced(ClientPacket* const argPacket) { + //TODO: HandleDisconnectForced +} \ No newline at end of file diff --git a/server/server_data.cpp b/server/server_data.cpp new file mode 100644 index 0000000..c8f3c92 --- /dev/null +++ b/server/server_data.cpp @@ -0,0 +1,86 @@ +/* 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 + +//------------------------- +//General data management +//------------------------- + +//TODO: Queries + +void ServerApplication::SaveServerState() { + //TODO: SaveServerState +} + +//------------------------- +//Map management +//------------------------- + +void ServerApplication::HandleRegionRequest(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::HandleCharacterExists(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)); + } +} diff --git a/server/server_logic.cpp b/server/server_logic.cpp index c83447b..df88632 100644 --- a/server/server_logic.cpp +++ b/server/server_logic.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -25,6 +25,7 @@ #include "sql_tools.hpp" #include "utility.hpp" +//std & STL #include #include #include @@ -35,12 +36,14 @@ //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 prerequisites - config.Load("rsc/config.cfg", argc, argv); + //load the config settings + config.Load("rsc/config.cfg", false, argc, argv); //------------------------- //Initialize the APIs @@ -75,7 +78,7 @@ void ServerApplication::Init(int argc, char* argv[]) { std::cout << "Initialized lua" << std::endl; - //append config["dir.scripts"] to the module path + //prepend config["dir.scripts"] to the module path if (config["dir.scripts"].size() > 0) { //get the original path lua_getglobal(luaState, "package"); @@ -160,16 +163,28 @@ void ServerApplication::Init(int argc, char* argv[]) { void ServerApplication::Proc() { SerialPacket* packetBuffer = reinterpret_cast(new char[MAX_PACKET_SIZE]); + memset(packetBuffer, 0, MAX_PACKET_SIZE); //zero the buffer + while(running) { //suck in the waiting packets & process them while(network.Receive(packetBuffer)) { - HandlePacket(packetBuffer); + try { + HandlePacket(packetBuffer); + } + catch(std::exception& e) { + std::cerr << "HandlePacket Error: " << e.what() << std::endl; + } + memset(packetBuffer, 0, MAX_PACKET_SIZE); //reset the buffer } //update the internals //... //Check connections - CheckClientConnections(); + int disconnected = clientMgr.CheckConnections(); + if (disconnected != -1) { + FullClientUnload(disconnected); + std::cerr << "Client dropped: " << disconnected << std::endl; + } //give the computer a break SDL_Delay(10); @@ -180,12 +195,14 @@ void ServerApplication::Proc() { void ServerApplication::Quit() { std::cout << "Shutting down" << std::endl; + //TODO: save the server state + //close the managers - clientMap.clear(); accountMgr.UnloadAll(); characterMgr.UnloadAll(); - //TODO: unload combats - //TODO: unload enemies + clientMgr.UnloadAll(); + doorMgr.UnloadAll(); + monsterMgr.UnloadAll(); roomMgr.UnloadAll(); //APIs @@ -204,59 +221,95 @@ void ServerApplication::Quit() { void ServerApplication::HandlePacket(SerialPacket* const argPacket) { switch(argPacket->type) { - //basic connections + //heartbeat system case SerialPacketType::PING: HandlePing(static_cast(argPacket)); break; case SerialPacketType::PONG: HandlePong(static_cast(argPacket)); break; + + //client connections case SerialPacketType::BROADCAST_REQUEST: HandleBroadcastRequest(static_cast(argPacket)); break; case SerialPacketType::JOIN_REQUEST: HandleJoinRequest(static_cast(argPacket)); break; - case SerialPacketType::DISCONNECT: - HandleDisconnect(static_cast(argPacket)); - break; - case SerialPacketType::SHUTDOWN: - HandleShutdown(static_cast(argPacket)); + case SerialPacketType::LOGIN_REQUEST: + HandleLoginRequest(static_cast(argPacket)); break; - //map management + //client disconnections + case SerialPacketType::LOGOUT_REQUEST: + HandleLogoutRequest(static_cast(argPacket)); + break; + case SerialPacketType::DISCONNECT_REQUEST: + HandleDisconnectRequest(static_cast(argPacket)); + break; + + //server commands +// case SerialPacketType::DISCONNECT_FORCED: +// HandleDisconnectForced(static_cast(argPacket)); +// break; + case SerialPacketType::SHUTDOWN_REQUEST: + HandleShutdownRequest(static_cast(argPacket)); + break; + + //data management & queries case SerialPacketType::REGION_REQUEST: HandleRegionRequest(static_cast(argPacket)); break; - - //combat management - //TODO: combat management + case SerialPacketType::QUERY_CHARACTER_EXISTS: + HandleCharacterExists(static_cast(argPacket)); + break; //character management - case SerialPacketType::CHARACTER_NEW: - HandleCharacterNew(static_cast(argPacket)); + case SerialPacketType::CHARACTER_CREATE: + HandleCharacterCreate(static_cast(argPacket)); break; case SerialPacketType::CHARACTER_DELETE: HandleCharacterDelete(static_cast(argPacket)); break; - case SerialPacketType::CHARACTER_UPDATE: - case SerialPacketType::CHARACTER_STATS_REQUEST: - HandleCharacterUpdate(static_cast(argPacket)); + case SerialPacketType::CHARACTER_LOAD: + HandleCharacterLoad(static_cast(argPacket)); + break; + case SerialPacketType::CHARACTER_UNLOAD: + HandleCharacterUnload(static_cast(argPacket)); + break; + + //character movement + case SerialPacketType::CHARACTER_SET_ROOM: + HandleCharacterSetRoom(static_cast(argPacket)); + break; + case SerialPacketType::CHARACTER_SET_ORIGIN: + HandleCharacterSetOrigin(static_cast(argPacket)); + break; + case SerialPacketType::CHARACTER_SET_MOTION: + HandleCharacterSetMotion(static_cast(argPacket)); + break; +/* + case SerialPacketType::QUERY_CHARACTER_STATS: +// HandleCharacterStatsRequest(static_cast(argPacket)); + break; + case SerialPacketType::QUERY_CHARACTER_LOCATION: +// HandleCharacterStatsRequest(static_cast(argPacket)); + break; + case SerialPacketType::TEXT_BROADCAST: +// HandleCharacterStatsRequest(static_cast(argPacket)); break; //enemy management //TODO: enemy management - //mismanagement - case SerialPacketType::SYNCHRONIZE: - HandleSynchronize(static_cast(argPacket)); - break; - + //TODO: text +*/ //handle errors default: { - std::string msg = "Unknown SerialPacketType encountered in the server: "; - msg += to_string_custom(static_cast(argPacket->type)); - throw(std::runtime_error(msg)); + std::ostringstream msg; + msg << "Unknown SerialPacketType encountered in the server: "; + msg << to_string_custom(static_cast(argPacket->type)); + throw(std::runtime_error(msg.str())); } break; } diff --git a/server/server_methods.cpp b/server/server_methods.cpp index 79f8d46..1a97a68 100644 --- a/server/server_methods.cpp +++ b/server/server_methods.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 @@ -23,125 +23,69 @@ #include #include +#include //------------------------- -//basic connections +//these should've come standard //------------------------- -void ServerApplication::HandlePing(ServerPacket* const argPacket) { - ServerPacket newPacket; - newPacket.type = SerialPacketType::PONG; - network.SendTo(argPacket->srcAddress, &newPacket); +bool operator==(IPaddress lhs, IPaddress rhs) { + return lhs.host == rhs.host && lhs.port == rhs.port; } -void ServerApplication::HandlePong(ServerPacket* const argPacket) { - //find and update the specified client - for (auto& it : clientMap) { - if (it.second.GetAddress().host == argPacket->srcAddress.host && - it.second.GetAddress().port == argPacket->srcAddress.port - ) { - it.second.ResetAttempts(); - break; - } +bool operator!=(IPaddress lhs, IPaddress rhs) { + return !(lhs == rhs); +} + +//------------------------- +//server commands +//------------------------- + +void ServerApplication::HandleShutdownRequest(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())); } -} -void ServerApplication::HandleBroadcastRequest(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::HandleJoinRequest(ClientPacket* const argPacket) { - //load the user account - //TODO: handle passwords - int accountIndex = accountMgr.Load(argPacket->username, clientIndex); - - //Cannot load - if (accountIndex < 0) { - TextPacket newPacket; - newPacket.type = SerialPacketType::JOIN_REJECTION; - std::string msg = std::string() + "Account already loaded: " + argPacket->username; - memset(newPacket.name, 0, PACKET_STRING_SIZE); - strncpy(newPacket.text, msg.c_str(), PACKET_STRING_SIZE); //BUG: If the name is too long this would truncate it - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); + //check for fraud + if (clientData->GetAddress() != argPacket->srcAddress) { + std::cerr << "Falsified server shutdown detected from: " << accountData->GetUsername() << std::endl; return; } - //send the client their info - ClientPacket newPacket; - newPacket.type = SerialPacketType::JOIN_RESPONSE; - newPacket.clientIndex = clientIndex; - newPacket.accountIndex = accountIndex; + //reject non-admin requests + if (accountData->GetAdministrator() != true) { + std::cerr << "Rejected server shutdown command from: " << accountData->GetUsername() << std::endl; - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); + //build the message + std::ostringstream msg; + msg << "Invalid admin status"; - //register the client - ClientData newClient; - newClient.SetAddress(argPacket->srcAddress); - clientMap[clientIndex++] = newClient; + //build the packet + TextPacket newPacket; + newPacket.type = SerialPacketType::SHUTDOWN_REJECTION; + strncpy(newPacket.text, msg.str().c_str(), PACKET_STRING_SIZE); - //finished this routine - std::cout << "New connection, " << clientMap.size() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl; -} + //send the rejection message + network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); -void ServerApplication::HandleDisconnect(ClientPacket* const argPacket) { - //TODO: authenticate who is disconnecting/kicking - /*Pseudocode: - if sender's account index -> client index -> address == sender's address then - continue - end - if sender's account index -> admin == true OR sender's account index -> mod == true then - continue - end - if neither of the above is true, then output a warning to the console, and return - */ - - //forward to the specified client - network.SendTo( - clientMap[ accountMgr.Get(argPacket->accountIndex)->GetClientIndex() ].GetAddress(), - static_cast(argPacket) - ); - - //save and unload this account's characters - characterMgr.UnloadIf([&](std::pair it) -> bool { - if (argPacket->accountIndex == it.second.GetOwner()) { - //pump the unload message to all remaining clients - PumpCharacterUnload(it.first); - return true; - } - return false; - }); - - //erase the in-memory stuff - clientMap.erase(accountMgr.Get(argPacket->accountIndex)->GetClientIndex()); - accountMgr.Unload(argPacket->accountIndex); - - //finished this routine - std::cout << "Disconnection, " << clientMap.size() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl; -} - -void ServerApplication::HandleShutdown(ClientPacket* const argPacket) { - //TODO: authenticate who is shutting the server down - /*Pseudocode: - if sender's account -> admin is not true then - print a warning - return - end - */ + return; + } //end the server running = false; //disconnect all clients - ClientPacket newPacket; - newPacket.type = SerialPacketType::DISCONNECT; + TextPacket newPacket; + newPacket.type = SerialPacketType::DISCONNECT_FORCED; + strncpy(newPacket.text, "Server shutdown", PACKET_STRING_SIZE); PumpPacket(&newPacket); //finished this routine @@ -149,222 +93,92 @@ void ServerApplication::HandleShutdown(ClientPacket* const argPacket) { } //------------------------- -//map management +//full unload methods //------------------------- -void ServerApplication::HandleRegionRequest(RegionPacket* const argPacket) { - RegionPacket newPacket; - - newPacket.type = SerialPacketType::REGION_CONTENT; - newPacket.roomIndex = argPacket->roomIndex; - newPacket.x = argPacket->x; - newPacket.y = argPacket->y; - - //BUG: possibly related to #35 - newPacket.region = roomMgr.Get(argPacket->roomIndex)->GetPager()->GetRegion(argPacket->x, argPacket->y); - - //send the content - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); -} - -//------------------------- -//Character Management -//------------------------- - -void ServerApplication::HandleCharacterNew(CharacterPacket* const argPacket) { - //NOTE: misnomer, try to load the character first - int characterIndex = characterMgr.Load(argPacket->accountIndex, argPacket->handle, argPacket->avatar); - - //cannot load or create - if (characterIndex < 0) { - //build the error message - std::string msg; - if (characterIndex == -1) { - msg += "Character already loaded: "; +void ServerApplication::FullClientUnload(int index) { + clientMgr.UnloadIf([&](std::pair client) -> bool { + //skip the wrong clients + if (client.first != index) { + return false; } - else if (characterIndex == -2) { - msg += "Character already exists: "; + + //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; + } } - msg += argPacket->handle; - //create, fill and send the packet - TextPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_REJECTION; - memset(newPacket.name, 0, PACKET_STRING_SIZE); - strncpy(newPacket.text, msg.c_str(), PACKET_STRING_SIZE); - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); - return; - } - - //send this new character to all clients - CharacterPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_NEW; - CopyCharacterToPacket(&newPacket, characterIndex); - PumpPacket(&newPacket); + //unload this client + return true; + }); } -void ServerApplication::HandleCharacterDelete(CharacterPacket* const argPacket) { - //NOTE: Disconnecting only unloads a character, this explicitly deletes it - - //Authenticate the owner is doing this - int characterIndex = characterMgr.Load(argPacket->accountIndex, argPacket->handle, argPacket->avatar); - - //if this is not your character - if (characterIndex < 0 && characterMgr.Get(characterIndex)->GetOwner() != argPacket->accountIndex) { - //send the rejection packet - TextPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_REJECTION; - memset(newPacket.name, 0, PACKET_STRING_SIZE); - strncpy(newPacket.text, "Character cannot be deleted", PACKET_STRING_SIZE); - network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); - - //unload an unneeded character - if (characterIndex != -1) { - characterMgr.Unload(characterIndex); +void ServerApplication::FullAccountUnload(int index) { + accountMgr.UnloadIf([&](std::pair account) -> bool { + //skip the wrong accounts + if (account.first != index) { + return false; } - return; - } - //delete it - characterMgr.Delete(characterIndex); + //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; + } + } - //TODO: success packet - - //Unload this character from all clients - PumpCharacterUnload(characterIndex); + //unload this account + return true; + }); } -void ServerApplication::HandleCharacterUpdate(CharacterPacket* const argPacket) { - CharacterData* character = characterMgr.Get(argPacket->characterIndex); +void ServerApplication::FullCharacterUnload(int index) { + characterMgr.UnloadIf([&](std::pair character) -> bool { + //skip the wrong characters + if (character.first != index) { + return false; + } - //make a new character if this one doesn't exist - if (!character) { - HandleCharacterNew(argPacket); - return; - } + //pump character unload + CharacterPacket newPacket; + newPacket.type = SerialPacketType::CHARACTER_DELETE; + newPacket.characterIndex = character.first; + //NOTE: more character info as needed - //accept client-side logic - character->SetRoomIndex(argPacket->roomIndex); - character->SetOrigin(argPacket->origin); - character->SetMotion(argPacket->motion); + PumpPacket(&newPacket); - *character->GetBaseStats() = argPacket->stats; - - //TODO: gameplay components: equipment, items, buffs, debuffs - - PumpPacket(argPacket); -} - -//------------------------- -//mismanagement -//------------------------- - -void ServerApplication::HandleSynchronize(ClientPacket* const argPacket) { - //TODO: compensate for large distances - //NOTE: I quite dislike this function - - //send all of the server's data to this client - ClientData& client = clientMap[argPacket->clientIndex]; - - //send all characters - CharacterPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_UPDATE; - - for (auto& it : *characterMgr.GetContainer()) { - CopyCharacterToPacket(&newPacket, it.first); - network.SendTo(client.GetAddress(), static_cast(&newPacket)); - } - - //TODO: more in HandleSynchronize() + //unload this character + return true; + }); } //------------------------- //utility methods //------------------------- -void ServerApplication::CheckClientConnections() { - for (auto& it : clientMap) { - if (std::chrono::steady_clock::now() - it.second.GetLastBeat() > std::chrono::seconds(3)) { - ServerPacket newPacket; - newPacket.type = SerialPacketType::PING; - network.SendTo(it.second.GetAddress(), &newPacket); - it.second.IncrementAttempts(); - } - - if (it.second.GetAttempts() > 2) { - CleanupLostConnection(it.first); - //all iterators are invalid, so we can't continue - break; - } - } -} - -void ServerApplication::CleanupLostConnection(int clientIndex) { - //NOTE: This assumes each player has only one account and character at a time - //TODO: handle multiple characters (bots, etc.) - - //find the account - int accountIndex = -1; - for (auto& it : *accountMgr.GetContainer()) { - if (it.second.GetClientIndex() == clientIndex) { - accountIndex = it.first; - break; - } - } - - //find the character - int characterIndex = -1; - for (auto& it : *characterMgr.GetContainer()) { - if (it.second.GetOwner() == accountIndex) { - characterIndex = it.first; - break; - } - } - - //send a disconnection message just in case - ClientPacket newPacket; - newPacket.type = SerialPacketType::DISCONNECT; - network.SendTo(clientMap[clientIndex].GetAddress(), &newPacket); - - //clean up this mess - characterMgr.Unload(characterIndex); - accountMgr.Unload(accountIndex); - clientMap.erase(clientIndex); - - PumpCharacterUnload(characterIndex); - - //output a message - std::cerr << "Connection lost: " << std::endl; - std::cerr << "\tClient: " << clientIndex << std::endl; - std::cerr << "\tAccount: " << accountIndex << std::endl; - std::cerr << "\tCharacter: " << characterIndex << std::endl; - std::cout << clientMap.size() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl; -} - -//TODO: a function that only sends to characters in a certain proximity - void ServerApplication::PumpPacket(SerialPacket* const argPacket) { - for (auto& it : clientMap) { + for (auto& it : *clientMgr.GetContainer()) { network.SendTo(it.second.GetAddress(), argPacket); } } -void ServerApplication::PumpCharacterUnload(int uid) { - //delete the client-side character(s) - //NOTE: This is a strange function - CharacterPacket newPacket; - newPacket.type = SerialPacketType::CHARACTER_DELETE; - newPacket.characterIndex = uid; - PumpPacket(static_cast(&newPacket)); -} - void ServerApplication::CopyCharacterToPacket(CharacterPacket* const packet, int characterIndex) { CharacterData* character = characterMgr.Get(characterIndex); if (!character) { throw(std::runtime_error("Failed to copy a character to a packet")); } - //TODO: keep this up to date when the character changes + //NOTE: keep this up to date when the character changes packet->characterIndex = characterIndex; strncpy(packet->handle, character->GetHandle().c_str(), PACKET_STRING_SIZE); strncpy(packet->avatar, character->GetAvatar().c_str(), PACKET_STRING_SIZE); @@ -372,5 +186,4 @@ void ServerApplication::CopyCharacterToPacket(CharacterPacket* const packet, int packet->roomIndex = character->GetRoomIndex(); packet->origin = character->GetOrigin(); packet->motion = character->GetMotion(); - packet->stats = *character->GetBaseStats(); -} \ No newline at end of file +} diff --git a/server/server_utilities/manager_interface.hpp b/server/server_utilities/manager_interface.hpp index 8a5161f..c10e6d2 100644 --- a/server/server_utilities/manager_interface.hpp +++ b/server/server_utilities/manager_interface.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/server/server_utilities/sql_tools.cpp b/server/server_utilities/sql_tools.cpp index 19e0ddb..d83acba 100644 --- a/server/server_utilities/sql_tools.cpp +++ b/server/server_utilities/sql_tools.cpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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 diff --git a/server/server_utilities/sql_tools.hpp b/server/server_utilities/sql_tools.hpp index 99d0902..6e019f8 100644 --- a/server/server_utilities/sql_tools.hpp +++ b/server/server_utilities/sql_tools.hpp @@ -1,4 +1,4 @@ -/* Copyright: (c) Kayne Ruse 2014 +/* 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