diff --git a/client/scenes/in_world.cpp b/client/scenes/in_world.cpp index 6e96e0d..8db57e1 100644 --- a/client/scenes/in_world.cpp +++ b/client/scenes/in_world.cpp @@ -142,7 +142,7 @@ void InWorld::Update() { camera.y = localCharacter->GetOrigin().y - camera.marginY; //check the connection - if (Clock::now() - lastBeat > std::chrono::seconds(5)) { + if (Clock::now() - lastBeat > std::chrono::seconds(3)) { if (attemptedBeats > 2) { throw(std::runtime_error("Connection lost")); } diff --git a/rsc/scripts/setup_server.lua b/rsc/scripts/setup_server.lua index 8b43720..6396596 100644 --- a/rsc/scripts/setup_server.lua +++ b/rsc/scripts/setup_server.lua @@ -17,7 +17,7 @@ tiles = { --custom generation systems here function islandGenerator(region) - io.write("Generating (", Region.GetX(region), ", ", Region.GetY(region), ")\n") +-- io.write("Generating (", Region.GetX(region), ", ", Region.GetY(region), ")\n") for i = 1, Region.GetWidth(region) do for j = 1, Region.GetHeight(region) do local dist = math.dist(0, 0, i + Region.GetX(region) -1, j + Region.GetY(region) -1) diff --git a/server/characters/character_manager.cpp b/server/characters/character_manager.cpp index 3718dd6..f24378f 100644 --- a/server/characters/character_manager.cpp +++ b/server/characters/character_manager.cpp @@ -225,7 +225,7 @@ int CharacterManager::SaveCharacter(int uid) { if (sqlite3_step(statement) != SQLITE_DONE) { //if this fails, than something went horribly wrong sqlite3_finalize(statement); - throw( std::runtime_error(std::string() + "Unknown SQL error when saving an account: " + sqlite3_errmsg(database)) ); + throw( std::runtime_error(std::string() + "Unknown SQL error when saving a character: " + sqlite3_errmsg(database)) ); } sqlite3_finalize(statement); @@ -258,7 +258,7 @@ void CharacterManager::DeleteCharacter(int uid) { if (sqlite3_step(statement) != SQLITE_DONE) { //if this fails, than something went horribly wrong sqlite3_finalize(statement); - throw( std::runtime_error(std::string() + "Unknown SQL error when deleting an account: " + sqlite3_errmsg(database)) ); + throw( std::runtime_error(std::string() + "Unknown SQL error when deleting a character: " + sqlite3_errmsg(database)) ); } //finish the routine diff --git a/server/server_logic.cpp b/server/server_logic.cpp index bb86ed2..b770cdf 100644 --- a/server/server_logic.cpp +++ b/server/server_logic.cpp @@ -151,7 +151,7 @@ void ServerApplication::Proc() { //TODO: This could be checked only every few seconds //Check connections for (auto& it : clientMap) { - if (std::chrono::steady_clock::now() - it.second.GetLastBeat() > std::chrono::seconds(5)) { + if (std::chrono::steady_clock::now() - it.second.GetLastBeat() > std::chrono::seconds(3)) { ServerPacket newPacket; newPacket.type = SerialPacketType::PING; network.SendTo(it.second.GetAddress(), &newPacket); diff --git a/server/server_methods.cpp b/server/server_methods.cpp index 766479d..184dd28 100644 --- a/server/server_methods.cpp +++ b/server/server_methods.cpp @@ -60,19 +60,16 @@ void ServerApplication::HandleBroadcastRequest(ServerPacket* const argPacket) { } void ServerApplication::HandleJoinRequest(ClientPacket* const argPacket) { - //create the new client - ClientData newClient; - newClient.SetAddress(argPacket->srcAddress); - //load the user account //TODO: handle passwords int accountIndex = accountMgr.LoadAccount(argPacket->username, clientIndex); - //Error checking + //Cannot load if (accountIndex < 0) { TextPacket newPacket; newPacket.type = SerialPacketType::JOIN_REJECTION; std::string msg = std::string() + "Account already loaded: " + argPacket->username; + memset(newPacket.name, 0, PACKET_STRING_SIZE); strncpy(newPacket.text, msg.c_str(), PACKET_STRING_SIZE); //BUG: If the name is too long this would truncate it network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); return; @@ -84,10 +81,14 @@ void ServerApplication::HandleJoinRequest(ClientPacket* const argPacket) { newPacket.clientIndex = clientIndex; newPacket.accountIndex = accountIndex; - network.SendTo(newClient.GetAddress(), static_cast(&newPacket)); + network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); + + //register the client + ClientData newClient; + newClient.SetAddress(argPacket->srcAddress); + clientMap[clientIndex++] = newClient; //finished this routine - clientMap[clientIndex++] = newClient; std::cout << "New connection, " << clientMap.size() << " clients and " << accountMgr.GetContainer()->size() << " accounts total" << std::endl; } @@ -110,9 +111,9 @@ void ServerApplication::HandleDisconnect(ClientPacket* const argPacket) { ); //save and unload this account's characters - //pump the unload message to all remaining clients characterMgr.UnloadCharacterIf([&](std::map::iterator it) -> bool { if (argPacket->accountIndex == it->second.GetOwner()) { + //pump the unload message to all remaining clients PumpCharacterUnload(it->first); return true; } @@ -172,23 +173,32 @@ void ServerApplication::HandleRegionRequest(RegionPacket* const argPacket) { void ServerApplication::HandleCharacterNew(CharacterPacket* const argPacket) { //BUG: #27 Characters can be created with an invalid account index + //TODO: Make sure that a character's owner's account is loaded before continuing + //NOTE: misnomer, try to load the character first int characterIndex = characterMgr.LoadCharacter(argPacket->accountIndex, argPacket->handle, argPacket->avatar); - if (characterIndex == -1) { - //TODO: rejection packet - std::cerr << "Warning: Character already loaded" << std::endl; + //cannot load or create + if (characterIndex < 0) { + //build the error message + std::string msg; + if (characterIndex == -1) { + msg += "Character already loaded: "; + } + else if (characterIndex == -1) { + msg += "Character already exists: "; + } + msg += argPacket->handle; + + //create, fill and send the packet + TextPacket newPacket; + newPacket.type = SerialPacketType::CHARACTER_REJECTION; + memset(newPacket.name, 0, PACKET_STRING_SIZE); + strncpy(newPacket.text, msg.c_str(), PACKET_STRING_SIZE); + network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); return; } - if (characterIndex == -2) { - //TODO: rejection packet - std::cerr << "Warning: Character already exists" << std::endl; - return; - } - - //TODO: Make sure that a character's owner's account is loaded before continuing - //send this new character to all clients CharacterPacket newPacket; newPacket.type = SerialPacketType::CHARACTER_NEW; @@ -203,9 +213,13 @@ void ServerApplication::HandleCharacterDelete(CharacterPacket* const argPacket) int characterIndex = characterMgr.LoadCharacter(argPacket->accountIndex, argPacket->handle, argPacket->avatar); //if this is not your character - if (characterIndex == -2) { - //TODO: rejection packet - std::cerr << "Warning: Character cannot be deleted" << std::endl; + if (characterIndex < 0 && characterMgr.GetCharacter(characterIndex)->GetOwner() != argPacket->accountIndex) { + //send the rejection packet + TextPacket newPacket; + newPacket.type = SerialPacketType::CHARACTER_REJECTION; + memset(newPacket.name, 0, PACKET_STRING_SIZE); + strncpy(newPacket.text, "Character cannot be deleted", PACKET_STRING_SIZE); + network.SendTo(argPacket->srcAddress, static_cast(&newPacket)); //unload an unneeded character if (characterIndex != -1) { @@ -260,7 +274,6 @@ void ServerApplication::HandleSynchronize(ClientPacket* const argPacket) { newPacket.type = SerialPacketType::CHARACTER_UPDATE; for (auto& it : *characterMgr.GetContainer()) { - newPacket.characterIndex = it.first; CopyCharacterToPacket(&newPacket, it.first); network.SendTo(client.GetAddress(), static_cast(&newPacket)); } @@ -323,6 +336,7 @@ void ServerApplication::PumpPacket(SerialPacket* const argPacket) { void ServerApplication::PumpCharacterUnload(int uid) { //delete the client-side character(s) + //NOTE: This is a strange function CharacterPacket newPacket; newPacket.type = SerialPacketType::CHARACTER_DELETE; newPacket.characterIndex = uid; diff --git a/todo.txt b/todo.txt index f7575db..77e8d80 100644 --- a/todo.txt +++ b/todo.txt @@ -1,3 +1,4 @@ +TODO: Remove the BUGFIX tags TODO: Rejection messages TODO: The error handling is terrible TODO: Get the rooms working, even if only via hotkeys