|
|
|
@ -472,6 +472,88 @@ bool GetArgumentInteger(uint32 *value, const char *arg)
|
|
|
|
|
return (arg == endptr) ? false : true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// * ************************* * //
|
|
|
|
|
// * hooking code * //
|
|
|
|
|
// * ************************* * //
|
|
|
|
|
/**
|
|
|
|
|
* General internal hooking code that is the same for both commands and variables
|
|
|
|
|
* @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 successfull 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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add a hook to a variable that will be triggered at certain points
|
|
|
|
|
* @param name name of the variable 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 IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc)
|
|
|
|
|
{
|
|
|
|
|
IConsoleVar *var = IConsoleVarGet(name);
|
|
|
|
|
if (var == NULL) return;
|
|
|
|
|
IConsoleHookAdd(&var->hook, type, proc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Perhaps ugly macro, but this saves us the trouble of writing the same function
|
|
|
|
|
* three types, just with different variables. Yes, templates would be handy. It was
|
|
|
|
@ -729,6 +811,7 @@ IConsoleVar *IConsoleVarGet(const char *name)
|
|
|
|
|
*/
|
|
|
|
|
static void IConsoleVarSetValue(const IConsoleVar *var, uint32 value)
|
|
|
|
|
{
|
|
|
|
|
IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_PRE_ACTION);
|
|
|
|
|
switch (var->type) {
|
|
|
|
|
case ICONSOLE_VAR_BOOLEAN:
|
|
|
|
|
*(bool*)var->addr = (value != 0);
|
|
|
|
@ -751,6 +834,7 @@ static void IConsoleVarSetValue(const IConsoleVar *var, uint32 value)
|
|
|
|
|
default: NOT_REACHED();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_POST_ACTION);
|
|
|
|
|
IConsoleVarPrintSetValue(var);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -764,7 +848,9 @@ static void IConsoleVarSetStringvalue(const IConsoleVar *var, char *value)
|
|
|
|
|
{
|
|
|
|
|
if (var->type != ICONSOLE_VAR_STRING || var->addr == NULL) return;
|
|
|
|
|
|
|
|
|
|
IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_PRE_ACTION);
|
|
|
|
|
ttd_strlcpy((char*)var->addr, (char*)value, var->size);
|
|
|
|
|
IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_POST_ACTION);
|
|
|
|
|
IConsoleVarPrintSetValue(var); // print out the new value, giving feedback
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -918,88 +1004,6 @@ void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[ICON_T
|
|
|
|
|
IConsoleError("invalid variable assignment");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// * ************************* * //
|
|
|
|
|
// * hooking code * //
|
|
|
|
|
// * ************************* * //
|
|
|
|
|
/**
|
|
|
|
|
* General internal hooking code that is the same for both commands and variables
|
|
|
|
|
* @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 successfull execution of the hook command or if there
|
|
|
|
|
* is no hook/trigger present at all. False otherwise
|
|
|
|
|
*/
|
|
|
|
|
static bool IConsoleHookHandle(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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add a hook to a variable that will be triggered at certain points
|
|
|
|
|
* @param name name of the variable 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 IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc)
|
|
|
|
|
{
|
|
|
|
|
IConsoleVar *var = IConsoleVarGet(name);
|
|
|
|
|
if (var == NULL) return;
|
|
|
|
|
IConsoleHookAdd(&var->hook, type, proc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add a callback function to the variable. Some variables need
|
|
|
|
|
* very special processing, which can only be done with custom code
|
|
|
|
@ -1109,12 +1113,9 @@ void IConsoleCmdExec(const char *cmdstr)
|
|
|
|
|
|
|
|
|
|
var = IConsoleVarGet(tokens[0]);
|
|
|
|
|
if (var != NULL) {
|
|
|
|
|
if (IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_ACCESS)) {
|
|
|
|
|
IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_PRE_ACTION);
|
|
|
|
|
if (IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_ACCESS))
|
|
|
|
|
IConsoleVarExec(var, t_index, &tokens[1]);
|
|
|
|
|
if (t_index != 0) // value has indeed been changed
|
|
|
|
|
IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_POST_ACTION);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|