Ctrl K
ComunidadGuías…

src/webui/map_presets.py

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
"""Built-in visual presets for the location map.

Presets provide only a background and a default viewport. Locations still come
from the current Lorebook or a declarative map package, so existing saves do
not need a location-data migration.
"""

from __future__ import annotations

from typing import Any


_PRESETS = {
    "fantasy": {
        "asset_id": "fantasy-region-v1",
        "name": "奇幻地域图",
        "description": "适合中世纪、异世界与传统奇幻冒险的地域底图。",
    },
    "occult": {
        "asset_id": "occult-town-v1",
        "name": "调查城镇图",
        "description": "适合克苏鲁、现代悬疑与都市怪谈的调查城镇底图。",
    },
    "cyber": {
        "asset_id": "cyber-city-v1",
        "name": "赛博都市图",
        "description": "适合赛博朋克与近未来都市冒险的城市底图。",
    },
}

# Rules select one of three broad visual themes; they do not own individual
# map assets. ``tavern_free`` is deliberately omitted because its sandbox
# world may not be fantasy themed.
_RULE_THEMES = {
    "base_d20": "fantasy",
    "dnd5e": "fantasy",
    "freeform_fantasy": "fantasy",
    "freeform_wuxia": "fantasy",
    "freeform_coc": "occult",
    "freeform_cyberpunk": "cyber",
}

_WORLD_THEMES = {
    "default_fantasy": "fantasy",
    "zhongshi_fantasy": "fantasy",
    "jp_isekai": "fantasy",
    "tavern_generic": "fantasy",
    "coc_horror": "occult",
    "scifi_cyberpunk": "cyber",
}


def builtin_map_preset(world_id: str, rule_id: str = "") -> dict[str, Any] | None:
    """Return the read-only visual preset recommended for a world and rule."""
    theme = _RULE_THEMES.get(str(rule_id or "")) or _WORLD_THEMES.get(str(world_id or ""))
    return _preset_for_theme(theme or "")


def builtin_map_preset_by_asset(asset_id: str) -> dict[str, Any] | None:
    """Return one built-in preset by its stable asset ID."""
    theme = next(
        (key for key, value in _PRESETS.items() if value["asset_id"] == str(asset_id or "")),
        "",
    )
    return _preset_for_theme(theme)


def builtin_map_options() -> list[dict[str, str]]:
    """Return the three user-selectable built-in visual themes."""
    return [
        {
            "id": value["asset_id"],
            "name": value["name"],
            "description": value["description"],
            "url": f"/v2-assets/ui/maps/{value['asset_id']}.webp",
        }
        for value in _PRESETS.values()
    ]


def _preset_for_theme(theme: str) -> dict[str, Any] | None:
    preset = _PRESETS.get(theme)
    if not preset:
        return None

    asset_id = preset["asset_id"]
    return {
        "id": f"builtin:map:{asset_id}",
        "source_id": asset_id,
        "name": preset["name"],
        "description": preset["description"],
        "mode": "graph",
        "plugin_id": "",
        "plugin_name": "DiceFrame",
        "background": {
            "id": asset_id,
            "ref": f"builtin:scene:{asset_id}",
            "name": preset["name"],
            "url": f"/v2-assets/ui/maps/{asset_id}.webp",
        },
        "default_view": {"x": 0, "y": 0, "zoom": 1},
    }