Merged. Still need to update some migrations.

This commit is contained in:
Griatch 2013-07-11 19:11:27 +02:00
commit c676c9965f
29 changed files with 821 additions and 401 deletions

View file

@ -561,6 +561,7 @@ class CrumblingWall(TutorialObject, Exit):
self.aliases = ["secret passage", "passage", "crack", "opening", "secret door"]
# this is assigned first when pushing button, so assign this at creation time!
self.db.destination = 2
# locks on the object directly transfer to the exit "command"
self.locks.add("cmd:not locattr(is_dark)")

View file

@ -139,14 +139,25 @@ def get_and_merge_cmdsets(caller):
cmdsets = yield [caller_cmdset] + [player_cmdset] + [channel_cmdset] + local_objects_cmdsets
# weed out all non-found sets
cmdsets = yield [cmdset for cmdset in cmdsets if cmdset]
cmdsets = yield [cmdset for cmdset in cmdsets if cmdset and cmdset.key!="Empty"]
# report cmdset errors to user (these should already have been logged)
yield [caller.msg(cmdset.message) for cmdset in cmdsets if cmdset.key == "_CMDSET_ERROR"]
# sort cmdsets after reverse priority (highest prio are merged in last)
yield cmdsets.sort(key=lambda x: x.priority)
#cmdsets = yield sorted(cmdsets, key=lambda x: x.priority)
yield [caller.msg(cmdset.errmessage) for cmdset in cmdsets if cmdset.key == "_CMDSET_ERROR"]
if cmdsets:
# we group and merge all same-prio cmdsets separately (this avoids order-dependent
# clashes in certain cases, such as when duplicates=True)
tempmergers = {}
for cmdset in cmdsets:
prio = cmdset.priority
if prio in tempmergers:
# merge same-prio cmdset together separately
tempmergers[prio] = yield cmdset + tempmergers[prio]
else:
tempmergers[prio] = cmdset
# sort cmdsets after reverse priority (highest prio are merged in last)
cmdsets = yield sorted(tempmergers.values(), key=lambda x: x.priority)
# Merge all command sets into one, beginning with the lowest-prio one
cmdset = cmdsets.pop(0)
for merging_cmdset in cmdsets:

View file

@ -128,9 +128,10 @@ class CmdSet(object):
no_objs = False
no_channels = False
permanent = False
errmessage = ""
# pre-store properties to duplicate straight off
to_duplicate = ("key", "cmdsetobj", "no_exits", "no_objs", "no_channels", "permanent",
"mergetype", "priority", "duplicates")
"mergetype", "priority", "duplicates", "errmessage")
def __init__(self, cmdsetobj=None, key=None):
"""
@ -152,21 +153,21 @@ class CmdSet(object):
# Priority-sensitive merge operations for cmdsets
def _union(self, cmdset_a, cmdset_b, duplicates=False):
def _union(self, cmdset_a, cmdset_b):
"C = A U B. CmdSet A is assumed to have higher priority"
cmdset_c = cmdset_a._duplicate()
# we make copies, not refs by use of [:]
cmdset_c.commands = cmdset_a.commands[:]
if duplicates and cmdset_a.priority == cmdset_b.priority:
if cmdset_a.duplicates and cmdset_a.priority == cmdset_b.priority:
cmdset_c.commands.extend(cmdset_b.commands)
else:
cmdset_c.commands.extend([cmd for cmd in cmdset_b if not cmd in cmdset_a])
return cmdset_c
def _intersect(self, cmdset_a, cmdset_b, duplicates=False):
def _intersect(self, cmdset_a, cmdset_b):
"C = A (intersect) B. A is assumed higher priority"
cmdset_c = cmdset_a._duplicate()
if duplicates and cmdset_a.priority == cmdset_b.priority:
if cmdset_a.duplicates and cmdset_a.priority == cmdset_b.priority:
for cmd in [cmd for cmd in cmdset_a if cmd in cmdset_b]:
cmdset_c.add(cmd)
cmdset_c.add(cmdset_b.get(cmd))
@ -174,13 +175,13 @@ class CmdSet(object):
cmdset_c.commands = [cmd for cmd in cmdset_a if cmd in cmdset_b]
return cmdset_c
def _replace(self, cmdset_a, cmdset_b, cmdset_c):
def _replace(self, cmdset_a, cmdset_b):
"C = A + B where the result is A."
cmdset_c = cmdset_a._duplicate()
cmdset_c.commands = cmdset_a.commands[:]
return cmdset_c
def _remove(self, cmdset_a, cmdset_b, cmdset_c):
def _remove(self, cmdset_a, cmdset_b):
"C = A + B, where B is filtered by A"
cmdset_c = cmdset_a._duplicate()
cmdset_c.commands = [cmd for cmd in cmdset_b if not cmd in cmdset_a]
@ -267,13 +268,13 @@ class CmdSet(object):
mergetype = self.key_mergetypes.get(cmdset_b.key, self.mergetype)
if mergetype == "Intersect":
cmdset_c = self._intersect(self, cmdset_b, cmdset_b.duplicates)
cmdset_c = self._intersect(self, cmdset_b)
elif mergetype == "Replace":
cmdset_c = self._replace(self, cmdset_b, cmdset_b.duplicates)
cmdset_c = self._replace(self, cmdset_b)
elif mergetype == "Remove":
cmdset_c = self._remove(self, cmdset_b, cmdset_b.duplicates)
cmdset_c = self._remove(self, cmdset_b)
else: # Union
cmdset_c = self._union(self, cmdset_b, cmdset_b.duplicates)
cmdset_c = self._union(self, cmdset_b)
cmdset_c.no_channels = self.no_channels
cmdset_c.no_exits = self.no_exits
cmdset_c.no_objs = self.no_objs
@ -286,13 +287,13 @@ class CmdSet(object):
mergetype = cmdset_b.key_mergetypes.get(self.key, cmdset_b.mergetype)
if mergetype == "Intersect":
cmdset_c = self._intersect(cmdset_b, self, self.duplicates)
cmdset_c = self._intersect(cmdset_b, self)
elif mergetype == "Replace":
cmdset_c = self._replace(cmdset_b, self, self.duplicates)
cmdset_c = self._replace(cmdset_b, self)
elif mergetype == "Remove":
cmdset_c = self._remove(self, cmdset_b, self.duplicates)
cmdset_c = self._remove(self, cmdset_b)
else: # Union
cmdset_c = self._union(cmdset_b, self, self.duplicates)
cmdset_c = self._union(cmdset_b, self)
cmdset_c.no_channels = cmdset_b.no_channels
cmdset_c.no_exits = cmdset_b.no_exits
cmdset_c.no_objs = cmdset_b.no_objs

View file

@ -76,7 +76,7 @@ _CACHED_CMDSETS = {}
class _ErrorCmdSet(CmdSet):
"This is a special cmdset used to report errors"
key = "_CMDSET_ERROR"
message = "Error when loading cmdset."
errmessage = "Error when loading cmdset."
def import_cmdset(python_path, cmdsetobj, emit_to_obj=None, no_logging=False):
"""
@ -130,7 +130,7 @@ def import_cmdset(python_path, cmdsetobj, emit_to_obj=None, no_logging=False):
if emit_to_obj and not ServerConfig.objects.conf("server_starting_mode"):
object.__getattribute__(emit_to_obj, "msg")(errstring)
err_cmdset = _ErrorCmdSet()
err_cmdset.message = errstring
err_cmdset.errmessage = errstring
return err_cmdset
# classes
@ -283,7 +283,7 @@ class CmdSetHandler(object):
elif isinstance(cmdset, basestring):
# this is (maybe) a python path. Try to import from cache.
cmdset = self._import_cmdset(cmdset)
if cmdset:
if cmdset and cmdset.key != '_CMDSET_ERROR':
if permanent and cmdset.key != '_CMDSET_ERROR':
# store the path permanently
cmdset.permanent = True
@ -315,7 +315,7 @@ class CmdSetHandler(object):
elif isinstance(cmdset, basestring):
# this is (maybe) a python path. Try to import from cache.
cmdset = self._import_cmdset(cmdset)
if cmdset:
if cmdset and cmdset.key != '_CMDSET_ERROR':
if self.cmdset_stack:
self.cmdset_stack[0] = cmdset
self.mergetype_stack[0] = cmdset.mergetype

