mirror of
https://github.com/evennia/evennia.git
synced 2026-03-18 13:56:30 +01:00
The system uses a hybrid blacklisting/whitelisting and AST-traversal approach to both remove dangerous builtins as well as disallow potentially exploitable python structures alltogether. Examples are while structures and attribute allocation. All advanced functionality is accessed through a set of "safe" methods on a holder object. You can extend this with your own safe methods in order to add more functionality befitting your game. The system comes with a host of examples, a few scriptable objects and complete commands for adding code to objects. At this point it's not guaranteed that all systems are safe against meddling however - notably Attributes have no locks defined on them by default (although this system does properly check Attribute lock types should they exixt). Please test and try to break - and report problems to the Issue tracker/forum as usual.
136 lines
4.8 KiB
Python
136 lines
4.8 KiB
Python
|
|
"""
|
|
|
|
Evlang usage examples
|
|
Commands for use with evlang
|
|
|
|
Evennia contribution - Griatch 2012
|
|
|
|
The @code command allows to add scripted evlang code to
|
|
a ScriptableObject. It will handle access checks.
|
|
|
|
"""
|
|
|
|
from ev import utils
|
|
from ev import default_cmds
|
|
|
|
#------------------------------------------------------------
|
|
# Evlang-related commands
|
|
#
|
|
# Easiest is to add this command to the default cmdset.
|
|
# Alternatively one could imagine storing it directly only
|
|
# on scriptable objects.
|
|
#------------------------------------------------------------
|
|
|
|
class CmdCode(default_cmds.MuxCommand):
|
|
"""
|
|
add custom code to a scriptable object
|
|
|
|
Usage:
|
|
@code[/switch] <obj>[/<type> [= <codestring> ]]
|
|
|
|
Switch:
|
|
|
|
delete - clear code of given type from the object.
|
|
debug - immediately run the given code after adding it.
|
|
|
|
This will add custom scripting to an object
|
|
which allows such modification.
|
|
|
|
<type> must be one of the script types allowed
|
|
on the object. Only supplying the command will
|
|
return a list of script types possible to add
|
|
custom scripts to.
|
|
|
|
"""
|
|
key = "@code"
|
|
locks = "cmd:perm(Builders)"
|
|
help_category = "Building"
|
|
|
|
def func(self):
|
|
"implements the functionality."
|
|
caller = self.caller
|
|
|
|
if not self.args:
|
|
caller.msg("Usage: @code <obj>[/<type> [= <codestring>]]")
|
|
return
|
|
codetype = None
|
|
objname = self.lhs
|
|
if '/' in self.lhs:
|
|
objname, codetype = [part.strip() for part in self.lhs.rsplit("/", 1)]
|
|
|
|
obj = self.caller.search(objname)
|
|
if not obj:
|
|
return
|
|
|
|
# get the dicts from db storage for easy referencing
|
|
evlang_scripts = obj.db.evlang_scripts
|
|
evlang_locks = obj.db.evlang_locks
|
|
if not (evlang_scripts != None and evlang_locks and obj.ndb.evlang):
|
|
caller.msg("Object %s can not be scripted." % obj.key)
|
|
return
|
|
|
|
if 'delete' in self.switches:
|
|
# clearing a code snippet
|
|
if not codetype:
|
|
caller.msg("You must specify a code type.")
|
|
return
|
|
if not codetype in evlang_scripts:
|
|
caller.msg("Code type '%s' not found on %s." % (codetype, obj.key))
|
|
return
|
|
# this will also update the database
|
|
obj.ndb.evlang.delete(codetype)
|
|
caller.msg("Code for type '%s' cleared on %s." % (codetype, obj.key))
|
|
return
|
|
|
|
if not self.rhs:
|
|
if codetype:
|
|
scripts = [(name, tup[1], utils.crop(tup[0])) for name, tup in evlang_scripts.items() if name==codetype]
|
|
scripts.extend([(name, "--", "--") for name in evlang_locks if name not in evlang_scripts if name==codetype])
|
|
else:
|
|
# no type specified. List all scripts/slots on object
|
|
print evlang_scripts
|
|
scripts = [(name, tup[1], utils.crop(tup[0])) for name, tup in evlang_scripts.items()]
|
|
scripts.extend([(name, "--", "--") for name in evlang_locks if name not in evlang_scripts])
|
|
scripts = sorted(scripts, key=lambda p: p[0])
|
|
|
|
table = [["type"] + [tup[0] for tup in scripts],
|
|
["creator"] + [tup[1] for tup in scripts],
|
|
["code"] + [tup[2] for tup in scripts]]
|
|
ftable = utils.format_table(table, extra_space=5)
|
|
string = "{wEvlang scripts on %s:{n" % obj.key
|
|
for irow, row in enumerate(ftable):
|
|
if irow == 0:
|
|
string += "\n" + "".join("{w%s{n" % col for col in row)
|
|
else:
|
|
string += "\n" + "".join(col for col in row)
|
|
|
|
caller.msg(string)
|
|
return
|
|
|
|
# we have rhs
|
|
codestring = self.rhs
|
|
if not codetype in evlang_locks:
|
|
caller.msg("Code type '%s' cannot be coded on %s." % (codetype, obj.key))
|
|
return
|
|
# check access with the locktype "code"
|
|
if not obj.ndb.evlang.lockhandler.check(caller, "code"):
|
|
caller.msg("You are not permitted to add code of type %s." % codetype)
|
|
return
|
|
# we have code access to this type.
|
|
oldcode = None
|
|
if codetype in evlang_scripts:
|
|
oldcode = str(evlang_scripts[codetype][0])
|
|
# this updates the database right away too
|
|
obj.ndb.evlang.add(codetype, codestring, scripter=caller)
|
|
if oldcode:
|
|
caller.msg("{wReplaced{n\n %s\n{wWith{n\n %s" % (oldcode, codestring))
|
|
else:
|
|
caller.msg("Code added in '%s':\n %s" % (codetype, codestring))
|
|
if "debug" in self.switches:
|
|
# debug mode
|
|
caller.msg("{wDebug: running script (look out for errors below) ...{n\n" + "-"*68)
|
|
obj.ndb.evlang.run_by_name(codetype, caller, quiet=False)
|
|
|
|
|
|
|