(svn r19085) -Codechange: simplify hooking of console commands

This commit is contained in:
smatz 2010-02-10 18:18:08 +00:00
parent c5b34444af
commit 8cd83f87df
3 changed files with 34 additions and 157 deletions

View File

@ -191,76 +191,6 @@ bool GetArgumentInteger(uint32 *value, const char *arg)
return arg != endptr; return arg != endptr;
} }
/* * *************************
* hooking code *
* *************************/
/**
* General internal hooking code
* @param hooks IConsoleHooks structure that will be set according to
* @param type type access trigger
* @param proc function called when the hook criteria is met
*/
static void IConsoleHookAdd(IConsoleHooks *hooks, IConsoleHookTypes type, IConsoleHook *proc)
{
if (hooks == NULL || proc == NULL) return;
switch (type) {
case ICONSOLE_HOOK_ACCESS:
hooks->access = proc;
break;
case ICONSOLE_HOOK_PRE_ACTION:
hooks->pre = proc;
break;
case ICONSOLE_HOOK_POST_ACTION:
hooks->post = proc;
break;
default: NOT_REACHED();
}
}
/**
* Handle any special hook triggers. If the hook type is met check if
* there is a function associated with that and if so, execute it
* @param hooks IConsoleHooks structure that will be checked
* @param type type of hook, trigger that needs to be activated
* @return true on a successful execution of the hook command or if there
* is no hook/trigger present at all. False otherwise
*/
static bool IConsoleHookHandle(const IConsoleHooks *hooks, IConsoleHookTypes type)
{
IConsoleHook *proc = NULL;
if (hooks == NULL) return false;
switch (type) {
case ICONSOLE_HOOK_ACCESS:
proc = hooks->access;
break;
case ICONSOLE_HOOK_PRE_ACTION:
proc = hooks->pre;
break;
case ICONSOLE_HOOK_POST_ACTION:
proc = hooks->post;
break;
default: NOT_REACHED();
}
return (proc == NULL) ? true : proc();
}
/**
* Add a hook to a command that will be triggered at certain points
* @param name name of the command that the hook is added to
* @param type type of hook that is added (ACCESS, BEFORE and AFTER change)
* @param proc function called when the hook criteria is met
*/
void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc)
{
IConsoleCmd *cmd = IConsoleCmdGet(name);
if (cmd == NULL) return;
IConsoleHookAdd(&cmd->hook, type, proc);
}
/** /**
* Perhaps ugly macro, but this saves us the trouble of writing the same function * Perhaps ugly macro, but this saves us the trouble of writing the same function
* twice, just with different variables. Yes, templates would be handy. It was * twice, just with different variables. Yes, templates would be handy. It was
@ -308,18 +238,13 @@ void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *
* @param name name of the command that will be used * @param name name of the command that will be used
* @param proc function that will be called upon execution of command * @param proc function that will be called upon execution of command
*/ */
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc) void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc, IConsoleHook *hook)
{ {
char *new_cmd = strdup(name);
IConsoleCmd *item_new = MallocT<IConsoleCmd>(1); IConsoleCmd *item_new = MallocT<IConsoleCmd>(1);
item_new->name = strdup(name);
item_new->next = NULL; item_new->next = NULL;
item_new->proc = proc; item_new->proc = proc;
item_new->name = new_cmd; item_new->hook = hook;
item_new->hook.access = NULL;
item_new->hook.pre = NULL;
item_new->hook.post = NULL;
IConsoleAddSorted(_iconsole_cmds, item_new, IConsoleCmd, "a command"); IConsoleAddSorted(_iconsole_cmds, item_new, IConsoleCmd, "a command");
} }
@ -541,11 +466,8 @@ void IConsoleCmdExec(const char *cmdstr)
*/ */
cmd = IConsoleCmdGet(tokens[0]); cmd = IConsoleCmdGet(tokens[0]);
if (cmd != NULL) { if (cmd != NULL) {
if (IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_ACCESS)) { if (cmd->hook == NULL || cmd->hook()) {
IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_PRE_ACTION); if (!cmd->proc(t_index, tokens)) { // index started with 0
if (cmd->proc(t_index, tokens)) { // index started with 0
IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_POST_ACTION);
} else {
cmd->proc(0, NULL); // if command failed, give help cmd->proc(0, NULL); // if command failed, give help
} }
} }

