updates to LAN player list thingy

This commit is contained in:
Arisotura
2023-09-14 18:09:00 +02:00
parent d3a6dbeed3
commit a5b4fc2517
2 changed files with 195 additions and 59 deletions

View File

@ -286,6 +286,8 @@ LANDialog::LANDialog(QWidget* parent) : QDialog(parent), ui(new Ui::LANDialog)
QStandardItemModel* model = new QStandardItemModel(); QStandardItemModel* model = new QStandardItemModel();
ui->tvPlayerList->setModel(model); ui->tvPlayerList->setModel(model);
const QStringList header = {"#", "Player", "Status", "Ping", "IP"};
model->setHorizontalHeaderLabels(header);
connect(this, &LANDialog::sgUpdatePlayerList, this, &LANDialog::doUpdatePlayerList); connect(this, &LANDialog::sgUpdatePlayerList, this, &LANDialog::doUpdatePlayerList);
} }
@ -302,50 +304,90 @@ void LANDialog::done(int r)
QDialog::done(r); QDialog::done(r);
} }
void LANDialog::updatePlayerList(LAN::Player* players, int num) void LANDialog::updatePlayerList()
{ {
emit sgUpdatePlayerList(players, num); playerListMutex.lock();
memcpy(playerList, LAN::Players, sizeof(playerList));
memcpy(playerPing, LAN::PlayerPing, sizeof(playerPing));
numPlayers = LAN::NumPlayers;
maxPlayers = LAN::MaxPlayers;
myPlayerID = LAN::MyPlayer.ID;
hostAddress = LAN::HostAddress;
playerListMutex.unlock();
emit sgUpdatePlayerList();
} }
void LANDialog::doUpdatePlayerList(LAN::Player* players, int num) void LANDialog::doUpdatePlayerList()
{ {
playerListMutex.lock();
QStandardItemModel* model = (QStandardItemModel*)ui->tvPlayerList->model(); QStandardItemModel* model = (QStandardItemModel*)ui->tvPlayerList->model();
int curcount = model->rowCount();
model->clear(); int newcount = numPlayers;
model->setRowCount(num); if (curcount > newcount)
// TODO: remove IP column in final product
const QStringList header = {"#", "Player", "Status", "Ping", "IP"};
model->setHorizontalHeaderLabels(header);
for (int i = 0; i < num; i++)
{ {
LAN::Player* player = &players[i]; model->removeRows(newcount, curcount-newcount);
}
else if (curcount < newcount)
{
for (int i = curcount; i < newcount; i++)
{
QList<QStandardItem*> row;
row.append(new QStandardItem());
row.append(new QStandardItem());
row.append(new QStandardItem());
row.append(new QStandardItem());
row.append(new QStandardItem());
model->appendRow(row);
}
}
for (int i = 0; i < 16; i++)
{
LAN::Player* player = &playerList[i];
if (player->Status == 0) break;
QString id = QString("%0").arg(player->ID+1); QString id = QString("%0").arg(player->ID+1);
model->setItem(i, 0, new QStandardItem(id)); model->item(i, 0)->setText(id);
QString name = player->Name; QString name = player->Name;
model->setItem(i, 1, new QStandardItem(name)); model->item(i, 1)->setText(name);
QString status; QString status;
switch (player->Status) switch (player->Status)
{ {
case 1: status = ""; break; case 1: status = "Ready"; break;
case 2: status = "Host"; break; case 2: status = "Host"; break;
default: status = "ded"; break; case 3: status = "Connecting"; break;
} }
model->setItem(i, 2, new QStandardItem(status)); model->item(i, 2)->setText(status);
// TODO: ping if (i == myPlayerID)
model->setItem(i, 3, new QStandardItem("x")); {
model->item(i, 3)->setText("");
model->item(i, 4)->setText("(local)");
}
else
{
QString ping = QString("%0 ms").arg(playerPing[i]);
model->item(i, 3)->setText(ping);
char ip[32]; // note on the player IP display
u32 addr = player->Address; // * we make an exception for the host -- the player list is issued by the host, so the host IP would be 127.0.0.1
sprintf(ip, "%d.%d.%d.%d", addr&0xFF, (addr>>8)&0xFF, (addr>>16)&0xFF, addr>>24); // * for the same reason, the host can't know its own IP, so for the current player we force it to 127.0.0.1
model->setItem(i, 4, new QStandardItem(ip)); u32 ip;
if (player->Status == 1)
ip = hostAddress;
else
ip = player->Address;
QString ips = QString("%0.%1.%2.%3").arg(ip&0xFF).arg((ip>>8)&0xFF).arg((ip>>16)&0xFF).arg(ip>>24);
model->item(i, 4)->setText(ips);
}
} }
playerListMutex.unlock();
} }
@ -353,6 +395,7 @@ namespace LAN
{ {
const u32 kDiscoveryMagic = 0x444E414C; // LAND const u32 kDiscoveryMagic = 0x444E414C; // LAND
const u32 kLANMagic = 0x504E414C; // LANP
const u32 kPacketMagic = 0x4946494E; // NIFI const u32 kPacketMagic = 0x4946494E; // NIFI
const u32 kProtocolVersion = 1; const u32 kProtocolVersion = 1;
@ -381,6 +424,7 @@ ENetHost* Host;
ENetPeer* RemotePeers[16]; ENetPeer* RemotePeers[16];
Player Players[16]; Player Players[16];
u32 PlayerPing[16];
int NumPlayers; int NumPlayers;
int MaxPlayers; int MaxPlayers;
@ -395,6 +439,8 @@ int LastHostID;
ENetPeer* LastHostPeer; ENetPeer* LastHostPeer;
std::queue<ENetPacket*> RXQueue; std::queue<ENetPacket*> RXQueue;
u32 FrameCount;
bool Init() bool Init()
{ {
@ -408,6 +454,7 @@ bool Init()
memset(RemotePeers, 0, sizeof(RemotePeers)); memset(RemotePeers, 0, sizeof(RemotePeers));
memset(Players, 0, sizeof(Players)); memset(Players, 0, sizeof(Players));
memset(PlayerPing, 0, sizeof(PlayerPing));
NumPlayers = 0; NumPlayers = 0;
MaxPlayers = 0; MaxPlayers = 0;
@ -417,6 +464,8 @@ bool Init()
LastHostID = -1; LastHostID = -1;
LastHostPeer = nullptr; LastHostPeer = nullptr;
FrameCount = 0;
// TODO we init enet here but also in Netplay // TODO we init enet here but also in Netplay
// that is redundant // that is redundant
if (enet_initialize() != 0) if (enet_initialize() != 0)
@ -533,7 +582,7 @@ bool StartHost(const char* playername, int numplayers)
IsHost = true; IsHost = true;
if (lanDlg) if (lanDlg)
lanDlg->updatePlayerList(Players, NumPlayers); lanDlg->updatePlayerList();
StartDiscovery(); StartDiscovery();
return true; return true;
@ -583,21 +632,39 @@ bool StartClient(const char* playername, const char* host)
u8* data = event.packet->data; u8* data = event.packet->data;
if (event.channelID != 0) continue; if (event.channelID != 0) continue;
if (data[0] != 0x01) continue; if (data[0] != 0x01) continue;
if (event.packet->dataLength != 3) continue; if (event.packet->dataLength != 11) continue;
MaxPlayers = data[2]; u32 magic = data[1] | (data[2] << 8) | (data[3] << 16) | (data[4] << 24);
u32 version = data[5] | (data[6] << 8) | (data[7] << 16) | (data[8] << 24);
if (magic != kLANMagic) continue;
if (version != kProtocolVersion) continue;
MaxPlayers = data[10];
// send player information // send player information
MyPlayer.ID = data[1]; MyPlayer.ID = data[9];
u8 cmd[1+sizeof(Player)]; u8 cmd[9+sizeof(Player)];
cmd[0] = 0x02; cmd[0] = 0x02;
memcpy(&cmd[1], &MyPlayer, sizeof(Player)); cmd[1] = (u8)kLANMagic;
ENetPacket* pkt = enet_packet_create(cmd, 1+sizeof(Player), ENET_PACKET_FLAG_RELIABLE); cmd[2] = (u8)(kLANMagic >> 8);
cmd[3] = (u8)(kLANMagic >> 16);
cmd[4] = (u8)(kLANMagic >> 24);
cmd[5] = (u8)kProtocolVersion;
cmd[6] = (u8)(kProtocolVersion >> 8);
cmd[7] = (u8)(kProtocolVersion >> 16);
cmd[8] = (u8)(kProtocolVersion >> 24);
memcpy(&cmd[9], &MyPlayer, sizeof(Player));
ENetPacket* pkt = enet_packet_create(cmd, 9+sizeof(Player), ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(event.peer, 0, pkt); enet_peer_send(event.peer, 0, pkt);
conn = 2; conn = 2;
break; break;
} }
else if (event.type == ENET_EVENT_TYPE_DISCONNECT)
{
conn = 0;
break;
}
} }
else else
break; break;
@ -614,6 +681,7 @@ bool StartClient(const char* playername, const char* host)
HostAddress = addr.host; HostAddress = addr.host;
LastHostID = -1; LastHostID = -1;
LastHostPeer = nullptr; LastHostPeer = nullptr;
RemotePeers[0] = peer;
Active = true; Active = true;
IsHost = false; IsHost = false;
@ -689,6 +757,7 @@ void ProcessDiscovery()
} }
beacon.Magic = tick; beacon.Magic = tick;
beacon.SessionName[63] = '\0';
DiscoveryList[key] = beacon; DiscoveryList[key] = beacon;
} }
@ -718,6 +787,19 @@ void ProcessDiscovery()
} }
} }
void HostUpdatePlayerList()
{
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);
if (lanDlg)
lanDlg->updatePlayerList();
}
void ProcessHostEvent(ENetEvent& event) void ProcessHostEvent(ENetEvent& event)
{ {
switch (event.type) switch (event.type)
@ -742,11 +824,19 @@ void ProcessHostEvent(ENetEvent& event)
if (id < 16) if (id < 16)
{ {
u8 cmd[3]; u8 cmd[11];
cmd[0] = 0x01; cmd[0] = 0x01;
cmd[1] = (u8)id; cmd[1] = (u8)kLANMagic;
cmd[2] = MaxPlayers; cmd[2] = (u8)(kLANMagic >> 8);
ENetPacket* pkt = enet_packet_create(cmd, 3, ENET_PACKET_FLAG_RELIABLE); cmd[3] = (u8)(kLANMagic >> 16);
cmd[4] = (u8)(kLANMagic >> 24);
cmd[5] = (u8)kProtocolVersion;
cmd[6] = (u8)(kProtocolVersion >> 8);
cmd[7] = (u8)(kProtocolVersion >> 16);
cmd[8] = (u8)(kProtocolVersion >> 24);
cmd[9] = (u8)id;
cmd[10] = MaxPlayers;
ENetPacket* pkt = enet_packet_create(cmd, 11, ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(event.peer, 0, pkt); enet_peer_send(event.peer, 0, pkt);
Players[id].ID = id; Players[id].ID = id;
@ -767,8 +857,18 @@ void ProcessHostEvent(ENetEvent& event)
case ENET_EVENT_TYPE_DISCONNECT: case ENET_EVENT_TYPE_DISCONNECT:
{ {
// TODO Player* player = (Player*)event.peer->data;
printf("disco\n"); if (!player) break;
int id = player->ID;
RemotePeers[id] = nullptr;
player->ID = 0;
player->Status = 0;
NumPlayers--;
// broadcast updated player list
HostUpdatePlayerList();
} }
break; break;
@ -781,17 +881,24 @@ void ProcessHostEvent(ENetEvent& event)
{ {
case 0x02: // client sending player info case 0x02: // client sending player info
{ {
if (event.packet->dataLength != (1+sizeof(Player))) break; if (event.packet->dataLength != (9+sizeof(Player))) break;
u32 magic = data[1] | (data[2] << 8) | (data[3] << 16) | (data[4] << 24);
u32 version = data[5] | (data[6] << 8) | (data[7] << 16) | (data[8] << 24);
if ((magic != kLANMagic) || (version != kProtocolVersion))
{
enet_peer_disconnect(event.peer, 0);
break;
}
Player player; Player player;
memcpy(&player, &data[1], sizeof(Player)); memcpy(&player, &data[9], sizeof(Player));
player.Name[31] = '\0'; player.Name[31] = '\0';
Player* hostside = (Player*)event.peer->data; Player* hostside = (Player*)event.peer->data;
if (player.ID != hostside->ID) if (player.ID != hostside->ID)
{ {
printf("what??? %d =/= %d\n", player.ID, hostside->ID); enet_peer_disconnect(event.peer, 0);
// TODO: disconnect
break; break;
} }
@ -800,15 +907,7 @@ void ProcessHostEvent(ENetEvent& event)
memcpy(hostside, &player, sizeof(Player)); memcpy(hostside, &player, sizeof(Player));
// broadcast updated player list // broadcast updated player list
u8 cmd[2+sizeof(Players)]; HostUpdatePlayerList();
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);
if (lanDlg)
lanDlg->updatePlayerList(Players, NumPlayers);
} }
break; break;
@ -851,7 +950,7 @@ void ProcessClientEvent(ENetEvent& event)
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
Player* player = &Players[i]; Player* player = &Players[i];
if (player->ID == MyPlayer.ID) continue; if (i == MyPlayer.ID) continue;
if (player->Status != 1) continue; if (player->Status != 1) continue;
if (player->Address == event.peer->address.host) if (player->Address == event.peer->address.host)
@ -874,8 +973,11 @@ void ProcessClientEvent(ENetEvent& event)
case ENET_EVENT_TYPE_DISCONNECT: case ENET_EVENT_TYPE_DISCONNECT:
{ {
// TODO Player* player = (Player*)event.peer->data;
printf("shma\n"); if (!player) break;
int id = player->ID;
RemotePeers[id] = nullptr;
} }
break; break;
@ -899,13 +1001,13 @@ void ProcessClientEvent(ENetEvent& event)
} }
if (lanDlg) if (lanDlg)
lanDlg->updatePlayerList(Players, NumPlayers); lanDlg->updatePlayerList();
// establish connections to any new clients // establish connections to any new clients
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
Player* player = &Players[i]; Player* player = &Players[i];
if (player->ID == MyPlayer.ID) continue; if (i == MyPlayer.ID) continue;
if (player->Status != 1) continue; if (player->Status != 1) continue;
if (!RemotePeers[i]) if (!RemotePeers[i])
@ -992,6 +1094,24 @@ void ProcessFrame()
{ {
ProcessDiscovery(); ProcessDiscovery();
Process(false); Process(false);
FrameCount++;
if (FrameCount >= 60)
{
FrameCount = 0;
for (int i = 0; i < 16; i++)
{
if (Players[i].Status == 0) continue;
if (i == MyPlayer.ID) continue;
if (!RemotePeers[i]) continue;
PlayerPing[i] = RemotePeers[i]->roundTripTime;
}
if (lanDlg)
lanDlg->updatePlayerList();
}
} }

View File

@ -127,18 +127,26 @@ public:
return dlg; return dlg;
} }
void updatePlayerList(LAN::Player* players, int num); void updatePlayerList();
signals: signals:
void sgUpdatePlayerList(LAN::Player* players, int num); void sgUpdatePlayerList();
private slots: private slots:
void done(int r); void done(int r);
void doUpdatePlayerList(LAN::Player* players, int num); void doUpdatePlayerList();
private: private:
Ui::LANDialog* ui; Ui::LANDialog* ui;
LAN::Player playerList[16];
u32 playerPing[16];
int numPlayers;
int maxPlayers;
int myPlayerID;
u32 hostAddress;
QMutex playerListMutex;
}; };
namespace LAN namespace LAN
@ -149,6 +157,14 @@ extern bool Active;
extern std::map<u32, DiscoveryData> DiscoveryList; extern std::map<u32, DiscoveryData> DiscoveryList;
extern QMutex DiscoveryMutex; extern QMutex DiscoveryMutex;
extern Player Players[16];
extern u32 PlayerPing[16];
extern int NumPlayers;
extern int MaxPlayers;
extern Player MyPlayer;
extern u32 HostAddress;
bool Init(); bool Init();
void DeInit(); void DeInit();