Skip to content

Repository files navigation

bedrock-protocol

Version-aware C++ packet codecs for the Minecraft: Bedrock protocol, generated from a Python schema.

CI

Bedrock's wire format moves between protocol versions: fields appear, packets get reordered, and whole packets migrate to BDS's Cereal serialization. This repository holds one schema covering every version it supports, and a protoc-shaped compiler (bpc) that turns it into C++ types and serializers — one shape per version, so a consumer names the version it wants and gets a compile error if it asks for a field that era never had.

Modelled today: protocol 975 (1.26.20) and 1001 (1.26.30).

Example

The schema lives in protocol/*.py. A packet whose shape changed is declared once per era; anything smaller carries its own version range:

@packet(id=175, until=1001)
class SubChunkRequestPacket:
    dimension_type: DimensionType
    center_pos: SubChunkPos
    sub_chunk_pos_offsets: list[SubChunkPosOffset] = field(prefix=uint32)


@packet(id=175, since=1001)
class SubChunkRequestPacket:
    dimension_type: DimensionType
    sub_chunk_pos_offsets: list[SubChunkPosOffset]
    center_pos: SubChunkPos

The compiler emits one struct per version behind a selector alias, so both eras are reachable from a single name:

#include <bedrock/protocol.hpp>

namespace bp = bedrock::protocol;
using Packet = bp::SubChunkRequestPacket_<975>;

Packet packet;
packet.dimension_type = static_cast<bp::DimensionType>(0);

std::string buffer;
bp::BinaryWriter writer{buffer};
bp::Serializer<Packet>::serialize(writer, packet);

bp::BinaryReader reader{buffer};
std::expected<Packet, std::error_code> back = bp::Serializer<Packet>::deserialize(reader);

Unversioned types keep their plain name; bp::SubChunkRequestPacket without the suffix is the latest version.

Building

Requires CMake, a C++23 compiler, and uv, which runs the compiler during the build. CI covers GCC (libstdc++), Clang 18 (libc++) and MSVC.

cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
ctest --test-dir build --output-on-failure

Code generation is wired into the build, but bpc can be run directly:

uv run bpc --language cpp --out build/protocol --import-path . protocol/inventory.py

Using it

add_subdirectory(bedrock-protocol)
target_link_libraries(my_target PRIVATE bedrock::protocol)

bedrock::protocol is a static library holding the generated serializer bodies; <bedrock/protocol.hpp> includes every generated header.

Layout

path
protocol/ the schema — one module per packet family
src/bedrock_protocol/ the compiler: compiler/ (parser, descriptors, pool) and compiler/cpp/ (backend)
include/bedrock/ hand-written runtime — binary streams, the Serializer entry point, NBT
tests/ per-packet round-trip tests against goldens generated by running gophertunnel

Wire shapes are taken from protocol-docs, names and C++ types from reverse-engineered BDS headers, and golden bytes from gophertunnel. CLAUDE.md documents those sources and the conventions the schema follows.

About

A Python DSL that generates version-aware C++ packet codecs for the Minecraft: Bedrock protocol

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages