Статус: Draft


Пользовательский контент (UGC) через Steam Workshop: AI-профили, кастомные персонажи, кастомные битвы. Реализация — post-festival (после настройки AppID). Здесь — план, процессы, подводные камни и то, что нужно заложить уже сейчас, чтобы потом не переделывать.


AppID

Существует AppID 3259720 (от прошлой игры «Few Seconds - Many Deaths!»; пакет продаж 1155180, prerelease/скрыт). Открытый вопрос — переиспользовать его под Guildmaster или завести новый (решает наличие публичных вишлистов + позиция Valve; авторитетный ответ — Steam partner support). Для Steamworks SDK / Workshop нужен именно AppID, не номер пакета.


Принцип

Steam хостит UGC, сам качает подписанное в локальный кэш и обновляет. Игра только читает файлы из папки, которую дал Steam, и интерпретирует данные.

🔴 Контент — только ДАННЫЕ, никогда код. Никаких DLL/скриптов в item (дыра в безопасности). Игра интерпретирует данные, а не загружает сборки. Поэтому «AI-профиль = сериализуемые данные» (5, 6) — обязательное условие.

Вся контент-модель проекта (данные + строковые ID) уже заточена под Workshop: item = папка с твоими файлами данных + превью.


Поток

  1. Внутриигровой редактор отдаёт файл данных (AI-профиль = JSON через DTO/ES3-слой).
  2. «Опубликовать» → CreateItem → положить данные + preview.pngSubmitItemUpdate (title/description/теги/видимость) → Steam заливает.
  3. Другой игрок браузит (in-game query или сайт Workshop) → подписывается.
  4. Steam качает в кэш → игра перебирает подписанные items, читает их папки, регистрирует контент по строковым ID.

API: ISteamUGC через Facepunch (Ugc.Editor для создания/загрузки, Ugc.Query для браузинга, GetItemInstallInfo для пути установленного item, отслеживание прогресса).


Подводные камни

  1. AppID + запущенный Steam. Полноценно тестировать на AppID 480 (Spacewar) нельзя — нужен свой AppID. (Гейт снят: AppID есть.)
  2. Только данные, не код (см. принцип) — критично для безопасности.
  3. UGC = враждебный ввод. Битый JSON, числа вне диапазона, ссылки на несуществующий ID. Валидировать и клампить на загрузке, падать мягко (пропустить кривой item, не крашиться).
  4. Зависимости / недостающий контент. Профиль ссылается на юнитов/реликвии по ID; у подписчика их может не быть. Нужна декларация зависимостей + мягкий фолбэк.
  5. 🔴 Версионирование схемы. Item из v1 должен грузиться (или деградировать) в v2 — иначе апдейт игры ломает чужой UGC. См. ниже.
  6. Превью и размер. Превью обязательно (PNG, ~1MB лимит); items держать лёгкими.
  7. Детерминизм. Кастом-битвы/реплеи опираются на seed + детерминированную симуляцию (несущая стена из 5).
  8. Лайв-апдейты items — докачка/инвалидация кэша при новой версии от создателя.
  9. Модерация/легал — теги, репорт-путь, Workshop-соглашение Valve.

Версионирование схемы (актуально и для сейвов)

В каждом файле данных (контент, профили, сейвы) — поле schemaVersion. При изменении формата — миграции (старая версия → новая). Это:

  • защищает чужой Workshop-UGC от поломки при апдейтах игры;
  • защищает сейвы игроков (2. Сохранения).

Без версионирования каждый апдейт ломает и сейвы, и UGC.


Что заложить СЕЙЧАС (дёшево; ретрофит дорого)

Хоть реализация Workshop — post-festival, это стоит ~0 сейчас:

  • schemaVersion в каждом файле данных + заготовка под миграции.
  • Строгая валидация на загрузке (клампы/скип невалидного) — нужна и для своего контента.
  • Стабильные строковые ID + осознание зависимостей (уже в модели).

UI публикации/браузинга и ISteamUGC-интеграцию делаем, когда дойдём до Workshop по плану.


Открытые вопросы

  • Переиспользовать AppID 3259720 или новый — сверить вишлисты + спросить Valve.
  • Формат декларации зависимостей UGC-item (какой базовый/мод-контент требуется).
  • Объём первого Workshop-релиза: только AI-профили, или сразу персонажи/битвы.