View file

@ -9,58 +9,72 @@ import re
from src.locks.lockhandler import LockHandler
from src.utils.utils import is_iter, fill
def _init_command(mcs, **kwargs):
"""
Helper command.
Makes sure all data are stored as lowercase and
do checking on all properties that should be in list form.
Sets up locks to be more forgiving. This is used both by the metaclass
and (optionally) at instantiation time.
If kwargs are given, these are set as instance-specific properties on the command.
"""
for i in range(len(kwargs)):
# used for dynamic creation of commands
key, value = kwargs.popitem()
setattr(mcs, key, value)
mcs.key = mcs.key.lower()
if mcs.aliases and not is_iter(mcs.aliases):
try:
mcs.aliases = [str(alias).strip().lower() for alias in mcs.aliases.split(',')]
except Exception:
mcs.aliases = []
mcs.aliases = list(set(alias for alias in mcs.aliases if alias != mcs.key))
# optimization - a set is much faster to match against than a list
mcs._matchset = set([mcs.key] + mcs.aliases)
# optimization for looping over keys+aliases
mcs._keyaliases = tuple(mcs._matchset)
# by default we don't save the command between runs
if not hasattr(mcs, "save_for_next"):
mcs.save_for_next = False
# pre-process locks as defined in class definition
temp = []
if hasattr(mcs, 'permissions'):
mcs.locks = mcs.permissions
if not hasattr(mcs, 'locks'):
# default if one forgets to define completely
mcs.locks = "cmd:all()"
if not "cmd:" in mcs.locks:
mcs.locks = "cmd:all();" + mcs.locks
for lockstring in mcs.locks.split(';'):
if lockstring and not ':' in lockstring:
lockstring = "cmd:%s" % lockstring
temp.append(lockstring)
mcs.lock_storage = ";".join(temp)
if hasattr(mcs, 'arg_regex') and isinstance(mcs.arg_regex, basestring):
mcs.arg_regex = re.compile(r"%s" % mcs.arg_regex, re.I)
else:
mcs.arg_regex = None
if not hasattr(mcs, "auto_help"):
mcs.auto_help = True
if not hasattr(mcs, 'is_exit'):
mcs.is_exit = False
if not hasattr(mcs, "help_category"):
mcs.help_category = "general"
mcs.help_category = mcs.help_category.lower()
class CommandMeta(type):
"""
This metaclass makes some minor on-the-fly convenience fixes to the command
class in case the admin forgets to put things in lowercase etc.
The metaclass cleans up all properties on the class
"""
def __init__(mcs, *args, **kwargs):
"""
Simply make sure all data are stored as lowercase and
do checking on all properties that should be in list form.
Sets up locks to be more forgiving.
"""
mcs.key = mcs.key.lower()
if mcs.aliases and not is_iter(mcs.aliases):
try:
mcs.aliases = [str(alias).strip().lower() for alias in mcs.aliases.split(',')]
except Exception:
mcs.aliases = []
mcs.aliases = list(set(alias for alias in mcs.aliases if alias != mcs.key))
# optimization - a set is much faster to match against than a list
mcs._matchset = set([mcs.key] + mcs.aliases)
# optimization for looping over keys+aliases
mcs._keyaliases = tuple(mcs._matchset)
# by default we don't save the command between runs
if not hasattr(mcs, "save_for_next"):
mcs.save_for_next = False
# pre-process locks as defined in class definition
temp = []
if hasattr(mcs, 'permissions'):
mcs.locks = mcs.permissions
if not hasattr(mcs, 'locks'):
# default if one forgets to define completely
mcs.locks = "cmd:all()"
for lockstring in mcs.locks.split(';'):
if lockstring and not ':' in lockstring:
lockstring = "cmd:%s" % lockstring
temp.append(lockstring)
mcs.lock_storage = ";".join(temp)
if hasattr(mcs, 'arg_regex') and isinstance(mcs.arg_regex, basestring):
mcs.arg_regex = re.compile(r"%s" % mcs.arg_regex, re.I)
else:
mcs.arg_regex = None
if not hasattr(mcs, "auto_help"):
mcs.auto_help = True
if not hasattr(mcs, 'is_exit'):
mcs.is_exit = False
if not hasattr(mcs, "help_category"):
mcs.help_category = "general"
mcs.help_category = mcs.help_category.lower()
_init_command(mcs, **kwargs)
super(CommandMeta, mcs).__init__(*args, **kwargs)
# The Command class is the basic unit of an Evennia command; when
@ -125,8 +139,12 @@ class Command(object):
# sessid - which session-id (if any) is responsible for triggering this command
#
def __init__(self):
"the lockhandler works the same as for objects."
def __init__(self, **kwargs):
"""the lockhandler works the same as for objects.
optional kwargs will be set as properties on the Command at runtime,
overloading evential same-named class properties."""
if kwargs:
_init_command(self, **kwargs)
self.lockhandler = LockHandler(self)
def __str__(self):

View file

