mirror of
https://github.com/evennia/evennia.git
synced 2026-03-31 21:17:17 +02:00
Add an event handler on all objects
This commit is contained in:
parent
81f4c590bd
commit
38563a6593
4 changed files with 226 additions and 11 deletions
|
|
@ -67,7 +67,7 @@ def patch_hook(typeclass, method_name):
|
|||
inheritance tree for a couple of methods.
|
||||
|
||||
"""
|
||||
hook = getattr(typeclass, method_name)
|
||||
hook = getattr(typeclass, method_name, None)
|
||||
def wrapper(method):
|
||||
"""Wrapper around the hook."""
|
||||
def overridden_hook(*args, **kwargs):
|
||||
|
|
|
|||
182
evennia/contrib/events/handler.py
Normal file
182
evennia/contrib/events/handler.py
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
"""
|
||||
Module containing the EventHandler for individual objects.
|
||||
"""
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
class EventsHandler(object):
|
||||
|
||||
"""
|
||||
The event handler for a specific object.
|
||||
|
||||
The script that contains all events will be reached through this
|
||||
handler. This handler is therefore a shortcut to be used by
|
||||
developers. This handler (accessible through `obj.events`) is a
|
||||
shortcut to manipulating events within this object, getting,
|
||||
adding, editing, deleting and calling them.
|
||||
|
||||
"""
|
||||
|
||||
script = None
|
||||
|
||||
def __init__(self, obj):
|
||||
self.obj = obj
|
||||
|
||||
def all(self):
|
||||
"""
|
||||
Return all events linked to this object.
|
||||
|
||||
Returns:
|
||||
All events in a dictionary event_name: event}. The event
|
||||
is returned as a namedtuple to simply manipulation.
|
||||
|
||||
"""
|
||||
events = {}
|
||||
handler = type(self).script
|
||||
if handler:
|
||||
dicts = handler.get_events(self.obj)
|
||||
for event_name, in_list in dicts.items():
|
||||
new_list = []
|
||||
for event in in_list:
|
||||
event = self.format_event(event)
|
||||
new_list.append(event)
|
||||
|
||||
if new_list:
|
||||
events[event_name] = new_list
|
||||
|
||||
return events
|
||||
|
||||
def get(self, event_name):
|
||||
"""
|
||||
Return the events associated with this name.
|
||||
|
||||
Args:
|
||||
event_name (str): the name of the event.
|
||||
|
||||
This method returns a list of Event objects (namedtuple
|
||||
representations). If the event name cannot be found in the
|
||||
object's events, return an empty list.
|
||||
|
||||
"""
|
||||
return self.all().get(event_name, [])
|
||||
|
||||
def add(self, event_name, code, author=None, valid=False, parameters=""):
|
||||
"""
|
||||
Add a new event for this object.
|
||||
|
||||
Args:
|
||||
event_name (str): the name of the event to add.
|
||||
code (str): the Python code associated with this event.
|
||||
author (Character or Player, optional): the author of the event.
|
||||
valid (bool, optional): should the event be connected?
|
||||
parameters (str, optional): optional parameters.
|
||||
|
||||
Returns:
|
||||
The event definition that was added or None.
|
||||
|
||||
"""
|
||||
handler = type(self).script
|
||||
if handler:
|
||||
return self.format_event(handler.add_event(self.obj, event_name, code,
|
||||
author=author, valid=valid, parameters=parameters))
|
||||
|
||||
def edit(self, event_name, number, code, author=None, valid=False):
|
||||
"""
|
||||
Edit an existing event bound to this object.
|
||||
|
||||
Args:
|
||||
event_name (str): the name of the event to edit.
|
||||
number (int): the event number to be changed.
|
||||
code (str): the Python code associated with this event.
|
||||
author (Character or Player, optional): the author of the event.
|
||||
valid (bool, optional): should the event be connected?
|
||||
|
||||
Returns:
|
||||
The event definition that was edited or None.
|
||||
|
||||
Raises:
|
||||
RuntimeError if the event is locked.
|
||||
|
||||
"""
|
||||
handler = type(self).script
|
||||
if handler:
|
||||
return self.format_event(handler.edit_event(self.obj, event_name,
|
||||
number, code, author=author, valid=valid))
|
||||
|
||||
def remove(self, event_name, number):
|
||||
"""
|
||||
Delete the specified event bound to this object.
|
||||
|
||||
Args:
|
||||
event_name (str): the name of the event to delete.
|
||||
number (int): the number of the event to delete.
|
||||
|
||||
Raises:
|
||||
RuntimeError if the event is locked.
|
||||
|
||||
"""
|
||||
handler = type(self).script
|
||||
if handler:
|
||||
handler.del_event(self.obj, event_name, number)
|
||||
|
||||
def call(self, event_name, *args, **kwargs):
|
||||
"""
|
||||
Call the specified event(s) bound to this object.
|
||||
|
||||
Args:
|
||||
event_name (str): the event name to call.
|
||||
*args: additional variables for this event.
|
||||
|
||||
Kwargs:
|
||||
number (int, optional): call just a specific event.
|
||||
parameters (str, optional): call an event with parameters.
|
||||
locals (dict, optional): a locals replacement.
|
||||
|
||||
Returns:
|
||||
True to report the event was called without interruption,
|
||||
False otherwise.
|
||||
|
||||
"""
|
||||
handler = type(self).script
|
||||
if handler:
|
||||
return handler.call_event(self.obj, event_name, *args, **kwargs)
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def format_event(event):
|
||||
"""
|
||||
Return the Event namedtuple to represent the specified event.
|
||||
|
||||
Args:
|
||||
event (dict): the event definition.
|
||||
|
||||
The event given in argument should be a dictionary containing
|
||||
the expected fields for an event (code, author, valid...).
|
||||
|
||||
"""
|
||||
if "obj" not in event:
|
||||
event["obj"] = None
|
||||
if "name" not in event:
|
||||
event["name"] = "unknown"
|
||||
if "number" not in event:
|
||||
event["number"] = -1
|
||||
if "code" not in event:
|
||||
event["code"] = ""
|
||||
if "author" not in event:
|
||||
event["author"] = None
|
||||
if "valid" not in event:
|
||||
event["valid"] = False
|
||||
if "parameters" not in event:
|
||||
event["parameters"] = ""
|
||||
if "created_on" not in event:
|
||||
event["created_on"] = None
|
||||
if "updated_by" not in event:
|
||||
event["updated_by"] = None
|
||||
if "updated_on" not in event:
|
||||
event["updated_on"] = None
|
||||
|
||||
return Event(**event)
|
||||
|
||||
Event = namedtuple("Event", ("obj", "name", "number", "code", "author",
|
||||
"valid", "parameters", "created_on", "updated_by", "updated_on"))
|
||||
|
|
@ -6,13 +6,14 @@ from datetime import datetime, timedelta
|
|||
from Queue import Queue
|
||||
|
||||
from django.conf import settings
|
||||
from evennia import DefaultScript, ScriptDB
|
||||
from evennia import DefaultObject, DefaultScript, ScriptDB
|
||||
from evennia import logger
|
||||
from evennia.utils.dbserialize import dbserialize
|
||||
from evennia.utils.utils import all_from_module, delay
|
||||
from evennia.contrib.events.custom import connect_event_types, \
|
||||
get_next_wait, patch_hooks
|
||||
from evennia.contrib.events.custom import (
|
||||
connect_event_types, get_next_wait, patch_hooks)
|
||||
from evennia.contrib.events.exceptions import InterruptEvent
|
||||
from evennia.contrib.events.handler import EventsHandler as Handler
|
||||
from evennia.contrib.events import typeclasses
|
||||
|
||||
class EventHandler(DefaultScript):
|
||||
|
|
@ -65,6 +66,10 @@ class EventHandler(DefaultScript):
|
|||
|
||||
delay(seconds, complete_task, task_id)
|
||||
|
||||
# Place the script in the EventsHandler
|
||||
Handler.script = self
|
||||
DefaultObject.events = typeclasses.PatchedObject.events
|
||||
|
||||
def get_events(self, obj):
|
||||
"""
|
||||
Return a dictionary of the object's events.
|
||||
|
|
@ -80,7 +85,21 @@ class EventHandler(DefaultScript):
|
|||
when several objects would share events.
|
||||
|
||||
"""
|
||||
return self.db.events.get(obj, {})
|
||||
obj_events = self.db.events.get(obj, {})
|
||||
events = {}
|
||||
for event_name, event_list in obj_events.items():
|
||||
new_list = []
|
||||
for i, event in enumerate(event_list):
|
||||
event = dict(event)
|
||||
event["obj"] = obj
|
||||
event["name"] = event_name
|
||||
event["number"] = i
|
||||
new_list.append(event)
|
||||
|
||||
if new_list:
|
||||
events[event_name] = new_list
|
||||
|
||||
return events
|
||||
|
||||
def get_event_types(self, obj):
|
||||
"""
|
||||
|
|
@ -212,6 +231,13 @@ class EventHandler(DefaultScript):
|
|||
elif valid and (obj, event_name, number) in self.db.to_valid:
|
||||
self.db.to_valid.remove((obj, event_name, number))
|
||||
|
||||
# Build the definition to return (a dictionary)
|
||||
definition = dict(events[number])
|
||||
definition["obj"] = obj
|
||||
definition["name"] = event_name
|
||||
definition["number"] = number
|
||||
return definition
|
||||
|
||||
def del_event(self, obj, event_name, number):
|
||||
"""
|
||||
Delete the specified event.
|
||||
|
|
@ -259,11 +285,11 @@ class EventHandler(DefaultScript):
|
|||
i += 1
|
||||
|
||||
# Update locked event
|
||||
for line in self.db.locked:
|
||||
for i, line in enumerate(self.db.locked):
|
||||
t_obj, t_event_name, t_number = line
|
||||
if obj is t_obj and event_name == t_event_name:
|
||||
if number > t_number:
|
||||
line[2] -= 1
|
||||
if number < t_number:
|
||||
self.db.locked[i] = (t_obj, t_event_name, t_number - 1)
|
||||
|
||||
# Delete time-related events associated with this object
|
||||
for script in list(obj.scripts.all()):
|
||||
|
|
|
|||
|
|
@ -4,9 +4,16 @@ Patched typeclasses for Evennia.
|
|||
|
||||
from evennia import DefaultCharacter, DefaultExit, DefaultObject, DefaultRoom
|
||||
from evennia import ScriptDB
|
||||
from evennia.utils.utils import inherits_from
|
||||
from evennia.contrib.events.custom import create_event_type, patch_hook, \
|
||||
create_time_event
|
||||
from evennia.utils.utils import inherits_from, lazy_property
|
||||
from evennia.contrib.events.custom import (
|
||||
create_event_type, patch_hook, create_time_event)
|
||||
from evennia.contrib.events.handler import EventsHandler
|
||||
|
||||
class PatchedObject(object):
|
||||
@lazy_property
|
||||
def events(self):
|
||||
"""Return the EventsHandler."""
|
||||
return EventsHandler(self)
|
||||
|
||||
class PatchedExit(object):
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue