Implemented locks.
The main command to use is @lock, which accept three types of locks at the moment, and three types of keys: Locks: DefaultLock, UseLock, EnterLock Keys: ObjectIDs, Groups, Permissions This offers the most useful functionality - stopping people from picking up things, blocking exits and stopping anyone from using an object. If the attributes lock_msg, use_lock_msg and enter_lock_msg are defined on the locked object, these will be used as error messages instead of a standard one (so "the door is locked" instead of "you cannot traverse that exit"). Behind the scenes, there is a new module, src/locks.py that defines Keys and Locks. A Locks object is a collection of Lock types. This is stored in the LOCKS attribute on objects. Each Lock contains a set of Keys that might be of mixed type and which the player must match in order to pass the lock. /Griatch
This commit is contained in:
parent
7f7306a6e4
commit
66095a0b16
7 changed files with 491 additions and 26 deletions
|
|
@ -278,7 +278,11 @@ def match_exits(command,test=False):
|
|||
if targ_exit.get_home():
|
||||
# SCRIPT: See if the player can traverse the exit
|
||||
if not targ_exit.scriptlink.default_lock(source_object):
|
||||
source_object.emit_to("You can't traverse that exit.")
|
||||
lock_msg = targ_exit.get_attribute_value("lock_msg")
|
||||
if lock_msg:
|
||||
source_object.emit_to(lock_msg)
|
||||
else:
|
||||
source_object.emit_to("You can't traverse that exit.")
|
||||
else:
|
||||
source_object.move_to(targ_exit.get_home())
|
||||
else:
|
||||
|
|
@ -287,22 +291,33 @@ def match_exits(command,test=False):
|
|||
raise ExitCommandHandler
|
||||
|
||||
|
||||
def command_table_lookup(command, command_table, eval_perms=True,test=False):
|
||||
def command_table_lookup(command, command_table, eval_perms=True,test=False,neighbor=None):
|
||||
"""
|
||||
Performs a command table lookup on the specified command table. Also
|
||||
evaluates the permissions tuple.
|
||||
The test flag only checks without manipulating the command
|
||||
neighbor (object) If this is supplied, we are looking at a object table and
|
||||
must check for locks.
|
||||
"""
|
||||
# Get the command's function reference (Or False)
|
||||
cmdtuple = command_table.get_command_tuple(command.command_string)
|
||||
if cmdtuple:
|
||||
# Check if this is just a test.
|
||||
if test:
|
||||
return True
|
||||
# Check locks
|
||||
if neighbor and not neighbor.scriptlink.use_lock(command.source_object):
|
||||
# send an locked error message only if lock_desc is defined
|
||||
lock_msg = neighbor.get_attribute_value("use_lock_msg")
|
||||
if lock_msg:
|
||||
command.source_object.emit_to(lock_msg)
|
||||
raise ExitCommandHandler
|
||||
return False
|
||||
# If there is a permissions element to the entry, check perms.
|
||||
if eval_perms and cmdtuple[1]:
|
||||
if not command.source_object.has_perm_list(cmdtuple[1]):
|
||||
command.source_object.emit_to(defines_global.NOPERMS_MSG)
|
||||
raise ExitCommandHandler
|
||||
raise ExitCommandHandler
|
||||
# If flow reaches this point, user has perms and command is ready.
|
||||
command.command_function = cmdtuple[0]
|
||||
command.extra_vars = cmdtuple[2]
|
||||
|
|
@ -321,7 +336,9 @@ def match_neighbor_ctables(command,test=False):
|
|||
neighbors = source_object.location.get_contents()
|
||||
for neighbor in neighbors:
|
||||
if command_table_lookup(command,
|
||||
neighbor.scriptlink.command_table, test=test):
|
||||
neighbor.scriptlink.command_table,
|
||||
test=test, neighbor=neighbor):
|
||||
# test for a use-lock
|
||||
# If there was a command match, set the scripted_obj attribute
|
||||
# for the script parent to pick up.
|
||||
if test:
|
||||
|
|
|
|||
|
|
@ -167,13 +167,22 @@ def cmd_get(command):
|
|||
return
|
||||
|
||||
if not obj_is_staff and (target_obj.is_player() or target_obj.is_exit()):
|
||||
|
||||
source_object.emit_to("You can't get that.")
|
||||
return
|
||||
|
||||
|
||||
if target_obj.is_room() or target_obj.is_garbage() or target_obj.is_going():
|
||||
source_object.emit_to("You can't get that.")
|
||||
return
|
||||
|
||||
|
||||
if not target_obj.scriptlink.default_lock(source_object):
|
||||
lock_msg = target_obj.get_attribute_value("lock_msg")
|
||||
if lock_msg:
|
||||
source_object.emit_to(lock_msg)
|
||||
else:
|
||||
source_object.emit_to("You can't get that.")
|
||||
return
|
||||
|
||||
target_obj.move_to(source_object, quiet=True)
|
||||
source_object.emit_to("You pick up %s." % (target_obj.get_name(show_dbref=False),))
|
||||
source_object.get_location().emit_to_contents("%s picks up %s." %
|
||||
|
|
@ -282,11 +291,14 @@ def cmd_examine(command):
|
|||
|
||||
s += str(target_obj.get_name(fullname=True)) + newl
|
||||
s += str("Type: %s Flags: %s" % (target_obj.get_type(),
|
||||
target_obj.get_flags())) + newl
|
||||
#s += str("Desc: %s" % target_obj.get_attribute_value('desc')) + newl
|
||||
target_obj.get_flags())) + newl
|
||||
s += str("Owner: %s " % target_obj.get_owner()) + newl
|
||||
s += str("Zone: %s" % target_obj.get_zone()) + newl
|
||||
s += str("Parent: %s " % target_obj.get_script_parent()) + newl
|
||||
|
||||
locks = target_obj.get_attribute_value("LOCKS")
|
||||
if locks and "%s" % locks:
|
||||
s += str("Locks: %s" % locks) + newl
|
||||
|
||||
# Contents container lists for sorting by type.
|
||||
con_players = []
|
||||
|
|
@ -313,6 +325,7 @@ def cmd_examine(command):
|
|||
# This obviously isn't valid for rooms.
|
||||
s += str("Location: %s" % target_obj.get_location()) + newl
|
||||
|
||||
# Render other attributes
|
||||
for attribute in target_obj.get_all_attributes():
|
||||
s += str(attribute.get_attrline()) + newl
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
"""
|
||||
These commands typically are to do with building or modifying Objects.
|
||||
"""
|
||||
from django.contrib.auth.models import Permission, Group
|
||||
from src.objects.models import Object, Attribute
|
||||
# We'll import this as the full path to avoid local variable clashes.
|
||||
import src.flags
|
||||
from src import locks
|
||||
from src import ansi
|
||||
from src.cmdtable import GLOBAL_CMD_TABLE
|
||||
from src import defines_global
|
||||
|
|
@ -445,7 +447,7 @@ def cmd_create(command):
|
|||
return
|
||||
|
||||
eq_args = command.command_argument.split(':', 1)
|
||||
target_name = eq_args[0]
|
||||
target_name = eq_args[0].strip()
|
||||
|
||||
#check if we want to set a custom parent
|
||||
script_parent = None
|
||||
|
|
@ -814,7 +816,7 @@ def cmd_dig(command):
|
|||
where you are.
|
||||
|
||||
Usage:
|
||||
@dig[/switches] roomname [:parent] [= exitthere [: parent][;alias]] [, exithere [: parent][;alias]]
|
||||
@dig[/switches] roomname [:parent] [= exit_to_there [: parent][;alias]] [, exit_to_here [: parent][;alias]]
|
||||
|
||||
switches:
|
||||
teleport - move yourself to the new room
|
||||
|
|
@ -829,7 +831,7 @@ def cmd_dig(command):
|
|||
switches = command.command_switches
|
||||
|
||||
if not args:
|
||||
source_object.emit_to("Usage[/teleport]: @dig roomname [:parent][= exitthere [:parent] [;alias]] [, exithere [:parent] [;alias]]")
|
||||
source_object.emit_to("Usage: @dig[/teleport] roomname [:parent][= exit_to_there [:parent] [;alias]] [, exit_to_here [:parent] [;alias]]")
|
||||
return
|
||||
|
||||
room_name = None
|
||||
|
|
@ -1158,3 +1160,148 @@ def cmd_destroy(command):
|
|||
|
||||
GLOBAL_CMD_TABLE.add_command("@destroy", cmd_destroy,
|
||||
priv_tuple=("objects.create",),auto_help=True,staff_help=True)
|
||||
|
||||
def cmd_lock(command):
|
||||
"""@lock
|
||||
Usage:
|
||||
@lock[/switch] <obj> [:type] [= <key>[,key2,key3,...]]
|
||||
|
||||
switches:
|
||||
add - add a lock (default) from object
|
||||
del - remove a lock from object
|
||||
list - view all locks on object (default)
|
||||
type:
|
||||
DefaultLock - the default lock type (default)
|
||||
|
||||
Locks an object for everyone except those matching the keys.
|
||||
The keys can be of the following types (and searched in this order):
|
||||
- a user #dbref (#2, #45 etc)
|
||||
- a Group name (Builder, Immortal etc, case sensitive)
|
||||
- a Permission string (genperms.get, etc)
|
||||
If no keys are given, the object is locked for everyone.
|
||||
|
||||
When the lock blocks a user, you may customize which error is given by
|
||||
storing error messages in an attribute. For DefaultLocks, UseLocks and
|
||||
EnterLocks, these attributes are called lock_msg, use_lock_msg and
|
||||
enter_lock_msg respectively.
|
||||
<<TOPIC:lock types>>
|
||||
Lock types:
|
||||
|
||||
Name: Affects: Effect:
|
||||
-----------------------------------------------------------------------
|
||||
DefaultLock: Exits: controls who may traverse the exit to
|
||||
its destination.
|
||||
Rooms: controls whether the player sees a failure
|
||||
message after the room description when
|
||||
looking at the room.
|
||||
Players/Things: controls who may 'get' the object.
|
||||
|
||||
UseLock: All but Exits: controls who may use commands defined on
|
||||
the locked object.
|
||||
|
||||
EnterLock: Players/Things: controls who may enter/teleport into
|
||||
the object.
|
||||
|
||||
Fail messages echoed to the player are stored in the attributes 'lock_msg',
|
||||
'use_lock_msg' and 'enter_lock_msg' on the locked object in question. If no
|
||||
such message is stored, a default will be used (or none at all in some cases).
|
||||
"""
|
||||
|
||||
source_object = command.source_object
|
||||
arg = command.command_argument
|
||||
switches = command.command_switches
|
||||
|
||||
if not arg:
|
||||
source_object.emit_to("Usage: @lock[/switch] <obj> [:type] [= <key>[,key2,key3,...]]")
|
||||
return
|
||||
keys = ""
|
||||
#deal with all possible arguments.
|
||||
try:
|
||||
lside, keys = arg.split("=",1)
|
||||
except ValueError:
|
||||
lside = arg
|
||||
lside, keys = lside.strip(), keys.strip()
|
||||
try:
|
||||
obj_name, ltype = lside.split(":",1)
|
||||
except:
|
||||
obj_name = lside
|
||||
ltype = "DefaultLock"
|
||||
obj_name, ltype = obj_name.strip(), ltype.strip()
|
||||
|
||||
if ltype not in ["DefaultLock","UseLock","EnterLock"]:
|
||||
source_object.emit_to("Lock type '%s' not recognized." % ltype)
|
||||
return
|
||||
|
||||
obj = source_object.search_for_object(obj_name)
|
||||
if not obj:
|
||||
return
|
||||
|
||||
obj_locks = obj.get_attribute_value("LOCKS")
|
||||
|
||||
if "list" in switches or not switches:
|
||||
if not obj_locks:
|
||||
s = "There are no locks on %s." % obj.get_name()
|
||||
else:
|
||||
s = "Locks on %s:" % obj.get_name()
|
||||
s += obj_locks.show()
|
||||
source_object.emit_to(s)
|
||||
return
|
||||
|
||||
# we are trying to change things. Check permissions.
|
||||
if not source_object.controls_other(obj):
|
||||
source_object.emit_to(defines_global.NOCONTROL_MSG)
|
||||
return
|
||||
|
||||
if "del" in switches:
|
||||
# clear a lock
|
||||
if obj_locks:
|
||||
if not obj_locks.has_type(ltype):
|
||||
source_object.emit_to("No %s set on this object." % ltype)
|
||||
else:
|
||||
obj_locks.del_type(ltype)
|
||||
obj.set_attribute("LOCKS", obj_locks)
|
||||
source_object.emit_to("Cleared lock %s on %s." % (ltype, obj.get_name()))
|
||||
else:
|
||||
source_object.emit_to("No %s set on this object." % ltype)
|
||||
return
|
||||
else:
|
||||
#try to add a lock
|
||||
if not obj_locks:
|
||||
obj_locks = locks.Locks()
|
||||
if not keys:
|
||||
#add an impassable lock
|
||||
obj_locks.add_type(ltype, locks.Key())
|
||||
source_object.emit_to("Added impassable '%s' lock to %s." % (ltype, obj.get_name()))
|
||||
else:
|
||||
keys = [k.strip() for k in keys.split(",")]
|
||||
okeys, gkeys, pkeys = [], [], []
|
||||
allgroups = [g.name for g in Group.objects.all()]
|
||||
allperms = ["%s.%s" % (p.content_type.app_label, p.codename) for p in Permission.objects.all()]
|
||||
for key in keys:
|
||||
#differentiate different type of keys
|
||||
if Object.objects.is_dbref(key):
|
||||
okeys.append(key)
|
||||
elif key in allgroups:
|
||||
gkeys.append(key)
|
||||
elif key in allperms:
|
||||
pkeys.append(key)
|
||||
else:
|
||||
source_object.emit_to("Key '%s' is not recognized as a valid dbref, group or permission." % key)
|
||||
return
|
||||
# Create actual key objects from the respective lists
|
||||
keys = []
|
||||
if okeys:
|
||||
keys.append(locks.ObjKey(okeys))
|
||||
if gkeys:
|
||||
keys.append(locks.GroupKey(gkeys))
|
||||
if pkeys:
|
||||
keys.append(locks.PermKey(pkeys))
|
||||
#store the keys in the lock
|
||||
obj_locks.add_type(ltype, keys)
|
||||
kstring = ""
|
||||
for key in keys:
|
||||
kstring += " %s" % key
|
||||
source_object.emit_to("Added lock '%s' to %s with keys%s." % (ltype, obj.get_name(), kstring))
|
||||
|
||||
obj.set_attribute("LOCKS",obj_locks)
|
||||
GLOBAL_CMD_TABLE.add_command("@lock", cmd_lock, priv_tuple=("objects.create",),auto_help=True, staff_help=True)
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ OBJECT_TYPES = (
|
|||
|
||||
# These attribute names can't be modified by players.
|
||||
NOSET_ATTRIBS = ["MONEY", "ALIAS", "LASTPAGED", "__CHANLIST", "LAST",
|
||||
"__PARENT", "LASTSITE"]
|
||||
"__PARENT", "LASTSITE", "LOCKS"]
|
||||
|
||||
# These attributes don't show up on objects when examined.
|
||||
HIDDEN_ATTRIBS = ["__CHANLIST", "__PARENT"]
|
||||
HIDDEN_ATTRIBS = ["__CHANLIST", "__PARENT", "LOCKS"]
|
||||
|
||||
# Server version number.
|
||||
REVISION = os.popen('svnversion .', 'r').readline().strip()
|
||||
|
|
|
|||
246
src/locks.py
Normal file
246
src/locks.py
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
"""
|
||||
This module handles all in-game locks.
|
||||
|
||||
A lock object contains a set of criteria (keys). When queried, the
|
||||
lock tries the tested object/player against these criteria and returns
|
||||
a True/False result.
|
||||
"""
|
||||
import traceback
|
||||
from src.objects.models import Object
|
||||
from src import logger
|
||||
|
||||
class Key(object):
|
||||
"""
|
||||
This implements a lock key.
|
||||
|
||||
Normally the Key is of OR type; if an object matches any criterion in the key,
|
||||
the entire key is considered a match. With the 'exact' criterion, all criteria
|
||||
contained in the key (except the list of object dbrefs) must also exist in the
|
||||
object.
|
||||
With the NOT flag the key is inversed, that is, only objects which do not
|
||||
match the criterias (exact or not) will be considered to have access.
|
||||
|
||||
Supplying no criteria will make the lock impassable (NOT flag results in an alvays open lock)
|
||||
"""
|
||||
def __init__(self, criteria=[], extra=[], NOT=False, exact=False):
|
||||
"""
|
||||
Defines the basic permission laws
|
||||
permlist (list of strings) - permission definitions
|
||||
grouplist (list of strings) - group names
|
||||
objlist (list of obj or dbrefs) - match individual objects to the lock
|
||||
NOT (bool) - invert the lock
|
||||
exact (bool) - objects must match all criteria. Default is OR operation.
|
||||
"""
|
||||
self.criteria = criteria
|
||||
self.extra = extra
|
||||
|
||||
#set the boolean operators
|
||||
self.NOT = not NOT
|
||||
self.exact = exact
|
||||
|
||||
# if we have no criteria, this is an impassable lock (or always open if NOT given).
|
||||
self.impassable = not(criteria)
|
||||
|
||||
def __str__(self):
|
||||
s = ""
|
||||
if not self.criteria:
|
||||
s += " <Impassable>"
|
||||
for crit in self.criteria:
|
||||
s += " <%s>" % crit
|
||||
return s.strip()
|
||||
|
||||
def _result(self, result):
|
||||
if self.exact:
|
||||
result = result == len(self.criteria)
|
||||
if result:
|
||||
return self.NOT
|
||||
else:
|
||||
return not self.NOT
|
||||
|
||||
def check(self, object):
|
||||
"""
|
||||
Compare the object to see if the key matches.
|
||||
"""
|
||||
if self.NOT:
|
||||
return not self.impassable
|
||||
return self.impassable
|
||||
|
||||
class ObjKey(Key):
|
||||
"""
|
||||
This implements a Key matching against object id
|
||||
"""
|
||||
def check(self, object):
|
||||
|
||||
if self.impassable:
|
||||
return self.NOT
|
||||
if object.dbref() in self.criteria:
|
||||
return self.NOT
|
||||
else:
|
||||
return not self.NOT
|
||||
|
||||
class GroupKey(Key):
|
||||
"""
|
||||
This key matches against group membership
|
||||
"""
|
||||
def check(self, object):
|
||||
if self.impassable: return self.NOT
|
||||
user = object.get_user_account()
|
||||
if not user: return False
|
||||
return self._result(len([g for g in user.groups.all() if str(g) in self.criteria]))
|
||||
|
||||
class PermKey(Key):
|
||||
"""
|
||||
This key matches against permissions
|
||||
"""
|
||||
def check(self, object):
|
||||
if self.impassable: return self.NOT
|
||||
user = object.get_user_account()
|
||||
if not user: return False
|
||||
return self._result(len([p for p in self.criteria if object.has_perm(p)]))
|
||||
|
||||
class FlagKey(Key):
|
||||
"""
|
||||
This key use a set of object flagss to define access.
|
||||
"""
|
||||
def check(self, object):
|
||||
if self.impassable: return self.NOT
|
||||
return self._result(len([f for f in self.criteria if object.has_flag(f)]))
|
||||
|
||||
class AttrKey(Key):
|
||||
"""
|
||||
This key use a list of arbitrary attributes to define access.
|
||||
|
||||
The attribute names are in the usual criteria. If there is a matching
|
||||
list of values in the self.extra list we compare the values directly,
|
||||
otherwise we just check for the existence of the attribute.
|
||||
"""
|
||||
def check(self, object):
|
||||
if self.impassable: return self.NOT
|
||||
val_list = self.extra
|
||||
attr_list = self.criteria
|
||||
if len(val_list) == len(attr_list):
|
||||
return self._result(len([i for i in range(attr_list)
|
||||
if object.get_attribute_value(attr_list[i])==val_list[i]]))
|
||||
else:
|
||||
return _result(len([a for a in attr_list if object.get_attribute_value(a)]))
|
||||
|
||||
class Locks(object):
|
||||
"""
|
||||
The Locks object defines an overall grouping of Locks based after type. Each lock
|
||||
contains a set of keys to limit access to a certain action.
|
||||
The Lock object is stored in the attribute LOCKS on the object in question and the
|
||||
engine queries it during the relevant situations.
|
||||
|
||||
Below is a list copied from MUX. Currently Evennia only use 3 lock types:
|
||||
Default, Use and Enter; it's not clear if any more are really needed.
|
||||
|
||||
Name: Affects: Effect:
|
||||
-----------------------------------------------------------------------
|
||||
DefaultLock: Exits: controls who may traverse the exit to
|
||||
its destination.
|
||||
Rooms: controls whether the player sees the SUCC
|
||||
or FAIL message for the room following the
|
||||
room description when looking at the room.
|
||||
Players/Things: controls who may GET the object.
|
||||
EnterLock: Players/Things: controls who may ENTER the object if the
|
||||
object is ENTER_OK. Also, the enter lock
|
||||
of an object being used as a Zone Master
|
||||
Object determines control of that zone.
|
||||
GetFromLock: All but Exits: controls who may gets things from a given
|
||||
location.
|
||||
GiveLock: Players/Things: controls who may give the object.
|
||||
LeaveLock: Players/Things: controls who may LEAVE the object.
|
||||
LinkLock: All but Exits: controls who may link to the location if the
|
||||
location is LINK_OK (for linking exits or
|
||||
setting drop-tos) or ABODE (for setting
|
||||
homes)
|
||||
MailLock: Players: controls who may @mail the player.
|
||||
OpenLock: All but Exits: controls who may open an exit.
|
||||
PageLock: Players: controls who may page the player.
|
||||
ParentLock: All: controls who may make @parent links to the
|
||||
object.
|
||||
ReceiveLock: Players/Things: controls who may give things to the object.
|
||||
SpeechLock: All but Exits: controls who may speak in that location
|
||||
(only checked if AUDITORIUM flag is set
|
||||
on that location)
|
||||
TeloutLock: All but Exits: controls who may teleport out of the
|
||||
location.
|
||||
TportLock: Rooms/Things: controls who may teleport there if the
|
||||
location is JUMP_OK.
|
||||
UseLock: All but Exits: controls who may USE the object, GIVE the
|
||||
object money and have the PAY attributes
|
||||
run, have their messages heard and possibly
|
||||
acted on by LISTEN and AxHEAR, and invoke
|
||||
$-commands stored on the object.
|
||||
DropLock: All but rooms: controls who may drop that object.
|
||||
UserLock: All: Not used by MUX, is intended to be used
|
||||
in MUX programming where a user-defined
|
||||
lock is needed.
|
||||
VisibleLock: All: Controls object visibility when the object
|
||||
is not dark and the looker passes the lock.
|
||||
In DARK locations, the object must also be
|
||||
set LIGHT and the viewer must pass the
|
||||
VisibleLock.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
|
||||
The Lock logic is strictly OR. If you want to make access restricted,
|
||||
make it so in the respective Key.
|
||||
"""
|
||||
self.locks = {}
|
||||
|
||||
def __str__(self):
|
||||
s = ""
|
||||
for lock in self.locks.keys():
|
||||
s += " %s" % lock
|
||||
return s.strip()
|
||||
|
||||
def add_type(self, ltype, keys=[]):
|
||||
"""
|
||||
type (string) : the type pf lock, like DefaultLock, UseLock etc.
|
||||
keylist = list of Key objects defining who have access.
|
||||
"""
|
||||
if type(keys) != type(list()):
|
||||
keys = [keys]
|
||||
self.locks[ltype] = keys
|
||||
|
||||
def del_type(self,ltype):
|
||||
"""
|
||||
Clears a lock.
|
||||
"""
|
||||
if self.has_type(ltype):
|
||||
del self.locks[ltype]
|
||||
|
||||
def has_type(self,ltype):
|
||||
return self.locks.has_key(ltype)
|
||||
|
||||
def show(self):
|
||||
if not self.locks:
|
||||
return "No locks."
|
||||
s = ""
|
||||
for lock, keys in self.locks.items():
|
||||
s += "\n %s\n " % lock
|
||||
for key in keys:
|
||||
s += " %s" % key
|
||||
return s
|
||||
|
||||
def check(self, ltype, object):
|
||||
"""
|
||||
This is called by the engine. It checks if this lock is of the right type,
|
||||
and if so if there is access. If the type does not exist, there is no
|
||||
lock for it and thus we return True.
|
||||
"""
|
||||
if not self.has_type(ltype):
|
||||
return True
|
||||
result = False
|
||||
for key in self.locks[ltype]:
|
||||
try:
|
||||
result = result or key.check(object)
|
||||
except KeyError:
|
||||
pass
|
||||
if not result and object.is_superuser():
|
||||
object.emit_to("Lock '%s' - Superuser override." % ltype)
|
||||
return True
|
||||
return result
|
||||
|
|
@ -338,6 +338,22 @@ class Object(models.Model):
|
|||
# Fall through to failure
|
||||
return False
|
||||
|
||||
def has_group(self, group):
|
||||
"""
|
||||
Checks if a user is member of a particular user group.
|
||||
"""
|
||||
if not self.is_player():
|
||||
return False
|
||||
|
||||
if self.is_superuser():
|
||||
return True
|
||||
|
||||
if group in [g.name for g in self.get_user_account().groups.all()]:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def owns_other(self, other_obj):
|
||||
"""
|
||||
See if the envoked object owns another object.
|
||||
|
|
@ -367,7 +383,7 @@ class Object(models.Model):
|
|||
|
||||
# When builder_override is enabled, a builder permission means
|
||||
# the object controls the other.
|
||||
if builder_override and not other_obj.is_player() and self.has_perm('genperms.builder'):
|
||||
if builder_override and not other_obj.is_player() and self.has_group('Builders'):
|
||||
return True
|
||||
|
||||
# They've failed to meet any of the above conditions.
|
||||
|
|
@ -883,9 +899,18 @@ class Object(models.Model):
|
|||
quiet: (bool) If true, don't emit left/arrived messages.
|
||||
force_look: (bool) If true and self is a player, make them 'look'.
|
||||
"""
|
||||
|
||||
|
||||
#first, check if we can enter that location at all.
|
||||
if not target.scriptlink.enter_lock(self):
|
||||
lock_desc = self.get_attribute_value("enter_lock_msg")
|
||||
if lock_desc:
|
||||
self.emit_to(lock_desc)
|
||||
else:
|
||||
self.emit_to("That destination is blocked from you.")
|
||||
return
|
||||
|
||||
#before the move, call eventual pre-commands.
|
||||
if self.scriptlink.at_before_move(target) != None:
|
||||
if self.scriptlink.at_before_move(target) != None:
|
||||
return
|
||||
|
||||
if not quiet:
|
||||
|
|
|
|||
|
|
@ -135,16 +135,24 @@ class EvenniaBasicObject(object):
|
|||
# This is the object being looked at.
|
||||
target_obj = self.scripted_obj
|
||||
# See if the envoker sees dbref numbers.
|
||||
lock_msg = ""
|
||||
if pobject:
|
||||
show_dbrefs = pobject.sees_dbrefs()
|
||||
show_dbrefs = pobject.sees_dbrefs()
|
||||
|
||||
#check for the defaultlock, this shows a lock message after the normal desc, if one is defined.
|
||||
if target_obj.is_room() and \
|
||||
not target_obj.scriptlink.default_lock(pobject):
|
||||
temp = target_obj.get_attribute_value("lock_msg")
|
||||
if temp:
|
||||
lock_msg = "\n%s" % temp
|
||||
else:
|
||||
show_dbrefs = False
|
||||
|
||||
|
||||
description = target_obj.get_attribute_value('desc')
|
||||
if description is not None:
|
||||
retval = "%s\r\n%s" % (
|
||||
retval = "%s\r\n%s%s" % (
|
||||
target_obj.get_name(show_dbref=show_dbrefs),
|
||||
target_obj.get_attribute_value('desc'),
|
||||
target_obj.get_attribute_value('desc'), lock_msg
|
||||
)
|
||||
else:
|
||||
retval = "%s" % (
|
||||
|
|
@ -192,8 +200,11 @@ class EvenniaBasicObject(object):
|
|||
values:
|
||||
* pobject: (Object) The object requesting the action.
|
||||
"""
|
||||
# Assume everyone passes the default lock by default.
|
||||
return True
|
||||
locks = self.scripted_obj.get_attribute_value("LOCKS")
|
||||
if locks:
|
||||
return locks.check("DefaultLock", pobject)
|
||||
else:
|
||||
return True
|
||||
|
||||
def use_lock(self, pobject):
|
||||
"""
|
||||
|
|
@ -204,8 +215,11 @@ class EvenniaBasicObject(object):
|
|||
values:
|
||||
* pobject: (Object) The object requesting the action.
|
||||
"""
|
||||
# Assume everyone passes the use lock by default.
|
||||
return True
|
||||
locks = self.scripted_obj.get_attribute_value("LOCKS")
|
||||
if locks:
|
||||
return locks.check("UseLock", pobject)
|
||||
else:
|
||||
return True
|
||||
|
||||
def enter_lock(self, pobject):
|
||||
"""
|
||||
|
|
@ -216,5 +230,8 @@ class EvenniaBasicObject(object):
|
|||
values:
|
||||
* pobject: (Object) The object requesting the action.
|
||||
"""
|
||||
# Assume everyone passes the enter lock by default.
|
||||
return True
|
||||
locks = self.scripted_obj.get_attribute_value("LOCKS")
|
||||
if locks:
|
||||
return locks.check("EnterLock", pobject)
|
||||
else:
|
||||
return True
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue