Wire TOML help topics into help command
This commit is contained in:
parent
b69c2e83d9
commit
d7698ca830
3 changed files with 89 additions and 2 deletions
|
|
@ -4,11 +4,14 @@ from typing import TYPE_CHECKING, cast
|
||||||
|
|
||||||
from mudlib.commands import CommandDefinition, _registry, register, resolve_prefix
|
from mudlib.commands import CommandDefinition, _registry, register, resolve_prefix
|
||||||
from mudlib.commands.movement import DIRECTIONS
|
from mudlib.commands.movement import DIRECTIONS
|
||||||
|
from mudlib.content import HelpTopic
|
||||||
from mudlib.player import Player
|
from mudlib.player import Player
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from mudlib.combat.moves import CombatMove
|
from mudlib.combat.moves import CombatMove
|
||||||
|
|
||||||
|
_help_topics: dict[str, HelpTopic] = {}
|
||||||
|
|
||||||
|
|
||||||
async def _show_command_detail(player: Player, command_name: str) -> None:
|
async def _show_command_detail(player: Player, command_name: str) -> None:
|
||||||
"""Show detailed information about a specific command.
|
"""Show detailed information about a specific command.
|
||||||
|
|
@ -438,6 +441,15 @@ async def cmd_help(player: Player, args: str) -> None:
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Check TOML help topics first
|
||||||
|
topic = _help_topics.get(args)
|
||||||
|
if topic is not None:
|
||||||
|
if topic.admin and not player.is_admin:
|
||||||
|
await player.send(f"Unknown command: {args}\r\n")
|
||||||
|
return
|
||||||
|
await player.send(f"{topic.title}\r\n{topic.body}\r\n")
|
||||||
|
return
|
||||||
|
|
||||||
# Check if this is a help topic (hidden command)
|
# Check if this is a help topic (hidden command)
|
||||||
defn = _registry.get(args)
|
defn = _registry.get(args)
|
||||||
if defn is not None and defn.hidden:
|
if defn is not None and defn.hidden:
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,8 @@ import mudlib.commands.use
|
||||||
from mudlib.caps import parse_mtts
|
from mudlib.caps import parse_mtts
|
||||||
from mudlib.combat.commands import register_combat_commands
|
from mudlib.combat.commands import register_combat_commands
|
||||||
from mudlib.combat.engine import process_combat
|
from mudlib.combat.engine import process_combat
|
||||||
from mudlib.content import load_commands
|
from mudlib.commands.help import _help_topics
|
||||||
|
from mudlib.content import load_commands, load_help_topics
|
||||||
from mudlib.corpse import process_decomposing
|
from mudlib.corpse import process_decomposing
|
||||||
from mudlib.crafting import load_recipes, recipes
|
from mudlib.crafting import load_recipes, recipes
|
||||||
from mudlib.creation import character_creation
|
from mudlib.creation import character_creation
|
||||||
|
|
@ -598,6 +599,13 @@ async def run_server() -> None:
|
||||||
mudlib.commands.register(cmd_def)
|
mudlib.commands.register(cmd_def)
|
||||||
log.debug("registered content command: %s", cmd_def.name)
|
log.debug("registered content command: %s", cmd_def.name)
|
||||||
|
|
||||||
|
# Load help topics from content/help/
|
||||||
|
help_dir = pathlib.Path(__file__).resolve().parents[2] / "content" / "help"
|
||||||
|
if help_dir.exists():
|
||||||
|
loaded_topics = load_help_topics(help_dir)
|
||||||
|
_help_topics.update(loaded_topics)
|
||||||
|
log.info("loaded %d help topics from %s", len(loaded_topics), help_dir)
|
||||||
|
|
||||||
# Load combat moves and register as commands
|
# Load combat moves and register as commands
|
||||||
combat_dir = pathlib.Path(__file__).resolve().parents[2] / "content" / "combat"
|
combat_dir = pathlib.Path(__file__).resolve().parents[2] / "content" / "combat"
|
||||||
if combat_dir.exists():
|
if combat_dir.exists():
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
"""Tests for TOML help topic loading."""
|
"""Tests for TOML help topic loading."""
|
||||||
|
|
||||||
import textwrap
|
import textwrap
|
||||||
|
from unittest.mock import AsyncMock, MagicMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mudlib.content import load_help_topics
|
from mudlib import commands
|
||||||
|
from mudlib.commands import help as help_mod # noqa: F401
|
||||||
|
from mudlib.commands.help import _help_topics
|
||||||
|
from mudlib.content import HelpTopic, load_help_topics
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
@ -77,3 +81,66 @@ def test_load_help_topics_skips_bad_files(tmp_path):
|
||||||
topics = load_help_topics(tmp_path)
|
topics = load_help_topics(tmp_path)
|
||||||
assert "good" in topics
|
assert "good" in topics
|
||||||
assert "broken" not in topics
|
assert "broken" not in topics
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_writer():
|
||||||
|
writer = MagicMock()
|
||||||
|
writer.write = MagicMock()
|
||||||
|
writer.drain = AsyncMock()
|
||||||
|
return writer
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def player(mock_writer):
|
||||||
|
from mudlib.player import Player
|
||||||
|
|
||||||
|
return Player(name="Tester", x=0, y=0, reader=MagicMock(), writer=mock_writer)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def admin_player(mock_writer):
|
||||||
|
from mudlib.player import Player
|
||||||
|
|
||||||
|
p = Player(name="Admin", x=0, y=0, reader=MagicMock(), writer=mock_writer)
|
||||||
|
p.is_admin = True
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def _clear_topics():
|
||||||
|
_help_topics.clear()
|
||||||
|
yield
|
||||||
|
_help_topics.clear()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_help_shows_toml_topic(player):
|
||||||
|
_help_topics["combat"] = HelpTopic(
|
||||||
|
name="combat", body="fight stuff", title="combat primer"
|
||||||
|
)
|
||||||
|
await commands.dispatch(player, "help combat")
|
||||||
|
output = "".join(c[0][0] for c in player.writer.write.call_args_list)
|
||||||
|
assert "combat primer" in output
|
||||||
|
assert "fight stuff" in output
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_help_admin_topic_hidden_from_players(player):
|
||||||
|
_help_topics["secret"] = HelpTopic(
|
||||||
|
name="secret", body="hidden", title="secret stuff", admin=True
|
||||||
|
)
|
||||||
|
await commands.dispatch(player, "help secret")
|
||||||
|
output = "".join(c[0][0] for c in player.writer.write.call_args_list)
|
||||||
|
assert "hidden" not in output
|
||||||
|
assert "unknown" in output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_help_admin_topic_visible_to_admins(admin_player):
|
||||||
|
_help_topics["secret"] = HelpTopic(
|
||||||
|
name="secret", body="hidden", title="secret stuff", admin=True
|
||||||
|
)
|
||||||
|
await commands.dispatch(admin_player, "help secret")
|
||||||
|
output = "".join(c[0][0] for c in admin_player.writer.write.call_args_list)
|
||||||
|
assert "hidden" in output
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue