net_structures

package
v0.0.0-...-075a84e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 17, 2026 License: MIT Imports: 10 Imported by: 0

README

net_structures

Go implementation of Minecraft Java Edition protocol data types.

Based on the Minecraft Wiki protocol documentation and the decompiled 1.21.11 client source code.

Data Types

Primitives

All multi-byte integers use big-endian byte order (same as Java/Netty). These map directly to Go's encoding/binary.BigEndian.

Protocol Type Go Type Size Notes
Boolean Boolean 1 0x00 = false, 0x01 = true
Byte Int8 1 Signed 8-bit
Unsigned Byte Uint8 1 Unsigned 8-bit
Short Int16 2 Signed 16-bit
Unsigned Short Uint16 2 Unsigned 16-bit
Int Int32 4 Signed 32-bit
Long Int64 8 Signed 64-bit
Float Float32 4 IEEE 754 single-precision
Double Float64 8 IEEE 754 double-precision
Variable-Length Integers
Protocol Type Go Type Max Size Notes
VarInt VarInt 5 bytes 7-bit encoding with continuation bit
VarLong VarLong 10 bytes Same encoding for 64-bit

Encoding: each byte uses bits 0-6 for data, bit 7 as continuation flag (1 = more bytes follow).

0          -> [0x00]
127        -> [0x7f]
128        -> [0x80, 0x01]
-1         -> [0xff, 0xff, 0xff, 0xff, 0x0f]
Strings
Protocol Type Go Type Notes
String String VarInt byte-length prefix + UTF-8 bytes
Identifier Identifier Same as String, format: namespace:path
Complex Types
Protocol Type Go Type Notes
Position Position Block coordinates packed into int64: X(26 bits) + Z(26 bits) + Y(12 bits)
UUID UUID 128-bit, stored as [16]byte
Angle Angle Rotation in 1/256 of a full turn (1 byte)
Byte Array ByteArray VarInt length prefix + raw bytes
LpVec3 LpVec3 Low-precision 3D vector for entity velocity
Composite Types

These types handle common patterns like length-prefixed arrays, boolean-prefixed optionals, and bit sets.

Protocol Type Go Type Wire Format
Prefixed Array PrefixedArray[T] VarInt length + elements
Prefixed Optional PrefixedOptional[T] Boolean + value (if true)
BitSet BitSet VarInt length (in longs) + int64 array
Fixed BitSet FixedBitSet ceil(n/8) bytes (no length prefix)
ID Set IDSet VarInt type + tag name or IDs
X or Y XOrY[X, Y] Boolean selector + X or Y value
ID or X IDOrX[T] VarInt ID (0 = inline value follows)

Usage

import ns "github.com/go-mclib/protocol/java_protocol/net_structures"

// writing
buf := ns.NewWriter()
buf.WriteVarInt(25565)
buf.WriteString("localhost")
buf.WriteUint16(25565)
buf.WritePosition(ns.Position{X: 100, Y: 64, Z: -200})
data := buf.Bytes()

// reading
buf := ns.NewReader(data)
version, _ := buf.ReadVarInt()
address, _ := buf.ReadString(255)
port, _ := buf.ReadUint16()
pos, _ := buf.ReadPosition()

// low-level streaming (directly with net.Conn)
buf := ns.NewWriterTo(conn)
buf.WriteVarInt(0x00)

buf := ns.NewReaderFrom(conn)
packetID, _ := buf.ReadVarInt()
Composite Types Usage
// PrefixedArray - VarInt length-prefixed array
type MyPacket struct {
    Names ns.PrefixedArray[ns.String]
}

func (p *MyPacket) Read(buf *ns.PacketBuffer) error {
    return p.Names.DecodeWith(buf, func(b *ns.PacketBuffer) (ns.String, error) {
        return b.ReadString(32767)
    })
}

func (p *MyPacket) Write(buf *ns.PacketBuffer) error {
    return p.Names.EncodeWith(buf, func(b *ns.PacketBuffer, v ns.String) error {
        return b.WriteString(v)
    })
}

// PrefixedOptional - Boolean-prefixed optional
type MyPacket2 struct {
    Title ns.PrefixedOptional[ns.String]
}

// create optionals
title := ns.Some("Hello")       // present
noTitle := ns.None[ns.String]() // absent

// BitSet - dynamic bit set
bits := ns.NewBitSet(128)
bits.Set(5)
bits.Get(5) // true
bits.Encode(buf)

// FixedBitSet - fixed-size bit set
fixed := ns.NewFixedBitSet(20) // 20 bits = 3 bytes
fixed.Set(0)
fixed.Encode(buf)

// IDSet - registry ID set
tagSet := ns.NewTagIDSet("minecraft:climbable")
inlineSet := ns.NewInlineIDSet([]ns.VarInt{1, 2, 3})
XOrY - Boolean-Selected Variant

XOrY[X, Y] represents a value that can be one of two types, selected by a boolean.

// wire format: Boolean (isX) + X or Y value
type MyPacket struct {
    // either an inline value or a registry reference
    Data ns.XOrY[InlineData, ns.VarInt]
}

// create variants
xVal := ns.NewX[InlineData, ns.VarInt](myData) // isX = true
yVal := ns.NewY[InlineData, ns.VarInt](42)     // isX = false

// decode
var v ns.XOrY[InlineData, ns.VarInt]
v.DecodeWith(buf,
    func(b *ns.PacketBuffer) (InlineData, error) { return decodeInline(b) },
    func(b *ns.PacketBuffer) (ns.VarInt, error) { return b.ReadVarInt() },
)

// check which variant
x, y, isX := v.Get()
if isX {
    // use x
} else {
    // use y
}
IDOrX - Registry ID or Inline Value

IDOrX[T] represents either a registry ID reference or an inline value.

// wire format: VarInt (0 = inline follows, >0 = ID + 1)
type MyPacket struct {
    Effect ns.IDOrX[EffectData]
}

// create variants
byID := ns.NewIDRef[EffectData](5)           // references registry ID 5
inline := ns.NewInlineValue(EffectData{...}) // inline value

// decode
var v ns.IDOrX[EffectData]
v.DecodeWith(buf, func(b *ns.PacketBuffer) (EffectData, error) {
    return decodeEffect(b)
})

// check which variant
id, value, isInline := v.Get()
if isInline {
    // use value
} else {
    // look up id in registry
}
LpVec3 - Low-Precision Vector

LpVec3 encodes 3 float64 values in typically 6 bytes using 15-bit scaled values. Used for entity velocity.

// write
vel := ns.LpVec3{X: 0.5, Y: -0.1, Z: 0.0}
buf.WriteLpVec3(vel)

// read
vel, _ := buf.ReadLpVec3()
fmt.Printf("velocity: %.4f, %.4f, %.4f\n", vel.X, vel.Y, vel.Z)

Wire format:

  • If all components are essentially zero (< 3.05e-5), sends single 0x00 byte
  • Otherwise: 6 bytes encoding scale (3 bits) + X/Y/Z (15 bits each)
GameProfile

GameProfile represents a player's profile with UUID, username, and properties.

// read
profile, _ := buf.ReadGameProfile()
fmt.Printf("player: %s (%s)\n", profile.Username, profile.UUID)

// write
profile := ns.GameProfile{
    UUID:     playerUUID,
    Username: "Steve",
}
buf.WriteGameProfile(profile)

// with properties (e.g., textures)
profile.Properties = ns.PrefixedArray[ns.ProfileProperty]{
    {
        Name:  "textures",
        Value: base64TextureData,
        Signature: ns.Some(signatureData),
    },
}

ResolvableProfile is a variant that can be partial (for lookups) or complete:

// partial profile (for server-side resolution)
partial := ns.NewPartialProfile()
partial.PartialUsername = ns.Some("Steve")

// complete profile
complete := ns.NewCompleteProfile(gameProfile)
complete.BodyModel = ns.Some(ns.Identifier("minecraft:slim"))
NBT (Named Binary Tag)

NBT is used for complex structured data in packets. The nbt package supports both file format (with root name) and network format (nameless root) used in packets. For communication with the server, use the network format.

Direct decoding
import "github.com/go-mclib/protocol/nbt"

type EntityData struct {
    Name     string `nbt:"Name"`
    Position int64  `nbt:"Position"`
    OnGround bool   `nbt:"OnGround"`
}

type S2CSomePacket struct {
    EntityID   ns.VarInt
    Data       EntityData
    ExtraField ns.VarInt
}

func (p *S2CSomePacket) Read(buf *ns.PacketBuffer) error {
    var err error
    if p.EntityID, err = buf.ReadVarInt(); err != nil {
        return err
    }

    // use nbt.NewReaderFrom to read the NBT data, which stops at TAG_End
    nbtReader := nbt.NewReaderFrom(buf.Reader())
    tag, _, err := nbtReader.ReadTag(true) // true = network format
    if err != nil {
        return err
    }
    if err := nbt.UnmarshalTag(tag, &p.Data); err != nil {
        return err
    }
    p.ExtraField, err = buf.ReadVarInt()
    return err
}

func (p *S2CSomePacket) Write(buf *ns.PacketBuffer) error {
    if err := buf.WriteVarInt(p.EntityID); err != nil {
        return err
    }
    nbtData, err := nbt.MarshalNetwork(p.Data)
    if err != nil {
        return err
    }
    if _, err := buf.Write(nbtData); err != nil {
        return err
    }
    return buf.WriteVarInt(p.ExtraField)
}
Storing as nbt.Tag (lazy processing)

For packets where you want to defer NBT processing (maybe the NBT data is too large, or dynamic):

type S2CSomePacket struct {
    EntityID ns.VarInt
    Data     nbt.Tag   // store as generic Tag
}

func (p *S2CSomePacket) Read(buf *ns.PacketBuffer) error {
    var err error
    if p.EntityID, err = buf.ReadVarInt(); err != nil {
        return err
    }
    nbtReader := nbt.NewReaderFrom(buf.Reader())
    p.Data, _, err = nbtReader.ReadTag(true)
    return err
}

// later, convert to struct to grab values when needed
// extra fields in the NBT data that are not present in
// the EntityData struct will be skipped
var entityData EntityData
err := nbt.UnmarshalTag(packet.Data, &entityData)
Empty/Optional NBT

Some packets use a single TAG_End byte (0x00) to indicate empty or absent NBT data. Check for nbt.End{} type after reading:

tag, _, err := nbtReader.ReadTag(true)
if _, isEmpty := tag.(nbt.End); isEmpty {
    // no NBT data present
}
Text Component

Text components are used for chat messages, item names, titles, and other formatted text. Simple text-only components use NBT String tags, complex components use NBT Compound tags. JSON serialization is also supported (all fields carry json struct tags).

// simple text
tc := ns.NewTextComponent("Hello, World!")

// with style
bold := true
tc := ns.TextComponent{
    Text:  "Styled text",
    Color: "red",
    Bold:  &bold,
}

// translatable
tc := ns.NewTranslateComponent("chat.type.text",
    ns.NewTextComponent("Player"),
    ns.NewTextComponent("Hello"),
)

// with children
tc := ns.TextComponent{
    Text: "Hello, ",
    Extra: []ns.TextComponent{
        {Text: "World", Color: "gold"},
        {Text: "!"},
    },
}

// read/write (NBT format)
buf.WriteTextComponent(tc)
tc, _ := buf.ReadTextComponent()

// JSON (handles both plain strings and objects)
json.Unmarshal([]byte(`"Hello"`), &tc)        // plain string
json.Unmarshal([]byte(`{"text":"Hello"}`), &tc) // object
data, _ := json.Marshal(tc)
Rendering

Text components can be converted to various text formats:

tc := ns.TextComponent{Text: "Hello", Color: "red", Bold: &bold}

tc.String()     // "Hello"                - plain text, no formatting
tc.ANSI()       // "\033[91m\033[1mHello\033[0m" - ANSI terminal colors
tc.ColorCodes() // "§c§lHello"            - Bukkit-style § color codes
tc.MiniMessage() // "<red><bold>Hello</bold></red>" - Adventure MiniMessage

All renderers recurse into Extra and With children. ANSI() supports named colors, hex colors (#rrggbb via 24-bit ANSI), bold, italic, underline, strikethrough, and obfuscated. MiniMessage() emits <lang:key:args> for translatable components and <key:name> for keybinds.

Slot (Item Stack)

Slots represent item stacks with data components. This package stores components as raw bytes - callers should use a higher-level package to parse specific component types.

Wire format:

  • VarInt count - item count (0 = empty slot)
  • VarInt item_id - registry ID (only if count > 0)
  • VarInt add_count - components to add
  • VarInt remove_count - components to remove
  • Components: each is VarInt id + component-specific data
// empty slot
slot := ns.EmptySlot()

// basic item
slot := ns.NewSlot(1, 64) // item ID 1, 64 count

// add raw component data
slot.AddComponent(3, []byte{0x32}) // component ID 3 with data

// remove a component type
slot.RemoveComponent(4)

// reading requires a decoder that knows component sizes
slot, err := buf.ReadSlot(func(buf *ns.PacketBuffer, id ns.VarInt) ([]byte, error) {
    // decode component based on ID, return raw bytes
    switch id {
    case 3: // damage component
        v, err := buf.ReadVarInt()
        if err != nil {
            return nil, err
        }
        return encodeVarInt(v), nil
    default:
        return nil, fmt.Errorf("unknown component: %d", id)
    }
})

// writing
buf.WriteSlot(slot)

// get raw component by ID
if comp := slot.GetComponent(3); comp != nil {
    // comp.ID, comp.Data
}
Chunk Data

ChunkData represents chunk section data and block entities. Heightmaps are stored as raw NBT, chunk sections as raw bytes. Parsing block data requires knowledge of the current registry.

// read chunk data
chunkData, err := buf.ReadChunkData()

// heightmaps as NBT compound
fmt.Printf("heightmaps: %v\n", chunkData.Heightmaps)

// raw chunk section data (needs registry to parse)
fmt.Printf("data size: %d bytes\n", len(chunkData.Data))

// block entities
for _, be := range chunkData.BlockEntities {
    x, z := be.X(), be.Z() // relative coords 0-15
    y := be.Y             // absolute Y
    typeID := be.Type     // block entity type registry ID
    data := be.Data       // NBT data
}

// write
buf.WriteChunkData(chunkData)
Light Data

LightData represents lighting information for a chunk, including sky and block light.

// read light data
lightData, err := buf.ReadLightData()

// check which sections have light data
if lightData.SkyLightMask.Get(5) {
    // section 5 has sky light data
}

// light arrays are 2048 bytes each (4096 nibbles for 16x16x16 blocks)
for i, arr := range lightData.SkyLightArrays {
    // each byte contains 2 light values (4 bits each)
}

// write
buf.WriteLightData(lightData)

Wire format:

  • SkyLightMask - BitSet indicating sections with sky light
  • BlockLightMask - BitSet indicating sections with block light
  • EmptySkyLightMask - BitSet indicating sections with all-zero sky light
  • EmptyBlockLightMask - BitSet indicating sections with all-zero block light
  • SkyLightArrays - VarInt count + 2048-byte arrays
  • BlockLightArrays - VarInt count + 2048-byte arrays

References

Documentation

Overview

These types handle common patterns like length-prefixed arrays, boolean-prefixed optionals, and bit sets.

See https://minecraft.wiki/w/Java_Edition_protocol/Data_types

Package net_structures provides primitive types and serialization utilities for the Minecraft Java Edition protocol.

All types follow the Minecraft protocol specification: https://minecraft.wiki/w/Java_Edition_protocol/Data_types

Index

Constants

This section is empty.

Variables

View Source
var NilUUID = UUID{}

NilUUID is the zero UUID (all zeros).

Functions

func ValidateUUID

func ValidateUUID(uuid string) bool

ValidateUUID checks if a string is a valid UUID format. Accepts formats: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" (36 chars) or "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" (32 chars)

Types

type Angle

type Angle uint8

Angle represents a rotation angle.

Stored as a single byte where 256 units = 360 degrees (full rotation). Each unit represents 1/256 of a full turn (1.40625 degrees).

Examples:

0   = 0°
64  = 90°
128 = 180°
192 = 270°

func AngleFromDegrees

func AngleFromDegrees(degrees float64) Angle

AngleFromDegrees converts degrees to an Angle.

func DecodeAngle

func DecodeAngle(r io.Reader) (Angle, error)

DecodeAngle reads an Angle from r.

func (Angle) Degrees

func (a Angle) Degrees() float64

Degrees converts the Angle to degrees (0-360).

func (Angle) Encode

func (a Angle) Encode(w io.Writer) error

Encode writes the Angle to w.

func (Angle) Radians

func (a Angle) Radians() float64

Radians converts the Angle to radians (0-2π).

type BitSet

type BitSet struct {
	// contains filtered or unexported fields
}

BitSet is a dynamically-sized bit set, prefixed by its length in longs.

Wire format:

┌─────────────────┬─────────────────────────────────────┐
│  Length (VarInt)│  Longs (Int64 × Length)             │
└─────────────────┴─────────────────────────────────────┘

The ith bit is set when (Data[i/64] & (1 << (i % 64))) != 0.

func NewBitSet

func NewBitSet(capacity int) *BitSet

NewBitSet creates a BitSet with the given capacity in bits.

func (*BitSet) Clear

func (b *BitSet) Clear(i int)

Clear clears the bit at index i.

func (*BitSet) Decode

func (b *BitSet) Decode(buf *PacketBuffer) error

Decode reads a BitSet from the buffer.

func (*BitSet) Encode

func (b *BitSet) Encode(buf *PacketBuffer) error

Encode writes a BitSet to the buffer.

func (*BitSet) Get

func (b *BitSet) Get(i int) bool

Get returns whether the bit at index i is set.

func (*BitSet) Longs

func (b *BitSet) Longs() []int64

Longs returns the underlying long array.

func (*BitSet) Set

func (b *BitSet) Set(i int)

Set sets the bit at index i.

type BlockEntity

type BlockEntity struct {
	// PackedXZ contains relative X (high nibble) and Z (low nibble) coordinates.
	PackedXZ Uint8

	// Y is the absolute Y coordinate.
	Y Int16

	// Type is the block entity type registry ID.
	Type VarInt

	// Data is the block entity's NBT data (without x, y, z fields).
	Data nbt.Tag
}

BlockEntity represents a block entity within a chunk.

Wire format:

┌──────────────────┬────────────────────┬─────────────────┬──────────────────┐
│  PackedXZ (byte) │  Y (short)         │  Type (VarInt)  │  Data (NBT)      │
└──────────────────┴────────────────────┴─────────────────┴──────────────────┘

PackedXZ encodes relative X and Z coordinates:

packed = ((blockX & 15) << 4) | (blockZ & 15)
x = packed >> 4, z = packed & 15

func (*BlockEntity) Decode

func (b *BlockEntity) Decode(buf *PacketBuffer) error

Decode reads a BlockEntity from the buffer.

func (*BlockEntity) Encode

func (b *BlockEntity) Encode(buf *PacketBuffer) error

Encode writes a BlockEntity to the buffer.

func (*BlockEntity) SetXZ

func (b *BlockEntity) SetXZ(x, z int)

SetXZ sets the PackedXZ field from relative X and Z coordinates.

func (*BlockEntity) X

func (b *BlockEntity) X() int

X returns the relative X coordinate (0-15) from PackedXZ.

func (*BlockEntity) Z

func (b *BlockEntity) Z() int

Z returns the relative Z coordinate (0-15) from PackedXZ.

type Boolean

type Boolean bool

Boolean is a single byte (0x00 = false, 0x01 = true).

func DecodeBoolean

func DecodeBoolean(r io.Reader) (Boolean, error)

DecodeBoolean reads a Boolean from r.

func (Boolean) Encode

func (v Boolean) Encode(w io.Writer) error

Encode writes the Boolean to w.

type ByteArray

type ByteArray = []byte

ByteArray is a raw byte sequence used throughout the protocol.

type ChunkData

type ChunkData struct {
	// Heightmaps maps heightmap type IDs to long arrays.
	// Type IDs: 1=WORLD_SURFACE, 4=MOTION_BLOCKING, 5=MOTION_BLOCKING_NO_LEAVES.
	Heightmaps map[int32][]int64

	// Data contains packed chunk sections. Each section contains:
	// - Block count (short)
	// - Block states (paletted container)
	// - Biomes (paletted container)
	Data []byte

	// BlockEntities in this chunk.
	BlockEntities []BlockEntity
}

ChunkData represents the data portion of chunk packets. Heightmaps are encoded as a VarInt-keyed map of long arrays (protocol 774+). Chunk sections are raw bytes. Block entities follow.

Wire format:

┌─────────────────────────────────────────────────────────────────────────┐
│  Heightmaps (VarInt count + entries of VarInt key + VarInt len + longs) │
├─────────────────────────────────────────────────────────────────────────┤
│  Data (VarInt length + raw bytes containing chunk sections)             │
├─────────────────────────────────────────────────────────────────────────┤
│  BlockEntities (VarInt length + array of BlockEntity)                   │
└─────────────────────────────────────────────────────────────────────────┘

func (*ChunkData) Decode

func (c *ChunkData) Decode(buf *PacketBuffer) error

Decode reads ChunkData from the buffer.

func (*ChunkData) Encode

func (c *ChunkData) Encode(buf *PacketBuffer) error

Encode writes ChunkData to the buffer.

type ClickEvent

type ClickEvent struct {
	Action  string `nbt:"action"`
	URL     string `nbt:"url,omitempty"`     // open_url
	Path    string `nbt:"path,omitempty"`    // open_file
	Command string `nbt:"command,omitempty"` // run_command, suggest_command
	Page    int32  `nbt:"page,omitempty"`    // change_page
	Value   string `nbt:"value,omitempty"`   // copy_to_clipboard
	Dialog  any    `nbt:"dialog,omitempty"`  // show_dialog
	ID      string `nbt:"id,omitempty"`      // custom
	Payload any    `nbt:"payload,omitempty"` // custom
}

ClickEvent represents a click event for text components (1.21.5+ format). Each action type uses a different field; the Action field determines which is relevant.

type ElementDecoder

type ElementDecoder[T any] func(buf *PacketBuffer) (T, error)

ElementDecoder is a function that decodes an element from a buffer.

type ElementEncoder

type ElementEncoder[T any] func(buf *PacketBuffer, v T) error

ElementEncoder is a function that encodes an element to a buffer.

type FixedBitSet

type FixedBitSet struct {
	// contains filtered or unexported fields
}

FixedBitSet is a fixed-size bit set encoded as ceil(n/8) bytes.

Wire format:

┌─────────────────────────────────────────────────────────┐
│  Bytes (ceil(n/8) bytes, no length prefix)              │
└─────────────────────────────────────────────────────────┘

The ith bit is set when (Data[i/8] & (1 << (i % 8))) != 0.

func FixedBitSetFromBytes

func FixedBitSetFromBytes(data []byte, size int) *FixedBitSet

FixedBitSetFromBytes creates a FixedBitSet from raw bytes.

func NewFixedBitSet

func NewFixedBitSet(size int) *FixedBitSet

NewFixedBitSet creates a FixedBitSet with the given size in bits.

func (*FixedBitSet) Bytes

func (b *FixedBitSet) Bytes() []byte

Bytes returns the underlying byte array.

func (*FixedBitSet) Clear

func (b *FixedBitSet) Clear(i int)

Clear clears the bit at index i.

func (*FixedBitSet) Decode

func (b *FixedBitSet) Decode(buf *PacketBuffer) error

Decode reads a FixedBitSet of the configured size from the buffer.

func (*FixedBitSet) Encode

func (b *FixedBitSet) Encode(buf *PacketBuffer) error

Encode writes a FixedBitSet to the buffer.

func (*FixedBitSet) Get

func (b *FixedBitSet) Get(i int) bool

Get returns whether the bit at index i is set.

func (*FixedBitSet) Set

func (b *FixedBitSet) Set(i int)

Set sets the bit at index i.

func (*FixedBitSet) Size

func (b *FixedBitSet) Size() int

Size returns the number of bits in the set.

type Float32

type Float32 float32

Float32 is a big-endian IEEE 754 single-precision float.

func DecodeFloat32

func DecodeFloat32(r io.Reader) (Float32, error)

DecodeFloat32 reads a Float32 from r.

func (Float32) Encode

func (v Float32) Encode(w io.Writer) error

Encode writes the Float32 to w.

type Float64

type Float64 float64

Float64 is a big-endian IEEE 754 double-precision float.

func DecodeFloat64

func DecodeFloat64(r io.Reader) (Float64, error)

DecodeFloat64 reads a Float64 from r.

func (Float64) Encode

func (v Float64) Encode(w io.Writer) error

Encode writes the Float64 to w.

type GameProfile

type GameProfile struct {
	UUID       UUID
	Username   String
	Properties PrefixedArray[ProfileProperty]
}

GameProfile represents a complete player profile with UUID, username, and properties.

Wire format:

┌───────────────────┬─────────────────────────────────────────────────┐
│  UUID (16 bytes)  │  Username (String, max 16)                      │
├───────────────────┼─────────────────────────────────────────────────┤
│  Properties (VarInt length + array of ProfileProperty)              │
└─────────────────────────────────────────────────────────────────────┘

func (*GameProfile) Decode

func (p *GameProfile) Decode(buf *PacketBuffer) error

Decode reads a GameProfile from the buffer.

func (*GameProfile) Encode

func (p *GameProfile) Encode(buf *PacketBuffer) error

Encode writes a GameProfile to the buffer.

type GlobalPos

type GlobalPos struct {
	Dimension Identifier
	Pos       Position
}

GlobalPos represents a position in a specific dimension. Used for things like death locations.

Wire format:

┌─────────────────────────┬─────────────────────────┐
│  Dimension (Identifier)  │  Position (Int64)       │
└─────────────────────────┴─────────────────────────┘

func DecodeGlobalPos

func DecodeGlobalPos(r io.Reader) (GlobalPos, error)

DecodeGlobalPos reads a GlobalPos from r.

func (GlobalPos) Encode

func (g GlobalPos) Encode(w io.Writer) error

Encode writes the GlobalPos to w.

type HashedComponent

type HashedComponent struct {
	ID   VarInt
	Hash Int32
}

HashedComponent stores a component type ID and its CRC32C hash.

type HashedComponents

type HashedComponents struct {
	Add    []HashedComponent // component type ID → CRC32C hash
	Remove []VarInt          // component type IDs to remove
}

HashedComponents holds component hashes for a hashed slot.

type HashedSlot

type HashedSlot struct {
	Present    bool
	ItemID     VarInt
	Count      VarInt
	Components HashedComponents
}

HashedSlot represents an item stack where component data is replaced with CRC32C hashes. Used in C2S packets (e.g. ContainerClick) where the server only needs to verify component identity, not read full data.

Wire format:

┌───────────────────┬─────────────────┬─────────────────┬───────────────────────────────────────┐
│  Present (Bool)   │  ItemID (VarInt)│  Count (VarInt) │  HashedPatchMap                       │
└───────────────────┴─────────────────┴─────────────────┴───────────────────────────────────────┘

If Present is false, the slot is empty and no further data is read.

HashedPatchMap:

┌──────────────────────┬────────────────────────────────┬──────────────────────┬─────────────────────┐
│  AddedCount (VarInt) │  Added (VarInt ID + Int32) × N │  RemovedCount (VarInt)│  Removed (VarInt) × M│
└──────────────────────┴────────────────────────────────┴──────────────────────┴─────────────────────┘

func EmptyHashedSlot

func EmptyHashedSlot() HashedSlot

EmptyHashedSlot returns an empty hashed slot.

func NewHashedSlot

func NewHashedSlot(itemID VarInt, count VarInt) HashedSlot

NewHashedSlot creates a hashed slot with the given item and count.

func (*HashedSlot) Decode

func (s *HashedSlot) Decode(buf *PacketBuffer) error

Decode reads a hashed slot from the buffer.

func (*HashedSlot) Encode

func (s *HashedSlot) Encode(buf *PacketBuffer) error

Encode writes the hashed slot to the buffer.

func (*HashedSlot) IsEmpty

func (s *HashedSlot) IsEmpty() bool

IsEmpty returns true if the hashed slot is empty.

type HoverEvent

type HoverEvent struct {
	Action string `nbt:"action"`
	// show_text
	Value any `nbt:"value,omitempty"` // TextComponent (string or compound NBT)
	// show_entity and show_item
	ID string `nbt:"id,omitempty"` // entity type or item ID
	// show_entity
	EntityUUID any `nbt:"uuid,omitempty"` // IntArray in NBT
	Name       any `nbt:"name,omitempty"` // optional TextComponent (string or compound NBT)
	// show_item
	Count      int32 `nbt:"count,omitempty"`
	Components any   `nbt:"components,omitempty"` // item components compound
}

HoverEvent represents a hover event for text components (1.21.5+ format). Each action type uses different fields; the Action field determines which are relevant.

type IDOrX

type IDOrX[T any] struct {
	// IsInline indicates whether this contains an inline value (true) or a registry ID (false).
	IsInline bool
	// ID is the registry ID (only valid if IsInline is false).
	// Note: wire format uses ID+1, but this field stores the actual ID.
	ID VarInt
	// Value is the inline value (only valid if IsInline is true).
	Value T
}

IDOrX represents a registry ID or an inline value. Used when a field can reference a registry entry by ID or define a value inline.

Wire format:

┌─────────────────┬─────────────────────────────────────┐
│  ID (VarInt)    │  Value (X, only if ID = 0)          │
└─────────────────┴─────────────────────────────────────┘

If ID = 0, the inline value follows. If ID > 0, it represents registry ID + 1 (actual ID is ID - 1).

func NewIDRef

func NewIDRef[T any](id VarInt) IDOrX[T]

NewIDRef creates an IDOrX that references a registry entry.

func NewInlineValue

func NewInlineValue[T any](value T) IDOrX[T]

NewInlineValue creates an IDOrX with an inline value.

func (*IDOrX[T]) DecodeWith

func (x *IDOrX[T]) DecodeWith(buf *PacketBuffer, decode ElementDecoder[T]) error

DecodeWith reads an IDOrX using the provided decoder for inline values.

func (IDOrX[T]) EncodeWith

func (x IDOrX[T]) EncodeWith(buf *PacketBuffer, encode ElementEncoder[T]) error

EncodeWith writes an IDOrX using the provided encoder for inline values.

func (IDOrX[T]) Get

func (x IDOrX[T]) Get() (id VarInt, value T, isInline bool)

Get returns the ID (if reference) or -1 (if inline), and the inline value if present.

type IDSet

type IDSet struct {
	// IsTag indicates whether this is a tag reference (true) or inline IDs (false).
	IsTag bool
	// TagName is the tag identifier (only valid if IsTag is true).
	TagName Identifier
	// IDs is the list of registry IDs (only valid if IsTag is false).
	IDs []VarInt
}

IDSet represents a registry ID set, which can be either a tag reference or an inline list of IDs.

Wire format:

┌─────────────────┬─────────────────────────────────────┐
│  Type (VarInt)  │  Data (depends on Type)             │
└─────────────────┴─────────────────────────────────────┘

If Type = 0: followed by an Identifier (tag name) If Type > 0: followed by (Type - 1) VarInt IDs

func NewInlineIDSet

func NewInlineIDSet(ids []VarInt) *IDSet

NewInlineIDSet creates an IDSet with inline IDs.

func NewTagIDSet

func NewTagIDSet(tagName Identifier) *IDSet

NewTagIDSet creates an IDSet that references a tag.

func (*IDSet) Decode

func (s *IDSet) Decode(buf *PacketBuffer) error

Decode reads an IDSet from the buffer.

func (*IDSet) Encode

func (s *IDSet) Encode(buf *PacketBuffer) error

Encode writes an IDSet to the buffer.

type Identifier

type Identifier string

Identifier is a namespaced location string.

Format: "namespace:path" where:

  • namespace: Only lowercase letters, digits, underscores, hyphens, and periods
  • path: Same as namespace plus forward slashes
  • If no colon, defaults to "minecraft" namespace

Examples:

"minecraft:stone"
"minecraft:textures/block/stone.png"
"custom:my_item"

func DecodeIdentifier

func DecodeIdentifier(r io.Reader) (Identifier, error)

DecodeIdentifier reads an Identifier from r.

func (Identifier) Encode

func (v Identifier) Encode(w io.Writer) error

Encode writes the Identifier to w.

func (Identifier) Namespace

func (id Identifier) Namespace() string

Namespace returns the namespace part of the identifier. Returns "minecraft" if no namespace is specified.

func (Identifier) Path

func (id Identifier) Path() string

Path returns the path part of the identifier.

type Int8

type Int8 int8

Int8 is a signed 8-bit integer (-128 to 127).

func DecodeInt8

func DecodeInt8(r io.Reader) (Int8, error)

DecodeInt8 reads an Int8 from r.

func (Int8) Encode

func (v Int8) Encode(w io.Writer) error

Encode writes the Int8 to w.

type Int16

type Int16 int16

Int16 is a big-endian signed 16-bit integer.

func DecodeInt16

func DecodeInt16(r io.Reader) (Int16, error)

DecodeInt16 reads an Int16 from r.

func (Int16) Encode

func (v Int16) Encode(w io.Writer) error

Encode writes the Int16 to w.

type Int32

type Int32 int32

Int32 is a big-endian signed 32-bit integer.

func DecodeInt32

func DecodeInt32(r io.Reader) (Int32, error)

DecodeInt32 reads an Int32 from r.

func (Int32) Encode

func (v Int32) Encode(w io.Writer) error

Encode writes the Int32 to w.

type Int64

type Int64 int64

Int64 is a big-endian signed 64-bit integer.

func DecodeInt64

func DecodeInt64(r io.Reader) (Int64, error)

DecodeInt64 reads an Int64 from r.

func (Int64) Encode

func (v Int64) Encode(w io.Writer) error

Encode writes the Int64 to w.

type LightData

type LightData struct {
	// SkyLightMask indicates which sections have sky light data.
	SkyLightMask BitSet

	// BlockLightMask indicates which sections have block light data.
	BlockLightMask BitSet

	// EmptySkyLightMask indicates which sections have all-zero sky light.
	EmptySkyLightMask BitSet

	// EmptyBlockLightMask indicates which sections have all-zero block light.
	EmptyBlockLightMask BitSet

	// SkyLightArrays contains sky light data for sections with SkyLightMask bit set.
	// Each array is 2048 bytes (half a byte per block, 16×16×16 = 4096 blocks).
	SkyLightArrays [][]byte

	// BlockLightArrays contains block light data for sections with BlockLightMask bit set.
	// Each array is 2048 bytes.
	BlockLightArrays [][]byte
}

LightData represents lighting information for a chunk. Contains bit masks indicating which sections have light data, and the actual light arrays.

Wire format:

┌─────────────────────────────────────────────────────────────────────────┐
│  SkyLightMask (BitSet)                                                  │
├─────────────────────────────────────────────────────────────────────────┤
│  BlockLightMask (BitSet)                                                │
├─────────────────────────────────────────────────────────────────────────┤
│  EmptySkyLightMask (BitSet)                                             │
├─────────────────────────────────────────────────────────────────────────┤
│  EmptyBlockLightMask (BitSet)                                           │
├─────────────────────────────────────────────────────────────────────────┤
│  SkyLightArrays (VarInt count + arrays of 2048 bytes each)              │
├─────────────────────────────────────────────────────────────────────────┤
│  BlockLightArrays (VarInt count + arrays of 2048 bytes each)            │
└─────────────────────────────────────────────────────────────────────────┘

Each BitSet contains bits for each section in the world + 2 (one above and below). Light arrays are 2048 bytes each (4096 nibbles for 16×16×16 blocks).

func (*LightData) Decode

func (l *LightData) Decode(buf *PacketBuffer) error

Decode reads LightData from the buffer.

func (*LightData) Encode

func (l *LightData) Encode(buf *PacketBuffer) error

Encode writes LightData to the buffer.

type LpVec3

type LpVec3 struct {
	X, Y, Z float64
}

LpVec3 is a low-precision 3D vector used for entity velocity. Matches net.minecraft.network.LpVec3 from the Minecraft Java Edition source.

Wire format:

  • 1 byte if zero vector (0x00)
  • Otherwise 6 bytes + optional VarInt for large scale: byte 0 (lowest): bits 0-1 = scale low, bit 2 = continuation, bits 3-7 = x[0:4] byte 1 (middle): x[5:12] bytes 2-5 (big-endian uint32): x[13:14] | y[0:14] | z[0:14]

Components are unsigned 15-bit values in [0, 32766] mapped to [-1, +1], then multiplied by the integer scale factor.

func (*LpVec3) Decode

func (v *LpVec3) Decode(buf *PacketBuffer) error

Decode reads an LpVec3 from the buffer.

func (*LpVec3) Encode

func (v *LpVec3) Encode(buf *PacketBuffer) error

Encode writes an LpVec3 to the buffer.

type PacketBuffer

type PacketBuffer struct {
	// contains filtered or unexported fields
}

PacketBuffer provides methods for reading and writing Minecraft protocol data types. It wraps io.Reader and io.Writer interfaces for streaming network communication.

func NewReader

func NewReader(data []byte) *PacketBuffer

NewReader creates a PacketBuffer for reading from data.

func NewReaderFrom

func NewReaderFrom(r io.Reader) *PacketBuffer

NewReaderFrom creates a PacketBuffer for reading from an io.Reader.

func NewWriter

func NewWriter() *PacketBuffer

NewWriter creates a PacketBuffer for writing data.

func NewWriterTo

func NewWriterTo(w io.Writer) *PacketBuffer

NewWriterTo creates a PacketBuffer that writes directly to an io.Writer.

func (*PacketBuffer) Bytes

func (pb *PacketBuffer) Bytes() []byte

Bytes returns the written bytes. Only valid for buffers created with NewWriter.

func (*PacketBuffer) CopyBool

func (pb *PacketBuffer) CopyBool(src *PacketBuffer) error

CopyBool copies a Boolean from src to this buffer.

func (*PacketBuffer) CopyFloat32

func (pb *PacketBuffer) CopyFloat32(src *PacketBuffer) error

CopyFloat32 copies a Float32 from src to this buffer.

func (*PacketBuffer) CopyFloat64

func (pb *PacketBuffer) CopyFloat64(src *PacketBuffer) error

CopyFloat64 copies a Float64 from src to this buffer.

func (*PacketBuffer) CopyInt8

func (pb *PacketBuffer) CopyInt8(src *PacketBuffer) error

CopyInt8 copies an Int8 from src to this buffer.

func (*PacketBuffer) CopyInt16

func (pb *PacketBuffer) CopyInt16(src *PacketBuffer) error

CopyInt16 copies an Int16 from src to this buffer.

func (*PacketBuffer) CopyInt32

func (pb *PacketBuffer) CopyInt32(src *PacketBuffer) error

CopyInt32 copies an Int32 from src to this buffer.

func (*PacketBuffer) CopyInt64

func (pb *PacketBuffer) CopyInt64(src *PacketBuffer) error

CopyInt64 copies an Int64 from src to this buffer.

func (*PacketBuffer) CopyPosition

func (pb *PacketBuffer) CopyPosition(src *PacketBuffer) error

CopyPosition copies a Position from src to this buffer.

func (*PacketBuffer) CopySlot

func (pb *PacketBuffer) CopySlot(src *PacketBuffer) error

CopySlot copies a slot from src to this buffer. This only works for empty slots or slots without component modifications. For slots with components, use ReadSlot with a decoder and WriteSlot.

func (*PacketBuffer) CopyString

func (pb *PacketBuffer) CopyString(src *PacketBuffer, maxLen int) error

CopyString copies a String from src to this buffer.

func (*PacketBuffer) CopyUUID

func (pb *PacketBuffer) CopyUUID(src *PacketBuffer) error

CopyUUID copies a UUID from src to this buffer.

func (*PacketBuffer) CopyVarInt

func (pb *PacketBuffer) CopyVarInt(src *PacketBuffer) error

CopyVarInt copies a VarInt from src to this buffer.

func (*PacketBuffer) CopyVarLong

func (pb *PacketBuffer) CopyVarLong(src *PacketBuffer) error

CopyVarLong copies a VarLong from src to this buffer.

func (*PacketBuffer) Len

func (pb *PacketBuffer) Len() int

Len returns the number of written bytes. Only valid for buffers created with NewWriter.

func (*PacketBuffer) Read

func (pb *PacketBuffer) Read(p []byte) (int, error)

Read reads exactly len(p) bytes from the buffer.

func (*PacketBuffer) ReadAngle

func (pb *PacketBuffer) ReadAngle() (Angle, error)

ReadAngle reads a rotation angle (1 byte = 1/256 of a full turn).

func (*PacketBuffer) ReadBool

func (pb *PacketBuffer) ReadBool() (Boolean, error)

ReadBool reads a boolean (1 byte: 0x00 = false, 0x01 = true).

func (*PacketBuffer) ReadByte

func (pb *PacketBuffer) ReadByte() (byte, error)

ReadByte reads a single byte.

func (*PacketBuffer) ReadByteArray

func (pb *PacketBuffer) ReadByteArray(maxLen int) (ByteArray, error)

ReadByteArray reads a byte array with VarInt length prefix.

func (*PacketBuffer) ReadChunkData

func (pb *PacketBuffer) ReadChunkData() (ChunkData, error)

ReadChunkData reads ChunkData from the buffer.

func (*PacketBuffer) ReadFixedByteArray

func (pb *PacketBuffer) ReadFixedByteArray(n int) (ByteArray, error)

ReadFixedByteArray reads exactly n bytes.

func (*PacketBuffer) ReadFloat32

func (pb *PacketBuffer) ReadFloat32() (Float32, error)

ReadFloat32 reads a big-endian 32-bit IEEE 754 float.

func (*PacketBuffer) ReadFloat64

func (pb *PacketBuffer) ReadFloat64() (Float64, error)

ReadFloat64 reads a big-endian 64-bit IEEE 754 double.

func (*PacketBuffer) ReadGameProfile

func (pb *PacketBuffer) ReadGameProfile() (GameProfile, error)

ReadGameProfile reads a GameProfile from the buffer.

func (*PacketBuffer) ReadGlobalPos

func (pb *PacketBuffer) ReadGlobalPos() (GlobalPos, error)

ReadGlobalPos reads a global position (dimension + block position).

func (*PacketBuffer) ReadHashedSlot

func (pb *PacketBuffer) ReadHashedSlot() (HashedSlot, error)

ReadHashedSlot reads a hashed slot from the buffer.

func (*PacketBuffer) ReadIdentifier

func (pb *PacketBuffer) ReadIdentifier() (Identifier, error)

ReadIdentifier reads a Minecraft identifier (namespaced ID).

func (*PacketBuffer) ReadInt8

func (pb *PacketBuffer) ReadInt8() (Int8, error)

ReadInt8 reads a signed 8-bit integer.

func (*PacketBuffer) ReadInt16

func (pb *PacketBuffer) ReadInt16() (Int16, error)

ReadInt16 reads a big-endian signed 16-bit integer.

func (*PacketBuffer) ReadInt32

func (pb *PacketBuffer) ReadInt32() (Int32, error)

ReadInt32 reads a big-endian signed 32-bit integer.

func (*PacketBuffer) ReadInt64

func (pb *PacketBuffer) ReadInt64() (Int64, error)

ReadInt64 reads a big-endian signed 64-bit integer.

func (*PacketBuffer) ReadJsonTextComponent

func (pb *PacketBuffer) ReadJsonTextComponent() (TextComponent, error)

ReadJsonTextComponent reads a text component as a VarInt-prefixed JSON string. Used by login disconnect (ByteBufCodecs.lenientJson in vanilla).

func (*PacketBuffer) ReadLightData

func (pb *PacketBuffer) ReadLightData() (LightData, error)

ReadLightData reads LightData from the buffer.

func (*PacketBuffer) ReadLpVec3

func (pb *PacketBuffer) ReadLpVec3() (LpVec3, error)

ReadLpVec3 reads an LpVec3 from the buffer.

func (*PacketBuffer) ReadPosition

func (pb *PacketBuffer) ReadPosition() (Position, error)

ReadPosition reads a block position packed into a 64-bit integer.

func (*PacketBuffer) ReadResolvableProfile

func (pb *PacketBuffer) ReadResolvableProfile() (ResolvableProfile, error)

ReadResolvableProfile reads a ResolvableProfile from the buffer.

func (*PacketBuffer) ReadSlot

func (pb *PacketBuffer) ReadSlot(decode SlotDecoder) (Slot, error)

ReadSlot reads a slot from the buffer using the provided decoder.

func (*PacketBuffer) ReadString

func (pb *PacketBuffer) ReadString(maxLen int) (String, error)

ReadString reads a UTF-8 string with VarInt length prefix. maxLen is the maximum allowed string length in characters (usually 32767, 0 means no limit).

func (*PacketBuffer) ReadTextComponent

func (pb *PacketBuffer) ReadTextComponent() (TextComponent, error)

ReadTextComponent reads a text component from the buffer (NBT wire format).

func (*PacketBuffer) ReadUUID

func (pb *PacketBuffer) ReadUUID() (UUID, error)

ReadUUID reads a 128-bit UUID (two 64-bit integers).

func (*PacketBuffer) ReadUint8

func (pb *PacketBuffer) ReadUint8() (Uint8, error)

ReadUint8 reads an unsigned 8-bit integer.

func (*PacketBuffer) ReadUint16

func (pb *PacketBuffer) ReadUint16() (Uint16, error)

ReadUint16 reads a big-endian unsigned 16-bit integer.

func (*PacketBuffer) ReadVarInt

func (pb *PacketBuffer) ReadVarInt() (VarInt, error)

ReadVarInt reads a variable-length 32-bit integer.

func (*PacketBuffer) ReadVarLong

func (pb *PacketBuffer) ReadVarLong() (VarLong, error)

ReadVarLong reads a variable-length 64-bit integer.

func (*PacketBuffer) Reader

func (pb *PacketBuffer) Reader() io.Reader

Reader returns the underlying io.Reader.

func (*PacketBuffer) Reset

func (pb *PacketBuffer) Reset()

Reset resets the buffer for reuse. Only valid for buffers created with NewWriter.

func (*PacketBuffer) Write

func (pb *PacketBuffer) Write(p []byte) (int, error)

Write writes p to the buffer.

func (*PacketBuffer) WriteAngle

func (pb *PacketBuffer) WriteAngle(v Angle) error

WriteAngle writes a rotation angle.

func (*PacketBuffer) WriteBool

func (pb *PacketBuffer) WriteBool(v Boolean) error

WriteBool writes a boolean.

func (*PacketBuffer) WriteByte

func (pb *PacketBuffer) WriteByte(b byte) error

WriteByte writes a single byte.

func (*PacketBuffer) WriteByteArray

func (pb *PacketBuffer) WriteByteArray(v ByteArray) error

WriteByteArray writes a byte array with VarInt length prefix.

func (*PacketBuffer) WriteChunkData

func (pb *PacketBuffer) WriteChunkData(c ChunkData) error

WriteChunkData writes ChunkData to the buffer.

func (*PacketBuffer) WriteFixedByteArray

func (pb *PacketBuffer) WriteFixedByteArray(v ByteArray) error

WriteFixedByteArray writes bytes without length prefix.

func (*PacketBuffer) WriteFloat32

func (pb *PacketBuffer) WriteFloat32(v Float32) error

WriteFloat32 writes a big-endian 32-bit IEEE 754 float.

func (*PacketBuffer) WriteFloat64

func (pb *PacketBuffer) WriteFloat64(v Float64) error

WriteFloat64 writes a big-endian 64-bit IEEE 754 double.

func (*PacketBuffer) WriteGameProfile

func (pb *PacketBuffer) WriteGameProfile(p GameProfile) error

WriteGameProfile writes a GameProfile to the buffer.

func (*PacketBuffer) WriteGlobalPos

func (pb *PacketBuffer) WriteGlobalPos(v GlobalPos) error

WriteGlobalPos writes a global position (dimension + block position).

func (*PacketBuffer) WriteHashedSlot

func (pb *PacketBuffer) WriteHashedSlot(s HashedSlot) error

WriteHashedSlot writes a hashed slot to the buffer.

func (*PacketBuffer) WriteIdentifier

func (pb *PacketBuffer) WriteIdentifier(v Identifier) error

WriteIdentifier writes a Minecraft identifier.

func (*PacketBuffer) WriteInt8

func (pb *PacketBuffer) WriteInt8(v Int8) error

WriteInt8 writes a signed 8-bit integer.

func (*PacketBuffer) WriteInt16

func (pb *PacketBuffer) WriteInt16(v Int16) error

WriteInt16 writes a big-endian signed 16-bit integer.

func (*PacketBuffer) WriteInt32

func (pb *PacketBuffer) WriteInt32(v Int32) error

WriteInt32 writes a big-endian signed 32-bit integer.

func (*PacketBuffer) WriteInt64

func (pb *PacketBuffer) WriteInt64(v Int64) error

WriteInt64 writes a big-endian signed 64-bit integer.

func (*PacketBuffer) WriteJsonTextComponent

func (pb *PacketBuffer) WriteJsonTextComponent(tc TextComponent) error

WriteJsonTextComponent writes a text component as a VarInt-prefixed JSON string.

func (*PacketBuffer) WriteLightData

func (pb *PacketBuffer) WriteLightData(l LightData) error

WriteLightData writes LightData to the buffer.

func (*PacketBuffer) WriteLpVec3

func (pb *PacketBuffer) WriteLpVec3(v LpVec3) error

WriteLpVec3 writes an LpVec3 to the buffer.

func (*PacketBuffer) WritePosition

func (pb *PacketBuffer) WritePosition(v Position) error

WritePosition writes a block position packed into a 64-bit integer.

func (*PacketBuffer) WriteResolvableProfile

func (pb *PacketBuffer) WriteResolvableProfile(p ResolvableProfile) error

WriteResolvableProfile writes a ResolvableProfile to the buffer.

func (*PacketBuffer) WriteSlot

func (pb *PacketBuffer) WriteSlot(s Slot) error

WriteSlot writes a slot to the buffer.

func (*PacketBuffer) WriteSlotWith

func (pb *PacketBuffer) WriteSlotWith(s Slot, encode SlotEncoder) error

WriteSlotWith writes a slot using a custom encoder.

func (*PacketBuffer) WriteString

func (pb *PacketBuffer) WriteString(v String) error

WriteString writes a UTF-8 string with VarInt length prefix.

func (*PacketBuffer) WriteTextComponent

func (pb *PacketBuffer) WriteTextComponent(tc TextComponent) error

WriteTextComponent writes a text component to the buffer (NBT wire format).

func (*PacketBuffer) WriteUUID

func (pb *PacketBuffer) WriteUUID(v UUID) error

WriteUUID writes a 128-bit UUID.

func (*PacketBuffer) WriteUint8

func (pb *PacketBuffer) WriteUint8(v Uint8) error

WriteUint8 writes an unsigned 8-bit integer.

func (*PacketBuffer) WriteUint16

func (pb *PacketBuffer) WriteUint16(v Uint16) error

WriteUint16 writes a big-endian unsigned 16-bit integer.

func (*PacketBuffer) WriteVarInt

func (pb *PacketBuffer) WriteVarInt(v VarInt) error

WriteVarInt writes a variable-length 32-bit integer.

func (*PacketBuffer) WriteVarLong

func (pb *PacketBuffer) WriteVarLong(v VarLong) error

WriteVarLong writes a variable-length 64-bit integer.

func (*PacketBuffer) Writer

func (pb *PacketBuffer) Writer() io.Writer

Writer returns the underlying io.Writer.

type Position

type Position struct {
	X, Y, Z int
}

Position represents a block position in the world.

Encoded as a 64-bit integer with the following bit layout:

  • X: 26 bits (signed, bits 38-63)
  • Z: 26 bits (signed, bits 12-37)
  • Y: 12 bits (signed, bits 0-11)

This allows coordinates:

  • X, Z: -33554432 to 33554431
  • Y: -2048 to 2047

func DecodePosition

func DecodePosition(r io.Reader) (Position, error)

DecodePosition reads a Position from r.

func NewPosition

func NewPosition(x, y, z int) Position

NewPosition creates a new Position.

func UnpackPosition

func UnpackPosition(val int64) Position

UnpackPosition decodes a 64-bit integer into a Position.

func (Position) Encode

func (p Position) Encode(w io.Writer) error

Encode writes the Position to w as a packed 64-bit integer.

func (Position) Pack

func (p Position) Pack() int64

Pack encodes the position into a 64-bit integer.

type PrefixedArray

type PrefixedArray[T any] []T

PrefixedArray is a VarInt length-prefixed array of elements.

Wire format:

┌───────────────────────┬───────────────────────────────┐
│  Length (VarInt)      │  Elements (T × Length)        │
└───────────────────────┴───────────────────────────────┘

Example usage:

type MyPacket struct {
    Names PrefixedArray[String]
}

// in Read:
p.Names.DecodeWith(buf, func(b *PacketBuffer) (String, error) {
    return b.ReadString(32767)
})

// in Write:
p.Names.EncodeWith(buf, func(b *PacketBuffer, v String) error {
    return b.WriteString(v)
})

func (*PrefixedArray[T]) DecodeWith

func (a *PrefixedArray[T]) DecodeWith(buf *PacketBuffer, decode ElementDecoder[T]) error

DecodeWith reads a length-prefixed array using the provided decoder function.

func (PrefixedArray[T]) EncodeWith

func (a PrefixedArray[T]) EncodeWith(buf *PacketBuffer, encode ElementEncoder[T]) error

EncodeWith writes a length-prefixed array using the provided encoder function.

func (PrefixedArray[T]) Len

func (a PrefixedArray[T]) Len() int

Len returns the number of elements in the array.

type PrefixedOptional

type PrefixedOptional[T any] struct {
	Present bool
	Value   T
}

PrefixedOptional is a Boolean-prefixed optional value.

Wire format:

┌──────────────────┬─────────────────────────────────────┐
│  Present (Bool)  │  Value (T, only if Present=true)    │
└──────────────────┴─────────────────────────────────────┘

Example usage:

type MyPacket struct {
    Title PrefixedOptional[String]
}

// In Read:
p.Title.DecodeWith(buf, func(b *PacketBuffer) (String, error) {
    return b.ReadString(32767)
})

// In Write:
p.Title.EncodeWith(buf, func(b *PacketBuffer, v String) error {
    return b.WriteString(v)
})

func None

func None[T any]() PrefixedOptional[T]

None creates an empty PrefixedOptional.

func Some

func Some[T any](value T) PrefixedOptional[T]

Some creates a PrefixedOptional with a value.

func (*PrefixedOptional[T]) DecodeWith

func (o *PrefixedOptional[T]) DecodeWith(buf *PacketBuffer, decode ElementDecoder[T]) error

DecodeWith reads a boolean-prefixed optional using the provided decoder.

func (PrefixedOptional[T]) EncodeWith

func (o PrefixedOptional[T]) EncodeWith(buf *PacketBuffer, encode ElementEncoder[T]) error

EncodeWith writes a boolean-prefixed optional using the provided encoder.

func (PrefixedOptional[T]) Get

func (o PrefixedOptional[T]) Get() (T, bool)

Get returns the value and whether it's present.

func (PrefixedOptional[T]) GetOrDefault

func (o PrefixedOptional[T]) GetOrDefault(defaultValue T) T

GetOrDefault returns the value if present, otherwise returns the default.

type ProfileProperty

type ProfileProperty struct {
	Name      String
	Value     String
	Signature PrefixedOptional[String]
}

ProfileProperty represents a single property in a game profile.

func (*ProfileProperty) Decode

func (p *ProfileProperty) Decode(buf *PacketBuffer) error

Decode reads a ProfileProperty from the buffer.

func (*ProfileProperty) Encode

func (p *ProfileProperty) Encode(buf *PacketBuffer) error

Encode writes a ProfileProperty to the buffer.

type RawSlotComponent

type RawSlotComponent struct {
	ID   VarInt
	Data []byte
}

RawSlotComponent stores a component as ID + raw bytes. This allows passthrough without parsing component internals.

type ResolvableProfile

type ResolvableProfile struct {
	Kind ResolvableProfileKind

	// partial profile fields (Kind = 0)
	PartialUsername   PrefixedOptional[String]
	PartialUUID       PrefixedOptional[UUID]
	PartialProperties PrefixedOptional[PrefixedArray[ProfileProperty]]
	PartialSignature  PrefixedOptional[String]

	// complete profile fields (Kind = 1)
	CompleteProfile GameProfile
	BodyModel       PrefixedOptional[Identifier]
	CapeModel       PrefixedOptional[Identifier]
	ElytraModel     PrefixedOptional[Identifier]
	SkinModel       PrefixedOptional[VarInt] // enum: 0=wide, 1=slim
}

ResolvableProfile represents a player profile that can be either partial or complete.

Wire format:

┌─────────────────────┬───────────────────────────────────────────────┐
│  Kind (VarInt Enum) │  Data (depends on Kind)                       │
└─────────────────────┴───────────────────────────────────────────────┘

Partial (0): Optional username, optional UUID, optional properties, optional signature Complete (1): Full GameProfile + optional body/cape/elytra/model identifiers

func NewCompleteProfile

func NewCompleteProfile(profile GameProfile) *ResolvableProfile

NewCompleteProfile creates a complete resolvable profile from a game profile.

func NewPartialProfile

func NewPartialProfile() *ResolvableProfile

NewPartialProfile creates a partial resolvable profile.

func (*ResolvableProfile) Decode

func (p *ResolvableProfile) Decode(buf *PacketBuffer) error

Decode reads a ResolvableProfile from the buffer.

func (*ResolvableProfile) Encode

func (p *ResolvableProfile) Encode(buf *PacketBuffer) error

Encode writes a ResolvableProfile to the buffer.

type ResolvableProfileKind

type ResolvableProfileKind VarInt

ResolvableProfileKind indicates whether a profile is partial or complete.

const (
	ProfilePartial  ResolvableProfileKind = 0
	ProfileComplete ResolvableProfileKind = 1
)

type Score

type Score struct {
	Name      string `nbt:"name"`
	Objective string `nbt:"objective"`
}

Score represents score component content.

type Slot

type Slot struct {
	Count      VarInt
	ItemID     VarInt         // only if Count > 0
	Components SlotComponents // only if Count > 0
}

Slot represents an item stack with data components. Components are stored as raw bytes to keep this package protocol-level only. Callers should use a higher-level package to parse specific component types.

Wire format:

┌──────────────────┬─────────────────┬─────────────────┬─────────────────┬──────────────────────────────────┐
│  Count (VarInt)  │  ItemID (VarInt)│  Add (VarInt)   │  Remove (VarInt)│  Components...                   │
└──────────────────┴─────────────────┴─────────────────┴─────────────────┴──────────────────────────────────┘

If Count <= 0, the slot is empty and no further data is read. ItemID is the registry ID from minecraft:item. Add count is the number of components to add (with data). Remove count is the number of component type IDs to remove.

func EmptySlot

func EmptySlot() Slot

EmptySlot returns an empty slot.

func NewSlot

func NewSlot(itemID VarInt, count VarInt) Slot

NewSlot creates a slot with the given item and count.

func (*Slot) AddComponent

func (s *Slot) AddComponent(id VarInt, data []byte)

AddComponent adds a raw component to the slot.

func (*Slot) Decode

func (s *Slot) Decode(buf *PacketBuffer, decode SlotDecoder) error

Decode reads a slot from the buffer using a decoder that knows component sizes. The decoder must return the raw bytes for each component.

func (*Slot) Encode

func (s *Slot) Encode(buf *PacketBuffer) error

Encode writes the slot to the buffer.

func (*Slot) EncodeWith

func (s *Slot) EncodeWith(buf *PacketBuffer, encode SlotEncoder) error

EncodeWith writes the slot using a custom encoder for components.

func (*Slot) GetComponent

func (s *Slot) GetComponent(id VarInt) *RawSlotComponent

GetComponent returns the first component with the given ID, or nil if not found.

func (*Slot) IsEmpty

func (s *Slot) IsEmpty() bool

IsEmpty returns true if the slot is empty.

func (*Slot) RemoveComponent

func (s *Slot) RemoveComponent(id VarInt)

RemoveComponent marks a component type for removal.

type SlotComponents

type SlotComponents struct {
	Add    []RawSlotComponent // components with data (ID + raw bytes)
	Remove []VarInt           // component type IDs to remove
}

SlotComponents holds the component modifications for a slot.

type SlotDecoder

type SlotDecoder func(buf *PacketBuffer, componentID VarInt) ([]byte, error)

SlotDecoder is a function that decodes a component's data given its ID. Returns the raw bytes of the component. If the component format is unknown, return an error - there's no way to know where a component ends without understanding its format.

type SlotEncoder

type SlotEncoder func(buf *PacketBuffer, componentID VarInt, data []byte) error

SlotEncoder is a function that encodes a component's data. By default, raw bytes are written as-is.

type String

type String string

String is a UTF-8 encoded string with a VarInt length prefix (byte count).

The length prefix indicates the number of bytes, not characters. Maximum length is 32767 characters (which can be up to ~130KB in UTF-8).

func DecodeString

func DecodeString(r io.Reader, maxLen int) (String, error)

DecodeString reads a String from r. maxLen is the maximum allowed string length in characters (0 = no limit).

func (String) Encode

func (v String) Encode(w io.Writer) error

Encode writes the String to w with VarInt length prefix.

type TextComponent

type TextComponent struct {
	// content types (only one should be set)
	Text       string `nbt:"text,omitempty" json:"text,omitempty"`
	Translate  string `nbt:"translate,omitempty" json:"translate,omitempty"`
	Keybind    string `nbt:"keybind,omitempty" json:"keybind,omitempty"`
	Score      *Score `nbt:"score,omitempty" json:"score,omitempty"`
	Selector   string `nbt:"selector,omitempty" json:"selector,omitempty"`
	NBT        string `nbt:"nbt,omitempty" json:"nbt,omitempty"`
	NBTBlock   string `nbt:"block,omitempty" json:"block,omitempty"`         // for nbt content type
	NBTEntity  string `nbt:"entity,omitempty" json:"entity,omitempty"`       // for nbt content type
	NBTStorage string `nbt:"storage,omitempty" json:"storage,omitempty"`     // for nbt content type
	Interpret  *bool  `nbt:"interpret,omitempty" json:"interpret,omitempty"` // for nbt content type

	// translation arguments (for translate content type)
	With []TextComponent `nbt:"with,omitempty" json:"with,omitempty"`

	// style
	Color         string `nbt:"color,omitempty" json:"color,omitempty"`
	Bold          *bool  `nbt:"bold,omitempty" json:"bold,omitempty"`
	Italic        *bool  `nbt:"italic,omitempty" json:"italic,omitempty"`
	Underlined    *bool  `nbt:"underlined,omitempty" json:"underlined,omitempty"`
	Strikethrough *bool  `nbt:"strikethrough,omitempty" json:"strikethrough,omitempty"`
	Obfuscated    *bool  `nbt:"obfuscated,omitempty" json:"obfuscated,omitempty"`
	Font          string `nbt:"font,omitempty" json:"font,omitempty"`
	Insertion     string `nbt:"insertion,omitempty" json:"insertion,omitempty"`

	// click/hover events
	ClickEvent *ClickEvent `nbt:"click_event,omitempty" json:"clickEvent,omitempty"`
	HoverEvent *HoverEvent `nbt:"hover_event,omitempty" json:"hoverEvent,omitempty"`

	// children
	Extra []TextComponent `nbt:"extra,omitempty" json:"extra,omitempty"`
}

TextComponent represents a Minecraft text component. Encoded as NBT over the network (since 1.20.3+).

A text component can be:

  • A plain string (text content only)
  • A compound with content, style, and children

Wire format: NBT (network format, nameless root)

func FromColorCodes

func FromColorCodes(s string) TextComponent

FromColorCodes parses a string with Bukkit-style section sign (§) color/format codes into a TextComponent tree.

FromColorCodes("§6Hello §lworld") → gold "Hello " + gold+bold "world"

func FromMiniMessage

func FromMiniMessage(s string) TextComponent

FromMiniMessage parses a subset of Adventure MiniMessage format into a TextComponent tree. Supports color tags (<gold>, <#ff0000>), format tags (<bold>, <italic>, etc.), <reset>, and <lang:key:arg1:arg2>.

FromMiniMessage("<gold>Hello <bold>world</bold></gold>")

func NewTextComponent

func NewTextComponent(text string) TextComponent

NewTextComponent creates a simple text component with the given text.

func NewTranslateComponent

func NewTranslateComponent(key string, args ...TextComponent) TextComponent

NewTranslateComponent creates a translatable text component.

func ParseFormatted

func ParseFormatted(s string) TextComponent

ParseFormatted parses a string containing legacy color codes (§ or &) and MiniMessage-style tags (<red>, <bold>, <gradient:red:blue>, etc.) into a TextComponent tree.

func (TextComponent) ANSI

func (tc TextComponent) ANSI() string

ANSI returns the text with ANSI terminal escape codes for colors and formatting. Translate keys are shown as-is.

func (TextComponent) ColorCodes

func (tc TextComponent) ColorCodes() string

ColorCodes returns the text with Bukkit-style section sign (§) color codes. Translate keys are shown as-is.

func (*TextComponent) Decode

func (tc *TextComponent) Decode(buf *PacketBuffer) error

Decode reads a text component from NBT.

func (*TextComponent) Encode

func (tc *TextComponent) Encode(buf *PacketBuffer) error

Encode writes the text component as NBT to the writer. Simple text-only components are encoded as NBT String tags for efficiency.

func (TextComponent) MiniMessage

func (tc TextComponent) MiniMessage() string

MiniMessage returns the text in Adventure MiniMessage format. Translate keys are shown as-is.

func (*TextComponent) PlainText

func (tc *TextComponent) PlainText() string

PlainText extracts the plain text content from a TextComponent tree, stripping all formatting.

func (TextComponent) Render

func (tc TextComponent) Render(translate func(string) string) string

Render returns the plain text with translate keys resolved by fn (if non-nil).

func (TextComponent) RenderANSI

func (tc TextComponent) RenderANSI(translate func(string) string) string

RenderANSI returns ANSI-formatted text with translate keys resolved by fn (if non-nil).

func (TextComponent) RenderColorCodes

func (tc TextComponent) RenderColorCodes(translate func(string) string) string

RenderColorCodes returns section-sign colored text with translate keys resolved by fn (if non-nil).

func (TextComponent) RenderMiniMessage

func (tc TextComponent) RenderMiniMessage(translate func(string) string) string

RenderMiniMessage returns MiniMessage-formatted text with translate keys resolved by fn (if non-nil).

func (TextComponent) String

func (tc TextComponent) String() string

String returns the plain text content of the component and all children, with no formatting. Translate keys are shown as-is.

func (*TextComponent) UnmarshalJSON

func (tc *TextComponent) UnmarshalJSON(data []byte) error

UnmarshalJSON handles both plain JSON strings (e.g. `"hello"`) and JSON objects (e.g. `{"text":"hello","color":"red"}`).

func (*TextComponent) UnmarshalNBT

func (tc *TextComponent) UnmarshalNBT(tag nbt.Tag) error

UnmarshalNBT implements nbt.TagUnmarshaler, allowing TextComponent to be correctly unmarshaled from both NBT String (plain text shorthand) and Compound tags.

type UUID

type UUID [16]byte

UUID is a 128-bit universally unique identifier.

Encoded as two big-endian 64-bit integers (most significant bits first).

func DecodeUUID

func DecodeUUID(r io.Reader) (UUID, error)

DecodeUUID reads a UUID from r.

func UUIDFromBytes

func UUIDFromBytes(b []byte) (UUID, error)

UUIDFromBytes creates a UUID from a 16-byte slice.

func UUIDFromInt64s

func UUIDFromInt64s(msb, lsb int64) UUID

UUIDFromInt64s creates a UUID from most and least significant bits.

func UUIDFromString

func UUIDFromString(s string) (UUID, error)

UUIDFromString parses a UUID from its string representation. Accepts formats: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" or "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

func (UUID) Encode

func (u UUID) Encode(w io.Writer) error

Encode writes the UUID to w.

func (UUID) IsNil

func (u UUID) IsNil() bool

IsNil returns true if this is the nil UUID (all zeros).

func (UUID) LeastSignificantBits

func (u UUID) LeastSignificantBits() int64

LeastSignificantBits returns the last 64 bits of the UUID.

func (UUID) MostSignificantBits

func (u UUID) MostSignificantBits() int64

MostSignificantBits returns the first 64 bits of the UUID.

func (UUID) String

func (u UUID) String() string

String returns the UUID in standard hyphenated format.

type Uint8

type Uint8 uint8

Uint8 is an unsigned 8-bit integer (0 to 255).

func DecodeUint8

func DecodeUint8(r io.Reader) (Uint8, error)

DecodeUint8 reads a Uint8 from r.

func (Uint8) Encode

func (v Uint8) Encode(w io.Writer) error

Encode writes the Uint8 to w.

type Uint16

type Uint16 uint16

Uint16 is a big-endian unsigned 16-bit integer.

func DecodeUint16

func DecodeUint16(r io.Reader) (Uint16, error)

DecodeUint16 reads a Uint16 from r.

func (Uint16) Encode

func (v Uint16) Encode(w io.Writer) error

Encode writes the Uint16 to w.

type VarInt

type VarInt int32

VarInt is a variable-length signed 32-bit integer.

Uses 7 bits per byte with bit 7 as continuation flag. Values are encoded in little-endian order within the variable-length format. Maximum 5 bytes for 32-bit values.

Encoding:

For each byte:
  - Bits 0-6: 7 bits of data
  - Bit 7: 1 if more bytes follow, 0 if this is the last byte

Examples:

0          -> [0x00]
1          -> [0x01]
127        -> [0x7f]
128        -> [0x80, 0x01]
255        -> [0xff, 0x01]
2147483647 -> [0xff, 0xff, 0xff, 0xff, 0x07]
-1         -> [0xff, 0xff, 0xff, 0xff, 0x0f]

func DecodeVarInt

func DecodeVarInt(r io.Reader) (VarInt, error)

DecodeVarInt reads a VarInt from r.

func (VarInt) Encode

func (v VarInt) Encode(w io.Writer) error

Encode writes the VarInt to w.

func (VarInt) Len

func (v VarInt) Len() int

Len returns the number of bytes needed to encode this VarInt.

func (VarInt) ToBytes

func (v VarInt) ToBytes() (ByteArray, error)

ToBytes encodes the VarInt to bytes.

type VarLong

type VarLong int64

VarLong is a variable-length signed 64-bit integer.

Same encoding as VarInt but for 64-bit values. Maximum 10 bytes for 64-bit values.

Examples:

0                    -> [0x00]
9223372036854775807  -> [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]
-1                   -> [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01]

func DecodeVarLong

func DecodeVarLong(r io.Reader) (VarLong, error)

DecodeVarLong reads a VarLong from r.

func (VarLong) Encode

func (v VarLong) Encode(w io.Writer) error

Encode writes the VarLong to w.

func (VarLong) Len

func (v VarLong) Len() int

Len returns the number of bytes needed to encode this VarLong.

func (VarLong) ToBytes

func (v VarLong) ToBytes() (ByteArray, error)

ToBytes encodes the VarLong to bytes.

type XOrY

type XOrY[X, Y any] struct {
	IsX bool
	X   X
	Y   Y
}

XOrY represents a boolean-selected variant between two types. When IsX is true, the X value is encoded; otherwise, Y is encoded.

Wire format:

┌──────────────────┬─────────────────────────────────────┐
│  IsX (Boolean)   │  X or Y (depending on IsX)          │
└──────────────────┴─────────────────────────────────────┘

This pattern is relatively rare and is typically handled inline in packet definitions since both X and Y types must be known at compile time.

func NewX

func NewX[X, Y any](value X) XOrY[X, Y]

NewX creates an XOrY with an X value.

func NewY

func NewY[X, Y any](value Y) XOrY[X, Y]

NewY creates an XOrY with a Y value.

func (*XOrY[X, Y]) DecodeWith

func (v *XOrY[X, Y]) DecodeWith(buf *PacketBuffer, decodeX ElementDecoder[X], decodeY ElementDecoder[Y]) error

DecodeWith reads an XOrY using the provided decoders.

func (XOrY[X, Y]) EncodeWith

func (v XOrY[X, Y]) EncodeWith(buf *PacketBuffer, encodeX ElementEncoder[X], encodeY ElementEncoder[Y]) error

EncodeWith writes an XOrY using the provided encoders.

func (XOrY[X, Y]) Get

func (v XOrY[X, Y]) Get() (x X, y Y, isX bool)

Get returns either the X value (if IsX) or Y value, along with the selector.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL