diff --git a/dep/ggpo-x/src/backends/p2p.cpp b/dep/ggpo-x/src/backends/p2p.cpp index 9131b13b1..8a7d178aa 100644 --- a/dep/ggpo-x/src/backends/p2p.cpp +++ b/dep/ggpo-x/src/backends/p2p.cpp @@ -60,12 +60,9 @@ GGPOErrorCode Peer2PeerBackend::AddSpectator(ENetPeer* peer) if (_num_spectators == GGPO_MAX_SPECTATORS) { return GGPO_ERRORCODE_TOO_MANY_SPECTATORS; } - /* - * Currently, we can only add spectators before the game starts. - */ - if (!_synchronizing) { - return GGPO_ERRORCODE_INVALID_REQUEST; - } + + _synchronizing = true; + int queue = _num_spectators++; _spectators[queue].Init(peer, queue + 1000, _local_connect_status); @@ -164,7 +161,7 @@ Peer2PeerBackend::DoPoll() input.size = _input_size * _num_players; _sync.GetConfirmedInputs(input.bits, _input_size * _num_players, _next_spectator_frame); for (int i = 0; i < _num_spectators; i++) { - _spectators[i].SendInput(input); + _spectators[i].SendInput(input); } _next_spectator_frame++; } @@ -721,6 +718,7 @@ Peer2PeerBackend::CheckInitialSync() return; } } + for (i = 0; i < _num_spectators; i++) { if (_spectators[i].IsInitialized() && !_spectators[i].IsSynchronized()) { return; diff --git a/dep/ggpo-x/src/backends/spectator.cpp b/dep/ggpo-x/src/backends/spectator.cpp index d93cc1bfe..bf0f81b39 100644 --- a/dep/ggpo-x/src/backends/spectator.cpp +++ b/dep/ggpo-x/src/backends/spectator.cpp @@ -17,13 +17,6 @@ SpectatorBackend::SpectatorBackend(GGPOSessionCallbacks* cb, int num_players, in _inputs[i].frame = -1; } - /* - * Initialize the UDP port - */ - // FIXME - //abort(); - //_udp.Init(localport, &_poll, this); - /* * Init the host endpoint */ diff --git a/dep/ggpo-x/src/network/udp_proto.cpp b/dep/ggpo-x/src/network/udp_proto.cpp index 5b8d4543c..f45138e9d 100644 --- a/dep/ggpo-x/src/network/udp_proto.cpp +++ b/dep/ggpo-x/src/network/udp_proto.cpp @@ -63,7 +63,7 @@ int UdpProtocol::RemoteFrameDelay()const void UdpProtocol::Init(ENetPeer* peer, int queue, UdpMsg::connect_status *status) { - _peer = peer; + _peer = peer; _queue = queue; _local_connect_status = status; @@ -75,6 +75,12 @@ void UdpProtocol::Init(ENetPeer* peer, int queue, UdpMsg::connect_status *status void UdpProtocol::SendInput(GameInput &input) { + // when spectating and you hit the end of the buffer its time to acknowledge that the peer is dead. + if (_queue >= 1000 && _pending_output.size() >= 63) { + Disconnect(); + return; + } + if (_peer) { if (_current_state == Running) { /* diff --git a/src/core/netplay.cpp b/src/core/netplay.cpp index 10c554b25..24c364bd4 100644 --- a/src/core/netplay.cpp +++ b/src/core/netplay.cpp @@ -169,6 +169,7 @@ static Common::Timer s_last_host_connection_attempt; static std::array s_spectators; static std::bitset s_reset_spectators; static s32 s_num_spectators = 0; +static s32 s_spectating_failed_count = 0; static bool s_local_spectating; /// GGPO @@ -848,6 +849,7 @@ void Netplay::DestroyGGPOSession() s_ggpo = nullptr; s_save_buffer_pool.clear(); s_local_handle = GGPO_INVALID_HANDLE; + s_spectating_failed_count = 0; for (Peer& p : s_peers) p.ggpo_handle = GGPO_INVALID_HANDLE; @@ -1072,10 +1074,6 @@ void Netplay::DropSpectator(s32 slot_id, DropPlayerReason reason) enet_peer_disconnect_now(s_spectators[slot_id].peer, 0); s_spectators[slot_id] = {}; s_num_spectators--; - // sadly we have to reset here. this really sucks for the active players since you dont really want to halt for a spectator. - // not resetting seems to be creating index out of bounds errors in the ringbuffer. - // TODO ? - Reset(); } void Netplay::UpdateConnectingState() @@ -1771,7 +1769,7 @@ void Netplay::SetSettings(const ConnectResponseMessage* msg) si.SetBoolValue("GPU", "UseSoftwareRendererForReadbacks", true); // No cheats.. yet. Need to serialize them, and that has security risks. - si.SetBoolValue("Main", "AutoLoadCheats", false); + // si.SetBoolValue("Main", "AutoLoadCheats", false); // No PCDRV or texture replacements, they require local files. si.SetBoolValue("PCDrv", "Enabled", false); @@ -1973,6 +1971,14 @@ void Netplay::RunFrame() if (GGPO_SUCCEEDED(result)) { result = SyncInput(inputs, &disconnect_flags); + if (s_local_spectating && result != GGPO_OK) + { + s_spectating_failed_count++; + // after 5 seconds and still not spectating close since you are stuck. + if (s_spectating_failed_count >= 300) + CloseSessionWithError("Failed to sync spectator. Please try again."); + } + if (GGPO_SUCCEEDED(result)) { // enable again when rolling back done