mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Merge pull request #2904 from Henddher/issue_2695
fix: xyzgrid spawn doesn't call at_object_creation
This commit is contained in:
commit
4ba7df7f61
3 changed files with 105 additions and 24 deletions
|
|
@ -53,28 +53,31 @@ Exits: northeast and east
|
|||
(then go back to your mygame/ folder)
|
||||
|
||||
This will install all optional requirements of Evennia.
|
||||
2. Import and add the `evennia.contrib.commands.XYZGridCmdSet` to the
|
||||
2. Import and [add] the `evennia.contrib.grid.xyzgrid.commands.XYZGridCmdSet` to the
|
||||
`CharacterCmdset` cmdset in `mygame/commands.default_cmds.py`. Reload
|
||||
the server. This makes the `map`, `goto/path` and the modified `teleport` and
|
||||
`open` commands available in-game.
|
||||
|
||||
[add]: docs/source/Command-Sets.md#defining-command-sets
|
||||
|
||||
3. Edit `mygame/server/conf/settings.py` and add
|
||||
|
||||
EXTRA_LAUNCHER_COMMANDS['xyzgrid'] = 'evennia.contrib.launchcmd.xyzcommand'
|
||||
|
||||
and
|
||||
|
||||
PROTOTYPE_MODULES += [’evennia.contrib.grid.xyzgrid.prototypes’]
|
||||
EXTRA_LAUNCHER_COMMANDS['xyzgrid'] = 'evennia.contrib.grid.xyzgrid.launchcmd.xyzcommand'
|
||||
PROTOTYPE_MODULES += ['evennia.contrib.grid.xyzgrid.prototypes']
|
||||
|
||||
This will add the new ability to enter `evennia xyzgrid <option>` on the
|
||||
command line. It will also make the `xyz_room` and `xyz_exit` prototypes
|
||||
available for use as prototype-parents when spawning the grid.
|
||||
|
||||
4. Run `evennia xyzgrid help` for available options.
|
||||
|
||||
5. (Optional): By default, the xyzgrid will only spawn module-based
|
||||
[prototypes](../Components/Prototypes.md). This is an optimization and usually makes sense
|
||||
[prototypes]. This is an optimization and usually makes sense
|
||||
since the grid is entirely defined outside the game anyway. If you want to
|
||||
also make use of in-game (db-) created prototypes, add
|
||||
`XYZGRID_USE_DB_PROTOTYPES = True` to settings.
|
||||
|
||||
[prototypes]: ../Components/Prototypes.md
|
||||
|
||||
## Overview
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
Tests for the XYZgrid system.
|
||||
|
||||
"""
|
||||
from unittest import mock
|
||||
|
||||
from random import randint
|
||||
from parameterized import parameterized
|
||||
|
|
@ -1415,3 +1416,78 @@ class TestBuildExampleGrid(BaseEvenniaTest):
|
|||
self.assertTrue(room2a.db.desc.startswith("This is the entrance to"))
|
||||
self.assertEqual(room2b.key, "North-west corner of the atrium")
|
||||
self.assertTrue(room2b.db.desc.startswith("Sunlight sifts down"))
|
||||
|
||||
|
||||
mock_room_callbacks = mock.MagicMock()
|
||||
mock_exit_callbacks = mock.MagicMock()
|
||||
|
||||
class TestXyzRoom(xyzroom.XYZRoom):
|
||||
def at_object_creation(self):
|
||||
mock_room_callbacks.at_object_creation()
|
||||
|
||||
class TestXyzExit(xyzroom.XYZExit):
|
||||
def at_object_creation(self):
|
||||
mock_exit_callbacks.at_object_creation()
|
||||
|
||||
MAP_DATA = {
|
||||
"map": """
|
||||
|
||||
+ 0 1
|
||||
|
||||
0 #-#
|
||||
|
||||
+ 0 1
|
||||
|
||||
""",
|
||||
"zcoord": "map1",
|
||||
"prototypes": {
|
||||
("*", "*"): {
|
||||
"key": "room",
|
||||
"desc": "A room.",
|
||||
"prototype_parent": "xyz_room",
|
||||
},
|
||||
("*", "*", "*"): {
|
||||
"desc": "A passage.",
|
||||
"prototype_parent": "xyz_exit",
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"map_visual_range": 1,
|
||||
"map_mode": "scan",
|
||||
}
|
||||
}
|
||||
|
||||
class TestCallbacks(BaseEvenniaTest):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
mock_room_callbacks.reset_mock()
|
||||
mock_exit_callbacks.reset_mock()
|
||||
|
||||
def setup_grid(self, map_data):
|
||||
self.grid, err = xyzgrid.XYZGrid.create("testgrid")
|
||||
|
||||
def _log(msg):
|
||||
print(msg)
|
||||
self.grid.log = _log
|
||||
|
||||
self.map_data = map_data
|
||||
self.grid.add_maps(map_data)
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
self.grid.delete()
|
||||
|
||||
def test_typeclassed_xyzroom_and_xyzexit_with_at_object_creation_are_called(self):
|
||||
map_data = dict(MAP_DATA)
|
||||
for prototype_key, prototype_value in map_data["prototypes"].items():
|
||||
if len(prototype_key) == 2:
|
||||
prototype_value["typeclass"] = "evennia.contrib.grid.xyzgrid.tests.TestXyzRoom"
|
||||
if len(prototype_key) == 3:
|
||||
prototype_value["typeclass"] = "evennia.contrib.grid.xyzgrid.tests.TestXyzExit"
|
||||
self.setup_grid(map_data)
|
||||
|
||||
self.grid.spawn()
|
||||
|
||||
# Two rooms and 2 exits, Each one should have gotten one `at_object_creation` callback.
|
||||
self.assertEqual(mock_room_callbacks.at_object_creation.mock_calls, [mock.call(), mock.call()])
|
||||
self.assertEqual(mock_exit_callbacks.at_object_creation.mock_calls, [mock.call(), mock.call()])
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@ from collections import defaultdict
|
|||
|
||||
from django.core import exceptions as django_exceptions
|
||||
from evennia.prototypes import spawner
|
||||
from evennia.utils.utils import class_from_module
|
||||
|
||||
from .utils import MAPSCAN, REVERSE_DIRECTIONS, MapParserError, BIGVAL
|
||||
from .utils import MAPSCAN, REVERSE_DIRECTIONS, MapParserError, BIGVAL, MapError
|
||||
|
||||
NodeTypeclass = None
|
||||
ExitTypeclass = None
|
||||
|
|
@ -316,13 +317,14 @@ class MapNode:
|
|||
try:
|
||||
nodeobj = NodeTypeclass.objects.get_xyz(xyz=xyz)
|
||||
except django_exceptions.ObjectDoesNotExist:
|
||||
# create a new entity with proper coordinates etc
|
||||
tclass = self.prototype["typeclass"]
|
||||
tclass = (
|
||||
f" ({tclass})" if tclass != "evennia.contrib.grid.xyzgrid.xyzroom.XYZRoom" else ""
|
||||
)
|
||||
self.log(f" spawning room at xyz={xyz}{tclass}")
|
||||
nodeobj, err = NodeTypeclass.create(self.prototype.get("key", "An empty room"), xyz=xyz)
|
||||
# create a new entity, using the specified typeclass (if there's one) and
|
||||
# with proper coordinates etc
|
||||
typeclass = self.prototype.get("typeclass")
|
||||
if typeclass is None:
|
||||
raise MapError(f"The prototype {self.prototype} for this node has no 'typeclass' key.", self)
|
||||
self.log(f" spawning room at xyz={xyz} ({typeclass})")
|
||||
Typeclass = class_from_module(typeclass)
|
||||
nodeobj, err = Typeclass.create(self.prototype.get("key", "An empty room"), xyz=xyz)
|
||||
if err:
|
||||
raise RuntimeError(err)
|
||||
else:
|
||||
|
|
@ -400,7 +402,14 @@ class MapNode:
|
|||
continue
|
||||
|
||||
exitnode = self.links[direction]
|
||||
exi, err = ExitTypeclass.create(
|
||||
prot = maplinks[key.lower()][3].prototype
|
||||
typeclass = prot.get("typeclass")
|
||||
if typeclass is None:
|
||||
raise MapError(f"The prototype {self.prototype} for this node has no 'typeclass' key.", self)
|
||||
self.log(f" spawning/updating exit xyz={xyz}, direction={key} ({typeclass})")
|
||||
|
||||
Typeclass = class_from_module(typeclass)
|
||||
exi, err = Typeclass.create(
|
||||
key,
|
||||
xyz=xyz,
|
||||
xyz_destination=exitnode.get_spawn_xyz(),
|
||||
|
|
@ -408,15 +417,8 @@ class MapNode:
|
|||
)
|
||||
if err:
|
||||
raise RuntimeError(err)
|
||||
|
||||
linkobjs[key.lower()] = exi
|
||||
prot = maplinks[key.lower()][3].prototype
|
||||
tclass = prot["typeclass"]
|
||||
tclass = (
|
||||
f" ({tclass})"
|
||||
if tclass != "evennia.contrib.grid.xyzgrid.xyzroom.XYZExit"
|
||||
else ""
|
||||
)
|
||||
self.log(f" spawning/updating exit xyz={xyz}, direction={key}{tclass}")
|
||||
|
||||
# apply prototypes to catch any changes
|
||||
for key, linkobj in linkobjs.items():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue