add test for preserve_items opt and fix

This commit is contained in:
InspectorCaracal 2022-11-21 20:23:56 -07:00
parent ab317a691e
commit de24d2646d
2 changed files with 81 additions and 31 deletions

View file

@ -136,3 +136,30 @@ class TestWilderness(BaseEvenniaTest):
for direction, correct_loc in directions.items(): for direction, correct_loc in directions.items():
new_loc = wilderness.get_new_coordinates(loc, direction) new_loc = wilderness.get_new_coordinates(loc, direction)
self.assertEqual(new_loc, correct_loc, direction) self.assertEqual(new_loc, correct_loc, direction)
def test_preserve_items(self):
wilderness.create_wilderness()
w = self.get_wilderness_script()
# move char and obj to wilderness
wilderness.enter_wilderness(self.char1)
wilderness.enter_wilderness(self.obj1)
# move to a new room
w.move_obj(self.char1, (1, 1))
# the room should be remapped and 0,0 should not exist
self.assertTrue((0, 0) not in w.db.rooms)
self.assertEqual(1, len(w.db.rooms))
# verify obj1 moved to None
self.assertIsNone(self.obj1.location)
# now change to preserve items
w.preserve_items = True
wilderness.enter_wilderness(self.obj1, (1, 1))
# move the character again
w.move_obj(self.char1, (0, 1))
# check that the previous room was preserved
self.assertIn((1, 1), w.db.rooms)
self.assertEqual(2, len(w.db.rooms))
# and verify that obj1 is still at 1,1
self.assertEqual(self.obj1.location, w.db.rooms[(1, 1)])

View file