View File

@ -106,6 +106,8 @@ DEF_CONSOLE_HOOK(ConHookNoNetwork)
return true; return true;
} }
#else
# define ConHookNoNetwork NULL
#endif /* ENABLE_NETWORK */ #endif /* ENABLE_NETWORK */
static void IConsoleHelp(const char *str) static void IConsoleHelp(const char *str)
@ -1263,9 +1265,7 @@ DEF_CONSOLE_CMD(ConInfoCmd)
IConsolePrintF(CC_DEFAULT, "command name: %s", cmd->name); IConsolePrintF(CC_DEFAULT, "command name: %s", cmd->name);
IConsolePrintF(CC_DEFAULT, "command proc: %p", cmd->proc); IConsolePrintF(CC_DEFAULT, "command proc: %p", cmd->proc);
if (cmd->hook.access) IConsoleWarning("command is access hooked"); if (cmd->hook != NULL) IConsoleWarning("command is hooked");
if (cmd->hook.pre) IConsoleWarning("command is pre hooked");
if (cmd->hook.post) IConsoleWarning("command is post hooked");
return true; return true;
} }
@ -1721,7 +1721,7 @@ void IConsoleStdLibRegister()
IConsoleCmdRegister("getseed", ConGetSeed); IConsoleCmdRegister("getseed", ConGetSeed);
IConsoleCmdRegister("getdate", ConGetDate); IConsoleCmdRegister("getdate", ConGetDate);
IConsoleCmdRegister("quit", ConExit); IConsoleCmdRegister("quit", ConExit);
IConsoleCmdRegister("resetengines", ConResetEngines); IConsoleCmdRegister("resetengines", ConResetEngines, ConHookNoNetwork);
IConsoleCmdRegister("return", ConReturn); IConsoleCmdRegister("return", ConReturn);
IConsoleCmdRegister("screenshot", ConScreenShot); IConsoleCmdRegister("screenshot", ConScreenShot);
IConsoleCmdRegister("script", ConScript); IConsoleCmdRegister("script", ConScript);
@ -1761,66 +1761,42 @@ void IConsoleStdLibRegister()
/* networking functions */ /* networking functions */
#ifdef ENABLE_NETWORK #ifdef ENABLE_NETWORK
/* Network hooks; only active in network */
IConsoleCmdHookAdd ("resetengines", ICONSOLE_HOOK_ACCESS, ConHookNoNetwork);
/* Content downloading is only available with ZLIB */ /* Content downloading is only available with ZLIB */
#if defined(WITH_ZLIB) #if defined(WITH_ZLIB)
IConsoleCmdRegister("content", ConContent); IConsoleCmdRegister("content", ConContent);
#endif /* defined(WITH_ZLIB) */ #endif /* defined(WITH_ZLIB) */
/*** Networking commands ***/ /*** Networking commands ***/
IConsoleCmdRegister("say", ConSay); IConsoleCmdRegister("say", ConSay, ConHookNeedNetwork);
IConsoleCmdHookAdd("say", ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork); IConsoleCmdRegister("companies", ConCompanies, ConHookServerOnly);
IConsoleCmdRegister("companies", ConCompanies);
IConsoleCmdHookAdd("companies", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
IConsoleAliasRegister("players", "companies"); IConsoleAliasRegister("players", "companies");
IConsoleCmdRegister("say_company", ConSayCompany); IConsoleCmdRegister("say_company", ConSayCompany, ConHookNeedNetwork);
IConsoleCmdHookAdd("say_company", ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
IConsoleAliasRegister("say_player", "say_company %+"); IConsoleAliasRegister("say_player", "say_company %+");
IConsoleCmdRegister("say_client", ConSayClient); IConsoleCmdRegister("say_client", ConSayClient, ConHookNeedNetwork);
IConsoleCmdHookAdd("say_client", ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
IConsoleCmdRegister("connect", ConNetworkConnect); IConsoleCmdRegister("connect", ConNetworkConnect, ConHookClientOnly);
IConsoleCmdHookAdd("connect", ICONSOLE_HOOK_ACCESS, ConHookClientOnly); IConsoleCmdRegister("clients", ConNetworkClients, ConHookNeedNetwork);
IConsoleCmdRegister("clients", ConNetworkClients); IConsoleCmdRegister("status", ConStatus, ConHookServerOnly);
IConsoleCmdHookAdd("clients", ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork); IConsoleCmdRegister("server_info", ConServerInfo, ConHookServerOnly);
IConsoleCmdRegister("status", ConStatus);
IConsoleCmdHookAdd("status", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
IConsoleCmdRegister("server_info", ConServerInfo);
IConsoleCmdHookAdd("server_info", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
IConsoleAliasRegister("info", "server_info"); IConsoleAliasRegister("info", "server_info");
IConsoleCmdRegister("reconnect", ConNetworkReconnect); IConsoleCmdRegister("reconnect", ConNetworkReconnect, ConHookClientOnly);
IConsoleCmdHookAdd("reconnect", ICONSOLE_HOOK_ACCESS, ConHookClientOnly); IConsoleCmdRegister("rcon", ConRcon, ConHookNeedNetwork);
IConsoleCmdRegister("rcon", ConRcon);
IConsoleCmdHookAdd("rcon", ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
IConsoleCmdRegister("join", ConJoinCompany); IConsoleCmdRegister("join", ConJoinCompany, ConHookNeedNetwork);
IConsoleCmdHookAdd("join", ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
IConsoleAliasRegister("spectate", "join 255"); IConsoleAliasRegister("spectate", "join 255");
IConsoleCmdRegister("move", ConMoveClient); IConsoleCmdRegister("move", ConMoveClient, ConHookServerOnly);
IConsoleCmdHookAdd("move", ICONSOLE_HOOK_ACCESS, ConHookServerOnly); IConsoleCmdRegister("reset_company", ConResetCompany, ConHookServerOnly);
IConsoleCmdRegister("reset_company", ConResetCompany);
IConsoleCmdHookAdd("reset_company", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
IConsoleAliasRegister("clean_company", "reset_company %A"); IConsoleAliasRegister("clean_company", "reset_company %A");
IConsoleCmdRegister("client_name", ConClientNickChange); IConsoleCmdRegister("client_name", ConClientNickChange, ConHookServerOnly);
IConsoleCmdHookAdd("client_name", ICONSOLE_HOOK_ACCESS, ConHookServerOnly); IConsoleCmdRegister("kick", ConKick, ConHookServerOnly);
IConsoleCmdRegister("kick", ConKick); IConsoleCmdRegister("ban", ConBan, ConHookServerOnly);
IConsoleCmdHookAdd("kick", ICONSOLE_HOOK_ACCESS, ConHookServerOnly); IConsoleCmdRegister("unban", ConUnBan, ConHookServerOnly);
IConsoleCmdRegister("ban", ConBan); IConsoleCmdRegister("banlist", ConBanList, ConHookServerOnly);
IConsoleCmdHookAdd("ban", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
IConsoleCmdRegister("unban", ConUnBan);
IConsoleCmdHookAdd("unban", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
IConsoleCmdRegister("banlist", ConBanList);
IConsoleCmdHookAdd("banlist", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
IConsoleCmdRegister("pause", ConPauseGame); IConsoleCmdRegister("pause", ConPauseGame, ConHookServerOnly);
IConsoleCmdHookAdd("pause", ICONSOLE_HOOK_ACCESS, ConHookServerOnly); IConsoleCmdRegister("unpause", ConUnPauseGame, ConHookServerOnly);
IConsoleCmdRegister("unpause", ConUnPauseGame);
IConsoleCmdHookAdd("unpause", ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
IConsoleCmdRegister("company_pw", ConCompanyPassword); IConsoleCmdRegister("company_pw", ConCompanyPassword, ConHookNeedNetwork);
IConsoleCmdHookAdd("company_pw", ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
IConsoleAliasRegister("company_password", "company_pw %+"); IConsoleAliasRegister("company_password", "company_pw %+");
IConsoleAliasRegister("net_frame_freq", "setting frame_freq %+"); IConsoleAliasRegister("net_frame_freq", "setting frame_freq %+");

View File

@ -19,24 +19,6 @@ enum {
ICON_MAX_STREAMSIZE = 2048, ///< maximum length of a totally expanded command ICON_MAX_STREAMSIZE = 2048, ///< maximum length of a totally expanded command
}; };
enum IConsoleHookTypes {
ICONSOLE_HOOK_ACCESS,
ICONSOLE_HOOK_PRE_ACTION,
ICONSOLE_HOOK_POST_ACTION
};
/** --Hooks--
* Hooks are certain triggers that are executed on either
* access, before execution or after execution. This allows
* for general flow of permissions or special action needed in some cases
*/
typedef bool IConsoleHook();
struct IConsoleHooks {
IConsoleHook *access; ///< trigger when accessing the command
IConsoleHook *pre; ///< trigger before the command is executed
IConsoleHook *post; ///< trigger after the command is executed
};
/** --Commands-- /** --Commands--
* Commands are commands, or functions. They get executed once and any * Commands are commands, or functions. They get executed once and any
* effect they produce are carried out. The arguments to the commands * effect they produce are carried out. The arguments to the commands
@ -44,14 +26,14 @@ struct IConsoleHooks {
* If you want to handle multiple words as one, enclose them in double-quotes * If you want to handle multiple words as one, enclose them in double-quotes
* eg. 'say "hello sexy boy"' * eg. 'say "hello sexy boy"'
*/ */
typedef bool (IConsoleCmdProc)(byte argc, char *argv[]); typedef bool IConsoleCmdProc(byte argc, char *argv[]);
typedef bool IConsoleHook();
struct IConsoleCmd { struct IConsoleCmd {
char *name; ///< name of command char *name; ///< name of command
IConsoleCmd *next; ///< next command in list IConsoleCmd *next; ///< next command in list
IConsoleCmdProc *proc; ///< process executed when command is typed IConsoleCmdProc *proc; ///< process executed when command is typed
IConsoleHooks hook; ///< any special trigger action that needs executing IConsoleHook *hook; ///< any special trigger action that needs executing
}; };
/** --Aliases-- /** --Aliases--
@ -80,7 +62,7 @@ extern IConsoleAlias *_iconsole_aliases; ///< list of registred aliases
void IConsoleClearBuffer(); void IConsoleClearBuffer();
/* Commands */ /* Commands */
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc); void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc, IConsoleHook *hook = NULL);
void IConsoleAliasRegister(const char *name, const char *cmd); void IConsoleAliasRegister(const char *name, const char *cmd);
IConsoleCmd *IConsoleCmdGet(const char *name); IConsoleCmd *IConsoleCmdGet(const char *name);
IConsoleAlias *IConsoleAliasGet(const char *name); IConsoleAlias *IConsoleAliasGet(const char *name);
@ -88,9 +70,6 @@ IConsoleAlias *IConsoleAliasGet(const char *name);
/* console std lib (register ingame commands/aliases) */ /* console std lib (register ingame commands/aliases) */
void IConsoleStdLibRegister(); void IConsoleStdLibRegister();
/* Hooking code */
void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
/* Supporting functions */ /* Supporting functions */
bool GetArgumentInteger(uint32 *value, const char *arg); bool GetArgumentInteger(uint32 *value, const char *arg);