From e2f1da52107284d1d797ac71671f1c5cb6919077 Mon Sep 17 00:00:00 2001 From: Techjar Date: Mon, 1 Apr 2019 22:36:48 -0400 Subject: [PATCH] NetPlay: Move host input authority logic to client This is a prerequisite for golf mode, as the client needs to be in control of sending pad states. --- Source/Core/Core/NetPlayClient.cpp | 68 ++++++++--- Source/Core/Core/NetPlayClient.h | 1 + Source/Core/Core/NetPlayProto.h | 3 +- Source/Core/Core/NetPlayServer.cpp | 108 +++++++----------- Source/Core/Core/NetPlayServer.h | 4 - Source/Core/DolphinQt/MainWindow.cpp | 3 +- .../Core/DolphinQt/NetPlay/NetPlayDialog.cpp | 34 +++--- 7 files changed, 112 insertions(+), 109 deletions(-) diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index c90aba3959..5de24892e3 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -442,6 +442,30 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) } break; + case NP_MSG_PAD_HOST_DATA: + { + while (!packet.endOfPacket()) + { + PadIndex map; + packet >> map; + + GCPadStatus pad; + packet >> pad.button >> pad.analogA >> pad.analogB >> pad.stickX >> pad.stickY >> + pad.substickX >> pad.substickY >> pad.triggerLeft >> pad.triggerRight >> pad.isConnected; + + // Trusting server for good map value (>=0 && <4) + // write to last status + m_last_pad_status[map] = pad; + + if (!m_first_pad_status_received[map]) + { + m_first_pad_status_received[map] = true; + m_first_pad_status_received_event.Set(); + } + } + } + break; + case NP_MSG_WIIMOTE_DATA: { PadIndex map; @@ -471,15 +495,6 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) } break; - case NP_MSG_PAD_FIRST_RECEIVED: - { - PadIndex map; - packet >> map; - packet >> m_first_pad_status_received[map]; - m_first_pad_status_received_event.Set(); - } - break; - case NP_MSG_HOST_INPUT_AUTHORITY: { packet >> m_host_input_authority; @@ -1865,9 +1880,18 @@ bool NetPlayClient::PollLocalPad(const int local_pad, sf::Packet& packet) if (m_host_input_authority) { - // add to packet - AddPadStateToPacket(ingame_pad, pad_status, packet); - data_added = true; + if (!m_local_player->IsHost()) + { + // add to packet + AddPadStateToPacket(ingame_pad, pad_status, packet); + data_added = true; + } + else + { + // set locally + m_last_pad_status[ingame_pad] = pad_status; + m_first_pad_status_received[ingame_pad] = true; + } } else { @@ -1892,6 +1916,9 @@ void NetPlayClient::SendPadHostPoll(const PadIndex pad_num) if (!m_local_player->IsHost()) return; + sf::Packet packet; + packet << static_cast(NP_MSG_PAD_HOST_DATA); + if (pad_num < 0) { for (size_t i = 0; i < m_pad_map.size(); i++) @@ -1907,6 +1934,16 @@ void NetPlayClient::SendPadHostPoll(const PadIndex pad_num) m_first_pad_status_received_event.Wait(); } } + + for (size_t i = 0; i < m_pad_map.size(); i++) + { + if (m_pad_map[i] == 0) + continue; + + const GCPadStatus& pad_status = m_last_pad_status[i]; + m_pad_buffer[i].Push(pad_status); + AddPadStateToPacket(static_cast(i), pad_status, packet); + } } else if (m_pad_map[pad_num] != 0) { @@ -1917,11 +1954,12 @@ void NetPlayClient::SendPadHostPoll(const PadIndex pad_num) m_first_pad_status_received_event.Wait(); } + + const GCPadStatus& pad_status = m_last_pad_status[pad_num]; + m_pad_buffer[pad_num].Push(pad_status); + AddPadStateToPacket(pad_num, pad_status, packet); } - sf::Packet packet; - packet << static_cast(NP_MSG_PAD_HOST_POLL); - packet << pad_num; SendAsync(std::move(packet)); } diff --git a/Source/Core/Core/NetPlayClient.h b/Source/Core/Core/NetPlayClient.h index e7b3b20363..cfe6e37543 100644 --- a/Source/Core/Core/NetPlayClient.h +++ b/Source/Core/Core/NetPlayClient.h @@ -158,6 +158,7 @@ protected: std::array, 4> m_pad_buffer; std::array, 4> m_wiimote_buffer; + std::array m_last_pad_status{}; std::array m_first_pad_status_received{}; std::chrono::time_point m_buffer_under_target_last; diff --git a/Source/Core/Core/NetPlayProto.h b/Source/Core/Core/NetPlayProto.h index 5eaedcd840..908b8fe004 100644 --- a/Source/Core/Core/NetPlayProto.h +++ b/Source/Core/Core/NetPlayProto.h @@ -123,8 +123,7 @@ enum NP_MSG_PAD_DATA = 0x60, NP_MSG_PAD_MAPPING = 0x61, NP_MSG_PAD_BUFFER = 0x62, - NP_MSG_PAD_HOST_POLL = 0x63, - NP_MSG_PAD_FIRST_RECEIVED = 0x64, + NP_MSG_PAD_HOST_DATA = 0x63, NP_MSG_WIIMOTE_DATA = 0x70, NP_MSG_WIIMOTE_MAPPING = 0x71, diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 166ce881bf..2c6e4aa181 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -527,12 +527,16 @@ void NetPlayServer::AdjustPadBufferSize(unsigned int size) m_target_buffer_size = size; - // tell clients to change buffer size - sf::Packet spac; - spac << static_cast(NP_MSG_PAD_BUFFER); - spac << static_cast(m_target_buffer_size); + // not needed on clients with host input authority + if (!m_host_input_authority) + { + // tell clients to change buffer size + sf::Packet spac; + spac << static_cast(NP_MSG_PAD_BUFFER); + spac << static_cast(m_target_buffer_size); - SendAsyncToClients(std::move(spac)); + SendAsyncToClients(std::move(spac)); + } } void NetPlayServer::SetHostInputAuthority(const bool enable) @@ -652,7 +656,7 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player) break; sf::Packet spac; - spac << static_cast(NP_MSG_PAD_DATA); + spac << static_cast(m_host_input_authority ? NP_MSG_PAD_HOST_DATA : NP_MSG_PAD_DATA); while (!packet.endOfPacket()) { @@ -670,59 +674,42 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player) packet >> pad.button >> pad.analogA >> pad.analogB >> pad.stickX >> pad.stickY >> pad.substickX >> pad.substickY >> pad.triggerLeft >> pad.triggerRight >> pad.isConnected; - if (m_host_input_authority) - { - m_last_pad_status[map] = pad; - - if (!m_first_pad_status_received[map]) - { - m_first_pad_status_received[map] = true; - SendFirstReceivedToHost(map, true); - } - } - else - { - spac << map << pad.button << pad.analogA << pad.analogB << pad.stickX << pad.stickY - << pad.substickX << pad.substickY << pad.triggerLeft << pad.triggerRight - << pad.isConnected; - } - } - - if (!m_host_input_authority) - SendToClients(spac, player.pid); - } - break; - - case NP_MSG_PAD_HOST_POLL: - { - PadIndex pad_num; - packet >> pad_num; - - sf::Packet spac; - spac << static_cast(NP_MSG_PAD_DATA); - - if (pad_num < 0) - { - for (size_t i = 0; i < m_pad_map.size(); i++) - { - if (m_pad_map[i] == 0) - continue; - - const GCPadStatus& pad = m_last_pad_status[i]; - spac << static_cast(i) << pad.button << pad.analogA << pad.analogB << pad.stickX - << pad.stickY << pad.substickX << pad.substickY << pad.triggerLeft << pad.triggerRight - << pad.isConnected; - } - } - else if (m_pad_map.at(pad_num) != 0) - { - const GCPadStatus& pad = m_last_pad_status[pad_num]; - spac << pad_num << pad.button << pad.analogA << pad.analogB << pad.stickX << pad.stickY + spac << map << pad.button << pad.analogA << pad.analogB << pad.stickX << pad.stickY << pad.substickX << pad.substickY << pad.triggerLeft << pad.triggerRight << pad.isConnected; } - SendToClients(spac); + if (m_host_input_authority) + Send(m_players.at(1).socket, spac); + else + SendToClients(spac, player.pid); + } + break; + + case NP_MSG_PAD_HOST_DATA: + { + // Kick player if they're not the host. + if (!player.IsHost()) + return 1; + + sf::Packet spac; + spac << static_cast(NP_MSG_PAD_DATA); + + while (!packet.endOfPacket()) + { + PadIndex map; + packet >> map; + + GCPadStatus pad; + packet >> pad.button >> pad.analogA >> pad.analogB >> pad.stickX >> pad.stickY >> + pad.substickX >> pad.substickY >> pad.triggerLeft >> pad.triggerRight >> pad.isConnected; + + spac << map << pad.button << pad.analogA << pad.analogB << pad.stickX << pad.stickY + << pad.substickX << pad.substickY << pad.triggerLeft << pad.triggerRight + << pad.isConnected; + } + + SendToClients(spac, player.pid); } break; @@ -1141,8 +1128,6 @@ bool NetPlayServer::StartGame() if (!m_host_input_authority) AdjustPadBufferSize(m_target_buffer_size); - m_first_pad_status_received.fill(false); - const sf::Uint64 initial_rtc = GetInitialNetPlayRTC(); const std::string region = SConfig::GetDirectoryForRegion( @@ -1720,15 +1705,6 @@ bool NetPlayServer::CompressBufferIntoPacket(const std::vector& in_buffer, s return true; } -void NetPlayServer::SendFirstReceivedToHost(const PadIndex map, const bool state) -{ - sf::Packet pac; - pac << static_cast(NP_MSG_PAD_FIRST_RECEIVED); - pac << map; - pac << state; - Send(m_players.at(1).socket, pac); -} - u64 NetPlayServer::GetInitialNetPlayRTC() const { const auto& config = SConfig::GetInstance(); diff --git a/Source/Core/Core/NetPlayServer.h b/Source/Core/Core/NetPlayServer.h index 70c354a41d..447b3de161 100644 --- a/Source/Core/Core/NetPlayServer.h +++ b/Source/Core/Core/NetPlayServer.h @@ -118,7 +118,6 @@ private: void CheckSyncAndStartGame(); bool CompressFileIntoPacket(const std::string& file_path, sf::Packet& packet); bool CompressBufferIntoPacket(const std::vector& in_buffer, sf::Packet& packet); - void SendFirstReceivedToHost(PadIndex map, bool state); u64 GetInitialNetPlayRTC() const; @@ -161,9 +160,6 @@ private: std::unordered_map>> m_timebase_by_frame; bool m_desync_detected; - std::array m_last_pad_status{}; - std::array m_first_pad_status_received{}; - struct { std::recursive_mutex game; diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp index 9814644f78..5e7a5f2b46 100644 --- a/Source/Core/DolphinQt/MainWindow.cpp +++ b/Source/Core/DolphinQt/MainWindow.cpp @@ -1284,8 +1284,7 @@ bool MainWindow::NetPlayJoin() if (server) { server->SetHostInputAuthority(host_input_authority); - if (!host_input_authority) - server->AdjustPadBufferSize(Config::Get(Config::NETPLAY_BUFFER_SIZE)); + server->AdjustPadBufferSize(Config::Get(Config::NETPLAY_BUFFER_SIZE)); } // Create Client diff --git a/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp b/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp index 49c0c8310c..9adafba0b4 100644 --- a/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp +++ b/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp @@ -300,7 +300,7 @@ void NetPlayDialog::ConnectWidgets() auto client = Settings::Instance().GetNetPlayClient(); auto server = Settings::Instance().GetNetPlayServer(); - if (server) + if (server && !m_host_input_authority) server->AdjustPadBufferSize(value); else client->AdjustPadBufferSize(value); @@ -539,8 +539,6 @@ void NetPlayDialog::show(std::string nickname, bool use_traversal) m_game_button->setEnabled(is_hosting); m_kick_button->setEnabled(false); - m_buffer_label->setText(is_hosting ? tr("Buffer:") : tr("Max Buffer:")); - QDialog::show(); UpdateGUI(); } @@ -857,9 +855,8 @@ void NetPlayDialog::OnPadBufferChanged(u32 buffer) const QSignalBlocker blocker(m_buffer_size_box); m_buffer_size_box->setValue(buffer); }); - DisplayMessage(m_host_input_authority && !IsHosting() ? - tr("Max buffer size changed to %1").arg(buffer) : - tr("Buffer size changed to %1").arg(buffer), + DisplayMessage(m_host_input_authority ? tr("Max buffer size changed to %1").arg(buffer) : + tr("Buffer size changed to %1").arg(buffer), "darkcyan"); m_buffer_size = static_cast(buffer); @@ -867,6 +864,10 @@ void NetPlayDialog::OnPadBufferChanged(u32 buffer) void NetPlayDialog::OnHostInputAuthorityChanged(bool enabled) { + m_host_input_authority = enabled; + DisplayMessage(enabled ? tr("Host input authority enabled") : tr("Host input authority disabled"), + ""); + QueueOnObject(this, [this, enabled] { const bool is_hosting = IsHosting(); const bool enable_buffer = is_hosting != enabled; @@ -878,7 +879,7 @@ void NetPlayDialog::OnHostInputAuthorityChanged(bool enabled) m_buffer_size_box->setHidden(false); m_buffer_label->setHidden(false); - QSignalBlocker blocker(m_host_input_authority_action); + const QSignalBlocker blocker(m_host_input_authority_action); m_host_input_authority_action->setChecked(enabled); } else @@ -887,15 +888,12 @@ void NetPlayDialog::OnHostInputAuthorityChanged(bool enabled) m_buffer_label->setEnabled(true); m_buffer_size_box->setHidden(!enable_buffer); m_buffer_label->setHidden(!enable_buffer); - - if (enabled) - m_buffer_size_box->setValue(Config::Get(Config::NETPLAY_CLIENT_BUFFER_SIZE)); } - }); - DisplayMessage(enabled ? tr("Host input authority enabled") : tr("Host input authority disabled"), - ""); - m_host_input_authority = enabled; + m_buffer_label->setText(enabled ? tr("Max Buffer:") : tr("Buffer:")); + if (enabled) + m_buffer_size_box->setValue(Config::Get(Config::NETPLAY_CLIENT_BUFFER_SIZE)); + }); } void NetPlayDialog::OnDesync(u32 frame, const std::string& player) @@ -1002,14 +1000,10 @@ void NetPlayDialog::SaveSettings() Config::ConfigChangeCallbackGuard config_guard; if (m_host_input_authority) - { - if (!IsHosting()) - Config::SetBase(Config::NETPLAY_CLIENT_BUFFER_SIZE, m_buffer_size_box->value()); - } + Config::SetBase(Config::NETPLAY_CLIENT_BUFFER_SIZE, m_buffer_size_box->value()); else - { Config::SetBase(Config::NETPLAY_BUFFER_SIZE, m_buffer_size_box->value()); - } + Config::SetBase(Config::NETPLAY_WRITE_SAVE_SDCARD_DATA, m_save_sd_action->isChecked()); Config::SetBase(Config::NETPLAY_LOAD_WII_SAVE, m_load_wii_action->isChecked()); Config::SetBase(Config::NETPLAY_SYNC_SAVES, m_sync_save_data_action->isChecked());