From 8c25336b7fee4b120c5330b00fb4bfc94ad24365 Mon Sep 17 00:00:00 2001 From: Aciz Date: Wed, 20 May 2026 12:42:10 +0300 Subject: [PATCH] Add support for extended CMD_BACKUP/MASK Support doubling 'CMD_BACKUP/MASK' buffers with 'CG_CMDBACKUP_EXT' engine extension. This allows mods to request a higher buffers for user commands, increasing the maximum FPS that clients can use before high FPS combined with high ping will start dropping user commands. The cgame import value matches what ET: Legacy uses, for interoperability with ETe + legacy mod, and to make it such that mods don't need to add support for both explicitly. --- src/cgame/cg_public.h | 5 +++++ src/client/cl_cgame.c | 14 ++++++++++++-- src/client/cl_input.c | 4 ++-- src/client/cl_main.c | 3 +++ src/client/client.h | 9 ++++++--- 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/cgame/cg_public.h b/src/cgame/cg_public.h index 16853369..186b5992 100644 --- a/src/cgame/cg_public.h +++ b/src/cgame/cg_public.h @@ -30,6 +30,9 @@ If you have questions concerning this license or the applicable additional terms #define CMD_BACKUP 64 #define CMD_MASK ( CMD_BACKUP - 1 ) + +#define CMD_BACKUP_EXT 128 +#define CMD_MASK_EXT ( CMD_BACKUP_EXT - 1 ) // allow a lot of command backups for very fast systems // multiple commands may be combined into a single packet, so this // needs to be larger than PACKET_BACKUP @@ -273,6 +276,8 @@ typedef enum { CG_R_ADDLINEARLIGHTTOSCENE, CG_PC_REMOVE_ALL_GLOBAL_DEFINES, CG_GETCLIPBOARDDATA, + CG_CMDBACKUP_EXT, + CG_TRAP_GETVALUE = COM_TRAP_GETVALUE, #endif diff --git a/src/client/cl_cgame.c b/src/client/cl_cgame.c index c4e3e63a..f751e11f 100644 --- a/src/client/cl_cgame.c +++ b/src/client/cl_cgame.c @@ -124,11 +124,11 @@ static qboolean CL_GetUserCmd( int cmdNumber, usercmd_t *ucmd ) { // the usercmd has been overwritten in the wrapping // buffer because it is too far out of date - if ( cl.cmdNumber - cmdNumber >= CMD_BACKUP ) { + if ( cl.cmdNumber - cmdNumber >= cl.cmdBackup ) { return qfalse; } - *ucmd = cl.cmds[ cmdNumber & CMD_MASK ]; + *ucmd = cl.cmds[ cmdNumber & cl.cmdMask ]; return qtrue; } @@ -684,6 +684,11 @@ static qboolean CL_CG_GetValue( char* value, int valueSize, const char* key ) { return qtrue; } + if ( !Q_stricmp( key, "trap_CmdBackup_Ext_Legacy" ) ) { + Com_sprintf( value, valueSize, "%i", CG_CMDBACKUP_EXT ); + return qtrue; + } + return qfalse; } @@ -1200,6 +1205,11 @@ static intptr_t CL_CgameSystemCalls( intptr_t *args ) { CL_GetClipboardData( VMA(1), args[2] ); return 0; + case CG_CMDBACKUP_EXT: + cl.cmdBackup = CMD_BACKUP_EXT; + cl.cmdMask = CMD_MASK_EXT; + return 0; + case CG_TRAP_GETVALUE: return CL_CG_GetValue( VMA(1), args[2], VMA(3) ); diff --git a/src/client/cl_input.c b/src/client/cl_input.c index 4a255383..3c9ffd5a 100644 --- a/src/client/cl_input.c +++ b/src/client/cl_input.c @@ -779,7 +779,7 @@ static void CL_CreateNewCommands( void ) { // generate a command for this frame cl.cmdNumber++; - cmdNum = cl.cmdNumber & CMD_MASK; + cmdNum = cl.cmdNumber & cl.cmdMask; cl.cmds[cmdNum] = CL_CreateCmd(); } @@ -939,7 +939,7 @@ void CL_WritePacket( void ) { // write all the commands, including the predicted command for ( i = 0 ; i < count ; i++ ) { - j = (cl.cmdNumber - count + i + 1) & CMD_MASK; + j = (cl.cmdNumber - count + i + 1) & cl.cmdMask; cmd = &cl.cmds[j]; MSG_WriteDeltaUsercmdKey (&buf, key, oldcmd, cmd); oldcmd = cmd; diff --git a/src/client/cl_main.c b/src/client/cl_main.c index 00077059..8078228f 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -1309,6 +1309,9 @@ void CL_ClearState( void ) { // S_StopAllSounds(); Com_Memset( &cl, 0, sizeof( cl ) ); + + cl.cmdBackup = CMD_BACKUP; + cl.cmdMask = CMD_MASK; } /* diff --git a/src/client/client.h b/src/client/client.h index 13156836..707346ea 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -157,9 +157,12 @@ typedef struct { // cmds[cmdNumber] is the predicted command, [cmdNumber-1] is the last // properly generated command - usercmd_t cmds[CMD_BACKUP]; // each mesage will send several old cmds - int cmdNumber; // incremented each frame, because multiple - // frames may need to be packed into a single packet + usercmd_t cmds[CMD_BACKUP_EXT]; // each mesage will send several old cmds + int cmdNumber; // incremented each frame, because multiple + // frames may need to be packed into a single packet + + int cmdBackup; + int cmdMask; // Arnout: double tapping doubleTap_t doubleTap;