Start add evennia xyzgrid launch command
This commit is contained in:
parent
74111f2e80
commit
a1438150c0
4 changed files with 266 additions and 7 deletions
181
evennia/contrib/xyzgrid/launchcmd.py
Normal file
181
evennia/contrib/xyzgrid/launchcmd.py
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
"""
|
||||||
|
Custom Evennia launcher command option for building/rebuilding the grid in a separate process than
|
||||||
|
the main server (since this can be slow).
|
||||||
|
|
||||||
|
To use, add to the settings:
|
||||||
|
::
|
||||||
|
|
||||||
|
EXTRA_LAUNCHER_COMMANDS.update({'xyzgrid': 'evennia.contrib.xyzgrid.launchcmd.xyzcommand'})
|
||||||
|
|
||||||
|
You should now be able to do
|
||||||
|
::
|
||||||
|
|
||||||
|
evennia xyzgrid <options>
|
||||||
|
|
||||||
|
Use `evennia xyzgrid help` for usage help.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from evennia.contrib.xyzgrid.xyzgrid import get_xyzgrid
|
||||||
|
|
||||||
|
_HELP_SHORT = """
|
||||||
|
evennia xyzgrid help|list|init|add|build|initpath|delete [<options>]
|
||||||
|
Manages the XYZ grid. Use 'xyzgrid help' for documentation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_HELP_LONG = """
|
||||||
|
evennia xyzgrid list
|
||||||
|
|
||||||
|
Lists the map grid structure and any loaded maps.
|
||||||
|
|
||||||
|
evennia xyzgrid list Z|mapname
|
||||||
|
|
||||||
|
Display the given XYmap in more detail. Also 'show' works.
|
||||||
|
|
||||||
|
evennia xyzgrid init
|
||||||
|
|
||||||
|
First start of the grid. This will create the XYZGrid global script. No maps are loaded yet!
|
||||||
|
It's safe to run this command multiple times; the grid will only be initialized once.
|
||||||
|
|
||||||
|
evennia xyzgrid add path.to.xymap.module
|
||||||
|
|
||||||
|
Add one or more XYmaps (each a string-map representing one Z position along with prototypes
|
||||||
|
etc). The module will be parsed for
|
||||||
|
|
||||||
|
- a XYMAP_DATA a dict
|
||||||
|
{"map": mapstring, "zcoord": mapname/zcoord, "legend": dict, "prototypes": dict}
|
||||||
|
describing one single XYmap, or
|
||||||
|
- a XYMAP_LIST - a list of multiple dicts on the XYMAP_DATA form. This allows to load
|
||||||
|
multiple maps from the same module.
|
||||||
|
|
||||||
|
Note that adding a map does *not* build it. If maps are linked to one another, you should add
|
||||||
|
all linked maps before building, or you'll get errors when spawning the linking exits.
|
||||||
|
|
||||||
|
evennia xyzgrid build
|
||||||
|
|
||||||
|
Builds/updates the entire database grid based on the added maps. For a new grid, this will spawn
|
||||||
|
all new rooms/exits (and may take a good while!). For updating, rooms may be removed/spawned if
|
||||||
|
a map changed since the last build.
|
||||||
|
|
||||||
|
evennia xyzgrid build (X,Y,Z|mapname)
|
||||||
|
|
||||||
|
Builds/updates only a part of the grid. This should usually only be used if the full grid has
|
||||||
|
already been built once - otherwise inter-map transitions may fail! Z is the name/z-coordinate
|
||||||
|
of the map. Use '*' as a wildcard. For example (*, *, mymap) will only update map `mymap` and
|
||||||
|
(12, 6, mymap) will only update position (12, 6) on the map 'mymap'.
|
||||||
|
|
||||||
|
evennia xyzgrid initpath
|
||||||
|
|
||||||
|
Recreates the pathfinder matrices for the entire grid. These are used for all shortest-path
|
||||||
|
calculations. The result will be cached to disk (in mygame/server/.cache/). If not run, each map
|
||||||
|
will run this automatically first time it's used. Running this will always force to rebuild the
|
||||||
|
cache.
|
||||||
|
|
||||||
|
evennia xyzgrid initpath Z|mapname
|
||||||
|
|
||||||
|
recreate the pathfinder matrix for a specific map only. Z is the name/z-coordinate of the map.
|
||||||
|
|
||||||
|
evennia xyzgrid delete Z|mapname
|
||||||
|
|
||||||
|
Remove a previously added XYmap with the name/z-coordinate Z. E.g. 'remove mymap'. If the map
|
||||||
|
was built, this will also wipe all its spawned rooms/exits. You will be asked to confirm before
|
||||||
|
continuing with this operation.
|
||||||
|
|
||||||
|
evennia xyzgrid delete
|
||||||
|
|
||||||
|
WARNING: This will delete the entire xyz-grid (all maps), and *all* rooms/exits built to match
|
||||||
|
it (they serve no purpose without the grid). You will be asked to confirm before continuing with
|
||||||
|
this operation.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _option_list(**suboptions):
|
||||||
|
"""
|
||||||
|
List/view grid.
|
||||||
|
|
||||||
|
"""
|
||||||
|
xyzgrid = get_xyzgrid()
|
||||||
|
xymap_data = xyzgrid.grid
|
||||||
|
if not xymap_data:
|
||||||
|
print("The XYZgrid is currently empty. Use 'add' to add paths to your map data.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not suboptions:
|
||||||
|
print("XYMaps stored in grid:")
|
||||||
|
for zcoord, xymap in sorted(xymap_data.items(), key=lambda tup: tup[0]):
|
||||||
|
print(str(xymap))
|
||||||
|
|
||||||
|
|
||||||
|
def _option_init(**suboptions):
|
||||||
|
"""
|
||||||
|
Initialize a new grid. Will fail if a Grid already exists.
|
||||||
|
|
||||||
|
"""
|
||||||
|
grid = get_xyzgrid()
|
||||||
|
print(f"The grid is initalized as the Script 'XYZGrid'({grid.dbref})")
|
||||||
|
|
||||||
|
def _option_add(**suboptions):
|
||||||
|
"""
|
||||||
|
Add a new map to the grid.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _option_build(**suboptions):
|
||||||
|
"""
|
||||||
|
Build the grid or part of it.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _option_initpath(**suboptions):
|
||||||
|
"""
|
||||||
|
Initialize the pathfinding matrices for grid or part of it.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _option_delete(**suboptions):
|
||||||
|
"""
|
||||||
|
Delete the grid or parts of it.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not suboptions:
|
||||||
|
repl = input("WARNING: This will delete the ENTIRE Grid and wipe all rooms/exits!"
|
||||||
|
"\nObjects/Chars inside deleted rooms will be moved to their home locations."
|
||||||
|
"\nThis can't be undone. Are you sure you want to continue? Y/[N]?")
|
||||||
|
if repl.lower() not in ('yes', 'y'):
|
||||||
|
print("Aborted.")
|
||||||
|
else:
|
||||||
|
print("Deleting grid ...")
|
||||||
|
grid = get_xyzgrid()
|
||||||
|
grid.delete()
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def xyzcommand(*args):
|
||||||
|
"""
|
||||||
|
Evennia launcher command. This is made available as `evennia xyzgrid` on the command line,
|
||||||
|
once `settings.EXTRA_LAUNCHER_COMMANDS` is updated.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not args:
|
||||||
|
print(_HELP_SHORT.strip())
|
||||||
|
return
|
||||||
|
|
||||||
|
option, *suboptions = args
|
||||||
|
|
||||||
|
if option in ('help', 'h'):
|
||||||
|
print(f"{_HELP_SHORT.strip()}\n{_HELP_LONG.rstrip()}")
|
||||||
|
|
||||||
|
if option in ('list', 'show'):
|
||||||
|
_option_list(*suboptions)
|
||||||
|
elif option == 'init':
|
||||||
|
_option_init(*suboptions)
|
||||||
|
elif option == 'add':
|
||||||
|
_option_add(*suboptions)
|
||||||
|
elif option == 'build':
|
||||||
|
_option_build(*suboptions)
|
||||||
|
elif option == 'initpath':
|
||||||
|
_option_initpath(*suboptions)
|
||||||
|
elif option == 'delete':
|
||||||
|
_option_delete(*suboptions)
|
||||||
|
|
@ -62,3 +62,7 @@ MAP_DATA = {
|
||||||
"legend": LEGEND,
|
"legend": LEGEND,
|
||||||
"rooms": ROOMS,
|
"rooms": ROOMS,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XYMAP_LIST = [
|
||||||
|
MAP_DATA
|
||||||
|
]
|
||||||
|
|
|
||||||
35
evennia/contrib/xyzgrid/prototypes.py
Normal file
35
evennia/contrib/xyzgrid/prototypes.py
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
"""
|
||||||
|
Prototypes for building the XYZ-grid into actual game-rooms.
|
||||||
|
|
||||||
|
Add this to mygame/conf/settings/settings.py:
|
||||||
|
|
||||||
|
PROTOTYPE_MODULES += ['evennia.contrib.xyzgrid.prototypes']
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Note - the XYZRoom/exit parents track the XYZ coordinates automatically
|
||||||
|
# so we don't need to add custom tags to them here.
|
||||||
|
_ROOM_PARENT = {
|
||||||
|
'prototype_tags': ("xyzroom", ),
|
||||||
|
'typeclass': 'evennia.contrib.xyzgrid.xyzroom.XYZRoom'
|
||||||
|
}
|
||||||
|
|
||||||
|
_EXIT_PARENT = {
|
||||||
|
'prototype_tags': ("xyzexit", ),
|
||||||
|
'typeclass': 'evennia.contrib.xyzgrid.xyzroom.XYZExit'
|
||||||
|
}
|
||||||
|
|
||||||
|
PROTOTYPE_LIST = [
|
||||||
|
{
|
||||||
|
'prototype_key': 'xyz_room_prototype',
|
||||||
|
'prototype_parent': _ROOM_PARENT,
|
||||||
|
'key': "A non-descript room",
|
||||||
|
},{
|
||||||
|
'prototype_key': 'xyz_transition_room_prototype',
|
||||||
|
'prototype_parent': _ROOM_PARENT,
|
||||||
|
'typeclass': 'evennia.contrib.xyzgrid.xyzroom.XYZMapTransitionRoom',
|
||||||
|
},{
|
||||||
|
'prototype_key': 'xyz_exit_prototype',
|
||||||
|
'prototype_parent': _EXIT_PARENT,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -16,11 +16,10 @@ The grid has three main functions:
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import itertools
|
|
||||||
from evennia.scripts.scripts import DefaultScript
|
from evennia.scripts.scripts import DefaultScript
|
||||||
from evennia.utils import logger
|
from evennia.utils import logger
|
||||||
from .xymap import XYMap
|
from .xymap import XYMap
|
||||||
from .xyzroom import XYZRoom, XYZExit
|
from .xyzroom import XYZRoom
|
||||||
|
|
||||||
|
|
||||||
class XYZGrid(DefaultScript):
|
class XYZGrid(DefaultScript):
|
||||||
|
|
@ -41,8 +40,28 @@ class XYZGrid(DefaultScript):
|
||||||
self.reload()
|
self.reload()
|
||||||
return self.ndb.grid
|
return self.ndb.grid
|
||||||
|
|
||||||
def get(self, mapname, default=None):
|
def get(self, zcoord):
|
||||||
return self.grid.get(mapname, default)
|
"""
|
||||||
|
Get a specific xymap.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
zcoord (str): The name/zcoord of the xymap.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
XYMap: Or None if no map was found.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self.grid.get(zcoord)
|
||||||
|
|
||||||
|
def all(self):
|
||||||
|
"""
|
||||||
|
Get all xymaps stored in the grid.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: All initialized xymaps stored with this grid.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self.grid
|
||||||
|
|
||||||
def reload(self):
|
def reload(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -119,10 +138,11 @@ class XYZGrid(DefaultScript):
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
"""
|
"""
|
||||||
Clear the entire grid, including database entities.
|
Clear the entire grid, including database entities, then the grid too.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.remove_map(*(zcoord for zcoord in self.db.map_data), remove_objects=True)
|
self.remove_map(*(zcoord for zcoord in self.db.map_data), remove_objects=True)
|
||||||
|
super().delete()
|
||||||
|
|
||||||
def spawn(self, xyz=('*', '*', '*'), directions=None):
|
def spawn(self, xyz=('*', '*', '*'), directions=None):
|
||||||
"""
|
"""
|
||||||
|
|
@ -163,3 +183,22 @@ class XYZGrid(DefaultScript):
|
||||||
for zcoord, xymap in xymaps.items():
|
for zcoord, xymap in xymaps.items():
|
||||||
logger.log_info(f"[grid] spawning/updating links for {zcoord} ...")
|
logger.log_info(f"[grid] spawning/updating links for {zcoord} ...")
|
||||||
xymap.spawn_links(xy=(x, y), directions=directions)
|
xymap.spawn_links(xy=(x, y), directions=directions)
|
||||||
|
|
||||||
|
|
||||||
|
def get_xyzgrid():
|
||||||
|
"""
|
||||||
|
Helper for getting the grid. This will create the XYZGrid global script if it didn't
|
||||||
|
previously exist.
|
||||||
|
|
||||||
|
"""
|
||||||
|
xyzgrid = XYZGrid.objects.all()
|
||||||
|
if not xyzgrid:
|
||||||
|
# create a new one
|
||||||
|
xyzgrid, err = XYZGrid.create("XYZGrid")
|
||||||
|
if err:
|
||||||
|
raise RuntimeError(err)
|
||||||
|
return xyzgrid
|
||||||
|
elif len(xyzgrid) > 1:
|
||||||
|
("Warning: More than one XYZGrid instances were found. This is an error and "
|
||||||
|
"only the first one will be used. Delete the other one(s) manually.")
|
||||||
|
return xyzgrid[0]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue