engine: command: introduce new type of commands that can be overriden by a mod DLL for better compatibility

This commit is contained in:
Alibek Omarov 2024-12-26 01:15:32 +03:00
parent 65750f0cf3
commit 0e42e5b9e3
2 changed files with 39 additions and 21 deletions

View file

@ -518,14 +518,14 @@ static void Cmd_UnAlias_f ( void )
============================================================================= =============================================================================
*/ */
typedef struct cmd_s struct cmd_s
{ {
struct cmd_s *next; struct cmd_s *next;
char *name; char *name;
xcommand_t function; xcommand_t function;
int flags; int flags;
char *desc; char *desc;
} cmd_t; };
static int cmd_argc; static int cmd_argc;
static const char *cmd_args = NULL; static const char *cmd_args = NULL;
@ -693,11 +693,28 @@ int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd
return 0; return 0;
} }
// fail if the command already exists // fail if the command already exists and cannot be overriden
if( Cmd_Exists( cmd_name )) cmd = Cmd_Exists( cmd_name );
if( cmd )
{ {
Con_DPrintf( S_ERROR "%s: %s already defined\n", funcname, cmd_name ); // some mods register commands that share the name with some engine's commands
return 0; // when they aren't critical to keep engine running, we can let mods to override them
// unfortunately, we lose original command this way
if( FBitSet( cmd->flags, CMD_OVERRIDABLE ))
{
Mem_Free( cmd->desc );
cmd->desc = copystring( cmd_desc );
cmd->function = function;
cmd->flags = iFlags;
Con_DPrintf( S_WARN "%s: %s already defined but is allowed to be overriden\n", funcname, cmd_name );
return 1;
}
else
{
Con_DPrintf( S_ERROR "%s: %s already defined\n", funcname, cmd_name );
return 0;
}
} }
// use a small malloc to avoid zone fragmentation // use a small malloc to avoid zone fragmentation
@ -789,19 +806,18 @@ void Cmd_LookupCmds( void *buffer, void *ptr, setpair_t callback )
Cmd_Exists Cmd_Exists
============ ============
*/ */
qboolean Cmd_Exists( const char *cmd_name ) cmd_t *Cmd_Exists( const char *cmd_name )
{ {
#if defined(XASH_HASHED_VARS) #if defined(XASH_HASHED_VARS)
return BaseCmd_Find( HM_CMD, cmd_name ) != NULL; return BaseCmd_Find( HM_CMD, cmd_name );
#else #else
cmd_t *cmd; cmd_t *cmd;
for( cmd = cmd_functions; cmd; cmd = cmd->next ) for( cmd = cmd_functions; cmd; cmd = cmd->next )
{ {
if( !Q_strcmp( cmd_name, cmd->name )) if( !Q_strcmp( cmd_name, cmd->name ))
return true; return cmd;
} }
return false; return NULL;
#endif #endif
} }

View file

@ -362,12 +362,13 @@ typedef struct host_parm_s
extern host_parm_t host; extern host_parm_t host;
#define CMD_SERVERDLL BIT( 0 ) // added by server.dll #define CMD_SERVERDLL BIT( 0 ) // added by server.dll
#define CMD_CLIENTDLL BIT( 1 ) // added by client.dll #define CMD_CLIENTDLL BIT( 1 ) // added by client.dll
#define CMD_GAMEUIDLL BIT( 2 ) // added by GameUI.dll #define CMD_GAMEUIDLL BIT( 2 ) // added by GameUI.dll
#define CMD_PRIVILEGED BIT( 3 ) // only available in privileged mode #define CMD_PRIVILEGED BIT( 3 ) // only available in privileged mode
#define CMD_FILTERABLE BIT( 4 ) // filtered in unprivileged mode if cl_filterstuffcmd is 1 #define CMD_FILTERABLE BIT( 4 ) // filtered in unprivileged mode if cl_filterstuffcmd is 1
#define CMD_REFDLL BIT( 5 ) // added by ref.dll #define CMD_REFDLL BIT( 5 ) // added by ref.dll
#define CMD_OVERRIDABLE BIT( 6 ) // can be removed by DLLs if name matches
typedef void (*xcommand_t)( void ); typedef void (*xcommand_t)( void );
@ -418,6 +419,7 @@ byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr )
// //
// cmd.c // cmd.c
// //
typedef struct cmd_s cmd_t;
void Cbuf_Clear( void ); void Cbuf_Clear( void );
void Cbuf_AddText( const char *text ); void Cbuf_AddText( const char *text );
void Cbuf_AddTextf( const char *text, ... ) FORMAT_CHECK( 1 ); void Cbuf_AddTextf( const char *text, ... ) FORMAT_CHECK( 1 );
@ -431,7 +433,7 @@ const char *Cmd_Args( void ) RETURNS_NONNULL;
const char *Cmd_Argv( int arg ) RETURNS_NONNULL; const char *Cmd_Argv( int arg ) RETURNS_NONNULL;
void Cmd_Init( void ); void Cmd_Init( void );
void Cmd_Unlink( int group ); void Cmd_Unlink( int group );
int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int iFlags, const char *funcname ); int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int flags, const char *funcname );
static inline int Cmd_AddCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc ) static inline int Cmd_AddCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc )
{ {
@ -443,13 +445,13 @@ static inline int Cmd_AddRestrictedCommand( const char *cmd_name, xcommand_t fun
return Cmd_AddCommandEx( cmd_name, function, cmd_desc, CMD_PRIVILEGED, __func__ ); return Cmd_AddCommandEx( cmd_name, function, cmd_desc, CMD_PRIVILEGED, __func__ );
} }
static inline int Cmd_AddFilteredCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc ) static inline int Cmd_AddCommandWithFlags( const char *cmd_name, xcommand_t function, const char *cmd_desc, int flags )
{ {
return Cmd_AddCommandEx( cmd_name, function, cmd_desc, CMD_FILTERABLE, __func__ ); return Cmd_AddCommandEx( cmd_name, function, cmd_desc, flags, __func__ );
} }
void Cmd_RemoveCommand( const char *cmd_name ); void Cmd_RemoveCommand( const char *cmd_name );
qboolean Cmd_Exists( const char *cmd_name ); cmd_t *Cmd_Exists( const char *cmd_name );
void Cmd_LookupCmds( void *buffer, void *ptr, setpair_t callback ); void Cmd_LookupCmds( void *buffer, void *ptr, setpair_t callback );
int Cmd_ListMaps( search_t *t , char *lastmapname, size_t len ); int Cmd_ListMaps( search_t *t , char *lastmapname, size_t len );
void Cmd_TokenizeString( const char *text ); void Cmd_TokenizeString( const char *text );