123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- <html>
- <head>
- <link href="../tutorial.css" rel="stylesheet" type="text/css">
- </head>
- <body>
- <div class="header">
- The NakedMud Tutorial :: Events
- </div>
- <!-- content starts here -->
- <div class="content-wrap"><div class="content-body-wrap"><div class="content">
- <div class="head">Events</div>
- <div class="info">
- NakedMud provides support for delayed events. These are simply functions that
- are called after a pre-specified amount of time. They are not to be confused
- with Events in, say, Java, which refer to specific things that take place
- (such as someone clicking on a mouse) which have a set of 'listeners' that
- execute some function once the event occurs. NakedMud supports this sort of
- behavior as well, in the form of hooks.
- <p></p>
- Events have three parameters. An owner, data, and a string argument, each of
- which might possibly be None. The owner is the person, place, or thing the event
- belongs to. If the owner ever leaves the game, the event is canceled. The
- owner can be None. For instance, you may want to write a combat update event
- that iterates across all characters and make them perform an attack every
- second. To do this, you could start the event up without an owner when your
- module is initialized, and have the event do its work, and re-start itself
- whenever it is called.
- </div>
- <div class="head">Delayed Commands</div>
- <div class="info">
- The most basic thing that could be done with events is creating a command that
- delays another command for a specified amount of time. Here is how something
- like that would be written:
- <pre class="code">
- import mudsys, event, mud
- def delayed_cmd_event(owner, data, arg):
- ch.act(arg)
- def cmd_delay(ch, cmd, arg):
- '''attempt to delay a command by a specified amount of time.'''
- try:
- # take two arguments: the delay time, and the command to execute
- time, todo = mud.parse_args(ch, True, cmd, arg, "int(time) string(cmd)")
- except: return
- # notify the character that their command has been delayed,
- # and start the event handler
- ch.send("In %d seconds you will perform '%s'." % (time, todo))
- event.start_event(ch, time, delayed_cmd_event, None, todo)
- mudsys.add_cmd("delay", None, cmd_delay, "player", False)
- </pre>
- <p></p>
- Data can be anything you want it to be. Suppose you want to implement a delayed
- fireball spell that hurts everyone in the room except for the person who set it
- up. The owner would be the room, and the data might be the character. You could
- possibly do it as the owner being the character and the data being None, but
- think what might happen if the character decided to move before the event went
- off! Here is one way to do a delayed fireball event
- <pre class="code">
- import mudsys, event
- def delayed_fireball_event(room, caster, arg):
- '''do the delayed fireball event. Hurt everyone in the room except the
- caster. arg is None.'''
- room.send("With violent force, a delayed fireball explodes in the room!")
- for ch in room:
- if ch != caster:
- # do something mean here
- ############
- # FINISH ME
- ############
- def cmd_delayed_fireball(ch, cmd, arg):
- '''cast a delayed fireball.'''
- ch.send("You set up a delayed fireball to go off in 5 seconds!")
- event.start_event(ch.room, 5, delayed_fireball_event, ch, None)
- mudsys.add_cmd("df", None, cmd_delayed_fireball, "player", False)
- </pre>
- </div>
- <div class="head">Writing Handlers</div>
- <div class="info">
- Suppose you want some sort of handler to run on a periodic basis. Maybe you want
- everyone in combat to attack each second, or maybe you want to extract linkdead
- characters every five minutes. Periodic handlers can be created with events that
- requeue theirselves. Here is an example of an event that saves characters every
- 5 minutes, and extracts those that are linkdead:
- <pre class="code">
- '''
- autosave.py
- automatically save all existing PCs, every 5 mins. Extract those that are
- linkdead.
- '''
- import mudsys, event, mud
- import char as mudchar
- __autosave_delay__ = 5 * 60
- def autosave_event(owner, data, arg):
- '''go through all our characters and save them. Then, force-quit them if
- they are linkdead.'''
- try:
- for ch in mudchar.char_list():
- if ch.is_pc:
- mudsys.do_save(ch)
- if ch.socket == None:
- mudsys.do_quit(ch)
- except: pass
- # make sure we requeue the event outside the body of the try block.
- # this is just so that if something goes wrong with the event, the event
- # is still requeued.
- event.start_event(None, __autosave_delay__, autosave_event)
- event.start_event(None, __autosave_delay__, autosave_event)
- </pre>
- </div>
- <div class="head">Starting and Stopping</div>
- <div class="info">
- Once an event is started, it cannot be canceled unless its owner is removed
- from the game, so be certain to design your events with this in mind.
- <p></p>
- Events are started with a call to start_event. This function takes three
- mandatory arguments, and two optional ones. The first argument is the owner,
- the second is the time to delay the event, and the third is the event itself.
- The fourth and fifth are the data and the string argument, respectively.
- </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>
|