Initial work to port network profile to use weak_ptr
This commit is contained in:
parent
ea8ba470d6
commit
1b8d4c80dc
@ -48,7 +48,7 @@ WorldStatus::WorldStatus()
|
||||
m_play_track_intro_sound = UserConfigParams::m_music;
|
||||
m_play_ready_set_go_sounds = true;
|
||||
m_play_racestart_sounds = true;
|
||||
m_server_is_ready = false;
|
||||
m_server_is_ready.store(false);
|
||||
|
||||
IrrlichtDevice *device = irr_driver->getDevice();
|
||||
|
||||
@ -98,7 +98,7 @@ void WorldStatus::reset()
|
||||
// In case of a networked race the race can only start once
|
||||
// all protocols are up. This flag is used to wait for
|
||||
// a confirmation before starting the actual race.
|
||||
m_server_is_ready = false;
|
||||
m_server_is_ready.store(false);
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -259,7 +259,7 @@ void WorldStatus::updateTime(const float dt)
|
||||
// loaded the world). The server waits for a confirmation from
|
||||
// each client that they have started (to guarantee that the
|
||||
// server is running with a local time behind all clients).
|
||||
if (!m_server_is_ready) return;
|
||||
if (m_server_is_ready.load() == false) return;
|
||||
|
||||
m_phase = READY_PHASE;
|
||||
auto cl = LobbyProtocol::get<ClientLobby>();
|
||||
@ -474,7 +474,7 @@ float WorldStatus::adjustDT(float dt)
|
||||
*/
|
||||
void WorldStatus::startReadySetGo()
|
||||
{
|
||||
m_server_is_ready = true;
|
||||
m_server_is_ready.store(true);
|
||||
} // startReadySetGo
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define HEADER_WORLD_STATUS_HPP
|
||||
|
||||
#include "utils/cpp2011.hpp"
|
||||
#include <atomic>
|
||||
|
||||
class SFXBase;
|
||||
|
||||
@ -138,7 +139,7 @@ private:
|
||||
* set go' to make sure all client are actually ready to start the game.
|
||||
* A server on the other hand will run behind all clients, so it will
|
||||
* wait for all clients to indicate that they have started the race. */
|
||||
bool m_server_is_ready;
|
||||
std::atomic_bool m_server_is_ready;
|
||||
|
||||
void startEngines();
|
||||
|
||||
@ -205,7 +206,7 @@ public:
|
||||
/** Get the time since start regardless of which way the clock counts */
|
||||
float getTimeSinceStart() const { return m_count_up_timer; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setReadyToRace() { m_server_is_ready = true; }
|
||||
void setReadyToRace() { m_server_is_ready.store(true); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets a time by which the clock should be adjusted. Used by networking
|
||||
* if too many rewinds are detected. */
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "network/game_setup.hpp"
|
||||
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "network/race_config.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/network_player_profile.hpp"
|
||||
#include "online/online_profile.hpp"
|
||||
@ -39,43 +40,39 @@ GameSetup::GameSetup()
|
||||
GameSetup::~GameSetup()
|
||||
{
|
||||
// remove all players
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
delete m_players[i];
|
||||
};
|
||||
m_players.clear();
|
||||
delete m_race_config;
|
||||
} // ~GameSetup
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GameSetup::addPlayer(NetworkPlayerProfile* profile)
|
||||
void GameSetup::addPlayer(std::shared_ptr<NetworkPlayerProfile> profile)
|
||||
{
|
||||
m_players.push_back(profile);
|
||||
Log::info("GameSetup", "New player in the game setup. Player id : %d.",
|
||||
profile->getGlobalPlayerId());
|
||||
Log::info("GameSetup", "New player in the game setup. Player name : %s.",
|
||||
StringUtils::wideToUtf8(profile->getName()).c_str());
|
||||
} // addPlayer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Removed a player give his NetworkPlayerProfile.
|
||||
* \param profile The NetworkPlayerProfile to remove.
|
||||
* \return True if the player was found and removed, false otherwise.
|
||||
/** Update and see if any player disconnects.
|
||||
* \param remove_disconnected_players remove the disconnected players,
|
||||
* otherwise replace with AI (when racing), so this function must be called
|
||||
* in main thread.
|
||||
*/
|
||||
bool GameSetup::removePlayer(const NetworkPlayerProfile *profile)
|
||||
void GameSetup::update(bool remove_disconnected_players)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
std::unique_lock<std::mutex> lock(m_players_mutex);
|
||||
if (remove_disconnected_players)
|
||||
{
|
||||
if (m_players[i] == profile)
|
||||
{
|
||||
delete m_players[i];
|
||||
m_players.erase(m_players.begin()+i, m_players.begin()+i+1);
|
||||
Log::verbose("GameSetup",
|
||||
"Removed a player from the game setup. Remains %u.",
|
||||
m_players.size());
|
||||
return true;
|
||||
}
|
||||
m_players.erase(std::remove_if(m_players.begin(), m_players.end(), []
|
||||
(const std::weak_ptr<NetworkPlayerProfile> npp)->bool
|
||||
{
|
||||
return npp.expired();
|
||||
}), m_players.end());
|
||||
return;
|
||||
}
|
||||
return false;
|
||||
lock.unlock();
|
||||
if (!World::getWorld())
|
||||
return;
|
||||
} // removePlayer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -97,38 +94,13 @@ bool GameSetup::isLocalMaster(uint8_t player_id)
|
||||
return m_local_master == player_id;
|
||||
} // isLocalMaster
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets the kart the specified player uses.
|
||||
* \param player_id ID of this player (in this race).
|
||||
* \param kart_name Name of the kart the player picked.
|
||||
*/
|
||||
void GameSetup::setPlayerKart(uint8_t player_id, const std::string &kart_name)
|
||||
{
|
||||
bool found = false;
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
if (m_players[i]->getGlobalPlayerId() == player_id)
|
||||
{
|
||||
m_players[i]->setKartName(kart_name);
|
||||
Log::info("GameSetup::setPlayerKart", "Player %d took kart %s",
|
||||
player_id, kart_name.c_str());
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
Log::info("GameSetup::setPlayerKart", "The player %d was unknown.",
|
||||
player_id);
|
||||
}
|
||||
} // setPlayerKart
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GameSetup::bindKartsToProfiles()
|
||||
{
|
||||
World::KartList karts = World::getWorld()->getKarts();
|
||||
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
/*for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
Log::info("GameSetup", "Player %d has id %d and kart %s", i,
|
||||
m_players[i]->getGlobalPlayerId(),
|
||||
@ -155,73 +127,5 @@ void GameSetup::bindKartsToProfiles()
|
||||
{
|
||||
Log::error("GameSetup", "Error while binding world kart ids to players profiles.");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
} // bindKartsToProfiles
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** \brief Get a network player profile with the specified player id.
|
||||
* \param player_id : Player id in this race.
|
||||
* \return The profile of the player having the specified player id, or
|
||||
* NULL if no such player exists.
|
||||
*/
|
||||
const NetworkPlayerProfile* GameSetup::getProfile(uint8_t player_id)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
if (m_players[i]->getGlobalPlayerId()== player_id)
|
||||
{
|
||||
return m_players[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
} // getProfile
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** \brief Get a network player profile matching a kart name.
|
||||
* \param kart_name : Name of the kart used by the player.
|
||||
* \return The profile of the player having the kart kart_name, or NULL
|
||||
* if no such network profile exists.
|
||||
*/
|
||||
|
||||
const NetworkPlayerProfile* GameSetup::getProfile(const std::string &kart_name)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
if (m_players[i]->getKartName() == kart_name)
|
||||
{
|
||||
return m_players[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
} // getProfile(kart_name)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the list of all player profiles from a specified host. Note that
|
||||
* this function is somewhat expensive (it loops over all network profiles
|
||||
* to find the ones with the specified host id).
|
||||
* \param host_id The host id which players should be collected.
|
||||
* \return List of NetworkPlayerProfile pointers/
|
||||
*/
|
||||
std::vector<NetworkPlayerProfile*> GameSetup::getAllPlayersOnHost(uint8_t host_id)
|
||||
{
|
||||
std::vector<NetworkPlayerProfile*> result;
|
||||
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
if (m_players[i]->getHostId() == host_id)
|
||||
result.push_back(m_players[i]);
|
||||
}
|
||||
return result;
|
||||
} // getAllPlayersOnHost
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GameSetup::isKartAvailable(std::string kart_name)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
if (m_players[i]->getKartName() == kart_name)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -22,15 +22,16 @@
|
||||
#ifndef GAME_SETUP_HPP
|
||||
#define GAME_SETUP_HPP
|
||||
|
||||
#include "network/race_config.hpp"
|
||||
#include "network/remote_kart_info.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class NetworkPlayerProfile;
|
||||
class RaceConfig;
|
||||
|
||||
// ============================================================================
|
||||
/*! \class GameSetup
|
||||
@ -40,8 +41,10 @@ class NetworkPlayerProfile;
|
||||
class GameSetup
|
||||
{
|
||||
private:
|
||||
mutable std::mutex m_players_mutex;
|
||||
|
||||
/** Information about all connected players. */
|
||||
std::vector<NetworkPlayerProfile*> m_players;
|
||||
std::vector<std::weak_ptr<NetworkPlayerProfile> > m_players;
|
||||
|
||||
/** The race configuration. */
|
||||
RaceConfig* m_race_config;
|
||||
@ -52,26 +55,22 @@ private:
|
||||
/** The player id of the local game master, used in
|
||||
* kart selection screen. */
|
||||
uint8_t m_local_master;
|
||||
|
||||
public:
|
||||
GameSetup();
|
||||
virtual ~GameSetup();
|
||||
|
||||
void addPlayer(NetworkPlayerProfile* profile); //!< Add a player.
|
||||
bool removePlayer(const NetworkPlayerProfile *profile);
|
||||
void setPlayerKart(uint8_t player_id, const std::string &kart_name);
|
||||
void bindKartsToProfiles(); //!< Sets the right world_kart_id in profiles
|
||||
// ------------------------------------------------------------------------
|
||||
GameSetup();
|
||||
// ------------------------------------------------------------------------
|
||||
~GameSetup();
|
||||
// ------------------------------------------------------------------------
|
||||
void addPlayer(std::shared_ptr<NetworkPlayerProfile> profile);
|
||||
// ------------------------------------------------------------------------
|
||||
void update(bool remove_disconnected_players);
|
||||
// ------------------------------------------------------------------------
|
||||
void bindKartsToProfiles();
|
||||
// ------------------------------------------------------------------------
|
||||
void setLocalMaster(uint8_t player_id);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
bool isLocalMaster(uint8_t player_id);
|
||||
const NetworkPlayerProfile* getProfile(uint8_t id);
|
||||
const NetworkPlayerProfile* getProfile(const std::string &kart_name);
|
||||
std::vector<NetworkPlayerProfile*> getAllPlayersOnHost(uint8_t host_id);
|
||||
|
||||
/*! \brief Used to know if a kart is available.
|
||||
* \param kart_name : Name of the kart to check.
|
||||
* \return True if the kart hasn't been selected yet, false elseway.
|
||||
*/
|
||||
bool isKartAvailable(std::string kart_name);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the number of local players. */
|
||||
void setNumLocalPlayers(int n) { m_num_local_players = n; }
|
||||
@ -79,26 +78,23 @@ public:
|
||||
/** Returns the nunber of local players. */
|
||||
int getNumLocalPlayers() const { return m_num_local_players; }
|
||||
// ------------------------------------------------------------------------
|
||||
/*! \brief Used to know if a kart is playable.
|
||||
* \param kart_name : Name of the kart to check.
|
||||
* \return True if the kart is playable (standard kart).
|
||||
* Currently this is always true as the kart selection screen shows
|
||||
* only the standard karts.
|
||||
*/
|
||||
bool isKartAllowed(std::string kart_name) { return true; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the configuration for this race. */
|
||||
RaceConfig* getRaceConfig() { return m_race_config; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** \brief Get the players that are in the game
|
||||
* \return A vector containing pointers on the players profiles. */
|
||||
const std::vector<NetworkPlayerProfile*>& getPlayers() const
|
||||
std::vector<std::weak_ptr<NetworkPlayerProfile> > getPlayers() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_players_mutex);
|
||||
return m_players;
|
||||
} // getPlayers
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of connected players. */
|
||||
int getPlayerCount() { return (int)m_players.size(); }
|
||||
unsigned getPlayerCount()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_players_mutex);
|
||||
return (unsigned)m_players.size();
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the id of the local master. */
|
||||
int getLocalMasterID() const { return m_local_master; }
|
||||
|
@ -70,7 +70,7 @@ private:
|
||||
uint16_t m_client_port;
|
||||
|
||||
/** Maximum number of players on the server. */
|
||||
int m_max_players;
|
||||
unsigned m_max_players;
|
||||
|
||||
/** True if a client should connect to the first server it finds and
|
||||
* immediately start a race. */
|
||||
@ -171,10 +171,10 @@ public:
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the maximum number of players for this server. */
|
||||
void setMaxPlayers(int n) { m_max_players = n; }
|
||||
void setMaxPlayers(unsigned n) { m_max_players = n; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the maximum number of players for this server. */
|
||||
int getMaxPlayers() const { return m_max_players; }
|
||||
unsigned getMaxPlayers() const { return m_max_players; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if this instance is a server. */
|
||||
bool isServer() const { return m_is_server; }
|
||||
|
@ -25,10 +25,12 @@
|
||||
#include "guiengine/message_queue.hpp"
|
||||
#include "modes/world_with_rank.hpp"
|
||||
#include "network/event.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_player_profile.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/protocols/latency_protocol.hpp"
|
||||
#include "network/race_config.hpp"
|
||||
#include "network/race_event_manager.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/stk_peer.hpp"
|
||||
@ -85,7 +87,7 @@ void ClientLobby::setAddress(const TransportAddress &address)
|
||||
|
||||
void ClientLobby::setup()
|
||||
{
|
||||
m_game_setup = STKHost::get()->setupNewGame(); // create a new game setup
|
||||
LobbyProtocol::setup();
|
||||
m_state = NONE;
|
||||
} // setup
|
||||
|
||||
@ -446,6 +448,7 @@ void ClientLobby::connectionAccepted(Event* event)
|
||||
Log::info("ClientLobby", "The server accepted the connection.");
|
||||
|
||||
STKHost::get()->setMyHostId(data.getUInt32());
|
||||
// For now no split screen so only 1 player
|
||||
m_game_setup->setNumLocalPlayers(1);
|
||||
// connection token
|
||||
uint32_t token = data.getToken();
|
||||
@ -596,18 +599,7 @@ void ClientLobby::kartSelectionRefused(Event* event)
|
||||
void ClientLobby::kartSelectionUpdate(Event* event)
|
||||
{
|
||||
if(!checkDataSize(event, 3)) return;
|
||||
const NetworkString &data = event->data();
|
||||
uint8_t player_id = data.getUInt8();
|
||||
std::string kart_name;
|
||||
data.decodeString(&kart_name);
|
||||
if (!m_game_setup->isKartAvailable(kart_name))
|
||||
{
|
||||
Log::error("ClientLobby",
|
||||
"The updated kart is taken already.");
|
||||
}
|
||||
m_game_setup->setPlayerKart(player_id, kart_name);
|
||||
NetworkKartSelectionScreen::getInstance()->playerSelected(player_id,
|
||||
kart_name);
|
||||
|
||||
} // kartSelectionUpdate
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -725,7 +717,7 @@ void ClientLobby::exitResultScreen(Event *event)
|
||||
{
|
||||
RaceResultGUI::getInstance()->backToLobby();
|
||||
// Will be reset to linked if connected to server, see update(float dt)
|
||||
m_game_setup = STKHost::get()->setupNewGame();
|
||||
LobbyProtocol::setup();
|
||||
STKHost::get()->getServerPeerForClient()->unsetClientServerToken();
|
||||
// stop race protocols
|
||||
auto pm = ProtocolManager::lock();
|
||||
@ -873,19 +865,8 @@ void ClientLobby::playerLapsVote(Event* event)
|
||||
*/
|
||||
void ClientLobby::finishedLoadingWorld()
|
||||
{
|
||||
assert(STKHost::get()->getPeerCount() == 1);
|
||||
std::vector<NetworkPlayerProfile*> players =
|
||||
STKHost::get()->getMyPlayerProfiles();
|
||||
NetworkString *ns = getNetworkString(2);
|
||||
NetworkString* ns = getNetworkString(1);
|
||||
ns->addUInt8(LE_CLIENT_LOADED_WORLD);
|
||||
ns->addUInt8( uint8_t(players.size()) ) ;
|
||||
for (unsigned int i = 0; i < players.size(); i++)
|
||||
{
|
||||
ns->addUInt8(players[i]->getGlobalPlayerId());
|
||||
Log::info("ClientLobby",
|
||||
"Player %d ready, notifying server.",
|
||||
players[i]->getGlobalPlayerId());
|
||||
} // for i < players.size()
|
||||
sendToServer(ns, /*reliable*/true);
|
||||
sendToServer(ns, true);
|
||||
delete ns;
|
||||
} // finishedLoadingWorld
|
||||
|
@ -176,7 +176,7 @@ void GameEventsProtocol::clientHasStarted()
|
||||
* ready set go. */
|
||||
void GameEventsProtocol::receivedClientHasStarted(Event *event)
|
||||
{
|
||||
assert(NetworkConfig::get()->isServer());
|
||||
/* assert(NetworkConfig::get()->isServer());
|
||||
m_count_ready_clients++;
|
||||
Log::verbose("GameEvent",
|
||||
"Host %d has started ready-set-go: %d out of %d done",
|
||||
@ -189,5 +189,5 @@ void GameEventsProtocol::receivedClientHasStarted(Event *event)
|
||||
// SIgnal the server to start now - since it is now behind the client
|
||||
// times by the latency of the 'slowest' client.
|
||||
World::getWorld()->startReadySetGo();
|
||||
}
|
||||
}*/
|
||||
} // receivedClientHasStarted
|
||||
|
@ -22,14 +22,15 @@
|
||||
#include "input/input_manager.hpp"
|
||||
#include "input/device_manager.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/game_setup.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/protocols/latency_protocol.hpp"
|
||||
#include "network/race_config.hpp"
|
||||
#include "network/race_event_manager.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
|
||||
@ -44,6 +45,8 @@ LobbyProtocol::LobbyProtocol(CallbackObject* callback_object)
|
||||
// ----------------------------------------------------------------------------
|
||||
LobbyProtocol::~LobbyProtocol()
|
||||
{
|
||||
if (m_game_setup)
|
||||
delete m_game_setup;
|
||||
} // ~LobbyProtocol
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -73,7 +76,7 @@ void LobbyProtocol::loadWorld()
|
||||
|
||||
// Create the kart information for the race manager:
|
||||
// -------------------------------------------------
|
||||
std::vector<NetworkPlayerProfile*> players = m_game_setup->getPlayers();
|
||||
/*std::vector<NetworkPlayerProfile*> players = m_game_setup->getPlayers();
|
||||
int local_player_id = 0;
|
||||
for (unsigned int i = 0; i < players.size(); i++)
|
||||
{
|
||||
@ -95,7 +98,7 @@ void LobbyProtocol::loadWorld()
|
||||
// corresponding device associated with it).
|
||||
RemoteKartInfo rki(is_local ? local_player_id
|
||||
: i - local_player_id
|
||||
+ STKHost::get()->getGameSetup()->getNumLocalPlayers(),
|
||||
+ m_game_setup->getNumLocalPlayers(),
|
||||
profile->getKartName(),
|
||||
profile->getName(),
|
||||
profile->getHostId(),
|
||||
@ -110,7 +113,7 @@ void LobbyProtocol::loadWorld()
|
||||
|
||||
// Inform the race manager about the data for this kart.
|
||||
race_manager->setPlayerKart(i, rki);
|
||||
} // for i in players
|
||||
} // for i in players*/
|
||||
|
||||
// Make sure that if there is only a single local player this player can
|
||||
// use all input devices.
|
||||
@ -137,3 +140,14 @@ void LobbyProtocol::terminateLatencyProtocol()
|
||||
{
|
||||
ProtocolManager::lock()->findAndTerminate(PROTOCOL_SYNCHRONIZATION);
|
||||
} // stopLatencyProtocol
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** A previous GameSetup is deleted and a new one is created.
|
||||
* \return Newly create GameSetup object.
|
||||
*/
|
||||
void LobbyProtocol::setup()
|
||||
{
|
||||
if (m_game_setup)
|
||||
delete m_game_setup;
|
||||
m_game_setup = new GameSetup();
|
||||
} // setupNewGame
|
||||
|
@ -20,10 +20,10 @@
|
||||
#define LOBBY_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
|
||||
class GameSetup;
|
||||
|
||||
/*!
|
||||
* \class LobbyProtocol
|
||||
* \brief Base class for both client and server lobby. The lobbies are started
|
||||
@ -78,7 +78,7 @@ public:
|
||||
protected:
|
||||
static std::weak_ptr<LobbyProtocol> m_lobby;
|
||||
|
||||
/** The game setup. */
|
||||
/** Stores data about the online game to play. */
|
||||
GameSetup* m_game_setup;
|
||||
|
||||
public:
|
||||
@ -109,7 +109,7 @@ public:
|
||||
|
||||
LobbyProtocol(CallbackObject* callback_object);
|
||||
virtual ~LobbyProtocol();
|
||||
virtual void setup() = 0;
|
||||
virtual void setup();
|
||||
virtual void update(float dt) = 0;
|
||||
virtual void finishedLoadingWorld() = 0;
|
||||
virtual void loadWorld();
|
||||
@ -120,6 +120,7 @@ public:
|
||||
{
|
||||
assert(false); // Only defined in client
|
||||
};
|
||||
GameSetup* getGameSetup() const { return m_game_setup; }
|
||||
|
||||
}; // class LobbyProtocol
|
||||
|
||||
|
@ -22,11 +22,13 @@
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/event.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_player_profile.hpp"
|
||||
#include "network/protocols/connect_to_peer.hpp"
|
||||
#include "network/protocols/latency_protocol.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/race_config.hpp"
|
||||
#include "network/race_event_manager.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/stk_peer.hpp"
|
||||
@ -42,6 +44,7 @@
|
||||
#include "utils/time.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <fstream>
|
||||
|
||||
/** This is the central game setup protocol running in the server. It is
|
||||
@ -102,9 +105,9 @@ ServerLobby::~ServerLobby()
|
||||
} // ~ServerLobby
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ServerLobby::setup()
|
||||
{
|
||||
LobbyProtocol::setup();
|
||||
// We use maximum 16bit unsigned limit
|
||||
auto all_k = kart_properties_manager->getAllAvailableKarts();
|
||||
auto all_t = track_manager->getAllTrackIdentifiers();
|
||||
@ -116,24 +119,14 @@ void ServerLobby::setup()
|
||||
m_available_kts.second = { all_t.begin(), all_t.end() };
|
||||
|
||||
m_server_registered = false;
|
||||
m_game_setup = STKHost::get()->setupNewGame();
|
||||
m_game_setup->setNumLocalPlayers(0); // no local players on a server
|
||||
m_next_player_id.setAtomic(0);
|
||||
m_selection_enabled = false;
|
||||
Log::info("ServerLobby", "Starting the protocol.");
|
||||
|
||||
// Initialise the data structures to detect if all clients and
|
||||
// the server are ready:
|
||||
m_player_states.clear();
|
||||
m_client_ready_count.setAtomic(0);
|
||||
m_server_has_loaded_world = false;
|
||||
const std::vector<NetworkPlayerProfile*> &players =
|
||||
m_game_setup->getPlayers();
|
||||
for (unsigned int i = 0; i < players.size(); i++)
|
||||
{
|
||||
m_player_states[players[i]->getGlobalPlayerId()] = false;
|
||||
}
|
||||
|
||||
m_server_has_loaded_world.store(false);
|
||||
m_peers_ready.clear();
|
||||
m_server_delay = 0.0;
|
||||
Log::info("ServerLobby", "Reset server to initial state.");
|
||||
} // setup
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -302,12 +295,55 @@ void ServerLobby::asynchronousUpdate()
|
||||
STKHost::get()->requestShutdown();
|
||||
break;
|
||||
}
|
||||
case WAIT_FOR_WORLD_LOADED:
|
||||
{
|
||||
// m_server_has_loaded_world is set by main thread with atomic write
|
||||
if (m_server_has_loaded_world.load() == false)
|
||||
return;
|
||||
if (!checkPeersReady())
|
||||
return;
|
||||
m_state = WAIT_FOR_RACE_STARTED;
|
||||
// Reset for next state usage
|
||||
for (auto p : m_peers_ready)
|
||||
{
|
||||
p.second = false;
|
||||
}
|
||||
signalRaceStartToClients();
|
||||
break;
|
||||
}
|
||||
case WAIT_FOR_RACE_STARTED:
|
||||
// The function startedRaceOnClient() will trigger the
|
||||
// next state.
|
||||
break;
|
||||
case DELAY_SERVER:
|
||||
if (m_server_delay < StkTime::getRealTime())
|
||||
{
|
||||
Log::verbose("ServerLobby", "End delay at %lf",
|
||||
StkTime::getRealTime());
|
||||
m_state = RACING;
|
||||
World::getWorld()->setReadyToRace();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
} // asynchronousUpdate
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ServerLobby::checkPeersReady() const
|
||||
{
|
||||
bool all_ready = true;
|
||||
for (auto p : m_peers_ready)
|
||||
{
|
||||
if (p.first.expired())
|
||||
continue;
|
||||
all_ready = all_ready && p.second;
|
||||
if (!all_ready)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} // checkPeersReady
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Simple finite state machine. Once this
|
||||
* is known, register the server and its address with the stk server so that
|
||||
@ -317,12 +353,20 @@ void ServerLobby::update(float dt)
|
||||
{
|
||||
// Check if server owner has left
|
||||
updateServerOwner();
|
||||
|
||||
if (m_game_setup)
|
||||
{
|
||||
// Remove disconnected players if in these two states
|
||||
m_game_setup->update(m_state.load() == ACCEPTING_CLIENTS ||
|
||||
m_state.load() == SELECTING);
|
||||
}
|
||||
switch (m_state.load())
|
||||
{
|
||||
case SET_PUBLIC_ADDRESS:
|
||||
case REGISTER_SELF_ADDRESS:
|
||||
case ACCEPTING_CLIENTS:
|
||||
case WAIT_FOR_WORLD_LOADED:
|
||||
case WAIT_FOR_RACE_STARTED:
|
||||
case DELAY_SERVER:
|
||||
{
|
||||
// Waiting for asynchronousUpdate
|
||||
break;
|
||||
@ -337,33 +381,6 @@ void ServerLobby::update(float dt)
|
||||
loadWorld();
|
||||
m_state = WAIT_FOR_WORLD_LOADED;
|
||||
break;
|
||||
case WAIT_FOR_WORLD_LOADED:
|
||||
// Note that m_server_has_loaded_world is called by the main thread
|
||||
// (same as the thread updating this protocol)
|
||||
m_client_ready_count.lock();
|
||||
if (m_server_has_loaded_world &&
|
||||
m_client_ready_count.getData() == m_game_setup->getPlayerCount())
|
||||
{
|
||||
signalRaceStartToClients();
|
||||
m_client_ready_count.getData() = 0;
|
||||
}
|
||||
m_client_ready_count.unlock();
|
||||
// Initialise counter again, to wait for all clients to indicate that
|
||||
// they have started the race/
|
||||
break;
|
||||
case WAIT_FOR_RACE_STARTED:
|
||||
// The function startedRaceOnClient() will trigger the
|
||||
// next state.
|
||||
break;
|
||||
case DELAY_SERVER:
|
||||
if (m_server_delay < StkTime::getRealTime())
|
||||
{
|
||||
Log::verbose("ServerLobby", "End delay at %lf",
|
||||
StkTime::getRealTime());
|
||||
m_state = RACING;
|
||||
World::getWorld()->setReadyToRace();
|
||||
}
|
||||
break;
|
||||
case RACING:
|
||||
if (World::getWorld() &&
|
||||
RaceEventManager::getInstance<RaceEventManager>()->isRunning())
|
||||
@ -374,16 +391,6 @@ void ServerLobby::update(float dt)
|
||||
case RESULT_DISPLAY:
|
||||
if(StkTime::getRealTime() > m_timeout)
|
||||
{
|
||||
// Send a notification to all clients to exit
|
||||
// the race result screen
|
||||
NetworkString *exit_result_screen = getNetworkString(1);
|
||||
exit_result_screen->setSynchronous(true);
|
||||
exit_result_screen->addUInt8(LE_EXIT_RESULT);
|
||||
sendMessageToPeersChangingToken(exit_result_screen,
|
||||
/*reliable*/true);
|
||||
delete exit_result_screen;
|
||||
m_state = NetworkConfig::get()->isLAN() ?
|
||||
ACCEPTING_CLIENTS : REGISTER_SELF_ADDRESS;
|
||||
RaceResultGUI::getInstance()->backToLobby();
|
||||
// notify the network world that it is stopped
|
||||
RaceEventManager::getInstance()->stop();
|
||||
@ -394,6 +401,16 @@ void ServerLobby::update(float dt)
|
||||
pm->findAndTerminate(PROTOCOL_KART_UPDATE);
|
||||
pm->findAndTerminate(PROTOCOL_GAME_EVENTS);
|
||||
setup();
|
||||
m_state = NetworkConfig::get()->isLAN() ?
|
||||
ACCEPTING_CLIENTS : REGISTER_SELF_ADDRESS;
|
||||
// Send a notification to all clients to exit
|
||||
// the race result screen
|
||||
NetworkString *exit_result_screen = getNetworkString(1);
|
||||
exit_result_screen->setSynchronous(true);
|
||||
exit_result_screen->addUInt8(LE_EXIT_RESULT);
|
||||
sendMessageToPeersChangingToken(exit_result_screen,
|
||||
/*reliable*/true);
|
||||
delete exit_result_screen;
|
||||
}
|
||||
break;
|
||||
case ERROR_LEAVE:
|
||||
@ -502,7 +519,6 @@ void ServerLobby::signalRaceStartToClients()
|
||||
ns->addUInt8(LE_START_RACE);
|
||||
sendMessageToPeersChangingToken(ns, /*reliable*/true);
|
||||
delete ns;
|
||||
m_state = WAIT_FOR_RACE_STARTED;
|
||||
} // startGame
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -555,8 +571,6 @@ void ServerLobby::startSelection(const Event *event)
|
||||
sendMessageToPeersChangingToken(ns, /*reliable*/true);
|
||||
delete ns;
|
||||
|
||||
m_selection_enabled = true;
|
||||
|
||||
m_state = SELECTING;
|
||||
WaitingForOthersScreen::getInstance()->push();
|
||||
|
||||
@ -591,7 +605,7 @@ void ServerLobby::checkIncomingConnectionRequests()
|
||||
const TransportAddress &addr = STKHost::get()->getPublicAddress();
|
||||
request->addParameter("address", addr.getIP() );
|
||||
request->addParameter("port", addr.getPort());
|
||||
request->addParameter("current_players", STKHost::get()->getPeerCount());
|
||||
request->addParameter("current_players", m_game_setup->getPlayerCount());
|
||||
|
||||
request->executeNow();
|
||||
assert(request->isDone());
|
||||
@ -684,7 +698,9 @@ void ServerLobby::clientDisconnected(Event* event)
|
||||
msg->addUInt8((uint8_t)players_on_peer.size());
|
||||
for (auto p : players_on_peer)
|
||||
{
|
||||
msg->encodeString(p->getName());
|
||||
std::string name = StringUtils::wideToUtf8(p->getName());
|
||||
msg->encodeString(name);
|
||||
Log::info("ServerLobby", "%s disconnected", name.c_str());
|
||||
}
|
||||
sendMessageToPeersChangingToken(msg, /*reliable*/true);
|
||||
updatePlayerList();
|
||||
@ -852,6 +868,9 @@ void ServerLobby::connectionRequested(Event* event)
|
||||
peer->sendPacket(message_ack);
|
||||
delete message_ack;
|
||||
|
||||
m_peers_ready[peer] = false;
|
||||
for (std::shared_ptr<NetworkPlayerProfile> npp : peer->getPlayerProfiles())
|
||||
m_game_setup->addPlayer(npp);
|
||||
updatePlayerList();
|
||||
Log::verbose("ServerLobby", "New player.");
|
||||
|
||||
@ -922,74 +941,41 @@ void ServerLobby::updateServerOwner()
|
||||
} // updateServerOwner
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*! \brief Called when a player asks to select a kart.
|
||||
/*! \brief Called when a player asks to select karts.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2
|
||||
* ----------------------------------------------
|
||||
* Size | 1 | 1 | N |
|
||||
* Data |player id | N (kart name size) | kart name |
|
||||
* ----------------------------------------------
|
||||
*/
|
||||
void ServerLobby::kartSelectionRequested(Event* event)
|
||||
{
|
||||
if(m_state!=SELECTING)
|
||||
std::lock_guard<std::mutex> lock(m_connection_mutex);
|
||||
if (m_state != SELECTING)
|
||||
{
|
||||
Log::warn("Server", "Received kart selection while in state %d.",
|
||||
Log::warn("ServerLobby", "Received kart selection while in state %d.",
|
||||
m_state.load());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkDataSize(event, 1)) return;
|
||||
|
||||
const NetworkString &data = event->data();
|
||||
const NetworkString& data = event->data();
|
||||
STKPeer* peer = event->getPeer();
|
||||
|
||||
uint8_t player_id = data.getUInt8();
|
||||
std::string kart_name;
|
||||
data.decodeString(&kart_name);
|
||||
// check if selection is possible
|
||||
if (!m_selection_enabled)
|
||||
unsigned player_count = data.getUInt8();
|
||||
for (unsigned i = 0; i < player_count; i++)
|
||||
{
|
||||
NetworkString *answer = getNetworkString(2);
|
||||
// selection still not started
|
||||
answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(2);
|
||||
peer->sendPacket(answer);
|
||||
delete answer;
|
||||
return;
|
||||
std::string kart;
|
||||
data.decodeString(&kart);
|
||||
if (m_available_kts.first.find(kart) == m_available_kts.first.end())
|
||||
{
|
||||
Log::debug("ServerLobby", "Player %d from peer %d chose unknown "
|
||||
"kart %s, use a random one", i, peer->getHostId(),
|
||||
kart.c_str());
|
||||
RandomGenerator rg;
|
||||
std::set<std::string>::iterator it = m_available_kts.first.begin();
|
||||
std::advance(it, rg.get((int)m_available_kts.first.size()));
|
||||
kart = *it;
|
||||
}
|
||||
peer->getPlayerProfiles()[i]->setKartName(kart);
|
||||
Log::verbose("ServerLobby", "Player %d from peer %d chose %s", i,
|
||||
peer->getHostId(), kart.c_str());
|
||||
}
|
||||
// check if somebody picked that kart
|
||||
if (!m_game_setup->isKartAvailable(kart_name))
|
||||
{
|
||||
NetworkString *answer = getNetworkString(2);
|
||||
// kart is already taken
|
||||
answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(0);
|
||||
peer->sendPacket(answer);
|
||||
delete answer;
|
||||
return;
|
||||
}
|
||||
// check if this kart is authorized
|
||||
if (!m_game_setup->isKartAllowed(kart_name))
|
||||
{
|
||||
NetworkString *answer = getNetworkString(2);
|
||||
// kart is not authorized
|
||||
answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(1);
|
||||
peer->sendPacket(answer);
|
||||
delete answer;
|
||||
return;
|
||||
}
|
||||
|
||||
// send a kart update to everyone
|
||||
NetworkString *answer = getNetworkString(3+kart_name.size());
|
||||
// This message must be handled synchronously on the client.
|
||||
answer->setSynchronous(true);
|
||||
// kart update (3), 1, race id
|
||||
answer->addUInt8(LE_KART_SELECTION_UPDATE).addUInt8(player_id)
|
||||
.encodeString(kart_name);
|
||||
sendMessageToPeersChangingToken(answer);
|
||||
delete answer;
|
||||
m_game_setup->setPlayerKart(player_id, kart_name);
|
||||
} // kartSelectionRequested
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1179,7 +1165,7 @@ void ServerLobby::playerLapsVote(Event* event)
|
||||
*/
|
||||
void ServerLobby::finishedLoadingWorld()
|
||||
{
|
||||
m_server_has_loaded_world = true;
|
||||
m_server_has_loaded_world.store(true);
|
||||
} // finishedLoadingWorld;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1188,30 +1174,10 @@ void ServerLobby::finishedLoadingWorld()
|
||||
*/
|
||||
void ServerLobby::finishedLoadingWorldClient(Event *event)
|
||||
{
|
||||
if (!checkDataSize(event, 1)) return;
|
||||
|
||||
const NetworkString &data = event->data();
|
||||
uint8_t player_count = data.getUInt8();
|
||||
m_client_ready_count.lock();
|
||||
for (unsigned int i = 0; i < player_count; i++)
|
||||
{
|
||||
uint8_t player_id = data.getUInt8();
|
||||
if (m_player_states[player_id])
|
||||
{
|
||||
Log::error("ServerLobbyProtocol",
|
||||
"Player %d send more than one ready message.",
|
||||
player_id);
|
||||
m_client_ready_count.unlock();
|
||||
return;
|
||||
}
|
||||
m_player_states[player_id] = true;
|
||||
m_client_ready_count.getData()++;
|
||||
Log::info("ServerLobbyeProtocol", "Player %d is ready (%d/%d).",
|
||||
player_id, m_client_ready_count.getData(),
|
||||
m_game_setup->getPlayerCount());
|
||||
}
|
||||
m_client_ready_count.unlock();
|
||||
|
||||
std::shared_ptr<STKPeer> peer = event->getPeerSP();
|
||||
m_peers_ready.at(peer) = true;
|
||||
Log::info("ServerLobby", "Peer %d has finished loading world",
|
||||
peer->getHostId());
|
||||
} // finishedLoadingWorldClient
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1225,20 +1191,19 @@ void ServerLobby::finishedLoadingWorldClient(Event *event)
|
||||
*/
|
||||
void ServerLobby::startedRaceOnClient(Event *event)
|
||||
{
|
||||
m_client_ready_count.lock();
|
||||
Log::verbose("ServerLobby", "Host %d has started race at %lf.",
|
||||
event->getPeer()->getHostId(), StkTime::getRealTime());
|
||||
m_client_ready_count.getData()++;
|
||||
if (m_client_ready_count.getData() == m_game_setup->getPlayerCount())
|
||||
std::shared_ptr<STKPeer> peer = event->getPeerSP();
|
||||
m_peers_ready.at(peer) = true;
|
||||
Log::info("ServerLobby", "Peer %d has started race at %lf",
|
||||
peer->getHostId(), StkTime::getRealTime());
|
||||
|
||||
if (checkPeersReady())
|
||||
{
|
||||
m_state = DELAY_SERVER;
|
||||
m_server_delay = StkTime::getRealTime() + 0.1f;
|
||||
m_server_delay = StkTime::getRealTime() + 0.1;
|
||||
Log::verbose("ServerLobby", "Started delay at %lf set delay to %lf",
|
||||
StkTime::getRealTime(),
|
||||
m_server_delay);
|
||||
StkTime::getRealTime(), m_server_delay);
|
||||
terminateLatencyProtocol();
|
||||
}
|
||||
m_client_ready_count.unlock();
|
||||
} // startedRaceOnClient
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -3,9 +3,9 @@
|
||||
|
||||
#include "network/protocols/lobby_protocol.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
#include "utils/synchronised.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
@ -42,19 +42,12 @@ private:
|
||||
* with data in server first. */
|
||||
std::pair<std::set<std::string>, std::set<std::string> > m_available_kts;
|
||||
|
||||
/** Next id to assign to a peer. */
|
||||
Synchronised<int> m_next_player_id;
|
||||
|
||||
/** Keeps track of the server state. */
|
||||
bool m_server_has_loaded_world;
|
||||
std::atomic_bool m_server_has_loaded_world;
|
||||
|
||||
/** Counts how many clients have finished loading the world. */
|
||||
Synchronised<int> m_client_ready_count;
|
||||
|
||||
/** For debugging: keep track of the state (ready or not) of each player,
|
||||
* to make sure no client/player reports more than once. Needs to be a
|
||||
* map since the client IDs can be non-consecutive. */
|
||||
std::map<uint8_t, bool> m_player_states;
|
||||
/** Counts how many peers have finished loading the world. */
|
||||
std::map<std::weak_ptr<STKPeer>, bool,
|
||||
std::owner_less<std::weak_ptr<STKPeer> > > m_peers_ready;
|
||||
|
||||
/** Keeps track of an artificial server delay (which makes sure that the
|
||||
* data from all clients has arrived when the server computes a certain
|
||||
@ -62,8 +55,6 @@ private:
|
||||
* seconds), which is the real time at which the server should start. */
|
||||
double m_server_delay;
|
||||
|
||||
bool m_selection_enabled;
|
||||
|
||||
bool m_has_created_server_id_file;
|
||||
|
||||
/** It indicates if this server is registered with the stk server. */
|
||||
@ -101,6 +92,7 @@ private:
|
||||
void createServerIdFile();
|
||||
void updatePlayerList();
|
||||
void updateServerOwner();
|
||||
bool checkPeersReady() const;
|
||||
|
||||
public:
|
||||
ServerLobby();
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "config/user_config.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "network/event.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_console.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
@ -72,8 +73,9 @@ void STKHost::create(std::shared_ptr<Server> server, SeparateProcess* p)
|
||||
assert(m_stk_host == NULL);
|
||||
if (NetworkConfig::get()->isServer())
|
||||
{
|
||||
std::shared_ptr<ServerLobby> sl = LobbyProtocol::create<ServerLobby>();
|
||||
m_stk_host = new STKHost(NetworkConfig::get()->getServerName());
|
||||
LobbyProtocol::create<ServerLobby>()->requestStart();
|
||||
sl->requestStart();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -319,7 +321,6 @@ void STKHost::init()
|
||||
m_shutdown = false;
|
||||
m_authorised = false;
|
||||
m_network = NULL;
|
||||
m_game_setup = NULL;
|
||||
m_exit_timeout.store(std::numeric_limits<double>::max());
|
||||
|
||||
// Start with initialising ENet
|
||||
@ -351,10 +352,6 @@ STKHost::~STKHost()
|
||||
requestShutdown();
|
||||
if (m_network_console.joinable())
|
||||
m_network_console.join();
|
||||
// delete the game setup
|
||||
if (m_game_setup)
|
||||
delete m_game_setup;
|
||||
m_game_setup = NULL;
|
||||
|
||||
disconnectAllPeers(true/*timeout_waiting*/);
|
||||
Network::closeLog();
|
||||
@ -607,18 +604,6 @@ void STKHost::setPrivatePort()
|
||||
m_private_port = ntohs(sin.sin_port);
|
||||
} // setPrivatePort
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** A previous GameSetup is deletea and a new one is created.
|
||||
* \return Newly create GameSetup object.
|
||||
*/
|
||||
GameSetup* STKHost::setupNewGame()
|
||||
{
|
||||
if (m_game_setup)
|
||||
delete m_game_setup;
|
||||
m_game_setup = new GameSetup();
|
||||
return m_game_setup;
|
||||
} // setupNewGame
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Disconnect all connected peers.
|
||||
*/
|
||||
@ -730,7 +715,7 @@ void STKHost::mainLoop()
|
||||
auto sl = LobbyProtocol::get<ServerLobby>();
|
||||
if (direct_socket && sl && sl->waitingForPlayers())
|
||||
{
|
||||
handleDirectSocketRequest(direct_socket);
|
||||
handleDirectSocketRequest(direct_socket, sl);
|
||||
} // if discovery host
|
||||
|
||||
std::list<std::tuple<ENetPeer*, ENetPacket*, uint32_t,
|
||||
@ -847,7 +832,8 @@ void STKHost::mainLoop()
|
||||
* message is received, will answer with a message containing server details
|
||||
* (and sender IP address and port).
|
||||
*/
|
||||
void STKHost::handleDirectSocketRequest(Network* direct_socket)
|
||||
void STKHost::handleDirectSocketRequest(Network* direct_socket,
|
||||
std::shared_ptr<ServerLobby> sl)
|
||||
{
|
||||
const int LEN=2048;
|
||||
char buffer[LEN];
|
||||
@ -877,7 +863,7 @@ void STKHost::handleDirectSocketRequest(Network* direct_socket)
|
||||
s.addUInt8(NetworkConfig::m_server_version);
|
||||
s.encodeString(name);
|
||||
s.addUInt8(NetworkConfig::get()->getMaxPlayers());
|
||||
s.addUInt8(0); // FIXME: current number of connected players
|
||||
s.addUInt8((uint8_t)sl->getGameSetup()->getPlayerCount());
|
||||
s.addUInt16(m_private_port);
|
||||
s.addUInt8((uint8_t)race_manager->getDifficulty());
|
||||
s.addUInt8((uint8_t)
|
||||
@ -938,12 +924,6 @@ bool STKHost::peerExists(const TransportAddress& peer)
|
||||
return false;
|
||||
} // peerExists
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::vector<NetworkPlayerProfile*> STKHost::getMyPlayerProfiles()
|
||||
{
|
||||
return m_game_setup->getAllPlayersOnHost(m_host_id);
|
||||
} // getMyPlayerProfiles
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** \brief Return the only server peer for client.
|
||||
* \return STKPeer the STKPeer of server.
|
||||
|
@ -45,6 +45,7 @@
|
||||
class GameSetup;
|
||||
class NetworkPlayerProfile;
|
||||
class Server;
|
||||
class ServerLobby;
|
||||
class SeparateProcess;
|
||||
|
||||
enum ENetCommandType : unsigned int
|
||||
@ -104,9 +105,6 @@ private:
|
||||
/** Host id of this host. */
|
||||
uint32_t m_host_id = 0;
|
||||
|
||||
/** Stores data about the online game to play. */
|
||||
GameSetup* m_game_setup;
|
||||
|
||||
/** Id of thread listening to enet events. */
|
||||
std::thread m_listening_thread;
|
||||
|
||||
@ -133,17 +131,22 @@ private:
|
||||
/** The private port enet socket is bound. */
|
||||
uint16_t m_private_port;
|
||||
|
||||
STKHost(std::shared_ptr<Server> server);
|
||||
STKHost(const irr::core::stringw &server_name);
|
||||
virtual ~STKHost();
|
||||
// ------------------------------------------------------------------------
|
||||
STKHost(std::shared_ptr<Server> server);
|
||||
// ------------------------------------------------------------------------
|
||||
STKHost(const irr::core::stringw &server_name);
|
||||
// ------------------------------------------------------------------------
|
||||
~STKHost();
|
||||
// ------------------------------------------------------------------------
|
||||
void init();
|
||||
void handleDirectSocketRequest(Network* direct_socket);
|
||||
// ------------------------------------------------------------------------
|
||||
void handleDirectSocketRequest(Network* direct_socket,
|
||||
std::shared_ptr<ServerLobby> sl);
|
||||
// ------------------------------------------------------------------------
|
||||
void mainLoop();
|
||||
|
||||
public:
|
||||
/** If a network console should be started. Note that the console can cause
|
||||
* a crash in release mode on windows (see #1529). */
|
||||
/** If a network console should be started. */
|
||||
static bool m_enable_console;
|
||||
|
||||
/** Creates the STKHost. It takes all confifguration parameters from
|
||||
@ -181,8 +184,6 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
void setPublicAddress();
|
||||
// ------------------------------------------------------------------------
|
||||
GameSetup* setupNewGame();
|
||||
// ------------------------------------------------------------------------
|
||||
void disconnectAllPeers(bool timeout_waiting = false);
|
||||
// ------------------------------------------------------------------------
|
||||
bool connect(const TransportAddress& peer);
|
||||
@ -217,19 +218,25 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
std::shared_ptr<STKPeer> findPeerByHostId(uint32_t id) const;
|
||||
// ------------------------------------------------------------------------
|
||||
void sendPacketExcept(STKPeer* peer,
|
||||
NetworkString *data,
|
||||
void sendPacketExcept(STKPeer* peer, NetworkString *data,
|
||||
bool reliable = true);
|
||||
void setupClient(int peer_count, int channel_limit,
|
||||
uint32_t max_incoming_bandwidth,
|
||||
uint32_t max_outgoing_bandwidth);
|
||||
void startListening();
|
||||
void stopListening();
|
||||
bool peerExists(const TransportAddress& peer_address);
|
||||
bool isConnectedTo(const TransportAddress& peer_address);
|
||||
// ------------------------------------------------------------------------
|
||||
void setupClient(int peer_count, int channel_limit,
|
||||
uint32_t max_incoming_bandwidth,
|
||||
uint32_t max_outgoing_bandwidth);
|
||||
// ------------------------------------------------------------------------
|
||||
void startListening();
|
||||
// ------------------------------------------------------------------------
|
||||
void stopListening();
|
||||
// ------------------------------------------------------------------------
|
||||
bool peerExists(const TransportAddress& peer_address);
|
||||
// ------------------------------------------------------------------------
|
||||
bool isConnectedTo(const TransportAddress& peer_address);
|
||||
// ------------------------------------------------------------------------
|
||||
std::shared_ptr<STKPeer> getServerPeerForClient() const;
|
||||
std::vector<NetworkPlayerProfile*> getMyPlayerProfiles();
|
||||
void setErrorMessage(const irr::core::stringw &message);
|
||||
// ------------------------------------------------------------------------
|
||||
void setErrorMessage(const irr::core::stringw &message);
|
||||
// ------------------------------------------------------------------------
|
||||
void addEnetCommand(ENetPeer* peer, ENetPacket* packet, uint32_t i,
|
||||
ENetCommandType ect)
|
||||
{
|
||||
@ -245,9 +252,6 @@ public:
|
||||
* requested. */
|
||||
bool requestedShutdown() const { return m_shutdown.load(); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the current game setup. */
|
||||
GameSetup* getGameSetup() { return m_game_setup; }
|
||||
// ------------------------------------------------------------------------
|
||||
int receiveRawPacket(char *buffer, int buffer_len,
|
||||
TransportAddress* sender, int max_tries = -1)
|
||||
{
|
||||
|
@ -86,8 +86,8 @@ public:
|
||||
bool isSamePeer(const STKPeer* peer) const;
|
||||
bool isSamePeer(const ENetPeer* peer) const;
|
||||
// ------------------------------------------------------------------------
|
||||
std::vector<std::shared_ptr<NetworkPlayerProfile> >
|
||||
getPlayerProfiles() const { return m_players; }
|
||||
std::vector<std::shared_ptr<NetworkPlayerProfile> >& getPlayerProfiles()
|
||||
{ return m_players; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool hasPlayerProfiles() const { return !m_players.empty(); }
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "items/item_manager.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_player_profile.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
@ -71,16 +72,13 @@ void NetworkKartSelectionScreen::init()
|
||||
back_button->setImage("gui/main_quit.png");
|
||||
|
||||
// add a widget for each player except self (already exists):
|
||||
GameSetup* setup = STKHost::get()->getGameSetup();
|
||||
if (!setup)
|
||||
GameSetup* game_setup = LobbyProtocol::get<LobbyProtocol>()->getGameSetup();
|
||||
if (!game_setup)
|
||||
{
|
||||
Log::error("NetworkKartSelectionScreen",
|
||||
"No network game setup registered.");
|
||||
return;
|
||||
}
|
||||
std::vector<NetworkPlayerProfile*> players = setup->getPlayers();
|
||||
|
||||
Log::info("NKSS", "There are %d players", players.size());
|
||||
// ---- Get available area for karts
|
||||
// make a copy of the area, ands move it to be outside the screen
|
||||
Widget* kartsAreaWidget = getWidget("playerskarts");
|
||||
@ -90,7 +88,6 @@ void NetworkKartSelectionScreen::init()
|
||||
kartsAreaWidget->m_y,
|
||||
kartsAreaWidget->m_x + shift + kartsAreaWidget->m_w,
|
||||
kartsAreaWidget->m_y + kartsAreaWidget->m_h);
|
||||
GameSetup *game_setup = STKHost::get()->getGameSetup();
|
||||
|
||||
// FIXME: atm only adds the local master, split screen supports
|
||||
// needs to be added
|
||||
@ -115,7 +112,6 @@ void NetworkKartSelectionScreen::init()
|
||||
assert(w != NULL);
|
||||
w->setSelection(UserConfigParams::m_default_kart, /*player id*/0, /*focus*/true);
|
||||
playerConfirm(0);
|
||||
RaceSetupScreen::getInstance()->push();
|
||||
}
|
||||
|
||||
} // init
|
||||
@ -142,81 +138,21 @@ void NetworkKartSelectionScreen::playerConfirm(const int playerID)
|
||||
SFXManager::get()->quickSound( "anvil" );
|
||||
return;
|
||||
}
|
||||
if(playerID == PLAYER_ID_GAME_MASTER) // self
|
||||
if (playerID == PLAYER_ID_GAME_MASTER) // self
|
||||
{
|
||||
auto clrp = LobbyProtocol::get<ClientLobby>();
|
||||
assert(clrp);
|
||||
// FIXME SPLITSCREEN: we need to supply the global player id of the
|
||||
// player selecting the kart here. For now ... just vote the same kart
|
||||
// for each local player.
|
||||
std::vector<NetworkPlayerProfile*> players =
|
||||
STKHost::get()->getMyPlayerProfiles();
|
||||
for(unsigned int i=0; i<players.size(); i++)
|
||||
{
|
||||
clrp->requestKartSelection(players[i]->getGlobalPlayerId(),
|
||||
selection );
|
||||
}
|
||||
uint8_t player_count = 1;
|
||||
NetworkString kart(PROTOCOL_LOBBY_ROOM);
|
||||
kart.addUInt8(LobbyProtocol::LE_KART_SELECTION).addUInt8(player_count)
|
||||
.encodeString(selection);
|
||||
STKHost::get()->sendToServer(&kart, true);
|
||||
input_manager->getDeviceManager()->setAssignMode(ASSIGN);
|
||||
TracksScreen::getInstance()->push();
|
||||
}
|
||||
} // playerConfirm
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void NetworkKartSelectionScreen::playerSelected(uint8_t player_id,
|
||||
const std::string &kart_name)
|
||||
{
|
||||
int widget_id = -1;
|
||||
for (unsigned int i = 0; i < m_id_mapping.size(); i++)
|
||||
{
|
||||
Log::info("NKSS", "Checking race id %d : mapped of %d is %d",
|
||||
player_id, i, m_id_mapping[i]);
|
||||
if (m_id_mapping[i] == player_id)
|
||||
widget_id = i;
|
||||
}
|
||||
|
||||
// This selection was for a remote kart, which is not shown
|
||||
// Just ignore it.
|
||||
if(widget_id==-1)
|
||||
return;
|
||||
|
||||
// In case of auto-connect the screen is already replaced, so
|
||||
// m_kart_widget is empty.
|
||||
if (! STKHost::get()->isAuthorisedToControl())
|
||||
{
|
||||
KartSelectionScreen::updateKartWidgetModel(widget_id, kart_name,
|
||||
irr::core::stringw(kart_name.c_str()),
|
||||
/*Todo get color*/0.0f);
|
||||
KartSelectionScreen::updateKartStats(widget_id, kart_name);
|
||||
m_kart_widgets[widget_id].setKartInternalName(kart_name);
|
||||
m_kart_widgets[widget_id].markAsReady(); // mark player ready
|
||||
}
|
||||
|
||||
// If this is the authorised client, send the currently set race config
|
||||
// to the server.
|
||||
if(STKHost::get()->isAuthorisedToControl())
|
||||
{
|
||||
auto clrp = LobbyProtocol::get<ClientLobby>();
|
||||
assert(clrp);
|
||||
// FIXME: for now we submit a vote from the authorised user
|
||||
// for the various modes based on the settings in the race manager.
|
||||
// This needs more/better gui elements (and some should be set when
|
||||
// defining the server).
|
||||
std::vector<NetworkPlayerProfile*> players =
|
||||
STKHost::get()->getMyPlayerProfiles();
|
||||
for(unsigned int i=0; i<players.size(); i++)
|
||||
{
|
||||
uint8_t id = players[i]->getGlobalPlayerId();
|
||||
clrp->voteMajor(id, race_manager->getMajorMode());
|
||||
clrp->voteMinor(id, race_manager->getMinorMode());
|
||||
clrp->voteReversed(id, race_manager->getReverseTrack());
|
||||
clrp->voteRaceCount(id, 1);
|
||||
clrp->voteLaps(id, 1);
|
||||
}
|
||||
//WaitingForOthersScreen::getInstance()->push();
|
||||
//return;
|
||||
}
|
||||
TracksScreen::getInstance()->push();
|
||||
} // playerSelected
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool NetworkKartSelectionScreen::onEscapePressed()
|
||||
{
|
||||
|
@ -50,8 +50,6 @@ public:
|
||||
}
|
||||
virtual void init() OVERRIDE;
|
||||
virtual bool onEscapePressed() OVERRIDE;
|
||||
virtual void playerSelected(uint8_t player_id,
|
||||
const std::string &kart_name);
|
||||
};
|
||||
|
||||
#endif // NETWORK_KART_SELECTION_HPP
|
||||
|
@ -96,13 +96,13 @@ void TracksScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
// FIXME SPLITSCREEN: we need to supply the global player id of the
|
||||
// player selecting the track here. For now ... just vote the same
|
||||
// track for each local player.
|
||||
std::vector<NetworkPlayerProfile*> players =
|
||||
/*std::vector<NetworkPlayerProfile*> players =
|
||||
STKHost::get()->getMyPlayerProfiles();
|
||||
for(unsigned int i=0; i<players.size(); i++)
|
||||
{
|
||||
clrp->voteTrack(players[i]->getGlobalPlayerId(),selection);
|
||||
}
|
||||
WaitingForOthersScreen::getInstance()->push();
|
||||
WaitingForOthersScreen::getInstance()->push();*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -16,89 +16,38 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "states_screens/waiting_for_others.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "guiengine/widget.hpp"
|
||||
#include "guiengine/widgets/label_widget.hpp"
|
||||
#include "input/device_manager.hpp"
|
||||
#include "input/input_manager.hpp"
|
||||
#include "input/keyboard_device.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_player_profile.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/stk_peer.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
|
||||
using namespace GUIEngine;
|
||||
|
||||
DEFINE_SCREEN_SINGLETON( WaitingForOthersScreen );
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
WaitingForOthersScreen::WaitingForOthersScreen() : Screen("online/waiting_for_others.stkgui")
|
||||
WaitingForOthersScreen::WaitingForOthersScreen()
|
||||
: Screen("online/waiting_for_others.stkgui")
|
||||
{
|
||||
} // WaitingForOthersScreen
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void WaitingForOthersScreen::loadedFromFile()
|
||||
{
|
||||
} // loadedFromFile
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void WaitingForOthersScreen::eventCallback(Widget* widget, const std::string& name, const int playerID)
|
||||
void WaitingForOthersScreen::eventCallback(Widget* widget,
|
||||
const std::string& name,
|
||||
const int player_id)
|
||||
{
|
||||
} // eventCallback
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void WaitingForOthersScreen::init()
|
||||
{
|
||||
Screen::init();
|
||||
} //init
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void WaitingForOthersScreen::onUpdate(float dt)
|
||||
{
|
||||
const GameSetup *setup = STKHost::get()->getGameSetup();
|
||||
const std::vector<NetworkPlayerProfile*> &all_profiles = setup->getPlayers();
|
||||
|
||||
RaceConfig* config = STKHost::get()->getGameSetup()->getRaceConfig();
|
||||
core::stringw w;
|
||||
for (unsigned int i = 0; i < all_profiles.size(); i++)
|
||||
{
|
||||
const NetworkPlayerProfile* profile = all_profiles[i];
|
||||
if (profile == NULL)
|
||||
continue;
|
||||
core::stringw name = profile->getName();
|
||||
|
||||
|
||||
int playerId = profile->getGlobalPlayerId();
|
||||
const std::string &kart = profile->getKartName();
|
||||
if (!kart.empty())
|
||||
name += StringUtils::insertValues(L" (%s)", core::stringw(kart.c_str()));
|
||||
|
||||
w += name + L" : ";
|
||||
const RaceVote& vote = config->getRaceVote(playerId);
|
||||
if (vote.hasVotedTrack())
|
||||
{
|
||||
w += vote.getTrackVote().c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
w += L"...";
|
||||
}
|
||||
|
||||
w += "\n";
|
||||
}
|
||||
|
||||
GUIEngine::LabelWidget* lbl = getWidget<GUIEngine::LabelWidget>("lblDetails");
|
||||
lbl->setText(w.c_str(), true);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user