Merged script/scripts commands. Resolve #1502

This commit is contained in:
Griatch 2021-08-07 23:11:21 +02:00
parent 8497dfa933
commit 1196196ed8
5 changed files with 374 additions and 408 deletions

View file

@ -80,6 +80,8 @@ Up requirements to Django 3.2+
`Command.retain_instance` flag for reusing the same command instance.
- The `typeclass` command will now correctly search the correct database-table for the target
obj (avoids mistakenly assigning an AccountDB-typeclass to a Character etc).
- Merged `script` and `scripts` commands into one, for both managing global- and
on-object Scripts. Moved `CmdScripts` and `CmdObjects` to `commands/default/building.py`.
### Evennia 0.9.5 (2019-2020)

View file

@ -2,9 +2,11 @@
Building and world design commands
"""
import re
from django.core.paginator import Paginator
from django.conf import settings
from django.db.models import Q, Min, Max
from evennia import InterruptCommand
from evennia.scripts.models import ScriptDB
from evennia.objects.models import ObjectDB
from evennia.locks.lockhandler import LockException
from evennia.commands.cmdhandler import get_and_merge_cmdsets
@ -14,13 +16,14 @@ from evennia.utils.utils import (
class_from_module,
get_all_typeclasses,
variable_from_module,
dbref,
dbref, crop,
interactive,
list_to_string,
display_len,
)
from evennia.utils.eveditor import EvEditor
from evennia.utils.evmore import EvMore
from evennia.utils.evtable import EvTable
from evennia.prototypes import spawner, prototypes as protlib, menus as olc_menus
from evennia.utils.ansi import raw as ansi_raw
@ -53,7 +56,8 @@ __all__ = (
"CmdExamine",
"CmdFind",
"CmdTeleport",
"CmdScript",
"CmdScripts",
"CmdObjects",
"CmdTag",
"CmdSpawn",
)
@ -2983,6 +2987,330 @@ class CmdFind(COMMAND_DEFAULT_CLASS):
caller.msg(string.strip())
class ScriptEvMore(EvMore):
"""
Listing 1000+ Scripts can be very slow and memory-consuming. So
we use this custom EvMore child to build en EvTable only for
each page of the list.
"""
def init_pages(self, scripts):
"""Prepare the script list pagination"""
script_pages = Paginator(scripts, max(1, int(self.height / 2)))
super().init_pages(script_pages)
def page_formatter(self, scripts):
"""Takes a page of scripts and formats the output
into an EvTable."""
if not scripts:
return "<No scripts>"
table = EvTable(
"|wdbref|n",
"|wobj|n",
"|wkey|n",
"|wintval|n",
"|wnext|n",
"|wrept|n",
"|wtypeclass|n",
"|wdesc|n",
align="r",
border="tablecols",
width=self.width,
)
for script in scripts:
nextrep = script.time_until_next_repeat()
if nextrep is None:
nextrep = script.db._paused_time
nextrep = f"PAUSED {int(nextrep)}s" if nextrep else "--"
else:
nextrep = f"{nextrep}s"
maxrepeat = script.repeats
remaining = script.remaining_repeats() or 0
if maxrepeat:
rept = "%i/%i" % (maxrepeat - remaining, maxrepeat)
else:
rept = "-/-"
table.add_row(
f"#{script.id}",
f"{script.obj.key}({script.obj.dbref})"
if (hasattr(script, "obj") and script.obj)
else "<Global>",
script.key,
script.interval if script.interval > 0 else "--",
nextrep,
rept,
script.typeclass_path.rsplit(".", 1)[-1],
crop(script.desc, width=20),
)
return str(table)
class CmdScripts(COMMAND_DEFAULT_CLASS):
"""
List and manage all running scripts. Allows for creating new global
scripts.
Usage:
script[/switches] [script-#dbref, key, script.path or <obj>]
script[/start||stop] <obj> = <script.path or script-key>
Switches:
start - start/unpause an existing script's timer.
stop - stops an existing script's timer
pause - pause a script's timer
delete - deletes script. This will also stop the timer as needed
Examples:
script - list scripts
script myobj - list all scripts on object
script foo.bar.Script - create a new global Script
script scriptname - examine named existing global script
script myobj = foo.bar.Script - create and assign script to object
script/stop myobj = scriptname - stop script on object
script/pause foo.Bar.Script - pause global script
script/delete myobj - delete ALL scripts on object
When given with an `<obj>` as left-hand-side, this creates and
assigns a new script to that object. Without an `<obj>`, this
manages and inspects global scripts
If no switches are given, this command just views all active
scripts. The argument can be either an object, at which point it
will be searched for all scripts defined on it, or a script name
or #dbref. For using the /stop switch, a unique script #dbref is
required since whole classes of scripts often have the same name.
Use the `script` build-level command for managing scripts attached to
objects.
"""
key = "scripts"
aliases = ["script"]
switch_options = ("create", "start", "stop", "pause", "delete")
locks = "cmd:perm(scripts) or perm(Builder)"
help_category = "System"
excluded_typeclass_paths = ["evennia.prototypes.prototypes.DbPrototype"]
switch_mapping = {
"create": "|gCreated|n",
"start": "|gStarted|n",
"stop": "|RStopped|n",
"pause": "|Paused|n",
"delete": "|rDeleted|n"
}
def _search_script(self, args):
# test first if this is a script match
scripts = ScriptDB.objects.get_all_scripts(key=args)
if scripts:
return scripts
# try typeclass path
scripts = ScriptDB.objects.filter(db_typeclass_path__iendswith=args)
if scripts:
return scripts
def func(self):
"""implement method"""
caller = self.caller
if not self.args:
# show all scripts
scripts = ScriptDB.objects.all()
if not scripts:
caller.msg("No scripts found.")
return
ScriptEvMore(caller, scripts.order_by("id"), session=self.session)
return
# find script or object to operate on
scripts, obj = None, None
if self.rhs:
obj_query = self.lhs
script_query = self.rhs
else:
obj_query = script_query = self.args
scripts = self._search_script(script_query)
objects = ObjectDB.objects.object_search(obj_query)
obj = objects[0] if objects else None
if not self.switches:
# creation / view mode
if obj:
# we have an object
if self.rhs:
# creation mode
if obj.scripts.add(self.rhs, autostart=True):
caller.msg(
f"Script |w{self.rhs}|n successfully added and "
f"started on {obj.get_display_name(caller)}.")
else:
caller.msg(f"Script {self.rhs} could not be added and/or started "
f"on {obj.get_display_name(caller)} (or it started and "
"immediately shut down).")
else:
# just show all scripts on object
scripts = ScriptDB.objects.filter(db_obj=obj)
if scripts:
ScriptEvMore(caller, scripts.order_by("id"), session=self.session)
else:
caller.msg(f"No scripts defined on {obj}")
elif scripts:
# show found script(s)
ScriptEvMore(caller, scripts.order_by("id"), session=self.session)
else:
# create global script
try:
new_script = create.create_script(self.args)
except ImportError:
logger.log_trace()
new_script = None
if new_script:
caller.msg(f"Global Script Created - "
f"{new_script.key} ({new_script.typeclass_path})")
ScriptEvMore(caller, [new_script], session=self.session)
else:
caller.msg(f"Global Script |rNOT|n Created |r(see log)|n - "
f"arguments: {self.args}")
elif scripts or obj:
# modification switches - must operate on existing scripts
if not scripts:
scripts = ScriptDB.objects.filter(db_obj=obj)
if scripts.count() > 1:
ret = yield(f"Multiple scripts found: {scripts}. Are you sure you want to "
"operate on all of them? [Y]/N? ")
if ret.lower() in ('n', 'no'):
caller.msg("Aborted.")
return
for script in scripts:
script_key = script.key
script_typeclass_path = script.typeclass_path
scripttype = f"Script on {obj}" if obj else "Global Script"
for switch in self.switches:
verb = self.switch_mapping[switch]
msgs = []
try:
getattr(script, switch)()
except Exception:
logger.log_trace()
msgs.append(f"{scripttype} |rNOT|n {verb} |r(see log)|n - "
f"{script_key} ({script_typeclass_path})|n")
else:
msgs.append(f"{scripttype} {verb} - "
f"{script_key} ({script_typeclass_path})")
caller.msg("\n".join(msgs))
if "delete" not in self.switches:
ScriptEvMore(caller, [script], session=self.session)
else:
caller.msg("No scripts found.")
class CmdObjects(COMMAND_DEFAULT_CLASS):
"""
statistics on objects in the database
Usage:
objects [<nr>]
Gives statictics on objects in database as well as
a list of <nr> latest objects in database. If not
given, <nr> defaults to 10.
"""
key = "objects"
aliases = ["listobjects", "listobjs", "stats", "db"]
locks = "cmd:perm(listobjects) or perm(Builder)"
help_category = "System"
def func(self):
"""Implement the command"""
caller = self.caller
nlim = int(self.args) if self.args and self.args.isdigit() else 10
nobjs = ObjectDB.objects.count()
Character = class_from_module(settings.BASE_CHARACTER_TYPECLASS)
nchars = Character.objects.all_family().count()
Room = class_from_module(settings.BASE_ROOM_TYPECLASS)
nrooms = Room.objects.all_family().count()
Exit = class_from_module(settings.BASE_EXIT_TYPECLASS)
nexits = Exit.objects.all_family().count()
nother = nobjs - nchars - nrooms - nexits
nobjs = nobjs or 1 # fix zero-div error with empty database
# total object sum table
totaltable = self.styled_table(
"|wtype|n", "|wcomment|n", "|wcount|n", "|w%|n", border="table", align="l"
)
totaltable.align = "l"
totaltable.add_row(
"Characters",
"(BASE_CHARACTER_TYPECLASS + children)",
nchars,
"%.2f" % ((float(nchars) / nobjs) * 100),
)
totaltable.add_row(
"Rooms",
"(BASE_ROOM_TYPECLASS + children)",
nrooms,
"%.2f" % ((float(nrooms) / nobjs) * 100),
)
totaltable.add_row(
"Exits",
"(BASE_EXIT_TYPECLASS + children)",
nexits,
"%.2f" % ((float(nexits) / nobjs) * 100),
)
totaltable.add_row("Other", "", nother, "%.2f" % ((float(nother) / nobjs) * 100))
# typeclass table
typetable = self.styled_table(
"|wtypeclass|n", "|wcount|n", "|w%|n", border="table", align="l"
)
typetable.align = "l"
dbtotals = ObjectDB.objects.get_typeclass_totals()
for stat in dbtotals:
typetable.add_row(
stat.get("typeclass", "<error>"),
stat.get("count", -1),
"%.2f" % stat.get("percent", -1),
)
# last N table
objs = ObjectDB.objects.all().order_by("db_date_created")[max(0, nobjs - nlim) :]
latesttable = self.styled_table(
"|wcreated|n", "|wdbref|n", "|wname|n", "|wtypeclass|n", align="l", border="table"
)
latesttable.align = "l"
for obj in objs:
latesttable.add_row(
utils.datetime_format(obj.date_created), obj.dbref, obj.key, obj.path
)
string = "\n|wObject subtype totals (out of %i Objects):|n\n%s" % (nobjs, totaltable)
string += "\n|wObject typeclass distribution:|n\n%s" % typetable
string += "\n|wLast %s Objects created:|n\n%s" % (min(nobjs, nlim), latesttable)
caller.msg(string)
class CmdTeleport(COMMAND_DEFAULT_CLASS):
"""
teleport object to another location
@ -3107,113 +3435,6 @@ class CmdTeleport(COMMAND_DEFAULT_CLASS):
caller.msg("Teleportation failed.")
class CmdScript(COMMAND_DEFAULT_CLASS):
"""
attach a script to an object
Usage:
addscript[/switch] <obj> [= script_path or <scriptkey>]
Switches:
start - start all non-running scripts on object, or a given script only
stop - stop all scripts on objects, or a given script only
If no script path/key is given, lists all scripts active on the given
object.
Script path can be given from the base location for scripts as given in
settings. If adding a new script, it will be started automatically
(no /start switch is needed). Using the /start or /stop switches on an
object without specifying a script key/path will start/stop ALL scripts on
the object.
"""
key = "addscript"
aliases = ["attachscript"]
switch_options = ("start", "stop")
locks = "cmd:perm(script) or perm(Builder)"
help_category = "Building"
def func(self):
"""Do stuff"""
caller = self.caller
if not self.args:
string = "Usage: script[/switch] <obj> [= script_path or <script key>]"
caller.msg(string)
return
if not self.lhs:
caller.msg("To create a global script you need |wscripts/add <typeclass>|n.")
return
obj = caller.search(self.lhs)
if not obj:
return
result = []
if not self.rhs:
# no rhs means we want to operate on all scripts
scripts = obj.scripts.all()
if not scripts:
result.append("No scripts defined on %s." % obj.get_display_name(caller))
elif not self.switches:
# view all scripts
from evennia.commands.default.system import ScriptEvMore
ScriptEvMore(self.caller, scripts.order_by("id"), session=self.session)
return
elif "start" in self.switches:
num = sum([obj.scripts.start(script.key) for script in scripts])
result.append("%s scripts started on %s." % (num, obj.get_display_name(caller)))
elif "stop" in self.switches:
for script in scripts:
result.append(
"Stopping script %s on %s."
% (script.get_display_name(caller), obj.get_display_name(caller))
)
script.stop()
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:
result.append(
"\nScript %s could not be added and/or started on %s "
"(or it started and immediately shut down)."
% (self.rhs, obj.get_display_name(caller))
)
else:
result.append(
"Script |w%s|n successfully added and started on %s."
% (self.rhs, obj.get_display_name(caller))
)
else:
paths = [self.rhs] + [
"%s.%s" % (prefix, self.rhs) for prefix in settings.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:
result.append("\nScript %s could not be stopped. Does it exist?" % path)
else:
result = ["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:
result.append("\nScript %s could not be (re)started." % path)
else:
result = ["Script started successfully."]
break
EvMore(caller, "".join(result).strip())
class CmdTag(COMMAND_DEFAULT_CLASS):
"""

View file

@ -41,8 +41,6 @@ class CharacterCmdSet(CmdSet):
# System commands
self.add(system.CmdPy())
self.add(system.CmdScripts())
self.add(system.CmdObjects())
self.add(system.CmdAccounts())
self.add(system.CmdService())
self.add(system.CmdAbout())
@ -83,10 +81,11 @@ class CharacterCmdSet(CmdSet):
self.add(building.CmdExamine())
self.add(building.CmdTypeclass())
self.add(building.CmdLock())
self.add(building.CmdScript())
self.add(building.CmdSetHome())
self.add(building.CmdTag())
self.add(building.CmdSpawn())
self.add(building.CmdScripts())
self.add(building.CmdObjects())
# Batchprocessor commands
self.add(batchprocess.CmdBatchCommands())

View file

@ -15,17 +15,13 @@ import twisted
import time
from django.conf import settings
from django.core.paginator import Paginator
from evennia.server.sessionhandler import SESSIONS
from evennia.scripts.models import ScriptDB
from evennia.objects.models import ObjectDB
from evennia.accounts.models import AccountDB
from evennia.utils import logger, utils, gametime, create, search
from evennia.utils import logger, utils, gametime, search
from evennia.utils.eveditor import EvEditor
from evennia.utils.evtable import EvTable
from evennia.utils.evmore import EvMore
from evennia.utils.evmenu import ask_yes_no
from evennia.utils.utils import crop, class_from_module, iter_to_str
from evennia.utils.utils import class_from_module, iter_to_str
from evennia.scripts.taskhandler import TaskHandlerTask
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
@ -41,8 +37,6 @@ __all__ = (
"CmdReset",
"CmdShutdown",
"CmdPy",
"CmdScripts",
"CmdObjects",
"CmdService",
"CmdAbout",
"CmdTime",
@ -412,278 +406,6 @@ class CmdPy(COMMAND_DEFAULT_CLASS):
)
class ScriptEvMore(EvMore):
"""
Listing 1000+ Scripts can be very slow and memory-consuming. So
we use this custom EvMore child to build en EvTable only for
each page of the list.
"""
def init_pages(self, scripts):
"""Prepare the script list pagination"""
script_pages = Paginator(scripts, max(1, int(self.height / 2)))
super().init_pages(script_pages)
def page_formatter(self, scripts):
"""Takes a page of scripts and formats the output
into an EvTable."""
if not scripts:
return "<No scripts>"
table = EvTable(
"|wdbref|n",
"|wobj|n",
"|wkey|n",
"|wintval|n",
"|wnext|n",
"|wrept|n",
"|wtypeclass|n",
"|wdesc|n",
align="r",
border="tablecols",
width=self.width,
)
for script in scripts:
nextrep = script.time_until_next_repeat()
if nextrep is None:
nextrep = script.db._paused_time
nextrep = f"PAUSED {int(nextrep)}s" if nextrep else "--"
else:
nextrep = f"{nextrep}s"
maxrepeat = script.repeats
remaining = script.remaining_repeats() or 0
if maxrepeat:
rept = "%i/%i" % (maxrepeat - remaining, maxrepeat)
else:
rept = "-/-"
table.add_row(
f"#{script.id}",
f"{script.obj.key}({script.obj.dbref})"
if (hasattr(script, "obj") and script.obj)
else "<Global>",
script.key,
script.interval if script.interval > 0 else "--",
nextrep,
rept,
script.typeclass_path.rsplit(".", 1)[-1],
crop(script.desc, width=20),
)
return str(table)
class CmdScripts(COMMAND_DEFAULT_CLASS):
"""
List and manage all running scripts. Allows for creating new global
scripts.
Usage:
script[/switches] [#dbref, key, script.path or <obj>]
Switches:
create - create a new global script of given typeclass path. This will
auto-start the script's timer if it has one.
start - start/unpause an existing script's timer.
stop - stops an existing script's timer
pause - pause a script's timer
delete - deletes script. This will also stop the timer as needed
If no switches are given, this command just views all active
scripts. The argument can be either an object, at which point it
will be searched for all scripts defined on it, or a script name
or #dbref. For using the /stop switch, a unique script #dbref is
required since whole classes of scripts often have the same name.
Use the `script` build-level command for managing scripts attached to
objects.
"""
key = "scripts"
aliases = ["scripts"]
switch_options = ("create", "start", "stop", "pause", "delete")
locks = "cmd:perm(listscripts) or perm(Admin)"
help_category = "System"
excluded_typeclass_paths = ["evennia.prototypes.prototypes.DbPrototype"]
switch_mapping = {
"create": "|gCreated|n",
"start": "|gStarted|n",
"stop": "|RStopped|n",
"pause": "|Paused|n",
"delete": "|rDeleted|n"
}
def _search_script(self, args):
# test first if this is a script match
scripts = ScriptDB.objects.get_all_scripts(key=args)
if scripts:
return scripts
# try typeclass path
scripts = ScriptDB.objects.filter(db_typeclass_path__iendswith=args)
if scripts:
return scripts
# try to find an object instead.
objects = ObjectDB.objects.object_search(args)
if objects:
scripts = ScriptDB.objects.filter(db_obj__in=objects)
return scripts
def func(self):
"""implement method"""
caller = self.caller
args = self.args
if "create" in self.switches:
# global script-start mode
verb = self.switch_mapping['create']
if not args:
caller.msg("Usage script/create <key or typeclass>")
return
new_script = create.create_script(args)
if new_script:
caller.msg(f"Global Script {verb} - {new_script.key} ({new_script.typeclass_path})")
ScriptEvMore(caller, [new_script], session=self.session)
else:
caller.msg(f"Global Script |rNOT|n {verb} |r(see log)|n - arguments: {args}")
return
# all other switches require existing scripts
if args:
scripts = self._search_script(args)
if not scripts:
caller.msg(f"No scripts found matching '{args}'.")
return
else:
scripts = ScriptDB.objects.all()
if not scripts:
caller.msg("No scripts found.")
return
if args and self.switches:
# global script-modifying mode
if scripts.count() > 1:
caller.msg("Multiple script matches. Please refine your search.")
return
script = scripts[0]
script_key = script.key
script_typeclass_path = script.typeclass_path
for switch in self.switches:
verb = self.switch_mapping[switch]
msgs = []
try:
getattr(script, switch)()
except Exception:
logger.log_trace()
msgs.append(f"Global Script |rNOT|n {verb} |r(see log)|n - "
f"{script_key} ({script_typeclass_path})|n")
else:
msgs.append(f"Global Script {verb} - "
f"{script_key} ({script_typeclass_path})")
caller.msg("\n".join(msgs))
if "delete" not in self.switches:
ScriptEvMore(caller, [script], session=self.session)
return
else:
# simply show the found scripts
ScriptEvMore(caller, scripts.order_by("id"), session=self.session)
class CmdObjects(COMMAND_DEFAULT_CLASS):
"""
statistics on objects in the database
Usage:
objects [<nr>]
Gives statictics on objects in database as well as
a list of <nr> latest objects in database. If not
given, <nr> defaults to 10.
"""
key = "objects"
aliases = ["listobjects", "listobjs", "stats", "db"]
locks = "cmd:perm(listobjects) or perm(Builder)"
help_category = "System"
def func(self):
"""Implement the command"""
caller = self.caller
nlim = int(self.args) if self.args and self.args.isdigit() else 10
nobjs = ObjectDB.objects.count()
Character = class_from_module(settings.BASE_CHARACTER_TYPECLASS)
nchars = Character.objects.all_family().count()
Room = class_from_module(settings.BASE_ROOM_TYPECLASS)
nrooms = Room.objects.all_family().count()
Exit = class_from_module(settings.BASE_EXIT_TYPECLASS)
nexits = Exit.objects.all_family().count()
nother = nobjs - nchars - nrooms - nexits
nobjs = nobjs or 1 # fix zero-div error with empty database
# total object sum table
totaltable = self.styled_table(
"|wtype|n", "|wcomment|n", "|wcount|n", "|w%|n", border="table", align="l"
)
totaltable.align = "l"
totaltable.add_row(
"Characters",
"(BASE_CHARACTER_TYPECLASS + children)",
nchars,
"%.2f" % ((float(nchars) / nobjs) * 100),
)
totaltable.add_row(
"Rooms",
"(BASE_ROOM_TYPECLASS + children)",
nrooms,
"%.2f" % ((float(nrooms) / nobjs) * 100),
)
totaltable.add_row(
"Exits",
"(BASE_EXIT_TYPECLASS + children)",
nexits,
"%.2f" % ((float(nexits) / nobjs) * 100),
)
totaltable.add_row("Other", "", nother, "%.2f" % ((float(nother) / nobjs) * 100))
# typeclass table
typetable = self.styled_table(
"|wtypeclass|n", "|wcount|n", "|w%|n", border="table", align="l"
)
typetable.align = "l"
dbtotals = ObjectDB.objects.get_typeclass_totals()
for stat in dbtotals:
typetable.add_row(
stat.get("typeclass", "<error>"),
stat.get("count", -1),
"%.2f" % stat.get("percent", -1),
)
# last N table
objs = ObjectDB.objects.all().order_by("db_date_created")[max(0, nobjs - nlim) :]
latesttable = self.styled_table(
"|wcreated|n", "|wdbref|n", "|wname|n", "|wtypeclass|n", align="l", border="table"
)
latesttable.align = "l"
for obj in objs:
latesttable.add_row(
utils.datetime_format(obj.date_created), obj.dbref, obj.key, obj.path
)
string = "\n|wObject subtype totals (out of %i Objects):|n\n%s" % (nobjs, totaltable)
string += "\n|wObject typeclass distribution:|n\n%s" % typetable
string += "\n|wLast %s Objects created:|n\n%s" % (min(nobjs, nlim), latesttable)
caller.msg(string)
class CmdAccounts(COMMAND_DEFAULT_CLASS):
"""
Manage registered accounts

View file

@ -565,10 +565,10 @@ class TestSystem(CommandTest):
self.call(system.CmdPy(), "/clientraw 1+2", ">>> 1+2|3")
def test_scripts(self):
self.call(system.CmdScripts(), "", "dbref ")
self.call(building.CmdScripts(), "", "dbref ")
def test_objects(self):
self.call(system.CmdObjects(), "", "Object subtype totals")
self.call(building.CmdObjects(), "", "Object subtype totals")
def test_about(self):
self.call(system.CmdAbout(), "", None)
@ -1573,36 +1573,58 @@ class TestBuilding(CommandTest):
self.call(building.CmdFind(), f"=#{id1}-{id2}", f"{mdiff} Matches(#{id1}-#{id2}):")
def test_script(self):
self.call(building.CmdScript(), "Obj = ", "No scripts defined on Obj")
self.call(building.CmdScripts(), "Obj", "No scripts defined on Obj")
self.call(
building.CmdScript(), "Obj = scripts.Script", "Script scripts.Script successfully added"
building.CmdScripts(),
"Obj = scripts.Script",
"Script scripts.Script successfully added"
)
self.call(building.CmdScript(), "", "Usage: ")
self.call(
building.CmdScript(),
"= Obj",
"To create a global script you need scripts/add <typeclass>.",
building.CmdScripts(),
"evennia.Dummy",
"Global Script NOT Created "
)
self.call(building.CmdScript(), "Obj ", "dbref ")
self.call(
building.CmdScripts(),
"evennia.scripts.scripts.DoNothing",
"Global Script Created - sys_do_nothing "
)
self.call(building.CmdScripts(), "Obj ", "dbref ")
self.call(
building.CmdScript(), "/start Obj", "1 scripts started on Obj"
building.CmdScripts(), "/start Obj", "Script on Obj Started "
) # we allow running start again; this should still happen
self.call(building.CmdScript(), "/stop Obj", "Stopping script")
self.call(building.CmdScripts(), "/stop Obj", "Script on Obj Stopped - ")
self.call(
building.CmdScript(), "Obj = scripts.Script", "Script scripts.Script successfully added"
building.CmdScripts(), "Obj = scripts.Script",
"Script scripts.Script successfully added",
inputs=["Y"]
)
self.call(
building.CmdScript(),
building.CmdScripts(),
"/start Obj = scripts.Script",
"Script scripts.Script could not be (re)started.",
"Script on Obj Started ",
inputs=["Y"]
)
self.call(
building.CmdScript(),
building.CmdScripts(),
"/stop Obj = scripts.Script",
"Script stopped and removed from object.",
"Script on Obj Stopped ",
inputs=["Y"]
)
self.call(
building.CmdScripts(),
"/delete Obj = scripts.Script",
"Script on Obj Deleted ",
inputs=["Y"]
)
self.call(
building.CmdScripts(),
"/delete evennia.scripts.scripts.DoNothing",
"Global Script Deleted -"
)
def test_teleport(self):
oid = self.obj1.id