mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-10-30 08:01:01 +00:00
Standardized de-duplication of reliable packets
This commit is contained in:
parent
5d9d5ed9d7
commit
c214800faf
12 changed files with 24 additions and 133 deletions
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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[];
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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, ¶ms, 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, ¶ms, 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) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue