Complete local voxel MVP with server, client, MCP, packages and world interchange
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Приёмка Shacraft Core
|
||||
|
||||
Статус: план проверок; фактические результаты первого этапа находятся в `STATUS.md` и `VERIFICATION.md`. Рубежи A и B целиком ещё не пройдены. Основа — исходный запрос пользователя и текущий `docs/CONTRACT.md`. Последний описывает первый рабочий протокол, но пока не покрывает весь согласованный MVP.
|
||||
Статус: критерии для локального MVP. Реализованные сценарии и доказательства перечислены в STATUS и VERIFICATION. Этот документ сохраняет исходный план приёмки; ограничения более широких стресс-тестов и совместимости не скрываются общим флагом готовности.
|
||||
|
||||
Shacraft Core — самостоятельный открытый движок на Rust. Shacraft-сервер и Spleef проверяют его пригодность на практике. Экономия серверной RAM — основное архитектурное требование. Полный базовый каталог Minecraft 26.2 означает контент, состояния и формы, а не требование воспроизвести архитектуру Minecraft или весь ванильный игровой процесс.
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# Браузерный клиент MVP
|
||||
|
||||
Клиент находится в `client/` и раздаётся `shacraft-server` по `/`. Сборщик, npm-зависимости и готовый игровой движок не нужны: это ES-модули и собственный WebGL2-рендерер. Откройте `http://127.0.0.1:4000` после запуска сервера. Поддерживаются современные настольные браузеры с WebGL2; `localhost` или HTTPS необходим для `crypto.subtle` и проверки пакетов.
|
||||
|
||||
## Управление
|
||||
|
||||
- Нажмите на мир, чтобы захватить мышь. Если браузер запрещает захват, удерживайте кнопку и перетаскивайте для обзора.
|
||||
- WASD или стрелки — движение; пробел — прыжок. Направление определяется камерой, +Y вверх, yaw 0 смотрит вдоль −Z. Позиция игрока задаёт ступни.
|
||||
- ЛКМ — убрать выбранный блок, ПКМ — поставить блок на выбранной грани, средняя кнопка — взять выбранный материал в текущую ячейку.
|
||||
- 1–9 или колесо мыши — ячейка панели. E — библиотека всех состояний; поиск использует английские Minecraft-идентификаторы. Выбор заменяет текущую ячейку.
|
||||
- T или Enter — чат, Enter отправляет, Esc закрывает.
|
||||
- Кнопка имени мира открывает выбор экземпляра. F3 открывает диагностику. Меню содержит имя игрока, возвращение к точке появления и запуск Spleef.
|
||||
- Esc освобождает мышь; отпускание фокуса и открытие панели отправляют нулевой ввод, чтобы игрок не продолжал движение.
|
||||
|
||||
## Рендер и синхронизация
|
||||
|
||||
Геометрия строится по локальным box-формам материалов. Сетки разбиты на секции 16³; общие грани полных непрозрачных кубов отбрасываются. Изменение блока пересобирает его секцию и смежные секции. Шейдер использует направленный свет, туман, пиксельную фактуру и авторскую текстуру из проверенного пакета. Небо и солнце также рисуются WebGL. Прозрачные материалы рисуются отдельным проходом с сортировкой секций по расстоянию (внутри секции порядок прозрачных поверхностей упрощён). Пакет с декларативным стилем `effect: bounce` (включая trampoline и пользовательские блоки) подключает текстуру, проверенную GLSL-функцию подсветки и авторский звук; отклик привязан к полученному от сервера подъёму игрока. Формы сущностей берутся из каталога; игроки имеют отдельные составные аватары. Это собственное упрощённое визуальное представление, а не точное воспроизведение Minecraft.
|
||||
|
||||
Клиент отправляет ввод максимум 20 раз в секунду, не объявляет собственную позицию и не изменяет блоки оптимистически. Сервер рассчитывает движение, столкновения и правки, а клиент сглаживает полученные позиции между кадрами. Это добавляет небольшую задержку движения, зато визуальное положение следует авторитетной симуляции. Камера реагирует на мышь локально.
|
||||
|
||||
`welcome` и `snapshot` полностью заменяют видимую геометрию. Полный `registry` необязателен: снимок содержит не больше 256 описаний используемых материалов, остальные формы клиент постепенно запрашивает через `/api/catalog?ids=...&limit=128`. Каждый ответ достраивает только затронутые секции; до получения формы отображается нейтральный куб. События `blocks` применяются только по порядку ревизий; данные за пределами последнего окна 64×40×64 отбрасываются, сохраняя продвижение ревизии. Пропуск запрашивает `resync`; старые ревизии игнорируются. При потере соединения клиент переподключается с задержкой 1, 2, 4, 8, 16, затем 20 секунд. Ошибки подключения, несовместимого протокола, ресурсов и отказанные сервером действия выводятся пользователю.
|
||||
|
||||
## Пакеты
|
||||
|
||||
До WebSocket-входа клиент получает `/api/manifest`, загружает объявленные клиентские файлы с того же сервера, проверяет их размер и SHA-256 и сохраняет содержимое в CacheStorage по хешу. Кэшированные файлы повторно проверяются. Отказ кэша не отменяет проверку целостности. При несовпадении хеша файл удаляется из кэша, вход не выполняется. Максимум одного файла — 64 МиБ, набора за загрузку — 128 МиБ, кэш — 512 последних записей. Это ограничения проверяемого содержимого; браузерные сетевые буферы и декодирование изображений также используют память.
|
||||
|
||||
Токен Control API клиенту не передаётся. В браузере не выполняется произвольный привилегированный JavaScript из пакетов. Проверка клиентом хешей означает совместимость ресурсов и не доказывает неизменность самого клиента на устройстве игрока.
|
||||
|
||||
## Отладка и проверки
|
||||
|
||||
F3 показывает настоящие значения: мир, ревизию, число видимых блоков и сущностей, игроков, WebGL, FPS, треугольники, тик, подтверждённый ввод, координаты, пакеты и доступные серверные метрики. На `#world-canvas` есть `data-world`, `data-revision`, `data-blocks`, `data-entities`, `data-webgl`, `data-connected`; они обновляются раз в секунду для автоматизированной браузерной проверки. Секреты и управляющие команды через DOM не выставляются.
|
||||
|
||||
Проверки чистой математики: `cd client && npm test`. Проверяются оси камеры и проекция, отрицательные координаты, ближайшая грань, ограничения дальности и точное попадание в неполные формы. Визуальная и сквозная проверка выполняется с настоящим сервером отдельно от этих unit-тестов.
|
||||
+16
-90
@@ -1,104 +1,30 @@
|
||||
# Совместимость с Minecraft Java 26.2
|
||||
|
||||
Дата проверки источников: 14 сентября 2026 года. Это план и критерии приёмки; наличие этого документа не означает, что конвертер или полный каталог уже реализованы.
|
||||
Проверено 14 сентября 2026 года. Реализованы полный каталог целевой версии и двусторонний конвертер с явно определённым профилем точности. Подробные контракты и команды: [CONTENT](CONTENT.md), [interop](interop.md), [SERVER](SERVER.md).
|
||||
|
||||
## Цель и границы
|
||||
## Источник
|
||||
|
||||
Shacraft остаётся самостоятельным движком на Rust. Совместимость означает полный каталог идентификаторов блоков, их допустимых состояний и типов сущностей целевой версии, отдельное покрытие форм, а также обмен пользовательскими мирами и постройками с сохранением исходных данных. Совпадение всей симуляции Minecraft — редстоуна, генератора мира, поведения мобов, жидкостей и команд — требует собственных модулей и не следует автоматически из наличия каталога.
|
||||
Mojang выпустила [Java 26.2](https://www.minecraft.net/en-us/article/minecraft-java-edition-26-2) 16 июня 2026 года. [Официальный launcher manifest](https://piston-meta.mojang.com/mc/game/version_manifest_v2.json) указал точные [метаданные версии](https://piston-meta.mojang.com/v1/packages/bc42e43dfe43d65a2f6c2c1dbb322c75134e51fe/26.2.json):
|
||||
|
||||
Целевая версия действительно существует: Mojang выпустила Java 26.2 16 июня 2026 года. В ней добавлены, среди прочего, sulfur/cinnabar и sulfur cube; поэтому каталог более ранней версии нельзя выдавать за 26.2. [Официальный релиз](https://www.minecraft.net/en-us/article/minecraft-java-edition-26-2).
|
||||
- Server JAR: `823e2250d24b3ddac457a60c92a6a941943fcd6a`, 60 894 273 байта; Java major 25.
|
||||
- DataVersion, извлечённый из целевой версии: **4903**.
|
||||
- Отчёты и публичный API подтвердили **1 196 блоков**, **32 366 состояний**, **158 сущностей**.
|
||||
- Все состояния сопоставляются по канонической строке и множеству свойств, не только по общему количеству.
|
||||
|
||||
Первый рабочий срез может иметь небольшой демонстрационный каталог, однако в интерфейсе, README и отчётах он должен называться именно демонстрационным. Требование полного каталога остаётся незакрытым до проверки против зафиксированного источника.
|
||||
`scripts/catalog_generate.py` проверяет артефакт, извлекает отчёты и измеряет коллизии. Повторное извлечение дало побайтно одинаковые сжатые каталоги. JAR остаётся в игнорируемом кэше; исходный код, текстуры, модели и звуки Minecraft в дистрибутив не включаются.
|
||||
|
||||
## Зафиксированный источник данных
|
||||
## Что означает поддержка
|
||||
|
||||
При проверке [официального launcher manifest](https://piston-meta.mojang.com/mc/game/version_manifest_v2.json) получена запись `id=26.2`, `type=release`, `releaseTime=2026-06-16T12:03:33+00:00`. Она ссылается на [метаданные версии](https://piston-meta.mojang.com/v1/packages/bc42e43dfe43d65a2f6c2c1dbb322c75134e51fe/26.2.json):
|
||||
`identity`, `render`, `collision` и `behavior` — отдельные поля. Все ванильные состояния известны; 179 контекстных состояний явно помечены `approximate-context`. Остальные коллизии измерены при воздушных соседях и пустом контексте сущности. Это не обещает контекстную эквивалентность во всех ситуациях. Визуальные модели авторские процедурные, а не ванильные. Невидимые служебные блоки намеренно не получают видимую геометрию.
|
||||
|
||||
- SHA-1 JSON метаданных: `bc42e43dfe43d65a2f6c2c1dbb322c75134e51fe`.
|
||||
- Java runtime: major version `25`.
|
||||
- [Официальный server.jar](https://piston-data.mojang.com/v1/objects/823e2250d24b3ddac457a60c92a6a941943fcd6a/server.jar): размер `60894273` байта, SHA-1 `823e2250d24b3ddac457a60c92a6a941943fcd6a`.
|
||||
158 типов сущностей имеют измеренные размеры, сохраняемые экземпляры и собственные формы. Полноценная AI, redstone, инвентари, генератор и симуляция жидкостей не реализованы. Неизвестные импортированные состояния сохраняются в реестре и видимы как отмеченная заглушка; они не подменяются воздухом в данных.
|
||||
|
||||
SHA-1 здесь фиксирует артефакт по метаданным Mojang. Наш файл происхождения дополнительно должен содержать вычисленный SHA-256, дату, команду извлечения, Java version и хеш каждого итогового отчёта.
|
||||
Числовой runtime BlockId Shacraft не равен Minecraft state ID. Конвертер сопоставляет канонические строки; одинаковые названия в независимых WorldStore могут иметь разные внутренние номера.
|
||||
|
||||
План получения каталога:
|
||||
## Проверенный обмен
|
||||
|
||||
1. Скачать этот JAR в локальный игнорируемый кэш, проверить размер и хеш. Не включать его в репозиторий и дистрибутив Shacraft.
|
||||
2. Проверить доступную точку входа и `--help` генератора данных именно этого артефакта, затем получить отчёты блоков и реестров. Команда для старых версий не считается проверенной командой для 26.2. Сам факт существования `blocks.json` в генераторе подтверждён Mojang; его структура меняется, что видно уже в [изменениях 26.3 Snapshot 2](https://www.minecraft.net/en-us/article/minecraft-26-3-snapshot-2).
|
||||
3. Из отчёта блоков извлечь resource location, свойства, допустимые значения, все перечисленные состояния и состояние по умолчанию. Из реестров — типы сущностей, block entities, биомы и прочие необходимые для конвертации ключи. Если нужного поля нет в отчёте, пометить пробел и сделать отдельное воспроизводимое извлечение из исполняемого API целевой версии.
|
||||
4. Получить `DataVersion` из целевого артефакта/мира, сохранить в манифесте. Номер ещё не извлечён в рамках этого исследования; не подменять его номером datapack/resource pack.
|
||||
5. Хранить минимальный производный каталог и собственные правила адаптации. Текстуры, звуки, модели, шейдеры и декомпилированный код Minecraft в него не входят. Визуальные ресурсы Shacraft создаются отдельно либо подключаются из локальных ресурсов пользователя отдельным адаптером.
|
||||
Anvil импортируется по одному chunk с типизированным NBT, включая измерения и непрозрачные дополнительные данные. Неизменённый `exact` возвращает сохранённый оригинал после проверки хешей. После правок `exact` консервативно отказывает. `best-effort` переносит изменения блоков и поддержанных свойств сущностей, инвалидирует зависимые данные и сохраняет неподдержанные данные с отчётом и исходником.
|
||||
|
||||
Полнота проверяется равенством множеств канонических состояний и типов сущностей с отчётами, а не ожидаемым числом из статьи или ручного списка. Количества блоков/состояний/сущностей появятся только после фактического извлечения.
|
||||
Sponge `.schem` v3 поддерживается в обе стороны. Обмен между разными форматами не обещает преобразования всей семантики биомов/block entities: неперенесённые данные архивируются и отмечаются в отчёте. Старые версии, legacy `.schematic`, structure `.nbt` и полная миграция произвольных DataVersion не объявляются поддержанными.
|
||||
|
||||
## Контракт каталога и форм
|
||||
|
||||
В `WorldStore` используется каноническая строка `namespace:block[key=value,...]`, где ключи свойств отсортированы. Числовой `BlockId` — внутренний идентификатор Shacraft; он не равен числовому идентификатору Minecraft и не переносится между независимыми реестрами без явной таблицы соответствия. `air` остаётся ID 0 по `CONTRACT.md`.
|
||||
|
||||
Для совместимости необходимы разные признаки покрытия:
|
||||
|
||||
- `identity`: идентификатор и все состояния известны и проверены.
|
||||
- `render`: собственная геометрия отображает состояние; заглушка обозначена явно.
|
||||
- `collision`: проверена форма столкновений для этого состояния и контекста.
|
||||
- `behavior`: установлен модуль поведения, если он реализован.
|
||||
- `roundtrip`: данные можно вернуть в конкретную версию и формат.
|
||||
|
||||
Один флаг `supported` скрывал бы различия. Нельзя получать коллизию автоматически из текстур или из визуальной модели. Формы могут зависеть от соседей, сущности и состояния мира; лестницы, плиты, двери, заборы, стены, растения, жидкости и динамические блоки требуют раздельных тестов. Начать с собственных параметрических форм, затем сравнивать их с выборкой поведения целевой версии. Формы со сложным контекстом сохраняют статус `approximate` до проверки.
|
||||
|
||||
Сущность может быть известна по идентификатору и полностью сохраняться для экспорта, даже если в Shacraft она пока отображается маркером и не имеет AI. В интерфейсе это должно быть видно. Неизвестный блок сохраняет исходную строку и NBT; отображение заглушкой не должно заменять его на `air` в хранилище.
|
||||
|
||||
## Форматы и порядок поддержки
|
||||
|
||||
**NBT — слой сериализации, а не единый формат мира.** Для Java нужен типизированный big-endian NBT. Типы чисел, массивов и списков необходимо сохранять: преобразование к обычному JSON теряет информацию для обратной записи. Это различие прямо показано в [API Prismarine NBT](https://github.com/PrismarineJS/prismarine-nbt), который можно использовать как независимый тестовый декодер, не как зависимость Rust runtime.
|
||||
|
||||
**Sponge `.schem` v3 — первый полноценный адаптер построек.** Поддержать блоки и состояния, block entities, entities, 3D-биомы, размеры, offset, metadata и DataVersion. Спецификация предусматривает эти контейнеры и палитры; точный порядок байтов и кодирование брать из [первичной спецификации Sponge v3](https://github.com/SpongePowered/Schematic-Specification/blob/master/versions/schematic-3.md). Затем добавить v2 как отдельную ветку декодера. Старый MCEdit `.schematic` не считать тем же форматом и не распознавать по одному похожему расширению.
|
||||
|
||||
**Vanilla structure `.nbt` — отдельный адаптер.** Нужно зафиксировать схему 26.2 на файлах, сохранённых structure block: размеры, палитра/альтернативные палитры, блоки, относительные координаты, block entity NBT и сущности. Сырой NBT-декодер не равен поддержке этой схемы. Неподдерживаемые альтернативные палитры нельзя молча свести к первой.
|
||||
|
||||
**Anvil world directory — потоковый адаптер миров.** Обрабатывать `level.dat`, измерения, region-файлы, секции/палитры, биомы, block entities, отдельные файлы сущностей и POI, а также остальные файлы сохранения. Извлекать разделы по мере необходимости, с ограничением кэша, сохраняя оригинал на диске. Проверять chunk `DataVersion` наряду с версией мира.
|
||||
|
||||
Существующая реализация [WorldEdit AnvilChunk18](https://github.com/EngineHub/WorldEdit/blob/dca10737fe81bd81bb6a096e1801cc2d94f1793b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk18.java) подтверждает практическую работу с секционными палитрами `Name`/`Properties`; [McRegionReader](https://github.com/EngineHub/WorldEdit/blob/dca10737fe81bd81bb6a096e1801cc2d94f1793b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/McRegionReader.java) полезен для проверки контейнера. Эти реализации — независимые ориентиры, не доказательство полного соответствия 26.2. Код не копировать в ядро без отдельного решения о лицензии.
|
||||
|
||||
Нужно явно проверить варианты сжатия, внешние chunk payload и крупные chunks на целевых fixtures. Поддержкой одного zlib нельзя объявлять поддержку всех Anvil-файлов: возможность LZ4-сжатия регионов описана в [официальном релизе Java 1.20.5](https://www.minecraft.net/es-es/article/minecraft-java-edition-1-20-5). Неизвестное сжатие даёт диагностируемый отказ, а не пустой chunk.
|
||||
|
||||
## Режимы экспорта и сохранение оригинала
|
||||
|
||||
**`exact` — проверенная точность данных.** По умолчанию используется та же версия и тот же формат, что у источника. Исходные файлы помещаются в неизменяемое дисковое хранилище с хешами; изменения Shacraft хранятся отдельно. Нетронутые файлы копируются побайтно. В изменённых файлах переписываются только поддерживаемые данные; остальные типизированные NBT-поля сохраняются. Контракт точности — семантическое равенство NBT за исключением явных правок и заранее объявленных производных полей, а не одинаковое сжатие и размещение секторов.
|
||||
|
||||
При неизвестной версии, некорректной палитре, неподдерживаемой операции, несовместимой сущности, неразрешённом преобразовании metadata или отсутствии необходимых исходных данных `exact` прекращает экспорт до публикации результата. Особенно проверять замену блока с block entity, инвентари, пассажиров и UUID, а также зависимости от света, heightmaps, POI и scheduled ticks. Нельзя оставить заведомо неверные производные данные и назвать экспорт точным. Правило пересчёта/инвалидации каждого такого поля должно быть проверено целевым Minecraft.
|
||||
|
||||
**`best-effort` — преобразование с отчётом.** Разрешает только явно заданные правила замены. Формирует `conversion-report.json`: версия источника/назначения, формат, координата/UUID, код причины, исходное значение, действие, количество и тяжесть. Неизвестные данные остаются в сопровождающем архиве, однако это не означает, что целевой Minecraft сможет их использовать. Отчёт различает `preserved`, `approximated`, `dropped`, `unsupported`.
|
||||
|
||||
Для мира, созданного в Shacraft без Minecraft-оригинала, экспорт в `.schem` доступен после проверки всех данных на представимость. Создание полноценного Anvil-мира потребует отдельного генератора корректного окружения сохранения; одной записи массива блоков в `.mca` недостаточно.
|
||||
|
||||
Исходный мир никогда не редактируется конвертером на месте. Вывод готовится во временном каталоге и переименовывается после успешной проверки. Прерванный импорт можно возобновить по журналу chunks и хешам. Экспорт получает согласованный снимок мира; параллельные игровые правки не должны давать смесь ревизий.
|
||||
|
||||
## Необходимые дополнения к текущему API
|
||||
|
||||
`CONTRACT.md` покрывает блоки и ревизии. В нём пока нет durable API произвольного NBT, биомов, сущностей и provenance. До заявления о lossless-конвертации добавить версионируемый compatibility sidecar со ссылками на неизменяемые blobs, типизированными NBT и изменениями по chunk/UUID. Он должен участвовать в атомарной фиксации ревизии вместе с блоками.
|
||||
|
||||
Не перегружать строковый реестр блоков всем NBT мира и не держать sidecar целиком в RAM. Экспортёр/импортёр — отдельная библиотека/CLI над ядром; Java используется для получения эталонных данных и интеграционной проверки, но не для работы Shacraft-сервера.
|
||||
|
||||
## Приёмочные проверки
|
||||
|
||||
1. **Каталог:** равенство множеств всех состояний/типов целевому отчёту, один default на блок, канонизация независимо от порядка properties, сохранение неизвестного namespace, стабильность таблицы ID после перезапуска.
|
||||
2. **NBT:** все типы, пустые списки, 64-битные значения, массивы, Unicode, неизвестные поля. Проверка encode/decode независимым декодером; обычный JSON не выступает эталоном.
|
||||
3. **Палитры:** один блок на всю секцию, границы размера палитры и битовой упаковки, секции из воздуха, отрицательные X/Z/Y, границы chunks/regions, отсутствующие данные и повреждённые индексы.
|
||||
4. **Без правок:** Minecraft/WorldEdit fixture → Shacraft → исходный формат. Нетронутые файлы побайтно идентичны; пересобранные структуры семантически равны по типизированному NBT. Третий декодер подтверждает результат.
|
||||
5. **С правками:** поменять одно состояние, сломать контейнер, поставить лестницу/дверь, переместить поддерживаемую сущность. После экспорта меняются только предусмотренные данные; metadata, прочие inventories/entities/biomes и неизвестные теги сохраняются либо дают точный отказ.
|
||||
6. **Открытие:** отдельная копия экспортированного мира открывается целевым Java 26.2 без ошибок декодирования/утраты chunks; фиксируются хеш JAR, логи и проверяемые координаты. Одного собственного roundtrip недостаточно — одинаковая ошибка в reader/writer может остаться незамеченной.
|
||||
7. **Версии/потери:** unsupported DataVersion, модифицированный namespace, отсутствующая модель, неподдерживаемое NBT и cross-format export проверяют отказ `exact` и полный отчёт `best-effort`.
|
||||
8. **Ресурсы:** большие sparse-миры, высокоэнтропийные секции, большие payload, повреждённые длины и сильное сжатие. Ограничить распакованный размер, глубину NBT, очередь и кэш; измерить пик RAM. Прерывание/повтор импорта и сбой финальной записи не повреждают исходник и сохранённые ревизии.
|
||||
|
||||
Fixtures должны быть собственными маленькими мирами/постройками без сторонних карт и ассетов. Для версии и сжатия, которых нет в fixtures и внешней проверке, не ставить статус `verified`.
|
||||
|
||||
## Этапы и условия завершения
|
||||
|
||||
1. **Происхождение:** зафиксированный источник 26.2, воспроизводимый генератор, DataVersion, хеши и точные количества; отсутствие этих результатов оставляет полный каталог незавершённым.
|
||||
2. **Реестр:** все состояния и entity IDs загружаются в Shacraft, сохраняются и ищутся; формы и behavior имеют отдельную карту покрытия.
|
||||
3. **NBT + `.schem` v3:** типизированные данные и архив оригинала, оба направления, отчёт потерь, независимые roundtrip-тесты.
|
||||
4. **Structure NBT + `.schem` v2:** схемы разделены и проверены на эталонах, включая offset/повороты только там, где они реализованы.
|
||||
5. **Anvil 26.2:** потоковый импорт, возврат исходного мира, затем проверенные правки и создание новых экспортируемых миров; тесты с целевым Minecraft.
|
||||
6. **Полное покрытие форм:** все состояния имеют проверенную визуальную форму и отдельно коллизию либо явный незакрытый дефект. Завершение списка ID само по себе не закрывает этот этап.
|
||||
7. **Расширение версий:** добавлять другие DataVersion только через отдельные адаптеры/миграции и fixtures. Не обещать автоматический downgrade и произвольные модифицированные миры.
|
||||
|
||||
Главные технические риски: дрейф схем между версиями, скрытые связи block entities/POI/ticks, формы с зависимостью от контекста, полная пересборка мира из частично поддерживаемых данных и непредсказуемые пики RAM при распаковке. Каждый риск выше привязан к конкретному отказу или приёмочному тесту, чтобы он не превратился в молчаливую потерю пользовательского мира.
|
||||
Новый, неизменённый и отредактированный экспорт прочитаны официальными Java 26.2 `NbtIo`, `RegionFile`, `SerializableChunkData`, `PrimaryLevelData`, `WorldGenSettings` и читателем сущностей. Независимый nbtlib проверил Sponge и типы NBT. Это проверка официальных codecs без запуска игрового сервера и принятия EULA; игровой плейтест в Minecraft не заявляется.
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
# Каталог, формы и единые пакеты 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](https://piston-data.mojang.com/v1/objects/823e2250d24b3ddac457a60c92a6a941943fcd6a/server.jar). SHA-1 `823e2250d24b3ddac457a60c92a6a941943fcd6a`, размер 60 894 273 байта. Полные SHA-256, версия Java, команды и контрольные суммы отчётов находятся в `crates/shacraft-content/data/provenance.json`.
|
||||
|
||||
Генератор проверяет закреплённые размер и SHA-1 перед использованием JAR:
|
||||
|
||||
```sh
|
||||
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 меняется время запуска.
|
||||
|
||||
Фактически проверена точка входа:
|
||||
|
||||
```sh
|
||||
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`:
|
||||
|
||||
```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`, как собственный код проекта. Генерация ничего не скачивает.
|
||||
@@ -44,3 +44,12 @@ Client fetch GET /api/manifest -> {protocol:1,hash,packages:[],...}; GET /api/wo
|
||||
Control HTTP: GET /api/health, /api/metrics, /api/worlds, /api/catalog public; POST /api/control with Authorization: Bearer token and {method,params}, JSON return {result:...} or {error:'...'}.
|
||||
Control methods: world.list, world.create {name,template?}, world.reset {world,expected_revision,operation_id}, world.read {world,min,max}, world.edit {world,expected_revision,operation_id,changes}, world.undo {world,expected_revision,operation_id,target_operation}, catalog.search {query,limit}, metrics, arena.start {world}, camera.capture {world,min?,max?} (top-down PNG), entity.spawn {world,kind,position}, entity.list {world}.
|
||||
Default server host 127.0.0.1 port 4000, token file data/control.token (0600). No publishing or production access.
|
||||
|
||||
|
||||
## Интегрированные компоненты MVP
|
||||
|
||||
Игровой протокол и границы Control API описаны в SERVER.md, настоящий stdio MCP — в MCP.md, пакеты и WASM — в PACKAGES.md, полный каталог — в CONTENT.md, Anvil/Sponge и типизированные sidecar — в interop.md. Данные документы дополняют контракт ядра выше, не изменяя его durable-правил.
|
||||
|
||||
`WorldStore::section_positions(world, after: Option<Pos>, limit)` постранично возвращает эффективные координаты секций 16³, включая унаследованные секции и воздушные overrides, в порядке x/y/z. Лимит 1–4096. Экспорт удерживает единственного писателя и не меняет мир между страницами.
|
||||
|
||||
История ядра находится на диске. Метаданные сущностей/правил имеют отдельную транзакционную область и ревизию. Планы preview живут 5 минут и не переживают рестарт; принятая правка живёт по контракту WorldStore. Неуспешный metadata commit не публикует изменённое состояние. При прерывании активного матча арена сбрасывается к закреплённой основе на следующем запуске.
|
||||
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
# Shacraft MCP
|
||||
|
||||
`shacraft-mcp` — отдельный процесс с настоящим MCP поверх stdio и JSON-RPC 2.0. Он обращается к авторизованному Control API работающего сервера и не открывает файлы миров напрямую. Сервер хранит и проверяет ревизии, лимиты и долговечность операций.
|
||||
|
||||
```sh
|
||||
cargo run -p shacraft-mcp -- --server http://127.0.0.1:4000 --data data
|
||||
```
|
||||
|
||||
По умолчанию токен читается из `data/control.token`. Параметр `--token-file /absolute/path/control.token` переопределяет путь. Токен читается при управляющем вызове, поэтому MCP можно запустить раньше сервера. В стандартный вывод пишутся только JSON-RPC-сообщения, одна строка на сообщение; диагностика и CLI-ошибки идут в stderr. Не запускайте через командную обёртку, которая печатает посторонний текст в stdout.
|
||||
|
||||
Пример записи в конфигурации MCP-клиента (пути заменяются своими абсолютными):
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"shacraft": {
|
||||
"command": "/absolute/path/shacraft-core/target/release/shacraft-mcp",
|
||||
"args": ["--server", "http://127.0.0.1:4000", "--data", "/absolute/path/shacraft-data"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Протокол
|
||||
|
||||
Поддерживаются версии `2025-11-25`, `2025-06-18`, `2025-03-26`, `2024-11-05`. Сервер возвращает запрошенную поддерживаемую версию или новейшую поддерживаемую. Клиент начинает с `initialize`, затем посылает `notifications/initialized`. До этого доступны только `initialize` и `ping`. Уведомления не вызывают ответов; неизвестные методы запросов получают JSON-RPC-ошибку. Ошибки аргументов и выполнения известных инструментов возвращаются в `result.content` с `isError: true`.
|
||||
|
||||
Реализованы `tools/list`, `tools/call`, `resources/list`, `resources/read`, `resources/templates/list`, `prompts/list`, `prompts/get` и `ping`. Списки небольшие и возвращаются целиком. Подписки, асинхронные задачи и уведомления о смене списков не объявляются. Выполнение последовательное; уведомление об отмене не прерывает уже выполняющийся HTTP-запрос. Сетевой тайм-аут ограничен 20 секундами (установление соединения — 3 секунды).
|
||||
|
||||
Строка запроса и HTTP-ответ ограничены 8 МиБ. Слишком длинная входная строка отбрасывается до перевода строки, после чего поток продолжает разбираться. HTTP-редиректы отключены: bearer-токен не передаётся перенаправленному адресу.
|
||||
|
||||
## Инструменты и рабочий процесс
|
||||
|
||||
- `world_list`, `world_create`, `world_read`: осмотр миров и создание пустого мира или экземпляра закреплённого шаблона.
|
||||
- `catalog_search`: точные состояния, runtime ID, формы и сведения о покрытии реализации.
|
||||
- `world_edit`, `world_undo`, `world_reset`: атомарные правки, консервативная отмена последней операции и возврат к базе.
|
||||
- `build_plan`, `build_commit`: предварительный расчёт ограниченной постройки из box/line/cylinder и последующая фиксация плана.
|
||||
- `entity_list`, `entity_spawn`, `entity_update`, `entity_delete`: сохранённые сущности мира и их свойства.
|
||||
- `arena_configure`, `arena_start`: сохраняемые правила Spleef (время, минимум игроков, высота выбывания, точки появления, материал пола) и запуск матча. Правила нельзя менять во время начавшегося раунда; материал пола задаёт разрешённые для разрушения блоки, но не перестраивает карту.
|
||||
- `metrics`: измеренный RSS и отдельные оценки полезных данных кэша.
|
||||
- `camera_capture`: изометрическое изображение мира в формате MCP image plus metadata. Это диагностическая проекция сервера, не снимок WebGL-камеры игрока.
|
||||
|
||||
Полные JSON Schema доступны через `tools/list`. Имена инструментов соответствуют Control API с заменой первого `_` на точку, например `world_edit` → `world.edit`.
|
||||
|
||||
Для строительства сначала прочитайте ревизию и площадку через `world_list`/`world_read`, найдите точные материалы через `catalog_search`, сформируйте `build_plan`, оцените границы и объём, затем выполните `build_commit` с уникальным `operation_id` в пределах авторизованного запроса. После фиксации проверьте `camera_capture`. При конфликте перечитайте мир и сформируйте новый план. Тот же ключ операции используйте только при повторе идентичного запроса.
|
||||
|
||||
Отмена требует текущую ревизию и `target_operation` исходной правки. Последующие изменения и reset могут сделать отмену недоступной; инструмент не должен перезаписывать их молча.
|
||||
|
||||
## Ресурсы и prompt
|
||||
|
||||
Ресурсы `shacraft://server/status`, `shacraft://catalog/blocks`, `shacraft://catalog/entities`, `shacraft://packages` читают публичные сведения сервера. Ресурс блоков даёт начальную ограниченную страницу; полный каталог доступен поиском и пагинацией инструмента.
|
||||
|
||||
Prompt `construct` принимает строки `world` и `request` и описывает последовательность осмотра, планирования, правки и визуальной проверки. Он не расширяет пользовательское разрешение на действие.
|
||||
|
||||
Проверки: `cargo test -p shacraft-mcp`. Unit-тесты проверяют переходы жизненного цикла, согласование версии, отсутствие ответов на уведомления, ошибки аргументов и токена, недопустимые JSON-RPC ID, восстановление после слишком большой строки и схемы строительных операций. Сквозные тесты с настоящим сервером выполняются дополнительно.
|
||||
|
||||
Основание протокола: официальные [lifecycle](https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle), [stdio transport](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports) и [tools](https://modelcontextprotocol.io/specification/2025-11-25/server/tools).
|
||||
|
||||
## Проверка настоящим MCP SDK
|
||||
|
||||
После запуска отдельного тестового сервера:
|
||||
|
||||
```sh
|
||||
node crates/shacraft-mcp/tests/sdk-smoke.mjs --data /absolute/path/test-server-data
|
||||
```
|
||||
|
||||
Скрипт использует `@modelcontextprotocol/sdk` (проверен с 1.30.0), выполняет согласование протокола, читает все ресурсы, вызывает prompt, делает правку/повтор/конфликт/отмену, план/фиксацию, получает PNG, проверяет CRUD сущностей и reset. Он создаёт отдельный мир с префиксом `mcp_sdk_`. Путь к установленному SDK задаётся через `SHACRAFT_MCP_SDK`; в локальной среде поддерживается соседний `minecraft-builder-mcp/bridge/node_modules`. Это независимая проверка протокола, не зависимость исполняемого MCP от Minecraft Builder.
|
||||
|
||||
Для воспроизводимой проверки с автоматически запущенным отдельным сервером:
|
||||
|
||||
```sh
|
||||
node scripts/check_mcp.mjs --binary target/release/shacraft-server --mcp-binary target/release/shacraft-mcp --port 4002 --output artifacts/mcp-sdk.json
|
||||
```
|
||||
|
||||
Обёртка создаёт временный каталог данных, использует настоящий SDK и закрывает тестовый сервер. Рабочий сервер на порту 4000 не затрагивается. `--sdk` или `SHACRAFT_MCP_SDK` задают путь к уже установленному SDK; результат записывается JSON-файлом, включая ошибку при неуспешной проверке.
|
||||
|
||||
Связанный сквозной тест `scripts/check_server.mjs` проверяет HTTP/WebSocket-клиенты, действия, экземпляры миров, полный матч и восстановление после реального `SIGKILL`: подтверждённые блоки, сущности и правила арены должны пережить перезапуск того же каталога данных. Временные тестовые данные сохраняются для разбора.
|
||||
@@ -0,0 +1,43 @@
|
||||
# Единые пакеты расширений
|
||||
|
||||
`packages/<directory>/manifest.json` объявляет точные версии, лицензии, зависимости, возможности и ресурсы. При запуске сервер проверяет весь граф зависимостей, размеры, SHA-256, пути и отсутствие symlink. Отсутствующая версия, цикл, неизвестная возможность или изменённый ресурс останавливают запуск. Публикуются только `client` и `common`; файлы `server` не имеют публичного маршрута. Ресурс повторно проверяется при HTTP-чтении.
|
||||
|
||||
Примеры — `packages/base` и `packages/trampoline`. Все изображения, звук и модели авторские. Данные каталога происходят из официальных отчётов и измерения публичного API Java 26.2; ванильные текстуры и модели в пакеты не входят.
|
||||
|
||||
Манифест schema 1 содержит:
|
||||
|
||||
- `id`, `version` из трёх числовых частей, `license`;
|
||||
- `dependencies:[{id,version}]` с точными версиями;
|
||||
- `capabilities`, например `blocks.define`, `client.texture`, `server.on_jump`;
|
||||
- `resources:[{path,scope,role,sha256,size}]`.
|
||||
|
||||
Один ресурс не больше 16 МиБ; пакет не больше 64 МиБ, до 128 ресурсов, до 128 записей в каталоге пакетов. Это ограничения сервера; браузер дополнительно ограничивает суммарно проверяемые публичные ресурсы 128 МиБ на подключение. Определения блоков имеют роль `definitions`, ресурс с этой ролью требует schema 1. Сервер допускает до 4096 дополнительных определений. Блок задаёт `state` как новый идентификатор `namespace:path` без свойств (строчные ASCII-буквы, цифры, `_`, `.`, `-`, дополнительно `/` в path), `color:[r,g,b]`, `collision:[{min,max}]` и необязательный `render` аналогичной формы. Необязательный `opacity` — число 0…1. Если render не указан, используется существующая авторская форма того же состояния или коллизия нового блока. Максимум 64 бокса на каждый набор; допустимый локальный диапазон координат −2…3. Дубликаты определений и переопределение `minecraft:*` отвергаются. Runtime ID назначает сохраняемый реестр; `Game::open` расширяет каталог проверенными определениями до регистрации в WorldStore. Обычный пакетный блок без `behavior` хранится и участвует в физике; `behavior.server_hook: on_jump` связывает его с активным WASM-провайдером.
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": 1,
|
||||
"blocks": [{
|
||||
"state": "example:spring",
|
||||
"color": [97,205,151],
|
||||
"collision": [{"min":[0,0,0],"max":[1,1,1]}],
|
||||
"render": [{"min":[0,0,0],"max":[1,1,1]}],
|
||||
"behavior": {"server_hook":"on_jump"}
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
## Исполнение модуля
|
||||
|
||||
В MVP нужен ровно один активный провайдер серверного hook `on_jump`; отсутствие провайдера или два модуля с этой ролью останавливают запуск. Серверный `.wasm` объявляется ресурсом `role: "wasm-on-jump"`, `scope: "server"`; необходима capability `server.on_jump`. Экспорт `on_jump: () -> f32` возвращает импульс прыжка в блоках/с. Сервер вызывает его только при прыжке игрока с блока, который связан с hook через проверенное определение пакета.
|
||||
|
||||
Исполнение идёт в Wasmi: без импортов, файлов, сети и системных вызовов; до 10 000 единиц fuel на вызов, одна память до 64 КиБ, одна таблица до 128 элементов, один экземпляр. Бинарный модуль не больше 64 КиБ. Результат должен быть конечным числом 0…20; trap или недопустимое значение фиксируется метрикой и даёт обычный прыжок. Выполняемый пример возвращает 10. Тесты проверяют реальный вызов, бесконечный цикл, превышение памяти, попытку импорта и NaN. Отдельный тест создаёт пакет `example:spring`, проверяет его SHA-256, добавляет новый блок в каталог, регистрирует и сохраняет runtime ID, связывает блок с модулем и получает импульс 12 от собственного бинарного WASM. Дубликаты, Minecraft override, недопустимая геометрия, opacity/идентификатор и изменение ресурса после загрузки отвергаются.
|
||||
|
||||
Это ограниченный действующий API расширения, а не обещание произвольной совместимости с Forge/Fabric или доступа WASM к полному состоянию мира. Для нового hook необходима явная версия контракта. Spleef в этом MVP реализован серверным режимом Rust с сохраняемыми правилами.
|
||||
|
||||
## Клиентские ресурсы
|
||||
|
||||
`/api/manifest` возвращает публичный список с URL, точной версией, размерами и SHA-256. Браузер скачивает файлы, проверяет размер и хеш **до входа**, затем кладёт в CacheStorage по хешу. При повторном подключении содержимое кэша тоже проверяется. Ошибка хеша удаляет повреждённую запись и запрещает вход. Неподходящий `manifest_hash` сервер отвергает. Публичный хеш не подтверждает, что клиентское приложение не модифицировано.
|
||||
|
||||
Базовый пакет даёт пиксельную текстуру; trampoline — собственную текстуру, GLSL-функцию окраски, настройку стиля и короткий синтезированный звук. Они применяются собственным WebGL2-рендерером. В ядре и сервере отсутствует графический движок. Пакет не загружает произвольный привилегированный JavaScript.
|
||||
|
||||
Для изменения пакета пересчитайте размер и SHA-256 каждого изменённого ресурса, увеличьте версию и обновите точные зависимости. `scripts/catalog_assets.py` воспроизводимо генерирует встроенные авторские ресурсы и манифесты. Формат ориентирован на будущий лаунчер: лаунчер сможет получить тот же manifest и кэшировать по `(id,version,sha256)`; интеграция конкретного лаунчера в этот репозиторий не входит.
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
План составлен до реализации. Каждый этап заканчивается воспроизводимым результатом в локальном репозитории. `docs/STATUS.md` обновляется после проверок. Пункт не считается выполненным по наличию интерфейса, заглушки, каталога имён или успешной компиляции.
|
||||
|
||||
Текущий прогресс: этап 0 и первая реализация этапа 1 завершены. Проверены библиотека хранения, CLI и аварийное восстановление. Этапы 2–6 остаются впереди; подробности в STATUS и VERIFICATION.
|
||||
Текущий прогресс: этапы 0–6 реализованы для локального профиля MVP. Компоненты интегрированы; фактические проверки, пределы нагрузки и ограничения совместимости описаны в STATUS и VERIFICATION. Исходный порядок этапов ниже сохранён.
|
||||
|
||||
## Этап 0. Сохранить контекст и проверить проектирование
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# Сервер, протокол и эксплуатация MVP
|
||||
|
||||
## Запуск
|
||||
|
||||
Нужны Rust 1.96+ и современный браузер с WebGL2. Java не нужна для запуска Shacraft: проверенный каталог включён в исходники. Node 22+ используется для проверок клиента и сети.
|
||||
|
||||
```sh
|
||||
cargo build --release --locked --workspace
|
||||
bash scripts/run.sh --data data --listen 127.0.0.1:4000
|
||||
```
|
||||
|
||||
Открыть http://127.0.0.1:4000. Для друзей в локальной сети можно задать `--listen 0.0.0.0:4000`; браузерная проверка SHA-256 требует HTTPS для адресов вне localhost. Для внешней сети нужен обычный HTTPS/WSS reverse proxy. В MVP нет сервиса аккаунтов; имя игрока не является подтверждённой личностью. Контрольный токен выдаётся только владельцу сервера, клиент его не получает.
|
||||
|
||||
`--data` — каталог WorldStore, `--cache-sections` — ёмкость общего кэша (по умолчанию 64). `--client` и `--packages` задают каталоги статического клиента и проверенных пакетов. Скрипт запуска явно задаёт пути относительно распакованного проекта. Остановка — Ctrl+C; уже подтверждённые правки не зависят от корректного завершения процесса.
|
||||
|
||||
Первый запуск создаёт лобби, галерею `gallery`, неизменяемую основу Spleef и две независимые арены. Каталог содержит все состояния Java 26.2 и авторский trampoline. Импортированный WorldStore тоже можно открыть сервером; импортированные миры появятся в выборе миров рядом с демонстрационными. Галерея содержит 1 197 образцов состояний по умолчанию на полу 128×128, с шагом 3; это обзор всех типов блоков, а не всех 32 тысяч вариантов. Начальная позиция галереи — `[-50,2,58]`; клиент подгружает её частями по мере перемещения.
|
||||
|
||||
## Владение состоянием
|
||||
|
||||
Один выделенный поток владеет WorldStore, физикой и игровым состоянием. HTTP и WebSocket ставят ограниченные команды в очередь. Движение считается 20 раз в секунду: скорость 5 блоков/с, гравитация 20 блоков/с², обычный прыжок 7 блоков/с. Игрок занимает AABB 0.6×1.8 блока; позиция задаёт середину стоп. Оси +Y вверх, yaw растёт вправо, pitch вверх; направление взгляда `[sin(yaw)*cos(pitch),sin(pitch),-cos(yaw)*cos(pitch)]`.
|
||||
|
||||
Игровые позиции и точки появления ограничены диапазоном ±32 700 по каждой оси: физика этого клиента использует `f32`. Хранилище и конвертер сохраняют более широкий контракт ±30 000 000; это не обещание игровой физики на дальних координатах. Выход игрока за игровой диапазон возвращает его на spawn, а в активном матче означает выбывание.
|
||||
|
||||
Ввод содержит намерение двигаться, а не позицию. Сервер проверяет дальность 6 блоков, ближайшее пересечение форм, ячейку установки, пересечение с игроком и правила арены. Просроченный ввод обнуляется через секунду. Игровая физика использует ограниченную область соседних блоков на каждый тик; независимые миры без игроков не требуют массива загруженных секций.
|
||||
|
||||
В `worlds.sqlite3` хранятся блоки и их история. В `server.sqlite3` — конфигурация и сохраняемые сущности с отдельной ревизией. Это две транзакционные области: создание мира и добавление его настроек не заявляются одной общей транзакцией. Если сохранение настроек не удалось после создания мира, мир доступен с безопасными настройками по умолчанию; ошибку нельзя интерпретировать как разрешение повторно создать тот же мир. Для сущностей и настроек неуспешная запись восстанавливает состояние из последней сохранённой версии. Если даже чтение SQLite невозможно, операция возвращает ошибку; ошибка хранения не объявляется успешным подтверждением.
|
||||
|
||||
## HTTP и авторизация
|
||||
|
||||
Публичные GET: `/api/health`, `/api/manifest`, `/api/worlds`, `/api/catalog`, `/api/entities`, `/api/metrics`. Каталог принимает `query`, `offset`, `limit` (1–256) `ids` с максимум 128 runtime ID или `states` с каноническими состояниями, разделёнными запятыми вне скобок свойств. Runtime ID берётся из ответа; он не совпадает с числовым ID Minecraft.
|
||||
|
||||
`POST /api/control` принимает `{ "method": "world.read", "params": {...} }`, возвращает `{ "result": ... }` или HTTP 400 с `{ "error": "..." }`. Требуется `Authorization: Bearer <token>`. При первом запуске файл `control.token` создаётся с режимом 0600 на Unix. Параметры операций доступны в схемах `tools/list` отдельного MCP. Названия Control API используют точку: `world.edit`, `build.plan`, `camera.capture` и т.д.
|
||||
|
||||
Токен не является секретом от администратора локальной машины. Хеш manifest подтверждает совместимость ресурсов; он не доказывает неизменность исполняемого кода клиента. Защита игрового состояния основана на серверных проверках. Origin для браузерного WebSocket и Control API проверяется; межсайтовый доступ не включён.
|
||||
|
||||
## WebSocket, снимки и правки
|
||||
|
||||
Первое сообщение на `/ws` в течение 10 секунд:
|
||||
|
||||
```json
|
||||
{"type":"join","protocol":1,"manifest_hash":"из /api/manifest","name":"Игрок","world":"lobby"}
|
||||
```
|
||||
|
||||
`welcome` содержит `id`, `world`, `revision`, `blocks:[{pos,block}]`, определения использованных `materials`, `players`, `entities`, `spawn`, `view_center` и `manifest_hash`. Снимок покрывает `[centerX-32, centerY-8, centerZ-32]…[centerX+31, centerY+31, centerZ+31]`, максимумы включительные. При перемещении центра видимости сервер присылает новый `snapshot`; клиент полностью заменяет геометрию. Полный строковый реестр в снимке не передаётся. `materials` ограничен 256 записями и 128 КиБ; остальные определения клиент последовательно запрашивает через `/api/catalog?ids=1,2,...&limit=128`. Это позволяет войти в мир с большой палитрой, не переполняя исходящую очередь.
|
||||
|
||||
Клиент отправляет `input` с `seq,yaw,pitch,forward,strafe,jump`; `break` с `pos`; `place` с `pos,block` или `state`; `switch_world`, `resync`, `respawn`, `start_match`, `chat`, `ping`. Ответ `state` содержит авторитетные позиции, `tick`, подтверждённый `ack` и состояние матча. Блоки приходят в `blocks` с новой ревизией. При пропуске ревизии клиент запрашивает снимок. Подписка и создание снимка сериализованы с правками в одном потоке, поэтому промежуточная правка не теряется.
|
||||
|
||||
Для управляющих правок сохраняется контракт ядра: ожидаемая ревизия, уникальный `operation_id`, durable-подтверждение, повтор того же запроса без второй записи, отказ при конфликте. План строительства занимает не более 32 768 ячеек, хранится 5 минут, максимум 16 планов; preview не меняет мир. Планы эфемерны и исчезают после перезапуска, принятые правки остаются на диске. `camera.capture` возвращает PNG изометрической серверной проекции и точную ревизию; это не кадр WebGL-камеры игрока.
|
||||
|
||||
## Правила Spleef
|
||||
|
||||
Матч проходит `waiting → countdown → active → finished → waiting`. По умолчанию нужны 2 игрока, отсчёт занимает 3 секунды, раунд — до 180 секунд. Разрешено разрушать только `minecraft:snow_block` в активном раунде; установка блоков и разрушение границы запрещены. Падение ниже Y=−6 означает выбывание. При одном оставшемся участнике объявляется победитель; истечение времени с несколькими оставшимися даёт ничью. После результата через 5 секунд мир возвращается к своему закреплённому шаблону, игроки — на spawn. Арены независимы. Отключение/уход из мира исключает участника; повторный вход во время раунда остаётся входом зрителя. После перезапуска прерванный матч сбрасывается к шаблону.
|
||||
|
||||
`arena.configure` сохраняет настройки мира. Изменять их можно между матчами; попытка во время countdown/active/finished отклоняется. Доступны `mode`, `spawn` и следующие поля:
|
||||
|
||||
- `countdown_seconds`: целое 1…30, по умолчанию 3; `round_seconds`: целое 1…3600, по умолчанию 180.
|
||||
- `min_players`: целое 2…32, по умолчанию 2.
|
||||
- `elimination_y`: конечная координата в пределах ±32 700, по умолчанию −6.
|
||||
- `spawn_points`: до 32 точек `[x,y,z]`. Пустой список означает круг радиуса 7 вокруг X/Z=0 на высоте `spawn[1]`. Непустой список должен вмещать минимум участников, а при старте — всех вошедших; точки располагаются не ближе 0.8 блока друг к другу.
|
||||
- `spectator_spawn`: точка зрителя, по умолчанию `[13,2,0]`.
|
||||
- `floor_block`: известное каноническое состояние с коллизией, которое участникам разрешено разрушать. По умолчанию `minecraft:snow_block`. Пол в закреплённой карте должен уже содержать этот материал; configure не перекрашивает и не перестраивает карту.
|
||||
|
||||
Все точки появления находятся в игровом диапазоне, их Y выше `elimination_y + 0.5`. Необязательный `expected_revision` проверяет общую ревизию метаданных, доступную через `entity.list`/`metrics`; это отдельная ревизия от блоков мира. Правила возвращаются в `match.rules`. Старые настройки с двумя полями `mode/spawn` читаются с указанными значениями по умолчанию.
|
||||
|
||||
Журнал идемпотентности ядра относится к правкам блоков, undo/reset и подтверждению плана. Операции сущностей и настройки арен пока не имеют такого журнала: повторный `entity.spawn` создаёт ещё один экземпляр. После неопределённого сетевого результата сначала следует прочитать текущее состояние.
|
||||
|
||||
## Лимиты и наблюдаемость
|
||||
|
||||
- 32 WebSocket-сессии, включая ожидающие join; 16 одновременно обслуживаемых HTTP-запросов, очередь 64 команд.
|
||||
- Входное сообщение WebSocket до 64 КиБ, максимум 80 сообщений/с на соединение; действия блоков не чаще 110 мс, чат не чаще 700 мс, явный resync не чаще 500 мс, переход между мирами не чаще секунды, автоматический снимок при смене секции не чаще 2 секунд.
|
||||
- Control API до 2 МиБ JSON; штатная правка до 32 768 ячеек; чтение до 262 144 ячеек и 6 МиБ ответа; при превышении байтового лимита требуется уменьшить область.
|
||||
- Исходящая очередь на клиента: 16 сообщений и 8 МиБ. При переполнении или превышении срока отправки медленное соединение закрывается. Общее верхнее ограничение очередей зависит от числа клиентов; эти байты не следует путать с кэшем секций.
|
||||
- Метаданные сервера до 8 МиБ, до 4096 сущностей, свойства одной сущности до 16 КиБ. В игровые снимки входят компактные представления без произвольного JSON свойств; полные свойства читаются через `entity.list` с offset и limit (по умолчанию 64, максимум 128).
|
||||
- RAM процесса в `/api/metrics` — фактический Linux VmRSS, а `storage.cache_payload_bytes` — только полезные байты кодированных секций. Каталог, строки, SQLite, сетевые буферы, временные чтения и память аллокатора существуют отдельно.
|
||||
|
||||
Максимальная разрешённая конфигурация лимитов не равна измеренному целевому профилю нагрузки. Условия и результаты benchmark публикуются в VERIFICATION; заявлений о выигрыше относительно Paper без сопоставимого прогона нет.
|
||||
|
||||
## Сущности и совместимость
|
||||
|
||||
158 определений сущностей имеют реальные размеры и авторские процедурные модели. Сохраняемые экземпляры создаются, перемещаются и удаляются через MCP. Полноценные ванильные AI, redstone, жидкости, инвентари и игровая логика Minecraft не реализованы. Формы контекстно зависимых блоков явно отмечены в каталоге. Изменённые и неизвестные данные конвертер обрабатывает по правилам `docs/interop.md`, без молчаливого объявления lossless-совместимости.
|
||||
+21
-39
@@ -1,49 +1,31 @@
|
||||
# Состояние проекта
|
||||
|
||||
Обновлено: 2026-09-14. Рабочая папка: `/home/emil/Desktop/shacraft-core`.
|
||||
Обновлено 2026-09-14. Реализован и локально проверен весь согласованный профиль MVP. Рабочая папка: `/home/emil/Desktop/shacraft-core`. Исходный план сохранён до реализации коммитом `ddfcef2`; результаты старой облачной среды не использовались как доказательство.
|
||||
|
||||
## Завершено: планирование и первый этап хранения
|
||||
## Готово
|
||||
|
||||
План сохранён **до реализации**, отдельным Git-коммитом `ddfcef2`. Исходники старой облачной среды не восстановлены и не использованы как доказательство работы новой реализации.
|
||||
- Самостоятельное ядро Rust: компактные секции, общий ограниченный LRU, долговечные правки и история, immutable snapshots, независимые миры, revision/idempotency, undo/reset.
|
||||
- Отдельный авторитетный сервер с игровым циклом 20 Гц, проверкой движения/форм/дальности, ограниченными очередями, сохраняемыми настройками и сущностями.
|
||||
- Собственный браузерный WebGL2-клиент: строительство, каталог, игроки/сущности, чат, миры, загрузка пакетов и диагностика. Нет зависимости от готового игрового движка.
|
||||
- Настоящий отдельный stdio MCP: 17 инструментов, 4 ресурса, строительный prompt, планы/commit, визуальный PNG и проверка через независимый MCP SDK.
|
||||
- Полный каталог Java 26.2: 1 196 блоков, 32 366 состояний, 158 сущностей, DataVersion 4903. Коллизии измерены через официальный API, модели авторские; контекстные случаи отмечены.
|
||||
- Пакеты: точные версии, граф зависимостей, SHA-256/размеры, приватные серверные файлы, проверяемый клиентский кэш. Действующий WASM `on_jump`, пользовательские определения блоков и собственные текстуры/шейдер/звук.
|
||||
- Spleef: две независимые арены общей карты, отсчёт, выбывание, победитель/ничья, сброс, spectators, сохраняемые правила, восстановление после прерывания. Лобби и галерея 1 197 образцов.
|
||||
- Anvil и Sponge v3 import/export: типизированный NBT, сохранение оригинала, атомарная публикация, отчёты о потерях/преобразованиях, перенос игровых правок блоков и сущностей.
|
||||
|
||||
Работают две crate:
|
||||
## Проверено
|
||||
|
||||
- `shacraft-core`: versioned codec секций 16³ (uniform/palette/dense), компактный LRU, долговечный реестр, SQLite/WAL/FULL, блокировка второго писателя, неизменяемые снимки, независимые экземпляры, атомарные edit, revision/idempotency, undo/reset и явная уборка недостижимых blobs.
|
||||
- `shacraft-tools`: локальная JSON-lines сессия для тестирования API, demo, stats и воспроизводимый storage benchmark. Это не MCP и не игровой сервер.
|
||||
84 Rust-теста, 6 JS-тестов, fmt и Clippy без предупреждений; 14 групп реальных HTTP/WebSocket-сценариев, отдельная MCP SDK-сессия, SIGKILL и восстановление. Экспорты прочитаны официальными Java 26.2 codecs и независимым NBT-читателем. Клиент осмотрен в реальном браузере; подтверждены отрисовка, поиск состояний, переход в галерею, догрузка материалов, повторное соединение и кэш ресурсов.
|
||||
|
||||
Проверено на Linux x86_64 с Rust 1.96.0:
|
||||
Финальный release-стенд: 100 пустующих экземпляров карты — 50.50 МиБ RSS; 10 движущихся клиентов — максимум 59.65 МиБ RSS/VmHWM, p95 выборки работы тика 7.33–9.54 мс. Это ограниченный локальный профиль, не сравнение с Paper. Команды и доказательства — [VERIFICATION](VERIFICATION.md).
|
||||
|
||||
- `cargo fmt` и Clippy с запретом предупреждений.
|
||||
- 29 Rust-тестов: 11 codec, 8 black-box контрактов, 10 хранения.
|
||||
- Отдельные процессы: 80 подтверждённых правок → SIGKILL → восстановление реестра/данных/replay; прерывание транзакции на 32768 ячеек → отсутствие частичного состояния → безопасный повтор.
|
||||
- Вытеснение различных секций при превышении кэша; однородная секция остаётся компактной и в RAM.
|
||||
- Release demo и синтетический benchmark: 256 секций, 100 независимых экземпляров, чтение сверх кэша, edit/reset каждого экземпляра.
|
||||
## Точные границы
|
||||
|
||||
Команды и результаты: [DEVELOPMENT](DEVELOPMENT.md), [VERIFICATION](VERIFICATION.md), `docs/verification/`.
|
||||
- Это самостоятельная миниигровая платформа с каталогом Minecraft, не полная ванильная симуляция: нет полного AI, redstone, инвентарей или симуляции жидкостей. Формы с зависимостью от контекста помечены; модели не повторяют ванильные ассеты.
|
||||
- `exact` консервативно отказывает после правок; `best-effort` отражает изменения и выдаёт отчёт. Между Anvil и `.schem` не вся семантика биомов/block entities преобразуется — исходные данные архивируются. Ограничения версий, размеров и контекстов описаны в interop.md.
|
||||
- История блоков хранится на диске без автоматического удаления. Undo допускает только текущую целевую правку. Preview-планы эфемерны, 5 минут. Метаданные сущностей/правил имеют отдельную ревизию; их API не заявляет журнал идемпотентности ядра.
|
||||
- Предел игрового пространства с f32-физикой — ±32700; хранение и конвертер поддерживают координаты ядра ±30 миллионов. Память ограничивается несколькими структурами, а не одним магическим RSS-лимитом.
|
||||
- Проверены Linux x86_64 и локальная нагрузка. Длительный продакшен soak, аппаратное отключение питания, все ОС и игровой плейтест экспорта в запущенном Minecraft не заявляются пройденными.
|
||||
- Лаунчер, аккаунты, продакшен и существующие серверы — последующая интеграция. Ничего не опубликовано и не развёрнуто на удалённых машинах.
|
||||
|
||||
## Следующий этап: сервер и тестовый клиент
|
||||
|
||||
1. Добавить crate сервера с игровым циклом отдельно от долговечных редакторских транзакций. Не выполнять SQL/FULL commit каждого игрового ввода.
|
||||
2. Уточнить протокол resync, подписку без разрыва между снимком и изменениями, переключение миров и лимиты очередей.
|
||||
3. Реализовать серверные движение/коллизии/взаимодействия и минимальный WebGL2-клиент по решению D003.
|
||||
4. Пройти сценарий двух клиентов с общими блоками и независимыми мирами.
|
||||
5. Затем подключить собственный MCP через общий Control API, полный каталог и конвертер согласно PLAN.
|
||||
|
||||
## Ограничения первого этапа
|
||||
|
||||
- Полный MVP ещё не завершён. Нет игрового сервера, графического клиента, MCP, каталога 26.2, конвертера, системы исполняемых модулей и миниигры.
|
||||
- Undo консервативный: только целевая правка на текущей ревизии, без последующих операций. Каждый новый успешный edit, включая no-op, повышает ревизию. Retry не повышает.
|
||||
- История остаётся на диске без автоматического удаления. GC ограничивает число удалённых blobs, но не время сканирования. Он не удаляет историю/снимки и не уменьшает физический файл через VACUUM.
|
||||
- Реестр строк находится в RAM: максимум 262144 состояния по 512 ASCII-байт. Кэш секций не является лимитом всей памяти процесса. SQLite page-cache budget — настройка движка, не жёсткий RSS-лимит.
|
||||
- Benchmark проверяет хранение, не игроков/тики/полный каталог и не сравнительную экономию относительно Paper.
|
||||
- SIGKILL не имитирует отключение питания и отказы накопителя. Платформы вне Linux пока не проверены.
|
||||
- Продакшен, существующий лаунчер и удалённые репозитории не изменялись.
|
||||
|
||||
## Правила продолжения
|
||||
|
||||
- Перед работой прочитать REQUIREMENTS, PLAN, DECISIONS, CONTRACT и этот файл.
|
||||
- Новые результаты подтверждать командами, тестами или видимым поведением; старый облачный отчёт не использовать как доказательство.
|
||||
- Не помечать весь MVP готовым по завершению одного этапа.
|
||||
- Отмечать точные ограничения контента, конвертера, клиента, модулей и безопасности.
|
||||
- Команды запуска и проверки сохранять в репозитории; изменения коммитить в локальный Git после проверки.
|
||||
- Не помещать токены, данные реальных игроков и проприетарные ассеты в Git и архивы.
|
||||
Контракты компонентов: SERVER.md, MCP.md, CONTENT.md, PACKAGES.md, interop.md. Исходники и release-бинарные файлы упаковывает `scripts/make_release.py`; в архивы не входят токены, локальные миры и Minecraft JAR.
|
||||
|
||||
+50
-22
@@ -1,32 +1,60 @@
|
||||
# Проверки первого этапа, 14 сентября 2026
|
||||
# Проверка локального MVP
|
||||
|
||||
Проверены библиотека хранения и CLI. Рубеж A из ACCEPTANCE.md целиком ещё не пройден: сервер/клиент/MCP отсутствуют. Результаты ниже не объявляют полный MVP готовым.
|
||||
Дата: 2026-09-14. Стенд: Linux x86_64, AMD Ryzen 7 1700, Rust/Cargo 1.96.0, Node 22.22.3, Python 3.14.4. Точные версии — [environment.json](verification/environment.json). Исходная ревизия выпуска фиксируется в `RELEASE.json` каждого архива.
|
||||
|
||||
## Автоматические проверки
|
||||
|
||||
Команда `bash scripts/verify.sh` завершилась с кодом 0. В [полном журнале](verification/checks.txt) сохранены:
|
||||
|
||||
- форматирование и Clippy `--workspace --all-targets --locked -- -D warnings` без ошибок;
|
||||
- 29 Rust-тестов (11 секционного формата, 8 публичных контрактов, 10 хранилища);
|
||||
- сборка CLI;
|
||||
- девять проверок отдельного процесса, включая принудительное завершение и восстановление.
|
||||
|
||||
В аварийном сценарии 80 правок были подтверждены процессом до SIGKILL и сохранились после повторного открытия. Повтор старой операции вернул её исходный результат без повторной правки. Большая операция на 32768 блоков, завершения которой вызывающий код не наблюдал, восстановилась целиком или отсутствовала целиком; безопасный повтор завершился на одной ревизии. Дополнительно SQL-тест принудительно вызывает отказ в середине изменения и проверяет откат данных, истории и ревизии.
|
||||
|
||||
## Проверка работы и хранения
|
||||
|
||||
`cargo build --release -p shacraft-tools --locked` завершилась успешно. [Результат demo](verification/demo.json) подтверждает сценарий общей карты, двух экземпляров, изолированной правки, undo и reset.
|
||||
|
||||
[Сырой результат benchmark](verification/storage-benchmark.json) получен командой:
|
||||
|
||||
```bash
|
||||
target/release/shacraft-tools --data <пустой-временный-каталог> --cache 8 benchmark --sections 256 --worlds 100
|
||||
bash scripts/verify.sh
|
||||
cargo build --release --workspace --locked
|
||||
node scripts/check_server.mjs --binary target/release/shacraft-server --output artifacts/server-e2e-release.json
|
||||
node scripts/check_mcp.mjs --binary target/release/shacraft-server --output artifacts/mcp-sdk.json
|
||||
node scripts/benchmark_server.mjs --binary target/release/shacraft-server --output artifacts/server-benchmark-final.json
|
||||
```
|
||||
|
||||
После создания 100 экземпляров количество blobs осталось 256: карты разделяют неизменяемые данные. После обхода карты резидентный кэш остался в пределах восьми записей и зафиксировал вытеснения. Все экземпляры прошли независимую правку и сброс. RSS, размеры файлов и длительности сохранены в JSON вместе с версией Rust и системой.
|
||||
`verify.sh` завершился с кодом 0: fmt, Clippy `-D warnings`, **84 Rust-теста** (core 30, content 11, compat 17, MCP 8, server/WASM 18), **6 JS-тестов**, отдельная аварийная проверка хранилища и debug HTTP/WebSocket-сценарий. [Полный журнал](verification/mvp-checks.txt).
|
||||
|
||||
Это один синтетический прогон на небольшом реестре из двух состояний, без сети, игроков и симуляции. Не использовать его для оценки готового сервера или сравнения с Paper. Байты закодированных секций не включают служебные структуры/аллокатор; RSS измеряется отдельно.
|
||||
Release-прогон прошёл **14 групп**: проверка ресурсов/авторизации, несовместимый manifest, два клиента, авторитетное движение, недостижимая правка, реальные break/place, последовательные ревизии, late join, immutable template/изоляция, чат, события сущностей, reconnect, полный Spleef и reset, удаление отключённых игроков, **SIGKILL → восстановление блоков, свойств сущностей и настроек**. [Отчёт](verification/server-e2e.json).
|
||||
|
||||
## Ограничения доказательств
|
||||
Настоящий MCP SDK 1.30.0 прошёл initialize/notification/ping, 17 schemas, 4 resources, prompt, durable edit/replay/conflict/undo, plan/commit/retry, PNG image content, entities CRUD, настройки, metrics/reset. [Отчёт SDK](verification/mcp-sdk.json). Для воспроизведения установить независимый клиент:
|
||||
|
||||
Подтверждена работа на Linux x86_64. Тесты завершения процесса не имитируют отключение питания или аппаратные сбои. Часть защиты от повреждений проверяется на намеренно изменённых временных SQLite-базах; реальные миры пользователя не затрагиваются. Интеграция с Minecraft, лаунчером и MCP относится к следующим этапам и пока не проверялась.
|
||||
```bash
|
||||
npm install --prefix artifacts/mcp-sdk --no-package-lock @modelcontextprotocol/sdk@1.30.0
|
||||
SHACRAFT_MCP_SDK="$PWD/artifacts/mcp-sdk/node_modules/@modelcontextprotocol/sdk" node scripts/check_mcp.mjs --binary target/release/shacraft-server --output artifacts/mcp-sdk.json
|
||||
```
|
||||
|
||||
В репозитории нет зависимости рабочего клиента от Node/MCP SDK. Они нужны только проверке.
|
||||
|
||||
## Каталог и совместимость
|
||||
|
||||
Каталог сравнивается с независимой проекцией официальных отчётов по всем каноническим состояниям, properties/defaults и множеству сущностей. Отдельно проверены геометрия, ориентации плит/ступеней/дверей, контекстные случаи, entity dimensions. Повторный полный генератор отчётов/API и авторских ресурсов воспроизвёл файлы побайтно: [reproducibility](verification/catalog-reproducibility.json).
|
||||
|
||||
17 converter-тестов покрывают типизированный NBT, compression modes/external chunks, палитры, negative coordinates, unknown data, offset/3D biomes, удаление stale chest data, original checksums, no-overwrite, invalid input, создание/перемещение/удаление сущностей и отдельный entity fingerprint.
|
||||
|
||||
Официальный Java 26.2 прочитал exact (1 chunk, 3 блока, 1 сущность), edited (2 chunks, 3 блока, 1 сущность) и новый экспорт (2 chunks, 2 блока). nbtlib 2.0.4 проверил Sponge-теги и их числовые типы. [Машиночитаемый результат](verification/interop.json), [команды и ограничения](interop.md). Использовались публичные codecs без запуска Minecraft-сервера и без принятия EULA.
|
||||
|
||||
## Память и тик
|
||||
|
||||
Бюджеты записаны в скрипте **до прогона**: 256 МиБ для процесса с 10 клиентами, p95 выборки работы тика ≤50 мс. Полный каталог включён. Один сервер содержит 5 служебных/демонстрационных миров и 1, 10, затем 100 дополнительных immutable forks лобби. Активные этапы: 10 клиентов в одной области общего мира и в отдельных мирах, движение/прыжок с вводом 20 Гц, по 15 секунд; метрики каждые 100 мс. Затем все клиенты отключаются. Linux VmHWM дополнительно фиксирует пик процесса, включая промежутки между выборками.
|
||||
|
||||
Финальный прогон:
|
||||
|
||||
- 1 / 10 / 100 пустующих forks: максимальный RSS **50.28 / 50.35 / 50.50 МиБ**.
|
||||
- 10 клиентов в общем мире: RSS/VmHWM **57.00 МиБ**, p95 работы тика **9.54 мс**.
|
||||
- 10 клиентов в 10 мирах: RSS/VmHWM **59.65 МиБ**, p95 **7.33 мс**.
|
||||
- После отключения: 0 игроков и 0 активных миров; RSS остаётся **59.65 МиБ** из-за удерживаемого кэша/аллокатора. Нулевое число активных миров не означает нулевой RSS.
|
||||
- Ограничение кэша выполнено во всех выборках, исходящие очереди и активные миры измерены. Оба заранее заданных бюджета пройдены.
|
||||
|
||||
[Полные фазы и исходные выборки](verification/server-benchmark.json). p95 рассчитан по выборке последней работы тика, не по сетевой задержке и не по всей непрерывной последовательности тиков. Это короткий локальный тест движения; нагрузка ванильных механик, тысячи игроков и бесконечные пользовательские миры не включены. С Paper/NeoForge результат не сравнивался.
|
||||
|
||||
Отдельный storage benchmark этапа 1 сохраняется в [storage-benchmark.json](verification/storage-benchmark.json): 256 уникальных секций, кэш 8, 100 forks, обход сверх кэша и независимые edit/reset. После создания forks число immutable blobs осталось 256. Это синтетический профиль ядра с двумя состояниями, отдельный от полного сервера.
|
||||
|
||||
## Браузер и поставка
|
||||
|
||||
[Браузерный протокол проверки](verification/browser.md) фиксирует реальные снимки/DOM, каталог, неполные формы, сущности, чистое подключение без полного registry, галерею, повторное соединение и проверенный ресурсный кэш. На этом стенде наблюдались 144 FPS; переносить это число на другие устройства нельзя.
|
||||
|
||||
`python3 scripts/make_release.py` и вариант `--binaries` создают архив из чистого Git-коммита, добавляют `RELEASE.json` с SHA-256 каждого файла и проверяют каждый файл при повторном чтении архива. Соседний `.sha256` проверяет весь архив. Поставка проверяется повторной распаковкой, offline Cargo-проверкой исходников и запуском извлечённого Linux-бинарного файла с ресурсами из архива. Итоговый журнал упаковки находится рядом с архивами в `artifacts/`.
|
||||
|
||||
## Границы приёмки
|
||||
|
||||
Основные рубежи A-CORE/SERVER/CLIENT/MCP/SPLEEF подтверждены перечисленными тестами и браузерным осмотром. B-CONTENT, B-PACKAGES, B-INTEROP, B-PERSISTENCE выполнены в документированном профиле. B-MEMORY подтверждён указанной нагрузкой, а не произвольным масштабом. Более широкие пункты исходного ACCEPTANCE (долгий soak, все игровые контексты Minecraft, все варианты внешних миров и реальный Minecraft-плейтест) не объявляются пройденными. Заявления о полной ванильной симуляции, аппаратной отказоустойчивости или экономии относительно Paper отсутствуют.
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
# Interchange MVP: Java 26.2 и Sponge v3
|
||||
|
||||
`shacraft-compat` — отдельная Rust-библиотека и автономная CLI. Она действительно переносит состояния блоков в `WorldStore`: браузер, Control API и MCP редактируют импортированные данные, а экспорт читает текущие секции. Исходный мир хранится отдельно на диске с SHA-256. Возврат оригинала без изменений является отдельным проверенным режимом.
|
||||
|
||||
Целевая версия: **Minecraft Java 26.2, DataVersion 4903**. Библиотека не запускает JVM. Java 25 нужна только воспроизводимой проверке и генератору собственных тестовых сохранений.
|
||||
|
||||
## Команды
|
||||
|
||||
Команды выполняются из корня репозитория. Все выходные пути должны отсутствовать. Каждый экспорт публикует **каталог**, даже экспорт одной постройки: в нём находятся `world.schem` и `conversion-report.json`. Если исходный мир уже содержит файл с этим именем, новый отчёт получает числовой суффикс; исходный файл сохраняется.
|
||||
|
||||
```bash
|
||||
cargo build --release -p shacraft-compat -p shacraft-server
|
||||
|
||||
# Импорт остановленной копии Java-мира в новый native store.
|
||||
target/release/shacraft-compat import-anvil /path/to/java-world data/imported
|
||||
|
||||
# Открыть импорт в браузере через сервер; в списке миров выбрать main.
|
||||
target/release/shacraft-server --data data/imported --listen 127.0.0.1:4000
|
||||
|
||||
# После остановки сервера: все импортированные измерения вместе.
|
||||
target/release/shacraft-compat export-anvil data/imported artifacts/return-exact
|
||||
target/release/shacraft-compat export-anvil data/imported artifacts/return-edited --mode best-effort
|
||||
|
||||
# Новый мир Shacraft: полноценный каталог сохранения Java 26.2.
|
||||
target/release/shacraft-compat export-anvil data artifacts/new-java-world --world lobby --mode best-effort
|
||||
|
||||
# Sponge v3; Offset переносится в координаты native мира.
|
||||
target/release/shacraft-compat import-schem /path/to/build.schem data/build --world main
|
||||
target/release/shacraft-compat export-schem data/build artifacts/build-edited --mode best-effort
|
||||
|
||||
# Экспорт ограниченного объёма нового native мира; границы включительные.
|
||||
target/release/shacraft-compat export-schem data artifacts/build --world lobby --min=-16,-1,-16 --max=16,15,16
|
||||
```
|
||||
|
||||
CLI печатает отчёт JSON в stdout, ошибки — JSON в stderr и ненулевой exit code. Конвертация выполняется offline: `WorldStore` удерживает ту же блокировку единственного писателя, что сервер, поэтому параллельное редактирование не смешивает ревизии в одном экспорте. Сам исходный Java-мир должен быть остановленной копией: изменения размера/времени файла во время копирования обнаруживаются, но это не заменяет согласованный backup работающего Minecraft.
|
||||
|
||||
## Что реализовано
|
||||
|
||||
- Big-endian NBT: все 12 payload-типов, числовые разрядности, float/double bit patterns, signed arrays, Java modified UTF-8/CESU-8, Unicode, тип элемента пустого списка и неизвестные compound-поля. Duplicate compound keys, невозможные длины, превышение глубины и лишние распакованные байты отклоняются.
|
||||
- Anvil: `level.dat`, обычные измерения, `dimensions/<namespace>/<path>`, секционные палитры `Name`/`Properties`, современные непересекающие 64-битную границу индексы, отрицательные координаты, единообразные секции, биомы. Чтение gzip, zlib, raw и LZ4Block с checksum, включая внешние `c.x.z.mcc`. Запись zlib и внешний payload для chunk более 255 секторов.
|
||||
- Исходные `entities`, `block_entities`, POI, биомы, inventories, playerdata, datapacks, неизвестные поля и произвольные обычные файлы сохраняются на диске. Отдельные entity region-файлы действительно читаются для серверного представления, а не только копируются.
|
||||
- Sponge v3: `Blocks`, sparse palette indices и varints, block entities, сущности, полный 3D-контейнер биомов, размеры, Offset, Metadata и неизвестные теги. Контейнер `Schematic` вложен в корневой NBT compound согласно спецификации.
|
||||
- Новый Anvil-мир использует собственный маленький шаблон сохранения, созданный public API Java 26.2. В 26.2 параметры генерации и game rules находятся в `data/minecraft/world_gen_settings.dat` и `game_rules.dat`; экспорт включает эти файлы. Генератор — пустой flat overworld, creative, три стандартных измерения, биом plains в новых секциях, высота редактируемого экспорта −64…319.
|
||||
|
||||
## Сущности между MCP и файлами мира
|
||||
|
||||
Импорт создаёт совместимый `server.sqlite3`, таблица `metadata(id,json)`. До 4 096 сущностей становятся доступны через сервер и MCP с исходными UUID, типом, координатами и поворотом. Остальные сущности, неподходящие координаты и неподдерживаемые записи остаются в оригинале и отмечаются `preserved`; они не превращаются в пропавшие данные.
|
||||
|
||||
Исходный типизированный NBT каждой редактируемой сущности находится в `compat/entities/<uuid>.nbt`; его хеш закреплён в provenance. `compat/native-entities.json` содержит исходное серверное представление. Экспорт отдельно сравнивает fingerprint сущностей и ревизии блоков, поэтому перемещение сущности без правки блоков также отклоняет `exact`.
|
||||
|
||||
`best-effort` применяет создание, удаление и перемещение сущностей между chunks/regions и измерениями, а также yaw в радианах из серверного API. Явно поддерживаются свойства `Health`, `CustomName`, `NoGravity`, `Invisible`, `Invulnerable`, `Glowing`, `Silent`, `CustomNameVisible` с соответствующими числовыми/строковыми/логическими типами. Прочие свойства JSON сохраняются в `shacraft-native-entities*.json` и получают `entity_property_unmapped`; они не выдаются за vanilla NBT. Оригинальный NBT сохраняет остальные поля. AI, passengers, leash и связанные UUID не симулируются и не получают обещания точной семантики после перемещения.
|
||||
|
||||
## Exact и best-effort
|
||||
|
||||
`exact` использует DataVersion 4903 и тот же формат, что источник. Пока **любая новая ревизия блоков или изменённое серверное представление сущностей** консервативно запрещает точный возврат исходного мира/постройки. Это касается даже отменённой правки, восстановившей те же блоки: ревизия не возвращается назад. Без правок все исходные файлы побайтно идентичны после проверки SHA-256.
|
||||
|
||||
Для нового native мира `exact` поддерживает представимый Sponge v3. Создание нового Anvil-окружения и межформатное преобразование требуют `best-effort`, поскольку свет и производные данные нуждаются в восстановлении Minecraft. Режим не содержит скрытых замен блоков. Неизвестный namespace остаётся в палитре и получает `unsupported`: целевому Minecraft нужен соответствующий мод, иначе он может заменить неизвестный блок воздухом.
|
||||
|
||||
В изменённых Anvil chunks экспорт обновляет палитры/блоки, удаляет сохранённые light arrays и heightmaps, устанавливает `isLightOn=false`, удаляет устаревшие block entities и scheduled ticks непосредственно в изменённых координатах, инвалидирует POI record изменённого chunk. Все эти действия перечислены в отчёте, оригиналы находятся в `shacraft-source-sidecar*`. Это проверенный профиль сериализации и инвалидации; прохождение полной игровой симуляции света/POI не заявляется.
|
||||
|
||||
При экспорте между `.schem` и Anvil переносится блоковая модель и явный entity bridge. Биомная сетка, block entities и произвольные metadata разных форматов пока архивируются без преобразования и получают `cross_format_opaque_data`. Оригинал находится рядом с результатом. Неподдерживаемые версии не мигрируют через DataFixer: `exact` отказывает, а `best-effort` сохраняет исходный DataVersion и диагностирует непроверенную схему.
|
||||
|
||||
## Ограничения ресурсов и публикация
|
||||
|
||||
- Не более 16 MiB распакованного NBT на chunk/постройку, глубина 64, до 1 000 000 NBT nodes. Это лимиты входных данных, не обещание 16 MiB RSS: Rust-структуры и строки занимают дополнительную память.
|
||||
- Sponge: максимум 262 144 вокселя; Anvil обрабатывается по одному chunk, экспортная очередь координат находится на диске, страницы секций — не более 4 096 ключей. Кэш ядра конвертера — 32 секции плюс ограниченный SQLite cache.
|
||||
- Entity bridge: 4 096 записей, до 16 KiB properties на сущность, ограничение сериализованного metadata 8 MiB (импортируемый entity subset ограничен 6 MiB с запасом для настроек сервера). Избыточные исходные сущности сохраняются без загрузки всех записей в серверную RAM.
|
||||
- До 1 000 подробных issue в отчёте; `omitted_issues` явно считает оставшиеся события. До 256 импортированных измерений, 1 000 000 файлов, 8 GiB на исходный файл и 1 TiB суммарного источника. Symlinks, специальные файлы, выход из каталога, вложенный в исходный мир destination и повреждённые region headers отклоняются.
|
||||
- Импорт строит весь новый native store, metadata и provenance в соседнем временном каталоге. Экспорт тоже использует staging. Файлы и каталоги синхронизируются, публикация — Linux `renameat2(RENAME_NOREPLACE)` и fsync родителя. Конвертер никогда не перезаписывает существующий destination и не меняет исходный Java-мир.
|
||||
- При штатной ошибке staging удаляется; после SIGKILL может остаться непубликованный `.shacraft-convert-*`. Повторный импорт безопасно начинается заново. Возобновление с последнего chunk после аварии ещё не реализовано. Нужен запас диска: исходный архив плюс native DB, а изменённый экспорт сохраняет ещё одну полную копию исходника.
|
||||
|
||||
`.schem` v2, legacy `.schematic`, vanilla structure `.nbt`, произвольные повороты/миграции версий и полная ванильная симуляция не включены в этот профиль. Они не распознаются как v3 по расширению файла.
|
||||
|
||||
## Воспроизводимая проверка
|
||||
|
||||
```bash
|
||||
cargo test -p shacraft-compat
|
||||
cargo clippy -p shacraft-compat --all-targets -- -D warnings
|
||||
python3 -m venv artifacts/compat-venv
|
||||
artifacts/compat-venv/bin/pip install nbtlib==2.0.4
|
||||
artifacts/compat-venv/bin/python scripts/compat_verify.py
|
||||
```
|
||||
|
||||
Для последней команды нужен pinned JAR/JDK из `scripts/catalog_generate.py`; альтернативный JDK передаётся `--java-bin /path/to/jdk25/bin`. Скрипт проверяет SHA-1 JAR, компилирует `compat_java.java`, проверяет оригинальный, изменённый и новый Rust-экспорт через **официальные `NbtIo`, `RegionFile`, `SerializableChunkData`, `PrimaryLevelData`, `WorldGenSettings`**. Независимый `nbtlib 2.0.4` сравнивает типизированные Sponge-теги. Результат и Java logs сохраняются в `artifacts/compat-verification-*/verification.json`.
|
||||
|
||||
Проверка 14 сентября 2026: 17 Rust-тестов и clippy прошли; Java прочитал exact 1 chunk / 3 блока, edited 2 chunks / 3 блока, new 2 chunks / 2 блока. Плюс тесты всех четырёх compression modes, внешнего большого chunk, границ палитр, отрицательных координат, entities move/create/remove, отказа exact после entity edits, checksum и no-overwrite. Java-проверка использует codecs, **не запускает сервер, не принимает EULA и не является игровым плейтестом**.
|
||||
|
||||
Первичные источники: [Sponge v3 specification](https://github.com/SpongePowered/Schematic-Specification/blob/master/versions/schematic-3.md), [WorldEdit AnvilChunk18](https://github.com/EngineHub/WorldEdit/blob/dca10737fe81bd81bb6a096e1801cc2d94f1793b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk18.java), [lz4-java block stream](https://github.com/lz4/lz4-java/blob/master/src/java/net/jpountz/lz4/LZ4BlockInputStream.java). Runtime реализация написана самостоятельно; код Minecraft и оригинальные игровые ресурсы не включены.
|
||||
@@ -0,0 +1,14 @@
|
||||
# Браузерная проверка 2026-09-14
|
||||
|
||||
Проверялся реальный Codex In-app Browser на `http://127.0.0.1:4000` через CUA. API-тесты проводились отдельными HTTP/WebSocket-процессами.
|
||||
|
||||
- Чистое открытие страницы: manifest, 8 проверенных ресурсов, вход в lobby, собственный WebGL2-рендер без ошибки инициализации.
|
||||
- Лобби видно на реальном снимке: пиксельная площадка, световые столбы, арка, вода, trampoline, небо, солнце, HUD.
|
||||
- Каталог открыл 32 367 состояний; поиск `minecraft:oak_slab` вернул 6 вариантов с точными type/waterlogged. Выбран `type=bottom,waterlogged=false`, быстрый слот сменился на него.
|
||||
- Диагностика показывала live tick/ack, ревизию, координаты, число блоков, RAM и полезный кэш отдельно. В лобби на стенде наблюдались 144 FPS, 11 920 треугольников, 0 ожидающих секций.
|
||||
- После остановки и замены серверного процесса открытая страница автоматически переподключилась. Ранее выбранный материал остался выбранным.
|
||||
- Созданные через Control API сохраняемые сущности пришли в клиент; allay виден на снимке, счётчик сущностей обновился.
|
||||
- Второй чистый браузерный клиент загрузил финальный протокол **без передачи полного registry**. Hotbar заполнился через поиск каталога; 8 ресурсов повторно прошли проверку из кэша.
|
||||
- Выбор `gallery` заменил мир. На реальном снимке видны разные кубические и неполные формы, UI не перекрывает весь мир. Диагностика: 1 614 блоков в текущем окне, 7 808 треугольников, 144 FPS, 0 ожидающих секций. Все 1 197 образцов находятся в мире, а не обязательно в одном окне просмотра.
|
||||
|
||||
FPS описывает этот браузер, оборудование, размер окна и точку наблюдения. Это не минимальное требование и не обещание производительности на другом устройстве. Движение, reach, строительство двух клиентов, Spleef, переподключение и аварийная долговечность дополнительно проверены воспроизводимым `scripts/check_server.mjs`.
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"catalog": "byte-for-byte identical after full reports + runtime extraction",
|
||||
"package_assets": "byte-for-byte identical after authoring script",
|
||||
"source_hashes": {
|
||||
"catalog.json.gz": "df889f6ce074b96130011d00b2f3b661cf910aba44064a0b5f361d7c064ce8ed",
|
||||
"report-identities.json.gz": "938232b10d17071d3eefa54ce9a1c3026e17f39b5a2c0f4d6ede2644824d9135"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"date": "2026-09-14",
|
||||
"platform": "Linux",
|
||||
"machine": "x86_64",
|
||||
"kernel": "7.0.0-31-generic",
|
||||
"cpu": "AMD Ryzen 7 1700 Eight-Core Processor",
|
||||
"rustc": "rustc 1.96.0 (ac68faa20 2026-05-25)",
|
||||
"cargo": "cargo 1.96.0 (30a34c682 2026-05-25)",
|
||||
"node": "v22.22.3",
|
||||
"python": "3.14.4"
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"success": true,
|
||||
"directory": "/home/emil/Desktop/shacraft-core/artifacts/compat-verification-2rxmacov",
|
||||
"java": [
|
||||
{
|
||||
"java26_2_verified": true,
|
||||
"chunks": 1,
|
||||
"sections": 1,
|
||||
"entities": 1,
|
||||
"nonair_blocks": 3,
|
||||
"level_name": "Shacraft template",
|
||||
"scope": "NbtIo,RegionFile,SerializableChunkData,PrimaryLevelData,WorldGenSettings codecs; no server simulation",
|
||||
"case": "exact"
|
||||
},
|
||||
{
|
||||
"java26_2_verified": true,
|
||||
"chunks": 2,
|
||||
"sections": 25,
|
||||
"entities": 1,
|
||||
"nonair_blocks": 3,
|
||||
"level_name": "Shacraft template",
|
||||
"scope": "NbtIo,RegionFile,SerializableChunkData,PrimaryLevelData,WorldGenSettings codecs; no server simulation",
|
||||
"case": "edited"
|
||||
},
|
||||
{
|
||||
"java26_2_verified": true,
|
||||
"chunks": 2,
|
||||
"sections": 48,
|
||||
"entities": 0,
|
||||
"nonair_blocks": 2,
|
||||
"level_name": "own",
|
||||
"scope": "NbtIo,RegionFile,SerializableChunkData,PrimaryLevelData,WorldGenSettings codecs; no server simulation",
|
||||
"case": "new"
|
||||
}
|
||||
],
|
||||
"nbtlib_version": "2.0.4",
|
||||
"source_jar_sha1": "823e2250d24b3ddac457a60c92a6a941943fcd6a",
|
||||
"source_jar_sha256": "cdacdfb25898de5e4b4b0e5ddcc2722f77067e46605709c2d886c000ebb63ec5",
|
||||
"nbtlib_sponge_typed_roundtrip": true,
|
||||
"exact_source_files_identical": true,
|
||||
"edited_world": {
|
||||
"schema_version": 1,
|
||||
"format": "anvil",
|
||||
"mode": "best-effort",
|
||||
"data_version": 4903,
|
||||
"worlds": {
|
||||
"main": 2
|
||||
},
|
||||
"chunks": 2,
|
||||
"sections": 25,
|
||||
"nonair_blocks": 3,
|
||||
"issues": [
|
||||
{
|
||||
"code": "source_archive",
|
||||
"severity": "info",
|
||||
"action": "preserved",
|
||||
"location": "shacraft-source-sidecar",
|
||||
"detail": "Verified original world retained for unsupported/stale data",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"code": "dependent_records_invalidated",
|
||||
"severity": "warning",
|
||||
"action": "dropped",
|
||||
"location": "main:chunk-1,1",
|
||||
"detail": "Removed1 stale block_entities at edited coordinates; originals retained in sidecar",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"code": "derived_fields_invalidated",
|
||||
"severity": "warning",
|
||||
"action": "approximated",
|
||||
"location": "main:chunk-1,1",
|
||||
"detail": "Removed stored light arrays and heightmaps, marked isLightOn=false for Minecraft reconstruction; unknown fields/entities/biomes preserved. No vanilla simulation guarantee.",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"code": "derived_fields_invalidated",
|
||||
"severity": "warning",
|
||||
"action": "approximated",
|
||||
"location": "main:chunk32,-33",
|
||||
"detail": "Removed stored light arrays and heightmaps, marked isLightOn=false for Minecraft reconstruction; unknown fields/entities/biomes preserved. No vanilla simulation guarantee.",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"code": "entity_edited",
|
||||
"severity": "warning",
|
||||
"action": "approximated",
|
||||
"location": "00000001-0000-0002-0000-000300000004",
|
||||
"detail": "Position/yaw/type and supported scalar properties applied; unknown original NBT retained; passenger/tether/AI relationships not simulated",
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"issue_limit": 1000,
|
||||
"omitted_issues": 0,
|
||||
"source_files": 0,
|
||||
"source_bytes": 0,
|
||||
"native_entity_bytes": 0,
|
||||
"profile": "Java 26.2 (DataVersion 4903); blocks editable, other typed NBT preserved on disk; offline writer lock"
|
||||
},
|
||||
"native_world": {
|
||||
"schema_version": 1,
|
||||
"format": "anvil",
|
||||
"mode": "best-effort",
|
||||
"data_version": 4903,
|
||||
"worlds": {
|
||||
"own": 1
|
||||
},
|
||||
"chunks": 2,
|
||||
"sections": 48,
|
||||
"nonair_blocks": 2,
|
||||
"issues": [
|
||||
{
|
||||
"code": "new_world_profile",
|
||||
"severity": "warning",
|
||||
"action": "approximated",
|
||||
"location": "level.dat",
|
||||
"detail": "Creative Java 26.2 overworld, empty flat generator, Y[-64,319], default plains biomes. Minecraft reconstructs light/heightmaps. Native entities use the explicit property bridge.",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"code": "derived_fields_invalidated",
|
||||
"severity": "warning",
|
||||
"action": "approximated",
|
||||
"location": "own:chunk-1,0",
|
||||
"detail": "Removed stored light arrays and heightmaps, marked isLightOn=false for Minecraft reconstruction; unknown fields/entities/biomes preserved. No vanilla simulation guarantee.",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"code": "derived_fields_invalidated",
|
||||
"severity": "warning",
|
||||
"action": "approximated",
|
||||
"location": "own:chunk0,0",
|
||||
"detail": "Removed stored light arrays and heightmaps, marked isLightOn=false for Minecraft reconstruction; unknown fields/entities/biomes preserved. No vanilla simulation guarantee.",
|
||||
"count": 1
|
||||
}
|
||||
],
|
||||
"issue_limit": 1000,
|
||||
"omitted_issues": 0,
|
||||
"source_files": 0,
|
||||
"source_bytes": 0,
|
||||
"native_entity_bytes": 0,
|
||||
"profile": "Java 26.2 (DataVersion 4903); blocks editable, other typed NBT preserved on disk; offline writer lock"
|
||||
},
|
||||
"limitations": "Java checks official disk/container/palette/world-metadata codecs, not running server, client renderer, light simulation or EULA acceptance."
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"passed": true,
|
||||
"server_binary": "/home/emil/Desktop/shacraft-core/target/release/shacraft-server",
|
||||
"mcp_binary": "/home/emil/Desktop/shacraft-core/target/release/shacraft-mcp",
|
||||
"sdk": true,
|
||||
"checks": [
|
||||
"SDK initialize, version negotiation, notification and ping",
|
||||
"17 discoverable tool schemas accepted by SDK",
|
||||
"4 resources read through SDK",
|
||||
"Construction prompt and arguments",
|
||||
"Durable write, read, idempotent retry, conflict content and undo",
|
||||
"Plan and atomic idempotent commit",
|
||||
"MCP PNG image content",
|
||||
"Entity spawn/update/list/delete",
|
||||
"Persisted world configuration and measured metrics",
|
||||
"World reset"
|
||||
],
|
||||
"world": "mcp_sdk_1789395818564"
|
||||
}
|
||||
@@ -0,0 +1,402 @@
|
||||
Checking shacraft-compat v0.1.0 (/home/emil/Desktop/shacraft-core/crates/shacraft-compat)
|
||||
Checking shacraft-server v0.1.0 (/home/emil/Desktop/shacraft-core/crates/shacraft-server)
|
||||
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.77s
|
||||
Compiling shacraft-compat v0.1.0 (/home/emil/Desktop/shacraft-core/crates/shacraft-compat)
|
||||
Compiling shacraft-server v0.1.0 (/home/emil/Desktop/shacraft-core/crates/shacraft-server)
|
||||
Finished `test` profile [unoptimized + debuginfo] target(s) in 3.09s
|
||||
Running unittests src/lib.rs (target/debug/deps/shacraft_compat-cd22d99df205fe27)
|
||||
|
||||
running 8 tests
|
||||
test anvil::tests::lz4_raw_and_compressed ... ok
|
||||
test nbt::tests::rejects_bombs ... ok
|
||||
test schem::tests::varint_validation ... ok
|
||||
test nbt::tests::all_types_roundtrip ... ok
|
||||
test anvil::tests::negative_region_zlib_and_external ... ok
|
||||
test anvil::tests::all_compression_modes_and_external_payloads ... ok
|
||||
test anvil::tests::section_palette_boundaries ... ok
|
||||
test anvil::tests::oversized_chunk_writes_external_and_validates_checksum ... ok
|
||||
|
||||
test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.37s
|
||||
|
||||
Running unittests src/main.rs (target/debug/deps/shacraft_compat-bd4306d00d4a6c17)
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Running tests/roundtrip.rs (target/debug/deps/roundtrip-f70ba20f52297682)
|
||||
|
||||
running 9 tests
|
||||
test malformed_input_is_not_published ... ok
|
||||
test no_overwrite_and_provenance_hash_guard ... ok
|
||||
test unsupported_data_version_rejects_exact_before_publication ... ok
|
||||
test duplicate_entity_uuid_stays_outside_editable_subset ... ok
|
||||
test sponge_entity_metadata_guard_and_position_roundtrip ... ok
|
||||
test sponge_import_edits_unknown_states_and_preserves_nbt ... ok
|
||||
test native_entity_edit_move_create_remove_roundtrip ... ok
|
||||
test genuine_java_world_import_exact_roundtrip_edit_and_new_chunk ... ok
|
||||
test native_new_world_export_and_schematic ... ok
|
||||
|
||||
test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.13s
|
||||
|
||||
Running unittests src/lib.rs (target/debug/deps/shacraft_content-ee19c845f27f8fb2)
|
||||
|
||||
running 11 tests
|
||||
test shapes::tests::four_quarter_rotations_restore_box ... ok
|
||||
test shapes::tests::connected_fence_has_two_added_rails ... ok
|
||||
test shapes::tests::rail_ascent_reaches_next_block ... ok
|
||||
test packages::tests::changed_resource_rejected ... ok
|
||||
test packages::tests::bundled_packages_hashes_dependencies_and_privacy ... ok
|
||||
test packages::tests::paths_sizes_and_versions_are_validated ... ok
|
||||
test tests::key_collision_states_and_orientation ... ok
|
||||
test tests::official_entity_dimensions_and_authored_models_present ... ok
|
||||
test tests::sampler_defaults_and_palette_are_registered ... ok
|
||||
test tests::every_state_has_valid_shapes_and_explicit_coverage ... ok
|
||||
test tests::complete_against_independent_official_report_projection ... ok
|
||||
|
||||
test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.31s
|
||||
|
||||
Running unittests src/lib.rs (target/debug/deps/shacraft_core-f7257583d500a490)
|
||||
|
||||
running 11 tests
|
||||
test section::tests::crc32_matches_standard_check_value ... ok
|
||||
test section::tests::direct_read_rejects_out_of_range_cell - should panic ... ok
|
||||
test section::tests::packed_indices_match_cross_byte_wire_fixture ... ok
|
||||
test section::tests::uniform_round_trip_and_little_endian_layout ... ok
|
||||
test section::tests::invalid_palettes_and_indices_are_rejected ... ok
|
||||
test section::tests::structurally_invalid_headers_are_rejected_even_with_valid_checksum ... ok
|
||||
test section::tests::dense_round_trip_and_size_crossover ... ok
|
||||
test section::tests::truncated_extra_and_corrupted_bytes_are_rejected ... ok
|
||||
test section::tests::every_storage_mode_checks_registry_bounds ... ok
|
||||
test section::tests::palette_width_changes_at_powers_of_two ... ok
|
||||
test section::tests::every_palette_width_round_trips ... ok
|
||||
|
||||
test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s
|
||||
|
||||
Running tests/contract.rs (target/debug/deps/contract-b050c7d50e9640d3)
|
||||
|
||||
running 8 tests
|
||||
test accepted_noop_advances_revision_and_prevents_undo_of_earlier_edit ... ok
|
||||
test operation_id_collision_rejects_changed_payload_across_restart_and_methods ... ok
|
||||
test edit_replay_precedes_revision_check_and_survives_reset_and_reopen ... ok
|
||||
test invalid_batch_never_partially_writes_or_advances_revision ... ok
|
||||
test reset_is_monotonic_idempotent_durable_and_an_undo_barrier ... ok
|
||||
test undo_restores_inherited_content_and_replays_without_mutating_newer_state ... ok
|
||||
test strict_undo_rejects_later_nonoverlapping_edits_and_aba_cycles ... ok
|
||||
test snapshots_pin_effective_source_contents_and_air_overrides ... ok
|
||||
|
||||
test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.04s
|
||||
|
||||
Running tests/section_pages.rs (target/debug/deps/section_pages-92b3be09a3e83895)
|
||||
|
||||
running 1 test
|
||||
test section_pages_are_sorted_bounded_and_include_inherited_air_overrides ... ok
|
||||
|
||||
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s
|
||||
|
||||
Running tests/storage.rs (target/debug/deps/storage-be95f5d467d8c630)
|
||||
|
||||
running 10 tests
|
||||
test lock_is_exclusive_and_released_on_drop ... ok
|
||||
test registry_is_canonical_durable_and_rejects_malformed_identifiers ... ok
|
||||
test corrupted_blob_is_reported_instead_of_air ... ok
|
||||
test revision_overflow_rejects_mutation_but_keeps_original_replay ... ok
|
||||
test sqlite_failure_mid_edit_rolls_back_blobs_history_and_revision ... ok
|
||||
test explicit_gc_preserves_snapshots_history_and_cache_correctness ... ok
|
||||
test oversized_unreachable_blob_is_rejected_before_reinterning ... ok
|
||||
test compact_cache_evicts_distinct_blobs_and_shares_identical_sections ... ok
|
||||
test coordinate_boundaries_and_inclusive_read_limits ... ok
|
||||
test uniform_section_remains_twenty_bytes_in_resident_cache ... ok
|
||||
|
||||
test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.07s
|
||||
|
||||
Running unittests src/main.rs (target/debug/deps/shacraft_mcp-8af48a29a5cc1f7b)
|
||||
|
||||
running 8 tests
|
||||
test tests::build_shapes_validate_without_allowing_invented_parameters ... ok
|
||||
test tests::supported_version_is_preserved ... ok
|
||||
test tests::malformed_ids_and_requests_do_not_execute ... ok
|
||||
test tests::notifications_never_generate_responses ... ok
|
||||
test tests::invalid_tool_arguments_are_mcp_content_errors ... ok
|
||||
test tests::unavailable_token_is_a_tool_error_not_transport_error ... ok
|
||||
test tests::lifecycle_negotiates_and_rejects_before_initialization ... ok
|
||||
test tests::bounded_reader_recovers_after_oversized_line ... ok
|
||||
|
||||
test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.07s
|
||||
|
||||
Running unittests src/main.rs (target/debug/deps/shacraft_server-33e07bc1da9f7f4e)
|
||||
|
||||
running 18 tests
|
||||
test game::tests::legacy_world_configuration_gets_safe_spleef_defaults ... ok
|
||||
test packages::tests::changed_definition_or_module_fails_hash_verification_before_loading ... ok
|
||||
test game::tests::outbox_has_byte_and_message_limits ... ok
|
||||
test packages::tests::sandbox_executes_and_bounds_fuel_memory_and_results ... ok
|
||||
test packages::tests::verified_custom_package_registers_content_and_binds_real_wasm ... ok
|
||||
test packages::tests::duplicate_vanilla_and_invalid_geometry_definitions_are_rejected ... ok
|
||||
test game::tests::trampoline_executes_wasm_despite_small_contact_gap ... ok
|
||||
test game::tests::official_collision_shapes_drive_world_physics ... ok
|
||||
test game::tests::arena_configuration_validates_before_mutation ... ok
|
||||
test game::tests::authoritative_actions_reject_forged_targets_and_sync_real_edits ... ok
|
||||
test game::tests::material_payloads_are_bounded_and_runtime_id_lookup_works_without_registry_dump ... ok
|
||||
test game::tests::snapshots_carry_revision_and_slow_consumers_are_disconnected ... ok
|
||||
test game::tests::gallery_contains_every_default_state_over_a_bounded_floor ... ok
|
||||
test game::tests::eliminated_spleef_players_cannot_reenter_and_late_joins_spectate ... ok
|
||||
test game::tests::entities_are_durable_and_failed_commits_do_not_publish_changes ... ok
|
||||
test game::tests::restart_recovers_arena_configuration_and_cleans_interrupted_round ... ok
|
||||
test game::tests::configured_spleef_rules_control_full_round_and_survive_restart ... ok
|
||||
test game::tests::interrupted_creation_of_managed_world_can_finish_its_seed ... ok
|
||||
|
||||
test result: ok. 18 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 15.29s
|
||||
|
||||
Running unittests src/main.rs (target/debug/deps/shacraft_tools-1836b285f941c1f2)
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Doc-tests shacraft_compat
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Doc-tests shacraft_content
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Doc-tests shacraft_core
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Compiling shacraft-server v0.1.0 (/home/emil/Desktop/shacraft-core/crates/shacraft-server)
|
||||
Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.71s
|
||||
{
|
||||
"passed": true,
|
||||
"checks": [
|
||||
"bounded resident cache with verified eviction while reading 80 sections",
|
||||
"second writer rejected while owner is running",
|
||||
"80 acknowledged edits and registry survive SIGKILL without flush",
|
||||
"idempotent replay after SIGKILL precedes current revision check",
|
||||
"invalid batch leaves both blocks and revision unchanged",
|
||||
"interrupted 32768-cell transaction is atomic (recovered revision 0)",
|
||||
"uncertain interrupted request can safely be retried",
|
||||
"invalid request does not terminate the local test session",
|
||||
"4096-cell uniform section occupies 20 encoded payload bytes in resident cache"
|
||||
],
|
||||
"final_metrics": {
|
||||
"process": {
|
||||
"peak_rss_bytes": 8114176,
|
||||
"rss_bytes": 8114176,
|
||||
"source": "/proc/self/status (null when unavailable)"
|
||||
},
|
||||
"storage": {
|
||||
"cache_capacity_sections": 2,
|
||||
"cache_entries": 1,
|
||||
"cache_evictions": 0,
|
||||
"cache_hits": 0,
|
||||
"cache_misses": 1,
|
||||
"cache_payload_bytes": 20,
|
||||
"cache_representation": "encoded_uniform_palette_dense",
|
||||
"commits_this_handle": 0,
|
||||
"coordinate_limit": 30000000,
|
||||
"database_bytes": 647168,
|
||||
"history_change_count": 36944,
|
||||
"history_retention": "all_operations_until_explicit_future_retention_policy",
|
||||
"immutable_blob_count": 18,
|
||||
"last_mutation_duration_us": 0,
|
||||
"max_edit_cells": 32768,
|
||||
"max_read_volume": 262144,
|
||||
"operation_count": 82,
|
||||
"os_rss_bytes": null,
|
||||
"overlay_section_count": 97,
|
||||
"registry_count": 2,
|
||||
"registry_limit_states": 262144,
|
||||
"registry_text_bytes": 32,
|
||||
"schema_version": 1,
|
||||
"shm_bytes": 32768,
|
||||
"snapshot_count": 0,
|
||||
"sqlite_cache_budget_bytes": 4194304,
|
||||
"sqlite_journal_mode": "wal",
|
||||
"sqlite_synchronous": "FULL",
|
||||
"transient_decoded_payload_peak_estimate_bytes": 16384,
|
||||
"wal_bytes": 0,
|
||||
"world_count": 3,
|
||||
"world_limit": 10000
|
||||
}
|
||||
},
|
||||
"limits": [
|
||||
"process crash tested; power loss and faulty hardware are not simulated",
|
||||
"storage-only workload; no Paper or gameplay performance comparison"
|
||||
]
|
||||
}
|
||||
TAP version 13
|
||||
# Subtest: camera axes and world projection match the server coordinate convention
|
||||
ok 1 - camera axes and world projection match the server coordinate convention
|
||||
---
|
||||
duration_ms: 2.623771
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: DDA resolves negative world coordinates and nearest entry face
|
||||
ok 2 - DDA resolves negative world coordinates and nearest entry face
|
||||
---
|
||||
duration_ms: 4.264518
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: ray selection respects slab geometry and reach instead of selecting empty half
|
||||
ok 3 - ray selection respects slab geometry and reach instead of selecting empty half
|
||||
---
|
||||
duration_ms: 8.035945
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: axis aligned ray slabs reject parallel paths outside a box
|
||||
ok 4 - axis aligned ray slabs reject parallel paths outside a box
|
||||
---
|
||||
duration_ms: 0.271763
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: selection intersects a fence extension owned by the cell below
|
||||
ok 5 - selection intersects a fence extension owned by the cell below
|
||||
---
|
||||
duration_ms: 1.042738
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: package geometry is selectable across its documented three-block extent
|
||||
ok 6 - package geometry is selectable across its documented three-block extent
|
||||
---
|
||||
duration_ms: 1.65838
|
||||
type: 'test'
|
||||
...
|
||||
1..6
|
||||
# tests 6
|
||||
# suites 0
|
||||
# pass 6
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 134.144281
|
||||
{
|
||||
"passed": true,
|
||||
"checks": [
|
||||
"Manifest resource SHA-256/size, admin token required, server WASM not public",
|
||||
"Incompatible manifest rejected",
|
||||
"Two clients receive shared snapshot and presence",
|
||||
"Authoritative movement and collision; client position spoof ignored",
|
||||
"Forged out-of-reach block break rejected",
|
||||
"Reachable break/place, server revision ordering and broadcast",
|
||||
"Late join receives current geometry and revision",
|
||||
"Pinned template and independent clone isolation",
|
||||
"Scoped game chat delivered to peer",
|
||||
"Persisted entity events reach both clients",
|
||||
"Reconnect restores authoritative world snapshot",
|
||||
"Full two-player Spleef countdown, elimination, winner and automatic floor reset",
|
||||
"Disconnect removes players and active worlds",
|
||||
"Real SIGKILL/restart preserves committed blocks, entity properties and arena configuration"
|
||||
],
|
||||
"metrics": {
|
||||
"active_worlds": 0,
|
||||
"catalog": {
|
||||
"collision": {
|
||||
"approximate-context": 179,
|
||||
"authored-exact": 1,
|
||||
"measured-empty-context": 32187
|
||||
},
|
||||
"collision_context": "BlockPos.ZERO, air neighbors, empty entity context; contextual classes flagged separately",
|
||||
"data_version": 4903,
|
||||
"entities": 158,
|
||||
"minecraft_blocks": 1196,
|
||||
"minecraft_states": 32366,
|
||||
"minecraft_version": "26.2",
|
||||
"palette": {
|
||||
"fence": "minecraft:oak_fence[east=false,north=false,south=false,waterlogged=false,west=false]",
|
||||
"glass": "minecraft:glass",
|
||||
"grass": "minecraft:grass_block[snowy=false]",
|
||||
"light": "minecraft:sea_lantern",
|
||||
"sand": "minecraft:sand",
|
||||
"slab": "minecraft:oak_slab[type=bottom,waterlogged=false]",
|
||||
"snow": "minecraft:snow_block",
|
||||
"stairs": "minecraft:oak_stairs[facing=north,half=bottom,shape=straight,waterlogged=false]",
|
||||
"stone": "minecraft:stone",
|
||||
"trampoline": "shacraft:trampoline",
|
||||
"water": "minecraft:water[level=0]",
|
||||
"wood": "minecraft:oak_planks"
|
||||
},
|
||||
"render": {
|
||||
"authored-package": 1,
|
||||
"authored-procedural": 32316,
|
||||
"intentionally-invisible": 50
|
||||
},
|
||||
"simulation": "server movement, block editing, authored modules; vanilla AI/redstone/fluid simulation are not implemented",
|
||||
"total_states": 32367
|
||||
},
|
||||
"entities": 1,
|
||||
"entity_revision": 13,
|
||||
"limits": {
|
||||
"build_plans": 16,
|
||||
"bytes_per_client": 8388608,
|
||||
"command_queue": 64,
|
||||
"messages_per_client": 16,
|
||||
"plan_cells": 32768,
|
||||
"players": 32
|
||||
},
|
||||
"max_tick_ms": 3.362786,
|
||||
"plans": 0,
|
||||
"players": 0,
|
||||
"queued_client_bytes": 0,
|
||||
"rss_bytes": 61239296,
|
||||
"slow_clients_disconnected": 1,
|
||||
"storage": {
|
||||
"cache_capacity_sections": 64,
|
||||
"cache_entries": 8,
|
||||
"cache_evictions": 0,
|
||||
"cache_hits": 9,
|
||||
"cache_misses": 8,
|
||||
"cache_payload_bytes": 4304,
|
||||
"cache_representation": "encoded_uniform_palette_dense",
|
||||
"commits_this_handle": 0,
|
||||
"coordinate_limit": 30000000,
|
||||
"database_bytes": 7372800,
|
||||
"history_change_count": 22055,
|
||||
"history_retention": "all_operations_until_explicit_future_retention_policy",
|
||||
"immutable_blob_count": 87,
|
||||
"last_mutation_duration_us": 0,
|
||||
"max_edit_cells": 32768,
|
||||
"max_read_volume": 262144,
|
||||
"operation_count": 11,
|
||||
"os_rss_bytes": null,
|
||||
"overlay_section_count": 93,
|
||||
"registry_count": 32367,
|
||||
"registry_limit_states": 262144,
|
||||
"registry_text_bytes": 2671754,
|
||||
"schema_version": 1,
|
||||
"shm_bytes": 32768,
|
||||
"snapshot_count": 2,
|
||||
"sqlite_cache_budget_bytes": 4194304,
|
||||
"sqlite_journal_mode": "wal",
|
||||
"sqlite_synchronous": "FULL",
|
||||
"transient_decoded_payload_peak_estimate_bytes": 16384,
|
||||
"wal_bytes": 1384352,
|
||||
"world_count": 9,
|
||||
"world_limit": 10000
|
||||
},
|
||||
"tick": 1,
|
||||
"tick_ms": 3.362786,
|
||||
"uptime_seconds": 0,
|
||||
"wasm": {
|
||||
"calls": 0,
|
||||
"fuel_per_call": 10000,
|
||||
"imports": 0,
|
||||
"memory_limit": 65536,
|
||||
"runtime": "wasmi",
|
||||
"traps": 0
|
||||
},
|
||||
"world_count": 9
|
||||
},
|
||||
"binary": "/home/emil/Desktop/shacraft-core/target/debug/shacraft-server",
|
||||
"report_file": "/home/emil/Desktop/shacraft-core/artifacts/server-e2e-debug.json",
|
||||
"data": "/tmp/shacraft-server-test-nBiKWZ"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,119 @@
|
||||
{
|
||||
"passed": true,
|
||||
"checks": [
|
||||
"Manifest resource SHA-256/size, admin token required, server WASM not public",
|
||||
"Incompatible manifest rejected",
|
||||
"Two clients receive shared snapshot and presence",
|
||||
"Authoritative movement and collision; client position spoof ignored",
|
||||
"Forged out-of-reach block break rejected",
|
||||
"Reachable break/place, server revision ordering and broadcast",
|
||||
"Late join receives current geometry and revision",
|
||||
"Pinned template and independent clone isolation",
|
||||
"Scoped game chat delivered to peer",
|
||||
"Persisted entity events reach both clients",
|
||||
"Reconnect restores authoritative world snapshot",
|
||||
"Full two-player Spleef countdown, elimination, winner and automatic floor reset",
|
||||
"Disconnect removes players and active worlds",
|
||||
"Real SIGKILL/restart preserves committed blocks, entity properties and arena configuration"
|
||||
],
|
||||
"metrics": {
|
||||
"active_worlds": 0,
|
||||
"catalog": {
|
||||
"collision": {
|
||||
"approximate-context": 179,
|
||||
"authored-exact": 1,
|
||||
"measured-empty-context": 32187
|
||||
},
|
||||
"collision_context": "BlockPos.ZERO, air neighbors, empty entity context; contextual classes flagged separately",
|
||||
"data_version": 4903,
|
||||
"entities": 158,
|
||||
"minecraft_blocks": 1196,
|
||||
"minecraft_states": 32366,
|
||||
"minecraft_version": "26.2",
|
||||
"palette": {
|
||||
"fence": "minecraft:oak_fence[east=false,north=false,south=false,waterlogged=false,west=false]",
|
||||
"glass": "minecraft:glass",
|
||||
"grass": "minecraft:grass_block[snowy=false]",
|
||||
"light": "minecraft:sea_lantern",
|
||||
"sand": "minecraft:sand",
|
||||
"slab": "minecraft:oak_slab[type=bottom,waterlogged=false]",
|
||||
"snow": "minecraft:snow_block",
|
||||
"stairs": "minecraft:oak_stairs[facing=north,half=bottom,shape=straight,waterlogged=false]",
|
||||
"stone": "minecraft:stone",
|
||||
"trampoline": "shacraft:trampoline",
|
||||
"water": "minecraft:water[level=0]",
|
||||
"wood": "minecraft:oak_planks"
|
||||
},
|
||||
"render": {
|
||||
"authored-package": 1,
|
||||
"authored-procedural": 32316,
|
||||
"intentionally-invisible": 50
|
||||
},
|
||||
"simulation": "server movement, block editing, authored modules; vanilla AI/redstone/fluid simulation are not implemented",
|
||||
"total_states": 32367
|
||||
},
|
||||
"entities": 1,
|
||||
"entity_revision": 13,
|
||||
"limits": {
|
||||
"build_plans": 16,
|
||||
"bytes_per_client": 8388608,
|
||||
"command_queue": 64,
|
||||
"messages_per_client": 16,
|
||||
"plan_cells": 32768,
|
||||
"players": 32
|
||||
},
|
||||
"max_tick_ms": 0.001784,
|
||||
"plans": 0,
|
||||
"players": 0,
|
||||
"queued_client_bytes": 0,
|
||||
"rss_bytes": 51974144,
|
||||
"slow_clients_disconnected": 0,
|
||||
"storage": {
|
||||
"cache_capacity_sections": 64,
|
||||
"cache_entries": 8,
|
||||
"cache_evictions": 0,
|
||||
"cache_hits": 1,
|
||||
"cache_misses": 8,
|
||||
"cache_payload_bytes": 4304,
|
||||
"cache_representation": "encoded_uniform_palette_dense",
|
||||
"commits_this_handle": 0,
|
||||
"coordinate_limit": 30000000,
|
||||
"database_bytes": 7372800,
|
||||
"history_change_count": 22055,
|
||||
"history_retention": "all_operations_until_explicit_future_retention_policy",
|
||||
"immutable_blob_count": 87,
|
||||
"last_mutation_duration_us": 0,
|
||||
"max_edit_cells": 32768,
|
||||
"max_read_volume": 262144,
|
||||
"operation_count": 11,
|
||||
"os_rss_bytes": null,
|
||||
"overlay_section_count": 93,
|
||||
"registry_count": 32367,
|
||||
"registry_limit_states": 262144,
|
||||
"registry_text_bytes": 2671754,
|
||||
"schema_version": 1,
|
||||
"shm_bytes": 32768,
|
||||
"snapshot_count": 2,
|
||||
"sqlite_cache_budget_bytes": 4194304,
|
||||
"sqlite_journal_mode": "wal",
|
||||
"sqlite_synchronous": "FULL",
|
||||
"transient_decoded_payload_peak_estimate_bytes": 16384,
|
||||
"wal_bytes": 1384352,
|
||||
"world_count": 9,
|
||||
"world_limit": 10000
|
||||
},
|
||||
"tick": 1,
|
||||
"tick_ms": 0.001784,
|
||||
"uptime_seconds": 0,
|
||||
"wasm": {
|
||||
"calls": 0,
|
||||
"fuel_per_call": 10000,
|
||||
"imports": 0,
|
||||
"memory_limit": 65536,
|
||||
"runtime": "wasmi",
|
||||
"traps": 0
|
||||
},
|
||||
"world_count": 9
|
||||
},
|
||||
"binary": "/home/emil/Desktop/shacraft-core/target/release/shacraft-server"
|
||||
}
|
||||
Reference in New Issue
Block a user