evennia/evennia/contrib/xyzgrid/commands.py
2021-07-08 21:40:35 +02:00

187 lines
6.7 KiB
Python

"""
XYZ-aware commands
Just add the XYZGridCmdSet to the default character cmdset to override
the commands with XYZ-aware equivalents.
"""
from evennia import InterruptCommand
from evennia import MuxCommand, CmdSet
from evennia.commands.default import building, general
from evennia.contrib.xyzgrid.xyzroom import XYZRoom
from evennia.utils.utils import inherits_from
class CmdXYZLook(general.CmdLook):
character = '@'
visual_range = 2
map_mode = 'nodes' # or 'scan'
def func(self):
"""
Add xymap display before the normal look command.
"""
location = self.caller.location
if inherits_from(location, XYZRoom):
xyz = location.xyz
xymap = location.xyzgrid.get_map(xyz[2])
map_display = xymap.get_visual_range(
(xyz[0], xyz[1]),
dist=self.visual_range,
mode=self.map_mode)
maxw = min(xymap.max_x, self.client_width())
sep = "~" * maxw
map_display = f"|x{sep}|n\n{map_display}\n|x{sep}"
self.msg(map_display, {"type", "xymap"}, options=None)
# now run the normal look command
super().func()
class CmdXYZTeleport(building.CmdTeleport):
"""
teleport object to another location
Usage:
tel/switch [<object> to||=] <target location>
tel/switch [<object> to||=] (X,Y[,Z])
Examples:
tel Limbo
tel/quiet box = Limbo
tel/tonone box
tel (3, 3, the small cave)
tel (4, 1) # on the same map
Switches:
quiet - don't echo leave/arrive messages to the source/target
locations for the move.
intoexit - if target is an exit, teleport INTO
the exit object instead of to its destination
tonone - if set, teleport the object to a None-location. If this
switch is set, <target location> is ignored.
Note that the only way to retrieve
an object from a None location is by direct #dbref
reference. A puppeted object cannot be moved to None.
loc - teleport object to the target's location instead of its contents
Teleports an object somewhere. If no object is given, you yourself are
teleported to the target location. If (X,Y) or (X,Y,Z) coordinates
are given, the target is a location on the XYZGrid.
"""
def parse(self):
MuxCommand.parse(self)
self.obj_to_teleport = self.caller
self.destination = None
rhs = self.rhs
if self.lhs:
self.obj_to_teleport = self.caller.search(self.lhs, global_search=True)
if not self.obj_to_teleport:
self.caller.msg("Did not find object to teleport.")
raise InterruptCommand
if rhs:
if all(char in rhs for char in ("(", ")", ",")):
# search by (X,Y) or (X,Y,Z)
X, Y, *Z = rhs.split(",", 2)
if Z:
# Z was specified
Z = Z[0]
else:
# use current location's Z, if it exists
try:
xyz = self.caller.xyz
except AttributeError:
self.caller.msg("Z-coordinate is also required since you are not currently "
"in a room with a Z coordinate of its own.")
raise InterruptCommand
else:
Z = xyz[2]
# search by coordinate
X, Y, Z = str(X).strip(), str(Y).strip(), str(Z).strip()
try:
self.obj_to_teleport = XYZRoom.objects.get_xyz(xyz=(X, Y, Z))
except XYZRoom.DoesNotExist:
self.caller.msg("Found no target XYZRoom at ({X},{Y},{Y}).")
raise InterruptCommand
else:
# regular search
self.destination = self.caller.search(rhs, global_search=True)
class CmdXYZOpen(building.CmdOpen):
"""
open a new exit from the current room
Usage:
open <new exit>[;alias;..][:typeclass] [,<return exit>[;alias;..][:typeclass]]] = <destination>
open <new exit>[;alias;..][:typeclass] [,<return exit>[;alias;..][:typeclass]]] = (X,Y,Z)
Handles the creation of exits. If a destination is given, the exit
will point there. The destination can also be given as an (X,Y,Z) coordinate on the
XYZGrid - this command is used to link non-grid rooms to the grid and vice-versa.
The <return exit> argument sets up an exit at the destination leading back to the current room.
Apart from (X,Y,Z) coordinate, destination name can be given both as a #dbref and a name, if
that name is globally unique.
Examples:
open kitchen = Kitchen
open north, south = Town Center
open cave mouth;cave = (3, 4, the small cave)
"""
def parse(self):
building.ObjManipCommand.parse(self)
self.location = self.caller.location
if not self.args or not self.rhs:
self.caller.msg("Usage: open <new exit>[;alias...][:typeclass]"
"[,<return exit>[;alias..][:typeclass]]] "
"= <destination>")
raise InterruptCommand
if not self.location:
self.caller.msg("You cannot create an exit from a None-location.")
raise InterruptCommand
if all(char in self.rhs for char in ("(", ")", ",")):
# search by (X,Y) or (X,Y,Z)
X, Y, *Z = self.rhs.split(",", 2)
if not Z:
self.caller.msg("A full (X,Y,Z) coordinate must be given for the destination.")
raise InterruptCommand
Z = Z[0]
# search by coordinate
X, Y, Z = str(X).strip(), str(Y).strip(), str(Z).strip()
try:
self.destination = XYZRoom.objects.get_xyz(xyz=(X, Y, Z))
except XYZRoom.DoesNotExist:
self.caller.msg("Found no target XYZRoom at ({X},{Y},{Y}).")
raise InterruptCommand
else:
# regular search query
self.destination = self.caller.search(self.rhs, global_search=True)
if not self.destination:
raise InterruptCommand
self.exit_name = self.lhs_objs[0]["name"]
self.exit_aliases = self.lhs_objs[0]["aliases"]
self.exit_typeclass = self.lhs_objs[0]["option"]
class XYZGridCmdSet(CmdSet):
"""
Cmdset for easily adding the above cmds to the character cmdset.
"""
key = "xyzgrid_cmdset"
def at_cmdset_creation(self):
self.add(CmdXYZLook())
self.add(CmdXYZTeleport())
self.add(CmdXYZOpen())