Moved object methods up from ObjectDB and mainly onto the typeclass. In the process of converting players in the same way.
This commit is contained in:
parent
302f5bdd81
commit
db512cbbf5
6 changed files with 175 additions and 226 deletions
|
|
@ -823,6 +823,7 @@ class DefaultObject(ObjectDB):
|
||||||
return True
|
return True
|
||||||
# methods inherited from the typeclass system
|
# methods inherited from the typeclass system
|
||||||
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
"""
|
"""
|
||||||
Checks for equality against an id string or another object or user.
|
Checks for equality against an id string or another object or user.
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,9 @@ from django.utils.encoding import smart_str
|
||||||
from src.players.manager import PlayerDBManager
|
from src.players.manager import PlayerDBManager
|
||||||
from src.scripts.models import ScriptDB
|
from src.scripts.models import ScriptDB
|
||||||
from src.typeclasses.models import TypedObject
|
from src.typeclasses.models import TypedObject
|
||||||
from src.typeclasses.attributes import NickHandler
|
|
||||||
from src.scripts.scripthandler import ScriptHandler
|
|
||||||
from src.commands.cmdsethandler import CmdSetHandler
|
|
||||||
from src.commands import cmdhandler
|
from src.commands import cmdhandler
|
||||||
from src.utils import utils, logger
|
from src.utils import utils, logger
|
||||||
from src.utils.utils import to_str, make_iter, lazy_property
|
from src.utils.utils import to_str, make_iter
|
||||||
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
|
@ -111,20 +108,6 @@ class PlayerDB(TypedObject, AbstractUser):
|
||||||
app_label = 'players'
|
app_label = 'players'
|
||||||
verbose_name = 'Player'
|
verbose_name = 'Player'
|
||||||
|
|
||||||
# lazy-loading of handlers
|
|
||||||
@lazy_property
|
|
||||||
def cmdset(self):
|
|
||||||
return CmdSetHandler(self, True)
|
|
||||||
|
|
||||||
@lazy_property
|
|
||||||
def scripts(self):
|
|
||||||
return ScriptHandler(self)
|
|
||||||
|
|
||||||
@lazy_property
|
|
||||||
def nicks(self):
|
|
||||||
return NickHandler(self)
|
|
||||||
|
|
||||||
|
|
||||||
# alias to the objs property
|
# alias to the objs property
|
||||||
def __characters_get(self):
|
def __characters_get(self):
|
||||||
return self.objs
|
return self.objs
|
||||||
|
|
@ -143,7 +126,7 @@ class PlayerDB(TypedObject, AbstractUser):
|
||||||
"""
|
"""
|
||||||
Getter. Allows for value = self.name. Returns a list of cmdset_storage.
|
Getter. Allows for value = self.name. Returns a list of cmdset_storage.
|
||||||
"""
|
"""
|
||||||
storage = _GA(self, "db_cmdset_storage")
|
storage = self.db_cmdset_storage
|
||||||
# we need to check so storage is not None
|
# we need to check so storage is not None
|
||||||
return [path.strip() for path in storage.split(',')] if storage else []
|
return [path.strip() for path in storage.split(',')] if storage else []
|
||||||
|
|
||||||
|
|
@ -168,20 +151,22 @@ class PlayerDB(TypedObject, AbstractUser):
|
||||||
#
|
#
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return smart_str("%s(player %s)" % (_GA(self, "name"), _GA(self, "dbid")))
|
return smart_str("%s(player %s)" % (self.name, self.dbid))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u"%s(player#%s)" % (_GA(self, "name"), _GA(self, "dbid"))
|
return u"%s(player#%s)" % (self.name, self.dbid)
|
||||||
|
|
||||||
#@property
|
#@property
|
||||||
def __username_get(self):
|
def __username_get(self):
|
||||||
return _GA(self, "username")
|
return self.username
|
||||||
|
|
||||||
def __username_set(self, value):
|
def __username_set(self, value):
|
||||||
_SA(self, "username", value)
|
self.username = value
|
||||||
|
self.save(update_fields=["username"])
|
||||||
|
|
||||||
def __username_del(self):
|
def __username_del(self):
|
||||||
_DA(self, "username")
|
del self.username
|
||||||
|
|
||||||
# aliases
|
# aliases
|
||||||
name = property(__username_get, __username_set, __username_del)
|
name = property(__username_get, __username_set, __username_del)
|
||||||
key = property(__username_get, __username_set, __username_del)
|
key = property(__username_get, __username_set, __username_del)
|
||||||
|
|
@ -198,64 +183,10 @@ class PlayerDB(TypedObject, AbstractUser):
|
||||||
raise Exception("User id cannot be deleted!")
|
raise Exception("User id cannot be deleted!")
|
||||||
uid = property(__uid_get, __uid_set, __uid_del)
|
uid = property(__uid_get, __uid_set, __uid_del)
|
||||||
|
|
||||||
#@property
|
|
||||||
#def __is_superuser_get(self):
|
|
||||||
# "Superusers have all permissions."
|
|
||||||
# return self.db_is_superuser
|
|
||||||
# #is_suser = get_prop_cache(self, "_is_superuser")
|
|
||||||
# #if is_suser == None:
|
|
||||||
# # is_suser = _GA(self, "user").is_superuser
|
|
||||||
# # set_prop_cache(self, "_is_superuser", is_suser)
|
|
||||||
# #return is_suser
|
|
||||||
#is_superuser = property(__is_superuser_get)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# PlayerDB class access methods
|
# PlayerDB class access methods
|
||||||
#
|
#
|
||||||
|
|
||||||
def msg(self, text=None, from_obj=None, sessid=None, **kwargs):
|
|
||||||
"""
|
|
||||||
Evennia -> User
|
|
||||||
This is the main route for sending data back to the user from the
|
|
||||||
server.
|
|
||||||
|
|
||||||
outgoing_string (string) - text data to send
|
|
||||||
from_obj (Object/Player) - source object of message to send. Its
|
|
||||||
at_msg_send() hook will be called.
|
|
||||||
sessid - the session id of the session to send to. If not given, return
|
|
||||||
to all sessions connected to this player. This is usually only
|
|
||||||
relevant when using msg() directly from a player-command (from
|
|
||||||
a command on a Character, the character automatically stores
|
|
||||||
and handles the sessid). Can also be a list of sessids.
|
|
||||||
kwargs (dict) - All other keywords are parsed as extra data.
|
|
||||||
"""
|
|
||||||
if "data" in kwargs:
|
|
||||||
# deprecation warning
|
|
||||||
logger.log_depmsg("PlayerDB:msg() 'data'-dict keyword is deprecated. Use **kwargs instead.")
|
|
||||||
data = kwargs.pop("data")
|
|
||||||
if isinstance(data, dict):
|
|
||||||
kwargs.update(data)
|
|
||||||
|
|
||||||
text = to_str(text, force_string=True) if text else ""
|
|
||||||
if from_obj:
|
|
||||||
# call hook
|
|
||||||
try:
|
|
||||||
_GA(from_obj, "at_msg_send")(text=text, to_obj=self, **kwargs)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
sessions = _MULTISESSION_MODE > 1 and sessid and _GA(self, "get_session")(sessid) or None
|
|
||||||
if sessions:
|
|
||||||
for session in make_iter(sessions):
|
|
||||||
obj = session.puppet
|
|
||||||
if obj and not obj.at_msg_receive(text=text, **kwargs):
|
|
||||||
# if hook returns false, cancel send
|
|
||||||
continue
|
|
||||||
session.msg(text=text, **kwargs)
|
|
||||||
else:
|
|
||||||
# if no session was specified, send to them all
|
|
||||||
for sess in _GA(self, 'get_all_sessions')():
|
|
||||||
sess.msg(text=text, **kwargs)
|
|
||||||
|
|
||||||
# session-related methods
|
# session-related methods
|
||||||
|
|
||||||
def get_session(self, sessid):
|
def get_session(self, sessid):
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,13 @@ from src.players.manager import PlayerManager
|
||||||
from src.players.models import PlayerDB
|
from src.players.models import PlayerDB
|
||||||
from src.comms.models import ChannelDB
|
from src.comms.models import ChannelDB
|
||||||
from src.utils import logger
|
from src.utils import logger
|
||||||
__all__ = ("Player",)
|
from src.utils.utils import lazy_property, to_str, make_iter
|
||||||
|
from src.typeclasses.attributes import NickHandler
|
||||||
|
from src.scripts.scripthandler import ScriptHandler
|
||||||
|
from src.commands.cmdsethandler import CmdSetHandler
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ("DefaultPlayer",)
|
||||||
|
|
||||||
_MULTISESSION_MODE = settings.MULTISESSION_MODE
|
_MULTISESSION_MODE = settings.MULTISESSION_MODE
|
||||||
_CMDSET_PLAYER = settings.CMDSET_PLAYER
|
_CMDSET_PLAYER = settings.CMDSET_PLAYER
|
||||||
|
|
@ -26,105 +32,140 @@ _CONNECT_CHANNEL = None
|
||||||
|
|
||||||
class DefaultPlayer(PlayerDB):
|
class DefaultPlayer(PlayerDB):
|
||||||
"""
|
"""
|
||||||
Base typeclass for all Players.
|
This is the base Typeclass for all Players. Players represent
|
||||||
"""
|
the person playing the game and tracks account info, password
|
||||||
|
etc. They are OOC entities without presence in-game. A Player
|
||||||
|
can connect to a Character Object in order to "enter" the
|
||||||
|
game.
|
||||||
|
|
||||||
|
Player Typeclass API:
|
||||||
|
|
||||||
|
* Available properties (only available on initiated typeclass objects)
|
||||||
|
|
||||||
|
key (string) - name of player
|
||||||
|
name (string)- wrapper for user.username
|
||||||
|
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 (Player, read-only) - link to database model. dbobj.typeclass
|
||||||
|
points back to this class
|
||||||
|
typeclass (Player, 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
|
||||||
|
|
||||||
|
user (User, read-only) - django User authorization object
|
||||||
|
obj (Object) - game object controlled by player. 'character' can also
|
||||||
|
be used.
|
||||||
|
sessions (list of Sessions) - sessions connected to this player
|
||||||
|
is_superuser (bool, read-only) - if the connected user is a superuser
|
||||||
|
|
||||||
|
* Handlers
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
|
||||||
|
msg(outgoing_string, from_obj=None, **kwargs)
|
||||||
|
swap_character(new_character, delete_old_character=False)
|
||||||
|
execute_cmd(raw_string)
|
||||||
|
search(ostring, global_search=False, attribute_name=None,
|
||||||
|
use_nicks=False, location=None,
|
||||||
|
ignore_errors=False, player=False)
|
||||||
|
is_typeclass(typeclass, exact=False)
|
||||||
|
swap_typeclass(new_typeclass, clean_attributes=False, no_default=True)
|
||||||
|
access(accessing_obj, access_type='read', default=False)
|
||||||
|
check_permstring(permstring)
|
||||||
|
|
||||||
|
* Hook methods
|
||||||
|
|
||||||
|
basetype_setup()
|
||||||
|
at_player_creation()
|
||||||
|
|
||||||
|
- note that the following hooks are also found on Objects and are
|
||||||
|
usually handled on the character level:
|
||||||
|
|
||||||
|
at_init()
|
||||||
|
at_access()
|
||||||
|
at_cmdset_get(**kwargs)
|
||||||
|
at_first_login()
|
||||||
|
at_post_login(sessid=None)
|
||||||
|
at_disconnect()
|
||||||
|
at_message_receive()
|
||||||
|
at_message_send()
|
||||||
|
at_server_reload()
|
||||||
|
at_server_shutdown()
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
__metaclass__ = TypeclassBase
|
__metaclass__ = TypeclassBase
|
||||||
objects = PlayerManager()
|
objects = PlayerManager()
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
# properties
|
||||||
"""
|
@lazy_property
|
||||||
This is the base Typeclass for all Players. Players represent
|
def cmdset(self):
|
||||||
the person playing the game and tracks account info, password
|
return CmdSetHandler(self, True)
|
||||||
etc. They are OOC entities without presence in-game. A Player
|
|
||||||
can connect to a Character Object in order to "enter" the
|
|
||||||
game.
|
|
||||||
|
|
||||||
Player Typeclass API:
|
@lazy_property
|
||||||
|
def scripts(self):
|
||||||
|
return ScriptHandler(self)
|
||||||
|
|
||||||
* Available properties (only available on initiated typeclass objects)
|
@lazy_property
|
||||||
|
def nicks(self):
|
||||||
|
return NickHandler(self)
|
||||||
|
|
||||||
key (string) - name of player
|
|
||||||
name (string)- wrapper for user.username
|
|
||||||
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 (Player, read-only) - link to database model. dbobj.typeclass
|
|
||||||
points back to this class
|
|
||||||
typeclass (Player, 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
|
|
||||||
|
|
||||||
user (User, read-only) - django User authorization object
|
|
||||||
obj (Object) - game object controlled by player. 'character' can also
|
|
||||||
be used.
|
|
||||||
sessions (list of Sessions) - sessions connected to this player
|
|
||||||
is_superuser (bool, read-only) - if the connected user is a superuser
|
|
||||||
|
|
||||||
* Handlers
|
|
||||||
|
|
||||||
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
|
|
||||||
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
|
|
||||||
|
|
||||||
msg(outgoing_string, from_obj=None, **kwargs)
|
|
||||||
swap_character(new_character, delete_old_character=False)
|
|
||||||
execute_cmd(raw_string)
|
|
||||||
search(ostring, global_search=False, attribute_name=None,
|
|
||||||
use_nicks=False, location=None,
|
|
||||||
ignore_errors=False, player=False)
|
|
||||||
is_typeclass(typeclass, exact=False)
|
|
||||||
swap_typeclass(new_typeclass, clean_attributes=False, no_default=True)
|
|
||||||
access(accessing_obj, access_type='read', default=False)
|
|
||||||
check_permstring(permstring)
|
|
||||||
|
|
||||||
* Hook methods
|
|
||||||
|
|
||||||
basetype_setup()
|
|
||||||
at_player_creation()
|
|
||||||
|
|
||||||
- note that the following hooks are also found on Objects and are
|
|
||||||
usually handled on the character level:
|
|
||||||
|
|
||||||
at_init()
|
|
||||||
at_access()
|
|
||||||
at_cmdset_get(**kwargs)
|
|
||||||
at_first_login()
|
|
||||||
at_post_login(sessid=None)
|
|
||||||
at_disconnect()
|
|
||||||
at_message_receive()
|
|
||||||
at_message_send()
|
|
||||||
at_server_reload()
|
|
||||||
at_server_shutdown()
|
|
||||||
|
|
||||||
"""
|
|
||||||
super(DefaultPlayer, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
## methods inherited from database model
|
## methods inherited from database model
|
||||||
|
|
||||||
def msg(self, text=None, from_obj=None, sessid=None, **kwargs):
|
def msg(self, text=None, from_obj=None, sessid=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Evennia -> User
|
Evennia -> User
|
||||||
This is the main route for sending data back to the user from
|
This is the main route for sending data back to the user from the
|
||||||
the server.
|
server.
|
||||||
|
|
||||||
text (string) - text data to send
|
outgoing_string (string) - text data to send
|
||||||
from_obj (Object/DefaultPlayer) - source object of message to send
|
from_obj (Object/Player) - source object of message to send. Its
|
||||||
sessid - the session id of the session to send to. If not given,
|
at_msg_send() hook will be called.
|
||||||
return to all sessions connected to this player. This is usually only
|
sessid - the session id of the session to send to. If not given, return
|
||||||
relevant when using msg() directly from a player-command (from
|
to all sessions connected to this player. This is usually only
|
||||||
a command on a Character, the character automatically stores and
|
relevant when using msg() directly from a player-command (from
|
||||||
handles the sessid).
|
a command on a Character, the character automatically stores
|
||||||
kwargs - extra data to send through protocol
|
and handles the sessid). Can also be a list of sessids.
|
||||||
|
kwargs (dict) - All other keywords are parsed as extra data.
|
||||||
"""
|
"""
|
||||||
super(DefaultPlayer, self).msg(text=text, from_obj=from_obj, sessid=sessid, **kwargs)
|
if "data" in kwargs:
|
||||||
|
# deprecation warning
|
||||||
|
logger.log_depmsg("PlayerDB:msg() 'data'-dict keyword is deprecated. Use **kwargs instead.")
|
||||||
|
data = kwargs.pop("data")
|
||||||
|
if isinstance(data, dict):
|
||||||
|
kwargs.update(data)
|
||||||
|
|
||||||
|
text = to_str(text, force_string=True) if text else ""
|
||||||
|
if from_obj:
|
||||||
|
# call hook
|
||||||
|
try:
|
||||||
|
from_obj.at_msg_send(text=text, to_obj=self, **kwargs)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
sessions = _MULTISESSION_MODE > 1 and sessid and self.get_session(sessid) or None
|
||||||
|
if sessions:
|
||||||
|
for session in make_iter(sessions):
|
||||||
|
obj = session.puppet
|
||||||
|
if obj and not obj.at_msg_receive(text=text, **kwargs):
|
||||||
|
# if hook returns false, cancel send
|
||||||
|
continue
|
||||||
|
session.msg(text=text, **kwargs)
|
||||||
|
else:
|
||||||
|
# if no session was specified, send to them all
|
||||||
|
for sess in self.get_all_sessions():
|
||||||
|
sess.msg(text=text, **kwargs)
|
||||||
|
|
||||||
def swap_character(self, new_character, delete_old_character=False):
|
def swap_character(self, new_character, delete_old_character=False):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import django
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
from src.players.models import PlayerDB
|
||||||
from src.server.models import ServerConfig
|
from src.server.models import ServerConfig
|
||||||
from src.utils import create
|
from src.utils import create
|
||||||
from src.utils.utils import class_from_module
|
from src.utils.utils import class_from_module
|
||||||
|
|
@ -26,15 +27,14 @@ def get_god_player():
|
||||||
"""
|
"""
|
||||||
Creates the god user.
|
Creates the god user.
|
||||||
"""
|
"""
|
||||||
Player = class_from_module(settings.BASE_PLAYER_TYPECLASS)
|
|
||||||
try:
|
try:
|
||||||
god_player = Player.objects.get(id=1)
|
god_player = PlayerDB.objects.get(id=1)
|
||||||
except Player.DoesNotExist:
|
except PlayerDB.DoesNotExist:
|
||||||
txt = "\n\nNo superuser exists yet. The superuser is the 'owner'"
|
txt = "\n\nNo superuser exists yet. The superuser is the 'owner'\n" \
|
||||||
txt += "\account on the Evennia server. Create a new superuser using"
|
"account on the Evennia server. Create a new superuser using\n" \
|
||||||
txt += "\nthe command"
|
"the command\n\n" \
|
||||||
txt += "\n\n python manage.py createsuperuser"
|
" python manage.py createsuperuser\n\n" \
|
||||||
txt += "\n\nFollow the prompts, then restart the server."
|
"Follow the prompts, then restart the server."
|
||||||
raise Exception(txt)
|
raise Exception(txt)
|
||||||
return god_player
|
return god_player
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ def create_objects():
|
||||||
|
|
||||||
# run all creation hooks on god_player (we must do so manually
|
# run all creation hooks on god_player (we must do so manually
|
||||||
# since the manage.py command does not)
|
# since the manage.py command does not)
|
||||||
god_player.typeclass_path = player_typeclass
|
god_player.swap_typeclass(player_typeclass, clean_attributes=True)
|
||||||
god_player.basetype_setup()
|
god_player.basetype_setup()
|
||||||
god_player.at_player_creation()
|
god_player.at_player_creation()
|
||||||
god_player.locks.add("examine:perm(Immortals);edit:false();delete:false();boot:false();msg:all()")
|
god_player.locks.add("examine:perm(Immortals);edit:false();delete:false();boot:false();msg:all()")
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@ TICKER_HANDLER = None
|
||||||
|
|
||||||
_PERMISSION_HIERARCHY = [p.lower() for p in settings.PERMISSION_HIERARCHY]
|
_PERMISSION_HIERARCHY = [p.lower() for p in settings.PERMISSION_HIERARCHY]
|
||||||
_TYPECLASS_AGGRESSIVE_CACHE = settings.TYPECLASS_AGGRESSIVE_CACHE
|
_TYPECLASS_AGGRESSIVE_CACHE = settings.TYPECLASS_AGGRESSIVE_CACHE
|
||||||
|
_GA = object.__getattribute__
|
||||||
|
_SA = object.__setattr__
|
||||||
|
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
#
|
#
|
||||||
|
|
@ -150,16 +152,12 @@ class TypedObject(SharedMemoryModel):
|
||||||
# Main identifier of the object, for searching. Is accessed with self.key
|
# Main identifier of the object, for searching. Is accessed with self.key
|
||||||
# or self.name
|
# or self.name
|
||||||
db_key = models.CharField('key', max_length=255, db_index=True)
|
db_key = models.CharField('key', max_length=255, db_index=True)
|
||||||
# This is the python path to the type class this object is tied to the
|
# This is the python path to the type class this object is tied to. The
|
||||||
# typeclass is what defines what kind of Object this is)
|
# typeclass is what defines what kind of Object this is)
|
||||||
db_typeclass_path = models.CharField('typeclass', max_length=255, null=True,
|
db_typeclass_path = models.CharField('typeclass', max_length=255, null=True,
|
||||||
help_text="this defines what 'type' of entity this is. This variable holds a Python path to a module with a valid Evennia Typeclass.")
|
help_text="this defines what 'type' of entity this is. This variable holds a Python path to a module with a valid Evennia Typeclass.")
|
||||||
# Creation date. This is not changed once the object is created.
|
# Creation date. This is not changed once the object is created.
|
||||||
db_date_created = models.DateTimeField('creation date', editable=False, auto_now_add=True)
|
db_date_created = models.DateTimeField('creation date', editable=False, auto_now_add=True)
|
||||||
# Permissions (access these through the 'permissions' property)
|
|
||||||
#db_permissions = models.CharField('permissions', max_length=255, blank=True,
|
|
||||||
# help_text="a comma-separated list of text strings checked by
|
|
||||||
# in-game locks. They are often used for hierarchies, such as letting a Player have permission 'Wizards', 'Builders' etc. Character objects use 'Players' by default. Most other objects don't have any permissions.")
|
|
||||||
# Lock storage
|
# Lock storage
|
||||||
db_lock_storage = models.TextField('locks', blank=True,
|
db_lock_storage = models.TextField('locks', blank=True,
|
||||||
help_text="locks limit access to an entity. A lock is defined as a 'lock string' on the form 'type:lockfunctions', defining what functionality is locked and how to determine access. Not defining a lock means no access is granted.")
|
help_text="locks limit access to an entity. A lock is defined as a 'lock string' on the form 'type:lockfunctions', defining what functionality is locked and how to determine access. Not defining a lock means no access is granted.")
|
||||||
|
|
@ -178,6 +176,11 @@ class TypedObject(SharedMemoryModel):
|
||||||
# typeclass mechanism
|
# typeclass mechanism
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
This is the main function of the typeclass system -
|
||||||
|
to dynamically re-apply a class based on the
|
||||||
|
db_typeclass_path rather than use the one in the model.
|
||||||
|
"""
|
||||||
typeclass_path = kwargs.pop("typeclass", None)
|
typeclass_path = kwargs.pop("typeclass", None)
|
||||||
super(TypedObject, self).__init__(*args, **kwargs)
|
super(TypedObject, self).__init__(*args, **kwargs)
|
||||||
if typeclass_path:
|
if typeclass_path:
|
||||||
|
|
@ -250,8 +253,6 @@ class TypedObject(SharedMemoryModel):
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
_typeclass_paths = settings.OBJECT_TYPECLASS_PATHS
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return other and hasattr(other, 'dbid') and self.dbid == other.dbid
|
return other and hasattr(other, 'dbid') and self.dbid == other.dbid
|
||||||
|
|
||||||
|
|
@ -332,16 +333,13 @@ class TypedObject(SharedMemoryModel):
|
||||||
boolean True/False depending on if the swap worked or not.
|
boolean True/False depending on if the swap worked or not.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if callable(new_typeclass):
|
|
||||||
# this is an actual class object - build the path
|
|
||||||
cls = new_typeclass
|
|
||||||
new_typeclass = "%s.%s" % (cls.__module__, cls.__name__)
|
|
||||||
else:
|
|
||||||
new_typeclass = "%s" % to_str(new_typeclass)
|
|
||||||
|
|
||||||
# Try to set the new path
|
if not callable(new_typeclass):
|
||||||
# this will automatically save to database
|
# this is an actual class object - build the path
|
||||||
old_typeclass_path = self.typeclass_path
|
new_typeclass = class_from_module(new_typeclass)
|
||||||
|
|
||||||
|
# if we get to this point, the class is ok.
|
||||||
|
|
||||||
|
|
||||||
if inherits_from(self, "src.scripts.models.ScriptDB"):
|
if inherits_from(self, "src.scripts.models.ScriptDB"):
|
||||||
if self.interval > 0:
|
if self.interval > 0:
|
||||||
|
|
@ -349,15 +347,7 @@ class TypedObject(SharedMemoryModel):
|
||||||
"Script '%s'.\nStop and start a new Script of the " \
|
"Script '%s'.\nStop and start a new Script of the " \
|
||||||
"right type instead." % self.key)
|
"right type instead." % self.key)
|
||||||
|
|
||||||
self.typeclass_path = new_typeclass.strip()
|
self.typeclass_path = new_typeclass.path
|
||||||
# this will automatically use a default class if
|
|
||||||
# there is an error with the given typeclass.
|
|
||||||
new_typeclass = self
|
|
||||||
if self.typeclass_path != new_typeclass.path and no_default:
|
|
||||||
# something went wrong; the default was loaded instead,
|
|
||||||
# and we don't allow that; instead we return to previous.
|
|
||||||
self.typeclass_path = old_typeclass_path
|
|
||||||
return False
|
|
||||||
|
|
||||||
if clean_attributes:
|
if clean_attributes:
|
||||||
# Clean out old attributes
|
# Clean out old attributes
|
||||||
|
|
@ -373,21 +363,7 @@ class TypedObject(SharedMemoryModel):
|
||||||
self.nattributes.clear()
|
self.nattributes.clear()
|
||||||
|
|
||||||
if run_start_hooks:
|
if run_start_hooks:
|
||||||
# run hooks for this new typeclass
|
self.at_instance_creation()
|
||||||
if inherits_from(self, "src.objects.models.ObjectDB"):
|
|
||||||
new_typeclass.basetype_setup()
|
|
||||||
new_typeclass.at_object_creation()
|
|
||||||
elif inherits_from(self, "src.players.models.PlayerDB"):
|
|
||||||
new_typeclass.basetype_setup()
|
|
||||||
new_typeclass.at_player_creation()
|
|
||||||
elif inherits_from(self, "src.scripts.models.ScriptDB"):
|
|
||||||
new_typeclass.at_script_creation()
|
|
||||||
new_typeclass.start()
|
|
||||||
elif inherits_from(self, "src.channels.models.Channel"):
|
|
||||||
# channels do no initial setup
|
|
||||||
pass
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Lock / permission methods
|
# Lock / permission methods
|
||||||
|
|
@ -493,25 +469,25 @@ class TypedObject(SharedMemoryModel):
|
||||||
class DbHolder(object):
|
class DbHolder(object):
|
||||||
"Holder for allowing property access of attributes"
|
"Holder for allowing property access of attributes"
|
||||||
def __init__(self, obj):
|
def __init__(self, obj):
|
||||||
self.attrhandler = obj.attributes
|
_SA(self, "attrhandler", obj.attributes)
|
||||||
|
|
||||||
def __getattribute__(self, attrname):
|
def __getattribute__(self, attrname):
|
||||||
if attrname == 'all':
|
if attrname == 'all':
|
||||||
# we allow to overload our default .all
|
# we allow to overload our default .all
|
||||||
attr = self.attrhandler.get("all")
|
attr = _GA(self, "attrhandler").get("all")
|
||||||
if attr:
|
if attr:
|
||||||
return attr
|
return attr
|
||||||
return self.all
|
return self.all
|
||||||
return self.attrhandler.get(attrname)
|
return _GA(self, "attrhandler").get(attrname)
|
||||||
|
|
||||||
def __setattr__(self, attrname, value):
|
def __setattr__(self, attrname, value):
|
||||||
self.attrhandler.add(attrname, value)
|
_GA(self, "attrhandler").add(attrname, value)
|
||||||
|
|
||||||
def __delattr__(self, attrname):
|
def __delattr__(self, attrname):
|
||||||
self.attrhandler.remove(attrname)
|
_GA(self, "attrhandler").remove(attrname)
|
||||||
|
|
||||||
def get_all(self):
|
def get_all(self):
|
||||||
return self.attrhandler.all()
|
return _GA(self, "attrhandler").all()
|
||||||
all = property(get_all)
|
all = property(get_all)
|
||||||
self._db_holder = DbHolder(self)
|
self._db_holder = DbHolder(self)
|
||||||
return self._db_holder
|
return self._db_holder
|
||||||
|
|
@ -547,25 +523,25 @@ class TypedObject(SharedMemoryModel):
|
||||||
class NDbHolder(object):
|
class NDbHolder(object):
|
||||||
"Holder for allowing property access of attributes"
|
"Holder for allowing property access of attributes"
|
||||||
def __init__(self, obj):
|
def __init__(self, obj):
|
||||||
self.nattrhandler = obj.nattributes
|
_SA(self, "nattrhandler", obj.nattributes)
|
||||||
|
|
||||||
def __getattribute__(self, attrname):
|
def __getattribute__(self, attrname):
|
||||||
if attrname == 'all':
|
if attrname == 'all':
|
||||||
# we allow to overload our default .all
|
# we allow to overload our default .all
|
||||||
attr = self.nattrhandler.get('all')
|
attr = _GA(self, "nattrhandler").get('all')
|
||||||
if attr:
|
if attr:
|
||||||
return attr
|
return attr
|
||||||
return self.all
|
return self.all
|
||||||
return self.nattrhandler.get(attrname)
|
return _GA(self, "nattrhandler").get(attrname)
|
||||||
|
|
||||||
def __setattr__(self, attrname, value):
|
def __setattr__(self, attrname, value):
|
||||||
self.nattrhandler.add(attrname, value)
|
_GA(self, "nattrhandler").add(attrname, value)
|
||||||
|
|
||||||
def __delattr__(self, attrname):
|
def __delattr__(self, attrname):
|
||||||
self.nattrhandler.remove(attrname)
|
_GA(self, "nattrhandler").remove(attrname)
|
||||||
|
|
||||||
def get_all(self):
|
def get_all(self):
|
||||||
return self.nattrhandler.all()
|
return _GA(self, "nattrhandler").all()
|
||||||
all = property(get_all)
|
all = property(get_all)
|
||||||
self._ndb_holder = NDbHolder(self)
|
self._ndb_holder = NDbHolder(self)
|
||||||
return self._ndb_holder
|
return self._ndb_holder
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ def pack_dbobj(item):
|
||||||
_init_globals()
|
_init_globals()
|
||||||
obj = hasattr(item, 'dbobj') and item.dbobj or item
|
obj = hasattr(item, 'dbobj') and item.dbobj or item
|
||||||
natural_key = _FROM_MODEL_MAP[hasattr(obj, "id") and hasattr(obj, "db_date_created") and
|
natural_key = _FROM_MODEL_MAP[hasattr(obj, "id") and hasattr(obj, "db_date_created") and
|
||||||
hasattr(obj, '__class__') and obj.__class__.__name__.lower()]
|
hasattr(obj, '__dbclass__') and obj.__dbclass__.__name__.lower()]
|
||||||
# build the internal representation as a tuple
|
# build the internal representation as a tuple
|
||||||
# ("__packed_dbobj__", key, creation_time, id)
|
# ("__packed_dbobj__", key, creation_time, id)
|
||||||
return natural_key and ('__packed_dbobj__', natural_key,
|
return natural_key and ('__packed_dbobj__', natural_key,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue