Initial commit: RegionIO Minecraft server core (26.1.2/protocol 775)
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.
This commit is contained in:
commit
a7bb9496ae
146 changed files with 217621 additions and 0 deletions
95
internal/nbt/encode.go
Normal file
95
internal/nbt/encode.go
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
package nbt
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// Marshal encodes root in the network format: the root tag's type byte followed
|
||||
// by its payload, with no root name (Minecraft 1.20.2+).
|
||||
func Marshal(root Tag) []byte {
|
||||
dst := []byte{root.ID()}
|
||||
return appendPayload(dst, root)
|
||||
}
|
||||
|
||||
// MarshalNamed encodes root in the classic named format: type byte, root name,
|
||||
// then payload. Used for files and legacy framing.
|
||||
func MarshalNamed(name string, root Tag) []byte {
|
||||
dst := []byte{root.ID()}
|
||||
dst = appendString(dst, name)
|
||||
return appendPayload(dst, root)
|
||||
}
|
||||
|
||||
// appendString writes a modified-UTF-8 string with an unsigned-short length.
|
||||
func appendString(dst []byte, s string) []byte {
|
||||
start := len(dst)
|
||||
dst = append(dst, 0, 0) // length placeholder
|
||||
dst = encodeModifiedUTF8(dst, s)
|
||||
binary.BigEndian.PutUint16(dst[start:], uint16(len(dst)-start-2))
|
||||
return dst
|
||||
}
|
||||
|
||||
// appendPayload writes a tag's payload (no type byte, no name).
|
||||
func appendPayload(dst []byte, t Tag) []byte {
|
||||
switch v := t.(type) {
|
||||
case Byte:
|
||||
return append(dst, byte(v))
|
||||
case Short:
|
||||
return binary.BigEndian.AppendUint16(dst, uint16(v))
|
||||
case Int:
|
||||
return binary.BigEndian.AppendUint32(dst, uint32(v))
|
||||
case Long:
|
||||
return binary.BigEndian.AppendUint64(dst, uint64(v))
|
||||
case Float:
|
||||
return binary.BigEndian.AppendUint32(dst, math.Float32bits(float32(v)))
|
||||
case Double:
|
||||
return binary.BigEndian.AppendUint64(dst, math.Float64bits(float64(v)))
|
||||
case ByteArray:
|
||||
dst = binary.BigEndian.AppendUint32(dst, uint32(len(v)))
|
||||
return append(dst, v...)
|
||||
case String:
|
||||
return appendString(dst, string(v))
|
||||
case IntArray:
|
||||
dst = binary.BigEndian.AppendUint32(dst, uint32(len(v)))
|
||||
for _, n := range v {
|
||||
dst = binary.BigEndian.AppendUint32(dst, uint32(n))
|
||||
}
|
||||
return dst
|
||||
case LongArray:
|
||||
dst = binary.BigEndian.AppendUint32(dst, uint32(len(v)))
|
||||
for _, n := range v {
|
||||
dst = binary.BigEndian.AppendUint64(dst, uint64(n))
|
||||
}
|
||||
return dst
|
||||
case List:
|
||||
return appendList(dst, v)
|
||||
case *Compound:
|
||||
return appendCompound(dst, v)
|
||||
default:
|
||||
panic(fmt.Sprintf("nbt: cannot encode %T", t))
|
||||
}
|
||||
}
|
||||
|
||||
func appendList(dst []byte, l List) []byte {
|
||||
elemID := l.ElemID
|
||||
if len(l.Elems) == 0 {
|
||||
elemID = TagEnd // Java writes TagEnd for empty lists.
|
||||
}
|
||||
dst = append(dst, elemID)
|
||||
dst = binary.BigEndian.AppendUint32(dst, uint32(len(l.Elems)))
|
||||
for _, e := range l.Elems {
|
||||
dst = appendPayload(dst, e)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func appendCompound(dst []byte, c *Compound) []byte {
|
||||
for _, k := range c.keys {
|
||||
t := c.m[k]
|
||||
dst = append(dst, t.ID())
|
||||
dst = appendString(dst, k)
|
||||
dst = appendPayload(dst, t)
|
||||
}
|
||||
return append(dst, TagEnd)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue