Перейти к содержанию

Game Plugin SDK

Назначение

Единый контракт для добавления игр из шоу без изменения session/realtime слоя.

Интерфейс плагина

from abc import ABC, abstractmethod
from typing import Any
from pydantic import BaseModel

class ValidationResult(BaseModel):
    ok: bool
    error_code: str | None = None
    message: str | None = None

class WebViewModel(BaseModel):
    board: list[list[Any]]
    highlights: list[tuple[int, int]]
    dice: tuple[int, int] | None
    phase: str
    current_player_name: str
    actions_available: list[str]

class TelegramViewModel(BaseModel):
    caption: str
    image_url: str | None
    buttons: list[list[dict]]  # inline keyboard rows

class GamePlugin(ABC):
    plugin_id: str
    display_name: str
    min_players: int
    max_players: int
    version: str

    @abstractmethod
    def initial_state(self, player_ids: list[str], config: dict) -> dict: ...

    @abstractmethod
    def validate_action(
        self, state: dict, action_type: str, payload: dict, player_id: str
    ) -> ValidationResult: ...

    @abstractmethod
    def apply_action(
        self, state: dict, action_type: str, payload: dict, player_id: str
    ) -> dict: ...

    @abstractmethod
    def get_current_player(self, state: dict) -> str | None: ...

    @abstractmethod
    def is_finished(self, state: dict) -> bool: ...

    @abstractmethod
    def get_winner(self, state: dict) -> str | None: ...

    @abstractmethod
    def render_web(self, state: dict) -> WebViewModel: ...

    @abstractmethod
    def render_telegram(self, state: dict) -> TelegramViewModel: ...

    def allowed_actions(self, state: dict, player_id: str) -> list[str]:
        """Опционально: список action_type для UI."""
        return []

Регистрация плагина

# plugins/registry.py
PLUGINS: dict[str, GamePlugin] = {
    "dice_board": DiceBoardPlugin(),
}

Фазы игры (общий паттерн)

Phase Описание
setup Расстановка, выбор параметров
playing Основной цикл
finished Победитель определён

Action contract

Поле Тип Обязательно
action_id UUID да
action_type string да
payload object зависит от типа
player_id UUID из auth context

dice_board actions

action_type payload phase
roll_dice {} RollDice
choose_cell {row, col} AwaitCellChoice
pass {} TBD edge cases

Тестирование плагина

  1. Unitvalidate_action, apply_action, is_finished
  2. Property — инварианты поля после каждого хода
  3. Gherkin — acceptance через game-runtime API

Tutorial: добавить новую игру

  1. Создать plugins/my_game/plugin.py implements GamePlugin
  2. Добавить в PLUGINS registry
  3. Описать game-spec.md в docs/05-games/my-game/
  4. Добавить Gherkin в acceptance-tests.md
  5. UI assets для media-service renderer
  6. Зарегистрировать в catalog-roadmap.md

Связанные документы