From e3ea0bc94adcc88507cca22dfa4c12faa88fb79b Mon Sep 17 00:00:00 2001
From: Evennia docbuilder action
Date: Fri, 27 Jan 2023 21:31:01 +0000
Subject: [PATCH] Updated HTML docs.
---
docs/1.0/.buildinfo | 2 +-
docs/1.0/Coding/Changelog.html | 16 +-
docs/1.0/Coding/Coding-Overview.html | 1 +
docs/1.0/Contribs/Contrib-XYZGrid.html | 102 +++++++++++--
docs/1.0/_modules/evennia/accounts/bots.html | 2 +-
.../contrib/grid/xyzgrid/commands.html | 80 +++++++++-
.../evennia/contrib/grid/xyzgrid/tests.html | 138 +++++++++++++++---
.../evennia/contrib/grid/xyzgrid/xyzgrid.html | 2 +-
.../evennia/contrib/grid/xyzgrid/xyzroom.html | 7 +-
.../evennia/server/portal/discord.html | 2 +-
.../evennia/server/serversession.html | 2 +-
.../_modules/evennia/utils/funcparser.html | 3 +-
docs/1.0/_sources/Coding/Changelog.md.txt | 13 +-
.../_sources/Contribs/Contrib-XYZGrid.md.txt | 108 ++++++++++++--
.../api/evennia.commands.default.account.html | 4 +-
...evennia.commands.default.batchprocess.html | 4 +-
.../evennia.commands.default.building.html | 4 +-
.../api/evennia.commands.default.comms.html | 8 +-
.../api/evennia.commands.default.general.html | 20 +--
.../api/evennia.commands.default.system.html | 4 +-
.../api/evennia.commands.default.tests.html | 2 +-
.../evennia.commands.default.unloggedin.html | 12 +-
....base_systems.email_login.email_login.html | 12 +-
...b.base_systems.ingame_python.commands.html | 4 +-
...systems.mux_comms_cmds.mux_comms_cmds.html | 4 +-
...rib.full_systems.evscaperoom.commands.html | 16 +-
...ia.contrib.game_systems.barter.barter.html | 4 +-
...ontrib.game_systems.clothing.clothing.html | 4 +-
...trib.game_systems.turnbattle.tb_basic.html | 4 +-
...trib.game_systems.turnbattle.tb_equip.html | 4 +-
...trib.game_systems.turnbattle.tb_items.html | 4 +-
...trib.game_systems.turnbattle.tb_magic.html | 4 +-
...trib.game_systems.turnbattle.tb_range.html | 4 +-
...trib.grid.extended_room.extended_room.html | 4 +-
...evennia.contrib.grid.xyzgrid.commands.html | 72 +++++++++
.../evennia.contrib.grid.xyzgrid.tests.html | 89 +++++++++++
.../api/evennia.contrib.rpg.dice.dice.html | 4 +-
...evennia.contrib.rpg.rpsystem.rpsystem.html | 4 +-
...ontrib.tutorials.evadventure.commands.html | 4 +-
...ntrib.tutorials.red_button.red_button.html | 12 +-
...trib.tutorials.tutorial_world.objects.html | 12 +-
...ontrib.tutorials.tutorial_world.rooms.html | 12 +-
...utils.git_integration.git_integration.html | 4 +-
docs/1.0/api/evennia.utils.eveditor.html | 4 +-
docs/1.0/api/evennia.utils.evmenu.html | 4 +-
docs/1.0/api/evennia.utils.evmore.html | 4 +-
docs/1.0/genindex.html | 60 +++++++-
docs/1.0/objects.inv | Bin 157394 -> 157614 bytes
docs/1.0/searchindex.js | 2 +-
49 files changed, 728 insertions(+), 163 deletions(-)
diff --git a/docs/1.0/.buildinfo b/docs/1.0/.buildinfo
index f81b76de37..f50da4ae6b 100644
--- a/docs/1.0/.buildinfo
+++ b/docs/1.0/.buildinfo
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
-config: 0e68b8fe2e214849d5b14fd5963bb034
+config: 54a57cda813eeb17e132cf9f8e867e51
tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/docs/1.0/Coding/Changelog.html b/docs/1.0/Coding/Changelog.html
index c21c05d97f..41f26416cd 100644
--- a/docs/1.0/Coding/Changelog.html
+++ b/docs/1.0/Coding/Changelog.html
@@ -62,6 +62,7 @@
- Changelog
+- Main
- Evennia 1.1.1
- Evennia 1.1.0
- Evennia 1.0.2
@@ -165,13 +166,24 @@
Changelog
+
+Main
+
+Feature: Add fly/dive commands to XYZGrid contrib to showcase treating its
+Z-axis as a full 3D grid. Also fixed minor bug in XYZGrid contrib when using
+a Z axis named using an integer rather than a string.
+Bug fix: $an() inlinefunc didn’t understand to use ‘an’ words starting with a
+capital vowel
+Bug fix: Another case of the ‘duplicate Discord bot connections’ bug
+
+
Evennia 1.1.1
Bug fix: Better handler malformed alias-regex given to nickhandler. A
regex-relevant character in a channel alias could cause server to not restart.
-Add attr keyword to create_channel. This allows setting attributes on
-channels at creation, also from DEFAULT_CHANNELS definitions.
+Feature: Add attr keyword to create_channel. This allows setting
+attributes on channels at creation, also from DEFAULT_CHANNELS definitions.
diff --git a/docs/1.0/Coding/Coding-Overview.html b/docs/1.0/Coding/Coding-Overview.html
index b706ec2251..3dc7b238d9 100644
--- a/docs/1.0/Coding/Coding-Overview.html
+++ b/docs/1.0/Coding/Coding-Overview.html
@@ -161,6 +161,7 @@ make your game, also if you never coded before.
- Changelog
+- Main
- Evennia 1.1.1
- Evennia 1.1.0
- Evennia 1.0.2
diff --git a/docs/1.0/Contribs/Contrib-XYZGrid.html b/docs/1.0/Contribs/Contrib-XYZGrid.html
index 55108b52b9..19b2a69a45 100644
--- a/docs/1.0/Contribs/Contrib-XYZGrid.html
+++ b/docs/1.0/Contribs/Contrib-XYZGrid.html
@@ -67,7 +67,10 @@
- Overview
- First example usage
- Defining an XYMap
-- The Zcoord
+- The Zcoord
+
- Map String
- Map legend
In the following sections we’ll discuss each component in turn.
The Zcoord
-Each XYMap on the grid has a Z-coordinate which usually can be treated just as the
-name of the map. This is a string that must be unique across the entire grid.
-It is added as the key ‘zcoord’ to XYMAP_DATA.
-Actual 3D movement is usually impractical in a text-based game, so all movements
-and pathfinding etc happens within each XYMap (up/down is ‘faked’ within the XY
-plane). Even for the most hardcore of sci-fi space game, moving on a 2D plane
-usually makes it much easier for players than to attempt to have them visualize
-actual 3D movements.
-If you really wanted an actual 3D coordinate system, you could theoretically
-make all maps the same size and name them 0, 1, 2 etc. But even then, you
-could not freely move up/down between every point (a special Transitional Node
-is required as outlined below). Also pathfinding will only work per-XYMap.
+Each XYMap on the grid has a Z-coordinate which usually can be treated just as
+the name of the map. The Z-coordinate can be either a string or an integer, and must
+be unique across the entire grid. It is added as the key ‘zcoord’ to XYMAP_DATA.
Most users will want to just treat each map as a location, and name the
-“Z-coordinate” things like Dungeon of Doom, The ice queen's palace or City of Blackhaven.
+“Z-coordinate” things like Dungeon of Doom, The ice queen's palace or City of Blackhaven. But you could also name it -1, 0, 1, 2, 3 if you wanted.
+Pathfinding happens only within each XYMap (up/down is normally ‘faked’ by moving
+sideways to a new area of the XY plane).
+
+A true 3D map
+Even for the most hardcore of sci-fi space game, consider sticking to 2D
+movement. It’s hard enough for players to visualize a 3D volume with graphics.
+In text it’s even harder.
+That said, if you want to set up a true X, Y, Z 3D coordinate system (where
+you can move up/down from every point), you can do that too.
+This contrib provides an example command commands.CmdFlyAndDive that provides the player
+with the ability to use fly and dive to move straight up/down between Z
+coordinates. Just add it (or its cmdset commands.XYZGridFlyDiveCmdSet) to your
+Character cmdset and reload to try it out.
+For the fly/dive to work you need to build your grid as a ‘stack’ of XY-grid maps
+and name them by their Z-coordinate as an integer. The fly/dive actions will
+only work if there is actually a matching room directly above/below.
+
+Note that since pathfinding only works within each XYmap, the player will not
+be able to include fly/dive in their autowalking - this is always a manual
+action.
+
+As an example, let’s assume coordinate (1, 1, -3)
+is the bottom of a deep well leading up to the surface (at level 0)
+LEVEL_MINUS_3 = r"""
++ 0 1
+
+1 #
+ |
+0 #-#
+
++ 0 1
+"""
+
+LEVEL_MINUS_2 = r"""
++ 0 1
+
+1 #
+
+0
+
++ 0 1
+"""
+
+LEVEL_MINUS_1 = r"""
++ 0 1
+
+1 #
+
+0
+
++ 0 1
+"""
+
+LEVEL_0 = r"""
++ 0 1
+
+1 #-#
+ |x|
+0 #-#
+
++ 0 1
+"""
+
+XYMAP_DATA_LIST = [
+ {"zcoord": -3, "map": LEVEL_MINUS_3},
+ {"zcoord": -2, "map": LEVEL_MINUS_2},
+ {"zcoord": -1, "map": LEVEL_MINUS_1},
+ {"zcoord": 0, "map": LEVEL_0},
+]
+
+
+In this example, if we arrive to the bottom of the well at (1, 1, -3) we
+fly straight up three levels until we arrive at (1, 1, 0), at the corner
+of some sort of open field.
+We can dive down from (1, 1, 0). In the default implementation you must dive 3 times
+to get to the bottom. If you wanted you could tweak the command so you
+automatically fall to the bottom and take damage etc.
+We can’t fly/dive up/down from any other XY positions because there are no open rooms at the
+adjacent Z coordinates.
+
Map String
diff --git a/docs/1.0/_modules/evennia/accounts/bots.html b/docs/1.0/_modules/evennia/accounts/bots.html
index 1706ffb7a1..d6fda93596 100644
--- a/docs/1.0/_modules/evennia/accounts/bots.html
+++ b/docs/1.0/_modules/evennia/accounts/bots.html
@@ -698,7 +698,7 @@
# connect
global _SESSIONS
if not _SESSIONS:
- from evennia.server.sessionhandler import SESSIONS as _SESSIONS
+ from evennia.server.sessionhandler import SESSION_HANDLER as _SESSIONS
# these will be made available as properties on the protocol factory
configdict = {"uid": self.dbid}
_SESSIONS.start_bot_session(self.factory_path, configdict)
diff --git a/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/commands.html b/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/commands.html
index df8a85ea1f..5febab13c1 100644
--- a/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/commands.html
+++ b/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/commands.html
@@ -87,7 +87,6 @@
from collections import namedtuple
from django.conf import settings
-
from evennia import CmdSet, InterruptCommand, default_cmds
from evennia.commands.default import building
from evennia.contrib.grid.xyzgrid.xyzgrid import get_xyzgrid
@@ -584,6 +583,85 @@
self.add(CmdXYZOpen())
self.add(CmdGoto())
self.add(CmdMap())
+
+
+# Optional fly/dive commands to move between maps (enable
+# full 3D-grid movements)
+
+
+[docs]class CmdFlyAndDive(COMMAND_DEFAULT_CLASS):
+
"""
+
Fly or Dive up and down.
+
+
Usage:
+
fly
+
dive
+
+
Will fly up one room or dive down one room at your current position. If
+
there is no room above/below you, your movement will fail.
+
+
"""
+
+
key = "fly or dive"
+
aliases = ("fly", "dive")
+
+
[docs] def func(self):
+
caller = self.caller
+
+
action = self.cmdname
+
+
try:
+
xyz_start = caller.location.xyz
+
except AttributeError:
+
caller.msg(f"You cannot {action} here.")
+
return
+
try:
+
zcoord = int(xyz_start[2])
+
except ValueError:
+
caller.msg(f"You cannot {action} here.")
+
return
+
+
if action == "fly":
+
diff = 1
+
direction = "upwards"
+
from_direction = "below"
+
error_message = "Can't fly here - you'd hit your head."
+
elif action == "dive":
+
diff = -1
+
direction = "downwards"
+
from_direction = "above"
+
error_message = "Can't dive here - you'd just fall flat on the ground."
+
else:
+
caller.msg("You must decide if you want to |wfly|n up or |wdive|n down.")
+
return
+
+
target_coord = (str(xyz_start[0]), str(xyz_start[1]), zcoord + diff)
+
try:
+
target = XYZRoom.objects.get_xyz(xyz=(target_coord))
+
except XYZRoom.DoesNotExist:
+
# no available room above/below to fly/dive to
+
caller.msg(error_message)
+
return
+
# action succeeds, we have a target. One could picture being able to
+
# lock certain rooms from flight/dive, here we allow it as long as there
+
# is a suitable room above/below.
+
caller.location.msg_contents(f"$You() {action} {direction}.", from_obj=caller)
+
caller.move_to(target, quiet=True)
+
target.msg_contents(
+
f"$You() {action} from {from_direction}.", from_obj=caller, exclude=[caller]
+
)
+
+
+[docs]class XYZGridFlyDiveCmdSet(CmdSet):
+
"""
+
Optional cmdset if you want the fly/dive commands to move in a 3D environment.
+
+
"""
+
+
key = "xyzgrid_flydive_cmdset"
+
+
[docs] def at_cmdset_creation(self):
+
self.add(CmdFlyAndDive())
diff --git a/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/tests.html b/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/tests.html
index 67eec68a25..b9be39b610 100644
--- a/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/tests.html
+++ b/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/tests.html
@@ -84,11 +84,10 @@
from unittest import mock
from django.test import TestCase
+from evennia.utils.test_resources import BaseEvenniaCommandTest, BaseEvenniaTest
from parameterized import parameterized
-from evennia.utils.test_resources import BaseEvenniaTest
-
-from . import xymap, xymap_legend, xyzgrid, xyzroom
+from . import commands, xymap, xymap_legend, xyzgrid, xyzroom
MAP1 = """
@@ -418,6 +417,54 @@
"""
+MAP13a = r"""
+
++ 0 1
+
+1 #-#
+ |
+0 #
+
++ 0 1
+
+"""
+
+MAP13b = r"""
+
++ 0 1
+
+1 #
+
+0
+
++ 0 1
+
+"""
+
+MAP13c = r"""
+
++ 0 1
+
+1 #
+
+0
+
++ 0 1
+
+"""
+
+MAP13d = r"""
+
++ 0 1
+
+1 #-#
+ |
+0 #
+
++ 0 1
+
+"""
+
class _MapTest(BaseEvenniaTest):
"""
@@ -594,8 +641,10 @@
((1, 0), "#-#-#-#\n| | \n#-#-#--\n | \n @-#-#"),
(
(2, 2),
- " #---#\n | |\n# | #\n| | \n#-#-@-#--\n| "
- "| \n#-#-#---#\n | |\n #-#-#-#",
+ (
+ " #---#\n | |\n# | #\n| | \n#-#-@-#--\n| "
+ "| \n#-#-#---#\n | |\n #-#-#-#"
+ ),
),
((4, 5), "#-#-@ \n| | \n#---# \n| | \n| #-#"),
((5, 2), "--# \n | \n #-#\n |\n#---@\n \n--#-#\n | \n#-# "),
@@ -654,8 +703,10 @@
(2, 2),
2,
None,
- " # \n | \n #---# \n | \n | \n | \n"
- "#-#-@-#---#\n | \n #-#---# ",
+ (
+ " # \n | \n #---# \n | \n | \n | \n"
+ "#-#-@-#---#\n | \n #-#---# "
+ ),
),
((2, 2), 2, (5, 5), " | \n | \n#-@-#\n | \n#-#--"), # limit display size
((2, 2), 4, (3, 3), " | \n-@-\n | "),
@@ -725,8 +776,10 @@
(2, 2),
2,
None,
- " # \n / \n # / \n |/ \n # #\n |\\ / \n # @-# \n "
- "|/ \\ \n # #\n / \\ \n# # ",
+ (
+ " # \n / \n # / \n |/ \n # #\n |\\ / \n # @-# \n"
+ " |/ \\ \n # #\n / \\ \n# # "
+ ),
),
((5, 2), 2, None, " # \n | \n # \n / \\ \n# @\n \\ / \n # \n | \n # "),
]
@@ -956,8 +1009,7 @@
(2, 2),
1,
None,
- " #-o \n | \n# o \n| | \no-o-@-#\n "
- "| \n o \n | \n # ",
+ " #-o \n | \n# o \n| | \no-o-@-#\n | \n o \n | \n # ",
),
]
)
@@ -978,24 +1030,24 @@
(3, 2),
1,
None,
- " #-o \n | \n# o \n| | \no-o-@..\n | \n o "
- "\n | \n # ",
+ " #-o \n | \n# o \n| | \no-o-@..\n | \n o \n | \n # ",
),
(
(2, 2),
(5, 3),
1,
None,
- " #-o \n | \n# o \n| | \no-o-@-#\n . \n . "
- "\n . \n ...",
+ " #-o \n | \n# o \n| | \no-o-@-#\n . \n . \n . \n ...",
),
(
(2, 2),
(5, 3),
2,
None,
- "#-#-o \n| \\| \n#-o-o-# .\n| |\\ .\no-o-@-"
- "# .\n . . \n . . \n . . \n#---... ",
+ (
+ "#-#-o \n| \\| \n#-o-o-# .\n| |\\ .\no-o-@-"
+ "# .\n . . \n . . \n . . \n#---... "
+ ),
),
((5, 3), (2, 2), 2, (13, 7), " o-o\n | |\n o-@\n .\n. .\n. . "),
(
@@ -1003,8 +1055,10 @@
(1, 1),
2,
None,
- " o-o\n | |\n o-@\n. .\n..... "
- ".\n . . \n . . \n . . \n#---... ",
+ (
+ " o-o\n | |\n o-@\n. .\n..... "
+ ".\n . . \n . . \n . . \n#---... "
+ ),
),
]
)
@@ -1578,6 +1632,52 @@
self.assertEqual(
mock_exit_callbacks.at_object_creation.mock_calls, [mock.call(), mock.call()]
)
+
+
+[docs]class TestFlyDiveCommand(BaseEvenniaCommandTest):
+
[docs] def setUp(self):
+
super().setUp()
+
+
self.grid, err = xyzgrid.XYZGrid.create("testgrid")
+
+
self.map_data13a = {"map": MAP13a, "zcoord": -2}
+
self.map_data13b = {"map": MAP13b, "zcoord": -1}
+
self.map_data13c = {"map": MAP13c, "zcoord": 0}
+
self.map_data13d = {"map": MAP13d, "zcoord": 1} # not contiguous
+
+
self.grid.add_maps(self.map_data13a, self.map_data13b, self.map_data13c, self.map_data13d)
+
self.grid.spawn()
+
+
[docs] def tearDown(self):
+
self.grid.delete()
+
+
@parameterized.expand(
+
[
+
# startcoord, cmd, succeed?, endcoord
+
((0, 0, -2), "fly", False, (0, 0, -2)),
+
((1, 1, -2), "fly", True, (1, 1, -1)),
+
((1, 1, -1), "fly", True, (1, 1, 0)),
+
((1, 1, 0), "fly", True, (1, 1, 1)),
+
((1, 1, 1), "fly", False, (1, 1, 1)),
+
((0, 0, 1), "fly", False, (0, 0, 1)),
+
((0, 0, 1), "dive", False, (0, 0, 1)),
+
((1, 1, 1), "dive", True, (1, 1, 0)),
+
((1, 1, 0), "dive", True, (1, 1, -1)),
+
((1, 1, -1), "dive", True, (1, 1, -2)),
+
((1, 1, -2), "dive", False, (1, 1, -2)),
+
]
+
)
+
def test_fly_and_dive(self, startcoord, cmdstring, success, endcoord):
+
"""
+
Test flying up and down and seeing if it works at different locations.
+
+
"""
+
start_room = xyzgrid.XYZRoom.objects.get_xyz(xyz=startcoord)
+
self.char1.move_to(start_room)
+
+
self.call(commands.CmdFlyAndDive(), "", "You" if success else "Can't", cmdstring=cmdstring)
+
+
self.assertEqual(self.char1.location.xyz, endcoord)
diff --git a/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/xyzgrid.html b/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/xyzgrid.html
index 70cf3349d1..3e645f97fd 100644
--- a/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/xyzgrid.html
+++ b/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/xyzgrid.html
@@ -278,7 +278,7 @@
"""
for mapdata in mapdatas:
zcoord = mapdata.get("zcoord")
- if not zcoord:
+ if not zcoord is not None:
raise RuntimeError("XYZGrid.add_map data must contain 'zcoord'.")
self.db.map_data[zcoord] = mapdata
diff --git a/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/xyzroom.html b/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/xyzroom.html
index 4ad8332c4e..024c75e2d9 100644
--- a/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/xyzroom.html
+++ b/docs/1.0/_modules/evennia/contrib/grid/xyzgrid/xyzroom.html
@@ -86,7 +86,6 @@
from django.conf import settings
from django.db.models import Q
-
from evennia.objects.manager import ObjectManager
from evennia.objects.objects import DefaultExit, DefaultRoom
@@ -367,11 +366,13 @@
if x is None or y is None or z is None:
# don't cache unfinished coordinate (probably tags have not finished saving)
return tuple(
- int(coord) if coord is not None and coord.isdigit() else coord
+ int(coord) if coord is not None and coord.lstrip("-").isdigit() else coord
for coord in (x, y, z)
)
# cache result, convert to correct types (tags are strings)
- self._xyz = tuple(int(coord) if coord.isdigit() else coord for coord in (x, y, z))
+ self._xyz = tuple(
+ int(coord) if coord.lstrip("-").isdigit() else coord for coord in (x, y, z)
+ )
return self._xyz
diff --git a/docs/1.0/_modules/evennia/server/portal/discord.html b/docs/1.0/_modules/evennia/server/portal/discord.html
index f4abd057e1..20d8bb3f8c 100644
--- a/docs/1.0/_modules/evennia/server/portal/discord.html
+++ b/docs/1.0/_modules/evennia/server/portal/discord.html
@@ -400,6 +400,7 @@
reason (str or None): Close reason as sent by the WebSocket peer.
"""
+ self.sessionhandler.disconnect(self)
if self.nextHeartbeatCall:
self.nextHeartbeatCall.cancel()
self.nextHeartbeatCall = None
@@ -501,7 +502,6 @@
reason (str or None): Motivation for the disconnection.
"""
- self.sessionhandler.disconnect(self)
self.sendClose(self.CLOSE_STATUS_CODE_NORMAL, reason)
[docs] def identify(self, *args, **kwargs):
diff --git a/docs/1.0/_modules/evennia/server/serversession.html b/docs/1.0/_modules/evennia/server/serversession.html
index 456f4c312d..f880fa7e85 100644
--- a/docs/1.0/_modules/evennia/server/serversession.html
+++ b/docs/1.0/_modules/evennia/server/serversession.html
@@ -289,7 +289,7 @@
"""
flags = self.protocol_flags
-
print("session flags:", flags)
+
# print("session flags:", flags)
width = flags.get("SCREENWIDTH", {}).get(0, settings.CLIENT_DEFAULT_WIDTH)
height = flags.get("SCREENHEIGHT", {}).get(0, settings.CLIENT_DEFAULT_HEIGHT)
return width, height
diff --git a/docs/1.0/_modules/evennia/utils/funcparser.html b/docs/1.0/_modules/evennia/utils/funcparser.html
index 187a1c32ca..ece39a62f6 100644
--- a/docs/1.0/_modules/evennia/utils/funcparser.html
+++ b/docs/1.0/_modules/evennia/utils/funcparser.html
@@ -125,7 +125,6 @@
import random
from django.conf import settings
-
from evennia.utils import logger, search
from evennia.utils.utils import (
callables_from_module,
@@ -783,7 +782,7 @@
if not args:
return ""
item = str(args[0])
- if item and item[0] in "aeiouy":
+ if item and item[0] in "aeiouyAEIOUY":
return f"an {item}"
return f"a {item}"
diff --git a/docs/1.0/_sources/Coding/Changelog.md.txt b/docs/1.0/_sources/Coding/Changelog.md.txt
index c7f01c2ac0..04f81095f1 100644
--- a/docs/1.0/_sources/Coding/Changelog.md.txt
+++ b/docs/1.0/_sources/Coding/Changelog.md.txt
@@ -1,11 +1,20 @@
# Changelog
+## Main
+
+- Feature: Add `fly/dive` commands to `XYZGrid` contrib to showcase treating its
+ Z-axis as a full 3D grid. Also fixed minor bug in `XYZGrid` contrib when using
+ a Z axis named using an integer rather than a string.
+- Bug fix: `$an()` inlinefunc didn't understand to use 'an' words starting with a
+ capital vowel
+- Bug fix: Another case of the 'duplicate Discord bot connections' bug
+
## Evennia 1.1.1
- Bug fix: Better handler malformed alias-regex given to nickhandler. A
regex-relevant character in a channel alias could cause server to not restart.
-- Add `attr` keyword to `create_channel`. This allows setting attributes on
- channels at creation, also from `DEFAULT_CHANNELS` definitions.
+- Feature: Add `attr` keyword to `create_channel`. This allows setting
+ attributes on channels at creation, also from `DEFAULT_CHANNELS` definitions.
## Evennia 1.1.0
Jan 7, 2023
diff --git a/docs/1.0/_sources/Contribs/Contrib-XYZGrid.md.txt b/docs/1.0/_sources/Contribs/Contrib-XYZGrid.md.txt
index f10cab5258..2bcb4d5d95 100644
--- a/docs/1.0/_sources/Contribs/Contrib-XYZGrid.md.txt
+++ b/docs/1.0/_sources/Contribs/Contrib-XYZGrid.md.txt
@@ -310,24 +310,102 @@ In the following sections we'll discuss each component in turn.
### The Zcoord
-Each XYMap on the grid has a Z-coordinate which usually can be treated just as the
-name of the map. This is a string that must be unique across the entire grid.
-It is added as the key 'zcoord' to `XYMAP_DATA`.
-
-Actual 3D movement is usually impractical in a text-based game, so all movements
-and pathfinding etc happens within each XYMap (up/down is 'faked' within the XY
-plane). Even for the most hardcore of sci-fi space game, moving on a 2D plane
-usually makes it much easier for players than to attempt to have them visualize
-actual 3D movements.
-
-If you really wanted an actual 3D coordinate system, you could theoretically
-make all maps the same size and name them `0`, `1`, `2` etc. But even then, you
-could not freely move up/down between every point (a special Transitional Node
-is required as outlined below). Also pathfinding will only work per-XYMap.
+Each XYMap on the grid has a Z-coordinate which usually can be treated just as
+the name of the map. The Z-coordinate can be either a string or an integer, and must
+be unique across the entire grid. It is added as the key 'zcoord' to `XYMAP_DATA`.
Most users will want to just treat each map as a location, and name the
"Z-coordinate" things like `Dungeon of Doom`, `The ice queen's palace` or `City
-of Blackhaven`.
+of Blackhaven`. But you could also name it -1, 0, 1, 2, 3 if you wanted.
+
+Pathfinding happens only within each XYMap (up/down is normally 'faked' by moving
+sideways to a new area of the XY plane).
+
+#### A true 3D map
+
+Even for the most hardcore of sci-fi space game, consider sticking to 2D
+movement. It's hard enough for players to visualize a 3D volume with graphics.
+In text it's even harder.
+
+That said, if you want to set up a true X, Y, Z 3D coordinate system (where
+you can move up/down from every point), you can do that too.
+
+This contrib provides an example command `commands.CmdFlyAndDive` that provides the player
+with the ability to use `fly` and `dive` to move straight up/down between Z
+coordinates. Just add it (or its cmdset `commands.XYZGridFlyDiveCmdSet`) to your
+Character cmdset and reload to try it out.
+
+For the fly/dive to work you need to build your grid as a 'stack' of XY-grid maps
+and name them by their Z-coordinate as an integer. The fly/dive actions will
+only work if there is actually a matching room directly above/below.
+
+> Note that since pathfinding only works within each XYmap, the player will not
+> be able to include fly/dive in their autowalking - this is always a manual
+> action.
+
+As an example, let's assume coordinate `(1, 1, -3)`
+is the bottom of a deep well leading up to the surface (at level 0)
+
+```
+LEVEL_MINUS_3 = r"""
++ 0 1
+
+1 #
+ |
+0 #-#
+
++ 0 1
+"""
+
+LEVEL_MINUS_2 = r"""
++ 0 1
+
+1 #
+
+0
+
++ 0 1
+"""
+
+LEVEL_MINUS_1 = r"""
++ 0 1
+
+1 #
+
+0
+
++ 0 1
+"""
+
+LEVEL_0 = r"""
++ 0 1
+
+1 #-#
+ |x|
+0 #-#
+
++ 0 1
+"""
+
+XYMAP_DATA_LIST = [
+ {"zcoord": -3, "map": LEVEL_MINUS_3},
+ {"zcoord": -2, "map": LEVEL_MINUS_2},
+ {"zcoord": -1, "map": LEVEL_MINUS_1},
+ {"zcoord": 0, "map": LEVEL_0},
+]
+```
+
+In this example, if we arrive to the bottom of the well at `(1, 1, -3)` we
+`fly` straight up three levels until we arrive at `(1, 1, 0)`, at the corner
+of some sort of open field.
+
+We can dive down from `(1, 1, 0)`. In the default implementation you must `dive` 3 times
+to get to the bottom. If you wanted you could tweak the command so you
+automatically fall to the bottom and take damage etc.
+
+We can't fly/dive up/down from any other XY positions because there are no open rooms at the
+adjacent Z coordinates.
+
### Map String
diff --git a/docs/1.0/api/evennia.commands.default.account.html b/docs/1.0/api/evennia.commands.default.account.html
index a97a0367ae..fc0e2dabf1 100644
--- a/docs/1.0/api/evennia.commands.default.account.html
+++ b/docs/1.0/api/evennia.commands.default.account.html
@@ -132,7 +132,7 @@ method. Otherwise all text will be returned to all connected sessions.
-
-
aliases = ['l', 'ls']
+aliases = ['ls', 'l']
@@ -163,7 +163,7 @@ method. Otherwise all text will be returned to all connected sessions.
-
-
search_index_entry = {'aliases': 'l ls', 'category': 'general', 'key': 'look', 'no_prefix': ' l ls', 'tags': '', 'text': '\n look while out-of-character\n\n Usage:\n look\n\n Look in the ooc state.\n '}
+search_index_entry = {'aliases': 'ls l', 'category': 'general', 'key': 'look', 'no_prefix': ' ls l', 'tags': '', 'text': '\n look while out-of-character\n\n Usage:\n look\n\n Look in the ooc state.\n '}
diff --git a/docs/1.0/api/evennia.commands.default.batchprocess.html b/docs/1.0/api/evennia.commands.default.batchprocess.html
index 93229cffca..9725e81dd9 100644
--- a/docs/1.0/api/evennia.commands.default.batchprocess.html
+++ b/docs/1.0/api/evennia.commands.default.batchprocess.html
@@ -137,7 +137,7 @@ skipping, reloading etc.
-
-
aliases = ['batchcmd', 'batchcommand']
+aliases = ['batchcommand', 'batchcmd']
@@ -168,7 +168,7 @@ skipping, reloading etc.
-
-
search_index_entry = {'aliases': 'batchcmd batchcommand', 'category': 'building', 'key': 'batchcommands', 'no_prefix': ' batchcmd batchcommand', 'tags': '', 'text': '\n build from batch-command file\n\n Usage:\n batchcommands[/interactive] <python.path.to.file>\n\n Switch:\n interactive - this mode will offer more control when\n executing the batch file, like stepping,\n skipping, reloading etc.\n\n Runs batches of commands from a batch-cmd text file (*.ev).\n\n '}
+search_index_entry = {'aliases': 'batchcommand batchcmd', 'category': 'building', 'key': 'batchcommands', 'no_prefix': ' batchcommand batchcmd', 'tags': '', 'text': '\n build from batch-command file\n\n Usage:\n batchcommands[/interactive] <python.path.to.file>\n\n Switch:\n interactive - this mode will offer more control when\n executing the batch file, like stepping,\n skipping, reloading etc.\n\n Runs batches of commands from a batch-cmd text file (*.ev).\n\n '}
diff --git a/docs/1.0/api/evennia.commands.default.building.html b/docs/1.0/api/evennia.commands.default.building.html
index dd9c7d049c..fc8115d723 100644
--- a/docs/1.0/api/evennia.commands.default.building.html
+++ b/docs/1.0/api/evennia.commands.default.building.html
@@ -1344,7 +1344,7 @@ server settings.
-
-
aliases = ['@type', '@parent', '@typeclasses', '@update', '@swap']
+aliases = ['@typeclasses', '@type', '@swap', '@update', '@parent']
@@ -1375,7 +1375,7 @@ server settings.
-
-
search_index_entry = {'aliases': '@type @parent @typeclasses @update @swap', 'category': 'building', 'key': '@typeclass', 'no_prefix': 'typeclass type parent typeclasses update swap', 'tags': '', 'text': "\n set or change an object's typeclass\n\n Usage:\n typeclass[/switch] <object> [= typeclass.path]\n typeclass/prototype <object> = prototype_key\n\n typeclasses or typeclass/list/show [typeclass.path]\n swap - this is a shorthand for using /force/reset flags.\n update - this is a shorthand for using the /force/reload flag.\n\n Switch:\n show, examine - display the current typeclass of object (default) or, if\n given a typeclass path, show the docstring of that typeclass.\n update - *only* re-run at_object_creation on this object\n meaning locks or other properties set later may remain.\n reset - clean out *all* the attributes and properties on the\n object - basically making this a new clean object. This will also\n reset cmdsets!\n force - change to the typeclass also if the object\n already has a typeclass of the same name.\n list - show available typeclasses. Only typeclasses in modules actually\n imported or used from somewhere in the code will show up here\n (those typeclasses are still available if you know the path)\n prototype - clean and overwrite the object with the specified\n prototype key - effectively making a whole new object.\n\n Example:\n type button = examples.red_button.RedButton\n type/prototype button=a red button\n\n If the typeclass_path is not given, the current object's typeclass is\n assumed.\n\n View or set an object's typeclass. If setting, the creation hooks of the\n new typeclass will be run on the object. If you have clashing properties on\n the old class, use /reset. By default you are protected from changing to a\n typeclass of the same name as the one you already have - use /force to\n override this protection.\n\n The given typeclass must be identified by its location using python\n dot-notation pointing to the correct module and class. If no typeclass is\n given (or a wrong typeclass is given). Errors in the path or new typeclass\n will lead to the old typeclass being kept. The location of the typeclass\n module is searched from the default typeclass directory, as defined in the\n server settings.\n\n "}
+search_index_entry = {'aliases': '@typeclasses @type @swap @update @parent', 'category': 'building', 'key': '@typeclass', 'no_prefix': 'typeclass typeclasses type swap update parent', 'tags': '', 'text': "\n set or change an object's typeclass\n\n Usage:\n typeclass[/switch] <object> [= typeclass.path]\n typeclass/prototype <object> = prototype_key\n\n typeclasses or typeclass/list/show [typeclass.path]\n swap - this is a shorthand for using /force/reset flags.\n update - this is a shorthand for using the /force/reload flag.\n\n Switch:\n show, examine - display the current typeclass of object (default) or, if\n given a typeclass path, show the docstring of that typeclass.\n update - *only* re-run at_object_creation on this object\n meaning locks or other properties set later may remain.\n reset - clean out *all* the attributes and properties on the\n object - basically making this a new clean object. This will also\n reset cmdsets!\n force - change to the typeclass also if the object\n already has a typeclass of the same name.\n list - show available typeclasses. Only typeclasses in modules actually\n imported or used from somewhere in the code will show up here\n (those typeclasses are still available if you know the path)\n prototype - clean and overwrite the object with the specified\n prototype key - effectively making a whole new object.\n\n Example:\n type button = examples.red_button.RedButton\n type/prototype button=a red button\n\n If the typeclass_path is not given, the current object's typeclass is\n assumed.\n\n View or set an object's typeclass. If setting, the creation hooks of the\n new typeclass will be run on the object. If you have clashing properties on\n the old class, use /reset. By default you are protected from changing to a\n typeclass of the same name as the one you already have - use /force to\n override this protection.\n\n The given typeclass must be identified by its location using python\n dot-notation pointing to the correct module and class. If no typeclass is\n given (or a wrong typeclass is given). Errors in the path or new typeclass\n will lead to the old typeclass being kept. The location of the typeclass\n module is searched from the default typeclass directory, as defined in the\n server settings.\n\n "}
diff --git a/docs/1.0/api/evennia.commands.default.comms.html b/docs/1.0/api/evennia.commands.default.comms.html
index 703b50ad74..4c425bb42c 100644
--- a/docs/1.0/api/evennia.commands.default.comms.html
+++ b/docs/1.0/api/evennia.commands.default.comms.html
@@ -255,7 +255,7 @@ ban mychannel1,mychannel2= EvilUser : Was banned for spamming.
-
-
aliases = ['@chan', '@channels']
+aliases = ['@channels', '@chan']
@@ -781,7 +781,7 @@ don’t actually sub to yet.
-
-
search_index_entry = {'aliases': '@chan @channels', 'category': 'comms', 'key': '@channel', 'no_prefix': 'channel chan channels', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}
+search_index_entry = {'aliases': '@channels @chan', 'category': 'comms', 'key': '@channel', 'no_prefix': 'channel channels chan', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}
@@ -934,7 +934,7 @@ ban mychannel1,mychannel2= EvilUser : Was banned for spamming.
-
-
aliases = ['@chan', '@channels']
+aliases = ['@channels', '@chan']
@@ -954,7 +954,7 @@ ban mychannel1,mychannel2= EvilUser : Was banned for spamming.
-
-
search_index_entry = {'aliases': '@chan @channels', 'category': 'comms', 'key': '@channel', 'no_prefix': 'channel chan channels', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}
+search_index_entry = {'aliases': '@channels @chan', 'category': 'comms', 'key': '@channel', 'no_prefix': 'channel channels chan', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}
diff --git a/docs/1.0/api/evennia.commands.default.general.html b/docs/1.0/api/evennia.commands.default.general.html
index 104bc4bdd2..4c67226bbf 100644
--- a/docs/1.0/api/evennia.commands.default.general.html
+++ b/docs/1.0/api/evennia.commands.default.general.html
@@ -174,7 +174,7 @@ look *<account&g
-
-
aliases = ['l', 'ls']
+aliases = ['ls', 'l']
@@ -205,7 +205,7 @@ look *<account&g
-
-
search_index_entry = {'aliases': 'l ls', 'category': 'general', 'key': 'look', 'no_prefix': ' l ls', 'tags': '', 'text': '\n look at location or object\n\n Usage:\n look\n look <obj>\n look *<account>\n\n Observes your location or objects in your vicinity.\n '}
+search_index_entry = {'aliases': 'ls l', 'category': 'general', 'key': 'look', 'no_prefix': ' ls l', 'tags': '', 'text': '\n look at location or object\n\n Usage:\n look\n look <obj>\n look *<account>\n\n Observes your location or objects in your vicinity.\n '}
@@ -322,7 +322,7 @@ inv
-
-
aliases = ['inv', 'i']
+aliases = ['i', 'inv']
@@ -353,7 +353,7 @@ inv
-
-
search_index_entry = {'aliases': 'inv i', 'category': 'general', 'key': 'inventory', 'no_prefix': ' inv i', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}
+search_index_entry = {'aliases': 'i inv', 'category': 'general', 'key': 'inventory', 'no_prefix': ' i inv', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}
@@ -597,7 +597,7 @@ placing it in their inventory.
-
-
aliases = ["'", '"']
+aliases = ['"', "'"]
@@ -628,7 +628,7 @@ placing it in their inventory.
-
-
search_index_entry = {'aliases': '\' "', 'category': 'general', 'key': 'say', 'no_prefix': ' \' "', 'tags': '', 'text': '\n speak as your character\n\n Usage:\n say <message>\n\n Talk to those in your current location.\n '}
+search_index_entry = {'aliases': '" \'', 'category': 'general', 'key': 'say', 'no_prefix': ' " \'', 'tags': '', 'text': '\n speak as your character\n\n Usage:\n say <message>\n\n Talk to those in your current location.\n '}
@@ -708,7 +708,7 @@ automatically begin with your name.
-
-
aliases = ['emote', ':']
+aliases = [':', 'emote']
@@ -749,7 +749,7 @@ space.
-
-
search_index_entry = {'aliases': 'emote :', 'category': 'general', 'key': 'pose', 'no_prefix': ' emote :', 'tags': '', 'text': "\n strike a pose\n\n Usage:\n pose <pose text>\n pose's <pose text>\n\n Example:\n pose is standing by the wall, smiling.\n -> others will see:\n Tom is standing by the wall, smiling.\n\n Describe an action being taken. The pose text will\n automatically begin with your name.\n "}
+search_index_entry = {'aliases': ': emote', 'category': 'general', 'key': 'pose', 'no_prefix': ' : emote', 'tags': '', 'text': "\n strike a pose\n\n Usage:\n pose <pose text>\n pose's <pose text>\n\n Example:\n pose is standing by the wall, smiling.\n -> others will see:\n Tom is standing by the wall, smiling.\n\n Describe an action being taken. The pose text will\n automatically begin with your name.\n "}
@@ -772,7 +772,7 @@ which permission groups you are a member of.
-
-
aliases = ['groups', 'hierarchy']
+aliases = ['hierarchy', 'groups']
@@ -803,7 +803,7 @@ which permission groups you are a member of.
-
-
search_index_entry = {'aliases': 'groups hierarchy', 'category': 'general', 'key': 'access', 'no_prefix': ' groups hierarchy', 'tags': '', 'text': '\n show your current game access\n\n Usage:\n access\n\n This command shows you the permission hierarchy and\n which permission groups you are a member of.\n '}
+search_index_entry = {'aliases': 'hierarchy groups', 'category': 'general', 'key': 'access', 'no_prefix': ' hierarchy groups', 'tags': '', 'text': '\n show your current game access\n\n Usage:\n access\n\n This command shows you the permission hierarchy and\n which permission groups you are a member of.\n '}
diff --git a/docs/1.0/api/evennia.commands.default.system.html b/docs/1.0/api/evennia.commands.default.system.html
index 0494751365..eda035c4ad 100644
--- a/docs/1.0/api/evennia.commands.default.system.html
+++ b/docs/1.0/api/evennia.commands.default.system.html
@@ -682,7 +682,7 @@ See |luhttps://ww
-
-
aliases = ['@delays', '@task']
+aliases = ['@task', '@delays']
@@ -728,7 +728,7 @@ to all the variables defined therein.
-
-
search_index_entry = {'aliases': '@delays @task', 'category': 'system', 'key': '@tasks', 'no_prefix': 'tasks delays task', 'tags': '', 'text': "\n Display or terminate active tasks (delays).\n\n Usage:\n tasks[/switch] [task_id or function_name]\n\n Switches:\n pause - Pause the callback of a task.\n unpause - Process all callbacks made since pause() was called.\n do_task - Execute the task (call its callback).\n call - Call the callback of this task.\n remove - Remove a task without executing it.\n cancel - Stop a task from automatically executing.\n\n Notes:\n A task is a single use method of delaying the call of a function. Calls are created\n in code, using `evennia.utils.delay`.\n See |luhttps://www.evennia.com/docs/latest/Command-Duration.html|ltthe docs|le for help.\n\n By default, tasks that are canceled and never called are cleaned up after one minute.\n\n Examples:\n - `tasks/cancel move_callback` - Cancels all movement delays from the slow_exit contrib.\n In this example slow exits creates it's tasks with\n `utils.delay(move_delay, move_callback)`\n - `tasks/cancel 2` - Cancel task id 2.\n\n "}
+search_index_entry = {'aliases': '@task @delays', 'category': 'system', 'key': '@tasks', 'no_prefix': 'tasks task delays', 'tags': '', 'text': "\n Display or terminate active tasks (delays).\n\n Usage:\n tasks[/switch] [task_id or function_name]\n\n Switches:\n pause - Pause the callback of a task.\n unpause - Process all callbacks made since pause() was called.\n do_task - Execute the task (call its callback).\n call - Call the callback of this task.\n remove - Remove a task without executing it.\n cancel - Stop a task from automatically executing.\n\n Notes:\n A task is a single use method of delaying the call of a function. Calls are created\n in code, using `evennia.utils.delay`.\n See |luhttps://www.evennia.com/docs/latest/Command-Duration.html|ltthe docs|le for help.\n\n By default, tasks that are canceled and never called are cleaned up after one minute.\n\n Examples:\n - `tasks/cancel move_callback` - Cancels all movement delays from the slow_exit contrib.\n In this example slow exits creates it's tasks with\n `utils.delay(move_delay, move_callback)`\n - `tasks/cancel 2` - Cancel task id 2.\n\n "}
diff --git a/docs/1.0/api/evennia.commands.default.tests.html b/docs/1.0/api/evennia.commands.default.tests.html
index 2a5c0fd524..df135cbb3a 100644
--- a/docs/1.0/api/evennia.commands.default.tests.html
+++ b/docs/1.0/api/evennia.commands.default.tests.html
@@ -954,7 +954,7 @@ main test suite started with
Test the batch processor.
-
-
red_button = <module 'evennia.contrib.tutorials.red_button.red_button' from '/tmp/tmpt6kc_u3p/e4e7668cf542bd2f053319cf63b56fc8c90dbcd1/evennia/contrib/tutorials/red_button/red_button.py'>
+red_button = <module 'evennia.contrib.tutorials.red_button.red_button' from '/tmp/tmpjsypa7mo/439a37762583036f5f67f650055154ee18914026/evennia/contrib/tutorials/red_button/red_button.py'>
diff --git a/docs/1.0/api/evennia.commands.default.unloggedin.html b/docs/1.0/api/evennia.commands.default.unloggedin.html
index a63ba66a7e..f6f6d64f83 100644
--- a/docs/1.0/api/evennia.commands.default.unloggedin.html
+++ b/docs/1.0/api/evennia.commands.default.unloggedin.html
@@ -121,7 +121,7 @@ connect “account name” “pass word”
-
-
aliases = ['con', 'co', 'conn']
+aliases = ['conn', 'co', 'con']
@@ -156,7 +156,7 @@ there is no object yet before the account has logged in)
-
-
search_index_entry = {'aliases': 'con co conn', 'category': 'general', 'key': 'connect', 'no_prefix': ' con co conn', 'tags': '', 'text': '\n connect to the game\n\n Usage (at login screen):\n connect accountname password\n connect "account name" "pass word"\n\n Use the create command to first create an account before logging in.\n\n If you have spaces in your name, enclose it in double quotes.\n '}
+search_index_entry = {'aliases': 'conn co con', 'category': 'general', 'key': 'connect', 'no_prefix': ' conn co con', 'tags': '', 'text': '\n connect to the game\n\n Usage (at login screen):\n connect accountname password\n connect "account name" "pass word"\n\n Use the create command to first create an account before logging in.\n\n If you have spaces in your name, enclose it in double quotes.\n '}
@@ -180,7 +180,7 @@ create “account name” “pass word”
-
-
aliases = ['cre', 'cr']
+aliases = ['cr', 'cre']
@@ -217,7 +217,7 @@ create “account name” “pass word”
-
-
search_index_entry = {'aliases': 'cre cr', 'category': 'general', 'key': 'create', 'no_prefix': ' cre cr', 'tags': '', 'text': '\n create a new account account\n\n Usage (at login screen):\n create <accountname> <password>\n create "account name" "pass word"\n\n This creates a new account account.\n\n If you have spaces in your name, enclose it in double quotes.\n '}
+search_index_entry = {'aliases': 'cr cre', 'category': 'general', 'key': 'create', 'no_prefix': ' cr cre', 'tags': '', 'text': '\n create a new account account\n\n Usage (at login screen):\n create <accountname> <password>\n create "account name" "pass word"\n\n This creates a new account account.\n\n If you have spaces in your name, enclose it in double quotes.\n '}
@@ -340,7 +340,7 @@ for simplicity. It shows a pane of info.
-
-
aliases = ['h', '?']
+aliases = ['?', 'h']
@@ -366,7 +366,7 @@ for simplicity. It shows a pane of info.
-
-
search_index_entry = {'aliases': 'h ?', 'category': 'general', 'key': 'help', 'no_prefix': ' h ?', 'tags': '', 'text': '\n get help when in unconnected-in state\n\n Usage:\n help\n\n This is an unconnected version of the help command,\n for simplicity. It shows a pane of info.\n '}
+search_index_entry = {'aliases': '? h', 'category': 'general', 'key': 'help', 'no_prefix': ' ? h', 'tags': '', 'text': '\n get help when in unconnected-in state\n\n Usage:\n help\n\n This is an unconnected version of the help command,\n for simplicity. It shows a pane of info.\n '}
diff --git a/docs/1.0/api/evennia.contrib.base_systems.email_login.email_login.html b/docs/1.0/api/evennia.contrib.base_systems.email_login.email_login.html
index b13f1810cc..6e309707b6 100644
--- a/docs/1.0/api/evennia.contrib.base_systems.email_login.email_login.html
+++ b/docs/1.0/api/evennia.contrib.base_systems.email_login.email_login.html
@@ -138,7 +138,7 @@ the module given by settings.CONNECTION_SCREEN_MODULE.
-
-
aliases = ['con', 'co', 'conn']
+aliases = ['conn', 'co', 'con']
@@ -168,7 +168,7 @@ there is no object yet before the account has logged in)
-
-
search_index_entry = {'aliases': 'con co conn', 'category': 'general', 'key': 'connect', 'no_prefix': ' con co conn', 'tags': '', 'text': '\n Connect to the game.\n\n Usage (at login screen):\n connect <email> <password>\n\n Use the create command to first create an account before logging in.\n '}
+search_index_entry = {'aliases': 'conn co con', 'category': 'general', 'key': 'connect', 'no_prefix': ' conn co con', 'tags': '', 'text': '\n Connect to the game.\n\n Usage (at login screen):\n connect <email> <password>\n\n Use the create command to first create an account before logging in.\n '}
@@ -190,7 +190,7 @@ there is no object yet before the account has logged in)
-
-
aliases = ['cre', 'cr']
+aliases = ['cr', 'cre']
@@ -226,7 +226,7 @@ name enclosed in quotes:
-
-
search_index_entry = {'aliases': 'cre cr', 'category': 'general', 'key': 'create', 'no_prefix': ' cre cr', 'tags': '', 'text': '\n Create a new account.\n\n Usage (at login screen):\n create "accountname" <email> <password>\n\n This creates a new account account.\n\n '}
+search_index_entry = {'aliases': 'cr cre', 'category': 'general', 'key': 'create', 'no_prefix': ' cr cre', 'tags': '', 'text': '\n Create a new account.\n\n Usage (at login screen):\n create "accountname" <email> <password>\n\n This creates a new account account.\n\n '}
@@ -334,7 +334,7 @@ for simplicity. It shows a pane of info.
-
-
aliases = ['h', '?']
+aliases = ['?', 'h']
@@ -360,7 +360,7 @@ for simplicity. It shows a pane of info.
-
-
search_index_entry = {'aliases': 'h ?', 'category': 'general', 'key': 'help', 'no_prefix': ' h ?', 'tags': '', 'text': '\n This is an unconnected version of the help command,\n for simplicity. It shows a pane of info.\n '}
+search_index_entry = {'aliases': '? h', 'category': 'general', 'key': 'help', 'no_prefix': ' ? h', 'tags': '', 'text': '\n This is an unconnected version of the help command,\n for simplicity. It shows a pane of info.\n '}
diff --git a/docs/1.0/api/evennia.contrib.base_systems.ingame_python.commands.html b/docs/1.0/api/evennia.contrib.base_systems.ingame_python.commands.html
index 4979b7dc9e..92b34d003e 100644
--- a/docs/1.0/api/evennia.contrib.base_systems.ingame_python.commands.html
+++ b/docs/1.0/api/evennia.contrib.base_systems.ingame_python.commands.html
@@ -115,7 +115,7 @@
-
-
aliases = ['@calls', '@callbacks', '@callback']
+aliases = ['@callback', '@calls', '@callbacks']
@@ -196,7 +196,7 @@ on user permission.
-
-
search_index_entry = {'aliases': '@calls @callbacks @callback', 'category': 'building', 'key': '@call', 'no_prefix': 'call calls callbacks callback', 'tags': '', 'text': '\n Command to edit callbacks.\n '}
+search_index_entry = {'aliases': '@callback @calls @callbacks', 'category': 'building', 'key': '@call', 'no_prefix': 'call callback calls callbacks', 'tags': '', 'text': '\n Command to edit callbacks.\n '}
diff --git a/docs/1.0/api/evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.html b/docs/1.0/api/evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.html
index 7737b76315..a9b16d190d 100644
--- a/docs/1.0/api/evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.html
+++ b/docs/1.0/api/evennia.contrib.base_systems.mux_comms_cmds.mux_comms_cmds.html
@@ -159,7 +159,7 @@ aliases to an already joined channel.
-
-
aliases = ['chanalias', 'aliaschan']
+aliases = ['aliaschan', 'chanalias']
@@ -190,7 +190,7 @@ aliases to an already joined channel.
-
-
search_index_entry = {'aliases': 'chanalias aliaschan', 'category': 'comms', 'key': 'addcom', 'no_prefix': ' chanalias aliaschan', 'tags': '', 'text': '\n Add a channel alias and/or subscribe to a channel\n\n Usage:\n addcom [alias=] <channel>\n\n Joins a given channel. If alias is given, this will allow you to\n refer to the channel by this alias rather than the full channel\n name. Subsequent calls of this command can be used to add multiple\n aliases to an already joined channel.\n '}
+search_index_entry = {'aliases': 'aliaschan chanalias', 'category': 'comms', 'key': 'addcom', 'no_prefix': ' aliaschan chanalias', 'tags': '', 'text': '\n Add a channel alias and/or subscribe to a channel\n\n Usage:\n addcom [alias=] <channel>\n\n Joins a given channel. If alias is given, this will allow you to\n refer to the channel by this alias rather than the full channel\n name. Subsequent calls of this command can be used to add multiple\n aliases to an already joined channel.\n '}
diff --git a/docs/1.0/api/evennia.contrib.full_systems.evscaperoom.commands.html b/docs/1.0/api/evennia.contrib.full_systems.evscaperoom.commands.html
index bb492eeba6..2a3edd4b9c 100644
--- a/docs/1.0/api/evennia.contrib.full_systems.evscaperoom.commands.html
+++ b/docs/1.0/api/evennia.contrib.full_systems.evscaperoom.commands.html
@@ -210,7 +210,7 @@ the operation will be general or on the room.
-
-
aliases = ['abort', 'q', 'quit', 'chicken out']
+aliases = ['q', 'chicken out', 'quit', 'abort']
@@ -234,7 +234,7 @@ set in self.parse())
-
-
search_index_entry = {'aliases': 'abort q quit chicken out', 'category': 'evscaperoom', 'key': 'give up', 'no_prefix': ' abort q quit chicken out', 'tags': '', 'text': '\n Give up\n\n Usage:\n give up\n\n Abandons your attempts at escaping and of ever winning the pie-eating contest.\n\n '}
+search_index_entry = {'aliases': 'q chicken out quit abort', 'category': 'evscaperoom', 'key': 'give up', 'no_prefix': ' q chicken out quit abort', 'tags': '', 'text': '\n Give up\n\n Usage:\n give up\n\n Abandons your attempts at escaping and of ever winning the pie-eating contest.\n\n '}
@@ -255,7 +255,7 @@ set in self.parse())
-
-
aliases = ['l', 'ls']
+aliases = ['ls', 'l']
@@ -289,7 +289,7 @@ set in self.parse())
-
-
search_index_entry = {'aliases': 'l ls', 'category': 'evscaperoom', 'key': 'look', 'no_prefix': ' l ls', 'tags': '', 'text': '\n Look at the room, an object or the currently focused object\n\n Usage:\n look [obj]\n\n '}
+search_index_entry = {'aliases': 'ls l', 'category': 'evscaperoom', 'key': 'look', 'no_prefix': ' ls l', 'tags': '', 'text': '\n Look at the room, an object or the currently focused object\n\n Usage:\n look [obj]\n\n '}
@@ -489,7 +489,7 @@ looks and what actions is available.
-
-
aliases = ['unfocus', 'ex', 'examine', 'e']
+aliases = ['e', 'examine', 'ex', 'unfocus']
@@ -518,7 +518,7 @@ set in self.parse())
-
-
search_index_entry = {'aliases': 'unfocus ex examine e', 'category': 'evscaperoom', 'key': 'focus', 'no_prefix': ' unfocus ex examine e', 'tags': '', 'text': '\n Focus your attention on a target.\n\n Usage:\n focus <obj>\n\n Once focusing on an object, use look to get more information about how it\n looks and what actions is available.\n\n '}
+search_index_entry = {'aliases': 'e examine ex unfocus', 'category': 'evscaperoom', 'key': 'focus', 'no_prefix': ' e examine ex unfocus', 'tags': '', 'text': '\n Focus your attention on a target.\n\n Usage:\n focus <obj>\n\n Once focusing on an object, use look to get more information about how it\n looks and what actions is available.\n\n '}
@@ -580,7 +580,7 @@ set in self.parse())
-
-
aliases = ['inventory', 'inv', 'i', 'give']
+aliases = ['inventory', 'give', 'inv', 'i']
@@ -604,7 +604,7 @@ set in self.parse())
-
-
search_index_entry = {'aliases': 'inventory inv i give', 'category': 'evscaperoom', 'key': 'get', 'no_prefix': ' inventory inv i give', 'tags': '', 'text': '\n Use focus / examine instead.\n\n '}
+search_index_entry = {'aliases': 'inventory give inv i', 'category': 'evscaperoom', 'key': 'get', 'no_prefix': ' inventory give inv i', 'tags': '', 'text': '\n Use focus / examine instead.\n\n '}
diff --git a/docs/1.0/api/evennia.contrib.game_systems.barter.barter.html b/docs/1.0/api/evennia.contrib.game_systems.barter.barter.html
index 554e88711c..e600e0c308 100644
--- a/docs/1.0/api/evennia.contrib.game_systems.barter.barter.html
+++ b/docs/1.0/api/evennia.contrib.game_systems.barter.barter.html
@@ -744,7 +744,7 @@ try to influence the other part in the deal.
-
-
aliases = ['deal', 'offers']
+aliases = ['offers', 'deal']
@@ -770,7 +770,7 @@ try to influence the other part in the deal.
-
-
search_index_entry = {'aliases': 'deal offers', 'category': 'trading', 'key': 'status', 'no_prefix': ' deal offers', 'tags': '', 'text': "\n show a list of the current deal\n\n Usage:\n status\n deal\n offers\n\n Shows the currently suggested offers on each sides of the deal. To\n accept the current deal, use the 'accept' command. Use 'offer' to\n change your deal. You might also want to use 'say', 'emote' etc to\n try to influence the other part in the deal.\n "}
+search_index_entry = {'aliases': 'offers deal', 'category': 'trading', 'key': 'status', 'no_prefix': ' offers deal', 'tags': '', 'text': "\n show a list of the current deal\n\n Usage:\n status\n deal\n offers\n\n Shows the currently suggested offers on each sides of the deal. To\n accept the current deal, use the 'accept' command. Use 'offer' to\n change your deal. You might also want to use 'say', 'emote' etc to\n try to influence the other part in the deal.\n "}
diff --git a/docs/1.0/api/evennia.contrib.game_systems.clothing.clothing.html b/docs/1.0/api/evennia.contrib.game_systems.clothing.clothing.html
index 240e407907..3411847bc4 100644
--- a/docs/1.0/api/evennia.contrib.game_systems.clothing.clothing.html
+++ b/docs/1.0/api/evennia.contrib.game_systems.clothing.clothing.html
@@ -621,7 +621,7 @@ inv
-
-
aliases = ['inv', 'i']
+aliases = ['i', 'inv']
@@ -652,7 +652,7 @@ inv
-
-
search_index_entry = {'aliases': 'inv i', 'category': 'general', 'key': 'inventory', 'no_prefix': ' inv i', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}
+search_index_entry = {'aliases': 'i inv', 'category': 'general', 'key': 'inventory', 'no_prefix': ' i inv', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}
diff --git a/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_basic.html b/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_basic.html
index 44b8145af6..ea94e92d94 100644
--- a/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_basic.html
+++ b/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_basic.html
@@ -671,7 +671,7 @@ if there are still any actions you can take.
-
-
aliases = ['hold', 'wait']
+aliases = ['wait', 'hold']
@@ -697,7 +697,7 @@ if there are still any actions you can take.
-
-
search_index_entry = {'aliases': 'hold wait', 'category': 'combat', 'key': 'pass', 'no_prefix': ' hold wait', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
+search_index_entry = {'aliases': 'wait hold', 'category': 'combat', 'key': 'pass', 'no_prefix': ' wait hold', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
diff --git a/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_equip.html b/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_equip.html
index f1f3397d2e..4423cbe821 100644
--- a/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_equip.html
+++ b/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_equip.html
@@ -566,7 +566,7 @@ if there are still any actions you can take.
-
-
aliases = ['hold', 'wait']
+aliases = ['wait', 'hold']
@@ -586,7 +586,7 @@ if there are still any actions you can take.
-
-
search_index_entry = {'aliases': 'hold wait', 'category': 'combat', 'key': 'pass', 'no_prefix': ' hold wait', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
+search_index_entry = {'aliases': 'wait hold', 'category': 'combat', 'key': 'pass', 'no_prefix': ' wait hold', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
diff --git a/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_items.html b/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_items.html
index f7a8ad332f..e207216222 100644
--- a/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_items.html
+++ b/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_items.html
@@ -689,7 +689,7 @@ if there are still any actions you can take.
-
-
aliases = ['hold', 'wait']
+aliases = ['wait', 'hold']
@@ -709,7 +709,7 @@ if there are still any actions you can take.
-
-
search_index_entry = {'aliases': 'hold wait', 'category': 'combat', 'key': 'pass', 'no_prefix': ' hold wait', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
+search_index_entry = {'aliases': 'wait hold', 'category': 'combat', 'key': 'pass', 'no_prefix': ' wait hold', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
diff --git a/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_magic.html b/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_magic.html
index d505f6169f..31676ffefd 100644
--- a/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_magic.html
+++ b/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_magic.html
@@ -468,7 +468,7 @@ if there are still any actions you can take.
-
-
aliases = ['hold', 'wait']
+aliases = ['wait', 'hold']
@@ -488,7 +488,7 @@ if there are still any actions you can take.
-
-
search_index_entry = {'aliases': 'hold wait', 'category': 'combat', 'key': 'pass', 'no_prefix': ' hold wait', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
+search_index_entry = {'aliases': 'wait hold', 'category': 'combat', 'key': 'pass', 'no_prefix': ' wait hold', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
diff --git a/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_range.html b/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_range.html
index 7b781cb996..bbe24c1062 100644
--- a/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_range.html
+++ b/docs/1.0/api/evennia.contrib.game_systems.turnbattle.tb_range.html
@@ -928,7 +928,7 @@ if there are still any actions you can take.
-
-
aliases = ['hold', 'wait']
+aliases = ['wait', 'hold']
@@ -948,7 +948,7 @@ if there are still any actions you can take.
-
-
search_index_entry = {'aliases': 'hold wait', 'category': 'combat', 'key': 'pass', 'no_prefix': ' hold wait', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
+search_index_entry = {'aliases': 'wait hold', 'category': 'combat', 'key': 'pass', 'no_prefix': ' wait hold', 'tags': '', 'text': '\n Passes on your turn.\n\n Usage:\n pass\n\n When in a fight, you can use this command to end your turn early, even\n if there are still any actions you can take.\n '}
diff --git a/docs/1.0/api/evennia.contrib.grid.extended_room.extended_room.html b/docs/1.0/api/evennia.contrib.grid.extended_room.extended_room.html
index 525e56a0c8..04447b85fa 100644
--- a/docs/1.0/api/evennia.contrib.grid.extended_room.extended_room.html
+++ b/docs/1.0/api/evennia.contrib.grid.extended_room.extended_room.html
@@ -339,7 +339,7 @@ look *<account&g
-
-
aliases = ['l', 'ls']
+aliases = ['ls', 'l']
@@ -359,7 +359,7 @@ look *<account&g
-
-
search_index_entry = {'aliases': 'l ls', 'category': 'general', 'key': 'look', 'no_prefix': ' l ls', 'tags': '', 'text': '\n look\n\n Usage:\n look\n look <obj>\n look <room detail>\n look *<account>\n\n Observes your location, details at your location or objects in your vicinity.\n '}
+search_index_entry = {'aliases': 'ls l', 'category': 'general', 'key': 'look', 'no_prefix': ' ls l', 'tags': '', 'text': '\n look\n\n Usage:\n look\n look <obj>\n look <room detail>\n look *<account>\n\n Observes your location, details at your location or objects in your vicinity.\n '}
diff --git a/docs/1.0/api/evennia.contrib.grid.xyzgrid.commands.html b/docs/1.0/api/evennia.contrib.grid.xyzgrid.commands.html
index b563ff0337..2aa3851b02 100644
--- a/docs/1.0/api/evennia.contrib.grid.xyzgrid.commands.html
+++ b/docs/1.0/api/evennia.contrib.grid.xyzgrid.commands.html
@@ -402,6 +402,78 @@ self.add().
+
+-
+class
evennia.contrib.grid.xyzgrid.commands.CmdFlyAndDive(**kwargs)[source]
+Bases: evennia.commands.default.muxcommand.MuxCommand
+Fly or Dive up and down.
+
+- Usage:
fly
+dive
+
+
+Will fly up one room or dive down one room at your current position. If
+there is no room above/below you, your movement will fail.
+
+-
+
key = 'fly or dive'
+
+
+
+-
+
aliases = ['dive', 'fly']
+
+
+
+-
+
func()[source]
+This is the hook function that actually does all the work. It is called
+by the cmdhandler right after self.parser() finishes, and so has access
+to all the variables defined therein.
+
+
+
+-
+
help_category = 'general'
+
+
+
+-
+
lock_storage = 'cmd:all();'
+
+
+
+-
+
search_index_entry = {'aliases': 'dive fly', 'category': 'general', 'key': 'fly or dive', 'no_prefix': ' dive fly', 'tags': '', 'text': '\n Fly or Dive up and down.\n\n Usage:\n fly\n dive\n\n Will fly up one room or dive down one room at your current position. If\n there is no room above/below you, your movement will fail.\n\n '}
+
+
+
+
+
+-
+class
evennia.contrib.grid.xyzgrid.commands.XYZGridFlyDiveCmdSet(cmdsetobj=None, key=None)[source]
+Bases: evennia.commands.cmdset.CmdSet
+Optional cmdset if you want the fly/dive commands to move in a 3D environment.
+
+-
+
key = 'xyzgrid_flydive_cmdset'
+
+
+
+-
+
at_cmdset_creation()[source]
+Hook method - this should be overloaded in the inheriting
+class, and should take care of populating the cmdset by use of
+self.add().
+
+
+
+-
+
path = 'evennia.contrib.grid.xyzgrid.commands.XYZGridFlyDiveCmdSet'
+
+
+
+
diff --git a/docs/1.0/api/evennia.contrib.grid.xyzgrid.tests.html b/docs/1.0/api/evennia.contrib.grid.xyzgrid.tests.html
index 51b7fe1413..04ed0646a6 100644
--- a/docs/1.0/api/evennia.contrib.grid.xyzgrid.tests.html
+++ b/docs/1.0/api/evennia.contrib.grid.xyzgrid.tests.html
@@ -1478,6 +1478,95 @@ normal hook to overload for most object types.
+
+-
+class
evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand(methodName='runTest')[source]
+Bases: evennia.utils.test_resources.BaseEvenniaCommandTest
+
+-
+
setUp()[source]
+Sets up testing environment
+
+
+
+-
+
tearDown()[source]
+Hook method for deconstructing the test fixture after testing it.
+
+
+
+-
+
test_fly_and_dive = None
+
+
+
+-
+
test_fly_and_dive_00()
+Test flying up and down and seeing if it works at different locations [with startcoord=(0, 0, -2), cmdstring=’fly’, success=False, endcoord=(0, 0, -2)].
+
+
+
+-
+
test_fly_and_dive_01()
+Test flying up and down and seeing if it works at different locations [with startcoord=(1, 1, -2), cmdstring=’fly’, success=True, endcoord=(1, 1, -1)].
+
+
+
+-
+
test_fly_and_dive_02()
+Test flying up and down and seeing if it works at different locations [with startcoord=(1, 1, -1), cmdstring=’fly’, success=True, endcoord=(1, 1, 0)].
+
+
+
+-
+
test_fly_and_dive_03()
+Test flying up and down and seeing if it works at different locations [with startcoord=(1, 1, 0), cmdstring=’fly’, success=True, endcoord=(1, 1, 1)].
+
+
+
+-
+
test_fly_and_dive_04()
+Test flying up and down and seeing if it works at different locations [with startcoord=(1, 1, 1), cmdstring=’fly’, success=False, endcoord=(1, 1, 1)].
+
+
+
+-
+
test_fly_and_dive_05()
+Test flying up and down and seeing if it works at different locations [with startcoord=(0, 0, 1), cmdstring=’fly’, success=False, endcoord=(0, 0, 1)].
+
+
+
+-
+
test_fly_and_dive_06()
+Test flying up and down and seeing if it works at different locations [with startcoord=(0, 0, 1), cmdstring=’dive’, success=False, endcoord=(0, 0, 1)].
+
+
+
+-
+
test_fly_and_dive_07()
+Test flying up and down and seeing if it works at different locations [with startcoord=(1, 1, 1), cmdstring=’dive’, success=True, endcoord=(1, 1, 0)].
+
+
+
+-
+
test_fly_and_dive_08()
+Test flying up and down and seeing if it works at different locations [with startcoord=(1, 1, 0), cmdstring=’dive’, success=True, endcoord=(1, 1, -1)].
+
+
+
+-
+
test_fly_and_dive_09()
+Test flying up and down and seeing if it works at different locations [with startcoord=(1, 1, -1), cmdstring=’dive’, success=True, endcoord=(1, 1, -2)].
+
+
+
+-
+
test_fly_and_dive_10()
+Test flying up and down and seeing if it works at different locations [with startcoord=(1, 1, -2), cmdstring=’dive’, success=False, endcoord=(1, 1, -2)].
+
+
+
+
diff --git a/docs/1.0/api/evennia.contrib.rpg.dice.dice.html b/docs/1.0/api/evennia.contrib.rpg.dice.dice.html
index fbfe7c8199..1eb2a4ff7a 100644
--- a/docs/1.0/api/evennia.contrib.rpg.dice.dice.html
+++ b/docs/1.0/api/evennia.contrib.rpg.dice.dice.html
@@ -304,7 +304,7 @@ everyone but the person rolling.
-
-
aliases = ['@dice', 'roll']
+aliases = ['roll', '@dice']
@@ -330,7 +330,7 @@ everyone but the person rolling.
-
-
search_index_entry = {'aliases': '@dice roll', 'category': 'general', 'key': 'dice', 'no_prefix': ' dice roll', 'tags': '', 'text': "\n roll dice\n\n Usage:\n dice[/switch] <nr>d<sides> [modifier] [success condition]\n\n Switch:\n hidden - tell the room the roll is being done, but don't show the result\n secret - don't inform the room about neither roll nor result\n\n Examples:\n dice 3d6 + 4\n dice 1d100 - 2 < 50\n\n This will roll the given number of dice with given sides and modifiers.\n So e.g. 2d6 + 3 means to 'roll a 6-sided die 2 times and add the result,\n then add 3 to the total'.\n Accepted modifiers are +, -, * and /.\n A success condition is given as normal Python conditionals\n (<,>,<=,>=,==,!=). So e.g. 2d6 + 3 > 10 means that the roll will succeed\n only if the final result is above 8. If a success condition is given, the\n outcome (pass/fail) will be echoed along with how much it succeeded/failed\n with. The hidden/secret switches will hide all or parts of the roll from\n everyone but the person rolling.\n "}
+search_index_entry = {'aliases': 'roll @dice', 'category': 'general', 'key': 'dice', 'no_prefix': ' roll dice', 'tags': '', 'text': "\n roll dice\n\n Usage:\n dice[/switch] <nr>d<sides> [modifier] [success condition]\n\n Switch:\n hidden - tell the room the roll is being done, but don't show the result\n secret - don't inform the room about neither roll nor result\n\n Examples:\n dice 3d6 + 4\n dice 1d100 - 2 < 50\n\n This will roll the given number of dice with given sides and modifiers.\n So e.g. 2d6 + 3 means to 'roll a 6-sided die 2 times and add the result,\n then add 3 to the total'.\n Accepted modifiers are +, -, * and /.\n A success condition is given as normal Python conditionals\n (<,>,<=,>=,==,!=). So e.g. 2d6 + 3 > 10 means that the roll will succeed\n only if the final result is above 8. If a success condition is given, the\n outcome (pass/fail) will be echoed along with how much it succeeded/failed\n with. The hidden/secret switches will hide all or parts of the roll from\n everyone but the person rolling.\n "}
diff --git a/docs/1.0/api/evennia.contrib.rpg.rpsystem.rpsystem.html b/docs/1.0/api/evennia.contrib.rpg.rpsystem.rpsystem.html
index 1aad4ca7a1..271c6c79f0 100644
--- a/docs/1.0/api/evennia.contrib.rpg.rpsystem.rpsystem.html
+++ b/docs/1.0/api/evennia.contrib.rpg.rpsystem.rpsystem.html
@@ -694,7 +694,7 @@ a different language.
-
-
aliases = ["'", '"']
+aliases = ['"', "'"]
@@ -725,7 +725,7 @@ a different language.
-
-
search_index_entry = {'aliases': '\' "', 'category': 'general', 'key': 'say', 'no_prefix': ' \' "', 'tags': '', 'text': '\n speak as your character\n\n Usage:\n say <message>\n\n Talk to those in your current location.\n '}
+search_index_entry = {'aliases': '" \'', 'category': 'general', 'key': 'say', 'no_prefix': ' " \'', 'tags': '', 'text': '\n speak as your character\n\n Usage:\n say <message>\n\n Talk to those in your current location.\n '}
diff --git a/docs/1.0/api/evennia.contrib.tutorials.evadventure.commands.html b/docs/1.0/api/evennia.contrib.tutorials.evadventure.commands.html
index 22d8babf84..89ab0d060d 100644
--- a/docs/1.0/api/evennia.contrib.tutorials.evadventure.commands.html
+++ b/docs/1.0/api/evennia.contrib.tutorials.evadventure.commands.html
@@ -255,7 +255,7 @@ set in self.parse())
-
-
aliases = ['inv', 'i']
+aliases = ['i', 'inv']
@@ -279,7 +279,7 @@ set in self.parse())
-
-
search_index_entry = {'aliases': 'inv i', 'category': 'general', 'key': 'inventory', 'no_prefix': ' inv i', 'tags': '', 'text': '\n View your inventory\n\n Usage:\n inventory\n\n '}
+search_index_entry = {'aliases': 'i inv', 'category': 'general', 'key': 'inventory', 'no_prefix': ' i inv', 'tags': '', 'text': '\n View your inventory\n\n Usage:\n inventory\n\n '}
diff --git a/docs/1.0/api/evennia.contrib.tutorials.red_button.red_button.html b/docs/1.0/api/evennia.contrib.tutorials.red_button.red_button.html
index 965b93358d..fc4b6be3e5 100644
--- a/docs/1.0/api/evennia.contrib.tutorials.red_button.red_button.html
+++ b/docs/1.0/api/evennia.contrib.tutorials.red_button.red_button.html
@@ -152,7 +152,7 @@ such as when closing the lid and un-blinding a character.
-
-
aliases = ['press button', 'press', 'push']
+aliases = ['push', 'press button', 'press']
@@ -181,7 +181,7 @@ check if the lid is open or closed.
-
-
search_index_entry = {'aliases': 'press button press push', 'category': 'general', 'key': 'push button', 'no_prefix': ' press button press push', 'tags': '', 'text': '\n Push the red button (lid closed)\n\n Usage:\n push button\n\n '}
+search_index_entry = {'aliases': 'push press button press', 'category': 'general', 'key': 'push button', 'no_prefix': ' push press button press', 'tags': '', 'text': '\n Push the red button (lid closed)\n\n Usage:\n push button\n\n '}
@@ -378,7 +378,7 @@ be mutually exclusive.
-
-
aliases = ['press button', 'press', 'push']
+aliases = ['push', 'press button', 'press']
@@ -407,7 +407,7 @@ set in self.parse())
-
-
search_index_entry = {'aliases': 'press button press push', 'category': 'general', 'key': 'push button', 'no_prefix': ' press button press push', 'tags': '', 'text': '\n Push the red button\n\n Usage:\n push button\n\n '}
+search_index_entry = {'aliases': 'push press button press', 'category': 'general', 'key': 'push button', 'no_prefix': ' push press button press', 'tags': '', 'text': '\n Push the red button\n\n Usage:\n push button\n\n '}
@@ -505,7 +505,7 @@ be mutually exclusive.
-
-
aliases = ['ex', 'feel', 'l', 'examine', 'listen', 'get']
+aliases = ['ex', 'get', 'l', 'examine', 'listen', 'feel']
@@ -531,7 +531,7 @@ be mutually exclusive.
-
-
search_index_entry = {'aliases': 'ex feel l examine listen get', 'category': 'general', 'key': 'look', 'no_prefix': ' ex feel l examine listen get', 'tags': '', 'text': "\n Looking around in darkness\n\n Usage:\n look <obj>\n\n ... not that there's much to see in the dark.\n\n "}
+search_index_entry = {'aliases': 'ex get l examine listen feel', 'category': 'general', 'key': 'look', 'no_prefix': ' ex get l examine listen feel', 'tags': '', 'text': "\n Looking around in darkness\n\n Usage:\n look <obj>\n\n ... not that there's much to see in the dark.\n\n "}
diff --git a/docs/1.0/api/evennia.contrib.tutorials.tutorial_world.objects.html b/docs/1.0/api/evennia.contrib.tutorials.tutorial_world.objects.html
index 0e0b0047d0..8e5bd5ae28 100644
--- a/docs/1.0/api/evennia.contrib.tutorials.tutorial_world.objects.html
+++ b/docs/1.0/api/evennia.contrib.tutorials.tutorial_world.objects.html
@@ -555,7 +555,7 @@ shift green root up/down
-
-
aliases = ['pull', 'shiftroot', 'move', 'push']
+aliases = ['pull', 'push', 'shiftroot', 'move']
@@ -591,7 +591,7 @@ yellow/green - horizontal roots
-
-
search_index_entry = {'aliases': 'pull shiftroot move push', 'category': 'tutorialworld', 'key': 'shift', 'no_prefix': ' pull shiftroot move push', 'tags': '', 'text': '\n Shifts roots around.\n\n Usage:\n shift blue root left/right\n shift red root left/right\n shift yellow root up/down\n shift green root up/down\n\n '}
+search_index_entry = {'aliases': 'pull push shiftroot move', 'category': 'tutorialworld', 'key': 'shift', 'no_prefix': ' pull push shiftroot move', 'tags': '', 'text': '\n Shifts roots around.\n\n Usage:\n shift blue root left/right\n shift red root left/right\n shift yellow root up/down\n shift green root up/down\n\n '}
@@ -608,7 +608,7 @@ yellow/green - horizontal roots
-
-
aliases = ['push button', 'button', 'press button']
+aliases = ['button', 'push button', 'press button']
@@ -634,7 +634,7 @@ yellow/green - horizontal roots
-
-
search_index_entry = {'aliases': 'push button button press button', 'category': 'tutorialworld', 'key': 'press', 'no_prefix': ' push button button press button', 'tags': '', 'text': '\n Presses a button.\n '}
+search_index_entry = {'aliases': 'button push button press button', 'category': 'tutorialworld', 'key': 'press', 'no_prefix': ' button push button press button', 'tags': '', 'text': '\n Presses a button.\n '}
@@ -778,7 +778,7 @@ parry - forgoes your attack but will make you harder to hit on next
-
-
aliases = ['fight', 'thrust', 'parry', 'bash', 'chop', 'hit', 'defend', 'pierce', 'kill', 'stab', 'slash']
+aliases = ['chop', 'fight', 'bash', 'defend', 'thrust', 'parry', 'hit', 'kill', 'pierce', 'slash', 'stab']
@@ -804,7 +804,7 @@ parry - forgoes your attack but will make you harder to hit on next
-
-
search_index_entry = {'aliases': 'fight thrust parry bash chop hit defend pierce kill stab slash', 'category': 'tutorialworld', 'key': 'attack', 'no_prefix': ' fight thrust parry bash chop hit defend pierce kill stab slash', 'tags': '', 'text': '\n Attack the enemy. Commands:\n\n stab <enemy>\n slash <enemy>\n parry\n\n stab - (thrust) makes a lot of damage but is harder to hit with.\n slash - is easier to land, but does not make as much damage.\n parry - forgoes your attack but will make you harder to hit on next\n enemy attack.\n\n '}
+search_index_entry = {'aliases': 'chop fight bash defend thrust parry hit kill pierce slash stab', 'category': 'tutorialworld', 'key': 'attack', 'no_prefix': ' chop fight bash defend thrust parry hit kill pierce slash stab', 'tags': '', 'text': '\n Attack the enemy. Commands:\n\n stab <enemy>\n slash <enemy>\n parry\n\n stab - (thrust) makes a lot of damage but is harder to hit with.\n slash - is easier to land, but does not make as much damage.\n parry - forgoes your attack but will make you harder to hit on next\n enemy attack.\n\n '}
diff --git a/docs/1.0/api/evennia.contrib.tutorials.tutorial_world.rooms.html b/docs/1.0/api/evennia.contrib.tutorials.tutorial_world.rooms.html
index 49462a3209..cb24cf4462 100644
--- a/docs/1.0/api/evennia.contrib.tutorials.tutorial_world.rooms.html
+++ b/docs/1.0/api/evennia.contrib.tutorials.tutorial_world.rooms.html
@@ -247,7 +247,7 @@ code except for adding in the details.
-
-
aliases = ['l', 'ls']
+aliases = ['ls', 'l']
@@ -262,7 +262,7 @@ code except for adding in the details.
-
-
search_index_entry = {'aliases': 'l ls', 'category': 'tutorialworld', 'key': 'look', 'no_prefix': ' l ls', 'tags': '', 'text': '\n looks at the room and on details\n\n Usage:\n look <obj>\n look <room detail>\n look *<account>\n\n Observes your location, details at your location or objects\n in your vicinity.\n\n Tutorial: This is a child of the default Look command, that also\n allows us to look at "details" in the room. These details are\n things to examine and offers some extra description without\n actually having to be actual database objects. It uses the\n return_detail() hook on TutorialRooms for this.\n '}
+search_index_entry = {'aliases': 'ls l', 'category': 'tutorialworld', 'key': 'look', 'no_prefix': ' ls l', 'tags': '', 'text': '\n looks at the room and on details\n\n Usage:\n look <obj>\n look <room detail>\n look *<account>\n\n Observes your location, details at your location or objects\n in your vicinity.\n\n Tutorial: This is a child of the default Look command, that also\n allows us to look at "details" in the room. These details are\n things to examine and offers some extra description without\n actually having to be actual database objects. It uses the\n return_detail() hook on TutorialRooms for this.\n '}
@@ -815,7 +815,7 @@ if they fall off the bridge.
-
-
aliases = ['h', '?']
+aliases = ['?', 'h']
@@ -841,7 +841,7 @@ if they fall off the bridge.
-
-
search_index_entry = {'aliases': 'h ?', 'category': 'tutorial world', 'key': 'help', 'no_prefix': ' h ?', 'tags': '', 'text': '\n Overwritten help command while on the bridge.\n '}
+search_index_entry = {'aliases': '? h', 'category': 'tutorial world', 'key': 'help', 'no_prefix': ' ? h', 'tags': '', 'text': '\n Overwritten help command while on the bridge.\n '}
@@ -967,7 +967,7 @@ to find something.
-
-
aliases = ['fiddle', 'feel', 'search', 'feel around', 'l']
+aliases = ['l', 'search', 'feel around', 'fiddle', 'feel']
@@ -995,7 +995,7 @@ random chance of eventually finding a light source.
-
-
search_index_entry = {'aliases': 'fiddle feel search feel around l', 'category': 'tutorialworld', 'key': 'look', 'no_prefix': ' fiddle feel search feel around l', 'tags': '', 'text': '\n Look around in darkness\n\n Usage:\n look\n\n Look around in the darkness, trying\n to find something.\n '}
+search_index_entry = {'aliases': 'l search feel around fiddle feel', 'category': 'tutorialworld', 'key': 'look', 'no_prefix': ' l search feel around fiddle feel', 'tags': '', 'text': '\n Look around in darkness\n\n Usage:\n look\n\n Look around in the darkness, trying\n to find something.\n '}
diff --git a/docs/1.0/api/evennia.contrib.utils.git_integration.git_integration.html b/docs/1.0/api/evennia.contrib.utils.git_integration.git_integration.html
index 0e20b4f8ae..12cb32f6d5 100644
--- a/docs/1.0/api/evennia.contrib.utils.git_integration.git_integration.html
+++ b/docs/1.0/api/evennia.contrib.utils.git_integration.git_integration.html
@@ -207,7 +207,7 @@ git evennia pull - Pull the latest evennia code.
-
-
directory = '/tmp/tmpt6kc_u3p/e4e7668cf542bd2f053319cf63b56fc8c90dbcd1/evennia'
+directory = '/tmp/tmpjsypa7mo/439a37762583036f5f67f650055154ee18914026/evennia'
@@ -268,7 +268,7 @@ git pull - Pull the latest code from your current branch.
-
-
directory = '/tmp/tmpt6kc_u3p/e4e7668cf542bd2f053319cf63b56fc8c90dbcd1/evennia/game_template'
+directory = '/tmp/tmpjsypa7mo/439a37762583036f5f67f650055154ee18914026/evennia/game_template'
diff --git a/docs/1.0/api/evennia.utils.eveditor.html b/docs/1.0/api/evennia.utils.eveditor.html
index 21af6abdd6..90a2aa80c5 100644
--- a/docs/1.0/api/evennia.utils.eveditor.html
+++ b/docs/1.0/api/evennia.utils.eveditor.html
@@ -335,7 +335,7 @@ indentation.
-
-
aliases = [':I', ':DD', ':A', ':w', ':>', ':s', ':q', ':i', ':S', ':', ':dw', ':dd', ':wq', ':x', ':echo', ':u', ':j', ':!', ':q!', ':UU', ':<', ':y', ':uu', ':h', ':f', ':fi', ':=', ':p', ':fd', ':r', ':::', '::']
+aliases = [':f', ':echo', ':x', ':w', ':fd', ':i', ':u', ':<', ':dd', ':r', ':s', ':y', ':j', ':q!', ':UU', ':S', '::', ':DD', ':A', ':q', ':uu', ':!', ':fi', ':wq', ':h', ':=', ':>', ':p', ':', ':I', ':::', ':dw']
@@ -363,7 +363,7 @@ efficient presentation.
-
-
search_index_entry = {'aliases': ':I :DD :A :w :> :s :q :i :S : :dw :dd :wq :x :echo :u :j :! :q! :UU :< :y :uu :h :f :fi := :p :fd :r ::: ::', 'category': 'general', 'key': ':editor_command_group', 'no_prefix': ' :I :DD :A :w :> :s :q :i :S : :dw :dd :wq :x :echo :u :j :! :q! :UU :< :y :uu :h :f :fi := :p :fd :r ::: ::', 'tags': '', 'text': '\n Commands for the editor\n '}
+search_index_entry = {'aliases': ':f :echo :x :w :fd :i :u :< :dd :r :s :y :j :q! :UU :S :: :DD :A :q :uu :! :fi :wq :h := :> :p : :I ::: :dw', 'category': 'general', 'key': ':editor_command_group', 'no_prefix': ' :f :echo :x :w :fd :i :u :< :dd :r :s :y :j :q! :UU :S :: :DD :A :q :uu :! :fi :wq :h := :> :p : :I ::: :dw', 'tags': '', 'text': '\n Commands for the editor\n '}
diff --git a/docs/1.0/api/evennia.utils.evmenu.html b/docs/1.0/api/evennia.utils.evmenu.html
index 37ee86f6e7..4b4e38ac80 100644
--- a/docs/1.0/api/evennia.utils.evmenu.html
+++ b/docs/1.0/api/evennia.utils.evmenu.html
@@ -930,7 +930,7 @@ single question.
+aliases = ['y', 'abort', 'yes', 'no', 'a', 'n', '__nomatch_command']
@@ -956,7 +956,7 @@ single question.
+search_index_entry = {'aliases': 'y abort yes no a n __nomatch_command', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' y abort yes no a n __nomatch_command', 'tags': '', 'text': '\n Handle a prompt for yes or no. Press [return] for the default choice.\n\n '}
diff --git a/docs/1.0/api/evennia.utils.evmore.html b/docs/1.0/api/evennia.utils.evmore.html
index af76680850..86bf5d38b1 100644
--- a/docs/1.0/api/evennia.utils.evmore.html
+++ b/docs/1.0/api/evennia.utils.evmore.html
@@ -136,7 +136,7 @@ the caller.msg() construct every time the page is updated.
-
-
aliases = ['quit', 'abort', 'end', 'next', 'previous', 'p', 'n', 't', 'e', 'q', 'top', 'a']
+aliases = ['t', 'abort', 'q', 'top', 'previous', 'p', 'a', 'n', 'e', 'quit', 'end', 'next']
@@ -162,7 +162,7 @@ the caller.msg() construct every time the page is updated.
-
-
search_index_entry = {'aliases': 'quit abort end next previous p n t e q top a', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' quit abort end next previous p n t e q top a', 'tags': '', 'text': '\n Manipulate the text paging. Catch no-input with aliases.\n '}
+search_index_entry = {'aliases': 't abort q top previous p a n e quit end next', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' t abort q top previous p a n e quit end next', 'tags': '', 'text': '\n Manipulate the text paging. Catch no-input with aliases.\n '}
diff --git a/docs/1.0/genindex.html b/docs/1.0/genindex.html
index 6043a54d03..3ee5537120 100644
--- a/docs/1.0/genindex.html
+++ b/docs/1.0/genindex.html
@@ -1194,6 +1194,8 @@
(evennia.contrib.grid.slow_exit.slow_exit.CmdSetSpeed attribute)
(evennia.contrib.grid.slow_exit.slow_exit.CmdStop attribute)
+
+ (evennia.contrib.grid.xyzgrid.commands.CmdFlyAndDive attribute)
(evennia.contrib.grid.xyzgrid.commands.CmdGoto attribute)
@@ -1796,6 +1798,8 @@
(evennia.contrib.grid.slow_exit.slow_exit.SlowExitCmdSet method)
(evennia.contrib.grid.xyzgrid.commands.XYZGridCmdSet method)
+
+ (evennia.contrib.grid.xyzgrid.commands.XYZGridFlyDiveCmdSet method)
(evennia.contrib.rpg.dice.dice.DiceCmdSet method)
@@ -3775,6 +3779,8 @@
CmdFind (class in evennia.commands.default.building)
CmdFinish (class in evennia.contrib.game_systems.barter.barter)
+
+ CmdFlyAndDive (class in evennia.contrib.grid.xyzgrid.commands)
CmdFocus (class in evennia.contrib.full_systems.evscaperoom.commands)
@@ -3905,11 +3911,11 @@
CmdOffer (class in evennia.contrib.game_systems.barter.barter)
CmdOOC (class in evennia.commands.default.account)
-
- CmdOOCLook (class in evennia.commands.default.account)
+ - CmdOOCLook (class in evennia.commands.default.account)
+
- CmdOpen (class in evennia.commands.default.building)
@@ -9745,6 +9751,8 @@
- (evennia.contrib.grid.slow_exit.slow_exit.CmdSetSpeed method)
- (evennia.contrib.grid.slow_exit.slow_exit.CmdStop method)
+
+ - (evennia.contrib.grid.xyzgrid.commands.CmdFlyAndDive method)
- (evennia.contrib.grid.xyzgrid.commands.CmdGoto method)
@@ -11309,6 +11317,8 @@
- (evennia.contrib.grid.slow_exit.slow_exit.CmdSetSpeed attribute)
- (evennia.contrib.grid.slow_exit.slow_exit.CmdStop attribute)
+
+ - (evennia.contrib.grid.xyzgrid.commands.CmdFlyAndDive attribute)
- (evennia.contrib.grid.xyzgrid.commands.CmdGoto attribute)
@@ -12441,6 +12451,8 @@
- (evennia.contrib.grid.slow_exit.slow_exit.CmdSetSpeed attribute)
- (evennia.contrib.grid.slow_exit.slow_exit.CmdStop attribute)
+
+ - (evennia.contrib.grid.xyzgrid.commands.CmdFlyAndDive attribute)
- (evennia.contrib.grid.xyzgrid.commands.CmdGoto attribute)
@@ -12451,6 +12463,8 @@
- (evennia.contrib.grid.xyzgrid.commands.CmdXYZTeleport attribute)
- (evennia.contrib.grid.xyzgrid.commands.XYZGridCmdSet attribute)
+
+ - (evennia.contrib.grid.xyzgrid.commands.XYZGridFlyDiveCmdSet attribute)
- (evennia.contrib.rpg.buffs.buff.BaseBuff attribute)
@@ -13361,6 +13375,8 @@
- (evennia.contrib.grid.slow_exit.slow_exit.CmdSetSpeed attribute)
- (evennia.contrib.grid.slow_exit.slow_exit.CmdStop attribute)
+
+ - (evennia.contrib.grid.xyzgrid.commands.CmdFlyAndDive attribute)
- (evennia.contrib.grid.xyzgrid.commands.CmdGoto attribute)
@@ -16606,6 +16622,8 @@
- (evennia.contrib.grid.wilderness.wilderness.WildernessScript attribute)
- (evennia.contrib.grid.xyzgrid.commands.XYZGridCmdSet attribute)
+
+ - (evennia.contrib.grid.xyzgrid.commands.XYZGridFlyDiveCmdSet attribute)
- (evennia.contrib.grid.xyzgrid.tests.TestXyzExit attribute)
@@ -18676,6 +18694,8 @@
- (evennia.contrib.grid.slow_exit.slow_exit.CmdSetSpeed attribute)
- (evennia.contrib.grid.slow_exit.slow_exit.CmdStop attribute)
+
+ - (evennia.contrib.grid.xyzgrid.commands.CmdFlyAndDive attribute)
- (evennia.contrib.grid.xyzgrid.commands.CmdGoto attribute)
@@ -19216,6 +19236,8 @@
- (evennia.contrib.grid.xyzgrid.tests.TestBuildExampleGrid method)
- (evennia.contrib.grid.xyzgrid.tests.TestCallbacks method)
+
+ - (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand method)
- (evennia.contrib.grid.xyzgrid.tests.TestXYZGrid method)
@@ -20196,6 +20218,8 @@
- (evennia.contrib.grid.xyzgrid.tests.TestBuildExampleGrid method)
- (evennia.contrib.grid.xyzgrid.tests.TestCallbacks method)
+
+ - (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand method)
- (evennia.contrib.grid.xyzgrid.tests.TestXYZGrid method)
@@ -20861,6 +20885,30 @@
- test_flee__success() (evennia.contrib.tutorials.evadventure.tests.test_combat.EvAdventureTurnbasedCombatActionTest method)
- test_floordiv() (evennia.contrib.rpg.traits.tests.TestNumericTraitOperators method)
+
+ - test_fly_and_dive (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand attribute)
+
+ - test_fly_and_dive_00() (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand method)
+
+ - test_fly_and_dive_01() (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand method)
+
+ - test_fly_and_dive_02() (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand method)
+
+ - test_fly_and_dive_03() (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand method)
+
+ - test_fly_and_dive_04() (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand method)
+
+ - test_fly_and_dive_05() (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand method)
+
+ - test_fly_and_dive_06() (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand method)
+
+ - test_fly_and_dive_07() (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand method)
+
+ - test_fly_and_dive_08() (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand method)
+
+ - test_fly_and_dive_09() (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand method)
+
+ - test_fly_and_dive_10() (evennia.contrib.grid.xyzgrid.tests.TestFlyDiveCommand method)
- test_focus() (evennia.contrib.full_systems.evscaperoom.tests.TestEvscaperoomCommands method)
@@ -22367,6 +22415,8 @@
- TestExtendedRoom (class in evennia.contrib.grid.extended_room.tests)
- TestFieldFillFunc (class in evennia.contrib.utils.tree_select.tests)
+
+ - TestFlyDiveCommand (class in evennia.contrib.grid.xyzgrid.tests)
- TestGenderSub (class in evennia.contrib.game_systems.gendersub.tests)
@@ -23782,14 +23832,14 @@
- xymap() (evennia.contrib.grid.xyzgrid.xyzroom.XYZRoom property)
- |
- |
+
- xyz_destination() (evennia.contrib.grid.xyzgrid.xyzroom.XYZExit property)
- xyzcommand() (in module evennia.contrib.grid.xyzgrid.launchcmd)
@@ -23815,6 +23865,8 @@
- XYZGrid.MultipleObjectsReturned
- XYZGridCmdSet (class in evennia.contrib.grid.xyzgrid.commands)
+
+ - XYZGridFlyDiveCmdSet (class in evennia.contrib.grid.xyzgrid.commands)
- XYZManager (class in evennia.contrib.grid.xyzgrid.xyzroom)
diff --git a/docs/1.0/objects.inv b/docs/1.0/objects.inv
index 70a4781789e68faf90071a2e399cd13fea7511ff..fda21767bc8c8c2215e0872bf8ced1509429b997 100644
GIT binary patch
delta 147491
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 |