diff --git a/src/network/protocols/client_lobby.cpp b/src/network/protocols/client_lobby.cpp index fa866e6a8..06ccf3b9a 100644 --- a/src/network/protocols/client_lobby.cpp +++ b/src/network/protocols/client_lobby.cpp @@ -29,7 +29,8 @@ #include "network/game_setup.hpp" #include "network/network_config.hpp" #include "network/network_player_profile.hpp" -#include "network/protocol_manager.hpp" +#include "network/protocols/game_protocol.hpp" +#include "network/protocols/game_events_protocol.hpp" #include "network/race_event_manager.hpp" #include "network/stk_host.hpp" #include "network/stk_peer.hpp" @@ -706,10 +707,16 @@ void ClientLobby::raceFinished(Event* event) } // stop race protocols - auto pm = ProtocolManager::lock(); - assert(pm); - pm->findAndTerminate(PROTOCOL_CONTROLLER_EVENTS); - pm->findAndTerminate(PROTOCOL_GAME_EVENTS); + RaceEventManager::getInstance()->stop(); + + RaceEventManager::getInstance()->getProtocol()->requestTerminate(); + GameProtocol::lock()->requestTerminate(); + + while (!RaceEventManager::getInstance()->protocolStopped()) + StkTime::sleep(1); + while (!GameProtocol::emptyInstance()) + StkTime::sleep(1); + m_received_server_result = true; } // raceFinished diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index a0d22c97b..aa8d0c4e1 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -26,7 +26,8 @@ #include "network/network_config.hpp" #include "network/network_player_profile.hpp" #include "network/protocols/connect_to_peer.hpp" -#include "network/protocol_manager.hpp" +#include "network/protocols/game_protocol.hpp" +#include "network/protocols/game_events_protocol.hpp" #include "network/race_event_manager.hpp" #include "network/stk_host.hpp" #include "network/stk_peer.hpp" @@ -369,6 +370,22 @@ void ServerLobby::asynchronousUpdate() */ void ServerLobby::update(int ticks) { + // Reset server to initial state if no more connected players + if (m_state.load() > ACCEPTING_CLIENTS && + STKHost::get()->getPeerCount() == 0 && + NetworkConfig::get()->getServerIdFile().empty()) + { + std::lock_guard lock(m_connection_mutex); + if (RaceEventManager::getInstance() && + RaceEventManager::getInstance()->isRunning()) + { + stopCurrentRace(); + } + m_state = NetworkConfig::get()->isLAN() ? + ACCEPTING_CLIENTS : REGISTER_SELF_ADDRESS; + setup(); + } + // Check if server owner has left updateServerOwner(); if (m_game_setup) @@ -650,7 +667,7 @@ void ServerLobby::checkIncomingConnectionRequests() * to state RESULT_DISPLAY, during which the race result gui is shown and all * clients can click on 'continue'. */ - void ServerLobby::checkRaceFinished() +void ServerLobby::checkRaceFinished() { assert(RaceEventManager::getInstance()->isRunning()); assert(World::getWorld()); @@ -671,14 +688,8 @@ void ServerLobby::checkIncomingConnectionRequests() static_cast(World::getWorld())->getFastestLapTicks(); total->addUInt32(fastest_lap); } - RaceResultGUI::getInstance()->backToLobby(); - // notify the network world that it is stopped - RaceEventManager::getInstance()->stop(); - // stop race protocols - auto pm = ProtocolManager::lock(); - assert(pm); - pm->findAndTerminate(PROTOCOL_CONTROLLER_EVENTS); - pm->findAndTerminate(PROTOCOL_GAME_EVENTS); + + stopCurrentRace(); // Set the delay before the server forces all clients to exit the race // result screen and go back to the lobby m_timeout.store((float)StkTime::getRealTime() + 15.0f); @@ -689,6 +700,27 @@ void ServerLobby::checkIncomingConnectionRequests() } // checkRaceFinished +//----------------------------------------------------------------------------- +/** Stop any race currently in server, should only be called in main thread. + */ +void ServerLobby::stopCurrentRace() +{ + // notify the network world that it is stopped + RaceEventManager::getInstance()->stop(); + + // stop race protocols before going back to lobby (end race) + RaceEventManager::getInstance()->getProtocol()->requestTerminate(); + GameProtocol::lock()->requestTerminate(); + + while (!RaceEventManager::getInstance()->protocolStopped()) + StkTime::sleep(1); + while (!GameProtocol::emptyInstance()) + StkTime::sleep(1); + + // This will go back to lobby in server (and exit the current race) + RaceResultGUI::getInstance()->backToLobby(); +} // stopCurrentRace + //----------------------------------------------------------------------------- /** Called when a client disconnects. * \param event The disconnect event. diff --git a/src/network/protocols/server_lobby.hpp b/src/network/protocols/server_lobby.hpp index 378d37aa6..c8661b3ac 100644 --- a/src/network/protocols/server_lobby.hpp +++ b/src/network/protocols/server_lobby.hpp @@ -124,6 +124,7 @@ private: } } std::tuple handleVote(); + void stopCurrentRace(); public: ServerLobby(); diff --git a/src/network/race_event_manager.hpp b/src/network/race_event_manager.hpp index 525ae9d05..f2a173e9c 100755 --- a/src/network/race_event_manager.hpp +++ b/src/network/race_event_manager.hpp @@ -62,6 +62,11 @@ public: /** Returns if this instance is in running state or not. */ bool isRunning() { return m_running; } // ------------------------------------------------------------------------ + std::shared_ptr getProtocol() const + { return m_game_events_protocol.lock(); } + // ------------------------------------------------------------------------ + bool protocolStopped() const { return m_game_events_protocol.expired(); } + // ------------------------------------------------------------------------ bool isRaceOver(); // ------------------------------------------------------------------------ void collectedItem(Item *item, AbstractKart *kart);