mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-10-30 08:01:01 +00:00
Added ability for client to send a packet to server, and for the server to broadcast to all clients
This commit is contained in:
parent
3f798609be
commit
5d9d5ed9d7
13 changed files with 89 additions and 47 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue