395 lines
13 KiB
Diff
395 lines
13 KiB
Diff
diff --git a/server/server_connections.cpp b/server/server_connections.cpp
|
|
index 1a96d5b..2f35566 100644
|
|
--- a/server/server_connections.cpp
|
|
+++ b/server/server_connections.cpp
|
|
@@ -21,212 +21,106 @@
|
|
*/
|
|
#include "server_application.hpp"
|
|
|
|
-#include "utility.hpp"
|
|
-
|
|
#include <stdexcept>
|
|
#include <iostream>
|
|
-#include <string>
|
|
-
|
|
-//-------------------------
|
|
-//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
|
|
+ //pack the server's data
|
|
packet.meta.type = SerialPacket::Type::BROADCAST_RESPONSE;
|
|
-
|
|
- //pack the data
|
|
+ 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
|
|
+ //bounce this packet
|
|
char buffer[PACKET_BUFFER_SIZE];
|
|
serialize(&packet, buffer);
|
|
network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE);
|
|
}
|
|
|
|
void ServerApplication::HandleJoinRequest(SerialPacket packet) {
|
|
- //register the new client
|
|
+ //create the new client
|
|
ClientEntry newClient;
|
|
newClient.address = packet.meta.srcAddress;
|
|
- clientMap[ClientEntry::uidCounter] = newClient;
|
|
|
|
- //send the client their index
|
|
- char buffer[PACKET_BUFFER_SIZE];
|
|
+ //TODO: move this into the player management code
|
|
+ //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;
|
|
+
|
|
+ //send the client their info
|
|
packet.meta.type = SerialPacket::Type::JOIN_RESPONSE;
|
|
- packet.clientInfo.index = ClientEntry::uidCounter;
|
|
- serialize(&packet, buffer);
|
|
+ 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);
|
|
|
|
+ //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;
|
|
}
|
|
|
|
+void ServerApplication::HandleSynchronize(SerialPacket packet) {
|
|
+ //TODO: compensate for large distances
|
|
+
|
|
+ //send all the server's data to this client
|
|
+ SerialPacket newPacket;
|
|
+ char buffer[PACKET_BUFFER_SIZE];
|
|
+
|
|
+ //players
|
|
+ newPacket.meta.type = SerialPacket::Type::PLAYER_UPDATE;
|
|
+ for (auto& it : playerMap) {
|
|
+ //TODO: update this for the expanded PlayerEntry structure
|
|
+ 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);
|
|
+ network.Send(&clientMap[packet.clientInfo.clientIndex].address, buffer, PACKET_BUFFER_SIZE);
|
|
+ }
|
|
+}
|
|
+
|
|
void ServerApplication::HandleDisconnect(SerialPacket packet) {
|
|
//TODO: authenticate who is disconnecting/kicking
|
|
+ //TODO: define the difference between unloading and deletng a player
|
|
|
|
//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);
|
|
+ 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;
|
|
|
|
- //TODO: can this use DeletePlayer() instead?
|
|
//delete server and client side players
|
|
- erase_if(playerMap, [&](std::pair<unsigned int, PlayerEntry> it) -> bool {
|
|
+ erase_if(playerMap, [&](std::pair<int, PlayerEntry> it) -> bool {
|
|
//find the internal players to delete
|
|
- if (it.second.clientIndex == packet.clientInfo.index) {
|
|
+ if (it.second.clientIndex == packet.clientInfo.clientIndex) {
|
|
//send the delete player command to all clients
|
|
delPacket.playerInfo.playerIndex = it.first;
|
|
PumpPacket(delPacket);
|
|
@@ -243,102 +137,23 @@ void ServerApplication::HandleDisconnect(SerialPacket packet) {
|
|
std::cout << "Disconnect, total: " << clientMap.size() << std::endl;
|
|
}
|
|
|
|
-void ServerApplication::HandleSynchronize(SerialPacket packet) {
|
|
- //TODO: compensate for large distances
|
|
-
|
|
- //send all the server's data to this client
|
|
- SerialPacket newPacket;
|
|
- char buffer[PACKET_BUFFER_SIZE];
|
|
-
|
|
- //players
|
|
- newPacket.meta.type = SerialPacket::Type::PLAYER_UPDATE;
|
|
- for (auto& it : playerMap) {
|
|
- //TODO: update this for the expanded PlayerEntry structure
|
|
- 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.position = it.second.position;
|
|
- newPacket.playerInfo.motion = it.second.motion;
|
|
- serialize(&newPacket, buffer);
|
|
- network.Send(&clientMap[packet.clientInfo.index].address, buffer, PACKET_BUFFER_SIZE);
|
|
- }
|
|
-}
|
|
-
|
|
void ServerApplication::HandleShutdown(SerialPacket packet) {
|
|
+ //TODO: authenticate who is shutting 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::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?
|
|
-
|
|
- //prep the delete packet
|
|
- SerialPacket delPacket;
|
|
- delPacket.meta.type = SerialPacket::Type::PLAYER_DELETE;
|
|
-
|
|
- //delete the specified playerEntry
|
|
- erase_if(playerMap, [&](std::pair<unsigned int, PlayerEntry> it) -> bool {
|
|
- //find the specified PlayerEntry
|
|
- if (it.first == packet.playerInfo.playerIndex) {
|
|
- //send to all
|
|
- delPacket.playerInfo.playerIndex = it.first;
|
|
- PumpPacket(delPacket);
|
|
-
|
|
- //delete this player
|
|
- return true;
|
|
- }
|
|
- //skip this player
|
|
- return false;
|
|
- });
|
|
-}
|
|
-
|
|
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"));
|
|
}
|
|
@@ -351,9 +166,12 @@ void ServerApplication::HandlePlayerUpdate(SerialPacket packet) {
|
|
}
|
|
|
|
void ServerApplication::HandleRegionRequest(SerialPacket packet) {
|
|
- char buffer[PACKET_BUFFER_SIZE];
|
|
+ //TODO: this should be moved elsewhere
|
|
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);
|
|
}
|