Trunk: Merged griatch-branch. This implements a new reload mechanism - splitting Evennia into two processes: Server and Portal with different tasks. Also cleans and fixes several bugs in script systems as well as introduces i18n (courtesy of raydeejay).
This commit is contained in:
parent
14dae44a46
commit
f13e8cdf7c
50 changed files with 3175 additions and 2565 deletions
|
|
@ -87,7 +87,7 @@ class CmdBoot(MuxCommand):
|
|||
feedback += "\nReason given: %s" % reason
|
||||
|
||||
for session in boot_list:
|
||||
name = session.name
|
||||
name = session.uname
|
||||
session.msg(feedback)
|
||||
session.disconnect()
|
||||
caller.msg("You booted %s." % name)
|
||||
|
|
|
|||
|
|
@ -408,7 +408,8 @@ class CmdCreate(ObjManipCommand):
|
|||
if caller.location:
|
||||
obj.home = caller.location
|
||||
obj.move_to(caller.location, quiet=True)
|
||||
caller.msg(string)
|
||||
if string:
|
||||
caller.msg(string)
|
||||
|
||||
|
||||
class CmdDebug(MuxCommand):
|
||||
|
|
@ -1077,7 +1078,7 @@ class CmdOpen(ObjManipCommand):
|
|||
exit_obj.destination = destination
|
||||
string = "Created new Exit '%s' from %s to %s (aliases: %s)." % (exit_name,location.name,
|
||||
destination.name,
|
||||
exit_aliases)
|
||||
", ".join([str(e) for e in exit_aliases]))
|
||||
else:
|
||||
string = "Error: Exit '%s' not created." % (exit_name)
|
||||
# emit results
|
||||
|
|
@ -1824,17 +1825,19 @@ class CmdScript(MuxCommand):
|
|||
attach scripts
|
||||
|
||||
Usage:
|
||||
@script[/switch] <obj> = <script.path or scriptkey>
|
||||
@script[/switch] <obj> [= <script.path or scriptkey>]
|
||||
|
||||
Switches:
|
||||
start - start a previously added script
|
||||
stop - stop a previously added script
|
||||
|
||||
Attaches the given script to the object and starts it. Script path can be given
|
||||
from the base location for scripts as given in settings.
|
||||
If stopping/starting an already existing script, the script's key
|
||||
can be given instead (if giving a path, *all* scripts with this path
|
||||
on <obj> will be affected).
|
||||
Attaches the given script to the object and starts it. Script path
|
||||
can be given from the base location for scripts as given in
|
||||
settings. If stopping/starting an already existing script, the
|
||||
script's key can be given instead (if giving a path, *all* scripts
|
||||
with this path on <obj> will be affected). If no script name is given,
|
||||
all scripts on the object is affected (or displayed if no start/stop
|
||||
switch is set).
|
||||
"""
|
||||
|
||||
key = "@script"
|
||||
|
|
@ -1847,8 +1850,8 @@ class CmdScript(MuxCommand):
|
|||
|
||||
caller = self.caller
|
||||
|
||||
if not self.rhs:
|
||||
string = "Usage: @script[/switch] <obj> = <script.path or script key>"
|
||||
if not self.args:
|
||||
string = "Usage: @script[/switch] <obj> [= <script.path or script key>]"
|
||||
caller.msg(string)
|
||||
return
|
||||
|
||||
|
|
@ -1857,33 +1860,52 @@ class CmdScript(MuxCommand):
|
|||
return
|
||||
|
||||
string = ""
|
||||
if not self.switches:
|
||||
# adding a new script, and starting it
|
||||
ok = obj.scripts.add(self.rhs, autostart=True)
|
||||
if not ok:
|
||||
string += "\nScript %s could not be added and/or started." % self.rhs
|
||||
if not self.rhs:
|
||||
# no rhs means we want to operate on all scripts
|
||||
scripts = obj.scripts.all()
|
||||
if not scripts:
|
||||
string += "No scripts defined on %s." % obj.key
|
||||
elif not self.switches:
|
||||
# view all scripts
|
||||
from src.commands.default.system import format_script_list
|
||||
string += format_script_list(scripts)
|
||||
elif "start" in self.switches:
|
||||
num = sum([obj.scripts.start(script.key) for script in scripts])
|
||||
string += "%s scripts started on %s." % num
|
||||
elif "stop" in self.switches:
|
||||
for script in scripts:
|
||||
string += "Stopping script %s." % script.key
|
||||
script.stop()
|
||||
string = string.strip()
|
||||
obj.scripts.validate()
|
||||
else: # rhs exists
|
||||
if not self.switches:
|
||||
# adding a new script, and starting it
|
||||
ok = obj.scripts.add(self.rhs, autostart=True)
|
||||
if not ok:
|
||||
string += "\nScript %s could not be added and/or started." % self.rhs
|
||||
else:
|
||||
string = "Script successfully added and started."
|
||||
|
||||
else:
|
||||
string = "Script successfully added and started."
|
||||
|
||||
else:
|
||||
paths = [self.rhs] + ["%s.%s" % (prefix, self.rhs)
|
||||
for prefix in settings.SCRIPT_TYPECLASS_PATHS]
|
||||
if "stop" in self.switches:
|
||||
# we are stopping an already existing script
|
||||
for path in paths:
|
||||
ok = obj.scripts.stop(path)
|
||||
if not ok:
|
||||
string += "\nScript %s could not be stopped. Does it exist?" % path
|
||||
else:
|
||||
string = "Script stopped and removed from object."
|
||||
break
|
||||
if "start" in self.switches:
|
||||
# we are starting an already existing script
|
||||
for path in paths:
|
||||
ok = obj.scripts.start(path)
|
||||
if not ok:
|
||||
string += "\nScript %s could not be (re)started." % path
|
||||
else:
|
||||
string = "Script started successfully."
|
||||
break
|
||||
paths = [self.rhs] + ["%s.%s" % (prefix, self.rhs)
|
||||
for prefix in settings.SCRIPT_TYPECLASS_PATHS]
|
||||
if "stop" in self.switches:
|
||||
# we are stopping an already existing script
|
||||
for path in paths:
|
||||
ok = obj.scripts.stop(path)
|
||||
if not ok:
|
||||
string += "\nScript %s could not be stopped. Does it exist?" % path
|
||||
else:
|
||||
string = "Script stopped and removed from object."
|
||||
break
|
||||
if "start" in self.switches:
|
||||
# we are starting an already existing script
|
||||
for path in paths:
|
||||
ok = obj.scripts.start(path)
|
||||
if not ok:
|
||||
string += "\nScript %s could not be (re)started." % path
|
||||
else:
|
||||
string = "Script started successfully."
|
||||
break
|
||||
caller.msg(string.strip())
|
||||
|
|
|
|||
|
|
@ -34,11 +34,12 @@ class DefaultCmdSet(CmdSet):
|
|||
|
||||
# System commands
|
||||
self.add(system.CmdReload())
|
||||
self.add(system.CmdReset())
|
||||
self.add(system.CmdShutdown())
|
||||
self.add(system.CmdPy())
|
||||
self.add(system.CmdScripts())
|
||||
self.add(system.CmdObjects())
|
||||
self.add(system.CmdService())
|
||||
self.add(system.CmdShutdown())
|
||||
self.add(system.CmdVersion())
|
||||
self.add(system.CmdTime())
|
||||
self.add(system.CmdServerLoad())
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ from src.comms import irc, imc2
|
|||
from src.comms.channelhandler import CHANNELHANDLER
|
||||
from src.utils import create, utils
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
from src.server.sessionhandler import SESSIONS
|
||||
|
||||
def find_channel(caller, channelname, silent=False, noaliases=False):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ class CmdLook(MuxCommand):
|
|||
"""
|
||||
caller = self.caller
|
||||
args = self.args
|
||||
|
||||
if args:
|
||||
# Use search to handle duplicate/nonexistant results.
|
||||
looking_at_obj = caller.search(args, use_nicks=True)
|
||||
|
|
@ -345,7 +344,7 @@ class CmdQuit(MuxCommand):
|
|||
def func(self):
|
||||
"hook function"
|
||||
for session in self.caller.sessions:
|
||||
session.msg("Quitting. Hope to see you soon again.")
|
||||
session.msg("{RQuitting{n. Hope to see you soon again.")
|
||||
session.session_disconnect()
|
||||
|
||||
class CmdWho(MuxCommand):
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from src.scripts.models import ScriptDB
|
|||
from src.objects.models import ObjectDB
|
||||
from src.players.models import PlayerDB
|
||||
from src.server.models import ServerConfig
|
||||
from src.utils import reloads, create, logger, utils, gametime
|
||||
from src.utils import create, logger, utils, gametime
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
|
||||
|
|
@ -26,8 +26,9 @@ class CmdReload(MuxCommand):
|
|||
Usage:
|
||||
@reload
|
||||
|
||||
This reloads the system modules and
|
||||
re-validates all scripts.
|
||||
This restarts the server. The Portal is not
|
||||
affected. Non-persistent scripts will survive a @reload (use
|
||||
@reset to purge) and at_reload() hooks will be called.
|
||||
"""
|
||||
key = "@reload"
|
||||
locks = "cmd:perm(reload) or perm(Immortals)"
|
||||
|
|
@ -37,7 +38,62 @@ class CmdReload(MuxCommand):
|
|||
"""
|
||||
Reload the system.
|
||||
"""
|
||||
reloads.start_reload_loop()
|
||||
SESSIONS.announce_all(" Server restarting ...")
|
||||
SESSIONS.server.shutdown(mode='reload')
|
||||
|
||||
class CmdReset(MuxCommand):
|
||||
"""
|
||||
Reset and reboot the system
|
||||
|
||||
Usage:
|
||||
@reset
|
||||
|
||||
A cold reboot. This works like a mixture of @reload and @shutdown,
|
||||
- all shutdown hooks will be called and non-persistent scrips will
|
||||
be purged. But the Portal will not be affected and the server will
|
||||
automatically restart again.
|
||||
"""
|
||||
key = "@reset"
|
||||
aliases = ['@reboot']
|
||||
locks = "cmd:perm(reload) or perm(Immortals)"
|
||||
help_category = "System"
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
Reload the system.
|
||||
"""
|
||||
SESSIONS.announce_all(" Server restarting ...")
|
||||
SESSIONS.server.shutdown(mode='reset')
|
||||
|
||||
|
||||
class CmdShutdown(MuxCommand):
|
||||
|
||||
"""
|
||||
@shutdown
|
||||
|
||||
Usage:
|
||||
@shutdown [announcement]
|
||||
|
||||
Gracefully shut down both Server and Portal.
|
||||
"""
|
||||
key = "@shutdown"
|
||||
locks = "cmd:perm(shutdown) or perm(Immortals)"
|
||||
help_category = "System"
|
||||
|
||||
def func(self):
|
||||
"Define function"
|
||||
try:
|
||||
session = self.caller.sessions[0]
|
||||
except Exception:
|
||||
return
|
||||
self.caller.msg('Shutting down server ...')
|
||||
announcement = "\nServer is being SHUT DOWN!\n"
|
||||
if self.args:
|
||||
announcement += "%s\n" % self.args
|
||||
logger.log_infomsg('Server shutdown by %s.' % self.caller.name)
|
||||
SESSIONS.announce_all(announcement)
|
||||
SESSIONS.portal_shutdown()
|
||||
SESSIONS.server.shutdown(mode='shutdown')
|
||||
|
||||
class CmdPy(MuxCommand):
|
||||
"""
|
||||
|
|
@ -115,6 +171,58 @@ class CmdPy(MuxCommand):
|
|||
except AssertionError: # this is a strange thing; the script looses its id somehow..?
|
||||
pass
|
||||
|
||||
|
||||
# helper function. Kept outside so it can be imported and run
|
||||
# by other commands.
|
||||
|
||||
def format_script_list(scripts):
|
||||
"Takes a list of scripts and formats the output."
|
||||
if not scripts:
|
||||
return "<No scripts>"
|
||||
|
||||
table = [["id"], ["obj"], ["key"], ["intval"], ["next"], ["rept"], ["db"], ["typeclass"], ["desc"]]
|
||||
for script in scripts:
|
||||
|
||||
table[0].append(script.id)
|
||||
if not hasattr(script, 'obj') or not script.obj:
|
||||
table[1].append("<Global>")
|
||||
else:
|
||||
table[1].append(script.obj.key)
|
||||
table[2].append(script.key)
|
||||
if not hasattr(script, 'interval') or script.interval < 0:
|
||||
table[3].append("--")
|
||||
else:
|
||||
table[3].append("%ss" % script.interval)
|
||||
next = script.time_until_next_repeat()
|
||||
if not next:
|
||||
table[4].append("--")
|
||||
else:
|
||||
table[4].append("%ss" % next)
|
||||
|
||||
if not hasattr(script, 'repeats') or not script.repeats:
|
||||
table[5].append("--")
|
||||
else:
|
||||
table[5].append("%s" % script.repeats)
|
||||
if script.persistent:
|
||||
table[6].append("*")
|
||||
else:
|
||||
table[6].append("-")
|
||||
typeclass_path = script.typeclass_path.rsplit('.', 1)
|
||||
table[7].append("%s" % typeclass_path[-1])
|
||||
table[8].append(script.desc)
|
||||
|
||||
ftable = utils.format_table(table)
|
||||
string = ""
|
||||
for irow, row in enumerate(ftable):
|
||||
if irow == 0:
|
||||
srow = "\n" + "".join(row)
|
||||
srow = "{w%s{n" % srow.rstrip()
|
||||
else:
|
||||
srow = "\n" + "{w%s{n" % row[0] + "".join(row[1:])
|
||||
string += srow.rstrip()
|
||||
return string.strip()
|
||||
|
||||
|
||||
class CmdScripts(MuxCommand):
|
||||
"""
|
||||
Operate on scripts.
|
||||
|
|
@ -137,54 +245,7 @@ class CmdScripts(MuxCommand):
|
|||
aliases = "@listscripts"
|
||||
locks = "cmd:perm(listscripts) or perm(Wizards)"
|
||||
help_category = "System"
|
||||
|
||||
def format_script_list(self, scripts):
|
||||
"Takes a list of scripts and formats the output."
|
||||
if not scripts:
|
||||
return "<No scripts>"
|
||||
|
||||
table = [["id"], ["obj"], ["key"], ["intval"], ["next"], ["rept"], ["db"], ["typeclass"], ["desc"]]
|
||||
for script in scripts:
|
||||
|
||||
table[0].append(script.id)
|
||||
if not hasattr(script, 'obj') or not script.obj:
|
||||
table[1].append("<Global>")
|
||||
else:
|
||||
table[1].append(script.obj.key)
|
||||
table[2].append(script.key)
|
||||
if not hasattr(script, 'interval') or script.interval < 0:
|
||||
table[3].append("--")
|
||||
else:
|
||||
table[3].append("%ss" % script.interval)
|
||||
next = script.time_until_next_repeat()
|
||||
if not next:
|
||||
table[4].append("--")
|
||||
else:
|
||||
table[4].append("%ss" % next)
|
||||
|
||||
if not hasattr(script, 'repeats') or not script.repeats:
|
||||
table[5].append("--")
|
||||
else:
|
||||
table[5].append("%s" % script.repeats)
|
||||
if script.persistent:
|
||||
table[6].append("*")
|
||||
else:
|
||||
table[6].append("-")
|
||||
typeclass_path = script.typeclass_path.rsplit('.', 1)
|
||||
table[7].append("%s" % typeclass_path[-1])
|
||||
table[8].append(script.desc)
|
||||
|
||||
ftable = utils.format_table(table)
|
||||
string = ""
|
||||
for irow, row in enumerate(ftable):
|
||||
if irow == 0:
|
||||
srow = "\n" + "".join(row)
|
||||
srow = "{w%s{n" % srow.rstrip()
|
||||
else:
|
||||
srow = "\n" + "{w%s{n" % row[0] + "".join(row[1:])
|
||||
string += srow.rstrip()
|
||||
return string.strip()
|
||||
|
||||
|
||||
def func(self):
|
||||
"implement method"
|
||||
|
||||
|
|
@ -232,7 +293,7 @@ class CmdScripts(MuxCommand):
|
|||
else:
|
||||
# multiple matches.
|
||||
string = "Multiple script matches. Please refine your search:\n"
|
||||
string += self.format_script_list(scripts)
|
||||
string += format_script_list(scripts)
|
||||
elif self.switches and self.switches[0] in ("validate", "valid", "val"):
|
||||
# run validation on all found scripts
|
||||
nr_started, nr_stopped = ScriptDB.objects.validate(scripts=scripts)
|
||||
|
|
@ -240,7 +301,7 @@ class CmdScripts(MuxCommand):
|
|||
string += "Started %s and stopped %s scripts." % (nr_started, nr_stopped)
|
||||
else:
|
||||
# No stopping or validation. We just want to view things.
|
||||
string = self.format_script_list(scripts)
|
||||
string = format_script_list(scripts)
|
||||
caller.msg(string)
|
||||
|
||||
|
||||
|
|
@ -411,34 +472,6 @@ class CmdService(MuxCommand):
|
|||
caller.msg("Starting service '%s'." % self.args)
|
||||
service.startService()
|
||||
|
||||
class CmdShutdown(MuxCommand):
|
||||
|
||||
"""
|
||||
@shutdown
|
||||
|
||||
Usage:
|
||||
@shutdown [announcement]
|
||||
|
||||
Shut the game server down gracefully.
|
||||
"""
|
||||
key = "@shutdown"
|
||||
locks = "cmd:perm(shutdown) or perm(Immortals)"
|
||||
help_category = "System"
|
||||
|
||||
def func(self):
|
||||
"Define function"
|
||||
try:
|
||||
session = self.caller.sessions[0]
|
||||
except Exception:
|
||||
return
|
||||
self.caller.msg('Shutting down server ...')
|
||||
announcement = "\nServer is being SHUT DOWN!\n"
|
||||
if self.args:
|
||||
announcement += "%s\n" % self.args
|
||||
logger.log_infomsg('Server shutdown by %s.' % self.caller.name)
|
||||
SESSIONS.announce_all(announcement)
|
||||
SESSIONS.server.shutdown()
|
||||
|
||||
class CmdVersion(MuxCommand):
|
||||
"""
|
||||
@version - game version
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ except ImportError:
|
|||
from django.test import TestCase
|
||||
from django.conf import settings
|
||||
from src.utils import create, ansi
|
||||
from src.server import session, sessionhandler
|
||||
from src.server import serversession, sessionhandler
|
||||
from src.locks.lockhandler import LockHandler
|
||||
from src.server.models import ServerConfig
|
||||
from src.comms.models import Channel, Msg, PlayerChannelConnection, ExternalChannelConnection
|
||||
|
|
@ -46,15 +46,37 @@ def cleanup():
|
|||
ExternalChannelConnection.objects.all().delete()
|
||||
ServerConfig.objects.all().delete()
|
||||
|
||||
class FakeSession(session.Session):
|
||||
class FakeSessionHandler(sessionhandler.ServerSessionHandler):
|
||||
"""
|
||||
Fake sessionhandler, without an amp connection
|
||||
"""
|
||||
def portal_shutdown(self):
|
||||
pass
|
||||
def disconnect(self, session, reason=""):
|
||||
pass
|
||||
def login(self, session):
|
||||
pass
|
||||
def session_sync(self):
|
||||
pass
|
||||
def data_out(self, session, string="", data=""):
|
||||
return string
|
||||
|
||||
SESSIONS = FakeSessionHandler()
|
||||
|
||||
class FakeSession(serversession.ServerSession):
|
||||
"""
|
||||
A fake session that
|
||||
implements dummy versions of the real thing; this is needed to
|
||||
mimic a logged-in player.
|
||||
"""
|
||||
protocol_key = "TestProtocol"
|
||||
sessdict = {'protocol_key':'telnet', 'address':('0.0.0.0','5000'), 'sessid':2, 'uid':2, 'uname':None,
|
||||
'logged_in':False, 'cid':None, 'ndb':{}, 'encoding':'utf-8',
|
||||
'conn_time':time.time(), 'cmd_last':time.time(), 'cmd_last_visible':time.time(), 'cmd_total':1}
|
||||
|
||||
def connectionMade(self):
|
||||
self.session_connect('0,0,0,0')
|
||||
self.load_sync_data(self.sessdict)
|
||||
self.sessionhandler = SESSIONS
|
||||
def disconnectClient(self):
|
||||
pass
|
||||
def lineReceived(self, raw_string):
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ class CmdQuit(MuxCommand):
|
|||
"Simply close the connection."
|
||||
session = self.caller
|
||||
session.msg("Good bye! Disconnecting ...")
|
||||
session.at_disconnect()
|
||||
session.session_disconnect()
|
||||
|
||||
class CmdUnconnectedLook(MuxCommand):
|
||||
"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue