mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Add a contents indexer to optimize inventory lookups.
This commit is contained in:
parent
a8a5453a97
commit
2fcb6e9466
2 changed files with 44 additions and 24 deletions
|
|
@ -13,6 +13,7 @@ Attributes are separate objects that store values persistently onto
|
|||
the database object. Like everything else, they can be accessed
|
||||
transparently through the decorating TypeClass.
|
||||
"""
|
||||
from collections import defaultdict
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
|
@ -42,8 +43,9 @@ class ContentsHandler(object):
|
|||
|
||||
"""
|
||||
self.obj = obj
|
||||
self._pkcache = {}
|
||||
self._pkcache = set()
|
||||
self._idcache = obj.__class__.__instance_cache__
|
||||
self._typecache = defaultdict(set)
|
||||
self.init()
|
||||
|
||||
def init(self):
|
||||
|
|
@ -51,25 +53,30 @@ class ContentsHandler(object):
|
|||
Re-initialize the content cache
|
||||
|
||||
"""
|
||||
self._pkcache.update(
|
||||
dict((obj.pk, None) for obj in ObjectDB.objects.filter(db_location=self.obj) if obj.pk)
|
||||
)
|
||||
objects = [obj for obj in ObjectDB.objects.filter(db_location=self.obj) if obj.pk]
|
||||
self._pkcache = {obj.pk for obj in objects}
|
||||
for obj in objects:
|
||||
for ctype in obj._content_types:
|
||||
self._typecache[ctype].add(obj.pk)
|
||||
|
||||
def get(self, exclude=None):
|
||||
def get(self, exclude=None, category=None):
|
||||
"""
|
||||
Return the contents of the cache.
|
||||
|
||||
Args:
|
||||
exclude (Object or list of Object): object(s) to ignore
|
||||
category (str or None): Filter list by a content-type. If None, don't filter.
|
||||
|
||||
Returns:
|
||||
objects (list): the Objects inside this location
|
||||
|
||||
"""
|
||||
if exclude:
|
||||
pks = [pk for pk in self._pkcache if pk not in [excl.pk for excl in make_iter(exclude)]]
|
||||
if category is not None:
|
||||
pks = self._typecache[category]
|
||||
else:
|
||||
pks = self._pkcache
|
||||
if exclude:
|
||||
pks = pks - {excl.pk for excl in make_iter(exclude)}
|
||||
try:
|
||||
return [self._idcache[pk] for pk in pks]
|
||||
except KeyError:
|
||||
|
|
@ -91,7 +98,9 @@ class ContentsHandler(object):
|
|||
obj (Object): object to add
|
||||
|
||||
"""
|
||||
self._pkcache[obj.pk] = None
|
||||
self._pkcache.add(obj.pk)
|
||||
for ctype in obj._content_types:
|
||||
self._typecache[ctype].add(obj.pk)
|
||||
|
||||
def remove(self, obj):
|
||||
"""
|
||||
|
|
@ -101,7 +110,9 @@ class ContentsHandler(object):
|
|||
obj (Object): object to remove
|
||||
|
||||
"""
|
||||
self._pkcache.pop(obj.pk, None)
|
||||
self._pkcache.remove(obj.pk)
|
||||
for ctype in obj._content_types:
|
||||
self._typecache[ctype].discard(obj.pk)
|
||||
|
||||
def clear(self):
|
||||
"""
|
||||
|
|
@ -109,6 +120,7 @@ class ContentsHandler(object):
|
|||
|
||||
"""
|
||||
self._pkcache = {}
|
||||
self._typecache = defaultdict(set)
|
||||
self.init()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -203,6 +203,8 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
|||
without `obj.save()` having to be called explicitly.
|
||||
|
||||
"""
|
||||
# Used for sorting / filtering.
|
||||
_content_types = ("object")
|
||||
|
||||
# lockstring of newly created objects, for easy overloading.
|
||||
# Will be formatted with the appropriate attributes.
|
||||
|
|
@ -257,7 +259,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
|||
and not self.db_account.attributes.get("_quell")
|
||||
)
|
||||
|
||||
def contents_get(self, exclude=None):
|
||||
def contents_get(self, exclude=None, category=None):
|
||||
"""
|
||||
Returns the contents of this object, i.e. all
|
||||
objects that has this object set as its location.
|
||||
|
|
@ -266,6 +268,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
|||
Args:
|
||||
exclude (Object): Object to exclude from returned
|
||||
contents list
|
||||
category (str): A category to filter by. None for no filtering.
|
||||
|
||||
Returns:
|
||||
contents (list): List of contents of this Object.
|
||||
|
|
@ -1656,20 +1659,25 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
|||
**kwargs (dict): Arbitrary, optional arguments for users
|
||||
overriding the call (unused by default).
|
||||
"""
|
||||
def filter_visible(obj_list):
|
||||
# Helper method to determine if objects are visible to the looker.
|
||||
return [obj for obj in obj_list if obj != looker and obj.access(looker, "view")]
|
||||
|
||||
if not looker:
|
||||
return ""
|
||||
|
||||
# get and identify all objects
|
||||
visible = (con for con in self.contents if con != looker and con.access(looker, "view"))
|
||||
exits, users, things = [], [], defaultdict(list)
|
||||
for con in visible:
|
||||
key = con.get_display_name(looker)
|
||||
if con.destination:
|
||||
exits.append(key)
|
||||
elif con.has_account:
|
||||
users.append("|c%s|n" % key)
|
||||
else:
|
||||
# things can be pluralized
|
||||
things[key].append(con)
|
||||
exits_list = filter_visible(self.contents_get(category='exit'))
|
||||
users_list = filter_visible(self.contents_get(category='character'))
|
||||
things_list = filter_visible(self.contents_get(category="object"))
|
||||
|
||||
things = defaultdict(list)
|
||||
|
||||
for thing in things_list:
|
||||
things[thing.key].append(thing)
|
||||
users = [f"|c{user.key}|n" for user in users_list]
|
||||
exits = [ex.key for ex in exits_list]
|
||||
|
||||
# get description, build string
|
||||
string = "|c%s|n\n" % self.get_display_name(looker)
|
||||
desc = self.db.desc
|
||||
|
|
@ -2026,7 +2034,7 @@ class DefaultCharacter(DefaultObject):
|
|||
a character avatar controlled by an account.
|
||||
|
||||
"""
|
||||
|
||||
_content_types = ("character")
|
||||
# lockstring of newly created rooms, for easy overloading.
|
||||
# Will be formatted with the appropriate attributes.
|
||||
lockstring = "puppet:id({character_id}) or pid({account_id}) or perm(Developer) or pperm(Developer);delete:id({account_id}) or perm(Admin)"
|
||||
|
|
@ -2277,7 +2285,7 @@ class DefaultRoom(DefaultObject):
|
|||
This is the base room object. It's just like any Object except its
|
||||
location is always `None`.
|
||||
"""
|
||||
|
||||
_content_types = ("room", "object")
|
||||
# lockstring of newly created rooms, for easy overloading.
|
||||
# Will be formatted with the {id} of the creating object.
|
||||
lockstring = (
|
||||
|
|
@ -2427,7 +2435,7 @@ class DefaultExit(DefaultObject):
|
|||
exits simply by giving the exit-object's name on its own.
|
||||
|
||||
"""
|
||||
|
||||
_content_types = ("exit")
|
||||
exit_command = ExitCommand
|
||||
priority = 101
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue