diff options
Diffstat (limited to 'src/game')
-rw-r--r-- | src/game/bg_lib.c | 22 | ||||
-rw-r--r-- | src/game/bg_lib.h | 2 | ||||
-rw-r--r-- | src/game/bg_misc.c | 4 | ||||
-rw-r--r-- | src/game/bg_public.h | 6 | ||||
-rw-r--r-- | src/game/g_admin.c | 11 | ||||
-rw-r--r-- | src/game/g_cmds.c | 118 | ||||
-rw-r--r-- | src/game/g_spawn.c | 251 | ||||
-rw-r--r-- | src/game/g_svcmds.c | 64 |
8 files changed, 236 insertions, 242 deletions
diff --git a/src/game/bg_lib.c b/src/game/bg_lib.c index 1ed9c6b3..7a3afdfb 100644 --- a/src/game/bg_lib.c +++ b/src/game/bg_lib.c @@ -2450,4 +2450,26 @@ int sscanf( const char *buffer, const char *fmt, ... ) return count; } +void *bsearch( const void *key, const void *base, size_t nmemb, size_t size, + cmp_t *compar ) +{ + size_t low = 0, high = nmemb, mid; + int comp; + void *ptr; + + while( low <= high ) + { + mid = low + (high - low) / 2; + ptr = (void *)((char *)base + ( mid * size )); + comp = compar (key, ptr); + if( comp < 0 ) + high = mid - 1; + else if( comp > 0 ) + low = mid + 1; + else + return ptr; + } + return NULL; +} + #endif diff --git a/src/game/bg_lib.h b/src/game/bg_lib.h index 5b5bacaf..005f285d 100644 --- a/src/game/bg_lib.h +++ b/src/game/bg_lib.h @@ -87,6 +87,8 @@ typedef int cmp_t( const void *, const void * ); void qsort( void *a, size_t n, size_t es, cmp_t *cmp ); void srand( unsigned seed ); int rand( void ); +void *bsearch( const void *key, const void *base, size_t nmemb, + size_t size, cmp_t *compar ); // String functions size_t strlen( const char *string ); diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index 204fa878..ed4dd30c 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -3973,3 +3973,7 @@ char *BG_TeamName( team_t team ) return "<team>"; } +int cmdcmp( const void *a, const void *b ) +{ + return Q_stricmp( (const char *)a, ((dummyCmd_t *)b)->name ); +} diff --git a/src/game/bg_public.h b/src/game/bg_public.h index 30ac860d..e952624a 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -1307,3 +1307,9 @@ voiceTrack_t *BG_VoiceTrackFind( voiceTrack_t *head, team_t team, int BG_LoadEmoticons( char names[ ][ MAX_EMOTICON_NAME_LEN ], int widths[ ] ); char *BG_TeamName( team_t team ); + +typedef struct +{ + const char *name; +} dummyCmd_t; +int cmdcmp( const void *a, const void *b ); diff --git a/src/game/g_admin.c b/src/game/g_admin.c index 9981812b..b894324b 100644 --- a/src/game/g_admin.c +++ b/src/game/g_admin.c @@ -225,15 +225,8 @@ static qboolean admin_permission( char *flags, const char *flag, qboolean *perm g_admin_cmd_t *G_admin_cmd( const char *cmd ) { - int i; - - for( i = 0; i < adminNumCmds; i++ ) - { - if( !Q_stricmp( g_admin_cmds[ i ].keyword, cmd ) ) - return &g_admin_cmds[ i ]; - } - - return NULL; + return bsearch( cmd, g_admin_cmds, adminNumCmds, sizeof( g_admin_cmd_t ), + cmdcmp ); } g_admin_level_t *G_admin_level( const int l ) diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index ac88b825..ed32ae05 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -2887,63 +2887,49 @@ int G_FloodLimited( gentity_t *ent ) } commands_t cmds[ ] = { - // normal commands - { "team", 0, Cmd_Team_f }, - { "vote", 0, Cmd_Vote_f }, - { "ignore", 0, Cmd_Ignore_f }, - { "unignore", 0, Cmd_Ignore_f }, - - // communication commands - { "callvote", CMD_MESSAGE, Cmd_CallVote_f }, - { "callteamvote", CMD_MESSAGE|CMD_TEAM, Cmd_CallVote_f }, - { "say_area", CMD_MESSAGE|CMD_TEAM|CMD_LIVING, Cmd_SayArea_f }, - // can be used even during intermission - { "say", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, - { "say_team", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, - { "vsay", CMD_MESSAGE|CMD_INTERMISSION, Cmd_VSay_f }, - { "vsay_team", CMD_MESSAGE|CMD_INTERMISSION, Cmd_VSay_f }, - { "vsay_local", CMD_MESSAGE|CMD_INTERMISSION, Cmd_VSay_f }, - { "m", CMD_MESSAGE|CMD_INTERMISSION, Cmd_PrivateMessage_f }, - { "mt", CMD_MESSAGE|CMD_INTERMISSION, Cmd_PrivateMessage_f }, { "a", CMD_MESSAGE|CMD_INTERMISSION, Cmd_AdminMessage_f }, - - { "score", CMD_INTERMISSION, ScoreboardMessage }, - - // cheats - { "give", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_Give_f }, - { "god", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_God_f }, - { "notarget", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_Notarget_f }, - { "noclip", CMD_CHEAT_TEAM, Cmd_Noclip_f }, - { "levelshot", CMD_CHEAT, Cmd_LevelShot_f }, - { "setviewpos", CMD_CHEAT_TEAM, Cmd_SetViewpos_f }, - { "destroy", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_Destroy_f }, - { "test", CMD_CHEAT, Cmd_Test_f }, + { "build", CMD_TEAM|CMD_LIVING, Cmd_Build_f }, + { "buy", CMD_HUMAN|CMD_LIVING, Cmd_Buy_f }, + { "callteamvote", CMD_MESSAGE|CMD_TEAM, Cmd_CallVote_f }, + { "callvote", CMD_MESSAGE, Cmd_CallVote_f }, + { "class", CMD_TEAM, Cmd_Class_f }, { "damage", CMD_CHEAT|CMD_LIVING, Cmd_Damage_f }, - { "where", 0, Cmd_Where_f }, - - // game commands - { "ptrcverify", CMD_SPEC, Cmd_PTRCVerify_f }, - { "ptrcrestore", CMD_SPEC, Cmd_PTRCRestore_f }, - + { "deconstruct", CMD_TEAM|CMD_LIVING, Cmd_Destroy_f }, + { "destroy", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_Destroy_f }, { "follow", CMD_SPEC, Cmd_Follow_f }, - { "follownext", CMD_SPEC, Cmd_FollowCycle_f }, { "followprev", CMD_SPEC, Cmd_FollowCycle_f }, - - { "teamvote", CMD_TEAM, Cmd_Vote_f }, - { "class", CMD_TEAM, Cmd_Class_f }, - { "kill", CMD_TEAM|CMD_LIVING, Cmd_Kill_f }, - - { "build", CMD_TEAM|CMD_LIVING, Cmd_Build_f }, - { "deconstruct", CMD_TEAM|CMD_LIVING, Cmd_Destroy_f }, - - { "buy", CMD_HUMAN|CMD_LIVING, Cmd_Buy_f }, - { "sell", CMD_HUMAN|CMD_LIVING, Cmd_Sell_f }, + { "give", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_Give_f }, + { "god", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_God_f }, + { "ignore", 0, Cmd_Ignore_f }, { "itemact", CMD_HUMAN|CMD_LIVING, Cmd_ActivateItem_f }, { "itemdeact", CMD_HUMAN|CMD_LIVING, Cmd_DeActivateItem_f }, { "itemtoggle", CMD_HUMAN|CMD_LIVING, Cmd_ToggleItem_f }, + { "kill", CMD_TEAM|CMD_LIVING, Cmd_Kill_f }, + { "levelshot", CMD_CHEAT, Cmd_LevelShot_f }, + { "m", CMD_MESSAGE|CMD_INTERMISSION, Cmd_PrivateMessage_f }, + { "mt", CMD_MESSAGE|CMD_INTERMISSION, Cmd_PrivateMessage_f }, + { "noclip", CMD_CHEAT_TEAM, Cmd_Noclip_f }, + { "notarget", CMD_CHEAT|CMD_TEAM|CMD_LIVING, Cmd_Notarget_f }, + { "ptrcrestore", CMD_SPEC, Cmd_PTRCRestore_f }, + { "ptrcverify", CMD_SPEC, Cmd_PTRCVerify_f }, { "reload", CMD_HUMAN|CMD_LIVING, Cmd_Reload_f }, + { "say_area", CMD_MESSAGE|CMD_TEAM|CMD_LIVING, Cmd_SayArea_f }, + { "say", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, + { "say_team", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, + { "score", CMD_INTERMISSION, ScoreboardMessage }, + { "sell", CMD_HUMAN|CMD_LIVING, Cmd_Sell_f }, + { "setviewpos", CMD_CHEAT_TEAM, Cmd_SetViewpos_f }, + { "team", 0, Cmd_Team_f }, + { "teamvote", CMD_TEAM, Cmd_Vote_f }, + { "test", CMD_CHEAT, Cmd_Test_f }, + { "unignore", 0, Cmd_Ignore_f }, + { "vote", 0, Cmd_Vote_f }, + { "vsay", CMD_MESSAGE|CMD_INTERMISSION, Cmd_VSay_f }, + { "vsay_local", CMD_MESSAGE|CMD_INTERMISSION, Cmd_VSay_f }, + { "vsay_team", CMD_MESSAGE|CMD_INTERMISSION, Cmd_VSay_f }, + { "where", 0, Cmd_Where_f } }; -static int numCmds = sizeof( cmds ) / sizeof( cmds[ 0 ] ); +static size_t numCmds = sizeof( cmds ) / sizeof( cmds[ 0 ] ); /* ================= @@ -2952,9 +2938,9 @@ ClientCommand */ void ClientCommand( int clientNum ) { - gentity_t *ent; - char cmd[ MAX_TOKEN_CHARS ]; - int i; + gentity_t *ent; + char cmd[ MAX_TOKEN_CHARS ]; + commands_t *command; ent = g_entities + clientNum; if( !ent->client ) @@ -2962,13 +2948,9 @@ void ClientCommand( int clientNum ) trap_Argv( 0, cmd, sizeof( cmd ) ); - for( i = 0; i < numCmds; i++ ) - { - if( Q_stricmp( cmd, cmds[ i ].cmdName ) == 0 ) - break; - } + command = bsearch( cmd, cmds, numCmds, sizeof( cmds[ 0 ] ), cmdcmp ); - if( i == numCmds ) + if( !command ) { if( !G_admin_cmd_check( ent, qfalse ) ) trap_SendServerCommand( clientNum, @@ -2978,56 +2960,56 @@ void ClientCommand( int clientNum ) // do tests here to reduce the amount of repeated code - if( !( cmds[ i ].cmdFlags & CMD_INTERMISSION ) && level.intermissiontime ) + if( !( command->cmdFlags & CMD_INTERMISSION ) && level.intermissiontime ) return; - if( cmds[ i ].cmdFlags & CMD_CHEAT && !g_cheats.integer ) + if( command->cmdFlags & CMD_CHEAT && !g_cheats.integer ) { G_TriggerMenu( clientNum, MN_CMD_CHEAT ); return; } - if( cmds[ i ].cmdFlags & CMD_MESSAGE && ( ent->client->pers.muted || + if( command->cmdFlags & CMD_MESSAGE && ( ent->client->pers.muted || G_FloodLimited( ent ) ) ) return; - if( ( cmds[ i ].cmdFlags & CMD_TEAM || - ( cmds[ i ].cmdFlags & CMD_CHEAT_TEAM && !g_cheats.integer ) ) && + if( ( command->cmdFlags & CMD_TEAM || + ( command->cmdFlags & CMD_CHEAT_TEAM && !g_cheats.integer ) ) && ent->client->pers.teamSelection == TEAM_NONE ) { G_TriggerMenu( clientNum, MN_CMD_TEAM ); return; } - if( cmds[ i ].cmdFlags & CMD_CHEAT_TEAM && !g_cheats.integer && + if( command->cmdFlags & CMD_CHEAT_TEAM && !g_cheats.integer && ent->client->pers.teamSelection != TEAM_NONE ) { G_TriggerMenu( clientNum, MN_CMD_CHEAT_TEAM ); return; } - if( cmds[ i ].cmdFlags & CMD_SPEC && + if( command->cmdFlags & CMD_SPEC && ent->client->sess.spectatorState == SPECTATOR_NOT ) { G_TriggerMenu( clientNum, MN_CMD_SPEC ); return; } - if( cmds[ i ].cmdFlags & CMD_ALIEN && + if( command->cmdFlags & CMD_ALIEN && ent->client->pers.teamSelection != TEAM_ALIENS ) { G_TriggerMenu( clientNum, MN_CMD_ALIEN ); return; } - if( cmds[ i ].cmdFlags & CMD_HUMAN && + if( command->cmdFlags & CMD_HUMAN && ent->client->pers.teamSelection != TEAM_HUMANS ) { G_TriggerMenu( clientNum, MN_CMD_HUMAN ); return; } - if( cmds[ i ].cmdFlags & CMD_LIVING && + if( command->cmdFlags & CMD_LIVING && ( ent->client->ps.stats[ STAT_HEALTH ] <= 0 || ent->client->sess.spectatorState != SPECTATOR_NOT ) ) { @@ -3035,7 +3017,7 @@ void ClientCommand( int clientNum ) return; } - cmds[ i ].cmdHandler( ent ); + command->cmdHandler( ent ); } /* diff --git a/src/game/g_spawn.c b/src/game/g_spawn.c index 35c29b4e..0eade5c4 100644 --- a/src/game/g_spawn.c +++ b/src/game/g_spawn.c @@ -116,34 +116,32 @@ typedef struct field_t fields[ ] = { + {"acceleration", FOFS(acceleration), F_VECTOR}, + {"alpha", FOFS(pos1), F_VECTOR}, + {"angle", FOFS(s.angles), F_ANGLEHACK}, + {"angles", FOFS(s.angles), F_VECTOR}, + {"animation", FOFS(animation), F_VECTOR4}, + {"bounce", FOFS(physicsBounce), F_FLOAT}, {"classname", FOFS(classname), F_LSTRING}, - {"origin", FOFS(s.origin), F_VECTOR}, + {"count", FOFS(count), F_INT}, + {"dmg", FOFS(damage), F_INT}, + {"health", FOFS(health), F_INT}, + {"light", 0, F_IGNORE}, + {"message", FOFS(message), F_LSTRING}, {"model", FOFS(model), F_LSTRING}, {"model2", FOFS(model2), F_LSTRING}, + {"origin", FOFS(s.origin), F_VECTOR}, + {"radius", FOFS(pos2), F_VECTOR}, + {"random", FOFS(random), F_FLOAT}, + {"rotatorAngle", FOFS(rotatorAngle), F_FLOAT}, {"spawnflags", FOFS(spawnflags), F_INT}, {"speed", FOFS(speed), F_FLOAT}, {"target", FOFS(target), F_LSTRING}, {"targetname", FOFS(targetname), F_LSTRING}, - {"message", FOFS(message), F_LSTRING}, - {"team", FOFS(team), F_LSTRING}, - {"wait", FOFS(wait), F_FLOAT}, - {"random", FOFS(random), F_FLOAT}, - {"count", FOFS(count), F_INT}, - {"health", FOFS(health), F_INT}, - {"light", 0, F_IGNORE}, - {"dmg", FOFS(damage), F_INT}, - {"angles", FOFS(s.angles), F_VECTOR}, - {"angle", FOFS(s.angles), F_ANGLEHACK}, - {"bounce", FOFS(physicsBounce), F_FLOAT}, - {"alpha", FOFS(pos1), F_VECTOR}, - {"radius", FOFS(pos2), F_VECTOR}, - {"acceleration", FOFS(acceleration), F_VECTOR}, - {"animation", FOFS(animation), F_VECTOR4}, - {"rotatorAngle", FOFS(rotatorAngle), F_FLOAT}, {"targetShaderName", FOFS(targetShaderName), F_LSTRING}, {"targetShaderNewName", FOFS(targetShaderNewName), F_LSTRING}, - - {NULL} + {"team", FOFS(team), F_LSTRING}, + {"wait", FOFS(wait), F_FLOAT} }; @@ -228,30 +226,54 @@ void SP_misc_light_flare( gentity_t *ent ); spawn_t spawns[ ] = { + { "func_bobbing", SP_func_bobbing }, + { "func_button", SP_func_button }, + { "func_door", SP_func_door }, + { "func_door_model", SP_func_door_model }, + { "func_door_rotating", SP_func_door_rotating }, + { "func_group", SP_info_null }, + { "func_pendulum", SP_func_pendulum }, + { "func_plat", SP_func_plat }, + { "func_rotating", SP_func_rotating }, + { "func_static", SP_func_static }, + { "func_timer", SP_func_timer }, // rename trigger_timer? + { "func_train", SP_func_train }, + // info entities don't do anything at all, but provide positional // information for things controlled by other processes - { "info_player_start", SP_info_player_start }, - { "info_player_deathmatch", SP_info_player_deathmatch }, - { "info_player_intermission", SP_info_player_intermission }, - { "info_alien_intermission", SP_info_alien_intermission }, { "info_human_intermission", SP_info_human_intermission }, - - { "info_null", SP_info_null }, { "info_notnull", SP_info_notnull }, // use target_position instead + { "info_null", SP_info_null }, + { "info_player_deathmatch", SP_info_player_deathmatch }, + { "info_player_intermission", SP_info_player_intermission }, + { "info_player_start", SP_info_player_start }, + { "light", SP_light }, + { "misc_anim_model", SP_misc_anim_model }, + { "misc_light_flare", SP_misc_light_flare }, + { "misc_model", SP_misc_model }, + { "misc_particle_system", SP_misc_particle_system }, + { "misc_portal_camera", SP_misc_portal_camera }, + { "misc_portal_surface", SP_misc_portal_surface }, + { "misc_teleporter_dest", SP_misc_teleporter_dest }, + { "path_corner", SP_path_corner }, - { "func_plat", SP_func_plat }, - { "func_button", SP_func_button }, - { "func_door", SP_func_door }, - { "func_door_rotating", SP_func_door_rotating }, - { "func_door_model", SP_func_door_model }, - { "func_static", SP_func_static }, - { "func_rotating", SP_func_rotating }, - { "func_bobbing", SP_func_bobbing }, - { "func_pendulum", SP_func_pendulum }, - { "func_train", SP_func_train }, - { "func_group", SP_info_null }, - { "func_timer", SP_func_timer }, // rename trigger_timer? + // targets perform no action by themselves, but must be triggered + // by another entity + { "target_alien_win", SP_target_alien_win }, + { "target_delay", SP_target_delay }, + { "target_human_win", SP_target_human_win }, + { "target_hurt", SP_target_hurt }, + { "target_kill", SP_target_kill }, + { "target_location", SP_target_location }, + { "target_position", SP_target_position }, + { "target_print", SP_target_print }, + { "target_push", SP_target_push }, + { "target_relay", SP_target_relay }, + { "target_rumble", SP_target_rumble }, + { "target_score", SP_target_score }, + { "target_speaker", SP_target_speaker }, + { "target_teleporter", SP_target_teleporter }, // Triggers are brush objects that cause an effect when contacted // by a living player, usually involving firing targets. @@ -259,49 +281,18 @@ spawn_t spawns[ ] = // a single trigger class and different targets, triggered effects // could not be client side predicted (push and teleport). { "trigger_always", SP_trigger_always }, - { "trigger_multiple", SP_trigger_multiple }, - { "trigger_push", SP_trigger_push }, - { "trigger_teleport", SP_trigger_teleport }, - { "trigger_hurt", SP_trigger_hurt }, - { "trigger_stage", SP_trigger_stage }, - { "trigger_win", SP_trigger_win }, + { "trigger_ammo", SP_trigger_ammo }, { "trigger_buildable", SP_trigger_buildable }, { "trigger_class", SP_trigger_class }, { "trigger_equipment", SP_trigger_equipment }, { "trigger_gravity", SP_trigger_gravity }, { "trigger_heal", SP_trigger_heal }, - { "trigger_ammo", SP_trigger_ammo }, - - // targets perform no action by themselves, but must be triggered - // by another entity - { "target_delay", SP_target_delay }, - { "target_speaker", SP_target_speaker }, - { "target_print", SP_target_print }, - { "target_score", SP_target_score }, - { "target_teleporter", SP_target_teleporter }, - { "target_relay", SP_target_relay }, - { "target_kill", SP_target_kill }, - { "target_position", SP_target_position }, - { "target_location", SP_target_location }, - { "target_push", SP_target_push }, - { "target_rumble", SP_target_rumble }, - { "target_alien_win", SP_target_alien_win }, - { "target_human_win", SP_target_human_win }, - { "target_hurt", SP_target_hurt }, - - { "light", SP_light }, - { "path_corner", SP_path_corner }, - - { "misc_teleporter_dest", SP_misc_teleporter_dest }, - { "misc_model", SP_misc_model }, - { "misc_portal_surface", SP_misc_portal_surface }, - { "misc_portal_camera", SP_misc_portal_camera }, - - { "misc_particle_system", SP_misc_particle_system }, - { "misc_anim_model", SP_misc_anim_model }, - { "misc_light_flare", SP_misc_light_flare }, - - { NULL, 0 } + { "trigger_hurt", SP_trigger_hurt }, + { "trigger_multiple", SP_trigger_multiple }, + { "trigger_push", SP_trigger_push }, + { "trigger_stage", SP_trigger_stage }, + { "trigger_teleport", SP_trigger_teleport }, + { "trigger_win", SP_trigger_win } }; /* @@ -342,14 +333,13 @@ qboolean G_CallSpawn( gentity_t *ent ) } // check normal spawn functions - for( s = spawns; s->name; s++ ) + s = bsearch( ent->classname, spawns, sizeof( spawns ) / sizeof( spawn_t ), + sizeof( spawn_t ), cmdcmp ); + if( s ) { - if( !strcmp( s->name, ent->classname ) ) - { - // found it - s->spawn( ent ); - return qtrue; - } + // found it + s->spawn( ent ); + return qtrue; } G_Printf( "%s doesn't have a spawn function\n", ent->classname ); @@ -412,58 +402,53 @@ void G_ParseField( const char *key, const char *value, gentity_t *ent ) vec3_t vec; vec4_t vec4; - for( f = fields; f->name; f++ ) + f = bsearch( key, fields, sizeof( fields ) / sizeof( field_t ), + sizeof( field_t ), cmdcmp ); + if( !f ) + return; + b = (byte *)ent; + + switch( f->type ) { - if( !Q_stricmp( f->name, key ) ) - { - // found it - b = (byte *)ent; - - switch( f->type ) - { - case F_LSTRING: - *(char **)( b + f->ofs ) = G_NewString( value ); - break; - - case F_VECTOR: - sscanf( value, "%f %f %f", &vec[ 0 ], &vec[ 1 ], &vec[ 2 ] ); - - ( (float *)( b + f->ofs ) )[ 0 ] = vec[ 0 ]; - ( (float *)( b + f->ofs ) )[ 1 ] = vec[ 1 ]; - ( (float *)( b + f->ofs ) )[ 2 ] = vec[ 2 ]; - break; - - case F_VECTOR4: - sscanf( value, "%f %f %f %f", &vec4[ 0 ], &vec4[ 1 ], &vec4[ 2 ], &vec4[ 3 ] ); - - ( (float *)( b + f->ofs ) )[ 0 ] = vec4[ 0 ]; - ( (float *)( b + f->ofs ) )[ 1 ] = vec4[ 1 ]; - ( (float *)( b + f->ofs ) )[ 2 ] = vec4[ 2 ]; - ( (float *)( b + f->ofs ) )[ 3 ] = vec4[ 3 ]; - break; - - case F_INT: - *(int *)( b + f->ofs ) = atoi( value ); - break; - - case F_FLOAT: - *(float *)( b + f->ofs ) = atof( value ); - break; - - case F_ANGLEHACK: - v = atof( value ); - ( (float *)( b + f->ofs ) )[ 0 ] = 0; - ( (float *)( b + f->ofs ) )[ 1 ] = v; - ( (float *)( b + f->ofs ) )[ 2 ] = 0; - break; - - default: - case F_IGNORE: - break; - } - - return; - } + case F_LSTRING: + *(char **)( b + f->ofs ) = G_NewString( value ); + break; + + case F_VECTOR: + sscanf( value, "%f %f %f", &vec[ 0 ], &vec[ 1 ], &vec[ 2 ] ); + + ( (float *)( b + f->ofs ) )[ 0 ] = vec[ 0 ]; + ( (float *)( b + f->ofs ) )[ 1 ] = vec[ 1 ]; + ( (float *)( b + f->ofs ) )[ 2 ] = vec[ 2 ]; + break; + + case F_VECTOR4: + sscanf( value, "%f %f %f %f", &vec4[ 0 ], &vec4[ 1 ], &vec4[ 2 ], &vec4[ 3 ] ); + + ( (float *)( b + f->ofs ) )[ 0 ] = vec4[ 0 ]; + ( (float *)( b + f->ofs ) )[ 1 ] = vec4[ 1 ]; + ( (float *)( b + f->ofs ) )[ 2 ] = vec4[ 2 ]; + ( (float *)( b + f->ofs ) )[ 3 ] = vec4[ 3 ]; + break; + + case F_INT: + *(int *)( b + f->ofs ) = atoi( value ); + break; + + case F_FLOAT: + *(float *)( b + f->ofs ) = atof( value ); + break; + + case F_ANGLEHACK: + v = atof( value ); + ( (float *)( b + f->ofs ) )[ 0 ] = 0; + ( (float *)( b + f->ofs ) )[ 1 ] = v; + ( (float *)( b + f->ofs ) )[ 2 ] = 0; + break; + + default: + case F_IGNORE: + break; } } diff --git a/src/game/g_svcmds.c b/src/game/g_svcmds.c index 755948b5..f75236ed 100644 --- a/src/game/g_svcmds.c +++ b/src/game/g_svcmds.c @@ -513,34 +513,33 @@ static void Svcmd_SuddenDeath_f( void ) offset, offset == 1 ? "" : "s" ) ); } -struct +struct svcmd { char *cmd; qboolean dedicated; void ( *function )( void ); } svcmds[ ] = { - { "entityList", qfalse, Svcmd_EntityList_f }, - { "status", qfalse, Svcmd_Status_f }, - { "forceTeam", qfalse, Svcmd_ForceTeam_f }, - { "mapRotation", qfalse, Svcmd_MapRotation_f }, - { "stopMapRotation", qfalse, G_StopMapRotation }, + { "a", qtrue, Svcmd_MessageWrapper }, + { "admitDefeat", qfalse, Svcmd_AdmitDefeat_f }, { "advanceMapRotation", qfalse, G_AdvanceMapRotation }, { "alienWin", qfalse, Svcmd_TeamWin_f }, - { "humanWin", qfalse, Svcmd_TeamWin_f }, - { "layoutSave", qfalse, Svcmd_LayoutSave_f }, - { "layoutLoad", qfalse, Svcmd_LayoutLoad_f }, - { "eject", qfalse, Svcmd_EjectClient_f }, + { "chat", qtrue, Svcmd_MessageWrapper }, + { "cp", qtrue, Svcmd_CenterPrint_f }, { "dumpuser", qfalse, Svcmd_DumpUser_f }, - { "admitDefeat", qfalse, Svcmd_AdmitDefeat_f }, + { "eject", qfalse, Svcmd_EjectClient_f }, + { "entityList", qfalse, Svcmd_EntityList_f }, { "evacuation", qfalse, Svcmd_Evacuation_f }, + { "forceTeam", qfalse, Svcmd_ForceTeam_f }, + { "humanWin", qfalse, Svcmd_TeamWin_f }, + { "layoutLoad", qfalse, Svcmd_LayoutLoad_f }, + { "layoutSave", qfalse, Svcmd_LayoutSave_f }, + { "m", qtrue, Svcmd_MessageWrapper }, + { "mapRotation", qfalse, Svcmd_MapRotation_f }, { "printqueue", qfalse, Svcmd_PrintQueue_f }, - // don't handle communication commands unless dedicated - { "cp", qtrue, Svcmd_CenterPrint_f }, - { "say_team", qtrue, Svcmd_TeamMessage_f }, { "say", qtrue, Svcmd_MessageWrapper }, - { "chat", qtrue, Svcmd_MessageWrapper }, - { "m", qtrue, Svcmd_MessageWrapper }, - { "a", qtrue, Svcmd_MessageWrapper }, + { "say_team", qtrue, Svcmd_TeamMessage_f }, + { "status", qfalse, Svcmd_Status_f }, + { "stopMapRotation", qfalse, G_StopMapRotation }, { "suddendeath", qfalse, Svcmd_SuddenDeath_f } }; @@ -553,28 +552,29 @@ ConsoleCommand qboolean ConsoleCommand( void ) { char cmd[ MAX_TOKEN_CHARS ]; - int i; + struct svcmd *command; trap_Argv( 0, cmd, sizeof( cmd ) ); - for( i = 0; i < sizeof( svcmds ) / sizeof( svcmds[ 0 ] ); i++ ) + command = bsearch( cmd, svcmds, sizeof( svcmds ) / sizeof( struct svcmd ), + sizeof( struct svcmd ), cmdcmp ); + + if( !command ) { - if( !Q_stricmp( cmd, svcmds[ i ].cmd ) ) - { - if( svcmds[ i ].dedicated && !g_dedicated.integer ) - return qfalse; - svcmds[ i ].function( ); + // see if this is an admin command + if( G_admin_cmd_check( NULL, qfalse ) ) return qtrue; - } - } - // see if this is an admin command - if( G_admin_cmd_check( NULL, qfalse ) ) - return qtrue; + if( g_dedicated.integer ) + G_Printf( "unknown command: %s\n", cmd ); + + return qfalse; + } - if( g_dedicated.integer ) - G_Printf( "unknown command: %s\n", cmd ); + if( command->dedicated && !g_dedicated.integer ) + return qfalse; - return qfalse; + command->function( ); + return qtrue; } |