From 63be0ee70d3e9c236d06e05557bda876fe8b42d7 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sat, 7 Jun 2014 02:12:40 +1000 Subject: [PATCH] The server is building, but still needs work There is some missing character creation/unloading code, and there are a few other issues highlighted by TODO tags, see below. In general, 'mapIndex' has been renamed to 'roomIndex'. Multiple rooms have not been fully implemented yet, but I'm working on it. Other issues: * FileFormat needs to be changed to MapLoader * Server's character movement is still slaved to the clients The client does not build. --- common/gameplay/character_data.hpp | 2 +- common/map/map_file_format.hpp | 2 + common/map/region.hpp | 6 +- common/script/map_api.cpp | 2 + rsc/scripts/setup_server.sql | 2 +- server/character_manager.cpp | 6 +- server/room_data.hpp | 16 ++++-- server/room_manager.hpp | 1 + server/server_application.cpp | 91 +++++++++++++++++++----------- server/server_application.hpp | 13 ++--- 10 files changed, 85 insertions(+), 56 deletions(-) diff --git a/common/gameplay/character_data.hpp b/common/gameplay/character_data.hpp index ff129b2..361788b 100644 --- a/common/gameplay/character_data.hpp +++ b/common/gameplay/character_data.hpp @@ -45,7 +45,7 @@ struct CharacterData { std::string avatar; //world position - int mapIndex = 0; + int roomIndex = 0; Vector2 origin = {0.0,0.0}; Vector2 motion = {0.0,0.0}; Vector2 bounds = {0.0,0.0}; diff --git a/common/map/map_file_format.hpp b/common/map/map_file_format.hpp index 92f0c8d..75f5204 100644 --- a/common/map/map_file_format.hpp +++ b/common/map/map_file_format.hpp @@ -28,6 +28,8 @@ #include +//TODO: I'm unhappy with using this system, there needs to be a way to handle saving/loading better + class DummyFormat { public: void Load(Region** const, int x, int y); diff --git a/common/map/region.hpp b/common/map/region.hpp index 560161b..4c0d2cd 100644 --- a/common/map/region.hpp +++ b/common/map/region.hpp @@ -22,9 +22,9 @@ #ifndef REGION_HPP_ #define REGION_HPP_ -#define REGION_WIDTH 20 -#define REGION_HEIGHT 20 -#define REGION_DEPTH 3 +constexpr int REGION_WIDTH = 20; +constexpr int REGION_HEIGHT = 20; +constexpr int REGION_DEPTH = 3; class Region { public: diff --git a/common/script/map_api.cpp b/common/script/map_api.cpp index 9ecfea4..0bcaf80 100644 --- a/common/script/map_api.cpp +++ b/common/script/map_api.cpp @@ -27,6 +27,8 @@ #include "region_pager.hpp" //NOTE: When operating on a region, setTile() & getTile() *are not* zero indexed, but when operating on the entire map they *are* zero indexed. +//TODO: enforce all possible parameter counts +//TODO: update the map API to handle multiple rooms static int setTile(lua_State* L) { if (lua_gettop(L) == 5) { diff --git a/rsc/scripts/setup_server.sql b/rsc/scripts/setup_server.sql index 04a6aab..88d0a82 100644 --- a/rsc/scripts/setup_server.sql +++ b/rsc/scripts/setup_server.sql @@ -23,7 +23,7 @@ CREATE TABLE IF NOT EXISTS Characters ( birth timestamp NOT NULL DEFAULT (datetime()), --position - mapIndex INTEGER DEFAULT 0, + roomIndex INTEGER DEFAULT 0, originX INTEGER DEFAULT 0, originY INTEGER DEFAULT 0, diff --git a/server/character_manager.cpp b/server/character_manager.cpp index 34310c9..5767e60 100644 --- a/server/character_manager.cpp +++ b/server/character_manager.cpp @@ -33,7 +33,7 @@ static const char* CREATE_CHARACTER = "INSERT INTO Characters (owner, handle, av static const char* LOAD_CHARACTER = "SELECT * FROM Characters WHERE handle = ?;"; static const char* SAVE_CHARACTER = "UPDATE OR FAIL Characters SET " - "mapIndex = ?2," + "roomIndex = ?2," "originX = ?3," "originY = ?4," "level = ?5," @@ -148,7 +148,7 @@ int CharacterManager::LoadCharacter(int owner, std::string handle, std::string a //Don't cache the birth //world origin - newChar.mapIndex = sqlite3_column_int(statement, 5); + newChar.roomIndex = sqlite3_column_int(statement, 5); newChar.origin.x = (double)sqlite3_column_int(statement, 6); newChar.origin.y = (double)sqlite3_column_int(statement, 7); @@ -208,7 +208,7 @@ int CharacterManager::SaveCharacter(int uid) { //parameters bool ret = false; ret |= sqlite3_bind_int(statement, 1, uid) != SQLITE_OK; - ret |= sqlite3_bind_int(statement, 2, character.mapIndex) != SQLITE_OK; + ret |= sqlite3_bind_int(statement, 2, character.roomIndex) != SQLITE_OK; ret |= sqlite3_bind_int(statement, 3, (int)character.origin.x) != SQLITE_OK; ret |= sqlite3_bind_int(statement, 4, (int)character.origin.y) != SQLITE_OK; diff --git a/server/room_data.hpp b/server/room_data.hpp index 6826314..c436d54 100644 --- a/server/room_data.hpp +++ b/server/room_data.hpp @@ -22,6 +22,11 @@ #ifndef ROOMDATA_HPP_ #define ROOMDATA_HPP_ +//map system +#include "map_allocator.hpp" +#include "map_file_format.hpp" +#include "region_pager.hpp" + struct RoomData { enum class RoomType { OVERWORLD, @@ -31,11 +36,12 @@ struct RoomData { CAVES, }; - /* TODO: more - * "multiple rooms system" using this structure - * Pager - * collision map - */ + //members + RegionPager pager; + RoomType type; + + //TODO: collision map + //TODO: NPCs? }; #endif diff --git a/server/room_manager.hpp b/server/room_manager.hpp index 9b1dfc6..2caadaa 100644 --- a/server/room_manager.hpp +++ b/server/room_manager.hpp @@ -35,6 +35,7 @@ public: //public access methods //TODO + //TODO: setup the pagers and functors of each room object //accessors and mutators RoomData* GetRoom(int uid); diff --git a/server/server_application.cpp b/server/server_application.cpp index 7ef5f45..836af2b 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -174,14 +174,14 @@ void ServerApplication::HandlePacket(SerialPacket* const argPacket) { //character management case SerialPacketType::CHARACTER_NEW: - HandleCharacterNew(dynamic_cast(argPacket)); + HandleCharacterNew(dynamic_cast(argPacket)); break; case SerialPacketType::CHARACTER_DELETE: - HandleCharacterDelete(dynamic_cast(argPacket)); + HandleCharacterDelete(dynamic_cast(argPacket)); break; case SerialPacketType::CHARACTER_UPDATE: case SerialPacketType::CHARACTER_STATS_REQUEST: //TODO: ? - HandleCharacterUpdate(dynamic_cast(argPacket)); + HandleCharacterUpdate(dynamic_cast(argPacket)); break; //enemy management @@ -189,7 +189,7 @@ void ServerApplication::HandlePacket(SerialPacket* const argPacket) { //mismanagement case SerialPacketType::SYNCHRONIZE: - HandleSynchronize(dynamic_cast(argPacket)); + HandleSynchronize(dynamic_cast(argPacket)); break; //handle errors @@ -296,7 +296,7 @@ void ServerApplication::HandleRegionRequest(RegionPacket* const argPacket) { newPacket.x = argPacket->x; newPacket.y = argPacket->y; - newPacket.region = roomMgr.GetRoom(argPacket->roomIndex)->GetPager()->GetRegion(argPacket->x, argPacket->y); + newPacket.region = roomMgr.GetRoom(argPacket->roomIndex)->pager.GetRegion(argPacket->x, argPacket->y); //send the content network.SendTo(&argPacket->srcAddress, dynamic_cast(argPacket)); @@ -312,25 +312,46 @@ void ServerApplication::HandleRegionRequest(RegionPacket* const argPacket) { //Character Management //------------------------- -void ServerApplication::HandleCharacterNew(SerialPacket) { +void ServerApplication::HandleCharacterNew(CharacterPacket* const argPacket) { //TODO: fill this } -void ServerApplication::HandleCharacterDelete(SerialPacket) { +void ServerApplication::HandleCharacterDelete(CharacterPacket* const argPacket) { //TODO: fill this } -void ServerApplication::HandleCharacterUpdate(SerialPacket packet) { - //TODO: this should be moved elsewhere - if (characterMap.find(packet.characterInfo.characterIndex) == characterMap.end()) { - throw(std::runtime_error("Cannot update a non-existant character")); +void ServerApplication::HandleCharacterUpdate(CharacterPacket* const argPacket) { + CharacterData* character = characterMgr.GetCharacter(argPacket->characterIndex); + + //make a new character if this one doesn't exist + if (!character) { + //this isn't normal + std::cerr << "Warning: HandleCharacterUpdate() is passing to HandleCharacterNew()" << std::endl; + HandleCharacterNew(argPacket); + return; } - //TODO: the server needs it's own movement system too - characterMap[packet.characterInfo.characterIndex].origin = packet.characterInfo.origin; - characterMap[packet.characterInfo.characterIndex].motion = packet.characterInfo.motion; + /* TODO: rewrite this design flaw, read more + * Slaving the client to the server here is a terrible idea, instead there + * needs to be a utility function to update and send the server-side character + * to the clients. + * + * Other things to consider include functionality to reequip the character, + * apply status effects and to change the stats as well. These should all be + * handled server-side. + */ + character->roomIndex = argPacket->roomIndex; + character->origin = argPacket->origin; + character->motion = argPacket->motion; - PumpPacket(packet); + character->stats = argPacket->stats; + + //TODO: equipment + //TODO: items + //TODO: buffs + //TODO: debuffs + + PumpPacket(argPacket); } //------------------------- @@ -343,26 +364,29 @@ void ServerApplication::HandleCharacterUpdate(SerialPacket packet) { //mismanagement //------------------------- -void ServerApplication::HandleSynchronize(SerialPacket packet) { +void ServerApplication::HandleSynchronize(ClientPacket* const argPacket) { //TODO: compensate for large distances + //TODO: I quite dislike this function //send all the server's data to this client - SerialPacket newPacket; + CharacterPacket characterPacket; //characters - newPacket.meta.type = SerialPacket::Type::CHARACTER_UPDATE; - for (auto& it : characterMap) { + characterPacket.type = SerialPacketType::CHARACTER_UPDATE; + for (auto& it : *characterMgr.GetContainer()) { //TODO: update this for the expanded CharacterData structure - newPacket.characterInfo.characterIndex = it.first; - snprintf(newPacket.characterInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str()); - snprintf(newPacket.characterInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str()); - newPacket.characterInfo.mapIndex = it.second.mapIndex; - newPacket.characterInfo.origin = it.second.origin; - newPacket.characterInfo.motion = it.second.motion; - newPacket.characterInfo.stats = it.second.stats; + characterPacket.characterIndex = it.first; + snprintf(characterPacket.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str()); + snprintf(characterPacket.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str()); + characterPacket.roomIndex = it.second.roomIndex; + characterPacket.origin = it.second.origin; + characterPacket.motion = it.second.motion; + characterPacket.stats = it.second.stats; - network.SendTo(&clientMap[packet.clientInfo.clientIndex].address, &newPacket); + network.SendTo(&clientMap[argPacket->clientIndex].address, dynamic_cast(&characterPacket)); } + + //TODO: more } //------------------------- @@ -371,17 +395,16 @@ void ServerApplication::HandleSynchronize(SerialPacket packet) { //TODO: a function that only sends to characters in a certain proximity -void ServerApplication::PumpPacket(SerialPacket packet) { - //NOTE: I don't really like this, but it'll do for now +void ServerApplication::PumpPacket(SerialPacket* const argPacket) { for (auto& it : clientMap) { - network.SendTo(&it.second.address, &packet); + network.SendTo(&it.second.address, argPacket); } } void ServerApplication::PumpCharacterUnload(int uid) { //delete the client-side character(s) - SerialPacket delPacket; - delPacket.meta.type = SerialPacket::Type::CHARACTER_DELETE; - delPacket.characterInfo.characterIndex = uid; - PumpPacket(delPacket); + CharacterPacket newPacket; + newPacket.type = SerialPacketType::CHARACTER_DELETE; + newPacket.characterIndex = uid; + PumpPacket(dynamic_cast(&newPacket)); } diff --git a/server/server_application.hpp b/server/server_application.hpp index a0cb9b3..05168df 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -30,11 +30,6 @@ #include "enemy_manager.hpp" #include "room_manager.hpp" -//maps -#include "map_allocator.hpp" -#include "map_file_format.hpp" -#include "region_pager.hpp" - //common utilities #include "udp_network_utility.hpp" #include "config_utility.hpp" @@ -76,15 +71,15 @@ private: //TODO: combat management //character management - void HandleCharacterNew(SerialPacket* const); - void HandleCharacterDelete(SerialPacket* const); - void HandleCharacterUpdate(SerialPacket* const); + void HandleCharacterNew(CharacterPacket* const); + void HandleCharacterDelete(CharacterPacket* const); + void HandleCharacterUpdate(CharacterPacket* const); //enemy management //TODO: enemy management //mismanagement - void HandleSynchronize(SerialPacket* const); + void HandleSynchronize(ClientPacket* const); //utility methods //TODO: a function that only sends to characters in a certain proximity