Changeset - r14504:48ad1703d7ec
[Not reviewed]
master
0 3 0
smatz - 14 years ago 2010-02-10 18:18:08
smatz@openttd.org
(svn r19085) -Codechange: simplify hooking of console commands
3 files changed with 34 insertions and 157 deletions:
0 comments (0 inline, 0 general)
src/console.cpp
Show inline comments
 
@@ -191,76 +191,6 @@ bool GetArgumentInteger(uint32 *value, c
 
	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
 
 * twice, just with different variables. Yes, templates would be handy. It was
 
@@ -308,18 +238,13 @@ void IConsoleCmdHookAdd(const char *name
 
 * @param name name of the command that will be used
 
 * @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);
 

	
 
	item_new->name = strdup(name);
 
	item_new->next = NULL;
 
	item_new->proc = proc;
 
	item_new->name = new_cmd;
 

	
 
	item_new->hook.access = NULL;
 
	item_new->hook.pre = NULL;
 
	item_new->hook.post = NULL;
 
	item_new->hook = hook;
 

	
 
	IConsoleAddSorted(_iconsole_cmds, item_new, IConsoleCmd, "a command");
 
}
 
@@ -541,11 +466,8 @@ void IConsoleCmdExec(const char *cmdstr)
 
	 */
 
	cmd = IConsoleCmdGet(tokens[0]);
 
	if (cmd != NULL) {
 
		if (IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_ACCESS)) {
 
			IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_PRE_ACTION);
 
			if (cmd->proc(t_index, tokens)) { // index started with 0
 
				IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_POST_ACTION);
 
			} else {
 
		if (cmd->hook == NULL || cmd->hook()) {
 
			if (!cmd->proc(t_index, tokens)) { // index started with 0
 
				cmd->proc(0, NULL); // if command failed, give help
 
			}
 
		}
src/console_cmds.cpp
Show inline comments
 
@@ -106,6 +106,8 @@ DEF_CONSOLE_HOOK(ConHookNoNetwork)
 
	return true;
 
}
 

	
 
#else
 
#	define ConHookNoNetwork NULL
 
#endif /* ENABLE_NETWORK */
 

	
 
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 proc: %p", cmd->proc);
 

	
 
	if (cmd->hook.access) IConsoleWarning("command is access hooked");
 
	if (cmd->hook.pre) IConsoleWarning("command is pre hooked");
 
	if (cmd->hook.post) IConsoleWarning("command is post hooked");
 
	if (cmd->hook != NULL) IConsoleWarning("command is hooked");
 

	
 
	return true;
 
}
 
@@ -1721,7 +1721,7 @@ void IConsoleStdLibRegister()
 
	IConsoleCmdRegister("getseed",      ConGetSeed);
 
	IConsoleCmdRegister("getdate",      ConGetDate);
 
	IConsoleCmdRegister("quit",         ConExit);
 
	IConsoleCmdRegister("resetengines", ConResetEngines);
 
	IConsoleCmdRegister("resetengines", ConResetEngines, ConHookNoNetwork);
 
	IConsoleCmdRegister("return",       ConReturn);
 
	IConsoleCmdRegister("screenshot",   ConScreenShot);
 
	IConsoleCmdRegister("script",       ConScript);
 
@@ -1761,66 +1761,42 @@ void IConsoleStdLibRegister()
 

	
 
	/* networking functions */
 
#ifdef ENABLE_NETWORK
 
	/* Network hooks; only active in network */
 
	IConsoleCmdHookAdd ("resetengines", ICONSOLE_HOOK_ACCESS, ConHookNoNetwork);
 

	
 
/* Content downloading is only available with ZLIB */
 
#if defined(WITH_ZLIB)
 
	IConsoleCmdRegister("content",         ConContent);
 
