Standardized de-duplication of reliable packets

This commit is contained in:
MysterD 2020-10-12 18:40:38 -07:00
parent 5d9d5ed9d7
commit c214800faf
12 changed files with 24 additions and 133 deletions

View file

@ -37,5 +37,5 @@ $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'
$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

@ -68,6 +68,7 @@ void network_player_update(void) {
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) {
if (type == NPT_LOCAL) {
memset(&gNetworkPlayers[0], 0, sizeof(struct NetworkPlayer));
gNetworkPlayers[0].connected = true;
gNetworkPlayers[0].type = type;
gNetworkPlayers[0].localIndex = 0;
@ -92,6 +93,7 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) {
for (int i = 1; i < MAX_PLAYERS; i++) {
struct NetworkPlayer* np = &gNetworkPlayers[i];
if (np->connected) { continue; }
memset(np, 0, sizeof(struct NetworkPlayer));
np->connected = true;
np->currLevelNum = -1;
np->currAreaIndex = -1;

View file

@ -8,6 +8,7 @@
#define UNKNOWN_GLOBAL_INDEX ((u8)-1)
#define UNKNOWN_NETWORK_INDEX ((u64)-1)
#define NETWORK_PLAYER_TIMEOUT 10
#define MAX_RX_SEQ_IDS 16
enum NetworkPlayerType {
NPT_UNKNOWN,
@ -25,6 +26,8 @@ struct NetworkPlayer {
s16 currLevelNum;
s16 currAreaIndex;
u8 fadeOpacity;
u16 rxSeqIds[MAX_RX_SEQ_IDS];
u8 onRxSeqId;
};
extern struct NetworkPlayer gNetworkPlayers[];

View file

@ -14,6 +14,21 @@ void packet_receive(struct Packet* p) {
// send an ACK if requested
network_send_ack(p);
// check if we've already seen this packet
if (p->localIndex != 0 && p->seqId != 0 && gNetworkPlayers[p->localIndex].connected) {
struct NetworkPlayer* np = &gNetworkPlayers[p->localIndex];
for (int i = 0; i < MAX_RX_SEQ_IDS; i++) {
if (np->rxSeqIds[i] == p->seqId) {
LOG_INFO("received duplicate packet");
return;
}
}
// remember seq id
np->rxSeqIds[np->onRxSeqId] = p->seqId;
np->onRxSeqId++;
if (np->onRxSeqId >= MAX_RX_SEQ_IDS) { np->onRxSeqId = 0; }
}
// check if we should drop packet
if (!packet_initial_read(p)) { LOG_ERROR("initial read failed (%d - %d)", packetType, p->levelAreaMustMatch); return; }
@ -50,6 +65,7 @@ void packet_receive(struct Packet* p) {
if (gNetworkType == NT_SERVER && gNetworkSystem->requireServerBroadcast) {
for (int i = 1; i < MAX_PLAYERS; i++) {
if (!gNetworkPlayers[i].connected) { continue; }
if (i == p->localIndex) { continue; }
struct Packet p2 = { 0 };
packet_init(&p2, packetType, p->reliable, p->levelAreaMustMatch);
packet_write(&p2, &p->buffer[p2.cursor], p->cursor - p2.cursor);

View file

@ -2,50 +2,23 @@
#include "../network.h"
#include "game/chat.h"
static u8 localChatId = 1;
// two-player hack: the remoteChatIds stuff is only valid for the one remote player
// will need to be extended if MAX_PLAYERS is ever increased
#define MAX_CHAT_IDS 16
static u8 remoteChatIds[MAX_CHAT_IDS] = { 0 };
static u8 onRemoteChatId = 0;
void network_send_chat(char* message) {
u16 messageLength = strlen(message);
struct Packet p;
packet_init(&p, PACKET_CHAT, true, false);
packet_write(&p, &localChatId, sizeof(u8));
packet_write(&p, &messageLength, sizeof(u16));
packet_write(&p, message, messageLength * sizeof(u8));
network_send(&p);
localChatId++;
}
void network_receive_chat(struct Packet* p) {
u8 remoteChatId = 0;
u16 remoteMessageLength = 0;
char remoteMessage[255] = { 0 };
packet_read(p, &remoteChatId, sizeof(u8));
packet_read(p, &remoteMessageLength, sizeof(u16));
if (remoteMessageLength > 255) { remoteMessageLength = 254; }
packet_read(p, &remoteMessage, remoteMessageLength * sizeof(u8));
// check if remote chat id has already been seen
for (u16 i = 0; i < MAX_CHAT_IDS; i++) {
if (remoteChatIds[i] == remoteChatId) {
// we already saw this message!
return;
}
}
// cache the seen id
remoteChatIds[onRemoteChatId] = remoteChatId;
onRemoteChatId = (onRemoteChatId + 1) % MAX_CHAT_IDS;
// add the message
chat_add_message(remoteMessage, CMT_REMOTE);
return;
}

View file

@ -12,14 +12,6 @@
// defined in sparkle_spawn_star.inc.c
void bhv_spawn_star_no_level_exit(struct Object* object, u32 sp20, u8 networkSendEvent);
static u8 localCoinId = 1;
// two-player hack: the remoteCoinId stuff is only valid for the one remote player
// will need to be extended if MAX_PLAYERS is ever increased
#define MAX_REMOTE_COIN_IDS 16
static u8 remoteCoinIds[MAX_REMOTE_COIN_IDS] = { 0 };
static u8 onRemoteCoinId = 0;
static f32 dist_to_pos(struct Object* o, f32* pos) {
f32 x = o->oPosX - pos[0]; x *= x;
f32 y = o->oPosY - pos[1]; y *= y;
@ -56,24 +48,20 @@ void network_send_collect_coin(struct Object* o) {
struct Packet p;
packet_init(&p, PACKET_COLLECT_COIN, true, true);
packet_write(&p, &localCoinId, sizeof(u8));
packet_write(&p, &behaviorId, sizeof(enum BehaviorId));
packet_write(&p, &o->oPosX, sizeof(f32) * 3);
packet_write(&p, &gMarioStates[0].numCoins, sizeof(s16));
packet_write(&p, &o->oDamageOrCoinValue, sizeof(s32));
network_send(&p);
localCoinId++;
}
void network_receive_collect_coin(struct Packet* p) {
u8 remoteCoinId = 0;
enum BehaviorId behaviorId;
f32 pos[3] = { 0 };
s16 numCoins = 0;
s32 coinValue = 0;
packet_read(p, &remoteCoinId, sizeof(u8));
packet_read(p, &behaviorId, sizeof(enum BehaviorId));
packet_read(p, &pos, sizeof(f32) * 3);
packet_read(p, &numCoins, sizeof(s16));
@ -81,17 +69,6 @@ void network_receive_collect_coin(struct Packet* p) {
const void* behavior = get_behavior_from_id(behaviorId);
// check if remote coin id has already been seen
for (u16 i = 0; i < MAX_REMOTE_COIN_IDS; i++) {
if (remoteCoinIds[i] == remoteCoinId) {
// we already saw this coin!
goto SANITY_CHECK_COINS;
}
}
// cache the seen id
remoteCoinIds[onRemoteCoinId] = remoteCoinId;
onRemoteCoinId = (onRemoteCoinId + 1) % MAX_REMOTE_COIN_IDS;
// make sure it's valid
if (behavior == NULL) { goto SANITY_CHECK_COINS; }

View file

@ -9,14 +9,6 @@
#include "src/game/memory.h"
#include "src/game/object_helpers.h"
static u8 localItemId = 1;
// two-player hack: the remoteItemId stuff is only valid for the one remote player
// will need to be extended if MAX_PLAYERS is ever increased
#define MAX_REMOTE_ITEM_IDS 16
static u8 remoteItemIds[MAX_REMOTE_ITEM_IDS] = { 0 };
static u8 onRemoteItemId = 0;
static f32 dist_to_pos(struct Object* o, f32* pos) {
f32 x = o->oPosX - pos[0]; x *= x;
f32 y = o->oPosY - pos[1]; y *= y;
@ -53,36 +45,21 @@ void network_send_collect_item(struct Object* o) {
struct Packet p;
packet_init(&p, PACKET_COLLECT_ITEM, true, true);
packet_write(&p, &localItemId, sizeof(u8));
packet_write(&p, &behaviorId, sizeof(enum BehaviorId));
packet_write(&p, &o->oPosX, sizeof(f32) * 3);
network_send(&p);
localItemId++;
}
void network_receive_collect_item(struct Packet* p) {
u8 remoteItemId = 0;
enum BehaviorId behaviorId;
f32 pos[3] = { 0 };
packet_read(p, &remoteItemId, sizeof(u8));
packet_read(p, &behaviorId, sizeof(enum BehaviorId));
packet_read(p, &pos, sizeof(f32) * 3);
const void* behavior = get_behavior_from_id(behaviorId);
// check if remote item id has already been seen
for (u16 i = 0; i < MAX_REMOTE_ITEM_IDS; i++) {
if (remoteItemIds[i] == remoteItemId) {
// we already saw this item!
return;
}
}
// cache the seen id
remoteItemIds[onRemoteItemId] = remoteItemId;
onRemoteItemId = (onRemoteItemId + 1) % MAX_REMOTE_ITEM_IDS;
// make sure it's valid
if (behavior == NULL) { return; }

View file

@ -14,17 +14,12 @@ extern s8 sReceivedLoadedActNum;
#pragma pack(1)
struct PacketInsidePaintingData {
u8 seqId;
u8 starIndex;
u8 actIndex;
u8 loadedActNum;
};
static u8 seqId = 0;
static u8 remoteLastSeqId = (u8)-1;
static void populate_packet_data(struct PacketInsidePaintingData* data) {
data->seqId = seqId;
data->starIndex = sSelectableStarIndex;
data->actIndex = sSelectedActIndex;
data->loadedActNum = sLoadedActNum;
@ -38,7 +33,6 @@ void network_send_inside_painting(void) {
packet_init(&p, PACKET_INSIDE_PAINTING, true, false);
packet_write(&p, &data, sizeof(struct PacketInsidePaintingData));
network_send(&p);
seqId++;
}
void network_receive_inside_painting(struct Packet* p) {
@ -48,13 +42,6 @@ void network_receive_inside_painting(struct Packet* p) {
struct PacketInsidePaintingData remote = { 0 };
packet_read(p, &remote, sizeof(struct PacketInsidePaintingData));
// de-dup
if (remote.seqId == remoteLastSeqId) {
LOG_INFO("we've seen this packet, escape!");
return;
}
remoteLastSeqId = remote.seqId;
// two-player hack: gControlledWarp is a bool instead of an index
if (gControlledWarp) {
LOG_ERROR("this should never happen, received inside_painting when gControlledWarp");

View file

@ -11,19 +11,14 @@
extern u8 gRejectInstantWarp;
static u8 seqId = 0;
static u8 remoteLastSeqId = (u8)-1;
#pragma pack(1)
struct PacketInstantWarpData {
u8 seqId;
Vec3f pos;
s16 areaIndex;
s16 yaw;
};
static void populate_packet_data(struct PacketInstantWarpData* data) {
data->seqId = seqId;
data->pos[0] = gMarioStates[0].pos[0];
data->pos[1] = gMarioStates[0].pos[1];
data->pos[2] = gMarioStates[0].pos[2];
@ -43,21 +38,12 @@ void network_send_instant_warp(void) {
LOG_INFO("tx %d", data.areaIndex);
gRejectInstantWarp = 120;
seqId++;
}
void network_receive_instant_warp(struct Packet* p) {
struct PacketInstantWarpData remote = { 0 };
packet_read(p, &remote, sizeof(struct PacketInstantWarpData));
// de-dup
if (remote.seqId == remoteLastSeqId) {
LOG_INFO("we've seen this packet, escape!");
return;
}
remoteLastSeqId = remote.seqId;
LOG_INFO("rx instant warp");
if (gCurrAreaIndex == remote.areaIndex) {

View file

@ -10,9 +10,6 @@
static u8 eventId = 0;
static u8 remoteFinishedEventId[2] = { (u8)-1, (u8)-1 };
static u8 seqId = 0;
static u8 remoteLastSeqId = (u8)-1;
extern s16 gTTCSpeedSetting;
extern s16 D_80339EE0;
extern float gPaintingMarioYEntry;
@ -26,7 +23,6 @@ static bool isInWarp = FALSE;
#pragma pack(1)
struct PacketLevelWarpData {
u8 seqId;
u8 eventId;
u8 done;
u8 controlledWarp;
@ -38,7 +34,6 @@ struct PacketLevelWarpData {
};
static void populate_packet_data(struct PacketLevelWarpData* data, bool done, u8 packetEventId) {
data->seqId = seqId;
data->eventId = packetEventId;
data->done = done;
data->controlledWarp = gControlledWarp;
@ -73,8 +68,6 @@ void network_send_level_warp_begin(void) {
packet_init(&p, PACKET_LEVEL_WARP, true, false);
packet_write(&p, &data, sizeof(struct PacketLevelWarpData));
network_send(&p);
seqId++;
}
void network_send_level_warp_repeat(void) {
@ -91,8 +84,6 @@ void network_send_level_warp_repeat(void) {
packet_init(&p, PACKET_LEVEL_WARP, false, false);
packet_write(&p, &data, sizeof(struct PacketLevelWarpData));
network_send(&p);
seqId++;
}
static void network_send_level_warp_done(u8 remoteEventId) {
@ -106,8 +97,6 @@ static void network_send_level_warp_done(u8 remoteEventId) {
packet_init(&p, PACKET_LEVEL_WARP, true, false);
packet_write(&p, &data, sizeof(struct PacketLevelWarpData));
network_send(&p);
seqId++;
}
static void do_warp(void) {
@ -124,13 +113,6 @@ void network_receive_level_warp(struct Packet* p) {
struct PacketLevelWarpData remote = { 0 };
packet_read(p, &remote, sizeof(struct PacketLevelWarpData));
// de-dup
if (remote.seqId == remoteLastSeqId) {
LOG_INFO("we've seen this packet, escape!");
return;
}
remoteLastSeqId = remote.seqId;
LOG_INFO("rx event [%d] last [%d, %d]", remote.eventId, remoteFinishedEventId[0], remoteFinishedEventId[1]);
if (remote.done && remote.eventId != eventId) {

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->seqId = seqId;
p->reliable = (seqId != 0);
if (seqId == 0) { return; }

View file

@ -7,9 +7,6 @@
extern struct Object* gCurrentObject;
static u8 txSeqId = 0;
static u8 rxLastSeqId = (u8)-1;
void network_send_spawn_star(struct Object* o, u8 starType, f32 x, f32 y, f32 z, u32 behParams) {
struct Packet p;
packet_init(&p, PACKET_SPAWN_STAR, true, true);
@ -62,32 +59,22 @@ void network_send_spawn_star_nle(struct Object* o, u32 params) {
struct Packet p;
packet_init(&p, PACKET_SPAWN_STAR_NLE, true, true);
packet_write(&p, &txSeqId, sizeof(u8));
packet_write(&p, &globalIndex, sizeof(u8));
packet_write(&p, &o->oSyncID, sizeof(u32));
packet_write(&p, &params, sizeof(u32));
network_send(&p);
txSeqId++;
}
void network_receive_spawn_star_nle(struct Packet* p) {
u8 seqId = 0;
u8 globalIndex = UNKNOWN_GLOBAL_INDEX;
u32 syncId = 0;
u32 params = 0;
packet_read(p, &seqId, sizeof(u8));
packet_read(p, &globalIndex, sizeof(u8));
packet_read(p, &syncId, sizeof(u32));
packet_read(p, &params, sizeof(u32));
// de-dup
if (seqId == rxLastSeqId) {
LOG_INFO("Already seen seqId %d", seqId);
return;
}
// grab network player first
struct Object* object = NULL;
if (globalIndex != UNKNOWN_GLOBAL_INDEX) {