Плагины, которые могут исчезнуть бесследно — разделение manifest/definition/core/ui
Как мы спроектировали систему плагинов, где ни одна часть кода не знает ни одного плагина по имени — и почему это важно.
Tinker Dice в основе своей — игровой движок, который ничего не знает об играх. Он знает плагины. И вся система построена так, чтобы он никогда, ни при каких обстоятельствах не знал, какие плагины существуют.
Это не случайность. Это ограничение, которое мы ввели рано: ни в одном месте проекта — ни в движке, ни на сервере, ни в редакторе — не должно быть упоминания какого-либо конкретного плагина. Ни if (pluginId === 'cards'), ни захардкоженных импортов, ни особых случаев. Каждый плагин живёт в своей папке под shared/plugins/{pluginId}/, самодостаточный и заменяемый.
Каждый плагин — это четыре файла:
core.ts— рантайм-логика. Хэндлеры, исполняемые на сервере. Это мир движка.definition.ts— спецификация для AI. Параметры, типы, ноды редактора. Так AI знает, что плагин умеет.manifest.ts— документация для AI. Описания, возможности, примеры. Так AI рассказывает о плагине.ui-widget.tsx— React-компоненты для отображения данных плагина в UI. Это мир игрока.
Разделение на четыре файла соответствует четырём разным аудиториям: движок, AI-дизайнер, база знаний AI и человек-игрок. Каждый файл принадлежит своей зоне ответственности, и ни один не просачивается в другие.
Плата за это — жёсткая простота остальной кодовой базы. Движок загружает плагины по конвенции, а не по имени. Можно удалить папку плагина, переименовать его или заменить — и ничего больше не сломается. Редактор не знает про карты, ходы или голосования. Он знает про плагины — в общем виде.
Это тот вид ограничений, который кажется избыточным до того момента, когда нужно удалить или отрефакторить плагин. А тогда он кажется предусмотрительностью.