Статус: 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 = папка с твоими файлами данных + превью.
Поток
- Внутриигровой редактор отдаёт файл данных (AI-профиль = JSON через DTO/ES3-слой).
- «Опубликовать» →
CreateItem→ положить данные +preview.png→SubmitItemUpdate(title/description/теги/видимость) → Steam заливает. - Другой игрок браузит (in-game query или сайт Workshop) → подписывается.
- Steam качает в кэш → игра перебирает подписанные items, читает их папки, регистрирует контент по строковым ID.
API: ISteamUGC через Facepunch (Ugc.Editor для создания/загрузки, Ugc.Query для браузинга, GetItemInstallInfo для пути установленного item, отслеживание прогресса).
Подводные камни
- AppID + запущенный Steam. Полноценно тестировать на AppID 480 (Spacewar) нельзя — нужен свой AppID. (Гейт снят: AppID есть.)
- Только данные, не код (см. принцип) — критично для безопасности.
- UGC = враждебный ввод. Битый JSON, числа вне диапазона, ссылки на несуществующий ID. Валидировать и клампить на загрузке, падать мягко (пропустить кривой item, не крашиться).
- Зависимости / недостающий контент. Профиль ссылается на юнитов/реликвии по ID; у подписчика их может не быть. Нужна декларация зависимостей + мягкий фолбэк.
- 🔴 Версионирование схемы. Item из v1 должен грузиться (или деградировать) в v2 — иначе апдейт игры ломает чужой UGC. См. ниже.
- Превью и размер. Превью обязательно (PNG, ~1MB лимит); items держать лёгкими.
- Детерминизм. Кастом-битвы/реплеи опираются на seed + детерминированную симуляцию (несущая стена из 5).
- Лайв-апдейты items — докачка/инвалидация кэша при новой версии от создателя.
- Модерация/легал — теги, репорт-путь, Workshop-соглашение Valve.
Версионирование схемы (актуально и для сейвов)
В каждом файле данных (контент, профили, сейвы) — поле schemaVersion. При изменении формата — миграции (старая версия → новая). Это:
- защищает чужой Workshop-UGC от поломки при апдейтах игры;
- защищает сейвы игроков (2. Сохранения).
Без версионирования каждый апдейт ломает и сейвы, и UGC.
Что заложить СЕЙЧАС (дёшево; ретрофит дорого)
Хоть реализация Workshop — post-festival, это стоит ~0 сейчас:
schemaVersionв каждом файле данных + заготовка под миграции.- Строгая валидация на загрузке (клампы/скип невалидного) — нужна и для своего контента.
- Стабильные строковые ID + осознание зависимостей (уже в модели).
UI публикации/браузинга и ISteamUGC-интеграцию делаем, когда дойдём до Workshop по плану.
Открытые вопросы
- Переиспользовать AppID 3259720 или новый — сверить вишлисты + спросить Valve.
- Формат декларации зависимостей UGC-item (какой базовый/мод-контент требуется).
- Объём первого Workshop-релиза: только AI-профили, или сразу персонажи/битвы.