From 050d940d53f0dad146ab6286093ab37f0fd3303d Mon Sep 17 00:00:00 2001 From: MysterD Date: Mon, 7 Jun 2021 23:12:17 -0700 Subject: [PATCH] Added ability for clients to send packets to each other skipping server Added memory of last reliable packet about each sync object --- src/pc/network/network.c | 10 +++ src/pc/network/packets/packet.c | 68 ++++++++++--------- src/pc/network/packets/packet.h | 4 ++ src/pc/network/packets/packet_chat.c | 1 - src/pc/network/packets/packet_level_area.c | 2 +- .../network/packets/packet_location_request.c | 29 +------- src/pc/network/packets/packet_object.c | 16 +++++ src/pc/network/packets/packet_read_write.c | 24 +++++-- 8 files changed, 89 insertions(+), 65 deletions(-) diff --git a/src/pc/network/network.c b/src/pc/network/network.c index becb61d7c..2a9b14a3d 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -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; } diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c index 2ff2e1143..8e4c4e6c4 100644 --- a/src/pc/network/packets/packet.c +++ b/src/pc/network/packets/packet.c @@ -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 diff --git a/src/pc/network/packets/packet.h b/src/pc/network/packets/packet.h index 0e0063de6..935bf08c8 100644 --- a/src/pc/network/packets/packet.h +++ b/src/pc/network/packets/packet.h @@ -8,6 +8,7 @@ #include #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); diff --git a/src/pc/network/packets/packet_chat.c b/src/pc/network/packets/packet_chat.c index 487b56e78..39b086c68 100644 --- a/src/pc/network/packets/packet_chat.c +++ b/src/pc/network/packets/packet_chat.c @@ -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(); diff --git a/src/pc/network/packets/packet_level_area.c b/src/pc/network/packets/packet_level_area.c index cd6d6c446..5d94637cc 100644 --- a/src/pc/network/packets/packet_level_area.c +++ b/src/pc/network/packets/packet_level_area.c @@ -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) { diff --git a/src/pc/network/packets/packet_location_request.c b/src/pc/network/packets/packet_location_request.c index 2866123de..882db2ca3 100644 --- a/src/pc/network/packets/packet_location_request.c +++ b/src/pc/network/packets/packet_location_request.c @@ -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; diff --git a/src/pc/network/packets/packet_object.c b/src/pc/network/packets/packet_object.c index 58cad7f00..72c71050d 100644 --- a/src/pc/network/packets/packet_object.c +++ b/src/pc/network/packets/packet_object.c @@ -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) { diff --git a/src/pc/network/packets/packet_read_write.c b/src/pc/network/packets/packet_read_write.c index 707ae0328..c44878048 100644 --- a/src/pc/network/packets/packet_read_write.c +++ b/src/pc/network/packets/packet_read_write.c @@ -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;