From 134a5ef9c0bb7624111bfb3dd2594de23a17fbd0 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 1 Apr 2023 22:08:21 -0700 Subject: [PATCH 01/20] WIP --- src/CMakeLists.txt | 1 + src/d_clisrv.c | 13 +++- src/d_main.c | 5 ++ src/d_netcmd.c | 6 ++ src/g_game.c | 3 + src/k_pwrlv.c | 16 +--- src/k_serverstats.c | 179 ++++++++++++++++++++++++++++++++++++++++++++ src/k_serverstats.h | 49 ++++++++++++ src/typedef.h | 3 + 9 files changed, 261 insertions(+), 14 deletions(-) create mode 100644 src/k_serverstats.c create mode 100644 src/k_serverstats.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 21ef13ce9..f92be390e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -141,6 +141,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 k_podium.c k_rank.c k_vote.c + k_serverstats.c ) if(SRB2_CONFIG_ENABLE_WEBM_MOVIES) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 37bb6323b..f1ff9cf96 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -61,6 +61,7 @@ #include "m_cond.h" // netUnlocked #include "g_party.h" #include "k_vote.h" +#include "k_serverstats.h" // cl loading screen #include "v_video.h" @@ -2972,12 +2973,18 @@ static void Command_Nodes(void) if (playernode[i] != UINT8_MAX) { - CONS_Printf(" - node %.2d", playernode[i]); + CONS_Printf(" [node %.2d]", playernode[i]); if (I_GetNodeAddress && (address = I_GetNodeAddress(playernode[i])) != NULL) CONS_Printf(" - %s", address); } - CONS_Printf(" [RRID-%s] ", GetPrettyRRID(players[i].public_key, true)); + if (K_UsingPowerLevels() != PWRLV_DISABLED) // No power type?! + { + CONS_Printf(" [%.4d PWR]", clientpowerlevels[i][K_UsingPowerLevels()]); + } + + + CONS_Printf(" [RRID-%s]", GetPrettyRRID(players[i].public_key, true)); if (IsPlayerAdmin(i)) CONS_Printf(M_GetText(" (verified admin)")); @@ -3910,6 +3917,8 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) HU_AddChatText(joinmsg, false); } + SV_RetrieveStats(newplayernum); + if (server && multiplayer && motd[0] != '\0') COM_BufAddText(va("sayto %d %s\n", newplayernum, motd)); diff --git a/src/d_main.c b/src/d_main.c index c96ff0dc9..2821d7686 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -82,6 +82,7 @@ #include "acs/interface.h" #include "k_podium.h" #include "k_vote.h" +#include "k_serverstats.h" #ifdef HWRENDER #include "hardware/hw_main.h" // 3D View Rendering @@ -1619,6 +1620,8 @@ void D_SRB2Main(void) // Load Profiles now that default controls have been defined PR_LoadProfiles(); // load control profiles + SV_LoadStats(); + #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) VID_PrepareModeList(); // Regenerate Modelist according to cv_fullscreen #endif @@ -1888,6 +1891,8 @@ void D_SRB2Main(void) } } + SV_SaveStats(); + if (autostart || netgame) { gameaction = ga_nothing; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 27cdc9042..c1fa1b7d0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1809,6 +1809,9 @@ static void Got_WeaponPref(UINT8 **cp,INT32 playernum) static void Got_PowerLevel(UINT8 **cp,INT32 playernum) { + // Server keeps track of this now, no-sell XD_POWERLEVEL + + /* UINT16 race = (UINT16)READUINT16(*cp); UINT16 battle = (UINT16)READUINT16(*cp); @@ -1816,6 +1819,7 @@ static void Got_PowerLevel(UINT8 **cp,INT32 playernum) clientpowerlevels[playernum][PWRLV_BATTLE] = min(PWRLVRECORD_MAX, battle); CONS_Debug(DBG_GAMELOGIC, "set player %d to power %d\n", playernum, race); + */ } static void Got_PartyInvite(UINT8 **cp,INT32 playernum) @@ -1977,6 +1981,7 @@ void D_SendPlayerConfig(UINT8 n) SendNameAndColor(n); WeaponPref_Send(n); + /* if (pr != NULL) { // Send it over @@ -1991,6 +1996,7 @@ void D_SendPlayerConfig(UINT8 n) } SendNetXCmdForPlayer(n, XD_POWERLEVEL, buf, p-buf); + */ } void D_Cheat(INT32 playernum, INT32 cheat, ...) diff --git a/src/g_game.c b/src/g_game.c index f5173e642..7a767bdf7 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -67,6 +67,7 @@ #include "acs/interface.h" #include "g_party.h" #include "k_vote.h" +#include "k_serverstats.h" #ifdef HAVE_DISCORDRPC #include "discord.h" @@ -1580,6 +1581,8 @@ void G_DoLoadLevelEx(boolean resetplayer, gamestate_t newstate) // clear hud messages remains (usually from game startup) CON_ClearHUD(); + SV_UpdateStats(); + server_lagless = cv_lagless.value; if (doAutomate == true) diff --git a/src/k_pwrlv.c b/src/k_pwrlv.c index 0f234a504..5b1611d7b 100644 --- a/src/k_pwrlv.c +++ b/src/k_pwrlv.c @@ -17,6 +17,7 @@ #include "p_tick.h" // leveltime #include "k_grandprix.h" #include "k_profiles.h" +#include "k_serverstats.h" // Client-sided calculations done for Power Levels. // This is done so that clients will never be able to hack someone else's score over the server. @@ -636,18 +637,9 @@ void K_PlayerForfeit(UINT8 playerNum, boolean pointLoss) return; } - if (inc < 0 && pointLoss == false) + if (pointLoss) { - // Don't record point losses for sync-out / crashes. - return; - } - - pr = PR_GetPlayerProfile(&players[playerNum]); - if (pr != NULL) - { - pr->powerlevels[powerType] = yourPower + inc; - - M_UpdateUnlockablesAndExtraEmblems(true, true); - G_SaveGameData(); + CONS_Printf("Stats update by %d\n", inc); + SV_UpdateStats(); } } diff --git a/src/k_serverstats.c b/src/k_serverstats.c new file mode 100644 index 000000000..49541e315 --- /dev/null +++ b/src/k_serverstats.c @@ -0,0 +1,179 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file k_serverstats.c +/// \brief implements methods for serverside stat tracking. + +#include "doomtype.h" +#include "d_main.h" // pandf +#include "byteptr.h" // READ/WRITE macros +#include "p_saveg.h" // savebuffer_t +#include "m_misc.h" //FIL_WriteFile() +#include "k_serverstats.h" +#include "z_zone.h" + +static serverplayer_t trackedList[MAXTRACKEDSERVERPLAYERS]; +static UINT32 numtracked = 0; + +// Read stats file to trackedList for ingame use +void SV_LoadStats(void) +{ + const size_t headerlen = strlen(SERVERSTATSHEADER); + savebuffer_t save = {0}; + + if (!server) + return; + + if (P_SaveBufferFromFile(&save, va(pandf, srb2home, SERVERSTATSFILE)) == false) + { + return; + } + + if (strncmp(SERVERSTATSHEADER, (const char *)save.buffer, headerlen)) + { + const char *gdfolder = "the Ring Racers folder"; + if (strcmp(srb2home,".")) + gdfolder = srb2home; + + P_SaveBufferFree(&save); + I_Error("Not a valid server stats file.\nDelete %s (maybe in %s) and try again.", SERVERSTATSFILE, gdfolder); + } + + save.p += headerlen; + + numtracked = READUINT32(save.p); + if (numtracked > MAXTRACKEDSERVERPLAYERS) + numtracked = MAXTRACKEDSERVERPLAYERS; + + READMEM(save.p, trackedList, (numtracked * sizeof(serverplayer_t))); +} + +// Save trackedList to disc +void SV_SaveStats(void) +{ + size_t length = 0; + const size_t headerlen = strlen(SERVERSTATSHEADER); + UINT8 i; + savebuffer_t save = {0}; + + if (!server) + return; + + /* + if (profilesList[PROFILE_GUEST] == NULL) + { + // Profiles have not been loaded yet, don't overwrite with garbage. + return; + } + */ + + if (P_SaveBufferAlloc(&save, headerlen + sizeof(UINT32) + (numtracked * sizeof(serverplayer_t))) == false) + { + I_Error("No more free memory for saving server stats\n"); + return; + } + + // Add header. + WRITESTRINGN(save.p, SERVERSTATSHEADER, headerlen); + + WRITEUINT32(save.p, numtracked); + + WRITEMEM(save.p, trackedList, (numtracked * sizeof(serverplayer_t))); + + for (i = 0; i < numtracked; i++) + { + + } + + length = save.p - save.buffer; + + if (!FIL_WriteFile(va(pandf, srb2home, SERVERSTATSFILE), save.buffer, length)) + { + P_SaveBufferFree(&save); + I_Error("Couldn't save server stats. Are you out of Disk space / playing in a protected folder?"); + } + P_SaveBufferFree(&save); +} + +// New player, grab their stats from trackedList or initialize new ones if they're new +void SV_RetrieveStats(int player) +{ + if (!server) + return; + + UINT32 j; + + for(j = 0; j < numtracked; j++) + { + if (memcmp(trackedList[j].public_key, players[player].public_key, PUBKEYLENGTH) == 0) + { + memcpy(clientpowerlevels[player], trackedList[j].powerlevels, sizeof(trackedList[j].powerlevels)); + return; + } + } + + uint8_t allZero[PUBKEYLENGTH]; + memset(allZero, 0, PUBKEYLENGTH); + + for(j = 0; j < PWRLV_NUMTYPES; j++) + { + if (memcmp(players[player].public_key, allZero, PUBKEYLENGTH) == 0) + clientpowerlevels[player][j] = 0; + else + clientpowerlevels[player][j] = PWRLVRECORD_START; + } + +} + +// Write player stats to trackedList, then save to disk +void SV_UpdateStats(void) +{ + UINT32 i, j; + uint8_t allZero[PUBKEYLENGTH]; + memset(allZero, 0, PUBKEYLENGTH); + + if (!server) + return; + + CONS_Printf("SV_UpdateStats\n"); + + for(i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (memcmp(players[i].public_key, allZero, PUBKEYLENGTH) == 0) + { + continue; + } + + CONS_Printf("updating %d\n", i); + + boolean match = false; + for(j = 0; j < numtracked; j++) + { + if (memcmp(trackedList[j].public_key, players[i].public_key, PUBKEYLENGTH) == 0) + { + memcpy(trackedList[j].powerlevels, clientpowerlevels[i], sizeof(trackedList[j].powerlevels)); + match = true; + break; + } + } + + if (match) + continue; + + memcpy(trackedList[numtracked].public_key, players[i].public_key, PUBKEYLENGTH); + memcpy(trackedList[numtracked].powerlevels, clientpowerlevels[i], sizeof(trackedList[numtracked].powerlevels)); + + numtracked++; + } + + SV_SaveStats(); +} \ No newline at end of file diff --git a/src/k_serverstats.h b/src/k_serverstats.h new file mode 100644 index 000000000..161d11cd7 --- /dev/null +++ b/src/k_serverstats.h @@ -0,0 +1,49 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 2011-2016 by Matthew "Inuyasha" Walsh. +// Copyright (C) 1999-2018 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file k_serverstats.h +/// \brief serverside stat tracking definitions + +#ifndef __SERVERSTATS_H__ +#define __SERVERSTATS_H__ + +#include "doomdef.h" // MAXPLAYERNAME +#include "g_input.h" // Input related stuff +#include "string.h" // strcpy etc +#include "g_game.h" // game CVs + +#ifdef __cplusplus +extern "C" { +#endif + +#define SERVERSTATSFILE "srvstats.dat" +#define MAXTRACKEDSERVERPLAYERS 9999 +#define SERVERSTATSHEADER "Doctor Robotnik's Ring Racers Server Stats" + +struct serverplayer_t +{ + uint8_t public_key[PUBKEYLENGTH]; + UINT16 powerlevels[PWRLV_NUMTYPES]; +}; + +void SV_SaveStats(void); + +void SV_LoadStats(void); + +void SV_RetrieveStats(int player); + +void SV_UpdateStats(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/src/typedef.h b/src/typedef.h index 2683bff70..a8d2d669f 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -195,6 +195,9 @@ TYPEDEF (pathfindsetup_t); // k_profiles.h TYPEDEF (profile_t); +// h_serverstats.h +TYPEDEF (serverplayer_t); + // k_terrain.h TYPEDEF (t_splash_t); TYPEDEF (t_footstep_t); From d89d06be314f6eec475201eded1ce2012a5b6dd6 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 1 Apr 2023 23:15:57 -0700 Subject: [PATCH 02/20] Instantly update stats when players leave --- src/k_pwrlv.c | 3 ++- src/k_serverstats.c | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/k_pwrlv.c b/src/k_pwrlv.c index 5b1611d7b..5aec0e5e9 100644 --- a/src/k_pwrlv.c +++ b/src/k_pwrlv.c @@ -639,7 +639,8 @@ void K_PlayerForfeit(UINT8 playerNum, boolean pointLoss) if (pointLoss) { - CONS_Printf("Stats update by %d\n", inc); + clientpowerlevels[playerNum][powerType] += clientPowerAdd[playerNum]; + clientPowerAdd[playerNum] = 0; SV_UpdateStats(); } } diff --git a/src/k_serverstats.c b/src/k_serverstats.c index 49541e315..46aa06d3f 100644 --- a/src/k_serverstats.c +++ b/src/k_serverstats.c @@ -141,8 +141,6 @@ void SV_UpdateStats(void) if (!server) return; - CONS_Printf("SV_UpdateStats\n"); - for(i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i]) @@ -153,8 +151,6 @@ void SV_UpdateStats(void) continue; } - CONS_Printf("updating %d\n", i); - boolean match = false; for(j = 0; j < numtracked; j++) { From 7eb5755963e26479d5d66337418a65c5116b8537 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sun, 2 Apr 2023 00:01:34 -0700 Subject: [PATCH 03/20] Disallow duplicate non-GUEST pubkeys --- src/d_clisrv.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index f1ff9cf96..d2f1b1ac1 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4297,7 +4297,7 @@ static boolean IsPlayerGuest(int player) static void HandleConnect(SINT8 node) { char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1]; - INT32 i; + INT32 i, j; UINT8 availabilitiesbuffer[MAXAVAILABILITY]; // Sal: Dedicated mode is INCREDIBLY hacked together. @@ -4396,6 +4396,8 @@ static void HandleConnect(SINT8 node) { int sigcheck; boolean newnode = false; + char allZero[PUBKEYLENGTH]; + memset(allZero, 0, sizeof(allZero)); for (i = 0; i < netbuffer->u.clientcfg.localplayers - playerpernode[node]; i++) { @@ -4411,10 +4413,7 @@ static void HandleConnect(SINT8 node) memcpy(lastReceivedKey[node][i], PR_GetLocalPlayerProfile(i)->public_key, sizeof(lastReceivedKey[node][i])); } else // Remote player, gotta check their signature. - { - char allZero[PUBKEYLENGTH]; - memset(allZero, 0, sizeof(allZero)); - + { if (memcmp(lastReceivedKey[node][i], allZero, PUBKEYLENGTH) == 0) // IsSplitPlayerOnNodeGuest isn't appropriate here, they're not in-game yet! { if (!cv_allowguests.value) @@ -4436,6 +4435,34 @@ static void HandleConnect(SINT8 node) return; } } + + // Check non-GUESTS for duplicate pubkeys, they'll create nonsense stats + if (memcmp(lastReceivedKey[node][i], allZero, PUBKEYLENGTH) != 0) + { + // Players already here + for (j = 0; j < MAXPLAYERS; j++) + { + if (memcmp(lastReceivedKey[node][i], players[j].public_key, PUBKEYLENGTH) == 0) + { + SV_SendRefuse(node, M_GetText("Duplicate pubkey already on server.\n(Did you share your profile?)")); + return; + } + } + + // Players we're trying to add + for (j = 0; j < netbuffer->u.clientcfg.localplayers - playerpernode[node]; j++) + { + if (memcmp(lastReceivedKey[node][i], allZero, PUBKEYLENGTH) == 0) + continue; + if (i == j) + continue; + if (memcmp(lastReceivedKey[node][i], lastReceivedKey[node][j], PUBKEYLENGTH) == 0) + { + SV_SendRefuse(node, M_GetText("Duplicate pubkey in local party.\n(How did you even do this?)")); + return; + } + } + } } memcpy(availabilitiesbuffer, netbuffer->u.clientcfg.availabilities, sizeof(availabilitiesbuffer)); From 10fb49668908f14368ccd35843f81743c25de49b Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sun, 2 Apr 2023 00:29:58 -0700 Subject: [PATCH 04/20] Version field for srvstats.dat --- src/k_serverstats.c | 8 ++++++-- src/k_serverstats.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/k_serverstats.c b/src/k_serverstats.c index 46aa06d3f..3e30f9290 100644 --- a/src/k_serverstats.c +++ b/src/k_serverstats.c @@ -46,7 +46,8 @@ void SV_LoadStats(void) } save.p += headerlen; - + UINT8 version = READUINT8(save.p); + numtracked = READUINT32(save.p); if (numtracked > MAXTRACKEDSERVERPLAYERS) numtracked = MAXTRACKEDSERVERPLAYERS; @@ -73,7 +74,8 @@ void SV_SaveStats(void) } */ - if (P_SaveBufferAlloc(&save, headerlen + sizeof(UINT32) + (numtracked * sizeof(serverplayer_t))) == false) + // header + version + numtracked + payload + if (P_SaveBufferAlloc(&save, headerlen + sizeof(UINT32) + sizeof(UINT8) + (numtracked * sizeof(serverplayer_t))) == false) { I_Error("No more free memory for saving server stats\n"); return; @@ -82,6 +84,8 @@ void SV_SaveStats(void) // Add header. WRITESTRINGN(save.p, SERVERSTATSHEADER, headerlen); + WRITEUINT8(save.p, SERVERSTATSVER); + WRITEUINT32(save.p, numtracked); WRITEMEM(save.p, trackedList, (numtracked * sizeof(serverplayer_t))); diff --git a/src/k_serverstats.h b/src/k_serverstats.h index 161d11cd7..ffaaf571b 100644 --- a/src/k_serverstats.h +++ b/src/k_serverstats.h @@ -27,6 +27,7 @@ extern "C" { #define SERVERSTATSFILE "srvstats.dat" #define MAXTRACKEDSERVERPLAYERS 9999 #define SERVERSTATSHEADER "Doctor Robotnik's Ring Racers Server Stats" +#define SERVERSTATSVER 1 struct serverplayer_t { From 3012839138d09d134f0cabd5239107ed4c3923f8 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 5 Apr 2023 21:01:26 -0700 Subject: [PATCH 05/20] Serverside PWR: Completely rip out profile PWR, add PWR to XD_ADDPLAYER --- src/d_clisrv.c | 48 +++++++++++++++++++++++++-------------------- src/d_netcmd.c | 37 ++++++++++------------------------ src/d_netcmd.h | 2 +- src/deh_soc.c | 19 ------------------ src/k_menudraw.c | 10 ++-------- src/k_profiles.c | 9 +++++++++ src/k_profiles.h | 2 ++ src/k_pwrlv.c | 15 +------------- src/k_serverstats.c | 41 ++++++++++++++------------------------ src/k_serverstats.h | 2 +- src/m_cond.c | 25 ----------------------- src/m_cond.h | 2 -- 12 files changed, 68 insertions(+), 144 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d2f1b1ac1..bd4c5064a 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3853,6 +3853,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME); READMEM(*p, players[newplayernum].public_key, PUBKEYLENGTH); + READMEM(*p, clientpowerlevels[newplayernum], sizeof(((serverplayer_t *)0)->powerlevels)); console = READUINT8(*p); splitscreenplayer = READUINT8(*p); @@ -3917,8 +3918,6 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) HU_AddChatText(joinmsg, false); } - SV_RetrieveStats(newplayernum); - if (server && multiplayer && motd[0] != '\0') COM_BufAddText(va("sayto %d %s\n", newplayernum, motd)); @@ -4011,8 +4010,10 @@ static void Got_AddBot(UINT8 **p, INT32 playernum) } static boolean SV_AddWaitingPlayers(SINT8 node, UINT8 *availabilities, -const char *name, uint8_t *key, const char *name2, uint8_t *key2, -const char *name3, uint8_t *key3, const char *name4, uint8_t *key4) +const char *name, uint8_t *key, UINT16 *pwr, +const char *name2, uint8_t *key2, UINT16 *pwr2, +const char *name3, uint8_t *key3, UINT16 *pwr3, +const char *name4, uint8_t *key4, UINT16 *pwr4) { INT32 n, newplayernum, i; UINT8 buf[4 + MAXPLAYERNAME + PUBKEYLENGTH + MAXAVAILABILITY]; @@ -4079,24 +4080,28 @@ const char *name3, uint8_t *key3, const char *name4, uint8_t *key4) nodetoplayer[node] = newplayernum; WRITESTRINGN(buf_p, name, MAXPLAYERNAME); WRITEMEM(buf_p, key, PUBKEYLENGTH); + WRITEMEM(buf_p, pwr, sizeof(((serverplayer_t *)0)->powerlevels)); } else if (playerpernode[node] < 2) { nodetoplayer2[node] = newplayernum; WRITESTRINGN(buf_p, name2, MAXPLAYERNAME); WRITEMEM(buf_p, key2, PUBKEYLENGTH); + WRITEMEM(buf_p, pwr2, sizeof(((serverplayer_t *)0)->powerlevels)); } else if (playerpernode[node] < 3) { nodetoplayer3[node] = newplayernum; WRITESTRINGN(buf_p, name3, MAXPLAYERNAME); WRITEMEM(buf_p, key3, PUBKEYLENGTH); + WRITEMEM(buf_p, pwr3, sizeof(((serverplayer_t *)0)->powerlevels)); } else if (playerpernode[node] < 4) { nodetoplayer4[node] = newplayernum; WRITESTRINGN(buf_p, name4, MAXPLAYERNAME); WRITEMEM(buf_p, key4, PUBKEYLENGTH); + WRITEMEM(buf_p, pwr4, sizeof(((serverplayer_t *)0)->powerlevels)); } WRITEUINT8(buf_p, nodetoplayer[node]); // consoleplayer @@ -4186,8 +4191,11 @@ boolean SV_SpawnServer(void) UINT8 *availabilitiesbuffer = R_GetSkinAvailabilities(false, false); SINT8 node = 0; for (; node < MAXNETNODES; node++) - result |= SV_AddWaitingPlayers(node, availabilitiesbuffer, cv_playername[0].zstring, PR_GetLocalPlayerProfile(0)->public_key, cv_playername[1].zstring, PR_GetLocalPlayerProfile(1)->public_key, - cv_playername[2].zstring, PR_GetLocalPlayerProfile(2)->public_key, cv_playername[3].zstring, PR_GetLocalPlayerProfile(3)->public_key); + result |= SV_AddWaitingPlayers(node, availabilitiesbuffer, + cv_playername[0].zstring, PR_GetLocalPlayerProfile(0)->public_key, SV_RetrievePWR(PR_GetLocalPlayerProfile(0)->public_key), + cv_playername[1].zstring, PR_GetLocalPlayerProfile(1)->public_key, SV_RetrievePWR(PR_GetLocalPlayerProfile(1)->public_key), + cv_playername[2].zstring, PR_GetLocalPlayerProfile(2)->public_key, SV_RetrievePWR(PR_GetLocalPlayerProfile(2)->public_key), + cv_playername[3].zstring, PR_GetLocalPlayerProfile(3)->public_key, SV_RetrievePWR(PR_GetLocalPlayerProfile(3)->public_key)); } return result; #endif @@ -4268,13 +4276,13 @@ static size_t TotalTextCmdPerTic(tic_t tic) memset(allZero, 0, PUBKEYLENGTH); if (split == 0) - return (memcmp(players[nodetoplayer[node]].public_key, allZero, PUBKEYLENGTH) == 0); + return PR_IsKeyGuest(players[nodetoplayer[node]].public_key); else if (split == 1) - return (memcmp(players[nodetoplayer2[node]].public_key, allZero, PUBKEYLENGTH) == 0); + return PR_IsKeyGuest(players[nodetoplayer2[node]].public_key); else if (split == 2) - return (memcmp(players[nodetoplayer3[node]].public_key, allZero, PUBKEYLENGTH) == 0); + return PR_IsKeyGuest(players[nodetoplayer3[node]].public_key); else if (split == 3) - return (memcmp(players[nodetoplayer4[node]].public_key, allZero, PUBKEYLENGTH) == 0); + return PR_IsKeyGuest(players[nodetoplayer4[node]].public_key); else I_Error("IsSplitPlayerOnNodeGuest: Out of bounds"); return false; // unreachable @@ -4283,10 +4291,7 @@ static size_t TotalTextCmdPerTic(tic_t tic) static boolean IsPlayerGuest(int player) { - char allZero[PUBKEYLENGTH]; - memset(allZero, 0, PUBKEYLENGTH); - - return (memcmp(players[player].public_key, allZero, PUBKEYLENGTH) == 0); + return PR_IsKeyGuest(players[player].public_key); } /** Called when a PT_CLIENTJOIN packet is received @@ -4396,8 +4401,6 @@ static void HandleConnect(SINT8 node) { int sigcheck; boolean newnode = false; - char allZero[PUBKEYLENGTH]; - memset(allZero, 0, sizeof(allZero)); for (i = 0; i < netbuffer->u.clientcfg.localplayers - playerpernode[node]; i++) { @@ -4414,7 +4417,7 @@ static void HandleConnect(SINT8 node) } else // Remote player, gotta check their signature. { - if (memcmp(lastReceivedKey[node][i], allZero, PUBKEYLENGTH) == 0) // IsSplitPlayerOnNodeGuest isn't appropriate here, they're not in-game yet! + if (PR_IsKeyGuest(lastReceivedKey[node][i])) // IsSplitPlayerOnNodeGuest isn't appropriate here, they're not in-game yet! { if (!cv_allowguests.value) { @@ -4437,7 +4440,7 @@ static void HandleConnect(SINT8 node) } // Check non-GUESTS for duplicate pubkeys, they'll create nonsense stats - if (memcmp(lastReceivedKey[node][i], allZero, PUBKEYLENGTH) != 0) + if (!PR_IsKeyGuest(lastReceivedKey[node][i])) { // Players already here for (j = 0; j < MAXPLAYERS; j++) @@ -4452,7 +4455,7 @@ static void HandleConnect(SINT8 node) // Players we're trying to add for (j = 0; j < netbuffer->u.clientcfg.localplayers - playerpernode[node]; j++) { - if (memcmp(lastReceivedKey[node][i], allZero, PUBKEYLENGTH) == 0) + if (PR_IsKeyGuest(lastReceivedKey[node][j])) continue; if (i == j) continue; @@ -4502,8 +4505,11 @@ static void HandleConnect(SINT8 node) DEBFILE("send savegame\n"); } - SV_AddWaitingPlayers(node, availabilitiesbuffer, names[0], lastReceivedKey[node][0], names[1], lastReceivedKey[node][1], - names[2], lastReceivedKey[node][2], names[3], lastReceivedKey[node][3]); + SV_AddWaitingPlayers(node, availabilitiesbuffer, + names[0], lastReceivedKey[node][0], SV_RetrievePWR(lastReceivedKey[node][0]), + names[1], lastReceivedKey[node][1], SV_RetrievePWR(lastReceivedKey[node][1]), + names[2], lastReceivedKey[node][2], SV_RetrievePWR(lastReceivedKey[node][2]), + names[3], lastReceivedKey[node][3], SV_RetrievePWR(lastReceivedKey[node][3])); joindelay += cv_joindelay.value * TICRATE; player_joining = true; } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index c1fa1b7d0..2dbf96b62 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -618,7 +618,6 @@ const char *netxcmdnames[MAXNETXCMD - 1] = "MODIFYVOTE", // XD_MODIFYVOTE "PICKVOTE", // XD_PICKVOTE "REMOVEPLAYER", // XD_REMOVEPLAYER - "POWERLEVEL", // XD_POWERLEVEL "PARTYINVITE", // XD_PARTYINVITE "ACCEPTPARTYINVITE", // XD_ACCEPTPARTYINVITE "LEAVEPARTY", // XD_LEAVEPARTY @@ -657,7 +656,6 @@ void D_RegisterServerCommands(void) RegisterNetXCmd(XD_NAMEANDCOLOR, Got_NameAndColor); RegisterNetXCmd(XD_WEAPONPREF, Got_WeaponPref); - RegisterNetXCmd(XD_POWERLEVEL, Got_PowerLevel); RegisterNetXCmd(XD_PARTYINVITE, Got_PartyInvite); RegisterNetXCmd(XD_ACCEPTPARTYINVITE, Got_AcceptPartyInvite); RegisterNetXCmd(XD_CANCELPARTYINVITE, Got_CancelPartyInvite); @@ -1807,19 +1805,21 @@ static void Got_WeaponPref(UINT8 **cp,INT32 playernum) demo_extradata[playernum] |= DXD_WEAPONPREF; } +// Currently unused, PWR is sent in XD_ADDPLAYER static void Got_PowerLevel(UINT8 **cp,INT32 playernum) { - // Server keeps track of this now, no-sell XD_POWERLEVEL + int i; - /* - UINT16 race = (UINT16)READUINT16(*cp); - UINT16 battle = (UINT16)READUINT16(*cp); + for(i = 0; i < MAXPLAYERS; i++) + { + UINT16 race = (UINT16)READUINT16(*cp); + UINT16 battle = (UINT16)READUINT16(*cp); - clientpowerlevels[playernum][PWRLV_RACE] = min(PWRLVRECORD_MAX, race); - clientpowerlevels[playernum][PWRLV_BATTLE] = min(PWRLVRECORD_MAX, battle); + clientpowerlevels[i][PWRLV_RACE] = min(PWRLVRECORD_MAX, race); + clientpowerlevels[i][PWRLV_BATTLE] = min(PWRLVRECORD_MAX, battle); - CONS_Debug(DBG_GAMELOGIC, "set player %d to power %d\n", playernum, race); - */ + CONS_Debug(DBG_GAMELOGIC, "set player %d to power %d\n", i, race); + } } static void Got_PartyInvite(UINT8 **cp,INT32 playernum) @@ -1980,23 +1980,6 @@ void D_SendPlayerConfig(UINT8 n) SendNameAndColor(n); WeaponPref_Send(n); - - /* - if (pr != NULL) - { - // Send it over - WRITEUINT16(p, pr->powerlevels[PWRLV_RACE]); - WRITEUINT16(p, pr->powerlevels[PWRLV_BATTLE]); - } - else - { - // Guest players have no power level - WRITEUINT16(p, 0); - WRITEUINT16(p, 0); - } - - SendNetXCmdForPlayer(n, XD_POWERLEVEL, buf, p-buf); - */ } void D_Cheat(INT32 playernum, INT32 cheat, ...) diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 8cab1e10f..d4d5fee85 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -169,7 +169,7 @@ typedef enum XD_MODIFYVOTE, // 24 XD_PICKVOTE, // 25 XD_REMOVEPLAYER,// 26 - XD_POWERLEVEL, // 27 + XD_POWERLEVEL, // 27 [No longer used, might be repurposed - PWR is in XD_ADDPLAYER now] XD_PARTYINVITE, // 28 XD_ACCEPTPARTYINVITE, // 29 XD_LEAVEPARTY, // 30 diff --git a/src/deh_soc.c b/src/deh_soc.c index a7962e3af..fea7df30e 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -2458,25 +2458,6 @@ static void readcondition(UINT8 set, UINT32 id, char *word2) return; } } - else if (fastcmp(params[0], "POWERLEVEL")) - { - PARAMCHECK(2); - ty = UC_POWERLEVEL; - re = atoi(params[1]); - x1 = atoi(params[2]); - - if (re < PWRLVRECORD_MIN || re > PWRLVRECORD_MAX) - { - deh_warning("Power level requirement %d out of range (%d - %d) for condition ID %d", re, PWRLVRECORD_MIN, PWRLVRECORD_MAX, id+1); - return; - } - - if (x1 < 0 || x1 >= PWRLV_NUMTYPES) - { - deh_warning("Power level type %d out of range (0 - %d) for condition ID %d", x1, PWRLV_NUMTYPES-1, id+1); - return; - } - } else if (fastcmp(params[0], "GAMECLEAR")) { ty = UC_GAMECLEAR; diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 33cbf3aec..b7e633c47 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -1673,7 +1673,6 @@ static void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p) UINT16 truecol = SKINCOLOR_BLACK; UINT8 *colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_BLACK, GTC_CACHE); INT32 skinnum = -1; - INT32 powerlevel = -1; char pname[PROFILENAMELEN+1] = "NEW"; @@ -1683,7 +1682,6 @@ static void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p) colormap = R_GetTranslationColormap(TC_DEFAULT, truecol, GTC_CACHE); strcpy(pname, p->profilename); skinnum = R_SkinAvailable(p->skinname); - powerlevel = p->powerlevels[0]; // Only display race power level. } // check setup_player for colormap for the card. @@ -1700,12 +1698,8 @@ static void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p) if (greyedout) return; // only used for profiles we can't select. - // Draw pwlv if we can - if (powerlevel > -1) - { - V_DrawFixedPatch((x+30)*FRACUNIT, (y+84)*FRACUNIT, FRACUNIT, 0, pwrlv, colormap); - V_DrawCenteredKartString(x+30, y+87, 0, va("%d\n", powerlevel)); - } + V_DrawFixedPatch((x+30)*FRACUNIT, (y+84)*FRACUNIT, FRACUNIT, 0, pwrlv, colormap); + V_DrawCenteredKartString(x+30, y+87, 0, "TEMP"); // check what setup_player is doing in priority. if (sp->mdepth >= CSSTEP_CHARS) diff --git a/src/k_profiles.c b/src/k_profiles.c index 853306556..d8b421d7c 100644 --- a/src/k_profiles.c +++ b/src/k_profiles.c @@ -630,3 +630,12 @@ char *GetPrettyRRID(const unsigned char *bin, boolean brief) return rrid_buf; } + + +char allZero[PUBKEYLENGTH]; + +boolean PR_IsKeyGuest(uint8_t *key) +{ + memset(allZero, 0, PUBKEYLENGTH); + return (memcmp(key, allZero, PUBKEYLENGTH) == 0); +} \ No newline at end of file diff --git a/src/k_profiles.h b/src/k_profiles.h index 2a866868f..65e1d740f 100644 --- a/src/k_profiles.h +++ b/src/k_profiles.h @@ -166,6 +166,8 @@ boolean PR_IsLocalPlayerGuest(INT32 player); char *GetPrettyRRID(const unsigned char *bin, boolean brief); +boolean PR_IsKeyGuest(uint8_t *key); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/k_pwrlv.c b/src/k_pwrlv.c index 5aec0e5e9..9e3b3f640 100644 --- a/src/k_pwrlv.c +++ b/src/k_pwrlv.c @@ -400,7 +400,6 @@ void K_CashInPowerLevels(void) { SINT8 powerType = K_UsingPowerLevels(); UINT8 i; - boolean gamedataupdate; //CONS_Printf("\n========\n"); //CONS_Printf("Cashing in power level changes...\n"); @@ -410,29 +409,17 @@ void K_CashInPowerLevels(void) { if (playeringame[i] == true && powerType != PWRLV_DISABLED) { - profile_t *pr = PR_GetPlayerProfile(&players[i]); INT16 inc = K_FinalPowerIncrement(&players[i], clientpowerlevels[i][powerType], clientPowerAdd[i]); clientpowerlevels[i][powerType] += inc; //CONS_Printf("%s: %d -> %d (%d)\n", player_names[i], clientpowerlevels[i][powerType] - inc, clientpowerlevels[i][powerType], inc); - - if (pr != NULL && inc != 0) - { - pr->powerlevels[powerType] = clientpowerlevels[i][powerType]; - - gamedataupdate = true; - } } clientPowerAdd[i] = 0; } - if (gamedataupdate) - { - M_UpdateUnlockablesAndExtraEmblems(true, true); - G_SaveGameData(); - } + SV_UpdateStats(); //CONS_Printf("========\n"); } diff --git a/src/k_serverstats.c b/src/k_serverstats.c index 3e30f9290..f04a3c182 100644 --- a/src/k_serverstats.c +++ b/src/k_serverstats.c @@ -21,6 +21,8 @@ static serverplayer_t trackedList[MAXTRACKEDSERVERPLAYERS]; static UINT32 numtracked = 0; +UINT16 guestpwr[PWRLV_NUMTYPES]; // All-zero power level to reference for guests + // Read stats file to trackedList for ingame use void SV_LoadStats(void) { @@ -106,41 +108,35 @@ void SV_SaveStats(void) } // New player, grab their stats from trackedList or initialize new ones if they're new -void SV_RetrieveStats(int player) +UINT16 *SV_RetrievePWR(uint8_t *key) { - if (!server) - return; - UINT32 j; + // Existing record? for(j = 0; j < numtracked; j++) { - if (memcmp(trackedList[j].public_key, players[player].public_key, PUBKEYLENGTH) == 0) + if (memcmp(trackedList[j].public_key, key, PUBKEYLENGTH) == 0) { - memcpy(clientpowerlevels[player], trackedList[j].powerlevels, sizeof(trackedList[j].powerlevels)); - return; + return trackedList[j].powerlevels; } } - uint8_t allZero[PUBKEYLENGTH]; - memset(allZero, 0, PUBKEYLENGTH); - + // Untracked, make a new record + memcpy(trackedList[numtracked].public_key, key, PUBKEYLENGTH); for(j = 0; j < PWRLV_NUMTYPES; j++) { - if (memcmp(players[player].public_key, allZero, PUBKEYLENGTH) == 0) - clientpowerlevels[player][j] = 0; - else - clientpowerlevels[player][j] = PWRLVRECORD_START; + trackedList[numtracked].powerlevels[j] = PR_IsKeyGuest(key) ? 0 : PWRLVRECORD_START; } + + numtracked++; + return trackedList[numtracked - 1].powerlevels; } // Write player stats to trackedList, then save to disk void SV_UpdateStats(void) { UINT32 i, j; - uint8_t allZero[PUBKEYLENGTH]; - memset(allZero, 0, PUBKEYLENGTH); if (!server) return; @@ -150,29 +146,22 @@ void SV_UpdateStats(void) if (!playeringame[i]) continue; - if (memcmp(players[i].public_key, allZero, PUBKEYLENGTH) == 0) + if (PR_IsKeyGuest(players[i].public_key)) { continue; } - boolean match = false; for(j = 0; j < numtracked; j++) { if (memcmp(trackedList[j].public_key, players[i].public_key, PUBKEYLENGTH) == 0) { memcpy(trackedList[j].powerlevels, clientpowerlevels[i], sizeof(trackedList[j].powerlevels)); - match = true; break; } } - if (match) - continue; - - memcpy(trackedList[numtracked].public_key, players[i].public_key, PUBKEYLENGTH); - memcpy(trackedList[numtracked].powerlevels, clientpowerlevels[i], sizeof(trackedList[numtracked].powerlevels)); - - numtracked++; + // SV_RetrievePWR should always be called for a key before SV_UpdateStats runs, + // so this shouldn't be reachable. } SV_SaveStats(); diff --git a/src/k_serverstats.h b/src/k_serverstats.h index ffaaf571b..73210095b 100644 --- a/src/k_serverstats.h +++ b/src/k_serverstats.h @@ -39,7 +39,7 @@ void SV_SaveStats(void); void SV_LoadStats(void); -void SV_RetrieveStats(int player); +UINT16 *SV_RetrievePWR(uint8_t *key); void SV_UpdateStats(void); diff --git a/src/m_cond.c b/src/m_cond.c index 45db53caf..5b551f646 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -683,25 +683,6 @@ boolean M_CheckCondition(condition_t *cn, player_t *player) } case UC_TOTALRINGS: // Requires grabbing >= x rings return (gamedata->totalrings >= (unsigned)cn->requirement); - case UC_POWERLEVEL: // Requires power level >= x on a certain gametype - { - UINT8 i; - - if (gamestate == GS_LEVEL) - return false; // this one could be laggy with many profiles available - - for (i = PROFILE_GUEST; i < PR_GetNumProfiles(); i++) - { - profile_t *p = PR_GetProfile(i); - - if (p->powerlevels[cn->extrainfo1] >= (unsigned)cn->requirement) - { - return true; - } - } - - return false; - } case UC_GAMECLEAR: // Requires game beaten >= x times return (gamedata->timesBeaten >= (unsigned)cn->requirement); case UC_OVERALLTIME: // Requires overall time <= x @@ -1039,12 +1020,6 @@ static const char *M_GetConditionString(condition_t *cn) return va("collect %u,%03u Rings", (cn->requirement/1000), (cn->requirement%1000)); return va("collect %u Rings", cn->requirement); - case UC_POWERLEVEL: // Requires power level >= x on a certain gametype - return va("get a PWR of %d in %s", cn->requirement, - (cn->extrainfo1 == PWRLV_RACE) - ? "Race" - : "Battle"); - case UC_GAMECLEAR: // Requires game beaten >= x times if (cn->requirement > 1) return va("beat game %d times", cn->requirement); diff --git a/src/m_cond.h b/src/m_cond.h index c7712d5f7..a53e66ad7 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -32,8 +32,6 @@ typedef enum UC_ROUNDSPLAYED, // ROUNDSPLAYED [x played] UC_TOTALRINGS, // TOTALRINGS [x collected] - UC_POWERLEVEL, // SRB2Kart: POWERLEVEL [power level to reach] [gametype, "0" for race, "1" for battle] - UC_GAMECLEAR, // GAMECLEAR UC_OVERALLTIME, // OVERALLTIME [time to beat, tics] From c7c9f145cad920c7c94558f9791a7c67827be599 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 5 Apr 2023 21:06:05 -0700 Subject: [PATCH 06/20] Really get rid of XD_POWERLEVEL --- src/d_netcmd.c | 18 ------------------ src/d_netcmd.h | 23 +++++++++++------------ 2 files changed, 11 insertions(+), 30 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 2dbf96b62..d366888b6 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -80,7 +80,6 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum); static void Got_WeaponPref(UINT8 **cp, INT32 playernum); -static void Got_PowerLevel(UINT8 **cp, INT32 playernum); static void Got_PartyInvite(UINT8 **cp, INT32 playernum); static void Got_AcceptPartyInvite(UINT8 **cp, INT32 playernum); static void Got_CancelPartyInvite(UINT8 **cp, INT32 playernum); @@ -1805,23 +1804,6 @@ static void Got_WeaponPref(UINT8 **cp,INT32 playernum) demo_extradata[playernum] |= DXD_WEAPONPREF; } -// Currently unused, PWR is sent in XD_ADDPLAYER -static void Got_PowerLevel(UINT8 **cp,INT32 playernum) -{ - int i; - - for(i = 0; i < MAXPLAYERS; i++) - { - UINT16 race = (UINT16)READUINT16(*cp); - UINT16 battle = (UINT16)READUINT16(*cp); - - clientpowerlevels[i][PWRLV_RACE] = min(PWRLVRECORD_MAX, race); - clientpowerlevels[i][PWRLV_BATTLE] = min(PWRLVRECORD_MAX, battle); - - CONS_Debug(DBG_GAMELOGIC, "set player %d to power %d\n", i, race); - } -} - static void Got_PartyInvite(UINT8 **cp,INT32 playernum) { UINT8 invitee; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index d4d5fee85..31f430ed2 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -169,18 +169,17 @@ typedef enum XD_MODIFYVOTE, // 24 XD_PICKVOTE, // 25 XD_REMOVEPLAYER,// 26 - XD_POWERLEVEL, // 27 [No longer used, might be repurposed - PWR is in XD_ADDPLAYER now] - XD_PARTYINVITE, // 28 - XD_ACCEPTPARTYINVITE, // 29 - XD_LEAVEPARTY, // 30 - XD_CANCELPARTYINVITE, // 31 - XD_CHEAT, // 32 - XD_ADDBOT, // 33 - XD_DISCORD, // 34 - XD_PLAYSOUND, // 35 - XD_SCHEDULETASK, // 36 - XD_SCHEDULECLEAR, // 37 - XD_AUTOMATE, // 38 + XD_PARTYINVITE, // 27 + XD_ACCEPTPARTYINVITE, // 28 + XD_LEAVEPARTY, // 29 + XD_CANCELPARTYINVITE, // 30 + XD_CHEAT, // 31 + XD_ADDBOT, // 32 + XD_DISCORD, // 33 + XD_PLAYSOUND, // 34 + XD_SCHEDULETASK, // 35 + XD_SCHEDULECLEAR, // 36 + XD_AUTOMATE, // 37 MAXNETXCMD } netxcmd_t; From 4f569641fc39e36eeb9438c3a8ac0ab08b23bc74 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 6 Apr 2023 22:01:10 -0700 Subject: [PATCH 07/20] Store total wins in profiles --- src/k_menudraw.c | 8 ++++++-- src/k_profiles.c | 28 +++++++++++----------------- src/k_profiles.h | 2 +- src/k_serverstats.c | 13 ------------- src/p_user.c | 8 ++++++++ 5 files changed, 26 insertions(+), 33 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index b7e633c47..2111acfbb 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -1698,8 +1698,12 @@ static void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p) if (greyedout) return; // only used for profiles we can't select. - V_DrawFixedPatch((x+30)*FRACUNIT, (y+84)*FRACUNIT, FRACUNIT, 0, pwrlv, colormap); - V_DrawCenteredKartString(x+30, y+87, 0, "TEMP"); + if (p != NULL) + { + V_DrawFixedPatch((x+30)*FRACUNIT, (y+84)*FRACUNIT, FRACUNIT, 0, pwrlv, colormap); + V_DrawCenteredKartString(x+30, y+87, 0, va("%d", p->wins)); + } + // check what setup_player is doing in priority. if (sp->mdepth >= CSSTEP_CHARS) diff --git a/src/k_profiles.c b/src/k_profiles.c index d8b421d7c..2a7c95350 100644 --- a/src/k_profiles.c +++ b/src/k_profiles.c @@ -72,11 +72,7 @@ profile_t* PR_MakeProfile( // Copy from gamecontrol directly as we'll be setting controls up directly in the profile. memcpy(new->controls, controlarray, sizeof(new->controls)); - // Init both power levels - for (i = 0; i < PWRLV_NUMTYPES; i++) - { - new->powerlevels[i] = (guest ? 0 : PWRLVRECORD_START); - } + new->wins = 0; return new; } @@ -270,11 +266,7 @@ void PR_SaveProfiles(void) WRITESTRINGN(save.p, profilesList[i]->follower, SKINNAMESIZE); WRITEUINT16(save.p, profilesList[i]->followercolor); - // PWR. - for (j = 0; j < PWRLV_NUMTYPES; j++) - { - WRITEUINT16(save.p, profilesList[i]->powerlevels[j]); - } + WRITEUINT32(save.p, profilesList[i]->wins); // Consvars. WRITEUINT8(save.p, profilesList[i]->kickstartaccel); @@ -397,16 +389,18 @@ void PR_LoadProfiles(void) profilesList[i]->followercolor = PROFILEDEFAULTFOLLOWERCOLOR; } - // PWR. - for (j = 0; j < PWRLV_NUMTYPES; j++) + // Profile update 4-->5: PWR isn't in profile data anymore. + if (version < 5) { - profilesList[i]->powerlevels[j] = READUINT16(save.p); - if (profilesList[i]->powerlevels[j] < PWRLVRECORD_MIN - || profilesList[i]->powerlevels[j] > PWRLVRECORD_MAX) + for (j = 0; j < PWRLV_NUMTYPES; j++) { - // invalid, reset - profilesList[i]->powerlevels[j] = PWRLVRECORD_START; + READUINT16(save.p); } + profilesList[i]->wins = 0; + } + else + { + profilesList[i]->wins = READUINT32(save.p); } // Consvars. diff --git a/src/k_profiles.h b/src/k_profiles.h index 65e1d740f..4890a4207 100644 --- a/src/k_profiles.h +++ b/src/k_profiles.h @@ -69,7 +69,7 @@ struct profile_t char follower[SKINNAMESIZE+1]; // Follower UINT16 followercolor; // Follower color - UINT16 powerlevels[PWRLV_NUMTYPES]; // PWRLV for each gametype. + UINT32 wins; // PWRLV for each gametype. // Player-specific consvars. // @TODO: List all of those diff --git a/src/k_serverstats.c b/src/k_serverstats.c index f04a3c182..aba804c31 100644 --- a/src/k_serverstats.c +++ b/src/k_serverstats.c @@ -68,14 +68,6 @@ void SV_SaveStats(void) if (!server) return; - /* - if (profilesList[PROFILE_GUEST] == NULL) - { - // Profiles have not been loaded yet, don't overwrite with garbage. - return; - } - */ - // header + version + numtracked + payload if (P_SaveBufferAlloc(&save, headerlen + sizeof(UINT32) + sizeof(UINT8) + (numtracked * sizeof(serverplayer_t))) == false) { @@ -92,11 +84,6 @@ void SV_SaveStats(void) WRITEMEM(save.p, trackedList, (numtracked * sizeof(serverplayer_t))); - for (i = 0; i < numtracked; i++) - { - - } - length = save.p - save.buffer; if (!FIL_WriteFile(va(pandf, srb2home, SERVERSTATSFILE), save.buffer, length)) diff --git a/src/p_user.c b/src/p_user.c index e05d1a0f7..96201366d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -62,6 +62,7 @@ #include "k_rank.h" #include "k_director.h" #include "g_party.h" +#include "k_profiles.h" #ifdef HW3SOUND #include "hardware/hw3sound.h" @@ -1378,6 +1379,13 @@ void P_DoPlayerExit(player_t *player) if (modeattacking) G_UpdateRecords(); + profile_t *pr = PR_GetPlayerProfile(player); + if (pr != NULL && !losing) + { + pr->wins++; + PR_SaveProfiles(); + } + player->karthud[khud_cardanimation] = 0; // srb2kart: reset battle animation if (player == &players[consoleplayer]) From 0aabb6ddcdb72d3db653f85cc7c17b803a8fc130 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Mon, 10 Apr 2023 18:58:51 -0700 Subject: [PATCH 08/20] Return full stats struct, dynamically allocate trackedList --- src/d_clisrv.c | 16 ++++----- src/k_serverstats.c | 84 ++++++++++++++++++++++++++++++++++++--------- src/k_serverstats.h | 4 +-- 3 files changed, 78 insertions(+), 26 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index bd4c5064a..6fd96e8ad 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4192,10 +4192,10 @@ boolean SV_SpawnServer(void) SINT8 node = 0; for (; node < MAXNETNODES; node++) result |= SV_AddWaitingPlayers(node, availabilitiesbuffer, - cv_playername[0].zstring, PR_GetLocalPlayerProfile(0)->public_key, SV_RetrievePWR(PR_GetLocalPlayerProfile(0)->public_key), - cv_playername[1].zstring, PR_GetLocalPlayerProfile(1)->public_key, SV_RetrievePWR(PR_GetLocalPlayerProfile(1)->public_key), - cv_playername[2].zstring, PR_GetLocalPlayerProfile(2)->public_key, SV_RetrievePWR(PR_GetLocalPlayerProfile(2)->public_key), - cv_playername[3].zstring, PR_GetLocalPlayerProfile(3)->public_key, SV_RetrievePWR(PR_GetLocalPlayerProfile(3)->public_key)); + cv_playername[0].zstring, PR_GetLocalPlayerProfile(0)->public_key, SV_RetrieveStats(PR_GetLocalPlayerProfile(0)->public_key)->powerlevels, + cv_playername[1].zstring, PR_GetLocalPlayerProfile(1)->public_key, SV_RetrieveStats(PR_GetLocalPlayerProfile(1)->public_key)->powerlevels, + cv_playername[2].zstring, PR_GetLocalPlayerProfile(2)->public_key, SV_RetrieveStats(PR_GetLocalPlayerProfile(2)->public_key)->powerlevels, + cv_playername[3].zstring, PR_GetLocalPlayerProfile(3)->public_key, SV_RetrieveStats(PR_GetLocalPlayerProfile(3)->public_key)->powerlevels); } return result; #endif @@ -4506,10 +4506,10 @@ static void HandleConnect(SINT8 node) } SV_AddWaitingPlayers(node, availabilitiesbuffer, - names[0], lastReceivedKey[node][0], SV_RetrievePWR(lastReceivedKey[node][0]), - names[1], lastReceivedKey[node][1], SV_RetrievePWR(lastReceivedKey[node][1]), - names[2], lastReceivedKey[node][2], SV_RetrievePWR(lastReceivedKey[node][2]), - names[3], lastReceivedKey[node][3], SV_RetrievePWR(lastReceivedKey[node][3])); + names[0], lastReceivedKey[node][0], SV_RetrieveStats(lastReceivedKey[node][0])->powerlevels, + names[1], lastReceivedKey[node][1], SV_RetrieveStats(lastReceivedKey[node][1])->powerlevels, + names[2], lastReceivedKey[node][2], SV_RetrieveStats(lastReceivedKey[node][2])->powerlevels, + names[3], lastReceivedKey[node][3], SV_RetrieveStats(lastReceivedKey[node][3])->powerlevels); joindelay += cv_joindelay.value * TICRATE; player_joining = true; } diff --git a/src/k_serverstats.c b/src/k_serverstats.c index aba804c31..1114ecbb0 100644 --- a/src/k_serverstats.c +++ b/src/k_serverstats.c @@ -17,12 +17,57 @@ #include "m_misc.h" //FIL_WriteFile() #include "k_serverstats.h" #include "z_zone.h" +#include "time.h" -static serverplayer_t trackedList[MAXTRACKEDSERVERPLAYERS]; -static UINT32 numtracked = 0; +static serverplayer_t *trackedList; +static size_t numtracked = 0; +static size_t numallocated = 0; +static boolean initialized = false; UINT16 guestpwr[PWRLV_NUMTYPES]; // All-zero power level to reference for guests +static void SV_InitializeStats(void) +{ + if (!initialized) + { + numallocated = 8; + trackedList = Z_Calloc( + sizeof(serverplayer_t) * numallocated, + PU_STATIC, + &trackedList + ); + + if (trackedList == NULL) + { + I_Error("Not enough memory for server stats\n"); + } + + initialized = true; + } +} + +static void SV_ExpandStats(size_t needed) +{ + I_Assert(trackedList != NULL); + + while (numallocated < needed) + { + numallocated *= numtracked; + trackedList = Z_Realloc( + trackedList, + sizeof(serverplayer_t) * numallocated, + PU_STATIC, + &trackedList + ); + + if (trackedList == NULL) + { + I_Error("Not enough memory for server stats\n"); + } + } + +} + // Read stats file to trackedList for ingame use void SV_LoadStats(void) { @@ -37,6 +82,8 @@ void SV_LoadStats(void) return; } + SV_InitializeStats(); + if (strncmp(SERVERSTATSHEADER, (const char *)save.buffer, headerlen)) { const char *gdfolder = "the Ring Racers folder"; @@ -51,8 +98,8 @@ void SV_LoadStats(void) UINT8 version = READUINT8(save.p); numtracked = READUINT32(save.p); - if (numtracked > MAXTRACKEDSERVERPLAYERS) - numtracked = MAXTRACKEDSERVERPLAYERS; + + SV_ExpandStats(numtracked); READMEM(save.p, trackedList, (numtracked * sizeof(serverplayer_t))); } @@ -95,29 +142,33 @@ void SV_SaveStats(void) } // New player, grab their stats from trackedList or initialize new ones if they're new -UINT16 *SV_RetrievePWR(uint8_t *key) +serverplayer_t *SV_RetrieveStats(uint8_t *key) { UINT32 j; + SV_InitializeStats(); + // Existing record? for(j = 0; j < numtracked; j++) { if (memcmp(trackedList[j].public_key, key, PUBKEYLENGTH) == 0) - { - return trackedList[j].powerlevels; - } + return &trackedList[j]; } - // Untracked, make a new record - memcpy(trackedList[numtracked].public_key, key, PUBKEYLENGTH); + // Untracked below this point, make a new record + SV_ExpandStats(numtracked+1); + + // Default stats + trackedList[numtracked].lastseen = time(NULL); + memcpy(&trackedList[numtracked].public_key, key, PUBKEYLENGTH); for(j = 0; j < PWRLV_NUMTYPES; j++) { trackedList[numtracked].powerlevels[j] = PR_IsKeyGuest(key) ? 0 : PWRLVRECORD_START; } - + numtracked++; - return trackedList[numtracked - 1].powerlevels; + return &trackedList[numtracked - 1]; } // Write player stats to trackedList, then save to disk @@ -128,21 +179,22 @@ void SV_UpdateStats(void) if (!server) return; + SV_InitializeStats(); + for(i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i]) continue; if (PR_IsKeyGuest(players[i].public_key)) - { continue; - } for(j = 0; j < numtracked; j++) { - if (memcmp(trackedList[j].public_key, players[i].public_key, PUBKEYLENGTH) == 0) + if (memcmp(&trackedList[j].public_key, players[i].public_key, PUBKEYLENGTH) == 0) { - memcpy(trackedList[j].powerlevels, clientpowerlevels[i], sizeof(trackedList[j].powerlevels)); + trackedList[j].lastseen = time(NULL); + memcpy(&trackedList[j].powerlevels, clientpowerlevels[i], sizeof(trackedList[j].powerlevels)); break; } } diff --git a/src/k_serverstats.h b/src/k_serverstats.h index 73210095b..143f39892 100644 --- a/src/k_serverstats.h +++ b/src/k_serverstats.h @@ -25,13 +25,13 @@ extern "C" { #endif #define SERVERSTATSFILE "srvstats.dat" -#define MAXTRACKEDSERVERPLAYERS 9999 #define SERVERSTATSHEADER "Doctor Robotnik's Ring Racers Server Stats" #define SERVERSTATSVER 1 struct serverplayer_t { uint8_t public_key[PUBKEYLENGTH]; + time_t lastseen; UINT16 powerlevels[PWRLV_NUMTYPES]; }; @@ -39,7 +39,7 @@ void SV_SaveStats(void); void SV_LoadStats(void); -UINT16 *SV_RetrievePWR(uint8_t *key); +serverplayer_t *SV_RetrieveStats(uint8_t *key); void SV_UpdateStats(void); From a97373cb7a8541012b92fae46d0756bae4a42a47 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 11 Apr 2023 19:49:08 +0100 Subject: [PATCH 09/20] Increment PROFILEVER due to merge conflict resolution --- src/k_profiles.c | 6 +++--- src/k_profiles.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/k_profiles.c b/src/k_profiles.c index 2a7c95350..67a0b822e 100644 --- a/src/k_profiles.c +++ b/src/k_profiles.c @@ -389,8 +389,8 @@ void PR_LoadProfiles(void) profilesList[i]->followercolor = PROFILEDEFAULTFOLLOWERCOLOR; } - // Profile update 4-->5: PWR isn't in profile data anymore. - if (version < 5) + // Profile update 5-->6: PWR isn't in profile data anymore. + if (version < 6) { for (j = 0; j < PWRLV_NUMTYPES; j++) { @@ -419,7 +419,7 @@ void PR_LoadProfiles(void) { #ifdef DEVELOP // Profile update 1-->2: Add gc_rankings. - // Profile update 3-->5: Add gc_startlossless. + // Profile update 4-->5: Add gc_startlossless. if ((j == gc_rankings && version < 2) || (j == gc_startlossless && version < 5)) { diff --git a/src/k_profiles.h b/src/k_profiles.h index 4890a4207..117c91900 100644 --- a/src/k_profiles.h +++ b/src/k_profiles.h @@ -31,7 +31,7 @@ extern "C" { #define SKINNAMESIZE 16 #define PROFILENAMELEN 6 -#define PROFILEVER 5 +#define PROFILEVER 6 #define MAXPROFILES 16 #define PROFILESFILE "ringprofiles.prf" #define PROFILE_GUEST 0 From d61d822231eedaf93fa45f3aba75499e12c8f17e Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 11 Apr 2023 20:02:39 +0100 Subject: [PATCH 10/20] Compilation fixes: Unused variable warnings --- src/d_netcmd.c | 5 ----- src/k_profiles.c | 6 +----- src/k_pwrlv.c | 1 - src/k_serverstats.c | 4 ++-- 4 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d366888b6..8d79971bf 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1955,11 +1955,6 @@ static void Got_LeaveParty(UINT8 **cp,INT32 playernum) void D_SendPlayerConfig(UINT8 n) { - const profile_t *pr = PR_GetProfile(cv_lastprofile[n].value); - - UINT8 buf[4]; - UINT8 *p = buf; - SendNameAndColor(n); WeaponPref_Send(n); } diff --git a/src/k_profiles.c b/src/k_profiles.c index 67a0b822e..630c83af9 100644 --- a/src/k_profiles.c +++ b/src/k_profiles.c @@ -46,7 +46,6 @@ profile_t* PR_MakeProfile( boolean guest) { profile_t *new = Z_Malloc(sizeof(profile_t), PU_STATIC, NULL); - UINT8 i; new->version = PROFILEVER; @@ -392,10 +391,7 @@ void PR_LoadProfiles(void) // Profile update 5-->6: PWR isn't in profile data anymore. if (version < 6) { - for (j = 0; j < PWRLV_NUMTYPES; j++) - { - READUINT16(save.p); - } + save.p += PWRLV_NUMTYPES*2; profilesList[i]->wins = 0; } else diff --git a/src/k_pwrlv.c b/src/k_pwrlv.c index 9e3b3f640..528c7afd0 100644 --- a/src/k_pwrlv.c +++ b/src/k_pwrlv.c @@ -553,7 +553,6 @@ void K_SetPowerLevelScrambles(SINT8 powertype) void K_PlayerForfeit(UINT8 playerNum, boolean pointLoss) { - profile_t *pr; UINT8 p = 0; SINT8 powerType = PWRLV_DISABLED; diff --git a/src/k_serverstats.c b/src/k_serverstats.c index 1114ecbb0..351c69b4d 100644 --- a/src/k_serverstats.c +++ b/src/k_serverstats.c @@ -96,7 +96,8 @@ void SV_LoadStats(void) save.p += headerlen; UINT8 version = READUINT8(save.p); - + (void)version; // for now + numtracked = READUINT32(save.p); SV_ExpandStats(numtracked); @@ -109,7 +110,6 @@ void SV_SaveStats(void) { size_t length = 0; const size_t headerlen = strlen(SERVERSTATSHEADER); - UINT8 i; savebuffer_t save = {0}; if (!server) From d85779c12b731cdf027e2151358b04da6facec92 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 11 Apr 2023 20:05:43 +0100 Subject: [PATCH 11/20] Newlines at end of k_profiles and k_serverstats --- src/k_profiles.c | 1 - src/k_serverstats.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/k_profiles.c b/src/k_profiles.c index 630c83af9..04fbf0b46 100644 --- a/src/k_profiles.c +++ b/src/k_profiles.c @@ -628,4 +628,3 @@ boolean PR_IsKeyGuest(uint8_t *key) { memset(allZero, 0, PUBKEYLENGTH); return (memcmp(key, allZero, PUBKEYLENGTH) == 0); -} \ No newline at end of file diff --git a/src/k_serverstats.c b/src/k_serverstats.c index 351c69b4d..e046dcc4c 100644 --- a/src/k_serverstats.c +++ b/src/k_serverstats.c @@ -204,4 +204,4 @@ void SV_UpdateStats(void) } SV_SaveStats(); -} \ No newline at end of file +} From 86fe3e266b0ff9801a92a6ffbb1131fc31736236 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 11 Apr 2023 20:05:53 +0100 Subject: [PATCH 12/20] allZero doesn't need to be memset --- src/k_profiles.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/k_profiles.c b/src/k_profiles.c index 04fbf0b46..e536f95e3 100644 --- a/src/k_profiles.c +++ b/src/k_profiles.c @@ -622,9 +622,10 @@ char *GetPrettyRRID(const unsigned char *bin, boolean brief) } -char allZero[PUBKEYLENGTH]; +static char allZero[PUBKEYLENGTH]; boolean PR_IsKeyGuest(uint8_t *key) { - memset(allZero, 0, PUBKEYLENGTH); + //memset(allZero, 0, PUBKEYLENGTH); -- not required, allZero is 0's return (memcmp(key, allZero, PUBKEYLENGTH) == 0); +} From df38d6fcde6d258277fa4035f0a6a955116bc778 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 11 Apr 2023 20:07:45 +0100 Subject: [PATCH 13/20] Comment fix --- src/k_profiles.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_profiles.h b/src/k_profiles.h index 117c91900..f0ac07d56 100644 --- a/src/k_profiles.h +++ b/src/k_profiles.h @@ -69,7 +69,7 @@ struct profile_t char follower[SKINNAMESIZE+1]; // Follower UINT16 followercolor; // Follower color - UINT32 wins; // PWRLV for each gametype. + UINT32 wins; // I win I win I win // Player-specific consvars. // @TODO: List all of those From f0658910afcd212f946830ef19f6ac528ace5674 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 11 Apr 2023 22:15:55 -0700 Subject: [PATCH 14/20] Credit in k_serverstats.c --- src/k_serverstats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/k_serverstats.c b/src/k_serverstats.c index e046dcc4c..0bcb500ed 100644 --- a/src/k_serverstats.c +++ b/src/k_serverstats.c @@ -2,6 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 2023 by AJ "Tyron" Martinez // // This program is free software distributed under the // terms of the GNU General Public License, version 2. From 2961629332a48077cbdbdeec7c7004027080d5c4 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 11 Apr 2023 22:24:12 -0700 Subject: [PATCH 15/20] Allow and warn about duplicate pubkeys in DEVELOP --- src/d_clisrv.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 6fd96e8ad..37f0db6f2 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4447,8 +4447,12 @@ static void HandleConnect(SINT8 node) { if (memcmp(lastReceivedKey[node][i], players[j].public_key, PUBKEYLENGTH) == 0) { - SV_SendRefuse(node, M_GetText("Duplicate pubkey already on server.\n(Did you share your profile?)")); - return; + #ifdef DEVELOP + CONS_Alert(CONS_WARNING, "Joining player's pubkey matches existing player, stat updates will be nonsense!\n"); + #else + SV_SendRefuse(node, M_GetText("Duplicate pubkey already on server.\n(Did you share your profile?)")); + return; + #endif } } @@ -4461,8 +4465,12 @@ static void HandleConnect(SINT8 node) continue; if (memcmp(lastReceivedKey[node][i], lastReceivedKey[node][j], PUBKEYLENGTH) == 0) { - SV_SendRefuse(node, M_GetText("Duplicate pubkey in local party.\n(How did you even do this?)")); - return; + #ifdef DEVELOP + CONS_Alert(CONS_WARNING, "Players with same pubkey in the joning party, stat updates will be nonsense!\n"); + #else + SV_SendRefuse(node, M_GetText("Duplicate pubkey in local party.\n(How did you even do this?)")); + return; + #endif } } } From 44848717df1f4ebfb6f9739e65151cb780b6d85a Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 11 Apr 2023 22:27:13 -0700 Subject: [PATCH 16/20] Credit in k_serverstats.h --- src/k_serverstats.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/k_serverstats.h b/src/k_serverstats.h index 143f39892..636e48dc9 100644 --- a/src/k_serverstats.h +++ b/src/k_serverstats.h @@ -4,6 +4,7 @@ // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2011-2016 by Matthew "Inuyasha" Walsh. // Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 2023 by AJ "Tyron" Martinez // // This program is free software distributed under the // terms of the GNU General Public License, version 2. From 515e0baa01c9c4328555da2b26ea067f35e979c1 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 11 Apr 2023 22:55:13 -0700 Subject: [PATCH 17/20] Do serverstats file I/O entry by entry --- src/k_serverstats.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/k_serverstats.c b/src/k_serverstats.c index 0bcb500ed..b3b259361 100644 --- a/src/k_serverstats.c +++ b/src/k_serverstats.c @@ -74,6 +74,7 @@ void SV_LoadStats(void) { const size_t headerlen = strlen(SERVERSTATSHEADER); savebuffer_t save = {0}; + unsigned int i, j; if (!server) return; @@ -103,7 +104,15 @@ void SV_LoadStats(void) SV_ExpandStats(numtracked); - READMEM(save.p, trackedList, (numtracked * sizeof(serverplayer_t))); + for(i = 0; i < numtracked; i++) + { + READMEM(save.p, trackedList[i].public_key, PUBKEYLENGTH); + READMEM(save.p, &trackedList[i].lastseen, sizeof(trackedList[i].lastseen)); + for(j = 0; j < PWRLV_NUMTYPES; j++) + { + trackedList[i].powerlevels[j] = READUINT16(save.p); + } + } } // Save trackedList to disc @@ -112,6 +121,7 @@ void SV_SaveStats(void) size_t length = 0; const size_t headerlen = strlen(SERVERSTATSHEADER); savebuffer_t save = {0}; + unsigned int i, j; if (!server) return; @@ -130,7 +140,15 @@ void SV_SaveStats(void) WRITEUINT32(save.p, numtracked); - WRITEMEM(save.p, trackedList, (numtracked * sizeof(serverplayer_t))); + for(i = 0; i < numtracked; i++) + { + WRITEMEM(save.p, trackedList[i].public_key, PUBKEYLENGTH); + WRITEMEM(save.p, &trackedList[i].lastseen, sizeof(trackedList[i].lastseen)); + for(j = 0; j < PWRLV_NUMTYPES; j++) + { + WRITEUINT16(save.p, trackedList[i].powerlevels[j]); + } + } length = save.p - save.buffer; From 2426170e0bd6270292c27523ca982a7e67331ee9 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 11 Apr 2023 23:09:40 -0700 Subject: [PATCH 18/20] Hash pubkeys for early out during stat retrieval --- src/k_serverstats.c | 16 +++++++++++++--- src/k_serverstats.h | 2 ++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/k_serverstats.c b/src/k_serverstats.c index b3b259361..a71bcca4f 100644 --- a/src/k_serverstats.c +++ b/src/k_serverstats.c @@ -112,6 +112,7 @@ void SV_LoadStats(void) { trackedList[i].powerlevels[j] = READUINT16(save.p); } + trackedList[i].hash = quickncasehash((char*)trackedList[i].public_key, PUBKEYLENGTH); } } @@ -163,13 +164,17 @@ void SV_SaveStats(void) // New player, grab their stats from trackedList or initialize new ones if they're new serverplayer_t *SV_RetrieveStats(uint8_t *key) { - UINT32 j; + UINT32 j, hash; SV_InitializeStats(); + hash = quickncasehash((char*)key, PUBKEYLENGTH); + // Existing record? for(j = 0; j < numtracked; j++) { + if (hash != trackedList[j].hash) // Not crypto magic, just an early out with a faster comparison + continue; if (memcmp(trackedList[j].public_key, key, PUBKEYLENGTH) == 0) return &trackedList[j]; } @@ -184,6 +189,7 @@ serverplayer_t *SV_RetrieveStats(uint8_t *key) { trackedList[numtracked].powerlevels[j] = PR_IsKeyGuest(key) ? 0 : PWRLVRECORD_START; } + trackedList[numtracked].hash = quickncasehash((char*)key, PUBKEYLENGTH); numtracked++; @@ -193,7 +199,7 @@ serverplayer_t *SV_RetrieveStats(uint8_t *key) // Write player stats to trackedList, then save to disk void SV_UpdateStats(void) { - UINT32 i, j; + UINT32 i, j, hash; if (!server) return; @@ -208,8 +214,12 @@ void SV_UpdateStats(void) if (PR_IsKeyGuest(players[i].public_key)) continue; + hash = quickncasehash((char*)players[i].public_key, PUBKEYLENGTH); + for(j = 0; j < numtracked; j++) - { + { + if (hash != trackedList[j].hash) // Not crypto magic, just an early out with a faster comparison + continue; if (memcmp(&trackedList[j].public_key, players[i].public_key, PUBKEYLENGTH) == 0) { trackedList[j].lastseen = time(NULL); diff --git a/src/k_serverstats.h b/src/k_serverstats.h index 636e48dc9..313582e85 100644 --- a/src/k_serverstats.h +++ b/src/k_serverstats.h @@ -34,6 +34,8 @@ struct serverplayer_t uint8_t public_key[PUBKEYLENGTH]; time_t lastseen; UINT16 powerlevels[PWRLV_NUMTYPES]; + + UINT32 hash; // Not persisted! Used for early outs during key comparisons }; void SV_SaveStats(void); From 2b8f71bec5b341fd512ca4fa189684ac72dedf66 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 11 Apr 2023 23:11:23 -0700 Subject: [PATCH 19/20] It's probably bad to allocate exponential memory --- src/k_serverstats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_serverstats.c b/src/k_serverstats.c index a71bcca4f..7959d3dc5 100644 --- a/src/k_serverstats.c +++ b/src/k_serverstats.c @@ -53,7 +53,7 @@ static void SV_ExpandStats(size_t needed) while (numallocated < needed) { - numallocated *= numtracked; + numallocated *= 2; trackedList = Z_Realloc( trackedList, sizeof(serverplayer_t) * numallocated, From 4f2dccbf7243279265d2d23b07d987cb898b69f1 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 12 Apr 2023 02:51:48 -0700 Subject: [PATCH 20/20] Use UINT32 time_t --- src/k_serverstats.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_serverstats.h b/src/k_serverstats.h index 313582e85..d739a5185 100644 --- a/src/k_serverstats.h +++ b/src/k_serverstats.h @@ -32,7 +32,7 @@ extern "C" { struct serverplayer_t { uint8_t public_key[PUBKEYLENGTH]; - time_t lastseen; + UINT32 lastseen; UINT16 powerlevels[PWRLV_NUMTYPES]; UINT32 hash; // Not persisted! Used for early outs during key comparisons