Patched the batch-processor's interactive mode so it will not abort if it processes an object/script parent that changes the player's state. Also added a variable BATCH_IMPORT_PATH to config so one can keep all batch scripts in one location and don't have to write the full path to get them. Default is the new directory game/gamesrc/world.
Added the permission genperms.admin_nostate so that builders can avoid entering a state when working on a room with a state-changing parent. Superusers have to set the flag ADMIN_NOSTATE on themselves to achieve the same effect (this is necessary since superusers always have all permissions, so they would otherwise never be able to enter states). /Griatch
This commit is contained in:
parent
c4114938cc
commit
a6ae6e936a
4 changed files with 63 additions and 16 deletions
|
|
@ -48,6 +48,7 @@ An example batch file is found in game/gamesrc/commands/examples.
|
|||
"""
|
||||
import os
|
||||
import re
|
||||
from django.conf import settings
|
||||
from src import logger
|
||||
from src import defines_global
|
||||
from src.cmdtable import GLOBAL_CMD_TABLE
|
||||
|
|
@ -55,7 +56,7 @@ from src.statetable import GLOBAL_STATE_TABLE
|
|||
|
||||
#global defines for storage
|
||||
|
||||
STATENAME="interactive batch processor"
|
||||
STATENAME="_interactive batch processor"
|
||||
CMDSTACKS={} # user:cmdstack pairs (for interactive)
|
||||
STACKPTRS={} # user:stackpointer pairs (for interactive)
|
||||
FILENAMES={} # user:filename pairs (for interactive/reload)
|
||||
|
|
@ -69,8 +70,10 @@ cnorm = r"%cn"
|
|||
def read_batchbuild_file(filename):
|
||||
"""
|
||||
This reads the contents of batchfile.
|
||||
"""
|
||||
filename = os.path.abspath(filename)
|
||||
Filename is considered to be the name of the batch file
|
||||
relative the directory specified in settings.py
|
||||
"""
|
||||
filename = os.path.abspath("%s/%s" % (settings.BATCH_IMPORT_PATH, filename))
|
||||
try:
|
||||
f = open(filename)
|
||||
except IOError:
|
||||
|
|
@ -191,12 +194,15 @@ def cmd_batchprocess(command):
|
|||
#parse indata file
|
||||
commands = parse_batchbuild_file(filename)
|
||||
if not commands:
|
||||
source_object.emit_to("'%s'\ncould not be found. Remember that you have to supply the absolute path to the file." % filename)
|
||||
source_object.emit_to("'%s' not found.\nYou have to supply the real path to the file relative to \nyour batch-file directory (e.g. game/gamesrc/world)." % filename)
|
||||
return
|
||||
switches = command.command_switches
|
||||
if switches and switches[0] in ['inter','interactive']:
|
||||
#allow more control over how batch file is executed
|
||||
source_object.set_state(STATENAME)
|
||||
# allow more control over how batch file is executed
|
||||
if not source_object.set_state(STATENAME):
|
||||
source_object.emit_to("You cannot use the interactive mode while you have the flag ADMIN_NOSTATE set.")
|
||||
return
|
||||
|
||||
CMDSTACKS[source_object] = commands
|
||||
STACKPTRS[source_object] = 0
|
||||
FILENAMES[source_object] = filename
|
||||
|
|
@ -288,7 +294,10 @@ def exit_state(source_object):
|
|||
del FILENAMES[source_object]
|
||||
except KeyError:
|
||||
logger.log_errmsg("Batchprocessor quit error: all state vars could not be deleted.")
|
||||
source_object.clear_state()
|
||||
# since clear_state() is protected against exiting the interactive mode
|
||||
# (to avoid accidental drop-outs by rooms clearing a player's state),
|
||||
# we have to clear the state directly here.
|
||||
source_object.state = None
|
||||
|
||||
def cmd_state_ll(command):
|
||||
"""
|
||||
|
|
@ -517,7 +526,7 @@ def cmd_state_hh(command):
|
|||
#create the state; we want it as open as possible so we can do everything
|
||||
# in our batch processing.
|
||||
GLOBAL_STATE_TABLE.add_state(STATENAME,global_cmds='all',
|
||||
allow_exits=True,allow_obj_cmds=True)
|
||||
allow_exits=True,allow_obj_cmds=True,exit_command=True)
|
||||
#add state commands
|
||||
GLOBAL_STATE_TABLE.add_command(STATENAME,"nn",cmd_state_nn)
|
||||
GLOBAL_STATE_TABLE.add_command(STATENAME,"nl",cmd_state_nl)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ SRC_DIR = os.path.join(BASE_PATH, 'src')
|
|||
# Example: "/home/media/media.lawrence.com"
|
||||
MEDIA_ROOT = os.path.join(GAME_DIR, 'web', 'media')
|
||||
|
||||
# Import style path to the script parent module. Must be in the import path.
|
||||
# Import style path to the directory holding script parents. Must be in the import path.
|
||||
SCRIPT_IMPORT_PATH = 'game.gamesrc.parents'
|
||||
# Default parent associated with non-player objects. This starts from where
|
||||
# the SCRIPT_IMPORT_PATH left off.
|
||||
|
|
@ -52,6 +52,10 @@ SCRIPT_DEFAULT_OBJECT = 'base.basicobject'
|
|||
# Default parent associated with player objects. This starts from where
|
||||
# the SCRIPT_IMPORT_PATH left off.
|
||||
SCRIPT_DEFAULT_PLAYER = 'base.basicplayer'
|
||||
# Real path to a directory to be searched for batch scripts for the
|
||||
# batch processor. Specify relative evennia's 'game' directory.
|
||||
BATCH_IMPORT_PATH = 'gamesrc/world'
|
||||
|
||||
|
||||
# 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3', and 'oracle'.
|
||||
DATABASE_ENGINE = 'sqlite3'
|
||||
|
|
@ -125,9 +129,10 @@ PERM_GENPERMS = (
|
|||
("announce", "May make announcements to everyone."),
|
||||
("admin_perm", "Can modify individual permissions."),
|
||||
("admin_group", "Can manage membership in groups."),
|
||||
("process_control", "May shutdown/restart/reload the game"),
|
||||
("process_control", "May shutdown/restart/reload the game."),
|
||||
("manage_players", "Can change passwords, siteban, etc."),
|
||||
("game_info", "Can review game metadata"),)
|
||||
("game_info", "Can review game metadata."),
|
||||
("admin_nostate", "Do not enter states (should be set only temporarily)."),)
|
||||
|
||||
## These permissions are not yet used in the default engine.
|
||||
## ("boot", "May use @boot to kick players"),
|
||||
|
|
|
|||
|
|
@ -1090,13 +1090,46 @@ class Object(models.Model):
|
|||
"""
|
||||
Only allow setting a state on a player object, otherwise
|
||||
fail silently.
|
||||
"""
|
||||
if self.is_player():
|
||||
self.state = state_name
|
||||
|
||||
This command safeguards the batch processor against dropping
|
||||
out of interactive mode; it also allows builders to
|
||||
sidestep room-based states when building (the genperm.admin_nostate
|
||||
permission is not set on anyone by default, set it temporarily
|
||||
when building a state-based room).
|
||||
"""
|
||||
if not self.is_player():
|
||||
return False
|
||||
|
||||
if self.is_superuser():
|
||||
# we have to deal with superusers separately since
|
||||
# they would always appear to have the genperm.admin_nostate
|
||||
# permission. Instead we expect them to set the flag
|
||||
# ADMIN_NOSTATE on themselves if they don't want to
|
||||
# enter states.
|
||||
nostate = self.has_flag("admin_nostate")
|
||||
else:
|
||||
# for other users we request the permission as normal.
|
||||
nostate = self.has_perm("genperms.admin_nostate")
|
||||
|
||||
# we never enter other states if we are in the interactive batch processor.
|
||||
nostate = nostate or self.state == "_interactive batch processor"
|
||||
|
||||
if nostate:
|
||||
return False
|
||||
self.state = state_name
|
||||
return True
|
||||
|
||||
|
||||
def clear_state(self):
|
||||
"Set to no state (return to normal operation)"
|
||||
self.state = None
|
||||
"""
|
||||
Set to no state (return to normal operation)
|
||||
|
||||
This safeguards the batch processor from exiting its
|
||||
interactive mode when entering a room cancelling states.
|
||||
(batch processor clears the state directly instead)
|
||||
"""
|
||||
if not self.state == "_interactive batch processor":
|
||||
self.state = None
|
||||
|
||||
def purge_object(self):
|
||||
"Completely clears all aspects of the object."
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue