A dependency-free, fully managed .NET library for reading, writing, and inspecting
Minecraft Bedrock Edition .brarchive files - the archive format Mojang introduced
to bundle the many small files inside built-in resource/behavior packs
(textures.brarchive, sounds.brarchive, etc.) into a single file per directory likely to improve speed.
There's no official public specification for this format. This library is an
independent, clean-room C# implementation based on the on-disk layout as understood
from community reverse-engineering, cross-checked against two existing open-source
implementations (one Rust, one C - see THIRD-PARTY-NOTICES.md
for full credit). No code was copied from either project.
- Targets
netstandard2.0,net8.0, andnet10.0- works from .NET Framework 4.6.1+ through the latest .NET, including Unity and Xamarin/MAUI via netstandard2.0. - Zero external dependencies.
- Read, write, edit, and query archives. Pack a whole directory in one call.
- Defensive parsing: corrupt/truncated files raise a clear
BrArchiveFormatExceptioninstead of crashing or reading garbage.
dotnet add package BrArchive.Netusing BrArchive;
var archive = BrArchiveFile.ReadFile("textures.brarchive");
Console.WriteLine($"{archive.Count} entries, format version {archive.FormatVersion}");
foreach (var entry in archive.Entries)
Console.WriteLine($"{entry.Name} ({entry.Length} bytes)");if (archive.TryGetEntry("terrain_texture.json", out var entry))
{
string json = entry!.GetText(); // defaults to UTF-8
}
// Or, if you're confident it exists:
byte[] bytes = archive["flipbook_textures.json"].Data;
bool exists = archive.Contains("some_file.json");using BrArchive;
using System.Text;
BrArchiveBuilder.Create()
.Add("terrain_texture.json", jsonBytes)
.Add("flipbook_textures.json", "[]", Encoding.UTF8)
.AddFile("icon.png", "path/to/icon.png")
.SaveFile("output.brarchive");// Mirrors how vanilla archives work: one .brarchive per directory.
BrArchiveBuilder.FromDirectory("./textures")
.SaveFile("textures.brarchive");
// Or, opt in to recursive packing with '/'-separated relative names:
BrArchiveBuilder.FromDirectory("./textures", recursive: true)
.SaveFile("textures.brarchive");var archive = BrArchiveFile.ReadFile("textures.brarchive");
archive.ToBuilder()
.Remove("old_entry.json")
.Add("new_entry.json", newBytes)
.SaveFile("textures.brarchive"); // overwrite in placevar archive = await BrArchiveFile.ReadFileAsync("textures.brarchive");
await archive.WriteFileAsync("copy.brarchive");The samples/BrArchive.Net.Cli project in this repository is a small command-line
tool built on top of the library, useful on its own and as a reference for the API.
If you just want a command-line tool and don't write .NET code:
- Download a ready-to-run build - grab the zip for your OS from the Releases page, unzip it, and run it directly. No .NET SDK required.
- Or, if you already have the .NET SDK, build it from source:
git clone https://github.com/Cubeir/BrArchive.Net.git cd BrArchive.Net dotnet run --project samples/BrArchive.Net.Cli -- list mypack.brarchive
The samples/BrArchive.Net.Cli project is also useful as a reference for the
library's API if you're integrating it into your own code.
brarchive list textures.brarchive
brarchive info textures.brarchive
brarchive extract textures.brarchive ./extracted
brarchive pack ./my_textures textures.brarchive --recursive- Every valid file starts with a fixed 8-byte magic number, followed by a 4-byte
little-endian entry count and a 4-byte little-endian format version (the only
known value is
1). - Each entry is a fixed 256-byte record: a 1-byte name length, a 247-byte zero-padded UTF-8 name buffer, a 4-byte little-endian relative content offset, and a 4-byte little-endian content length.
- The full byte-level layout, with field-by-field offsets, is documented in the
XML doc comments on
BrArchiveFormatinsrc/BrArchive.Net/BrArchiveFormat.cs. - Some entries have a content length of zero - historically a common case for non-JSON
files specifically, though that's an observation, not a rule the format enforces, and
it appears to have changed across game versions as Mojang has expanded what gets
embedded. This library surfaces a zero-length entry as one with empty
DataandHasData == false, rather than guessing - it never assumes content based on file type. - Because this is a community-derived understanding of an undocumented format rather than an official spec, treat any single-project reverse-engineering (including this one) with appropriate skepticism, and please open an issue if you find a real-world archive this library mis-parses.
Minecraft's Bedrock resource pack usually mirrors its own folder structure under __brarchive/,
with one archive per directory - a nested subdirectory gets its own separate
archive file, not a combined one:
resource_pack/
├── __brarchive/
│ ├── sounds.brarchive
│ ├── textures.brarchive
│ └── textures/
│ └── entity/
│ └── banner.brarchive <- a separate archive for this subfolder
├── sounds/
└── textures/
└── entity/
└── banner/*.png
BrArchiveBuilder.FromDirectory(path) (non-recursive) produces exactly one of
these archives at a time - that's the real atomic operation. Reproducing a whole
__brarchive tree for an entire pack is a straightforward composition of that
single call, one directory level at a time:
void PackTree(string sourceDir, string archiveOutputDir)
{
Directory.CreateDirectory(archiveOutputDir);
string archiveName = Path.GetFileName(sourceDir.TrimEnd(Path.DirectorySeparatorChar)) + ".brarchive";
BrArchiveBuilder.FromDirectory(sourceDir).SaveFile(Path.Combine(archiveOutputDir, archiveName));
foreach (var subDir in Directory.GetDirectories(sourceDir))
PackTree(subDir, Path.Combine(archiveOutputDir, Path.GetFileName(subDir)));
}This library intentionally stops at that single-archive primitive rather than
shipping a full pack-replicating tool - producing an exact __brarchive tree
means guessing at Mojang's own (undocumented) packing policy, not just the
file format, so that's left to whatever you build on top.
git clone https://github.com/Cubeir/BrArchive.Net.git
cd BrArchive.Net
dotnet build
dotnet testContributions welcome - please open an issue or PR. Licensed under the
MIT License. See
THIRD-PARTY-NOTICES.md
for credit to the prior open-source work this library's understanding of the
format is based on, and CHANGELOG.md
for release history.