Parser for Hytale .region.bin files (IndexedStorageFile format)
Project description
Hytale Region Parser
A Python library for parsing Hytale .region.bin files (IndexedStorageFile format).
Overview
This tool parses Hytale world region files to extract and analyze chunk data, including block information, components, containers, and entities. It implements a parser compatible with Hytale's codec system and handles zstandard-compressed data blobs.
The code is mostly written by letting Claude Sonnet and Opus analyze the HytaleServer.jar's decompiled code and reimplementing the relevant parts in Python. I mainly wrote this because I wanted to learn about ore distribution, but it quickly evolved into a library.
Feel free to explore the examples for common use cases and report bugs or request features on the GitHub Issues page.
Features
- Parse IndexedStorageFile format (
.region.binfiles) - JSON output to file by default with position-keyed block data
- Folder processing - parse entire directories or universe structures
- All output files written to current working directory
- Extract chunk data with block palettes and component information
- Decode BSON documents using Hytale's codec format
- Identify and list unique block types across regions
- Parse item containers (chests, barrels, etc.) with position and capacity
- Extract block components and entity data
- Support for zstandard decompression
- Type hints and dataclasses for clean API
- Command-line interface and Python API
Installation
From PyPI
pip install hytale-region-parser
From Source
git clone https://github.com/TheMcSebi/hytale-region-parser.git
cd hytale-region-parser
pip install -e .
Development Installation
pip install -e ".[dev]"
Quick Start
Command Line
# Parse single file (writes -2.-3.region.json in current directory)
hytale-region-parser chunks/-2.-3.region.bin
# Parse a "chunks" folder (writes <worldname>.json in current directory)
hytale-region-parser path/to/worldname/chunks/
# Parse a universe folder (writes <worldname>.json for each world in current directory)
hytale-region-parser path/to/universe/worlds/
# Parse a flat folder of region files (writes regions.json in current directory)
hytale-region-parser path/to/region_files/
# Output to stdout instead of file
hytale-region-parser path/to/0.0.region.bin --stdout
# Specify custom output file
hytale-region-parser path/to/0.0.region.bin -o output.json
# Compact JSON (no indentation)
hytale-region-parser path/to/0.0.region.bin --compact
# Suppress progress messages
hytale-region-parser path/to/chunks/ -q
Python API
from pathlib import Path
from hytale_region_parser import RegionFileParser
# Get JSON output (recommended)
with RegionFileParser(Path("0.0.region.bin")) as parser:
# Get as dictionary
data = parser.to_dict()
# Or as JSON string
json_str = parser.to_json(indent=2)
print(json_str)
# Iterate over chunks for custom processing
with RegionFileParser(Path("0.0.region.bin")) as parser:
for chunk in parser.iter_chunks():
print(f"Chunk ({chunk.chunk_x}, {chunk.chunk_z})")
print(f" Block types: {len(chunk.block_names)}")
print(f" Containers: {len(chunk.containers)}")
# Get a summary of the entire region
with RegionFileParser(Path("0.0.region.bin")) as parser:
summary = parser.get_summary()
print(f"Unique block types: {summary['unique_blocks']}")
JSON Output Format
The default output is JSON with world coordinates as keys:
{
"100,64,200": {
"name": "Container",
"components": {
"container": {
"capacity": 18,
"items": [
{"Id": "Ore_Copper", "Quantity": 4}
],
"allow_viewing": true,
"custom_name": null
}
}
},
"150,32,180": {
"name": "FarmingBlock",
"components": {
"FarmingBlock": {
"SpreadRate": 0.0
}
}
}
}
The coordinates are in world space (chunk_x * 32 + local_x, etc.).
Folder Processing
The CLI supports three folder structures:
All output files are written to the current working directory where the command is executed.
Single File
hytale-region-parser chunks/-2.-3.region.bin
# Output: ./-2.-3.region.json
Chunks Folder
When pointing to a folder named "chunks", the parent folder is used as the world name:
hytale-region-parser path/to/default/chunks/
# Output: ./default.json (merges all region files)
Universe Folder
When pointing to a folder containing world subfolders with "chunks" directories:
hytale-region-parser path/to/universe/worlds/
# Output: ./world1.json
# ./world2.json
# (one JSON file per world)
Flat Folder
Any other folder containing .region.bin files:
hytale-region-parser path/to/region_files/
# Output: ./regions.json (merges all region files)
Data Models
ParsedChunkData
The main result type containing all parsed chunk information:
@dataclass
class ParsedChunkData:
chunk_x: int # Chunk X coordinate
chunk_z: int # Chunk Z coordinate
version: int # Data format version
sections: List[ChunkSectionData] # 32x32x32 block sections
block_components: List[BlockComponent] # Block component data
containers: List[ItemContainerData] # Item containers (chests, etc.)
entities: List[Dict[str, Any]] # Entity data
block_names: Set[str] # Unique block type names
raw_components: Dict[str, Any] # Raw BSON component data
ItemContainerData
Represents storage blocks like chests:
@dataclass
class ItemContainerData:
position: Tuple[int, int, int] # Block position
capacity: int # Number of slots
items: List[Dict[str, Any]] # Item data in slots
custom_name: Optional[str] # Custom container name
About Hytale's File Format
Region File Structure (.region.bin)
Hytale stores world data in IndexedStorageFile format, a custom binary container:
┌─────────────────────────────────────────────────────────────┐
│ HEADER (32 bytes) │
│ ├─ Magic: "HytaleIndexedStorage" (20 bytes) │
│ ├─ Version: uint32 BE (0 or 1) │
│ ├─ Blob Count: uint32 BE (1024 for 32×32 chunks) │
│ └─ Segment Size: uint32 BE │
├─────────────────────────────────────────────────────────────┤
│ BLOB INDEX TABLE (blob_count × 4 bytes) │
│ └─ Segment index for each chunk (uint32 BE, 0 = empty) │
├─────────────────────────────────────────────────────────────┤
│ SEGMENTS (variable size) │
│ └─ Zstandard-compressed chunk data blobs │
└─────────────────────────────────────────────────────────────┘
Each region file contains up to 1024 chunks (32×32 grid). The filename X.Z.region.bin indicates region coordinates, where each chunk's world position is calculated as (region_x * 32 + local_x, region_z * 32 + local_z).
Blob/Chunk Data Structure
Each compressed blob contains a BSON document with the following hierarchy:
Root
├─ Version: int
└─ Components
├─ ChunkColumn
│ └─ Sections[] (up to 10 vertical sections, 32 blocks each = 320 height)
│ └─ Components
│ └─ Block
│ └─ Data: hex-encoded block section data
├─ BlockComponentChunk
│ └─ BlockComponents{} (keyed by block index)
│ └─ Components (container, sign, farming, etc.)
└─ EntityChunk
└─ Entities[]
Block Section Data Format
The hex-encoded Block.Data field contains:
| Offset | Size | Field |
|---|---|---|
| 0 | 4 | Block migration version (uint32 BE) |
| 4 | 1 | Palette type: 0=Empty, 1=HalfByte, 2=Byte, 3=Short |
| 5 | 2 | Palette entry count (uint16 BE) |
| 7+ | var | Palette entries (ID + name + count per entry) |
| var | var | Block indices (32×32×32 = 32768 blocks per section) |
Palette Entry Format:
- 1 byte: Internal ID
- 2 bytes: String length (uint16 BE)
- N bytes: Block name (UTF-8, e.g.,
Rock_Stone_Mossy) - 2 bytes: Block count (int16 BE)
Block Index Encoding (based on palette type):
- HalfByte (1): 4 bits per block (16 max palette entries)
- Byte (2): 8 bits per block (256 max palette entries)
- Short (3): 16 bits per block (65536 max palette entries)
Block index formula: index = x + z*32 + y*32*32
How the Parser Works
- Open & Validate: Read header, verify magic string
HytaleIndexedStorage - Index Table: Load segment pointers for all 1024 chunk slots
- Iterate Chunks: For each non-empty slot:
- Seek to segment position
- Read blob header (source length + compressed length)
- Decompress with zstandard
- Parse as BSON document
- Extract Block Data: For each section in
ChunkColumn.Sections:- Decode hex block data
- Parse palette (block names + counts)
- Optionally decode full block indices for position mapping
- Extract Components: Parse containers, signs, farming blocks, etc. from
BlockComponentChunk
Development
Running Tests
python -m pytest tests/ -v
Type Checking
python -m mypy src/hytale_region_parser --ignore-missing-imports
Linting
python -m ruff check src/hytale_region_parser
Building for PyPI
python -m pytest tests/ -q; python -m mypy src/hytale_region_parser; python -m ruff check src/hytale_region_parser
pip install build twine
python -m build
twine upload dist/*
License
This project is licensed under the MIT License - see the LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hytale_region_parser-0.1.2.tar.gz.
File metadata
- Download URL: hytale_region_parser-0.1.2.tar.gz
- Upload date:
- Size: 31.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef04333c4acb60c50baa91315861b45edd592d724fb8501530ec6bfe2ba70ab3
|
|
| MD5 |
dfd870f414c17588b06808da31257f83
|
|
| BLAKE2b-256 |
58d86df2d13aaa0641fbcf4a6203312d009c391c07b853f4b97ca39a16cfddc7
|
File details
Details for the file hytale_region_parser-0.1.2-py3-none-any.whl.
File metadata
- Download URL: hytale_region_parser-0.1.2-py3-none-any.whl
- Upload date:
- Size: 22.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f19df805632428885b578f0f881a8ae9895d439044aab10164846b44d081fcd4
|
|
| MD5 |
27dd7c90192e7b5ab2a8688b1b899a72
|
|
| BLAKE2b-256 |
bf1534472819d179e6e6baed28c13236ce16505aab80c9ac00abc8ff837da6e3
|