Add the /add and /edit switches to the @event command
This commit is contained in:
parent
0d7b1cb2be
commit
4bdee14adb
3 changed files with 222 additions and 41 deletions
|
|
@ -2,12 +2,16 @@
|
||||||
Module containing the commands of the event system.
|
Module containing the commands of the event system.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from evennia import Command
|
from evennia import Command
|
||||||
from evennia.contrib.events.extend import get_event_handler
|
from evennia.contrib.events.extend import get_event_handler
|
||||||
|
from evennia.utils.eveditor import EvEditor
|
||||||
from evennia.utils.evtable import EvTable
|
from evennia.utils.evtable import EvTable
|
||||||
from evennia.utils.utils import class_from_module
|
from evennia.utils.utils import class_from_module, time_format
|
||||||
|
|
||||||
|
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
||||||
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
||||||
|
|
||||||
# Permissions
|
# Permissions
|
||||||
|
|
@ -120,81 +124,203 @@ class CmdEvent(COMMAND_DEFAULT_CLASS):
|
||||||
lock = "perm({}) or perm(events_validating)".format(VALIDATING)
|
lock = "perm({}) or perm(events_validating)".format(VALIDATING)
|
||||||
validator = caller.locks.check_lockstring(caller, lock)
|
validator = caller.locks.check_lockstring(caller, lock)
|
||||||
|
|
||||||
# First and foremost, get the event handler
|
# First and foremost, get the event handler and set other variables
|
||||||
self.handler = get_event_handler()
|
self.handler = get_event_handler()
|
||||||
|
self.obj = None
|
||||||
|
rhs = self.rhs or ""
|
||||||
|
self.event_name, sep, self.parameters = rhs.partition(" ")
|
||||||
|
self.event_name = self.event_name.lower()
|
||||||
|
self.is_validator = validator
|
||||||
if self.handler is None:
|
if self.handler is None:
|
||||||
caller.msg("The event handler is not running, can't " \
|
caller.msg("The event handler is not running, can't " \
|
||||||
"access the event system.")
|
"access the event system.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Before the equal sign is always an object name
|
# Before the equal sign is always an object name
|
||||||
obj = None
|
|
||||||
if self.args.strip():
|
if self.args.strip():
|
||||||
obj = caller.search(self.lhs)
|
self.obj = caller.search(self.lhs)
|
||||||
if not obj:
|
if not self.obj:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Switches are mutually exclusive
|
# Switches are mutually exclusive
|
||||||
switch = self.switches and self.switches[0] or ""
|
switch = self.switches and self.switches[0] or ""
|
||||||
if switch == "":
|
if switch == "":
|
||||||
if not obj:
|
if not self.obj:
|
||||||
caller.msg("Specify an object's name or #ID.")
|
caller.msg("Specify an object's name or #ID.")
|
||||||
return
|
return
|
||||||
|
|
||||||
self.list_events(obj)
|
self.list_events()
|
||||||
elif switch == "add":
|
elif switch == "add":
|
||||||
if not obj:
|
if not self.obj:
|
||||||
caller.msg("Specify an object's name or #ID.")
|
caller.msg("Specify an object's name or #ID.")
|
||||||
return
|
return
|
||||||
|
|
||||||
self.add_event(obj)
|
self.add_event()
|
||||||
elif switch == "edit":
|
elif switch == "edit":
|
||||||
if not obj:
|
if not self.obj:
|
||||||
caller.msg("Specify an object's name or #ID.")
|
caller.msg("Specify an object's name or #ID.")
|
||||||
return
|
return
|
||||||
|
|
||||||
self.edit_event(obj)
|
self.edit_event()
|
||||||
elif switch == "del":
|
elif switch == "del":
|
||||||
if not obj:
|
if not self.obj:
|
||||||
caller.msg("Specify an object's name or #ID.")
|
caller.msg("Specify an object's name or #ID.")
|
||||||
return
|
return
|
||||||
|
|
||||||
self.del_event(obj)
|
self.del_event()
|
||||||
elif switch == "accept" and validator:
|
elif switch == "accept" and validator:
|
||||||
self.accept_event(obj)
|
self.accept_event()
|
||||||
else:
|
else:
|
||||||
caller.msg("Mutually exclusive or invalid switches were " \
|
caller.msg("Mutually exclusive or invalid switches were " \
|
||||||
"used, cannot proceed.")
|
"used, cannot proceed.")
|
||||||
|
|
||||||
def list_events(self, obj):
|
def list_events(self):
|
||||||
"""Display the list of events connected to the object."""
|
"""Display the list of events connected to the object."""
|
||||||
|
obj = self.obj
|
||||||
|
event_name = self.event_name
|
||||||
events = self.handler.get_events(obj)
|
events = self.handler.get_events(obj)
|
||||||
types = self.handler.get_event_types(obj)
|
types = self.handler.get_event_types(obj)
|
||||||
table = EvTable("Event name", "Number", "Lines", "Description",
|
|
||||||
width=78)
|
|
||||||
for name, infos in sorted(types.items()):
|
|
||||||
number = len(events.get(name, []))
|
|
||||||
lines = sum(len(e["code"].splitlines()) for e in \
|
|
||||||
events.get(name, []))
|
|
||||||
description = infos[1].splitlines()[0]
|
|
||||||
table.add_row(name, number, lines, description)
|
|
||||||
|
|
||||||
table.reformat_column(1, align="r")
|
if event_name:
|
||||||
table.reformat_column(2, align="r")
|
# Check that the event name can be found in this object
|
||||||
self.msg(table)
|
created = events.get(event_name)
|
||||||
|
if created is None:
|
||||||
|
self.msg("No event {} has been set on {}.".format(event_name, obj))
|
||||||
|
return
|
||||||
|
|
||||||
def add_event(self, obj):
|
# Create the table
|
||||||
|
cols = ["Number", "Author", "Updated"]
|
||||||
|
if self.is_validator:
|
||||||
|
cols.append("Valid")
|
||||||
|
|
||||||
|
table = EvTable(*cols, width=78)
|
||||||
|
now = datetime.now()
|
||||||
|
for i, event in enumerate(created):
|
||||||
|
author = event.get("author")
|
||||||
|
author = author.key if author else "|gUnknown|n"
|
||||||
|
updated_on = event.get("updated_on")
|
||||||
|
if updated_on is None:
|
||||||
|
updated_on = event.get("created_on")
|
||||||
|
|
||||||
|
if updated_on:
|
||||||
|
updated_on = time_format(
|
||||||
|
(now - updated_on).total_seconds(), 1)
|
||||||
|
else:
|
||||||
|
updated_on = "|gUnknown|n"
|
||||||
|
|
||||||
|
row = [str(i + 1), author, updated_on]
|
||||||
|
if self.is_validator:
|
||||||
|
row.append("Yes" if event.get("valid") else "no")
|
||||||
|
table.add_row(*row)
|
||||||
|
|
||||||
|
table.reformat_column(0, align="r")
|
||||||
|
self.msg(table)
|
||||||
|
else:
|
||||||
|
table = EvTable("Event name", "Number", "Lines", "Description",
|
||||||
|
width=78)
|
||||||
|
for name, infos in sorted(types.items()):
|
||||||
|
number = len(events.get(name, []))
|
||||||
|
lines = sum(len(e["code"].splitlines()) for e in \
|
||||||
|
events.get(name, []))
|
||||||
|
description = infos[1].splitlines()[0]
|
||||||
|
table.add_row(name, number, lines, description)
|
||||||
|
|
||||||
|
table.reformat_column(1, align="r")
|
||||||
|
table.reformat_column(2, align="r")
|
||||||
|
self.msg(table)
|
||||||
|
|
||||||
|
def add_event(self):
|
||||||
"""Add an event."""
|
"""Add an event."""
|
||||||
self.msg("Calling add.")
|
obj = self.obj
|
||||||
|
event_name = self.event_name
|
||||||
|
types = self.handler.get_event_types(obj)
|
||||||
|
|
||||||
def edit_event(self, obj):
|
# Check that the event exists
|
||||||
"""Add an event."""
|
if not event_name in types:
|
||||||
self.msg("Calling edit.")
|
self.msg("The event name {} can't be found in {} of " \
|
||||||
|
"typeclass {}.".format(event_name, obj, type(obj)))
|
||||||
|
return
|
||||||
|
|
||||||
def del_event(self, obj):
|
definition = types[event_name]
|
||||||
"""Add an event."""
|
description = definition[1]
|
||||||
|
self.msg(description)
|
||||||
|
|
||||||
|
# Open the editor
|
||||||
|
event = self.handler.add_event(obj, event_name, "",
|
||||||
|
self.caller, False)
|
||||||
|
self.caller.db._event = event
|
||||||
|
EvEditor(self.caller, loadfunc=_ev_load, savefunc=_ev_save,
|
||||||
|
quitfunc=_ev_quit, key="Event {} of {}".format(
|
||||||
|
event_name, obj), persistent=True, codefunc=_ev_save)
|
||||||
|
|
||||||
|
def edit_event(self):
|
||||||
|
"""Edit an event."""
|
||||||
|
obj = self.obj
|
||||||
|
event_name = self.event_name
|
||||||
|
parameters = self.parameters
|
||||||
|
events = self.handler.get_events(obj)
|
||||||
|
types = self.handler.get_event_types(obj)
|
||||||
|
|
||||||
|
# Check that the event exists
|
||||||
|
if not event_name in events:
|
||||||
|
self.msg("The event name {} can't be found in {}.".format(
|
||||||
|
event_name, obj))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Check that the parameter points to an existing event
|
||||||
|
try:
|
||||||
|
parameters = int(parameters) - 1
|
||||||
|
assert parameters >= 0
|
||||||
|
event = events[event_name][parameters]
|
||||||
|
except (AssertionError, ValueError):
|
||||||
|
self.msg("The event {} {} cannot be found in {}.".format(
|
||||||
|
event_name, parameters, obj))
|
||||||
|
return
|
||||||
|
|
||||||
|
definition = types[event_name]
|
||||||
|
description = definition[1]
|
||||||
|
self.msg(description)
|
||||||
|
|
||||||
|
# Open the editor
|
||||||
|
event = dict(event)
|
||||||
|
event["obj"] = obj
|
||||||
|
event["name"] = event_name
|
||||||
|
event["number"] = parameters
|
||||||
|
self.caller.db._event = event
|
||||||
|
EvEditor(self.caller, loadfunc=_ev_load, savefunc=_ev_save,
|
||||||
|
quitfunc=_ev_quit, key="Event {} of {}".format(
|
||||||
|
event_name, obj), persistent=True, codefunc=_ev_save)
|
||||||
|
|
||||||
|
def del_event(self):
|
||||||
|
"""Delete an event."""
|
||||||
|
obj = self.obj
|
||||||
self.msg("Calling del.")
|
self.msg("Calling del.")
|
||||||
|
|
||||||
def accept_event(self, obj):
|
def accept_event(self):
|
||||||
"""Add an event."""
|
"""Accept an event."""
|
||||||
|
obj = self.obj
|
||||||
self.msg("Calling accept.")
|
self.msg("Calling accept.")
|
||||||
|
|
||||||
|
# Private functions to handle editing
|
||||||
|
def _ev_load(caller):
|
||||||
|
return caller.db._event and caller.db._event.get("code", "") or ""
|
||||||
|
|
||||||
|
def _ev_save(caller, buf):
|
||||||
|
"""Save and add the event."""
|
||||||
|
lock = "perm({}) or perm(events_without_validation)".format(
|
||||||
|
WITHOUT_VALIDATION)
|
||||||
|
autovalid = caller.locks.check_lockstring(caller, lock)
|
||||||
|
event = caller.db._event
|
||||||
|
handler = get_event_handler()
|
||||||
|
if not handler or not event or not all(key in event for key in \
|
||||||
|
("obj", "name", "number", "valid")):
|
||||||
|
caller.msg("Couldn't save this event.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
handler.edit_event(event["obj"], event["name"], event["number"], buf,
|
||||||
|
caller, valid=autovalid)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _ev_quit(caller):
|
||||||
|
del caller.db._event
|
||||||
|
caller.msg("Exited the code editor.")
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,10 @@ from Queue import Queue
|
||||||
|
|
||||||
from evennia import DefaultScript
|
from evennia import DefaultScript
|
||||||
from evennia import logger
|
from evennia import logger
|
||||||
|
from evennia.contrib.events.exceptions import InterruptEvent
|
||||||
from evennia.contrib.events.extend import patch_hooks
|
from evennia.contrib.events.extend import patch_hooks
|
||||||
from evennia.contrib.events import typeclasses
|
from evennia.contrib.events import typeclasses
|
||||||
|
from evennia.utils.utils import all_from_module
|
||||||
|
|
||||||
class EventHandler(DefaultScript):
|
class EventHandler(DefaultScript):
|
||||||
|
|
||||||
|
|
@ -60,7 +62,7 @@ class EventHandler(DefaultScript):
|
||||||
|
|
||||||
return types
|
return types
|
||||||
|
|
||||||
def add_event(self, obj, event_name, code, author=None, valid=True):
|
def add_event(self, obj, event_name, code, author=None, valid=False):
|
||||||
"""
|
"""
|
||||||
Add the specified event.
|
Add the specified event.
|
||||||
|
|
||||||
|
|
@ -92,6 +94,46 @@ class EventHandler(DefaultScript):
|
||||||
"code": code,
|
"code": code,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
definition = dict(events[-1])
|
||||||
|
definition["obj"] = obj
|
||||||
|
definition["name"] = event_name
|
||||||
|
definition["number"] = len(events) - 1
|
||||||
|
return definition
|
||||||
|
|
||||||
|
def edit_event(self, obj, event_name, number, code, author=None,
|
||||||
|
valid=False):
|
||||||
|
"""
|
||||||
|
Edit the specified event.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
obj (Object): the Evennia typeclassed object to be modified.
|
||||||
|
event_name (str): the name of the event to add.
|
||||||
|
number (int): the event number to be changed.
|
||||||
|
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?
|
||||||
|
|
||||||
|
This method doesn't check that the event type exists.
|
||||||
|
|
||||||
|
"""
|
||||||
|
obj_events = self.db.events.get(obj, {})
|
||||||
|
if not obj_events:
|
||||||
|
self.db.events[obj] = {}
|
||||||
|
obj_events = self.db.events[obj]
|
||||||
|
|
||||||
|
events = obj_events.get(event_name, [])
|
||||||
|
if not events:
|
||||||
|
obj_events[event_name] = []
|
||||||
|
events = obj_events[event_name]
|
||||||
|
|
||||||
|
# Edit the event
|
||||||
|
events[number].update({
|
||||||
|
"updated_on": datetime.now(),
|
||||||
|
"updated_by": author,
|
||||||
|
"valid": valid,
|
||||||
|
"code": code,
|
||||||
|
})
|
||||||
|
|
||||||
def call_event(self, obj, event_name, *args):
|
def call_event(self, obj, event_name, *args):
|
||||||
"""
|
"""
|
||||||
Call the event.
|
Call the event.
|
||||||
|
|
@ -115,7 +157,7 @@ class EventHandler(DefaultScript):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Prepare the locals
|
# Prepare the locals
|
||||||
locals = {}
|
locals = all_from_module("evennia.contrib.events.helpers")
|
||||||
for i, variable in enumerate(event_type[0]):
|
for i, variable in enumerate(event_type[0]):
|
||||||
try:
|
try:
|
||||||
locals[variable] = args[i]
|
locals[variable] = args[i]
|
||||||
|
|
@ -131,4 +173,9 @@ class EventHandler(DefaultScript):
|
||||||
if not event["valid"]:
|
if not event["valid"]:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
exec(event["code"], locals, locals)
|
try:
|
||||||
|
exec(event["code"], locals, locals)
|
||||||
|
except InterruptEvent:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,19 @@ class PatchedExit(object):
|
||||||
"""
|
"""
|
||||||
if inherits_from(traversing_object, DefaultCharacter):
|
if inherits_from(traversing_object, DefaultCharacter):
|
||||||
script = ScriptDB.objects.get(db_key="event_handler")
|
script = ScriptDB.objects.get(db_key="event_handler")
|
||||||
script.call_event(exit, "at_traverse", traversing_object,
|
allow = script.call_event(exit, "can_traverse", traversing_object,
|
||||||
exit, exit.location)
|
exit, exit.location)
|
||||||
|
if not allow:
|
||||||
|
return
|
||||||
|
|
||||||
hook(exit, traversing_object, target_location)
|
hook(exit, traversing_object, target_location)
|
||||||
|
|
||||||
# Default events
|
# Default events
|
||||||
create_event_type(DefaultExit, "at_traverse", ["character", "exit", "room"],
|
create_event_type(DefaultExit, "can_traverse", ["character", "exit", "room"],
|
||||||
"""When traversing""")
|
"""Can the character traverse through this exit?
|
||||||
|
This event is called when a character is about to traverse this
|
||||||
|
exit. You can use the deny() function to deny the character from
|
||||||
|
using this exit for the time being. The 'character' variable
|
||||||
|
contains the character who wants to traverse through this exit.
|
||||||
|
The 'exit' variable contains the exit, the 'room' variable
|
||||||
|
contains the room in which the character and exit are.""")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue