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.store import account_exists, load_player_data, set_admin
|
||||||
from mudlib.things import spawn_thing, thing_templates
|
from mudlib.things import spawn_thing, thing_templates
|
||||||
from mudlib.zone import Zone
|
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 directory, set during server startup
|
||||||
_content_dir: Path | None = None
|
_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")
|
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("@goto", cmd_goto, admin=True, help="Teleport to a zone"))
|
||||||
register(CommandDefinition("@dig", cmd_dig, admin=True, help="Create a new zone"))
|
register(CommandDefinition("@dig", cmd_dig, admin=True, help="Create a new zone"))
|
||||||
register(CommandDefinition("@save", cmd_save, admin=True, help="Save current zone"))
|
register(CommandDefinition("@save", cmd_save, admin=True, help="Save current zone"))
|
||||||
|
|
@ -190,3 +208,4 @@ register(
|
||||||
register(
|
register(
|
||||||
CommandDefinition("@demote", cmd_demote, admin=True, help="Revoke admin status")
|
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()
|
mock_writer.write.assert_called()
|
||||||
written = mock_writer.write.call_args_list[-1][0][0]
|
written = mock_writer.write.call_args_list[-1][0][0]
|
||||||
assert "permission" in written.lower()
|
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