Add container support to thing template loader
Extended ThingTemplate with optional container fields (capacity, closed, locked). When a template includes capacity, spawn_thing now creates a Container instead of a regular Thing. Added two example container templates: - chest.toml: non-portable, capacity 5, starts closed - sack.toml: portable, capacity 3, starts open
This commit is contained in:
parent
3be4370b2f
commit
68161fd025
4 changed files with 186 additions and 0 deletions
7
content/things/chest.toml
Normal file
7
content/things/chest.toml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
name = "chest"
|
||||
description = "a sturdy wooden chest with iron bindings"
|
||||
portable = false
|
||||
capacity = 5
|
||||
closed = true
|
||||
locked = false
|
||||
aliases = ["box"]
|
||||
7
content/things/sack.toml
Normal file
7
content/things/sack.toml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
name = "sack"
|
||||
description = "a rough cloth sack with drawstring closure"
|
||||
portable = true
|
||||
capacity = 3
|
||||
closed = false
|
||||
locked = false
|
||||
aliases = ["bag"]
|
||||
|
|
@ -4,6 +4,7 @@ import tomllib
|
|||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
|
||||
from mudlib.container import Container
|
||||
from mudlib.object import Object
|
||||
from mudlib.thing import Thing
|
||||
|
||||
|
|
@ -16,6 +17,10 @@ class ThingTemplate:
|
|||
description: str
|
||||
portable: bool = True
|
||||
aliases: list[str] = field(default_factory=list)
|
||||
# Container fields (presence of capacity indicates a container template)
|
||||
capacity: int | None = None
|
||||
closed: bool = False
|
||||
locked: bool = False
|
||||
|
||||
|
||||
# Module-level registry
|
||||
|
|
@ -31,6 +36,9 @@ def load_thing_template(path: Path) -> ThingTemplate:
|
|||
description=data["description"],
|
||||
portable=data.get("portable", True),
|
||||
aliases=data.get("aliases", []),
|
||||
capacity=data.get("capacity"),
|
||||
closed=data.get("closed", False),
|
||||
locked=data.get("locked", False),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -51,6 +59,21 @@ def spawn_thing(
|
|||
y: int | None = None,
|
||||
) -> Thing:
|
||||
"""Create a Thing instance from a template at the given location."""
|
||||
# If template has capacity, spawn a Container instead of a Thing
|
||||
if template.capacity is not None:
|
||||
return Container(
|
||||
name=template.name,
|
||||
description=template.description,
|
||||
portable=template.portable,
|
||||
aliases=list(template.aliases),
|
||||
capacity=template.capacity,
|
||||
closed=template.closed,
|
||||
locked=template.locked,
|
||||
location=location,
|
||||
x=x,
|
||||
y=y,
|
||||
)
|
||||
|
||||
return Thing(
|
||||
name=template.name,
|
||||
description=template.description,
|
||||
|
|
|
|||
149
tests/test_container_templates.py
Normal file
149
tests/test_container_templates.py
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
"""Tests for container template loading and spawning."""
|
||||
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from mudlib.container import Container
|
||||
from mudlib.thing import Thing
|
||||
from mudlib.things import load_thing_template, spawn_thing
|
||||
from mudlib.zone import Zone
|
||||
|
||||
|
||||
def test_load_container_template_with_capacity():
|
||||
"""load_thing_template recognizes container templates (has capacity field)."""
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
toml_path = Path(tmpdir) / "chest.toml"
|
||||
toml_path.write_text(
|
||||
"""
|
||||
name = "chest"
|
||||
description = "a wooden chest"
|
||||
capacity = 5
|
||||
"""
|
||||
)
|
||||
template = load_thing_template(toml_path)
|
||||
assert template.name == "chest"
|
||||
assert template.description == "a wooden chest"
|
||||
assert hasattr(template, "capacity")
|
||||
assert template.capacity == 5
|
||||
|
||||
|
||||
def test_load_container_template_with_closed():
|
||||
"""load_thing_template handles closed field."""
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
toml_path = Path(tmpdir) / "chest.toml"
|
||||
toml_path.write_text(
|
||||
"""
|
||||
name = "chest"
|
||||
description = "a wooden chest"
|
||||
capacity = 5
|
||||
closed = true
|
||||
"""
|
||||
)
|
||||
template = load_thing_template(toml_path)
|
||||
assert template.closed is True
|
||||
|
||||
|
||||
def test_load_container_template_with_locked():
|
||||
"""load_thing_template handles locked field."""
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
toml_path = Path(tmpdir) / "chest.toml"
|
||||
toml_path.write_text(
|
||||
"""
|
||||
name = "chest"
|
||||
description = "a wooden chest"
|
||||
capacity = 5
|
||||
closed = true
|
||||
locked = true
|
||||
"""
|
||||
)
|
||||
template = load_thing_template(toml_path)
|
||||
assert template.locked is True
|
||||
|
||||
|
||||
def test_load_container_template_defaults():
|
||||
"""Container template fields have sensible defaults."""
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
toml_path = Path(tmpdir) / "sack.toml"
|
||||
toml_path.write_text(
|
||||
"""
|
||||
name = "sack"
|
||||
description = "a cloth sack"
|
||||
capacity = 3
|
||||
"""
|
||||
)
|
||||
template = load_thing_template(toml_path)
|
||||
assert template.capacity == 3
|
||||
assert template.closed is False # default: open
|
||||
assert template.locked is False # default: unlocked
|
||||
|
||||
|
||||
def test_spawn_container_from_template():
|
||||
"""spawn_thing creates a Container when template has capacity."""
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
toml_path = Path(tmpdir) / "chest.toml"
|
||||
toml_path.write_text(
|
||||
"""
|
||||
name = "chest"
|
||||
description = "a wooden chest"
|
||||
capacity = 5
|
||||
closed = true
|
||||
"""
|
||||
)
|
||||
template = load_thing_template(toml_path)
|
||||
terrain = [["." for _ in range(10)] for _ in range(10)]
|
||||
zone = Zone(name="test", width=10, height=10, terrain=terrain)
|
||||
|
||||
thing = spawn_thing(template, zone, x=5, y=5)
|
||||
|
||||
assert isinstance(thing, Container)
|
||||
assert thing.name == "chest"
|
||||
assert thing.description == "a wooden chest"
|
||||
assert thing.capacity == 5
|
||||
assert thing.closed is True
|
||||
assert thing.location is zone
|
||||
|
||||
|
||||
def test_spawn_regular_thing_from_template_without_capacity():
|
||||
"""spawn_thing creates a regular Thing when template lacks capacity."""
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
toml_path = Path(tmpdir) / "rock.toml"
|
||||
toml_path.write_text(
|
||||
"""
|
||||
name = "rock"
|
||||
description = "a smooth grey rock"
|
||||
portable = true
|
||||
"""
|
||||
)
|
||||
template = load_thing_template(toml_path)
|
||||
terrain = [["." for _ in range(10)] for _ in range(10)]
|
||||
zone = Zone(name="test", width=10, height=10, terrain=terrain)
|
||||
|
||||
thing = spawn_thing(template, zone, x=5, y=5)
|
||||
|
||||
assert isinstance(thing, Thing)
|
||||
assert not isinstance(thing, Container)
|
||||
assert thing.name == "rock"
|
||||
assert thing.portable is True
|
||||
|
||||
|
||||
def test_spawn_portable_container():
|
||||
"""spawn_thing creates a portable Container (like a sack)."""
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
toml_path = Path(tmpdir) / "sack.toml"
|
||||
toml_path.write_text(
|
||||
"""
|
||||
name = "sack"
|
||||
description = "a cloth sack"
|
||||
capacity = 3
|
||||
portable = true
|
||||
"""
|
||||
)
|
||||
template = load_thing_template(toml_path)
|
||||
terrain = [["." for _ in range(10)] for _ in range(10)]
|
||||
zone = Zone(name="test", width=10, height=10, terrain=terrain)
|
||||
|
||||
thing = spawn_thing(template, zone, x=5, y=5)
|
||||
|
||||
assert isinstance(thing, Container)
|
||||
assert thing.portable is True
|
||||
assert thing.capacity == 3
|
||||
Loading…
Reference in a new issue