mirror of
https://github.com/evennia/evennia.git
synced 2026-03-23 00:06:30 +01:00
Cleaning some unnecessary whitespace, overall cleanup of various source codes.
This commit is contained in:
parent
d4c97d7df8
commit
c0322c9eae
27 changed files with 1342 additions and 1318 deletions
|
|
@ -1,6 +1,6 @@
|
|||
#
|
||||
# This sets up how models are displayed
|
||||
# in the web admin interface.
|
||||
# This sets up how models are displayed
|
||||
# in the web admin interface.
|
||||
#
|
||||
|
||||
from django import forms
|
||||
|
|
@ -35,38 +35,38 @@ class ObjectCreateForm(forms.ModelForm):
|
|||
db_typeclass_path = forms.CharField(label="Typeclass",initial="Change to (for example) %s or %s." % (settings.BASE_OBJECT_TYPECLASS, settings.BASE_CHARACTER_TYPECLASS),
|
||||
widget=forms.TextInput(attrs={'size':'78'}),
|
||||
help_text="This defines what 'type' of entity this is. This variable holds a Python path to a module with a valid Evennia Typeclass. If you are creating a Character you should use the typeclass defined by settings.BASE_CHARACTER_TYPECLASS or one derived from that.")
|
||||
db_permissions = forms.CharField(label="Permissions",
|
||||
initial=settings.PERMISSION_PLAYER_DEFAULT,
|
||||
db_permissions = forms.CharField(label="Permissions",
|
||||
initial=settings.PERMISSION_PLAYER_DEFAULT,
|
||||
required=False,
|
||||
widget=forms.TextInput(attrs={'size':'78'}),
|
||||
help_text="a comma-separated list of text strings checked by certain locks. They are mainly of use for Character objects. Character permissions overload permissions defined on a controlling Player. Most objects normally don't have any permissions defined.")
|
||||
db_cmdset_storage = forms.CharField(label="CmdSet",
|
||||
db_cmdset_storage = forms.CharField(label="CmdSet",
|
||||
initial=settings.CMDSET_DEFAULT,
|
||||
required=False,
|
||||
widget=forms.TextInput(attrs={'size':'78'}),
|
||||
help_text="Most non-character objects don't need a cmdset and can leave this field blank.")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ObjectEditForm(ObjectCreateForm):
|
||||
"Form used for editing. Extends the create one with more fields"
|
||||
|
||||
db_lock_storage = forms.CharField(label="Locks",
|
||||
required=False,
|
||||
db_lock_storage = forms.CharField(label="Locks",
|
||||
required=False,
|
||||
widget=forms.Textarea(attrs={'cols':'100', 'rows':'2'}),
|
||||
help_text="In-game lock definition string. If not given, defaults will be used. This string should be on the form <i>type:lockfunction(args);type2:lockfunction2(args);...")
|
||||
|
||||
|
||||
class ObjectDBAdmin(admin.ModelAdmin):
|
||||
|
||||
class ObjectDBAdmin(admin.ModelAdmin):
|
||||
|
||||
list_display = ('id', 'db_key', 'db_location', 'db_player', 'db_typeclass_path')
|
||||
list_display_links = ('id', 'db_key')
|
||||
ordering = ['db_player', 'db_typeclass_path', 'id']
|
||||
search_fields = ['^db_key', 'db_typeclass_path']
|
||||
|
||||
save_as = True
|
||||
|
||||
save_as = True
|
||||
save_on_top = True
|
||||
list_select_related = True
|
||||
list_select_related = True
|
||||
list_filter = ('db_permissions', 'db_location', 'db_typeclass_path')
|
||||
|
||||
# editing fields setup
|
||||
|
|
@ -74,7 +74,7 @@ class ObjectDBAdmin(admin.ModelAdmin):
|
|||
form = ObjectEditForm
|
||||
fieldsets = (
|
||||
(None, {
|
||||
'fields': (('db_key','db_typeclass_path'), ('db_permissions', 'db_lock_storage'),
|
||||
'fields': (('db_key','db_typeclass_path'), ('db_permissions', 'db_lock_storage'),
|
||||
('db_location', 'db_home'), 'db_destination','db_cmdset_storage'
|
||||
)}),
|
||||
)
|
||||
|
|
@ -88,7 +88,7 @@ class ObjectDBAdmin(admin.ModelAdmin):
|
|||
add_form = ObjectCreateForm
|
||||
add_fieldsets = (
|
||||
(None, {
|
||||
'fields': (('db_key','db_typeclass_path'), 'db_permissions',
|
||||
'fields': (('db_key','db_typeclass_path'), 'db_permissions',
|
||||
('db_location', 'db_home'), 'db_destination','db_cmdset_storage'
|
||||
)}),
|
||||
)
|
||||
|
|
@ -116,8 +116,8 @@ class ObjectDBAdmin(admin.ModelAdmin):
|
|||
obj = obj.typeclass
|
||||
obj.basetype_setup()
|
||||
obj.basetype_posthook_setup()
|
||||
obj.at_object_creation()
|
||||
obj.at_object_creation()
|
||||
obj.at_init()
|
||||
|
||||
|
||||
|
||||
admin.site.register(ObjectDB, ObjectDBAdmin)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Custom manager for Objects.
|
|||
"""
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models.fields import exceptions
|
||||
from django.db.models.fields import exceptions
|
||||
from src.typeclasses.managers import TypedObjectManager
|
||||
from src.typeclasses.managers import returns_typeclass, returns_typeclass_list
|
||||
from src.utils import utils
|
||||
|
|
@ -17,11 +17,11 @@ AT_MULTIMATCH_INPUT = utils.mod_import(*settings.SEARCH_AT_MULTIMATCH_INPUT.rspl
|
|||
class ObjectManager(TypedObjectManager):
|
||||
"""
|
||||
This ObjectManager implementes methods for searching
|
||||
and manipulating Objects directly from the database.
|
||||
and manipulating Objects directly from the database.
|
||||
|
||||
Evennia-specific search methods (will return Typeclasses or
|
||||
lists of Typeclasses, whereas Django-general methods will return
|
||||
Querysets or database objects).
|
||||
Querysets or database objects).
|
||||
|
||||
dbref (converter)
|
||||
dbref_search
|
||||
|
|
@ -41,19 +41,19 @@ class ObjectManager(TypedObjectManager):
|
|||
copy_object
|
||||
|
||||
"""
|
||||
|
||||
|
||||
#
|
||||
# ObjectManager Get methods
|
||||
# ObjectManager Get methods
|
||||
#
|
||||
|
||||
# user/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.
|
||||
returns just one result or None.
|
||||
|
||||
user - may be a user object or user id.
|
||||
"""
|
||||
|
|
@ -61,26 +61,26 @@ class ObjectManager(TypedObjectManager):
|
|||
uid = int(user)
|
||||
except TypeError:
|
||||
try:
|
||||
uid = user.id
|
||||
uid = user.id
|
||||
except:
|
||||
return None
|
||||
try:
|
||||
return self.get(db_player__user__id=uid)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
# This returns typeclass since get_object_with_user and get_dbref does.
|
||||
|
||||
# This returns typeclass since get_object_with_user and get_dbref does.
|
||||
def get_object_with_player(self, search_string):
|
||||
"""
|
||||
Search for an object based on its player's name or dbref.
|
||||
"""
|
||||
Search for an object based on its player's name or dbref.
|
||||
This search
|
||||
is sometimes initiated by appending a * to the beginning of
|
||||
the search criterion (e.g. in local_and_global_search).
|
||||
the search criterion (e.g. in local_and_global_search).
|
||||
search_string: (string) The name or dbref to search for.
|
||||
"""
|
||||
search_string = to_unicode(search_string).lstrip('*')
|
||||
search_string = to_unicode(search_string).lstrip('*')
|
||||
dbref = self.dbref(search_string)
|
||||
if not dbref:
|
||||
if not dbref:
|
||||
# not a dbref. Search by name.
|
||||
player_matches = User.objects.filter(username__iexact=search_string)
|
||||
if player_matches:
|
||||
|
|
@ -105,17 +105,17 @@ class ObjectManager(TypedObjectManager):
|
|||
from src.objects.models import ObjAttribute
|
||||
lstring = ""
|
||||
if location:
|
||||
lstring = ", db_obj__db_location=location"
|
||||
lstring = ", db_obj__db_location=location"
|
||||
attrs = eval("ObjAttribute.objects.filter(db_key=attribute_name%s)" % lstring)
|
||||
return [attr.obj for attr in attrs]
|
||||
|
||||
|
||||
@returns_typeclass_list
|
||||
def get_objs_with_attr_match(self, attribute_name, attribute_value, location=None, exact=False):
|
||||
"""
|
||||
Returns all objects having the valid
|
||||
Returns all objects having the valid
|
||||
attrname set to the given value. Note that no conversion is made
|
||||
to attribute_value, and so it can accept also non-strings.
|
||||
"""
|
||||
"""
|
||||
from src.objects.models import ObjAttribute
|
||||
lstring = ""
|
||||
if location:
|
||||
|
|
@ -123,27 +123,27 @@ class ObjectManager(TypedObjectManager):
|
|||
attrs = eval("ObjAttribute.objects.filter(db_key=attribute_name%s)" % lstring)
|
||||
# since attribute values are pickled in database, we cannot search directly, but
|
||||
# must loop through the results. .
|
||||
if exact:
|
||||
if exact:
|
||||
return [attr.obj for attr in attrs if attribute_value == attr.value]
|
||||
else:
|
||||
return [attr.obj for attr in attrs if to_unicode(attribute_value) in str(attr.value)]
|
||||
|
||||
|
||||
@returns_typeclass_list
|
||||
def get_objs_with_db_property(self, property_name, location=None):
|
||||
"""
|
||||
Returns all objects having a given db field property.
|
||||
property_name = search string
|
||||
property_name = search string
|
||||
location - actual location object to restrict to
|
||||
|
||||
"""
|
||||
lstring = ""
|
||||
if location:
|
||||
lstring = ".filter(db_location=location)"
|
||||
lstring = ".filter(db_location=location)"
|
||||
try:
|
||||
return eval("self.exclude(db_%s=None)%s" % (property_name, lstring))
|
||||
except exceptions.FieldError:
|
||||
return []
|
||||
|
||||
|
||||
@returns_typeclass_list
|
||||
def get_objs_with_db_property_match(self, property_name, property_value, location, exact=False):
|
||||
"""
|
||||
|
|
@ -165,7 +165,7 @@ class ObjectManager(TypedObjectManager):
|
|||
def get_objs_with_key_or_alias(self, ostring, location, exact=False):
|
||||
"""
|
||||
Returns objects based on key or alias match
|
||||
"""
|
||||
"""
|
||||
lstring_key, lstring_alias, estring = "", "", "icontains"
|
||||
if location:
|
||||
lstring_key = ", db_location=location"
|
||||
|
|
@ -181,7 +181,7 @@ class ObjectManager(TypedObjectManager):
|
|||
return matches
|
||||
|
||||
# main search methods and helper functions
|
||||
|
||||
|
||||
@returns_typeclass_list
|
||||
def get_contents(self, location, excludeobj=None):
|
||||
"""
|
||||
|
|
@ -192,31 +192,40 @@ class ObjectManager(TypedObjectManager):
|
|||
if excludeobj:
|
||||
estring = ".exclude(db_key=excludeobj)"
|
||||
return eval("self.filter(db_location__id=location.id)%s" % estring)
|
||||
|
||||
|
||||
@returns_typeclass_list
|
||||
def object_search(self, ostring, caller=None,
|
||||
global_search=False,
|
||||
global_search=False,
|
||||
attribute_name=None, location=None):
|
||||
"""
|
||||
Search as an object and return results. The result is always an Object.
|
||||
If * is appended (player search, a Character controlled by this Player
|
||||
is looked for. The Character is returned, not the Player. Use player_search
|
||||
to find Player objects. Always returns a list.
|
||||
|
||||
|
||||
Arguments:
|
||||
ostring: (string) The string to compare names against.
|
||||
Can be a dbref. If name is appended by *, a player is searched for.
|
||||
caller: (Object) The object performing the search.
|
||||
global_search: Search all objects, not just the current location/inventory
|
||||
attribute_name: (string) Which attribute to search in each object.
|
||||
If None, the default 'key' attribute is used.
|
||||
location: If None, character.location will be used.
|
||||
Can be a dbref. If name is appended by *, a player is searched for.
|
||||
caller: (Object) The optional object performing the search.
|
||||
global_search (bool). Defaults to False. If a caller is defined, search will
|
||||
be restricted to the contents of caller.location unless global_search
|
||||
is True. If no caller is given (or the caller has no location), a
|
||||
global search is assumed automatically.
|
||||
attribute_name: (string) Which object attribute to match ostring against. If not
|
||||
set, the "key" and "aliases" properties are searched in order.
|
||||
location (Object): If set, this location's contents will be used to limit the search instead
|
||||
of the callers. global_search will override this argument
|
||||
|
||||
Returns:
|
||||
A list of matching objects (or a list with one unique match)
|
||||
|
||||
"""
|
||||
ostring = to_unicode(ostring, force_string=True)
|
||||
|
||||
if not ostring:
|
||||
return []
|
||||
return []
|
||||
|
||||
# Easiest case - dbref matching (always exact)
|
||||
# Easiest case - dbref matching (always exact)
|
||||
dbref = self.dbref(ostring)
|
||||
if dbref:
|
||||
dbref_match = self.dbref_search(dbref)
|
||||
|
|
@ -229,12 +238,12 @@ class ObjectManager(TypedObjectManager):
|
|||
# Test some common self-references
|
||||
|
||||
if location and ostring == 'here':
|
||||
return [location]
|
||||
return [location]
|
||||
if caller and ostring in ('me', 'self'):
|
||||
return [caller]
|
||||
if caller and ostring in ('*me', '*self'):
|
||||
return [caller]
|
||||
|
||||
if caller and ostring in ('*me', '*self'):
|
||||
return [caller]
|
||||
|
||||
# Test if we are looking for an object controlled by a
|
||||
# specific player
|
||||
|
||||
|
|
@ -244,24 +253,24 @@ class ObjectManager(TypedObjectManager):
|
|||
player_match = self.get_object_with_player(ostring)
|
||||
if player_match is not None:
|
||||
return [player_match]
|
||||
|
||||
|
||||
# Search for keys, aliases or other attributes
|
||||
|
||||
|
||||
search_locations = [None] # this means a global search
|
||||
if not global_search and location:
|
||||
# Test if we are referring to the current room
|
||||
if location and (ostring.lower() == location.key.lower()
|
||||
if location and (ostring.lower() == location.key.lower()
|
||||
or ostring.lower() in [alias.lower() for alias in location.aliases]):
|
||||
return [location]
|
||||
# otherwise, setup the locations to search in
|
||||
# otherwise, setup the locations to search in
|
||||
search_locations = [location]
|
||||
if caller:
|
||||
search_locations.append(caller)
|
||||
|
||||
|
||||
def local_and_global_search(ostring, exact=False):
|
||||
"Helper method for searching objects"
|
||||
matches = []
|
||||
for location in search_locations:
|
||||
"Helper method for searching objects"
|
||||
matches = []
|
||||
for location in search_locations:
|
||||
if attribute_name:
|
||||
# Attribute/property search. First, search for db_<attrname> matches on the model
|
||||
matches.extend(self.get_objs_with_db_property_match(attribute_name, ostring, location, exact))
|
||||
|
|
@ -269,14 +278,14 @@ class ObjectManager(TypedObjectManager):
|
|||
# Next, try Attribute matches
|
||||
matches.extend(self.get_objs_with_attr_match(attribute_name, ostring, location, exact))
|
||||
else:
|
||||
# No attribute/property named. Do a normal key/alias-search
|
||||
# No attribute/property named. Do a normal key/alias-search
|
||||
matches.extend(self.get_objs_with_key_or_alias(ostring, location, exact))
|
||||
return matches
|
||||
|
||||
# Search through all possibilities.
|
||||
|
||||
match_number = None
|
||||
matches = local_and_global_search(ostring, exact=True)
|
||||
matches = local_and_global_search(ostring, exact=True)
|
||||
if not matches:
|
||||
# if we have no match, check if we are dealing with an "N-keyword" query - if so, strip it.
|
||||
match_number, ostring = AT_MULTIMATCH_INPUT(ostring)
|
||||
|
|
@ -289,7 +298,7 @@ class ObjectManager(TypedObjectManager):
|
|||
elif len(matches) > 1:
|
||||
# multiple matches already. Run a fuzzy search. This catches partial matches (suggestions)
|
||||
matches = local_and_global_search(ostring, exact=False)
|
||||
|
||||
|
||||
# deal with the result
|
||||
if len(matches) > 1 and match_number != None:
|
||||
# We have multiple matches, but a N-type match number is available to separate them.
|
||||
|
|
@ -299,21 +308,21 @@ class ObjectManager(TypedObjectManager):
|
|||
pass
|
||||
# This is always a list.
|
||||
return matches
|
||||
|
||||
|
||||
#
|
||||
# ObjectManager Copy method
|
||||
#
|
||||
|
||||
def copy_object(self, original_object, new_key=None,
|
||||
new_location=None, new_player=None, new_home=None,
|
||||
new_location=None, new_player=None, new_home=None,
|
||||
new_permissions=None, new_locks=None, new_aliases=None, new_destination=None):
|
||||
"""
|
||||
Create and return a new object as a copy of the original object. All will
|
||||
be identical to the original except for the arguments given specifically
|
||||
be identical to the original except for the arguments given specifically
|
||||
to this method.
|
||||
|
||||
original_object (obj) - the object to make a copy from
|
||||
new_key (str) - name the copy differently from the original.
|
||||
new_key (str) - name the copy differently from the original.
|
||||
new_location (obj) - if not None, change the location
|
||||
new_home (obj) - if not None, change the Home
|
||||
new_aliases (list of strings) - if not None, change object aliases.
|
||||
|
|
@ -322,7 +331,7 @@ class ObjectManager(TypedObjectManager):
|
|||
|
||||
# get all the object's stats
|
||||
typeclass_path = original_object.typeclass_path
|
||||
if not new_key:
|
||||
if not new_key:
|
||||
new_key = original_object.key
|
||||
if not new_location:
|
||||
new_location = original_object.location
|
||||
|
|
@ -331,36 +340,36 @@ class ObjectManager(TypedObjectManager):
|
|||
if not new_player:
|
||||
new_player = original_object.player
|
||||
if not new_aliases:
|
||||
new_aliases = original_object.aliases
|
||||
new_aliases = original_object.aliases
|
||||
if not new_locks:
|
||||
new_locks = original_object.db_lock_storage
|
||||
if not new_permissions:
|
||||
new_permissions = original_object.permissions
|
||||
new_permissions = original_object.permissions
|
||||
if not new_destination:
|
||||
new_destination = original_object.destination
|
||||
|
||||
# create new object
|
||||
from src.utils import create
|
||||
|
||||
# create new object
|
||||
from src.utils import create
|
||||
from src.scripts.models import ScriptDB
|
||||
new_object = create.create_object(typeclass_path, key=new_key, location=new_location,
|
||||
home=new_home, player=new_player, permissions=new_permissions,
|
||||
home=new_home, player=new_player, permissions=new_permissions,
|
||||
locks=new_locks, aliases=new_aliases, destination=new_destination)
|
||||
if not new_object:
|
||||
return None
|
||||
return None
|
||||
|
||||
# copy over all attributes from old to new.
|
||||
# copy over all attributes from old to new.
|
||||
for attr in original_object.get_all_attributes():
|
||||
new_object.set_attribute(attr.key, attr.value)
|
||||
|
||||
# copy over all cmdsets, if any
|
||||
# copy over all cmdsets, if any
|
||||
for icmdset, cmdset in enumerate(original_object.cmdset.all()):
|
||||
if icmdset == 0:
|
||||
new_object.cmdset.add_default(cmdset)
|
||||
else:
|
||||
new_object.cmdset.add(cmdset)
|
||||
|
||||
# copy over all scripts, if any
|
||||
# copy over all scripts, if any
|
||||
for script in original_object.scripts.all():
|
||||
ScriptDB.objects.copy_script(script, new_obj=new_object.dbobj)
|
||||
|
||||
|
||||
return new_object
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"""
|
||||
This module defines the database models for all in-game objects, that
|
||||
is, all objects that has an actual existence in-game.
|
||||
is, all objects that has an actual existence in-game.
|
||||
|
||||
Each database object is 'decorated' with a 'typeclass', a normal
|
||||
python class that implements all the various logics needed by the game
|
||||
|
|
@ -66,11 +66,11 @@ class Alias(SharedMemoryModel):
|
|||
This model holds a range of alternate names for an object.
|
||||
These are intrinsic properties of the object. The split
|
||||
is so as to allow for effective global searches also by
|
||||
alias.
|
||||
"""
|
||||
alias.
|
||||
"""
|
||||
db_key = models.CharField('alias', max_length=255, db_index=True)
|
||||
db_obj = models.ForeignKey("ObjectDB", verbose_name='object')
|
||||
|
||||
|
||||
class Meta:
|
||||
"Define Django meta options"
|
||||
verbose_name = "Object alias"
|
||||
|
|
@ -79,8 +79,8 @@ class Alias(SharedMemoryModel):
|
|||
return u"%s" % self.db_key
|
||||
def __str__(self):
|
||||
return str(self.db_key)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
|
|
@ -90,11 +90,11 @@ class Alias(SharedMemoryModel):
|
|||
|
||||
class ObjectNick(TypeNick):
|
||||
"""
|
||||
|
||||
The default nick types used by Evennia are:
|
||||
|
||||
The default nick types used by Evennia are:
|
||||
inputline (default) - match against all input
|
||||
player - match against player searches
|
||||
obj - match against object searches
|
||||
obj - match against object searches
|
||||
channel - used to store own names for channels
|
||||
"""
|
||||
db_obj = models.ForeignKey("ObjectDB", verbose_name='object')
|
||||
|
|
@ -108,7 +108,7 @@ class ObjectNick(TypeNick):
|
|||
class ObjectNickHandler(TypeNickHandler):
|
||||
"""
|
||||
Handles nick access and setting. Accessed through ObjectDB.nicks
|
||||
"""
|
||||
"""
|
||||
NickClass = ObjectNick
|
||||
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ class ObjectDB(TypedObject):
|
|||
|
||||
Note that the base objectdb is very simple, with
|
||||
few defined fields. Use attributes to extend your
|
||||
type class with new database-stored variables.
|
||||
type class with new database-stored variables.
|
||||
|
||||
The TypedObject supplies the following (inherited) properties:
|
||||
key - main name
|
||||
|
|
@ -134,11 +134,11 @@ class ObjectDB(TypedObject):
|
|||
typeclass_path - the path to the decorating typeclass
|
||||
typeclass - auto-linked typeclass
|
||||
date_created - time stamp of object creation
|
||||
permissions - perm strings
|
||||
permissions - perm strings
|
||||
locks - lock definitions (handler)
|
||||
dbref - #id of object
|
||||
dbref - #id of object
|
||||
db - persistent attribute storage
|
||||
ndb - non-persistent attribute storage
|
||||
ndb - non-persistent attribute storage
|
||||
|
||||
The ObjectDB adds the following properties:
|
||||
player - optional connected player
|
||||
|
|
@ -148,7 +148,7 @@ class ObjectDB(TypedObject):
|
|||
scripts - scripts assigned to object (handler from typeclass)
|
||||
cmdset - active cmdset on object (handler from typeclass)
|
||||
aliases - aliases for this object (property)
|
||||
nicks - nicknames for *other* things in Evennia (handler)
|
||||
nicks - nicknames for *other* things in Evennia (handler)
|
||||
sessions - sessions connected to this object (see also player)
|
||||
has_player - bool if an active player is currently connected
|
||||
contents - other objects having this object as location
|
||||
|
|
@ -160,7 +160,7 @@ class ObjectDB(TypedObject):
|
|||
#
|
||||
#
|
||||
# inherited fields (from TypedObject):
|
||||
# db_key (also 'name' works), db_typeclass_path, db_date_created,
|
||||
# db_key (also 'name' works), db_typeclass_path, db_date_created,
|
||||
# db_permissions
|
||||
#
|
||||
# These databse fields (including the inherited ones) are all set
|
||||
|
|
@ -168,11 +168,11 @@ class ObjectDB(TypedObject):
|
|||
# but withtout the db_* prefix.
|
||||
|
||||
# If this is a character object, the player is connected here.
|
||||
db_player = models.ForeignKey("players.PlayerDB", blank=True, null=True, verbose_name='player',
|
||||
help_text='a Player connected to this object, if any.')
|
||||
db_player = models.ForeignKey("players.PlayerDB", blank=True, null=True, verbose_name='player',
|
||||
help_text='a Player connected to this object, if any.')
|
||||
# The location in the game world. Since this one is likely
|
||||
# to change often, we set this with the 'location' property
|
||||
# to transparently handle Typeclassing.
|
||||
# to transparently handle Typeclassing.
|
||||
db_location = models.ForeignKey('self', related_name="locations_set",db_index=True,
|
||||
blank=True, null=True, verbose_name='game location')
|
||||
# a safety location, this usually don't change much.
|
||||
|
|
@ -193,24 +193,24 @@ class ObjectDB(TypedObject):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"Parent must be initialized first."
|
||||
TypedObject.__init__(self, *args, **kwargs)
|
||||
# handlers
|
||||
TypedObject.__init__(self, *args, **kwargs)
|
||||
# handlers
|
||||
self.cmdset = CmdSetHandler(self)
|
||||
self.cmdset.update(init_mode=True)
|
||||
self.scripts = ScriptHandler(self)
|
||||
self.nicks = ObjectNickHandler(self)
|
||||
self.nicks = ObjectNickHandler(self)
|
||||
# store the attribute class
|
||||
|
||||
|
||||
# Wrapper properties to easily set database fields. These are
|
||||
# @property decorators that allows to access these fields using
|
||||
# normal python operations (without having to remember to save()
|
||||
# etc). So e.g. a property 'attr' has a get/set/del decorator
|
||||
# defined that allows the user to do self.attr = value,
|
||||
# value = self.attr and del self.attr respectively (where self
|
||||
# defined that allows the user to do self.attr = value,
|
||||
# value = self.attr and del self.attr respectively (where self
|
||||
# is the object in question).
|
||||
|
||||
# aliases property (wraps (db_aliases)
|
||||
#@property
|
||||
#@property
|
||||
def aliases_get(self):
|
||||
"Getter. Allows for value = self.aliases"
|
||||
try:
|
||||
|
|
@ -218,10 +218,10 @@ class ObjectDB(TypedObject):
|
|||
except AttributeError:
|
||||
aliases = list(Alias.objects.filter(db_obj=self).values_list("db_key", flat=True))
|
||||
SA(self, "_cached_aliases", aliases)
|
||||
return aliases
|
||||
return aliases
|
||||
#@aliases.setter
|
||||
def aliases_set(self, aliases):
|
||||
"Setter. Allows for self.aliases = value"
|
||||
"Setter. Allows for self.aliases = value"
|
||||
for alias in make_iter(aliases):
|
||||
new_alias = Alias(db_key=alias, db_obj=self)
|
||||
new_alias.save()
|
||||
|
|
@ -258,121 +258,121 @@ class ObjectDB(TypedObject):
|
|||
player = property(player_get, player_set, player_del)
|
||||
|
||||
# location property (wraps db_location)
|
||||
#@property
|
||||
#@property
|
||||
def location_get(self):
|
||||
"Getter. Allows for value = self.location."
|
||||
loc = get_cache(self, "location")
|
||||
if loc:
|
||||
return loc.typeclass
|
||||
return None
|
||||
return None
|
||||
#@location.setter
|
||||
def location_set(self, location):
|
||||
"Setter. Allows for self.location = location"
|
||||
try:
|
||||
if location == None or type(location) == ObjectDB:
|
||||
# location is None or a valid object
|
||||
loc = location
|
||||
loc = location
|
||||
elif ObjectDB.objects.dbref(location):
|
||||
# location is a dbref; search
|
||||
loc = ObjectDB.objects.dbref_search(location)
|
||||
if loc and hasattr(loc,'dbobj'):
|
||||
loc = loc.dbobj
|
||||
else:
|
||||
loc = location.dbobj
|
||||
else:
|
||||
loc = location.dbobj
|
||||
loc = location.dbobj
|
||||
else:
|
||||
loc = location.dbobj
|
||||
set_cache(self, "location", loc)
|
||||
except Exception:
|
||||
string = "Cannot set location: "
|
||||
string += "%s is not a valid location."
|
||||
string += "%s is not a valid location."
|
||||
self.msg(string % location)
|
||||
logger.log_trace(string)
|
||||
raise
|
||||
raise
|
||||
#@location.deleter
|
||||
def location_del(self):
|
||||
"Deleter. Allows for del self.location"
|
||||
self.db_location = None
|
||||
self.db_location = None
|
||||
self.save()
|
||||
del_cache()
|
||||
location = property(location_get, location_set, location_del)
|
||||
|
||||
# home property (wraps db_home)
|
||||
#@property
|
||||
#@property
|
||||
def home_get(self):
|
||||
"Getter. Allows for value = self.home"
|
||||
home = get_cache(self, "home")
|
||||
if home:
|
||||
return home.typeclass
|
||||
return None
|
||||
return None
|
||||
#@home.setter
|
||||
def home_set(self, home):
|
||||
"Setter. Allows for self.home = value"
|
||||
try:
|
||||
if home == None or type(home) == ObjectDB:
|
||||
hom = home
|
||||
hom = home
|
||||
elif ObjectDB.objects.dbref(home):
|
||||
hom = ObjectDB.objects.dbref_search(home)
|
||||
if hom and hasattr(hom,'dbobj'):
|
||||
hom = hom.dbobj
|
||||
else:
|
||||
hom = home.dbobj
|
||||
else:
|
||||
hom = home.dbobj
|
||||
hom = home.dbobj
|
||||
else:
|
||||
hom = home.dbobj
|
||||
set_cache(self, "home", hom)
|
||||
except Exception:
|
||||
string = "Cannot set home: "
|
||||
string += "%s is not a valid home."
|
||||
string += "%s is not a valid home."
|
||||
self.msg(string % home)
|
||||
logger.log_trace(string)
|
||||
#raise
|
||||
#raise
|
||||
#@home.deleter
|
||||
def home_del(self):
|
||||
"Deleter. Allows for del self.home."
|
||||
self.db_home = None
|
||||
self.db_home = None
|
||||
self.save()
|
||||
del_cache(self, "home")
|
||||
home = property(home_get, home_set, home_del)
|
||||
|
||||
# destination property (wraps db_destination)
|
||||
#@property
|
||||
#@property
|
||||
def destination_get(self):
|
||||
"Getter. Allows for value = self.destination."
|
||||
dest = get_cache(self, "destination")
|
||||
if dest:
|
||||
return dest.typeclass
|
||||
return None
|
||||
return None
|
||||
#@destination.setter
|
||||
def destination_set(self, destination):
|
||||
"Setter. Allows for self.destination = destination"
|
||||
try:
|
||||
if destination == None or type(destination) == ObjectDB:
|
||||
# destination is None or a valid object
|
||||
dest = destination
|
||||
dest = destination
|
||||
elif ObjectDB.objects.dbref(destination):
|
||||
# destination is a dbref; search
|
||||
dest = ObjectDB.objects.dbref_search(destination)
|
||||
if dest and hasattr(dest,'dbobj'):
|
||||
dest = dest.dbobj
|
||||
else:
|
||||
dest = destination.dbobj
|
||||
else:
|
||||
dest = destination.dbobj
|
||||
dest = destination.dbobj
|
||||
else:
|
||||
dest = destination.dbobj
|
||||
set_cache(self, "destination", dest)
|
||||
except Exception:
|
||||
string = "Cannot set destination: "
|
||||
string += "%s is not a valid destination."
|
||||
string += "%s is not a valid destination."
|
||||
self.msg(string % destination)
|
||||
logger.log_trace(string)
|
||||
raise
|
||||
raise
|
||||
#@destination.deleter
|
||||
def destination_del(self):
|
||||
"Deleter. Allows for del self.destination"
|
||||
self.db_destination = None
|
||||
self.db_destination = None
|
||||
self.save()
|
||||
del_cache(self, "destination")
|
||||
destination = property(destination_get, destination_set, destination_del)
|
||||
|
||||
# cmdset_storage property.
|
||||
# cmdset_storage property.
|
||||
# This seems very sensitive to caching, so leaving it be for now. /Griatch
|
||||
#@property
|
||||
def cmdset_storage_get(self):
|
||||
|
|
@ -385,7 +385,7 @@ class ObjectDB(TypedObject):
|
|||
"Setter. Allows for self.name = value. Stores as a comma-separated string."
|
||||
value = ",".join(str(val).strip() for val in make_iter(value))
|
||||
self.db_cmdset_storage = value
|
||||
self.save()
|
||||
self.save()
|
||||
#@cmdset_storage.deleter
|
||||
def cmdset_storage_del(self):
|
||||
"Deleter. Allows for del self.name"
|
||||
|
|
@ -400,12 +400,12 @@ class ObjectDB(TypedObject):
|
|||
|
||||
#
|
||||
# ObjectDB class access methods/properties
|
||||
#
|
||||
#
|
||||
|
||||
# this is required to properly handle attributes and typeclass loading.
|
||||
#attribute_model_path = "src.objects.models"
|
||||
#attribute_model_name = "ObjAttribute"
|
||||
typeclass_paths = settings.OBJECT_TYPECLASS_PATHS
|
||||
typeclass_paths = settings.OBJECT_TYPECLASS_PATHS
|
||||
attribute_class = ObjAttribute
|
||||
db_model_name = "objectdb" # used by attributes to safely store objects
|
||||
|
||||
|
|
@ -420,13 +420,13 @@ class ObjectDB(TypedObject):
|
|||
"""
|
||||
Retrieve sessions connected to this object.
|
||||
"""
|
||||
# if the player is not connected, this will simply be an empty list.
|
||||
# if the player is not connected, this will simply be an empty list.
|
||||
if self.player:
|
||||
return self.player.sessions
|
||||
return []
|
||||
sessions = property(sessions_get)
|
||||
|
||||
#@property
|
||||
#@property
|
||||
def has_player_get(self):
|
||||
"""
|
||||
Convenience function for checking if an active player is
|
||||
|
|
@ -436,13 +436,13 @@ class ObjectDB(TypedObject):
|
|||
has_player = property(has_player_get)
|
||||
is_player = property(has_player_get)
|
||||
|
||||
#@property
|
||||
#@property
|
||||
def is_superuser_get(self):
|
||||
"Check if user has a player, and if so, if it is a superuser."
|
||||
return any(self.sessions) and self.player.is_superuser
|
||||
is_superuser = property(is_superuser_get)
|
||||
|
||||
#@property
|
||||
#@property
|
||||
def contents_get(self, exclude=None):
|
||||
"""
|
||||
Returns the contents of this object, i.e. all
|
||||
|
|
@ -461,11 +461,11 @@ class ObjectDB(TypedObject):
|
|||
if exi.destination]
|
||||
exits = property(exits_get)
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Main Search method
|
||||
#
|
||||
|
||||
|
||||
def search(self, ostring,
|
||||
global_search=False,
|
||||
attribute_name=None,
|
||||
|
|
@ -474,49 +474,49 @@ class ObjectDB(TypedObject):
|
|||
"""
|
||||
Perform a standard object search in the database, handling
|
||||
multiple results and lack thereof gracefully.
|
||||
|
||||
|
||||
ostring: (str) The string to match object names against.
|
||||
Obs - To find a player, append * to the
|
||||
start of ostring.
|
||||
start of ostring.
|
||||
global_search: Search all objects, not just the current
|
||||
location/inventory
|
||||
attribute_name: (string) Which attribute to match
|
||||
(if None, uses default 'name')
|
||||
use_nicks : Use nickname replace (off by default)
|
||||
use_nicks : Use nickname replace (off by default)
|
||||
location : If None, use caller's current location
|
||||
ignore_errors : Don't display any error messages even
|
||||
if there are none/multiple matches -
|
||||
just return the result as a list.
|
||||
player : Don't search for an Object but a Player.
|
||||
if there are none/multiple matches -
|
||||
just return the result as a list.
|
||||
player : Don't search for an Object but a Player.
|
||||
This will also find players that don't
|
||||
currently have a character.
|
||||
|
||||
Returns - a unique Object/Player match or None. All error
|
||||
messages are handled by system-commands and the parser-handlers
|
||||
specified in settings.
|
||||
specified in settings.
|
||||
|
||||
Use *<string> to search for objects controlled by a specific
|
||||
player. Note that the object controlled by the player will be
|
||||
returned, not the player object itself. This also means that
|
||||
this will not find Players without a character. Use the keyword
|
||||
player=True to find player objects.
|
||||
|
||||
player=True to find player objects.
|
||||
|
||||
Note - for multiple matches, the engine accepts a number
|
||||
linked to the key in order to separate the matches from
|
||||
each other without showing the dbref explicitly. Default
|
||||
syntax for this is 'N-searchword'. So for example, if there
|
||||
are three objects in the room all named 'ball', you could
|
||||
address the individual ball as '1-ball', '2-ball', '3-ball'
|
||||
etc.
|
||||
etc.
|
||||
"""
|
||||
if use_nicks:
|
||||
if ostring.startswith('*') or player:
|
||||
# player nick replace
|
||||
# player nick replace
|
||||
ostring = self.nicks.get(ostring.lstrip('*'), nick_type="player")
|
||||
if not player:
|
||||
ostring = "*%s" % ostring
|
||||
else:
|
||||
# object nick replace
|
||||
# object nick replace
|
||||
ostring = self.nicks.get(ostring, nick_type="object")
|
||||
|
||||
if player:
|
||||
|
|
@ -525,11 +525,11 @@ class ObjectDB(TypedObject):
|
|||
else:
|
||||
results = PlayerDB.objects.player_search(ostring.lstrip('*'))
|
||||
else:
|
||||
results = ObjectDB.objects.object_search(ostring, caller=self,
|
||||
results = ObjectDB.objects.object_search(ostring, caller=self,
|
||||
global_search=global_search,
|
||||
attribute_name=attribute_name,
|
||||
location=location)
|
||||
|
||||
|
||||
if ignore_errors:
|
||||
return results
|
||||
# this import is cache after the first call.
|
||||
|
|
@ -538,50 +538,50 @@ class ObjectDB(TypedObject):
|
|||
#
|
||||
# Execution/action methods
|
||||
#
|
||||
|
||||
|
||||
def execute_cmd(self, raw_string):
|
||||
"""
|
||||
Do something as this object. This command transparently
|
||||
lets its typeclass execute the command. Evennia also calls
|
||||
this method whenever the player sends a command on the command line.
|
||||
|
||||
Argument:
|
||||
Argument:
|
||||
raw_string (string) - raw command input
|
||||
|
||||
Returns Deferred - this is an asynchronous Twisted object that will
|
||||
not fire until the command has actually finished executing. To overload
|
||||
this one needs to attach callback functions to it, with addCallback(function).
|
||||
this one needs to attach callback functions to it, with addCallback(function).
|
||||
This function will be called with an eventual return value from the command
|
||||
execution.
|
||||
execution.
|
||||
|
||||
This return is not used at all by Evennia by default, but might be useful
|
||||
for coders intending to implement some sort of nested command structure.
|
||||
"""
|
||||
for coders intending to implement some sort of nested command structure.
|
||||
"""
|
||||
# nick replacement - we require full-word matching.
|
||||
|
||||
# do text encoding conversion
|
||||
|
||||
# do text encoding conversion
|
||||
raw_string = to_unicode(raw_string)
|
||||
|
||||
raw_list = raw_string.split(None)
|
||||
raw_list = [" ".join(raw_list[:i+1]) for i in range(len(raw_list)) if raw_list[:i+1]]
|
||||
for nick in ObjectNick.objects.filter(db_obj=self, db_type__in=("inputline","channel")):
|
||||
for nick in ObjectNick.objects.filter(db_obj=self, db_type__in=("inputline","channel")):
|
||||
if nick.db_nick in raw_list:
|
||||
raw_string = raw_string.replace(nick.db_nick, nick.db_real, 1)
|
||||
break
|
||||
raw_string = raw_string.replace(nick.db_nick, nick.db_real, 1)
|
||||
break
|
||||
return cmdhandler.cmdhandler(self.typeclass, raw_string)
|
||||
|
||||
def msg(self, message, from_obj=None, data=None):
|
||||
"""
|
||||
Emits something to any sessions attached to the object.
|
||||
|
||||
|
||||
message (str): The message to send
|
||||
from_obj (obj): object that is sending.
|
||||
data (object): an optional data object that may or may not
|
||||
be used by the protocol.
|
||||
be used by the protocol.
|
||||
"""
|
||||
# This is an important function that must always work.
|
||||
# This is an important function that must always work.
|
||||
# we use a different __getattribute__ to avoid recursive loops.
|
||||
|
||||
|
||||
if object.__getattribute__(self, 'player'):
|
||||
object.__getattribute__(self, 'player').msg(message, from_obj=from_obj, data=data)
|
||||
|
||||
|
|
@ -589,7 +589,7 @@ class ObjectDB(TypedObject):
|
|||
"Deprecated. Alias for msg"
|
||||
logger.log_depmsg("emit_to() is deprecated. Use msg() instead.")
|
||||
self.msg(message, from_obj, data)
|
||||
|
||||
|
||||
def msg_contents(self, message, exclude=None, from_obj=None, data=None):
|
||||
"""
|
||||
Emits something to all objects inside an object.
|
||||
|
|
@ -608,7 +608,7 @@ class ObjectDB(TypedObject):
|
|||
"Deprecated. Alias for msg_contents"
|
||||
logger.log_depmsg("emit_to_contents() is deprecated. Use msg_contents() instead.")
|
||||
self.msg_contents(message, exclude=exclude, from_obj=from_obj, data=data)
|
||||
|
||||
|
||||
def move_to(self, destination, quiet=False,
|
||||
emit_to_obj=None, use_destination=True):
|
||||
"""
|
||||
|
|
@ -618,19 +618,19 @@ class ObjectDB(TypedObject):
|
|||
exit object (i.e. it has "destination"!=None), the move_to will
|
||||
happen to this destination and -not- into the exit object itself, unless
|
||||
use_destination=False. Note that no lock checks are done by this function,
|
||||
such things are assumed to have been handled before calling move_to.
|
||||
|
||||
such things are assumed to have been handled before calling move_to.
|
||||
|
||||
destination: (Object) Reference to the object to move to. This
|
||||
can also be an exit object, in which case the destination
|
||||
property is used as destination.
|
||||
property is used as destination.
|
||||
quiet: (bool) If true, don't emit left/arrived messages.
|
||||
emit_to_obj: (Object) object to receive error messages
|
||||
use_destination (bool): Default is for objects to use the "destination" property
|
||||
of destinations as the target to move to. Turning off this
|
||||
keyword allows objects to move "inside" exit objects.
|
||||
keyword allows objects to move "inside" exit objects.
|
||||
|
||||
Returns True/False depending on if there were problems with the move. This method
|
||||
may also return various error messages to the emit_to_obj.
|
||||
may also return various error messages to the emit_to_obj.
|
||||
"""
|
||||
def logerr(string=""):
|
||||
trc = traceback.format_exc()
|
||||
|
|
@ -644,7 +644,7 @@ class ObjectDB(TypedObject):
|
|||
|
||||
if not destination:
|
||||
emit_to_obj.msg("The destination doesn't exist.")
|
||||
return
|
||||
return
|
||||
if destination.destination:
|
||||
# traverse exits
|
||||
destination = destination.destination
|
||||
|
|
@ -658,8 +658,8 @@ class ObjectDB(TypedObject):
|
|||
#emit_to_obj.msg(errtxt % "at_before_move()")
|
||||
#logger.log_trace()
|
||||
return False
|
||||
|
||||
# Save the old location
|
||||
|
||||
# Save the old location
|
||||
source_location = self.location
|
||||
if not source_location:
|
||||
# there was some error in placing this room.
|
||||
|
|
@ -678,16 +678,16 @@ class ObjectDB(TypedObject):
|
|||
#emit_to_obj.msg(errtxt % "at_object_leave()")
|
||||
#logger.log_trace()
|
||||
return False
|
||||
|
||||
|
||||
if not quiet:
|
||||
#tell the old room we are leaving
|
||||
try:
|
||||
self.announce_move_from(destination)
|
||||
self.announce_move_from(destination)
|
||||
except Exception:
|
||||
logerr(errtxt % "at_announce_move()")
|
||||
logerr(errtxt % "at_announce_move()")
|
||||
#emit_to_obj.msg(errtxt % "at_announce_move()" )
|
||||
#logger.log_trace()
|
||||
return False
|
||||
return False
|
||||
|
||||
# Perform move
|
||||
try:
|
||||
|
|
@ -695,18 +695,18 @@ class ObjectDB(TypedObject):
|
|||
except Exception:
|
||||
emit_to_obj.msg(errtxt % "location change")
|
||||
logger.log_trace()
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
if not quiet:
|
||||
# Tell the new room we are there.
|
||||
# Tell the new room we are there.
|
||||
try:
|
||||
self.announce_move_to(source_location)
|
||||
except Exception:
|
||||
logerr(errtxt % "announce_move_to()")
|
||||
#emit_to_obj.msg(errtxt % "announce_move_to()")
|
||||
#logger.log_trace()
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
# Perform eventual extra commands on the receiving location
|
||||
# (the object has already arrived at this point)
|
||||
try:
|
||||
|
|
@ -715,7 +715,7 @@ class ObjectDB(TypedObject):
|
|||
logerr(errtxt % "at_object_receive()")
|
||||
#emit_to_obj.msg(errtxt % "at_object_receive()")
|
||||
#logger.log_trace()
|
||||
return False
|
||||
return False
|
||||
|
||||
# Execute eventual extra commands on this object after moving it
|
||||
# (usually calling 'look')
|
||||
|
|
@ -725,13 +725,13 @@ class ObjectDB(TypedObject):
|
|||
logerr(errtxt % "at_after_move")
|
||||
#emit_to_obj.msg(errtxt % "at_after_move()")
|
||||
#logger.log_trace()
|
||||
return False
|
||||
return True
|
||||
return False
|
||||
return True
|
||||
|
||||
#
|
||||
# Object Swap, Delete and Cleanup methods
|
||||
#
|
||||
|
||||
# Object Swap, Delete and Cleanup methods
|
||||
#
|
||||
|
||||
def clear_exits(self):
|
||||
"""
|
||||
Destroys all of the exits and any exits pointing to this
|
||||
|
|
@ -745,7 +745,7 @@ class ObjectDB(TypedObject):
|
|||
def clear_contents(self):
|
||||
"""
|
||||
Moves all objects (players/things) to their home
|
||||
location or to default home.
|
||||
location or to default home.
|
||||
"""
|
||||
# Gather up everything that thinks this is its location.
|
||||
objs = ObjectDB.objects.filter(db_location=self)
|
||||
|
|
@ -754,29 +754,29 @@ class ObjectDB(TypedObject):
|
|||
default_home = ObjectDB.objects.get(id=default_home_id)
|
||||
if default_home.id == self.id:
|
||||
# we are deleting default home!
|
||||
default_home = None
|
||||
default_home = None
|
||||
except Exception:
|
||||
string = "Could not find default home '(#%d)'."
|
||||
logger.log_errmsg(string % default_home_id)
|
||||
default_home = None
|
||||
default_home = None
|
||||
|
||||
for obj in objs:
|
||||
home = obj.home
|
||||
for obj in objs:
|
||||
home = obj.home
|
||||
# Obviously, we can't send it back to here.
|
||||
if not home or (home and home.id == self.id):
|
||||
obj.home = default_home
|
||||
|
||||
obj.home = default_home
|
||||
|
||||
# If for some reason it's still None...
|
||||
if not obj.home:
|
||||
string = "Missing default home, '%s(#%d)' "
|
||||
string += "now has a null location."
|
||||
obj.location = None
|
||||
obj.location = None
|
||||
obj.msg("Something went wrong! You are dumped into nowhere. Contact an admin.")
|
||||
logger.log_errmsg(string % (obj.name, obj.id))
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
if obj.has_player:
|
||||
if home:
|
||||
if home:
|
||||
string = "Your current location has ceased to exist,"
|
||||
string += " moving you to %s(#%d)."
|
||||
obj.msg(string % (home.name, home.id))
|
||||
|
|
@ -787,22 +787,22 @@ class ObjectDB(TypedObject):
|
|||
obj.move_to(home)
|
||||
|
||||
def copy(self, new_key=None):
|
||||
"""
|
||||
"""
|
||||
Makes an identical copy of this object. If you want to customize the copy by
|
||||
changing some settings, use ObjectDB.object.copy_object() directly.
|
||||
|
||||
new_key (string) - new key/name of copied object. If new_key is not specified, the copy will be named
|
||||
<old_key>_copy by default.
|
||||
Returns: Object (copy of this one)
|
||||
<old_key>_copy by default.
|
||||
Returns: Object (copy of this one)
|
||||
"""
|
||||
if not new_key:
|
||||
new_key = "%s_copy" % self.key
|
||||
return ObjectDB.objects.copy_object(self, new_key=new_key)
|
||||
|
||||
delete_iter = 0
|
||||
def delete(self):
|
||||
def delete(self):
|
||||
"""
|
||||
Deletes this object.
|
||||
Deletes this object.
|
||||
Before deletion, this method makes sure to move all contained
|
||||
objects to their respective home locations, as well as clean
|
||||
up all exits to/from the object.
|
||||
|
|
@ -815,7 +815,7 @@ class ObjectDB(TypedObject):
|
|||
if not self.at_object_delete():
|
||||
# this is an extra pre-check
|
||||
# run before deletion mechanism
|
||||
# is kicked into gear.
|
||||
# is kicked into gear.
|
||||
self.delete_iter == 0
|
||||
return False
|
||||
|
||||
|
|
@ -825,17 +825,17 @@ class ObjectDB(TypedObject):
|
|||
|
||||
for session in self.sessions:
|
||||
session.msg("Your character %s has been destroyed." % self.name)
|
||||
# no need to disconnect, Player just jumps to OOC mode.
|
||||
# no need to disconnect, Player just jumps to OOC mode.
|
||||
# sever the connection (important!)
|
||||
if object.__getattribute__(self, 'player') and self.player:
|
||||
self.player.character = None
|
||||
self.player = None
|
||||
self.player = None
|
||||
|
||||
for script in self.scripts.all():
|
||||
script.stop()
|
||||
|
||||
|
||||
# if self.player:
|
||||
# self.player.user.is_active = False
|
||||
# self.player.user.is_active = False
|
||||
# self.player.user.save(
|
||||
|
||||
# Destroy any exits to and from this room, if any
|
||||
|
|
@ -844,4 +844,4 @@ class ObjectDB(TypedObject):
|
|||
self.clear_contents()
|
||||
# Perform the deletion of the object
|
||||
super(ObjectDB, self).delete()
|
||||
return True
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
"""
|
||||
This is the basis of the typeclass system.
|
||||
This is the basis of the typeclass system.
|
||||
|
||||
The idea is have the object as a normal class with the
|
||||
database-connection tied to itself through a property.
|
||||
|
|
@ -19,15 +19,15 @@ from src.typeclasses.typeclass import TypeClass
|
|||
from src.commands import cmdset, command
|
||||
|
||||
#
|
||||
# Base class to inherit from.
|
||||
# Base class to inherit from.
|
||||
#
|
||||
|
||||
class Object(TypeClass):
|
||||
"""
|
||||
This is the base class for all in-game objects.
|
||||
Inherit from this to create different types of
|
||||
objects in the game.
|
||||
"""
|
||||
objects in the game.
|
||||
"""
|
||||
|
||||
def __init__(self, dbobj):
|
||||
"""
|
||||
|
|
@ -39,18 +39,18 @@ class Object(TypeClass):
|
|||
seen in src.object.objects).
|
||||
|
||||
|
||||
Object Typeclass API:
|
||||
Object Typeclass API:
|
||||
|
||||
* Available properties (only available on initiated typeclass objects)
|
||||
|
||||
key (string) - name of object
|
||||
key (string) - name of object
|
||||
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
|
||||
typeclass (Object, read-only) - this links back to this class as an identified only. Use self.swap_typeclass() to switch.
|
||||
date_created (string) - time stamp of object creation
|
||||
permissions (list of strings) - list of permission strings
|
||||
permissions (list of strings) - list of permission strings
|
||||
|
||||
player (Player) - controlling player (will also return offline player)
|
||||
location (Object) - current location. Is None if this is a room
|
||||
|
|
@ -59,19 +59,19 @@ class Object(TypeClass):
|
|||
has_player (bool, read-only)- will only return *connected* players
|
||||
contents (list of Objects, read-only) - returns all objects inside this object (including exits)
|
||||
exits (list of Objects, read-only) - returns all exits from this object, if any
|
||||
destination (Object) - only set if this object is an exit.
|
||||
destination (Object) - only set if this object is an exit.
|
||||
is_superuser (bool, read-only) - True/False if this user is a superuser
|
||||
|
||||
* Handlers available
|
||||
* Handlers available
|
||||
|
||||
locks - lock-handler: use locks.add() to add new lock strings
|
||||
db - attribute-handler: store/retrieve database attributes on this self.db.myattr=val, val=self.db.myattr
|
||||
ndb - non-persistent attribute handler: same as db but does not create a database entry when storing data
|
||||
ndb - non-persistent attribute handler: same as db but does not create a database entry when storing data
|
||||
scripts - script-handler. Add new scripts to object with scripts.add()
|
||||
cmdset - cmdset-handler. Use cmdset.add() to add new cmdsets to object
|
||||
nicks - nick-handler. New nicks with nicks.add().
|
||||
|
||||
* Helper methods (see src.objects.objects.py for full headers)
|
||||
* Helper methods (see src.objects.objects.py for full headers)
|
||||
|
||||
search(ostring, global_search=False, attribute_name=None, use_nicks=False, location=None, ignore_errors=False, player=False)
|
||||
execute_cmd(raw_string)
|
||||
|
|
@ -90,15 +90,15 @@ class Object(TypeClass):
|
|||
basetype_setup() - only called once, used for behind-the-scenes setup. Normally not modified.
|
||||
basetype_posthook_setup() - customization in basetype, after the object has been created; Normally not modified.
|
||||
|
||||
at_object_creation() - only called once, when object is first created. Object customizations go here.
|
||||
at_object_creation() - only called once, when object is first created. Object customizations go here.
|
||||
at_object_delete() - called just before deleting an object. If returning False, deletion is aborted. Note that all objects
|
||||
inside a deleted object are automatically moved to their <home>, they don't need to be removed here.
|
||||
inside a deleted object are automatically moved to their <home>, they don't need to be removed here.
|
||||
|
||||
at_init() - called whenever typeclass is cached from memory, at least once every server restart/reload
|
||||
at_cmdset_get() - this is called just before the command handler requests a cmdset from this object
|
||||
at_first_login() - (player-controlled objects only) called once, the very first time user logs in.
|
||||
at_init() - called whenever typeclass is cached from memory, at least once every server restart/reload
|
||||
at_cmdset_get() - this is called just before the command handler requests a cmdset from this object
|
||||
at_first_login() - (player-controlled objects only) called once, the very first time user logs in.
|
||||
at_pre_login() - (player-controlled objects only) called every time the user connects, after they have identified, before other setup
|
||||
at_post_login() - (player-controlled objects only) called at the end of login, just before setting the player loose in the world.
|
||||
at_post_login() - (player-controlled objects only) called at the end of login, just before setting the player loose in the world.
|
||||
at_disconnect() - (player-controlled objects only) called just before the user disconnects (or goes linkless)
|
||||
at_server_reload() - called before server is reloaded
|
||||
at_server_shutdown() - called just before server is fully shut down
|
||||
|
|
@ -111,19 +111,19 @@ class Object(TypeClass):
|
|||
at_object_receive(obj, source_location) - called when this object receives another object
|
||||
|
||||
at_before_traverse(traversing_object) - (exit-objects only) called just before an object traverses this object
|
||||
at_after_traverse(traversing_object, source_location) - (exit-objects only) called just after a traversal has happened.
|
||||
at_after_traverse(traversing_object, source_location) - (exit-objects only) called just after a traversal has happened.
|
||||
at_failed_traverse(traversing_object) - (exit-objects only) called if traversal fails and property err_traverse is not defined.
|
||||
|
||||
at_msg_receive(self, msg, from_obj=None, data=None) - called when a message (via self.msg()) is sent to this obj.
|
||||
at_msg_receive(self, msg, from_obj=None, data=None) - called when a message (via self.msg()) is sent to this obj.
|
||||
If returns false, aborts send.
|
||||
at_msg_send(self, msg, to_obj=None, data=None) - called when this objects sends a message to someone via self.msg().
|
||||
at_msg_send(self, msg, to_obj=None, data=None) - called when this objects sends a message to someone via self.msg().
|
||||
|
||||
return_appearance(looker) - describes this object. Used by "look" command by default
|
||||
at_desc(looker=None) - called by 'look' whenever the appearance is requested.
|
||||
at_desc(looker=None) - called by 'look' whenever the appearance is requested.
|
||||
at_get(getter) - called after object has been picked up. Does not stop pickup.
|
||||
at_drop(dropper) - called when this object has been dropped.
|
||||
at_say(speaker, message) - by default, called if an object inside this object speaks
|
||||
|
||||
|
||||
"""
|
||||
super(Object, self).__init__(dbobj)
|
||||
|
||||
|
|
@ -132,84 +132,84 @@ class Object(TypeClass):
|
|||
def search(self, ostring,
|
||||
global_search=False,
|
||||
attribute_name=None,
|
||||
use_nicks=False,
|
||||
use_nicks=False,
|
||||
location=None,
|
||||
ignore_errors=False,
|
||||
ignore_errors=False,
|
||||
player=False):
|
||||
"""
|
||||
Perform a standard object search in the database, handling
|
||||
multiple results and lack thereof gracefully.
|
||||
|
||||
|
||||
ostring: (str) The string to match object names against.
|
||||
Obs - To find a player, append * to the
|
||||
start of ostring.
|
||||
start of ostring.
|
||||
global_search(bool): Search all objects, not just the current
|
||||
location/inventory
|
||||
attribute_name (string) Which attribute to match
|
||||
(if None, uses default 'name')
|
||||
use_nicks (bool) : Use nickname replace (off by default)
|
||||
use_nicks (bool) : Use nickname replace (off by default)
|
||||
location (Object): If None, use caller's current location
|
||||
ignore_errors (bool): Don't display any error messages even
|
||||
if there are none/multiple matches -
|
||||
just return the result as a list.
|
||||
player (Objectt): Don't search for an Object but a Player.
|
||||
if there are none/multiple matches -
|
||||
just return the result as a list.
|
||||
player (Objectt): Don't search for an Object but a Player.
|
||||
This will also find players that don't
|
||||
currently have a character.
|
||||
|
||||
Returns - a unique Object/Player match or None. All error
|
||||
messages are handled by system-commands and the parser-handlers
|
||||
specified in settings.
|
||||
specified in settings.
|
||||
|
||||
Use *<string> to search for objects controlled by a specific
|
||||
player. Note that the object controlled by the player will be
|
||||
returned, not the player object itself. This also means that
|
||||
this will not find Players without a character. Use the keyword
|
||||
player=True to find player objects.
|
||||
|
||||
player=True to find player objects.
|
||||
|
||||
Note - for multiple matches, the engine accepts a number
|
||||
linked to the key in order to separate the matches from
|
||||
each other without showing the dbref explicitly. Default
|
||||
syntax for this is 'N-searchword'. So for example, if there
|
||||
are three objects in the room all named 'ball', you could
|
||||
address the individual ball as '1-ball', '2-ball', '3-ball'
|
||||
etc.
|
||||
etc.
|
||||
"""
|
||||
return self.dbobj.search(ostring,
|
||||
global_search=global_search,
|
||||
return self.dbobj.search(ostring,
|
||||
global_search=global_search,
|
||||
attribute_name=attribute_name,
|
||||
use_nicks=use_nicks,
|
||||
location=location,
|
||||
ignore_errors=ignore_errors,
|
||||
ignore_errors=ignore_errors,
|
||||
player=player)
|
||||
|
||||
|
||||
def execute_cmd(self, raw_string):
|
||||
"""
|
||||
Do something as this object. This command transparently
|
||||
lets its typeclass execute the command. Evennia also calls
|
||||
this method whenever the player sends a command on the command line.
|
||||
|
||||
Argument:
|
||||
Argument:
|
||||
raw_string (string) - raw command input
|
||||
|
||||
Returns Deferred - this is an asynchronous Twisted object that will
|
||||
not fire until the command has actually finished executing. To overload
|
||||
this one needs to attach callback functions to it, with addCallback(function).
|
||||
this one needs to attach callback functions to it, with addCallback(function).
|
||||
This function will be called with an eventual return value from the command
|
||||
execution.
|
||||
execution.
|
||||
|
||||
This return is not used at all by Evennia by default, but might be useful
|
||||
for coders intending to implement some sort of nested command structure.
|
||||
"""
|
||||
for coders intending to implement some sort of nested command structure.
|
||||
"""
|
||||
return self.dbobj.execute_cmd(raw_string)
|
||||
|
||||
def msg(self, message, from_obj=None, data=None):
|
||||
"""
|
||||
Emits something to any sessions attached to the object.
|
||||
|
||||
|
||||
message (str): The message to send
|
||||
from_obj (obj): object that is sending.
|
||||
data (object): an optional data object that may or may not
|
||||
be used by the protocol.
|
||||
be used by the protocol.
|
||||
"""
|
||||
self.dbobj.msg(message, from_obj=from_obj, data=data)
|
||||
|
||||
|
|
@ -228,44 +228,44 @@ class Object(TypeClass):
|
|||
exit object (i.e. it has "destination"!=None), the move_to will
|
||||
happen to this destination and -not- into the exit object itself, unless
|
||||
use_destination=False. Note that no lock checks are done by this function,
|
||||
such things are assumed to have been handled before calling move_to.
|
||||
|
||||
such things are assumed to have been handled before calling move_to.
|
||||
|
||||
destination: (Object) Reference to the object to move to. This
|
||||
can also be an exit object, in which case the destination
|
||||
property is used as destination.
|
||||
property is used as destination.
|
||||
quiet: (bool) If true, don't emit left/arrived messages.
|
||||
emit_to_obj: (Object) object to receive error messages
|
||||
use_destination (bool): Default is for objects to use the "destination" property
|
||||
of destinations as the target to move to. Turning off this
|
||||
keyword allows objects to move "inside" exit objects.
|
||||
keyword allows objects to move "inside" exit objects.
|
||||
Returns True/False depending on if there were problems with the move. This method
|
||||
may also return various error messages to the emit_to_obj.
|
||||
may also return various error messages to the emit_to_obj.
|
||||
|
||||
"""
|
||||
return self.dbobj.move_to(destination, quiet=quiet,
|
||||
emit_to_obj=emit_to_obj, use_destination=use_destination)
|
||||
|
||||
|
||||
def copy(self, new_key=None):
|
||||
"""
|
||||
"""
|
||||
Makes an identical copy of this object. If you want to customize the copy by
|
||||
changing some settings, use ObjectDB.object.copy_object() directly.
|
||||
|
||||
new_key (string) - new key/name of copied object. If new_key is not specified, the copy will be named
|
||||
<old_key>_copy by default.
|
||||
Returns: Object (copy of this one)
|
||||
<old_key>_copy by default.
|
||||
Returns: Object (copy of this one)
|
||||
"""
|
||||
return self.dbobj.copy(new_key=new_key)
|
||||
|
||||
def delete(self):
|
||||
|
||||
def delete(self):
|
||||
"""
|
||||
Deletes this object.
|
||||
Deletes this object.
|
||||
Before deletion, this method makes sure to move all contained
|
||||
objects to their respective home locations, as well as clean
|
||||
up all exits to/from the object.
|
||||
|
||||
Returns: boolean True if deletion succeded, False if there
|
||||
were errors during deletion or deletion otherwise
|
||||
failed.
|
||||
failed.
|
||||
"""
|
||||
return self.dbobj.delete()
|
||||
|
||||
|
|
@ -277,16 +277,16 @@ class Object(TypeClass):
|
|||
Returns true if this object has this type
|
||||
OR has a typeclass which is an subclass of
|
||||
the given typeclass.
|
||||
|
||||
|
||||
typeclass - can be a class object or the
|
||||
python path to such an object to match against.
|
||||
|
||||
python path to such an object to match against.
|
||||
|
||||
exact - returns true only if the object's
|
||||
type is exactly this typeclass, ignoring
|
||||
parents.
|
||||
|
||||
Returns: Boolean
|
||||
"""
|
||||
Returns: Boolean
|
||||
"""
|
||||
return self.dbobj.is_typeclass(typeclass, exact=exact)
|
||||
|
||||
def swap_typeclass(self, new_typeclass, clean_attributes=False, no_default=True):
|
||||
|
|
@ -294,18 +294,18 @@ class Object(TypeClass):
|
|||
This performs an in-situ swap of the typeclass. This means
|
||||
that in-game, this object will suddenly be something else.
|
||||
Player will not be affected. To 'move' a player to a different
|
||||
object entirely (while retaining this object's type), use
|
||||
object entirely (while retaining this object's type), use
|
||||
self.player.swap_object().
|
||||
|
||||
Note that this might be an error prone operation if the
|
||||
Note that this might be an error prone operation if the
|
||||
old/new typeclass was heavily customized - your code
|
||||
might expect one and not the other, so be careful to
|
||||
might expect one and not the other, so be careful to
|
||||
bug test your code if using this feature! Often its easiest
|
||||
to create a new object and just swap the player over to
|
||||
that one instead.
|
||||
that one instead.
|
||||
|
||||
Arguments:
|
||||
new_typeclass (path/classobj) - type to switch to
|
||||
Arguments:
|
||||
new_typeclass (path/classobj) - type to switch to
|
||||
clean_attributes (bool/list) - will delete all attributes
|
||||
stored on this object (but not any
|
||||
of the database fields such as name or
|
||||
|
|
@ -317,10 +317,10 @@ class Object(TypeClass):
|
|||
no_default - if this is active, the swapper will not allow for
|
||||
swapping to a default typeclass in case the given
|
||||
one fails for some reason. Instead the old one
|
||||
will be preserved.
|
||||
Returns:
|
||||
will be preserved.
|
||||
Returns:
|
||||
boolean True/False depending on if the swap worked or not.
|
||||
|
||||
|
||||
|
||||
"""
|
||||
self.dbobj.swap_typeclass(new_typeclass, clean_attributes=clean_attributes, no_default=no_default)
|
||||
|
|
@ -332,14 +332,14 @@ class Object(TypeClass):
|
|||
accessing_obj (Object)- object trying to access this one
|
||||
access_type (string) - type of access sought
|
||||
default (bool) - what to return if no lock of access_type was found
|
||||
"""
|
||||
"""
|
||||
return self.dbobj.access(accessing_obj, access_type=access_type, default=default)
|
||||
|
||||
def check_permstring(self, permstring):
|
||||
"""
|
||||
This explicitly checks the given string against this object's
|
||||
'permissions' property without involving any locks.
|
||||
|
||||
|
||||
permstring (string) - permission string that need to match a permission on the object.
|
||||
(example: 'Builders')
|
||||
"""
|
||||
|
|
@ -355,7 +355,7 @@ class Object(TypeClass):
|
|||
"""
|
||||
result = self.id == other
|
||||
if not result and hasattr(other, "id"):
|
||||
result = self.id == other.id
|
||||
result = self.id == other.id
|
||||
if not result:
|
||||
try:
|
||||
result = other and self.user.id == other.user.id
|
||||
|
|
@ -366,14 +366,14 @@ class Object(TypeClass):
|
|||
|
||||
## hooks called by the game engine
|
||||
|
||||
|
||||
|
||||
def basetype_setup(self):
|
||||
"""
|
||||
This sets up the default properties of an Object,
|
||||
just before the more general at_object_creation.
|
||||
|
||||
Don't change this, instead edit at_object_creation() to
|
||||
overload the defaults (it is called after this one).
|
||||
overload the defaults (it is called after this one).
|
||||
"""
|
||||
# the default security setup fallback for a generic
|
||||
# object. Overload in child for a custom setup. Also creation
|
||||
|
|
@ -383,13 +383,13 @@ class Object(TypeClass):
|
|||
dbref = self.dbobj.dbref
|
||||
|
||||
self.locks.add("control:id(%s) or perm(Immortals)" % dbref) # edit locks/permissions, delete
|
||||
self.locks.add("examine:perm(Builders)") # examine properties
|
||||
self.locks.add("examine:perm(Builders)") # examine properties
|
||||
self.locks.add("view:all()") # look at object (visibility)
|
||||
self.locks.add("edit:perm(Wizards)") # edit properties/attributes
|
||||
self.locks.add("delete:perm(Wizards)") # delete object
|
||||
self.locks.add("edit:perm(Wizards)") # edit properties/attributes
|
||||
self.locks.add("delete:perm(Wizards)") # delete object
|
||||
self.locks.add("get:all()") # pick up object
|
||||
self.locks.add("call:true()") # allow to call commands on this object
|
||||
self.locks.add("puppet:id(%s) or perm(Immortals) or pperm(Immortals)" % dbref) # restricts puppeting of this object
|
||||
self.locks.add("puppet:id(%s) or perm(Immortals) or pperm(Immortals)" % dbref) # restricts puppeting of this object
|
||||
|
||||
def basetype_posthook_setup(self):
|
||||
"""
|
||||
|
|
@ -403,27 +403,27 @@ class Object(TypeClass):
|
|||
def at_object_creation(self):
|
||||
"""
|
||||
Called once, when this object is first created.
|
||||
"""
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def at_object_delete(self):
|
||||
"""
|
||||
Called just before the database object is
|
||||
permanently delete()d from the database. If
|
||||
this method returns False, deletion is aborted.
|
||||
this method returns False, deletion is aborted.
|
||||
"""
|
||||
return True
|
||||
|
||||
def at_init(self):
|
||||
"""
|
||||
"""
|
||||
This is always called whenever this object is initiated --
|
||||
that is, whenever it its typeclass is cached from memory. This
|
||||
happens on-demand first time the object is used or activated
|
||||
in some way after being created but also after each server
|
||||
restart or reload.
|
||||
"""
|
||||
pass
|
||||
pass
|
||||
|
||||
def at_cmdset_get(self):
|
||||
"""
|
||||
|
|
@ -450,7 +450,7 @@ class Object(TypeClass):
|
|||
"""
|
||||
Called at the end of the login
|
||||
process, just before letting
|
||||
them loose.
|
||||
them loose.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
|
@ -463,16 +463,16 @@ class Object(TypeClass):
|
|||
|
||||
def at_server_reload(self):
|
||||
"""
|
||||
This hook is called whenever the server is shutting down for restart/reboot.
|
||||
This hook is called whenever the server is shutting down for restart/reboot.
|
||||
If you want to, for example, save non-persistent properties across a restart,
|
||||
this is the place to do it.
|
||||
this is the place to do it.
|
||||
"""
|
||||
pass
|
||||
|
||||
def at_server_shutdown(self):
|
||||
"""
|
||||
This hook is called whenever the server is shutting down fully (i.e. not for
|
||||
a restart).
|
||||
This hook is called whenever the server is shutting down fully (i.e. not for
|
||||
a restart).
|
||||
"""
|
||||
pass
|
||||
|
||||
|
|
@ -482,63 +482,63 @@ class Object(TypeClass):
|
|||
def at_before_move(self, destination):
|
||||
"""
|
||||
Called just before starting to move
|
||||
this object to destination.
|
||||
this object to destination.
|
||||
|
||||
destination - the object we are moving to
|
||||
|
||||
If this method returns False/None, the move
|
||||
is cancelled before it is even started.
|
||||
is cancelled before it is even started.
|
||||
"""
|
||||
#return has_perm(self, destination, "can_move")
|
||||
return True
|
||||
return True
|
||||
|
||||
def announce_move_from(self, destination):
|
||||
"""
|
||||
Called if the move is to be announced. This is
|
||||
called while we are still standing in the old
|
||||
location.
|
||||
location.
|
||||
|
||||
destination - the place we are going to.
|
||||
destination - the place we are going to.
|
||||
"""
|
||||
if not self.location:
|
||||
return
|
||||
name = self.name
|
||||
return
|
||||
name = self.name
|
||||
loc_name = ""
|
||||
loc_name = self.location.name
|
||||
loc_name = self.location.name
|
||||
dest_name = destination.name
|
||||
string = "%s is leaving %s, heading for %s."
|
||||
self.location.msg_contents(string % (name, loc_name, dest_name), exclude=self)
|
||||
|
||||
|
||||
def announce_move_to(self, source_location):
|
||||
"""
|
||||
Called after the move if the move was not quiet. At this
|
||||
point we are standing in the new location.
|
||||
point we are standing in the new location.
|
||||
|
||||
source_location - the place we came from
|
||||
source_location - the place we came from
|
||||
"""
|
||||
|
||||
name = self.name
|
||||
name = self.name
|
||||
if not source_location and self.location.has_player:
|
||||
# This was created from nowhere and added to a player's
|
||||
# inventory; it's probably the result of a create command.
|
||||
string = "You now have %s in your possession." % name
|
||||
self.location.msg(string)
|
||||
return
|
||||
return
|
||||
|
||||
src_name = "nowhere"
|
||||
loc_name = self.location.name
|
||||
if source_location:
|
||||
src_name = source_location.name
|
||||
string = "%s arrives to %s from %s."
|
||||
string = "%s arrives to %s from %s."
|
||||
self.location.msg_contents(string % (name, loc_name, src_name), exclude=self)
|
||||
|
||||
|
||||
def at_after_move(self, source_location):
|
||||
"""
|
||||
Called after move has completed, regardless of quiet mode or not.
|
||||
Called after move has completed, regardless of quiet mode or not.
|
||||
Allows changes to the object due to the location it is now in.
|
||||
|
||||
source_location - where we came from
|
||||
source_location - where we came from
|
||||
"""
|
||||
pass
|
||||
|
||||
|
|
@ -554,92 +554,92 @@ class Object(TypeClass):
|
|||
|
||||
def at_object_receive(self, moved_obj, source_location):
|
||||
"""
|
||||
Called after an object has been moved into this object.
|
||||
Called after an object has been moved into this object.
|
||||
|
||||
moved_obj - the object moved into this one
|
||||
source_location - where moved_object came from.
|
||||
source_location - where moved_object came from.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def at_before_traverse(self, traversing_object):
|
||||
"""
|
||||
Called just before an object uses this object to
|
||||
Called just before an object uses this object to
|
||||
traverse to another object (i.e. this object is a type of Exit)
|
||||
|
||||
|
||||
The target location should normally be available as self.destination.
|
||||
"""
|
||||
pass
|
||||
|
||||
def at_after_traverse(self, traversing_object, source_location):
|
||||
"""
|
||||
Called just after an object successfully used this object to
|
||||
Called just after an object successfully used this object to
|
||||
traverse to another object (i.e. this object is a type of Exit)
|
||||
|
||||
|
||||
The target location should normally be available as self.destination.
|
||||
"""
|
||||
pass
|
||||
|
||||
def at_failed_traverse(self, traversing_object):
|
||||
"""
|
||||
This is called if an object fails to traverse this object for some
|
||||
This is called if an object fails to traverse this object for some
|
||||
reason. It will not be called if the attribute err_traverse is defined,
|
||||
that attribute will then be echoed back instead.
|
||||
that attribute will then be echoed back instead.
|
||||
"""
|
||||
pass
|
||||
pass
|
||||
|
||||
def at_msg_receive(self, msg, from_obj=None, data=None):
|
||||
"""
|
||||
This hook is called whenever someone
|
||||
This hook is called whenever someone
|
||||
sends a message to this object.
|
||||
|
||||
Note that from_obj may be None if the sender did
|
||||
not include itself as an argument to the obj.msg()
|
||||
call - so you have to check for this. .
|
||||
|
||||
call - so you have to check for this. .
|
||||
|
||||
Consider this a pre-processing method before
|
||||
msg is passed on to the user sesssion. If this
|
||||
method returns False, the msg will not be
|
||||
msg is passed on to the user sesssion. If this
|
||||
method returns False, the msg will not be
|
||||
passed on.
|
||||
|
||||
msg = the message received
|
||||
from_obj = the one sending the message
|
||||
"""
|
||||
return True
|
||||
return True
|
||||
|
||||
def at_msg_send(self, msg, to_obj=None, data=None):
|
||||
"""
|
||||
This is a hook that is called when /this/ object
|
||||
sends a message to another object with obj.msg()
|
||||
while also specifying that it is the one sending.
|
||||
|
||||
while also specifying that it is the one sending.
|
||||
|
||||
Note that this method is executed on the object
|
||||
passed along with the msg() function (i.e. using
|
||||
obj.msg(msg, caller) will then launch caller.at_msg())
|
||||
and if no object was passed, it will never be called.
|
||||
and if no object was passed, it will never be called.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
# hooks called by the default cmdset.
|
||||
|
||||
|
||||
# hooks called by the default cmdset.
|
||||
|
||||
def return_appearance(self, pobject):
|
||||
"""
|
||||
This is a convenient hook for a 'look'
|
||||
command to call.
|
||||
command to call.
|
||||
"""
|
||||
if not pobject:
|
||||
return
|
||||
return
|
||||
string = "{c%s{n" % self.name
|
||||
desc = self.attr("desc")
|
||||
if desc:
|
||||
string += "\n %s" % desc
|
||||
exits = []
|
||||
exits = []
|
||||
users = []
|
||||
things = []
|
||||
for content in [con for con in self.contents if con.access(pobject, 'view')]:
|
||||
if content == pobject:
|
||||
continue
|
||||
continue
|
||||
name = content.name
|
||||
if content.destination:
|
||||
exits.append(name)
|
||||
|
|
@ -651,17 +651,17 @@ class Object(TypeClass):
|
|||
string += "\n{wExits:{n " + ", ".join(exits)
|
||||
if users or things:
|
||||
string += "\n{wYou see: {n"
|
||||
if users:
|
||||
if users:
|
||||
string += "{c" + ", ".join(users) + "{n "
|
||||
if things:
|
||||
string += ", ".join(things)
|
||||
if things:
|
||||
string += ", ".join(things)
|
||||
return string
|
||||
|
||||
def at_desc(self, looker=None):
|
||||
"""
|
||||
This is called whenever someone looks
|
||||
at this object. Looker is the looking
|
||||
object.
|
||||
object.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
|
@ -685,8 +685,8 @@ class Object(TypeClass):
|
|||
def at_say(self, speaker, message):
|
||||
"""
|
||||
Called on this object if an object inside this object speaks.
|
||||
The string returned from this method is the final form
|
||||
of the speech. Obs - you don't have to add things like
|
||||
The string returned from this method is the final form
|
||||
of the speech. Obs - you don't have to add things like
|
||||
'you say: ' or similar, that is handled by the say command.
|
||||
|
||||
speaker - the object speaking
|
||||
|
|
@ -695,7 +695,7 @@ class Object(TypeClass):
|
|||
return message
|
||||
|
||||
#
|
||||
# Base Player object
|
||||
# Base Player object
|
||||
#
|
||||
|
||||
class Character(Object):
|
||||
|
|
@ -703,24 +703,24 @@ class Character(Object):
|
|||
This is just like the Object except it implements its own
|
||||
version of the at_object_creation to set up the script
|
||||
that adds the default cmdset to the object.
|
||||
"""
|
||||
"""
|
||||
|
||||
def basetype_setup(self):
|
||||
"""
|
||||
Setup character-specific security
|
||||
|
||||
Don't change this, instead edit at_object_creation() to
|
||||
overload the defaults (it is called after this one).
|
||||
overload the defaults (it is called after this one).
|
||||
"""
|
||||
super(Character, self).basetype_setup()
|
||||
self.locks.add("get:false()") # noone can pick up the character
|
||||
self.locks.add("call:false()") # no commands can be called on character from outside
|
||||
self.locks.add("call:false()") # no commands can be called on character from outside
|
||||
|
||||
# add the default cmdset
|
||||
from settings import CMDSET_DEFAULT
|
||||
from settings import CMDSET_DEFAULT
|
||||
self.cmdset.add_default(CMDSET_DEFAULT, permanent=True)
|
||||
# no other character should be able to call commands on the Character.
|
||||
self.cmdset.outside_access = False
|
||||
# no other character should be able to call commands on the Character.
|
||||
self.cmdset.outside_access = False
|
||||
|
||||
def at_object_creation(self):
|
||||
"""
|
||||
|
|
@ -728,8 +728,8 @@ class Character(Object):
|
|||
the script is permanently stored to this object (the permanent
|
||||
keyword creates a script to do this), we should never need to
|
||||
do this again for as long as this object exists.
|
||||
"""
|
||||
pass
|
||||
"""
|
||||
pass
|
||||
|
||||
def at_after_move(self, source_location):
|
||||
"Default is to look around after a move."
|
||||
|
|
@ -737,34 +737,34 @@ class Character(Object):
|
|||
|
||||
def at_disconnect(self):
|
||||
"""
|
||||
We stove away the character when logging off, otherwise the character object will
|
||||
We stove away the character when logging off, otherwise the character object will
|
||||
remain in the room also after the player logged off ("headless", so to say).
|
||||
"""
|
||||
if self.location: # have to check, in case of multiple connections closing
|
||||
if self.location: # have to check, in case of multiple connections closing
|
||||
self.location.msg_contents("%s has left the game." % self.name, exclude=[self])
|
||||
self.db.prelogout_location = self.location
|
||||
self.location = None
|
||||
self.location = None
|
||||
|
||||
def at_post_login(self):
|
||||
"""
|
||||
This recovers the character again after having been "stoved away" at disconnect.
|
||||
"""
|
||||
if self.db.prelogout_location:
|
||||
# try to recover
|
||||
self.location = self.db.prelogout_location
|
||||
# try to recover
|
||||
self.location = self.db.prelogout_location
|
||||
if self.location == None:
|
||||
# make sure location is never None (home should always exist)
|
||||
self.location = self.home
|
||||
# save location again to be sure
|
||||
# save location again to be sure
|
||||
self.db.prelogout_location = self.location
|
||||
|
||||
self.location.msg_contents("%s has entered the game." % self.name, exclude=[self])
|
||||
self.location.at_object_receive(self, self.location)
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Base Room object
|
||||
# Base Room object
|
||||
#
|
||||
|
||||
class Room(Object):
|
||||
|
|
@ -778,16 +778,16 @@ class Room(Object):
|
|||
(since default is None anyway)
|
||||
|
||||
Don't change this, instead edit at_object_creation() to
|
||||
overload the defaults (it is called after this one).
|
||||
overload the defaults (it is called after this one).
|
||||
"""
|
||||
|
||||
super(Room, self).basetype_setup()
|
||||
self.locks.add("get:false();puppet:false()") # would be weird to puppet a room ...
|
||||
self.location = None
|
||||
self.location = None
|
||||
|
||||
|
||||
#
|
||||
# Exits
|
||||
# Exits
|
||||
#
|
||||
|
||||
class Exit(Object):
|
||||
|
|
@ -795,16 +795,16 @@ 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
|
||||
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.
|
||||
|
||||
"""
|
||||
|
||||
"""
|
||||
|
||||
# Helper classes and methods to implement the Exit. These need not
|
||||
# be overloaded unless one want to change the foundation for how
|
||||
# Exits work. See the end of the class for hook methods to overload.
|
||||
# Exits work. See the end of the class for hook methods to overload.
|
||||
|
||||
def create_exit_cmdset(self, exidbobj):
|
||||
"""
|
||||
|
|
@ -812,8 +812,8 @@ class Exit(Object):
|
|||
|
||||
The command of this cmdset has the same name as the Exit object
|
||||
and allows the exit to react when the player enter the exit's name,
|
||||
triggering the movement between rooms.
|
||||
|
||||
triggering the movement between rooms.
|
||||
|
||||
Note that exitdbobj is an ObjectDB instance. This is necessary
|
||||
for handling reloads and avoid tracebacks if this is called while
|
||||
the typeclass system is rebooting.
|
||||
|
|
@ -821,9 +821,9 @@ class Exit(Object):
|
|||
class ExitCommand(command.Command):
|
||||
"""
|
||||
This is a command that simply cause the caller
|
||||
to traverse the object it is attached to.
|
||||
to traverse the object it is attached to.
|
||||
"""
|
||||
locks = "cmd:all()" # should always be set to this.
|
||||
locks = "cmd:all()" # should always be set to this.
|
||||
obj = None
|
||||
arg_regex=r"\s.*?|$"
|
||||
|
||||
|
|
@ -831,15 +831,15 @@ class Exit(Object):
|
|||
"Default exit traverse if no syscommand is defined."
|
||||
|
||||
if self.obj.access(self.caller, 'traverse'):
|
||||
# we may traverse the exit.
|
||||
# we may traverse the exit.
|
||||
|
||||
old_location = None
|
||||
old_location = None
|
||||
if hasattr(self.caller, "location"):
|
||||
old_location = self.caller.location
|
||||
old_location = self.caller.location
|
||||
|
||||
# call pre/post hooks and move object.
|
||||
self.obj.at_before_traverse(self.caller)
|
||||
self.caller.move_to(self.obj.destination)
|
||||
self.caller.move_to(self.obj.destination)
|
||||
self.obj.at_after_traverse(self.caller, old_location)
|
||||
|
||||
else:
|
||||
|
|
@ -853,7 +853,7 @@ class Exit(Object):
|
|||
# create an exit command.
|
||||
cmd = ExitCommand()
|
||||
cmd.key = exidbobj.db_key.strip().lower()
|
||||
cmd.obj = exidbobj
|
||||
cmd.obj = exidbobj
|
||||
cmd.aliases = exidbobj.aliases
|
||||
cmd.locks = str(exidbobj.locks)
|
||||
cmd.destination = exidbobj.db_destination
|
||||
|
|
@ -861,18 +861,18 @@ class Exit(Object):
|
|||
exit_cmdset = cmdset.CmdSet(None)
|
||||
exit_cmdset.key = '_exitset'
|
||||
exit_cmdset.priority = 9
|
||||
exit_cmdset.duplicates = True
|
||||
# add command to cmdset
|
||||
exit_cmdset.add(cmd)
|
||||
exit_cmdset.duplicates = True
|
||||
# add command to cmdset
|
||||
exit_cmdset.add(cmd)
|
||||
return exit_cmdset
|
||||
|
||||
# Command hooks
|
||||
# Command hooks
|
||||
def basetype_setup(self):
|
||||
"""
|
||||
Setup exit-security
|
||||
|
||||
Don't change this, instead edit at_object_creation() to
|
||||
overload the default locks (it is called after this one).
|
||||
overload the default locks (it is called after this one).
|
||||
"""
|
||||
super(Exit, self).basetype_setup()
|
||||
|
||||
|
|
@ -880,34 +880,34 @@ class Exit(Object):
|
|||
self.locks.add("puppet:false()") # would be weird to puppet an exit ...
|
||||
self.locks.add("traverse:all()") # who can pass through exit by default
|
||||
self.locks.add("get:false()") # noone can pick up the exit
|
||||
|
||||
|
||||
# an exit should have a destination (this is replaced at creation time)
|
||||
if self.dbobj.location:
|
||||
self.destination = self.dbobj.location
|
||||
self.destination = self.dbobj.location
|
||||
|
||||
def at_cmdset_get(self):
|
||||
"""
|
||||
Called when the cmdset is requested from this object, just before the cmdset is
|
||||
Called when the cmdset is requested from this object, just before the cmdset is
|
||||
actually extracted. If no Exit-cmdset is cached, create it now.
|
||||
"""
|
||||
"""
|
||||
|
||||
if self.ndb.exit_reset or not self.cmdset.has_cmdset("_exitset", must_be_default=True):
|
||||
# we are resetting, or no exit-cmdset was set. Create one dynamically.
|
||||
self.cmdset.add_default(self.create_exit_cmdset(self.dbobj), permanent=False)
|
||||
self.ndb.exit_reset = False
|
||||
self.cmdset.add_default(self.create_exit_cmdset(self.dbobj), permanent=False)
|
||||
self.ndb.exit_reset = False
|
||||
|
||||
# this and other hooks are what usually can be modified safely.
|
||||
# this and other hooks are what usually can be modified safely.
|
||||
|
||||
def at_object_creation(self):
|
||||
"Called once, when object is first created (after basetype_setup)."
|
||||
pass
|
||||
pass
|
||||
|
||||
def at_failed_traverse(self, traversing_object):
|
||||
"""
|
||||
This is called if an object fails to traverse this object for some
|
||||
This is called if an object fails to traverse this object for some
|
||||
reason. It will not be called if the attribute "err_traverse" is defined,
|
||||
that attribute will then be echoed back instead as a convenient shortcut.
|
||||
that attribute will then be echoed back instead as a convenient shortcut.
|
||||
|
||||
(See also hooks at_before_traverse and at_after_traverse).
|
||||
(See also hooks at_before_traverse and at_after_traverse).
|
||||
"""
|
||||
traversing_object.msg("You cannot go there.")
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ try:
|
|||
from django.utils.unittest import TestCase
|
||||
except ImportError:
|
||||
from django.test import TestCase
|
||||
try:
|
||||
try:
|
||||
from django.utils import unittest
|
||||
except ImportError:
|
||||
import unittest
|
||||
|
|
@ -47,10 +47,10 @@ class TestObjAttrs(TestCase):
|
|||
self.obj1.db.testattr = self.obj2
|
||||
self.assertEqual(self.obj2 ,self.obj1.db.testattr)
|
||||
self.assertEqual(self.obj2.location, self.obj1.db.testattr.location)
|
||||
|
||||
|
||||
def suite():
|
||||
"""
|
||||
This function is called automatically by the django test runner.
|
||||
This function is called automatically by the django test runner.
|
||||
This also runs the command tests defined in src/commands/default/tests.py.
|
||||
"""
|
||||
tsuite = unittest.TestSuite()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue