A CLI tool for building and verifying Minecraft-style content-addressable asset stores.
mc-assets takes a directory of game assets, hashes each file with SHA1, and organizes them
into a content-addressable object store — the same format Minecraft's launcher uses. An index
JSON file maps logical asset paths (e.g. minecraft/sounds/ambient/cave.ogg) to their hash
and file size. This makes asset distribution efficient: files are deduplicated by content, and
clients can verify integrity or fetch only what changed.
cargo install --path .
Hashes all files in a source directory and copies them into the object store.
mc-assets assemble <source-dir> <output-dir> --name <index-name>
Example:
mc-assets assemble ./assets ./store --name 1.7.10
Produces:
store/
indexes/
1.7.10.json
objects/
ab/
abcdef1234... (content-addressed file)
...
Idempotent: running twice on the same input produces identical output. Files already present in the object store with the correct size are skipped.
Reconstructs a flat directory of assets from an assembled object store. The reverse of assemble.
mc-assets disassemble <assets-dir> <output-dir> --index <index-name>
Example:
mc-assets disassemble ./store ./assets-restored --index 1.7.10
Reads assets-dir/indexes/<index-name>.json, then for each entry copies
assets-dir/objects/<hash[0..2]>/<hash> to output-dir/<logical-path>,
recreating the original directory tree.
Progress is printed to stderr:
Disassembled 1/1842: minecraft/sounds/ambient/cave.ogg
Disassembled 2/1842: minecraft/textures/dirt.png
...
Disassembled 1842 files to ./assets-restored
Idempotent: files already present at the destination with the correct size are skipped. If any object file is missing from the store, an error is printed and processing continues; exits with code 1 when done if any errors occurred.
Checks that every entry in an index exists and has the correct hash.
mc-assets verify <output-dir> --index <index-name>
Example:
mc-assets verify ./store --index 1.7.10
Prints only failures:
MISSING: minecraft/sounds/old.ogg
CORRUPTED: minecraft/textures/dirt.png (expected abc..., got def...)
OK: 1842 Missing: 1 Corrupted: 1
Exits with code 1 if any failures are found, 0 otherwise.
Compares two index versions from the same asset store and shows what changed between them.
mc-assets diff <assets-dir> <index-a> <index-b>
Example:
mc-assets diff ./store 1.7.10 1.7.11
Output:
Added (3):
+ minecraft/sounds/new_ambient.ogg
...
Removed (1):
- minecraft/sounds/deprecated.ogg
Changed (12):
~ minecraft/textures/terrain.png
a: aabbccdd...
b: eeff0011...
...
Unchanged: 1830 files
Always exits with code 0.
Minecraft stores asset files by their SHA1 hash rather than by name. The path of each object is:
objects/<first-2-chars-of-hash>/<full-hash>
For example, a file with hash abcdef1234... lives at objects/ab/abcdef1234....
This design has several advantages:
- Deduplication: identical files (e.g. the same sound in multiple packs) are stored once.
- Integrity: the filename is the checksum, so corruption is detected without a separate manifest.
- Incremental updates: clients fetch only hashes missing from their local store; unchanged files need no network traffic regardless of version bumps.
- Parallelism: the two-character prefix spreads files across 256 subdirectories, avoiding filesystem hotspots on large asset sets.