mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-22 12:05:11 +00:00
Added ability for clients to send packets to each other skipping server
Added memory of last reliable packet about each sync object
This commit is contained in:
parent
e593bedc77
commit
050d940d53
8 changed files with 89 additions and 65 deletions
|
@ -115,6 +115,11 @@ void network_send_to(u8 localIndex, struct Packet* p) {
|
|||
// set the flags again
|
||||
packet_set_flags(p);
|
||||
|
||||
// set destination
|
||||
packet_set_destination(p, p->requestBroadcast
|
||||
? PACKET_DESTINATION_BROADCAST
|
||||
: gNetworkPlayers[(localIndex == 0) ? p->localIndex : localIndex].globalIndex);
|
||||
|
||||
p->localIndex = localIndex;
|
||||
|
||||
// remember reliable packets
|
||||
|
@ -124,6 +129,11 @@ void network_send_to(u8 localIndex, struct Packet* p) {
|
|||
u32 hash = packet_hash(p);
|
||||
memcpy(&p->buffer[p->dataLength], &hash, sizeof(u32));
|
||||
|
||||
// redirect to server if required
|
||||
if (localIndex != 0 && gNetworkType != NT_SERVER && gNetworkSystem->requireServerBroadcast) {
|
||||
localIndex = gNetworkPlayerServer->localIndex;
|
||||
}
|
||||
|
||||
// send
|
||||
int rc = gNetworkSystem->send(localIndex, p->buffer, p->cursor + sizeof(u32));
|
||||
if (rc == SOCKET_ERROR) { LOG_ERROR("send error %d", rc); return; }
|
||||
|
|
|
@ -31,38 +31,44 @@ void packet_receive(struct Packet* p) {
|
|||
|
||||
// check if we should process the packet
|
||||
if (packet_initial_read(p)) {
|
||||
switch (packetType) {
|
||||
case PACKET_ACK: network_receive_ack(p); break;
|
||||
case PACKET_PLAYER: network_receive_player(p); break;
|
||||
case PACKET_OBJECT: network_receive_object(p); break;
|
||||
case PACKET_SPAWN_OBJECTS: network_receive_spawn_objects(p); break;
|
||||
case PACKET_SPAWN_STAR: network_receive_spawn_star(p); break;
|
||||
case PACKET_SPAWN_STAR_NLE: network_receive_spawn_star_nle(p); break;
|
||||
case PACKET_COLLECT_STAR: network_receive_collect_star(p); break;
|
||||
case PACKET_COLLECT_COIN: network_receive_collect_coin(p); break;
|
||||
case PACKET_COLLECT_ITEM: network_receive_collect_item(p); break;
|
||||
case PACKET_RESERVATION_REQUEST: network_receive_reservation_request(p); break;
|
||||
case PACKET_RESERVATION: network_receive_reservation(p); break;
|
||||
case PACKET_JOIN_REQUEST: network_receive_join_request(p); break;
|
||||
case PACKET_JOIN: network_receive_join(p); break;
|
||||
case PACKET_CHAT: network_receive_chat(p); break;
|
||||
case PACKET_KICK: network_receive_kick(p); break;
|
||||
case PACKET_KEEP_ALIVE: network_receive_keep_alive(p); break;
|
||||
case PACKET_LEAVING: network_receive_leaving(p); break;
|
||||
case PACKET_SAVE_FILE: network_receive_save_file(p); break;
|
||||
case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break;
|
||||
case PACKET_DEATH: network_receive_death(p); break;
|
||||
case PACKET_LEVEL_AREA: network_receive_level_area(p); break;
|
||||
case PACKET_LEVEL_AREA_VALID: network_receive_level_area_valid(p); break;
|
||||
case PACKET_LOCATION_REQUEST: network_receive_location_request(p); break;
|
||||
case PACKET_CLIENT_LOCATION_REQUEST: network_receive_client_location_request(p); break;
|
||||
case PACKET_LOCATION_RESPONSE: network_receive_location_response(p); break;
|
||||
///
|
||||
case PACKET_CUSTOM: network_receive_custom(p); break;
|
||||
default: LOG_ERROR("received unknown packet: %d", p->buffer[0]);
|
||||
if (gNetworkType == NT_SERVER && p->destGlobalId != PACKET_DESTINATION_BROADCAST && p->destGlobalId != 0 && packetType != PACKET_ACK) {
|
||||
// this packet is meant for someone else
|
||||
struct Packet p2 = { 0 };
|
||||
packet_duplicate(p, &p2);
|
||||
network_send_to(p->destGlobalId, &p2);
|
||||
} else {
|
||||
// process the packet
|
||||
switch (packetType) {
|
||||
case PACKET_ACK: network_receive_ack(p); break;
|
||||
case PACKET_PLAYER: network_receive_player(p); break;
|
||||
case PACKET_OBJECT: network_receive_object(p); break;
|
||||
case PACKET_SPAWN_OBJECTS: network_receive_spawn_objects(p); break;
|
||||
case PACKET_SPAWN_STAR: network_receive_spawn_star(p); break;
|
||||
case PACKET_SPAWN_STAR_NLE: network_receive_spawn_star_nle(p); break;
|
||||
case PACKET_COLLECT_STAR: network_receive_collect_star(p); break;
|
||||
case PACKET_COLLECT_COIN: network_receive_collect_coin(p); break;
|
||||
case PACKET_COLLECT_ITEM: network_receive_collect_item(p); break;
|
||||
case PACKET_RESERVATION_REQUEST: network_receive_reservation_request(p); break;
|
||||
case PACKET_RESERVATION: network_receive_reservation(p); break;
|
||||
case PACKET_JOIN_REQUEST: network_receive_join_request(p); break;
|
||||
case PACKET_JOIN: network_receive_join(p); break;
|
||||
case PACKET_CHAT: network_receive_chat(p); break;
|
||||
case PACKET_KICK: network_receive_kick(p); break;
|
||||
case PACKET_KEEP_ALIVE: network_receive_keep_alive(p); break;
|
||||
case PACKET_LEAVING: network_receive_leaving(p); break;
|
||||
case PACKET_SAVE_FILE: network_receive_save_file(p); break;
|
||||
case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break;
|
||||
case PACKET_DEATH: network_receive_death(p); break;
|
||||
case PACKET_LEVEL_AREA: network_receive_level_area(p); break;
|
||||
case PACKET_LEVEL_AREA_VALID: network_receive_level_area_valid(p); break;
|
||||
case PACKET_LOCATION_REQUEST: network_receive_location_request(p); break;
|
||||
case PACKET_CLIENT_LOCATION_REQUEST: network_receive_client_location_request(p); break;
|
||||
case PACKET_LOCATION_RESPONSE: network_receive_location_response(p); break;
|
||||
///
|
||||
case PACKET_CUSTOM: network_receive_custom(p); break;
|
||||
default: LOG_ERROR("received unknown packet: %d", p->buffer[0]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//LOG_ERROR("initial read failed (%d - %d)", packetType, p->levelAreaMustMatch);
|
||||
}
|
||||
|
||||
// broadcast packet
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#define PACKET_LENGTH 1024
|
||||
#define PACKET_DESTINATION_BROADCAST ((u8)-1)
|
||||
|
||||
enum PacketType {
|
||||
PACKET_ACK,
|
||||
|
@ -47,6 +48,7 @@ struct Packet {
|
|||
bool reliable;
|
||||
bool levelAreaMustMatch;
|
||||
bool requestBroadcast;
|
||||
u8 destGlobalId;
|
||||
u16 seqId;
|
||||
bool sent;
|
||||
u8 buffer[PACKET_LENGTH];
|
||||
|
@ -64,6 +66,7 @@ void packet_receive(struct Packet* packet);
|
|||
void packet_init(struct Packet* packet, enum PacketType packetType, bool reliable, bool levelAreaMustMatch);
|
||||
void packet_duplicate(struct Packet* srcPacket, struct Packet* dstPacket);
|
||||
void packet_set_flags(struct Packet* packet);
|
||||
void packet_set_destination(struct Packet* packet, u8 destGlobalId);
|
||||
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);
|
||||
|
@ -82,6 +85,7 @@ void network_update_player(void);
|
|||
void network_receive_player(struct Packet* p);
|
||||
|
||||
// packet_object.c
|
||||
struct Packet* get_last_sync_ent_reliable_packet(u8 syncId);
|
||||
struct SyncObject* network_init_object(struct Object* object, float maxSyncDistance);
|
||||
void network_init_object_field(struct Object* o, void* field);
|
||||
bool network_owns_object(struct Object* o);
|
||||
|
|
|
@ -36,7 +36,6 @@ void network_send_chat(char* message, u8 rgb[3]) {
|
|||
packet_write(&p, &messageLength, sizeof(u16));
|
||||
packet_write(&p, message, messageLength * sizeof(u8));
|
||||
network_send(&p);
|
||||
LOG_INFO("tx chat: %s", message);
|
||||
|
||||
#ifdef DEVELOPMENT
|
||||
print_network_player_table();
|
||||
|
|
|
@ -98,7 +98,7 @@ static void network_send_level_area_valid_server(u8 toGlobalIndex) {
|
|||
static void network_send_level_area_valid_client() {
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_LEVEL_AREA_VALID, true, false);
|
||||
network_send_to(0, &p);
|
||||
network_send_to(gNetworkPlayerServer->localIndex, &p);
|
||||
}
|
||||
|
||||
void network_send_level_area_valid(u8 toGlobalIndex) {
|
||||
|
|
|
@ -168,7 +168,6 @@ void network_send_location_response(u8 destGlobalIndex) {
|
|||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_LOCATION_RESPONSE, true, false);
|
||||
packet_write(&p, &destGlobalIndex, sizeof(u8));
|
||||
packet_write(&p, &gCurrCourseNum, sizeof(s16));
|
||||
packet_write(&p, &gCurrActNum, sizeof(s16));
|
||||
packet_write(&p, &gCurrLevelNum, sizeof(s16));
|
||||
|
@ -183,18 +182,11 @@ void network_send_location_response(u8 destGlobalIndex) {
|
|||
|
||||
//LOG_INFO("network_send_location_response() { %d, %d, %d, %d, %d } to: %d", destGlobalIndex, gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex, (gNetworkType == NT_SERVER) ? destNp->localIndex : 0);
|
||||
|
||||
network_send_to((gNetworkType == NT_SERVER) ? destNp->localIndex : 0, &p);
|
||||
|
||||
if (gNetworkType == NT_SERVER) {
|
||||
LOG_INFO("sending response from global %d to global %d", gNetworkPlayerLocal->globalIndex, destNp->globalIndex);
|
||||
}
|
||||
|
||||
network_send_to(destGlobalIndex, &p);
|
||||
}
|
||||
|
||||
void network_receive_location_response(struct Packet* p) {
|
||||
u8 destGlobalIndex;
|
||||
s16 courseNum, actNum, levelNum, areaIndex;
|
||||
packet_read(p, &destGlobalIndex, sizeof(u8));
|
||||
packet_read(p, &courseNum, sizeof(s16));
|
||||
packet_read(p, &actNum, sizeof(s16));
|
||||
packet_read(p, &levelNum, sizeof(s16));
|
||||
|
@ -204,25 +196,6 @@ void network_receive_location_response(struct Packet* p) {
|
|||
|
||||
//LOG_INFO("network_receive_location_response() { %d, %d, %d, %d, %d }", destGlobalIndex, courseNum, actNum, levelNum, areaIndex);
|
||||
|
||||
if (gNetworkType == NT_SERVER && gNetworkPlayerLocal->globalIndex != destGlobalIndex) {
|
||||
// recreate packet and send to destination
|
||||
struct Packet p2;
|
||||
packet_duplicate(p, &p2);
|
||||
|
||||
struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
|
||||
if (destNp == NULL || !destNp->connected) {
|
||||
LOG_ERROR("network_receive_location_response: dest np is invalid");
|
||||
return;
|
||||
}
|
||||
struct NetworkPlayer* srcNp = &gNetworkPlayers[p->localIndex];
|
||||
LOG_INFO("sending location response from global %d to global %d", srcNp->globalIndex, destNp->globalIndex);
|
||||
network_send_to(destNp->localIndex, &p2);
|
||||
return;
|
||||
} else if (gNetworkPlayerLocal->globalIndex != destGlobalIndex) {
|
||||
LOG_ERROR("Receiving 'location response' meant for someone else!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
|
||||
LOG_ERROR("Receiving 'location response' with the wrong location!");
|
||||
return;
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
|
||||
static u8 nextSyncID = 1;
|
||||
struct SyncObject gSyncObjects[MAX_SYNC_OBJECTS] = { 0 };
|
||||
struct Packet sLastSyncEntReliablePacket[MAX_SYNC_OBJECTS] = { 0 };
|
||||
|
||||
struct Packet* get_last_sync_ent_reliable_packet(u8 syncId) {
|
||||
return &sLastSyncEntReliablePacket[syncId];
|
||||
}
|
||||
|
||||
// todo: move this to somewhere more general
|
||||
static float player_distance(struct MarioState* marioState, struct Object* o) {
|
||||
|
@ -81,6 +86,8 @@ struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance)
|
|||
so->staticLevelSpawn = false;
|
||||
memset(so->extraFields, 0, sizeof(void*) * MAX_SYNC_OBJECT_FIELDS);
|
||||
|
||||
sLastSyncEntReliablePacket[o->oSyncID].error = true;
|
||||
|
||||
return so;
|
||||
}
|
||||
|
||||
|
@ -403,6 +410,9 @@ void network_send_object_reliability(struct Object* o, bool reliable) {
|
|||
// check for object death
|
||||
if (o->activeFlags == ACTIVE_FLAG_DEACTIVATED) {
|
||||
network_forget_sync_object(so);
|
||||
} else {
|
||||
// remember packet
|
||||
packet_duplicate(&p, &sLastSyncEntReliablePacket[o->oSyncID]);
|
||||
}
|
||||
|
||||
// send the packet out
|
||||
|
@ -444,6 +454,9 @@ void network_receive_object(struct Packet* p) {
|
|||
// deactivated
|
||||
if (o->activeFlags == ACTIVE_FLAG_DEACTIVATED) {
|
||||
network_forget_sync_object(so);
|
||||
} else if (p->reliable) {
|
||||
// remember packet
|
||||
packet_duplicate(p, &sLastSyncEntReliablePacket[o->oSyncID]);
|
||||
}
|
||||
|
||||
// trigger on-received callback
|
||||
|
@ -467,6 +480,7 @@ void network_receive_object(struct Packet* p) {
|
|||
for (int j = 0; j < 3; j++) { gMarioStates[i].pos[j] += deltaPos[j]; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void network_forget_sync_object(struct SyncObject* so) {
|
||||
|
@ -475,6 +489,7 @@ void network_forget_sync_object(struct SyncObject* so) {
|
|||
struct SyncObject* so2 = &gSyncObjects[syncId];
|
||||
if (so == so2) {
|
||||
static_spawn_removal_remember(syncId);
|
||||
sLastSyncEntReliablePacket[syncId].error = true;
|
||||
}
|
||||
}
|
||||
so->o = NULL;
|
||||
|
@ -482,6 +497,7 @@ void network_forget_sync_object(struct SyncObject* so) {
|
|||
so->reserved = 0;
|
||||
so->owned = false;
|
||||
so->staticLevelSpawn = false;
|
||||
|
||||
}
|
||||
|
||||
void network_update_objects(void) {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#include "../network.h"
|
||||
#include "game/area.h"
|
||||
|
||||
#define PACKET_FLAG_BUFFER_OFFSET 3
|
||||
#define PACKET_FLAG_BUFFER_OFFSET 3
|
||||
#define PACKET_DESTINATION_BUFFER_OFFSET 4
|
||||
|
||||
static u16 nextSeqNum = 1;
|
||||
void packet_init(struct Packet* packet, enum PacketType packetType, bool reliable, bool levelAreaMustMatch) {
|
||||
|
@ -15,6 +16,8 @@ void packet_init(struct Packet* packet, enum PacketType packetType, bool reliabl
|
|||
packet->sent = false;
|
||||
|
||||
packet_write(packet, &packetType, sizeof(u8));
|
||||
|
||||
// write seq number
|
||||
if (reliable) {
|
||||
packet_write(packet, &nextSeqNum, sizeof(u16));
|
||||
packet->seqId = nextSeqNum;
|
||||
|
@ -30,6 +33,11 @@ void packet_init(struct Packet* packet, enum PacketType packetType, bool reliabl
|
|||
packet_write(packet, &flags, sizeof(u8)); // fill in the byte
|
||||
packet_set_flags(packet);
|
||||
|
||||
// write destination
|
||||
u8 destination = PACKET_DESTINATION_BROADCAST;
|
||||
packet_write(packet, &destination, sizeof(u8));
|
||||
|
||||
// write location
|
||||
if (levelAreaMustMatch) {
|
||||
packet_write(packet, &gCurrCourseNum, sizeof(s16));
|
||||
packet_write(packet, &gCurrActNum, sizeof(s16));
|
||||
|
@ -46,6 +54,7 @@ void packet_duplicate(struct Packet* srcPacket, struct Packet* dstPacket) {
|
|||
dstPacket->reliable = srcPacket->reliable;
|
||||
dstPacket->levelAreaMustMatch = srcPacket->levelAreaMustMatch;
|
||||
dstPacket->requestBroadcast = srcPacket->requestBroadcast;
|
||||
dstPacket->destGlobalId = srcPacket->destGlobalId;
|
||||
dstPacket->sent = false;
|
||||
|
||||
memcpy(&dstPacket->buffer[0], &srcPacket->buffer[0], srcPacket->dataLength);
|
||||
|
@ -64,15 +73,19 @@ void packet_duplicate(struct Packet* srcPacket, struct Packet* dstPacket) {
|
|||
void packet_set_flags(struct Packet* packet) {
|
||||
u8 flags = 0;
|
||||
flags |= SET_BIT(packet->levelAreaMustMatch, 0);
|
||||
flags |= SET_BIT(packet->requestBroadcast, 1);
|
||||
flags |= SET_BIT(packet->requestBroadcast, 1);
|
||||
packet->buffer[PACKET_FLAG_BUFFER_OFFSET] = flags;
|
||||
}
|
||||
|
||||
void packet_set_destination(struct Packet* packet, u8 destGlobalId) {
|
||||
packet->buffer[PACKET_DESTINATION_BUFFER_OFFSET] = destGlobalId;
|
||||
}
|
||||
|
||||
void packet_write(struct Packet* packet, void* data, u16 length) {
|
||||
if (data == NULL) { packet->error = true; return; }
|
||||
memcpy(&packet->buffer[packet->cursor], data, length);
|
||||
packet->dataLength += length;
|
||||
packet->cursor += length;
|
||||
packet->cursor += length;
|
||||
}
|
||||
|
||||
u8 packet_initial_read(struct Packet* packet) {
|
||||
|
@ -80,7 +93,10 @@ 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);
|
||||
packet->requestBroadcast = GET_BIT(flags, 1);
|
||||
|
||||
// read destination
|
||||
packet_read(packet, &packet->destGlobalId, sizeof(u8));
|
||||
|
||||
if (packet->levelAreaMustMatch) {
|
||||
s16 currCourseNum, currActNum, currLevelNum, currAreaIndex;
|
||||
|
|
Loading…
Reference in a new issue