Упаковка и выпуск
Точная текущая grammar, совместимость target/platform, pack tokens, payloads и command-line arguments находятся в сгенерированном package interface. Перед тем как называть полученный artifact поддерживаемым, сверяйтесь с Матрицей поддержки.
Решение о пакете
Для каждого объявленного application variant соберите точную target, выполните
ForceBakeResources для его release configuration, затем вызовите
сгенерированную цель MakePackage и проверьте изолированный artifact. Текущие
output-producing packs: Raw, Zip, SingleZip, Tar, TarGz, Root,
Wix и Apk; допустимые packs всё равно зависят от target и platform.
Реализованный payload или pack является capability, а не support claim.
Встраивающий проект владеет своей package
matrix, release policy, signing credentials, distribution, acceptance, rollout
и rollback. Возможность упаковки Engine не доказывает эти проектные решения.
В частности, Apk копирует выбранный signed или debug APK; pack token не
доказывает release signing. Описывайте проверенную capability и её evidence, а
не гарантию Engine для каждого host или project.
Не утверждайте, что output packs можно комбинировать с любым target/platform:
используйте только реализованную совместимую строку generated matrix.
Debug+Apk выбирает Gradle assembleDebug, development artifact которого
подписан Gradle debug key; это debug-signed, а не unsigned и не production
release-signed artifact.
Текущие допустимые targets: Server, Client, Mapper, Baker,
AnimationViewer и ParticleViewer. Упаковка payload реализована для
Windows, Linux, Android и Web; macOS и iOS являются принимаемыми
parser dimensions, package implementations которых имеют статус unsupported.
Реализованные payloads: native PE с companion files, native ELF с companion
files, Android Gradle client project с ABI libraries и assets, а также browser
JavaScript/Wasm client с preloaded resources.
Называйте artifact, создаваемый выбранным совместимым output pack: Raw
сохраняет staged directory; Zip создаёт ZIP; SingleZip дополняет один
package-wide ZIP; Tar создаёт tar archive; TarGz создаёт gzip-compressed tar
archive; Root объединяет staged directory с package output root; Wix
создаёт MSI; Apk копирует выбранный signed или debug APK. Это проверенные
packager capabilities, а не универсальные гарантии Engine или evidence релиза
проекта.
Знайте, что доказывает Engine
Engine предоставляет переиспользуемую package grammar, staging и patching бинарных файлов, встроенные resources/configs, архивы, генерацию MSI/APK и проверочные fixtures. Эти механизмы доказывают только конкретные пути, которые запущены на конкретной ревизии.
Игровой проект остаётся владельцем:
- фактического release matrix и поддерживаемых host/target combinations;
- product identity, versioning, channels и publication destinations;
- signing credentials, trust policy, timestamping и verification;
- installer/store metadata, deployment, rollout и rollback;
- device/browser/renderer/audio/input/network acceptance;
- database migration, backup/restore и operational readiness;
- лицензий, attribution и происхождения добавленных assets/dependencies.
Не называйте package production-ready только потому, что package.py создал
файл. Build capability, packager capability, project qualification и
publication — разные уровни evidence.
Подготовьте принадлежащую релизу package matrix
До написания DefinePackage запишите для каждой release candidate:
- package ID и selected sub-config;
- target, platform, architecture и все binary variants;
- host, compiler/toolchain и workspace image;
- обязательные pack tokens и ожидаемые artifacts;
- signing identity и источник secret без значений secret;
- acceptance job, устройство/browser/service environment;
- updater, network, save/database и rollback compatibility;
- владельца publication и recovery decision.
Один package ID должен объединять только те entries, чьи compiled inputs
доступны в одном FO_OUTPUT_PATH и проходят общий процесс владения. Разделяйте
IDs, когда различаются build hosts, credentials, acceptance lanes или
publication destinations.
Объявите packages
Вызывайте DefinePackage(...) после регистрации project sources и до
BuildPackages(). Используйте отдельные package IDs, если различаются build
hosts, credentials, acceptance lanes или publication destinations.
DefinePackage(ReleaseWindows
CONFIG PublicRelease
BINARY Client Windows win64 Raw+Zip+Wix
BINARY Server Windows win64 Headless+Service+Raw+Zip)
DefinePackage(ReleaseLinux
CONFIG PublicRelease
BINARY Server Linux x64 Headless+Daemon+Raw+TarGz)
DefinePackage(ReleaseWeb
CONFIG PublicRelease
BINARY Client Web wasm Raw+Zip+WebServer)
DefinePackage(ReleaseAndroidArm64
CONFIG PublicRelease
BINARY Client Android arm64 Raw+Apk)
Это пример grammar, а не заявление о поддержке и не универсальная production matrix. Удалите каждую строку, которую игра не собирает и не квалифицирует.
Каждая clause BINARY имеет форму:
BINARY <target> <platform> <architecture> <pack+tokens> [POSTFIX <variant>]
CONFIG выбирает baked sub-config. Для resource-bearing client и server
packages baking должен создать Baking/Configs/<config>.fomain-client или
...-server через baker Config. Package target не создаёт незаметно
отсутствующие application binaries или baked resources.
Используйте POSTFIX, когда отдельно собранный binary variant имеет
FO_BINARY_OUTPUT_POSTFIX. Значение declaration должно совпадать с build
output. Это согласует выбор package input, packaged runtime identity и имена
server-staged updater payload. Не используйте package name как неявный
variant selector.
Используйте INCLUDE <source-glob> <target-path> только для проверенных
распространяемых файлов, уже находящихся под build output. Packager отклоняет
escaping paths и обновляет package root и существующий SingleZip. License
notices, attribution и approval third-party payload остаются обязанностями
проекта.
Соберите, запеките, затем упакуйте
Выполняйте стадии явно и останавливайтесь после первой ошибки:
- Начните с чистого рекурсивно инициализированного game checkout на release revision и проверьте точный Engine SHA.
- Подготовьте host закреплённой workspace command Engine и preset или CI image встраивающего проекта.
- Сконфигурируйте проект с release-owned cache values. Не переиспользуйте необъяснённый developer cache.
- Соберите каждый application variant из package declaration.
- Выполните forced bake release resources и configs, если candidate не должен зависеть от incremental state.
- Вызывайте
MakePackage-<package-id>только после появления binary и baking inputs. - Сохраните полный package log и отклоняйте assertions, warnings-as-errors, signing failures, missing symbols, configs или resource packs.
Конкретные target names выбирает проект. Типичная multi-config sequence:
cmake --preset release-host
cmake --build Build/release-host --config Release --target <application-targets>
cmake --build Build/release-host --config Release --target ForceBakeResources
cmake --build Build/release-host --config Release --target MakePackage-ReleaseWindows
Не запускайте несколько platform entries из одного package ID, если их
compiled inputs недоступны в одном FO_OUTPUT_PATH. Отдельные IDs упрощают
владение cross-build и диагностику failures.
Packager изменяет зарезервированные data regions после linking. Он встраивает resources и выбранный baked config, записывает packaged build name и может изменять PE PDB paths. Он не генерирует и не исполняет код в этих regions. Если настроена подпись, она выполняется после patching и до создания archives или installers.
Каждая подстановка embedded data или конфигурации находит первый подходящий marker,
проверяет размер payload и границы зарезервированного поля, затем записывает только
это поле на месте. Длина бинарника и окружающие байты не меняются; отсутствие marker,
слишком большой payload или обрезанное поле вызывают отказ до изменения этого поля.
Это проверка отдельного поля, а не атомарная транзакция всех package patches.
Поле packaged name записывается отдельно в фиксированном размере с NUL padding.
BuildTools/tests/test_package_internal_config.py проверяет совместный результат
трёх подстановок, variant config, выбор первого marker и неизменность файла при
невалидном поле.
Запустите packaging fixture Engine
Examples/PackagingMatrix — исполняемая Engine-owned база для нативных package
mechanics. Она намеренно отделена от читаемых starter и multiplayer tutorials,
поскольку ConfigBaker требует инициализации каждого server/client runtime
setting. Checked-in FOnlinePackagingMatrix.fomain детерминированно генерируется
из Source/Common/Settings.inc; generate_config.py --check завершается
ошибкой при расхождении settings и fixture.
Эта fixture и Examples/MinimalMultiplayer получают значения по умолчанию из
текущих объявлений SETTING(...). После изменения схемы настроек пересоздайте
конфигурации обоих примеров, затем проверьте их актуальность.
В отдельном checkout Examples/PackagingMatrix с инициализированным submodule
Engine сконфигурируйте host build и соберите принадлежащую fixture цель
RunPackagingChecks. Эта цель не зарегистрирована как обязательный lane
Engine BuildTools validate.
cmake --build <packaging-matrix-build-dir> --config Release --target RunPackagingChecks
Каждый маршрут собирает client, headless client, server, headless server,
host service/daemon role и baker; принудительно запекает resources и
server/client configs PackageSmoke; создаёт raw payloads и ZIP или TAR.GZ;
сравнивает archive members со staged payloads; запускает packaged headless
client против packaged server через реальный updater handshake. Оба процесса
должны увидеть Common.Packaged, использовать embedded fixture setting,
вывести success markers и завершиться с code zero.
Verifier записывает FOPKG-PackageSmoke/packaging-manifest.json с точной
ревизией Engine, hashes и sizes архивов, полной инвентаризацией payload, наличием
roles и runtime results. Сохраняйте manifest и archives в release lane
подключающего проекта, когда это evidence обязательно; текущий Engine workflow
их не публикует.
Fixture даёт необязательное evidence для Engine package path Windows x64 или Ubuntu/Linux x64 на host, где он был запущен. Он не квалифицирует package declaration другой игры, signing, installer, store, deployment host, database, renderer или rollback. Перенесите evidence pattern в release lane встраивающего проекта и храните конкретную acceptance там.
Приёмка package публичного multiplayer-примера
Examples/MinimalMultiplayer применяет тот же pattern к читаемым игровым
исходникам. Его package Tutorial принудительно запекает automated gameplay
configuration и создаёт нативные raw и ZIP/tar.gz client/server payloads.
Собственный verifier примера проверяет parity archive/payload, записывает
SHA-256 каждого archive и payload file и запускает взаимодействие packaged
headless server/client с картой и предметом через общий gameplay process
runner.
Checked-in .fomain генерируется из текущих defaults Settings.inc и
проверенных tutorial overrides/sections. CheckTutorialConfig выполняется до
baking, поэтому новый или изменённый saved setting обнаруживает stale source,
а не проявляется позднее как неполный packaged config.
Presets windows-package и linux-package в Examples/MinimalMultiplayer
по запросу собирают принадлежащую fixture цель RunTutorialPackageChecks.
Сохраняйте archives, package manifest и runtime report в workflow проекта,
когда они обязательны; текущий Engine workflow эти presets не запускает.
Эти evidence уже, чем product release: archives являются
unsigned, headless и audio-disabled fixtures без installer, store, public
deployment, durable backend, upgrade или rollback claim.
Windows x64 lane прошла локально на Engine fac978a67: два archives совпали с
raw payloads, inventories client из 28 файлов и server из 37 файлов были
захэшированы, packaged interaction scenario прошёл. Это только local host
evidence. Для Linux support и immutable example-release evidence необходимы
зелёная landed job и проверенный внешний repository commit/tag.
Выберите artifacts по платформе
Windows client
Rawсохраняет staged portable directory.Zipсоздаёт portable archive из этой directory.Wixсоздаёт per-user MSI. На Windows подготовьте закреплённый Engine portable toolset WiX v3 командойbuildtools.py prepare-workspace wix;package.pyищетFO_WIX_ROOT, соседний workspacewix3, затемcandle/lightвPATH. Выбранный каталог передаётся вcreatemsi.py --wix-dir; прямой вызов принимает тот же параметр, включая путь с пробелами как один аргумент. Без него инструменты берутся изPATH.lightсначала запускает ICE validation и повторяется один раз с-svalтолько при недоступности Windows Installer service; любая другая ошибка linker/ICE и failed fallback остаются фатальными. На POSIX packaging host требуетсяwixlверсии 0.102 или новее.OGLдобавляет отдельно собранный OpenGL runtime variant.Libвыбирает library form там, где target её поддерживает.POSTFIXне даёт независимо собранным variants, например depot-specific client, конфликтовать.
Сгенерированный MSI использует InstallScope="perUser". Компоненты shortcuts
Start Menu и Desktop получают отдельные key paths в HKCU, регистрация PATH
остаётся per-user (System="no"), а сгенерированные directory components
удаляются при uninstall. Поэтому одно описание installer собирается закреплённым
WiX на Windows или wixl на Linux без machine-wide registration. MSI не
доказывает, что client подписан, доверен endpoint protection, совместим при
upgrade или принят distribution channel. Проверяйте эти свойства на финальном
emitted artifact.
В диалогах выбора каталога установки и просмотра папок push button стоит
перед text и path controls. WiX и wixl строят tab loop по порядку controls
по-разному; если loop не включает Control_First, msiexec прекращает
установку ещё до первого экрана с internal error 2834. Generated XML
проверяется на замкнутый tab loop по правилам обоих linkers. При wixl
path controls остаются доступны мышью и через просмотр папок, хотя не входят
в его tab loop. Реальный installer проверяйте на каждом поддерживаемом host.
Диалог выбора каталога должен выполняться после CostFinalize, когда Windows Installer уже вычислил путь INSTALLDIR. Иначе wixl может поставить диалог, ограниченный только Before="ProgressDlg", перед costing из-за изменчивого порядка обхода зависимостей; msiexec тогда прерывает установку с internal error 2343 из-за пустого пути. Генератор закрепляет диалог After="CostFinalize" для WiX и wixl. Руководство MSI creator и регрессионные тесты описывают проверку порядка у обоих компоновщиков. Успешная линковка MSI не заменяет видимую проверку установки на поддерживаемом host.
Linux client или server
- Доступны output forms
Raw,Zip,TarиTarGz. Headlessдобавляет headless variant к обычной target.Daemonдобавляет Linux daemon server variant.TotalProfilingиOnDemandProfilingдобавляют отдельно скомпилированные profiling variants там, где они допустимы.
Packager назначает target executables логический mode 0755 независимо от
packaging host и записывает эти modes в metadata ZIP и TAR. Для Raw или Root
output также создаётся package-root handoff .lf-package-modes.json: versioned
map нормализованных POSIX-relative payload paths в единственные допустимые
логические modes 0644 и 0755. Publisher, копирующий или переупаковывающий raw
trees, обязан проверить и применить handoff, затем исключить его из публичного
payload; unsafe, escaping, drive-qualified paths и paths с backslash
отклоняются. Квалифицируйте фактический Linux distribution, runtime libraries,
filesystem paths, process account, signals, logs и service manager игры.
Payload Managed C#
При включённом FO_MANAGED_SCRIPTING baker Managed помещает target-specific assemblies и подготовленный payload class libraries ManagedRuntime/ в выбранный resource pack. Native client packages используют payload ровно своего application target; Web и Android несут его в assets ресурсов. Server package для client updates размещает один target-specific pack в PlatformBinaries/<target>/, а -expect-client-runtime Platform:arch[:postfix] превращает отсутствие запрошенного payload в ошибку packaging. Если несколько native variants разделяют этот updater target, pack поставляет наименее квалифицированная подходящая binary entry — обычно default Release; эквивалентные независимо собранные CoreLib payloads не обязаны быть byte-identical. Проверяйте отдельно target assembly, runtime.manifest, content hash и запуск packaged artifact; см. Скрипты Managed C#.
Web client
Payload Web client содержит JavaScript, patched Wasm, HTML shell, preloaded
Resources.data / Resources.js, target-specific Managed assemblies/runtime resources при включённом backend и optional helper WebServer. Принадлежащий
Engine-команда Content Showcase python validate.py --web-runtime может дать
необязательное evidence для baking на native-хосте,
точный состав raw/ZIP package, localhost HTTP delivery, подключение к native-серверу,
обязательные lifecycle-маркеры, настоящий контекст WebGL 2 и пиксели композитора
для одного детерминированного fixture Content Showcase в закреплённом Chromium.
Она не входит в обязательный Engine workflow и не доказывает публичный browser
deployment подключающей игры.
Для local staging следуйте сборке, упаковке и отладке в браузере. Release lane должна дополнительно проверить HTTPS hosting, MIME types, cache policy, cross-origin isolation или другие обязательные headers, WebSocket reachability, browser compatibility, storage persistence, audio activation, UX ошибки loading и хотя бы одну видимую representative scene.
Android client
Android payload является сгенерированным Gradle project с одной libmain.so
на выбранную ABI и baked resources в application assets; Managed build хранит там же target assemblies и подготовленный runtime. Apk запускает
Gradle assembly и копирует полученный APK рядом со staged project.
Закреплённые SDK/NDK workspace, ABI mapping, device connection, resource staging и configuration fields описаны в сборке, упаковке и отладке на Android. Android ARM32 и ARM64 имеют build gate; Android x86 остаётся source-capable. Игра владеет emulator/device gates, GPU/input/audio/network/background behavior, signing identity, versioning, store policy и rollout.
APK без release keystore settings использует development key Gradle и не является production release artifact.
macOS и iOS
Сейчас package.py прерывает работу и для macOS, и для iOS. Не добавляйте
для них строки DefinePackage. Support matrix проверяет build inputs client в
более узкой области, но встраивающий проект должен предоставить и сопровождать
application-bundle assembly, resources, entitlements, provisioning, signing,
notarization где применимо, device/simulator checks, store metadata и delivery.
Пока этот путь не станет существующим и повторяемым, описывайте Apple targets
как build-gated inputs, а не packaged или release-supported products.
Варианты client runtime
Client package копирует выбранные пары host/runtime явно. Generic companion
library pass исключает обычные и headless input/alias имена Engine client на
Windows и Linux, потому что все эти файлы могут одновременно находиться в одной
build-output directory. Поэтому обычный package не наследует оставшийся
headless runtime только из-за другой build job; token Headless по-прежнему
добавляет headless host/runtime под packaged names. Перед signing/publication
проверяйте Raw и archive inventories одновременно на наличие требуемой пары и
отсутствие незапрошенных sibling names.
Server, service и daemon
Server package включает server resources и client update resource packs. При наличии совместимых client runtime libraries он также staging-ит platform runtime payloads для updater. Перед публикацией server с самообновляющимися clients прочитайте Client Runtime Split and Updater.
Service и Daemon — binary variants, а не deployment systems. Игра должна
версионировать и проверять:
- process arguments и environment;
- least-privilege account и filesystem permissions;
- service-manager definition и restart limits;
- network exposure и TLS termination;
- database schema, credentials, migration, backup и restore;
- logs, metrics, crash reports, health checks и alerting;
- graceful drain/shutdown и rollback к совместимому binary/config/data set.
Храните эти product и infrastructure details во встраивающем проекте. эксплуатация релиза предоставляет переиспользуемый runbook process, readiness, rollout, shutdown и rollback, не объявляя инфраструктуру собственностью Engine.
Воспроизводимость и происхождение
Native host build создаёт необязательную библиотеку FOnlineResourcePackHash
под Binaries/BuildTools-<host>-<arch>/ одного из input roots. Упаковщик ищет её
в порядке inputs; -resource-pack-hash-library <path> выбирает явный путь.
Без найденной библиотеки используется Python. Найденная, но незагружаемая library
или неверный known-vector/streaming-seed check — ошибка, а не fallback.
На Windows загрузка временно включает SEM_FAILCRITICALERRORS у вызывающего
потока, сохраняя остальные флаги и восстанавливая прежний режим при успехе и при
ошибке. Повреждённая DLL вызывает OSError без интерактивного окна загрузчика;
режим ошибок процесса не меняется. Ошибка установки или восстановления режима
потока тоже считается ошибкой.
Каждый packager, включая spawned workers, отдельно загружает backend. Оба используют
одинаковый streaming FNV-1a 64 и сохраняют header, physical, decoded-payload и logical
content validation, включая cache hits. Байты архива, compression settings и cache
keys не зависят от ускорителя. Это host tooling, не игровой payload.
test_resource_pack_hash.py собирает настоящую library, сравнивает Python/native
и serial/parallel Raw results и отклоняет повреждённые payloads.
Корректная и повреждённая библиотеки загружаются в дочерних процессах с ограниченным
таймаутом; на Windows также проверяются восстановление флагов потока и неизменность
режима ошибок процесса.
Архивы ресурсов по умолчанию создаются последовательно. package.py -resource-pack-jobs N переопределяет FO_RESOURCE_PACK_JOBS (по умолчанию 1); допустимы только положительные целые. Независимые .fores создаются не более чем в N процессах с spawn на любом host. Задачи с общим именем pack или физическим destination выполняются по порядку в одном worker, сохраняя локальное повторное использование и исключая конкурентную запись. Группы распределяются по объёму source bytes, начиная с самых крупных. Каждый worker использует полный writer, cache protocol и payload validation; недоступность optional cache сохраняется внутри batch, ограничивая неудачные probes числом workers. Parent принимает проверенные archive identities и дожидается workers до переписывания runtime-specific packs или очистки неудавшегося package. Embedded resources и конечные distribution bundles не входят в эту worker lane. Выбирайте лимит по доступным CPU и памяти; это не изменение формата и не гарантия измеренного ускорения.
FOnline записывает каждый не-Embedded resource pack как детерминированную базу .fores из отсортированных нормализованных путей, не сохраняя timestamps. Формат пакетов ресурсов определяет заголовок версии 2, физический и логический хеши, полный каталог, необязательный writable-патч и проверки целостности. Baking.ResourcePackCompressLevel и Baking.ResourcePackMinCompressGain управляют сжатием отдельных ресурсов; Baking.BundleCompressLevel — внешними пакетами и ZIP Embedded. Для одного запуска package.py принимает -resource-pack-compress-level и -bundle-compress-level. Он проверяет декодированную длину и хеш каждого payload до завершения упаковки. Embedded ZIP сохраняет фиксированные timestamps/permissions и проходит CRC-проверку до встраивания в бинарный файл. Внешние ZIP и TAR packages используют
логические file modes target, а не modes filesystem host, поэтому Windows
packaging host также создаёт исполняемые Linux targets. Raw package parts
объединяют mode records в один package-root handoff .lf-package-modes.json, не
теряя предыдущие parts. Это gates создания package, а не доказательство
того, что installer, delivery channel, publication step или installed filesystem
сохранили результат. Parser package declarations и сгенерированный contract
детерминированы и проверяются в CI.
FO_RESOURCE_ARCHIVE_CACHE_HELPER может указывать на принадлежащий проекту
Python helper с интерфейсом `restore|store|release –key