Публичный сервер и его расширение
Что уже есть для публичного сервера Bullet Hero в открытом SDK и что ещё не решено: протокол, API, инструменты модерации
Кода сервера и протокола пока нет. Ниже - часть SDK, на которой будет работать сервер, и она уже работает. Адресов, формата сообщений и API самого сервера здесь нет, их не существует
SDK работает на сервере
SDK - открытая модель данных игры: модели, сериализация в JSON и в бинарный формат, правила валидации, генераторы.
Те же исходники, что компилирует Unity, собираются как обычная библиотека netstandard2.1 без движка. На неё может ссылаться сервер или утилита:
dotnet build -c Release BH.SDK.csproj
dotnet pack -c Release BH.SDK.csproj
Пакет называется BulletHero.SDK. Код - в github.com/bullet-hero/sdk, под MIT
Версия SDK обычно совпадает с версией игры и пока не обещает стабильности API. Подробнее - Версии и миграции
Клиент и сервер запускают одни и те же проверки над одними и теми же моделями. Уровень, который редактор считает готовым, готов и для сервера. Второго набора правил, который надо держать в согласии, нет
ValidateForPublish
Один вызов отвечает на вопрос "можно ли опубликовать этот уровень здесь":
ValidationFacade.ValidateForPublish(meta, profile, level, now, payload)
Он выполняет три прохода сразу:
- декларативные правила над уровнем и его метаданными
- проверки графа уровня
- собственные условия сервиса из его
PublishProfile
Сам уровень передавать не обязательно. metadata.json - отдельный файл, чтобы каталог мог оценить тысячи уровней, не открывая ни одного. Этот дешёвый проход покрывает большую часть политики
Но двум проверкам нужен level.json: ресурсу без записи вообще и способу получения ресурсов. Чистый отчёт только по метаданным значит "в прочитанном ошибок нет". IsReady остаётся false, пока файл уровня не проверен
payload несёт измеренные размеры: каждого ресурса, level.json, metadata.json, всего уровня. Без него ограничения профиля по размеру не проверить
Во время проверки ничего не исправляется, и это намеренно. Тихая правка контента на выходе - последнее, что нужно сервису. Подробнее - Валидация
Три вердикта
| Группа | Значение | Что делает сервер |
|---|---|---|
Error | сервис отказывает | отклоняет загрузку (HasErrors) |
Warning | публиковать можно, но нужен взгляд человека | ставит уровень в очередь модерации (NeedsManualReview) |
Advice | отмечено | ничего |
Клиент блокирует загрузку по тем же ошибкам ещё до её начала. Уровень, который ваш сервер отклонит, редко до него доберётся
Свой PublishProfile
Политика сервиса - это файл, сериализованная модель SDK. Более строгий или более мягкий сервер - это другой файл, а не форк кода
Уровень, который остаётся на устройстве игрока, не проверяется никак. Профиль важен только в момент, когда уровень предлагают сервису. Как автору подготовить уровень к этому моменту - Готовность к публикации
Пресеты:
| Пресет | Ключ | Для чего |
|---|---|---|
CreateOpen() | local | уровни на устройстве, ничего не требуется |
CreateStandard() | standard | публичный сервер, политика из Лицензионная политика для пользовательских уровней |
CreateStrict() | strict | сборки из магазинов, без прямых ссылок, хэш у каждого ресурса |
Основные поля:
| Поле | Что решает |
|---|---|
AllowedLicenses | какие типовые лицензии принимаются, пустой список принимает все |
AllowedUriTypes | как можно получать ресурсы, пустой список разрешает все способы |
AllowUnknownLicense | может ли ресурс ничего не сообщать о своих условиях |
AllowPermissionInstead | может ли разрешение правообладателя заменить отклонённую лицензию (всегда отправляется на проверку) |
RequireResourceMeta, RequireResourceUrl, RequireAttribution | что должна содержать запись каждого ресурса |
RequireAgeRating, RequireLevelAuthors, RequireHashes | что должен объявить уровень |
MaxResourceBytes, MaxDataFileBytes, MaxTotalBytes | ограничения по размеру, ноль значит без ограничения |
Sources, UnknownSourceTrust | список доверенных сайтов и то, как оценивается сайт вне списка |
Два публичных пресета:
standard | strict | |
|---|---|---|
| Прямые ссылки на ресурсы | разрешены | запрещены |
| Указание автора у каждого ресурса | не требуется | требуется |
| Хэш содержимого в каждой записи | не требуется | требуется |
| Самый большой ресурс | 64 МБ | 32 МБ |
Самый большой level.json или metadata.json | 32 МБ | 16 МБ |
| Самый большой уровень | 256 МБ | 128 МБ |
| Сайт вне списка | RequiresLicenseCheck | RequiresResourceCheck |
Все пресеты и поля - Профили публикации
Почему в standard нет GPL
Лицензий семейства GPL в standard нет намеренно. GPL-работа, распространяемая через App Store, конфликтует с условиями Apple. Каталог, который их допускал, потом нельзя было бы отдать на iOS
Список доверенных сайтов, который поставляется с SDK, - только отправная точка. Сайты меняют свои условия, поэтому каждый владелец сервера должен переопределить его в своём профиле. Ничто не может рассчитывать, что конкретный сайт в списке есть
Модерация
Что официальный сервер планирует добавить поверх проверки. Публичному серверу это, скорее всего, тоже понадобится:
- Очередь модерации. Её наполняют находки
Warning - Жалобы и блокировка уровней и пользователей. Правила Google Play и App Store требуют и то и другое для любого контента, который видят другие люди
- Удаление по хэшу. Запись ресурса может хранить хэши содержимого его файлов в виде
sha256:<hex>. Жалоба называет работу, и с хэшами каждый уровень с ней находится поиском, а не угадыванием по названиям. Редактор записывает хэш при импорте ресурса - Условия использования. Они покрывают то, чего не покрывает лицензия: заявление автора, что права у него есть, право владельца сервера удалить уровень, право показывать его название и обложку в списках
Steam Workshop устроен иначе. Файлы хранит Valve. Разработчики могут только проверить их после публикации и решить, что игра загружает
Форматы архивов
Уровень - это папка файлов, а архив делает её переносимой. Что SDK читает и пишет:
| Формат | Чтение | Запись | Примечание |
|---|---|---|---|
.tar.gz | да | да | по умолчанию |
.zip | да | да | можно зашифровать по записям AES-256 |
.tar.gz.gpg, .zip.gpg | да | да | сообщение OpenPGP под паролем, единственная защита, доступная .tar.gz |
level.json.gpg | да | да | один защищённый файл уровня |
.7z | нет | нет | распознаётся, чтобы отказать с понятным названием |
Формат определяется по первым байтам файла, а не по расширению. Имя - единственная часть файла, которую может поменять кто угодно
tar -xzf, gpg -d и любой zip-архиватор открывают все записываемые форматы. Для распаковки уровня игра не нужна. Подробнее - Архивы и защита
Что не решено
- протокол между игрой и сервером и будет ли он один для OWS и NOWS
- API сервера: загрузка, каталог, поиск, аккаунты
- как указать игре общественный сервер
- как расширяется сам сервер и на каком языке
- совместная игра на сервере: транспорт, авторитет, синхронизация уровня и лобби
Для совместной игры продумано только одно: как аватар игрока появляется и исчезает по сетевому сообщению
Публикация уровней в любой сервис появится не раньше обновления после gv 1.0.0. Данные, на которые опирается проверка, должны попасть в уровни до того, как их опубликуют
Лицензия уровней и любой сервер
По умолчанию уровень распространяется под CC BY-NC, и автор может выбрать другую лицензию в метаданных уровня. Разрешение делиться уровнем идёт от его автора напрямую к каждому получателю. Поэтому ни один сервер, официальный или общественный, не может размещать уровень под CC BY-NC коммерчески
Сервер с другим кодом под другой лицензией ничего не меняет в правах на контент. Полные правила для авторов - Лицензионная политика для пользовательских уровней