From ba681a7cf8e5d449d4c133f0f9be80d71510de2c Mon Sep 17 00:00:00 2001 From: Benau Date: Sat, 21 Apr 2018 16:00:14 +0800 Subject: [PATCH] Initial GP in network --- src/main_loop.cpp | 1 + src/network/game_setup.cpp | 33 +++++++++++- src/network/game_setup.hpp | 13 ++++- src/network/network_player_profile.hpp | 43 ++++++++++----- src/network/protocols/client_lobby.cpp | 68 +++++++++++------------ src/network/protocols/client_lobby.hpp | 3 +- src/network/protocols/server_lobby.cpp | 67 ++++++++++++++++++++--- src/network/protocols/server_lobby.hpp | 3 +- src/race/grand_prix_data.hpp | 19 ++++--- src/race/race_manager.cpp | 68 ++++++++++++++++++++++- src/race/race_manager.hpp | 6 ++- src/states_screens/race_result_gui.cpp | 75 ++++++++++++++++---------- 12 files changed, 300 insertions(+), 99 deletions(-) diff --git a/src/main_loop.cpp b/src/main_loop.cpp index 79c7ad3f0..5e1a4de58 100644 --- a/src/main_loop.cpp +++ b/src/main_loop.cpp @@ -363,6 +363,7 @@ void MainLoop::run() GUIEngine::ModalDialog::dismiss(); if (World::getWorld()) { + race_manager->clearNetworkGrandPrixResult(); race_manager->exitRace(); } if (!ProfileWorld::isNoGraphics()) diff --git a/src/network/game_setup.cpp b/src/network/game_setup.cpp index 3b1b16f81..5481f83b2 100644 --- a/src/network/game_setup.cpp +++ b/src/network/game_setup.cpp @@ -19,6 +19,7 @@ #include "network/game_setup.hpp" #include "config/player_manager.hpp" +#include "config/user_config.hpp" #include "karts/abstract_kart.hpp" #include "modes/world.hpp" #include "network/network_config.hpp" @@ -28,6 +29,8 @@ #include "race/race_manager.hpp" #include "utils/log.hpp" +#include + //----------------------------------------------------------------------------- /** Update and see if any player disconnects. * \param remove_disconnected_players remove the disconnected players, @@ -113,7 +116,10 @@ void GameSetup::addServerInfo(NetworkString* ns) { if (isGrandPrix()) { - ns->addUInt8((uint8_t)2).addUInt8((uint8_t)m_tracks.size()) + uint8_t cur_track = (uint8_t)m_tracks.size(); + if (!isGrandPrixStarted()) + cur_track = 0; + ns->addUInt8((uint8_t)2).addUInt8(cur_track) .addUInt8(getExtraServerInfo()); } else @@ -129,3 +135,28 @@ void GameSetup::addServerInfo(NetworkString* ns) } ns->encodeString(NetworkConfig::get()->getMOTD()); } // addServerInfo + +//----------------------------------------------------------------------------- +void GameSetup::sortPlayersForGrandPrix() +{ + if (!isGrandPrix() || m_tracks.size() == 1) + return; + std::lock_guard lock(m_players_mutex); + std::sort(m_players.begin(), m_players.end(), + [](const std::weak_ptr& a, + const std::weak_ptr& b) + { + // They should never expired + auto c = a.lock(); + assert(c); + auto d = b.lock(); + assert(d); + return (c->getScore() < d->getScore()) || + (c->getScore() == d->getScore() && + c->getOverallTime() > d->getOverallTime()); + }); + if (UserConfigParams::m_gp_most_points_first) + { + std::reverse(m_players.begin(), m_players.end()); + } +} // sortPlayersForGrandPrix diff --git a/src/network/game_setup.hpp b/src/network/game_setup.hpp index 30b26a770..4ded38054 100644 --- a/src/network/game_setup.hpp +++ b/src/network/game_setup.hpp @@ -118,7 +118,8 @@ public: // ------------------------------------------------------------------------ void reset() { - m_tracks.clear(); + if (!isGrandPrixStarted()) + m_tracks.clear(); m_laps = 0; m_reverse = false; } @@ -153,7 +154,17 @@ public: return m_extra_server_info != 0; } // ------------------------------------------------------------------------ + bool isGrandPrixStarted() const + { + return isGrandPrix() && !m_tracks.empty() && + m_tracks.size() != getTotalGrandPrixTracks(); + } + // ------------------------------------------------------------------------ + void stopGrandPrix() { m_tracks.clear(); } + // ------------------------------------------------------------------------ const std::vector& getAllTracks() const { return m_tracks; } + // ------------------------------------------------------------------------ + void sortPlayersForGrandPrix(); }; #endif // GAME_SETUP_HPP diff --git a/src/network/network_player_profile.hpp b/src/network/network_player_profile.hpp index 2b02977fe..cbd11f534 100644 --- a/src/network/network_player_profile.hpp +++ b/src/network/network_player_profile.hpp @@ -59,6 +59,12 @@ private: /** The local player id relative to each peer. */ int m_local_player_id; + /** Score if grand prix. */ + int m_score; + + /** Overall time if grand prix. */ + float m_overall_time; + public: NetworkPlayerProfile(std::shared_ptr peer, const irr::core::stringw &name, uint32_t host_id, @@ -72,7 +78,8 @@ public: m_default_kart_color = default_kart_color; m_online_id = online_id; m_per_player_difficulty = per_player_difficulty; - m_local_player_id = local_player_id; + m_local_player_id = local_player_id; + resetGrandPrixData(); } // ------------------------------------------------------------------------ ~NetworkPlayerProfile() {} @@ -80,33 +87,45 @@ public: bool isLocalPlayer() const; // ------------------------------------------------------------------------ /** Returns the host id of this player. */ - uint32_t getHostId() const { return m_host_id; } + uint32_t getHostId() const { return m_host_id; } // ------------------------------------------------------------------------ /** Sets the kart name for this player. */ void setKartName(const std::string &kart_name) { m_kart_name = kart_name; } // ------------------------------------------------------------------------ /** Returns the name of the kart this player has selected. */ - const std::string &getKartName() const { return m_kart_name; } + const std::string &getKartName() const { return m_kart_name; } // ------------------------------------------------------------------------ /** Retuens the local player id for this player. */ - int getLocalPlayerId() const { return m_local_player_id; } + int getLocalPlayerId() const { return m_local_player_id; } // ------------------------------------------------------------------------ /** Returns the per-player difficulty. */ PerPlayerDifficulty getPerPlayerDifficulty() const - { - return m_per_player_difficulty; - } // getPerPlayerDifficulty + { return m_per_player_difficulty; } // ------------------------------------------------------------------------ /** Returns the name of this player. */ - const irr::core::stringw& getName() const { return m_player_name; } + const irr::core::stringw& getName() const { return m_player_name; } // ------------------------------------------------------------------------ - float getDefaultKartColor() const { return m_default_kart_color; } + float getDefaultKartColor() const { return m_default_kart_color; } // ------------------------------------------------------------------------ - uint32_t getOnlineId() const { return m_online_id; } + uint32_t getOnlineId() const { return m_online_id; } // ------------------------------------------------------------------------ - bool isOfflineAccount() const { return m_online_id == 0; } + bool isOfflineAccount() const { return m_online_id == 0; } // ------------------------------------------------------------------------ - std::shared_ptr getPeer() const { return m_peer.lock(); } + std::shared_ptr getPeer() const { return m_peer.lock(); } + // ------------------------------------------------------------------------ + int getScore() const { return m_score; } + // ------------------------------------------------------------------------ + float getOverallTime() const { return m_overall_time; } + // ------------------------------------------------------------------------ + void setScore(int score) { m_score = score; } + // ------------------------------------------------------------------------ + void setOverallTime(float time) { m_overall_time = time; } + // ------------------------------------------------------------------------ + void resetGrandPrixData() + { + m_score = 0; + m_overall_time = 0.0f; + } }; // class NetworkPlayerProfile diff --git a/src/network/protocols/client_lobby.cpp b/src/network/protocols/client_lobby.cpp index 219f927f0..d65cedb82 100644 --- a/src/network/protocols/client_lobby.cpp +++ b/src/network/protocols/client_lobby.cpp @@ -320,35 +320,7 @@ void ClientLobby::update(int ticks) break; case CONNECTED: break; - case KART_SELECTION: - { - // In case the user opened a user info dialog - GUIEngine::ModalDialog::dismiss(); - NetworkKartSelectionScreen* screen = - NetworkKartSelectionScreen::getInstance(); - screen->setAvailableKartsFromServer(m_available_karts); - // In case of auto-connect, use random karts (or previous kart) from - // server and go to track selection (or grand prix later) - if (NetworkConfig::get()->isAutoConnect()) - { - input_manager->setMasterPlayerOnly(true); - for (auto& p : NetworkConfig::get()->getNetworkPlayers()) - { - StateManager::get() - ->createActivePlayer(std::get<1>(p), std::get<0>(p)); - } - input_manager->getDeviceManager()->setAssignMode(ASSIGN); - TracksScreen::getInstance()->setNetworkTracks(); - TracksScreen::getInstance()->push(); - } - else - { - screen->push(); - } - m_state.store(SELECTING_KARTS); - } - break; - case SELECTING_KARTS: + case SELECTING_ASSETS: break; case PLAYING: break; @@ -481,8 +453,8 @@ void ClientLobby::handleServerInfo(Event* event) NetworkConfig::get()->setServerMode(u_data); auto game_mode = NetworkConfig::get()->getLocalGameMode(); race_manager->setMinorMode(game_mode.first); - // We may use single mode in network even it's grand prix - //race_manager->setMajorMode(game_mode.second); + // We use single mode in network even it's grand prix + race_manager->setMajorMode(RaceManager::MAJOR_MODE_GRAND_PRIX); //I18N: In the networking lobby core::stringw mode_name = NetworkConfig::get()->getModeName(u_data); @@ -660,8 +632,8 @@ void ClientLobby::startingRaceNow() */ void ClientLobby::startSelection(Event* event) { - m_state.store(KART_SELECTION); const NetworkString& data = event->data(); + uint8_t skip_kart_screen = data.getUInt8(); const unsigned kart_num = data.getUInt16(); const unsigned track_num = data.getUInt16(); m_available_karts.clear(); @@ -678,7 +650,33 @@ void ClientLobby::startSelection(Event* event) data.decodeString(&track); m_available_tracks.insert(track); } - Log::info("ClientLobby", "Kart selection starts now"); + + // In case the user opened a user info dialog + GUIEngine::ModalDialog::dismiss(); + NetworkKartSelectionScreen* screen = + NetworkKartSelectionScreen::getInstance(); + screen->setAvailableKartsFromServer(m_available_karts); + // In case of auto-connect or continue a grand prix, use random karts + // (or previous kart) from server and go to track selection + if (NetworkConfig::get()->isAutoConnect() || skip_kart_screen == 1) + { + input_manager->setMasterPlayerOnly(true); + for (auto& p : NetworkConfig::get()->getNetworkPlayers()) + { + StateManager::get() + ->createActivePlayer(std::get<1>(p), std::get<0>(p)); + } + input_manager->getDeviceManager()->setAssignMode(ASSIGN); + TracksScreen::getInstance()->setNetworkTracks(); + TracksScreen::getInstance()->push(); + } + else + { + screen->push(); + } + + m_state.store(SELECTING_ASSETS); + Log::info("ClientLobby", "Selection starts now"); } // startSelection //----------------------------------------------------------------------------- @@ -699,7 +697,9 @@ void ClientLobby::raceFinished(Event* event) Log::info("ClientLobby", "Server notified that the race is finished."); if (m_game_setup->isGrandPrix()) { - // fastest lap, and than each kart before / after grand prix points + int t = data.getUInt32(); + static_cast(World::getWorld())->setFastestLapTicks(t); + race_manager->configGrandPrixResultFromNetwork(data); } else if (race_manager->modeHasLaps()) { diff --git a/src/network/protocols/client_lobby.hpp b/src/network/protocols/client_lobby.hpp index 93524a311..245ae96b9 100644 --- a/src/network/protocols/client_lobby.hpp +++ b/src/network/protocols/client_lobby.hpp @@ -35,8 +35,7 @@ private: LINKED, REQUESTING_CONNECTION, CONNECTED, // means in the lobby room - KART_SELECTION, // Start kart selection, then go to next state - SELECTING_KARTS, // in the network kart selection screen + SELECTING_ASSETS, // in the kart selection or tracks screen PLAYING, // racing RACE_FINISHED, // race result shown DONE, diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index f303377fc..4a6c2e893 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -107,6 +107,13 @@ ServerLobby::~ServerLobby() void ServerLobby::setup() { LobbyProtocol::setup(); + if (m_game_setup->isGrandPrix() && !m_game_setup->isGrandPrixStarted()) + { + auto players = m_game_setup->getConnectedPlayers(); + for (auto player : players) + player->resetGrandPrixData(); + } + StateManager::get()->resetActivePlayers(); // We use maximum 16bit unsigned limit auto all_k = kart_properties_manager->getAllAvailableKarts(); @@ -266,6 +273,11 @@ void ServerLobby::asynchronousUpdate() } case REGISTER_SELF_ADDRESS: { + if (m_game_setup->isGrandPrixStarted()) + { + m_state = ACCEPTING_CLIENTS; + break; + } // Register this server with the STK server. This will block // this thread, but there is no need for the protocol manager // to react to any requests before the server is registered. @@ -321,9 +333,11 @@ void ServerLobby::asynchronousUpdate() case SELECTING: if (m_timeout.load() < (float)StkTime::getRealTime()) { + std::lock_guard lock(m_connection_mutex); auto result = handleVote(); // Remove disconnected player (if any) one last time m_game_setup->update(true); + m_game_setup->sortPlayersForGrandPrix(); auto players = m_game_setup->getConnectedPlayers(); NetworkString* load_world = getNetworkString(); load_world->setSynchronous(true); @@ -348,7 +362,6 @@ void ServerLobby::asynchronousUpdate() } load_world->encodeString(player->getKartName()); } - // TODO: sort players for grand prix here configRemoteKart(players); // Reset for next state usage @@ -382,6 +395,7 @@ void ServerLobby::update(int ticks) stopCurrentRace(); } std::lock_guard lock(m_connection_mutex); + m_game_setup->stopGrandPrix(); m_state = NetworkConfig::get()->isLAN() ? ACCEPTING_CLIENTS : REGISTER_SELF_ADDRESS; setup(); @@ -577,18 +591,18 @@ void ServerLobby::startSelection(const Event *event) return; } - if (NetworkConfig::get()->isWAN()) + if (NetworkConfig::get()->isWAN() && m_server_registered) { - 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. + // a new screen, which must be done from the main thread. ns->setSynchronous(true); - ns->addUInt8(LE_START_SELECTION); + ns->addUInt8(LE_START_SELECTION).addUInt8( + m_game_setup->isGrandPrixStarted() ? 1 : 0); // Remove karts / tracks from server that are not supported on all clients std::set karts_erase, tracks_erase; @@ -699,7 +713,36 @@ void ServerLobby::checkRaceFinished() total->addUInt8(LE_RACE_FINISHED); if (m_game_setup->isGrandPrix()) { - // fastest lap, and than each kart before / after grand prix points + // fastest lap + int fastest_lap = + static_cast(World::getWorld())->getFastestLapTicks(); + total->addUInt32(fastest_lap); + + // all gp tracks + total->addUInt8((uint8_t)m_game_setup->getTotalGrandPrixTracks()) + .addUInt8((uint8_t)m_game_setup->getAllTracks().size()); + for (const std::string& gp_track : m_game_setup->getAllTracks()) + total->encodeString(gp_track); + + // each kart score and total time + auto& players = m_game_setup->getPlayers(); + total->addUInt8((uint8_t)players.size()); + for (unsigned i = 0; i < players.size(); i++) + { + int last_score = race_manager->getKartScore(i); + int cur_score = last_score; + float overall_time = race_manager->getOverallTime(i); + if (auto player = players[i].lock()) + { + last_score = player->getScore(); + cur_score += last_score; + overall_time = overall_time + player->getOverallTime(); + player->setScore(cur_score); + player->setOverallTime(overall_time); + } + total->addUInt32(last_score).addUInt32(cur_score) + .addFloat(overall_time); + } } else if (race_manager->modeHasLaps()) { @@ -786,7 +829,8 @@ void ServerLobby::connectionRequested(Event* event) const NetworkString &data = event->data(); // can we add the player ? - if (m_state != ACCEPTING_CLIENTS) + if (m_state != ACCEPTING_CLIENTS || + m_game_setup->isGrandPrixStarted()) { NetworkString *message = getNetworkString(2); message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(RR_BUSY); @@ -1054,7 +1098,7 @@ void ServerLobby::updateServerOwner() void ServerLobby::kartSelectionRequested(Event* event) { std::lock_guard lock(m_connection_mutex); - if (m_state != SELECTING) + if (m_state != SELECTING || m_game_setup->isGrandPrixStarted()) { Log::warn("ServerLobby", "Received kart selection while in state %d.", m_state.load()); @@ -1284,3 +1328,10 @@ void ServerLobby::updateBanList() m_ban_list[TransportAddress(ban.first).getIP()] = ban.second; } } // updateBanList + +//----------------------------------------------------------------------------- +bool ServerLobby::waitingForPlayers() const +{ + return m_state.load() == ACCEPTING_CLIENTS && + !m_game_setup->isGrandPrixStarted(); +} // waitingForPlayers diff --git a/src/network/protocols/server_lobby.hpp b/src/network/protocols/server_lobby.hpp index c8661b3ac..7594ee901 100644 --- a/src/network/protocols/server_lobby.hpp +++ b/src/network/protocols/server_lobby.hpp @@ -143,8 +143,7 @@ public: void finishedLoadingWorld() OVERRIDE; ServerState getCurrentState() const { return m_state.load(); } void updateBanList(); - virtual bool waitingForPlayers() const OVERRIDE - { return m_state.load() == ACCEPTING_CLIENTS; } + virtual bool waitingForPlayers() const OVERRIDE; virtual bool allPlayersReady() const OVERRIDE { return m_state.load() >= WAIT_FOR_RACE_STARTED; } diff --git a/src/race/grand_prix_data.hpp b/src/race/grand_prix_data.hpp index 7fb4bb149..f6d650ea6 100644 --- a/src/race/grand_prix_data.hpp +++ b/src/race/grand_prix_data.hpp @@ -36,6 +36,12 @@ class Track; */ class GrandPrixData { +protected: + /** The ident of the tracks in this grand prix in their right order, ident + * means the filename of the .track file without .track extension + * (ie. 'volcano'). */ + std::vector m_tracks; + public: /** Used to classify GPs into groups */ enum GPGroupType @@ -57,11 +63,6 @@ private: /** Original filename, only for error handling needed. */ std::string m_filename; - /** The ident of the tracks in this grand prix in their right order, ident - * means the filename of the .track file without .track extension - * (ie. 'volcano'). */ - std::vector m_tracks; - /** The number of laps that each track will be raced, in the right order */ std::vector m_laps; @@ -105,7 +106,11 @@ public: GrandPrixData(const std::string& filename, enum GPGroupType group); /** Needed for simple creation of an instance of GrandPrixData */ - GrandPrixData() {}; + GrandPrixData() {} + + virtual ~GrandPrixData() {} + virtual std::vector getTrackNames(const bool includeLocked=false) const; + virtual unsigned int getNumberOfTracks(const bool includeLocked=false) const; void changeTrackNumber(const unsigned int number_of_tracks, const std::string& track_group); @@ -128,11 +133,9 @@ public: bool writeToFile(); bool checkConsistency(bool log_error=true) const; - std::vector getTrackNames(const bool includeLocked=false) const; std::vector getLaps(const bool includeLocked=false) const; std::vector getReverse(const bool includeLocked=false) const; bool isEditable() const; - unsigned int getNumberOfTracks(const bool includeLocked=false) const; const std::string& getTrackId(const unsigned int track) const; irr::core::stringw getTrackName(const unsigned int track) const; unsigned int getLaps(const unsigned int track) const; diff --git a/src/race/race_manager.cpp b/src/race/race_manager.cpp index d2e224947..585fb8bd1 100644 --- a/src/race/race_manager.cpp +++ b/src/race/race_manager.cpp @@ -45,6 +45,7 @@ #include "modes/soccer_world.hpp" #include "network/protocol_manager.hpp" #include "network/network_config.hpp" +#include "network/network_string.hpp" #include "network/protocols/lobby_protocol.hpp" #include "network/race_event_manager.hpp" #include "replay/replay_play.hpp" @@ -980,5 +981,70 @@ void RaceManager::startWatchingReplay(const std::string &track_ident, } // startSingleRace //----------------------------------------------------------------------------- +void RaceManager::configGrandPrixResultFromNetwork(NetworkString& ns) +{ + setMajorMode(MAJOR_MODE_GRAND_PRIX); + class NetworkGrandPrixData : public GrandPrixData + { + public: + NetworkGrandPrixData() : GrandPrixData() + { setGroup(GrandPrixData::GP_STANDARD); } + virtual std::vector + getTrackNames(const bool includeLocked=false) const + { return m_tracks; } + virtual unsigned int + getNumberOfTracks(const bool includeLocked=false) const + { return m_tracks.size(); } + void addNetworkTrack(const std::string& t) { m_tracks.push_back(t); } + }; -/* EOF */ + NetworkGrandPrixData ngpd; + unsigned int track_size = ns.getUInt8(); + unsigned int all_track_size = ns.getUInt8(); + assert(all_track_size > 0); + m_track_number = all_track_size -1; + for (unsigned i = 0; i < all_track_size; i++) + { + std::string t; + ns.decodeString(&t); + ngpd.addNetworkTrack(t); + } + while (all_track_size < track_size) + { + ngpd.addNetworkTrack(""); + all_track_size++; + } + + m_tracks = ngpd.getTrackNames(); + // For result screen we only need current lap and reserve + m_num_laps.resize(track_size, m_num_laps[0]); + m_reverse_track.resize(track_size, m_reverse_track[0]); + + m_grand_prix = ngpd; + unsigned int player_size = ns.getUInt8(); + assert(player_size == m_kart_status.size()); + for (unsigned i = 0; i < player_size; i++) + { + int last_score = ns.getUInt32(); + int cur_score = ns.getUInt32(); + float overall_time = ns.getFloat(); + m_kart_status[i].m_last_score = last_score; + m_kart_status[i].m_score = cur_score; + m_kart_status[i].m_overall_time = overall_time; + m_kart_status[i].m_gp_rank = i; + } +} // configGrandPrixResultFromNetwork + +//----------------------------------------------------------------------------- +void RaceManager::clearNetworkGrandPrixResult() +{ + if (m_major_mode != MAJOR_MODE_GRAND_PRIX) + return; + setMajorMode(MAJOR_MODE_SINGLE); + m_grand_prix = GrandPrixData(); + m_track_number = 0; + m_tracks.clear(); + m_num_laps.clear(); + m_reverse_track.clear(); + +} // clearNetworkGrandPrixResult diff --git a/src/race/race_manager.hpp b/src/race/race_manager.hpp index cde562ebf..7c60df1f2 100644 --- a/src/race/race_manager.hpp +++ b/src/race/race_manager.hpp @@ -36,6 +36,7 @@ #include "utils/vec3.hpp" class AbstractKart; +class NetworkString; class SavedGrandPrix; class Track; @@ -303,7 +304,6 @@ private: /** Stores remote kart information about all player karts. */ std::vector m_player_karts; std::vector m_tracks; - std::vector m_host_ids; /** Number of local players. */ unsigned int m_num_local_players; @@ -786,6 +786,10 @@ public: { return m_num_spare_tire_karts; } // getNumSpareTireKarts + // ------------------------------------------------------------------------ + void configGrandPrixResultFromNetwork(NetworkString& ns); + // ------------------------------------------------------------------------ + void clearNetworkGrandPrixResult(); }; // RaceManager diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index ccda743fc..6ad94e703 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -27,6 +27,7 @@ #include "graphics/2dutils.hpp" #include "graphics/material.hpp" #include "guiengine/engine.hpp" +#include "guiengine/message_queue.hpp" #include "guiengine/modaldialog.hpp" #include "guiengine/scalable_font.hpp" #include "guiengine/widget.hpp" @@ -89,7 +90,7 @@ void RaceResultGUI::init() for (unsigned int kart_id = 0; kart_id < num_karts; kart_id++) { const AbstractKart *kart = World::getWorld()->getKart(kart_id); - if (kart->getController()->isPlayerController()) + if (kart->getController()->isLocalPlayerController()) human_win = human_win && kart->getRaceResult(); } @@ -250,6 +251,33 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget, displayScreenShots(); } + // If we're playing online : + if (World::getWorld()->isNetworkWorld()) + { + if (name == "middle") // Continue button (return to server lobby) + { + // Signal to the server that this client is back in the lobby now. + auto cl = LobbyProtocol::get(); + if (cl) + cl->doneWithResults(); + getWidget("middle")->setText(_("Waiting for others")); + } + if (name == "bottom") // Quit server (return to online lan / wan menu) + { + race_manager->clearNetworkGrandPrixResult(); + if (STKHost::existHost()) + { + STKHost::get()->shutdown(); + } + race_manager->exitRace(); + race_manager->setAIKartOverride(""); + StateManager::get()->resetAndSetStack( + NetworkConfig::get()->getResetScreens().data()); + NetworkConfig::get()->unsetNetworking(); + } + return; + } + // If something was unlocked, the 'continue' button was // actually used to display "Show unlocked feature(s)" text. // --------------------------------------------------------- @@ -330,32 +358,6 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget, name.c_str()); } - // If we're playing online : - if (World::getWorld()->isNetworkWorld()) - { - if (name == "middle") // Continue button (return to server lobby) - { - // Signal to the server that this client is back in the lobby now. - auto cl = LobbyProtocol::get(); - if (cl) - cl->doneWithResults(); - getWidget("middle")->setText(_("Waiting for others")); - } - if (name == "bottom") // Quit server (return to online lan / wan menu) - { - if (STKHost::existHost()) - { - STKHost::get()->shutdown(); - } - race_manager->exitRace(); - race_manager->setAIKartOverride(""); - StateManager::get()->resetAndSetStack( - NetworkConfig::get()->getResetScreens().data()); - NetworkConfig::get()->unsetNetworking(); - } - return; - } - // Next check for GP // ----------------- if (race_manager->getMajorMode() == RaceManager::MAJOR_MODE_GRAND_PRIX) @@ -426,9 +428,17 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget, */ void RaceResultGUI::backToLobby() { + if (race_manager->getMajorMode() == RaceManager::MAJOR_MODE_GRAND_PRIX && + race_manager->getTrackNumber() == race_manager->getNumOfTracks() - 1) + { + core::stringw msg = _("Network grand prix has been finished."); + MessageQueue::add(MessageQueue::MT_ACHIEVEMENT, msg); + } + race_manager->clearNetworkGrandPrixResult(); race_manager->exitRace(); race_manager->setAIKartOverride(""); GUIEngine::ModalDialog::dismiss(); + cleanupGPProgress(); StateManager::get()->resetAndSetStack( NetworkConfig::get()->getResetScreens(true/*lobby*/).data()); } // backToLobby @@ -1467,9 +1477,16 @@ void RaceResultGUI::backToLobby() ("sshot_" + StringUtils::toString(n_sshot)).c_str()); GUIEngine::LabelWidget* label = getWidget( ("sshot_label_" + StringUtils::toString(n_sshot)).c_str()); - assert(track != NULL && sshot != NULL && label != NULL); + assert(sshot != NULL && label != NULL); - sshot->setImage(track->getScreenshotFile()); + // Network grand prix chooses each track 1 bye 1 + if (track == NULL) + { + sshot->setImage(file_manager->getAsset(FileManager::GUI, + "main_help.png")); + } + else + sshot->setImage(track->getScreenshotFile()); if (i <= currentTrack) sshot->setBadge(GUIEngine::OK_BADGE); else