mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-05-31 13:11:07 +00:00
Merge 04e5916c4b into 23d8a7370a
This commit is contained in:
commit
c111356639
3 changed files with 181 additions and 2 deletions
158
src/pc/network/badnet.c
Normal file
158
src/pc/network/badnet.c
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
#include "badnet.h"
|
||||
|
||||
#include "socket/socket.h"
|
||||
#include "pc/utils/misc.h"
|
||||
|
||||
/*
|
||||
|
||||
Bad Net is a tool for simulating a bad network connection.
|
||||
|
||||
It wraps gNetworkSystemSocket and manipulates out-going packets
|
||||
to recreate the same types of issues caused by an internet connection;
|
||||
all from the comfort of your direct connection over localhost.
|
||||
|
||||
*/
|
||||
|
||||
struct DelayedPacket {
|
||||
u8 localIndex;
|
||||
u8* data;
|
||||
u16 dataLength;
|
||||
f64 time;
|
||||
struct DelayedPacket* next;
|
||||
};
|
||||
|
||||
// Requires reconnection
|
||||
// Set to `true` to wrap gNetworkSystemSocket
|
||||
bool gBadNetEnabled = false;
|
||||
|
||||
// Time in seconds for round trip
|
||||
// 0.1 -> Good
|
||||
// 0.2 -> Common
|
||||
// 0.3 -> Across the sea
|
||||
// 1.0 -> Too slow!
|
||||
f64 gBadNetLatency = 0.0;
|
||||
|
||||
//Add an additional random delay to packets (Can cause out of order packets)
|
||||
// 0.0 -> No Jitter
|
||||
// 0.5 -> Extra 0 to 500ms extra delay.
|
||||
f64 gBadNetLatencyJitter = 0.0;
|
||||
|
||||
// Randomly drop packets
|
||||
// 0.0 -> No Packets Lost
|
||||
// 1.0 -> All Packets Lost
|
||||
f64 gBadNetPacketLoss = 0.0;
|
||||
|
||||
// Chance of packet being sent again. (Warning: This stacks! Use small values)
|
||||
// 0.0 -> No duplication
|
||||
// 0.1 -> Every packet has a 10% chance of
|
||||
// 1.0 -> :Skull:
|
||||
f64 gBadNetPacketDuplicate = 0.0;
|
||||
|
||||
struct NetworkSystem *gNetworkSystemBadNetWraps = &gNetworkSystemSocket;
|
||||
|
||||
struct DelayedPacket* delayedPackets = NULL;
|
||||
|
||||
static bool ns_badnet_initialize(enum NetworkType networkType, bool reconnecting) {
|
||||
return gNetworkSystemBadNetWraps->initialize(networkType, reconnecting);
|
||||
}
|
||||
|
||||
static s64 ns_badnet_get_id(u8 localId) {
|
||||
return gNetworkSystemBadNetWraps->get_id(localId);
|
||||
}
|
||||
|
||||
static char* ns_badnet_get_id_str(u8 localId) {
|
||||
return gNetworkSystemBadNetWraps->get_id_str(localId);
|
||||
}
|
||||
|
||||
static void ns_badnet_save_id(u8 localId, s64 networkId) {
|
||||
gNetworkSystemBadNetWraps->save_id(localId, networkId);
|
||||
}
|
||||
|
||||
static void ns_badnet_clear_id(u8 localId) {
|
||||
gNetworkSystemBadNetWraps->clear_id(localId);
|
||||
}
|
||||
|
||||
static void* ns_badnet_dup_addr(u8 localIndex) {
|
||||
return gNetworkSystemBadNetWraps->dup_addr(localIndex);
|
||||
}
|
||||
|
||||
static bool ns_badnet_match_addr(void* addr1, void* addr2) {
|
||||
return gNetworkSystemBadNetWraps->match_addr(addr1, addr2);
|
||||
}
|
||||
|
||||
static void ns_badnet_update(void) {
|
||||
struct DelayedPacket* prev = NULL;
|
||||
struct DelayedPacket* p = delayedPackets;
|
||||
while(p) {
|
||||
struct DelayedPacket *next = p->next;
|
||||
if (clock_elapsed_f64() > p->time) {
|
||||
gNetworkSystemBadNetWraps->send(
|
||||
p->localIndex,
|
||||
gNetworkSystemBadNetWraps->dup_addr(p->localIndex),
|
||||
p->data,
|
||||
p->dataLength
|
||||
);
|
||||
free(p->data);
|
||||
free(p);
|
||||
if (prev) {
|
||||
prev->next = next;
|
||||
} else {
|
||||
delayedPackets = next;
|
||||
}
|
||||
} else {
|
||||
prev = p;
|
||||
}
|
||||
p = next;
|
||||
}
|
||||
|
||||
gNetworkSystemBadNetWraps->update();
|
||||
}
|
||||
|
||||
static f64 random_f64() {
|
||||
return (float)rand()/(float)RAND_MAX;
|
||||
}
|
||||
|
||||
static int ns_badnet_send(u8 localIndex, UNUSED void* address, u8* data, u16 dataLength) {
|
||||
if (random_f64() > gBadNetPacketLoss) {
|
||||
do {
|
||||
struct DelayedPacket* p = malloc(sizeof(struct DelayedPacket));
|
||||
p->localIndex = localIndex;
|
||||
p->data = calloc(dataLength, sizeof(u8));
|
||||
memcpy(p->data, data, dataLength);
|
||||
p->dataLength = dataLength;
|
||||
p->time = clock_elapsed_f64() + (gBadNetLatency + gBadNetLatencyJitter * random_f64()) * 0.5;
|
||||
p->next = delayedPackets;
|
||||
delayedPackets = p;
|
||||
} while (random_f64() < gBadNetPacketDuplicate);
|
||||
}
|
||||
return dataLength;
|
||||
}
|
||||
|
||||
static void ns_badnet_get_lobby_id(char* destination, u32 destLength) {
|
||||
gNetworkSystemBadNetWraps->get_lobby_id(destination, destLength);
|
||||
}
|
||||
|
||||
static void ns_badnet_get_lobby_secret(char* destination, u32 destLength) {
|
||||
gNetworkSystemBadNetWraps->get_lobby_secret(destination, destLength);
|
||||
}
|
||||
|
||||
static void ns_badnet_shutdown(bool reconnecting) {
|
||||
gNetworkSystemBadNetWraps->shutdown(reconnecting);
|
||||
}
|
||||
|
||||
struct NetworkSystem gNetworkSystemBadNet = {
|
||||
.initialize = ns_badnet_initialize,
|
||||
.get_id = ns_badnet_get_id,
|
||||
.get_id_str = ns_badnet_get_id_str,
|
||||
.save_id = ns_badnet_save_id,
|
||||
.clear_id = ns_badnet_clear_id,
|
||||
.dup_addr = ns_badnet_dup_addr,
|
||||
.match_addr = ns_badnet_match_addr,
|
||||
.update = ns_badnet_update,
|
||||
.send = ns_badnet_send,
|
||||
.get_lobby_id = ns_badnet_get_lobby_id,
|
||||
.get_lobby_secret = ns_badnet_get_lobby_secret,
|
||||
.shutdown = ns_badnet_shutdown,
|
||||
.requireServerBroadcast = true,
|
||||
.name = "BadNet",
|
||||
};
|
||||
13
src/pc/network/badnet.h
Normal file
13
src/pc/network/badnet.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef BADNET_H
|
||||
#define BADNET_H
|
||||
|
||||
#include <PR/ultratypes.h>
|
||||
|
||||
extern bool gBadNetEnabled;
|
||||
extern f64 gBadNetLatency;
|
||||
extern f64 gBadNetLatencyJitter;
|
||||
extern f64 gBadNetPacketLoss;
|
||||
extern f64 gBadNetPacketDuplicate;
|
||||
extern struct NetworkSystem gNetworkSystemBadNet;
|
||||
|
||||
#endif
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
#include "coopnet/coopnet.h"
|
||||
#include <stdio.h>
|
||||
#include "network.h"
|
||||
|
||||
#include "badnet.h"
|
||||
#include "object_fields.h"
|
||||
#include "game/level_update.h"
|
||||
#include "object_constants.h"
|
||||
|
|
@ -100,7 +102,13 @@ void network_set_system(enum NetworkSystemType nsType) {
|
|||
network_forget_all_reliable();
|
||||
|
||||
switch (nsType) {
|
||||
case NS_SOCKET: gNetworkSystem = &gNetworkSystemSocket; break;
|
||||
case NS_SOCKET:
|
||||
if (gBadNetEnabled) {
|
||||
gNetworkSystem = &gNetworkSystemBadNet;
|
||||
} else {
|
||||
gNetworkSystem = &gNetworkSystemSocket;
|
||||
}
|
||||
break;
|
||||
#ifdef COOPNET
|
||||
case NS_COOPNET: gNetworkSystem = &gNetworkSystemCoopNet; break;
|
||||
#endif
|
||||
|
|
@ -645,7 +653,7 @@ static inline void color_set(Color color, u8 r, u8 g, u8 b) {
|
|||
}
|
||||
|
||||
bool network_allow_mod_dev_mode(void) {
|
||||
return (configModDevMode && gNetworkSystem == &gNetworkSystemSocket && gNetworkType == NT_SERVER);
|
||||
return (configModDevMode && gNetworkSystem != &gNetworkSystemCoopNet && gNetworkType == NT_SERVER);
|
||||
}
|
||||
|
||||
void network_mod_dev_mode_reload(void) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue