Mi2dRPGamEng/tests/test_db_roundtrip.py

147 lines
5.2 KiB
Python

import sqlite3
from pathlib import Path
import pytest
from engine.character import Ailment, BodyPart, Character, ClothingPiece
from engine.db import WorldRepository
from engine.defs import DefRegistry
from engine.entity import EntityPosition
from engine.inventory import Inventory
from engine.item import ItemInstance
from engine.map_loader import MapLoader
from engine.world import World
DEFS_DIR = Path(__file__).resolve().parent.parent / "resources" / "defs"
@pytest.fixture()
def registry():
return DefRegistry.load(DEFS_DIR)
def build_world(registry) -> World:
loader = MapLoader(DEFS_DIR / "maps")
demo_world = loader.load("demo_world.json")
ship = demo_world.embeddings[0].child_map
world = World(registry=registry)
world.add_map(demo_world)
world.add_map(ship)
player = Character(
entity_id="player-1",
name="Player",
def_id="player",
position=EntityPosition("demo_world", 7, 5, 0),
species_id="human",
gender="nonbinary",
body_type="thin",
hair_color="red",
blood_percentage=82.5,
body_parts=[
BodyPart("head", "human_head_hat"),
BodyPart("left_leg", "human_left_leg", integrity=40.0, ailments=[Ailment("frostbite", "Frostbite", 0.5)]),
],
default_body_parts=registry.new_default_body_parts("human"),
clothing=[ClothingPiece("torso", "leather_jacket")],
default_clothing=registry.new_default_clothing("player"),
mental_stats={"insanity": 12.5},
)
player.bio["stealth"] = 3
backpack_inventory = player.get_equipped_inventory("back", registry)
backpack_inventory.place(ItemInstance("rope-1", "sandwich"), registry.get_item_def("sandwich"), 0, 0)
player.inventory = Inventory(6, 5)
player.inventory.place(ItemInstance("staff-1", "staff_oak"), registry.get_item_def("staff_oak"), 0, 0)
player.inventory.place(ItemInstance("sandwich-1", "sandwich"), registry.get_item_def("sandwich"), 1, 0)
world.add_entity(player)
world.player = player
return world
def test_save_and_load_roundtrip_preserves_entity_and_inventory(registry):
world = build_world(registry)
repo = WorldRepository(sqlite3.connect(":memory:"))
repo.save_world(world)
loader = MapLoader(DEFS_DIR / "maps")
reloaded = repo.load_world(registry, loader)
assert reloaded is not None
assert reloaded.player is not None
assert reloaded.player.entity_id == "player-1"
assert (reloaded.player.position.map_id, reloaded.player.position.x, reloaded.player.position.y) == (
"demo_world",
7,
5,
)
assert isinstance(reloaded.player, Character)
assert reloaded.player.get_body_part("head").part_def_id == "human_head_hat"
assert reloaded.player.get_body_part("torso").part_def_id == "human_torso"
placed = {p.item.item_id: (p.x, p.y) for p in reloaded.player.inventory.items()}
assert placed == {"staff-1": (0, 0), "sandwich-1": (1, 0)}
def test_save_and_load_roundtrip_preserves_health_fields(registry):
world = build_world(registry)
repo = WorldRepository(sqlite3.connect(":memory:"))
repo.save_world(world)
loader = MapLoader(DEFS_DIR / "maps")
reloaded = repo.load_world(registry, loader)
player = reloaded.player
assert player.species_id == "human"
assert player.gender == "nonbinary"
assert player.body_type == "thin"
assert player.hair_color == "red"
assert player.blood_percentage == pytest.approx(82.5)
assert player.mental_stats == {"insanity": 12.5}
assert player.bio["stealth"] == 3
assert player.bio["athletics"] == 0
left_leg = player.get_body_part("left_leg")
assert left_leg.integrity == pytest.approx(40.0)
assert [a.id for a in left_leg.ailments] == ["frostbite"]
assert left_leg.ailments[0].severity == pytest.approx(0.5)
assert player.get_clothing("torso").item_def_id == "leather_jacket"
backpack = player.get_clothing("back")
assert backpack.item_def_id == "backpack_basic"
assert backpack.inventory is not None
assert (backpack.inventory.width, backpack.inventory.height) == (4, 4)
assert {p.item.item_id for p in backpack.inventory.items()} == {"rope-1"}
def test_load_world_returns_none_when_no_save_exists(registry):
repo = WorldRepository(sqlite3.connect(":memory:"))
loader = MapLoader(DEFS_DIR / "maps")
assert repo.load_world(registry, loader) is None
def test_runtime_tile_edits_survive_save_and_load(registry):
world = build_world(registry)
demo_world = world.maps["demo_world"]
# simulate base-building: knock a wall down on the ship, damage a flooring tile elsewhere
ship = world.maps["ship_small"]
ship.get_tile(0, 0, 0).room = None
demo_world.get_tile(3, 3, 0).flooring.integrity = 42.0
repo = WorldRepository(sqlite3.connect(":memory:"))
repo.save_world(world)
loader = MapLoader(DEFS_DIR / "maps")
reloaded = repo.load_world(registry, loader)
reloaded_ship = reloaded.maps["ship_small"]
assert reloaded_ship.get_tile(0, 0, 0).room is None
reloaded_demo = reloaded.maps["demo_world"]
edited_tile = reloaded_demo.get_tile(3, 3, 0)
assert edited_tile.flooring.def_id == "grass"
assert edited_tile.flooring.integrity == pytest.approx(42.0)