mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-24 14:49:53 -06:00
basic host/client connect infrastructure, player list
This commit is contained in:
@ -23,13 +23,146 @@
|
|||||||
|
|
||||||
#include <enet/enet.h>
|
#include <enet/enet.h>
|
||||||
|
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
|
||||||
#include "NDS.h"
|
#include "NDS.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "Netplay.h"
|
#include "Netplay.h"
|
||||||
#include "Input.h"
|
#include "Input.h"
|
||||||
|
|
||||||
|
#include "ui_NetplayStartHostDialog.h"
|
||||||
|
#include "ui_NetplayStartClientDialog.h"
|
||||||
|
#include "ui_NetplayDialog.h"
|
||||||
|
|
||||||
|
|
||||||
extern EmuThread* emuThread;
|
extern EmuThread* emuThread;
|
||||||
|
NetplayDialog* netplayDlg;
|
||||||
|
|
||||||
|
|
||||||
|
NetplayStartHostDialog::NetplayStartHostDialog(QWidget* parent) : QDialog(parent), ui(new Ui::NetplayStartHostDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
|
ui->txtPort->setText("8064");
|
||||||
|
}
|
||||||
|
|
||||||
|
NetplayStartHostDialog::~NetplayStartHostDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetplayStartHostDialog::done(int r)
|
||||||
|
{
|
||||||
|
if (r == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
std::string player = ui->txtPlayerName->text().toStdString();
|
||||||
|
int port = ui->txtPort->text().toInt();
|
||||||
|
|
||||||
|
// TODO validate input!!
|
||||||
|
|
||||||
|
netplayDlg = NetplayDialog::openDlg(parentWidget());
|
||||||
|
|
||||||
|
Netplay::StartHost(player.c_str(), port);
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialog::done(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NetplayStartClientDialog::NetplayStartClientDialog(QWidget* parent) : QDialog(parent), ui(new Ui::NetplayStartClientDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
|
ui->txtPort->setText("8064");
|
||||||
|
}
|
||||||
|
|
||||||
|
NetplayStartClientDialog::~NetplayStartClientDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetplayStartClientDialog::done(int r)
|
||||||
|
{
|
||||||
|
if (r == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
std::string player = ui->txtPlayerName->text().toStdString();
|
||||||
|
std::string host = ui->txtIPAddress->text().toStdString();
|
||||||
|
int port = ui->txtPort->text().toInt();
|
||||||
|
|
||||||
|
// TODO validate input!!
|
||||||
|
|
||||||
|
netplayDlg = NetplayDialog::openDlg(parentWidget());
|
||||||
|
|
||||||
|
Netplay::StartClient(player.c_str(), host.c_str(), port);
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialog::done(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NetplayDialog::NetplayDialog(QWidget* parent) : QDialog(parent), ui(new Ui::NetplayDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
|
QStandardItemModel* model = new QStandardItemModel();
|
||||||
|
ui->tvPlayerList->setModel(model);
|
||||||
|
|
||||||
|
connect(this, &sgUpdatePlayerList, this, &doUpdatePlayerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetplayDialog::~NetplayDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetplayDialog::done(int r)
|
||||||
|
{
|
||||||
|
// ???
|
||||||
|
|
||||||
|
QDialog::done(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetplayDialog::updatePlayerList(Netplay::Player* players, int num)
|
||||||
|
{
|
||||||
|
emit sgUpdatePlayerList(players, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetplayDialog::doUpdatePlayerList(Netplay::Player* players, int num)
|
||||||
|
{
|
||||||
|
QStandardItemModel* model = (QStandardItemModel*)ui->tvPlayerList->model();
|
||||||
|
|
||||||
|
model->clear();
|
||||||
|
model->setRowCount(num);
|
||||||
|
|
||||||
|
const QStringList header = {"#", "Player", "Status", "Ping"};
|
||||||
|
model->setHorizontalHeaderLabels(header);
|
||||||
|
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
Netplay::Player* player = &players[i];
|
||||||
|
|
||||||
|
QString id = QString("%0").arg(player->ID+1);
|
||||||
|
model->setItem(i, 0, new QStandardItem(id));
|
||||||
|
|
||||||
|
QString name = player->Name;
|
||||||
|
model->setItem(i, 1, new QStandardItem(name));
|
||||||
|
|
||||||
|
QString status;
|
||||||
|
switch (player->Status)
|
||||||
|
{
|
||||||
|
case 1: status = ""; break;
|
||||||
|
case 2: status = "Host"; break;
|
||||||
|
default: status = "ded"; break;
|
||||||
|
}
|
||||||
|
model->setItem(i, 2, new QStandardItem(status));
|
||||||
|
|
||||||
|
// TODO: ping
|
||||||
|
model->setItem(i, 3, new QStandardItem("x"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace Netplay
|
namespace Netplay
|
||||||
@ -39,7 +172,11 @@ bool Active;
|
|||||||
bool IsHost;
|
bool IsHost;
|
||||||
|
|
||||||
ENetHost* Host;
|
ENetHost* Host;
|
||||||
ENetPeer* Peer;
|
|
||||||
|
Player Players[16];
|
||||||
|
int NumPlayers;
|
||||||
|
|
||||||
|
Player TempPlayer; // holds client player info temporarily
|
||||||
|
|
||||||
struct InputFrame
|
struct InputFrame
|
||||||
{
|
{
|
||||||
@ -50,12 +187,18 @@ struct InputFrame
|
|||||||
std::queue<InputFrame> InputQueue;
|
std::queue<InputFrame> InputQueue;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
bool Init()
|
bool Init()
|
||||||
{
|
{
|
||||||
Active = false;
|
Active = false;
|
||||||
IsHost = false;
|
IsHost = false;
|
||||||
Host = nullptr;
|
Host = nullptr;
|
||||||
|
|
||||||
|
memset(Players, 0, sizeof(Players));
|
||||||
|
NumPlayers = 0;
|
||||||
|
|
||||||
if (enet_initialize() != 0)
|
if (enet_initialize() != 0)
|
||||||
{
|
{
|
||||||
printf("enet shat itself :(\n");
|
printf("enet shat itself :(\n");
|
||||||
@ -72,41 +215,48 @@ void DeInit()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StartHost()
|
void StartHost(const char* playername, int port)
|
||||||
{
|
{
|
||||||
ENetAddress addr;
|
ENetAddress addr;
|
||||||
addr.host = ENET_HOST_ANY;
|
addr.host = ENET_HOST_ANY;
|
||||||
addr.port = 8064;
|
addr.port = port;
|
||||||
|
|
||||||
// TODO determine proper number of clients/channels
|
Host = enet_host_create(&addr, 16, 1, 0, 0);
|
||||||
Host = enet_host_create(&addr, 16, 16, 0, 0);
|
|
||||||
if (!Host)
|
if (!Host)
|
||||||
{
|
{
|
||||||
printf("host shat itself :(\n");
|
printf("host shat itself :(\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Player* player = &Players[0];
|
||||||
|
memset(player, 0, sizeof(Player));
|
||||||
|
player->ID = 0;
|
||||||
|
strncpy(player->Name, playername, 31);
|
||||||
|
player->Status = 2;
|
||||||
|
NumPlayers = 1;
|
||||||
|
|
||||||
Active = true;
|
Active = true;
|
||||||
IsHost = true;
|
IsHost = true;
|
||||||
|
|
||||||
|
netplayDlg->updatePlayerList(Players, NumPlayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartClient()
|
void StartClient(const char* playername, const char* host, int port)
|
||||||
{
|
{
|
||||||
// TODO determine proper number of clients/channels
|
Host = enet_host_create(nullptr, 16, 1, 0, 0);
|
||||||
Host = enet_host_create(nullptr, 16, 16, 0, 0);
|
|
||||||
if (!Host)
|
if (!Host)
|
||||||
{
|
{
|
||||||
printf("client shat itself :(\n");
|
printf("client shat itself :(\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("client created, connecting\n");
|
printf("client created, connecting (%s, %s:%d)\n", playername, host, port);
|
||||||
|
|
||||||
ENetAddress addr;
|
ENetAddress addr;
|
||||||
enet_address_set_host(&addr, "127.0.0.1"); // TODO!!!!
|
enet_address_set_host(&addr, host);
|
||||||
addr.port = 8064;
|
addr.port = port;
|
||||||
Peer = enet_host_connect(Host, &addr, 2, 0);
|
ENetPeer* peer = enet_host_connect(Host, &addr, 1, 0);
|
||||||
if (!Peer)
|
if (!peer)
|
||||||
{
|
{
|
||||||
printf("connect shat itself :(\n");
|
printf("connect shat itself :(\n");
|
||||||
return;
|
return;
|
||||||
@ -126,9 +276,16 @@ void StartClient()
|
|||||||
if (!conn)
|
if (!conn)
|
||||||
{
|
{
|
||||||
printf("connection failed\n");
|
printf("connection failed\n");
|
||||||
enet_peer_reset(Peer);
|
enet_peer_reset(peer);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Player* player = &TempPlayer;
|
||||||
|
memset(player, 0, sizeof(Player));
|
||||||
|
player->ID = 0;
|
||||||
|
strncpy(player->Name, playername, 31);
|
||||||
|
player->Status = 3;
|
||||||
|
|
||||||
Active = true;
|
Active = true;
|
||||||
IsHost = false;
|
IsHost = false;
|
||||||
}
|
}
|
||||||
@ -153,8 +310,164 @@ void StartGame()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ProcessHost()
|
||||||
|
{
|
||||||
|
ENetEvent event;
|
||||||
|
while (enet_host_service(Host, &event, 0) > 0)
|
||||||
|
{
|
||||||
|
switch (event.type)
|
||||||
|
{
|
||||||
|
case ENET_EVENT_TYPE_CONNECT:
|
||||||
|
{
|
||||||
|
// client connected; assign player number
|
||||||
|
|
||||||
|
int id;
|
||||||
|
for (id = 0; id < 16; id++)
|
||||||
|
{
|
||||||
|
if (id >= NumPlayers) break;
|
||||||
|
if (Players[id].Status == 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id < 16)
|
||||||
|
{
|
||||||
|
u8 cmd[2];
|
||||||
|
cmd[0] = 0x01;
|
||||||
|
cmd[1] = (u8)id;
|
||||||
|
ENetPacket* pkt = enet_packet_create(cmd, 2, ENET_PACKET_FLAG_RELIABLE);
|
||||||
|
enet_peer_send(event.peer, 0, pkt);
|
||||||
|
|
||||||
|
Players[id].ID = id;
|
||||||
|
Players[id].Status = 3;
|
||||||
|
event.peer->data = &Players[id];
|
||||||
|
NumPlayers++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENET_EVENT_TYPE_DISCONNECT:
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
printf("disco\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENET_EVENT_TYPE_RECEIVE:
|
||||||
|
{
|
||||||
|
if (event.packet->dataLength < 1) break;
|
||||||
|
|
||||||
|
u8* data = (u8*)event.packet->data;
|
||||||
|
switch (data[0])
|
||||||
|
{
|
||||||
|
case 0x02: // client sending player info
|
||||||
|
{
|
||||||
|
if (event.packet->dataLength != (1+sizeof(Player))) break;
|
||||||
|
|
||||||
|
Player player;
|
||||||
|
memcpy(&player, &data[1], sizeof(Player));
|
||||||
|
player.Name[31] = '\0';
|
||||||
|
|
||||||
|
Player* hostside = (Player*)event.peer->data;
|
||||||
|
if (player.ID != hostside->ID)
|
||||||
|
{
|
||||||
|
printf("what??? %d =/= %d\n", player.ID, hostside->ID);
|
||||||
|
// TODO: disconnect
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.Status = 1;
|
||||||
|
memcpy(hostside, &player, sizeof(Player));
|
||||||
|
|
||||||
|
// broadcast updated player list
|
||||||
|
u8 cmd[2+sizeof(Players)];
|
||||||
|
cmd[0] = 0x03;
|
||||||
|
cmd[1] = (u8)NumPlayers;
|
||||||
|
memcpy(&cmd[2], Players, sizeof(Players));
|
||||||
|
ENetPacket* pkt = enet_packet_create(cmd, 2+sizeof(Players), ENET_PACKET_FLAG_RELIABLE);
|
||||||
|
enet_host_broadcast(Host, 0, pkt);
|
||||||
|
|
||||||
|
netplayDlg->updatePlayerList(Players, NumPlayers);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessClient()
|
||||||
|
{
|
||||||
|
ENetEvent event;
|
||||||
|
while (enet_host_service(Host, &event, 0) > 0)
|
||||||
|
{
|
||||||
|
switch (event.type)
|
||||||
|
{
|
||||||
|
case ENET_EVENT_TYPE_CONNECT:
|
||||||
|
printf("schmo\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENET_EVENT_TYPE_DISCONNECT:
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
printf("shma\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENET_EVENT_TYPE_RECEIVE:
|
||||||
|
{
|
||||||
|
if (event.packet->dataLength < 1) break;
|
||||||
|
|
||||||
|
u8* data = (u8*)event.packet->data;
|
||||||
|
switch (data[0])
|
||||||
|
{
|
||||||
|
case 0x01: // host sending player ID
|
||||||
|
{
|
||||||
|
if (event.packet->dataLength != 2) break;
|
||||||
|
|
||||||
|
// send player information
|
||||||
|
TempPlayer.ID = data[1];printf("host assigned ID: %d\n", data[1]);
|
||||||
|
u8 cmd[1+sizeof(Player)];
|
||||||
|
cmd[0] = 0x02;
|
||||||
|
memcpy(&cmd[1], &TempPlayer, sizeof(Player));
|
||||||
|
ENetPacket* pkt = enet_packet_create(cmd, 1+sizeof(Player), ENET_PACKET_FLAG_RELIABLE);
|
||||||
|
enet_peer_send(event.peer, 0, pkt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x03: // host sending player list
|
||||||
|
{
|
||||||
|
if (event.packet->dataLength != (2+sizeof(Players))) break;
|
||||||
|
if (data[1] > 16) break;
|
||||||
|
|
||||||
|
NumPlayers = data[1];
|
||||||
|
memcpy(Players, &data[2], sizeof(Players));
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
Players[i].Name[31] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
netplayDlg->updatePlayerList(Players, NumPlayers);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ProcessFrame()
|
void ProcessFrame()
|
||||||
{
|
{
|
||||||
|
if (IsHost)
|
||||||
|
{
|
||||||
|
ProcessHost();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ProcessClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
bool block = false;
|
bool block = false;
|
||||||
if (emuThread->emuIsRunning())
|
if (emuThread->emuIsRunning())
|
||||||
{
|
{
|
||||||
@ -181,12 +494,12 @@ void ProcessFrame()
|
|||||||
{
|
{
|
||||||
case ENET_EVENT_TYPE_CONNECT:
|
case ENET_EVENT_TYPE_CONNECT:
|
||||||
printf("client connected %08X %d\n", event.peer->address.host, event.peer->address.port);
|
printf("client connected %08X %d\n", event.peer->address.host, event.peer->address.port);
|
||||||
Peer = event.peer;
|
//Peer = event.peer;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENET_EVENT_TYPE_DISCONNECT:
|
case ENET_EVENT_TYPE_DISCONNECT:
|
||||||
printf("client disconnected %08X %d\n", event.peer->address.host, event.peer->address.port);
|
printf("client disconnected %08X %d\n", event.peer->address.host, event.peer->address.port);
|
||||||
Peer = nullptr;
|
//Peer = nullptr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENET_EVENT_TYPE_RECEIVE:
|
case ENET_EVENT_TYPE_RECEIVE:
|
||||||
|
@ -19,8 +19,106 @@
|
|||||||
#ifndef NETPLAY_H
|
#ifndef NETPLAY_H
|
||||||
#define NETPLAY_H
|
#define NETPLAY_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class NetplayStartHostDialog;
|
||||||
|
class NetplayStartClientDialog;
|
||||||
|
class NetplayDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NetplayStartHostDialog;
|
||||||
|
class NetplayStartClientDialog;
|
||||||
|
class NetplayDialog;
|
||||||
|
|
||||||
|
namespace Netplay
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Player
|
||||||
|
{
|
||||||
|
int ID;
|
||||||
|
char Name[32];
|
||||||
|
int Status; // 0=no player 1=normal 2=host 3=connecting
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class NetplayStartHostDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit NetplayStartHostDialog(QWidget* parent);
|
||||||
|
~NetplayStartHostDialog();
|
||||||
|
|
||||||
|
static NetplayStartHostDialog* openDlg(QWidget* parent)
|
||||||
|
{
|
||||||
|
NetplayStartHostDialog* dlg = new NetplayStartHostDialog(parent);
|
||||||
|
dlg->open();
|
||||||
|
return dlg;
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void done(int r);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::NetplayStartHostDialog* ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NetplayStartClientDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit NetplayStartClientDialog(QWidget* parent);
|
||||||
|
~NetplayStartClientDialog();
|
||||||
|
|
||||||
|
static NetplayStartClientDialog* openDlg(QWidget* parent)
|
||||||
|
{
|
||||||
|
NetplayStartClientDialog* dlg = new NetplayStartClientDialog(parent);
|
||||||
|
dlg->open();
|
||||||
|
return dlg;
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void done(int r);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::NetplayStartClientDialog* ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NetplayDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit NetplayDialog(QWidget* parent);
|
||||||
|
~NetplayDialog();
|
||||||
|
|
||||||
|
static NetplayDialog* openDlg(QWidget* parent)
|
||||||
|
{
|
||||||
|
NetplayDialog* dlg = new NetplayDialog(parent);
|
||||||
|
dlg->show();
|
||||||
|
return dlg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updatePlayerList(Netplay::Player* players, int num);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void sgUpdatePlayerList(Netplay::Player* players, int num);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void done(int r);
|
||||||
|
|
||||||
|
void doUpdatePlayerList(Netplay::Player* players, int num);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::NetplayDialog* ui;
|
||||||
|
};
|
||||||
|
|
||||||
namespace Netplay
|
namespace Netplay
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -29,8 +127,8 @@ extern bool Active;
|
|||||||
bool Init();
|
bool Init();
|
||||||
void DeInit();
|
void DeInit();
|
||||||
|
|
||||||
void StartHost();
|
void StartHost(const char* player, int port);
|
||||||
void StartClient();
|
void StartClient(const char* player, const char* host, int port);
|
||||||
|
|
||||||
void StartGame();
|
void StartGame();
|
||||||
|
|
||||||
|
@ -2855,12 +2855,14 @@ void MainWindow::onMPNewInstance()
|
|||||||
|
|
||||||
void MainWindow::onMPStartHost()
|
void MainWindow::onMPStartHost()
|
||||||
{
|
{
|
||||||
Netplay::StartHost();
|
//Netplay::StartHost();
|
||||||
|
NetplayStartHostDialog::openDlg(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onMPStartClient()
|
void MainWindow::onMPStartClient()
|
||||||
{
|
{
|
||||||
Netplay::StartClient();
|
//Netplay::StartClient();
|
||||||
|
NetplayStartClientDialog::openDlg(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onMPTest()
|
void MainWindow::onMPTest()
|
||||||
|
Reference in New Issue
Block a user