OBS: Run migrate! Made exit's destination into a database field for performance. Fixed a too greedy @reload that caused ContentTypes to loose information. Resolves issue 157.

Migrate with: "python manage.py migrate"
This commit is contained in:
Griatch 2011-04-08 23:10:04 +00:00
parent 0cff54f136
commit 6c53ec2bdb
11 changed files with 227 additions and 84 deletions

View file

@ -70,7 +70,7 @@ class ExitHandler(object):
# use exits to create searchable "commands" for the cmdhandler
for exi in (exi for exi in location.contents
if exi.has_attribute('_destination')):
if exi.destination):
if exi.id in self.cached_exit_cmds:
# retrieve from cache
exit_cmdset.add(self.cached_exit_cmds[exi.id])
@ -81,7 +81,7 @@ class ExitHandler(object):
cmd.obj = exi
if exi.aliases:
cmd.aliases = exi.aliases
cmd.destination = exi.attr('_destination')
cmd.destination = exi.destination
exit_cmdset.add(cmd)
self.cached_exit_cmds[exi.id] = cmd
return exit_cmdset

View file

@ -0,0 +1,113 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
from src.objects.models import ObjectDB
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'ObjectDB.db_destination'
db.add_column('objects_objectdb', 'db_destination', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='destinations_set', null=True, to=orm['objects.ObjectDB']), keep_default=False)
# move all exits to the new property
for exi in ObjectDB.objects.get_objs_with_attr('_destination'):
exi.destination = exi.db._destination
exi.del_attribute('_destination')
def backwards(self, orm):
# Deleting field 'ObjectDB.db_destination'
db.delete_column('objects_objectdb', 'db_destination_id')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'objects.alias': {
'Meta': {'object_name': 'Alias'},
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'objects.nick': {
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'Nick'},
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']"}),
'db_real': ('django.db.models.fields.TextField', [], {}),
'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'objects.objattribute': {
'Meta': {'object_name': 'ObjAttribute'},
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']"}),
'db_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'objects.objectdb': {
'Meta': {'object_name': 'ObjectDB'},
'db_cmdset_storage': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'players.playerdb': {
'Meta': {'object_name': 'PlayerDB'},
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']", 'null': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
}
}
complete_apps = ['objects']

View file

@ -217,6 +217,9 @@ class ObjectDB(TypedObject):
# a safety location, this usually don't change much.
db_home = models.ForeignKey('self', related_name="homes_set",
blank=True, null=True)
# destination of this object - primarily used by exits.
db_destination = models.ForeignKey('self', related_name="destinations_set",
blank=True, null=True)
# database storage of persistant cmdsets.
db_cmdset_storage = models.TextField(null=True)
@ -325,6 +328,7 @@ class ObjectDB(TypedObject):
def location_del(self):
"Deleter. Allows for del self.location"
self.db_location = None
self.save()
location = property(location_get, location_set, location_del)
# home property (wraps db_home)
@ -362,8 +366,48 @@ class ObjectDB(TypedObject):
def home_del(self):
"Deleter. Allows for del self.home."
self.db_home = None
self.save()
home = property(home_get, home_set, home_del)
# destination property (wraps db_destination)
#@property
def destination_get(self):
"Getter. Allows for value = self.destination."
dest = self.db_destination
if dest:
return dest.typeclass(dest)
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
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
self.db_destination = dest
self.save()
except Exception:
string = "Cannot set destination: "
string += "%s is not a valid destination."
self.msg(string % destination)
logger.log_trace(string)
raise
#@destination.deleter
def destination_del(self):
"Deleter. Allows for del self.destination"
self.db_destination = None
self.save()
destination = property(destination_get, destination_set, destination_del)
#@property for consistent aliases access throughout Evennia
#@aliases.setter
def aliases_set(self, aliases):
@ -462,10 +506,10 @@ class ObjectDB(TypedObject):
def exits_get(self):
"""
Returns all exits from this object, i.e. all objects
at this location having the property _destination.
at this location having the property destination != None.
"""
return [exi for exi in self.contents
if exi.has_attribute('_destination')]
if exi.destination]
exits = property(exits_get)
@ -589,8 +633,8 @@ class ObjectDB(TypedObject):
Moves this object to a new location.
destination: (Object) Reference to the object to move to. This
can also be an exit object, in which case the _destination
attribute is used as destination.
can also be an exit object, in which case the 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
"""
@ -601,9 +645,9 @@ class ObjectDB(TypedObject):
if not destination:
emit_to_obj.msg("The destination doesn't exist.")
return
if destination.has_attribute('_destination'):
if destination.destination:
# traverse exits
destination = destination.get_attribute('_destination')
destination = destination.destination
# Before the move, call eventual pre-commands.
try:
@ -689,8 +733,7 @@ class ObjectDB(TypedObject):
"""
for out_exit in self.exits:
out_exit.delete()
for in_exit in \
ObjectDB.objects.get_objs_with_attr_match('_destination', self):
for in_exit in ObjectDB.objects.filter(db_destination=self):
in_exit.delete()
def clear_contents(self):

View file

@ -128,7 +128,7 @@ class Object(TypeClass):
loc_name = self.location.name
dest_name = destination.name
string = "%s is leaving %s, heading for %s."
self.location.emit_to_contents(string % (name, loc_name, dest_name), exclude=self)
self.location.msg_contents(string % (name, loc_name, dest_name), exclude=self)
def announce_move_to(self, source_location):
"""
@ -143,7 +143,7 @@ class Object(TypeClass):
# 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.emit_to(string)
self.location.msg(string)
return
src_name = "nowhere"
@ -151,7 +151,7 @@ class Object(TypeClass):
if source_location:
src_name = source_location.name
string = "%s arrives to %s from %s."
self.location.emit_to_contents(string % (name, loc_name, src_name), exclude=self)
self.location.msg_contents(string % (name, loc_name, src_name), exclude=self)
def at_after_move(self, source_location):
@ -203,7 +203,7 @@ class Object(TypeClass):
if content == pobject:
continue
name = content.name
if content.attr('_destination'):
if content.destination:
exits.append(name)
elif content.has_player:
users.append(name)
@ -360,12 +360,12 @@ class Exit(Object):
"""
This is the base exit object - it connects a location
to another. What separates it from other objects
is that it has the '_destination' attribute defined.
Note that _destination is the only identifier to
separate an exit from normal objects, so if _destination
is that it has the 'destination' property defined.
Note that property is the only identifier to
separate an exit from normal objects, so if the property
is removed, it will be treated like any other object. This
also means that any object can be made an exit by setting
the attribute _destination to a valid location
the property destination to a valid location
('Quack like a duck...' and so forth).
"""
def basetype_setup(self):
@ -379,13 +379,17 @@ class Exit(Object):
def at_object_creation(self):
"""
An example just for show; the _destination attribute
An example just for show; the destination property
is usually set at creation time, not as part of the class
definition (unless you want an entire class of exits
all leadning to the same hard-coded place ...)
"""
# this is what makes it an exit
self.attr("_destination", "None")
# having destination != None is what makes it an exit
# (what's set here won't last)
if self.location:
self.destination = self.location
else:
self.destination = 2 # use limbo as a failsafe
def at_object_delete(self):
"""