From 9479057ce5bfb1ab3490a73002b5654e85cf3839 Mon Sep 17 00:00:00 2001 From: Griatch Date: Mon, 6 Jun 2016 22:12:22 +0200 Subject: [PATCH] Added a simpledoor contrib to give an example of a door Exit type. --- evennia/contrib/simpledoor.py | 164 ++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 evennia/contrib/simpledoor.py diff --git a/evennia/contrib/simpledoor.py b/evennia/contrib/simpledoor.py new file mode 100644 index 000000000..da8cead67 --- /dev/null +++ b/evennia/contrib/simpledoor.py @@ -0,0 +1,164 @@ +""" +SimpleDoor + +Contribution - Griatch 2016 + +A simple two-way exit that represents a door that can be opened and +closed. Can easily be expanded from to make it lockable, destroyable +etc. + +Installation: + + Import this module in mygame/commands/default_cmdsets and add + the CmdOpen and CmdOpenCloseDoor commands to the CharacterCmdSet; + then reload the server. + +To try it out, `@dig` a new room and then use the (overloaded) `@open` +commmand to open a new doorway to it like this: + + @open doorway:contrib.door.SimpleDoor = otherroom + +You can then use `open doorway' and `close doorway` to change the open +state. If you are not superuser (`@quell` yourself) you'll find you +cannot pass through either side of the door once it's closed from the +other side. + +""" + +from evennia import DefaultExit, default_cmds +from evennia.utils.utils import inherits_from + + +class SimpleDoor(DefaultExit): + """ + A two-way exit "door" with some methods for affecting both "sides" + of the door at the same time. For example, set a lock on either of the two + sides using `exitname.setlock("traverse:false())` + + """ + def at_object_creation(self): + """ + Called the very first time the door is created. + + """ + self.db.return_exit = None + + def setlock(self, lockstring): + """ + Sets identical locks on both sides of the door. + + Args: + lockstring (str): A lockstring, like `"traverse:true()"`. + + """ + self.locks.add(lockstring) + self.db.return_exit.locks.add(lockstring) + + def setdesc(self, description): + """ + Sets identical descs on both sides of the door. + + Args: + setdesc (str): A description. + + """ + self.db.desc = description + self.db.return_exit.db.desc = description + + def delete(self): + """ + Deletes both sides of the door. + + """ + # we have to be careful to avoid a delete-loop. + if self.db.return_exit: + super(SimpleDoor, self.db.return_exit).delete() + super(SimpleDoor, self).delete() + return True + + def at_failed_traverse(self, traversing_object): + """ + Called when door traverse: lock fails. + + Args: + traversing_object (Typeclassed entity): The object + attempting the traversal. + + """ + traversing_object.msg("%s is closed." % self.key) + + +class CmdOpen(default_cmds.CmdOpen): + __doc__ = default_cmds.CmdOpen.__doc__ + # overloading parts of the default CmdOpen command to support doors. + + def create_exit(self, exit_name, location, destination, + exit_aliases=None, typeclass=None): + """ + Simple wrapper for the default CmdOpen.create_exit + """ + if hasattr(self, "return_exit_already_created"): + # we don't create a return exit if it was already created (because + # we created a door) + del self.return_exit_already_created + return + # create a new exit as normal + new_exit = super(CmdOpen, self).create_exit(exit_name, location, destination, + exit_aliases=exit_aliases, typeclass=typeclass) + if inherits_from(new_exit, SimpleDoor): + # a door - create its counterpart and make sure to turn off the default + # return-exit creation of CmdOpen + self.caller.msg("Note: A door-type exit was created - ignored eventual custom return-exit type.") + self.return_exit_already_created = True + back_exit = super(CmdOpen, self).create_exit(exit_name, destination, location, + exit_aliases=exit_aliases, typeclass=typeclass) + new_exit.db.return_exit = back_exit + back_exit.db.return_exit = new_exit + return new_exit + + +# A simple example of a command making use of the door exit class' +# functionality. One could easily expand it with functionality to +# operate on other types of open-able objects as needed. + +class CmdOpenCloseDoor(default_cmds.MuxCommand): + """ + Open and close a door + + Usage: + open + close + + """ + + key = "open" + aliases = ["close"] + locks = "cmd:all()" + help_category = "General" + + def func(self): + "implement the door functionality" + if not self.args: + self.caller.msg("Usage: open||close ") + return + + door = self.caller.search(self.args) + if not door: + return + if not inherits_from(door, SimpleDoor): + self.caller.msg("This is not a door.") + return + + if self.cmdstring == "open": + if door.locks.check(self.caller, "traverse"): + self.caller.msg("%s is already open." % door.key) + else: + door.setlock("traverse:true()") + self.caller.msg("You open %s." % door.key) + else: # close + if not door.locks.check(self.caller, "traverse"): + self.caller.msg("%s is already closed." % door.key) + else: + door.setlock("traverse:false()") + self.caller.msg("You close %s." % door.key) +