mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-28 16:49:58 -06:00
Make netplay's "same game" check more robust
Instead of comparing the game ID, revision, disc number and name, we can compare a hash of important parts of the disc including all the aforementioned data but also additional data such as the FST. The primary reason why I'm making this change is to let us catch more desyncs before they happen, but this should also fix https://bugs.dolphin-emu.org/issues/12115. As a bonus, the UI can now distinguish the case where a client doesn't have the game at all from the case where a client has the wrong version of the game.
This commit is contained in:
@ -53,9 +53,11 @@
|
||||
#include "Core/IOS/Uids.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/SyncIdentifier.h"
|
||||
#include "InputCommon/ControllerEmu/ControlGroup/Attachments.h"
|
||||
#include "InputCommon/GCAdapter.h"
|
||||
#include "InputCommon/InputConfig.h"
|
||||
#include "UICommon/GameFile.h"
|
||||
#include "VideoCommon/OnScreenDisplay.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
@ -284,6 +286,22 @@ bool NetPlayClient::Connect()
|
||||
}
|
||||
}
|
||||
|
||||
static void ReceiveSyncIdentifier(sf::Packet& spac, SyncIdentifier& sync_identifier)
|
||||
{
|
||||
// We use a temporary variable here due to a potential long vs long long mismatch
|
||||
sf::Uint64 dol_elf_size;
|
||||
spac >> dol_elf_size;
|
||||
sync_identifier.dol_elf_size = dol_elf_size;
|
||||
|
||||
spac >> sync_identifier.game_id;
|
||||
spac >> sync_identifier.revision;
|
||||
spac >> sync_identifier.disc_number;
|
||||
spac >> sync_identifier.is_datel;
|
||||
|
||||
for (u8& x : sync_identifier.sync_hash)
|
||||
spac >> x;
|
||||
}
|
||||
|
||||
// called from ---NETPLAY--- thread
|
||||
unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
||||
{
|
||||
@ -572,24 +590,25 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
||||
|
||||
case NP_MSG_CHANGE_GAME:
|
||||
{
|
||||
std::string netplay_name;
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
|
||||
packet >> m_selected_game;
|
||||
ReceiveSyncIdentifier(packet, m_selected_game);
|
||||
packet >> netplay_name;
|
||||
}
|
||||
|
||||
INFO_LOG(NETPLAY, "Game changed to %s", m_selected_game.c_str());
|
||||
INFO_LOG(NETPLAY, "Game changed to %s", netplay_name.c_str());
|
||||
|
||||
// update gui
|
||||
m_dialog->OnMsgChangeGame(m_selected_game);
|
||||
m_dialog->OnMsgChangeGame(m_selected_game, netplay_name);
|
||||
|
||||
sf::Packet game_status_packet;
|
||||
game_status_packet << static_cast<MessageId>(NP_MSG_GAME_STATUS);
|
||||
|
||||
PlayerGameStatus status = m_dialog->FindGame(m_selected_game).empty() ?
|
||||
PlayerGameStatus::NotFound :
|
||||
PlayerGameStatus::Ok;
|
||||
SyncIdentifierComparison result;
|
||||
m_dialog->FindGameFile(m_selected_game, &result);
|
||||
|
||||
game_status_packet << static_cast<u32>(status);
|
||||
game_status_packet << static_cast<u32>(result);
|
||||
Send(game_status_packet);
|
||||
|
||||
sf::Packet ipl_status_packet;
|
||||
@ -609,7 +628,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
||||
Player& player = m_players[pid];
|
||||
u32 status;
|
||||
packet >> status;
|
||||
player.game_status = static_cast<PlayerGameStatus>(status);
|
||||
player.game_status = static_cast<SyncIdentifierComparison>(status);
|
||||
}
|
||||
|
||||
m_dialog->Update();
|
||||
@ -623,7 +642,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
||||
packet >> m_current_game;
|
||||
packet >> m_net_settings.m_CPUthread;
|
||||
|
||||
INFO_LOG(NETPLAY, "Start of game %s", m_selected_game.c_str());
|
||||
INFO_LOG(NETPLAY, "Start of game %s", m_selected_game.game_id.c_str());
|
||||
|
||||
{
|
||||
std::underlying_type_t<PowerPC::CPUCore> core;
|
||||
@ -1172,10 +1191,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
||||
|
||||
case NP_MSG_COMPUTE_MD5:
|
||||
{
|
||||
std::string file_identifier;
|
||||
packet >> file_identifier;
|
||||
SyncIdentifier sync_identifier;
|
||||
ReceiveSyncIdentifier(packet, sync_identifier);
|
||||
|
||||
ComputeMD5(file_identifier);
|
||||
ComputeMD5(sync_identifier);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1382,11 +1401,15 @@ void NetPlayClient::GetPlayerList(std::string& list, std::vector<int>& pid_list)
|
||||
|
||||
switch (player.game_status)
|
||||
{
|
||||
case PlayerGameStatus::Ok:
|
||||
case SyncIdentifierComparison::SameGame:
|
||||
ss << "ready";
|
||||
break;
|
||||
|
||||
case PlayerGameStatus::NotFound:
|
||||
case SyncIdentifierComparison::DifferentVersion:
|
||||
ss << "wrong game version";
|
||||
break;
|
||||
|
||||
case SyncIdentifierComparison::DifferentGame:
|
||||
ss << "game missing";
|
||||
break;
|
||||
|
||||
@ -2286,23 +2309,24 @@ bool NetPlayClient::DoAllPlayersHaveGame()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> 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; });
|
||||
return std::all_of(std::begin(m_players), std::end(m_players), [](auto entry) {
|
||||
return entry.second.game_status == SyncIdentifierComparison::SameGame;
|
||||
});
|
||||
}
|
||||
|
||||
void NetPlayClient::ComputeMD5(const std::string& file_identifier)
|
||||
void NetPlayClient::ComputeMD5(const SyncIdentifier& sync_identifier)
|
||||
{
|
||||
if (m_should_compute_MD5)
|
||||
return;
|
||||
|
||||
m_dialog->ShowMD5Dialog(file_identifier);
|
||||
m_dialog->ShowMD5Dialog(sync_identifier.game_id);
|
||||
m_should_compute_MD5 = true;
|
||||
|
||||
std::string file;
|
||||
if (file_identifier == WII_SDCARD)
|
||||
if (sync_identifier == GetSDCardIdentifier())
|
||||
file = File::GetUserPath(F_WIISDCARD_IDX);
|
||||
else
|
||||
file = m_dialog->FindGame(file_identifier);
|
||||
else if (auto game = m_dialog->FindGameFile(sync_identifier))
|
||||
file = game->GetFilePath();
|
||||
|
||||
if (file.empty() || !File::Exists(file))
|
||||
{
|
||||
@ -2348,6 +2372,11 @@ void NetPlayClient::AdjustPadBufferSize(const unsigned int size)
|
||||
m_dialog->OnPadBufferChanged(size);
|
||||
}
|
||||
|
||||
SyncIdentifier NetPlayClient::GetSDCardIdentifier()
|
||||
{
|
||||
return SyncIdentifier{{}, "sd", {}, {}, {}, {}};
|
||||
}
|
||||
|
||||
bool IsNetPlayRunning()
|
||||
{
|
||||
return netplay_client != nullptr;
|
||||
|
Reference in New Issue
Block a user