#endif /* defined(WITH_ZLIB) */
 

	
 
	/*** Networking commands ***/
 
	IConsoleCmdRegister("say",             ConSay);
 
	IConsoleCmdHookAdd("say",              ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
 
	IConsoleCmdRegister("companies",       ConCompanies);
 
	IConsoleCmdHookAdd("companies",        ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleCmdRegister("say",             ConSay, ConHookNeedNetwork);
 
	IConsoleCmdRegister("companies",       ConCompanies, ConHookServerOnly);
 
	IConsoleAliasRegister("players",       "companies");
 
	IConsoleCmdRegister("say_company",     ConSayCompany);
 
	IConsoleCmdHookAdd("say_company",      ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
 
	IConsoleCmdRegister("say_company",     ConSayCompany, ConHookNeedNetwork);
 
	IConsoleAliasRegister("say_player",    "say_company %+");
 
	IConsoleCmdRegister("say_client",      ConSayClient);
 
	IConsoleCmdHookAdd("say_client",       ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
 
	IConsoleCmdRegister("say_client",      ConSayClient, ConHookNeedNetwork);
 

	
 
	IConsoleCmdRegister("connect",         ConNetworkConnect);
 
	IConsoleCmdHookAdd("connect",          ICONSOLE_HOOK_ACCESS, ConHookClientOnly);
 
	IConsoleCmdRegister("clients",         ConNetworkClients);
 
	IConsoleCmdHookAdd("clients",          ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
 
	IConsoleCmdRegister("status",          ConStatus);
 
	IConsoleCmdHookAdd("status",           ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleCmdRegister("server_info",     ConServerInfo);
 
	IConsoleCmdHookAdd("server_info",      ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleCmdRegister("connect",         ConNetworkConnect, ConHookClientOnly);
 
	IConsoleCmdRegister("clients",         ConNetworkClients, ConHookNeedNetwork);
 
	IConsoleCmdRegister("status",          ConStatus, ConHookServerOnly);
 
	IConsoleCmdRegister("server_info",     ConServerInfo, ConHookServerOnly);
 
	IConsoleAliasRegister("info",          "server_info");
 
	IConsoleCmdRegister("reconnect",       ConNetworkReconnect);
 
	IConsoleCmdHookAdd("reconnect",        ICONSOLE_HOOK_ACCESS, ConHookClientOnly);
 
	IConsoleCmdRegister("rcon",            ConRcon);
 
	IConsoleCmdHookAdd("rcon",             ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
 
	IConsoleCmdRegister("reconnect",       ConNetworkReconnect, ConHookClientOnly);
 
	IConsoleCmdRegister("rcon",            ConRcon, ConHookNeedNetwork);
 

	
 
	IConsoleCmdRegister("join",            ConJoinCompany);
 
	IConsoleCmdHookAdd("join",             ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
 
	IConsoleCmdRegister("join",            ConJoinCompany, ConHookNeedNetwork);
 
	IConsoleAliasRegister("spectate",      "join 255");
 
	IConsoleCmdRegister("move",            ConMoveClient);
 
	IConsoleCmdHookAdd("move",             ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleCmdRegister("reset_company",   ConResetCompany);
 
	IConsoleCmdHookAdd("reset_company",    ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleCmdRegister("move",            ConMoveClient, ConHookServerOnly);
 
	IConsoleCmdRegister("reset_company",   ConResetCompany, ConHookServerOnly);
 
	IConsoleAliasRegister("clean_company", "reset_company %A");
 
	IConsoleCmdRegister("client_name",     ConClientNickChange);
 
	IConsoleCmdHookAdd("client_name",      ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleCmdRegister("kick",            ConKick);
 
	IConsoleCmdHookAdd("kick",             ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleCmdRegister("ban",             ConBan);
 
	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("client_name",     ConClientNickChange, ConHookServerOnly);
 
	IConsoleCmdRegister("kick",            ConKick, ConHookServerOnly);
 
	IConsoleCmdRegister("ban",             ConBan, ConHookServerOnly);
 
	IConsoleCmdRegister("unban",           ConUnBan, ConHookServerOnly);
 
	IConsoleCmdRegister("banlist",         ConBanList, ConHookServerOnly);
 

	
 
	IConsoleCmdRegister("pause",           ConPauseGame);
 
	IConsoleCmdHookAdd("pause",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleCmdRegister("unpause",         ConUnPauseGame);
 
	IConsoleCmdHookAdd("unpause",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
	IConsoleCmdRegister("pause",           ConPauseGame, ConHookServerOnly);
 
	IConsoleCmdRegister("unpause",         ConUnPauseGame, ConHookServerOnly);
 

	
 
	IConsoleCmdRegister("company_pw",      ConCompanyPassword);
 
	IConsoleCmdHookAdd("company_pw",       ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
 
	IConsoleCmdRegister("company_pw",      ConCompanyPassword, ConHookNeedNetwork);
 
	IConsoleAliasRegister("company_password",      "company_pw %+");
 

	
 
	IConsoleAliasRegister("net_frame_freq",        "setting frame_freq %+");
src/console_internal.h
Show inline comments
 
@@ -19,24 +19,6 @@ enum {
 
	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 are commands, or functions. They get executed once and any
 
 * 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
 
 * eg. 'say "hello sexy boy"'
 
 */
 
typedef bool (IConsoleCmdProc)(byte argc, char *argv[]);
 

	
 
typedef bool IConsoleCmdProc(byte argc, char *argv[]);
 
typedef bool IConsoleHook();
 
struct IConsoleCmd {
 
	char *name;               ///< name of command
 
	IConsoleCmd *next;        ///< next command in list
 

	
 
	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--
 
@@ -80,7 +62,7 @@ extern IConsoleAlias *_iconsole_aliases;
 
void IConsoleClearBuffer();
 

	
 
/* 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);
 
IConsoleCmd *IConsoleCmdGet(const char *name);
 
IConsoleAlias *IConsoleAliasGet(const char *name);
 
@@ -88,9 +70,6 @@ IConsoleAlias *IConsoleAliasGet(const ch
 
/* console std lib (register ingame commands/aliases) */
 
void IConsoleStdLibRegister();
 

	
 
/* Hooking code */
 
void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
 

	
 
/* Supporting functions */
 
bool GetArgumentInteger(uint32 *value, const char *arg);
 

	
0 comments (0 inline, 0 general)