- Update _find_container to use targeting module (prefix + ordinal) - Update cmd_put to use find_in_inventory directly - Add 'get all from <container>' support with portable item filtering - Add comprehensive tests for all container grammar features
134 lines
3.9 KiB
Python
134 lines
3.9 KiB
Python
"""Open and close commands for containers."""
|
|
|
|
from mudlib.commands import CommandDefinition, register
|
|
from mudlib.container import Container
|
|
from mudlib.player import Player
|
|
from mudlib.targeting import find_in_inventory, find_thing_on_tile
|
|
from mudlib.thing import Thing
|
|
from mudlib.zone import Zone
|
|
|
|
|
|
def _find_container(name: str, player: Player) -> Container | Thing | None:
|
|
"""Find a thing by name in inventory first, then on ground.
|
|
|
|
Uses targeting module for prefix matching and ordinal support.
|
|
Returns Thing if found (caller must check if it's a Container).
|
|
Returns None if not found.
|
|
"""
|
|
# Check inventory first
|
|
result = find_in_inventory(name, player)
|
|
if result is not None:
|
|
return result
|
|
|
|
# Check ground at player's position
|
|
zone = player.location
|
|
if zone is None or not isinstance(zone, Zone):
|
|
return None
|
|
|
|
return find_thing_on_tile(name, zone, player.x, player.y)
|
|
|
|
|
|
async def cmd_open(player: Player, args: str) -> None:
|
|
"""Open a container."""
|
|
if not args.strip():
|
|
await player.send("Open what?\r\n")
|
|
return
|
|
|
|
thing = _find_container(args.strip(), player)
|
|
if thing is None:
|
|
await player.send("You don't see that here.\r\n")
|
|
return
|
|
|
|
if not isinstance(thing, Container):
|
|
await player.send("You can't open that.\r\n")
|
|
return
|
|
|
|
if not thing.closed:
|
|
await player.send("It's already open.\r\n")
|
|
return
|
|
|
|
if thing.locked:
|
|
await player.send("It's locked.\r\n")
|
|
return
|
|
|
|
thing.closed = False
|
|
await player.send(f"You open the {thing.name}.\r\n")
|
|
|
|
|
|
async def cmd_close(player: Player, args: str) -> None:
|
|
"""Close a container."""
|
|
if not args.strip():
|
|
await player.send("Close what?\r\n")
|
|
return
|
|
|
|
thing = _find_container(args.strip(), player)
|
|
if thing is None:
|
|
await player.send("You don't see that here.\r\n")
|
|
return
|
|
|
|
if not isinstance(thing, Container):
|
|
await player.send("You can't close that.\r\n")
|
|
return
|
|
|
|
if thing.closed:
|
|
await player.send("It's already closed.\r\n")
|
|
return
|
|
|
|
thing.closed = True
|
|
await player.send(f"You close the {thing.name}.\r\n")
|
|
|
|
|
|
async def cmd_put(player: Player, args: str) -> None:
|
|
"""Put an item into a container."""
|
|
if not args.strip() or " in " not in args:
|
|
await player.send("Put what where? (put <item> in <container>)\r\n")
|
|
return
|
|
|
|
# Parse "thing in container"
|
|
parts = args.strip().split(" in ", 1)
|
|
if len(parts) != 2:
|
|
await player.send("Put what where? (put <item> in <container>)\r\n")
|
|
return
|
|
|
|
thing_name = parts[0].strip()
|
|
container_name = parts[1].strip()
|
|
|
|
if not thing_name or not container_name:
|
|
await player.send("Put what where? (put <item> in <container>)\r\n")
|
|
return
|
|
|
|
# Find thing in player's inventory
|
|
thing = find_in_inventory(thing_name, player)
|
|
if thing is None:
|
|
await player.send("You're not carrying that.\r\n")
|
|
return
|
|
|
|
# Find container (on ground or in inventory)
|
|
container_obj = _find_container(container_name, player)
|
|
if container_obj is None:
|
|
await player.send("You don't see that here.\r\n")
|
|
return
|
|
|
|
if not isinstance(container_obj, Container):
|
|
await player.send("That's not a container.\r\n")
|
|
return
|
|
|
|
if thing is container_obj:
|
|
await player.send("You can't put something inside itself.\r\n")
|
|
return
|
|
|
|
if container_obj.closed:
|
|
await player.send(f"The {container_obj.name} is closed.\r\n")
|
|
return
|
|
|
|
if not container_obj.can_accept(thing):
|
|
await player.send(f"The {container_obj.name} is full.\r\n")
|
|
return
|
|
|
|
thing.move_to(container_obj)
|
|
await player.send(f"You put the {thing.name} in the {container_obj.name}.\r\n")
|
|
|
|
|
|
register(CommandDefinition("open", cmd_open))
|
|
register(CommandDefinition("close", cmd_close))
|
|
register(CommandDefinition("put", cmd_put))
|