Add state to avoid deadlock when finishing the race
This commit is contained in:
parent
9af27d93c4
commit
d9ede4f213
@ -332,7 +332,8 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
} // while count >0
|
||||
|
||||
// Inform the server which events have been received.
|
||||
GameProtocol::lock()->sendItemEventConfirmation(World::getWorld()->getTimeTicks());
|
||||
if (auto gp = GameProtocol::lock())
|
||||
gp->sendItemEventConfirmation(World::getWorld()->getTimeTicks());
|
||||
|
||||
// Forward the confirmed item state till the world time:
|
||||
int dt = World::getWorld()->getTimeTicks() - current_time;
|
||||
|
@ -70,7 +70,7 @@ public:
|
||||
void sendItemUpdate();
|
||||
void saveInitialState();
|
||||
|
||||
virtual void reset();
|
||||
virtual void reset() OVERRIDE;
|
||||
virtual void setItemConfirmationTime(std::weak_ptr<STKPeer> peer,
|
||||
int ticks) OVERRIDE;
|
||||
virtual void collectedItem(Item *item, AbstractKart *kart) OVERRIDE;
|
||||
|
@ -322,6 +322,11 @@ void ClientLobby::update(int ticks)
|
||||
case PLAYING:
|
||||
break;
|
||||
case RACE_FINISHED:
|
||||
if (!RaceEventManager::getInstance()->protocolStopped() ||
|
||||
!GameProtocol::emptyInstance())
|
||||
return;
|
||||
if (!m_received_server_result)
|
||||
m_received_server_result = true;
|
||||
break;
|
||||
case DONE:
|
||||
m_state.store(EXITING);
|
||||
@ -762,16 +767,9 @@ void ClientLobby::raceFinished(Event* event)
|
||||
|
||||
// stop race protocols
|
||||
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;
|
||||
m_state.store(RACE_FINISHED);
|
||||
} // raceFinished
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -99,6 +99,9 @@ ServerLobby::ServerLobby() : LobbyProtocol(NULL)
|
||||
"STK addons server, don't bother host one if you don't have the "
|
||||
"corresponding permission, they will be rejected if so.");
|
||||
}
|
||||
m_result_ns = getNetworkString();
|
||||
m_result_ns->setSynchronous(true);
|
||||
m_waiting_for_reset = false;
|
||||
} // ServerLobby
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -110,6 +113,7 @@ ServerLobby::~ServerLobby()
|
||||
{
|
||||
unregisterServer(true/*now*/);
|
||||
}
|
||||
delete m_result_ns;
|
||||
} // ~ServerLobby
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -142,6 +146,8 @@ void ServerLobby::setup()
|
||||
m_peers_votes.clear();
|
||||
m_server_delay = 0.0;
|
||||
m_timeout.store(std::numeric_limits<float>::max());
|
||||
m_waiting_for_reset = false;
|
||||
|
||||
Log::info("ServerLobby", "Reset server to initial state.");
|
||||
} // setup
|
||||
|
||||
@ -426,6 +432,20 @@ void ServerLobby::asynchronousUpdate()
|
||||
void ServerLobby::update(int ticks)
|
||||
{
|
||||
// Reset server to initial state if no more connected players
|
||||
if (m_waiting_for_reset)
|
||||
{
|
||||
if (!RaceEventManager::getInstance()->protocolStopped() ||
|
||||
!GameProtocol::emptyInstance())
|
||||
return;
|
||||
|
||||
RaceResultGUI::getInstance()->backToLobby();
|
||||
std::lock_guard<std::mutex> lock(m_connection_mutex);
|
||||
m_game_setup->stopGrandPrix();
|
||||
m_state = NetworkConfig::get()->isLAN() ?
|
||||
ACCEPTING_CLIENTS : REGISTER_SELF_ADDRESS;
|
||||
setup();
|
||||
}
|
||||
|
||||
if ((m_state.load() > ACCEPTING_CLIENTS ||
|
||||
m_game_setup->isGrandPrixStarted()) &&
|
||||
STKHost::get()->getPeerCount() == 0 &&
|
||||
@ -434,13 +454,12 @@ void ServerLobby::update(int ticks)
|
||||
if (RaceEventManager::getInstance() &&
|
||||
RaceEventManager::getInstance()->isRunning())
|
||||
{
|
||||
stopCurrentRace();
|
||||
RaceEventManager::getInstance()->stop();
|
||||
RaceEventManager::getInstance()->getProtocol()->requestTerminate();
|
||||
GameProtocol::lock()->requestTerminate();
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(m_connection_mutex);
|
||||
m_game_setup->stopGrandPrix();
|
||||
m_state = NetworkConfig::get()->isLAN() ?
|
||||
ACCEPTING_CLIENTS : REGISTER_SELF_ADDRESS;
|
||||
setup();
|
||||
m_waiting_for_reset = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset for ranked server if in kart / track selection has only 1 player
|
||||
@ -502,6 +521,22 @@ void ServerLobby::update(int ticks)
|
||||
checkRaceFinished();
|
||||
}
|
||||
break;
|
||||
case WAIT_FOR_RACE_STOPPED:
|
||||
if (!RaceEventManager::getInstance()->protocolStopped() ||
|
||||
!GameProtocol::emptyInstance())
|
||||
return;
|
||||
|
||||
// This will go back to lobby in server (and exit the current race)
|
||||
RaceResultGUI::getInstance()->backToLobby();
|
||||
// Reset for next state usage
|
||||
resetPeersReady();
|
||||
// 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);
|
||||
m_state = RESULT_DISPLAY;
|
||||
sendMessageToPeers(m_result_ns, /*reliable*/ true);
|
||||
Log::info("ServerLobby", "End of game message sent");
|
||||
break;
|
||||
case RESULT_DISPLAY:
|
||||
if (checkPeersReady() ||
|
||||
StkTime::getRealTime() > m_timeout.load())
|
||||
@ -811,28 +846,32 @@ void ServerLobby::checkRaceFinished()
|
||||
if (!RaceEventManager::getInstance()->isRaceOver()) return;
|
||||
|
||||
Log::info("ServerLobby", "The game is considered finish.");
|
||||
// notify the network world that it is stopped
|
||||
RaceEventManager::getInstance()->stop();
|
||||
|
||||
// Reset for next state usage
|
||||
resetPeersReady();
|
||||
NetworkString* total = getNetworkString();
|
||||
total->setSynchronous(true);
|
||||
total->addUInt8(LE_RACE_FINISHED);
|
||||
// stop race protocols before going back to lobby (end race)
|
||||
RaceEventManager::getInstance()->getProtocol()->requestTerminate();
|
||||
GameProtocol::lock()->requestTerminate();
|
||||
|
||||
// Save race result before delete the world
|
||||
m_result_ns->clear();
|
||||
m_result_ns->addUInt8(LE_RACE_FINISHED);
|
||||
if (m_game_setup->isGrandPrix())
|
||||
{
|
||||
// fastest lap
|
||||
int fastest_lap =
|
||||
static_cast<LinearWorld*>(World::getWorld())->getFastestLapTicks();
|
||||
total->addUInt32(fastest_lap);
|
||||
m_result_ns->addUInt32(fastest_lap);
|
||||
|
||||
// all gp tracks
|
||||
total->addUInt8((uint8_t)m_game_setup->getTotalGrandPrixTracks())
|
||||
m_result_ns->addUInt8((uint8_t)m_game_setup->getTotalGrandPrixTracks())
|
||||
.addUInt8((uint8_t)m_game_setup->getAllTracks().size());
|
||||
for (const std::string& gp_track : m_game_setup->getAllTracks())
|
||||
total->encodeString(gp_track);
|
||||
m_result_ns->encodeString(gp_track);
|
||||
|
||||
// each kart score and total time
|
||||
auto& players = m_game_setup->getPlayers();
|
||||
total->addUInt8((uint8_t)players.size());
|
||||
m_result_ns->addUInt8((uint8_t)players.size());
|
||||
for (unsigned i = 0; i < players.size(); i++)
|
||||
{
|
||||
int last_score = race_manager->getKartScore(i);
|
||||
@ -846,7 +885,7 @@ void ServerLobby::checkRaceFinished()
|
||||
player->setScore(cur_score);
|
||||
player->setOverallTime(overall_time);
|
||||
}
|
||||
total->addUInt32(last_score).addUInt32(cur_score)
|
||||
m_result_ns->addUInt32(last_score).addUInt32(cur_score)
|
||||
.addFloat(overall_time);
|
||||
}
|
||||
}
|
||||
@ -854,23 +893,14 @@ void ServerLobby::checkRaceFinished()
|
||||
{
|
||||
int fastest_lap =
|
||||
static_cast<LinearWorld*>(World::getWorld())->getFastestLapTicks();
|
||||
total->addUInt32(fastest_lap);
|
||||
m_result_ns->addUInt32(fastest_lap);
|
||||
}
|
||||
if (NetworkConfig::get()->isRankedServer())
|
||||
{
|
||||
computeNewRankings();
|
||||
submitRankingsToAddons();
|
||||
}
|
||||
|
||||
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);
|
||||
m_state = RESULT_DISPLAY;
|
||||
sendMessageToPeers(total, /*reliable*/ true);
|
||||
delete total;
|
||||
Log::info("ServerLobby", "End of game message sent");
|
||||
|
||||
m_state.store(WAIT_FOR_RACE_STOPPED);
|
||||
} // checkRaceFinished
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1060,27 +1090,6 @@ double ServerLobby::distributeBasePoints(uint32_t online_id)
|
||||
return 0.0;
|
||||
} // distributeBasePoints
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** 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.
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <tuple>
|
||||
|
||||
class BareNetworkString;
|
||||
class NetworkString;
|
||||
class NetworkPlayerProfile;
|
||||
class STKPeer;
|
||||
|
||||
@ -34,6 +35,7 @@ public:
|
||||
WAIT_FOR_RACE_STARTED, // Wait for all clients to have started the race
|
||||
DELAY_SERVER, // Additional server delay
|
||||
RACING, // racing
|
||||
WAIT_FOR_RACE_STOPPED, // Wait server for stopping all race protocols
|
||||
RESULT_DISPLAY, // Show result screen
|
||||
ERROR_LEAVE, // shutting down server
|
||||
EXITING
|
||||
@ -119,6 +121,10 @@ private:
|
||||
/** Number of ranked races done for each current players */
|
||||
std::map<uint32_t, unsigned> m_num_ranked_races;
|
||||
|
||||
bool m_waiting_for_reset;
|
||||
|
||||
NetworkString* m_result_ns;
|
||||
|
||||
// connection management
|
||||
void clientDisconnected(Event* event);
|
||||
void connectionRequested(Event* event);
|
||||
@ -183,8 +189,6 @@ private:
|
||||
uint32_t online_id,
|
||||
const irr::core::stringw& online_name);
|
||||
std::tuple<std::string, uint8_t, bool, bool> handleVote();
|
||||
void stopCurrentRace();
|
||||
|
||||
void getRankingForPlayer(std::shared_ptr<NetworkPlayerProfile> p);
|
||||
void submitRankingsToAddons();
|
||||
void computeNewRankings();
|
||||
@ -193,6 +197,7 @@ private:
|
||||
double distributeBasePoints(uint32_t online_id);
|
||||
double getModeFactor();
|
||||
double getModeSpread();
|
||||
void checkRaceFinished();
|
||||
|
||||
public:
|
||||
ServerLobby();
|
||||
@ -207,7 +212,6 @@ public:
|
||||
void signalRaceStartToClients();
|
||||
void startSelection(const Event *event=NULL);
|
||||
void checkIncomingConnectionRequests();
|
||||
void checkRaceFinished();
|
||||
void finishedLoadingWorld() OVERRIDE;
|
||||
ServerState getCurrentState() const { return m_state.load(); }
|
||||
void updateBanList();
|
||||
|
@ -162,17 +162,20 @@ void RewindManager::addNetworkState(BareNetworkString *buffer, int ticks)
|
||||
void RewindManager::saveState(bool local_save)
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("RewindManager - save state", 0x20, 0x7F, 0x20);
|
||||
GameProtocol::lock()->startNewState(local_save);
|
||||
auto gp = GameProtocol::lock();
|
||||
if (!gp)
|
||||
return;
|
||||
gp->startNewState(local_save);
|
||||
AllRewinder::const_iterator rewinder;
|
||||
for (rewinder = m_all_rewinder.begin(); rewinder != m_all_rewinder.end(); ++rewinder)
|
||||
{
|
||||
// TODO: check if it's worth passing in a sufficiently large buffer from
|
||||
// GameProtocol - this would save the copy operation.
|
||||
BareNetworkString *buffer = (*rewinder)->saveState();
|
||||
if (buffer && buffer->size() >= 0)
|
||||
if (buffer)
|
||||
{
|
||||
m_overall_state_size += buffer->size();
|
||||
GameProtocol::lock()->addState(buffer);
|
||||
gp->addState(buffer);
|
||||
} // size >= 0
|
||||
delete buffer; // buffer can be freed
|
||||
}
|
||||
@ -186,10 +189,14 @@ void RewindManager::saveState(bool local_save)
|
||||
*/
|
||||
void RewindManager::saveLocalState()
|
||||
{
|
||||
auto gp = GameProtocol::lock();
|
||||
if (!gp)
|
||||
return;
|
||||
|
||||
int ticks = World::getWorld()->getTimeTicks();
|
||||
|
||||
saveState(/*local_state*/true);
|
||||
NetworkString *state = GameProtocol::lock()->getState();
|
||||
NetworkString *state = gp->getState();
|
||||
|
||||
// Copy the data to a new string, making the buffer in
|
||||
// GameProtocol availble for again.
|
||||
@ -208,7 +215,6 @@ void RewindManager::saveLocalState()
|
||||
void RewindManager::restoreState(BareNetworkString *data)
|
||||
{
|
||||
data->reset();
|
||||
int index = 0;
|
||||
|
||||
for (auto rewinder = m_all_rewinder.begin();
|
||||
rewinder != m_all_rewinder.end(); ++rewinder)
|
||||
@ -230,7 +236,6 @@ void RewindManager::update(int ticks_not_used)
|
||||
m_all_rewinder.size() == 0 ||
|
||||
m_is_rewinding) return;
|
||||
|
||||
float time = World::getWorld()->getTime();
|
||||
int ticks = World::getWorld()->getTimeTicks();
|
||||
|
||||
m_not_rewound_ticks.store(ticks, std::memory_order_relaxed);
|
||||
@ -245,7 +250,8 @@ void RewindManager::update(int ticks_not_used)
|
||||
// Save state
|
||||
saveState(/**allow_local_save*/false);
|
||||
PROFILER_PUSH_CPU_MARKER("RewindManager - send state", 0x20, 0x7F, 0x40);
|
||||
GameProtocol::lock()->sendState();
|
||||
if (auto gp = GameProtocol::lock())
|
||||
gp->sendState();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
m_last_saved_state = ticks;
|
||||
} // update
|
||||
|
Loading…
x
Reference in New Issue
Block a user