This is an early-stage experimental project. It is not ready for production use.
minecraft-protocol is a Kotlin Multiplatform library for the Minecraft Java Edition network protocol and world-storage
formats. It provides typed packet models, kotlinx.serialization wire codecs, Ktor transport and connection
orchestration, authentication helpers, version-matched vanilla data, binary NBT, and Anvil world I/O.
The library is infrastructure for Minecraft applications, not a complete game: gameplay, authoritative worlds, ticking, persistence policy, permissions, and operations remain application responsibilities.
| Module | Purpose |
|---|---|
nbt |
Format-independent NBT values and logical serializers |
nbt-serialization |
Binary NBT and NBT tree conversion through kotlinx.serialization |
protocol-model |
Format-independent packet payloads and shared protocol values |
protocol-serialization |
Minecraft wire encodings and composable packet registries |
protocol-vanilla-data |
Version-matched Known Packs, registries, tags, and vanilla catalogues |
protocol-transport |
Ktor sockets, framing, compression, and encryption |
protocol-session |
Typed connections, state transitions, and loader profiles |
account-auth |
Microsoft OAuth, Xbox, and Minecraft Services token/entitlement/profile HTTP APIs |
protocol-auth |
Game identities, Session Server HTTP, and Login key exchange |
protocol-client |
Status, Login, Configuration, and a Play-ready client connection |
protocol-server |
Connection admission and finite initial chunk/entity projection |
world-format |
Anvil formats and selected-release structured world-file models |
world-io |
Layered Region/Chunk, standalone NBT/JSON, live, and filesystem-backed world I/O |
The project is fully modular: depend on exactly the modules you need. Higher layers reuse the lower layers their APIs require, so a focused consumer never pulls in unrelated capabilities.
- Channel-first typed packet connections over standard coroutine channels.
- Public primitives for application-defined Status, Login, Configuration, Play entry, and initial-world synchronization; client/server presets are optional orchestration conveniences.
- Immutable, composable packet registries for vanilla and modded protocols, with preset Fabric, NeoForge, and Forge negotiation profiles.
- Offline and online Login with Session Server calls and Login key exchange; Microsoft OAuth and Xbox account HTTP APIs are available separately.
- Streaming binary NBT, selected-release level/advancement/statistics models, and filesystem-independent Anvil containers, plus Okio-based typed, full-value, and streaming world I/O—including live reads of official-server worlds.
Usage examples are documented at each owning layer: binary NBT in
nbt-serialization, compression and Anvil containers in
world-format, and filesystem-backed JSON, NBT, MCA, and MCC access in
world-io. Every published module in the table above documents its
own key entry points rather than requiring consumers to infer them from a higher layer.
Together these blocks cover applications such as:
- map editors that read, render, and rewrite Anvil worlds directly, including worlds owned by a running official server;
- Minecraft launchers, combining Microsoft/Xbox account authentication with server sessions;
- clients and servers built entirely on this library's protocol implementation, without depending on official Minecraft code.
Unknown top-level packet IDs, Login queries, and custom-payload routes stay lossless as direction-correct
UnknownPacket values; malformed wire data and invalid packet order propagate instead of being swallowed.
Ping a server as the multiplayer server list does. queryStatus() performs the Status handshake, obtains the server's
Status response, and completes the Ping/Pong exchange; it does not run Login negotiation:
SelectorManager(Dispatchers.Default).use { selector ->
MinecraftClientConnection.connect(
selectorManager = selector,
host = "127.0.0.1",
).use { connection ->
val status = connection.queryStatus()
val description = status.response.jsonResponse
val echoedPingPayload = status.pong.timestamp
}
}Status has no continuation into Login. Close this connection after the ping, then create a fresh connection and call
negotiate() only when joining the server.
Or log in and enter Play, then take over the packet loop:
connection.negotiate(MinecraftOfflineIdentity("Player"))
for (packet in connection.incoming) {
handlePlayPacket(packet)
}The preset runs in the calling coroutine and exclusively owns incoming and outgoing until it returns. No other
coroutine may read or write either channel during that interval. Applications can write the negotiation sequence
themselves under the same single-coroutine ownership precondition; the library assumes that ownership and does not lock
or arbitrate application-created races. Read the maintained client
negotiate implementation
and server
negotiate implementation
as the source-level packet-order references. The
protocol-client
and protocol-server guides identify the public primitives
used by those implementations.
MinecraftServer.bind(selectorManager = selector).use { server ->
while (server.isOpen) {
val connection = server.accept()
launch {
connection.use {
connection.negotiate() ?: return@use
for (packet in connection.incoming) {
handlePlayPacket(connection, packet)
}
}
}
}
}Requirements:
- A JDK with
javaonPATH; the project's Java major version follows the Java version required by the matching Minecraft release. SeeBuildVersions.JAVA_VERSIONin the Gradle configuration for the current value. - An Android SDK configured through the standard Gradle mechanisms, only when building or testing Android targets.
- Network access for the first build so Gradle can download dependencies; tests that verify against official Minecraft peers additionally download exact-version fixtures.
Use the checked-in Gradle wrapper; a separate Gradle installation is unnecessary. Gradle provisions Node and the other non-JVM toolchains automatically.
# Assemble everything
./gradlew build
# Focused feedback loop during development
./gradlew :protocol-serialization:jvmTest
# Every module's JVM suite
./gradlew jvmTest
# All configured multiplatform tests
./gradlew allTestsOn Windows, replace ./gradlew with .\gradlew.bat.
The repository aligns to one Minecraft release at a time. In code, the matching release and protocol number are exposed
by MinecraftProtocol:
val release = MinecraftProtocol.MINECRAFT_VERSION
val protocolVersion = MinecraftProtocol.PROTOCOL_VERSIONPrint the currently selected release from the command line:
./gradlew -q minecraftVersionChanging the target is a single-constant change in the build configuration, followed by the affected build or test tasks.
See each module's README for its API and examples.