<html> <head> <link href="../tutorial.css" rel="stylesheet" type="text/css"> </head> <body> <div class="header"> The NakedMud Tutorial :: Hooks </div> <!-- content starts here --> <div class="content-wrap"><div class="content-body-wrap"><div class="content"> <div class="head">Hooks</div> <div class="info"> NakedMud functions can be open-endedly extended in key areas, through the use of hooks. When a character enters a room, a few things might need to be done. If there are hostile NPCs in the room, they might start attacking the character. If the player is walking over soft earth, footprints might need to be placed. If a trap is present, it might need to go off. If the character is a king, his servants might need to greet him. If NPCs have other scripted behavior, it might also need to be resolved. Adding checks for this in the enter and exit function leads to unwieldy and unmanageable code. Instead, NakedMud provides a framework that allows you to specify places where functions can register to 'hook' on to. Those functions will then be called whenever the designated place is reached. </div> <div class="head">Creating a Hook Point</div> <div class="info"> In lib/pymodules/movement.c, there is a function called try_move. It it the main function for handling all directional movement. After a character has sucessfully moved between rooms, this line of code is called: <pre class="code"> import hooks ... hooks.run("enter", hooks.build_info("ch rm", (ch, ch.room))) </pre> This provides a point for other functions to hook on to. They can register to be called whenever this point in the code is reached. Hooks are not ordered, nor are they blocking. You cannot guarantee they will run in a particular ordering, nor can you stop sucessive hooks from executing if something special happens in a previous one. </div> <div class="head" style="text-transform: none;">hooks.run(type, info)</div> <div class="info"> The run function takes two arguments. The first is the type of the hooks to run. It can be any string. The second is a specially formatted list of variables to pass on to registered functions. This list is created with a call to hooks.build_info </div> <div class="head" style="text-transform: none;">hooks.build_info(format, variables)</div> <div class="info"> Hook points pass arguments to their attached hooks through a special information string that stores the argument information. Arguments can be characters, objects, rooms, exits, sockets, strings, integers, or doubles. Argument strings need to be built from a format string and a tuple of the variables that will be stored in the argument information. The format string is a space-separated list of shorthands for the argument types. The shorthands are: <div class="table"> <table width=100% border=1> <thead> <tr> <th> formatting </th> <th> argument type </th> <tr> </thead> <tbody> <tr class="odd"> <td>ch</td> <td>characters</td></tr> <tr class="even"><td>obj</td> <td>objects</td></tr> <tr class="odd"> <td>rm</td> <td>rooms</td></tr> <tr class="even"><td>ex</td> <td>exits</td></tr> <tr class="odd"> <td>sk</td> <td>sockets</td></tr> <tr class="even"><td>str</td> <td>strings</td></tr> <tr class="odd"> <td>int</td> <td>integers</td></tr> <tr class="even"><td>dbl</td> <td>doubles</td></tr> <tbody> </table> </div> </div> <div class="head" style="text-transform: none;">hooks.add(type, function)</div> <div class="info"> To add a hook, a call to hooks.add must be made during initialization. The add function takes two arguments: the type of hook point to attach to, and a function to be called. The function itself should take one argument: an argument string that is created by the hook point, with hooks.build_info <pre class="code"> def footstep_hook(info): """make crunchy footstep sounds when we enter a room with snow.""" ############ # FINISH ME ############ hooks.add("enter", footstep_hook) </pre> </div> <div class="head" style="text-transform: none;">hooks.parse_info(info)</div> <div class="info"> Hooks take a single argument: an information string, that can be unpacked to retreive the original arguments passed to hooks.build_info by the hook point. This function will return a tuple of the original arguments. Here is a continuation of the footstep hook: <pre class="code"> def footstep_hook(info): """make crunchy footstep sounds when we enter a room with snow.""" ch, room = hooks.parse_info(info) if room.terrain == "snow": ch.send("Snow crunches beneath your feet.") </pre> </div> <!-- content ends here--> </div></div></div> <!-- navigation starts here --> <div class="nav-wrap"><div class="nav"> <iframe src="nav.html" height="100%" width="100%" scrolling=no frameborder=0> </iframe> <!-- navigation ends here --> </div></div> <!--div class="footer">Edit Date: Nov 15, 2008. By Geoff Hollis</div--> </body> </html>