@ -606,9 +606,6 @@ class CmdQuell(MuxPlayerCommand):
Hierarchical permission quelling only work downwards, thus a Player cannot
use a higher-permission Character to escalate their permission level.
Use the unquell command to revert back to normal operation.
Note that the superuser character cannot be quelled. Use a separate
admin account for testing.
"""
key = "@quell"

View file

@ -4,7 +4,6 @@ Commands that are available from the connect screen.
import re
import traceback
from django.conf import settings
from django.contrib.auth.models import User
from src.players.models import PlayerDB
from src.objects.models import ObjectDB
from src.server.models import ServerConfig
@ -68,7 +67,7 @@ class CmdUnconnectedConnect(MuxCommand):
player = PlayerDB.objects.get_player_from_name(playername)
pswd = None
if player:
pswd = player.user.check_password(password)
pswd = player.check_password(password)
if not (player and pswd):
# No playername or password match
@ -142,7 +141,7 @@ class CmdUnconnectedCreate(MuxCommand):
return
# strip excessive spaces in playername
playername = re.sub(r"\s+", " ", playername).strip()
if PlayerDB.objects.filter(user__username__iexact=playername) or User.objects.filter(username__iexact=playername):
if PlayerDB.objects.filter(username__iexact=playername):
# player already exists (we also ignore capitalization here)
session.msg("Sorry, there is already a player with the name '%s'." % playername)
return

View file

@ -90,7 +90,7 @@ class ChannelCommand(command.Command):
msgobj.senders = sender
msgobj.channels = channel
# send new message object to channel
channel.msg(msgobj, senders=sender)
channel.msg(msgobj, senders=sender, online=True)
class ChannelHandler(object):
"""
@ -136,14 +136,11 @@ class ChannelHandler(object):
and run self.update on the handler.
"""
# map the channel to a searchable command
cmd = ChannelCommand()
cmd.key = channel.key.strip().lower()
cmd.obj = channel
cmd = ChannelCommand(key=channel.key.strip().lower(),
aliases=channel.aliases if channel.aliases else [],
locks="cmd:all();%s" % channel.locks,
obj=channel)
cmd.__doc__= self._format_help(channel)
if channel.aliases:
cmd.aliases = channel.aliases
cmd.lock_storage = "cmd:all();%s" % channel.locks
cmd.lockhandler.reset()
self.cached_channel_cmds.append(cmd)
self.cached_cmdsets = {}

View file

@ -11,6 +11,7 @@ _GA = object.__getattribute__
_PlayerDB = None
_ObjectDB = None
_Channel = None
_SESSIONS = None
_ExternalConnection = None
_User = None
@ -198,7 +199,7 @@ class MsgManager(models.Manager):
NOTE: This can potentially be slow, so make sure to supply
one of the other arguments to limit the search.
dbref - (int) the exact database id of the message. This will override
all other search crieteria since it's unique and
all other search criteria since it's unique and
always gives a list with only one match.
"""
# unique msg id
@ -299,19 +300,33 @@ class ChannelManager(models.Manager):
CHANNELHANDLER.update()
return None
def get_all_connections(self, channel):
def get_all_connections(self, channel, online=False):
"""
Return the connections of all players listening
to this channel
to this channel. If Online is true, it only returns
connected players.
"""
# import here to avoid circular imports
#from src.comms.models import PlayerChannelConnection
global _SESSIONS
if not _SESSIONS:
from src.server.sessionhandler import SESSIONS as _SESSIONS
PlayerChannelConnection = ContentType.objects.get(app_label="comms",
model="playerchannelconnection").model_class()
ExternalChannelConnection = ContentType.objects.get(app_label="comms",
model="externalchannelconnection").model_class()
return itertools.chain(PlayerChannelConnection.objects.get_all_connections(channel),
ExternalChannelConnection.objects.get_all_connections(channel))
players = []
if online:
session_list = _SESSIONS.get_sessions()
unique_online_users = set(sess.uid for sess in session_list if sess.logged_in)
online_players = (sess.get_player() for sess in session_list if sess.uid in unique_online_users)
for player in online_players:
players.extend(PlayerChannelConnection.objects.filter(db_player=player, db_channel=channel))
else:
players.extend(PlayerChannelConnection.objects.get_all_connections(channel))
external_connections = ExternalChannelConnection.objects.get_all_connections(channel)
return itertools.chain(players, external_connections)
def channel_search(self, ostring):
"""

View file

@ -553,7 +553,7 @@ class Channel(SharedMemoryModel):
# do the check
return PlayerChannelConnection.objects.has_player_connection(player, self)
def msg(self, msgobj, header=None, senders=None, persistent=True):
def msg(self, msgobj, header=None, senders=None, persistent=True, online=False):
"""
Send the given message to all players connected to channel. Note that
no permission-checking is done here; it is assumed to have been
@ -566,7 +566,8 @@ class Channel(SharedMemoryModel):
persistent=False.
persistent (bool) - ignored if msgobj is a Msg or TempMsg. If True, a Msg will be created, using
header and senders keywords. If False, other keywords will be ignored.
online (bool) - If this is set true, only messages people who are online. Otherwise, messages all players
connected. This can make things faster, but may not trigger listeners on players that are offline.
"""
if isinstance(msgobj, basestring):
@ -588,7 +589,7 @@ class Channel(SharedMemoryModel):
msg = msgobj.message
# get all players connected to this channel and send to them
for conn in Channel.objects.get_all_connections(self):
for conn in Channel.objects.get_all_connections(self, online=online):
try:
conn.player.msg(msg, senders)
except AttributeError:

View file

@ -34,7 +34,6 @@ class ObjectManager(TypedObjectManager):
get_dbref_range
object_totals
typeclass_search
get_object_with_user
get_object_with_player
get_objs_with_key_and_typeclass
get_objs_with_attr
@ -52,29 +51,8 @@ class ObjectManager(TypedObjectManager):
# ObjectManager Get methods
#
# user/player related
# 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.
user - may be a user object or user id.
"""
dbref = self.dbref(user)
if dbref:
try:
return self.get(db_player__user__id=dbref)
except self.model.DoesNotExist:
pass
try:
return self.get(db_player__user=user)
except self.model.DoesNotExist:
return None
# This returns typeclass since get_object_with_user and get_dbref does.
@returns_typeclass
def get_object_with_player(self, ostring, exact=True, candidates=None):
"""
@ -92,9 +70,9 @@ class ObjectManager(TypedObjectManager):
# not a dbref. Search by name.
cand_restriction = candidates and Q(pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q()
if exact:
return self.filter(cand_restriction & Q(db_player__user__username__iexact=ostring))
return self.filter(cand_restriction & Q(db_player__username__iexact=ostring))
else: # fuzzy matching
ply_cands = self.filter(cand_restriction & Q(playerdb__user__username__istartswith=ostring)).values_list("db_key", flat=True)
ply_cands = self.filter(cand_restriction & Q(playerdb__username__istartswith=ostring)).values_list("db_key", flat=True)
if candidates:
index_matches = string_partial_matching(ply_cands, ostring, ret_index=True)
return [obj for ind, obj in enumerate(make_iter(candidates)) if ind in index_matches]
@ -175,7 +153,8 @@ class ObjectManager(TypedObjectManager):
if isinstance(property_value, basestring):
property_value = to_unicode(property_value)
if isinstance(property_name, basestring):
property_name = "db_%s" % property_name.lstrip('db_')
if not property_name.startswith('db_'):
property_name = "db_%s" % property_name
querykwargs = {property_name:property_value}
cand_restriction = candidates and Q(pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q()
type_restriction = typeclasses and Q(db_typeclass_path__in=make_iter(typeclasses)) or Q()
@ -183,6 +162,10 @@ class ObjectManager(TypedObjectManager):
return list(self.filter(cand_restriction & type_restriction & Q(**querykwargs)))
except exceptions.FieldError:
return []
except ValueError:
from src.utils import logger
logger.log_errmsg("The property '%s' does not support search criteria of the type %s." % (property_name, type(property_value)))
return []
@returns_typeclass_list
def get_contents(self, location, excludeobj=None):
@ -253,7 +236,8 @@ class ObjectManager(TypedObjectManager):
By default (if not attribute_name is set), this will search object.key and object.aliases in order. Can also
be on the form #dbref, which will, if exact=True be matched against primary key.
attribute_name: (str): Use this named ObjectAttribute to match searchdata against, instead
of the defaults.
of the defaults. If this is the name of a database field (with or without the db_ prefix), that
will be matched too.
typeclass (str or TypeClass): restrict matches to objects having this typeclass. This will help
speed up global searches.
candidates (list obj ObjectDBs): If supplied, search will only be performed among the candidates

View file

@ -10,7 +10,7 @@ class Migration(DataMigration):
"Write your forwards methods here."
# we need to add a default lock string to all objects, then a separate set to Characters.
lockstring1 = 'control:id(1);get:all();edit:perm(Wizards);examine:perm(Builders);call:true();puppet:id(#4) or perm(Immortals) or pperm(Immortals);delete:id(1) or perm(Wizards)'
lockstring2 = 'control:id(#3) or perm(Immortals);get:perm(Wizards);edit:perm(Wizards);examine:perm(Builders);call:false();puppet:id(%i) or pid(%i) or perm(Immortals) or pperm(Immortals);delete:perm(Wizards)'
@ -21,10 +21,10 @@ class Migration(DataMigration):
for obj in orm.ObjectDB.objects.filter(db_player__isnull=False):
obj.db_lock_storage = lockstring2 % (obj.id, obj.db_player.id)
obj.save()
except utils.DatabaseError:
# running from scatch. In this case we just ignore this.
pass
pass
def backwards(self, orm):
"Write your backwards methods here."

View file

@ -640,7 +640,7 @@ class ObjectDB(TypedObject):
if searchdata == _HERE:
return self.location
if searchdata in (_ME, _SELF):
return self
return self.typeclass
if use_nicks:
nick = None

View file

@ -37,14 +37,14 @@ class Object(TypeClass):
# __init__ is only defined here in order to present docstring to API.
def __init__(self, dbobj):
"""
This is the root typeclass object representing all entities
that has and actual presence in-game. Objects generally has a
location, can be manipulated and looked at. Most game entities
you define should inherit from Object at some distance.
Important subclasses of Object are that Evennia defines by
default for you are Characters, Exits and Rooms.
This is the root typeclass object, representing all entities
that have an actual presence in-game. Objects generally have a
location. They can also be manipulated and looked at. Most
game entities you define should inherit from Object at some distance.
Evennia defines some important subclasses of Object by default, namely
Characters, Exits and Rooms (see the bottom of this module).
Note that all Objects and its subclasses *must* always be
Note that all new Objects and their subclasses *must* always be
created using the ev.create_object() function. This is so the
typeclass system can be correctly initiated behind the scenes.
@ -54,7 +54,7 @@ class Object(TypeClass):
* Available properties (only available on *initiated* typeclass objects)
key (string) - name of object
name (string)- same as key
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
@ -465,12 +465,13 @@ class Object(TypeClass):
"""
pass
def at_pre_puppet(self, player):
def at_pre_puppet(self, player, sessid=None):
"""
Called just before a Player connects to this object
to puppet it.
player - connecting player object
sessid - session id controlling the connection
"""
pass
@ -488,13 +489,14 @@ class Object(TypeClass):
"""
pass
def at_post_unpuppet(self, player):
def at_post_unpuppet(self, player, sessid=None):
"""
Called just after the Player successfully disconnected
from this object, severing all connections.
player - the player object that just disconnected from
this object.
sessid - session id controlling the connection
"""
pass
@ -755,7 +757,7 @@ class Object(TypeClass):
return message
#
# Base Player object
# Base Character object
#
class Character(Object):
@ -793,7 +795,7 @@ class Character(Object):
"Default is to look around after a move."
self.execute_cmd('look')
def at_pre_puppet(self, player):
def at_pre_puppet(self, player, sessid=None):
"""
This recovers the character again after having been "stoved away" at the unpuppet
"""
@ -809,7 +811,7 @@ class Character(Object):
self.location.msg_contents("%s has entered the game." % self.name, exclude=[self])
self.location.at_object_receive(self, self.location)
else:
player.msg("{r%s has no location and no home is set.{n" % self)
player.msg("{r%s has no location and no home is set.{n" % self, sessid=sessid)
def at_post_puppet(self):
"""
@ -820,7 +822,7 @@ class Character(Object):
if self.location:
self.location.msg_contents("%s has entered the game." % self.name, exclude=[self])
def at_post_unpuppet(self, player):
def at_post_unpuppet(self, player, sessid=None):
"""
We stove away the character when the player goes ooc/logs off, otherwise the character object will
remain in the room also after the player logged off ("headless", so to say).
@ -836,14 +838,13 @@ class Character(Object):
class Room(Object):
"""
This is the base room object. It's basically
like any Object except its location is None.
This is the base room object. It's just like any Object except its
location is None.
"""
def basetype_setup(self):
"""
Simple setup, shown as an example
(since default is None anyway)
"""
super(Room, self).basetype_setup()
@ -852,19 +853,18 @@ class Room(Object):
self.location = None
#
# Exits
# Base Exit object
#
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
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
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.
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
@ -909,13 +909,12 @@ class Exit(Object):
self.obj.at_failed_traverse(self.caller)
# create an exit command.
cmd = ExitCommand()
cmd.key = exidbobj.db_key.strip().lower()
cmd.obj = exidbobj
cmd.aliases = exidbobj.aliases
cmd.locks = str(exidbobj.locks)
cmd.destination = exidbobj.db_destination
cmd.auto_help = False
cmd = ExitCommand(key=exidbobj.db_key.strip().lower(),
aliases=exidbobj.aliases,
locks=str(exidbobj.locks),
auto_help=False,
destination=exidbobj.db_destination,
obj=exidbobj)
# create a cmdset
exit_cmdset = cmdset.CmdSet(None)
exit_cmdset.key = '_exitset'

