diff --git a/src/network/game_setup.hpp b/src/network/game_setup.hpp index e75ed32a8..047192421 100644 --- a/src/network/game_setup.hpp +++ b/src/network/game_setup.hpp @@ -25,13 +25,13 @@ #include "network/race_config.hpp" #include "network/remote_kart_info.hpp" -#include +#include +#include #include +#include -namespace Online { class OnlineProfile; } class NetworkPlayerProfile; - // ============================================================================ /*! \class GameSetup * \brief Used to store the needed data about the players that join a game. diff --git a/src/network/network_player_profile.cpp b/src/network/network_player_profile.cpp index 303aa56c2..f7f1c2425 100644 --- a/src/network/network_player_profile.cpp +++ b/src/network/network_player_profile.cpp @@ -19,31 +19,6 @@ #include "network/network_player_profile.hpp" #include "network/stk_host.hpp" -#include "online/online_player_profile.hpp" - -/** Constructor. - * \param global_player_id A unique number assigned from the server to this - * player (though it might not be the index in the peer list). - * \param name Name of this player. - * \param global_player_id Global id of this player. - * \param host_id The id of the host the player is connected from. - */ -NetworkPlayerProfile::NetworkPlayerProfile(const irr::core::stringw &name, - int global_player_id, - int host_id ) -{ - m_global_player_id = global_player_id; - m_host_id = host_id; - m_kart_name = ""; - m_world_kart_id = 0; - m_per_player_difficulty = PLAYER_DIFFICULTY_NORMAL; - m_player_name = name; -} // BetworkPlayerProfile - -// ---------------------------------------------------------------------------- -NetworkPlayerProfile::~NetworkPlayerProfile() -{ -} // ~NetworkPlayerProfile // ---------------------------------------------------------------------------- /** Returns true if this player is local, i.e. running on this computer. This * is done by comparing the host id of this player with the host id of this @@ -52,4 +27,4 @@ NetworkPlayerProfile::~NetworkPlayerProfile() bool NetworkPlayerProfile::isLocalPlayer() const { return m_host_id == STKHost::get()->getMyHostId(); -} // isLocalPlayer \ No newline at end of file +} // isLocalPlayer diff --git a/src/network/network_player_profile.hpp b/src/network/network_player_profile.hpp index 13ce72121..65522b24c 100644 --- a/src/network/network_player_profile.hpp +++ b/src/network/network_player_profile.hpp @@ -26,10 +26,11 @@ #include "utils/types.hpp" #include "irrString.h" - +#include #include -namespace Online { class OnlineProfile; } +#include +class STKPeer; /*! \class NetworkPlayerProfile * \brief Contains the profile of a player. @@ -37,31 +38,51 @@ namespace Online { class OnlineProfile; } class NetworkPlayerProfile { private: + std::weak_ptr m_peer; + + /** The name of the player. */ + irr::core::stringw m_player_name; + + /** Host id of this player. */ + uint32_t m_host_id; + + float m_default_kart_color; + + uint32_t m_online_id; + + /** Per player difficulty. */ + PerPlayerDifficulty m_per_player_difficulty; + + /** The selected kart id. */ + std::string m_kart_name; + /** The unique id of the player for this race. The number is assigned * by the server (and it might not be the index of this player in the * peer list. */ uint8_t m_global_player_id; - /** Host id of this player. */ - uint8_t m_host_id; - - /** The selected kart id. */ - std::string m_kart_name; - - /** The name of the player. */ - irr::core::stringw m_player_name; - /** The kart id in the World class (pointer to AbstractKart). */ uint8_t m_world_kart_id; - /** Per player difficulty. */ - PerPlayerDifficulty m_per_player_difficulty; public: - NetworkPlayerProfile(const irr::core::stringw &name, - int global_player_id, int host_id); - ~NetworkPlayerProfile(); + NetworkPlayerProfile(std::shared_ptr peer, + const irr::core::stringw &name, uint32_t host_id, + float default_kart_color, uint32_t online_id, + PerPlayerDifficulty per_player_difficulty) + { + m_peer = peer; + m_player_name = name; + m_host_id = host_id; + m_default_kart_color = default_kart_color; + m_online_id = online_id; + m_per_player_difficulty = per_player_difficulty; + m_global_player_id = 0; + m_world_kart_id = 0; + } + // ------------------------------------------------------------------------ + ~NetworkPlayerProfile() {} + // ------------------------------------------------------------------------ bool isLocalPlayer() const; - // ------------------------------------------------------------------------ /** Sets the global player id of this player. */ void setGlobalPlayerId(int player_id) { m_global_player_id = player_id; } @@ -93,6 +114,15 @@ public: /** Returns the name of this player. */ const irr::core::stringw& getName() const { return m_player_name; } // ------------------------------------------------------------------------ + float getDefaultKartColor() const { return m_default_kart_color; } + // ------------------------------------------------------------------------ + uint32_t getOnlineID() const { return m_online_id; } + // ------------------------------------------------------------------------ + std::shared_ptr getPeer() const { return m_peer.lock(); } + // ------------------------------------------------------------------------ + /** Returns the minimun info for networking lobby screen. */ + std::tuple toTuple() const + { return std::make_tuple(m_host_id, m_online_id, m_player_name); } }; // class NetworkPlayerProfile diff --git a/src/network/protocols/client_lobby.cpp b/src/network/protocols/client_lobby.cpp index ee5256cdf..80014cdec 100644 --- a/src/network/protocols/client_lobby.cpp +++ b/src/network/protocols/client_lobby.cpp @@ -20,6 +20,7 @@ #include "config/player_manager.hpp" #include "karts/kart_properties_manager.hpp" +#include "guiengine/message_queue.hpp" #include "modes/world_with_rank.hpp" #include "network/event.hpp" #include "network/network_config.hpp" @@ -29,6 +30,7 @@ #include "network/race_event_manager.hpp" #include "network/stk_host.hpp" #include "network/stk_peer.hpp" +#include "online/online_player_profile.hpp" #include "online/online_profile.hpp" #include "states_screens/networking_lobby.hpp" #include "states_screens/network_kart_selection.hpp" @@ -201,13 +203,6 @@ void ClientLobby::voteLaps(uint8_t player_id, uint8_t laps, delete request; } // voteLaps -//----------------------------------------------------------------------------- -/** Called when a client selects to exit a server. - */ -void ClientLobby::leave() -{ -} // leave - //----------------------------------------------------------------------------- /** Called from the gui when a client clicked on 'continue' on the race result * screen. It notifies the server that this client has exited the screen and @@ -239,6 +234,7 @@ bool ClientLobby::notifyEvent(Event* event) case LE_LOAD_WORLD: loadWorld(); break; case LE_RACE_FINISHED: raceFinished(event); break; case LE_EXIT_RESULT: exitResultScreen(event); break; + case LE_UPDATE_PLAYER_LIST: updatePlayerList(event); break; default: return false; break; @@ -261,7 +257,6 @@ bool ClientLobby::notifyEventAsynchronous(Event* event) message_type); switch(message_type) { - case LE_NEW_PLAYER_CONNECTED: newPlayer(event); break; case LE_PLAYER_DISCONNECTED : disconnectedPlayer(event); break; case LE_START_RACE: startGame(event); break; case LE_CONNECTION_REFUSED: connectionRefused(event); break; @@ -273,6 +268,7 @@ bool ClientLobby::notifyEventAsynchronous(Event* event) case LE_VOTE_TRACK: playerTrackVote(event); break; case LE_VOTE_REVERSE: playerReversedVote(event); break; case LE_VOTE_LAPS: playerLapsVote(event); break; + case LE_AUTHORISED: becomingServerOwner(); break; } // switch return true; @@ -321,20 +317,31 @@ void ClientLobby::update(float dt) break; case LINKED: { - core::stringw name; - if(PlayerManager::getCurrentOnlineState()==PlayerProfile::OS_SIGNED_IN) - name = PlayerManager::getCurrentOnlineUserName(); - else - name = PlayerManager::getCurrentPlayer()->getName(); - - std::string name_u8 = StringUtils::wideToUtf8(name); - const std::string &password = NetworkConfig::get()->getPassword(); - NetworkString *ns = getNetworkString(6+1+name_u8.size() - +1+password.size()); - // 4 (size of id), global id - ns->addUInt8(LE_CONNECTION_REQUESTED).encodeString(name) - .encodeString(NetworkConfig::get()->getPassword()); + // atm assume only 1 local player (no split screen yet) + NetworkString *ns = getNetworkString(); + ns->addUInt8(LE_CONNECTION_REQUESTED) + .encodeString(NetworkConfig::get()->getPassword()); + uint8_t num_player = 1; + ns->addUInt8(num_player); + for (unsigned i = 0; i < num_player; i++) + { + core::stringw name; + PlayerProfile* player = PlayerManager::getCurrentPlayer(); + if (PlayerManager::getCurrentOnlineState() == + PlayerProfile::OS_SIGNED_IN) + name = PlayerManager::getCurrentOnlineUserName(); + else + name = player->getName(); + std::string name_u8 = StringUtils::wideToUtf8(name); + ns->encodeString(name_u8).addFloat(player->getDefaultKartColor()); + Online::OnlinePlayerProfile* opp = + dynamic_cast(player); + ns->addUInt32(opp && opp->getProfile() ? + opp->getProfile()->getID() : 0); + // Assume no handicap player now + ns->addUInt8(PLAYER_DIFFICULTY_NORMAL); + } auto all_k = kart_properties_manager->getAllAvailableKarts(); auto all_t = track_manager->getAllTrackIdentifiers(); if (all_k.size() >= 65536) @@ -389,49 +396,6 @@ void ClientLobby::update(float dt) //----------------------------------------------------------------------------- -/*! \brief Called when a new player is connected to the server - * \param event : Event providing the information. - * - * Format of the data : - * Byte 0 1 2 - * ------------------------------------- - * Size | 1 | 1 | | - * Data | player_id | hostid | player name | - * ------------------------------------- - */ -void ClientLobby::newPlayer(Event* event) -{ - if (!checkDataSize(event, 2)) return; - const NetworkString &data = event->data(); - - uint8_t player_id = data.getUInt8(); - uint8_t host_id = data.getUInt8(); - core::stringw name; - data.decodeStringW(&name); - // FIXME need adjusting when splitscreen is used/ - if(STKHost::get()->getGameSetup()->isLocalMaster(player_id)) - { - Log::error("ClientLobby", - "The server notified me that I'm a new player in the " - "room (not normal)."); - } - else if (m_game_setup->getProfile(player_id) == NULL) - { - Log::verbose("ClientLobby", "New player connected."); - NetworkPlayerProfile* profile = - new NetworkPlayerProfile(name, player_id, host_id); - m_game_setup->addPlayer(profile); - NetworkingLobby::getInstance()->addPlayer(profile); - } - else - { - Log::error("ClientLobby", - "One of the player notified in the list is myself."); - } -} // newPlayer - -//----------------------------------------------------------------------------- - /*! \brief Called when a new player is disconnected * \param event : Event providing the information. * @@ -447,95 +411,67 @@ void ClientLobby::disconnectedPlayer(Event* event) if (!checkDataSize(event, 1)) return; NetworkString &data = event->data(); - while(data.size()>0) + unsigned disconnected_player_count = data.getUInt8(); + for (unsigned i = 0; i < disconnected_player_count; i++) { - const NetworkPlayerProfile *profile = - m_game_setup->getProfile(data.getUInt8()); - if (m_game_setup->removePlayer(profile)) - { - Log::info("ClientLobby", - "Player %d removed successfully.", - profile->getGlobalPlayerId()); - } - else - { - Log::error("ClientLobby", - "The disconnected peer wasn't known."); - } - } // while + core::stringw player_name; + data.decodeStringW(&player_name); + core::stringw msg = _("%s disconnected.", player_name); + // Use the friend icon to avoid an error-like message + MessageQueue::add(MessageQueue::MT_FRIEND, msg); + } } // disconnectedPlayer //----------------------------------------------------------------------------- - /*! \brief Called when the server accepts the connection. * \param event : Event providing the information. - * - * Format of the data : - * Byte 0 1 2 3 - * --------------------------------------------------------- - * Size | 1 | 1 | 1 | | - * Data | player_id| hostid | authorised |playernames* | - * --------------------------------------------------------- */ void ClientLobby::connectionAccepted(Event* event) { - // At least 3 bytes should remain now - if(!checkDataSize(event, 3)) return; + // At least 4 byte should remain now + if (!checkDataSize(event, 4)) return; NetworkString &data = event->data(); STKPeer* peer = event->getPeer(); // Accepted // ======== - Log::info("ClientLobby", - "The server accepted the connection."); + Log::info("ClientLobby", "The server accepted the connection."); - // self profile - irr::core::stringw name; - if (PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_IN) - name = PlayerManager::getCurrentOnlineUserName(); - else - name = PlayerManager::getCurrentPlayer()->getName(); - uint8_t my_player_id = data.getUInt8(); - uint8_t my_host_id = data.getUInt8(); - uint8_t authorised = data.getUInt8(); - // Store this client's authorisation status in the peer information - // for the server. - event->getPeer()->setAuthorised(authorised!=0); - STKHost::get()->setMyHostId(my_host_id); - - NetworkPlayerProfile* profile = - new NetworkPlayerProfile(name, my_player_id, my_host_id); - STKHost::get()->getGameSetup()->setLocalMaster(my_player_id); + STKHost::get()->setMyHostId(data.getUInt32()); m_game_setup->setNumLocalPlayers(1); // connection token uint32_t token = data.getToken(); peer->setClientServerToken(token); - - // Add all players - // =============== - while (data.size() > 0) - { - uint8_t player_id = data.getUInt8(); - uint8_t host_id = data.getUInt8(); - irr::core::stringw name; - data.decodeStringW(&name); - - NetworkPlayerProfile* profile2 = - new NetworkPlayerProfile(name, player_id, host_id); - m_game_setup->addPlayer(profile2); - // Inform the network lobby of all players so that the GUI can - // show all currently connected players. - NetworkingLobby::getInstance()->addPlayer(profile2); - } - - // Add self after other players so that player order is identical - // on server and all clients. - m_game_setup->addPlayer(profile); - NetworkingLobby::getInstance()->addPlayer(profile); m_state = CONNECTED; - if (NetworkConfig::get()->isAutoConnect()) +} // connectionAccepted + +//----------------------------------------------------------------------------- +void ClientLobby::updatePlayerList(Event* event) +{ + if (!checkDataSize(event, 1)) return; + NetworkString &data = event->data(); + unsigned player_count = data.getUInt8(); + NetworkingLobby::getInstance()->cleanPlayers(); + for (unsigned i = 0; i < player_count; i++) + { + std::tuple pl; + std::get<0>(pl) = data.getUInt32(); + std::get<1>(pl) = data.getUInt32(); + data.decodeStringW(&std::get<2>(pl)); + std::get<3>(pl) = data.getUInt8() == 1; + NetworkingLobby::getInstance()->addPlayer(pl); + } +} // updatePlayerList + +//----------------------------------------------------------------------------- +void ClientLobby::becomingServerOwner() +{ + MessageQueue::add(MessageQueue::MT_GENERIC, + _("You are now the owner of server.")); + STKHost::get()->setAuthorisedToControl(true); + if (m_state == CONNECTED && NetworkConfig::get()->isAutoConnect()) { // Send a message to the server to start NetworkString start(PROTOCOL_LOBBY_ROOM); @@ -543,8 +479,7 @@ void ClientLobby::connectionAccepted(Event* event) start.addUInt8(LobbyProtocol::LE_REQUEST_BEGIN); STKHost::get()->sendToServer(&start, true); } - -} // connectionAccepted +} // becomingServerOwner //----------------------------------------------------------------------------- @@ -562,26 +497,31 @@ void ClientLobby::connectionRefused(Event* event) { if (!checkDataSize(event, 1)) return; const NetworkString &data = event->data(); - - switch (data.getUInt8()) // the second byte + switch ((RejectReason)data.getUInt8()) // the second byte { - case 0: - Log::info("ClientLobby", - "Connection refused : too many players."); + case RR_BUSY: + STKHost::get()->setErrorMessage( + _("Connection refused: Server is busy.")); break; - case 1: - Log::info("ClientLobby", "Connection refused : banned."); + case RR_BANNED: + STKHost::get()->setErrorMessage( + _("Connection refused: You are banned from the server.")); break; - case 2: - Log::info("ClientLobby", "Client busy."); + case RR_INCORRECT_PASSWORD: + STKHost::get()->setErrorMessage( + _("Connection refused: Server password is incorrect.")); break; - case 3: - Log::info("ClientLobby", "Having incompatible karts / tracks."); + case RR_INCOMPATIBLE_DATA: + STKHost::get()->setErrorMessage( + _("Connection refused: Game data is incompatible.")); break; - default: - Log::info("ClientLobby", "Connection refused."); + case RR_TOO_MANY_PLAYERS: + STKHost::get()->setErrorMessage( + _("Connection refused: Server is full.")); break; } + STKHost::get()->disconnectAllPeers(false/*timeout_waiting*/); + STKHost::get()->requestShutdown(); } // connectionRefused //----------------------------------------------------------------------------- diff --git a/src/network/protocols/client_lobby.hpp b/src/network/protocols/client_lobby.hpp index 253c0cf99..29d960394 100644 --- a/src/network/protocols/client_lobby.hpp +++ b/src/network/protocols/client_lobby.hpp @@ -9,7 +9,6 @@ class ClientLobby : public LobbyProtocol { private: - void newPlayer(Event* event); void disconnectedPlayer(Event* event); void connectionAccepted(Event* event); //!< Callback function on connection acceptation void connectionRefused(Event* event); //!< Callback function on connection refusal @@ -26,6 +25,8 @@ private: void playerTrackVote(Event* event); void playerReversedVote(Event* event); void playerLapsVote(Event* event); + void updatePlayerList(Event* event); + void becomingServerOwner(); TransportAddress m_server_address; @@ -65,7 +66,6 @@ public: void voteLaps(uint8_t player_id, uint8_t laps, uint8_t track_nb = 0); void doneWithResults(); void startingRaceNow(); - void leave(); const std::set& getAvailableKarts() const { return m_available_karts; } diff --git a/src/network/protocols/lobby_protocol.hpp b/src/network/protocols/lobby_protocol.hpp index ac5020e04..56e701299 100644 --- a/src/network/protocols/lobby_protocol.hpp +++ b/src/network/protocols/lobby_protocol.hpp @@ -42,7 +42,7 @@ public: LE_KART_SELECTION_UPDATE, // inform client about kart selected LE_REQUEST_BEGIN, // begin of kart selection LE_KART_SELECTION_REFUSED, // Client not auth. to start selection - LE_NEW_PLAYER_CONNECTED, // inform client about new player + LE_UPDATE_PLAYER_LIST, // inform client about player list update LE_KART_SELECTION, // Player selected kart LE_PLAYER_DISCONNECTED, // Client disconnected LE_CLIENT_LOADED_WORLD, // Client finished loading world @@ -60,6 +60,18 @@ public: LE_VOTE_TRACK, // vote for a track LE_VOTE_REVERSE, // vote if race in reverse LE_VOTE_LAPS, // vote number of laps + LE_CHAT, + LE_FINAL_PLAYER_LIST, + LE_AUTHORISED + }; + + enum RejectReason : uint8_t + { + RR_BUSY = 0, + RR_BANNED = 1, + RR_INCORRECT_PASSWORD = 2, + RR_INCOMPATIBLE_DATA = 3, + RR_TOO_MANY_PLAYERS = 4 }; protected: diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index bc2b2313e..b4d4947ee 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -41,6 +41,7 @@ #include "utils/random_generator.hpp" #include "utils/time.hpp" +#include #include /** This is the central game setup protocol running in the server. It is @@ -84,18 +85,9 @@ */ ServerLobby::ServerLobby() : LobbyProtocol(NULL) { + m_has_created_server_id_file = false; setHandleDisconnections(true); m_state = SET_PUBLIC_ADDRESS; - - // We use maximum 16bit unsigned limit - auto all_k = kart_properties_manager->getAllAvailableKarts(); - auto all_t = track_manager->getAllTrackIdentifiers(); - if (all_k.size() >= 65536) - all_k.resize(65535); - if (all_t.size() >= 65536) - all_t.resize(65535); - m_available_kts.getData().first = { all_k.begin(), all_k.end() }; - m_available_kts.getData().second = { all_t.begin(), all_t.end() }; } // ServerLobby //----------------------------------------------------------------------------- @@ -113,6 +105,16 @@ ServerLobby::~ServerLobby() void ServerLobby::setup() { + // We use maximum 16bit unsigned limit + auto all_k = kart_properties_manager->getAllAvailableKarts(); + auto all_t = track_manager->getAllTrackIdentifiers(); + if (all_k.size() >= 65536) + all_k.resize(65535); + if (all_t.size() >= 65536) + all_t.resize(65535); + m_available_kts.first = { all_k.begin(), all_k.end() }; + 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 @@ -197,11 +199,12 @@ bool ServerLobby::notifyEventAsynchronous(Event* event) void ServerLobby::createServerIdFile() { const std::string& sid = NetworkConfig::get()->getServerIdFile(); - if (!sid.empty()) + if (!sid.empty() && !m_has_created_server_id_file) { std::fstream fs; fs.open(sid, std::ios::out); fs.close(); + m_has_created_server_id_file = true; } } // createServerIdFile @@ -265,6 +268,7 @@ void ServerLobby::asynchronousUpdate() default: break; } + } // asynchronousUpdate //----------------------------------------------------------------------------- @@ -274,6 +278,9 @@ void ServerLobby::asynchronousUpdate() */ void ServerLobby::update(float dt) { + // Check if server owner has left + updateServerOwner(); + switch (m_state.load()) { case SET_PUBLIC_ADDRESS: @@ -463,12 +470,6 @@ void ServerLobby::signalRaceStartToClients() void ServerLobby::startSelection(const Event *event) { std::lock_guard lock(m_connection_mutex); - if (NetworkConfig::get()->isWAN()) - { - assert(m_server_registered); - unregisterServer(); - m_server_registered = false; - } if (m_state != ACCEPTING_CLIENTS) { @@ -477,21 +478,28 @@ void ServerLobby::startSelection(const Event *event) m_state.load()); return; } - if(event && !event->getPeer()->isAuthorised()) + if (event->getPeerSP() != m_server_owner.lock()) { Log::warn("ServerLobby", "Client %lx is not authorised to start selection.", event->getPeer()); return; } + + if (NetworkConfig::get()->isWAN()) + { + assert(m_server_registered); + unregisterServer(); + m_server_registered = false; + } + NetworkString *ns = getNetworkString(1); // Start selection - must be synchronous since the receiver pushes // a new screen, which must be donefrom the main thread. ns->setSynchronous(true); ns->addUInt8(LE_START_SELECTION); - m_available_kts.lock(); - const auto& all_k = m_available_kts.getData().first; - const auto& all_t = m_available_kts.getData().second; + const auto& all_k = m_available_kts.first; + const auto& all_t = m_available_kts.second; ns->addUInt16((uint16_t)all_k.size()).addUInt16((uint16_t)all_t.size()); for (const std::string& kart : all_k) { @@ -501,7 +509,6 @@ void ServerLobby::startSelection(const Event *event) { ns->encodeString(track); } - m_available_kts.unlock(); sendMessageToPeersChangingToken(ns, /*reliable*/true); delete ns; @@ -625,23 +632,21 @@ void ServerLobby::checkIncomingConnectionRequests() */ void ServerLobby::clientDisconnected(Event* event) { - std::vector players_on_host = - event->getPeer()->getAllPlayerProfiles(); + std::lock_guard lock(m_connection_mutex); + auto players_on_peer = event->getPeer()->getPlayerProfiles(); + if (players_on_peer.empty()) + return; - NetworkString *msg = getNetworkString(2); + NetworkString* msg = getNetworkString(2); msg->addUInt8(LE_PLAYER_DISCONNECTED); - - for(unsigned int i=0; iaddUInt8((uint8_t)players_on_peer.size()); + for (auto p : players_on_peer) { - msg->addUInt8(players_on_host[i]->getGlobalPlayerId()); - Log::info("ServerLobby", "Player disconnected : id %d", - players_on_host[i]->getGlobalPlayerId()); - m_game_setup->removePlayer(players_on_host[i]); + msg->encodeString(p->getName()); } - sendMessageToPeersChangingToken(msg, /*reliable*/true); + updatePlayerList(); delete msg; - } // clientDisconnected //----------------------------------------------------------------------------- @@ -659,34 +664,62 @@ void ServerLobby::clientDisconnected(Event* event) void ServerLobby::connectionRequested(Event* event) { std::lock_guard lock(m_connection_mutex); - STKPeer* peer = event->getPeer(); + std::shared_ptr peer = event->getPeerSP(); + peer->cleanPlayerProfiles(); + const NetworkString &data = event->data(); // can we add the player ? - if (m_game_setup->getPlayerCount() >= NetworkConfig::get()->getMaxPlayers() || - m_state!=ACCEPTING_CLIENTS ) + if (m_game_setup->getPlayerCount() >= + NetworkConfig::get()->getMaxPlayers() || + m_state != ACCEPTING_CLIENTS) { NetworkString *message = getNetworkString(2); - // Len, error code: 2 = busy, 0 = too many players message->addUInt8(LE_CONNECTION_REFUSED) - .addUInt8(m_state!=ACCEPTING_CLIENTS ? 2 : 0); + .addUInt8(m_state != ACCEPTING_CLIENTS ? + RR_BUSY : RR_TOO_MANY_PLAYERS); - // send only to the peer that made the request + // send only to the peer that made the request and disconect it now peer->sendPacket(message); + peer->reset(); delete message; Log::verbose("ServerLobby", "Player refused"); return; } - // Connection accepted. - // ==================== - std::string name_u8; - data.decodeString(&name_u8); - core::stringw name = StringUtils::utf8ToWide(name_u8); + // Check for password std::string password; data.decodeString(&password); - bool is_authorised = (password==NetworkConfig::get()->getPassword()); + if (password != NetworkConfig::get()->getPassword()) + { + NetworkString *message = getNetworkString(2); + message->addUInt8(LE_CONNECTION_REFUSED) + .addUInt8(RR_INCORRECT_PASSWORD); + // send only to the peer that made the request and disconect it now + peer->sendPacket(message); + peer->reset(); + delete message; + Log::verbose("ServerLobby", "Player refused: incorrect password"); + return; + } + + // Connection accepted. + // ==================== + uint8_t player_count = data.getUInt8(); + for (unsigned i = 0; i < player_count; i++) + { + std::string name_u8; + data.decodeString(&name_u8); + core::stringw name = StringUtils::utf8ToWide(name_u8); + float default_kart_color = data.getFloat(); + uint32_t online_id = data.getUInt32(); + PerPlayerDifficulty per_player_difficulty = + (PerPlayerDifficulty)data.getUInt8(); + peer->addPlayer(std::make_shared + (peer, name, peer->getHostId(), default_kart_color, online_id, + per_player_difficulty)); + } std::set client_karts, client_tracks; const unsigned kart_num = data.getUInt16(); const unsigned track_num = data.getUInt16(); @@ -707,14 +740,14 @@ void ServerLobby::connectionRequested(Event* event) // so that in the end the server has a list of all karts/tracks available // on all clients std::set karts_erase, tracks_erase; - for (const std::string& server_kart : m_available_kts.getData().first) + for (const std::string& server_kart : m_available_kts.first) { if (client_karts.find(server_kart) == client_karts.end()) { karts_erase.insert(server_kart); } } - for (const std::string& server_track : m_available_kts.getData().second) + for (const std::string& server_track : m_available_kts.second) { if (client_tracks.find(server_track) == client_tracks.end()) { @@ -724,48 +757,27 @@ void ServerLobby::connectionRequested(Event* event) // Drop this player if he doesn't have at least 1 kart / track the same // from server - if (karts_erase.size() == m_available_kts.getData().first.size() || - tracks_erase.size() == m_available_kts.getData().second.size()) + if (karts_erase.size() == m_available_kts.first.size() || + tracks_erase.size() == m_available_kts.second.size()) { NetworkString *message = getNetworkString(2); - message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(3); + message->addUInt8(LE_CONNECTION_REFUSED) + .addUInt8(RR_INCOMPATIBLE_DATA); peer->sendPacket(message); + peer->reset(); delete message; Log::verbose("ServerLobby", "Player has incompatible karts / tracks"); - m_available_kts.unlock(); return; } for (const std::string& kart_erase : karts_erase) { - m_available_kts.getData().first.erase(kart_erase); + m_available_kts.first.erase(kart_erase); } for (const std::string& track_erase : tracks_erase) { - m_available_kts.getData().second.erase(track_erase); + m_available_kts.second.erase(track_erase); } - m_available_kts.unlock(); - - // Get the unique global ID for this player. - m_next_player_id.lock(); - m_next_player_id.getData()++; - int new_player_id = m_next_player_id.getData(); - m_next_player_id.unlock(); - if(m_game_setup->getLocalMasterID()==0) - m_game_setup->setLocalMaster(new_player_id); - - // The host id has already been incremented when the peer - // was added, so it is the right id now. - int new_host_id = STKHost::get()->getNextHostId(); - - // Notify everybody that there is a new player - // ------------------------------------------- - NetworkString *message = getNetworkString(3+1+name_u8.size()); - // size of id -- id -- size of local id -- local id; - message->addUInt8(LE_NEW_PLAYER_CONNECTED).addUInt8(new_player_id) - .addUInt8(new_host_id).encodeString(name_u8); - STKHost::get()->sendPacketExcept(peer, message); - delete message; // Now answer to the peer that just connected // ------------------------------------------ @@ -777,38 +789,83 @@ void ServerLobby::connectionRequested(Event* event) (token_generator.get(RAND_MAX) & 0xff)); peer->setClientServerToken(token); - peer->setAuthorised(is_authorised); - peer->setHostId(new_host_id); - - const std::vector &players = m_game_setup->getPlayers(); // send a message to the one that asked to connect - // Estimate 10 as average name length - NetworkString *message_ack = getNetworkString(4 + players.size() * (2+10)); - // connection success -- size of token -- token - message_ack->addUInt8(LE_CONNECTION_ACCEPTED).addUInt8(new_player_id) - .addUInt8(new_host_id).addUInt8(is_authorised); - // Add all players so that this user knows (this new player is only added - // to the list of players later, so the new player's info is not included) - for (unsigned int i = 0; i < players.size(); i++) - { - message_ack->addUInt8(players[i]->getGlobalPlayerId()) - .addUInt8(players[i]->getHostId()) - .encodeString(players[i]->getName()); - } + NetworkString *message_ack = getNetworkString(4); + // connection success -- return the host id of peer + message_ack->addUInt8(LE_CONNECTION_ACCEPTED).addUInt32(peer->getHostId()); peer->sendPacket(message_ack); delete message_ack; - NetworkPlayerProfile* profile = - new NetworkPlayerProfile(name, new_player_id, new_host_id); - m_game_setup->addPlayer(profile); - NetworkingLobby::getInstance()->addPlayer(profile); - + updatePlayerList(); Log::verbose("ServerLobby", "New player."); } // connectionRequested //----------------------------------------------------------------------------- +void ServerLobby::updatePlayerList() +{ + if (m_state.load() != ACCEPTING_CLIENTS) + return; + auto all_profiles = STKHost::get()->getAllPlayerProfiles(); + NetworkString* pl = getNetworkString(); + pl->setSynchronous(true); + pl->addUInt8(LE_UPDATE_PLAYER_LIST).addUInt8((uint8_t)all_profiles.size()); + for (auto profile : all_profiles) + { + pl->addUInt32(profile->getHostId()).addUInt32(profile->getOnlineID()) + .encodeString(profile->getName()); + uint8_t server_owner = 0; + if (m_server_owner.lock() == profile->getPeer()) + server_owner = 1; + pl->addUInt8(server_owner); + } + sendMessageToPeersChangingToken(pl); + delete pl; +} // updatePlayerList +//----------------------------------------------------------------------------- +void ServerLobby::updateServerOwner() +{ + if (m_state.load() < ACCEPTING_CLIENTS || + m_state.load() > RESULT_DISPLAY) + return; + if (!m_server_owner.expired()) + return; + auto peers = STKHost::get()->getPeers(); + if (peers.empty()) + return; + std::sort(peers.begin(), peers.end(), [](const std::shared_ptr a, + const std::shared_ptr b)->bool + { + return a->getHostId() < b->getHostId(); + }); + + std::shared_ptr owner; + std::lock_guard lock(m_connection_mutex); + // Make sure no one access the weak pointer or adding player to peers + for (auto peer: peers) + { + // Only 127.0.0.1 can be server owner in case of graphics-client-server + if (peer->hasPlayerProfiles() && + (NetworkConfig::get()->getServerIdFile().empty() || + peer->getAddress().getIP() == 0x7f000001)) + { + owner = peer; + break; + } + } + if (owner) + { + NetworkString* ns = getNetworkString(); + ns->addUInt8(LE_AUTHORISED); + owner->sendPacket(ns); + delete ns; + m_server_owner = owner; + updatePlayerList(); + } +} // updateServerOwner + +//----------------------------------------------------------------------------- /*! \brief Called when a player asks to select a kart. * \param event : Event providing the information. * diff --git a/src/network/protocols/server_lobby.hpp b/src/network/protocols/server_lobby.hpp index dff62411b..40ec450e2 100644 --- a/src/network/protocols/server_lobby.hpp +++ b/src/network/protocols/server_lobby.hpp @@ -6,9 +6,12 @@ #include "utils/synchronised.hpp" #include +#include #include #include +class STKPeer; + class ServerLobby : public LobbyProtocol { public: @@ -31,10 +34,13 @@ public: private: std::atomic m_state; + /** Hold the next connected peer for server owner if current one expired + * (disconnected). */ + std::weak_ptr m_server_owner; + /** Available karts and tracks for all clients, this will be initialized * with data in server first. */ - Synchronised, - std::set > > m_available_kts; + std::pair, std::set > m_available_kts; /** Next id to assign to a peer. */ Synchronised m_next_player_id; @@ -58,6 +64,8 @@ private: bool m_selection_enabled; + bool m_has_created_server_id_file; + /** It indicates if this server is registered with the stk server. */ std::atomic_bool m_server_registered; @@ -89,6 +97,9 @@ private: void startedRaceOnClient(Event *event); void unregisterServer(); void createServerIdFile(); + void updatePlayerList(); + void updateServerOwner(); + public: ServerLobby(); virtual ~ServerLobby(); diff --git a/src/network/remote_kart_info.hpp b/src/network/remote_kart_info.hpp index a78db09e6..41cbd9c37 100644 --- a/src/network/remote_kart_info.hpp +++ b/src/network/remote_kart_info.hpp @@ -34,9 +34,9 @@ enum SoccerTeam }; /** Game difficulty per player. */ -enum PerPlayerDifficulty +enum PerPlayerDifficulty : uint8_t { - PLAYER_DIFFICULTY_NORMAL, + PLAYER_DIFFICULTY_NORMAL = 0, PLAYER_DIFFICULTY_HANDICAP, PLAYER_DIFFICULTY_COUNT }; @@ -51,7 +51,7 @@ class RemoteKartInfo SoccerTeam m_soccer_team; bool m_network_player; PerPlayerDifficulty m_difficulty; - + float m_default_kart_color; public: RemoteKartInfo(int player_id, const std::string& kart_name, const irr::core::stringw& user_name, int host_id, @@ -75,6 +75,7 @@ public: void setGlobalPlayerId(int id) { m_global_player_id = id; } void setSoccerTeam(SoccerTeam team) { m_soccer_team = team; } void setNetworkPlayer(bool value) { m_network_player = value; } + void setDefaultKartColor(float value) { m_default_kart_color = value; } void setPerPlayerDifficulty(PerPlayerDifficulty value) { m_difficulty = value; } int getHostId() const { return m_host_id; } @@ -85,6 +86,7 @@ public: const irr::core::stringw& getPlayerName() const { return m_user_name; } SoccerTeam getSoccerTeam() const { return m_soccer_team; } PerPlayerDifficulty getDifficulty() const { return m_difficulty; } + float getDefaultKartColor() const { return m_default_kart_color; } bool operator<(const RemoteKartInfo& other) const { diff --git a/src/network/stk_host.cpp b/src/network/stk_host.cpp index 7de7f40a2..c43f5f4a2 100644 --- a/src/network/stk_host.cpp +++ b/src/network/stk_host.cpp @@ -262,7 +262,6 @@ void STKHost::create(std::shared_ptr server, SeparateProcess* p) */ STKHost::STKHost(std::shared_ptr server) { - m_next_unique_host_id = -1; // Will be overwritten with the correct value once a connection with the // server is made. m_host_id = 0; @@ -291,16 +290,14 @@ STKHost::STKHost(std::shared_ptr server) STKHost::STKHost(const irr::core::stringw &server_name) { init(); - // The host id will be increased whenever a new peer is added, so the - // first client will have host id 1 (host id 0 is the server). - m_next_unique_host_id = 0; m_host_id = 0; // indicates a server host. ENetAddress addr; addr.host = STKHost::HOST_ANY; addr.port = NetworkConfig::get()->getServerPort(); - m_network = new Network(NetworkConfig::get()->getMaxPlayers(), + // Reserver 1 peer to handle full server message + m_network = new Network(NetworkConfig::get()->getMaxPlayers() + 1, /*channel_limit*/2, /*max_in_bandwidth*/0, /*max_out_bandwidth*/ 0, &addr, @@ -320,6 +317,7 @@ STKHost::STKHost(const irr::core::stringw &server_name) void STKHost::init() { m_shutdown = false; + m_authorised = false; m_network = NULL; m_game_setup = NULL; m_exit_timeout.store(std::numeric_limits::max()); @@ -627,13 +625,14 @@ GameSetup* STKHost::setupNewGame() void STKHost::disconnectAllPeers(bool timeout_waiting) { std::lock_guard lock(m_peers_mutex); - if (!m_peers.empty()) + if (!m_peers.empty() && timeout_waiting) { + for (auto peer : m_peers) + peer.second->disconnect(); // Wait for at most 2 seconds for disconnect event to be generated - if (timeout_waiting) - m_exit_timeout.store(StkTime::getRealTime() + 2.0); - m_peers.clear(); + m_exit_timeout.store(StkTime::getRealTime() + 2.0); } + m_peers.clear(); } // disconnectAllPeers //----------------------------------------------------------------------------- @@ -694,23 +693,6 @@ void STKHost::stopListening() m_listening_thread.join(); } // stopListening -// ---------------------------------------------------------------------------- -/** Returns true if this client instance is allowed to control the server. - * A client can authorise itself by providing the server's password. It is - * then allowed to control the server (e.g. start kart selection). - * The information if this client was authorised by the server is actually - * stored in the peer (which is the server peer on a client). - */ -bool STKHost::isAuthorisedToControl() const -{ - assert(NetworkConfig::get()->isClient()); - // If we are not properly connected (i.e. only enet connection, but not - // stk logic), no peer is authorised. - if(m_peers.size()==0) - return false; - return m_peers.begin()->second->isAuthorised(); -} // isAuthorisedToControl - // ---------------------------------------------------------------------------- /** \brief Thread function checking if data is received. * This function tries to get data from network low-level functions as @@ -767,6 +749,14 @@ void STKHost::mainLoop() case ECT_DISCONNECT: enet_peer_disconnect(std::get<0>(p), std::get<2>(p)); break; + case ECT_RESET: + // Flush enet before reset (so previous command is send) + enet_host_flush(host); + enet_peer_reset(std::get<0>(p)); + // Remove the stk peer of it + std::lock_guard lock(m_peers_mutex); + m_peers.erase(std::get<0>(p)); + break; } } @@ -778,8 +768,8 @@ void STKHost::mainLoop() Event* stk_event = NULL; if (event.type == ENET_EVENT_TYPE_CONNECT) { - auto stk_peer = - std::make_shared(event.peer, this); + auto stk_peer = std::make_shared + (event.peer, this, m_next_unique_host_id++); std::unique_lock lock(m_peers_mutex); m_peers[event.peer] = stk_peer; lock.unlock(); @@ -1026,3 +1016,30 @@ void STKHost::sendToServer(NetworkString *data, bool reliable) assert(NetworkConfig::get()->isClient()); m_peers.begin()->second->sendPacket(data, reliable); } // sendToServer + +//----------------------------------------------------------------------------- +std::vector > + STKHost::getAllPlayerProfiles() const +{ + std::vector > p; + std::unique_lock lock(m_peers_mutex); + for (auto peer : m_peers) + { + auto peer_profile = peer.second->getPlayerProfiles(); + p.insert(p.end(), peer_profile.begin(), peer_profile.end()); + } + lock.unlock(); + return p; +} // getAllPlayerProfiles + +//----------------------------------------------------------------------------- +std::shared_ptr STKHost::findPeerByHostId(uint32_t id) const +{ + std::lock_guard lock(m_peers_mutex); + auto ret = std::find_if(m_peers.begin(), m_peers.end(), + [id](const std::pair >& p) + { + return p.second->getHostId() == id; + }); + return ret != m_peers.end() ? ret->second : nullptr; +} // findPeerByHostId diff --git a/src/network/stk_host.hpp b/src/network/stk_host.hpp index 061cce8c7..32cddb689 100644 --- a/src/network/stk_host.hpp +++ b/src/network/stk_host.hpp @@ -50,7 +50,8 @@ class SeparateProcess; enum ENetCommandType : unsigned int { ECT_SEND_PACKET = 0, - ECT_DISCONNECT = 1 + ECT_DISCONNECT = 1, + ECT_RESET = 2 }; class STKHost @@ -80,7 +81,7 @@ private: std::thread m_network_console; /** Make sure the removing or adding a peer is thread-safe. */ - std::mutex m_peers_mutex; + mutable std::mutex m_peers_mutex; /** Let (atm enet_peer_send and enet_peer_disconnect) run in the listening * thread. */ @@ -98,10 +99,10 @@ private: * getPeer()), but not decreased whena host (=peer) disconnects. This * results in a unique host id for each host, even when a host should * disconnect and then reconnect. */ - int m_next_unique_host_id; + uint32_t m_next_unique_host_id = 0; /** Host id of this host. */ - uint8_t m_host_id; + uint32_t m_host_id = 0; /** Stores data about the online game to play. */ GameSetup* m_game_setup; @@ -113,6 +114,9 @@ private: * triggers a shutdown of the STKHost (and the Protocolmanager). */ std::atomic_bool m_shutdown; + /** True if this local host is authorised to control a server. */ + std::atomic_bool m_authorised; + /** Use as a timeout to waiting a disconnect event when exiting. */ std::atomic m_exit_timeout; @@ -142,7 +146,6 @@ public: * a crash in release mode on windows (see #1529). */ static bool m_enable_console; - /** Creates the STKHost. It takes all confifguration parameters from * NetworkConfig. This STKHost can either be a client or a server. */ @@ -199,7 +202,21 @@ public: void shutdown(); //------------------------------------------------------------------------- void sendPacketToAllPeers(NetworkString *data, bool reliable = true); - //------------------------------------------------------------------------- + // ------------------------------------------------------------------------ + /** Returns true if this client instance is allowed to control the server. + * It will auto transfer ownership if previous server owner disconnected. + */ + bool isAuthorisedToControl() const { return m_authorised.load(); } + // ------------------------------------------------------------------------ + /** Sets if this local host is authorised to control the server. */ + void setAuthorisedToControl(bool authorised) + { m_authorised.store(authorised); } + // ------------------------------------------------------------------------ + std::vector > + getAllPlayerProfiles() const; + // ------------------------------------------------------------------------ + std::shared_ptr findPeerByHostId(uint32_t id) const; + // ------------------------------------------------------------------------ void sendPacketExcept(STKPeer* peer, NetworkString *data, bool reliable = true); @@ -213,8 +230,6 @@ public: std::shared_ptr getServerPeerForClient() const; std::vector getMyPlayerProfiles(); void setErrorMessage(const irr::core::stringw &message); - bool isAuthorisedToControl() const; - //------------------------------------------------------------------------- void addEnetCommand(ENetPeer* peer, ENetPacket* packet, uint32_t i, ENetCommandType ect) { @@ -247,7 +262,7 @@ public: } // sendRawPacket // ------------------------------------------------------------------------ /** Returns a copied list of peers. */ - std::vector > getPeers() + std::vector > getPeers() const { std::lock_guard lock(m_peers_mutex); std::vector > peers; @@ -266,17 +281,17 @@ public: } // ------------------------------------------------------------------------ /** Returns the number of currently connected peers. */ - unsigned int getPeerCount() + unsigned int getPeerCount() const { std::lock_guard lock(m_peers_mutex); return m_peers.size(); } // ------------------------------------------------------------------------ - /** Sets the global host id of this host. */ - void setMyHostId(uint8_t my_host_id) { m_host_id = my_host_id; } + /** Sets the global host id of this host (client use). */ + void setMyHostId(uint32_t my_host_id) { m_host_id = my_host_id; } // ------------------------------------------------------------------------ /** Returns the host id of this host. */ - uint8_t getMyHostId() const { return m_host_id; } + uint32_t getMyHostId() const { return m_host_id; } // ------------------------------------------------------------------------ void sendToServer(NetworkString *data, bool reliable = true); // ------------------------------------------------------------------------ diff --git a/src/network/stk_peer.cpp b/src/network/stk_peer.cpp index e264df9bf..60c44f242 100644 --- a/src/network/stk_peer.cpp +++ b/src/network/stk_peer.cpp @@ -29,27 +29,24 @@ /** Constructor for an empty peer. */ -STKPeer::STKPeer(ENetPeer *enet_peer, STKHost* host) +STKPeer::STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id) : m_peer_address(enet_peer->address), m_host(host) { m_enet_peer = enet_peer; - m_is_authorised = false; m_client_server_token = 0; - m_host_id = 0; + m_host_id = host_id; m_token_set = false; } // STKPeer //----------------------------------------------------------------------------- -/** Destructor. - */ -STKPeer::~STKPeer() +void STKPeer::disconnect() { TransportAddress a(m_enet_peer->address); if (m_enet_peer->state != ENET_PEER_STATE_CONNECTED || a != m_peer_address) return; m_host->addEnetCommand(m_enet_peer, NULL, PDI_NORMAL, ECT_DISCONNECT); -} // ~STKPeer +} // disconnect //----------------------------------------------------------------------------- /** Kick this peer (used by server). @@ -63,6 +60,18 @@ void STKPeer::kick() m_host->addEnetCommand(m_enet_peer, NULL, PDI_KICK, ECT_DISCONNECT); } // kick +//----------------------------------------------------------------------------- +/** Forcefully disconnects a peer (used by server). + */ +void STKPeer::reset() +{ + TransportAddress a(m_enet_peer->address); + if (m_enet_peer->state != ENET_PEER_STATE_CONNECTED || + a != m_peer_address) + return; + m_host->addEnetCommand(m_enet_peer, NULL, 0, ECT_RESET); +} // reset + //----------------------------------------------------------------------------- /** Sends a packet to this host. * \param data The data to send. @@ -111,14 +120,3 @@ bool STKPeer::isSamePeer(const ENetPeer* peer) const { return peer==m_enet_peer; } // isSamePeer - -//----------------------------------------------------------------------------- -/** Returns the list of all player profiles connected to this peer. Note that - * this function is somewhat expensive (it loops over all network profiles - * to find the ones with the same host id as this peer. - */ -std::vector STKPeer::getAllPlayerProfiles() -{ - return m_host->getGameSetup()->getAllPlayersOnHost(getHostId()); -} // getAllPlayerProfiles - diff --git a/src/network/stk_peer.hpp b/src/network/stk_peer.hpp index 85b4cf27c..c3a53ee57 100644 --- a/src/network/stk_peer.hpp +++ b/src/network/stk_peer.hpp @@ -29,6 +29,7 @@ #include +#include #include class NetworkPlayerProfile; @@ -62,26 +63,38 @@ protected: /** Host id of this peer. */ int m_host_id; - /** True if this peer is authorised to control a server. */ - bool m_is_authorised; - TransportAddress m_peer_address; STKHost* m_host; + std::vector > m_players; + public: - STKPeer(ENetPeer *enet_peer, STKHost* host); - ~STKPeer(); + STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id); + ~STKPeer() {} // ------------------------------------------------------------------------ void sendPacket(NetworkString *data, bool reliable = true); // ------------------------------------------------------------------------ + void disconnect(); + // ------------------------------------------------------------------------ void kick(); // ------------------------------------------------------------------------ + void reset(); + // ------------------------------------------------------------------------ bool isConnected() const; const TransportAddress& getAddress() const { return m_peer_address; } bool isSamePeer(const STKPeer* peer) const; bool isSamePeer(const ENetPeer* peer) const; - std::vector getAllPlayerProfiles(); + // ------------------------------------------------------------------------ + std::vector > + getPlayerProfiles() const { return m_players; } + // ------------------------------------------------------------------------ + bool hasPlayerProfiles() const { return !m_players.empty(); } + // ------------------------------------------------------------------------ + void cleanPlayerProfiles() { m_players.clear(); } + // ------------------------------------------------------------------------ + void addPlayer(std::shared_ptr p) + { m_players.push_back(p); } // ------------------------------------------------------------------------ /** Sets the token for this client. */ void setClientServerToken(const uint32_t& token) @@ -90,7 +103,11 @@ public: m_token_set = true; } // setClientServerToken // ------------------------------------------------------------------------ - void unsetClientServerToken() { m_token_set = false; } + void unsetClientServerToken() + { + m_token_set = false; + m_client_server_token = 0; + } // ------------------------------------------------------------------------ /** Returns the token of this client. */ uint32_t getClientServerToken() const { return m_client_server_token; } @@ -98,21 +115,9 @@ public: /** Returns if the token for this client is known. */ bool isClientServerTokenSet() const { return m_token_set; } // ------------------------------------------------------------------------ - /** Sets the host if of this peer. */ - void setHostId(int host_id) { m_host_id = host_id; } - // ------------------------------------------------------------------------ /** Returns the host id of this peer. */ - int getHostId() const { return m_host_id; } - // ------------------------------------------------------------------------ - /** Sets if this peer is authorised to control the server. */ - void setAuthorised(bool authorised) { m_is_authorised = authorised; } - // ------------------------------------------------------------------------ - /** Returns if this peer is authorised to control the server. The server - * uses this to check if a peer is allowed certain commands; and a client - * uses this function (in which case this peer is actually the server - * peer) to see if this client is allowed certain command (i.e. to - * display additional GUI elements). */ - bool isAuthorised() const { return m_is_authorised; } + uint32_t getHostId() const { return m_host_id; } + }; // STKPeer #endif // STK_PEER_HPP diff --git a/src/online/online_player_profile.hpp b/src/online/online_player_profile.hpp index 318a68dcd..9f2935b56 100644 --- a/src/online/online_player_profile.hpp +++ b/src/online/online_player_profile.hpp @@ -96,10 +96,6 @@ namespace Online return m_online_state; } // getOnlineState - // ---------------------------------------------------------------- - /** Returns a pointer to the profile associated with the current user. */ - OnlineProfile* getProfile() const { return m_profile; } - // ---------------------------------------------------------------- /** Returns the session token of the signed in user. */ const std::string& getToken() const { return m_token; } @@ -113,6 +109,9 @@ namespace Online OnlinePlayerProfile(const core::stringw &name, bool is_guest = false); virtual ~OnlinePlayerProfile() {} // ---------------------------------------------------------------- + /** Returns a pointer to the profile associated with the current user. */ + OnlineProfile* getProfile() const { return m_profile; } + // ---------------------------------------------------------------- }; // class OnlinePlayerProfile } // namespace Online #endif // HEADER_CURRENT_ONLINE_USER_HPP diff --git a/src/states_screens/networking_lobby.cpp b/src/states_screens/networking_lobby.cpp index 5d1e22dd6..058d12e71 100644 --- a/src/states_screens/networking_lobby.cpp +++ b/src/states_screens/networking_lobby.cpp @@ -34,7 +34,6 @@ #include "input/input_manager.hpp" #include "io/file_manager.hpp" #include "network/network_config.hpp" -#include "network/network_player_profile.hpp" #include "network/protocols/client_lobby.hpp" #include "network/protocols/server_lobby.hpp" #include "network/server.hpp" @@ -262,16 +261,25 @@ void NetworkingLobby::onDialogClose() } // onDialogClose() // ---------------------------------------------------------------------------- -void NetworkingLobby::addPlayer(NetworkPlayerProfile *profile) +void NetworkingLobby::addPlayer(const std::tuple& p) { // In GUI-less server this function will be called without proper // initialisation - if(m_player_list) - m_player_list->addItem(StringUtils::toString(profile->getGlobalPlayerId()), - profile->getName()); + if (m_player_list) + { + const std::string internal_name = + StringUtils::toString(std::get<0>(p)) + "_" + + StringUtils::toString(std::get<1>(p)); + m_player_list->addItem(internal_name, std::get<2>(p)); + if (std::get<3>(p)) + m_player_list->markItemRed(internal_name, true); + } } // addPlayer // ---------------------------------------------------------------------------- -void NetworkingLobby::removePlayer(NetworkPlayerProfile *profile) +void NetworkingLobby::cleanPlayers() { -} // removePlayer + if (m_player_list) + m_player_list->clear(); +} // cleanPlayers diff --git a/src/states_screens/networking_lobby.hpp b/src/states_screens/networking_lobby.hpp index 644a01301..84103bdf0 100644 --- a/src/states_screens/networking_lobby.hpp +++ b/src/states_screens/networking_lobby.hpp @@ -20,6 +20,7 @@ #include "guiengine/screen.hpp" #include +#include class Server; @@ -32,8 +33,6 @@ namespace GUIEngine class TextBoxWidget; } -class NetworkPlayerProfile; - /** * \brief Handles the main menu * \ingroup states_screens @@ -91,8 +90,9 @@ public: /** Used to insert each client chat message (reserved). */ void addMoreServerInfo(const core::stringw& info); void setJoinedServer(std::shared_ptr server); - void addPlayer(NetworkPlayerProfile *profile); - void removePlayer(NetworkPlayerProfile *profile); + void addPlayer(const std::tuple& p); + void cleanPlayers(); }; // class NetworkingLobby #endif