From dabb7b3b2ef7cdff670dd9146e3ac8db4a64d3a4 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Tue, 22 Apr 2014 01:55:09 +1000 Subject: [PATCH 01/10] Compiled a list of tasks The list in todo.txt are a list of tasks that will be needed to complete the login/user accounts overhaul, and will hopefully make the server a persistent system. Once the server is persistent (via the database) I can start on the combat system. --- todo.txt | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 todo.txt diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..1b1ce42 --- /dev/null +++ b/todo.txt @@ -0,0 +1,25 @@ +Please note that due to modificatons, the indicated line may be incorrect. + +## TODO +player_character.hpp:28 correct the PlayerCharacter class and it's movement system +in_world.cpp:65 the login system needs an overhaul +in_world.cpp:405 convert this into a more generic function?; using parameters for the bounds +lobby_menu.cpp:95 I need a proper UI system for the entire client and the editor +lobby_menu.cpp:101 draw headers for the server list +lobby_menu.cpp:158 The player login information should be collected by the lobby screen +region_pager.hpp:49 delete existing regions +serial_packet.hpp:93 login credentials +serial_packet.hpp:104 should move handle/avatar into clientInfo; these might actually do better during the login system +server_application.cpp:86 config parameter +server_application.cpp:214 authenticate who is disconnecting/kicking +server_application.cpp:226 can this use DeletePlayer() instead? +server_application.cpp:248 compensate for large distances +server_application.cpp:257 update this for the expanded PlayerEntry structure +server_application.cpp:296 Add the statistic creation code here +server_application.cpp:313 differentiate between delete and unload +server_application.cpp:315 authenticate who is deleting this player +server_application.cpp:320 remove the deleted player from the database? +server_application.cpp:347 the server needs it's own movement system too +server_application.hpp:77 a function that only sends to players in a certain proximity +server_application.hpp:90 I need to handle multiple map objects +server_application.hpp:91 Unload regions that are distant from any players From 235a05d006a853f9b126ca06f7d917030e92c5d9 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 25 Apr 2014 23:50:19 +1000 Subject: [PATCH 02/10] Rearranged the SerialPacket and serialization code The serialization code is now using macros to simplify each line, and to prevent errors. It should be noted that, apart from the region content, the serialization and deserialization code is essentially identical. --- common/network/serial.cpp | 227 ++++++++++++++----------------- common/network/serial.hpp | 4 +- common/network/serial_packet.hpp | 55 ++++---- 3 files changed, 127 insertions(+), 159 deletions(-) diff --git a/common/network/serial.cpp b/common/network/serial.cpp index ee88937..c6ca226 100644 --- a/common/network/serial.cpp +++ b/common/network/serial.cpp @@ -25,85 +25,59 @@ #include +//------------------------- +//Convenience Macros +//------------------------- + +#define SERIALIZE(buffer, data, size) memcpy(buffer, data, size); buffer += size; +#define DESERIALIZE(buffer, data, size) memcpy(data, buffer, size); buffer += size; + //------------------------- //internal serialization functions //------------------------- void serializeType(SerialPacket* packet, char* buffer) { - memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); + SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); } void serializeServer(SerialPacket* packet, char* buffer) { - memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); - buffer += sizeof(SerialPacket::Type); + SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); //server info - //Note: version info serialization goes here - memcpy(buffer, packet->serverInfo.name, PACKET_STRING_SIZE); - buffer += PACKET_STRING_SIZE; - memcpy(buffer, &packet->serverInfo.playerCount, sizeof(int)); - buffer += sizeof(int); - - //map format - memcpy(buffer, &packet->serverInfo.regionWidth, sizeof(int)); - buffer += sizeof(int); - memcpy(buffer, &packet->serverInfo.regionHeight, sizeof(int)); - buffer += sizeof(int); - memcpy(buffer, &packet->serverInfo.regionDepth, sizeof(int)); + SERIALIZE(buffer, &packet->serverInfo.networkVersion, sizeof(int)); + SERIALIZE(buffer, packet->serverInfo.name, PACKET_STRING_SIZE); + SERIALIZE(buffer, &packet->serverInfo.playerCount, sizeof(int)); } void serializeClient(SerialPacket* packet, char* buffer) { - memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); - buffer += sizeof(SerialPacket::Type); - memcpy(buffer, &packet->clientInfo.index, sizeof(int)); -} - -void serializePlayer(SerialPacket* packet, char* buffer) { - memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); - buffer += sizeof(SerialPacket::Type); + SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); //indexes - memcpy(buffer, &packet->playerInfo.clientIndex, sizeof(int)); - buffer += sizeof(int); - memcpy(buffer, &packet->playerInfo.playerIndex, sizeof(int)); - buffer += sizeof(int); + SERIALIZE(buffer, &packet->clientInfo.clientIndex, sizeof(int)); + SERIALIZE(buffer, &packet->clientInfo.playerIndex, sizeof(int)); - //text - memcpy(buffer, packet->playerInfo.handle, PACKET_STRING_SIZE); - buffer += PACKET_STRING_SIZE; - memcpy(buffer, packet->playerInfo.avatar, PACKET_STRING_SIZE); - buffer += PACKET_STRING_SIZE; - - //vectors - memcpy(buffer, &packet->playerInfo.position.x, sizeof(double)); - buffer += sizeof(double); - memcpy(buffer, &packet->playerInfo.position.y, sizeof(double)); - buffer += sizeof(double); - memcpy(buffer, &packet->playerInfo.motion.x, sizeof(double)); - buffer += sizeof(double); - memcpy(buffer, &packet->playerInfo.motion.y, sizeof(double)); + //texts + SERIALIZE(buffer, packet->clientInfo.player, PACKET_STRING_SIZE); + SERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE); + SERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE); } void serializeRegionFormat(SerialPacket* packet, char* buffer) { - memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); - buffer += sizeof(SerialPacket::Type); + SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); - //x & y - memcpy(buffer, &packet->regionInfo.x, sizeof(int)); - buffer += sizeof(int); - memcpy(buffer, &packet->regionInfo.y, sizeof(int)); + //format + SERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int)); + SERIALIZE(buffer, &packet->regionInfo.x, sizeof(int)); + SERIALIZE(buffer, &packet->regionInfo.y, sizeof(int)); } void serializeRegionContent(SerialPacket* packet, char* buffer) { - //format - memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); - buffer += sizeof(SerialPacket::Type); + SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); - //x & y - *reinterpret_cast(buffer) = packet->regionInfo.region->GetX(); - buffer += sizeof(int); - *reinterpret_cast(buffer) = packet->regionInfo.region->GetY(); - buffer += sizeof(int); + //format + SERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int)); + SERIALIZE(buffer, &packet->regionInfo.x, sizeof(int)); + SERIALIZE(buffer, &packet->regionInfo.y, sizeof(int)); //content for (register int i = 0; i < REGION_WIDTH; i++) { @@ -116,92 +90,75 @@ void serializeRegionContent(SerialPacket* packet, char* buffer) { } } +void serializePlayer(SerialPacket* packet, char* buffer) { + SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); + + //indexes + SERIALIZE(buffer, &packet->playerInfo.clientIndex, sizeof(int)); + SERIALIZE(buffer, &packet->playerInfo.playerIndex, sizeof(int)); + + //vectors + SERIALIZE(buffer, &packet->playerInfo.position.x, sizeof(double)); + SERIALIZE(buffer, &packet->playerInfo.position.y, sizeof(double)); + SERIALIZE(buffer, &packet->playerInfo.motion.x, sizeof(double)); + SERIALIZE(buffer, &packet->playerInfo.motion.y, sizeof(double)); +} + //------------------------- //internal deserialization functions //------------------------- void deserializeType(SerialPacket* packet, char* buffer) { - memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type)); + DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); } void deserializeServer(SerialPacket* packet, char* buffer) { - memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type)); - buffer += sizeof(SerialPacket::Type); + DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); //server info - //Note: version info deserialization goes here - memcpy(packet->serverInfo.name, buffer, PACKET_STRING_SIZE); - buffer += PACKET_STRING_SIZE; - memcpy(&packet->serverInfo.playerCount, buffer, sizeof(int)); - buffer += sizeof(int); - - //map format - memcpy(&packet->serverInfo.regionWidth, buffer, sizeof(int)); - buffer += sizeof(int); - memcpy(&packet->serverInfo.regionHeight, buffer, sizeof(int)); - buffer += sizeof(int); - memcpy(&packet->serverInfo.regionDepth, buffer, sizeof(int)); + DESERIALIZE(buffer, &packet->serverInfo.networkVersion, sizeof(int)); + DESERIALIZE(buffer, packet->serverInfo.name, PACKET_STRING_SIZE); + DESERIALIZE(buffer, &packet->serverInfo.playerCount, sizeof(int)); } void deserializeClient(SerialPacket* packet, char* buffer) { - memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type)); - buffer += sizeof(SerialPacket::Type); - memcpy(&packet->clientInfo.index, buffer, sizeof(int)); -} - -void deserializePlayer(SerialPacket* packet, char* buffer) { - memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type)); - buffer += sizeof(SerialPacket::Type); + DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); //indexes - memcpy(&packet->playerInfo.clientIndex, buffer, sizeof(int)); - buffer += sizeof(int); - memcpy(&packet->playerInfo.playerIndex, buffer, sizeof(int)); - buffer += sizeof(int); + DESERIALIZE(buffer, &packet->clientInfo.clientIndex, sizeof(int)); + DESERIALIZE(buffer, &packet->clientInfo.playerIndex, sizeof(int)); - //text - memcpy(packet->playerInfo.handle, buffer, PACKET_STRING_SIZE); - buffer += PACKET_STRING_SIZE; - memcpy(packet->playerInfo.avatar, buffer, PACKET_STRING_SIZE); - buffer += PACKET_STRING_SIZE; - - //vectors - memcpy(&packet->playerInfo.position.x, buffer, sizeof(double)); - buffer += sizeof(double); - memcpy(&packet->playerInfo.position.y, buffer, sizeof(double)); - buffer += sizeof(double); - memcpy(&packet->playerInfo.motion.x, buffer, sizeof(double)); - buffer += sizeof(double); - memcpy(&packet->playerInfo.motion.y, buffer, sizeof(double)); + //texts + DESERIALIZE(buffer, packet->clientInfo.player, PACKET_STRING_SIZE); + DESERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE); + DESERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE); } void deserializeRegionFormat(SerialPacket* packet, char* buffer) { - memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type)); - buffer += sizeof(SerialPacket::Type); + DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); - //x & y - memcpy(&packet->regionInfo.x, buffer, sizeof(int)); - buffer += sizeof(int); - memcpy(&packet->regionInfo.y, buffer, sizeof(int)); + //format + DESERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int)); + DESERIALIZE(buffer, &packet->regionInfo.x, sizeof(int)); + DESERIALIZE(buffer, &packet->regionInfo.y, sizeof(int)); } void deserializeRegionContent(SerialPacket* packet, char* buffer) { - memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type)); - buffer += sizeof(SerialPacket::Type); + DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); - //x & y - memcpy(&packet->regionInfo.x, buffer, sizeof(int)); - buffer += sizeof(int); - memcpy(&packet->regionInfo.y, buffer, sizeof(int)); - buffer += sizeof(int); + //format + DESERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int)); + DESERIALIZE(buffer, &packet->regionInfo.x, sizeof(int)); + DESERIALIZE(buffer, &packet->regionInfo.y, sizeof(int)); - //content + //an object to work on BlankAllocator().Create( &packet->regionInfo.region, packet->regionInfo.x, packet->regionInfo.y ); + //content for (register int i = 0; i < REGION_WIDTH; i++) { for (register int j = 0; j < REGION_HEIGHT; j++) { for (register int k = 0; k < REGION_DEPTH; k++) { @@ -212,6 +169,20 @@ void deserializeRegionContent(SerialPacket* packet, char* buffer) { } } +void deserializePlayer(SerialPacket* packet, char* buffer) { + DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); + + //indexes + DESERIALIZE(buffer, &packet->playerInfo.clientIndex, sizeof(int)); + DESERIALIZE(buffer, &packet->playerInfo.playerIndex, sizeof(int)); + + //vectors + DESERIALIZE(buffer, &packet->playerInfo.position.x, sizeof(double)); + DESERIALIZE(buffer, &packet->playerInfo.position.y, sizeof(double)); + DESERIALIZE(buffer, &packet->playerInfo.motion.x, sizeof(double)); + DESERIALIZE(buffer, &packet->playerInfo.motion.y, sizeof(double)); +} + //------------------------- //the interface functions //------------------------- @@ -223,8 +194,6 @@ void serialize(SerialPacket* packet, void* buffer) { case SerialPacket::Type::PING: case SerialPacket::Type::PONG: case SerialPacket::Type::BROADCAST_REQUEST: - case SerialPacket::Type::JOIN_REQUEST: - case SerialPacket::Type::SYNCHRONIZE: serializeType(packet, reinterpret_cast(buffer)); break; @@ -234,19 +203,14 @@ void serialize(SerialPacket* packet, void* buffer) { break; //Client info + case SerialPacket::Type::JOIN_REQUEST: case SerialPacket::Type::JOIN_RESPONSE: + case SerialPacket::Type::SYNCHRONIZE: case SerialPacket::Type::DISCONNECT: case SerialPacket::Type::SHUTDOWN: serializeClient(packet, reinterpret_cast(buffer)); break; - //Player info - case SerialPacket::Type::PLAYER_NEW: - case SerialPacket::Type::PLAYER_DELETE: - case SerialPacket::Type::PLAYER_UPDATE: - serializePlayer(packet, reinterpret_cast(buffer)); - break; - //region info case SerialPacket::Type::REGION_REQUEST: serializeRegionFormat(packet, reinterpret_cast(buffer)); @@ -255,6 +219,13 @@ void serialize(SerialPacket* packet, void* buffer) { case SerialPacket::Type::REGION_CONTENT: serializeRegionContent(packet, reinterpret_cast(buffer)); break; + + //Player info + case SerialPacket::Type::PLAYER_NEW: + case SerialPacket::Type::PLAYER_DELETE: + case SerialPacket::Type::PLAYER_UPDATE: + serializePlayer(packet, reinterpret_cast(buffer)); + break; } } @@ -267,8 +238,6 @@ void deserialize(SerialPacket* packet, void* buffer) { case SerialPacket::Type::PING: case SerialPacket::Type::PONG: case SerialPacket::Type::BROADCAST_REQUEST: - case SerialPacket::Type::JOIN_REQUEST: - case SerialPacket::Type::SYNCHRONIZE: //NOTHING break; @@ -278,19 +247,14 @@ void deserialize(SerialPacket* packet, void* buffer) { break; //Client info + case SerialPacket::Type::JOIN_REQUEST: case SerialPacket::Type::JOIN_RESPONSE: + case SerialPacket::Type::SYNCHRONIZE: case SerialPacket::Type::DISCONNECT: case SerialPacket::Type::SHUTDOWN: deserializeClient(packet, reinterpret_cast(buffer)); break; - //Player info - case SerialPacket::Type::PLAYER_NEW: - case SerialPacket::Type::PLAYER_DELETE: - case SerialPacket::Type::PLAYER_UPDATE: - deserializePlayer(packet, reinterpret_cast(buffer)); - break; - //region info case SerialPacket::Type::REGION_REQUEST: deserializeRegionFormat(packet, reinterpret_cast(buffer)); @@ -299,5 +263,12 @@ void deserialize(SerialPacket* packet, void* buffer) { case SerialPacket::Type::REGION_CONTENT: deserializeRegionContent(packet, reinterpret_cast(buffer)); break; + + //Player info + case SerialPacket::Type::PLAYER_NEW: + case SerialPacket::Type::PLAYER_DELETE: + case SerialPacket::Type::PLAYER_UPDATE: + deserializePlayer(packet, reinterpret_cast(buffer)); + break; } } \ No newline at end of file diff --git a/common/network/serial.hpp b/common/network/serial.hpp index b532bb8..609b1f3 100644 --- a/common/network/serial.hpp +++ b/common/network/serial.hpp @@ -27,10 +27,10 @@ /* NOTE: Keep the PACKET_BUFFER_SIZE up to date * NOTE: REGION_CONTENT is currently the largest type of packet * map content: REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizoeof(region::type_t) - * map format: sizeof(int) * 2 + * map format: sizeof(int) * 3 * metadata: sizeof(metadata) */ -#define PACKET_BUFFER_SIZE REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) + sizeof(int) * 2 + sizeof(SerialPacket::Metadata) +#define PACKET_BUFFER_SIZE REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) + sizeof(int) * 3 + sizeof(SerialPacket::Metadata) void serialize(SerialPacket* const, void*); void deserialize(SerialPacket* const, void*); diff --git a/common/network/serial_packet.hpp b/common/network/serial_packet.hpp index 86c9b2a..af897d6 100644 --- a/common/network/serial_packet.hpp +++ b/common/network/serial_packet.hpp @@ -27,6 +27,7 @@ #include "SDL/SDL_net.h" +#define NETWORK_VERSION 20140426 #define PACKET_STRING_SIZE 100 #pragma pack(push, 0) @@ -49,23 +50,23 @@ union SerialPacket { JOIN_REQUEST = 5, JOIN_RESPONSE = 6, - //disconnect from the server - DISCONNECT = 7, - //mass update - SYNCHRONIZE = 8, + SYNCHRONIZE = 7, + + //disconnect from the server + DISCONNECT = 8, //shut down the server SHUTDOWN = 9, - //Player movement, etc. - PLAYER_NEW = 10, - PLAYER_DELETE = 11, - PLAYER_UPDATE = 12, - //map data - REGION_REQUEST = 13, - REGION_CONTENT = 14, + REGION_REQUEST = 10, + REGION_CONTENT = 11, + + //Player movement, etc. + PLAYER_NEW = 12, + PLAYER_DELETE = 13, + PLAYER_UPDATE = 14, //TODO: combat packets }; @@ -79,42 +80,38 @@ union SerialPacket { //information about the server struct ServerInformation { Metadata meta; - //TODO: version info + int networkVersion; char name[PACKET_STRING_SIZE]; int playerCount; - - //map format - int regionWidth; - int regionHeight; - int regionDepth; }serverInfo; //information about the client - //TODO: login credentials struct ClientInformation { Metadata meta; - int index; + int clientIndex; + int playerIndex; + char player[PACKET_STRING_SIZE]; + char handle[PACKET_STRING_SIZE]; + char avatar[PACKET_STRING_SIZE]; }clientInfo; + //map data + struct RegionInformation { + Metadata meta; + int mapIndex; + int x, y; + Region* region; + }regionInfo; + //information about a player struct PlayerInformation { Metadata meta; int clientIndex; int playerIndex; - //TODO: should move handle/avatar into clientInfo; these might actually do better during the login system - char handle[PACKET_STRING_SIZE]; - char avatar[PACKET_STRING_SIZE]; Vector2 position; Vector2 motion; }playerInfo; - //map data - struct RegionInformation { - Metadata meta; - int x, y; - Region* region; - }regionInfo; - //defaults SerialPacket() { meta.type = Type::NONE; From d55dfb90e44333a25832faafb2af817aa8976f51 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sat, 26 Apr 2014 01:05:31 +1000 Subject: [PATCH 03/10] Worked the new protocol into the client (read more) I've added the handle and avatar fields back into the PlayerInfo section in the network code, because I need to be able to load a specific file when a new player is created. This wasn't forseen, but it's fine. i'm leaving the fields in ClientInfo as well, because LobbyMenu is using them to login to the server. PlayerIndex is now a shared parameter. I've shifted some code around in InWorld, however the overall logic is the same. This build (as well as the last) does not compile. --- client/client_application.cpp | 4 +- client/client_application.hpp | 4 +- client/scenes/in_world.cpp | 117 +++++++++++++++---------------- client/scenes/in_world.hpp | 12 ++-- client/scenes/lobby_menu.cpp | 21 +++--- client/scenes/lobby_menu.hpp | 10 ++- client/scenes/main_menu.hpp | 2 +- client/scenes/options_menu.hpp | 2 +- client/scenes/splash_screen.hpp | 2 +- common/network/serial.cpp | 8 +++ common/network/serial_packet.hpp | 2 + rsc/config.cfg | 5 +- 12 files changed, 99 insertions(+), 90 deletions(-) diff --git a/client/client_application.cpp b/client/client_application.cpp index ecddb97..b71140f 100644 --- a/client/client_application.cpp +++ b/client/client_application.cpp @@ -119,10 +119,10 @@ void ClientApplication::LoadScene(SceneList sceneIndex) { activeScene = new OptionsMenu(&config); break; case SceneList::LOBBYMENU: - activeScene = new LobbyMenu(&config, &network, &clientIndex); + activeScene = new LobbyMenu(&config, &network, &clientIndex, &playerIndex); break; case SceneList::INWORLD: - activeScene = new InWorld(&config, &network, &clientIndex); + activeScene = new InWorld(&config, &network, &clientIndex, &playerIndex); break; case SceneList::INCOMBAT: activeScene = new InCombat(); diff --git a/client/client_application.hpp b/client/client_application.hpp index d4b22f5..40e00b0 100644 --- a/client/client_application.hpp +++ b/client/client_application.hpp @@ -44,9 +44,11 @@ private: BaseScene* activeScene = nullptr; + //shared parameters ConfigUtility config; UDPNetworkUtility network; - int clientIndex = -1; //replace with a struct? + int clientIndex = -1; + int playerIndex = -1; }; #endif diff --git a/client/scenes/in_world.cpp b/client/scenes/in_world.cpp index 37c533f..fc1bdde 100644 --- a/client/scenes/in_world.cpp +++ b/client/scenes/in_world.cpp @@ -31,10 +31,11 @@ //Public access members //------------------------- -InWorld::InWorld(ConfigUtility* const argConfig, UDPNetworkUtility* const argNetwork, int* const argClientIndex): +InWorld::InWorld(ConfigUtility* const argConfig, UDPNetworkUtility* const argNetwork, int* const argClientIndex, int* const argPlayerIndex): config(*argConfig), network(*argNetwork), - clientIndex(*argClientIndex) + clientIndex(*argClientIndex), + playerIndex(*argPlayerIndex) { //setup the utility objects buttonImage.LoadSurface(config["dir.interface"] + "button_menu.bmp"); @@ -61,23 +62,12 @@ InWorld::InWorld(ConfigUtility* const argConfig, UDPNetworkUtility* const argNet //TODO: add the tilesheet to the map system? tileSheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15); - //create the server-side player object - //TODO: the login system needs an overhaul - SerialPacket packet; - packet.meta.type = SerialPacket::Type::PLAYER_NEW; - packet.playerInfo.clientIndex = clientIndex; - snprintf(packet.playerInfo.handle, PACKET_STRING_SIZE, "%s", config["player.handle"].c_str()); - snprintf(packet.playerInfo.avatar, PACKET_STRING_SIZE, "%s", config["player.avatar"].c_str()); - packet.playerInfo.position = {0,0}; - packet.playerInfo.motion = {0,0}; - - //send it - char buffer[PACKET_BUFFER_SIZE]; - serialize(&packet, buffer); - network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE); - //request a sync + SerialPacket packet; + char buffer[PACKET_STRING_SIZE]; packet.meta.type = SerialPacket::Type::SYNCHRONIZE; + packet.clientInfo.clientIndex = clientIndex; + packet.clientInfo.playerIndex = playerIndex; serialize(&packet, buffer); network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE); @@ -190,28 +180,28 @@ void InWorld::KeyDown(SDL_KeyboardEvent const& key) { case SDLK_LEFT: if (localCharacter) { localCharacter->AdjustDirection(PlayerCharacter::Direction::WEST); - SendState(); + SendPlayerUpdate(); } break; case SDLK_RIGHT: if (localCharacter) { localCharacter->AdjustDirection(PlayerCharacter::Direction::EAST); - SendState(); + SendPlayerUpdate(); } break; case SDLK_UP: if (localCharacter) { localCharacter->AdjustDirection(PlayerCharacter::Direction::NORTH); - SendState(); + SendPlayerUpdate(); } break; case SDLK_DOWN: if (localCharacter) { localCharacter->AdjustDirection(PlayerCharacter::Direction::SOUTH); - SendState(); + SendPlayerUpdate(); } break; } @@ -223,28 +213,28 @@ void InWorld::KeyUp(SDL_KeyboardEvent const& key) { case SDLK_LEFT: if (localCharacter) { localCharacter->AdjustDirection(PlayerCharacter::Direction::EAST); - SendState(); + SendPlayerUpdate(); } break; case SDLK_RIGHT: if (localCharacter) { localCharacter->AdjustDirection(PlayerCharacter::Direction::WEST); - SendState(); + SendPlayerUpdate(); } break; case SDLK_UP: if (localCharacter) { localCharacter->AdjustDirection(PlayerCharacter::Direction::SOUTH); - SendState(); + SendPlayerUpdate(); } break; case SDLK_DOWN: if (localCharacter) { localCharacter->AdjustDirection(PlayerCharacter::Direction::NORTH); - SendState(); + SendPlayerUpdate(); } break; } @@ -259,18 +249,18 @@ void InWorld::HandlePacket(SerialPacket packet) { case SerialPacket::Type::DISCONNECT: HandleDisconnect(packet); break; + case SerialPacket::Type::REGION_CONTENT: + HandleRegionContent(packet); + break; + case SerialPacket::Type::PLAYER_UPDATE: + HandlePlayerUpdate(packet); + break; case SerialPacket::Type::PLAYER_NEW: HandlePlayerNew(packet); break; case SerialPacket::Type::PLAYER_DELETE: HandlePlayerDelete(packet); break; - case SerialPacket::Type::PLAYER_UPDATE: - HandlePlayerUpdate(packet); - break; - case SerialPacket::Type::REGION_CONTENT: - HandleRegionContent(packet); - break; //handle errors default: throw(std::runtime_error("Unknown SerialPacket::Type encountered")); @@ -281,23 +271,48 @@ void InWorld::HandlePacket(SerialPacket packet) { void InWorld::HandleDisconnect(SerialPacket packet) { network.Unbind(Channels::SERVER); clientIndex = -1; + playerIndex = -1; SetNextScene(SceneList::MAINMENU); } +void InWorld::HandleRegionContent(SerialPacket packet) { + //replace existing regions + //TODO: account for map index + if (regionPager.FindRegion(packet.regionInfo.x, packet.regionInfo.y)) { + regionPager.UnloadRegion(packet.regionInfo.x, packet.regionInfo.y); + } + regionPager.PushRegion(packet.regionInfo.region); + packet.regionInfo.region = nullptr; +} + +void InWorld::HandlePlayerUpdate(SerialPacket packet) { + if (playerCharacters.find(packet.playerInfo.playerIndex) == playerCharacters.end()) { + throw(std::runtime_error("Cannot update nen-existant players")); + } + + //update only if the message didn't originate from here + if (packet.playerInfo.clientIndex != clientIndex) { + playerCharacters[packet.playerInfo.playerIndex].SetPosition(packet.playerInfo.position); + playerCharacters[packet.playerInfo.playerIndex].SetMotion(packet.playerInfo.motion); + } + playerCharacters[packet.playerInfo.playerIndex].ResetDirection(); +} + void InWorld::HandlePlayerNew(SerialPacket packet) { if (playerCharacters.find(packet.playerInfo.playerIndex) != playerCharacters.end()) { throw(std::runtime_error("Cannot create duplicate players")); } + //TODO: set the handle playerCharacters[packet.playerInfo.playerIndex].GetSprite()->LoadSurface(config["dir.sprites"] + packet.playerInfo.avatar, 4, 4); playerCharacters[packet.playerInfo.playerIndex].SetPosition(packet.playerInfo.position); playerCharacters[packet.playerInfo.playerIndex].SetMotion(packet.playerInfo.motion); playerCharacters[packet.playerInfo.playerIndex].ResetDirection(); //catch this client's player object - if (packet.playerInfo.clientIndex == clientIndex && !localCharacter) { - playerIndex = packet.playerInfo.playerIndex; + if (packet.playerInfo.playerIndex == playerIndex && !localCharacter) { localCharacter = &playerCharacters[playerIndex]; + //setup the camera camera.width = GetScreen()->w; camera.height = GetScreen()->h; @@ -315,40 +330,17 @@ void InWorld::HandlePlayerDelete(SerialPacket packet) { playerCharacters.erase(packet.playerInfo.playerIndex); //catch this client's player object - if (packet.playerInfo.clientIndex == clientIndex) { + if (packet.playerInfo.playerIndex == playerIndex) { playerIndex = -1; localCharacter = nullptr; } } -void InWorld::HandlePlayerUpdate(SerialPacket packet) { - if (playerCharacters.find(packet.playerInfo.playerIndex) == playerCharacters.end()) { - HandlePlayerNew(packet); - return; - } - - //update only if the message didn't originate from here - if (packet.playerInfo.clientIndex != clientIndex) { - playerCharacters[packet.playerInfo.playerIndex].SetPosition(packet.playerInfo.position); - playerCharacters[packet.playerInfo.playerIndex].SetMotion(packet.playerInfo.motion); - } - playerCharacters[packet.playerInfo.playerIndex].ResetDirection(); -} - -void InWorld::HandleRegionContent(SerialPacket packet) { - //replace existing regions - if (regionPager.FindRegion(packet.regionInfo.x, packet.regionInfo.y)) { - regionPager.UnloadRegion(packet.regionInfo.x, packet.regionInfo.y); - } - regionPager.PushRegion(packet.regionInfo.region); - packet.regionInfo.region = nullptr; -} - //------------------------- //Server control //------------------------- -void InWorld::SendState() { +void InWorld::SendPlayerUpdate() { SerialPacket packet; char buffer[PACKET_BUFFER_SIZE]; @@ -369,7 +361,7 @@ void InWorld::RequestDisconnect() { //send a disconnect request packet.meta.type = SerialPacket::Type::DISCONNECT; - packet.clientInfo.index = clientIndex; + packet.clientInfo.clientIndex = clientIndex; serialize(&packet, buffer); network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE); } @@ -380,17 +372,18 @@ void InWorld::RequestShutDown() { //send a shutdown request packet.meta.type = SerialPacket::Type::SHUTDOWN; - packet.clientInfo.index = clientIndex; + packet.clientInfo.clientIndex = clientIndex; serialize(&packet, buffer); network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE); } -void InWorld::RequestRegion(int x, int y) { +void InWorld::RequestRegion(int mapIndex, int x, int y) { SerialPacket packet; char buffer[PACKET_BUFFER_SIZE]; //pack the region's data packet.meta.type = SerialPacket::Type::REGION_REQUEST; + packet.regionInfo.mapIndex = mapIndex; packet.regionInfo.x = x; packet.regionInfo.y = y; serialize(&packet, buffer); @@ -430,7 +423,7 @@ void InWorld::UpdateMap() { for (int i = xStart; i <= xEnd; i += REGION_WIDTH) { for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) { if (!regionPager.FindRegion(i, j)) { - RequestRegion(i, j); + RequestRegion(0, i, j); } } } diff --git a/client/scenes/in_world.hpp b/client/scenes/in_world.hpp index bb0cc5c..00dcfa2 100644 --- a/client/scenes/in_world.hpp +++ b/client/scenes/in_world.hpp @@ -52,7 +52,7 @@ class InWorld : public BaseScene { public: //Public access members - InWorld(ConfigUtility* const, UDPNetworkUtility* const, int* const); + InWorld(ConfigUtility* const, UDPNetworkUtility* const, int* const, int* const); ~InWorld(); protected: @@ -80,19 +80,19 @@ protected: void HandleRegionContent(SerialPacket); //Server control - void SendState(); + void SendPlayerUpdate(); void RequestDisconnect(); void RequestShutDown(); - void RequestRegion(int x, int y); + void RequestRegion(int mapIndex, int x, int y); //utilities void UpdateMap(); - //globals + //shared parameters ConfigUtility& config; - FrameRate fps; UDPNetworkUtility& network; int& clientIndex; + int& playerIndex; //graphics Image buttonImage; @@ -111,11 +111,11 @@ protected: int width = 0, height = 0; int marginX = 0, marginY = 0; } camera; + FrameRate fps; //game std::map playerCharacters; PlayerCharacter* localCharacter = nullptr; - int playerIndex = -1; }; #endif diff --git a/client/scenes/lobby_menu.cpp b/client/scenes/lobby_menu.cpp index 1000af4..d6900da 100644 --- a/client/scenes/lobby_menu.cpp +++ b/client/scenes/lobby_menu.cpp @@ -30,10 +30,11 @@ //Public access members //------------------------- -LobbyMenu::LobbyMenu(ConfigUtility* const argConfig, UDPNetworkUtility* const argNetwork, int* const argClientIndex): +LobbyMenu::LobbyMenu(ConfigUtility* const argConfig, UDPNetworkUtility* const argNetwork, int* const argClientIndex, int* const argPlayerIndex): config(*argConfig), network(*argNetwork), - clientIndex(*argClientIndex) + clientIndex(*argClientIndex), + playerIndex(*argPlayerIndex) { //setup the utility objects image.LoadSurface(config["dir.interface"] + "button_menu.bmp"); @@ -155,13 +156,17 @@ void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) { } else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr && selection->compatible) { - //TODO: The player login information should be collected by the lobby screen //the vars SerialPacket packet; char buffer[PACKET_BUFFER_SIZE]; - //join the selected server + //pack the packet packet.meta.type = SerialPacket::Type::JOIN_REQUEST; + strncpy(packet.clientInfo.player, config["client.player"].c_str(), PACKET_STRING_SIZE); + strncpy(packet.clientInfo.handle, config["client.handle"].c_str(), PACKET_STRING_SIZE); + strncpy(packet.clientInfo.avatar, config["client.avatar"].c_str(), PACKET_STRING_SIZE); + + //join the selected server serialize(&packet, buffer); network.Send(&selection->address, buffer, PACKET_BUFFER_SIZE); selection = nullptr; @@ -203,20 +208,20 @@ void LobbyMenu::HandlePacket(SerialPacket packet) { //extract the data ServerInformation server; server.address = packet.meta.srcAddress; + server.networkVersion = packet.serverInfo.networkVersion; server.name = packet.serverInfo.name; server.playerCount = packet.serverInfo.playerCount; //NOTE: Check compatibility here - server.compatible = packet.serverInfo.regionWidth == REGION_WIDTH && - packet.serverInfo.regionHeight == REGION_HEIGHT && - packet.serverInfo.regionDepth == REGION_DEPTH; + server.compatible = server.networkVersion == NETWORK_VERSION; //push serverInfo.push_back(server); } break; case SerialPacket::Type::JOIN_RESPONSE: - clientIndex = packet.clientInfo.index; + clientIndex = packet.clientInfo.clientIndex; + playerIndex = packet.clientInfo.playerIndex; network.Bind(&packet.meta.srcAddress, Channels::SERVER); SetNextScene(SceneList::INWORLD); break; diff --git a/client/scenes/lobby_menu.hpp b/client/scenes/lobby_menu.hpp index 53808bb..4273400 100644 --- a/client/scenes/lobby_menu.hpp +++ b/client/scenes/lobby_menu.hpp @@ -28,9 +28,6 @@ #include "button.hpp" #include "config_utility.hpp" -//map -#include "region.hpp" - //network #include "udp_network_utility.hpp" #include "serial_packet.hpp" @@ -45,7 +42,7 @@ class LobbyMenu : public BaseScene { public: //Public access members - LobbyMenu(ConfigUtility* const, UDPNetworkUtility* const, int* const); + LobbyMenu(ConfigUtility* const, UDPNetworkUtility* const, int* const, int* const); ~LobbyMenu(); protected: @@ -64,10 +61,11 @@ protected: void HandlePacket(SerialPacket); - //global + //shared parameters ConfigUtility& config; UDPNetworkUtility& network; int& clientIndex; + int& playerIndex; //members Image image; @@ -79,7 +77,7 @@ protected: //server list struct ServerInformation { IPaddress address; - //TODO: version info + int networkVersion; std::string name; int playerCount; bool compatible; diff --git a/client/scenes/main_menu.hpp b/client/scenes/main_menu.hpp index 5aba53d..9c06a0d 100644 --- a/client/scenes/main_menu.hpp +++ b/client/scenes/main_menu.hpp @@ -49,7 +49,7 @@ protected: void KeyDown(SDL_KeyboardEvent const&); void KeyUp(SDL_KeyboardEvent const&); - //globals + //shared parameters ConfigUtility& config; //members diff --git a/client/scenes/options_menu.hpp b/client/scenes/options_menu.hpp index 6e99965..bc05e1f 100644 --- a/client/scenes/options_menu.hpp +++ b/client/scenes/options_menu.hpp @@ -49,7 +49,7 @@ protected: void KeyDown(SDL_KeyboardEvent const&); void KeyUp(SDL_KeyboardEvent const&); - //globals + //shared parameters ConfigUtility& config; //members diff --git a/client/scenes/splash_screen.hpp b/client/scenes/splash_screen.hpp index f332cbe..f24a1c6 100644 --- a/client/scenes/splash_screen.hpp +++ b/client/scenes/splash_screen.hpp @@ -40,7 +40,7 @@ protected: void Update(double delta); void Render(SDL_Surface* const); - //globals + //shared parameters ConfigUtility& config; //members diff --git a/common/network/serial.cpp b/common/network/serial.cpp index c6ca226..6f2f069 100644 --- a/common/network/serial.cpp +++ b/common/network/serial.cpp @@ -97,6 +97,10 @@ void serializePlayer(SerialPacket* packet, char* buffer) { SERIALIZE(buffer, &packet->playerInfo.clientIndex, sizeof(int)); SERIALIZE(buffer, &packet->playerInfo.playerIndex, sizeof(int)); + //texts + SERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE); + SERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE); + //vectors SERIALIZE(buffer, &packet->playerInfo.position.x, sizeof(double)); SERIALIZE(buffer, &packet->playerInfo.position.y, sizeof(double)); @@ -176,6 +180,10 @@ void deserializePlayer(SerialPacket* packet, char* buffer) { DESERIALIZE(buffer, &packet->playerInfo.clientIndex, sizeof(int)); DESERIALIZE(buffer, &packet->playerInfo.playerIndex, sizeof(int)); + //texts + DESERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE); + DESERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE); + //vectors DESERIALIZE(buffer, &packet->playerInfo.position.x, sizeof(double)); DESERIALIZE(buffer, &packet->playerInfo.position.y, sizeof(double)); diff --git a/common/network/serial_packet.hpp b/common/network/serial_packet.hpp index af897d6..ff4fb8c 100644 --- a/common/network/serial_packet.hpp +++ b/common/network/serial_packet.hpp @@ -108,6 +108,8 @@ union SerialPacket { Metadata meta; int clientIndex; int playerIndex; + char handle[PACKET_STRING_SIZE]; + char avatar[PACKET_STRING_SIZE]; Vector2 position; Vector2 motion; }playerInfo; diff --git a/rsc/config.cfg b/rsc/config.cfg index 0b5fec0..37fbd5e 100644 --- a/rsc/config.cfg +++ b/rsc/config.cfg @@ -23,7 +23,8 @@ map.pager.height = 20 map.pager.depth = 3 #player options -player.handle = username -player.avatar = elliot2.bmp +client.player = Kayne Ruse +client.handle = Ratstail91 +client.avatar = elliot2.bmp #debugging From 9c673928e60416cdb5ce8f19195775417fbe341f Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sat, 26 Apr 2014 02:05:22 +1000 Subject: [PATCH 04/10] Began segmenting the server's code I've created a separate branch for this because it's gonna be a bitch to get compiled, and then I'll still have to ensure that the client & server are work together correctly. This build does not compile. --- server/client_entry.cpp | 2 +- server/client_entry.hpp | 2 +- ...{server_application.cpp => networking.cpp} | 165 ++--------------- server/player_entry.cpp | 2 +- server/player_entry.hpp | 3 +- server/player_management.cpp | 46 +++++ server/server_application.hpp | 18 +- server/server_internals.cpp | 166 ++++++++++++++++++ 8 files changed, 238 insertions(+), 166 deletions(-) rename server/{server_application.cpp => networking.cpp} (61%) create mode 100644 server/player_management.cpp create mode 100644 server/server_internals.cpp diff --git a/server/client_entry.cpp b/server/client_entry.cpp index 7708423..88e2ab9 100644 --- a/server/client_entry.cpp +++ b/server/client_entry.cpp @@ -21,4 +21,4 @@ */ #include "client_entry.hpp" -unsigned int ClientEntry::uidCounter; +int ClientEntry::uidCounter = 0; diff --git a/server/client_entry.hpp b/server/client_entry.hpp index 42225b8..7e5dc90 100644 --- a/server/client_entry.hpp +++ b/server/client_entry.hpp @@ -26,7 +26,7 @@ struct ClientEntry { IPaddress address; - static unsigned int uidCounter; + static int uidCounter; }; #endif diff --git a/server/server_application.cpp b/server/networking.cpp similarity index 61% rename from server/server_application.cpp rename to server/networking.cpp index 1a96d5b..a981abf 100644 --- a/server/server_application.cpp +++ b/server/networking.cpp @@ -21,167 +21,19 @@ */ #include "server_application.hpp" -#include "utility.hpp" - #include #include -#include - -//------------------------- -//Define the public members -//------------------------- - -void ServerApplication::Init(int argc, char** argv) { - //NOTE: I might need to rearrange the init process so that lua & SQL can interact with the map system as needed. - std::cout << "Beginning startup" << std::endl; - - //initial setup - ClientEntry::uidCounter = 0; - PlayerEntry::uidCounter = 0; - config.Load("rsc\\config.cfg"); - - //Init SDL - if (SDL_Init(0)) { - throw(std::runtime_error("Failed to initialize SDL")); - } - std::cout << "Initialized SDL" << std::endl; - - //Init SDL_net - if (SDLNet_Init()) { - throw(std::runtime_error("Failed to initialize SDL_net")); - } - network.Open(config.Int("server.port"), PACKET_BUFFER_SIZE); - std::cout << "Initialized SDL_net" << std::endl; - - //Init SQL - int ret = sqlite3_open_v2(config["server.dbname"].c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, nullptr); - if (ret != SQLITE_OK || !database) { - throw(std::runtime_error(std::string() + "Failed to initialize SQL: " + sqlite3_errmsg(database) )); - } - std::cout << "Initialized SQL" << std::endl; - - //setup the database - if (runSQLScript(database, config["dir.scripts"] + "setup_server.sql")) { - throw(std::runtime_error("Failed to initialize SQL's setup script")); - } - std::cout << "Initialized SQL's setup script" << std::endl; - - //lua - luaState = luaL_newstate(); - if (!luaState) { - throw(std::runtime_error("Failed to initialize lua")); - } - luaL_openlibs(luaState); - std::cout << "Initialized lua" << std::endl; - - //run the startup script - if (luaL_dofile(luaState, (config["dir.scripts"] + "setup_server.lua").c_str())) { - throw(std::runtime_error(std::string() + "Failed to initialize lua's setup script: " + lua_tostring(luaState, -1) )); - } - std::cout << "Initialized lua's setup script" << std::endl; - - //setup the map object - regionPager.GetAllocator()->SetLuaState(luaState); - regionPager.GetFormat()->SetLuaState(luaState); - //TODO: config parameter - regionPager.GetFormat()->SetSaveDir("save/mapname/"); - - std::cout << "Initialized the map system" << std::endl; - std::cout << "\tsizeof(SerialPacket): " << sizeof(SerialPacket) << std::endl; - std::cout << "\tPACKET_BUFFER_SIZE: " << PACKET_BUFFER_SIZE << std::endl; - - //finalize the startup - std::cout << "Startup completed successfully" << std::endl; - - //debugging - // -} - -void ServerApplication::Proc() { - SerialPacket packet; - while(running) { - //suck in the waiting packets & process them - while(network.Receive()) { - //get the packet - deserialize(&packet, network.GetInData()); - //cache the source address - packet.meta.srcAddress = network.GetInPacket()->address; - //we need to go deeper - HandlePacket(packet); - } - //give the computer a break - SDL_Delay(10); - } -} - -void ServerApplication::Quit() { - std::cout << "Shutting down" << std::endl; - //empty the members - regionPager.UnloadAll(); - - //APIs - lua_close(luaState); - sqlite3_close_v2(database); - network.Close(); - SDLNet_Quit(); - SDL_Quit(); - std::cout << "Shutdown finished" << std::endl; -} - -//------------------------- -//Define the uber switch -//------------------------- - -void ServerApplication::HandlePacket(SerialPacket packet) { - switch(packet.meta.type) { - case SerialPacket::Type::BROADCAST_REQUEST: - HandleBroadcastRequest(packet); - break; - case SerialPacket::Type::JOIN_REQUEST: - HandleJoinRequest(packet); - break; - case SerialPacket::Type::DISCONNECT: - HandleDisconnect(packet); - break; - case SerialPacket::Type::SYNCHRONIZE: - HandleSynchronize(packet); - break; - case SerialPacket::Type::SHUTDOWN: - HandleShutdown(packet); - break; - case SerialPacket::Type::PLAYER_NEW: - HandlePlayerNew(packet); - break; - case SerialPacket::Type::PLAYER_DELETE: - HandlePlayerDelete(packet); - break; - case SerialPacket::Type::PLAYER_UPDATE: - HandlePlayerUpdate(packet); - break; - case SerialPacket::Type::REGION_REQUEST: - HandleRegionRequest(packet); - break; - //handle errors - default: - throw(std::runtime_error("Unknown SerialPacket::Type encountered")); - break; - } -} //------------------------- //Handle various network input //------------------------- void ServerApplication::HandleBroadcastRequest(SerialPacket packet) { - //send back the server's metadata - packet.meta.type = SerialPacket::Type::BROADCAST_RESPONSE; - //pack the data + packet.meta.type = SerialPacket::Type::BROADCAST_RESPONSE; + packet.serverInfo.networkVersion = NETWORK_VERSION; snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str()); packet.serverInfo.playerCount = playerMap.size(); - packet.serverInfo.regionWidth = REGION_WIDTH; - packet.serverInfo.regionHeight = REGION_HEIGHT; - packet.serverInfo.regionDepth = REGION_DEPTH; //send the data char buffer[PACKET_BUFFER_SIZE]; @@ -195,13 +47,16 @@ void ServerApplication::HandleJoinRequest(SerialPacket packet) { newClient.address = packet.meta.srcAddress; clientMap[ClientEntry::uidCounter] = newClient; - //send the client their index - char buffer[PACKET_BUFFER_SIZE]; + //create the new player + //TODO: make the player + + //send the client their info packet.meta.type = SerialPacket::Type::JOIN_RESPONSE; packet.clientInfo.index = ClientEntry::uidCounter; - serialize(&packet, buffer); //bounce this packet + char buffer[PACKET_BUFFER_SIZE]; + serialize(&packet, buffer); network.Send(&newClient.address, buffer, PACKET_BUFFER_SIZE); //finished this routine @@ -224,7 +79,7 @@ void ServerApplication::HandleDisconnect(SerialPacket packet) { //TODO: can this use DeletePlayer() instead? //delete server and client side players - erase_if(playerMap, [&](std::pair it) -> bool { + erase_if(playerMap, [&](std::pair it) -> bool { //find the internal players to delete if (it.second.clientIndex == packet.clientInfo.index) { //send the delete player command to all clients @@ -323,7 +178,7 @@ void ServerApplication::HandlePlayerDelete(SerialPacket packet) { delPacket.meta.type = SerialPacket::Type::PLAYER_DELETE; //delete the specified playerEntry - erase_if(playerMap, [&](std::pair it) -> bool { + erase_if(playerMap, [&](std::pair it) -> bool { //find the specified PlayerEntry if (it.first == packet.playerInfo.playerIndex) { //send to all diff --git a/server/player_entry.cpp b/server/player_entry.cpp index 11cfdfc..3eb8777 100644 --- a/server/player_entry.cpp +++ b/server/player_entry.cpp @@ -21,4 +21,4 @@ */ #include "player_entry.hpp" -unsigned int PlayerEntry::uidCounter; +int PlayerEntry::uidCounter = 0; diff --git a/server/player_entry.hpp b/server/player_entry.hpp index 17dca99..70939e6 100644 --- a/server/player_entry.hpp +++ b/server/player_entry.hpp @@ -31,6 +31,7 @@ struct PlayerEntry { //metadata int clientIndex; + std::string player; std::string handle; std::string avatar; @@ -56,7 +57,7 @@ struct PlayerEntry { float luck; //uid - static unsigned int uidCounter; + static int uidCounter; }; #endif diff --git a/server/player_management.cpp b/server/player_management.cpp new file mode 100644 index 0000000..78ab785 --- /dev/null +++ b/server/player_management.cpp @@ -0,0 +1,46 @@ +/* Copyright: (c) Kayne Ruse 2013, 2014 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "server_application.hpp" + +//------------------------- +//player management +//------------------------- + +void ServerApplication::LoadPlayer() { + // +} + +void ServerApplication::UnloadPlayer() { + // +} + +void ServerApplication::CreatePlayer() { + // +} + +void ServerApplication::DeletePlayer() { + // +} + +void ServerApplication::SavePlayer() { + // +} diff --git a/server/server_application.hpp b/server/server_application.hpp index 2da5de1..c010dd2 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -23,7 +23,6 @@ #define SERVERAPPLICATION_HPP_ //server specific stuff -#include "server_utility.hpp" #include "client_entry.hpp" #include "player_entry.hpp" @@ -63,28 +62,33 @@ public: private: void HandlePacket(SerialPacket); - //high cohesion utility functions + //handle incoming traffic void HandleBroadcastRequest(SerialPacket); void HandleJoinRequest(SerialPacket); - void HandleDisconnect(SerialPacket); void HandleSynchronize(SerialPacket); + void HandleDisconnect(SerialPacket); void HandleShutdown(SerialPacket); - void HandlePlayerNew(SerialPacket); - void HandlePlayerDelete(SerialPacket); void HandlePlayerUpdate(SerialPacket); void HandleRegionRequest(SerialPacket); //TODO: a function that only sends to players in a certain proximity void PumpPacket(SerialPacket); + //player management + void LoadPlayer(); + void UnloadPlayer(); + void CreatePlayer(); + void DeletePlayer(); + void SavePlayer(); + //APIs UDPNetworkUtility network; sqlite3* database = nullptr; lua_State* luaState = nullptr; //server tables - std::map clientMap; - std::map playerMap; + std::map clientMap; + std::map playerMap; //maps //TODO: I need to handle multiple map objects diff --git a/server/server_internals.cpp b/server/server_internals.cpp new file mode 100644 index 0000000..21f8372 --- /dev/null +++ b/server/server_internals.cpp @@ -0,0 +1,166 @@ +/* Copyright: (c) Kayne Ruse 2014 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "server_application.hpp" + +#include "server_utility.hpp" + +#include +#include +#include + +//------------------------- +//Define the public members +//------------------------- + +void ServerApplication::Init(int argc, char** argv) { + //NOTE: I might need to rearrange the init process so that lua & SQL can interact with the map system as needed. + std::cout << "Beginning startup" << std::endl; + + //initial setup + config.Load("rsc\\config.cfg"); + + //Init SDL + if (SDL_Init(0)) { + throw(std::runtime_error("Failed to initialize SDL")); + } + std::cout << "Initialized SDL" << std::endl; + + //Init SDL_net + if (SDLNet_Init()) { + throw(std::runtime_error("Failed to initialize SDL_net")); + } + network.Open(config.Int("server.port"), PACKET_BUFFER_SIZE); + std::cout << "Initialized SDL_net" << std::endl; + + //Init SQL + int ret = sqlite3_open_v2(config["server.dbname"].c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, nullptr); + if (ret != SQLITE_OK || !database) { + throw(std::runtime_error(std::string() + "Failed to initialize SQL: " + sqlite3_errmsg(database) )); + } + std::cout << "Initialized SQL" << std::endl; + + //setup the database + if (runSQLScript(database, config["dir.scripts"] + "setup_server.sql")) { + throw(std::runtime_error("Failed to initialize SQL's setup script")); + } + std::cout << "Initialized SQL's setup script" << std::endl; + + //lua + luaState = luaL_newstate(); + if (!luaState) { + throw(std::runtime_error("Failed to initialize lua")); + } + luaL_openlibs(luaState); + std::cout << "Initialized lua" << std::endl; + + //run the startup script + if (luaL_dofile(luaState, (config["dir.scripts"] + "setup_server.lua").c_str())) { + throw(std::runtime_error(std::string() + "Failed to initialize lua's setup script: " + lua_tostring(luaState, -1) )); + } + std::cout << "Initialized lua's setup script" << std::endl; + + //setup the map object + regionPager.GetAllocator()->SetLuaState(luaState); + regionPager.GetFormat()->SetLuaState(luaState); + //TODO: config parameter + regionPager.GetFormat()->SetSaveDir("save/mapname/"); + + std::cout << "Initialized the map system" << std::endl; + std::cout << "\tsizeof(SerialPacket): " << sizeof(SerialPacket) << std::endl; + std::cout << "\tPACKET_BUFFER_SIZE: " << PACKET_BUFFER_SIZE << std::endl; + + //finalize the startup + std::cout << "Startup completed successfully" << std::endl; + + //debugging + // +} + +void ServerApplication::Proc() { + SerialPacket packet; + while(running) { + //suck in the waiting packets & process them + while(network.Receive()) { + //get the packet + deserialize(&packet, network.GetInData()); + //cache the source address + packet.meta.srcAddress = network.GetInPacket()->address; + //we need to go deeper + HandlePacket(packet); + } + //give the computer a break + SDL_Delay(10); + } +} + +void ServerApplication::Quit() { + std::cout << "Shutting down" << std::endl; + + //save the server state + //TODO: save the existing players + + //empty the members + regionPager.UnloadAll(); + + //APIs + lua_close(luaState); + sqlite3_close_v2(database); + network.Close(); + SDLNet_Quit(); + SDL_Quit(); + + std::cout << "Shutdown finished" << std::endl; +} + +//------------------------- +//Define the uber switch +//------------------------- + +void ServerApplication::HandlePacket(SerialPacket packet) { + switch(packet.meta.type) { + case SerialPacket::Type::BROADCAST_REQUEST: + HandleBroadcastRequest(packet); + break; + case SerialPacket::Type::JOIN_REQUEST: + HandleJoinRequest(packet); + break; + case SerialPacket::Type::SYNCHRONIZE: + HandleSynchronize(packet); + break; + case SerialPacket::Type::DISCONNECT: + HandleDisconnect(packet); + break; + case SerialPacket::Type::SHUTDOWN: + HandleShutdown(packet); + break; + case SerialPacket::Type::PLAYER_UPDATE: + HandlePlayerUpdate(packet); + break; + case SerialPacket::Type::REGION_REQUEST: + HandleRegionRequest(packet); + break; + //handle errors + default: + throw(std::runtime_error("Unknown SerialPacket::Type encountered")); + break; + } +} From 01b50d5590ac60de07146d60c76740b537b01490 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sat, 26 Apr 2014 02:31:48 +1000 Subject: [PATCH 05/10] I guess it was easier to compile the fragmented server than I thought --- server/networking.cpp | 150 ++++++++++++------------------------ server/server_internals.cpp | 2 + 2 files changed, 53 insertions(+), 99 deletions(-) diff --git a/server/networking.cpp b/server/networking.cpp index a981abf..c7afbc9 100644 --- a/server/networking.cpp +++ b/server/networking.cpp @@ -29,13 +29,13 @@ //------------------------- void ServerApplication::HandleBroadcastRequest(SerialPacket packet) { - //pack the data + //pack the server's data packet.meta.type = SerialPacket::Type::BROADCAST_RESPONSE; packet.serverInfo.networkVersion = NETWORK_VERSION; snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str()); packet.serverInfo.playerCount = playerMap.size(); - //send the data + //bounce this packet char buffer[PACKET_BUFFER_SIZE]; serialize(&packet, buffer); network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE); @@ -47,57 +47,32 @@ void ServerApplication::HandleJoinRequest(SerialPacket packet) { newClient.address = packet.meta.srcAddress; clientMap[ClientEntry::uidCounter] = newClient; - //create the new player - //TODO: make the player + //register the new player + PlayerEntry newPlayer; + newPlayer.clientIndex = ClientEntry::uidCounter; + newPlayer.player = packet.clientInfo.player; + newPlayer.handle = packet.clientInfo.handle; + newPlayer.avatar = packet.clientInfo.avatar; + playerMap[PlayerEntry::uidCounter] = newPlayer; //send the client their info packet.meta.type = SerialPacket::Type::JOIN_RESPONSE; - packet.clientInfo.index = ClientEntry::uidCounter; + packet.clientInfo.clientIndex = ClientEntry::uidCounter; + packet.clientInfo.playerIndex = PlayerEntry::uidCounter; //bounce this packet char buffer[PACKET_BUFFER_SIZE]; serialize(&packet, buffer); network.Send(&newClient.address, buffer, PACKET_BUFFER_SIZE); + //TODO: finish the player's initialization + //finished this routine ClientEntry::uidCounter++; + PlayerEntry::uidCounter++; std::cout << "Connect, total: " << clientMap.size() << std::endl; } -void ServerApplication::HandleDisconnect(SerialPacket packet) { - //TODO: authenticate who is disconnecting/kicking - - //disconnect the specified client - char buffer[PACKET_BUFFER_SIZE]; - serialize(&packet, buffer); - network.Send(&clientMap[packet.clientInfo.index].address, buffer, PACKET_BUFFER_SIZE); - clientMap.erase(packet.clientInfo.index); - - //prep the delete packet - SerialPacket delPacket; - delPacket.meta.type = SerialPacket::Type::PLAYER_DELETE; - - //TODO: can this use DeletePlayer() instead? - //delete server and client side players - erase_if(playerMap, [&](std::pair it) -> bool { - //find the internal players to delete - if (it.second.clientIndex == packet.clientInfo.index) { - //send the delete player command to all clients - delPacket.playerInfo.playerIndex = it.first; - PumpPacket(delPacket); - - //delete this player object - return true; - } - - //don't delete this player object - return false; - }); - - //finished this routine - std::cout << "Disconnect, total: " << clientMap.size() << std::endl; -} - void ServerApplication::HandleSynchronize(SerialPacket packet) { //TODO: compensate for large distances @@ -115,82 +90,57 @@ void ServerApplication::HandleSynchronize(SerialPacket packet) { newPacket.playerInfo.position = it.second.position; newPacket.playerInfo.motion = it.second.motion; serialize(&newPacket, buffer); - network.Send(&clientMap[packet.clientInfo.index].address, buffer, PACKET_BUFFER_SIZE); + network.Send(&clientMap[packet.clientInfo.clientIndex].address, buffer, PACKET_BUFFER_SIZE); } } -void ServerApplication::HandleShutdown(SerialPacket packet) { - //end the server - running = false; +void ServerApplication::HandleDisconnect(SerialPacket packet) { + //TODO: authenticate who is disconnecting/kicking + //TODO: define the difference between unloading and deletng a player - //disconnect all clients - packet.meta.type = SerialPacket::Type::DISCONNECT; - PumpPacket(packet); - - //finished this routine - std::cout << "Shutdown signal accepted" << std::endl; -} - -void ServerApplication::HandlePlayerNew(SerialPacket packet) { - //register the new PlayerEntry - //NOTE: assigning each field one-by-one so adding or moving a field doesn't break this code - PlayerEntry newPlayer; - - //metadata - newPlayer.clientIndex = packet.playerInfo.clientIndex; - newPlayer.handle = packet.playerInfo.handle; - newPlayer.avatar = packet.playerInfo.avatar; - - //position - newPlayer.mapIndex = 0; - newPlayer.position = {0,0}; - newPlayer.motion = {0,0}; - newPlayer.bbox = {0, 0, 0, 0}; - - //TODO: Add the statistic creation code here - - //push this player - playerMap[PlayerEntry::uidCounter] = newPlayer; - - //send the client their info - packet.playerInfo.playerIndex = PlayerEntry::uidCounter; - packet.playerInfo.position = newPlayer.position; - packet.playerInfo.motion = newPlayer.motion; - - //actually send to everyone - PumpPacket(packet); - - //finish this routine - PlayerEntry::uidCounter++; -} - -//TODO: differentiate between delete and unload -void ServerApplication::HandlePlayerDelete(SerialPacket packet) { - //TODO: authenticate who is deleting this player - if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) { - throw(std::runtime_error("Cannot delete a non-existant player")); - } - - //TODO: remove the deleted player from the database? + //disconnect the specified client + char buffer[PACKET_BUFFER_SIZE]; + serialize(&packet, buffer); + network.Send(&clientMap[packet.clientInfo.clientIndex].address, buffer, PACKET_BUFFER_SIZE); + clientMap.erase(packet.clientInfo.clientIndex); //prep the delete packet SerialPacket delPacket; delPacket.meta.type = SerialPacket::Type::PLAYER_DELETE; - //delete the specified playerEntry + //delete server and client side players erase_if(playerMap, [&](std::pair it) -> bool { - //find the specified PlayerEntry - if (it.first == packet.playerInfo.playerIndex) { - //send to all + //find the internal players to delete + if (it.second.clientIndex == packet.clientInfo.clientIndex) { + //send the delete player command to all clients delPacket.playerInfo.playerIndex = it.first; PumpPacket(delPacket); - //delete this player + //delete this player object return true; } - //skip this player + + //don't delete this player object return false; }); + + //finished this routine + std::cout << "Disconnect, total: " << clientMap.size() << std::endl; +} + +void ServerApplication::HandleShutdown(SerialPacket packet) { + //TODO: authenticate who is shitting the server down + + //end the server + running = false; + + //disconnect all clients + packet.meta.type = SerialPacket::Type::DISCONNECT; + packet.clientInfo.clientIndex = -1; + PumpPacket(packet); + + //finished this routine + std::cout << "Shutdown signal accepted" << std::endl; } void ServerApplication::HandlePlayerUpdate(SerialPacket packet) { @@ -206,9 +156,11 @@ void ServerApplication::HandlePlayerUpdate(SerialPacket packet) { } void ServerApplication::HandleRegionRequest(SerialPacket packet) { - char buffer[PACKET_BUFFER_SIZE]; packet.meta.type = SerialPacket::Type::REGION_CONTENT; packet.regionInfo.region = regionPager.GetRegion(packet.regionInfo.x, packet.regionInfo.y); + + //send the content + char buffer[PACKET_BUFFER_SIZE]; serialize(&packet, buffer); network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE); } diff --git a/server/server_internals.cpp b/server/server_internals.cpp index 21f8372..e1a9cb9 100644 --- a/server/server_internals.cpp +++ b/server/server_internals.cpp @@ -107,6 +107,8 @@ void ServerApplication::Proc() { //we need to go deeper HandlePacket(packet); } + //update the internals + //TODO: update the internals i.e. player positions //give the computer a break SDL_Delay(10); } From 9ec1ddab99c43efa5fd5b6e3b77d51aa80448c40 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sat, 26 Apr 2014 02:48:15 +1000 Subject: [PATCH 06/10] Exceptions are being thrown; retiring for the night I don't know what's causing these issues, so I'm leaving it for tonight. --- client/scenes/in_world.cpp | 3 ++- common/network/serial_packet.hpp | 1 + server/{networking.cpp => server_networking.cpp} | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) rename server/{networking.cpp => server_networking.cpp} (99%) diff --git a/client/scenes/in_world.cpp b/client/scenes/in_world.cpp index fc1bdde..7e3805d 100644 --- a/client/scenes/in_world.cpp +++ b/client/scenes/in_world.cpp @@ -287,7 +287,8 @@ void InWorld::HandleRegionContent(SerialPacket packet) { void InWorld::HandlePlayerUpdate(SerialPacket packet) { if (playerCharacters.find(packet.playerInfo.playerIndex) == playerCharacters.end()) { - throw(std::runtime_error("Cannot update nen-existant players")); + HandlePlayerNew(packet); + return; } //update only if the message didn't originate from here diff --git a/common/network/serial_packet.hpp b/common/network/serial_packet.hpp index ff4fb8c..12574f7 100644 --- a/common/network/serial_packet.hpp +++ b/common/network/serial_packet.hpp @@ -110,6 +110,7 @@ union SerialPacket { int playerIndex; char handle[PACKET_STRING_SIZE]; char avatar[PACKET_STRING_SIZE]; + int mapIndex; Vector2 position; Vector2 motion; }playerInfo; diff --git a/server/networking.cpp b/server/server_networking.cpp similarity index 99% rename from server/networking.cpp rename to server/server_networking.cpp index c7afbc9..c206077 100644 --- a/server/networking.cpp +++ b/server/server_networking.cpp @@ -87,6 +87,7 @@ void ServerApplication::HandleSynchronize(SerialPacket packet) { newPacket.playerInfo.playerIndex = it.first; snprintf(newPacket.playerInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str()); snprintf(newPacket.playerInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str()); + newPacket.playerInfo.mapIndex = it.second.mapIndex; newPacket.playerInfo.position = it.second.position; newPacket.playerInfo.motion = it.second.motion; serialize(&newPacket, buffer); From fa9487c2f28b6fd5be7d348c43141a549a0747a5 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 27 Apr 2014 02:37:20 +1000 Subject: [PATCH 07/10] Fixed the previous bug (read more) The bug was being caused by not assigning default values to the player objects' internals. I've added a quick fix to these structs, but I think it's best to expand them into proper classes now. --- server/client_entry.hpp | 2 +- server/player_entry.hpp | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/server/client_entry.hpp b/server/client_entry.hpp index 7e5dc90..6e6b6a3 100644 --- a/server/client_entry.hpp +++ b/server/client_entry.hpp @@ -25,7 +25,7 @@ #include "SDL/SDL_net.h" struct ClientEntry { - IPaddress address; + IPaddress address = {0,0}; static int uidCounter; }; diff --git a/server/player_entry.hpp b/server/player_entry.hpp index 70939e6..a55c603 100644 --- a/server/player_entry.hpp +++ b/server/player_entry.hpp @@ -36,25 +36,25 @@ struct PlayerEntry { std::string avatar; //world position - int mapIndex; - Vector2 position; - Vector2 motion; - BBox bbox; + int mapIndex = 0; + Vector2 position = {0.0,0.0}; + Vector2 motion = {0.0,0.0}; + BBox bbox = {0,0,0,0}; //statistics - int level; - int exp; - int maxHP; - int health; - int maxMP; - int mana; - int attack; - int defence; - int intelligence; - int resistance; - float accuracy; - float evasion; - float luck; + 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; + float accuracy = 0.0; + float evasion = 0.0; + float luck = 0.0; //uid static int uidCounter; From 9a7f7b8684b1b934d6443a4c61fb0558f9818106 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 27 Apr 2014 03:55:44 +1000 Subject: [PATCH 08/10] Rewrote the TODO list --- todo.txt | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/todo.txt b/todo.txt index 1b1ce42..7a6eb10 100644 --- a/todo.txt +++ b/todo.txt @@ -1,25 +1,33 @@ Please note that due to modificatons, the indicated line may be incorrect. ## TODO +server_application.hpp:74 a function that only sends to players in a certain proximity +server_application.hpp:94 I need to handle multiple map objects +server_application.hpp:95 Unload regions that are distant from any players +server_internals.cpp:84 config parameter +server_internals.cpp:111 update the internals i.e. player positions +server_internals.cpp:121 save the existing players +server_networking.cpp:68 finish the player's initialization +server_networking.cpp:77 compensate for large distances +server_networking.cpp:86 update this for the expanded PlayerEntry structure +server_networking.cpp:99 authenticate who is disconnecting/kicking +server_networking.cpp:100 define the difference between unloading and deletng a player +server_networking.cpp:133 authenticate who is shitting the server down +server_networking.cpp:152 the server needs it's own movement system too player_character.hpp:28 correct the PlayerCharacter class and it's movement system -in_world.cpp:65 the login system needs an overhaul -in_world.cpp:405 convert this into a more generic function?; using parameters for the bounds -lobby_menu.cpp:95 I need a proper UI system for the entire client and the editor -lobby_menu.cpp:101 draw headers for the server list -lobby_menu.cpp:158 The player login information should be collected by the lobby screen +in_world.cpp:62 add the tilesheet to the map system? +in_world.cpp:104 sort the players and entities by Y position +in_world.cpp:280 account for map index +in_world.cpp:307 set the handle +in_world.cpp:398 convert this into a more generic function?; using parameters for the bounds +in_world.hpp:108 Fix the camera +lobby_menu.cpp:96 I need a proper UI system for the entire client and the editor +lobby_menu.cpp:102 draw headers for the server list +lobby_menu.cpp:122 ping? +bbox.hpp:29 This is supposed to interact with the vector region_pager.hpp:49 delete existing regions -serial_packet.hpp:93 login credentials -serial_packet.hpp:104 should move handle/avatar into clientInfo; these might actually do better during the login system -server_application.cpp:86 config parameter -server_application.cpp:214 authenticate who is disconnecting/kicking -server_application.cpp:226 can this use DeletePlayer() instead? -server_application.cpp:248 compensate for large distances -server_application.cpp:257 update this for the expanded PlayerEntry structure -server_application.cpp:296 Add the statistic creation code here -server_application.cpp:313 differentiate between delete and unload -server_application.cpp:315 authenticate who is deleting this player -server_application.cpp:320 remove the deleted player from the database? -server_application.cpp:347 the server needs it's own movement system too -server_application.hpp:77 a function that only sends to players in a certain proximity -server_application.hpp:90 I need to handle multiple map objects -server_application.hpp:91 Unload regions that are distant from any players +serial_packet.hpp:71 combat packets +setup_server.sql:1 The SQL startup script needs revising + +Move PlayerEntry into a proper class +Move ClientEntry into a proper class From 624369f1471b85adce92c5da0a058fff1a67db7c Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 27 Apr 2014 22:17:58 +1000 Subject: [PATCH 09/10] Discovered a bug --- server/player_management.cpp | 46 ------------------- server/server_application.hpp | 8 +--- ..._networking.cpp => server_connections.cpp} | 7 ++- todo.txt | 6 +-- 4 files changed, 10 insertions(+), 57 deletions(-) delete mode 100644 server/player_management.cpp rename server/{server_networking.cpp => server_connections.cpp} (95%) diff --git a/server/player_management.cpp b/server/player_management.cpp deleted file mode 100644 index 78ab785..0000000 --- a/server/player_management.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright: (c) Kayne Ruse 2013, 2014 - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. -*/ -#include "server_application.hpp" - -//------------------------- -//player management -//------------------------- - -void ServerApplication::LoadPlayer() { - // -} - -void ServerApplication::UnloadPlayer() { - // -} - -void ServerApplication::CreatePlayer() { - // -} - -void ServerApplication::DeletePlayer() { - // -} - -void ServerApplication::SavePlayer() { - // -} diff --git a/server/server_application.hpp b/server/server_application.hpp index c010dd2..cd6d4ac 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -74,12 +74,8 @@ private: //TODO: a function that only sends to players in a certain proximity void PumpPacket(SerialPacket); - //player management - void LoadPlayer(); - void UnloadPlayer(); - void CreatePlayer(); - void DeletePlayer(); - void SavePlayer(); + //TODO: manage the database + //TODO: combat systems //APIs UDPNetworkUtility network; diff --git a/server/server_networking.cpp b/server/server_connections.cpp similarity index 95% rename from server/server_networking.cpp rename to server/server_connections.cpp index c206077..35f54a9 100644 --- a/server/server_networking.cpp +++ b/server/server_connections.cpp @@ -47,6 +47,7 @@ void ServerApplication::HandleJoinRequest(SerialPacket packet) { newClient.address = packet.meta.srcAddress; clientMap[ClientEntry::uidCounter] = newClient; + //TODO: move this into the player management code //register the new player PlayerEntry newPlayer; newPlayer.clientIndex = ClientEntry::uidCounter; @@ -65,7 +66,7 @@ void ServerApplication::HandleJoinRequest(SerialPacket packet) { serialize(&packet, buffer); network.Send(&newClient.address, buffer, PACKET_BUFFER_SIZE); - //TODO: finish the player's initialization + //BUG: the new player object is not being sent to existing clients //finished this routine ClientEntry::uidCounter++; @@ -130,7 +131,7 @@ void ServerApplication::HandleDisconnect(SerialPacket packet) { } void ServerApplication::HandleShutdown(SerialPacket packet) { - //TODO: authenticate who is shitting the server down + //TODO: authenticate who is shutting the server down //end the server running = false; @@ -145,6 +146,7 @@ void ServerApplication::HandleShutdown(SerialPacket packet) { } void ServerApplication::HandlePlayerUpdate(SerialPacket packet) { + //TODO: this should be moved elsewhere if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) { throw(std::runtime_error("Cannot update a non-existant player")); } @@ -157,6 +159,7 @@ void ServerApplication::HandlePlayerUpdate(SerialPacket packet) { } void ServerApplication::HandleRegionRequest(SerialPacket packet) { + //TODO: this should be moved elsewhere packet.meta.type = SerialPacket::Type::REGION_CONTENT; packet.regionInfo.region = regionPager.GetRegion(packet.regionInfo.x, packet.regionInfo.y); diff --git a/todo.txt b/todo.txt index 7a6eb10..0ad57c6 100644 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,8 @@ Please note that due to modificatons, the indicated line may be incorrect. +## BUG +1. server_connections.cpp:68 the new player object is not being sent to existing clients + ## TODO server_application.hpp:74 a function that only sends to players in a certain proximity server_application.hpp:94 I need to handle multiple map objects @@ -28,6 +31,3 @@ bbox.hpp:29 This is supposed to interact with the vector region_pager.hpp:49 delete existing regions serial_packet.hpp:71 combat packets setup_server.sql:1 The SQL startup script needs revising - -Move PlayerEntry into a proper class -Move ClientEntry into a proper class From 5031352fe319c765ec7103a49df4900cee6ff4f3 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Tue, 29 Apr 2014 01:34:52 +1000 Subject: [PATCH 10/10] Fixed the bug (read more) The bug was being caused by a lack of a new player object being sent to some clients. Fixed this by adding in the sending code, and preventing the new entries being "registered" until the end of the HandleJoinRequest() method. Hopefully I can simply abstract away some of this code soon. --- server/server_connections.cpp | 17 ++++++++++++----- todo.txt | 3 --- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/server/server_connections.cpp b/server/server_connections.cpp index 35f54a9..2f35566 100644 --- a/server/server_connections.cpp +++ b/server/server_connections.cpp @@ -42,19 +42,17 @@ void ServerApplication::HandleBroadcastRequest(SerialPacket packet) { } void ServerApplication::HandleJoinRequest(SerialPacket packet) { - //register the new client + //create the new client ClientEntry newClient; newClient.address = packet.meta.srcAddress; - clientMap[ClientEntry::uidCounter] = newClient; //TODO: move this into the player management code - //register the new player + //create the new player PlayerEntry newPlayer; newPlayer.clientIndex = ClientEntry::uidCounter; newPlayer.player = packet.clientInfo.player; newPlayer.handle = packet.clientInfo.handle; newPlayer.avatar = packet.clientInfo.avatar; - playerMap[PlayerEntry::uidCounter] = newPlayer; //send the client their info packet.meta.type = SerialPacket::Type::JOIN_RESPONSE; @@ -66,9 +64,18 @@ void ServerApplication::HandleJoinRequest(SerialPacket packet) { serialize(&packet, buffer); network.Send(&newClient.address, buffer, PACKET_BUFFER_SIZE); - //BUG: the new player object is not being sent to existing clients + //send the new player to all clients + packet.meta.type = SerialPacket::Type::PLAYER_NEW; + packet.playerInfo.playerIndex = PlayerEntry::uidCounter; + strncpy(packet.playerInfo.handle, newPlayer.handle.c_str(), PACKET_STRING_SIZE); + strncpy(packet.playerInfo.avatar, newPlayer.avatar.c_str(), PACKET_STRING_SIZE); + packet.playerInfo.position = newPlayer.position; + packet.playerInfo.motion = newPlayer.motion; + PumpPacket(packet); //finished this routine + clientMap[ClientEntry::uidCounter] = newClient; + playerMap[PlayerEntry::uidCounter] = newPlayer; ClientEntry::uidCounter++; PlayerEntry::uidCounter++; std::cout << "Connect, total: " << clientMap.size() << std::endl; diff --git a/todo.txt b/todo.txt index 0ad57c6..8f42fcd 100644 --- a/todo.txt +++ b/todo.txt @@ -1,8 +1,5 @@ Please note that due to modificatons, the indicated line may be incorrect. -## BUG -1. server_connections.cpp:68 the new player object is not being sent to existing clients - ## TODO server_application.hpp:74 a function that only sends to players in a certain proximity server_application.hpp:94 I need to handle multiple map objects