Vanilla-faithful overworld generator (final_density + multi-noise biomes), full connection lifecycle (status/login/configuration/play), chunk streaming, creative block editing, and the protocol/nbt/registry infrastructure.
98 lines
2.8 KiB
Go
98 lines
2.8 KiB
Go
// Package nbt implements Minecraft's Named Binary Tag format, including the
|
|
// network variant used since 1.20.2 where the root tag carries no name.
|
|
//
|
|
// All numeric payloads are big-endian. Strings use Java's "modified UTF-8":
|
|
// an unsigned-short byte length followed by bytes where NUL and supplementary
|
|
// code points are escaped (see encode/decodeModifiedUTF8).
|
|
package nbt
|
|
|
|
// Tag type identifiers as defined by the NBT specification.
|
|
const (
|
|
TagEnd = 0x00
|
|
TagByte = 0x01
|
|
TagShort = 0x02
|
|
TagInt = 0x03
|
|
TagLong = 0x04
|
|
TagFloat = 0x05
|
|
TagDouble = 0x06
|
|
TagByteArray = 0x07
|
|
TagString = 0x08
|
|
TagList = 0x09
|
|
TagCompound = 0x0A
|
|
TagIntArray = 0x0B
|
|
TagLongArray = 0x0C
|
|
)
|
|
|
|
// Tag is any NBT value. ID returns its tag type identifier.
|
|
type Tag interface{ ID() byte }
|
|
|
|
// Primitive and array tag types map directly onto Go types.
|
|
type (
|
|
Byte int8
|
|
Short int16
|
|
Int int32
|
|
Long int64
|
|
Float float32
|
|
Double float64
|
|
ByteArray []byte
|
|
String string
|
|
IntArray []int32
|
|
LongArray []int64
|
|
)
|
|
|
|
func (Byte) ID() byte { return TagByte }
|
|
func (Short) ID() byte { return TagShort }
|
|
func (Int) ID() byte { return TagInt }
|
|
func (Long) ID() byte { return TagLong }
|
|
func (Float) ID() byte { return TagFloat }
|
|
func (Double) ID() byte { return TagDouble }
|
|
func (ByteArray) ID() byte { return TagByteArray }
|
|
func (String) ID() byte { return TagString }
|
|
func (IntArray) ID() byte { return TagIntArray }
|
|
func (LongArray) ID() byte { return TagLongArray }
|
|
|
|
// List is a homogeneous sequence of unnamed tags. ElemID must match the type
|
|
// of every element; for an empty list it is written as TagEnd, per Java.
|
|
type List struct {
|
|
ElemID byte
|
|
Elems []Tag
|
|
}
|
|
|
|
func (List) ID() byte { return TagList }
|
|
|
|
// Compound is an ordered set of named tags. Insertion order is preserved so
|
|
// that encoding is deterministic (the protocol does not require any order).
|
|
type Compound struct {
|
|
keys []string
|
|
m map[string]Tag
|
|
}
|
|
|
|
func (*Compound) ID() byte { return TagCompound }
|
|
|
|
// NewCompound returns an empty compound ready for Set.
|
|
func NewCompound() *Compound {
|
|
return &Compound{m: make(map[string]Tag)}
|
|
}
|
|
|
|
// Set inserts or replaces the tag for name, preserving first-insertion order,
|
|
// and returns the compound for chaining.
|
|
func (c *Compound) Set(name string, t Tag) *Compound {
|
|
if _, ok := c.m[name]; !ok {
|
|
c.keys = append(c.keys, name)
|
|
}
|
|
c.m[name] = t
|
|
return c
|
|
}
|
|
|
|
// Get returns the tag for name and whether it is present.
|
|
func (c *Compound) Get(name string) (Tag, bool) {
|
|
t, ok := c.m[name]
|
|
return t, ok
|
|
}
|
|
|
|
// Len returns the number of entries.
|
|
func (c *Compound) Len() int { return len(c.keys) }
|
|
|
|
// Keys returns the entry names in insertion order. The slice must not be
|
|
// mutated by callers.
|
|
func (c *Compound) Keys() []string { return c.keys }
|