From cd9a58b70470e3800d818c429c3b5453834ec0c6 Mon Sep 17 00:00:00 2001 From: Aestek Date: Sun, 10 Jul 2016 10:13:34 +0200 Subject: [PATCH] Check if all players have the game before starting netplay https://bugs.dolphin-emu.org/issues/8885 --- Source/Core/Core/NetPlayClient.cpp | 56 ++++++++++++++++++++- Source/Core/Core/NetPlayClient.h | 10 ++++ Source/Core/Core/NetPlayProto.h | 1 + Source/Core/Core/NetPlayServer.cpp | 24 ++++++++- Source/Core/Core/NetPlayServer.h | 3 ++ Source/Core/DolphinWX/NetPlay/NetWindow.cpp | 26 ++++++++-- Source/Core/DolphinWX/NetPlay/NetWindow.h | 3 +- 7 files changed, 116 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index e0639e9c1e..7895950747 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -356,6 +356,33 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) // update gui m_dialog->OnMsgChangeGame(m_selected_game); + + sf::Packet spac; + spac << static_cast(NP_MSG_GAME_STATUS); + + PlayerGameStatus status = m_dialog->FindGame(m_selected_game).empty() ? + PlayerGameStatus::NotFound : + PlayerGameStatus::Ok; + + spac << static_cast(status); + Send(spac); + } + break; + + case NP_MSG_GAME_STATUS: + { + PlayerId pid; + packet >> pid; + + { + std::lock_guard lkp(m_crit.players); + Player& player = m_players[pid]; + u32 status; + packet >> status; + player.game_status = static_cast(status); + } + + m_dialog->Update(); } break; @@ -597,7 +624,26 @@ void NetPlayClient::GetPlayerList(std::string& list, std::vector& pid_list) enumerate_player_controller_mappings(m_pad_map, player); enumerate_player_controller_mappings(m_wiimote_map, player); - ss << " |\nPing: " << player.ping << "ms\n\n"; + ss << " |\nPing: " << player.ping << "ms\n"; + ss << "Status: "; + + switch (player.game_status) + { + case PlayerGameStatus::Ok: + ss << "ready"; + break; + + case PlayerGameStatus::NotFound: + ss << "game missing"; + break; + + default: + ss << "unknown"; + break; + } + + ss << "\n\n"; + pid_list.push_back(player.pid); } @@ -1143,6 +1189,14 @@ void NetPlayClient::SendTimeBase() netplay_client->SendAsync(std::move(spac)); } +bool NetPlayClient::DoAllPlayersHaveGame() +{ + std::lock_guard lkp(m_crit.players); + + return std::all_of(std::begin(m_players), std::end(m_players), + [](auto entry) { return entry.second.game_status == PlayerGameStatus::Ok; }); +} + // stuff hacked into dolphin // called from ---CPU--- thread diff --git a/Source/Core/Core/NetPlayClient.h b/Source/Core/Core/NetPlayClient.h index 8853f9ca35..8004d13d0e 100644 --- a/Source/Core/Core/NetPlayClient.h +++ b/Source/Core/Core/NetPlayClient.h @@ -33,6 +33,14 @@ public: virtual void OnMsgStartGame() = 0; virtual void OnMsgStopGame() = 0; virtual bool IsRecording() = 0; + virtual std::string FindGame(const std::string& game) = 0; +}; + +enum class PlayerGameStatus +{ + Unknown, + Ok, + NotFound }; class Player @@ -42,6 +50,7 @@ public: std::string name; std::string revision; u32 ping; + PlayerGameStatus game_status; }; class NetPlayClient : public TraversalClientClient @@ -83,6 +92,7 @@ public: u8 LocalWiimoteToInGameWiimote(u8 local_pad); static void SendTimeBase(); + bool DoAllPlayersHaveGame(); protected: void ClearBuffers(); diff --git a/Source/Core/Core/NetPlayProto.h b/Source/Core/Core/NetPlayProto.h index 1e75f46c38..1454fb3678 100644 --- a/Source/Core/Core/NetPlayProto.h +++ b/Source/Core/Core/NetPlayProto.h @@ -53,6 +53,7 @@ enum NP_MSG_CHANGE_GAME = 0xA1, NP_MSG_STOP_GAME = 0xA2, NP_MSG_DISABLE_GAME = 0xA3, + NP_MSG_GAME_STATUS = 0xA4, NP_MSG_TIMEBASE = 0xB0, NP_MSG_DESYNC_DETECTED = 0xB1, diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index a207432761..d51074d66f 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -318,9 +318,14 @@ unsigned int NetPlayServer::OnConnect(ENetPeer* socket) for (const auto& p : m_players) { spac.clear(); - spac << (MessageId)NP_MSG_PLAYER_JOIN; + spac << static_cast(NP_MSG_PLAYER_JOIN); spac << p.second.pid << p.second.name << p.second.revision; Send(player.socket, spac); + + spac.clear(); + spac << static_cast(NP_MSG_GAME_STATUS); + spac << p.second.pid << static_cast(p.second.game_status); + Send(player.socket, spac); } // add client to the player list @@ -592,6 +597,23 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player) } break; + case NP_MSG_GAME_STATUS: + { + u32 status; + packet >> status; + + m_players[player.pid].game_status = static_cast(status); + + // send msg to other clients + sf::Packet spac; + spac << static_cast(NP_MSG_GAME_STATUS); + spac << player.pid; + spac << status; + + SendToClients(spac); + } + break; + case NP_MSG_TIMEBASE: { u32 x, y, frame; diff --git a/Source/Core/Core/NetPlayServer.h b/Source/Core/Core/NetPlayServer.h index 52a8f6424b..3fd72e38bf 100644 --- a/Source/Core/Core/NetPlayServer.h +++ b/Source/Core/Core/NetPlayServer.h @@ -17,6 +17,8 @@ #include "Common/TraversalClient.h" #include "Core/NetPlayProto.h" +enum class PlayerGameStatus; + class NetPlayUI; class NetPlayServer : public TraversalClientClient @@ -64,6 +66,7 @@ private: PlayerId pid; std::string name; std::string revision; + PlayerGameStatus game_status; ENetPeer* socket; u32 ping; diff --git a/Source/Core/DolphinWX/NetPlay/NetWindow.cpp b/Source/Core/DolphinWX/NetPlay/NetWindow.cpp index 632472b1d0..4f41921cca 100644 --- a/Source/Core/DolphinWX/NetPlay/NetWindow.cpp +++ b/Source/Core/DolphinWX/NetPlay/NetWindow.cpp @@ -288,19 +288,33 @@ void NetPlayDialog::GetNetSettings(NetSettings& settings) settings.m_EXIDevice[1] = instance.m_EXIDevice[1]; } -std::string NetPlayDialog::FindGame() +std::string NetPlayDialog::FindGame(const std::string& target_game) { // find path for selected game, sloppy.. for (u32 i = 0; auto game = m_game_list->GetISO(i); ++i) - if (m_selected_game == BuildGameName(*game)) + if (target_game == BuildGameName(*game)) return game->GetFileName(); - WxUtils::ShowErrorDialog(_("Game not found!")); return ""; } +std::string NetPlayDialog::FindCurrentGame() +{ + return FindGame(m_selected_game); +} + void NetPlayDialog::OnStart(wxCommandEvent&) { + bool should_start = true; + if (!netplay_client->DoAllPlayersHaveGame()) + { + should_start = wxMessageBox(_("Not all players have the game. Do you really want to start?"), + _("Warning"), wxYES_NO) == wxYES; + } + + if (!should_start) + return; + NetSettings settings; GetNetSettings(settings); netplay_server->SetNetSettings(settings); @@ -442,7 +456,11 @@ void NetPlayDialog::OnThread(wxThreadEvent& event) case NP_GUI_EVT_START_GAME: // client start game :/ { - netplay_client->StartGame(FindGame()); + std::string game = FindCurrentGame(); + if (game.empty()) + WxUtils::ShowErrorDialog(_("Game not found!")); + else + netplay_client->StartGame(game); } break; case NP_GUI_EVT_STOP_GAME: diff --git a/Source/Core/DolphinWX/NetPlay/NetWindow.h b/Source/Core/DolphinWX/NetPlay/NetWindow.h index 5646e0b23d..51ff07b06c 100644 --- a/Source/Core/DolphinWX/NetPlay/NetWindow.h +++ b/Source/Core/DolphinWX/NetPlay/NetWindow.h @@ -73,7 +73,8 @@ private: void OnKick(wxCommandEvent& event); void OnPlayerSelect(wxCommandEvent& event); void GetNetSettings(NetSettings& settings); - std::string FindGame(); + std::string FindCurrentGame(); + std::string FindGame(const std::string& game); void OnCopyIP(wxCommandEvent&); void OnChoice(wxCommandEvent& event);