mirror of
https://github.com/evennia/evennia.git
synced 2026-03-24 08:46:31 +01:00
Add the time-related events and events with parameters
This commit is contained in:
parent
1f4095c625
commit
e898ee0ec2
4 changed files with 165 additions and 17 deletions
|
|
@ -292,7 +292,7 @@ class CmdEvent(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
# Open the editor
|
||||
event = self.handler.add_event(obj, event_name, "",
|
||||
self.caller, False)
|
||||
self.caller, False, parameters=self.parameters)
|
||||
self.caller.db._event = event
|
||||
EvEditor(self.caller, loadfunc=_ev_load, savefunc=_ev_save,
|
||||
quitfunc=_ev_quit, key="Event {} of {}".format(
|
||||
|
|
|
|||
|
|
@ -8,8 +8,13 @@ and are designed to be used more by developers to add event types.
|
|||
|
||||
from textwrap import dedent
|
||||
|
||||
from django.conf import settings
|
||||
from evennia import logger
|
||||
from evennia import ScriptDB
|
||||
from evennia.contrib.custom_gametime import UNITS
|
||||
from evennia.contrib.custom_gametime import real_seconds_until as custom_rsu
|
||||
from evennia.utils.create import create_script
|
||||
from evennia.utils.gametime import real_seconds_until as standard_rsu
|
||||
|
||||
hooks = []
|
||||
event_types = []
|
||||
|
|
@ -24,7 +29,8 @@ def get_event_handler():
|
|||
|
||||
return script
|
||||
|
||||
def create_event_type(typeclass, event_name, variables, help_text):
|
||||
def create_event_type(typeclass, event_name, variables, help_text,
|
||||
custom_add=None):
|
||||
"""
|
||||
Create a new event type for a specific typeclass.
|
||||
|
||||
|
|
@ -33,6 +39,8 @@ def create_event_type(typeclass, event_name, variables, help_text):
|
|||
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.
|
||||
custom_add (function, default None): a callback to call when adding
|
||||
the new event.
|
||||
|
||||
Events obey the inheritance hierarchy: if you set an event on
|
||||
DefaultRoom, for instance, and if your Room typeclass inherits
|
||||
|
|
@ -44,7 +52,8 @@ def create_event_type(typeclass, event_name, variables, help_text):
|
|||
|
||||
"""
|
||||
typeclass_name = typeclass.__module__ + "." + typeclass.__name__
|
||||
event_types.append((typeclass_name, event_name, variables, help_text))
|
||||
event_types.append((typeclass_name, event_name, variables, help_text,
|
||||
custom_add))
|
||||
|
||||
def del_event_type(typeclass, event_name):
|
||||
"""
|
||||
|
|
@ -118,7 +127,8 @@ def connect_event_types():
|
|||
"cannot be found.")
|
||||
return
|
||||
|
||||
for typeclass_name, event_name, variables, help_text in event_types:
|
||||
for typeclass_name, event_name, variables, help_text, \
|
||||
custom_add in event_types:
|
||||
# Get the event types for this typeclass
|
||||
if typeclass_name not in script.ndb.event_types:
|
||||
script.ndb.event_types[typeclass_name] = {}
|
||||
|
|
@ -126,4 +136,80 @@ def connect_event_types():
|
|||
|
||||
# Add or replace the event
|
||||
help_text = dedent(help_text.strip("\n"))
|
||||
types[event_name] = (variables, help_text)
|
||||
types[event_name] = (variables, help_text, custom_add)
|
||||
|
||||
# Custom callbacks for specific events
|
||||
def get_next_wait(format):
|
||||
"""
|
||||
Get the length of time in seconds before format.
|
||||
|
||||
Args:
|
||||
format (str): a time format matching the set calendar.
|
||||
|
||||
The time format could be something like "2018-01-08 12:00". The
|
||||
number of units set in the calendar affects the way seconds are
|
||||
calculated.
|
||||
|
||||
"""
|
||||
calendar = getattr(settings, "EVENTS_CALENDAR", None)
|
||||
if calendar is None:
|
||||
logger.log_err("A time-related event has been set whereas " \
|
||||
"the gametime calendar has not been set in the settings.")
|
||||
return
|
||||
elif calendar == "standard":
|
||||
rsu = standard_rsu
|
||||
units = ["min", "hour", "day", "month", "year"]
|
||||
elif calendar == "custom":
|
||||
rsu = custom_rsu
|
||||
back = dict([(value, name) for name, value in UNITS.items()])
|
||||
sorted_units = sorted(back.items())
|
||||
del sorted_units[0]
|
||||
units = [n for v, n in sorted_units]
|
||||
|
||||
params = {}
|
||||
for delimiter in ("-", ":"):
|
||||
format = format.replace(delimiter, " ")
|
||||
|
||||
pieces = list(reversed(format.split()))
|
||||
details = []
|
||||
i = 0
|
||||
for uname in units:
|
||||
try:
|
||||
piece = pieces[i]
|
||||
except IndexError:
|
||||
break
|
||||
|
||||
if not piece.isdigit():
|
||||
logger.log_err("The time specified '{}' in {} isn't " \
|
||||
"a valid number".format(piece, format))
|
||||
return
|
||||
|
||||
# Convert the piece to int
|
||||
piece = int(piece)
|
||||
params[uname] = piece
|
||||
details.append("{}={}".format(uname, piece))
|
||||
i += 1
|
||||
|
||||
params["sec"] = 0
|
||||
details = " ".join(details)
|
||||
seconds = rsu(**params)
|
||||
return seconds, details
|
||||
|
||||
def create_time_event(obj, event_name, number, parameters):
|
||||
"""
|
||||
Create an time-related event.
|
||||
|
||||
args:
|
||||
obj (Object): the object on which stands the event.
|
||||
event_name (str): the event's name.
|
||||
number (int): the number of the event.
|
||||
parameter (str): the parameter of the event.
|
||||
|
||||
"""
|
||||
print "parameters", repr(parameters)
|
||||
seconds, key = get_next_wait(parameters)
|
||||
script = create_script("evennia.contrib.events.scripts.TimeEventScript", interval=seconds, obj=obj)
|
||||
script.key = key
|
||||
script.desc = "time event called regularly on {}".format(key)
|
||||
script.db.time_format = parameters
|
||||
script.db.number = number
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@ Scripts for the event system.
|
|||
from datetime import datetime
|
||||
from Queue import Queue
|
||||
|
||||
from evennia import DefaultScript
|
||||
from django.conf import settings
|
||||
from evennia import DefaultScript, ScriptDB
|
||||
from evennia import logger
|
||||
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.custom import connect_event_types, patch_hooks
|
||||
from evennia.contrib.events import typeclasses
|
||||
from evennia.utils.utils import all_from_module
|
||||
|
||||
|
|
@ -64,7 +66,8 @@ class EventHandler(DefaultScript):
|
|||
|
||||
return types
|
||||
|
||||
def add_event(self, obj, event_name, code, author=None, valid=False):
|
||||
def add_event(self, obj, event_name, code, author=None, valid=False,
|
||||
parameters=""):
|
||||
"""
|
||||
Add the specified event.
|
||||
|
||||
|
|
@ -74,6 +77,7 @@ class EventHandler(DefaultScript):
|
|||
code (str): the Python code associated with this event.
|
||||
author (optional, Character, Player): the author of the event.
|
||||
valid (optional, bool): should the event be connected?
|
||||
parameters (str, optional): optional parameters.
|
||||
|
||||
This method doesn't check that the event type exists.
|
||||
|
||||
|
|
@ -100,6 +104,13 @@ class EventHandler(DefaultScript):
|
|||
if not valid:
|
||||
self.db.to_valid.append((obj, event_name, len(events) - 1))
|
||||
|
||||
# Call the custom_add if needed
|
||||
custom_add = self.get_event_types(obj).get(
|
||||
event_name, [None, None, None])[2]
|
||||
print "custom_add", custom_add
|
||||
if custom_add:
|
||||
custom_add(obj, event_name, len(events) - 1, parameters)
|
||||
|
||||
# Build the definition to return (a dictionary)
|
||||
definition = dict(events[-1])
|
||||
definition["obj"] = obj
|
||||
|
|
@ -163,7 +174,7 @@ class EventHandler(DefaultScript):
|
|||
if (obj, event_name, number) in self.db.to_valid:
|
||||
self.db.to_valid.remove((obj, event_name, number))
|
||||
|
||||
def call_event(self, obj, event_name, *args):
|
||||
def call_event(self, obj, event_name, number=None, *args):
|
||||
"""
|
||||
Call the event.
|
||||
|
||||
|
|
@ -171,6 +182,7 @@ class EventHandler(DefaultScript):
|
|||
obj (Object): the Evennia typeclassed object.
|
||||
event_name (str): the event name to call.
|
||||
*args: additional variables for this event.
|
||||
number (int, default None): call just a specific event.
|
||||
|
||||
Returns:
|
||||
True to report the event was called without interruption,
|
||||
|
|
@ -198,13 +210,64 @@ class EventHandler(DefaultScript):
|
|||
|
||||
# Now execute all the valid events linked at this address
|
||||
events = self.db.events.get(obj, {}).get(event_name, [])
|
||||
for event in events:
|
||||
for i, event in enumerate(events):
|
||||
if not event["valid"]:
|
||||
continue
|
||||
|
||||
if number is not None and i != number:
|
||||
continue
|
||||
|
||||
try:
|
||||
exec(event["code"], locals, locals)
|
||||
except InterruptEvent:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
# Script to call time-related events
|
||||
class TimeEventScript(DefaultScript):
|
||||
|
||||
"""Gametime-sensitive script."""
|
||||
|
||||
def at_script_creation(self):
|
||||
"""The script is created."""
|
||||
self.start_delay = True
|
||||
self.persistent = True
|
||||
|
||||
# Script attributes
|
||||
self.db.time_format = None
|
||||
self.db.event_name = "time"
|
||||
self.db.number = None
|
||||
|
||||
def at_repeat(self):
|
||||
"""Call the event and reset interval."""
|
||||
# Get the event handler and call the script
|
||||
try:
|
||||
script = ScriptDB.objects.get(db_key="event_handler")
|
||||
except ScriptDB.DoesNotExist:
|
||||
logger.log_err("Can't get the event handler.")
|
||||
return
|
||||
|
||||
if self.db.event_name and self.db.number is not None:
|
||||
obj = self.obj
|
||||
event_name = self.db.event_name
|
||||
number = self.db.number
|
||||
events = script.db.events.get(obj, {}).get(event_name)
|
||||
if events is None:
|
||||
logger.log_err("Cannot find the event {} on {}".format(
|
||||
event_name, obj))
|
||||
return
|
||||
|
||||
try:
|
||||
event = events[number]
|
||||
except IndexError:
|
||||
logger.log_err("Cannot find the event {} {} on {}".format(
|
||||
event_name, number, obj))
|
||||
return
|
||||
|
||||
script.call_event(obj, event_name, number, obj)
|
||||
|
||||
if self.db.time_format:
|
||||
seconds, details = get_next_wait(self.db.time_format)
|
||||
self.restart(interval=seconds)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ Patched typeclasses for Evennia.
|
|||
|
||||
from evennia import DefaultCharacter, DefaultExit, DefaultObject, DefaultRoom
|
||||
from evennia import ScriptDB
|
||||
from evennia.contrib.events.custom import create_event_type, patch_hook
|
||||
from evennia.contrib.events.custom import create_event_type, patch_hook, \
|
||||
create_time_event
|
||||
from evennia.utils.utils import inherits_from
|
||||
|
||||
class PatchedExit(object):
|
||||
|
|
@ -31,7 +32,7 @@ class PatchedExit(object):
|
|||
is_character = inherits_from(traversing_object, DefaultCharacter)
|
||||
script = ScriptDB.objects.get(db_key="event_handler")
|
||||
if is_character:
|
||||
allow = script.call_event(exit, "can_traverse", traversing_object,
|
||||
allow = script.call_event(exit, "can_traverse", None, traversing_object,
|
||||
exit, exit.location)
|
||||
if not allow:
|
||||
return
|
||||
|
|
@ -40,7 +41,7 @@ class PatchedExit(object):
|
|||
|
||||
# After traversing
|
||||
if is_character:
|
||||
script.call_event(exit, "traverse", traversing_object,
|
||||
script.call_event(exit, "traverse", None, traversing_object,
|
||||
exit, exit.location, exit.destination)
|
||||
|
||||
|
||||
|
|
@ -71,7 +72,7 @@ create_event_type(DefaultExit, "traverse", ["character", "exit",
|
|||
""")
|
||||
|
||||
# Room events
|
||||
create_event_type(DefaultRoom, "time", ["room", "time"], """
|
||||
create_event_type(DefaultRoom, "time", ["room"], """
|
||||
A repeated event to be called regularly.
|
||||
This event is scheduled to repeat at different times, specified
|
||||
as parameters. You can set it to run every day at 8:00 AM (game
|
||||
|
|
@ -87,6 +88,4 @@ create_event_type(DefaultRoom, "time", ["room", "time"], """
|
|||
|
||||
Variables you can use in this event:
|
||||
room: the room connected to this event.
|
||||
time: a string containing the current time.
|
||||
""")
|
||||
|
||||
""", create_time_event)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue