145 changes: 26 additions & 119 deletions Source/Core/Core/Src/NetPlayServer.cpp
Expand Up @@ -4,11 +4,6 @@

#include "NetPlayServer.h"

NetPlayServer::Client::Client()
{
memset(pad_map, -1, sizeof(pad_map));
}

NetPlayServer::~NetPlayServer()
{
if (is_connected)
Expand All @@ -29,6 +24,7 @@ NetPlayServer::~NetPlayServer()
// called from ---GUI--- thread
NetPlayServer::NetPlayServer(const u16 port) : is_connected(false), m_is_running(false)
{
memset(m_pad_map, -1, sizeof(m_pad_map));
if (m_socket.Listen(port))
{
is_connected = true;
Expand Down Expand Up @@ -155,45 +151,16 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket)
rpac >> player.name;

// give new client first available id
player.pid = 0;
std::map<sf::SocketTCP, Client>::const_iterator
i,
e = m_players.end();
for (PlayerId p = 1; 0 == player.pid; ++p)
{
for (i = m_players.begin(); ; ++i)
{
if (e == i)
{
player.pid = p;
break;
}
if (p == i->second.pid)
break;
}
}
player.pid = m_players.size() + 1;

// TODO: this is crappy
// try to automatically assign new user a pad
for (unsigned int m = 0; m < 4; ++m)
{
bool is_mapped[4] = {false,false,false,false};

for ( unsigned int m = 0; m<4; ++m)
{
for (i = m_players.begin(); i!=e; ++i)
if (m_pad_map[m] == -1)
{
if (i->second.pad_map[m] >= 0)
is_mapped[(unsigned)i->second.pad_map[m]] = true;
}
}

for ( unsigned int m = 0; m<4; ++m)
if (false == is_mapped[m])
{
player.pad_map[0] = m;
m_pad_map[m] = player.pid;
break;
}

}

{
Expand Down Expand Up @@ -221,6 +188,9 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket)
}

// sync values with new client
std::map<sf::SocketTCP, Client>::const_iterator
i,
e = m_players.end();
for (i = m_players.begin(); i!=e; ++i)
{
spac.Clear();
Expand Down Expand Up @@ -279,83 +249,28 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket)
}

// called from ---GUI--- thread
bool NetPlayServer::GetPadMapping(const int pid, int map[])
void NetPlayServer::GetPadMapping(PadMapping map[4])
{
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::map<sf::SocketTCP, Client>::const_iterator
i = m_players.begin(),
e = m_players.end();
for (; i!=e; ++i)
if (pid == i->second.pid)
break;

// player not found
if (i == e)
return false;

// get pad mapping
for (unsigned int m = 0; m<4; ++m)
map[m] = i->second.pad_map[m];

return true;
for (int i = 0; i < 4; i++)
map[i] = m_pad_map[i];
}

// called from ---GUI--- thread
bool NetPlayServer::SetPadMapping(const int pid, const int map[])
void NetPlayServer::SetPadMapping(const PadMapping map[4])
{
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
if (m_is_running)
return false;

std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::map<sf::SocketTCP, Client>::iterator
i = m_players.begin(),
e = m_players.end();
for (; i!=e; ++i)
if (pid == i->second.pid)
break;

// player not found
if (i == e)
return false;

Client& player = i->second;

// set pad mapping
for (unsigned int m = 0; m<4; ++m)
{
player.pad_map[m] = (PadMapping)map[m];

// remove duplicate mappings
for (i = m_players.begin(); i!=e; ++i)
for (unsigned int p = 0; p<4; ++p)
if (p != m || i->second.pid != pid)
if (player.pad_map[m] == i->second.pad_map[p])
i->second.pad_map[p] = -1;
}

std::lock_guard<std::recursive_mutex> lks(m_crit.send);
UpdatePadMapping(); // sync pad mappings with everyone

return true;
for (int i = 0; i < 4; i++)
m_pad_map[i] = map[i];
UpdatePadMapping();
}

