Added ability for client to send a packet to server, and for the server to broadcast to all clients

This commit is contained in:
MysterD 2020-10-12 18:23:48 -07:00
parent 3f798609be
commit 5d9d5ed9d7
13 changed files with 89 additions and 47 deletions

View file

@ -389,7 +389,11 @@ struct MarioState
// NOTE: this defines the maximum number of players...
// HOWEVER, simply increasing this to 3 will not magically work
// many things will have to be overhauled!
#ifdef DEVELOPMENT
#define MAX_PLAYERS 4
#else
#define MAX_PLAYERS 2
#endif
// are you still deciding to increase it?
// networking will have to be rewritten to have more than one destination. 'reliable' messages would need to be sent per-player
// things that base priority on whether they are the host or not would need priority based on player index instead

View file

@ -30,12 +30,12 @@ fi
# debug on client #
###################
#winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --server 27015 --configfile sm64config_p1.txt' -ex 'quit'
$FILE --server 27015 --configfile sm64config_p1.txt &
$FILE --client 127.0.0.1 27015 --configfile sm64config_p2.txt &
# debug if cgdb exists
if ! [ -x "$(command -v cgdb)" ]; then
$FILE --client 127.0.0.1 27015 --configfile sm64config_p3.txt &
else
winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --client 127.0.0.1 27015 --configfile sm64config_p3.txt' -ex 'quit'
fi
sleep 2
$FILE --client 127.0.0.1 27015 --configfile sm64config_p2.txt &
sleep 2
$FILE --client 127.0.0.1 27015 --configfile sm64config_p3.txt &
sleep 2
#$FILE --client 127.0.0.1 27015 --configfile sm64config_p4.txt &
winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --client 127.0.0.1 27015 --configfile sm64config_p4.txt' -ex 'quit'

View file

@ -178,11 +178,11 @@ static void ns_discord_shutdown(void) {
}
struct NetworkSystem gNetworkSystemDiscord = {
.initialize = ns_discord_initialize,
.save_id = ns_discord_save_id,
.clear_id = ns_discord_clear_id,
.update = ns_discord_update,
.send = ns_discord_network_send,
.shutdown = ns_discord_shutdown,
.canBroadcast = true,
.initialize = ns_discord_initialize,
.save_id = ns_discord_save_id,
.clear_id = ns_discord_clear_id,
.update = ns_discord_update,
.send = ns_discord_network_send,
.shutdown = ns_discord_shutdown,
.requireServerBroadcast = false,
};

View file

@ -91,10 +91,13 @@ void network_on_loaded_level(void) {
void network_send_to(u8 localIndex, struct Packet* p) {
// sanity checks
if (gNetworkType == NT_NONE) { return; }
if (gNetworkType == NT_NONE) { LOG_ERROR("network type error none!"); return; }
if (p->error) { LOG_ERROR("packet error!"); return; }
if (gNetworkSystem == NULL) { LOG_ERROR("no network system attached"); return; }
// set the flags again
packet_set_flags(p);
p->localIndex = localIndex;
// remember reliable packets
@ -106,13 +109,27 @@ void network_send_to(u8 localIndex, struct Packet* p) {
// send
int rc = gNetworkSystem->send(localIndex, p->buffer, p->cursor + sizeof(u32));
if (rc != NO_ERROR) { return; }
if (rc == SOCKET_ERROR) { LOG_ERROR("send error %d", rc); return; }
p->sent = true;
gLastNetworkSend = clock();
}
void network_send(struct Packet* p) {
// set the flags again
packet_set_flags(p);
if (gNetworkType != NT_SERVER) {
p->requestBroadcast = TRUE;
if (gNetworkSystem != NULL && gNetworkSystem->requireServerBroadcast && gNetworkPlayerServer != NULL) {
int i = gNetworkPlayerServer->localIndex;
p->localIndex = i;
network_send_to(i, p);
gLastNetworkSend = clock();
return;
}
}
for (int i = 1; i < MAX_PLAYERS; i++) {
if (!gNetworkPlayers[i].connected) { continue; }
p->localIndex = i;

View file

@ -38,7 +38,7 @@ struct NetworkSystem {
void (*update)(void);
int (*send)(u8 localIndex, u8* data, u16 dataLength);
void (*shutdown)(void);
bool canBroadcast;
bool requireServerBroadcast;
};
struct SyncObject {

View file

@ -15,7 +15,7 @@ void packet_receive(struct Packet* p) {
network_send_ack(p);
// check if we should drop packet
if (!packet_initial_read(p)) { return; }
if (!packet_initial_read(p)) { LOG_ERROR("initial read failed (%d - %d)", packetType, p->levelAreaMustMatch); return; }
switch (packetType) {
case PACKET_ACK: network_receive_ack(p); break;
@ -44,4 +44,17 @@ void packet_receive(struct Packet* p) {
case PACKET_CUSTOM: network_receive_custom(p); break;
default: LOG_ERROR("received unknown packet: %d", p->buffer[0]);
}
// broadcast packet
if (p->requestBroadcast) {
if (gNetworkType == NT_SERVER && gNetworkSystem->requireServerBroadcast) {
for (int i = 1; i < MAX_PLAYERS; i++) {
if (!gNetworkPlayers[i].connected) { continue; }
struct Packet p2 = { 0 };
packet_init(&p2, packetType, p->reliable, p->levelAreaMustMatch);
packet_write(&p2, &p->buffer[p2.cursor], p->cursor - p2.cursor);
network_send_to(i, &p2);
}
}
}
}

View file

@ -43,6 +43,7 @@ struct Packet {
bool error;
bool reliable;
bool levelAreaMustMatch;
bool requestBroadcast;
u16 seqId;
bool sent;
u8 buffer[PACKET_LENGTH];
@ -58,6 +59,7 @@ void packet_receive(struct Packet* packet);
// packet_read_write.c
void packet_init(struct Packet* packet, enum PacketType packetType, bool reliable, bool levelAreaMustMatch);
void packet_set_flags(struct Packet* packet);
void packet_write(struct Packet* packet, void* data, u16 length);
u8 packet_initial_read(struct Packet* packet);
void packet_read(struct Packet* packet, void* data, u16 length);
@ -121,8 +123,8 @@ void network_receive_collect_item(struct Packet* p);
// packet_reservation.c
void network_send_reservation_request(void);
void network_receive_reservation_request(UNUSED struct Packet* p);
void network_send_reservation(void);
void network_receive_reservation_request(struct Packet* p);
void network_send_reservation(u8 toLocalIndex);
void network_receive_reservation(struct Packet* p);
// packet_join.c

View file

@ -335,11 +335,6 @@ void network_receive_player(struct Packet* p) {
// set model
m->marioObj->header.gfx.sharedChild = gLoadedGraphNodes[(np->globalIndex == 1) ? MODEL_LUIGI : MODEL_MARIO];
// broadcast player packet
if (gNetworkType == NT_SERVER && !gNetworkSystem->canBroadcast) {
network_send_player(globalIndex);
}
}
void network_update_player(void) {

View file

@ -1,6 +1,8 @@
#include "../network.h"
#include "game/area.h"
#define PACKET_FLAG_BUFFER_OFFSET 3
static u16 nextSeqNum = 1;
void packet_init(struct Packet* packet, enum PacketType packetType, bool reliable, bool levelAreaMustMatch) {
memset(packet->buffer, 0, PACKET_LENGTH);
@ -16,12 +18,13 @@ void packet_init(struct Packet* packet, enum PacketType packetType, bool reliabl
packet->error = false;
packet->reliable = reliable;
packet->levelAreaMustMatch = levelAreaMustMatch;
packet->requestBroadcast = false;
packet->sent = false;
// write packet flags
u8 flags;
flags |= SET_BIT(packet->levelAreaMustMatch, 0);
packet_write(packet, &flags, sizeof(u8));
u8 flags = 0;
packet_write(packet, &flags, sizeof(u8)); // fill in the byte
packet_set_flags(packet);
if (levelAreaMustMatch) {
packet_write(packet, &gCurrLevelNum, sizeof(s16));
@ -29,6 +32,13 @@ void packet_init(struct Packet* packet, enum PacketType packetType, bool reliabl
}
}
void packet_set_flags(struct Packet* packet) {
u8 flags = 0;
flags |= SET_BIT(packet->levelAreaMustMatch, 0);
flags |= SET_BIT(packet->requestBroadcast, 1);
packet->buffer[PACKET_FLAG_BUFFER_OFFSET] = flags;
}
void packet_write(struct Packet* packet, void* data, u16 length) {
if (data == NULL) { packet->error = true; return; }
memcpy(&packet->buffer[packet->cursor], data, length);
@ -41,6 +51,7 @@ u8 packet_initial_read(struct Packet* packet) {
u8 flags = 0;
packet_read(packet, &flags, sizeof(u8));
packet->levelAreaMustMatch = GET_BIT(flags, 0);
packet->requestBroadcast = GET_BIT(flags, 1);
if (packet->levelAreaMustMatch) {
s16 currLevelNum;

View file

@ -41,6 +41,7 @@ void network_send_ack(struct Packet* p) {
// grab seq num
u16 seqId = 0;
memcpy(&seqId, &p->buffer[1], 2);
p->reliable = (seqId != 0);
if (seqId == 0) { return; }
// send back the ACK

View file

@ -14,23 +14,23 @@ void network_send_reservation_request(void) {
struct Packet p;
packet_init(&p, PACKET_RESERVATION_REQUEST, true, false);
network_send(&p);
network_send_to(gNetworkPlayerServer->localIndex , &p);
}
void network_receive_reservation_request(UNUSED struct Packet* p) {
void network_receive_reservation_request(struct Packet* p) {
assert(gNetworkType == NT_SERVER);
network_send_reservation();
network_send_reservation(p->localIndex);
}
void network_send_reservation(void) {
void network_send_reservation(u8 toLocalIndex) {
assert(gNetworkType == NT_SERVER);
u8 clientPlayerIndex = 1; // two-player hack
assert(toLocalIndex != 0);
// find all reserved objects
u8 reservedObjs[RESERVATION_COUNT] = { 0 };
u16 reservedIndex = 0;
for (u16 i = 1; i < MAX_SYNC_OBJECTS; i++) {
if (gSyncObjects[i].reserved == clientPlayerIndex) {
if (gSyncObjects[i].reserved == toLocalIndex) {
reservedObjs[reservedIndex++] = i;
if (reservedIndex >= RESERVATION_COUNT) { break; }
}
@ -41,7 +41,7 @@ void network_send_reservation(void) {
for (u16 i = MAX_SYNC_OBJECTS - 1; i > 0; i--) {
if (gSyncObjects[i].o != NULL) { continue; }
if (gSyncObjects[i].reserved != 0) { continue; }
gSyncObjects[i].reserved = clientPlayerIndex;
gSyncObjects[i].reserved = toLocalIndex;
reservedObjs[reservedIndex++] = i;
if (reservedIndex >= RESERVATION_COUNT) { break; }
}
@ -50,12 +50,11 @@ void network_send_reservation(void) {
struct Packet p;
packet_init(&p, PACKET_RESERVATION, true, false);
packet_write(&p, reservedObjs, sizeof(u8) * RESERVATION_COUNT);
network_send(&p);
network_send_to(toLocalIndex, &p);
}
void network_receive_reservation(struct Packet* p) {
assert(gNetworkType == NT_CLIENT);
u8 clientPlayerIndex = 1; // two-player hack
// find all reserved objects
u8 reservedObjs[RESERVATION_COUNT] = { 0 };
@ -65,6 +64,6 @@ void network_receive_reservation(struct Packet* p) {
u16 index = reservedObjs[i];
if (index == 0) { continue; }
if (gSyncObjects[index].o != NULL) { continue; }
gSyncObjects[index].reserved = clientPlayerIndex;
gSyncObjects[index].reserved = gNetworkPlayerLocal->globalIndex;
}
}

View file

@ -152,6 +152,6 @@ void network_receive_spawn_objects(struct Packet* p) {
// update their block of reserved ids
if (gNetworkType == NT_SERVER && receivedReservedSyncObject) {
network_send_reservation();
network_send_reservation(p->localIndex);
}
}

View file

@ -138,11 +138,11 @@ static void ns_socket_shutdown(void) {
}
struct NetworkSystem gNetworkSystemSocket = {
.initialize = ns_socket_initialize,
.save_id = ns_socket_save_id,
.clear_id = ns_socket_clear_id,
.update = ns_socket_update,
.send = ns_socket_send,
.shutdown = ns_socket_shutdown,
.canBroadcast = false,
.initialize = ns_socket_initialize,
.save_id = ns_socket_save_id,
.clear_id = ns_socket_clear_id,
.update = ns_socket_update,
.send = ns_socket_send,
.shutdown = ns_socket_shutdown,
.requireServerBroadcast = true,
};