Prevent undefined behaviour if too many players joined battle or soccer
This commit is contained in:
parent
f99e13cb78
commit
875c2b8eb8
@ -2456,7 +2456,7 @@ void ServerLobby::startSelection(const Event *event)
|
||||
if (!has_peer_plays_game)
|
||||
{
|
||||
for (STKPeer* peer : always_spectate_peers)
|
||||
peer->setAlwaysSpectate(false);
|
||||
peer->setAlwaysSpectate(ASM_NONE);
|
||||
always_spectate_peers.clear();
|
||||
}
|
||||
else
|
||||
@ -2469,6 +2469,40 @@ void ServerLobby::startSelection(const Event *event)
|
||||
peer->setWaitingForGame(true);
|
||||
}
|
||||
|
||||
unsigned max_player = 0;
|
||||
STKHost::get()->updatePlayers(&max_player);
|
||||
|
||||
if (max_player > 10 && (RaceManager::get()->isBattleMode() ||
|
||||
RaceManager::get()->isSoccerMode()))
|
||||
{
|
||||
// Set late coming player to spectate if too many players in battle or
|
||||
// soccer
|
||||
std::sort(peers.begin(), peers.end(),
|
||||
[](const std::shared_ptr<STKPeer>& a,
|
||||
const std::shared_ptr<STKPeer>& b)
|
||||
{ return a->getHostId() > b->getHostId(); });
|
||||
int remove_player = max_player - 10;
|
||||
for (unsigned i = 0; i < peers.size(); i++)
|
||||
{
|
||||
auto& peer = peers[i];
|
||||
if (!peer->isValidated() || peer->isWaitingForGame())
|
||||
continue;
|
||||
peer->setAlwaysSpectate(ASM_FULL);
|
||||
peer->setWaitingForGame(true);
|
||||
always_spectate_peers.insert(peer.get());
|
||||
remove_player -= (int)peer->getPlayerProfiles().size();
|
||||
if (remove_player <= 0)
|
||||
break;
|
||||
// In case something goes wrong (all players need spectate)
|
||||
if (i == peers.size() - 1)
|
||||
{
|
||||
Log::error("ServerLobby", "Too many players and cannot set "
|
||||
"spectate for late coming players!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const std::string& kart_erase : karts_erase)
|
||||
{
|
||||
m_available_kts.first.erase(kart_erase);
|
||||
@ -2478,7 +2512,7 @@ void ServerLobby::startSelection(const Event *event)
|
||||
m_available_kts.second.erase(track_erase);
|
||||
}
|
||||
|
||||
unsigned max_player = 0;
|
||||
max_player = 0;
|
||||
STKHost::get()->updatePlayers(&max_player);
|
||||
if (auto ai = m_ai_peer.lock())
|
||||
{
|
||||
@ -4684,6 +4718,7 @@ void ServerLobby::addWaitingPlayersToGame()
|
||||
if (!peer || !peer->isValidated())
|
||||
continue;
|
||||
|
||||
peer->resetAlwaysSpectateFull();
|
||||
peer->setWaitingForGame(false);
|
||||
peer->setSpectator(false);
|
||||
if (m_peers_ready.find(peer) == m_peers_ready.end())
|
||||
@ -5522,10 +5557,10 @@ void ServerLobby::handleServerCommand(Event* event,
|
||||
delete chat;
|
||||
return;
|
||||
}
|
||||
peer->setAlwaysSpectate(true);
|
||||
peer->setAlwaysSpectate(ASM_COMMAND);
|
||||
}
|
||||
else
|
||||
peer->setAlwaysSpectate(false);
|
||||
peer->setAlwaysSpectate(ASM_NONE);
|
||||
updatePlayerList();
|
||||
}
|
||||
else if (argv[0] == "listserveraddon")
|
||||
|
@ -44,7 +44,7 @@ STKPeer::STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id)
|
||||
m_host_id = host_id;
|
||||
m_connected_time = StkTime::getMonoTimeMs();
|
||||
m_validated.store(false);
|
||||
m_always_spectate.store(false);
|
||||
m_always_spectate.store(ASM_NONE);
|
||||
m_average_ping.store(0);
|
||||
m_packet_loss.store(0);
|
||||
m_waiting_for_game.store(true);
|
||||
|
@ -61,6 +61,13 @@ enum AddonScore : int
|
||||
AS_TOTAL = 4,
|
||||
}; // AddonScore
|
||||
|
||||
enum AlwaysSpectateMode : uint8_t
|
||||
{
|
||||
ASM_NONE = 0, //!< Default, not spectating at all
|
||||
ASM_COMMAND = 1, //!< Set by player through command
|
||||
ASM_FULL = 2, //!< Set by server because too many players joined
|
||||
}; // AlwaysSpectateMode
|
||||
|
||||
/*! \class STKPeer
|
||||
* \brief Represents a peer.
|
||||
* This class is used to interface the ENetPeer structure.
|
||||
@ -85,7 +92,7 @@ protected:
|
||||
|
||||
std::atomic_bool m_warned_for_high_ping;
|
||||
|
||||
std::atomic_bool m_always_spectate;
|
||||
std::atomic<uint8_t> m_always_spectate;
|
||||
|
||||
/** Host id of this peer. */
|
||||
uint32_t m_host_id;
|
||||
@ -292,10 +299,17 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
const SocketAddress& getAddress() const { return *m_socket_address.get(); }
|
||||
// ------------------------------------------------------------------------
|
||||
void setAlwaysSpectate(bool val) { m_always_spectate.store(val); }
|
||||
void setAlwaysSpectate(AlwaysSpectateMode mode)
|
||||
{ m_always_spectate.store(mode); }
|
||||
// ------------------------------------------------------------------------
|
||||
bool alwaysSpectate() const { return m_always_spectate.load(); }
|
||||
|
||||
bool alwaysSpectate() const
|
||||
{ return m_always_spectate.load() != ASM_NONE; }
|
||||
// ------------------------------------------------------------------------
|
||||
void resetAlwaysSpectateFull()
|
||||
{
|
||||
if (m_always_spectate.load() == ASM_FULL)
|
||||
m_always_spectate.store(ASM_NONE);
|
||||
}
|
||||
}; // STKPeer
|
||||
|
||||
#endif // STK_PEER_HPP
|
||||
|
Loading…
x
Reference in New Issue
Block a user