From 4bede371a0f04d5edf3bd28f503ccf11cc9c6f47 Mon Sep 17 00:00:00 2001 From: "M. Kristall" Date: Mon, 19 Oct 2009 07:09:55 +0000 Subject: * Use binary searching instead of linear searching for many static arrays --- src/cgame/cg_consolecmds.c | 51 +++++---- src/cgame/cg_servercmds.c | 36 +++---- src/game/bg_lib.c | 22 ++++ src/game/bg_lib.h | 2 + src/game/bg_misc.c | 4 + src/game/bg_public.h | 6 ++ src/game/g_admin.c | 11 +- src/game/g_cmds.c | 118 +++++++++------------ src/game/g_spawn.c | 251 +++++++++++++++++++++------------------------ src/game/g_svcmds.c | 64 ++++++------ src/ui/ui_atoms.c | 27 +++-- src/ui/ui_shared.c | 52 +++++----- 12 files changed, 313 insertions(+), 331 deletions(-) diff --git a/src/cgame/cg_consolecmds.c b/src/cgame/cg_consolecmds.c index 17eddac1..da583214 100644 --- a/src/cgame/cg_consolecmds.c +++ b/src/cgame/cg_consolecmds.c @@ -185,31 +185,30 @@ static void CG_UIMenu_f( void ) static consoleCommand_t commands[ ] = { - { "ui_menu", CG_UIMenu_f }, - { "testgun", CG_TestGun_f }, - { "testmodel", CG_TestModel_f }, + { "+scores", CG_ScoresDown_f }, + { "-scores", CG_ScoresUp_f }, + { "clientlist", CG_ClientList_f }, + { "destroyTestPS", CG_DestroyTestPS_f }, + { "destroyTestTS", CG_DestroyTestTS_f }, { "nextframe", CG_TestModelNextFrame_f }, - { "prevframe", CG_TestModelPrevFrame_f }, { "nextskin", CG_TestModelNextSkin_f }, + { "prevframe", CG_TestModelPrevFrame_f }, { "prevskin", CG_TestModelPrevSkin_f }, - { "viewpos", CG_Viewpos_f }, - { "+scores", CG_ScoresDown_f }, - { "-scores", CG_ScoresUp_f }, - { "scoresUp", CG_scrollScoresUp_f }, { "scoresDown", CG_scrollScoresDown_f }, - { "sizeup", CG_SizeUp_f }, + { "scoresUp", CG_scrollScoresUp_f }, { "sizedown", CG_SizeDown_f }, - { "weapnext", CG_NextWeapon_f }, - { "weapprev", CG_PrevWeapon_f }, - { "weapon", CG_Weapon_f }, + { "sizeup", CG_SizeUp_f }, + { "testgun", CG_TestGun_f }, + { "testmodel", CG_TestModel_f }, { "testPS", CG_TestPS_f }, - { "destroyTestPS", CG_DestroyTestPS_f }, { "testTS", CG_TestTS_f }, - { "destroyTestTS", CG_DestroyTestTS_f }, - { "clientlist", CG_ClientList_f }, + { "ui_menu", CG_UIMenu_f }, + { "viewpos", CG_Viewpos_f }, + { "weapnext", CG_NextWeapon_f }, + { "weapon", CG_Weapon_f }, + { "weapprev", CG_PrevWeapon_f } }; - /* ================= CG_ConsoleCommand @@ -220,21 +219,17 @@ Cmd_Argc() / Cmd_Argv() */ qboolean CG_ConsoleCommand( void ) { - const char *cmd; - int i; + consoleCommand_t *cmd; - cmd = CG_Argv( 0 ); + cmd = bsearch( CG_Argv( 0 ), commands, + sizeof( commands ) / sizeof( commands[ 0 ]), sizeof( commands[ 0 ] ), + cmdcmp ); - for( i = 0; i < sizeof( commands ) / sizeof( commands[ 0 ] ); i++ ) - { - if( !Q_stricmp( cmd, commands[ i ].cmd ) ) - { - commands[ i ].function( ); - return qtrue; - } - } + if( !cmd ) + return qfalse; - return qfalse; + cmd->function( ); + return qtrue; } diff --git a/src/cgame/cg_servercmds.c b/src/cgame/cg_servercmds.c index 920858fc..6c43782a 100644 --- a/src/cgame/cg_servercmds.c +++ b/src/cgame/cg_servercmds.c @@ -1278,21 +1278,21 @@ static void CG_PTRConfirm_f( void ) static consoleCommand_t svcommands[ ] = { + { "chat", CG_Chat_f }, + { "clientLevelShot", CG_ClientLevelShot_f }, { "cp", CG_CenterPrint_f }, { "cs", CG_ConfigStringModified }, - { "print", CG_Print_f }, - { "chat", CG_Chat_f }, - { "scores", CG_ParseScores }, - { "tinfo", CG_ParseTeamInfo }, { "map_restart", CG_MapRestart }, - { "clientLevelShot", CG_ClientLevelShot_f }, - { "servermenu", CG_ServerMenu_f }, - { "serverclosemenus", CG_ServerCloseMenus_f }, { "poisoncloud", CG_PoisonCloud_f }, - { "voice", CG_ParseVoice }, - { "ptrcrequest", CG_PTRRequest_f }, + { "print", CG_Print_f }, + { "ptrcconfirm", CG_PTRConfirm_f }, { "ptrcissue", CG_PTRIssue_f }, - { "ptrcconfirm", CG_PTRConfirm_f } + { "ptrcrequest", CG_PTRRequest_f }, + { "scores", CG_ParseScores }, + { "serverclosemenus", CG_ServerCloseMenus_f }, + { "servermenu", CG_ServerMenu_f }, + { "tinfo", CG_ParseTeamInfo }, + { "voice", CG_ParseVoice } }; /* @@ -1305,18 +1305,18 @@ Cmd_Argc() / Cmd_Argv() */ static void CG_ServerCommand( void ) { - const char *cmd; - int i; + const char *cmd; + consoleCommand_t *command; cmd = CG_Argv( 0 ); + command = bsearch( cmd, svcommands, sizeof( svcommands ) / + sizeof( svcommands[ 0 ]), sizeof( svcommands[ 0 ] ), + cmdcmp ); - for( i = 0; i < sizeof( svcommands ) / sizeof( svcommands[ 0 ] ); i++ ) + if( command ) { - if( !Q_stricmp( cmd, svcommands[ i ].cmd ) ) - { - svcommands[ i ].function( ); - return; - } + command->function( ); + return; } CG_Printf( "Unknown client game command: %s\n", cmd ); 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 ""; } +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; } diff --git a/src/ui/ui_atoms.c b/src/ui/ui_atoms.c index 9f0f3a9a..8f31225f 100644 --- a/src/ui/ui_atoms.c +++ b/src/ui/ui_atoms.c @@ -153,18 +153,18 @@ static void UI_MessageMode_f( void ) Menus_ActivateByName( "say" ); } -struct +struct uicmd { char *cmd; void ( *function )( void ); } commands[ ] = { - { "ui_load", UI_Load }, - { "ui_report", UI_Report }, - { "ui_cache", UI_Cache_f }, + { "closemenus", UI_CloseMenus_f }, + { "menu", UI_Menu_f }, { "messagemode", UI_MessageMode_f }, { "messagemode2", UI_MessageMode_f }, - { "menu", UI_Menu_f }, - { "closemenus", UI_CloseMenus_f } + { "ui_cache", UI_Cache_f }, + { "ui_load", UI_Load }, + { "ui_report", UI_Report } }; /* @@ -174,20 +174,17 @@ UI_ConsoleCommand */ qboolean UI_ConsoleCommand( int realTime ) { - char *cmd; - int i; + struct uicmd *cmd = bsearch( UI_Argv( 0 ), commands, + sizeof( commands ) / sizeof( commands[ 0 ] ), sizeof( commands[ 0 ] ), + cmdcmp ); uiInfo.uiDC.frameTime = realTime - uiInfo.uiDC.realTime; uiInfo.uiDC.realTime = realTime; - cmd = UI_Argv( 0 ); - for( i = 0; i < sizeof( commands ) / sizeof( commands[ 0 ] ); i++ ) + if( cmd ) { - if( Q_stricmp( commands[ i ].cmd, cmd ) == 0 ) - { - commands[ i ].function( ); - return qtrue; - } + cmd->function( ); + return qtrue; } return qfalse; diff --git a/src/ui/ui_shared.c b/src/ui/ui_shared.c index d38a0243..d5ed79dc 100644 --- a/src/ui/ui_shared.c +++ b/src/ui/ui_shared.c @@ -2238,37 +2238,41 @@ void UI_Text_PaintWithCursor( float x, float y, float scale, vec4_t color, const commandDef_t commandList[] = { + {"close", &Script_Close}, // menu + {"conditionalopen", &Script_ConditionalOpen}, // menu + {"exec", &Script_Exec}, // group/name {"fadein", &Script_FadeIn}, // group/name {"fadeout", &Script_FadeOut}, // group/name - {"show", &Script_Show}, // group/name {"hide", &Script_Hide}, // group/name - {"setcolor", &Script_SetColor}, // works on this {"open", &Script_Open}, // menu - {"conditionalopen", &Script_ConditionalOpen}, // menu - {"close", &Script_Close}, // menu + {"orbit", &Script_Orbit}, // group/name + {"play", &Script_Play}, // group/name + {"playlooped", &Script_playLooped}, // group/name + {"reset", &Script_Reset}, // resets the state of the item argument {"setasset", &Script_SetAsset}, // works on this {"setbackground", &Script_SetBackground}, // works on this - {"setitemcolor", &Script_SetItemColor}, // group/name + {"setcolor", &Script_SetColor}, // works on this + {"setcvar", &Script_SetCvar}, // group/name {"setfocus", &Script_SetFocus}, // sets this background color to team color - {"reset", &Script_Reset}, // resets the state of the item argument - {"setplayermodel", &Script_SetPlayerModel}, // sets this background color to team color + {"setitemcolor", &Script_SetItemColor}, // group/name {"setplayerhead", &Script_SetPlayerHead}, // sets this background color to team color + {"setplayermodel", &Script_SetPlayerModel}, // sets this background color to team color + {"show", &Script_Show}, // group/name {"transition", &Script_Transition}, // group/name - {"setcvar", &Script_SetCvar}, // group/name - {"exec", &Script_Exec}, // group/name - {"play", &Script_Play}, // group/name - {"playlooped", &Script_playLooped}, // group/name - {"orbit", &Script_Orbit} // group/name }; -int scriptCommandCount = sizeof( commandList ) / sizeof( commandDef_t ); +static size_t scriptCommandCount = sizeof( commandList ) / sizeof( commandDef_t ); +// despite what lcc thinks, we do not get cmdcmp here +static int commandComp( const void *a, const void *b ) +{ + return Q_stricmp( (const char *)a, ((commandDef_t *)b)->name ); +} void Item_RunScript( itemDef_t *item, const char *s ) { char script[1024], *p; - int i; - qboolean bRan; + commandDef_t *cmd; memset( script, 0, sizeof( script ) ); if( item && s && s[0] ) @@ -2287,20 +2291,12 @@ void Item_RunScript( itemDef_t *item, const char *s ) if( command[0] == ';' && command[1] == '\0' ) continue; - bRan = qfalse; - - for( i = 0; i < scriptCommandCount; i++ ) - { - if( Q_stricmp( command, commandList[i].name ) == 0 ) - { - ( commandList[i].handler( item, &p ) ); - bRan = qtrue; - break; - } - } - + cmd = bsearch( command, commandList, scriptCommandCount, + sizeof( commandDef_t ), commandComp ); + if( cmd ) + cmd->handler( item, &p ); + else // not in our auto list, pass to handler - if( !bRan ) DC->runScript( &p ); } } -- cgit