View file

@ -142,6 +142,7 @@ class UserAdmin(BaseUserAdmin):
{'fields': ('username', 'password1', 'password2', 'email'),
'description':"<i>These account details are shared by the admin system and the game.</i>"},),)
# TODO! Remove User reference!
def save_formset(self, request, form, formset, change):
"Run all hooks on the player object"
super(UserAdmin, self).save_formset(request, form, formset, change)

View file

@ -3,8 +3,8 @@ The managers for the custom Player object and permissions.
"""
import datetime
from django.contrib.auth.models import UserManager
from functools import update_wrapper
from django.contrib.auth.models import User
from src.typeclasses.managers import returns_typeclass_list, returns_typeclass, TypedObjectManager
from src.utils import logger
__all__ = ("PlayerManager",)
@ -13,54 +13,7 @@ __all__ = ("PlayerManager",)
# Player Manager
#
def returns_player_list(method):
"""
decorator that makes sure that a method
returns a Player object instead of a User
one (if you really want the User object, not
the player, use the player's 'user' property)
"""
def func(self, *args, **kwargs):
"This *always* returns a list."
match = method(self, *args, **kwargs)
if not match:
return []
try:
match = list(match)
except TypeError:
match = [match]
players = []
for user in match:
try:
players.append(user.get_profile())
except Exception:
# there is something wrong with get_profile. But
# there is a 1-1 relation between Users-Players, so we
# try to go the other way instead.
from src.players.models import PlayerDB
match = PlayerDB.objects.filter(user__id=user.id)
if match:
players.append(match[0])
else:
logger.log_trace("No connection User<->Player, maybe database was partially reset?")
return players
return update_wrapper(func, method)
def returns_player(method):
"""
Decorator: Always returns a single result or None.
"""
def func(self, *args, **kwargs):
"decorator"
rfunc = returns_player_list(method)
match = rfunc(self, *args, **kwargs)
if match:
return match[0]
else:
return None
return update_wrapper(func, method)
class PlayerManager(TypedObjectManager):
class PlayerManager(TypedObjectManager, UserManager):
"""
This PlayerManager implements methods for searching
and manipulating Players directly from the database.
@ -87,7 +40,7 @@ class PlayerManager(TypedObjectManager):
"""
def num_total_players(self):
"""
Returns the total number of registered users/players.
Returns the total number of registered players.
"""
return self.count()
@ -99,7 +52,6 @@ class PlayerManager(TypedObjectManager):
return self.filter(db_is_connected=True)
@returns_typeclass_list
@returns_player_list
def get_recently_created_players(self, days=7):
"""
Returns a QuerySet containing the player User accounts that have been
@ -108,13 +60,12 @@ class PlayerManager(TypedObjectManager):
end_date = datetime.datetime.now()
tdelta = datetime.timedelta(days)
start_date = end_date - tdelta
return User.objects.filter(date_joined__range=(start_date, end_date))
return self.filter(date_joined__range=(start_date, end_date))
@returns_typeclass_list
@returns_player_list
def get_recently_connected_players(self, days=7):
"""
Returns a QuerySet containing the player User accounts that have been
Returns a QuerySet containing the player accounts that have been
connected within the last <days> days.
days - number of days backwards to check
@ -122,33 +73,31 @@ class PlayerManager(TypedObjectManager):
end_date = datetime.datetime.now()
tdelta = datetime.timedelta(days)
start_date = end_date - tdelta
return User.objects.filter(last_login__range=(
return self.filter(last_login__range=(
start_date, end_date)).order_by('-last_login')
@returns_typeclass
@returns_player
def get_player_from_email(self, uemail):
"""
Returns a player object when given an email address.
"""
return User.objects.filter(email__iexact=uemail)
return self.filter(email__iexact=uemail)
@returns_typeclass
@returns_player
def get_player_from_uid(self, uid):
"""
Returns a player object based on User id.
"""
try:
return User.objects.get(id=uid)
except User.model.DoesNotExist:
return self.get(id=uid)
except self.model.DoesNotExist:
return None
@returns_typeclass
def get_player_from_name(self, uname):
"Get player object based on name"
try:
return self.get(user__username__iexact=uname)
return self.get(username__iexact=uname)
except self.model.DoesNotExist:
return None
@ -165,7 +114,7 @@ class PlayerManager(TypedObjectManager):
matches = self.filter(id=dbref)
if matches:
return matches
return self.filter(user__username__iexact=ostring)
return self.filter(username__iexact=ostring)
def swap_character(self, player, new_character, delete_old_character=False):
"""

View file

@ -7,13 +7,13 @@ from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'PlayerDB.db_cmdset_storage'
db.add_column('players_playerdb', 'db_cmdset_storage', self.gf('django.db.models.fields.TextField')(null=True), keep_default=False)
def backwards(self, orm):
# Deleting field 'PlayerDB.db_cmdset_storage'
db.delete_column('players_playerdb', 'db_cmdset_storage')

View file

@ -0,0 +1,162 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models, connection
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'PlayerDBtmp'
if "auth_user" in connection.introspection.table_names():
# auth_user exists ffrom before. Use that as a base.
db.rename_table('auth_user', 'players_playerdbtmp')
else:
# from-scratch creation; no auth_user table available. Create vanilla User table
db.create_table(u'players_playerdbtmp', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('password', self.gf('django.db.models.fields.CharField')(max_length=128)),
('last_login', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
('is_superuser', self.gf('django.db.models.fields.BooleanField')(default=False)),
('username', self.gf('django.db.models.fields.CharField')(unique=True, max_length=30)),
('first_name', self.gf('django.db.models.fields.CharField')(max_length=30, blank=True)),
('last_name', self.gf('django.db.models.fields.CharField')(max_length=30, blank=True)),
('email', self.gf('django.db.models.fields.EmailField')(max_length=75, blank=True)),
('is_staff', self.gf('django.db.models.fields.BooleanField')(default=False)),
('is_active', self.gf('django.db.models.fields.BooleanField')(default=True)),
('date_joined', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
))
db.send_create_signal(u'players', ['PlayerDBtmp'])
# Adding M2M table for field groups on 'PlayerDBtmp'
db.create_table(u'players_playerdbtmp_groups', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('playerdbtmp', models.ForeignKey(orm[u'players.playerdbtmp'], null=False)),
('group', models.ForeignKey(orm[u'auth.group'], null=False))
))
db.create_unique(u'players_playerdbtmp_groups', ['playerdbtmp_id', 'group_id'])
# Adding M2M table for field user_permissions on 'PlayerDBtmp'
db.create_table(u'players_playerdbtmp_user_permissions', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('playerdbtmp', models.ForeignKey(orm[u'players.playerdbtmp'], null=False)),
('permission', models.ForeignKey(orm[u'auth.permission'], null=False))
))
db.create_unique(u'players_playerdbtmp_user_permissions', ['playerdbtmp_id', 'permission_id'])
# Adding field 'PlayerDB.db_is_connected'
db.add_column(u'players_playerdb', 'db_is_connected',
self.gf('django.db.models.fields.BooleanField')(default=False),
keep_default=False)
# Adding field 'PlayerDB.db_cmdset_storage'
db.add_column(u'players_playerdb', 'db_cmdset_storage',
self.gf('django.db.models.fields.CharField')(max_length=255, null=True),
keep_default=False)
# add Evennia-specific columns
db.add_column('players_playerdbtmp', 'db_key', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True, null=True))
db.add_column('players_playerdbtmp', 'db_typeclass_path', self.gf('django.db.models.fields.CharField')(max_length=255, null=True))
db.add_column('players_playerdbtmp', 'db_date_created', self.gf('django.db.models.fields.DateTimeField')(null=True, auto_now_add=True, blank=True))
db.add_column('players_playerdbtmp', 'db_permissions', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True, null=True))
db.add_column('players_playerdbtmp', 'db_lock_storage', self.gf('django.db.models.fields.TextField')(blank=True, null=True))
db.add_column('players_playerdbtmp', 'db_is_connected', self.gf('django.db.models.fields.BooleanField')(default=False))
db.add_column('players_playerdbtmp', 'db_cmdset_storage', self.gf('django.db.models.fields.CharField')(max_length=255, null=True))
def backwards(self, orm):
raise RuntimeError("Cannot revert migration")
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'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': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'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'}),
u'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'})
},
u'players.playerattribute': {
'Meta': {'object_name': 'PlayerAttribute'},
'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_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
u'players.playerdb': {
'Meta': {'object_name': 'PlayerDB'},
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
u'players.playerdbtmp': {
'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'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_index': 'True'}),
'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'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': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'players.playernick': {
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'},
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_real': ('django.db.models.fields.TextField', [], {}),
'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
}
}
complete_apps = ['players']

View file

@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
class Migration(DataMigration):
def forwards(self, orm):
"Write your forwards methods here."
# Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
if not db.dry_run:
for profile in orm['players.PlayerDB'].objects.all():
plyr = orm['players.PlayerDBtmp'].objects.get(id=profile.user_id)
plyr.db_cmdset_storage = profile.db_cmdset_storage
plyr.db_date_created = profile.db_date_created
plyr.db_is_connected = profile.db_is_connected
plyr.db_key = profile.db_key
plyr.db_lock_storage = profile.db_lock_storage
plyr.db_typeclass_path = profile.db_typeclass_path
plyr.db_permissions = profile.db_permissions
plyr.save()
def backwards(self, orm):
"Write your backwards methods here."
raise RuntimeError("Cannot revert this migration.")
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'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': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'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'}),
u'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'})
},
u'players.playerattribute': {
'Meta': {'object_name': 'PlayerAttribute'},
'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_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
u'players.playerdb': {
'Meta': {'object_name': 'PlayerDB'},
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
u'players.playerdbtmp': {
'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'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_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'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': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'players.playernick': {
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'},
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_real': ('django.db.models.fields.TextField', [], {}),
'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
}
}
complete_apps = ['players']
symmetrical = True

View file

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
db.delete_table('players_playerdb')
def backwards(self, orm):
raise RuntimeError("Cannot revert this migration")
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'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': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'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'}),
u'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'})
},
u'players.playerattribute': {
'Meta': {'object_name': 'PlayerAttribute'},
'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_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
u'players.playerdb': {
'Meta': {'object_name': 'PlayerDB'},
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
u'players.playerdbtmp': {
'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'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_index': 'True'}),
'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'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': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'players.playernick': {
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'},
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_real': ('django.db.models.fields.TextField', [], {}),
'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
}
}
complete_apps = ['players']

View file

@ -0,0 +1,101 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
db.rename_table('players_PlayerDBtmp', 'players_PlayerDB')
db.send_create_signal('players', ['PlayerDB'])
def backwards(self, orm):
raise RuntimeError("Cannot revert this migration.")
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'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'}),
u'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'})
},
u'players.playerattribute': {
'Meta': {'object_name': 'PlayerAttribute'},
'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_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
# u'players.playerdbtmp': {
# 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'},
# 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
# '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_index': 'True'}),
# 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
# 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
# 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
# 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
# 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
# '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': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
# u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
# 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
# },
u'players.playerdb': {
'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDB'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'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_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'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': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'players.playernick': {
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'},
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}),
'db_real': ('django.db.models.fields.TextField', [], {}),
'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
}
}
complete_apps = ['players']

