Add mode stack to Player and mode check in dispatch
This commit is contained in:
parent
dcc8b961bb
commit
d220835f7d
3 changed files with 66 additions and 1 deletions
|
|
@ -60,5 +60,11 @@ async def dispatch(player: Player, raw_input: str) -> None:
|
||||||
await player.writer.drain()
|
await player.writer.drain()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Check mode restriction
|
||||||
|
if defn.mode != "*" and defn.mode != player.mode:
|
||||||
|
player.writer.write("You can't do that right now.\r\n")
|
||||||
|
await player.writer.drain()
|
||||||
|
return
|
||||||
|
|
||||||
# Execute the handler
|
# Execute the handler
|
||||||
await defn.handler(player, args)
|
await defn.handler(player, args)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
"""Player state and registry."""
|
"""Player state and registry."""
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, field
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14,6 +14,12 @@ class Player:
|
||||||
writer: Any # telnetlib3 TelnetWriter for sending output
|
writer: Any # telnetlib3 TelnetWriter for sending output
|
||||||
reader: Any # telnetlib3 TelnetReader for reading input
|
reader: Any # telnetlib3 TelnetReader for reading input
|
||||||
flying: bool = False
|
flying: bool = False
|
||||||
|
mode_stack: list[str] = field(default_factory=lambda: ["normal"])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mode(self) -> str:
|
||||||
|
"""Current mode is the top of the stack."""
|
||||||
|
return self.mode_stack[-1]
|
||||||
|
|
||||||
|
|
||||||
# Global registry of connected players
|
# Global registry of connected players
|
||||||
|
|
|
||||||
|
|
@ -318,3 +318,56 @@ async def test_effects_dont_override_player_marker(player, mock_world):
|
||||||
assert "@" in output
|
assert "@" in output
|
||||||
|
|
||||||
active_effects.clear()
|
active_effects.clear()
|
||||||
|
|
||||||
|
|
||||||
|
# Test mode stack
|
||||||
|
def test_mode_stack_default(player):
|
||||||
|
"""Player starts in normal mode."""
|
||||||
|
assert player.mode == "normal"
|
||||||
|
assert player.mode_stack == ["normal"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_dispatch_blocks_wrong_mode(player, mock_writer):
|
||||||
|
"""Commands with wrong mode get rejected."""
|
||||||
|
|
||||||
|
async def combat_handler(p, args):
|
||||||
|
pass
|
||||||
|
|
||||||
|
commands.register(CommandDefinition("strike", combat_handler, mode="combat"))
|
||||||
|
await commands.dispatch(player, "strike")
|
||||||
|
|
||||||
|
assert mock_writer.write.called
|
||||||
|
written = mock_writer.write.call_args[0][0]
|
||||||
|
assert "can't" in written.lower()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_dispatch_allows_wildcard_mode(player):
|
||||||
|
"""Commands with mode='*' work from any mode."""
|
||||||
|
called = False
|
||||||
|
|
||||||
|
async def any_handler(p, args):
|
||||||
|
nonlocal called
|
||||||
|
called = True
|
||||||
|
|
||||||
|
commands.register(CommandDefinition("universal", any_handler, mode="*"))
|
||||||
|
await commands.dispatch(player, "universal")
|
||||||
|
|
||||||
|
assert called
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_dispatch_allows_matching_mode(player):
|
||||||
|
"""Commands work when player mode matches command mode."""
|
||||||
|
called = False
|
||||||
|
|
||||||
|
async def combat_handler(p, args):
|
||||||
|
nonlocal called
|
||||||
|
called = True
|
||||||
|
|
||||||
|
commands.register(CommandDefinition("strike", combat_handler, mode="combat"))
|
||||||
|
player.mode_stack.append("combat")
|
||||||
|
await commands.dispatch(player, "strike")
|
||||||
|
|
||||||
|
assert called
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue