mirror of
https://github.com/evennia/evennia.git
synced 2026-04-01 13:37:17 +02:00
Reshuffling the Evennia package into the new template paradigm.
This commit is contained in:
parent
2846e64833
commit
2b3a32e447
371 changed files with 17250 additions and 304 deletions
|
|
@ -1,178 +0,0 @@
|
|||
"""
|
||||
This module defines the database models for all in-game objects, that
|
||||
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
|
||||
in question. Objects created of this class transparently communicate
|
||||
with its related database object for storing all attributes. The
|
||||
admin should usually not have to deal directly with this database
|
||||
object layer.
|
||||
|
||||
Attributes are separate objects that store values persistently onto
|
||||
the database object. Like everything else, they can be accessed
|
||||
transparently through the decorating TypeClass.
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
from src.typeclasses.models import TypedObject
|
||||
from src.objects.manager import ObjectDBManager
|
||||
from src.utils import logger
|
||||
from src.utils.utils import (make_iter, dbref)
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
# ObjectDB
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
|
||||
class ObjectDB(TypedObject):
|
||||
"""
|
||||
All objects in the game use the ObjectDB model to store
|
||||
data in the database. This is handled transparently through
|
||||
the typeclass system.
|
||||
|
||||
Note that the base objectdb is very simple, with
|
||||
few defined fields. Use attributes to extend your
|
||||
type class with new database-stored variables.
|
||||
|
||||
The TypedObject supplies the following (inherited) properties:
|
||||
key - main name
|
||||
name - alias for key
|
||||
typeclass_path - the path to the decorating typeclass
|
||||
typeclass - auto-linked typeclass
|
||||
date_created - time stamp of object creation
|
||||
permissions - perm strings
|
||||
locks - lock definitions (handler)
|
||||
dbref - #id of object
|
||||
db - persistent attribute storage
|
||||
ndb - non-persistent attribute storage
|
||||
|
||||
The ObjectDB adds the following properties:
|
||||
player - optional connected player (always together with sessid)
|
||||
sessid - optional connection session id (always together with player)
|
||||
location - in-game location of object
|
||||
home - safety location for object (handler)
|
||||
|
||||
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)
|
||||
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
|
||||
exits - exits from this object
|
||||
"""
|
||||
#
|
||||
# ObjectDB Database model setup
|
||||
#
|
||||
#
|
||||
# inherited fields (from TypedObject):
|
||||
# db_key (also 'name' works), db_typeclass_path, db_date_created,
|
||||
# db_permissions
|
||||
#
|
||||
# These databse fields (including the inherited ones) should normally be
|
||||
# managed by their corresponding wrapper properties, named same as the
|
||||
# field, but without the db_* prefix (e.g. the db_key field is set with
|
||||
# self.key instead). The wrappers are created at the metaclass level and
|
||||
# will automatically save and cache the data more efficiently.
|
||||
|
||||
# If this is a character object, the player is connected here.
|
||||
db_player = models.ForeignKey("players.PlayerDB", null=True, verbose_name='player', on_delete=models.SET_NULL,
|
||||
help_text='a Player connected to this object, if any.')
|
||||
# the session id associated with this player, if any
|
||||
db_sessid = models.CommaSeparatedIntegerField(null=True, max_length=32, verbose_name="session id",
|
||||
help_text="csv list of session ids of connected Player, 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.
|
||||
db_location = models.ForeignKey('self', related_name="locations_set", db_index=True, on_delete=models.SET_NULL,
|
||||
blank=True, null=True, verbose_name='game location')
|
||||
# a safety location, this usually don't change much.
|
||||
db_home = models.ForeignKey('self', related_name="homes_set", on_delete=models.SET_NULL,
|
||||
blank=True, null=True, verbose_name='home location')
|
||||
# destination of this object - primarily used by exits.
|
||||
db_destination = models.ForeignKey('self', related_name="destinations_set", db_index=True, on_delete=models.SET_NULL,
|
||||
blank=True, null=True, verbose_name='destination',
|
||||
help_text='a destination, used only by exit objects.')
|
||||
# database storage of persistant cmdsets.
|
||||
db_cmdset_storage = models.CharField('cmdset', max_length=255, null=True, blank=True,
|
||||
help_text="optional python path to a cmdset class.")
|
||||
|
||||
# Database manager
|
||||
objects = ObjectDBManager()
|
||||
|
||||
# cmdset_storage property handling
|
||||
def __cmdset_storage_get(self):
|
||||
"getter"
|
||||
storage = self.db_cmdset_storage
|
||||
return [path.strip() for path in storage.split(',')] if storage else []
|
||||
|
||||
def __cmdset_storage_set(self, value):
|
||||
"setter"
|
||||
self.db_cmdset_storage = ",".join(str(val).strip() for val in make_iter(value))
|
||||
self.save(update_fields=["db_cmdset_storage"])
|
||||
|
||||
def __cmdset_storage_del(self):
|
||||
"deleter"
|
||||
self.db_cmdset_storage = None
|
||||
self.save(update_fields=["db_cmdset_storage"])
|
||||
cmdset_storage = property(__cmdset_storage_get, __cmdset_storage_set, __cmdset_storage_del)
|
||||
|
||||
# location getsetter
|
||||
def __location_get(self):
|
||||
"Get location"
|
||||
return self.db_location
|
||||
|
||||
def __location_set(self, location):
|
||||
"Set location, checking for loops and allowing dbref"
|
||||
if isinstance(location, (basestring, int)):
|
||||
# allow setting of #dbref
|
||||
dbid = dbref(location, reqhash=False)
|
||||
if dbid:
|
||||
try:
|
||||
location = ObjectDB.objects.get(id=dbid)
|
||||
except ObjectDoesNotExist:
|
||||
# maybe it is just a name that happens to look like a dbid
|
||||
pass
|
||||
try:
|
||||
def is_loc_loop(loc, depth=0):
|
||||
"Recursively traverse target location, trying to catch a loop."
|
||||
if depth > 10:
|
||||
return
|
||||
elif loc == self:
|
||||
raise RuntimeError
|
||||
elif loc == None:
|
||||
raise RuntimeWarning
|
||||
return is_loc_loop(loc.db_location, depth + 1)
|
||||
try:
|
||||
is_loc_loop(location)
|
||||
except RuntimeWarning:
|
||||
pass
|
||||
# actually set the field
|
||||
self.db_location = location
|
||||
self.save(update_fields=["db_location"])
|
||||
except RuntimeError:
|
||||
errmsg = "Error: %s.location = %s creates a location loop." % (self.key, location)
|
||||
logger.log_errmsg(errmsg)
|
||||
raise RuntimeError(errmsg)
|
||||
except Exception, e:
|
||||
errmsg = "Error (%s): %s is not a valid location." % (str(e), location)
|
||||
logger.log_errmsg(errmsg)
|
||||
raise Exception(errmsg)
|
||||
|
||||
def __location_del(self):
|
||||
"Cleanly delete the location reference"
|
||||
self.db_location = None
|
||||
self.save(update_fields=["db_location"])
|
||||
location = property(__location_get, __location_set, __location_del)
|
||||
|
||||
class Meta:
|
||||
"Define Django meta options"
|
||||
verbose_name = "Object"
|
||||
verbose_name_plural = "Objects"
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue