Files
ViaAxiom/docs/protocol.md
T
Jakob Schulz f373e3d6d9
Deploy / Build (push) Skipped
Pull Request Build / Build (pull_request) Failing after 17s
Add ViaAxiom
2026-11-01 15:30:21 +01:00

2.6 KiB

Axiom protocol notes

Taken from AxiomPaperPlugin. The "API version" is Axiom's own wire version.

Handshake

API 9: the client sends axiom:hello with VarInt API, data and protocol versions. The server answers with axiom:enable.

API 10: the server sends axiom:hello first, holding a long challenge. The client replies with the same three VarInts plus that long. Failures arrive as axiom:goodbye with a string.

Neither handshake carries the server's Minecraft version. The hello's protocol field describes the client, and the server translates IDs itself if it differs from its own. ViaAxiom writes the backend's protocol there, so only ViaAxiom translates.

An API 9 server has no hello to send. ViaAxiom detects it from minecraft:register containing axiom:hello without axiom:tunnel, and makes up the challenge itself.

axiom:enable fields:

API 9 API 10
boolean enabled boolean enabled
int max buffer size byte config version, currently 0
VarInt blueprint version VarInt blueprint version
VarInt custom data overrides int tunnel split size, default 31000
VarInt rotation overrides int max tunnel packet size, default 2097152
VarInt custom data overrides, always 0
VarInt rotation overrides, always 0
VarInt count, then serverbound channel names

Tunnel

API 10 sends large serverbound packets through axiom:tunnel. Each fragment starts with a flag byte, FIRST=1 and LAST=2. The joined body is the channel name, an int uncompressed size, a flag byte (1 means Zstd), and the payload. API 9 sends those packets raw instead, which needs Paper's large payload decoder.

Translation can change a packet's size, so ViaAxiom collects all fragments, translates, and splits again.

Payloads with block IDs

Channel Direction IDs
axiom:set_block serverbound map of long position to VarInt state
axiom:set_buffer serverbound paletted sections, type 0 only
axiom:response_chunk_data clientbound paletted sections
axiom:register_custom_block_v2 clientbound VarInt state, or -1 and a string

set_buffer is a dimension key, a UUID, a type byte, then sections of long index, paletted container, and block entities, ending at -9223371899415820288.

Paletted containers lost their long array length in protocol 770 (1.21.5). Bits per value of 0 is a single value, 4 to 8 uses a local palette, and anything higher stores global IDs.

The Axiom empty state is void_air, which means "leave this block alone". It must never become a placeholder.