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

View File

@ -171,9 +171,11 @@ public:
// ------------------------------------------------------------------------
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)
{

View File

@ -25,6 +25,7 @@
#include "karts/controller/player_controller.hpp"
#include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp"
#include "modes/capture_the_flag.hpp"
#include "modes/linear_world.hpp"
#include "network/crypto.hpp"
#include "network/event.hpp"
@ -245,7 +246,7 @@ void ServerLobby::updateTracksForMode()
void ServerLobby::setup()
{
LobbyProtocol::setup();
auto players = m_game_setup->getConnectedPlayers();
auto players = STKHost::get()->getPlayersForNewGame();
if (m_game_setup->isGrandPrix() && !m_game_setup->isGrandPrixStarted())
{
for (auto player : players)
@ -490,7 +491,7 @@ void ServerLobby::asynchronousUpdate()
if (ServerConfig::m_owner_less)
{
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 ||
m_game_setup->isGrandPrixStarted()) &&
m_timeout.load() == std::numeric_limits<int64_t>::max())
@ -545,11 +546,9 @@ void ServerLobby::asynchronousUpdate()
if (go_on_race)
{
m_game_setup->setRace(winner_vote);
// Remove disconnected player (if any) one last time
m_game_setup->update(true);
m_game_setup->sortPlayersForGrandPrix();
m_game_setup->sortPlayersForGame();
auto players = m_game_setup->getConnectedPlayers();
auto players = STKHost::get()->getPlayersForNewGame();
m_game_setup->sortPlayersForGrandPrix(players);
m_game_setup->sortPlayersForGame(players);
for (auto& player : players)
{
std::shared_ptr<STKPeer> peer = player->getPeer();
@ -670,7 +669,7 @@ void ServerLobby::update(int ticks)
if ((m_state.load() > WAITING_FOR_START_GAME ||
m_game_setup->isGrandPrixStarted()) &&
m_game_setup->getPlayerCount() == 0 &&
STKHost::get()->getPlayersInGame() == 0 &&
NetworkConfig::get()->getServerIdFile().empty())
{
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
if (ServerConfig::m_ranked &&
m_state.load() == SELECTING &&
m_game_setup->getPlayerCount() == 1)
STKHost::get()->getPlayersInGame() == 1)
{
NetworkString* exit_result_screen = getNetworkString(1);
exit_result_screen->setSynchronous(true);
@ -699,12 +698,9 @@ void ServerLobby::update(int ticks)
resetServer();
}
if (m_game_setup)
{
// Remove disconnected players if in these two states
m_game_setup->update(m_state.load() == WAITING_FOR_START_GAME ||
m_state.load() == SELECTING);
}
STKHost::get()->updateConnectedPlayersInGame();
handlePlayerDisconnection();
switch (m_state.load())
{
case SET_PUBLIC_ADDRESS:
@ -925,7 +921,7 @@ void ServerLobby::startSelection(const Event *event)
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) &&
red_blue.first + red_blue.second != 1)
{
@ -967,7 +963,7 @@ void ServerLobby::startSelection(const Event *event)
while (it != m_available_kts.second.end())
{
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);
}
@ -1184,7 +1180,7 @@ void ServerLobby::checkIncomingConnectionRequests()
request->addParameter("address", addr.getIP() );
request->addParameter("port", addr.getPort());
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",
m_state.load() == WAITING_FOR_START_GAME ? 0 : 1);
request->queue();
@ -1671,7 +1667,7 @@ void ServerLobby::connectionRequested(Event* event)
return;
}
if (m_game_setup->getPlayerCount() + player_count +
if (STKHost::get()->getPlayersInGame() + player_count +
m_waiting_players_counts.load() >
(unsigned)ServerConfig::m_server_max_players)
{
@ -1770,6 +1766,8 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr<STKPeer> peer,
{
core::stringw name;
data.decodeStringW(&name);
if (name.empty())
name = L"unnamed";
float default_kart_color = data.getFloat();
PerPlayerDifficulty per_player_difficulty =
(PerPlayerDifficulty)data.getUInt8();
@ -2927,3 +2925,56 @@ void ServerLobby::changeHandicap(Event* event)
player->setPerPlayerDifficulty(d);
updatePlayerList();
} // 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 addWaitingPlayersToGame();
void changeHandicap(Event* event);
void handlePlayerDisconnection() const;
public:
ServerLobby();
virtual ~ServerLobby();

View File

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

View File

@ -288,6 +288,7 @@ STKHost::STKHost(bool server)
*/
void STKHost::init()
{
m_players_in_game.store(0);
m_network_timer.store(StkTime::getRealTimeMs());
m_shutdown = false;
m_authorised = false;
@ -1081,8 +1082,7 @@ void STKHost::handleDirectSocketRequest(Network* direct_socket,
s.addUInt32(ServerConfig::m_server_version);
s.encodeString(name);
s.addUInt8((uint8_t)ServerConfig::m_server_max_players);
s.addUInt8((uint8_t)(sl->getGameSetup()->getPlayerCount() +
sl->getWaitingPlayersCount()));
s.addUInt8((uint8_t)(getPlayersInGame() + sl->getWaitingPlayersCount()));
s.addUInt16(m_private_port);
s.addUInt8((uint8_t)sl->getDifficulty());
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);
} // 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. */
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
* triggers a shutdown of the STKHost (and the Protocolmanager). */
std::atomic_bool m_shutdown;
@ -133,9 +136,6 @@ private:
/** The public address stun server used. */
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;
std::atomic<uint32_t> m_client_ping;
@ -144,6 +144,8 @@ private:
std::atomic<uint32_t> m_download_speed;
std::atomic<uint32_t> m_players_in_game;
std::atomic<uint64_t> m_network_timer;
std::unique_ptr<NetworkTimerSynchronizer> m_nts;
@ -349,6 +351,13 @@ public:
// ------------------------------------------------------------------------
/* Return download speed in bytes per second. */
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
#endif // STK_HOST_HPP