Browse Source

Add basecmd from old engine. Add basecmd_stats command

pull/2/head
Alibek Omarov 7 years ago
parent
commit
0561ac2076
  1. 2
      contib/a1batross/xash3d.files
  2. 2
      engine/client/cl_main.c
  3. 229
      engine/common/base_cmd.c
  4. 58
      engine/common/base_cmd.h
  5. 46
      engine/common/cmd.c
  6. 10
      engine/common/cvar.c
  7. 2
      engine/common/cvar.h
  8. 3
      engine/common/host.c

2
contib/a1batross/xash3d.files

@ -108,6 +108,8 @@ engine/client/vgui/vgui_draw.h
engine/client/vid_common.c engine/client/vid_common.c
engine/client/vid_common.h engine/client/vid_common.h
engine/client/vox.h engine/client/vox.h
engine/common/base_cmd.c
engine/common/base_cmd.h
engine/common/build.c engine/common/build.c
engine/common/cfgscript.c engine/common/cfgscript.c
engine/common/cmd.c engine/common/cmd.c

2
engine/client/cl_main.c

@ -83,6 +83,8 @@ client_t cl;
client_static_t cls; client_static_t cls;
clgame_static_t clgame; clgame_static_t clgame;
void CL_InternetServers_f( void );
//====================================================================== //======================================================================
int CL_Active( void ) int CL_Active( void )
{ {

229
engine/common/base_cmd.c

@ -0,0 +1,229 @@
/*
base_cmd.c - command & cvar hashmap. Insipred by Doom III
Copyright (C) 2016 a1batross
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "common.h"
#include "base_cmd.h"
// TODO: use another hash function, as COM_HashKey depends on string length
#define HASH_SIZE 128 // 128 * 4 * 4 == 2048 bytes
static base_command_hashmap_t *hashed_cmds[HASH_SIZE];
/*
============
BaseCmd_FindInBucket
Find base command in bucket
============
*/
base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name )
{
base_command_hashmap_t *i = bucket;
for( ; i && ( i->type != type || Q_stricmp( name, i->name ) ); // filter out
i = i->next );
return i;
}
/*
============
BaseCmd_GetBucket
Get bucket which contain basecmd by given name
============
*/
base_command_hashmap_t *BaseCmd_GetBucket( const char *name )
{
return hashed_cmds[ COM_HashKey( name, HASH_SIZE ) ];
}
/*
============
BaseCmd_Find
Find base command in hashmap
============
*/
base_command_t *BaseCmd_Find( base_command_type_e type, const char *name )
{
base_command_hashmap_t *base = BaseCmd_GetBucket( name );
base_command_hashmap_t *found = BaseCmd_FindInBucket( base, type, name );
if( found )
return found->basecmd;
return NULL;
}
/*
============
BaseCmd_Find
Find every type of base command and write into arguments
============
*/
void BaseCmd_FindAll(const char *name, base_command_t **cmd, base_command_t **alias, base_command_t **cvar)
{
base_command_hashmap_t *base = BaseCmd_GetBucket( name );
base_command_hashmap_t *i = base;
ASSERT( cmd && alias && cvar );
*cmd = *alias = *cvar = NULL;
for( ; i; i = i->next )
{
if( !Q_stricmp( i->name, name ) )
{
switch( i->type )
{
case HM_CMD:
*cmd = i->basecmd;
break;
case HM_CMDALIAS:
*alias = i->basecmd;
break;
case HM_CVAR:
*cvar = i->basecmd;
break;
default: break;
}
}
}
}
/*
============
BaseCmd_Insert
Add new typed base command to hashmap
============
*/
void BaseCmd_Insert( base_command_type_e type, base_command_t *basecmd, const char *name )
{
uint hash = COM_HashKey( name, HASH_SIZE );
base_command_hashmap_t *elem;
elem = Z_Malloc( sizeof( base_command_hashmap_t ) );
elem->basecmd = basecmd;
elem->type = type;
elem->name = name;
elem->next = hashed_cmds[hash];
hashed_cmds[hash] = elem;
}
/*
============
BaseCmd_Replace
Used in case, when basecmd has been registered, but gamedll wants to register it's own
============
*/
qboolean BaseCmd_Replace( base_command_type_e type, base_command_t *basecmd, const char *name )
{
base_command_hashmap_t *i = BaseCmd_GetBucket( name );
for( ; i && ( i->type != type || Q_stricmp( name, i->name ) ) ; // filter out
i = i->next );
if( !i )
{
MsgDev( D_ERROR, "BaseCmd_Replace: couldn't find %s\n", name);
return false;
}
i->basecmd = basecmd;
i->name = name; // may be freed after
return true;
}
/*
============
BaseCmd_Remove
Remove base command from hashmap
============
*/
void BaseCmd_Remove( base_command_type_e type, const char *name )
{
uint hash = COM_HashKey( name, HASH_SIZE );
base_command_hashmap_t *i, *prev;
for( prev = NULL, i = hashed_cmds[hash]; i &&
( Q_strcmp( i->name, name ) || i->type != type); // filter out
prev = i, i = i->next );
if( !i )
{
MsgDev( D_ERROR, "Couldn't find %s in buckets\n", name );
return;
}
if( prev )
prev->next = i->next;
else
hashed_cmds[hash] = i->next;
Z_Free( i );
}
/*
============
BaseCmd_Init
initialize base command hashmap system
============
*/
void BaseCmd_Init( void )
{
memset( hashed_cmds, 0, sizeof( hashed_cmds ) );
}
/*
============
BaseCmd_Stats_f
============
*/
void BaseCmd_Stats_f( void )
{
int i, minsize = 99999, maxsize = -1, empty = 0;
for( i = 0; i < HASH_SIZE; i++ )
{
base_command_hashmap_t *hm;
int len = 0;
// count bucket length
for( hm = hashed_cmds[i]; hm; hm = hm->next, len++ );
if( len == 0 )
{
empty++;
continue;
}
if( len < minsize )
minsize = len;
if( len > maxsize )
maxsize = len;
}
Con_Printf( "Base command stats:\n");
Con_Printf( "Bucket minimal length: %d\n", minsize );
Con_Printf( "Bucket maximum length: %d\n", maxsize );
Con_Printf( "Empty buckets: %d\n", empty );
}

58
engine/common/base_cmd.h

@ -0,0 +1,58 @@
/*
base_cmd.h - command & cvar hashmap. Insipred by Doom III
Copyright (C) 2016 a1batross
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#pragma once
#ifndef BASE_CMD_H
#define BASE_CMD_H
// TODO: Find cases when command hashmap works incorrect
// and maybe disable it
#define XASH_HASHED_VARS
#ifdef XASH_HASHED_VARS
typedef enum base_command_type
{
HM_DONTCARE = 0,
HM_CVAR,
HM_CMD,
HM_CMDALIAS
} base_command_type_e;
typedef void base_command_t;
typedef struct base_command_hashmap_s
{
base_command_t *basecmd; // base command: cvar, alias or command
const char *name; // key for searching
base_command_type_e type; // type for faster searching
struct base_command_hashmap_s *next;
} base_command_hashmap_t;
void BaseCmd_Init( void );
base_command_hashmap_t *BaseCmd_GetBucket( const char *name );
base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name );
base_command_t *BaseCmd_Find( base_command_type_e type, const char *name );
void BaseCmd_FindAll( const char *name,
base_command_t **cmd, base_command_t **alias, base_command_t **cvar );
void BaseCmd_Insert ( base_command_type_e type, base_command_t *basecmd, const char *name );
qboolean BaseCmd_Replace( base_command_type_e type, base_command_t *basecmd, const char *name ); // only if same name
void BaseCmd_Remove ( base_command_type_e type, const char *name );
void BaseCmd_Stats_f( void ); // to be registered later
#endif // XASH_HASHED_VARS
#endif // BASE_CMD_H

46
engine/common/cmd.c

@ -16,6 +16,7 @@ GNU General Public License for more details.
#include "common.h" #include "common.h"
#include "client.h" #include "client.h"
#include "server.h" #include "server.h"
#include "base_cmd.h"
#define MAX_CMD_BUFFER 32768 #define MAX_CMD_BUFFER 32768
#define MAX_CMD_LINE 2048 #define MAX_CMD_LINE 2048
@ -380,6 +381,10 @@ void Cmd_Alias_f( void )
if( prev ) prev->next = a; if( prev ) prev->next = a;
else cmd_alias = a; else cmd_alias = a;
a->next = cur; a->next = cur;
#if defined( XASH_HASHED_VARS )
BaseCmd_Insert( HM_CMDALIAS, a, a->name );
#endif
} }
// copy the rest of the command line // copy the rest of the command line
@ -425,6 +430,9 @@ static void Cmd_UnAlias_f ( void )
{ {
if( !Q_strcmp( s, a->name )) if( !Q_strcmp( s, a->name ))
{ {
#if defined( XASH_HASHED_VARS )
BaseCmd_Remove( HM_CMDALIAS, a->name );
#endif
if( a == cmd_alias ) if( a == cmd_alias )
cmd_alias = a->next; cmd_alias = a->next;
if( p ) p->next = a->next; if( p ) p->next = a->next;
@ -722,6 +730,10 @@ void Cmd_RemoveCommand( const char *cmd_name )
if( !Q_strcmp( cmd_name, cmd->name )) if( !Q_strcmp( cmd_name, cmd->name ))
{ {
#if defined(XASH_HASHED_VARS)
BaseCmd_Remove( HM_CMD, cmd->name );
#endif
*back = cmd->next; *back = cmd->next;
if( cmd->name ) if( cmd->name )
@ -768,6 +780,9 @@ Cmd_Exists
*/ */
qboolean Cmd_Exists( const char *cmd_name ) qboolean Cmd_Exists( const char *cmd_name )
{ {
#if defined(XASH_HASHED_VARS)
return BaseCmd_Find( HM_CMD, cmd_name ) != NULL;
#else
cmd_t *cmd; cmd_t *cmd;
for( cmd = cmd_functions; cmd; cmd = cmd->next ) for( cmd = cmd_functions; cmd; cmd = cmd->next )
@ -776,6 +791,7 @@ qboolean Cmd_Exists( const char *cmd_name )
return true; return true;
} }
return false; return false;
#endif
} }
/* /*
@ -860,8 +876,9 @@ A complete command line has been parsed, so try to execute it
*/ */
void Cmd_ExecuteString( char *text ) void Cmd_ExecuteString( char *text )
{ {
cmd_t *cmd; cmd_t *cmd = NULL;
cmdalias_t *a; cmdalias_t *a = NULL;
convar_t *cvar = NULL;
char command[MAX_CMD_LINE]; char command[MAX_CMD_LINE];
char *pcmd = command; char *pcmd = command;
int len = 0; int len = 0;
@ -916,9 +933,22 @@ void Cmd_ExecuteString( char *text )
if( !Cmd_Argc( )) return; // no tokens if( !Cmd_Argc( )) return; // no tokens
#if defined(XASH_HASHED_VARS)
BaseCmd_FindAll( cmd_argv[0],
(base_command_t**)&cmd,
(base_command_t**)&a,
(base_command_t**)&cvar );
#endif
if( !host.apply_game_config ) if( !host.apply_game_config )
{ {
// check aliases // check aliases
if( a ) // already found in basecmd
{
Cbuf_InsertText( a->value );
return;
}
for( a = cmd_alias; a; a = a->next ) for( a = cmd_alias; a; a = a->next )
{ {
if( !Q_stricmp( cmd_argv[0], a->name )) if( !Q_stricmp( cmd_argv[0], a->name ))
@ -933,6 +963,12 @@ void Cmd_ExecuteString( char *text )
if( !host.apply_game_config || !Q_strcmp( cmd_argv[0], "exec" )) if( !host.apply_game_config || !Q_strcmp( cmd_argv[0], "exec" ))
{ {
// check functions // check functions
if( cmd && cmd->function ) // already found in basecmd
{
cmd->function();
return;
}
for( cmd = cmd_functions; cmd; cmd = cmd->next ) for( cmd = cmd_functions; cmd; cmd = cmd->next )
{ {
if( !Q_stricmp( cmd_argv[0], cmd->name ) && cmd->function ) if( !Q_stricmp( cmd_argv[0], cmd->name ) && cmd->function )
@ -944,7 +980,7 @@ void Cmd_ExecuteString( char *text )
} }
// check cvars // check cvars
if( Cvar_Command( )) return; if( Cvar_Command( cvar )) return;
if( host.apply_game_config ) if( host.apply_game_config )
return; // don't send nothing to server: we is a server! return; // don't send nothing to server: we is a server!
@ -1125,4 +1161,8 @@ void Cmd_Init( void )
Cmd_AddCommand( "unalias", Cmd_UnAlias_f, "remove a script function" ); Cmd_AddCommand( "unalias", Cmd_UnAlias_f, "remove a script function" );
Cmd_AddCommand( "if", Cmd_If_f, "compare and set condition bits" ); Cmd_AddCommand( "if", Cmd_If_f, "compare and set condition bits" );
Cmd_AddCommand( "else", Cmd_Else_f, "invert condition bit" ); Cmd_AddCommand( "else", Cmd_Else_f, "invert condition bit" );
#if defined(XASH_HASHED_VARS)
Cmd_AddCommand( "basecmd_stats", BaseCmd_Stats_f, "print info about basecmd usage" );
#endif
} }

10
engine/common/cvar.c

@ -13,8 +13,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#include <math.h> // fabs...
#include "common.h" #include "common.h"
#include "math.h" // fabs... #include "base_cmd.h"
convar_t *cvar_vars = NULL; // head of list convar_t *cvar_vars = NULL; // head of list
convar_t *cmd_scripting; convar_t *cmd_scripting;
@ -690,10 +691,8 @@ Cvar_Command
Handles variable inspection and changing from the console Handles variable inspection and changing from the console
============ ============
*/ */
qboolean Cvar_Command( void ) qboolean Cvar_Command( convar_t *v )
{ {
convar_t *v;
// special case for setup opengl configuration // special case for setup opengl configuration
if( host.apply_opengl_config ) if( host.apply_opengl_config )
{ {
@ -702,7 +701,8 @@ qboolean Cvar_Command( void )
} }
// check variables // check variables
v = Cvar_FindVar( Cmd_Argv( 0 )); if( !v ) // already found in basecmd
v = Cvar_FindVar( Cmd_Argv( 0 ));
if( !v ) return false; if( !v ) return false;
// perform a variable print or set // perform a variable print or set

2
engine/common/cvar.h

@ -66,7 +66,7 @@ const char *Cvar_VariableString( const char *var_name );
void Cvar_WriteVariables( file_t *f, int group ); void Cvar_WriteVariables( file_t *f, int group );
void Cvar_Reset( const char *var_name ); void Cvar_Reset( const char *var_name );
void Cvar_SetCheatState( void ); void Cvar_SetCheatState( void );
qboolean Cvar_Command( void ); qboolean Cvar_Command( convar_t *v );
void Cvar_Init( void ); void Cvar_Init( void );
void Cvar_Unlink( int group ); void Cvar_Unlink( int group );

3
engine/common/host.c

@ -822,6 +822,9 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
// init host state machine // init host state machine
COM_InitHostState(); COM_InitHostState();
// init hashed commands
BaseCmd_Init();
// startup cmds and cvars subsystem // startup cmds and cvars subsystem
Cmd_Init(); Cmd_Init();
Cvar_Init(); Cvar_Init();

Loading…
Cancel
Save