Файлы регионов Minecraft хранятся в 3 разделах, первые два содержат информацию о том, где хранятся фрагменты, и информацию о самих фрагментах. В последнем разделе чанки представлены в виде 4-байтового числа, используемого типа сжатия (почти всегда это zlib, RFC1950).
Вот еще (возможно лучше) информация: https://minecraft.gamepedia.com/Region_file_format
У меня есть программа, которая успешно загружает данные фрагмента. Однако я не могу определить, насколько большими будут фрагменты при распаковке, поэтому я просто использую максимальное количество, которое может потребоваться при выделении пространства.
В файлах данных проигрывателя они указывают размер, который он занимает при распаковке, и (я думаю) он использует тот же тип сжатия.
Конец файла player.dat с указанием размера распакованных данных (с прямым порядком байтов):
Это начало данных фрагмента, первые 4 байта указывают, сколько байтов содержится в следующих сжатых данных:
Однако, если я посмотрю, где конкретно «заканчиваются» сжатые данные, после них еще много данных. Эти данные, похоже, бесполезны, но если я попытаюсь распаковать их вместе с остальной частью фрагмента, я получу ошибку.
Выделенные данные фрагментов и невыделенные таинственные данные:
И нет распакованного размера (или заголовка? Я могу ошибаться здесь). Окончательный размер фрагментов в этом примере составляет 32 562 байта, и это число (или любые близкие соседи) нигде не может быть найдено в данных фрагмента или таинственных данных. (Проверено как с прямым порядком байтов, так и с прямым порядком байтов)
Распакованные данные заканчиваются на индексе 32562 (наблюдают локальные пользователи Visual Studio):
Есть что-то, что мне не хватает? Действительно ли это сжатие отличается от сжатия данных плеера? Какие загадочные данные? И я застреваю, загружая 1 << 20 байт каждый раз, когда хочу загрузить фрагмент из файла региона?
Спасибо за любые ответы или предложения
Данные изолированного фрагмента: https://drive.google.com/file/d/1n3Ix8V8DAgR9v0rkUCXMUuW4LJjT1L8B/view?usp=sharing
Полные данные региона: https://drive.google.com/file/d/15aVdyyKazySaw9ZpXATR4dyvhVtrL6ZW/view?usp=sharing
(Не связывая данные игрока по возможным соображениям безопасности)
В данных региона данные фрагмента начинаются с индекса 1208320 (или 0x127000).
Информация о формате, которую вы связали, весьма полезна. Вы читали его?
Там написано: «Остальная часть файла состоит из данных до 1024 фрагментов, перемежающихся неиспользуемым пространством». Кроме того, «Minecraft всегда дополняет данные последнего фрагмента до длины, кратной 4096 байт» (курсив мой). Все кратно 4 КБ, поэтому конец каждого чанка дополняется до следующей границы 4 КБ.
Таким образом, ваши «загадочные» данные вовсе не являются загадкой, поскольку это полностью ожидается в соответствии с документацией по формату. Эти данные просто мусор, который нужно игнорировать.
Обратите внимание, что, согласно документации, «длина» данных в первых трех байтах фрагмента фактически на один больше, чем количество байтов данных в фрагменте (после пятибайтового заголовка).
Также из документации в формате действительно не указан несжатый размер.
zlib был разработан для потоковой передачи данных, когда вы не знаете заранее, сколько их будет. Вы можете использовать inflate()
для распаковки в любой размер буфера, который вам нравится. Если для завершения недостаточно места, вы можете либо сделать что-то с этими данными, а затем повторить в том же буфере, либо вы можете увеличить буфер с помощью realloc()
в C или эквивалентном для любого языка, который вы используете. (Не указано в вопросе или тегах.)
Спасибо, я использую C++, извините, что не упомянул об этом. Это точно поможет!