dolphin/Source/Core/Core/NetPlayClient.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

360 lines
12 KiB
C
Raw Normal View History

// Copyright 2010 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <SFML/Network/Packet.hpp>
#include <array>
NetPlay host input authority mode Currently, each player buffers their own inputs and sends them to the host. The host then relays those inputs to everyone else. Every player waits on inputs from all players to be buffered before continuing. What this means is all clients run in lockstep, and the total latency of inputs cannot be lower than the sum of the 2 highest client ping times in the game (in 3+ player sessions with people across the world, the latency can be very high). Host input authority mode changes it so players no longer buffer their own inputs, and only send them to the host. The host stores only the most recent input received from a player. The host then sends inputs for all pads at the SI poll interval, similar to the existing code. If a player sends inputs to slowly, their last received input is simply sent again. If they send too quickly, inputs are dropped. This means that the host has full control over what inputs are actually read by the game, hence the name of the mode. Also, because the rate at which inputs are received by SI is decoupled from the rate at which players are sending inputs, clients are no longer dependent on each other. They only care what the host is doing. This means that they can set their buffer individually based on their latency to the host, rather than the highest latency between any 2 players, allowing someone with lower ping to the host to have less latency than someone else. This is a catch to this: as a necessity of how the host's input sending works, the host has 0 latency. There isn't a good way to fix this, as input delay is now solely dependent on the real latency to the host's server. Having differing latency between players would be considered unfair for competitive play, but for casual play we don't really care. For this reason though, combined with the potential for a few inputs to be dropped on a bad connection, the old mode will remain and this new mode is entirely optional.
2018-08-24 08:17:18 +00:00
#include <chrono>
#include <map>
#include <memory>
2015-05-26 21:23:43 +00:00
#include <mutex>
#include <span>
#include <string>
2015-05-26 21:23:43 +00:00
#include <thread>
#include <unordered_map>
#include <utility>
#include <vector>
#include "Common/CommonTypes.h"
#include "Common/Event.h"
#include "Common/SPSCQueue.h"
#include "Common/TraversalClient.h"
#include "Core/NetPlayProto.h"
#include "Core/SyncIdentifier.h"
#include "InputCommon/GCPadStatus.h"
class BootSessionData;
namespace IOS::HLE::FS
{
class FileSystem;
}
namespace UICommon
{
class GameFile;
}
namespace WiimoteEmu
{
struct SerializedWiimoteState;
}
namespace NetPlay
{
class NetPlayUI
{
public:
2014-09-11 17:00:40 +00:00
virtual ~NetPlayUI() {}
virtual void BootGame(const std::string& filename,
std::unique_ptr<BootSessionData> boot_session_data) = 0;
virtual void StopGame() = 0;
virtual bool IsHosting() const = 0;
virtual void Update() = 0;
virtual void AppendChat(const std::string& msg) = 0;
virtual void OnMsgChangeGame(const SyncIdentifier& sync_identifier,
const std::string& netplay_name) = 0;
2021-07-04 11:33:58 +00:00
virtual void OnMsgChangeGBARom(int pad, const NetPlay::GBAConfig& config) = 0;
virtual void OnMsgStartGame() = 0;
virtual void OnMsgStopGame() = 0;
virtual void OnMsgPowerButton() = 0;
virtual void OnPlayerConnect(const std::string& player) = 0;
virtual void OnPlayerDisconnect(const std::string& player) = 0;
virtual void OnPadBufferChanged(u32 buffer) = 0;
NetPlay host input authority mode Currently, each player buffers their own inputs and sends them to the host. The host then relays those inputs to everyone else. Every player waits on inputs from all players to be buffered before continuing. What this means is all clients run in lockstep, and the total latency of inputs cannot be lower than the sum of the 2 highest client ping times in the game (in 3+ player sessions with people across the world, the latency can be very high). Host input authority mode changes it so players no longer buffer their own inputs, and only send them to the host. The host stores only the most recent input received from a player. The host then sends inputs for all pads at the SI poll interval, similar to the existing code. If a player sends inputs to slowly, their last received input is simply sent again. If they send too quickly, inputs are dropped. This means that the host has full control over what inputs are actually read by the game, hence the name of the mode. Also, because the rate at which inputs are received by SI is decoupled from the rate at which players are sending inputs, clients are no longer dependent on each other. They only care what the host is doing. This means that they can set their buffer individually based on their latency to the host, rather than the highest latency between any 2 players, allowing someone with lower ping to the host to have less latency than someone else. This is a catch to this: as a necessity of how the host's input sending works, the host has 0 latency. There isn't a good way to fix this, as input delay is now solely dependent on the real latency to the host's server. Having differing latency between players would be considered unfair for competitive play, but for casual play we don't really care. For this reason though, combined with the potential for a few inputs to be dropped on a bad connection, the old mode will remain and this new mode is entirely optional.
2018-08-24 08:17:18 +00:00
virtual void OnHostInputAuthorityChanged(bool enabled) = 0;
virtual void OnDesync(u32 frame, const std::string& player) = 0;
virtual void OnConnectionLost() = 0;
virtual void OnConnectionError(const std::string& message) = 0;
virtual void OnTraversalError(Common::TraversalClient::FailureReason error) = 0;
virtual void OnTraversalStateChanged(Common::TraversalClient::State state) = 0;
virtual void OnGameStartAborted() = 0;
virtual void OnGolferChanged(bool is_golfer, const std::string& golfer_name) = 0;
virtual void OnTtlDetermined(u8 ttl) = 0;
virtual bool IsRecording() = 0;
virtual std::shared_ptr<const UICommon::GameFile>
FindGameFile(const SyncIdentifier& sync_identifier,
SyncIdentifierComparison* found = nullptr) = 0;
2021-07-04 11:33:58 +00:00
virtual std::string FindGBARomPath(const std::array<u8, 20>& hash, std::string_view title,
int device_number) = 0;
2022-07-28 01:43:16 +00:00
virtual void ShowGameDigestDialog(const std::string& title) = 0;
virtual void SetGameDigestProgress(int pid, int progress) = 0;
virtual void SetGameDigestResult(int pid, const std::string& result) = 0;
virtual void AbortGameDigest() = 0;
virtual void OnIndexAdded(bool success, std::string error) = 0;
virtual void OnIndexRefreshFailed(std::string error) = 0;
virtual void ShowChunkedProgressDialog(const std::string& title, u64 data_size,
const std::vector<int>& players) = 0;
virtual void HideChunkedProgressDialog() = 0;
virtual void SetChunkedProgress(int pid, u64 progress) = 0;
virtual void SetHostWiiSyncData(std::vector<u64> titles, std::string redirect_folder) = 0;
};
class Player
{
2015-02-02 09:27:06 +00:00
public:
PlayerId pid{};
std::string name;
std::string revision;
u32 ping = 0;
SyncIdentifierComparison game_status = SyncIdentifierComparison::Unknown;
NetPlay host input authority mode Currently, each player buffers their own inputs and sends them to the host. The host then relays those inputs to everyone else. Every player waits on inputs from all players to be buffered before continuing. What this means is all clients run in lockstep, and the total latency of inputs cannot be lower than the sum of the 2 highest client ping times in the game (in 3+ player sessions with people across the world, the latency can be very high). Host input authority mode changes it so players no longer buffer their own inputs, and only send them to the host. The host stores only the most recent input received from a player. The host then sends inputs for all pads at the SI poll interval, similar to the existing code. If a player sends inputs to slowly, their last received input is simply sent again. If they send too quickly, inputs are dropped. This means that the host has full control over what inputs are actually read by the game, hence the name of the mode. Also, because the rate at which inputs are received by SI is decoupled from the rate at which players are sending inputs, clients are no longer dependent on each other. They only care what the host is doing. This means that they can set their buffer individually based on their latency to the host, rather than the highest latency between any 2 players, allowing someone with lower ping to the host to have less latency than someone else. This is a catch to this: as a necessity of how the host's input sending works, the host has 0 latency. There isn't a good way to fix this, as input delay is now solely dependent on the real latency to the host's server. Having differing latency between players would be considered unfair for competitive play, but for casual play we don't really care. For this reason though, combined with the potential for a few inputs to be dropped on a bad connection, the old mode will remain and this new mode is entirely optional.
2018-08-24 08:17:18 +00:00
bool IsHost() const { return pid == 1; }
};
class NetPlayClient : public Common::TraversalClientClient
{
public:
void ThreadFunc();
void SendAsync(sf::Packet&& packet, u8 channel_id = DEFAULT_CHANNEL);
NetPlayClient(const std::string& address, const u16 port, NetPlayUI* dialog,
const std::string& name, const NetTraversalConfig& traversal_config);
~NetPlayClient();
std::vector<const Player*> GetPlayers();
const NetSettings& GetNetSettings() const;
// Called from the GUI thread.
bool IsConnected() const { return m_is_connected; }
bool StartGame(const std::string& path);
void InvokeStop();
bool StopGame();
void Stop();
bool ChangeGame(const std::string& game);
void SendChatMessage(const std::string& msg);
2018-07-03 23:02:13 +00:00
void RequestStopGame();
void SendPowerButtonEvent();
void RequestGolfControl(PlayerId pid);
void RequestGolfControl();
2019-04-02 21:13:42 +00:00
std::string GetCurrentGolfer();
// Send and receive pads values
struct WiimoteDataBatchEntry
{
int wiimote;
WiimoteEmu::SerializedWiimoteState* state;
};
bool WiimoteUpdate(const std::span<WiimoteDataBatchEntry>& entries);
NetPlay host input authority mode Currently, each player buffers their own inputs and sends them to the host. The host then relays those inputs to everyone else. Every player waits on inputs from all players to be buffered before continuing. What this means is all clients run in lockstep, and the total latency of inputs cannot be lower than the sum of the 2 highest client ping times in the game (in 3+ player sessions with people across the world, the latency can be very high). Host input authority mode changes it so players no longer buffer their own inputs, and only send them to the host. The host stores only the most recent input received from a player. The host then sends inputs for all pads at the SI poll interval, similar to the existing code. If a player sends inputs to slowly, their last received input is simply sent again. If they send too quickly, inputs are dropped. This means that the host has full control over what inputs are actually read by the game, hence the name of the mode. Also, because the rate at which inputs are received by SI is decoupled from the rate at which players are sending inputs, clients are no longer dependent on each other. They only care what the host is doing. This means that they can set their buffer individually based on their latency to the host, rather than the highest latency between any 2 players, allowing someone with lower ping to the host to have less latency than someone else. This is a catch to this: as a necessity of how the host's input sending works, the host has 0 latency. There isn't a good way to fix this, as input delay is now solely dependent on the real latency to the host's server. Having differing latency between players would be considered unfair for competitive play, but for casual play we don't really care. For this reason though, combined with the potential for a few inputs to be dropped on a bad connection, the old mode will remain and this new mode is entirely optional.
2018-08-24 08:17:18 +00:00
bool GetNetPads(int pad_nb, bool from_vi, GCPadStatus* pad_status);
u64 GetInitialRTCValue() const;
void OnTraversalStateChanged() override;
void OnConnectReady(ENetAddress addr) override;
void OnConnectFailed(Common::TraversalConnectFailedReason reason) override;
void OnTtlDetermined(u8 ttl) override {}
bool IsFirstInGamePad(int ingame_pad) const;
int NumLocalPads() const;
int NumLocalWiimotes() const;
2017-03-19 13:07:33 +00:00
int InGamePadToLocalPad(int ingame_pad) const;
int LocalPadToInGamePad(int local_pad) const;
int InGameWiimoteToLocalWiimote(int ingame_wiimote) const;
int LocalWiimoteToInGameWiimote(int local_wiimote) const;
2019-04-02 21:13:42 +00:00
bool PlayerHasControllerMapped(PlayerId pid) const;
bool LocalPlayerHasControllerMapped() const;
bool IsLocalPlayer(PlayerId pid) const;
const PlayerId& GetLocalPlayerId() const;
2019-04-02 21:13:42 +00:00
static void SendTimeBase();
bool DoAllPlayersHaveGame();
2018-05-12 13:13:30 +00:00
const PadMappingArray& GetPadMapping() const;
2021-07-04 11:33:58 +00:00
const GBAConfigArray& GetGBAConfig() const;
2018-05-12 13:13:30 +00:00
const PadMappingArray& GetWiimoteMapping() const;
NetPlay host input authority mode Currently, each player buffers their own inputs and sends them to the host. The host then relays those inputs to everyone else. Every player waits on inputs from all players to be buffered before continuing. What this means is all clients run in lockstep, and the total latency of inputs cannot be lower than the sum of the 2 highest client ping times in the game (in 3+ player sessions with people across the world, the latency can be very high). Host input authority mode changes it so players no longer buffer their own inputs, and only send them to the host. The host stores only the most recent input received from a player. The host then sends inputs for all pads at the SI poll interval, similar to the existing code. If a player sends inputs to slowly, their last received input is simply sent again. If they send too quickly, inputs are dropped. This means that the host has full control over what inputs are actually read by the game, hence the name of the mode. Also, because the rate at which inputs are received by SI is decoupled from the rate at which players are sending inputs, clients are no longer dependent on each other. They only care what the host is doing. This means that they can set their buffer individually based on their latency to the host, rather than the highest latency between any 2 players, allowing someone with lower ping to the host to have less latency than someone else. This is a catch to this: as a necessity of how the host's input sending works, the host has 0 latency. There isn't a good way to fix this, as input delay is now solely dependent on the real latency to the host's server. Having differing latency between players would be considered unfair for competitive play, but for casual play we don't really care. For this reason though, combined with the potential for a few inputs to be dropped on a bad connection, the old mode will remain and this new mode is entirely optional.
2018-08-24 08:17:18 +00:00
void AdjustPadBufferSize(unsigned int size);
void SetWiiSyncData(std::unique_ptr<IOS::HLE::FS::FileSystem> fs, std::vector<u64> titles,
std::string redirect_folder);
static SyncIdentifier GetSDCardIdentifier();
protected:
struct AsyncQueueEntry
{
sf::Packet packet;
u8 channel_id = 0;
};
void ClearBuffers();
struct
{
std::recursive_mutex game;
// lock order
std::recursive_mutex players;
std::recursive_mutex async_queue_write;
} m_crit;
Common::SPSCQueue<AsyncQueueEntry, false> m_async_queue;
std::array<Common::SPSCQueue<GCPadStatus>, 4> m_pad_buffer;
std::array<Common::SPSCQueue<WiimoteEmu::SerializedWiimoteState>, 4> m_wiimote_buffer;
std::array<GCPadStatus, 4> m_last_pad_status{};
NetPlay host input authority mode Currently, each player buffers their own inputs and sends them to the host. The host then relays those inputs to everyone else. Every player waits on inputs from all players to be buffered before continuing. What this means is all clients run in lockstep, and the total latency of inputs cannot be lower than the sum of the 2 highest client ping times in the game (in 3+ player sessions with people across the world, the latency can be very high). Host input authority mode changes it so players no longer buffer their own inputs, and only send them to the host. The host stores only the most recent input received from a player. The host then sends inputs for all pads at the SI poll interval, similar to the existing code. If a player sends inputs to slowly, their last received input is simply sent again. If they send too quickly, inputs are dropped. This means that the host has full control over what inputs are actually read by the game, hence the name of the mode. Also, because the rate at which inputs are received by SI is decoupled from the rate at which players are sending inputs, clients are no longer dependent on each other. They only care what the host is doing. This means that they can set their buffer individually based on their latency to the host, rather than the highest latency between any 2 players, allowing someone with lower ping to the host to have less latency than someone else. This is a catch to this: as a necessity of how the host's input sending works, the host has 0 latency. There isn't a good way to fix this, as input delay is now solely dependent on the real latency to the host's server. Having differing latency between players would be considered unfair for competitive play, but for casual play we don't really care. For this reason though, combined with the potential for a few inputs to be dropped on a bad connection, the old mode will remain and this new mode is entirely optional.
2018-08-24 08:17:18 +00:00
std::array<bool, 4> m_first_pad_status_received{};
std::chrono::time_point<std::chrono::steady_clock> m_buffer_under_target_last;
NetPlayUI* m_dialog = nullptr;
2015-02-02 09:27:06 +00:00
ENetHost* m_client = nullptr;
ENetPeer* m_server = nullptr;
2015-02-02 09:27:06 +00:00
std::thread m_thread;
SyncIdentifier m_selected_game;
Common::Flag m_is_running{false};
Common::Flag m_do_loop{true};
// In non-host input authority mode, this is how many packets each client should
// try to keep in-flight to the other clients. In host input authority mode, this is how
// many incoming input packets need to be queued up before the client starts
// speeding up the game to drain the buffer.
unsigned int m_target_buffer_size = 20;
NetPlay host input authority mode Currently, each player buffers their own inputs and sends them to the host. The host then relays those inputs to everyone else. Every player waits on inputs from all players to be buffered before continuing. What this means is all clients run in lockstep, and the total latency of inputs cannot be lower than the sum of the 2 highest client ping times in the game (in 3+ player sessions with people across the world, the latency can be very high). Host input authority mode changes it so players no longer buffer their own inputs, and only send them to the host. The host stores only the most recent input received from a player. The host then sends inputs for all pads at the SI poll interval, similar to the existing code. If a player sends inputs to slowly, their last received input is simply sent again. If they send too quickly, inputs are dropped. This means that the host has full control over what inputs are actually read by the game, hence the name of the mode. Also, because the rate at which inputs are received by SI is decoupled from the rate at which players are sending inputs, clients are no longer dependent on each other. They only care what the host is doing. This means that they can set their buffer individually based on their latency to the host, rather than the highest latency between any 2 players, allowing someone with lower ping to the host to have less latency than someone else. This is a catch to this: as a necessity of how the host's input sending works, the host has 0 latency. There isn't a good way to fix this, as input delay is now solely dependent on the real latency to the host's server. Having differing latency between players would be considered unfair for competitive play, but for casual play we don't really care. For this reason though, combined with the potential for a few inputs to be dropped on a bad connection, the old mode will remain and this new mode is entirely optional.
2018-08-24 08:17:18 +00:00
bool m_host_input_authority = false;
PlayerId m_current_golfer = 1;
// This bool will stall the client at the start of GetNetPads, used for switching input control
// without deadlocking. Use the correspondingly named Event to wake it up.
bool m_wait_on_input;
bool m_wait_on_input_received;
Player* m_local_player = nullptr;
u32 m_current_game = 0;
2021-07-04 11:33:58 +00:00
PadMappingArray m_pad_map{};
GBAConfigArray m_gba_config{};
PadMappingArray m_wiimote_map{};
bool m_is_recording = false;
private:
enum class ConnectionState
{
WaitingForTraversalClientConnection,
WaitingForTraversalClientConnectReady,
Connecting,
WaitingForHelloResponse,
Connected,
Failure
};
void SendStartGamePacket();
void SendStopGamePacket();
void SyncSaveDataResponse(bool success);
void SyncCodeResponse(bool success);
NetPlay host input authority mode Currently, each player buffers their own inputs and sends them to the host. The host then relays those inputs to everyone else. Every player waits on inputs from all players to be buffered before continuing. What this means is all clients run in lockstep, and the total latency of inputs cannot be lower than the sum of the 2 highest client ping times in the game (in 3+ player sessions with people across the world, the latency can be very high). Host input authority mode changes it so players no longer buffer their own inputs, and only send them to the host. The host stores only the most recent input received from a player. The host then sends inputs for all pads at the SI poll interval, similar to the existing code. If a player sends inputs to slowly, their last received input is simply sent again. If they send too quickly, inputs are dropped. This means that the host has full control over what inputs are actually read by the game, hence the name of the mode. Also, because the rate at which inputs are received by SI is decoupled from the rate at which players are sending inputs, clients are no longer dependent on each other. They only care what the host is doing. This means that they can set their buffer individually based on their latency to the host, rather than the highest latency between any 2 players, allowing someone with lower ping to the host to have less latency than someone else. This is a catch to this: as a necessity of how the host's input sending works, the host has 0 latency. There isn't a good way to fix this, as input delay is now solely dependent on the real latency to the host's server. Having differing latency between players would be considered unfair for competitive play, but for casual play we don't really care. For this reason though, combined with the potential for a few inputs to be dropped on a bad connection, the old mode will remain and this new mode is entirely optional.
2018-08-24 08:17:18 +00:00
bool PollLocalPad(int local_pad, sf::Packet& packet);
void SendPadHostPoll(PadIndex pad_num);
NetPlay host input authority mode Currently, each player buffers their own inputs and sends them to the host. The host then relays those inputs to everyone else. Every player waits on inputs from all players to be buffered before continuing. What this means is all clients run in lockstep, and the total latency of inputs cannot be lower than the sum of the 2 highest client ping times in the game (in 3+ player sessions with people across the world, the latency can be very high). Host input authority mode changes it so players no longer buffer their own inputs, and only send them to the host. The host stores only the most recent input received from a player. The host then sends inputs for all pads at the SI poll interval, similar to the existing code. If a player sends inputs to slowly, their last received input is simply sent again. If they send too quickly, inputs are dropped. This means that the host has full control over what inputs are actually read by the game, hence the name of the mode. Also, because the rate at which inputs are received by SI is decoupled from the rate at which players are sending inputs, clients are no longer dependent on each other. They only care what the host is doing. This means that they can set their buffer individually based on their latency to the host, rather than the highest latency between any 2 players, allowing someone with lower ping to the host to have less latency than someone else. This is a catch to this: as a necessity of how the host's input sending works, the host has 0 latency. There isn't a good way to fix this, as input delay is now solely dependent on the real latency to the host's server. Having differing latency between players would be considered unfair for competitive play, but for casual play we don't really care. For this reason though, combined with the potential for a few inputs to be dropped on a bad connection, the old mode will remain and this new mode is entirely optional.
2018-08-24 08:17:18 +00:00
bool AddLocalWiimoteToBuffer(int local_wiimote, const WiimoteEmu::SerializedWiimoteState& state,
sf::Packet& packet);
void UpdateDevices();
void AddPadStateToPacket(int in_game_pad, const GCPadStatus& np, sf::Packet& packet);
void AddWiimoteStateToPacket(int in_game_pad, const WiimoteEmu::SerializedWiimoteState& np,
sf::Packet& packet);
void Send(const sf::Packet& packet, u8 channel_id = DEFAULT_CHANNEL);
2015-02-02 09:27:06 +00:00
void Disconnect();
bool Connect();
2021-07-04 11:33:58 +00:00
void SendGameStatus();
2022-07-28 01:43:16 +00:00
void ComputeGameDigest(const SyncIdentifier& sync_identifier);
void DisplayPlayersPing();
u32 GetPlayersMaxPing() const;
void OnData(sf::Packet& packet);
void OnPlayerJoin(sf::Packet& packet);
void OnPlayerLeave(sf::Packet& packet);
void OnChatMessage(sf::Packet& packet);
void OnChunkedDataStart(sf::Packet& packet);
void OnChunkedDataEnd(sf::Packet& packet);
void OnChunkedDataPayload(sf::Packet& packet);
void OnChunkedDataAbort(sf::Packet& packet);
void OnPadMapping(sf::Packet& packet);
void OnWiimoteMapping(sf::Packet& packet);
void OnGBAConfig(sf::Packet& packet);
void OnPadData(sf::Packet& packet);
void OnPadHostData(sf::Packet& packet);
void OnWiimoteData(sf::Packet& packet);
void OnPadBuffer(sf::Packet& packet);
void OnHostInputAuthority(sf::Packet& packet);
void OnGolfSwitch(sf::Packet& packet);
void OnGolfPrepare(sf::Packet& packet);
void OnChangeGame(sf::Packet& packet);
void OnGameStatus(sf::Packet& packet);
void OnStartGame(sf::Packet& packet);
void OnStopGame(sf::Packet& packet);
void OnPowerButton();
void OnPing(sf::Packet& packet);
void OnPlayerPingData(sf::Packet& packet);
void OnDesyncDetected(sf::Packet& packet);
void OnSyncSaveData(sf::Packet& packet);
void OnSyncSaveDataNotify(sf::Packet& packet);
void OnSyncSaveDataRaw(sf::Packet& packet);
void OnSyncSaveDataGCI(sf::Packet& packet);
void OnSyncSaveDataWii(sf::Packet& packet);
void OnSyncSaveDataGBA(sf::Packet& packet);
void OnSyncCodes(sf::Packet& packet);
void OnSyncCodesNotify();
void OnSyncCodesNotifyGecko(sf::Packet& packet);
void OnSyncCodesDataGecko(sf::Packet& packet);
void OnSyncCodesNotifyAR(sf::Packet& packet);
void OnSyncCodesDataAR(sf::Packet& packet);
2022-07-28 01:43:16 +00:00
void OnComputeGameDigest(sf::Packet& packet);
void OnGameDigestProgress(sf::Packet& packet);
void OnGameDigestResult(sf::Packet& packet);
void OnGameDigestError(sf::Packet& packet);
void OnGameDigestAbort();
bool m_is_connected = false;
ConnectionState m_connection_state = ConnectionState::Failure;
PlayerId m_pid = 0;
NetSettings m_net_settings{};
std::map<PlayerId, Player> m_players;
2015-02-02 09:27:06 +00:00
std::string m_host_spec;
std::string m_player_name;
bool m_connecting = false;
Common::TraversalClient* m_traversal_client = nullptr;
2022-07-28 01:43:16 +00:00
std::thread m_game_digest_thread;
bool m_should_compute_game_digest = false;
Common::Event m_gc_pad_event;
Common::Event m_wii_pad_event;
NetPlay host input authority mode Currently, each player buffers their own inputs and sends them to the host. The host then relays those inputs to everyone else. Every player waits on inputs from all players to be buffered before continuing. What this means is all clients run in lockstep, and the total latency of inputs cannot be lower than the sum of the 2 highest client ping times in the game (in 3+ player sessions with people across the world, the latency can be very high). Host input authority mode changes it so players no longer buffer their own inputs, and only send them to the host. The host stores only the most recent input received from a player. The host then sends inputs for all pads at the SI poll interval, similar to the existing code. If a player sends inputs to slowly, their last received input is simply sent again. If they send too quickly, inputs are dropped. This means that the host has full control over what inputs are actually read by the game, hence the name of the mode. Also, because the rate at which inputs are received by SI is decoupled from the rate at which players are sending inputs, clients are no longer dependent on each other. They only care what the host is doing. This means that they can set their buffer individually based on their latency to the host, rather than the highest latency between any 2 players, allowing someone with lower ping to the host to have less latency than someone else. This is a catch to this: as a necessity of how the host's input sending works, the host has 0 latency. There isn't a good way to fix this, as input delay is now solely dependent on the real latency to the host's server. Having differing latency between players would be considered unfair for competitive play, but for casual play we don't really care. For this reason though, combined with the potential for a few inputs to be dropped on a bad connection, the old mode will remain and this new mode is entirely optional.
2018-08-24 08:17:18 +00:00
Common::Event m_first_pad_status_received_event;
Common::Event m_wait_on_input_event;
u8 m_sync_save_data_count = 0;
u8 m_sync_save_data_success_count = 0;
u16 m_sync_gecko_codes_count = 0;
u16 m_sync_gecko_codes_success_count = 0;
bool m_sync_gecko_codes_complete = false;
u16 m_sync_ar_codes_count = 0;
u16 m_sync_ar_codes_success_count = 0;
bool m_sync_ar_codes_complete = false;
std::unordered_map<u32, sf::Packet> m_chunked_data_receive_queue;
u64 m_initial_rtc = 0;
u32 m_timebase_frame = 0;
std::unique_ptr<IOS::HLE::FS::FileSystem> m_wii_sync_fs;
std::vector<u64> m_wii_sync_titles;
std::string m_wii_sync_redirect_folder;
};
void NetPlay_Enable(NetPlayClient* const np);
void NetPlay_Disable();
bool NetPlay_GetWiimoteData(const std::span<NetPlayClient::WiimoteDataBatchEntry>& entries);
unsigned int NetPlay_GetLocalWiimoteForSlot(unsigned int slot);
} // namespace NetPlay