Add basic structure of event types and helpers

This commit is contained in:
Vincent Le Goff 2017-03-08 21:13:27 -08:00 committed by Griatch
parent 9f581ea7e1
commit 74ab1ed030
5 changed files with 147 additions and 3 deletions

View file

@ -122,7 +122,7 @@ This section will explain how to add new helper functions and events.
Default events are great but you may need more events to fit with your purposes. For instance, if you have a `yell` command and would like a `can_yell` event in all your rooms.
The way to do this is to add, below your class definition, lines to add these events. The `create_event` function should be called. It takes the following arguments:
The way to do this is to add, below your class definition, lines to add these events. The `create_event_type` function should be called. It takes the following arguments:
- The class to have these events (defined above).
- The name of the event to add (str).
@ -134,7 +134,7 @@ Here's an example of adding the `can_yell` event to all your rooms:
```python
# In typeclasses/rooms.py
from evennia import DefaultRoom
from evennia.contrib.events.extend import create_event
from evennia.contrib.events.extend import create_event_type
class Room(DefaultRoom):
"""
@ -149,7 +149,7 @@ class Room(DefaultRoom):
pass
# Room events
create_event(Room, "can_yell", ["character", "room", "message"], """
create_event_type(Room, "can_yell", ["character", "room", "message"], """
Can the character yell in this room?
This event is called when a character uses the 'yell' command
to yell in this room. This event is called BEFORE the character

View file

@ -0,0 +1,15 @@
"""
Module containing the exceptions of the event system.
"""
class InterruptEvent(RuntimeError):
"""
Interrupt the current event.
You shouldn't have to use this exception directly, probably use the
`deny()` function that handles it instead.
"""
pass

View file

@ -0,0 +1,72 @@
"""
Functions to extend the event system.
These funcitons are not helpers (helpers are in a separate module)
and are designed to be used more by developers to add event types.
"""
from evennia import logger
from evennia import ScriptDB
def create_event_type(typeclass, event_name, variables, help_text):
"""
Create a new event type for a specific typeclass.
Args:
typeclass (type): the class defining tye typeclass to be used.
event_name (str): the name of the event to be added.
variables (list of str): a list of variable names.
help_text (str): a help text of the event.
Events obey the inheritance hierarchy: if you set an event on
DefaultRoom, for instance, and if your Room typeclass inherits
from DefaultRoom (the default), the event will be available to
all rooms. Objects of the typeclass set in argument will be
able to set one or more events of that name.
If the event already exists in the typeclass, replace it.
"""
typeclass_name = typeclass.__module__ + "." + typeclass.__name__
try:
script = ScriptDB.objects.get(db_key="event_handler")
except ScriptDB.DoesNotExist:
logger.log_err("Can't create event {} in typeclass {}, the " \
"script handler isn't defined".format(name, typeclass_name))
return
# Get the event types for this typeclass
event_types = script.db.event_types.get(typeclass_name, {})
if not event_types:
script.db.event_types[typeclass_name] = event_types
# Add or replace the event
event_types[event_name] = (variables, help_text)
def del_event_type(typeclass, event_name):
"""
Delete the event type for this typeclass.
Args:
typeclass (type): the class defining the typeclass.
event_name (str): the name of the event to be deleted.
If you want to delete an event type, you need to remove it from
the typeclass that defined it: other typeclasses in the inheritance
hierarchy are not affected. This method doesn't remove the
already-created events associated with individual objects.
"""
typeclass_name = typeclass.__module__ + "." + typeclass.__name__
try:
script = ScriptDB.objects.get(db_key="event_handler")
except ScriptDB.DoesNotExist:
logger.log_err("Can't create event {} in typeclass {}, the " \
"script handler isn't defined".format(name, typeclass_name))
return
# Get the event types for this typeclass
event_types = script.db.event_types.get(typeclass_name, {})
if event_name in event_types:
del event_types[event_name]

View file

@ -0,0 +1,53 @@
"""
Module defining basic helpers for the event system.
Hlpers are just Python function that can be used inside of events. They
"""
from evennia import ObjectDB
from evennia.contrib.events.exceptions import InterruptEvent
def deny():
"""
Deny, that is stop, the event here.
This function will raise an exception to terminate the event
in a controlled way. If you use this function in an event called
prior to a command, the command will be cancelled as well. Good
situations to use the `deny()` function are in events that begins
by `can_`, because they usually can be cancelled as easily as that.
"""
raise InterruptEvent
def get(**kwargs):
"""
Return an object with the given search option or None if None is found.
This function is very useful to retrieve objects with a specific
ID. You know that room #32 exists, but you don't have it in
the event variables. Quite simple:
room = get(id=32)
This function doesn't perform a search on objects, but a direct
search in the database. It's recommended to use it for objects
you know exist, using their IDs or other unique attributes.
Looking for objects by key is possible (use `db_key` as an
argument) but remember several objects can share the same key.
Kwargs:
Any searchable data or property (id, db_key, db_location...).
Returns:
The object found that meet these criteria for research, or
None if none is found.
"""
try:
object = ObjectDB.objects.get(**kwargs)
except ObjectDB.DoesNotExist:
object = None
return object

View file

@ -12,3 +12,7 @@ class EventHandler(DefaultScript):
self.key = "event_handler"
self.desc = "Global event handler"
self.persistent = True
# Permanent data to be stored
self.db.event_types = {}
self.db.events = {}