Fixed the entire first_init script process with the new typeclass system.
This commit is contained in:
parent
11449f3d62
commit
b839614259
6 changed files with 114 additions and 121 deletions
|
|
@ -45,9 +45,74 @@ class Channel(ChannelDB):
|
||||||
if cdict["desc"]:
|
if cdict["desc"]:
|
||||||
self.attributes.add("desc", cdict["desc"])
|
self.attributes.add("desc", cdict["desc"])
|
||||||
|
|
||||||
|
def at_channel_creation(self):
|
||||||
|
"""
|
||||||
|
Called once, when the channel is first created.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
# helper methods, for easy overloading
|
# helper methods, for easy overloading
|
||||||
|
|
||||||
|
def has_connection(self, player):
|
||||||
|
"""
|
||||||
|
Checks so this player is actually listening
|
||||||
|
to this channel.
|
||||||
|
"""
|
||||||
|
if hasattr(player, "player"):
|
||||||
|
player = player.player
|
||||||
|
player = player.dbobj
|
||||||
|
return player in self.db_subscriptions.all()
|
||||||
|
|
||||||
|
def connect(self, player):
|
||||||
|
"Connect the user to this channel. This checks access."
|
||||||
|
if hasattr(player, "player"):
|
||||||
|
player = player.player
|
||||||
|
# check access
|
||||||
|
if not self.access(player, 'listen'):
|
||||||
|
return False
|
||||||
|
# pre-join hook
|
||||||
|
connect = self.pre_join_channel(player)
|
||||||
|
if not connect:
|
||||||
|
return False
|
||||||
|
# subscribe
|
||||||
|
self.db_subscriptions.add(player)
|
||||||
|
# post-join hook
|
||||||
|
self.post_join_channel(player)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def disconnect(self, player):
|
||||||
|
"Disconnect user from this channel."
|
||||||
|
if hasattr(player, "player"):
|
||||||
|
player = player.player
|
||||||
|
# pre-disconnect hook
|
||||||
|
disconnect = self.pre_leave_channel(player)
|
||||||
|
if not disconnect:
|
||||||
|
return False
|
||||||
|
# disconnect
|
||||||
|
self.db_subscriptions.remove(player.dbobj)
|
||||||
|
# post-disconnect hook
|
||||||
|
self.post_leave_channel(player.dbobj)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def access(self, accessing_obj, access_type='listen', default=False):
|
||||||
|
"""
|
||||||
|
Determines if another object has permission to access.
|
||||||
|
accessing_obj - object trying to access this one
|
||||||
|
access_type - type of access sought
|
||||||
|
default - what to return if no lock of access_type was found
|
||||||
|
"""
|
||||||
|
return self.locks.check(accessing_obj, access_type=access_type, default=default)
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
"""
|
||||||
|
Deletes channel while also cleaning up channelhandler
|
||||||
|
"""
|
||||||
|
self.attributes.clear()
|
||||||
|
self.aliases.clear()
|
||||||
|
super(Channel, self).delete()
|
||||||
|
from src.comms.channelhandler import CHANNELHANDLER
|
||||||
|
CHANNELHANDLER.update()
|
||||||
|
|
||||||
def channel_prefix(self, msg=None, emit=False):
|
def channel_prefix(self, msg=None, emit=False):
|
||||||
"""
|
"""
|
||||||
How the channel should prefix itself for users. Return a string.
|
How the channel should prefix itself for users. Return a string.
|
||||||
|
|
@ -134,12 +199,6 @@ class Channel(ChannelDB):
|
||||||
msg.message = body
|
msg.message = body
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def at_channel_create(self):
|
|
||||||
"""
|
|
||||||
Run at channel creation.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def pre_join_channel(self, joiner):
|
def pre_join_channel(self, joiner):
|
||||||
"""
|
"""
|
||||||
Run right before a channel is joined. If this returns a false value,
|
Run right before a channel is joined. If this returns a false value,
|
||||||
|
|
|
||||||
|
|
@ -363,69 +363,5 @@ class ChannelDB(TypedObject):
|
||||||
verbose_name = "Channel"
|
verbose_name = "Channel"
|
||||||
verbose_name_plural = "Channels"
|
verbose_name_plural = "Channels"
|
||||||
|
|
||||||
#
|
|
||||||
# Channel class methods
|
|
||||||
#
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Channel '%s' (%s)" % (self.key, self.db.desc)
|
return "Channel '%s' (%s)" % (self.key, self.db.desc)
|
||||||
|
|
||||||
def has_connection(self, player):
|
|
||||||
"""
|
|
||||||
Checks so this player is actually listening
|
|
||||||
to this channel.
|
|
||||||
"""
|
|
||||||
if hasattr(player, "player"):
|
|
||||||
player = player.player
|
|
||||||
player = player.dbobj
|
|
||||||
return player in self.db_subscriptions.all()
|
|
||||||
|
|
||||||
def connect(self, player):
|
|
||||||
"Connect the user to this channel. This checks access."
|
|
||||||
if hasattr(player, "player"):
|
|
||||||
player = player.player
|
|
||||||
# check access
|
|
||||||
if not self.access(player, 'listen'):
|
|
||||||
return False
|
|
||||||
# pre-join hook
|
|
||||||
connect = self.pre_join_channel(player)
|
|
||||||
if not connect:
|
|
||||||
return False
|
|
||||||
# subscribe
|
|
||||||
self.db_subscriptions.add(player.dbobj)
|
|
||||||
# post-join hook
|
|
||||||
self.post_join_channel(player)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def disconnect(self, player):
|
|
||||||
"Disconnect user from this channel."
|
|
||||||
if hasattr(player, "player"):
|
|
||||||
player = player.player
|
|
||||||
# pre-disconnect hook
|
|
||||||
disconnect = self.pre_leave_channel(player)
|
|
||||||
if not disconnect:
|
|
||||||
return False
|
|
||||||
# disconnect
|
|
||||||
self.db_subscriptions.remove(player.dbobj)
|
|
||||||
# post-disconnect hook
|
|
||||||
self.post_leave_channel(player.dbobj)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def access(self, accessing_obj, access_type='listen', default=False):
|
|
||||||
"""
|
|
||||||
Determines if another object has permission to access.
|
|
||||||
accessing_obj - object trying to access this one
|
|
||||||
access_type - type of access sought
|
|
||||||
default - what to return if no lock of access_type was found
|
|
||||||
"""
|
|
||||||
return self.locks.check(accessing_obj, access_type=access_type, default=default)
|
|
||||||
|
|
||||||
def delete(self):
|
|
||||||
"""
|
|
||||||
Deletes channel while also cleaning up channelhandler
|
|
||||||
"""
|
|
||||||
_GA(self, "attributes").clear()
|
|
||||||
_GA(self, "aliases").clear()
|
|
||||||
super(ChannelDB, self).delete()
|
|
||||||
from src.comms.channelhandler import CHANNELHANDLER
|
|
||||||
CHANNELHANDLER.update()
|
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ class ScriptDB(TypedObject):
|
||||||
#
|
#
|
||||||
# ScriptDB Database Model setup
|
# ScriptDB Database Model setup
|
||||||
#
|
#
|
||||||
# These databse fields are all set using their corresponding properties,
|
# These database fields are all set using their corresponding properties,
|
||||||
# named same as the field, but withtou the db_* prefix.
|
# named same as the field, but withtou the db_* prefix.
|
||||||
|
|
||||||
# inherited fields (from TypedObject):
|
# inherited fields (from TypedObject):
|
||||||
|
|
@ -100,10 +100,6 @@ class ScriptDB(TypedObject):
|
||||||
# Database manager
|
# Database manager
|
||||||
objects = ScriptDBManager()
|
objects = ScriptDBManager()
|
||||||
|
|
||||||
# caches for quick lookups
|
|
||||||
_typeclass_paths = settings.SCRIPT_TYPECLASS_PATHS
|
|
||||||
_default_typeclass_path = settings.BASE_SCRIPT_TYPECLASS or "src.scripts.scripts.DoNothing"
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"Define Django meta options"
|
"Define Django meta options"
|
||||||
verbose_name = "Script"
|
verbose_name = "Script"
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ class ScriptBase(ScriptDB):
|
||||||
if self.db._paused_time:
|
if self.db._paused_time:
|
||||||
# the script was paused; restarting
|
# the script was paused; restarting
|
||||||
callcount = self.db._paused_callcount or 0
|
callcount = self.db._paused_callcount or 0
|
||||||
self.ndb._task.start(self.dbobj.db_interval,
|
self.ndb._task.start(self.db_interval,
|
||||||
now=False,
|
now=False,
|
||||||
start_delay=self.db._paused_time,
|
start_delay=self.db._paused_time,
|
||||||
count_start=callcount)
|
count_start=callcount)
|
||||||
|
|
@ -143,8 +143,8 @@ class ScriptBase(ScriptDB):
|
||||||
del self.db._paused_repeats
|
del self.db._paused_repeats
|
||||||
else:
|
else:
|
||||||
# starting script anew
|
# starting script anew
|
||||||
self.ndb._task.start(self.dbobj.db_interval,
|
self.ndb._task.start(self.db_interval,
|
||||||
now=not self.dbobj.db_start_delay)
|
now=not self.db_start_delay)
|
||||||
|
|
||||||
def _stop_task(self):
|
def _stop_task(self):
|
||||||
"stop task runner"
|
"stop task runner"
|
||||||
|
|
@ -159,7 +159,7 @@ class ScriptBase(ScriptDB):
|
||||||
{"key": self.key, "dbid": self.dbid, "cname": cname,
|
{"key": self.key, "dbid": self.dbid, "cname": cname,
|
||||||
"err": e.getErrorMessage()}
|
"err": e.getErrorMessage()}
|
||||||
try:
|
try:
|
||||||
self.dbobj.db_obj.msg(estring)
|
self.db_obj.msg(estring)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
logger.log_errmsg(estring)
|
logger.log_errmsg(estring)
|
||||||
|
|
@ -176,7 +176,7 @@ class ScriptBase(ScriptDB):
|
||||||
|
|
||||||
# check repeats
|
# check repeats
|
||||||
callcount = self.ndb._task.callcount
|
callcount = self.ndb._task.callcount
|
||||||
maxcount = self.dbobj.db_repeats
|
maxcount = self.db_repeats
|
||||||
if maxcount > 0 and maxcount <= callcount:
|
if maxcount > 0 and maxcount <= callcount:
|
||||||
#print "stopping script!"
|
#print "stopping script!"
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
@ -210,7 +210,7 @@ class ScriptBase(ScriptDB):
|
||||||
"Get the number of returning repeats. Returns None if unlimited repeats."
|
"Get the number of returning repeats. Returns None if unlimited repeats."
|
||||||
task = self.ndb._task
|
task = self.ndb._task
|
||||||
if task:
|
if task:
|
||||||
return max(0, self.dbobj.db_repeats - task.callcount)
|
return max(0, self.db_repeats - task.callcount)
|
||||||
|
|
||||||
def start(self, force_restart=False):
|
def start(self, force_restart=False):
|
||||||
"""
|
"""
|
||||||
|
|
@ -224,10 +224,7 @@ class ScriptBase(ScriptDB):
|
||||||
Used in counting.
|
Used in counting.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#print "Script %s (%s) start (active:%s, force:%s) ..." % (self.key, id(self.dbobj),
|
if self.is_active and not force_restart:
|
||||||
# self.is_active, force_restart)
|
|
||||||
|
|
||||||
if self.dbobj.is_active and not force_restart:
|
|
||||||
# script already runs and should not be restarted.
|
# script already runs and should not be restarted.
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
@ -235,11 +232,11 @@ class ScriptBase(ScriptDB):
|
||||||
if obj:
|
if obj:
|
||||||
# check so the scripted object is valid and initalized
|
# check so the scripted object is valid and initalized
|
||||||
try:
|
try:
|
||||||
_GA(obj.dbobj, 'cmdset')
|
obj.cmdset
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# this means the object is not initialized.
|
# this means the object is not initialized.
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
self.dbobj.is_active = False
|
self.is_active = False
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
# try to restart a paused script
|
# try to restart a paused script
|
||||||
|
|
@ -247,13 +244,13 @@ class ScriptBase(ScriptDB):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# start the script from scratch
|
# start the script from scratch
|
||||||
self.dbobj.is_active = True
|
self.is_active = True
|
||||||
try:
|
try:
|
||||||
self.at_start()
|
self.at_start()
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
|
|
||||||
if self.dbobj.db_interval > 0:
|
if self.db_interval > 0:
|
||||||
self._start_task()
|
self._start_task()
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
@ -274,7 +271,7 @@ class ScriptBase(ScriptDB):
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
self._stop_task()
|
self._stop_task()
|
||||||
try:
|
try:
|
||||||
self.dbobj.delete()
|
self.delete()
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
return 0
|
return 0
|
||||||
|
|
@ -292,7 +289,7 @@ class ScriptBase(ScriptDB):
|
||||||
self.db._paused_time = task.next_call_time()
|
self.db._paused_time = task.next_call_time()
|
||||||
self.db._paused_callcount = task.callcount
|
self.db._paused_callcount = task.callcount
|
||||||
self._stop_task()
|
self._stop_task()
|
||||||
self.dbobj.is_active = False
|
self.is_active = False
|
||||||
|
|
||||||
def unpause(self):
|
def unpause(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -300,7 +297,7 @@ class ScriptBase(ScriptDB):
|
||||||
"""
|
"""
|
||||||
if self.db._paused_time:
|
if self.db._paused_time:
|
||||||
# only unpause if previously paused
|
# only unpause if previously paused
|
||||||
self.dbobj.is_active = True
|
self.is_active = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.at_start()
|
self.at_start()
|
||||||
|
|
@ -364,10 +361,6 @@ class Script(ScriptBase):
|
||||||
aliases (list of strings) - aliases to the object. Will be saved to
|
aliases (list of strings) - aliases to the object. Will be saved to
|
||||||
database as AliasDB entries but returned as strings.
|
database as AliasDB entries but returned as strings.
|
||||||
dbref (int, read-only) - unique #id-number. Also "id" can be used.
|
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
|
date_created (string) - time stamp of object creation
|
||||||
permissions (list of strings) - list of permission strings
|
permissions (list of strings) - list of permission strings
|
||||||
|
|
||||||
|
|
@ -441,7 +434,7 @@ class Script(ScriptBase):
|
||||||
Generally, you don't need to overload this, but only the hooks
|
Generally, you don't need to overload this, but only the hooks
|
||||||
called by this method.
|
called by this method.
|
||||||
"""
|
"""
|
||||||
self.at_script_creation(self)
|
self.at_script_creation()
|
||||||
|
|
||||||
if hasattr(self, "_createdict"):
|
if hasattr(self, "_createdict"):
|
||||||
# this will only be set if the utils.create_script
|
# this will only be set if the utils.create_script
|
||||||
|
|
@ -470,14 +463,6 @@ class Script(ScriptBase):
|
||||||
updates.append("db_persistent")
|
updates.append("db_persistent")
|
||||||
if updates:
|
if updates:
|
||||||
self.save(update_fields=updates)
|
self.save(update_fields=updates)
|
||||||
|
|
||||||
if cdict["permissions"]:
|
|
||||||
self.permissions.add(cdict["permissions"])
|
|
||||||
if cdict["locks"]:
|
|
||||||
self.locks.add(cdict["locks"])
|
|
||||||
if cdict["aliases"]:
|
|
||||||
self.aliases.add(cdict["aliases"])
|
|
||||||
|
|
||||||
if not cdict["autostart"]:
|
if not cdict["autostart"]:
|
||||||
# don't auto-start the script
|
# don't auto-start the script
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,8 @@ def create_objects():
|
||||||
# it to exist in Limbo.
|
# it to exist in Limbo.
|
||||||
character_typeclass = settings.BASE_CHARACTER_TYPECLASS
|
character_typeclass = settings.BASE_CHARACTER_TYPECLASS
|
||||||
god_character = create.create_object(character_typeclass,
|
god_character = create.create_object(character_typeclass,
|
||||||
key=god_player.username, nohome=True)
|
key=god_player.username,
|
||||||
|
nohome=True)
|
||||||
|
|
||||||
god_character.id = 1
|
god_character.id = 1
|
||||||
god_character.db.desc = _('This is User #1.')
|
god_character.db.desc = _('This is User #1.')
|
||||||
|
|
@ -84,14 +85,13 @@ def create_objects():
|
||||||
room_typeclass = settings.BASE_ROOM_TYPECLASS
|
room_typeclass = settings.BASE_ROOM_TYPECLASS
|
||||||
limbo_obj = create.create_object(room_typeclass, _('Limbo'), nohome=True)
|
limbo_obj = create.create_object(room_typeclass, _('Limbo'), nohome=True)
|
||||||
limbo_obj.id = 2
|
limbo_obj.id = 2
|
||||||
string = " ".join([
|
string = \
|
||||||
"Welcome to your new {wEvennia{n-based game. From here you are ready",
|
"Welcome to your new {wEvennia{n-based game. From here you are ready " \
|
||||||
"to begin development. Visit http://evennia.com if you should need",
|
"to begin development. Visit http://evennia.com if you should need " \
|
||||||
"help or would like to participate in community discussions. If you",
|
"help or would like to participate in community discussions. If you " \
|
||||||
"are logged in as User #1 you can create a demo/tutorial area with",
|
"are logged in as user #1 you can create a demo/tutorial area with " \
|
||||||
"'@batchcommand contrib.tutorial_world.build'. Log out and create",
|
"{w@batchcommand contrib.tutorial_world.build{n. Use {w@quell{n or login " \
|
||||||
"a new non-admin account at the login screen to play the tutorial",
|
"as normal player to play the demo properly."
|
||||||
"properly."])
|
|
||||||
string = _(string)
|
string = _(string)
|
||||||
limbo_obj.db.desc = string
|
limbo_obj.db.desc = string
|
||||||
limbo_obj.save()
|
limbo_obj.save()
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,7 @@ Models covered:
|
||||||
"""
|
"""
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
from src.utils.idmapper.models import SharedMemoryModel
|
from src.utils import logger
|
||||||
from src.utils import utils, logger
|
|
||||||
from src.utils.utils import make_iter, class_from_module, dbid_to_obj
|
from src.utils.utils import make_iter, class_from_module, dbid_to_obj
|
||||||
|
|
||||||
# delayed imports
|
# delayed imports
|
||||||
|
|
@ -71,6 +70,11 @@ def create_object(typeclass=None, key=None, location=None,
|
||||||
nohome - this allows the creation of objects without a default home location;
|
nohome - this allows the creation of objects without a default home location;
|
||||||
only used when creating the default location itself or during unittests
|
only used when creating the default location itself or during unittests
|
||||||
"""
|
"""
|
||||||
|
global _ObjectDB
|
||||||
|
if not _ObjectDB:
|
||||||
|
from src.objects.models import ObjectDB as _ObjectDB
|
||||||
|
|
||||||
|
|
||||||
typeclass = typeclass if typeclass else settings.BASE_OBJECT_TYPECLASS
|
typeclass = typeclass if typeclass else settings.BASE_OBJECT_TYPECLASS
|
||||||
|
|
||||||
if isinstance(typeclass, basestring):
|
if isinstance(typeclass, basestring):
|
||||||
|
|
@ -141,6 +145,10 @@ def create_script(typeclass, key=None, obj=None, player=None, locks=None,
|
||||||
error will be raised. If set, this method will
|
error will be raised. If set, this method will
|
||||||
return None upon errors.
|
return None upon errors.
|
||||||
"""
|
"""
|
||||||
|
global _ScriptDB
|
||||||
|
if not _ScriptDB:
|
||||||
|
from src.scripts.models import ScriptDB as _ScriptDB
|
||||||
|
|
||||||
typeclass = typeclass if typeclass else settings.BASE_SCRIPT_TYPECLASS
|
typeclass = typeclass if typeclass else settings.BASE_SCRIPT_TYPECLASS
|
||||||
|
|
||||||
if isinstance(typeclass, basestring):
|
if isinstance(typeclass, basestring):
|
||||||
|
|
@ -148,13 +156,18 @@ def create_script(typeclass, key=None, obj=None, player=None, locks=None,
|
||||||
typeclass = class_from_module(typeclass, settings.SCRIPT_TYPECLASS_PATHS)
|
typeclass = class_from_module(typeclass, settings.SCRIPT_TYPECLASS_PATHS)
|
||||||
|
|
||||||
# validate input
|
# validate input
|
||||||
player = dbid_to_obj(player)
|
kwarg = {}
|
||||||
obj = dbid_to_obj(obj)
|
if key: kwarg["db_key"] = key
|
||||||
|
if player: kwarg["db_player"] = dbid_to_obj(player, _ScriptDB)
|
||||||
|
if obj: kwarg["db_obj"] = dbid_to_obj(obj, _ScriptDB)
|
||||||
|
if interval: kwarg["db_interval"] = interval
|
||||||
|
if start_delay: kwarg["db_start_delay"] = start_delay
|
||||||
|
if repeats: kwarg["db_repeats"] = repeats
|
||||||
|
if persistent: kwarg["db_persistent"] = persistent
|
||||||
|
|
||||||
# create new instance
|
# create new instance
|
||||||
new_script = typeclass(db_key=key, db_obj=obj, db_player=player,
|
new_script = typeclass(**kwarg)
|
||||||
db_interval=interval, db_start_delay=start_delay,
|
|
||||||
db_repeats=repeats, db_peristent=persistent)
|
|
||||||
# store the call signature for the signal
|
# store the call signature for the signal
|
||||||
new_script._createdict = {"key":key, "obj":obj, "player":player,
|
new_script._createdict = {"key":key, "obj":obj, "player":player,
|
||||||
"locks":locks, "interval":interval,
|
"locks":locks, "interval":interval,
|
||||||
|
|
@ -326,6 +339,10 @@ def create_player(key, email, password,
|
||||||
operations and is thus not suitable for play-testing the game.
|
operations and is thus not suitable for play-testing the game.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
global _PlayerDB
|
||||||
|
if not _PlayerDB:
|
||||||
|
from src.players.models import PlayerDB as _PlayerDB
|
||||||
|
|
||||||
typeclass = typeclass if typeclass else settings.BASE_PLAYER_TYPECLASS
|
typeclass = typeclass if typeclass else settings.BASE_PLAYER_TYPECLASS
|
||||||
|
|
||||||
if isinstance(typeclass, basestring):
|
if isinstance(typeclass, basestring):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue