From b596cb2af28e12c15d048a9a19b4417691e3409c Mon Sep 17 00:00:00 2001 From: MysterD Date: Mon, 27 Mar 2023 11:50:32 -0700 Subject: [PATCH] Figure out a ping between every player, adjust resend rate based on it --- autogen/convert_structs.py | 5 ++- autogen/lua_definitions/constants.lua | 5 ++- autogen/lua_definitions/structs.lua | 4 ++ docs/lua/constants.md | 1 + docs/lua/structs.md | 4 ++ src/pc/lua/smlua_cobject_autogen.c | 12 ++--- src/pc/lua/smlua_constants_autogen.c | 3 +- src/pc/network/network_player.c | 11 +++++ src/pc/network/network_player.h | 3 ++ src/pc/network/packets/packet.c | 3 ++ src/pc/network/packets/packet.h | 9 +++- src/pc/network/packets/packet_ping.c | 56 ++++++++++++++++++++++++ src/pc/network/packets/packet_reliable.c | 12 ++++- 13 files changed, 115 insertions(+), 13 deletions(-) create mode 100644 src/pc/network/packets/packet_ping.c diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index da9e36d10..48399509a 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -86,11 +86,12 @@ override_field_immutable = { "GlobalObjectAnimations": [ "*"], "SpawnParticlesInfo": [ "model" ], "MarioBodyState": [ "updateTorsoTime" ], - "Area": [ "localAreaTimer" ], + "Area": [ "localAreaTimer", "nextSyncID" ], "Mod": [ "*" ], "ModFile": [ "*" ], "BassAudio": [ "*" ], - "Painting": [ "id", "imageCount", "textureType", "textureWidth", "textureHeight" ] + "Painting": [ "id", "imageCount", "textureType", "textureWidth", "textureHeight" ], + "SpawnInfo": [ "syncID" ] } override_allowed_structs = { diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index c5fb69032..fcba5c37d 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -4740,6 +4740,9 @@ PLAYER_INTERACTIONS_PVP = 2 --- @type integer MAX_RX_SEQ_IDS = 64 +--- @type integer +NETWORK_PLAYER_PING_TIMEOUT = 3 + --- @type integer NETWORK_PLAYER_TIMEOUT = 10 @@ -11516,7 +11519,7 @@ MAX_VERSION_LENGTH = 10 MINOR_VERSION_NUMBER = 0 --- @type integer -PATCH_VERSION_NUMBER = 1 +PATCH_VERSION_NUMBER = 3 --- @type integer VERSION_NUMBER = 32 diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 4666739a2..2b4596022 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -34,6 +34,7 @@ --- @field public macroObjectsAltered Pointer_integer --- @field public musicParam integer --- @field public musicParam2 integer +--- @field public nextSyncID integer --- @field public numRedCoins integer --- @field public numSecrets integer --- @field public objectSpawnInfos SpawnInfo @@ -821,6 +822,7 @@ --- @field public descriptionR integer --- @field public fadeOpacity integer --- @field public globalIndex integer +--- @field public lastPingSent number --- @field public lastReceived number --- @field public lastSent number --- @field public localIndex integer @@ -833,6 +835,7 @@ --- @field public overridePaletteIndexLp integer --- @field public palette PlayerPalette --- @field public paletteIndex integer +--- @field public ping integer --- @field public type integer --- @class Object @@ -1736,6 +1739,7 @@ --- @field public next SpawnInfo --- @field public startAngle Vec3s --- @field public startPos Vec3s +--- @field public syncID integer --- @field public unk18 GraphNode --- @class SpawnParticlesInfo diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 0437d7207..a9023b7f1 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -1704,6 +1704,7 @@ ## [network_player.h](#network_player.h) - MAX_RX_SEQ_IDS +- NETWORK_PLAYER_PING_TIMEOUT - NETWORK_PLAYER_TIMEOUT - UNKNOWN_GLOBAL_INDEX - UNKNOWN_LOCAL_INDEX diff --git a/docs/lua/structs.md b/docs/lua/structs.md index fa1637466..519e8ccde 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -131,6 +131,7 @@ | macroObjectsAltered | `Pointer` <`integer`> | read-only | | musicParam | `integer` | | | musicParam2 | `integer` | | +| nextSyncID | `integer` | read-only | | numRedCoins | `integer` | | | numSecrets | `integer` | | | objectSpawnInfos | [SpawnInfo](structs.md#SpawnInfo) | | @@ -1175,6 +1176,7 @@ | descriptionR | `integer` | read-only | | fadeOpacity | `integer` | read-only | | globalIndex | `integer` | read-only | +| lastPingSent | `number` | read-only | | lastReceived | `number` | read-only | | lastSent | `number` | read-only | | localIndex | `integer` | read-only | @@ -1187,6 +1189,7 @@ | overridePaletteIndexLp | `integer` | read-only | | palette | [PlayerPalette](structs.md#PlayerPalette) | read-only | | paletteIndex | `integer` | read-only | +| ping | `integer` | read-only | | type | `integer` | read-only | [:arrow_up_small:](#) @@ -2210,6 +2213,7 @@ | next | [SpawnInfo](structs.md#SpawnInfo) | | | startAngle | [Vec3s](structs.md#Vec3s) | read-only | | startPos | [Vec3s](structs.md#Vec3s) | read-only | +| syncID | `integer` | read-only | | unk18 | [GraphNode](structs.md#GraphNode) | | [:arrow_up_small:](#) diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index b5beb77a6..751a79075 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -51,10 +51,8 @@ static struct LuaObjectField sAnimationFields[LUA_ANIMATION_FIELD_COUNT] = { { "values", LVT_S16_P, offsetof(struct Animation, values), true, LOT_POINTER }, }; -#define LUA_AREA_FIELD_COUNT 17 +#define LUA_AREA_FIELD_COUNT 18 static struct LuaObjectField sAreaFields[LUA_AREA_FIELD_COUNT] = { -// { "cachedBehaviors", LOT_???, offsetof(struct Area, cachedBehaviors), false, LOT_??? }, <--- UNIMPLEMENTED -// { "cachedPositions", LOT_???, offsetof(struct Area, cachedPositions), false, LOT_??? }, <--- UNIMPLEMENTED { "camera", LVT_COBJECT_P, offsetof(struct Area, camera), false, LOT_CAMERA }, // { "dialog", LOT_???, offsetof(struct Area, dialog), false, LOT_??? }, <--- UNIMPLEMENTED { "flags", LVT_S8, offsetof(struct Area, flags), false, LOT_NONE }, @@ -65,6 +63,7 @@ static struct LuaObjectField sAreaFields[LUA_AREA_FIELD_COUNT] = { { "macroObjectsAltered", LVT_U8_P, offsetof(struct Area, macroObjectsAltered), true, LOT_POINTER }, { "musicParam", LVT_U16, offsetof(struct Area, musicParam), false, LOT_NONE }, { "musicParam2", LVT_U16, offsetof(struct Area, musicParam2), false, LOT_NONE }, + { "nextSyncID", LVT_U32, offsetof(struct Area, nextSyncID), true, LOT_NONE }, { "numRedCoins", LVT_U8, offsetof(struct Area, numRedCoins), false, LOT_NONE }, { "numSecrets", LVT_U8, offsetof(struct Area, numSecrets), false, LOT_NONE }, { "objectSpawnInfos", LVT_COBJECT_P, offsetof(struct Area, objectSpawnInfos), false, LOT_SPAWNINFO }, @@ -928,7 +927,7 @@ static struct LuaObjectField sModeTransitionInfoFields[LUA_MODE_TRANSITION_INFO_ { "transitionStart", LVT_COBJECT, offsetof(struct ModeTransitionInfo, transitionStart), true, LOT_LINEARTRANSITIONPOINT }, }; -#define LUA_NETWORK_PLAYER_FIELD_COUNT 29 +#define LUA_NETWORK_PLAYER_FIELD_COUNT 31 static struct LuaObjectField sNetworkPlayerFields[LUA_NETWORK_PLAYER_FIELD_COUNT] = { { "connected", LVT_BOOL, offsetof(struct NetworkPlayer, connected), true, LOT_NONE }, { "currActNum", LVT_S16, offsetof(struct NetworkPlayer, currActNum), true, LOT_NONE }, @@ -946,6 +945,7 @@ static struct LuaObjectField sNetworkPlayerFields[LUA_NETWORK_PLAYER_FIELD_COUNT { "descriptionR", LVT_U8, offsetof(struct NetworkPlayer, descriptionR), true, LOT_NONE }, { "fadeOpacity", LVT_U8, offsetof(struct NetworkPlayer, fadeOpacity), true, LOT_NONE }, { "globalIndex", LVT_U8, offsetof(struct NetworkPlayer, globalIndex), true, LOT_NONE }, + { "lastPingSent", LVT_F32, offsetof(struct NetworkPlayer, lastPingSent), true, LOT_NONE }, { "lastReceived", LVT_F32, offsetof(struct NetworkPlayer, lastReceived), true, LOT_NONE }, { "lastSent", LVT_F32, offsetof(struct NetworkPlayer, lastSent), true, LOT_NONE }, { "localIndex", LVT_U8, offsetof(struct NetworkPlayer, localIndex), true, LOT_NONE }, @@ -958,6 +958,7 @@ static struct LuaObjectField sNetworkPlayerFields[LUA_NETWORK_PLAYER_FIELD_COUNT { "overridePaletteIndexLp", LVT_U8, offsetof(struct NetworkPlayer, overridePaletteIndexLp), true, LOT_NONE }, { "palette", LVT_COBJECT, offsetof(struct NetworkPlayer, palette), true, LOT_PLAYERPALETTE }, { "paletteIndex", LVT_U8, offsetof(struct NetworkPlayer, paletteIndex), true, LOT_NONE }, + { "ping", LVT_U32, offsetof(struct NetworkPlayer, ping), true, LOT_NONE }, // { "rxPacketHash", LOT_???, offsetof(struct NetworkPlayer, rxPacketHash), true, LOT_??? }, <--- UNIMPLEMENTED // { "rxSeqIds", LOT_???, offsetof(struct NetworkPlayer, rxSeqIds), true, LOT_??? }, <--- UNIMPLEMENTED { "type", LVT_U8, offsetof(struct NetworkPlayer, type), true, LOT_NONE }, @@ -1907,7 +1908,7 @@ static struct LuaObjectField sSoundStateFields[LUA_SOUND_STATE_FIELD_COUNT] = { { "soundMagic", LVT_S32, offsetof(struct SoundState, soundMagic), false, LOT_NONE }, }; -#define LUA_SPAWN_INFO_FIELD_COUNT 7 +#define LUA_SPAWN_INFO_FIELD_COUNT 8 static struct LuaObjectField sSpawnInfoFields[LUA_SPAWN_INFO_FIELD_COUNT] = { { "activeAreaIndex", LVT_S8, offsetof(struct SpawnInfo, activeAreaIndex), false, LOT_NONE }, { "areaIndex", LVT_S8, offsetof(struct SpawnInfo, areaIndex), false, LOT_NONE }, @@ -1916,6 +1917,7 @@ static struct LuaObjectField sSpawnInfoFields[LUA_SPAWN_INFO_FIELD_COUNT] = { { "next", LVT_COBJECT_P, offsetof(struct SpawnInfo, next), false, LOT_SPAWNINFO }, { "startAngle", LVT_COBJECT, offsetof(struct SpawnInfo, startAngle), true, LOT_VEC3S }, { "startPos", LVT_COBJECT, offsetof(struct SpawnInfo, startPos), true, LOT_VEC3S }, + { "syncID", LVT_U32, offsetof(struct SpawnInfo, syncID), true, LOT_NONE }, { "unk18", LVT_COBJECT_P, offsetof(struct SpawnInfo, unk18), false, LOT_GRAPHNODE }, }; diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index bdca15f83..bd6732529 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -1766,6 +1766,7 @@ char gSmluaConstants[] = "" "UNKNOWN_GLOBAL_INDEX = (-1)\n" "UNKNOWN_NETWORK_INDEX = (-1)\n" "NETWORK_PLAYER_TIMEOUT = 10\n" +"NETWORK_PLAYER_PING_TIMEOUT = 3\n" "MAX_RX_SEQ_IDS = 64\n" "USE_REAL_PALETTE_VAR = 0xFF\n" "NPT_UNKNOWN = 0\n" @@ -4014,7 +4015,7 @@ char gSmluaConstants[] = "" "VERSION_TEXT = 'beta'\n" "VERSION_NUMBER = 32\n" "MINOR_VERSION_NUMBER = 0\n" -"PATCH_VERSION_NUMBER = 1\n" +"PATCH_VERSION_NUMBER = 3\n" "MAX_VERSION_LENGTH = 10\n" "MAX_LOCAL_VERSION_LENGTH = 12\n" ; \ No newline at end of file diff --git a/src/pc/network/network_player.c b/src/pc/network/network_player.c index f180cecdc..088425cd8 100644 --- a/src/pc/network/network_player.c +++ b/src/pc/network/network_player.c @@ -155,6 +155,16 @@ void network_player_update(void) { if (!network_player_any_connected()) { return; } + + for (s32 i = 1; i < MAX_PLAYERS; i++) { + struct NetworkPlayer *np = &gNetworkPlayers[i]; + if (!np->connected && i > 0) { continue; } + float elapsed = (clock_elapsed() - np->lastPingSent); + if (elapsed > NETWORK_PLAYER_PING_TIMEOUT) { + network_send_ping(np); + } + } + if (gNetworkType == NT_SERVER) { for (s32 i = 1; i < MAX_PLAYERS; i++) { struct NetworkPlayer *np = &gNetworkPlayers[i]; @@ -239,6 +249,7 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 mode np->type = type; np->localIndex = localIndex; np->globalIndex = globalIndex; + np->ping = 50; if ((type != NPT_LOCAL) && (gNetworkType == NT_SERVER || type == NPT_SERVER)) { gNetworkSystem->save_id(localIndex, 0); } network_player_set_description(np, NULL, 0, 0, 0, 0); diff --git a/src/pc/network/network_player.h b/src/pc/network/network_player.h index dbb4e3c68..6eafa4b6b 100644 --- a/src/pc/network/network_player.h +++ b/src/pc/network/network_player.h @@ -9,6 +9,7 @@ #define UNKNOWN_GLOBAL_INDEX ((u8)-1) #define UNKNOWN_NETWORK_INDEX ((u64)-1) #define NETWORK_PLAYER_TIMEOUT 10 +#define NETWORK_PLAYER_PING_TIMEOUT 3 #define MAX_RX_SEQ_IDS 64 #define USE_REAL_PALETTE_VAR 0xFF @@ -26,6 +27,7 @@ struct NetworkPlayer { u8 globalIndex; f32 lastReceived; f32 lastSent; + f32 lastPingSent; u16 currLevelAreaSeqId; s16 currCourseNum; s16 currActNum; @@ -37,6 +39,7 @@ struct NetworkPlayer { u8 fadeOpacity; u8 onRxSeqId; u8 modelIndex; + u32 ping; struct PlayerPalette palette; char name[MAX_PLAYER_STRING+1]; diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c index c8d4194a3..12c328c28 100644 --- a/src/pc/network/packets/packet.c +++ b/src/pc/network/packets/packet.c @@ -61,6 +61,9 @@ void packet_process(struct Packet* p) { case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break; case PACKET_DEATH: network_receive_death(p); break; + case PACKET_PING: network_receive_ping(p); break; + case PACKET_PONG: network_receive_pong(p); break; + // location case PACKET_CHANGE_LEVEL: network_receive_change_level(p); break; case PACKET_CHANGE_AREA: network_receive_change_area(p); break; diff --git a/src/pc/network/packets/packet.h b/src/pc/network/packets/packet.h index 605f3ccdc..03b09c19f 100644 --- a/src/pc/network/packets/packet.h +++ b/src/pc/network/packets/packet.h @@ -35,8 +35,8 @@ enum PacketType { PACKET_NETWORK_PLAYERS, PACKET_DEATH, - PACKET_UNUSED_21, - PACKET_UNUSED_22, + PACKET_PING, + PACKET_PONG, PACKET_UNUSED_23, PACKET_CHANGE_LEVEL, @@ -263,6 +263,11 @@ void network_receive_network_players(struct Packet* p); void network_send_death(void); void network_receive_death(struct Packet* p); +// packet_ping.c +void network_send_ping(struct NetworkPlayer* toNp); +void network_receive_ping(struct Packet* p); +void network_receive_pong(struct Packet* p); + // packet_change_level.c void network_send_change_level(void); void network_receive_change_level(struct Packet* p); diff --git a/src/pc/network/packets/packet_ping.c b/src/pc/network/packets/packet_ping.c new file mode 100644 index 000000000..974d5291e --- /dev/null +++ b/src/pc/network/packets/packet_ping.c @@ -0,0 +1,56 @@ +#include +#include "../network.h" +#include "pc/utils/misc.h" +#define DISABLE_MODULE_LOG 1 +#include "pc/debuglog.h" + +void network_send_ping(struct NetworkPlayer* toNp) { + struct Packet p = { 0 }; + f64 timestamp = clock_elapsed_f64(); + + toNp->lastPingSent = clock_elapsed(); + + packet_init(&p, PACKET_PING, true, PLMT_NONE); + packet_write(&p, &toNp->globalIndex, sizeof(u8)); + packet_write(&p, ×tamp, sizeof(f64)); + network_send_to(toNp->localIndex, &p); + + LOG_INFO("tx ping"); +} + +void network_receive_ping(struct Packet* p) { + LOG_INFO("rx ping"); + + u8 globalIndex; + f64 timestamp; + + packet_read(p, &globalIndex, sizeof(u8)); + packet_read(p, ×tamp, sizeof(f64)); + + struct Packet p2 = { 0 }; + packet_init(&p2, PACKET_PONG, true, PLMT_NONE); + packet_write(&p2, &globalIndex, sizeof(u8)); + packet_write(&p2, ×tamp, sizeof(f64)); + network_send_to(p->localIndex, &p2); +} + +void network_receive_pong(struct Packet* p) { + f64 now = clock_elapsed_f64(); + + u8 globalIndex; + f64 timestamp; + + packet_read(p, &globalIndex, sizeof(u8)); + packet_read(p, ×tamp, sizeof(f64)); + + struct NetworkPlayer* np = network_player_from_global_index(globalIndex); + if (np == NULL || np->localIndex == UNKNOWN_LOCAL_INDEX || !np->connected) { + LOG_ERROR("Receiving pong from inactive player!"); + return; + } + + u32 ping = (now - timestamp) * 1000; + np->ping = np->ping * 0.5f + ping * 0.5f; + if (np->ping > 1000) { np->ping = 1000; } + LOG_INFO("rx pong from %u: %u", globalIndex, ping); +} diff --git a/src/pc/network/packets/packet_reliable.c b/src/pc/network/packets/packet_reliable.c index 2f8cd91a3..45fc6849a 100644 --- a/src/pc/network/packets/packet_reliable.c +++ b/src/pc/network/packets/packet_reliable.c @@ -143,9 +143,17 @@ static float get_max_elapsed_time(int sendAttempts) { void network_update_reliable(void) { struct PacketLinkedList* node = head; while (node != NULL) { - float elapsed = (clock_elapsed() - node->lastSend); - float maxElapsed = get_max_elapsed_time(node->sendAttempts); + f32 elapsed = (clock_elapsed() - node->lastSend); + f32 maxElapsed = get_max_elapsed_time(node->sendAttempts); maxElapsed = adjust_max_elapsed(node->p.packetType, maxElapsed); + + // adjust resend time based on ping + struct NetworkPlayer* np = &gNetworkPlayers[node->p.localIndex]; + f32 pingElapsed = np->ping / 1000.0f; + if (pingElapsed > 1.0f) { pingElapsed = 1.0f; } + pingElapsed *= 1.1f; + if (maxElapsed < pingElapsed) { maxElapsed = pingElapsed; } + if (elapsed > maxElapsed) { if (node->p.packetType == PACKET_JOIN_REQUEST && gNetworkPlayerServer != NULL) { node->p.localIndex = gNetworkPlayerServer->localIndex;