From 889a0d7bcff92f2514b023edd21bdc33531fbf9b Mon Sep 17 00:00:00 2001 From: Jared Miller Date: Wed, 11 Feb 2026 22:13:56 -0500 Subject: [PATCH] Add paint mode for terrain editing --- src/mudlib/commands/movement.py | 8 +++-- src/mudlib/commands/paint.py | 58 +++++++++++++++++++++++++++++++++ src/mudlib/player.py | 3 ++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/mudlib/commands/paint.py diff --git a/src/mudlib/commands/movement.py b/src/mudlib/commands/movement.py index 0704f2a..dec0001 100644 --- a/src/mudlib/commands/movement.py +++ b/src/mudlib/commands/movement.py @@ -68,11 +68,15 @@ async def move_player(player: Player, dx: int, dy: int, direction_name: str) -> assert isinstance(zone, Zone), "Player must be in a zone to move" target_x, target_y = zone.wrap(player.x + dx, player.y + dy) - # Check if the target is passable - if not zone.is_passable(target_x, target_y): + # Check if the target is passable (skip check in paint mode) + if not player.paint_mode and not zone.is_passable(target_x, target_y): await player.send("You can't go that way.\r\n") return + # If painting, place the brush tile at the current position before moving + if player.paint_mode and player.painting: + zone.terrain[player.y][player.x] = player.paint_brush + # Send departure message to players in the old area opposite = OPPOSITE_DIRECTIONS[direction_name] await send_nearby_message( diff --git a/src/mudlib/commands/paint.py b/src/mudlib/commands/paint.py new file mode 100644 index 0000000..bf0230e --- /dev/null +++ b/src/mudlib/commands/paint.py @@ -0,0 +1,58 @@ +"""Paint mode commands for terrain editing.""" + +from mudlib.commands import CommandDefinition, register +from mudlib.player import Player + + +async def cmd_paint(player: Player, args: str) -> None: + """Toggle paint mode on/off. + + Paint mode allows admin to edit terrain tile-by-tile. + """ + if player.paint_mode: + # Exit paint mode + player.paint_mode = False + player.painting = False + await player.send("Paint mode off.\r\n") + else: + # Enter paint mode + player.paint_mode = True + player.painting = False + await player.send( + "Paint mode on. Use 'p' to toggle painting, " + "type a character to set brush.\r\n" + ) + + +async def cmd_toggle_painting(player: Player, args: str) -> None: + """Toggle between survey and painting states within paint mode.""" + if not player.paint_mode: + await player.send("You must be in paint mode to do that.\r\n") + return + + player.painting = not player.painting + if player.painting: + await player.send(f"Painting with '{player.paint_brush}'.\r\n") + else: + await player.send("Survey mode.\r\n") + + +async def cmd_set_brush(player: Player, args: str) -> None: + """Set the brush character for painting.""" + if not player.paint_mode: + await player.send("You must be in paint mode to do that.\r\n") + return + + char = args.strip() + if len(char) != 1: + await player.send("Brush must be a single character.\r\n") + return + + player.paint_brush = char + await player.send(f"Brush set to '{char}'.\r\n") + + +# Register paint mode commands +register(CommandDefinition("@paint", cmd_paint)) +register(CommandDefinition("p", cmd_toggle_painting)) +register(CommandDefinition("brush", cmd_set_brush)) diff --git a/src/mudlib/player.py b/src/mudlib/player.py index 814d48a..a97cc8c 100644 --- a/src/mudlib/player.py +++ b/src/mudlib/player.py @@ -25,6 +25,9 @@ class Player(Entity): caps: ClientCaps = field(default_factory=lambda: ClientCaps(ansi=True)) editor: Editor | None = None if_session: IFSession | EmbeddedIFSession | None = None + paint_mode: bool = False + painting: bool = False + paint_brush: str = "." @property def mode(self) -> str: