"""Builder commands for world editing.""" from pathlib import Path from mudlib.commands import CommandDefinition, register from mudlib.export import export_zone_to_file from mudlib.player import Player from mudlib.things import spawn_thing, thing_templates from mudlib.zone import Zone from mudlib.zones import get_zone, register_zone # Content directory, set during server startup _content_dir: Path | None = None def set_content_dir(path: Path) -> None: """Set the content directory for saving zones.""" global _content_dir _content_dir = path async def cmd_goto(player: Player, args: str) -> None: """Teleport to a named zone's spawn point.""" zone_name = args.strip() if not zone_name: await player.send("Usage: @goto \r\n") return target = get_zone(zone_name) if target is None: await player.send(f"Zone '{zone_name}' not found.\r\n") return player.move_to(target, x=target.spawn_x, y=target.spawn_y) await player.send(f"Teleported to {zone_name}.\r\n") from mudlib.commands.look import cmd_look await cmd_look(player, "") async def cmd_dig(player: Player, args: str) -> None: """Create a new blank zone and teleport there.""" parts = args.strip().split() if len(parts) != 3: await player.send("Usage: @dig \r\n") return name = parts[0] try: width = int(parts[1]) height = int(parts[2]) except ValueError: await player.send("Width and height must be numbers.\r\n") return if width < 1 or height < 1: await player.send("Zone dimensions must be at least 1x1.\r\n") return if get_zone(name) is not None: await player.send(f"Zone '{name}' already exists.\r\n") return terrain = [["." for _ in range(width)] for _ in range(height)] zone = Zone( name=name, width=width, height=height, terrain=terrain, toroidal=False, ) register_zone(name, zone) player.move_to(zone, x=0, y=0) await player.send(f"Created zone '{name}' ({width}x{height}).\r\n") from mudlib.commands.look import cmd_look await cmd_look(player, "") async def cmd_save(player: Player, args: str) -> None: """Save the current zone to its TOML file.""" zone = player.location if not isinstance(zone, Zone): await player.send("You're not in a zone.\r\n") return if _content_dir is None: await player.send("Content directory not configured.\r\n") return zones_dir = _content_dir / "zones" zones_dir.mkdir(parents=True, exist_ok=True) path = zones_dir / f"{zone.name}.toml" export_zone_to_file(zone, path) await player.send(f"Zone '{zone.name}' saved to {path.name}.\r\n") async def cmd_place(player: Player, args: str) -> None: """Place a thing from templates at the player's position.""" thing_name = args.strip() if not thing_name: await player.send("Usage: @place \r\n") return template = thing_templates.get(thing_name) if template is None: await player.send(f"Thing template '{thing_name}' not found.\r\n") return spawn_thing(template, player.location, x=player.x, y=player.y) await player.send(f"Placed {thing_name} at ({player.x}, {player.y}).\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")) register(CommandDefinition("@place", cmd_place, admin=True, help="Place a thing"))