Files
shacraft-core/docs/CONTENT.md
T

15 KiB

Каталог, формы и единые пакеты MVP

Встроенный каталог фактически извлечён из Minecraft Java 26.2, DataVersion = 4903: 1 196 блоков, 32 366 состояний, 158 типов сущностей. Проверка сравнивает полные множества состояний, числовые ID источника, состояния по умолчанию, свойства и типы сущностей с отдельной проекцией официальных отчётов. Дополнительно зарегистрирован собственный shacraft:trampoline: всего 1 197 блоков и 32 367 состояний.

Числовой minecraft_id — только идентификатор источника. Сервер отдельно регистрирует канонические строки в WorldStore; внутренний BlockId зависит от истории конкретного хранилища. Нельзя использовать minecraft_id в операциях редактирования мира. Для собственного состояния значение minecraft_id = u32::MAX означает отсутствие ID Minecraft.

Происхождение и воспроизведение

Источник: официальный server.jar Java 26.2. SHA-1 823e2250d24b3ddac457a60c92a6a941943fcd6a, размер 60 894 273 байта. Полные SHA-256, версия Java, команды и контрольные суммы отчётов находятся в crates/shacraft-content/data/provenance.json.

Генератор проверяет закреплённые размер и SHA-1 перед использованием JAR:

python3 scripts/catalog_generate.py --java /path/to/java25/bin/java
python3 scripts/catalog_assets.py
cargo test -p shacraft-content
cargo run -p shacraft-content --example catalog_report

Нужен установленный JDK 25 или новее, включая javac. Проверенный локальный runtime: Microsoft OpenJDK 25.0.1+8-LTS. Скрипт не меняет системную Java. --reuse-reports позволяет повторно упаковать уже полученные локальные отчёты; полное воспроизведение выполняют без него. Gzip имеет фиксированный mtime=0; содержимое каталога детерминировано. В provenance меняется время запуска.

Фактически проверена точка входа:

java -Xmx1G -DbundlerMainClass=net.minecraft.data.Main -jar server.jar --reports --output generated

catalog_extract.java — собственная небольшая программа, вызывающая публичные API реестров и коллизий 26.2. Она не содержит декомпилированного кода. Генератор данных и измерения не запускают игровой сервер, не создают eula=true, не принимают соглашений. JAR, распакованные библиотеки, отчёты и Java-классы остаются в игнорируемом artifacts/catalog-cache; в дистрибутив входят только минимальные фактические данные совместимости и авторский код.

Что проверено у форм

Для каждого из 32 366 состояний получен getCollisionShape официального исполняемого API. Измерение не использует текстуры или визуальные модели. Все измерения завершились без ошибок; после дедупликации осталось 326 различных наборов прямоугольных объёмов.

Базовый контекст измерения — BlockPos.ZERO, соседи air, отсутствие сущности (CollisionContext.empty()). Дополнительно сравнены каменные соседи и CollisionContext.positionContext(+10/-10): различия обнаружены у 32 состояний scaffolding. Помимо них явно помечены классы с зависимостью от сущности/блочной сущности/динамического состояния: powder snow, shulker box, moving piston и big dripleaf. Поэтому покрытие коллизий разделено:

  • 32 187 состояний: measured-empty-context — измерена форма в описанном контексте.
  • 179 состояний: approximate-context — геометрия базового контекста доступна, полной эквивалентности динамических условий нет.
  • 1 собственное состояние: authored-exact.

Первое значение не утверждает эквивалентность во всех произвольных контекстах. Положение игрока, специальные экипировки, поршневые блочные сущности, открывание shulker box, обновление связей соседей, AI, редстоун и течения жидкостей не следуют из каталога. Сервер реализует собственную симуляцию и явно ограниченные модули.

Отдельные регрессионные проверки подтверждают верхнюю/нижнюю плиту, объём и направления лестниц, открывание двери, пустую коллизию воды, коллизию забора высотой 1.5, контекстную пометку scaffolding/powder snow, валидность границ всех форм. Геометрия коллизий может выходить за клетку: нельзя безусловно ограничивать Y диапазоном [0,1].

Авторское отображение

render и collision — разные наборы Aabb { min, max }, координаты относительно блока. Рендерер использует собственные процедурные формы и палитру Shacraft. Встроенные PNG, звуковой WAV и GLSL написаны/сгенерированы в этом репозитории; оригинальных ресурсов Minecraft нет.

Семейства плит, лестниц, дверей, люков, панелей, сундуков и многих сложных твёрдых блоков используют измеренные объёмы как основу самостоятельной геометрии. Для заборов, стен, открытых калиток, знаков, рельсов, жидкостей, растений, кнопок, рычагов, ковров и других нетвёрдых форм предусмотрены отдельные параметрические шаблоны. Забор рисуется до Y=1, при этом коллизия достигает Y=1.5. У наклонного рельса ступенчатая геометрия; изогнутый рельс — угловая аппроксимация из прямоугольников. Это читаемый авторский стиль, а не копия визуальной точности Minecraft.

Покрытие: 32 317 состояний authored-procedural и 50 intentionally-invisible (включая воздух, технический light/barrier/structure void и moving piston без исходной динамической блочной сущности). Универсальных визуальных кубов-заглушек для неизвестных семейств встроенного каталога сейчас нет. При этом каждая декоративная деталь, текст надписей, анимация, waterlogged-жидкость внутри модели и световая симуляция не воспроизводятся автоматически по факту наличия состояния.

Для 158 типов сущностей извлечены начальные width/height/eye height, fixed dimensions, категория, summonable/serializable/fire immune, tracking/update interval и все доступные базовые числовые attributes. Эти свойства находятся в EntityDefinition.properties. Модели относительно ног — авторские семейства biped, quadruped, aquatic, winged, boat, cart, dragon, arthropod и другие. Служебные marker/interaction/area effect cloud/lightning bolt намеренно невидимы. Display-сущности имеют явно указанную зависимость от свойств экземпляра. Размеры возраста/позы/масштаба и произвольный NBT сохраняются слоем экземпляров; каталог хранит размеры по умолчанию. Наличие модели не означает наличие ванильного AI.

Rust API

  • Catalog::load_builtin() -> Result<Catalog>: полный встроенный каталог и trampoline.
  • catalog.state(canonical_or_block_name), catalog.entity(name), catalog.default_state(name).
  • catalog.palette(): 12 удобных канонических состояний для тестового клиента.
  • catalog.sampler(): 1 197 образцов по умолчанию в сетке 32 столбца с шагом 3; отдельные клетки относительно пола Y=0, X/Z в пределах ±64. Создание пола и запись в мир — ответственность сервера.
  • catalog.summary(): количества, раздельное покрытие, версия и ограничения.
  • canonical_state(name, properties): сортировка ключей и ограниченная валидация без потери неизвестных свойств.
  • Все публичные определения реализуют Clone, Serialize, Deserialize. После десериализации целого Catalog следует вызвать rebuild_indexes() перед поиском.

Хранение бинарного встроенного каталога занимает около 246 KiB gzip; при загрузке он распаковывается и создаёт строки/геометрию и индексы. Размер файла не равен RAM каталога. Полные строки 32 тысяч состояний и реестр WorldStore нужно учитывать отдельно в RSS измерениях процесса.

Единый формат пакета v1

Каждый подкаталог packages/ содержит manifest.json:

{
  "schema": 1,
  "id": "shacraft.trampoline",
  "version": "1.0.0",
  "license": "MIT OR Apache-2.0",
  "dependencies": [{"id": "shacraft.base", "version": "1.0.0"}],
  "capabilities": ["blocks.define", "client.texture", "client.style", "server.on_jump"],
  "resources": [{
    "path": "server/trampoline.wasm", "scope": "server", "role": "wasm-on-jump",
    "sha256": "<64 lowercase hexadecimal characters>", "size": 40
  }]
}

Пример иллюстрирует схему; действительные размеры и хеши берутся из сгенерированных манифестов. Версии зависимостей точные. load_packages(root) проверяет весь граф до выдачи ресурсов: схему, уникальность, зависимости, совпадение версий, циклы, допустимые capabilities, пути, размеры и SHA-256 всех объявленных ресурсов. Один ресурс ограничен 16 MiB, весь пакет — 64 MiB; symlink и traversal в ресурсных путях отвергаются. read_resource повторно проверяет хеш и размер при чтении.

Scopes: common — общие определения; client — ресурсы клиента; server — внутренние данные и код сервера. PackageManifest::client_manifest() исключает серверные ресурсы и capabilities. Package::public_resource(path) отказывает для server scope; HTTP-маршрут обязан использовать именно этот метод. Статический сервер не должен раздавать весь каталог packages/ напрямую.

shacraft.base включает описание каталога, собственный 64×64 текстурный шум и клиентский стиль. shacraft.trampoline включает общее определение блока, 32×32 текстуру сетки, клиентский визуальный эффект, короткий авторский звук, необязательную функцию GLSL и исполняемый серверный WebAssembly-модуль. Его экспорт on_jump() -> f32 возвращает скорость 10 блоков/с; импортов, памяти и внешних системных вызовов нет. WAT-исходник находится рядом. Сервер исполняет бинарный модуль в ограниченной среде; контракт предусматривает лимит топлива 10 000, памяти 1 страницу, проверку диапазона результата. Клиент использует встроенный эффект bounce по данным пакета, не произвольный JavaScript из сети. Произвольная среда клиентского кода и полноценная модовая экосистема не объявляются реализованными.

python3 scripts/catalog_assets.py детерминированно пересоздаёт все авторские ресурсы и хеши. Ресурсы пакетов доступны на условиях MIT OR Apache-2.0, как собственный код проекта. Генерация ничего не скачивает.