Man hooks
From LSWiki
(Difference between revisions)
Revision as of 15:33, 11 June 2007 (edit) Laine (Talk | contribs) ← Previous diff |
Current revision (17:04, 11 June 2007) (edit) Laine (Talk | contribs) (→Disambiguation) |
||
Line 1: | Line 1: | ||
- | ==Description== | + | =Disambiguation= |
- | To allow a greater flexibility of the muds, the gamedrivers | + | * [[man hooks(concepts)|hooks(concepts)]] |
- | since 3.2.1 moved several once hardcoded 'underground' | + | * [[man hooks(mechanism)|hooks(mechanism)]] |
- | activities from the driver into the mudlib. This includes for | + | |
- | example the differences between compat and native mode. | + | |
- | + | ||
- | The hooks are set with the privileged efun set_driver_hook(). | + | |
- | Some of the hooks are mandatory, some not. Most hooks accept | + | |
- | unbound lambda closures as values, some also lfun closures or | + | |
- | even strings. | + | |
- | + | ||
- | The hooks are identified by an ordinal number, for which | + | |
- | symbolic names are defined in /sys/driverhooks.h. | + | |
- | + | ||
- | *H_MOVE_OBJECT0, H_MOVE_OBJECT1 | + | |
- | + | ||
- | Mandatory hooks to implement the efun void move_object(). | + | |
- | Hook setting must be an unbound lambda closure: | + | |
- | + | ||
- | void <closure>(object item, object dest) | + | |
- | + | ||
- | Upon call, the hook has to perform the move itself (by using | + | |
- | set_environment()) and all depending actions (like the calls to | + | |
- | init() to add actions). | + | |
- | + | ||
- | The difference lies in the binding of the set hook prior to | + | |
- | the call: the H_MOVE_OBJECT0 closure is bound to the current | + | |
- | object, the H_MOVE_OBJECT1 to 'item'. If both hooks are set, H_MOVE_OBJECT0 is ignored. | + | |
- | + | ||
- | *H_LOAD_UIDS, H_CLONE_UIDS | + | |
- | + | ||
- | Mandatory hooks to determine the uid and euid of loaded or cloned | + | |
- | objects. Hook settings can be any closure: | + | |
- | + | ||
- | mixed <load_uids closure> (string objectname) | + | |
- | mixed <clone_uids closure>(object blueprint, string objectname) | + | |
- | + | ||
- | When an object is newly loaded, the H_LOAD_UIDS hook is | + | |
- | called with the object name as argument. When an object is cloned, the H_CLONE_UIDS hook is called | + | |
- | with the blueprint object as first and the clone's designated name as second argument. | + | |
- | In both cases the new object already exists, but has 0 uids. | + | |
- | + | ||
- | For the result, the following possibilities exist (<num> is | + | |
- | a non-zero number, <no-string> is anything but a string): | + | |
- | + | ||
- | "<uid>" -> uid = "<uid>", euid = "<uid>" | + | |
- | ({ "<uid>", "<euid>" }) -> uid = "<uid>", euid = "<euid>" | + | |
- | ({ "<uid>", <no-string> }) -> uid = "<uid>", euid = 0 | + | |
- | + | ||
- | If strict-euids is not active, the following results are | + | |
- | possible, too: | + | |
- | + | ||
- | <num> -> uid = 0, euid = 0 | + | |
- | ({ <num>, "<euid>" }) -> uid = 0, euid = "<euid>" | + | |
- | ({ <num>, <no-string> }) -> uid = 0, euid = 0 | + | |
- | + | ||
- | + | ||
- | *H_CREATE_SUPER, H_CREATE_OB, H_CREATE_CLONE | + | |
- | + | ||
- | Optional hooks to initialize an object after creation. Hook setting can be unbound lambda closures, or the name of the function to call in the object. | + | |
- | + | ||
- | H_CREATE_SUPER is called for blueprints implicitely loaded by inheritance, H_CREATE_OB for explicitely loaded blueprints/objects, and H_CREATE_CLONE for cloned objects. | + | |
- | + | ||
- | If the hook is a closure expecting an argument, it is bound to the current object and called as | + | |
- | + | ||
- | int <closure> (object obj_to_init) | + | |
- | + | ||
- | If the hook as a closure without arguments, it is bound to | + | |
- | the object to be initalized and called as | + | |
- | + | ||
- | int <closure> ( void ) | + | |
- | + | ||
- | If the result of the call is a non-zero number, it is used as the interval to wait before the first reset(), else the default interval computed from TIME_TO_RESET is used. | + | |
- | + | ||
- | If the hook is defined as the name of an lfun (static or public) | + | |
- | in the object, it is called in the object as | + | |
- | + | ||
- | void <name>(0) | + | |
- | + | ||
- | and any result is ignored. In this call the previous_object() is the object initiating the load. | + | |
- | + | ||
- | *H_RESET | + | |
- | + | ||
- | Optional hook to reset an object. Hook setting can be unbound lambda closures, or the name of | + | |
- | the function to call in the object. | + | |
- | + | ||
- | This hook is called to reset the object after a certain time since its creation/last reset. | + | |
- | + | ||
- | If the hook is a closure, it is bound to the object to be reset and called with no argument: | + | |
- | + | ||
- | void|int <closure> ( void ) | + | |
- | + | ||
- | If the result of the call is a positive number, it is used as the interval to wait before the next reset(). If the result is 0, the default interval computed from | + | |
- | TIME_TO_RESET is used. If the result is a negative number, the object will not be | + | |
- | reset again, unless directed otherwise by set_next_reset(). | + | |
- | + | ||
- | If the hook is defined as the name of an lfun (static or public) in the object, it is called in the object as | + | |
- | + | ||
- | void <name>(1) | + | |
- | + | ||
- | and any result is ignored. In this call the previous_object() is the object initiating | + | |
- | the reset. If the function does not exist, the object won't be reset again. | + | |
- | + | ||
- | *H_CLEAN_UP | + | |
- | Optional hook to clean up an object. Hook setting can be any closure, or the name of the function | + | |
- | to call in the object. | + | |
- | + | ||
- | This hook is called for an object if it hasn't been used for at least TIME_TO_CLEAN_UP seconds, to give it the opportunity to self destruct. | + | |
- | + | ||
- | If the hook is a closure, it is called as | + | |
- | + | ||
- | int <closure>(int ref, object ob) | + | |
- | + | ||
- | with the object's refcount as first argument, and object itself as | + | |
- | second. Lambda closures are also bound to the object prior to the | + | |
- | call. | + | |
- | + | ||
- | If the hook is the name of an lfun, it is called in the | + | |
- | object with its refcount as argument: | + | |
- | + | ||
- | void|int <name>(int ref) | + | |
- | + | ||
- | In both calls, the refcount is constructed as: | + | |
- | + | ||
- | ref = 0: the object is a clone, or a blueprint with | + | |
- | replaced program. | + | |
- | ref = 1: the object is a swapped or unused blueprint. | + | |
- | ref > 1: the object is a used blueprint with <ref> references. | + | |
- | + | ||
- | The cleanup method has the possibility to destruct the | + | |
- | object. To survive this time, but try again some time later, | + | |
- | the call has to result in a non-zero value. | + | |
- | + | ||
- | If the hook specifies a non-existing lfun, or if the call | + | |
- | returns 0, no further attempt to clean up this object will be done. | + | |
- | + | ||
- | + | ||
- | *H_COMMAND | + | |
- | + | ||
- | Optional hook to parse and execute commands. If this hook is used, | + | |
- | it bypasses the normal command parsing done by the driver (including | + | |
- | the MODIFY_COMMAND and NOTIFY_FAIL hooks). | + | |
- | + | ||
- | The hook is called with two parameters: the command received | + | |
- | from the living (interactive user or NPC), and the living object | + | |
- | (the 'command giver') itself. The hook has to return non-0 if the | + | |
- | command was found and executed, and 0 otherwise. | + | |
- | + | ||
- | At the time the hook is called, query_command() returns the command | + | |
- | string and this_player() returns the living object. query_verb() and | + | |
- | query_notify_fail() return 0. | + | |
- | + | ||
- | If the hook is a string, it is the name of an lfun in the command | + | |
- | giver: | + | |
- | + | ||
- | int <name>(string command, object command_giver) | + | |
- | + | ||
- | If the hook is a closure, it is called as: | + | |
- | + | ||
- | int <closure>(string command, object command_giver) | + | |
- | + | ||
- | Lambda-closures are additionally bound to the command_giver. | + | |
- | + | ||
- | + | ||
- | *H_MODIFY_COMMAND | + | |
- | Optional hook to modify commands (both entered or given by a | + | |
- | call to command()) before the parser sees them (this includes | + | |
- | special commands like 'status'). | + | |
- | + | ||
- | Hook setting can be any closure, the name of the function | + | |
- | to call in the object, or a mapping. | + | |
- | + | ||
- | For interactives this hook is used only if the interactive | + | |
- | object has no command modifier already set by the efun | + | |
- | set_modify_command(). | + | |
- | + | ||
- | If the hook is a closure, it is called as | + | |
- | + | ||
- | int|string <closure>(string cmd, object player) | + | |
- | + | ||
- | with the entered command as first, and the command giving | + | |
- | player as second argument. | + | |
- | + | ||
- | If the hook is a string, it is used as the name of an lfun | + | |
- | in the command giving player, which is called as | + | |
- | + | ||
- | int|string <name>(string cmd) | + | |
- | + | ||
- | If the hook is a mapping, it is queried with the given | + | |
- | command as index, and the data retrieved is used (defaults | + | |
- | to 0 if no data is stored for a given command). If an entry | + | |
- | is a closure, it is called as | + | |
- | + | ||
- | int|string <closure>(string cmd, object player) | + | |
- | + | ||
- | and the result from the call is used as 'the' result. | + | |
- | + | ||
- | The result is treated equal in all three cases. | + | |
- | If the result is a string, it is the new command to execute | + | |
- | instead of the given one. Note that it is not possible to | + | |
- | make several commands from one this way! | + | |
- | If the result is a non-zero number, the given command is to | + | |
- | be ignored. In case of the closure/lfun setting this may | + | |
- | mean that the closure/lfun already executed it. | + | |
- | If the result is 0, the originally given command is to be | + | |
- | used. | + | |
- | + | ||
- | It is possible for the hook to change the command giver | + | |
- | (this_player()) for the execution of the command. This means that | + | |
- | even though the commands are execute for the original commandgiver, | + | |
- | this_player() will return the changed commandgiver. | + | |
- | + | ||
- | *H_MODIFY_COMMAND_FNAME | + | |
- | Mandatory hook specifying the name of the 'modify_command' | + | |
- | function to call for newly entered commands as result of a | + | |
- | set_modify_command(). | + | |
- | + | ||
- | Hook setting must be a string. | + | |
- | + | ||
- | If set_modify_command() is used for an interactive user, all | + | |
- | newly entered commands are first passed to the function | + | |
- | named by this hook. | + | |
- | + | ||
- | The function is called as | + | |
- | + | ||
- | int|string <name>(string cmd) | + | |
- | + | ||
- | If the result is a string, it is the new command to execute | + | |
- | instead of the given one. Note that it is not possible to | + | |
- | make several commands from one this way! | + | |
- | If the result is a non-zero number, the given command is to | + | |
- | be ignored. In case of the closure/lfun setting this may | + | |
- | mean that the closure/lfun already executed it. | + | |
- | If the result is 0, the originally given command is to be | + | |
- | used. | + | |
- | + | ||
- | It is possible for the hook to change the command giver | + | |
- | (this_player()) for the execution of the command. This means that | + | |
- | even though the commands are execute for the original commandgiver, | + | |
- | this_player() will return the changed commandgiver. | + | |
- | + | ||
- | *H_NOTIFY_FAIL | + | |
- | + | ||
- | Mandatory hook to issue the default message if an entered | + | |
- | command couldn't be parsed and no notify_fail() command is | + | |
- | in effect. | + | |
- | Hook setting can be a any closure, or a string. | + | |
- | + | ||
- | If set to a string, it is the message returned to the | + | |
- | player. | + | |
- | If set to a closure, it is called as | + | |
- | + | ||
- | string <closure>(string entered_command, object cmd_giver) | + | |
- | + | ||
- | and the result is used as failure message. Lambda closures | + | |
- | are bound to this_player() prior to execution. | + | |
- | + | ||
- | <cmd_giver> is the object which received the command in | + | |
- | the first place. It is usually identical with this_player(), | + | |
- | unless the H_MODIFY_COMMAND hook changed it. | + | |
- | + | ||
- | *H_SEND_NOTIFY_FAIL | + | |
- | + | ||
- | Optional hook to send the notify fail message, regardless | + | |
- | of how it was determined, to the player. If the hook is not | + | |
- | set, the message is delivered using tell_object() internally. | + | |
- | Hook setting can be a string or a closure. | + | |
- | + | ||
- | If the hook is a string, it is the name of a (possibly static) | + | |
- | function to call in the current command giver. If the hook | + | |
- | is a closure, it is the function to be called. Lambda closures | + | |
- | are bound to the current command giver first. | + | |
- | + | ||
- | The function is called as | + | |
- | + | ||
- | void <function>(string msg, object msgobj, object orig_cmd_giver) | + | |
- | + | ||
- | <msg> is the notify fail message to be delivered. | + | |
- | <msgobj> is the object which set the message. It is 0 for the | + | |
- | default message. | + | |
- | <orig_cmd_giver> is the object for which the original command | + | |
- | was first received. It is usually identical with the current | + | |
- | command giver this_player(). | + | |
- | + | ||
- | *H_NO_IPC_SLOT | + | |
- | + | ||
- | Optional hook specifying the message given to logins | + | |
- | rejected due to space limitations (MAX_PLAYER). | + | |
- | Hook setting has to be string. | + | |
- | If set to 0, the default message "Lpmud is full. Come back | + | |
- | later." is issued. | + | |
- | + | ||
- | *H_INCLUDE_DIRS | + | |
- | + | ||
- | Semi-mandatory hook specifying the directories where <>-type | + | |
- | include files are searched (this includes ""-includes not | + | |
- | found as specified). Hook setting may be any closure or a string array. | + | |
- | If not set, only ""-type includes may be used in LPC | + | |
- | programs. | + | |
- | + | ||
- | The hook is called only if a call to master::include_file() | + | |
- | does not return a usable filename. | + | |
- | + | ||
- | If the hook setting is a string array, it has to contain the | + | |
- | path names of those directories where <>-type includes are | + | |
- | to be searched. The directories are searched in the order | + | |
- | they appear in the array. The directory name and the name of | + | |
- | the actual include file are concatenated, therefore the | + | |
- | directory names have to end in '/'. Leading slashes may be | + | |
- | omitted. | + | |
- | + | ||
- | If the setting is a closure, it is called as | + | |
- | + | ||
- | string <closure>(string include_name, string current_file) | + | |
- | + | ||
- | with the name of the desired include file as first, and the | + | |
- | name of the compiled LPC file as second argument. | + | |
- | Result has to be the complete path name of the include file | + | |
- | to use (leading slashes may be omitted). | + | |
- | If the closure is a lambda closure, it is bound to | + | |
- | this_object() prior to execution. | + | |
- | + | ||
- | *H_AUTO_INCLUDE | + | |
- | + | ||
- | Optional hook specifying a string to be included before | + | |
- | the source of every compiled LPC object. | + | |
- | Hook setting can be a string or a closure. | + | |
- | + | ||
- | If the setting is a string, it will be automatically included before | + | |
- | the source of every compiled LPC object. | + | |
- | + | ||
- | If the setting is a closure, it is called as | + | |
- | + | ||
- | string <closure>(string base_file, string current_file | + | |
- | , int sys_include) | + | |
- | + | ||
- | for every file opened by the compiler. <base_file> will be the | + | |
- | filename of the compiled object, <current_file> the name of a file | + | |
- | included directly or indirectly by the <base_file>. When the | + | |
- | <base_file> itself is opened, <current_file> will be 0. For an | + | |
- | included file, <sys_include> will be TRUE if it is a <>-type | + | |
- | include. | + | |
- | + | ||
- | If the result is a string, it will be included before the actual | + | |
- | text of the file. | + | |
- | + | ||
- | *H_TELNET_NEG | + | |
- | + | ||
- | Optional hook to specifiy how to perform a single telnet | + | |
- | negotiation. Hook setting may be any closure or a string. | + | |
- | If not set, most telnet options are rejected (read: only a | + | |
- | very minimal negotiation takes place). | + | |
- | + | ||
- | The hook is called whenever the driver receives a demand for | + | |
- | option negotiation for: | + | |
- | + | ||
- | SB: Suboption negotiation | + | |
- | TELOPT_LINEMODE: linemode | + | |
- | TELOPT_NAWS: window size | + | |
- | TELOPT_TTYPE: terminal type | + | |
- | TELOPT_TM: timing mark | + | |
- | TELOPT_NEWENV: remote environment variables | + | |
- | TELOPT_ENVIRON: remote environment variables | + | |
- | TELOPT_XDISPLOC: remote X display address | + | |
- | TELOPT_TSPEED: terminal speed | + | |
- | TELOPT_BINARY: binary data, needed for non-ASCII charsets | + | |
- | TELOPT_EOR: TinyFugue prompt marker (together with EOR) | + | |
- | + | ||
- | TELOPT_COMPRESS: Mud Compression Protocol | + | |
- | TELOPT_COMPRESS2: Mud Compression Protocol | + | |
- | TELOPT_MSP: Mud Sound Protocol | + | |
- | TELOPT_MXP: Mud Extension Protocol | + | |
- | + | ||
- | The hook has then to perform the negotiation using the efun | + | |
- | binary_message(). | + | |
- | + | ||
- | Alternatively, if H_NOECHO is set, this hook is called | + | |
- | for all telnet data received. | + | |
- | + | ||
- | If the setting is a string, it used as name of an lfun to | + | |
- | call in this_player(): | + | |
- | + | ||
- | void|mixed <name>(int action, int option [, int * opts ] ) | + | |
- | + | ||
- | Similar, if the setting is a closure, it is called as: | + | |
- | + | ||
- | void|mixed <closure>(int action, int option [, int * opts ] ) | + | |
- | + | ||
- | with unbound lambda-closures being bound to this_player() | + | |
- | prior to execution. | + | |
- | + | ||
- | The hook is called for a 'DO/DONT/WILL/WONT <opt>' with the action | + | |
- | (DO/DONT/...) as the first, and <opt> as the second argument. | + | |
- | + | ||
- | If the driver receives the sequence | + | |
- | + | ||
- | IAC SB <opt> <opts>... | + | |
- | + | ||
- | followed by IAC SB/SE, the hook is called with 'SB' as first | + | |
- | argument, <opt> as second, and <opts> as an array of integers as | + | |
- | third argument. | + | |
- | + | ||
- | *H_NOECHO | + | |
- | + | ||
- | Optional hook to specifiy how to perform the telnet actions | + | |
- | to switch the echo mode (used for e.g. password input_to()s). | + | |
- | Hook setting may be any closure or a string. | + | |
- | If not set, a default handling is performed. | + | |
- | + | ||
- | If the setting is a string, it used as name of an lfun to | + | |
- | call in the intercative <user>: | + | |
- | + | ||
- | void <name>(int flag, object user, int no_telnet) | + | |
- | + | ||
- | where <flag> is the echo-flag passed to the input_to() | + | |
- | statement. Similar, if the setting is a closure, it is called as: | + | |
- | + | ||
- | void <closure>(int flag, object user, int no_telnet) | + | |
- | + | ||
- | with unbound lambda-closures being bound to this_player() | + | |
- | prior to execution. | + | |
- | + | ||
- | When set, the hook is called whenever the driver needs to | + | |
- | change the echo mode, thus you can negotiate about things | + | |
- | that are coupled with it, like LINEMODE or | + | |
- | character-at-a-time. | + | |
- | + | ||
- | <local> is a boolean flag: it is TRUE when input_to() was | + | |
- | called with the INPUT_NO_TELNET flag. | + | |
- | + | ||
- | IMPORTANT: If this hook is used, the control of all telnet | + | |
- | negotiation is transferred to the mudlib: all incoming negotiations | + | |
- | are passed to H_TELNET_NEG, and the sending of no-echo negotiations | + | |
- | is handled by this hook. | + | |
- | + | ||
- | *H_ERQ_STOP | + | |
- | + | ||
- | Optional hook to notify the mudlib about the termination of | + | |
- | the erq demon. Hook setting may be any closure. | + | |
- | + | ||
- | The closure is called without arguments: | + | |
- | + | ||
- | void <closure>() | + | |
- | + | ||
- | and may do whatever it likes to clean-up after the erq. | + | |
- | + | ||
- | ==History== | + | |
- | + | ||
- | H_NOTIFY_FAIL recevied the new 'command_giver' argument in 3.2.7. | + | |
- | The hooks concept was introduced in 3.2.1 | + | |
- | The hook for moving was introduced in 3.2.1@1 | + | |
- | The hook for clean up was introduced in 3.2.1@34 | + | |
- | The hook for modifying commands was introduced in 3.2.1@51, | + | |
- | the evaluation of mapping as hooks was extended in 3.2.1@54. | + | |
- | The lfun called as result of set_modify_command() was | + | |
- | 'hooked' in 3.2.1@109. | + | |
- | The hooks for notify_fail and full muds were introduced in 3.2.1@55. | + | |
- | The hook for include dirs was introduced in 3.2.1@57. | + | |
- | The hook for telnet negotiation was introduced in 3.2.1@60. | + | |
- | The hooks for no-echo negotiation and erq-lossage notification | + | |
- | were introduced in 3.2.1@85. | + | |
- | H_COMMAND was introduced in 3.2.7. | + | |
- | H_SEND_NOTIFY_FAIL and H_AUTO_INCLUDE were introduced in 3.2.9. | + | |
- | LDMud 3.2.10 allowed static functions to be specified by name | + | |
- | for H_RESET and H_CREATE_* | + | |
- | LDMud 3.2.11 added the <no_telnet> argument to H_NOECHO. | + | |
- | + | ||
- | ==See Also== | + | |
- | + | ||
- | [[man native|native(C)]], [[man set driver hook|set_driver_hook(E)]] | + |
Current revision
[edit]