Use new method to start game

This commit is contained in:
Benau 2018-12-30 11:13:18 +08:00
parent 9a4013843e
commit 50aa334912
7 changed files with 139 additions and 48 deletions

View File

@ -224,57 +224,50 @@ void GameSetup::addServerInfo(NetworkString* ns)
} // addServerInfo } // addServerInfo
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void GameSetup::sortPlayersForGrandPrix() void GameSetup::sortPlayersForGrandPrix(
std::vector<std::shared_ptr<NetworkPlayerProfile> >& players) const
{ {
if (!isGrandPrix()) if (!isGrandPrix())
return; return;
std::lock_guard<std::mutex> lock(m_players_mutex);
if (m_tracks.size() == 1) if (m_tracks.size() == 1)
{ {
std::random_device rd; std::random_device rd;
std::mt19937 g(rd()); std::mt19937 g(rd());
std::shuffle(m_players.begin(), m_players.end(), g); std::shuffle(players.begin(), players.end(), g);
return; return;
} }
std::sort(m_players.begin(), m_players.end(), std::sort(players.begin(), players.end(),
[](const std::weak_ptr<NetworkPlayerProfile>& a, [](const std::shared_ptr<NetworkPlayerProfile>& a,
const std::weak_ptr<NetworkPlayerProfile>& b) const std::shared_ptr<NetworkPlayerProfile>& b)
{ {
// They should be never expired return (a->getScore() < b->getScore()) ||
auto c = a.lock(); (a->getScore() == b->getScore() &&
assert(c); a->getOverallTime() > b->getOverallTime());
auto d = b.lock();
assert(d);
return (c->getScore() < d->getScore()) ||
(c->getScore() == d->getScore() &&
c->getOverallTime() > d->getOverallTime());
}); });
if (UserConfigParams::m_gp_most_points_first) if (UserConfigParams::m_gp_most_points_first)
{ {
std::reverse(m_players.begin(), m_players.end()); std::reverse(players.begin(), players.end());
} }
} // sortPlayersForGrandPrix } // sortPlayersForGrandPrix
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void GameSetup::sortPlayersForGame() void GameSetup::sortPlayersForGame(
std::vector<std::shared_ptr<NetworkPlayerProfile> >& players) const
{ {
std::lock_guard<std::mutex> lock(m_players_mutex);
if (!isGrandPrix()) if (!isGrandPrix())
{ {
std::random_device rd; std::random_device rd;
std::mt19937 g(rd()); std::mt19937 g(rd());
std::shuffle(m_players.begin(), m_players.end(), g); std::shuffle(players.begin(), players.end(), g);
} }
if (!race_manager->teamEnabled() || if (!race_manager->teamEnabled() ||
ServerConfig::m_team_choosing) ServerConfig::m_team_choosing)
return; return;
for (unsigned i = 0; i < m_players.size(); i++) for (unsigned i = 0; i < players.size(); i++)
{ {
auto player = m_players[i].lock(); players[i]->setTeam((KartTeam)(i % 2));
assert(player);
player->setTeam((KartTeam)(i % 2));
} }
} // sortPlayersForGame } // sortPlayersForGame

View File

@ -171,9 +171,11 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
const std::vector<std::string>& getAllTracks() const { return m_tracks; } const std::vector<std::string>& getAllTracks() const { return m_tracks; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void sortPlayersForGrandPrix(); void sortPlayersForGrandPrix(
std::vector<std::shared_ptr<NetworkPlayerProfile> >& players) const;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void sortPlayersForGame(); void sortPlayersForGame(
std::vector<std::shared_ptr<NetworkPlayerProfile> >& players) const;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setHitCaptureTime(int hc, float time) void setHitCaptureTime(int hc, float time)
{ {

View File

@ -25,6 +25,7 @@
#include "karts/controller/player_controller.hpp" #include "karts/controller/player_controller.hpp"
#include "karts/kart_properties.hpp" #include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp" #include "karts/kart_properties_manager.hpp"
#include "modes/capture_the_flag.hpp"
#include "modes/linear_world.hpp" #include "modes/linear_world.hpp"
#include "network/crypto.hpp" #include "network/crypto.hpp"
#include "network/event.hpp" #include "network/event.hpp"
@ -245,7 +246,7 @@ void ServerLobby::updateTracksForMode()
void ServerLobby::setup() void ServerLobby::setup()
{ {
LobbyProtocol::setup(); LobbyProtocol::setup();
auto players = m_game_setup->getConnectedPlayers(); auto players = STKHost::get()->getPlayersForNewGame();
if (m_game_setup->isGrandPrix() && !m_game_setup->isGrandPrixStarted()) if (m_game_setup->isGrandPrix() && !m_game_setup->isGrandPrixStarted())
{ {
for (auto player : players) for (auto player : players)
@ -490,7 +491,7 @@ void ServerLobby::asynchronousUpdate()
if (ServerConfig::m_owner_less) if (ServerConfig::m_owner_less)
{ {
m_game_setup->update(true/*remove_disconnected_players*/); m_game_setup->update(true/*remove_disconnected_players*/);
int player_size = m_game_setup->getPlayerCount(); int player_size = STKHost::get()->getPlayersInGame();
if ((player_size >= ServerConfig::m_min_start_game_players || if ((player_size >= ServerConfig::m_min_start_game_players ||
m_game_setup->isGrandPrixStarted()) && m_game_setup->isGrandPrixStarted()) &&
m_timeout.load() == std::numeric_limits<int64_t>::max()) m_timeout.load() == std::numeric_limits<int64_t>::max())
@ -545,11 +546,9 @@ void ServerLobby::asynchronousUpdate()
if (go_on_race) if (go_on_race)
{ {
m_game_setup->setRace(winner_vote); m_game_setup->setRace(winner_vote);
// Remove disconnected player (if any) one last time auto players = STKHost::get()->getPlayersForNewGame();
m_game_setup->update(true); m_game_setup->sortPlayersForGrandPrix(players);
m_game_setup->sortPlayersForGrandPrix(); m_game_setup->sortPlayersForGame(players);
m_game_setup->sortPlayersForGame();
auto players = m_game_setup->getConnectedPlayers();
for (auto& player : players) for (auto& player : players)
{ {
std::shared_ptr<STKPeer> peer = player->getPeer(); std::shared_ptr<STKPeer> peer = player->getPeer();
@ -670,7 +669,7 @@ void ServerLobby::update(int ticks)
if ((m_state.load() > WAITING_FOR_START_GAME || if ((m_state.load() > WAITING_FOR_START_GAME ||
m_game_setup->isGrandPrixStarted()) && m_game_setup->isGrandPrixStarted()) &&
m_game_setup->getPlayerCount() == 0 && STKHost::get()->getPlayersInGame() == 0 &&
NetworkConfig::get()->getServerIdFile().empty()) NetworkConfig::get()->getServerIdFile().empty())
{ {
if (RaceEventManager::getInstance() && if (RaceEventManager::getInstance() &&
@ -687,7 +686,7 @@ void ServerLobby::update(int ticks)
// Reset for ranked server if in kart / track selection has only 1 player // Reset for ranked server if in kart / track selection has only 1 player
if (ServerConfig::m_ranked && if (ServerConfig::m_ranked &&
m_state.load() == SELECTING && m_state.load() == SELECTING &&
m_game_setup->getPlayerCount() == 1) STKHost::get()->getPlayersInGame() == 1)
{ {
NetworkString* exit_result_screen = getNetworkString(1); NetworkString* exit_result_screen = getNetworkString(1);
exit_result_screen->setSynchronous(true); exit_result_screen->setSynchronous(true);
@ -699,12 +698,9 @@ void ServerLobby::update(int ticks)
resetServer(); resetServer();
} }
if (m_game_setup) STKHost::get()->updateConnectedPlayersInGame();
{ handlePlayerDisconnection();
// Remove disconnected players if in these two states
m_game_setup->update(m_state.load() == WAITING_FOR_START_GAME ||
m_state.load() == SELECTING);
}
switch (m_state.load()) switch (m_state.load())
{ {
case SET_PUBLIC_ADDRESS: case SET_PUBLIC_ADDRESS:
@ -925,7 +921,7 @@ void ServerLobby::startSelection(const Event *event)
if (ServerConfig::m_team_choosing && race_manager->teamEnabled()) if (ServerConfig::m_team_choosing && race_manager->teamEnabled())
{ {
auto red_blue = m_game_setup->getPlayerTeamInfo(); auto red_blue = STKHost::get()->getAllPlayersTeamInfo();
if ((red_blue.first == 0 || red_blue.second == 0) && if ((red_blue.first == 0 || red_blue.second == 0) &&
red_blue.first + red_blue.second != 1) red_blue.first + red_blue.second != 1)
{ {
@ -967,7 +963,7 @@ void ServerLobby::startSelection(const Event *event)
while (it != m_available_kts.second.end()) while (it != m_available_kts.second.end())
{ {
Track* t = track_manager->getTrack(*it); Track* t = track_manager->getTrack(*it);
if (t->getMaxArenaPlayers() < m_game_setup->getPlayerCount()) if (t->getMaxArenaPlayers() < STKHost::get()->getPlayersInGame())
{ {
it = m_available_kts.second.erase(it); it = m_available_kts.second.erase(it);
} }
@ -1184,7 +1180,7 @@ void ServerLobby::checkIncomingConnectionRequests()
request->addParameter("address", addr.getIP() ); request->addParameter("address", addr.getIP() );
request->addParameter("port", addr.getPort()); request->addParameter("port", addr.getPort());
request->addParameter("current-players", request->addParameter("current-players",
m_game_setup->getPlayerCount() + m_waiting_players_counts.load()); STKHost::get()->getPlayersInGame() + m_waiting_players_counts.load());
request->addParameter("game-started", request->addParameter("game-started",
m_state.load() == WAITING_FOR_START_GAME ? 0 : 1); m_state.load() == WAITING_FOR_START_GAME ? 0 : 1);
request->queue(); request->queue();
@ -1671,7 +1667,7 @@ void ServerLobby::connectionRequested(Event* event)
return; return;
} }
if (m_game_setup->getPlayerCount() + player_count + if (STKHost::get()->getPlayersInGame() + player_count +
m_waiting_players_counts.load() > m_waiting_players_counts.load() >
(unsigned)ServerConfig::m_server_max_players) (unsigned)ServerConfig::m_server_max_players)
{ {
@ -1770,6 +1766,8 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr<STKPeer> peer,
{ {
core::stringw name; core::stringw name;
data.decodeStringW(&name); data.decodeStringW(&name);
if (name.empty())
name = L"unnamed";
float default_kart_color = data.getFloat(); float default_kart_color = data.getFloat();
PerPlayerDifficulty per_player_difficulty = PerPlayerDifficulty per_player_difficulty =
(PerPlayerDifficulty)data.getUInt8(); (PerPlayerDifficulty)data.getUInt8();
@ -2927,3 +2925,56 @@ void ServerLobby::changeHandicap(Event* event)
player->setPerPlayerDifficulty(d); player->setPerPlayerDifficulty(d);
updatePlayerList(); updatePlayerList();
} // changeHandicap } // changeHandicap
//-----------------------------------------------------------------------------
/** Update and see if any player disconnects, if so eliminate the kart in
* world, so this function must be called in main thread.
*/
void ServerLobby::handlePlayerDisconnection() const
{
if (!World::getWorld() ||
World::getWorld()->getPhase() < WorldStatus::MUSIC_PHASE)
{
return;
}
int red_count = 0;
int blue_count = 0;
unsigned total = 0;
for (unsigned i = 0; i < race_manager->getNumPlayers(); i++)
{
const RemoteKartInfo& rki = race_manager->getKartInfo(i);
bool disconnected = rki.disconnected();
if (race_manager->getKartInfo(i).getKartTeam() == KART_TEAM_RED &&
!disconnected)
red_count++;
else if (race_manager->getKartInfo(i).getKartTeam() ==
KART_TEAM_BLUE && !disconnected)
blue_count++;
if (!disconnected)
{
total++;
continue;
}
AbstractKart* k = World::getWorld()->getKart(i);
if (!k->isEliminated() && !k->hasFinishedRace())
{
CaptureTheFlag* ctf = dynamic_cast<CaptureTheFlag*>
(World::getWorld());
if (ctf)
ctf->loseFlagForKart(k->getWorldKartId());
World::getWorld()->eliminateKart(i,
false/*notify_of_elimination*/);
k->setPosition(
World::getWorld()->getCurrentNumKarts() + 1);
k->finishedRace(World::getWorld()->getTime(), true/*from_server*/);
}
}
if (race_manager->getNumPlayers() != 1 && World::getWorld()->hasTeam() &&
(red_count == 0 || blue_count == 0))
World::getWorld()->setUnfairTeam(true);
} // handlePlayerDisconnection

View File

@ -263,6 +263,7 @@ private:
void resetServer(); void resetServer();
void addWaitingPlayersToGame(); void addWaitingPlayersToGame();
void changeHandicap(Event* event); void changeHandicap(Event* event);
void handlePlayerDisconnection() const;
public: public:
ServerLobby(); ServerLobby();
virtual ~ServerLobby(); virtual ~ServerLobby();

View File

@ -108,6 +108,7 @@ public:
std::weak_ptr<NetworkPlayerProfile> getNetworkPlayerProfile() const std::weak_ptr<NetworkPlayerProfile> getNetworkPlayerProfile() const
{ return m_profile; } { return m_profile; }
bool disconnected() const { return m_profile.expired(); } bool disconnected() const { return m_profile.expired(); }
bool isReserved() const { return m_user_name.empty(); }
bool operator<(const RemoteKartInfo& other) const bool operator<(const RemoteKartInfo& other) const
{ {
return ((m_host_id<other.m_host_id) || return ((m_host_id<other.m_host_id) ||

View File

@ -288,6 +288,7 @@ STKHost::STKHost(bool server)
*/ */
void STKHost::init() void STKHost::init()
{ {
m_players_in_game.store(0);
m_network_timer.store(StkTime::getRealTimeMs()); m_network_timer.store(StkTime::getRealTimeMs());
m_shutdown = false; m_shutdown = false;
m_authorised = false; m_authorised = false;
@ -1081,8 +1082,7 @@ void STKHost::handleDirectSocketRequest(Network* direct_socket,
s.addUInt32(ServerConfig::m_server_version); s.addUInt32(ServerConfig::m_server_version);
s.encodeString(name); s.encodeString(name);
s.addUInt8((uint8_t)ServerConfig::m_server_max_players); s.addUInt8((uint8_t)ServerConfig::m_server_max_players);
s.addUInt8((uint8_t)(sl->getGameSetup()->getPlayerCount() + s.addUInt8((uint8_t)(getPlayersInGame() + sl->getWaitingPlayersCount()));
sl->getWaitingPlayersCount()));
s.addUInt16(m_private_port); s.addUInt16(m_private_port);
s.addUInt8((uint8_t)sl->getDifficulty()); s.addUInt8((uint8_t)sl->getDifficulty());
s.addUInt8((uint8_t)sl->getGameMode()); s.addUInt8((uint8_t)sl->getGameMode());
@ -1319,3 +1319,37 @@ std::pair<int, int> STKHost::getAllPlayersTeamInfo() const
return std::make_pair(red_count, blue_count); return std::make_pair(red_count, blue_count);
} // getAllPlayersTeamInfo } // getAllPlayersTeamInfo
// ----------------------------------------------------------------------------
/** \brief Get the players for starting a new game.
* \return A vector containing pointers on the players profiles. */
std::vector<std::shared_ptr<NetworkPlayerProfile> >
STKHost::getPlayersForNewGame() const
{
std::vector<std::shared_ptr<NetworkPlayerProfile> > players;
std::lock_guard<std::mutex> lock(m_peers_mutex);
for (auto& p : m_peers)
{
auto& stk_peer = p.second;
if (stk_peer->isWaitingForGame())
continue;
for (auto& q : stk_peer->getPlayerProfiles())
players.push_back(q);
}
return players;
} // getPlayersForNewGame
// ----------------------------------------------------------------------------
void STKHost::updateConnectedPlayersInGame()
{
uint32_t total = 0;
std::lock_guard<std::mutex> lock(m_peers_mutex);
for (auto& p : m_peers)
{
auto& stk_peer = p.second;
if (stk_peer->isWaitingForGame())
continue;
total += (uint32_t)stk_peer->getPlayerProfiles().size();
}
m_players_in_game.store(total);
} // updateConnectedPlayersInGame

View File

@ -113,6 +113,9 @@ private:
/** Id of thread listening to enet events. */ /** Id of thread listening to enet events. */
std::thread m_listening_thread; std::thread m_listening_thread;
/** The private port enet socket is bound. */
uint16_t m_private_port;
/** Flag which is set from the protocol manager thread which /** Flag which is set from the protocol manager thread which
* triggers a shutdown of the STKHost (and the Protocolmanager). */ * triggers a shutdown of the STKHost (and the Protocolmanager). */
std::atomic_bool m_shutdown; std::atomic_bool m_shutdown;
@ -133,9 +136,6 @@ private:
/** The public address stun server used. */ /** The public address stun server used. */
TransportAddress m_stun_address; TransportAddress m_stun_address;
/** The private port enet socket is bound. */
uint16_t m_private_port;
Synchronised<std::map<uint32_t, uint32_t> > m_peer_pings; Synchronised<std::map<uint32_t, uint32_t> > m_peer_pings;
std::atomic<uint32_t> m_client_ping; std::atomic<uint32_t> m_client_ping;
@ -144,6 +144,8 @@ private:
std::atomic<uint32_t> m_download_speed; std::atomic<uint32_t> m_download_speed;
std::atomic<uint32_t> m_players_in_game;
std::atomic<uint64_t> m_network_timer; std::atomic<uint64_t> m_network_timer;
std::unique_ptr<NetworkTimerSynchronizer> m_nts; std::unique_ptr<NetworkTimerSynchronizer> m_nts;
@ -349,6 +351,13 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/* Return download speed in bytes per second. */ /* Return download speed in bytes per second. */
unsigned getDownloadSpeed() const { return m_download_speed.load(); } unsigned getDownloadSpeed() const { return m_download_speed.load(); }
// ------------------------------------------------------------------------
void updateConnectedPlayersInGame();
// ------------------------------------------------------------------------
uint32_t getPlayersInGame() const { return m_players_in_game.load(); }
// ------------------------------------------------------------------------
std::vector<std::shared_ptr<NetworkPlayerProfile> >
getPlayersForNewGame() const;
}; // class STKHost }; // class STKHost
#endif // STK_HOST_HPP #endif // STK_HOST_HPP