OLC systen. Create olc_storage mechanism
This commit is contained in:
parent
38a81486e2
commit
70a81a939c
7 changed files with 205 additions and 9 deletions
|
|
@ -631,10 +631,31 @@ class DefaultAccount(with_metaclass(TypeclassBase, AccountDB)):
|
||||||
# this will only be set if the utils.create_account
|
# this will only be set if the utils.create_account
|
||||||
# function was used to create the object.
|
# function was used to create the object.
|
||||||
cdict = self._createdict
|
cdict = self._createdict
|
||||||
|
updates = []
|
||||||
|
if not cdict.get("key"):
|
||||||
|
if not self.db_key:
|
||||||
|
self.db_key = "#%i" % self.dbid
|
||||||
|
updates.append("db_key")
|
||||||
|
elif self.key != cdict.get("key"):
|
||||||
|
updates.append("db_key")
|
||||||
|
self.db_key = cdict["key"]
|
||||||
|
if updates:
|
||||||
|
self.save(update_fields=updates)
|
||||||
|
|
||||||
if cdict.get("locks"):
|
if cdict.get("locks"):
|
||||||
self.locks.add(cdict["locks"])
|
self.locks.add(cdict["locks"])
|
||||||
if cdict.get("permissions"):
|
if cdict.get("permissions"):
|
||||||
permissions = cdict["permissions"]
|
permissions = cdict["permissions"]
|
||||||
|
if cdict.get("tags"):
|
||||||
|
# this should be a list of tags, tuples (key, category) or (key, category, data)
|
||||||
|
self.tags.batch_add(*cdict["tags"])
|
||||||
|
if cdict.get("attributes"):
|
||||||
|
# this should be tuples (key, val, ...)
|
||||||
|
self.attributes.batch_add(*cdict["attributes"])
|
||||||
|
if cdict.get("nattributes"):
|
||||||
|
# this should be a dict of nattrname:value
|
||||||
|
for key, value in cdict["nattributes"]:
|
||||||
|
self.nattributes.add(key, value)
|
||||||
del self._createdict
|
del self._createdict
|
||||||
|
|
||||||
self.permissions.batch_add(*permissions)
|
self.permissions.batch_add(*permissions)
|
||||||
|
|
|
||||||
|
|
@ -1002,14 +1002,14 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
|
||||||
cdict["location"].at_object_receive(self, None)
|
cdict["location"].at_object_receive(self, None)
|
||||||
self.at_after_move(None)
|
self.at_after_move(None)
|
||||||
if cdict.get("tags"):
|
if cdict.get("tags"):
|
||||||
# this should be a list of tags
|
# this should be a list of tags, tuples (key, category) or (key, category, data)
|
||||||
self.tags.batch_add(*cdict["tags"])
|
self.tags.batch_add(*cdict["tags"])
|
||||||
if cdict.get("attributes"):
|
if cdict.get("attributes"):
|
||||||
# this should be a dict of attrname:value
|
# this should be tuples (key, val, ...)
|
||||||
self.attributes.batch_add(*cdict["attributes"])
|
self.attributes.batch_add(*cdict["attributes"])
|
||||||
if cdict.get("nattributes"):
|
if cdict.get("nattributes"):
|
||||||
# this should be a dict of nattrname:value
|
# this should be a dict of nattrname:value
|
||||||
for key, value in cdict["nattributes"].items():
|
for key, value in cdict["nattributes"]:
|
||||||
self.nattributes.add(key, value)
|
self.nattributes.add(key, value)
|
||||||
|
|
||||||
del self._createdict
|
del self._createdict
|
||||||
|
|
|
||||||
|
|
@ -513,6 +513,22 @@ class DefaultScript(ScriptBase):
|
||||||
updates.append("db_persistent")
|
updates.append("db_persistent")
|
||||||
if updates:
|
if updates:
|
||||||
self.save(update_fields=updates)
|
self.save(update_fields=updates)
|
||||||
|
|
||||||
|
if cdict.get("permissions"):
|
||||||
|
self.permissions.batch_add(*cdict["permissions"])
|
||||||
|
if cdict.get("locks"):
|
||||||
|
self.locks.add(cdict["locks"])
|
||||||
|
if cdict.get("tags"):
|
||||||
|
# this should be a list of tags, tuples (key, category) or (key, category, data)
|
||||||
|
self.tags.batch_add(*cdict["tags"])
|
||||||
|
if cdict.get("attributes"):
|
||||||
|
# this should be tuples (key, val, ...)
|
||||||
|
self.attributes.batch_add(*cdict["attributes"])
|
||||||
|
if cdict.get("nattributes"):
|
||||||
|
# this should be a dict of nattrname:value
|
||||||
|
for key, value in cdict["nattributes"]:
|
||||||
|
self.nattributes.add(key, value)
|
||||||
|
|
||||||
if not cdict.get("autostart"):
|
if not cdict.get("autostart"):
|
||||||
# don't auto-start the script
|
# don't auto-start the script
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -530,8 +530,8 @@ class AttributeHandler(object):
|
||||||
repeat-calling add when having many Attributes to add.
|
repeat-calling add when having many Attributes to add.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
indata (tuple): Tuples of varying length representing the
|
indata (list): List of tuples of varying length representing the
|
||||||
Attribute to add to this object.
|
Attribute to add to this object. Supported tuples are
|
||||||
- `(key, value)`
|
- `(key, value)`
|
||||||
- `(key, value, category)`
|
- `(key, value, category)`
|
||||||
- `(key, value, category, lockstring)`
|
- `(key, value, category, lockstring)`
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,8 @@ _GA = object.__getattribute__
|
||||||
|
|
||||||
def create_object(typeclass=None, key=None, location=None, home=None,
|
def create_object(typeclass=None, key=None, location=None, home=None,
|
||||||
permissions=None, locks=None, aliases=None, tags=None,
|
permissions=None, locks=None, aliases=None, tags=None,
|
||||||
destination=None, report_to=None, nohome=False):
|
destination=None, report_to=None, nohome=False, attributes=None,
|
||||||
|
nattributes=None):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Create a new in-game object.
|
Create a new in-game object.
|
||||||
|
|
@ -68,13 +69,18 @@ def create_object(typeclass=None, key=None, location=None, home=None,
|
||||||
permissions (list): A list of permission strings or tuples (permstring, category).
|
permissions (list): A list of permission strings or tuples (permstring, category).
|
||||||
locks (str): one or more lockstrings, separated by semicolons.
|
locks (str): one or more lockstrings, separated by semicolons.
|
||||||
aliases (list): A list of alternative keys or tuples (aliasstring, category).
|
aliases (list): A list of alternative keys or tuples (aliasstring, category).
|
||||||
tags (list): List of tag keys or tuples (tagkey, category).
|
tags (list): List of tag keys or tuples (tagkey, category) or (tagkey, category, data).
|
||||||
destination (Object or str): Obj or #dbref to use as an Exit's
|
destination (Object or str): Obj or #dbref to use as an Exit's
|
||||||
target.
|
target.
|
||||||
report_to (Object): The object to return error messages to.
|
report_to (Object): The object to return error messages to.
|
||||||
nohome (bool): This allows the creation of objects without a
|
nohome (bool): This allows the creation of objects without a
|
||||||
default home location; only used when creating the default
|
default home location; only used when creating the default
|
||||||
location itself or during unittests.
|
location itself or during unittests.
|
||||||
|
attributes (list): Tuples on the form (key, value) or (key, value, category),
|
||||||
|
(key, value, lockstring) or (key, value, lockstring, default_access).
|
||||||
|
to set as Attributes on the new object.
|
||||||
|
nattributes (list): Non-persistent tuples on the form (key, value). Note that
|
||||||
|
adding this rarely makes sense since this data will not survive a reload.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
object (Object): A newly created object of the given typeclass.
|
object (Object): A newly created object of the given typeclass.
|
||||||
|
|
@ -122,7 +128,8 @@ def create_object(typeclass=None, key=None, location=None, home=None,
|
||||||
# store the call signature for the signal
|
# store the call signature for the signal
|
||||||
new_object._createdict = dict(key=key, location=location, destination=destination, home=home,
|
new_object._createdict = dict(key=key, location=location, destination=destination, home=home,
|
||||||
typeclass=typeclass.path, permissions=permissions, locks=locks,
|
typeclass=typeclass.path, permissions=permissions, locks=locks,
|
||||||
aliases=aliases, tags=tags, report_to=report_to, nohome=nohome)
|
aliases=aliases, tags=tags, report_to=report_to, nohome=nohome,
|
||||||
|
attributes=attributes, nattributes=nattributes)
|
||||||
# this will trigger the save signal which in turn calls the
|
# this will trigger the save signal which in turn calls the
|
||||||
# at_first_save hook on the typeclass, where the _createdict can be
|
# at_first_save hook on the typeclass, where the _createdict can be
|
||||||
# used.
|
# used.
|
||||||
|
|
@ -139,7 +146,8 @@ object = create_object
|
||||||
|
|
||||||
def create_script(typeclass=None, key=None, obj=None, account=None, locks=None,
|
def create_script(typeclass=None, key=None, obj=None, account=None, locks=None,
|
||||||
interval=None, start_delay=None, repeats=None,
|
interval=None, start_delay=None, repeats=None,
|
||||||
persistent=None, autostart=True, report_to=None, desc=None):
|
persistent=None, autostart=True, report_to=None, desc=None,
|
||||||
|
tags=None, attributes=None):
|
||||||
"""
|
"""
|
||||||
Create a new script. All scripts are a combination of a database
|
Create a new script. All scripts are a combination of a database
|
||||||
object that communicates with the database, and an typeclass that
|
object that communicates with the database, and an typeclass that
|
||||||
|
|
|
||||||
0
evennia/utils/olc/__init__.py
Normal file
0
evennia/utils/olc/__init__.py
Normal file
151
evennia/utils/olc/olc_storage.py
Normal file
151
evennia/utils/olc/olc_storage.py
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
"""
|
||||||
|
OLC storage and sharing mechanism.
|
||||||
|
|
||||||
|
This sets up a central storage for prototypes. The idea is to make these
|
||||||
|
available in a repository for buildiers to use. Each prototype is stored
|
||||||
|
in a Script so that it can be tagged for quick sorting/finding and locked for limiting
|
||||||
|
access.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from evennia.scripts.scripts import DefaultScript
|
||||||
|
from evennia.utils.create import create_script
|
||||||
|
from evennia.utils.utils import make_iter
|
||||||
|
from evennia.utils.evtable import EvTable
|
||||||
|
|
||||||
|
|
||||||
|
class PersistentPrototype(DefaultScript):
|
||||||
|
"""
|
||||||
|
This stores a single prototype
|
||||||
|
"""
|
||||||
|
key = "persistent_prototype"
|
||||||
|
desc = "Stores a prototoype"
|
||||||
|
|
||||||
|
|
||||||
|
def store_prototype(caller, key, prototype, desc="", tags=None, locks="", delete=False):
|
||||||
|
"""
|
||||||
|
Store a prototype persistently.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
caller (Account or Object): Caller aiming to store prototype. At this point
|
||||||
|
the caller should have permission to 'add' new prototypes, but to edit
|
||||||
|
an existing prototype, the 'edit' lock must be passed on that prototype.
|
||||||
|
key (str): Name of prototype to store.
|
||||||
|
prototype (dict): Prototype dict.
|
||||||
|
desc (str, optional): Description of prototype, to use in listing.
|
||||||
|
tags (list, optional): Tag-strings to apply to prototype. These are always
|
||||||
|
applied with the 'persistent_prototype' category.
|
||||||
|
locks (str, optional): Locks to apply to this prototype. Used locks
|
||||||
|
are 'use' and 'edit'
|
||||||
|
delete (bool, optional): Delete an existing prototype identified by 'key'.
|
||||||
|
This requires `caller` to pass the 'edit' lock of the prototype.
|
||||||
|
Returns:
|
||||||
|
stored (StoredPrototype or None): The resulting prototype (new or edited),
|
||||||
|
or None if deleting.
|
||||||
|
Raises:
|
||||||
|
PermissionError: If edit lock was not passed by caller.
|
||||||
|
|
||||||
|
"""
|
||||||
|
key = key.lower()
|
||||||
|
locks = locks if locks else "use:all();edit:id({}) or edit:perm(Admin)".format(caller.id)
|
||||||
|
tags = [(tag, "persistent_prototype") for tag in make_iter(tags)]
|
||||||
|
|
||||||
|
stored_prototype = PersistentPrototype.objects.filter(db_key=key)
|
||||||
|
|
||||||
|
if stored_prototype:
|
||||||
|
stored_prototype = stored_prototype[0]
|
||||||
|
if not stored_prototype.access(caller, 'edit'):
|
||||||
|
PermissionError("{} does not have permission to edit prototype {}".format(caller, key))
|
||||||
|
|
||||||
|
if delete:
|
||||||
|
stored_prototype.delete()
|
||||||
|
return
|
||||||
|
|
||||||
|
if desc:
|
||||||
|
stored_prototype.desc = desc
|
||||||
|
if tags:
|
||||||
|
stored_prototype.tags.add(tags)
|
||||||
|
if locks:
|
||||||
|
stored_prototype.locks.add(locks)
|
||||||
|
if prototype:
|
||||||
|
stored_prototype.attributes.add("prototype", prototype)
|
||||||
|
else:
|
||||||
|
stored_prototype = create_script(
|
||||||
|
PersistentPrototype, key=key, desc=desc, persistent=True,
|
||||||
|
locks=locks, tags=tags, attributes=[("prototype", prototype)])
|
||||||
|
return stored_prototype
|
||||||
|
|
||||||
|
|
||||||
|
def search_prototype(key=None, tags=None):
|
||||||
|
"""
|
||||||
|
Find prototypes based on key and/or tags.
|
||||||
|
|
||||||
|
Kwargs:
|
||||||
|
key (str): An exact or partial key to query for.
|
||||||
|
tags (str or list): Tag key or keys to query for. These
|
||||||
|
will always be applied with the 'persistent_protototype'
|
||||||
|
tag category.
|
||||||
|
Return:
|
||||||
|
matches (queryset): All found PersistentPrototypes. This will
|
||||||
|
be all prototypes if no arguments are given.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
This will use the tags to make a subselection before attempting
|
||||||
|
to match on the key. So if key/tags don't match up nothing will
|
||||||
|
be found.
|
||||||
|
|
||||||
|
"""
|
||||||
|
matches = PersistentPrototype.objects.all()
|
||||||
|
if tags:
|
||||||
|
# exact match on tag(s)
|
||||||
|
tags = make_iter(tags)
|
||||||
|
tag_categories = ("persistent_prototype" for _ in tags)
|
||||||
|
matches = matches.get_by_tag(tags, tag_categories)
|
||||||
|
if key:
|
||||||
|
# partial match on key
|
||||||
|
matches = matches.filter(db_key=key) or matches.filter(db_key__icontains=key)
|
||||||
|
return matches
|
||||||
|
|
||||||
|
|
||||||
|
def get_prototype_list(caller, key=None, tags=None, show_non_use=False, show_non_edit=True):
|
||||||
|
"""
|
||||||
|
Collate a list of found prototypes based on search criteria and access.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
caller (Account or Object): The object requesting the list.
|
||||||
|
key (str, optional): Exact or partial key to query for.
|
||||||
|
tags (str or list, optional): Tag key or keys to query for.
|
||||||
|
show_non_use (bool, optional): Show also prototypes the caller may not use.
|
||||||
|
show_non_edit (bool, optional): Show also prototypes the caller may not edit.
|
||||||
|
Returns:
|
||||||
|
table (EvTable or None): An EvTable representation of the prototypes. None
|
||||||
|
if no prototypes were found.
|
||||||
|
|
||||||
|
"""
|
||||||
|
prototypes = search_prototype(key, tags)
|
||||||
|
|
||||||
|
if not prototypes:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# gather access permissions as (key, desc, can_use, can_edit)
|
||||||
|
prototypes = [(prototype.key, prototype.desc,
|
||||||
|
prototype.access(caller, "use"), prototype.access(caller, "edit"))
|
||||||
|
for prototype in prototypes]
|
||||||
|
|
||||||
|
if not show_non_use:
|
||||||
|
prototypes = [tup for tup in prototypes if tup[2]]
|
||||||
|
if not show_non_edit:
|
||||||
|
prototypes = [tup for tup in prototypes if tup[3]]
|
||||||
|
|
||||||
|
if not prototypes:
|
||||||
|
return None
|
||||||
|
|
||||||
|
table = []
|
||||||
|
for i in range(len(prototypes[0])):
|
||||||
|
table.append([tup[i] for tup in prototypes])
|
||||||
|
table = EvTable("Key", "Desc", "Use", "Edit", table, crop=True, width=78)
|
||||||
|
table.reformat_column(0, width=28)
|
||||||
|
table.reformat_column(1, width=40)
|
||||||
|
table.reformat_column(2, width=5)
|
||||||
|
table.reformat_column(3, width=5)
|
||||||
|
return table
|
||||||
Loading…
Add table
Add a link
Reference in a new issue