View file

@ -25,7 +25,7 @@ account info and OOC account configuration variables etc.
from django.conf import settings
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.models import AbstractUser, User
from django.utils.encoding import smart_str
from django.db.models.signals import post_init, pre_delete
@ -95,7 +95,8 @@ class PlayerNickHandler(TypeNickHandler):
#
#------------------------------------------------------------
class PlayerDB(TypedObject):
class PlayerDB(TypedObject, AbstractUser):
"""
This is a special model using Django's 'profile' functionality
and extends the default Django User model. It is defined as such
@ -130,8 +131,8 @@ class PlayerDB(TypedObject):
# this is the one-to-one link between the customized Player object and
# this profile model. It is required by django.
user = models.ForeignKey(User, unique=True, db_index=True,
help_text="The <I>User</I> object holds django-specific authentication for each Player. A unique User should be created and tied to each Player, the two should never be switched or changed around. The User will be deleted automatically when the Player is.")
#user = models.ForeignKey(User, unique=True, db_index=True,
# help_text="The <I>User</I> object holds django-specific authentication for each Player. A unique User should be created and tied to each Player, the two should never be switched or changed around. The User will be deleted automatically when the Player is.")
# store a connected flag here too, not just in sessionhandler.
# This makes it easier to track from various out-of-process locations
db_is_connected = models.BooleanField(default=False, verbose_name="is_connected", help_text="If player is connected to game or not")
@ -238,17 +239,19 @@ class PlayerDB(TypedObject):
#@property
def __name_get(self):
"Getter. Allows for value = self.name"
name = get_prop_cache(self, "_name")
if not name:
name = _GA(self,"user").username
set_prop_cache(self, "_name", name)
return name
return self.username
#name = get_prop_cache(self, "_name")
#if not name:
# name = _GA(self,"user").username
# set_prop_cache(self, "_name", name)
#return name
#@name.setter
def __name_set(self, value):
"Setter. Allows for player.name = newname"
_GA(self, "user").username = value
_GA(self, "user").save()
set_prop_cache(self, "_name", value)
self.username = value
#_GA(self, "user").username = value
#_GA(self, "user").save()
#set_prop_cache(self, "_name", value)
#@name.deleter
def __name_del(self):
"Deleter. Allows for del self.name"
@ -259,11 +262,12 @@ class PlayerDB(TypedObject):
#@property
def __uid_get(self):
"Getter. Retrieves the user id"
uid = get_prop_cache(self, "_uid")
if not uid:
uid = _GA(self, "user").id
set_prop_cache(self, "_uid", uid)
return uid
return self.id
#uid = get_prop_cache(self, "_uid")
#if not uid:
# uid = _GA(self, "user").id
# set_prop_cache(self, "_uid", uid)
#return uid
def __uid_set(self, value):
raise Exception("User id cannot be set!")
def __uid_del(self):
@ -271,14 +275,15 @@ class PlayerDB(TypedObject):
uid = property(__uid_get, __uid_set, __uid_del)
#@property
def __is_superuser_get(self):
"Superusers have all permissions."
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)
#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
@ -405,7 +410,7 @@ class PlayerDB(TypedObject):
# with a lingering player/sessid reference from an unclean server kill or similar
if normal_mode:
_GA(obj.typeclass, "at_pre_puppet")(self.typeclass)
_GA(obj.typeclass, "at_pre_puppet")(self.typeclass, sessid=sessid)
# do the connection
obj.sessid = sessid
obj.player = self
@ -437,7 +442,7 @@ class PlayerDB(TypedObject):
del obj.dbobj.player
session.puppet = None
session.puid = None
_GA(obj.typeclass, "at_post_unpuppet")(self)
_GA(obj.typeclass, "at_post_unpuppet")(self.typeclass, sessid=sessid)
return True
def unpuppet_all(self):
@ -500,16 +505,12 @@ class PlayerDB(TypedObject):
self.unpuppet_object(session.sessid)
session.sessionhandler.disconnect(session, reason=_("Player being deleted."))
try:
if _GA(self, "user"):
_GA(_GA(self, "user"), "delete")()
except AssertionError:
pass
try:
super(PlayerDB, self).delete(*args, **kwargs)
except AssertionError:
# this means deleting the user already cleared out the Player object.
pass
#try:
# if _GA(self, "user"):
# _GA(_GA(self, "user"), "delete")()
#except AssertionError:
# pass
super(PlayerDB, self).delete(*args, **kwargs)
def execute_cmd(self, raw_string, sessid=None):
"""
@ -557,3 +558,6 @@ class PlayerDB(TypedObject):
except:
pass
return matches
class PlayerDBtmp(AbstractUser):
pass

