From bc0bd0a77db9086e1d60f9f5b65e0b88ff486511 Mon Sep 17 00:00:00 2001 From: MysterD Date: Sun, 16 Apr 2023 02:29:59 -0700 Subject: [PATCH] Compressed and reduced rate of Player packets Now player packets are only sent immediately if their inputs or actions changed. Otherwise, it waits a bit before sending out another one --- src/pc/network/network_player.h | 2 +- src/pc/network/packets/packet_player.c | 88 ++++++++++++++++++++++++-- 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/src/pc/network/network_player.h b/src/pc/network/network_player.h index 3a365054f..99e8d1f46 100644 --- a/src/pc/network/network_player.h +++ b/src/pc/network/network_player.h @@ -9,7 +9,7 @@ #define UNKNOWN_GLOBAL_INDEX ((u8)-1) #define UNKNOWN_NETWORK_INDEX ((u64)-1) #define NETWORK_PLAYER_TIMEOUT 10 -#define NETWORK_PLAYER_PING_TIMEOUT 1 +#define NETWORK_PLAYER_PING_TIMEOUT 3 #define MAX_RX_SEQ_IDS 64 #define USE_REAL_PALETTE_VAR 0xFF diff --git a/src/pc/network/packets/packet_player.c b/src/pc/network/packets/packet_player.c index 66b882812..11a121df9 100644 --- a/src/pc/network/packets/packet_player.c +++ b/src/pc/network/packets/packet_player.c @@ -1,4 +1,5 @@ #include +#include #include "../network.h" #include "object_fields.h" #include "object_constants.h" @@ -75,6 +76,37 @@ struct PacketPlayerData { }; #pragma pack() +uLong sourceLen = sizeof(struct PacketPlayerData); +static u32 sCompBufferLen = 0; +static Bytef* sCompBuffer = NULL; + +static void increase_comp_buffer(u32 compressedLen) { + if (compressedLen <= sCompBufferLen && sCompBuffer) { return; } + + if (sCompBuffer != NULL) { free(sCompBuffer); } + + sCompBufferLen = compressedLen; + sCompBuffer = (Bytef*)malloc(sCompBufferLen); +} + +static u32 compress_player_data(struct PacketPlayerData* data) { + uLongf compressedLen = compressBound(sizeof(struct PacketPlayerData)); + increase_comp_buffer(compressedLen); + if (!sCompBuffer) { return 0; } + + if (compress2((Bytef*)sCompBuffer, &compressedLen, (Bytef*)data, sourceLen, Z_BEST_COMPRESSION) == Z_OK) { + return compressedLen; + } else { + return 0; + } +} + +static bool decompress_player_data(u32 compressedLen, struct PacketPlayerData* data) { + if (!sCompBuffer) { return false; } + uLong decompLen = sizeof(struct PacketPlayerData); + return uncompress((Bytef*)data, &decompLen, sCompBuffer, compressedLen) == Z_OK; +} + static void read_packet_data(struct PacketPlayerData* data, struct MarioState* m) { u32 heldSyncID = (m->heldObj != NULL) ? m->heldObj->oSyncID : 0; u32 heldBySyncID = (m->heldByObj != NULL) ? m->heldByObj->oSyncID : 0; @@ -211,10 +243,19 @@ void network_send_player(u8 localIndex) { struct PacketPlayerData data = { 0 }; read_packet_data(&data, &gMarioStates[localIndex]); + + // compress + u32 compressedSize = compress_player_data(&data); + struct Packet p = { 0 }; packet_init(&p, PACKET_PLAYER, false, PLMT_AREA); packet_write(&p, &gNetworkPlayers[localIndex].globalIndex, sizeof(u8)); - packet_write(&p, &data, sizeof(struct PacketPlayerData)); + packet_write(&p, &compressedSize, sizeof(u32)); + if (compressedSize > 0) { + packet_write(&p, sCompBuffer, compressedSize); + } else { + packet_write(&p, &data, sizeof(struct PacketPlayerData)); + } network_send(&p); } @@ -244,9 +285,22 @@ void network_receive_player(struct Packet* p) { u16 playerIndex = np->localIndex; u32 oldBehParams = m->marioObj->oBehParams; + // read compressed size + u32 compressedSize = 0; + packet_read(p, &compressedSize, sizeof(u32)); + // load mario information from packet struct PacketPlayerData data = { 0 }; - packet_read(p, &data, sizeof(struct PacketPlayerData)); + if (compressedSize > 0) { + // read compressed data + increase_comp_buffer(compressedSize); + if (!sCompBuffer) { LOG_ERROR("No compressed buffer!"); return; } + packet_read(p, sCompBuffer, compressedSize); + if (!decompress_player_data(compressedSize, &data)) { LOG_ERROR("Failed to decompress data!"); return; } + } else { + // read uncompressed data + packet_read(p, &data, sizeof(struct PacketPlayerData)); + } // check to see if we should just drop this packet if (oldData.action == ACT_JUMBO_STAR_CUTSCENE && data.action == ACT_JUMBO_STAR_CUTSCENE) { @@ -403,9 +457,33 @@ void network_receive_player(struct Packet* p) { void network_update_player(void) { if (!network_player_any_connected()) { return; } + struct MarioState* m = &gMarioStates[0]; u8 localIsHeadless = (&gNetworkPlayers[0] == gNetworkPlayerServer && gServerSettings.headlessServer); - if (!localIsHeadless) { - network_send_player(0); - } + if (localIsHeadless) { return; } + + // figure out if we should send it or not + static u8 sTicksSinceSend = 0; + static u32 sLastPlayerAction = 0; + static f32 sLastStickX = 0; + static f32 sLastStickY = 0; + static u32 sLastButtonDown = 0; + static u32 sLastButtonPressed = 0; + + f32 stickDist = sqrtf(powf(sLastStickX - m->controller->stickX, 2) + powf(sLastStickY - m->controller->stickY, 2)); + bool shouldSend = (sTicksSinceSend > 2) + || (sLastPlayerAction != m->action) + || (sLastButtonDown != m->controller->buttonDown) + || (sLastButtonPressed != m->controller->buttonPressed) + || (stickDist > 5.0f); + + if (!shouldSend) { sTicksSinceSend++; return; } + network_send_player(0); + sTicksSinceSend = 0; + + sLastPlayerAction = m->action; + sLastStickX = m->controller->stickX; + sLastStickY = m->controller->stickY; + sLastButtonDown = m->controller->buttonDown; + sLastButtonPressed = m->controller->buttonPressed; }