diff --git a/client/client_application.cpp b/client/client_application.cpp index 73a0ba1..297a903 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, &characterIndex); + activeScene = new LobbyMenu(&config, &network, &clientIndex, &accountIndex, &characterIndex); break; case SceneList::INWORLD: - activeScene = new InWorld(&config, &network, &clientIndex, &characterIndex); + activeScene = new InWorld(&config, &network, &clientIndex, &accountIndex, &characterIndex); break; case SceneList::INCOMBAT: activeScene = new InCombat(); diff --git a/client/client_application.hpp b/client/client_application.hpp index daf2c16..b6b3b31 100644 --- a/client/client_application.hpp +++ b/client/client_application.hpp @@ -48,6 +48,7 @@ private: ConfigUtility config; UDPNetworkUtility network; int clientIndex = -1; + int accountIndex = -1; int characterIndex = -1; }; diff --git a/client/scenes/in_world.cpp b/client/scenes/in_world.cpp index 6d43e9d..1f4538b 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, int* const argCharacterIndex): +InWorld::InWorld(ConfigUtility* const argConfig, UDPNetworkUtility* const argNetwork, int* const argClientIndex, int* const argAccountIndex, int* const argCharacterIndex): config(*argConfig), network(*argNetwork), clientIndex(*argClientIndex), + accountIndex(*argAccountIndex), characterIndex(*argCharacterIndex) { //setup the utility objects @@ -62,11 +63,13 @@ 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); + //TODO: move this into it's own function //request a sync SerialPacket packet; char buffer[PACKET_STRING_SIZE]; packet.meta.type = SerialPacket::Type::SYNCHRONIZE; packet.clientInfo.clientIndex = clientIndex; + packet.clientInfo.accountIndex = accountIndex; packet.clientInfo.characterIndex = characterIndex; serialize(&packet, buffer); network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE); @@ -263,7 +266,7 @@ void InWorld::HandlePacket(SerialPacket packet) { break; //handle errors default: - throw(std::runtime_error("Unknown SerialPacket::Type encountered")); + throw(std::runtime_error(std::string() + "Unknown SerialPacket::Type encountered in InWorld: " + to_string_custom(int(packet.meta.type)))); break; } } @@ -271,6 +274,7 @@ void InWorld::HandlePacket(SerialPacket packet) { void InWorld::HandleDisconnect(SerialPacket packet) { network.Unbind(Channels::SERVER); clientIndex = -1; + accountIndex = -1; characterIndex = -1; SetNextScene(SceneList::MAINMENU); } @@ -323,6 +327,7 @@ void InWorld::HandleCharacterNew(SerialPacket packet) { } void InWorld::HandleCharacterDelete(SerialPacket packet) { + //TODO: authenticate if (playerCharacters.find(packet.characterInfo.characterIndex) == playerCharacters.end()) { throw(std::runtime_error("Cannot delete non-existant characters")); } @@ -347,6 +352,7 @@ void InWorld::SendPlayerUpdate() { //pack the packet packet.meta.type = SerialPacket::Type::CHARACTER_UPDATE; packet.characterInfo.clientIndex = clientIndex; + packet.characterInfo.accountIndex = accountIndex; packet.characterInfo.characterIndex = characterIndex; packet.characterInfo.position = localCharacter->GetPosition(); packet.characterInfo.motion = localCharacter->GetMotion(); @@ -361,7 +367,7 @@ void InWorld::RequestDisconnect() { //send a disconnect request packet.meta.type = SerialPacket::Type::DISCONNECT; - packet.clientInfo.clientIndex = clientIndex; + packet.clientInfo.accountIndex = accountIndex; serialize(&packet, buffer); network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE); } @@ -372,7 +378,7 @@ void InWorld::RequestShutDown() { //send a shutdown request packet.meta.type = SerialPacket::Type::SHUTDOWN; - packet.clientInfo.clientIndex = clientIndex; + packet.clientInfo.accountIndex = accountIndex; serialize(&packet, buffer); network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE); } diff --git a/client/scenes/in_world.hpp b/client/scenes/in_world.hpp index 3a9088e..0b30f5f 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, int* const); + InWorld(ConfigUtility* const, UDPNetworkUtility* const, int* const, int* const, int* const); ~InWorld(); protected: @@ -92,6 +92,7 @@ protected: ConfigUtility& config; UDPNetworkUtility& network; int& clientIndex; + int& accountIndex; int& characterIndex; //graphics diff --git a/client/scenes/lobby_menu.cpp b/client/scenes/lobby_menu.cpp index bd92038..cd5a50d 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, int* const argCharacterIndex): +LobbyMenu::LobbyMenu(ConfigUtility* const argConfig, UDPNetworkUtility* const argNetwork, int* const argClientIndex, int* const argAccountIndex, int* const argCharacterIndex): config(*argConfig), network(*argNetwork), clientIndex(*argClientIndex), + accountIndex(*argAccountIndex), characterIndex(*argCharacterIndex) { //setup the utility objects @@ -221,6 +222,7 @@ void LobbyMenu::HandlePacket(SerialPacket packet) { break; case SerialPacket::Type::JOIN_RESPONSE: clientIndex = packet.clientInfo.clientIndex; + accountIndex = packet.clientInfo.accountIndex; characterIndex = packet.clientInfo.characterIndex; network.Bind(&packet.meta.srcAddress, Channels::SERVER); SetNextScene(SceneList::INWORLD); @@ -228,7 +230,7 @@ void LobbyMenu::HandlePacket(SerialPacket packet) { //handle errors default: - throw(std::runtime_error("Unknown SerialPacket::Type encountered")); + throw(std::runtime_error(std::string() + "Unknown SerialPacket::Type encountered in LobbyMenu: " + to_string_custom(int(packet.meta.type)))); break; } } \ No newline at end of file diff --git a/client/scenes/lobby_menu.hpp b/client/scenes/lobby_menu.hpp index a74f3db..7b6c8a9 100644 --- a/client/scenes/lobby_menu.hpp +++ b/client/scenes/lobby_menu.hpp @@ -42,7 +42,7 @@ class LobbyMenu : public BaseScene { public: //Public access members - LobbyMenu(ConfigUtility* const, UDPNetworkUtility* const, int* const, int* const); + LobbyMenu(ConfigUtility* const, UDPNetworkUtility* const, int* const, int* const, int* const); ~LobbyMenu(); protected: @@ -65,6 +65,7 @@ protected: ConfigUtility& config; UDPNetworkUtility& network; int& clientIndex; + int& accountIndex; int& characterIndex; //members diff --git a/common/network/serial.cpp b/common/network/serial.cpp index 7df8793..af527ef 100644 --- a/common/network/serial.cpp +++ b/common/network/serial.cpp @@ -54,6 +54,7 @@ void serializeClient(SerialPacket* packet, char* buffer) { //indexes SERIALIZE(buffer, &packet->clientInfo.clientIndex, sizeof(int)); + SERIALIZE(buffer, &packet->clientInfo.accountIndex, sizeof(int)); SERIALIZE(buffer, &packet->clientInfo.characterIndex, sizeof(int)); //texts @@ -95,6 +96,7 @@ void serializeCharacter(SerialPacket* packet, char* buffer) { //indexes SERIALIZE(buffer, &packet->characterInfo.clientIndex, sizeof(int)); + SERIALIZE(buffer, &packet->characterInfo.accountIndex, sizeof(int)); SERIALIZE(buffer, &packet->characterInfo.characterIndex, sizeof(int)); //texts @@ -130,6 +132,7 @@ void deserializeClient(SerialPacket* packet, char* buffer) { //indexes DESERIALIZE(buffer, &packet->clientInfo.clientIndex, sizeof(int)); + DESERIALIZE(buffer, &packet->clientInfo.accountIndex, sizeof(int)); DESERIALIZE(buffer, &packet->clientInfo.characterIndex, sizeof(int)); //texts @@ -178,6 +181,7 @@ void deserializeCharacter(SerialPacket* packet, char* buffer) { //indexes DESERIALIZE(buffer, &packet->characterInfo.clientIndex, sizeof(int)); + DESERIALIZE(buffer, &packet->characterInfo.accountIndex, sizeof(int)); DESERIALIZE(buffer, &packet->characterInfo.characterIndex, sizeof(int)); //texts diff --git a/common/network/serial_packet.hpp b/common/network/serial_packet.hpp index 7da184a..29f4af1 100644 --- a/common/network/serial_packet.hpp +++ b/common/network/serial_packet.hpp @@ -27,7 +27,7 @@ #include "SDL/SDL_net.h" -#define NETWORK_VERSION 20140428 +#define NETWORK_VERSION 20140506 #define PACKET_STRING_SIZE 100 #pragma pack(push, 0) @@ -88,8 +88,8 @@ union SerialPacket { //information about the client struct ClientInformation { Metadata meta; - //TODO: change clientIndex to accountIndex for player ID int clientIndex; + int accountIndex; int characterIndex; char username[PACKET_STRING_SIZE]; char handle[PACKET_STRING_SIZE]; @@ -108,6 +108,7 @@ union SerialPacket { struct CharacterInformation { Metadata meta; int clientIndex; + int accountIndex; int characterIndex; char handle[PACKET_STRING_SIZE]; char avatar[PACKET_STRING_SIZE]; diff --git a/server/account_data.hpp b/server/account_data.hpp index 220d831..f439c61 100644 --- a/server/account_data.hpp +++ b/server/account_data.hpp @@ -26,11 +26,12 @@ struct AccountData { std::string username; - //password + //TODO: password bool blackListed = false; bool whiteListed = true; int clientIndex; + int characterIndex; }; #endif diff --git a/server/character_data.hpp b/server/character_data.hpp index 3a12f36..dc94e7d 100644 --- a/server/character_data.hpp +++ b/server/character_data.hpp @@ -30,7 +30,6 @@ struct CharacterData { //metadata - int clientIndex; std::string handle; std::string avatar; diff --git a/server/server_application.hpp b/server/server_application.hpp index ea58017..d8e8589 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -77,8 +77,8 @@ private: void PumpPacket(SerialPacket); //Account management - int CreateUserAccount(std::string username, int clientIndex); - int LoadUserAccount(std::string username, int clientIndex); + int CreateUserAccount(std::string username, int clientIndex, int characterIndex); + int LoadUserAccount(std::string username, int clientIndex, int characterIndex); int SaveUserAccount(int uid); void UnloadUserAccount(int uid); void DeleteUserAccount(int uid); diff --git a/server/server_connections.cpp b/server/server_connections.cpp index 3d1387b..0d8eead 100644 --- a/server/server_connections.cpp +++ b/server/server_connections.cpp @@ -42,27 +42,28 @@ void ServerApplication::HandleBroadcastRequest(SerialPacket packet) { } void ServerApplication::HandleJoinRequest(SerialPacket packet) { + //load the user account + int accountIndex = LoadUserAccount(packet.clientInfo.username, ClientData::uidCounter, CharacterData::uidCounter); + if (accountIndex < 0) { + //TODO: send rejection packet + std::cerr << "Error: Account already loaded: " << accountIndex << std::endl; + return; + } + //create the new client ClientData newClient; newClient.address = packet.meta.srcAddress; - //load the user account - int uid = LoadUserAccount(packet.clientInfo.username, ClientData::uidCounter); - if (uid < 0) { - std::cerr << "Error: Account already loaded: " << uid << std::endl; - return; - } - //TODO: move this into the character management code //create the new character CharacterData newCharacter; - newCharacter.clientIndex = ClientData::uidCounter; newCharacter.handle = packet.clientInfo.handle; newCharacter.avatar = packet.clientInfo.avatar; //send the client their info packet.meta.type = SerialPacket::Type::JOIN_RESPONSE; packet.clientInfo.clientIndex = ClientData::uidCounter; + packet.clientInfo.accountIndex = accountIndex; packet.clientInfo.characterIndex = CharacterData::uidCounter; //bounce this packet @@ -79,11 +80,10 @@ void ServerApplication::HandleJoinRequest(SerialPacket packet) { packet.characterInfo.motion = newCharacter.motion; PumpPacket(packet); + //TODO: don't send anything to a certain client until they send the OK (the sync packet? or ignore client side?) //finished this routine - clientMap[ClientData::uidCounter] = newClient; - characterMap[CharacterData::uidCounter] = newCharacter; - ClientData::uidCounter++; - CharacterData::uidCounter++; + clientMap[ClientData::uidCounter++] = newClient; + characterMap[CharacterData::uidCounter++] = newCharacter; std::cout << "Connect, total: " << clientMap.size() << std::endl; } @@ -113,43 +113,24 @@ void ServerApplication::HandleDisconnect(SerialPacket packet) { //TODO: authenticate who is disconnecting/kicking //TODO: define the difference between unloading and deletng a character - //disconnect the specified client + //forward to 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); + network.Send(&clientMap[accountMap[packet.clientInfo.accountIndex].clientIndex].address, buffer, PACKET_BUFFER_SIZE); - //unload the client's account - //TODO: change clientIndex to accountIndex for player ID - for (auto it : accountMap) { - if (it.second.clientIndex == packet.clientInfo.clientIndex) { - UnloadUserAccount(it.first); - break; - } - } - - //prep the delete packet + //delete the client side character SerialPacket delPacket; delPacket.meta.type = SerialPacket::Type::CHARACTER_DELETE; + delPacket.characterInfo.characterIndex = accountMap[packet.clientInfo.accountIndex].characterIndex; + PumpPacket(delPacket); - //delete server and client side characters - erase_if(characterMap, [&](std::pair it) -> bool { - //find the internal characters to delete - if (it.second.clientIndex == packet.clientInfo.clientIndex) { - //send the delete characters command to all clients - delPacket.characterInfo.characterIndex = it.first; - PumpPacket(delPacket); - - //delete this characters object - return true; - } - - //don't delete this characters object - return false; - }); + //erase the in-memory stuff + clientMap.erase(accountMap[packet.clientInfo.accountIndex].clientIndex); + characterMap.erase(accountMap[packet.clientInfo.accountIndex].characterIndex); + UnloadUserAccount(packet.clientInfo.accountIndex); //finished this routine - std::cout << "Disconnect, total: " << clientMap.size() << std::endl; + std::cout << "Disconnect, total: " << accountMap.size() << std::endl; } void ServerApplication::HandleShutdown(SerialPacket packet) { @@ -160,7 +141,6 @@ void ServerApplication::HandleShutdown(SerialPacket packet) { //disconnect all clients packet.meta.type = SerialPacket::Type::DISCONNECT; - packet.clientInfo.clientIndex = -1; PumpPacket(packet); //finished this routine diff --git a/server/server_database.cpp b/server/server_database.cpp index 4f34947..87fbbdd 100644 --- a/server/server_database.cpp +++ b/server/server_database.cpp @@ -38,7 +38,7 @@ static const char* DELETE_USER_ACCOUNT = "DELETE FROM UserAccounts WHERE uid = ? //Define the methods //------------------------- -int ServerApplication::CreateUserAccount(std::string username, int clientIndex) { +int ServerApplication::CreateUserAccount(std::string username, int clientIndex, int characterIndex) { //create this user account, failing if it exists, leave this account in memory sqlite3_stmt* statement = nullptr; @@ -62,10 +62,10 @@ int ServerApplication::CreateUserAccount(std::string username, int clientIndex) sqlite3_finalize(statement); //load this account into memory - return LoadUserAccount(username, clientIndex); + return LoadUserAccount(username, clientIndex, characterIndex); } -int ServerApplication::LoadUserAccount(std::string username, int clientIndex) { +int ServerApplication::LoadUserAccount(std::string username, int clientIndex, int characterIndex) { //load this user account, failing if it is in memory, creating it if it doesn't exist sqlite3_stmt* statement = nullptr; @@ -99,6 +99,7 @@ int ServerApplication::LoadUserAccount(std::string username, int clientIndex) { newAccount.blackListed = sqlite3_column_int(statement, 2); newAccount.whiteListed = sqlite3_column_int(statement, 3); newAccount.clientIndex = clientIndex; + newAccount.characterIndex = characterIndex; //finish the routine sqlite3_finalize(statement); @@ -109,7 +110,7 @@ int ServerApplication::LoadUserAccount(std::string username, int clientIndex) { if (ret == SQLITE_DONE) { //create the non-existant account instead - return CreateUserAccount(username, clientIndex); + return CreateUserAccount(username, clientIndex, characterIndex); } throw(std::runtime_error(std::string() + "Unknown SQL error in LoadUserAccount: " + sqlite3_errmsg(database) ));