Netplay: Sync codes

Adds a tickbox to the server's window to syncronize codes. Codes
are temporarily sent to each client and are used for the duration of the
session.

Saves the "sync codes" tickbox as per PR Netplay: Properly save hosting
settings #7483
This commit is contained in:
Vin Bertinelli authored and Pierre Bourdon committed 2018-10-29 23:00:51 +01:00
1 parent 0140009114
commit 469f29350f
17 files changed
+545 -7

No files matched your search

+191
View File
@@ -33,8 +33,10 @@
#include "Common/StringUtil.h"
#include "Common/Timer.h"
#include "Common/Version.h"
#include "Core/ActionReplay.h"
#include "Core/Config/NetplaySettings.h"
#include "Core/ConfigManager.h"
#include "Core/GeckoCode.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/HW/SI/SI.h"
#include "Core/HW/SI/SI_DeviceGCController.h"
@@ -549,6 +551,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
packet >> m_net_settings.m_SyncSaveData;
packet >> m_net_settings.m_SaveDataRegion;
packet >> m_net_settings.m_SyncCodes;
m_net_settings.m_IsHosting = m_local_player->IsHost();
m_net_settings.m_HostInputAuthority = m_host_input_authority;
@@ -644,6 +647,9 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
{
case SYNC_SAVE_DATA_NOTIFY:
{
if (m_local_player->IsHost())
return 0;
packet >> m_sync_save_data_count;
m_sync_save_data_success_count = 0;
@@ -823,6 +829,163 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
}
break;
case NP_MSG_SYNC_CODES:
{
// Recieve Data Packet
MessageId sub_id;
packet >> sub_id;
// Check Which Operation to Perform with This Packet
switch (sub_id)
{
case SYNC_CODES_NOTIFY:
{
// Set both codes as unsynced
m_sync_gecko_codes_complete = false;
m_sync_ar_codes_complete = false;
}
break;
case SYNC_CODES_NOTIFY_GECKO:
{
// Return if this is the host
if (m_local_player->IsHost())
return 0;
// Receive Number of Codelines to Receive
packet >> m_sync_gecko_codes_count;
m_sync_gecko_codes_success_count = 0;
NOTICE_LOG(ACTIONREPLAY, "Receiving %d Gecko codelines", m_sync_gecko_codes_count);
// Check if no codes to sync, if so return as finished
if (m_sync_gecko_codes_count == 0)
{
m_sync_gecko_codes_complete = true;
SyncCodeResponse(true);
}
else
m_dialog->AppendChat(GetStringT("Synchronizing gecko codes..."));
}
break;
case SYNC_CODES_DATA_GECKO:
{
// Return if this is the host
if (m_local_player->IsHost())
return 0;
// Create a synced code vector
std::vector<Gecko::GeckoCode> synced_codes;
// Create a GeckoCode
Gecko::GeckoCode gcode;
gcode = Gecko::GeckoCode();
// Initialize gcode
gcode.name = "Synced Codes";
gcode.enabled = true;
// Receive code contents from packet
for (int i = 0; i < m_sync_gecko_codes_count; i++)
{
Gecko::GeckoCode::Code new_code;
packet >> new_code.address;
packet >> new_code.data;
NOTICE_LOG(ACTIONREPLAY, "Received %08x %08x", new_code.address, new_code.data);
gcode.codes.push_back(std::move(new_code));
if (++m_sync_gecko_codes_success_count >= m_sync_gecko_codes_count)
{
m_sync_gecko_codes_complete = true;
SyncCodeResponse(true);
}
}
// Add gcode containing all codes to Gecko Code vector
synced_codes.push_back(std::move(gcode));
// Clear Vector if received 0 codes (match host's end when using no codes)
if (m_sync_gecko_codes_count == 0)
synced_codes.clear();
// Copy this to the vector located in GeckoCode.cpp
Gecko::UpdateSyncedCodes(synced_codes);
}
break;
case SYNC_CODES_NOTIFY_AR:
{
// Return if this is the host
if (m_local_player->IsHost())
return 0;
// Receive Number of Codelines to Receive
packet >> m_sync_ar_codes_count;
m_sync_ar_codes_success_count = 0;
NOTICE_LOG(ACTIONREPLAY, "Receiving %d AR codelines", m_sync_ar_codes_count);
// Check if no codes to sync, if so return as finished
if (m_sync_ar_codes_count == 0)
{
m_sync_ar_codes_complete = true;
SyncCodeResponse(true);
}
else
m_dialog->AppendChat(GetStringT("Synchronizing AR codes..."));
}
break;
case SYNC_CODES_DATA_AR:
{
// Return if this is the host
if (m_local_player->IsHost())
return 0;
// Create a synced code vector
std::vector<ActionReplay::ARCode> synced_codes;
// Create an ARCode
ActionReplay::ARCode arcode;
arcode = ActionReplay::ARCode();
// Initialize arcode
arcode.name = "Synced Codes";
arcode.active = true;
// Receive code contents from packet
for (int i = 0; i < m_sync_ar_codes_count; i++)
{
ActionReplay::AREntry new_code;
packet >> new_code.cmd_addr;
packet >> new_code.value;
NOTICE_LOG(ACTIONREPLAY, "Received %08x %08x", new_code.cmd_addr, new_code.value);
arcode.ops.push_back(new_code);
if (++m_sync_ar_codes_success_count >= m_sync_ar_codes_count)
{
m_sync_ar_codes_complete = true;
SyncCodeResponse(true);
}
}
// Add arcode containing all codes to AR Code vector
synced_codes.push_back(std::move(arcode));
// Clear Vector if received 0 codes (match host's end when using no codes)
if (m_sync_ar_codes_count == 0)
synced_codes.clear();
// Copy this to the vector located in ActionReplay.cpp
ActionReplay::UpdateSyncedCodes(synced_codes);
}
break;
}
}
break;
case NP_MSG_COMPUTE_MD5:
{
std::string file_identifier;
@@ -1193,6 +1356,34 @@ void NetPlayClient::SyncSaveDataResponse(const bool success)
}
}
void NetPlayClient::SyncCodeResponse(const bool success)
{
// If something failed, immediately report back that code sync failed
if (!success)
{
m_dialog->AppendChat(GetStringT("Error processing Codes."));
sf::Packet response_packet;
response_packet << static_cast<MessageId>(NP_MSG_SYNC_CODES);
response_packet << static_cast<MessageId>(SYNC_CODES_FAILURE);
Send(response_packet);
return;
}
// If both gecko and AR codes have completely finished transferring, report back as successful
if (m_sync_gecko_codes_complete && m_sync_ar_codes_complete)
{
m_dialog->AppendChat(GetStringT("Codes received!"));
sf::Packet response_packet;
response_packet << static_cast<MessageId>(NP_MSG_SYNC_CODES);
response_packet << static_cast<MessageId>(SYNC_CODES_SUCCESS);
Send(response_packet);
}
}
bool NetPlayClient::DecompressPacketIntoFile(sf::Packet& packet, const std::string& file_path)
{
u64 file_size = Common::PacketReadU64(packet);