@ -46,11 +46,11 @@ needs.
## Example ## Example
To give an example of how to customize, we will create a very simple (and To give an example of how to customize, we will create a very simple (and
small) wilderness map that is shaped like a pyramid. The map will be small) wilderness map that is shaped like a pyramid. The map will be
provided as a string: a "." symbol is a location we can walk on. provided as a string: a "." symbol is a location we can walk on.
Let's create a file world/pyramid.py: Let's create a file world/pyramid.py:
```python ```python
map_str = ''' map_str = '''
@ -113,7 +113,6 @@ separate rooms.
Rooms are created as needed. Unneeded rooms are stored away to avoid the Rooms are created as needed. Unneeded rooms are stored away to avoid the
overhead cost of creating new rooms again in the future. overhead cost of creating new rooms again in the future.
""" """
from evennia import ( from evennia import (
@ -126,6 +125,7 @@ from evennia import (
from evennia.utils import inherits_from from evennia.utils import inherits_from
from evennia.typeclasses.attributes import AttributeProperty from evennia.typeclasses.attributes import AttributeProperty
def create_wilderness(name="default", mapprovider=None): def create_wilderness(name="default", mapprovider=None):
""" """
Creates a new wilderness map. Does nothing if a wilderness map already Creates a new wilderness map. Does nothing if a wilderness map already
@ -216,7 +216,7 @@ class WildernessScript(DefaultScript):
# Stores a dictionary of items on the map with their coordinates # Stores a dictionary of items on the map with their coordinates
# The key is the item, the value are the coordinates as (x, y) tuple. # The key is the item, the value are the coordinates as (x, y) tuple.
itemcoordinates = AttributeProperty() itemcoordinates = AttributeProperty()
# Determines whether or not rooms are recycled despite containing non-player objects # Determines whether or not rooms are recycled despite containing non-player objects
# True means that leaving behind a non-player object will prevent the room from being recycled # True means that leaving behind a non-player object will prevent the room from being recycled
# in order to preserve the object # in order to preserve the object
@ -241,7 +241,7 @@ class WildernessScript(DefaultScript):
# allows quick retrieval if a new room is needed without having to # allows quick retrieval if a new room is needed without having to
# create it. # create it.
self.db.unused_rooms = [] self.db.unused_rooms = []
def at_server_start(self): def at_server_start(self):
""" """
Called after the server is started or reloaded. Called after the server is started or reloaded.
@ -249,7 +249,6 @@ class WildernessScript(DefaultScript):
for coordinates, room in self.db.rooms.items(): for coordinates, room in self.db.rooms.items():
room.ndb.wildernessscript = self room.ndb.wildernessscript = self
room.ndb.active_coordinates = coordinates room.ndb.active_coordinates = coordinates
self.wilderness.mapprovider.at_prepare_room(coordinates, None, self)
for item in self.db.itemcoordinates.keys(): for item in self.db.itemcoordinates.keys():
# Items deleted while in the wilderness can leave None-type 'ghosts' # Items deleted while in the wilderness can leave None-type 'ghosts'
# These need to be cleaned up # These need to be cleaned up
@ -299,7 +298,11 @@ class WildernessScript(DefaultScript):
Returns: Returns:
[Object, ]: list of Objects at coordinates [Object, ]: list of Objects at coordinates
""" """
result = [ item for item, item_coords in self.itemcoordinates.items() if item_coords == coordinates and item is not None ] result = [
item
for item, item_coords in self.itemcoordinates.items()
if item_coords == coordinates and item is not None
]
return list(result) return list(result)
def move_obj(self, obj, new_coordinates): def move_obj(self, obj, new_coordinates):
@ -318,38 +321,56 @@ class WildernessScript(DefaultScript):
# appear in its old room should that room be deleted. # appear in its old room should that room be deleted.
obj.location = None obj.location = None
# By default, we'll assume we won't be making a new room and change this flag if necessary.
create_room = False
# See if we already have a room for that location # See if we already have a room for that location
if room := self.db.rooms.get(new_coordinates): if room := self.db.rooms.get(new_coordinates):
# There is. Try to destroy the old_room if it is not needed anymore # There is. Try to destroy the old_room if it is not needed anymore
self._destroy_room(old_room) self._destroy_room(old_room)
else: else:
# There is no room yet at new_location # There is no room yet at new_location
# Is the old room in this wilderness? # Is the old room in a wilderness?
if old_room in self.db.rooms.keys(): if hasattr(old_room, "wilderness"):
# Is there anything still left in the old_room, besides the exits? # Yes. Is it in THIS wilderness?
if len([ob for ob in old_room.contents if not inherits_from(ob, WildernessExit)]): if old_room.wilderness == self:
# There is, so we'll create a new room # Should we preserve rooms with any objects?
room = self._create_room(new_coordinates, obj) if self.preserve_items:
else: # Yes - check if ANY objects besides the exits are in old_room
# The room is empty, so we'll just reuse it if len(
room = old_room [
ob
for ob in old_room.contents
if not inherits_from(ob, WildernessExit)
]
):
# There is, so we'll create a new room
room = self._create_room(new_coordinates, obj)
else:
# The room is empty, so we'll reuse it
room = old_room
else:
# Only preserve rooms if there are players behind
if len([ob for ob in old_room.contents if ob.has_account]):
# There is still a player there; create a new room
room = self._create_room(new_coordinates, obj)
else:
# The room is empty of players, so we'll reuse it
room = old_room
# Is the previous room from a different wilderness? # It's in a different wilderness
elif inherits_from(old_room, WildernessRoom) and old_room.wilderness != self: else:
# It does, so we make sure to leave the other wilderness properly # It does, so we make sure to leave the other wilderness properly
old_room.wilderness.at_post_object_leave(obj) old_room.wilderness.at_post_object_leave(obj)
# We'll also need to create a new room in this wilderness # We'll also need to create a new room in this wilderness
room = self._create_room(new_coordinates, obj) room = self._create_room(new_coordinates, obj)
else: else:
# Obj comes from outside the wilderness entirely # Obj comes from outside the wilderness entirely
# We need to make a new room # We need to make a new room
room = self._create_room(new_coordinates, obj) room = self._create_room(new_coordinates, obj)
room.set_active_coordinates(new_coordinates, obj) # Set `room` to the new coordinates, however it was made
room.set_active_coordinates(new_coordinates, obj)
# Put obj back, now in the correct room
obj.location = room obj.location = room
obj.ndb.wilderness = self obj.ndb.wilderness = self
@ -407,7 +428,7 @@ class WildernessScript(DefaultScript):
""" """
Moves a room back to storage. If room is not a WildernessRoom or there Moves a room back to storage. If room is not a WildernessRoom or there
is something left inside the room, then this does nothing. is something left inside the room, then this does nothing.
Implementation note: If `preserve_items` is False (the default) then any Implementation note: If `preserve_items` is False (the default) then any
objects left in the rooms will be moved to None. You may want to implement objects left in the rooms will be moved to None. You may want to implement
your own cleanup or recycling routine for these objects. your own cleanup or recycling routine for these objects.
@ -555,6 +576,7 @@ class WildernessRoom(DefaultRoom):
rooms[self.coordinates] = self rooms[self.coordinates] = self
# Any object inside this room will get its location set to None # Any object inside this room will get its location set to None
# unless it's a wilderness exit
for item in self.contents: for item in self.contents:
if not item.destination or item.destination != item.location: if not item.destination or item.destination != item.location:
item.location = None item.location = None
@ -608,11 +630,11 @@ class WildernessRoom(DefaultRoom):
name += " {0}".format(self.coordinates) name += " {0}".format(self.coordinates)
return name return name
def get_display_desc(self, looker, **kwargs): def get_display_desc(self, looker, **kwargs):
""" """
Displays the description of the room. This is a core evennia hook. Displays the description of the room. This is a core evennia hook.
Allows the room's description to be customized in an ndb value, Allows the room's description to be customized in an ndb value,
avoiding having to write to the database on moving. avoiding having to write to the database on moving.
""" """
@ -624,6 +646,7 @@ class WildernessRoom(DefaultRoom):
# Otherwise, use the normal description hook. # Otherwise, use the normal description hook.
return super().get_display_desc(looker, **kwargs) return super().get_display_desc(looker, **kwargs)
class WildernessExit(DefaultExit): class WildernessExit(DefaultExit):
""" """
This is an Exit object used inside a WildernessRoom. Instead of changing This is an Exit object used inside a WildernessRoom. Instead of changing