Permalink
Browse files

NetPlay: Bundle multiple local pads into one packet

This saves a significant amount of bandwidth with multiple controllers on one client, as most of the packet is just protocol overhead.
  • Loading branch information...
Techjar committed Jul 9, 2018
1 parent 31d9ca3 commit f68dbed5351c33ec975445eb832e75b5e68a6fb2
Showing with 47 additions and 31 deletions.
  1. +25 −15 Source/Core/Core/NetPlayClient.cpp
  2. +1 −1 Source/Core/Core/NetPlayClient.h
  3. +21 −15 Source/Core/Core/NetPlayServer.cpp
@@ -334,15 +334,20 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
case NP_MSG_PAD_DATA:
{
PadMapping map = 0;
GCPadStatus pad;
packet >> map >> pad.button >> pad.analogA >> pad.analogB >> pad.stickX >> pad.stickY >>
pad.substickX >> pad.substickY >> pad.triggerLeft >> pad.triggerRight >> pad.isConnected;
while (!packet.endOfPacket())
{
PadMapping map;
packet >> map;
// Trusting server for good map value (>=0 && <4)
// add to pad buffer
m_pad_buffer.at(map).Push(pad);
m_gc_pad_event.Set();
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)
// add to pad buffer
m_pad_buffer.at(map).Push(pad);
m_gc_pad_event.Set();
}
}
break;
@@ -778,15 +783,12 @@ void NetPlayClient::SendChatMessage(const std::string& msg)
}
// called from ---CPU--- thread
void NetPlayClient::SendPadState(const int in_game_pad, const GCPadStatus& pad)
void NetPlayClient::AddPadStateToPacket(const int in_game_pad, const GCPadStatus& pad,
sf::Packet& packet)
{
sf::Packet packet;
packet << static_cast<MessageId>(NP_MSG_PAD_DATA);
packet << static_cast<PadMapping>(in_game_pad);
packet << pad.button << pad.analogA << pad.analogB << pad.stickX << pad.stickY << pad.substickX
<< pad.substickY << pad.triggerLeft << pad.triggerRight << pad.isConnected;
SendAsync(std::move(packet));
}
// called from ---CPU--- thread
@@ -1000,6 +1002,10 @@ bool NetPlayClient::GetNetPads(const int pad_nb, GCPadStatus* pad_status)
// clients.
if (IsFirstInGamePad(pad_nb))
{
sf::Packet packet;
packet << static_cast<MessageId>(NP_MSG_PAD_DATA);
bool send_packet = false;
const int num_local_pads = NumLocalPads();
for (int local_pad = 0; local_pad < num_local_pads; local_pad++)
{
@@ -1023,10 +1029,14 @@ bool NetPlayClient::GetNetPads(const int pad_nb, GCPadStatus* pad_status)
// add to buffer
m_pad_buffer[ingame_pad].Push(*pad_status);
// send
SendPadState(ingame_pad, *pad_status);
// add to packet
AddPadStateToPacket(ingame_pad, *pad_status, packet);
send_packet = true;
}
}
if (send_packet)
SendAsync(std::move(packet));
}
// Now, we either use the data pushed earlier, or wait for the
@@ -159,7 +159,7 @@ class NetPlayClient : public TraversalClientClient
void SendStopGamePacket();
void UpdateDevices();
void SendPadState(int in_game_pad, const GCPadStatus& np);
void AddPadStateToPacket(int in_game_pad, const GCPadStatus& np, sf::Packet& packet);
void SendWiimoteState(int in_game_pad, const NetWiimote& nw);
unsigned int OnData(sf::Packet& packet);
void Send(const sf::Packet& packet);
@@ -526,24 +526,30 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
if (player.current_game != m_current_game)
break;
PadMapping map = 0;
GCPadStatus pad;
packet >> map >> pad.button >> pad.analogA >> pad.analogB >> pad.stickX >> pad.stickY >>
pad.substickX >> pad.substickY >> pad.triggerLeft >> pad.triggerRight >> pad.isConnected;
sf::Packet spac;
spac << static_cast<MessageId>(NP_MSG_PAD_DATA);
// If the data is not from the correct player,
// then disconnect them.
if (m_pad_map.at(map) != player.pid)
while (!packet.endOfPacket())
{
return 1;
}
PadMapping map;
packet >> map;
// Relay to clients
sf::Packet spac;
spac << (MessageId)NP_MSG_PAD_DATA;
spac << map << pad.button << pad.analogA << pad.analogB << pad.stickX << pad.stickY
<< pad.substickX << pad.substickY << pad.triggerLeft << pad.triggerRight
<< pad.isConnected;
// If the data is not from the correct player,
// then disconnect them.
if (m_pad_map.at(map) != player.pid)
{
return 1;
}
GCPadStatus pad;
packet >> pad.button >> pad.analogA >> pad.analogB >> pad.stickX >> pad.stickY >>
pad.substickX >> pad.substickY >> pad.triggerLeft >> pad.triggerRight >> pad.isConnected;
// Add to packet for relay to clients
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);
}

0 comments on commit f68dbed

Please sign in to comment.