// called from ---NETPLAY--- thread
// called from ---GUI--- thread and ---NETPLAY--- thread
void NetPlayServer::UpdatePadMapping()
{
std::map<sf::SocketTCP, Client>::const_iterator
i = m_players.begin(),
e = m_players.end();
for (; i!=e; ++i)
{
sf::Packet spac;
spac << (MessageId)NP_MSG_PAD_MAPPING;
spac << i->second.pid;
for (unsigned int pm = 0; pm<4; ++pm)
spac << i->second.pad_map[pm];
SendToClients(spac);
}

sf::Packet spac;
spac << (MessageId)NP_MSG_PAD_MAPPING;
for (int i = 0; i < 4; i++)
spac << m_pad_map[i];
SendToClients(spac);
}

// called from ---GUI--- thread and ---NETPLAY--- thread
Expand Down Expand Up @@ -415,23 +330,15 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
int hi, lo;
packet >> map >> hi >> lo;

// check if client's pad indeed maps in game
if (map >= 0 && map < 4)
map = player.pad_map[(unsigned)map];
else
map = -1;

// if not, they are hacking, so disconnect them
// this could happen right after a pad map change, but that isn't implemented yet
if (map < 0)
// If the data is not from the correct player,
// then disconnect them.
if (m_pad_map[map] != player.pid)
return 1;


// relay to clients
// Relay to clients
sf::Packet spac;
spac << (MessageId)NP_MSG_PAD_DATA;
spac << map; // in game mapping
spac << hi << lo;
spac << map << hi << lo;

std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac, player.pid);
Expand Down
8 changes: 3 additions & 5 deletions Source/Core/Core/Src/NetPlayServer.h
Expand Up @@ -35,8 +35,8 @@ class NetPlayServer
bool StartGame(const std::string &path);
bool StopGame();

bool GetPadMapping(const int pid, int map[]);
bool SetPadMapping(const int pid, const int map[]);
void GetPadMapping(PadMapping map[]);
void SetPadMapping(const PadMapping map[]);

void AdjustPadBufferSize(unsigned int size);

Expand All @@ -50,11 +50,8 @@ class NetPlayServer
class Client
{
public:
Client();

PlayerId pid;
std::string name;
PadMapping pad_map[4];
std::string revision;

sf::SocketTCP socket;
Expand All @@ -77,6 +74,7 @@ class NetPlayServer
bool m_update_pings;
u32 m_current_game;
unsigned int m_target_buffer_size;
PadMapping m_pad_map[4];

std::map<sf::SocketTCP, Client> m_players;

Expand Down
76 changes: 33 additions & 43 deletions Source/Core/DolphinWX/Src/NetWindow.cpp
Expand Up @@ -559,23 +559,13 @@ void NetPlayDiag::OnChangeGame(wxCommandEvent&)

void NetPlayDiag::OnConfigPads(wxCommandEvent&)
{
int mapping[4];

// get selected player id
int pid = m_player_lbox->GetSelection();
if (pid < 0)
return;
pid = m_playerids.at(pid);

if (false == netplay_server->GetPadMapping(pid, mapping))
return;

PadMapDiag pmd(this, mapping);
PadMapping mapping[4];
std::vector<const Player *> player_list;
netplay_server->GetPadMapping(mapping);
netplay_client->GetPlayers(player_list);
PadMapDiag pmd(this, mapping, player_list);
pmd.ShowModal();

if (false == netplay_server->SetPadMapping(pid, mapping))
PanicAlertT("Could not set pads. The player left or the game is currently running!\n"
"(setting pads while the game is running is not yet supported)");
netplay_server->SetPadMapping(mapping);
}

ChangeGameDiag::ChangeGameDiag(wxWindow* const parent, const CGameListCtrl* const game_list, wxString& game_name)
Expand Down Expand Up @@ -605,45 +595,39 @@ void ChangeGameDiag::OnPick(wxCommandEvent& event)
EndModal(wxID_OK);
}

