diff --git a/engine/common/cmd.c b/engine/common/cmd.c index b909a669..6cf4a83c 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -518,14 +518,14 @@ static void Cmd_UnAlias_f ( void ) ============================================================================= */ -typedef struct cmd_s +struct cmd_s { struct cmd_s *next; char *name; xcommand_t function; int flags; char *desc; -} cmd_t; +}; static int cmd_argc; 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; } - // fail if the command already exists - if( Cmd_Exists( cmd_name )) + // fail if the command already exists and cannot be overriden + cmd = Cmd_Exists( cmd_name ); + if( cmd ) { - Con_DPrintf( S_ERROR "%s: %s already defined\n", funcname, cmd_name ); - return 0; + // some mods register commands that share the name with some engine's commands + // 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 @@ -789,19 +806,18 @@ void Cmd_LookupCmds( void *buffer, void *ptr, setpair_t callback ) Cmd_Exists ============ */ -qboolean Cmd_Exists( const char *cmd_name ) +cmd_t *Cmd_Exists( const char *cmd_name ) { #if defined(XASH_HASHED_VARS) - return BaseCmd_Find( HM_CMD, cmd_name ) != NULL; + return BaseCmd_Find( HM_CMD, cmd_name ); #else cmd_t *cmd; - for( cmd = cmd_functions; cmd; cmd = cmd->next ) { if( !Q_strcmp( cmd_name, cmd->name )) - return true; + return cmd; } - return false; + return NULL; #endif } diff --git a/engine/common/common.h b/engine/common/common.h index 72a486c0..28298bc9 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -362,12 +362,13 @@ typedef struct host_parm_s extern host_parm_t host; -#define CMD_SERVERDLL BIT( 0 ) // added by server.dll -#define CMD_CLIENTDLL BIT( 1 ) // added by client.dll -#define CMD_GAMEUIDLL BIT( 2 ) // added by GameUI.dll -#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_REFDLL BIT( 5 ) // added by ref.dll +#define CMD_SERVERDLL BIT( 0 ) // added by server.dll +#define CMD_CLIENTDLL BIT( 1 ) // added by client.dll +#define CMD_GAMEUIDLL BIT( 2 ) // added by GameUI.dll +#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_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 ); @@ -418,6 +419,7 @@ byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr ) // // cmd.c // +typedef struct cmd_s cmd_t; void Cbuf_Clear( void ); void Cbuf_AddText( const char *text ); 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; void Cmd_Init( void ); 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 ) { @@ -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__ ); } -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 ); -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 ); int Cmd_ListMaps( search_t *t , char *lastmapname, size_t len ); void Cmd_TokenizeString( const char *text );