Run Migrate. Implemented a full separation between Player and Character - Players (OOC entities) can now also hold cmdsets and execute commands. This means that "disconnecting" from a Character becomes possible, putting the Player in an "OOC" state outside the game. This overall makes the game much more stable since there used to be issues if the character was destroyed. Having an OOC set also avoids the previous problem of @puppeting into an object that didn't have any cmdset of its own - you couldn't get back out! A new default OOC-Cmdset handles commands available to a player while OOC. Commands in this set are applied with a low priority, allowing "IC" mode to give precedence if desired.

This change meant several changes to the lock and permission functionality, since it becomes important if permissions are assigned on the Player or on their Character (lock functions pperm() and pid() etc check on Player rather than Character). This has the boon of allowing Admins to switch and play/test the game as a "Low access" character as they like.

Plenty of bug fixes and adjustments. Migrations should make sure to move over all data properly.
This commit is contained in:
Griatch 2011-04-23 11:54:08 +00:00
parent ce2a8e9ffe
commit 28fe2ad3f4
37 changed files with 1622 additions and 555 deletions

View file

@ -106,6 +106,16 @@ from src.utils import utils
PERMISSION_HIERARCHY = [p.lower() for p in settings.PERMISSION_HIERARCHY]
def _to_player(accessing_obj):
"Helper function. Makes sure an accessing object is a player object"
if utils.inherits_from(accessing_obj, "src.objects.objects.Object"):
# an object. Convert to player.
accessing_obj = accessing_obj.player
return accessing_obj
# lock functions
def true(*args, **kwargs):
"Always returns True."
return True
@ -155,6 +165,29 @@ def perm_above(accessing_obj, accessed_obj, *args, **kwargs):
return any(True for hpos, hperm in enumerate(PERMISSION_HIERARCHY)
if hperm in [p.lower() for p in accessing_obj.permissions] and hpos > ppos)
def pperm(accessing_obj, accessed_obj, *args, **kwargs):
"""
The basic permission-checker for Player objects. Ignores case.
Usage:
pperm(<permission>)
where <permission> is the permission accessing_obj must
have in order to pass the lock. If the given permission
is part of PERMISSION_HIERARCHY, permission is also granted
to all ranks higher up in the hierarchy.
"""
return perm(_to_player(accessing_obj), accessed_obj, *args, **kwargs)
def pperm_above(accessing_obj, accessed_obj, *args, **kwargs):
"""
Only allow Player objects with a permission *higher* in the permission
hierarchy than the one given. If there is no such higher rank,
it's assumed we refer to superuser. If no hierarchy is defined,
this function has no meaning and returns False.
"""
return perm_above(_to_player(accessing_obj), accessed_obj, *args, **kwargs)
def dbref(accessing_obj, accessed_obj, *args, **kwargs):
"""
Usage:
@ -175,10 +208,21 @@ def dbref(accessing_obj, accessed_obj, *args, **kwargs):
return dbref == accessing_obj.id
return False
def pdbref(accessing_obj, accessed_obj, *args, **kwargs):
"""
Same as dbref, but making sure accessing_obj is a player.
"""
return dbref(_to_player(accessing_obj), accessed_obj, *args, **kwargs)
def id(accessing_obj, accessed_obj, *args, **kwargs):
"Alias to dbref"
return dbref(accessing_obj, accessed_obj, *args, **kwargs)
def pid(accessing_obj, accessed_obj, *args, **kwargs):
"Alias to dbref, for Players"
return dbref(_to_player(accessing_obj), accessed_obj, *args, **kwargs)
def attr(accessing_obj, accessed_obj, *args, **kwargs):
"""
Usage:

View file

@ -223,7 +223,8 @@ class LockHandler(object):
wlist.append("Lock: access type '%s' changed from '%s' to '%s' " % \
(access_type, locks[access_type][2], raw_lockstring))
locks[access_type] = (evalstring, tuple(lock_funcs), raw_lockstring)
if wlist:
if wlist and self.log_obj:
# not an error, so only report if log_obj is available.
self._log_error("\n".join(wlist))
if elist:
raise LockException("\n".join(elist))
@ -343,10 +344,11 @@ class LockHandler(object):
to None if the lock functions called don't access it). atype can also be
put to a dummy value since no lock selection is made.
"""
if (hasattr(accessing_obj, 'player') and hasattr(accessing_obj.player, 'user')
and hasattr(accessing_obj.player.user, 'is_superuser')
and accessing_obj.player.user.is_superuser):
return True # always grant access to the superuser.
if ((hasattr(accessing_obj, 'is_superuser') and accessing_obj.is_superuser)
or (hasattr(accessing_obj, 'player') and hasattr(accessing_obj.player, 'is_superuser') and accessing_obj.player.is_superuser)
or (hasattr(accessing_obj, 'get_player') and (accessing_obj.get_player()==None or accessing_obj.get_player().is_superuser))):
return True
locks = self. _parse_lockstring(lockstring)
for access_type in locks:
evalstring, func_tup, raw_string = locks[access_type]