PadMapDiag::PadMapDiag(wxWindow* const parent, int map[])
PadMapDiag::PadMapDiag(wxWindow* const parent, PadMapping map[], std::vector<const Player *>& player_list)
: wxDialog(parent, wxID_ANY, _("Configure Pads"), wxDefaultPosition, wxDefaultSize)
, m_mapping(map)
, m_player_list(player_list)
{
wxBoxSizer* const h_szr = new wxBoxSizer(wxHORIZONTAL);

h_szr->AddSpacer(20);

// labels
wxBoxSizer* const label_szr = new wxBoxSizer(wxVERTICAL);
label_szr->Add(new wxStaticText(this, wxID_ANY, _("Local")), 0, wxALIGN_TOP);
label_szr->AddStretchSpacer(1);
label_szr->Add(new wxStaticText(this, wxID_ANY, _("In-Game")), 0, wxALIGN_BOTTOM);

h_szr->Add(label_szr, 1, wxTOP | wxEXPAND, 20);

// set up choices
wxString pad_names[5];
pad_names[0] = _("None");
for (unsigned int i=1; i<5; ++i)
pad_names[i] = wxString(_("Pad ")) + (wxChar)(wxT('0')+i);
wxArrayString player_names;
player_names.Add(_("None"));
for (unsigned int i = 0; i < m_player_list.size(); i++)
player_names.Add(m_player_list[i]->name);

for (unsigned int i=0; i<4; ++i)
{
wxChoice* const pad_cbox = m_map_cbox[i]
= new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 5, pad_names);
pad_cbox->Select(m_mapping[i] + 1);
wxBoxSizer* const v_szr = new wxBoxSizer(wxVERTICAL);
v_szr->Add(new wxStaticText(this, wxID_ANY, (wxString(_("Pad ")) + (wxChar)(wxT('0')+i))),
1, wxALIGN_CENTER_HORIZONTAL);

pad_cbox->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &PadMapDiag::OnAdjust, this);
m_map_cbox[i] = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, player_names);
m_map_cbox[i]->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &PadMapDiag::OnAdjust, this);
if (m_mapping[i] == -1)
m_map_cbox[i]->Select(0);
else
for (unsigned int j = 0; j < m_player_list.size(); j++)
if (m_mapping[i] == m_player_list[j]->pid)
m_map_cbox[i]->Select(j + 1);

wxBoxSizer* const v_szr = new wxBoxSizer(wxVERTICAL);
v_szr->Add(new wxStaticText(this,wxID_ANY, pad_names[i + 1]), 1, wxALIGN_CENTER_HORIZONTAL);
v_szr->Add(pad_cbox, 1);
v_szr->Add(m_map_cbox[i], 1);

h_szr->Add(v_szr, 1, wxTOP | wxEXPAND, 20);
h_szr->AddSpacer(10);
}

h_szr->AddSpacer(20);

wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL);
main_szr->Add(h_szr);
main_szr->AddSpacer(5);
Expand All @@ -656,8 +640,14 @@ PadMapDiag::PadMapDiag(wxWindow* const parent, int map[])
void PadMapDiag::OnAdjust(wxCommandEvent& event)
{
(void)event;
for (unsigned int i=0; i<4; ++i)
m_mapping[i] = m_map_cbox[i]->GetSelection() - 1;
for (unsigned int i = 0; i < 4; i++)
{
int player_idx = m_map_cbox[i]->GetSelection();
if (player_idx > 0)
m_mapping[i] = m_player_list[player_idx - 1]->pid;
else
m_mapping[i] = -1;
}
}

void NetPlay::StopGame()
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/DolphinWX/Src/NetWindow.h
Expand Up @@ -124,13 +124,14 @@ class ChangeGameDiag : public wxDialog
class PadMapDiag : public wxDialog
{
public:
PadMapDiag(wxWindow* const parent, int map[]);
PadMapDiag(wxWindow* const parent, PadMapping map[], std::vector<const Player *>& player_list);

private:
void OnAdjust(wxCommandEvent& event);

wxChoice* m_map_cbox[4];
int* const m_mapping;
PadMapping* const m_mapping;
std::vector<const Player *>& m_player_list;
};

namespace NetPlay
Expand Down