mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-08-26 12:16:20 +00:00
pull in project-slippi/Ishiiruka/commit/9ed8bbc1f3d113808150de97ffb0a78afcd1df4d and project-slippi/Ishiiruka/commit/e6b5286f08088ea029c1c1c8ca58d117bde26b93
This commit is contained in:
parent
18e8c40cdf
commit
cf793e5560
3 changed files with 93 additions and 35 deletions
|
@ -177,7 +177,6 @@ private:
|
||||||
void handleSendInputs(u8* payload);
|
void handleSendInputs(u8* payload);
|
||||||
void handleCaptureSavestate(u8* payload);
|
void handleCaptureSavestate(u8* payload);
|
||||||
void handleLoadSavestate(u8* payload);
|
void handleLoadSavestate(u8* payload);
|
||||||
void handleNameEntryAutoComplete(u8* payload);
|
|
||||||
void handleNameEntryLoad(u8* payload);
|
void handleNameEntryLoad(u8* payload);
|
||||||
void startFindMatch(u8* payload);
|
void startFindMatch(u8* payload);
|
||||||
void prepareOnlineMatchState();
|
void prepareOnlineMatchState();
|
||||||
|
|
|
@ -125,6 +125,12 @@ SlippiNetplayClient::SlippiNetplayClient(std::vector<std::string> addrs, std::ve
|
||||||
ENetPeer* peer = enet_host_connect(m_client, &addr, 3, 0);
|
ENetPeer* peer = enet_host_connect(m_client, &addr, 3, 0);
|
||||||
m_server.push_back(peer);
|
m_server.push_back(peer);
|
||||||
|
|
||||||
|
// Store this connection
|
||||||
|
std::stringstream keyStrm;
|
||||||
|
keyStrm << addr.host << "-" << addr.port;
|
||||||
|
activeConnections[keyStrm.str()][peer] = true;
|
||||||
|
INFO_LOG_FMT(SLIPPI_ONLINE, "New connection (constr): {}", keyStrm.str().c_str());
|
||||||
|
|
||||||
if (peer == nullptr)
|
if (peer == nullptr)
|
||||||
{
|
{
|
||||||
PanicAlertT("Couldn't create peer.");
|
PanicAlertT("Couldn't create peer.");
|
||||||
|
@ -466,15 +472,18 @@ void SlippiNetplayClient::Disconnect()
|
||||||
{
|
{
|
||||||
ENetEvent netEvent;
|
ENetEvent netEvent;
|
||||||
slippiConnectStatus = SlippiConnectStatus::NET_CONNECT_STATUS_DISCONNECTED;
|
slippiConnectStatus = SlippiConnectStatus::NET_CONNECT_STATUS_DISCONNECTED;
|
||||||
if (!m_server.empty())
|
if (activeConnections.empty())
|
||||||
for (int i = 0; i < m_server.size(); i++)
|
|
||||||
{
|
|
||||||
INFO_LOG_FMT(SLIPPI_ONLINE, "[Netplay] Disconnecting peer {}", m_server[i]->address.port);
|
|
||||||
enet_peer_disconnect(m_server[i], 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
for (auto conn : activeConnections)
|
||||||
|
{
|
||||||
|
for (auto peer : conn.second)
|
||||||
|
{
|
||||||
|
INFO_LOG_FMT(SLIPPI_ONLINE, "[Netplay] Disconnecting peer {}", peer.first->address.port);
|
||||||
|
enet_peer_disconnect(peer.first, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (enet_host_service(m_client, &netEvent, 3000) > 0)
|
while (enet_host_service(m_client, &netEvent, 3000) > 0)
|
||||||
{
|
{
|
||||||
switch (netEvent.type)
|
switch (netEvent.type)
|
||||||
|
@ -491,10 +500,14 @@ void SlippiNetplayClient::Disconnect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// didn't disconnect gracefully force disconnect
|
// didn't disconnect gracefully force disconnect
|
||||||
for (int i = 0; i < m_server.size(); i++)
|
for (auto conn : activeConnections)
|
||||||
{
|
{
|
||||||
enet_peer_reset(m_server[i]);
|
for (auto peer : conn.second)
|
||||||
|
{
|
||||||
|
enet_peer_reset(peer.first);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
activeConnections.clear();
|
||||||
m_server.clear();
|
m_server.clear();
|
||||||
SLIPPI_NETPLAY = nullptr;
|
SLIPPI_NETPLAY = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -539,8 +552,8 @@ void SlippiNetplayClient::ThreadFunc()
|
||||||
INFO_LOG(SLIPPI_ONLINE, "[Netplay] got receive event with nil peer");
|
INFO_LOG(SLIPPI_ONLINE, "[Netplay] got receive event with nil peer");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ERROR_LOG_FMT(SLIPPI_ONLINE, "[Netplay] got receive event with peer addr {}:{}",
|
INFO_LOG_FMT(SLIPPI_ONLINE, "[Netplay] got receive event with peer addr {}:{}",
|
||||||
netEvent.peer->address.host, netEvent.peer->address.port);
|
netEvent.peer->address.host, netEvent.peer->address.port);
|
||||||
rpac.append(netEvent.packet->data, netEvent.packet->dataLength);
|
rpac.append(netEvent.packet->data, netEvent.packet->dataLength);
|
||||||
|
|
||||||
OnData(rpac, netEvent.peer);
|
OnData(rpac, netEvent.peer);
|
||||||
|
@ -566,6 +579,11 @@ void SlippiNetplayClient::ThreadFunc()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::stringstream keyStrm;
|
||||||
|
keyStrm << netEvent.peer->address.host << "-" << netEvent.peer->address.port;
|
||||||
|
activeConnections[keyStrm.str()][netEvent.peer] = true;
|
||||||
|
INFO_LOG_FMT(SLIPPI_ONLINE, "New connection (early): {}", keyStrm.str().c_str());
|
||||||
|
|
||||||
INFO_LOG_FMT(SLIPPI_ONLINE, "[Netplay] got connect event with peer addr {}:{}",
|
INFO_LOG_FMT(SLIPPI_ONLINE, "[Netplay] got connect event with peer addr {}:{}",
|
||||||
netEvent.peer->address.host, netEvent.peer->address.port);
|
netEvent.peer->address.host, netEvent.peer->address.port);
|
||||||
|
|
||||||
|
@ -586,7 +604,7 @@ void SlippiNetplayClient::ThreadFunc()
|
||||||
// Don't add this person again if they are already connected. Not doing this can cause one
|
// Don't add this person again if they are already connected. Not doing this can cause one
|
||||||
// person to take up 2 or more spots, denying one or more players from connecting and thus
|
// person to take up 2 or more spots, denying one or more players from connecting and thus
|
||||||
// getting stuck on the "Waiting" step
|
// getting stuck on the "Waiting" step
|
||||||
ERROR_LOG(SLIPPI_ONLINE, "Already connected!");
|
INFO_LOG(SLIPPI_ONLINE, "Already connected!");
|
||||||
break; // Breaks out of case
|
break; // Breaks out of case
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,7 +657,7 @@ void SlippiNetplayClient::ThreadFunc()
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(SLIPPI_ONLINE, "m_client peer {} state: {}", i, m_client->peers[i].state);
|
INFO_LOG_FMT(SLIPPI_ONLINE, "m_client peer {} state: {}", i, m_client->peers[i].state);
|
||||||
}
|
}
|
||||||
WARN_LOG_FMT(SLIPPI_ONLINE, "[Netplay] Not yet connected. Res: {}, Type: {}", net,
|
INFO_LOG_FMT(SLIPPI_ONLINE, "[Netplay] Not yet connected. Res: {}, Type: {}", net,
|
||||||
netEvent.type);
|
netEvent.type);
|
||||||
|
|
||||||
// Time out after enough time has passed
|
// Time out after enough time has passed
|
||||||
|
@ -728,35 +746,74 @@ void SlippiNetplayClient::ThreadFunc()
|
||||||
if (net > 0)
|
if (net > 0)
|
||||||
{
|
{
|
||||||
sf::Packet rpac;
|
sf::Packet rpac;
|
||||||
bool isConnectedClient = false;
|
|
||||||
switch (netEvent.type)
|
switch (netEvent.type)
|
||||||
{
|
{
|
||||||
case ENET_EVENT_TYPE_RECEIVE:
|
case ENET_EVENT_TYPE_RECEIVE:
|
||||||
rpac.append(netEvent.packet->data, netEvent.packet->dataLength);
|
{
|
||||||
OnData(rpac, netEvent.peer);
|
int oppIdx = 0;
|
||||||
|
for (int i = 0; i < m_server.size(); i++)
|
||||||
enet_packet_destroy(netEvent.packet);
|
|
||||||
break;
|
|
||||||
case ENET_EVENT_TYPE_DISCONNECT:
|
|
||||||
for (int i = 0; i < m_remotePlayerCount; i++)
|
|
||||||
{
|
{
|
||||||
if (remoteAddrs[i].host == netEvent.peer->address.host &&
|
if (netEvent.peer->address.host == m_server[i]->address.host &&
|
||||||
remoteAddrs[i].port == netEvent.peer->address.port)
|
netEvent.peer->address.port == m_server[i]->address.port)
|
||||||
{
|
{
|
||||||
isConnectedClient = true;
|
oppIdx = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ERROR_LOG_FMT(SLIPPI_ONLINE, "[Netplay] Disconnected Event detected: {}",
|
|
||||||
isConnectedClient ? "connected client" : "superfluous client");
|
// Here we check if we have more than 1 connection for a specific player, this can happen
|
||||||
|
// because both players try to connect to each other at the same time to increase the odds
|
||||||
|
// that one direction might work and for hole punching. That said there's no point in
|
||||||
|
// keeping more than 1 connection alive. I think they might use bandwidth with keep alives
|
||||||
|
// or something. Only the lower port player will initiate the disconnect
|
||||||
|
std::stringstream keyStrm;
|
||||||
|
keyStrm << netEvent.peer->address.host << "-" << netEvent.peer->address.port;
|
||||||
|
if (activeConnections[keyStrm.str()].size() > 1 && m_player_idx <= oppIdx)
|
||||||
|
{
|
||||||
|
m_server[oppIdx] = netEvent.peer;
|
||||||
|
INFO_LOG(SLIPPI_ONLINE, "Multiple connections detected for single peer. Initiating "
|
||||||
|
"process to disconnect superfluous connections.");
|
||||||
|
for (auto peer : activeConnections[keyStrm.str()])
|
||||||
|
{
|
||||||
|
if (peer.first == netEvent.peer)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
enet_peer_disconnect(peer.first, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rpac.append(netEvent.packet->data, netEvent.packet->dataLength);
|
||||||
|
OnData(rpac, netEvent.peer);
|
||||||
|
enet_packet_destroy(netEvent.packet);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ENET_EVENT_TYPE_DISCONNECT:
|
||||||
|
{
|
||||||
|
std::stringstream keyStrm;
|
||||||
|
keyStrm << netEvent.peer->address.host << "-" << netEvent.peer->address.port;
|
||||||
|
activeConnections[keyStrm.str()].erase(netEvent.peer);
|
||||||
|
|
||||||
|
/*INFO_LOG_FMT(SLIPPI_ONLINE, "[Netplay] Disconnect late {}:{}. {}. Remaining connections:
|
||||||
|
{}", netEvent.peer->address.host, netEvent.peer->address.port, netEvent.peer,
|
||||||
|
activeConnections[keyStrm.str()].size());*/
|
||||||
|
|
||||||
// If the disconnect event doesn't come from the client we are actually listening to,
|
// If the disconnect event doesn't come from the client we are actually listening to,
|
||||||
// it can be safely ignored
|
// it can be safely ignored
|
||||||
if (isConnectedClient)
|
if (activeConnections[keyStrm.str()].empty())
|
||||||
{
|
{
|
||||||
|
INFO_LOG(SLIPPI_ONLINE, "[Netplay] Final disconnect received for a client.");
|
||||||
m_do_loop.Clear(); // Stop the loop, will trigger a disconnect
|
m_do_loop.Clear(); // Stop the loop, will trigger a disconnect
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
case ENET_EVENT_TYPE_CONNECT:
|
||||||
|
{
|
||||||
|
std::stringstream keyStrm;
|
||||||
|
keyStrm << netEvent.peer->address.host << "-" << netEvent.peer->address.port;
|
||||||
|
activeConnections[keyStrm.str()][netEvent.peer] = true;
|
||||||
|
INFO_LOG_FMT(SLIPPI_ONLINE, "New connection (late): {}", keyStrm.str().c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -857,14 +914,14 @@ void SlippiNetplayClient::SendSlippiPad(std::unique_ptr<SlippiPad> pad)
|
||||||
if (lastFrameAcked[i] < minAckFrame)
|
if (lastFrameAcked[i] < minAckFrame)
|
||||||
minAckFrame = lastFrameAcked[i];
|
minAckFrame = lastFrameAcked[i];
|
||||||
}
|
}
|
||||||
INFO_LOG_FMT(SLIPPI_ONLINE,
|
/*INFO_LOG_FMT(SLIPPI_ONLINE,
|
||||||
"Checking to drop local inputs, oldest frame: {} | minAckFrame: {} | {}, {}, {}",
|
"Checking to drop local inputs, oldest frame: {} | minAckFrame: {} | {}, {}, {}",
|
||||||
localPadQueue.back()->frame, minAckFrame, lastFrameAcked[0], lastFrameAcked[1],
|
localPadQueue.back()->frame, minAckFrame, lastFrameAcked[0], lastFrameAcked[1],
|
||||||
lastFrameAcked[2]);
|
lastFrameAcked[2]);*/
|
||||||
while (!localPadQueue.empty() && localPadQueue.back()->frame < minAckFrame)
|
while (!localPadQueue.empty() && localPadQueue.back()->frame < minAckFrame)
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(SLIPPI_ONLINE, "Dropping local input for frame {} from queue",
|
/*INFO_LOG_FMT(SLIPPI_ONLINE, "Dropping local input for frame {} from queue",
|
||||||
localPadQueue.back()->frame);
|
localPadQueue.back()->frame);*/
|
||||||
localPadQueue.pop_back();
|
localPadQueue.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -997,12 +1054,12 @@ void SlippiNetplayClient::DropOldRemoteInputs(int32_t curFrame)
|
||||||
|
|
||||||
for (int i = 0; i < m_remotePlayerCount; i++)
|
for (int i = 0; i < m_remotePlayerCount; i++)
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(SLIPPI_ONLINE, "remotePadQueue[{}] size: {}", i, remotePadQueue[i].size());
|
// INFO_LOG_FMT(SLIPPI_ONLINE, "remotePadQueue[{}] size: {}", i, remotePadQueue[i].size());
|
||||||
while (remotePadQueue[i].size() > 1 && remotePadQueue[i].back()->frame < lowestCommonFrame &&
|
while (remotePadQueue[i].size() > 1 && remotePadQueue[i].back()->frame < lowestCommonFrame &&
|
||||||
remotePadQueue[i].back()->frame < curFrame)
|
remotePadQueue[i].back()->frame < curFrame)
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(SLIPPI_ONLINE, "Popping inputs for frame {} from back of player {} queue",
|
/*INFO_LOG_FMT(SLIPPI_ONLINE, "Popping inputs for frame {} from back of player {} queue",
|
||||||
remotePadQueue[i].back()->frame, i);
|
remotePadQueue[i].back()->frame, i);*/
|
||||||
remotePadQueue[i].pop_back();
|
remotePadQueue[i].pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,6 +194,8 @@ protected:
|
||||||
bool hasGameStarted = false;
|
bool hasGameStarted = false;
|
||||||
u8 m_player_idx = 0;
|
u8 m_player_idx = 0;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::map<ENetPeer*, bool>> activeConnections;
|
||||||
|
|
||||||
std::deque<std::unique_ptr<SlippiPad>> localPadQueue; // most recent inputs at start of deque
|
std::deque<std::unique_ptr<SlippiPad>> localPadQueue; // most recent inputs at start of deque
|
||||||
std::deque<std::unique_ptr<SlippiPad>>
|
std::deque<std::unique_ptr<SlippiPad>>
|
||||||
remotePadQueue[SLIPPI_REMOTE_PLAYER_MAX]; // most recent inputs at start of deque
|
remotePadQueue[SLIPPI_REMOTE_PLAYER_MAX]; // most recent inputs at start of deque
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue