mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Add multidescer contrib, inspired by MUSH origins.
This commit is contained in:
parent
c15f107ad9
commit
893cffc3e1
1 changed files with 237 additions and 0 deletions
237
evennia/contrib/multidescer.py
Normal file
237
evennia/contrib/multidescer.py
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
"""
|
||||
Evennia Mutltidescer
|
||||
|
||||
Contrib - Griatch 2016
|
||||
|
||||
A "multidescer" is a concept from the MUSH world. It allows for
|
||||
creating, managing and switching between multiple character
|
||||
descriptions. This multidescer will not require any changes to the
|
||||
Character class, rather it will use the `multidescs` Attribute (a
|
||||
list) and create it if it does not exist.
|
||||
|
||||
This contrib also works well together with the rpsystem contrib (which
|
||||
also adds the short descriptions and the `sdesc` command).
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
Edit `mygame/commands/default_cmdsets.py` and add
|
||||
`from contrib.multidesc import CmdMultiDesc` to the top.
|
||||
|
||||
Next, look up the `at_cmdset_create` method of the `CharacterCmdSet`
|
||||
class and add a line `self.add(CmdMultiDesc())` to the end
|
||||
of it.
|
||||
|
||||
Reload the server and you should have the +desc command available (it
|
||||
will replace the default `desc` command).
|
||||
|
||||
"""
|
||||
from evennia import default_cmds
|
||||
from evennia.utils.utils import crop
|
||||
from evennia.utils.eveditor import EvEditor
|
||||
|
||||
|
||||
# Helper functions for the Command
|
||||
|
||||
|
||||
def _update_store(caller, num=0, text=None, replace=False):
|
||||
"""
|
||||
Helper function for updating the database store.
|
||||
|
||||
Args:
|
||||
caller (Object): The caller of the command.
|
||||
num (int): Index of store to update.
|
||||
text (str): Description text.
|
||||
replace (bool): Replace or amend description.
|
||||
|
||||
"""
|
||||
if not caller.db.multidesc:
|
||||
# initialize the multidesc attribute
|
||||
caller.db.multidesc = [caller.db.desc or ""]
|
||||
if not text:
|
||||
return
|
||||
if replace:
|
||||
caller.db.multidesc[num] = text
|
||||
else:
|
||||
caller.db.multidesc.insert(num, text)
|
||||
|
||||
|
||||
class NumValidateError(ValueError):
|
||||
"Used for tracebacks from _validate_num"
|
||||
pass
|
||||
|
||||
|
||||
def _validate_num(caller, num):
|
||||
"""
|
||||
Check so the given num is a valid number in the storage interval.
|
||||
|
||||
Args:
|
||||
caller (Object): The caller of the command
|
||||
num (str): The number to validate.
|
||||
|
||||
Returns:
|
||||
num (int): Returns the valid index (starting from 0)
|
||||
|
||||
Raises:
|
||||
NumValidateError: For malformed numbers.
|
||||
|
||||
Notes:
|
||||
This function will also report errors.
|
||||
|
||||
"""
|
||||
if not caller.db.multidesc:
|
||||
_update_store(caller)
|
||||
nlen = len(caller.db.multidesc)
|
||||
if not num.strip().isdigit() or not (0 < int(num) <= nlen):
|
||||
raise NumValidateError("%s must be a number between 1 and %i." %
|
||||
('%s' % num or "Argument", nlen))
|
||||
else:
|
||||
return int(num) - 1
|
||||
|
||||
|
||||
# eveditor save/load/quit functions
|
||||
|
||||
def _save_editor(caller, buffer):
|
||||
"Called when the editor saves its contents"
|
||||
num = caller.db._multidesc_editnum
|
||||
replace = caller.db._multidesc_editreplace
|
||||
if num is not None:
|
||||
_update_store(caller, num, buffer, replace=replace)
|
||||
caller.msg("Saved the buffer to description slot %i." % (num + 1))
|
||||
return True
|
||||
|
||||
def _load_editor(caller):
|
||||
"Called when the editor loads contents"
|
||||
num = caller.db._multidesc_editnum
|
||||
if num is not None:
|
||||
try:
|
||||
return caller.db.multidesc[num]
|
||||
except IndexError:
|
||||
pass
|
||||
return ""
|
||||
|
||||
def _quit_editor(caller):
|
||||
"Called when the editor quits"
|
||||
del caller.db._multidesc_editnum
|
||||
del caller.db._multidesc_editreplace
|
||||
caller.msg("Exited editor.")
|
||||
|
||||
|
||||
# The actual command class
|
||||
|
||||
class CmdMultiDesc(default_cmds.MuxCommand):
|
||||
"""
|
||||
Manage multiple descriptions
|
||||
|
||||
Usage:
|
||||
+desc [n] - show current or desc <n>
|
||||
+desc/list - list descriptions (abbreviated)
|
||||
+desc/list/full - list descriptions (full texts)
|
||||
+desc/add [<n> =] <text> - add new desc or replace desc <n>
|
||||
+desc/edit [n] - open editor to modify current or desc <n>
|
||||
+desc/del [n] - delete current or desc <n>
|
||||
+desc/swap <n1>-<n2> - reorder list by swapping #n1 and <n2>
|
||||
+desc/set <n> - set which desc <n> as active desc
|
||||
|
||||
"""
|
||||
key = "+desc"
|
||||
aliases = ["desc"]
|
||||
locks = "cmd:all()"
|
||||
help_category = "General"
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
Implements the multidescer. We will use `db.desc` for the
|
||||
description in use and `db.multidesc` to store all descriptions.
|
||||
"""
|
||||
|
||||
caller = self.caller
|
||||
args = self.args.strip()
|
||||
switches = self.switches
|
||||
|
||||
try:
|
||||
if "list" in switches or "all" in switches:
|
||||
# list all stored descriptions, either in full or cropped.
|
||||
# Note that we list starting from 1, not from 0.
|
||||
_update_store(caller)
|
||||
do_crop = not "full" in switches
|
||||
outtext = "|wStored descs:|n"
|
||||
for inum, desc in enumerate(caller.db.multidesc):
|
||||
outtext += "\n|w%i:|n %s" % (inum + 1, crop(desc) if do_crop else "\n%s" % desc)
|
||||
caller.msg(outtext)
|
||||
|
||||
elif "add" in switches:
|
||||
# add text directly to a new entry or an existing one.
|
||||
if self.rhs:
|
||||
# this means a '=' was given
|
||||
num, desc = _validate_num(caller, self.lhs), self.rhs
|
||||
replace = True
|
||||
else:
|
||||
num, desc = 0, self.args
|
||||
replace = False
|
||||
if not desc:
|
||||
caller.msg("No description given.")
|
||||
return
|
||||
_update_store(caller, num, desc, replace=replace)
|
||||
caller.msg("Stored description in slot %i: \"%s\"" % (num + 1, crop(desc)))
|
||||
|
||||
elif "edit" in switches:
|
||||
# Use the eveditor to edit the description.
|
||||
if args:
|
||||
num = _validate_num(caller, args)
|
||||
replace = True
|
||||
else:
|
||||
num = 1
|
||||
replace = False
|
||||
# this is used by the editor to know what to edit; it's deleted automatically
|
||||
caller.db._multidesc_editnum = num
|
||||
caller.db._multidesc_editreplace = replace
|
||||
# start the editor
|
||||
EvEditor(caller, loadfunc=_load_editor, savefunc=_save_editor,
|
||||
quitfunc=_quit_editor, key="multidesc editor", persistent=True)
|
||||
|
||||
elif "delete" in switches or "del" in switches:
|
||||
# delete a multidesc entry.
|
||||
num = _validate_num(caller, args)
|
||||
del caller.db.multidesc[num]
|
||||
caller.msg("Deleted description number %i." % (num + 1))
|
||||
|
||||
elif "swap" in switches or "switch" in switches or "reorder" in switches:
|
||||
# Reorder list by swapping two entries. We expect numbers starting from 1
|
||||
nums = [_validate_num(caller, arg) for arg in args.split("-", 1)]
|
||||
if not len(nums) == 2:
|
||||
caller.msg("To swap two desc entries, use |w%s/swap <num1> - <num2>|n" % (self.key))
|
||||
return
|
||||
num1, num2 = nums
|
||||
if num1 == num2:
|
||||
caller.msg("Swapping position with itself changes nothing.")
|
||||
return
|
||||
# perform the swap
|
||||
desc1, desc2 = caller.db.multidesc[num1], caller.db.multidesc[num2]
|
||||
caller.db.multidesc[num2] = desc1
|
||||
caller.db.multidesc[num1] = desc2
|
||||
caller.msg("Swapped descs numbers %i and %i." % (num1 + 1, num2 + 1))
|
||||
|
||||
elif "set" in switches:
|
||||
# switches one of the multidescs to be the "active",
|
||||
# description, with numbers starting from 1
|
||||
if args:
|
||||
num = _validate_num(caller, args)
|
||||
else:
|
||||
_update_store(caller)
|
||||
num = 0
|
||||
# activating this description
|
||||
caller.db.desc = caller.db.multidesc[num]
|
||||
caller.msg("|wSet description %i as the current one:|n\n%s" % (num + 1, crop(caller.db.desc)))
|
||||
|
||||
else:
|
||||
# display the current description or a numbered description
|
||||
if args:
|
||||
num = _validate_num(caller, args)
|
||||
caller.msg("|wDecsription number %i:|n\n%s" % (num + 1, caller.db.multidesc[num]))
|
||||
else:
|
||||
caller.msg("|wCurrent desc:|n\n%s" % caller.db.desc)
|
||||
|
||||
except NumValidateError, err:
|
||||
# This is triggered by _validate_num
|
||||
caller.msg(err)
|
||||
Loading…
Add table
Add a link
Reference in a new issue