diff --git a/evennia/contrib/events/commands.py b/evennia/contrib/events/commands.py index 61809a27a7..7a761ec52b 100644 --- a/evennia/contrib/events/commands.py +++ b/evennia/contrib/events/commands.py @@ -123,6 +123,9 @@ class CmdEvent(COMMAND_DEFAULT_CLASS): caller = self.caller lock = "perm({}) or perm(events_validating)".format(VALIDATING) validator = caller.locks.check_lockstring(caller, lock) + lock = "perm({}) or perm(events_without_validation)".format( + WITHOUT_VALIDATION) + autovalid = caller.locks.check_lockstring(caller, lock) # First and foremost, get the event handler and set other variables self.handler = get_event_handler() @@ -131,6 +134,7 @@ class CmdEvent(COMMAND_DEFAULT_CLASS): self.event_name, sep, self.parameters = rhs.partition(" ") self.event_name = self.event_name.lower() self.is_validator = validator + self.autovalid = autovalid if self.handler is None: caller.msg("The event handler is not running, can't " \ "access the event system.") @@ -210,23 +214,23 @@ class CmdEvent(COMMAND_DEFAULT_CLASS): row = [str(i + 1), author, updated_on] if self.is_validator: - row.append("Yes" if event.get("valid") else "no") + 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", + table = EvTable("Event name", "Number", "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, [])) + no = "{} ({})".format(number, lines) description = infos[1].splitlines()[0] - table.add_row(name, number, lines, description) + table.add_row(name, no, description) - table.reformat_column(1, align="r") - table.reformat_column(2, align="r") + table.reformat_column(1, width=10, align="r") self.msg(table) def add_event(self): @@ -261,22 +265,43 @@ class CmdEvent(COMMAND_DEFAULT_CLASS): events = self.handler.get_events(obj) types = self.handler.get_event_types(obj) + # If no event name is specified, display the list of events + if not event_name: + self.list_events() + return + # 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)) + # If there's only one event, just edit it + if len(events[event_name]) == 1: + event = events[event_name][0] + else: + if not parameters: + self.msg("Which event do you wish to edit? Specify a number.") + self.list_events() + 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 + + # If caller can't edit without validation, forbid editing + # others' works + if not self.autovalid and event["author"] is not self.caller: + self.msg("You cannot edit this event created by someone else.") return + # Check the definition of the event definition = types[event_name] description = definition[1] self.msg(description) diff --git a/evennia/contrib/events/extend.py b/evennia/contrib/events/extend.py index 24f2280547..a0fa28475f 100644 --- a/evennia/contrib/events/extend.py +++ b/evennia/contrib/events/extend.py @@ -6,6 +6,8 @@ and are designed to be used more by developers to add event types. """ +from textwrap import dedent + from evennia import logger from evennia import ScriptDB @@ -123,4 +125,5 @@ def connect_event_types(): types = script.ndb.event_types[typeclass_name] # Add or replace the event + help_text = dedent(help_text.strip("\n")) types[event_name] = (variables, help_text) diff --git a/evennia/contrib/events/typeclasses.py b/evennia/contrib/events/typeclasses.py index c66df484f2..00bcd7443e 100644 --- a/evennia/contrib/events/typeclasses.py +++ b/evennia/contrib/events/typeclasses.py @@ -28,8 +28,9 @@ class PatchedExit(object): target_location (Object): Where target is going. """ - if inherits_from(traversing_object, DefaultCharacter): - script = ScriptDB.objects.get(db_key="event_handler") + 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, exit, exit.location) if not allow: @@ -37,12 +38,33 @@ class PatchedExit(object): hook(exit, traversing_object, target_location) + # After traversing + if is_character: + script.call_event(exit, "traverse", traversing_object, + exit, exit.location, exit.destination) + + # Default events create_event_type(DefaultExit, "can_traverse", ["character", "exit", "room"], - """Can the character traverse through this exit? + """ + 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.""") + contains the room in which the character and exit are. +""") +create_event_type(DefaultExit, "traverse", ["character", "exit", + "origin", "destination"], """ + After the characer has traversed through this exit. + This event is called after a character has traversed through this + exit. Traversing cannot be prevented using 'deny()' at this + point. The character will be in a different room and she will + have received the room's description when this event is called. + The 'character' variable contains the character who has traversed + through this exit. The 'exit' variable contains the exit, the + 'origin' variable contains the room in which the character was + before traversing, while 'destination' contains the room in which + the character now is. + """)