get some LAN comm started

This commit is contained in:
Arisotura 2023-09-03 19:35:47 +02:00
parent c148b77360
commit 272f4e5f3a
2 changed files with 317 additions and 196 deletions

View File

@ -19,8 +19,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <queue>
#include <enet/enet.h>
#include <SDL2/SDL.h>
#include <QStandardItemModel>
@ -173,6 +175,15 @@ void LANDialog::doUpdatePlayerList(LAN::Player* players, int num)
namespace LAN
{
struct MPPacketHeader
{
u32 Magic;
u32 SenderID;
u32 Type; // 0=regular 1=CMD 2=reply 3=ack
u32 Length;
u64 Timestamp;
};
const int kLANPort = 7064;
bool Active;
@ -185,10 +196,15 @@ Player Players[16];
int NumPlayers;
int MaxPlayers;
u16 ConnectedBitmask;
Player MyPlayer;
u32 HostAddress;
bool Lag;
int MPRecvTimeout;
std::queue<ENetPacket*> RXQueue;
bool Init()
{
@ -202,6 +218,10 @@ bool Init()
NumPlayers = 0;
MaxPlayers = 0;
ConnectedBitmask = 0;
MPRecvTimeout = 25;
// TODO we init enet here but also in Netplay
// that is redundant
if (enet_initialize() != 0)
@ -228,7 +248,7 @@ void StartHost(const char* playername, int numplayers)
addr.host = ENET_HOST_ANY;
addr.port = kLANPort;
Host = enet_host_create(&addr, 16, 1, 0, 0);
Host = enet_host_create(&addr, 16, 2, 0, 0);
if (!Host)
{
// TODO handle this gracefully
@ -256,7 +276,7 @@ void StartHost(const char* playername, int numplayers)
void StartClient(const char* playername, const char* host)
{
Host = enet_host_create(nullptr, 16, 1, 0, 0);
Host = enet_host_create(nullptr, 16, 2, 0, 0);
if (!Host)
{
// TODO handle this gracefully
@ -269,7 +289,7 @@ void StartClient(const char* playername, const char* host)
ENetAddress addr;
enet_address_set_host(&addr, host);
addr.port = kLANPort;
ENetPeer* peer = enet_host_connect(Host, &addr, 1, 0);
ENetPeer* peer = enet_host_connect(Host, &addr, 2, 0);
if (!peer)
{
printf("connect shat itself :(\n");
@ -307,13 +327,8 @@ void StartClient(const char* playername, const char* host)
}
void ProcessHost()
void ProcessHostEvent(ENetEvent& event)
{
if (!Host) return;
ENetEvent event;
while (enet_host_service(Host, &event, 0) > 0)
{
switch (event.type)
{
case ENET_EVENT_TYPE_CONNECT:
@ -404,20 +419,34 @@ void ProcessHost()
lanDlg->updatePlayerList(Players, NumPlayers);
}
break;
case 0x04: // player connected
{
if (event.packet->dataLength != 2) break;
if (data[1] > 15) break;
ConnectedBitmask |= (1<<data[1]);
}
break;
case 0x05: // player disconnected
{
if (event.packet->dataLength != 2) break;
if (data[1] > 15) break;
ConnectedBitmask &= ~(1<<data[1]);
}
break;
}
enet_packet_destroy(event.packet);
}
break;
}
}
void ProcessClient()
void ProcessClientEvent(ENetEvent& event)
{
if (!Host) return;
ENetEvent event;
while (enet_host_service(Host, &event, 0) > 0)
{
switch (event.type)
{
case ENET_EVENT_TYPE_CONNECT:
@ -504,7 +533,7 @@ void ProcessClient()
ENetAddress peeraddr;
peeraddr.host = player->Address;
peeraddr.port = kLANPort;
ENetPeer* peer = enet_host_connect(Host, &peeraddr, 1, 0);
ENetPeer* peer = enet_host_connect(Host, &peeraddr, 2, 0);
if (!peer)
{
// TODO deal with this
@ -515,78 +544,174 @@ void ProcessClient()
}
break;
case 0x04: // start game
case 0x04: // player connected
{
//
if (event.packet->dataLength != 2) break;
if (data[1] > 15) break;
ConnectedBitmask |= (1<<data[1]);
}
break;
case 0x05: // player disconnected
{
if (event.packet->dataLength != 2) break;
if (data[1] > 15) break;
ConnectedBitmask &= ~(1<<data[1]);
}
break;
}
enet_packet_destroy(event.packet);
}
break;
}
}
}
void Process()
void ProcessEvent(ENetEvent& event)
{
if (IsHost)
ProcessHost();
ProcessHostEvent(event);
else
ProcessClient();
ProcessClientEvent(event);
}
void Process(bool block)
{
if (!Host) return;
int timeout = block ? MPRecvTimeout : 0;
u32 time_last = SDL_GetTicks();
ENetEvent event;
while (enet_host_service(Host, &event, timeout) > 0)
{
if (event.type == ENET_EVENT_TYPE_RECEIVE && event.channelID == 1)
{
RXQueue.push(event.packet);
if (block) return;
}
else
{
ProcessEvent(event);
if (block)
{
u32 time = SDL_GetTicks();
timeout -= (time - time_last);
if (timeout <= 0) return;
}
}
}
}
void SetMPRecvTimeout(int timeout)
{
//MPRecvTimeout = timeout;
MPRecvTimeout = timeout;
}
void MPBegin()
{
//
ConnectedBitmask |= (1<<MyPlayer.ID);
u8 cmd[2] = {0x04, MyPlayer.ID};
ENetPacket* pkt = enet_packet_create(cmd, 2, ENET_PACKET_FLAG_RELIABLE);
enet_host_broadcast(Host, 0, pkt);
}
void MPEnd()
{
//
ConnectedBitmask &= ~(1<<MyPlayer.ID);
u8 cmd[2] = {0x05, MyPlayer.ID};
ENetPacket* pkt = enet_packet_create(&cmd, 2, ENET_PACKET_FLAG_RELIABLE);
enet_host_broadcast(Host, 0, pkt);
}
void SetActive(bool active)
int SendMPPacketGeneric(u32 type, u8* packet, int len, u64 timestamp)
{
//
if (!Host) return 0;
// TODO make the reliable part optional?
u32 flags = ENET_PACKET_FLAG_RELIABLE;
ENetPacket* enetpacket = enet_packet_create(nullptr, sizeof(MPPacketHeader)+len, flags);
MPPacketHeader pktheader;
pktheader.Magic = 0x4946494E;
pktheader.SenderID = MyPlayer.ID;
pktheader.Type = type;
pktheader.Length = len;
pktheader.Timestamp = timestamp;
memcpy(&enetpacket->data[0], &pktheader, sizeof(MPPacketHeader));
if (len)
memcpy(&enetpacket->data[sizeof(MPPacketHeader)], packet, len);
enet_host_broadcast(Host, 1, enetpacket);
enet_host_flush(Host);
return len;
}
u16 GetInstanceBitmask()
int RecvMPPacketGeneric(u8* packet, bool block, u64* timestamp)
{
//
if (!Host) return 0;
Process(block);
if (RXQueue.empty()) return 0;
ENetPacket* enetpacket = RXQueue.front();
RXQueue.pop();
MPPacketHeader* header = (MPPacketHeader*)&enetpacket->data[0];
bool good = true;
if (enetpacket->dataLength < sizeof(MPPacketHeader))
good = false;
else if (header->Magic != 0x4946494E)
good = false;
else if (header->SenderID == MyPlayer.ID)
good = false;
if (!good)
{
enet_packet_destroy(enetpacket);
return 0;
}
u32 len = header->Length;
if (len)
memcpy(packet, &enetpacket->data[sizeof(MPPacketHeader)], len);
if (timestamp) *timestamp = header->Timestamp;
return len;
}
int SendMPPacket(u8* packet, int len, u64 timestamp)
{
return 0;
return SendMPPacketGeneric(0, packet, len, timestamp);
}
int RecvMPPacket(u8* packet, u64* timestamp)
{
return 0;
return RecvMPPacketGeneric(packet, false, timestamp);
}
int SendMPCmd(u8* packet, int len, u64 timestamp)
{
return 0;
return SendMPPacketGeneric(1, packet, len, timestamp);
}
int SendMPReply(u8* packet, int len, u64 timestamp, u16 aid)
{
return 0;
return SendMPPacketGeneric(2 | (aid<<16), packet, len, timestamp);
}
int SendMPAck(u8* packet, int len, u64 timestamp)
{
return 0;
return SendMPPacketGeneric(3, packet, len, timestamp);
}
int RecvMPHostPacket(u8* packet, u64* timestamp)

View File

@ -126,16 +126,12 @@ void DeInit();
void StartHost(const char* player, int numplayers);
void StartClient(const char* player, const char* host);
void Process();
void Process(bool block = false);
void SetMPRecvTimeout(int timeout);
void MPBegin();
void MPEnd();
void SetActive(bool active);
u16 GetInstanceBitmask();
int SendMPPacket(u8* data, int len, u64 timestamp);
int RecvMPPacket(u8* data, u64* timestamp);
int SendMPCmd(u8* data, int len, u64 timestamp);