/* Do not remove the headers from this file! see /USAGE for more info. */ #include <mudlib.h> #include <hooks.h> #include <driver/function.h> //:MODULE // //The hook module is included as part of OBJECT, and allows a general method //of allowing keeping track of and calling hooks, along with a method if //specifying how multiple hooks should be resolved. private nosave mapping hooks = ([]); //:FUNCTION add_hook //add_hook(string tag, function hook) sets up the function 'hook' to be //called whenever call_hooks(tag, ...) is done. Note that if you want //to remove the tag later, you have to do so with the _exact_ same function //pointer. // //e.g. // //function my_hook = (: my_hook_func :); // // add_hook("foo", my_hook); // // remove_hook("foo", my_hook); // void add_hook(string tag, function hook) { array tmp = ({ hook }); if (hooks[tag]) { // Make sure we only have one hooks[tag] -= tmp; hooks[tag] += tmp; } else hooks[tag] = tmp; } //:FUNCTION remove_hook // //Remove a hook added with add_hook. The function pointer passed must be //the same one that was passed to add_hook. // //see: add_hook void remove_hook(string tag, function hook) { if (hooks[tag]) hooks[tag] -= ({ hook }); if(!sizeof(hooks[tag])) map_delete(hooks,tag); } //:FUNCTION hook_state // //hook_state(tag, hook, state) Either add or remove a hook based on the //state 'state' void hook_state(string tag, mixed hook, int state) { if (state) add_hook(tag, hook); else remove_hook(tag, hook); } //:FUNCTION call_hooks // //Call a set of hooks, with the specified method for resolving multiple //hooks. A setting from /include/hooks.h can be used, or a function pointer //which is appropriate for implode()ing with the return values. // //E.g. // // call_hooks("foo", (: $1 + $2 :), 2) will return 2 + the sum of the return // values of the hooks // // but 2 + call_hooks("foo", HOOK_SUM) is faster. // //see: implode //see: add_hook varargs mixed call_hooks(string tag, mixed func, mixed start, array args...) { array hooks_to_call; mixed tmp; function hook; if (hooks_to_call = hooks[tag]) { hooks_to_call = filter(hooks_to_call, (: !(functionp($1) & FP_OWNER_DESTED) :)); hooks[tag] = hooks_to_call; if (!intp(func)) return implode(map(hooks_to_call, (: evaluate($1, $(args)...) :)), func, start); switch (func) { case HOOK_IGNORE: map(hooks_to_call, (: evaluate($1, $(args)...) :)); return 0; case HOOK_SUM: foreach (hook in hooks_to_call) tmp += evaluate(hook, args...); return tmp; case HOOK_LAND: foreach (hook in hooks_to_call) if (!evaluate(hook, args...)) return 0; return 1; case HOOK_LOR: foreach (hook in hooks_to_call) if (tmp = evaluate(hook, args...)) return tmp; return 0; case HOOK_YES_NO_ERROR: foreach (hook in hooks_to_call) { tmp = evaluate(hook, args...); if (!tmp || stringp(tmp)) return tmp; } return (start || 1); default: error("Unknown hook type in call_hooks.\n"); } } else { if (!intp(func)) return start; switch (func) { case HOOK_IGNORE: case HOOK_SUM: case HOOK_LOR: return 0; case HOOK_LAND: return 1; case HOOK_YES_NO_ERROR: return (start || 1); default: error("Unknown hook type in call_hooks.\n"); } } } mapping debug_hooks() { return copy(hooks); }