Merged. Still need to update some migrations.

This commit is contained in:
Griatch 2013-07-11 19:11:27 +02:00
commit c676c9965f
29 changed files with 821 additions and 401 deletions

View file

@ -34,7 +34,6 @@ class ObjectManager(TypedObjectManager):
get_dbref_range
object_totals
typeclass_search
get_object_with_user
get_object_with_player
get_objs_with_key_and_typeclass
get_objs_with_attr
@ -52,29 +51,8 @@ class ObjectManager(TypedObjectManager):
# ObjectManager Get methods
#
# user/player related
# player related
@returns_typeclass
def get_object_with_user(self, user):
"""
Matches objects with obj.player.user matching the argument.
A player<->user is a one-to-relationship, so this always
returns just one result or None.
user - may be a user object or user id.
"""
dbref = self.dbref(user)
if dbref:
try:
return self.get(db_player__user__id=dbref)
except self.model.DoesNotExist:
pass
try:
return self.get(db_player__user=user)
except self.model.DoesNotExist:
return None
# This returns typeclass since get_object_with_user and get_dbref does.
@returns_typeclass
def get_object_with_player(self, ostring, exact=True, candidates=None):
"""
@ -92,9 +70,9 @@ class ObjectManager(TypedObjectManager):
# not a dbref. Search by name.
cand_restriction = candidates and Q(pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q()
if exact:
return self.filter(cand_restriction & Q(db_player__user__username__iexact=ostring))
return self.filter(cand_restriction & Q(db_player__username__iexact=ostring))
else: # fuzzy matching
ply_cands = self.filter(cand_restriction & Q(playerdb__user__username__istartswith=ostring)).values_list("db_key", flat=True)
ply_cands = self.filter(cand_restriction & Q(playerdb__username__istartswith=ostring)).values_list("db_key", flat=True)
if candidates:
index_matches = string_partial_matching(ply_cands, ostring, ret_index=True)
return [obj for ind, obj in enumerate(make_iter(candidates)) if ind in index_matches]
@ -175,7 +153,8 @@ class ObjectManager(TypedObjectManager):
if isinstance(property_value, basestring):
property_value = to_unicode(property_value)
if isinstance(property_name, basestring):
property_name = "db_%s" % property_name.lstrip('db_')
if not property_name.startswith('db_'):
property_name = "db_%s" % property_name
querykwargs = {property_name:property_value}
cand_restriction = candidates and Q(pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q()
type_restriction = typeclasses and Q(db_typeclass_path__in=make_iter(typeclasses)) or Q()
@ -183,6 +162,10 @@ class ObjectManager(TypedObjectManager):
return list(self.filter(cand_restriction & type_restriction & Q(**querykwargs)))
except exceptions.FieldError:
return []
except ValueError:
from src.utils import logger
logger.log_errmsg("The property '%s' does not support search criteria of the type %s." % (property_name, type(property_value)))
return []
@returns_typeclass_list
def get_contents(self, location, excludeobj=None):
@ -253,7 +236,8 @@ class ObjectManager(TypedObjectManager):
By default (if not attribute_name is set), this will search object.key and object.aliases in order. Can also
be on the form #dbref, which will, if exact=True be matched against primary key.
attribute_name: (str): Use this named ObjectAttribute to match searchdata against, instead
of the defaults.
of the defaults. If this is the name of a database field (with or without the db_ prefix), that
will be matched too.
typeclass (str or TypeClass): restrict matches to objects having this typeclass. This will help
speed up global searches.
candidates (list obj ObjectDBs): If supplied, search will only be performed among the candidates

View file

@ -10,7 +10,7 @@ class Migration(DataMigration):
"Write your forwards methods here."
# we need to add a default lock string to all objects, then a separate set to Characters.
lockstring1 = 'control:id(1);get:all();edit:perm(Wizards);examine:perm(Builders);call:true();puppet:id(#4) or perm(Immortals) or pperm(Immortals);delete:id(1) or perm(Wizards)'
lockstring2 = 'control:id(#3) or perm(Immortals);get:perm(Wizards);edit:perm(Wizards);examine:perm(Builders);call:false();puppet:id(%i) or pid(%i) or perm(Immortals) or pperm(Immortals);delete:perm(Wizards)'
@ -21,10 +21,10 @@ class Migration(DataMigration):
for obj in orm.ObjectDB.objects.filter(db_player__isnull=False):
obj.db_lock_storage = lockstring2 % (obj.id, obj.db_player.id)
obj.save()
except utils.DatabaseError:
# running from scatch. In this case we just ignore this.
pass
pass
def backwards(self, orm):
"Write your backwards methods here."

View file

@ -640,7 +640,7 @@ class ObjectDB(TypedObject):
if searchdata == _HERE:
return self.location
if searchdata in (_ME, _SELF):
return self
return self.typeclass
if use_nicks:
nick = None

View file

@ -37,14 +37,14 @@ class Object(TypeClass):
# __init__ is only defined here in order to present docstring to API.
def __init__(self, dbobj):
"""
This is the root typeclass object representing all entities
that has and actual presence in-game. Objects generally has a
location, can be manipulated and looked at. Most game entities
you define should inherit from Object at some distance.
Important subclasses of Object are that Evennia defines by
default for you are Characters, Exits and Rooms.
This is the root typeclass object, representing all entities
that have an actual presence in-game. Objects generally have a
location. They can also be manipulated and looked at. Most
game entities you define should inherit from Object at some distance.
Evennia defines some important subclasses of Object by default, namely
Characters, Exits and Rooms (see the bottom of this module).
Note that all Objects and its subclasses *must* always be
Note that all new Objects and their subclasses *must* always be
created using the ev.create_object() function. This is so the
typeclass system can be correctly initiated behind the scenes.
@ -54,7 +54,7 @@ class Object(TypeClass):
* Available properties (only available on *initiated* typeclass objects)
key (string) - name of object
name (string)- same as key
name (string) - same as key
aliases (list of strings) - aliases to the object. Will be saved to database as AliasDB entries but returned as strings.
dbref (int, read-only) - unique #id-number. Also "id" can be used.
dbobj (Object, read-only) - link to database model. dbobj.typeclass points back to this class
@ -465,12 +465,13 @@ class Object(TypeClass):
"""
pass
def at_pre_puppet(self, player):
def at_pre_puppet(self, player, sessid=None):
"""
Called just before a Player connects to this object
to puppet it.
player - connecting player object
sessid - session id controlling the connection
"""
pass
@ -488,13 +489,14 @@ class Object(TypeClass):
"""
pass
def at_post_unpuppet(self, player):
def at_post_unpuppet(self, player, sessid=None):
"""
Called just after the Player successfully disconnected
from this object, severing all connections.
player - the player object that just disconnected from
this object.
sessid - session id controlling the connection
"""
pass
@ -755,7 +757,7 @@ class Object(TypeClass):
return message
#
# Base Player object
# Base Character object
#
class Character(Object):
@ -793,7 +795,7 @@ class Character(Object):
"Default is to look around after a move."
self.execute_cmd('look')
def at_pre_puppet(self, player):
def at_pre_puppet(self, player, sessid=None):
"""
This recovers the character again after having been "stoved away" at the unpuppet
"""
@ -809,7 +811,7 @@ class Character(Object):
self.location.msg_contents("%s has entered the game." % self.name, exclude=[self])
self.location.at_object_receive(self, self.location)
else:
player.msg("{r%s has no location and no home is set.{n" % self)
player.msg("{r%s has no location and no home is set.{n" % self, sessid=sessid)
def at_post_puppet(self):
"""
@ -820,7 +822,7 @@ class Character(Object):
if self.location:
self.location.msg_contents("%s has entered the game." % self.name, exclude=[self])
def at_post_unpuppet(self, player):
def at_post_unpuppet(self, player, sessid=None):
"""
We stove away the character when the player goes ooc/logs off, otherwise the character object will
remain in the room also after the player logged off ("headless", so to say).
@ -836,14 +838,13 @@ class Character(Object):
class Room(Object):
"""
This is the base room object. It's basically
like any Object except its location is None.
This is the base room object. It's just like any Object except its
location is None.
"""
def basetype_setup(self):
"""
Simple setup, shown as an example
(since default is None anyway)
"""
super(Room, self).basetype_setup()
@ -852,19 +853,18 @@ class Room(Object):
self.location = None
#
# Exits
# Base Exit object
#
class Exit(Object):
"""
This is the base exit object - it connects a location to
another. This is done by the exit assigning a "command" on itself
with the same name as the exit object (to do this we need to
remember to re-create the command when the object is cached since it must be
This is the base exit object - it connects a location to another.
This is done by the exit assigning a "command" on itself with the
same name as the exit object (to do this we need to remember to
re-create the command when the object is cached since it must be
created dynamically depending on what the exit is called). This
command (which has a high priority) will thus allow us to traverse exits
simply by giving the exit-object's name on its own.
command (which has a high priority) will thus allow us to traverse
exits simply by giving the exit-object's name on its own.
"""
# Helper classes and methods to implement the Exit. These need not
@ -909,13 +909,12 @@ class Exit(Object):
self.obj.at_failed_traverse(self.caller)
# create an exit command.
cmd = ExitCommand()
cmd.key = exidbobj.db_key.strip().lower()
cmd.obj = exidbobj
cmd.aliases = exidbobj.aliases
cmd.locks = str(exidbobj.locks)
cmd.destination = exidbobj.db_destination
cmd.auto_help = False
cmd = ExitCommand(key=exidbobj.db_key.strip().lower(),
aliases=exidbobj.aliases,
locks=str(exidbobj.locks),
auto_help=False,
destination=exidbobj.db_destination,
obj=exidbobj)
# create a cmdset
exit_cmdset = cmdset.CmdSet(None)
exit_cmdset.key = '_exitset'