Add @zones command to list registered zones
This commit is contained in:
parent
7f6eda4be7
commit
938dd613d4
2 changed files with 149 additions and 1 deletions
|
|
@ -8,7 +8,7 @@ from mudlib.player import Player, players
|
|||
from mudlib.store import account_exists, load_player_data, set_admin
|
||||
from mudlib.things import spawn_thing, thing_templates
|
||||
from mudlib.zone import Zone
|
||||
from mudlib.zones import get_zone, register_zone
|
||||
from mudlib.zones import get_zone, register_zone, zone_registry
|
||||
|
||||
# Content directory, set during server startup
|
||||
_content_dir: Path | None = None
|
||||
|
|
@ -180,6 +180,24 @@ async def cmd_demote(player: Player, args: str) -> None:
|
|||
await player.send(f"{target_name} is no longer an admin.\r\n")
|
||||
|
||||
|
||||
async def cmd_zones(player: Player, args: str) -> None:
|
||||
"""List all registered zones."""
|
||||
if not zone_registry:
|
||||
await player.send("No zones registered.\r\n")
|
||||
return
|
||||
|
||||
await player.send("zones:\r\n")
|
||||
current_zone_name = (
|
||||
player.location.name if isinstance(player.location, Zone) else None
|
||||
)
|
||||
|
||||
for name in sorted(zone_registry.keys()):
|
||||
zone = zone_registry[name]
|
||||
dimensions = f"{zone.width}x{zone.height}"
|
||||
marker = " [here]" if name == current_zone_name else ""
|
||||
await player.send(f" {name:<15} {dimensions:>6}{marker}\r\n")
|
||||
|
||||
|
||||
register(CommandDefinition("@goto", cmd_goto, admin=True, help="Teleport to a zone"))
|
||||
register(CommandDefinition("@dig", cmd_dig, admin=True, help="Create a new zone"))
|
||||
register(CommandDefinition("@save", cmd_save, admin=True, help="Save current zone"))
|
||||
|
|
@ -190,3 +208,4 @@ register(
|
|||
register(
|
||||
CommandDefinition("@demote", cmd_demote, admin=True, help="Revoke admin status")
|
||||
)
|
||||
register(CommandDefinition("@zones", cmd_zones, admin=True, help="List all zones"))
|
||||
|
|
|
|||
|
|
@ -325,3 +325,132 @@ async def test_builder_commands_require_admin(zone, mock_writer, mock_reader):
|
|||
mock_writer.write.assert_called()
|
||||
written = mock_writer.write.call_args_list[-1][0][0]
|
||||
assert "permission" in written.lower()
|
||||
|
||||
|
||||
# --- @zones ---
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_zones_lists_registered_zones(player):
|
||||
"""@zones lists all registered zones."""
|
||||
from mudlib.commands.build import cmd_zones
|
||||
|
||||
# Register additional zones
|
||||
forest = Zone(
|
||||
name="forest",
|
||||
width=15,
|
||||
height=12,
|
||||
terrain=[["." for _ in range(15)] for _ in range(12)],
|
||||
)
|
||||
register_zone("forest", forest)
|
||||
|
||||
tavern = Zone(
|
||||
name="tavern",
|
||||
width=8,
|
||||
height=6,
|
||||
terrain=[["." for _ in range(8)] for _ in range(6)],
|
||||
)
|
||||
register_zone("tavern", tavern)
|
||||
|
||||
await cmd_zones(player, "")
|
||||
|
||||
# Check all zones are listed
|
||||
all_output = "".join(call[0][0] for call in player.writer.write.call_args_list)
|
||||
assert "hub" in all_output
|
||||
assert "forest" in all_output
|
||||
assert "tavern" in all_output
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_zones_shows_dimensions(player):
|
||||
"""@zones shows width x height for each zone."""
|
||||
from mudlib.commands.build import cmd_zones
|
||||
|
||||
forest = Zone(
|
||||
name="forest",
|
||||
width=20,
|
||||
height=15,
|
||||
terrain=[["." for _ in range(20)] for _ in range(15)],
|
||||
)
|
||||
register_zone("forest", forest)
|
||||
|
||||
await cmd_zones(player, "")
|
||||
|
||||
all_output = "".join(call[0][0] for call in player.writer.write.call_args_list)
|
||||
assert "10x10" in all_output # hub from fixture
|
||||
assert "20x15" in all_output # forest
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_zones_highlights_current_zone(player):
|
||||
"""@zones marks the player's current zone."""
|
||||
from mudlib.commands.build import cmd_zones
|
||||
|
||||
forest = Zone(
|
||||
name="forest",
|
||||
width=15,
|
||||
height=12,
|
||||
terrain=[["." for _ in range(15)] for _ in range(12)],
|
||||
)
|
||||
register_zone("forest", forest)
|
||||
|
||||
await cmd_zones(player, "")
|
||||
|
||||
all_output = "".join(call[0][0] for call in player.writer.write.call_args_list)
|
||||
# hub should be marked as current (player is in hub via fixture)
|
||||
assert "[here]" in all_output
|
||||
# [here] should be on the same line as hub
|
||||
hub_line_idx = all_output.find("hub")
|
||||
here_idx = all_output.find("[here]")
|
||||
assert hub_line_idx < here_idx < hub_line_idx + 50
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_zones_empty_registry(zone, mock_writer, mock_reader):
|
||||
"""@zones with no zones shows appropriate message."""
|
||||
from mudlib.commands.build import cmd_zones
|
||||
|
||||
# Create player not in a zone fixture
|
||||
zone_registry.clear()
|
||||
temp_zone = Zone(
|
||||
name="temp",
|
||||
width=5,
|
||||
height=5,
|
||||
terrain=[["." for _ in range(5)] for _ in range(5)],
|
||||
)
|
||||
p = Player(
|
||||
name="builder",
|
||||
x=0,
|
||||
y=0,
|
||||
writer=mock_writer,
|
||||
reader=mock_reader,
|
||||
location=temp_zone,
|
||||
is_admin=True,
|
||||
)
|
||||
|
||||
await cmd_zones(p, "")
|
||||
|
||||
mock_writer.write.assert_called()
|
||||
written = mock_writer.write.call_args_list[0][0][0]
|
||||
assert "no zones" in written.lower()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_zones_requires_admin(zone, mock_writer, mock_reader):
|
||||
"""Non-admin players cannot use @zones."""
|
||||
from mudlib.commands import dispatch
|
||||
|
||||
non_admin = Player(
|
||||
name="player",
|
||||
x=5,
|
||||
y=5,
|
||||
writer=mock_writer,
|
||||
reader=mock_reader,
|
||||
location=zone,
|
||||
is_admin=False,
|
||||
)
|
||||
|
||||
await dispatch(non_admin, "@zones")
|
||||
mock_writer.write.assert_called()
|
||||
written = mock_writer.write.call_args_list[-1][0][0]
|
||||
assert "permission" in written.lower()
|
||||
|
|
|
|||
Loading…
Reference in a new issue