View file

@ -2,6 +2,7 @@
The custom manager for Scripts.
"""
from django.db.models import Q
from src.typeclasses.managers import TypedObjectManager
from src.typeclasses.managers import returns_typeclass_list
from src.utils.utils import make_iter
@ -194,39 +195,24 @@ class ScriptManager(TypedObjectManager):
if dbref or dbref == 0:
# this is a dbref, try to find the script directly
dbref_match = self.dbref_search(dbref)
if dbref_match:
ok = True
if obj and obj != dbref_match.obj:
ok = False
if only_timed and dbref_match.interval:
ok = False
if ok:
return [dbref_match]
if obj:
# convenience check to make sure obj is really a dbobj
obj = hasattr(obj, "dbobj") and obj.dbobj or obj
if dbref_match and not ((obj and obj != dbref_match.obj)
or (only_timed and dbref_match.interval)):
return [dbref_match]
# not a dbref; normal search
scripts = self.filter(db_key__iexact=ostring)
if obj:
scripts = scripts.exclude(db_obj=None).filter(db_obj__db_key__iexact=ostring)
if only_timed:
scripts = scripts.exclude(interval=0)
obj_restriction = obj and Q(db_obj=obj.dbobj) or Q()
timed_restriction = only_timed and Q(interval__gt=0) or Q()
scripts = self.filter(timed_restriction & obj_restriction & Q(db_key__iexact=ostring))
return scripts
def copy_script(self, original_script, new_key=None, new_obj=None, new_locks=None):
"""
Make an identical copy of the original_script
"""
typeclass = original_script.typeclass_path
if not new_key:
new_key = original_script.key
if not new_obj:
new_obj = original_script.obj
if not new_locks:
new_locks = original_script.db_lock_storage
new_key = new_key if new_key!=None else original_script.key
new_obj = new_obj if new_obj!=None else original_script.obj
new_locks = new_locks if new_locks!=None else original_script.db_lock_storage
from src.utils import create
new_script = create.create_script(typeclass, key=new_key, obj=new_obj, locks=new_locks, autostart=True)

View file

@ -7,13 +7,15 @@ Everything starts at handle_setup()
"""
import django
from django.contrib.auth.models import User
from django.core import management
from django.conf import settings
from django.core.management import call_command
from django.contrib.auth import get_user_model
from src.server.models import ServerConfig
from src.help.models import HelpEntry
from src.utils import create
from django.utils.translation import ugettext as _
def create_config_values():
@ -23,11 +25,20 @@ def create_config_values():
ServerConfig.objects.conf("site_name", settings.SERVERNAME)
ServerConfig.objects.conf("idle_timeout", settings.IDLE_TIMEOUT)
def get_god_user():
def get_god_player():
"""
Returns the initially created 'god' User object.
Creates the god user.
"""
return User.objects.get(id=1)
PlayerDB = get_user_model()
try:
god_player = PlayerDB.objects.get(id=1)
except PlayerDB.DoesNotExist:
txt = "\n\nNo superuser exists yet. The superuser is the 'owner' account on the"
txt += "\nEvennia server. Create a new superuser using the command"
txt += "\n\n python manage.py createsuperuser"
txt += "\n\nFollow the prompts, then restart the server."
raise Exception(txt)
return god_player
def create_objects():
"""
@ -38,22 +49,26 @@ def create_objects():
# Set the initial User's account object's username on the #1 object.
# This object is pure django and only holds name, email and password.
god_user = get_god_user()
god_player = get_god_player()
# Create a Player 'user profile' object to hold eventual
# mud-specific settings for the bog standard User object. This is
# accessed by user.get_profile() and can also store attributes.
# It also holds mud permissions, but for a superuser these
# have no effect anyhow.
character_typeclass = settings.BASE_CHARACTER_TYPECLASS
player_typeclass = settings.BASE_PLAYER_TYPECLASS
# Create the Player object as well as the in-game god-character
# for user #1. We can't set location and home yet since nothing
# run all creation hooks on god_player (we must do so manually since the manage.py command does not)
god_player.typeclass_path = player_typeclass
god_player.basetype_setup()
god_player.at_player_creation()
god_player.locks.add("examine:perm(Immortals);edit:false();delete:false();boot:false();msg:all()")
# Create the in-game god-character for player #1. We can't set location and home yet since nothing
# exists. Also, all properties (name, email, password, is_superuser)
# is inherited from the user so we don't specify it again here.
god_player = create.create_player(god_user.username, None, None, user=god_user)
god_character = create.create_object(character_typeclass, key=god_user.username)
character_typeclass = settings.BASE_CHARACTER_TYPECLASS
god_character = create.create_object(character_typeclass, key=god_player.username)
god_character.id = 1
god_character.db.desc = _('This is User #1.')
@ -121,7 +136,7 @@ def create_channels():
return
# connect the god user to all these channels by default.
goduser = get_god_user()
goduser = get_god_player()
from src.comms.models import PlayerChannelConnection
PlayerChannelConnection.objects.create_connection(goduser, pchan)
PlayerChannelConnection.objects.create_connection(goduser, ichan)

View file

@ -77,17 +77,16 @@ class ServerSession(Session):
player - the player associated with the session
"""
self.player = player
self.user = player.user
self.uid = self.user.id
self.uname = self.user.username
self.uid = self.player.id
self.uname = self.player.username
self.logged_in = True
self.conn_time = time.time()
self.puid = None
self.puppet = None
# Update account's last login time.
self.user.last_login = datetime.now()
self.user.save()
self.player.last_login = datetime.now()
self.player.save()
def at_disconnect(self):
"""
@ -97,7 +96,7 @@ class ServerSession(Session):
sessid = self.sessid
player = self.player
_GA(player.dbobj, "unpuppet_object")(sessid)
uaccount = _GA(player.dbobj, "user")
uaccount = player.dbobj
uaccount.last_login = datetime.now()
uaccount.save()
# calling player hook

View file

@ -134,7 +134,6 @@ GAME_CACHE_TYPE = "local"
# memory. So every now and then Evennia checks the size of this cache and resets
# it if it's too big. This variable sets the maximum size (in MB).
ATTRIBUTE_CACHE_MAXSIZE = 100
# OOB (Out-of-band
######################################################################
# Evennia Database config
@ -487,11 +486,12 @@ INSTALLED_APPS = (
'src.comms',
'src.help',
'src.scripts',
'src.web.news',
#'src.web.news',
'src.web.website',)
# The user profile extends the User object with more functionality;
# This should usually not be changed.
AUTH_PROFILE_MODULE = "players.PlayerDB"
AUTH_USER_MODEL = "players.PlayerDB"
#AUTH_PROFILE_MODULE = "players.PlayerDB"
# Use a custom test runner that just tests Evennia-specific apps.
TEST_RUNNER = 'src.utils.test_utils.EvenniaTestSuiteRunner'

View file

@ -22,7 +22,6 @@ Models covered:
Players
"""
from django.conf import settings
from django.contrib.auth.models import User
from django.db import IntegrityError
from src.utils.idmapper.models import SharedMemoryModel
from src.utils import utils, logger
@ -387,49 +386,32 @@ channel = create_channel
# Player creation methods
#
def create_player(name, email, password,
user=None,
def create_player(key, email, password,
typeclass=None,
is_superuser=False,
locks=None, permissions=None,
player_dbobj=None, report_to=None):
report_to=None):
"""
This creates a new player, handling the creation of the User
object and its associated Player object.
This creates a new player.
If player_dbobj is given, this player object is used instead of
creating a new one. This is called by the admin interface since it
needs to create the player object in order to relate it automatically
to the user.
key - the player's name. This should be unique.
email - email on valid addr@addr.domain form.
password - password in cleartext
is_superuser - wether or not this player is to be a superuser
locks - lockstring
permission - list of permissions
report_to - an object with a msg() method to report errors to. If
not given, errors will be logged.
If create_character is
True, a game player object with the same name as the User/Player will
also be created. Its typeclass and base properties can also be given.
Returns the new game character, or the Player obj if no
character is created. For more info about the typeclass argument,
see create_objects() above.
Note: if user is supplied, it will NOT be modified (args name, email,
passw and is_superuser will be ignored). Change those properties
directly on the User instead.
If no permissions are given (None), the default permission group
as defined in settings.PERMISSION_PLAYER_DEFAULT will be
assigned. If permissions are given, no automatic assignment will
occur.
Will return the Player-typeclass or None/raise Exception if the
Typeclass given failed to load.
Concerning is_superuser:
A superuser should have access to everything
in the game and on the server/web interface. The very first user
created in the database is always a superuser (that's using
django's own creation, not this one).
Usually only the server admin should need to be superuser, all
other access levels can be handled with more fine-grained
permissions or groups.
Since superuser overrules all permissions, we don't
set any in this case.
permissions or groups. A superuser bypasses all lock checking
operations and is thus not suitable for play-testing the game.
"""
global _PlayerDB, _Player
@ -440,48 +422,28 @@ def create_player(name, email, password,
if not email:
email = "dummy@dummy.com"
if user:
new_user = user
email = user.email
if user:
conflict_check = User.objects.filter(username__iexact=user.username)
conflict_check = len(conflict_check) > 1
else:
conflict_check = User.objects.filter(username__iexact=name)
if conflict_check:
raise ValueError("A user with this name already exists.")
if not user:
if is_superuser:
new_user = User.objects.create_superuser(name, email, password)
else:
new_user = User.objects.create_user(name, email, password)
if _PlayerDB.objects.filter(username__iexact=key):
raise ValueError("A Player with this name already exists.")
try:
# create the correct Player object
if is_superuser:
new_db_player = _PlayerDB.objects.create_superuser(key, email, password)
else:
new_db_player = _PlayerDB.objects.create_user(key, email, password)
if not typeclass:
typeclass = settings.BASE_PLAYER_TYPECLASS
elif isinstance(typeclass, _PlayerDB):
# this is already an objectdb instance, extract its typeclass
# this is an PlayerDB instance, extract its typeclass path
typeclass = typeclass.typeclass.path
elif isinstance(typeclass, _Player) or utils.inherits_from(typeclass, _Player):
# this is already an object typeclass, extract its path
# this is Player object typeclass, extract its path
typeclass = typeclass.path
if player_dbobj:
try:
_GA(player_dbobj, "dbobj")
new_db_player = player_dbobj.dbobj
except AttributeError:
new_db_player = player_dbobj
# use the typeclass from this object
typeclass = new_db_player.typeclass_path
else:
new_user = User.objects.get(username=new_user.username)
new_db_player = _PlayerDB(db_key=name, user=new_user)
new_db_player.save()
# assign the typeclass
typeclass = utils.to_unicode(typeclass)
new_db_player.typeclass_path = typeclass
# assign the typeclass
typeclass = utils.to_unicode(typeclass)
new_db_player.typeclass_path = typeclass
# this will either load the typeclass or the default one
new_player = new_db_player.typeclass
@ -500,34 +462,27 @@ def create_player(name, email, password,
# call hook method (may override default permissions)
new_player.at_player_creation()
print
# custom given arguments potentially overrides the hook
if permissions:
new_player.permissions = permissions
elif not new_player.permissions:
new_player.permissions = settings.PERMISSION_PLAYER_DEFAULT
if locks:
new_player.locks.add(locks)
return new_player
except Exception:
# a failure in creating the character
if not user:
# in there was a failure we clean up everything we can
logger.log_trace()
try:
new_user.delete()
except Exception:
pass
try:
new_player.delete()
except Exception:
pass
try:
del new_player
except Exception:
pass
# a failure in creating the player; we try to clean
# up as much as we can
logger.log_trace()
try:
new_player.delete()
except Exception:
pass
try:
del new_player
except Exception:
pass
raise
# alias

View file

@ -16,11 +16,11 @@ the database model and call its 'objects' property.
Also remember that all commands in this file return lists (also if
there is only one match) unless noted otherwise.
Example: To reach the search method 'get_object_with_user'
Example: To reach the search method 'get_object_with_player'
in src/objects/managers.py:
> from src.objects.models import ObjectDB
> match = Object.objects.get_object_with_user(...)
> match = Object.objects.get_object_with_player(...)
"""

View file

@ -1,7 +1,7 @@
#
# This module implements a simple news entry system
# for the evennia website. One needs to use the
# admin interface to add/edit/delete entries.
# for the evennia website. One needs to use the
# admin interface to add/edit/delete entries.
#
from django.db import models
@ -13,8 +13,8 @@ class NewsTopic(models.Model):
"""
name = models.CharField(max_length=75, unique=True)
description = models.TextField(blank=True)
icon = models.ImageField(upload_to='newstopic_icons',
default='newstopic_icons/default.png',
icon = models.ImageField(upload_to='newstopic_icons',
default='newstopic_icons/default.png',
blank=True, help_text="Image for the news topic.")
def __str__(self):
@ -35,7 +35,7 @@ class NewsEntry(models.Model):
body = models.TextField()
topic = models.ForeignKey(NewsTopic, related_name='newstopic')
date_posted = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title