All block states' properties are parsed and all enums represented as byte
This commit is contained in:
@ -2,7 +2,7 @@ package block
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"compress/gzip"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"math/bits"
|
||||
@ -14,7 +14,7 @@ type Block interface {
|
||||
ID() string
|
||||
}
|
||||
|
||||
// This file stores all possible block states into a TAG_List with zlib compressed.
|
||||
// This file stores all possible block states into a TAG_List with gzip compressed.
|
||||
//go:embed block_states.nbt
|
||||
var blockStates []byte
|
||||
|
||||
@ -33,7 +33,7 @@ type State struct {
|
||||
func init() {
|
||||
var states []State
|
||||
// decompress
|
||||
z, err := zlib.NewReader(bytes.NewReader(blockStates))
|
||||
z, err := gzip.NewReader(bytes.NewReader(blockStates))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -1,7 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
_ "embed"
|
||||
"go/format"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
@ -20,7 +23,7 @@ var temp = template.Must(template.
|
||||
"UpperTheFirst": UpperTheFirst,
|
||||
"ToGoTypeName": ToGoTypeName,
|
||||
"GetType": GetType,
|
||||
"Generator": func() string { return "generator/main.go" },
|
||||
"Generator": func() string { return "generator/blocks/main.go" },
|
||||
}).
|
||||
Parse(tempSource))
|
||||
|
||||
@ -45,25 +48,31 @@ func readBlockStates(states *[]State) {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
r, err := gzip.NewReader(f)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
// parse the nbt format
|
||||
if _, err := nbt.NewDecoder(f).Decode(states); err != nil {
|
||||
if _, err := nbt.NewDecoder(r).Decode(states); err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func genSourceFile(states []State) {
|
||||
file, err := os.Create("blocks.go")
|
||||
if err != nil {
|
||||
var source bytes.Buffer
|
||||
if err := temp.Execute(&source, states); err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
// clean up the file
|
||||
if err := file.Truncate(0); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := temp.Execute(file, states); err != nil {
|
||||
log.Panic(err)
|
||||
formattedSource, err := format.Source(source.Bytes())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = os.WriteFile("blocks.go", formattedSource, 0666)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +88,6 @@ func ToGoTypeName(name string) string {
|
||||
var typeMaps = map[string]string{
|
||||
"BooleanProperty": "Boolean",
|
||||
"DirectionProperty": "Direction",
|
||||
"EnumProperty": "string",
|
||||
"IntegerProperty": "Integer",
|
||||
}
|
||||
|
97
level/block/generator/properties/main.go
Normal file
97
level/block/generator/properties/main.go
Normal file
@ -0,0 +1,97 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"go/format"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type EnumProperty struct {
|
||||
Name string
|
||||
TrimPrefix bool
|
||||
Values []string
|
||||
}
|
||||
|
||||
var EnumProperties = []EnumProperty{
|
||||
{Name: "AttachFace", Values: []string{"floor", "wall", "ceiling"}},
|
||||
{Name: "BambooLeaves", Values: []string{"none", "small", "large"}},
|
||||
{Name: "BedPart", Values: []string{"head", "foot"}},
|
||||
{Name: "BellAttachType", Values: []string{"floor", "ceiling", "single_wall", "double_wall"}},
|
||||
{Name: "ChestType", Values: []string{"single", "left", "right"}},
|
||||
{Name: "ComparatorMode", Values: []string{"compare", "subtract"}},
|
||||
{Name: "Direction", TrimPrefix: true, Values: []string{"down", "up", "north", "south", "west", "east"}},
|
||||
{Name: "Axis", TrimPrefix: true, Values: []string{"x", "y", "z"}},
|
||||
{Name: "DoorHingeSide", Values: []string{"left", "right"}},
|
||||
{Name: "DoubleBlockHalf", Values: []string{"upper", "lower"}},
|
||||
{Name: "DripstoneThickness", Values: []string{"tip_merge", "tip", "frustum", "middle", "base"}},
|
||||
{Name: "Half", TrimPrefix: true, Values: []string{"top", "bottom"}},
|
||||
{Name: "NoteBlockInstrument", Values: []string{
|
||||
"harp", "basedrum", "snare", "hat",
|
||||
"bass", "flute", "bell", "guitar",
|
||||
"chime", "xylophone", "iron_xylophone", "cow_bell",
|
||||
"didgeridoo", "bit", "banjo", "pling",
|
||||
}},
|
||||
{Name: "PistonType", Values: []string{"normal", "sticky"}},
|
||||
{Name: "RailShape", Values: []string{
|
||||
"north_south", "east_west",
|
||||
"ascending_east", "ascending_west", "ascending_north", "ascending_south",
|
||||
"south_east", "south_west", "north_west", "north_east",
|
||||
}},
|
||||
{Name: "RedstoneSide", Values: []string{"up", "side", "none"}},
|
||||
{Name: "SculkSensorPhase", Values: []string{"inactive", "active", "cooldown"}},
|
||||
{Name: "SlabType", Values: []string{"top", "bottom", "double"}},
|
||||
{Name: "StairsShape", Values: []string{"straight", "inner_left", "inner_right", "outer_left", "outer_right"}},
|
||||
{Name: "StructureMode", Values: []string{"save", "load", "corner", "data"}},
|
||||
{Name: "Tilt", Values: []string{"none", "unstable", "partial", "full"}},
|
||||
{Name: "WallSide", Values: []string{"none", "low", "tall"}},
|
||||
{Name: "FrontAndTop", TrimPrefix: true, Values: []string{
|
||||
"down_east", "down_north", "down_south", "down_west",
|
||||
"up_east", "up_north", "up_south", "up_west",
|
||||
"west_up", "east_up", "north_up", "south_up",
|
||||
}},
|
||||
}
|
||||
|
||||
//go:embed properties_enum.go.tmpl
|
||||
var tempSource string
|
||||
|
||||
func main() {
|
||||
var source bytes.Buffer
|
||||
err := template.Must(template.
|
||||
New("properties_enum").
|
||||
Funcs(template.FuncMap{
|
||||
"UpperTheFirst": UpperTheFirst,
|
||||
"ToLower": strings.ToLower,
|
||||
"Generator": func() string { return "generator/properties/main.go" },
|
||||
}).
|
||||
Parse(tempSource)).
|
||||
Execute(&source, EnumProperties)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
formattedSource, err := format.Source(source.Bytes())
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
err = os.WriteFile("properties_enum.go", formattedSource, 0666)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func UpperTheFirst(word string) string {
|
||||
var sb strings.Builder
|
||||
for _, word := range strings.Split(word, "_") {
|
||||
runes := []rune(word)
|
||||
if len(runes) > 0 {
|
||||
runes[0] = unicode.ToUpper(runes[0])
|
||||
}
|
||||
sb.WriteString(string(runes))
|
||||
}
|
||||
return sb.String()
|
||||
}
|
45
level/block/generator/properties/properties_enum.go.tmpl
Normal file
45
level/block/generator/properties/properties_enum.go.tmpl
Normal file
@ -0,0 +1,45 @@
|
||||
// Code generated by {{Generator}}; DO NOT EDIT.
|
||||
package block
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
)
|
||||
{{range $prop := .}}
|
||||
type {{.Name}} byte
|
||||
|
||||
const (
|
||||
{{- range $index, $element := .Values}}
|
||||
{{if not $prop.TrimPrefix}}{{$prop.Name}}{{end}}{{$element | UpperTheFirst}}{{if eq $index 0 }} {{$prop.Name}} = iota{{end}}
|
||||
{{- end}}
|
||||
)
|
||||
|
||||
{{- $v := slice (.Name | ToLower) 0 1 }}
|
||||
var str{{.Name}} = [...]string{ {{- range $index, $elem := .Values }}{{$elem | printf "%q"}}{{if ne $index (len $prop.Values)}}, {{end}}{{end -}} }
|
||||
|
||||
func ({{$v}} {{.Name}}) String() string {
|
||||
if int({{$v}}) < len(str{{.Name}}) {
|
||||
return str{{.Name}}[{{$v}}]
|
||||
}
|
||||
return "invalid {{.Name}}"
|
||||
}
|
||||
|
||||
func ({{$v}} {{.Name}}) MarshalText() (text []byte, err error) {
|
||||
if int({{$v}}) < len(str{{.Name}}) {
|
||||
return []byte(str{{.Name}}[{{$v}}]), nil
|
||||
}
|
||||
return nil, errors.New("invalid {{.Name}}: " + strconv.Itoa(int({{$v}})))
|
||||
}
|
||||
|
||||
func ({{$v}} *{{.Name}}) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
{{- range .Values}}
|
||||
case {{. | printf "%q"}}:
|
||||
*{{$v}} = {{if not $prop.TrimPrefix}}{{$prop.Name}}{{end}}{{. | UpperTheFirst}}
|
||||
{{- end}}
|
||||
default:
|
||||
return errors.New("unknown {{.Name}}: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
{{end}}
|
@ -1,14 +1,8 @@
|
||||
package block
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
import "strconv"
|
||||
|
||||
type (
|
||||
Boolean bool
|
||||
Direction string
|
||||
Integer int
|
||||
)
|
||||
type Boolean bool
|
||||
|
||||
func (b Boolean) MarshalText() (text []byte, err error) {
|
||||
return []byte(strconv.FormatBool(bool(b))), nil
|
||||
@ -19,14 +13,7 @@ func (b *Boolean) UnmarshalText(text []byte) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (d Direction) MarshalText() (text []byte, err error) {
|
||||
return []byte(d), nil
|
||||
}
|
||||
|
||||
func (d *Direction) UnmarshalText(text []byte) error {
|
||||
*d = Direction(text)
|
||||
return nil
|
||||
}
|
||||
type Integer int
|
||||
|
||||
func (i Integer) MarshalText() (text []byte, err error) {
|
||||
return []byte(strconv.Itoa(int(i))), nil
|
||||
@ -36,3 +23,34 @@ func (i *Integer) UnmarshalText(text []byte) (err error) {
|
||||
*((*int)(i)), err = strconv.Atoi(string(text))
|
||||
return
|
||||
}
|
||||
|
||||
func (f FrontAndTop) Directions() (front, top Direction) {
|
||||
switch f {
|
||||
case DownEast:
|
||||
return Down, East
|
||||
case DownNorth:
|
||||
return Down, North
|
||||
case DownSouth:
|
||||
return Down, South
|
||||
case DownWest:
|
||||
return Down, West
|
||||
case UpEast:
|
||||
return Up, East
|
||||
case UpNorth:
|
||||
return Up, North
|
||||
case UpSouth:
|
||||
return Up, South
|
||||
case UpWest:
|
||||
return Up, West
|
||||
case WestUp:
|
||||
return West, Up
|
||||
case EastUp:
|
||||
return East, Up
|
||||
case NorthUp:
|
||||
return North, Up
|
||||
case SouthUp:
|
||||
return South, Up
|
||||
default:
|
||||
panic("invalid FrontAndTop")
|
||||
}
|
||||
}
|
||||
|
980
level/block/properties_enum.go
Normal file
980
level/block/properties_enum.go
Normal file
@ -0,0 +1,980 @@
|
||||
// Code generated by generator/properties/main.go; DO NOT EDIT.
|
||||
package block
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type AttachFace byte
|
||||
|
||||
const (
|
||||
AttachFaceFloor AttachFace = iota
|
||||
AttachFaceWall
|
||||
AttachFaceCeiling
|
||||
)
|
||||
|
||||
var strAttachFace = [...]string{"floor", "wall", "ceiling"}
|
||||
|
||||
func (a AttachFace) String() string {
|
||||
if int(a) < len(strAttachFace) {
|
||||
return strAttachFace[a]
|
||||
}
|
||||
return "invalid AttachFace"
|
||||
}
|
||||
|
||||
func (a AttachFace) MarshalText() (text []byte, err error) {
|
||||
if int(a) < len(strAttachFace) {
|
||||
return []byte(strAttachFace[a]), nil
|
||||
}
|
||||
return nil, errors.New("invalid AttachFace: " + strconv.Itoa(int(a)))
|
||||
}
|
||||
|
||||
func (a *AttachFace) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "floor":
|
||||
*a = AttachFaceFloor
|
||||
case "wall":
|
||||
*a = AttachFaceWall
|
||||
case "ceiling":
|
||||
*a = AttachFaceCeiling
|
||||
default:
|
||||
return errors.New("unknown AttachFace: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type BambooLeaves byte
|
||||
|
||||
const (
|
||||
BambooLeavesNone BambooLeaves = iota
|
||||
BambooLeavesSmall
|
||||
BambooLeavesLarge
|
||||
)
|
||||
|
||||
var strBambooLeaves = [...]string{"none", "small", "large"}
|
||||
|
||||
func (b BambooLeaves) String() string {
|
||||
if int(b) < len(strBambooLeaves) {
|
||||
return strBambooLeaves[b]
|
||||
}
|
||||
return "invalid BambooLeaves"
|
||||
}
|
||||
|
||||
func (b BambooLeaves) MarshalText() (text []byte, err error) {
|
||||
if int(b) < len(strBambooLeaves) {
|
||||
return []byte(strBambooLeaves[b]), nil
|
||||
}
|
||||
return nil, errors.New("invalid BambooLeaves: " + strconv.Itoa(int(b)))
|
||||
}
|
||||
|
||||
func (b *BambooLeaves) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "none":
|
||||
*b = BambooLeavesNone
|
||||
case "small":
|
||||
*b = BambooLeavesSmall
|
||||
case "large":
|
||||
*b = BambooLeavesLarge
|
||||
default:
|
||||
return errors.New("unknown BambooLeaves: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type BedPart byte
|
||||
|
||||
const (
|
||||
BedPartHead BedPart = iota
|
||||
BedPartFoot
|
||||
)
|
||||
|
||||
var strBedPart = [...]string{"head", "foot"}
|
||||
|
||||
func (b BedPart) String() string {
|
||||
if int(b) < len(strBedPart) {
|
||||
return strBedPart[b]
|
||||
}
|
||||
return "invalid BedPart"
|
||||
}
|
||||
|
||||
func (b BedPart) MarshalText() (text []byte, err error) {
|
||||
if int(b) < len(strBedPart) {
|
||||
return []byte(strBedPart[b]), nil
|
||||
}
|
||||
return nil, errors.New("invalid BedPart: " + strconv.Itoa(int(b)))
|
||||
}
|
||||
|
||||
func (b *BedPart) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "head":
|
||||
*b = BedPartHead
|
||||
case "foot":
|
||||
*b = BedPartFoot
|
||||
default:
|
||||
return errors.New("unknown BedPart: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type BellAttachType byte
|
||||
|
||||
const (
|
||||
BellAttachTypeFloor BellAttachType = iota
|
||||
BellAttachTypeCeiling
|
||||
BellAttachTypeSingleWall
|
||||
BellAttachTypeDoubleWall
|
||||
)
|
||||
|
||||
var strBellAttachType = [...]string{"floor", "ceiling", "single_wall", "double_wall"}
|
||||
|
||||
func (b BellAttachType) String() string {
|
||||
if int(b) < len(strBellAttachType) {
|
||||
return strBellAttachType[b]
|
||||
}
|
||||
return "invalid BellAttachType"
|
||||
}
|
||||
|
||||
func (b BellAttachType) MarshalText() (text []byte, err error) {
|
||||
if int(b) < len(strBellAttachType) {
|
||||
return []byte(strBellAttachType[b]), nil
|
||||
}
|
||||
return nil, errors.New("invalid BellAttachType: " + strconv.Itoa(int(b)))
|
||||
}
|
||||
|
||||
func (b *BellAttachType) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "floor":
|
||||
*b = BellAttachTypeFloor
|
||||
case "ceiling":
|
||||
*b = BellAttachTypeCeiling
|
||||
case "single_wall":
|
||||
*b = BellAttachTypeSingleWall
|
||||
case "double_wall":
|
||||
*b = BellAttachTypeDoubleWall
|
||||
default:
|
||||
return errors.New("unknown BellAttachType: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ChestType byte
|
||||
|
||||
const (
|
||||
ChestTypeSingle ChestType = iota
|
||||
ChestTypeLeft
|
||||
ChestTypeRight
|
||||
)
|
||||
|
||||
var strChestType = [...]string{"single", "left", "right"}
|
||||
|
||||
func (c ChestType) String() string {
|
||||
if int(c) < len(strChestType) {
|
||||
return strChestType[c]
|
||||
}
|
||||
return "invalid ChestType"
|
||||
}
|
||||
|
||||
func (c ChestType) MarshalText() (text []byte, err error) {
|
||||
if int(c) < len(strChestType) {
|
||||
return []byte(strChestType[c]), nil
|
||||
}
|
||||
return nil, errors.New("invalid ChestType: " + strconv.Itoa(int(c)))
|
||||
}
|
||||
|
||||
func (c *ChestType) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "single":
|
||||
*c = ChestTypeSingle
|
||||
case "left":
|
||||
*c = ChestTypeLeft
|
||||
case "right":
|
||||
*c = ChestTypeRight
|
||||
default:
|
||||
return errors.New("unknown ChestType: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ComparatorMode byte
|
||||
|
||||
const (
|
||||
ComparatorModeCompare ComparatorMode = iota
|
||||
ComparatorModeSubtract
|
||||
)
|
||||
|
||||
var strComparatorMode = [...]string{"compare", "subtract"}
|
||||
|
||||
func (c ComparatorMode) String() string {
|
||||
if int(c) < len(strComparatorMode) {
|
||||
return strComparatorMode[c]
|
||||
}
|
||||
return "invalid ComparatorMode"
|
||||
}
|
||||
|
||||
func (c ComparatorMode) MarshalText() (text []byte, err error) {
|
||||
if int(c) < len(strComparatorMode) {
|
||||
return []byte(strComparatorMode[c]), nil
|
||||
}
|
||||
return nil, errors.New("invalid ComparatorMode: " + strconv.Itoa(int(c)))
|
||||
}
|
||||
|
||||
func (c *ComparatorMode) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "compare":
|
||||
*c = ComparatorModeCompare
|
||||
case "subtract":
|
||||
*c = ComparatorModeSubtract
|
||||
default:
|
||||
return errors.New("unknown ComparatorMode: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Direction byte
|
||||
|
||||
const (
|
||||
Down Direction = iota
|
||||
Up
|
||||
North
|
||||
South
|
||||
West
|
||||
East
|
||||
)
|
||||
|
||||
var strDirection = [...]string{"down", "up", "north", "south", "west", "east"}
|
||||
|
||||
func (d Direction) String() string {
|
||||
if int(d) < len(strDirection) {
|
||||
return strDirection[d]
|
||||
}
|
||||
return "invalid Direction"
|
||||
}
|
||||
|
||||
func (d Direction) MarshalText() (text []byte, err error) {
|
||||
if int(d) < len(strDirection) {
|
||||
return []byte(strDirection[d]), nil
|
||||
}
|
||||
return nil, errors.New("invalid Direction: " + strconv.Itoa(int(d)))
|
||||
}
|
||||
|
||||
func (d *Direction) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "down":
|
||||
*d = Down
|
||||
case "up":
|
||||
*d = Up
|
||||
case "north":
|
||||
*d = North
|
||||
case "south":
|
||||
*d = South
|
||||
case "west":
|
||||
*d = West
|
||||
case "east":
|
||||
*d = East
|
||||
default:
|
||||
return errors.New("unknown Direction: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Axis byte
|
||||
|
||||
const (
|
||||
X Axis = iota
|
||||
Y
|
||||
Z
|
||||
)
|
||||
|
||||
var strAxis = [...]string{"x", "y", "z"}
|
||||
|
||||
func (a Axis) String() string {
|
||||
if int(a) < len(strAxis) {
|
||||
return strAxis[a]
|
||||
}
|
||||
return "invalid Axis"
|
||||
}
|
||||
|
||||
func (a Axis) MarshalText() (text []byte, err error) {
|
||||
if int(a) < len(strAxis) {
|
||||
return []byte(strAxis[a]), nil
|
||||
}
|
||||
return nil, errors.New("invalid Axis: " + strconv.Itoa(int(a)))
|
||||
}
|
||||
|
||||
func (a *Axis) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "x":
|
||||
*a = X
|
||||
case "y":
|
||||
*a = Y
|
||||
case "z":
|
||||
*a = Z
|
||||
default:
|
||||
return errors.New("unknown Axis: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DoorHingeSide byte
|
||||
|
||||
const (
|
||||
DoorHingeSideLeft DoorHingeSide = iota
|
||||
DoorHingeSideRight
|
||||
)
|
||||
|
||||
var strDoorHingeSide = [...]string{"left", "right"}
|
||||
|
||||
func (d DoorHingeSide) String() string {
|
||||
if int(d) < len(strDoorHingeSide) {
|
||||
return strDoorHingeSide[d]
|
||||
}
|
||||
return "invalid DoorHingeSide"
|
||||
}
|
||||
|
||||
func (d DoorHingeSide) MarshalText() (text []byte, err error) {
|
||||
if int(d) < len(strDoorHingeSide) {
|
||||
return []byte(strDoorHingeSide[d]), nil
|
||||
}
|
||||
return nil, errors.New("invalid DoorHingeSide: " + strconv.Itoa(int(d)))
|
||||
}
|
||||
|
||||
func (d *DoorHingeSide) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "left":
|
||||
*d = DoorHingeSideLeft
|
||||
case "right":
|
||||
*d = DoorHingeSideRight
|
||||
default:
|
||||
return errors.New("unknown DoorHingeSide: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DoubleBlockHalf byte
|
||||
|
||||
const (
|
||||
DoubleBlockHalfUpper DoubleBlockHalf = iota
|
||||
DoubleBlockHalfLower
|
||||
)
|
||||
|
||||
var strDoubleBlockHalf = [...]string{"upper", "lower"}
|
||||
|
||||
func (d DoubleBlockHalf) String() string {
|
||||
if int(d) < len(strDoubleBlockHalf) {
|
||||
return strDoubleBlockHalf[d]
|
||||
}
|
||||
return "invalid DoubleBlockHalf"
|
||||
}
|
||||
|
||||
func (d DoubleBlockHalf) MarshalText() (text []byte, err error) {
|
||||
if int(d) < len(strDoubleBlockHalf) {
|
||||
return []byte(strDoubleBlockHalf[d]), nil
|
||||
}
|
||||
return nil, errors.New("invalid DoubleBlockHalf: " + strconv.Itoa(int(d)))
|
||||
}
|
||||
|
||||
func (d *DoubleBlockHalf) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "upper":
|
||||
*d = DoubleBlockHalfUpper
|
||||
case "lower":
|
||||
*d = DoubleBlockHalfLower
|
||||
default:
|
||||
return errors.New("unknown DoubleBlockHalf: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DripstoneThickness byte
|
||||
|
||||
const (
|
||||
DripstoneThicknessTipMerge DripstoneThickness = iota
|
||||
DripstoneThicknessTip
|
||||
DripstoneThicknessFrustum
|
||||
DripstoneThicknessMiddle
|
||||
DripstoneThicknessBase
|
||||
)
|
||||
|
||||
var strDripstoneThickness = [...]string{"tip_merge", "tip", "frustum", "middle", "base"}
|
||||
|
||||
func (d DripstoneThickness) String() string {
|
||||
if int(d) < len(strDripstoneThickness) {
|
||||
return strDripstoneThickness[d]
|
||||
}
|
||||
return "invalid DripstoneThickness"
|
||||
}
|
||||
|
||||
func (d DripstoneThickness) MarshalText() (text []byte, err error) {
|
||||
if int(d) < len(strDripstoneThickness) {
|
||||
return []byte(strDripstoneThickness[d]), nil
|
||||
}
|
||||
return nil, errors.New("invalid DripstoneThickness: " + strconv.Itoa(int(d)))
|
||||
}
|
||||
|
||||
func (d *DripstoneThickness) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "tip_merge":
|
||||
*d = DripstoneThicknessTipMerge
|
||||
case "tip":
|
||||
*d = DripstoneThicknessTip
|
||||
case "frustum":
|
||||
*d = DripstoneThicknessFrustum
|
||||
case "middle":
|
||||
*d = DripstoneThicknessMiddle
|
||||
case "base":
|
||||
*d = DripstoneThicknessBase
|
||||
default:
|
||||
return errors.New("unknown DripstoneThickness: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Half byte
|
||||
|
||||
const (
|
||||
Top Half = iota
|
||||
Bottom
|
||||
)
|
||||
|
||||
var strHalf = [...]string{"top", "bottom"}
|
||||
|
||||
func (h Half) String() string {
|
||||
if int(h) < len(strHalf) {
|
||||
return strHalf[h]
|
||||
}
|
||||
return "invalid Half"
|
||||
}
|
||||
|
||||
func (h Half) MarshalText() (text []byte, err error) {
|
||||
if int(h) < len(strHalf) {
|
||||
return []byte(strHalf[h]), nil
|
||||
}
|
||||
return nil, errors.New("invalid Half: " + strconv.Itoa(int(h)))
|
||||
}
|
||||
|
||||
func (h *Half) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "top":
|
||||
*h = Top
|
||||
case "bottom":
|
||||
*h = Bottom
|
||||
default:
|
||||
return errors.New("unknown Half: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NoteBlockInstrument byte
|
||||
|
||||
const (
|
||||
NoteBlockInstrumentHarp NoteBlockInstrument = iota
|
||||
NoteBlockInstrumentBasedrum
|
||||
NoteBlockInstrumentSnare
|
||||
NoteBlockInstrumentHat
|
||||
NoteBlockInstrumentBass
|
||||
NoteBlockInstrumentFlute
|
||||
NoteBlockInstrumentBell
|
||||
NoteBlockInstrumentGuitar
|
||||
NoteBlockInstrumentChime
|
||||
NoteBlockInstrumentXylophone
|
||||
NoteBlockInstrumentIronXylophone
|
||||
NoteBlockInstrumentCowBell
|
||||
NoteBlockInstrumentDidgeridoo
|
||||
NoteBlockInstrumentBit
|
||||
NoteBlockInstrumentBanjo
|
||||
NoteBlockInstrumentPling
|
||||
)
|
||||
|
||||
var strNoteBlockInstrument = [...]string{"harp", "basedrum", "snare", "hat", "bass", "flute", "bell", "guitar", "chime", "xylophone", "iron_xylophone", "cow_bell", "didgeridoo", "bit", "banjo", "pling"}
|
||||
|
||||
func (n NoteBlockInstrument) String() string {
|
||||
if int(n) < len(strNoteBlockInstrument) {
|
||||
return strNoteBlockInstrument[n]
|
||||
}
|
||||
return "invalid NoteBlockInstrument"
|
||||
}
|
||||
|
||||
func (n NoteBlockInstrument) MarshalText() (text []byte, err error) {
|
||||
if int(n) < len(strNoteBlockInstrument) {
|
||||
return []byte(strNoteBlockInstrument[n]), nil
|
||||
}
|
||||
return nil, errors.New("invalid NoteBlockInstrument: " + strconv.Itoa(int(n)))
|
||||
}
|
||||
|
||||
func (n *NoteBlockInstrument) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "harp":
|
||||
*n = NoteBlockInstrumentHarp
|
||||
case "basedrum":
|
||||
*n = NoteBlockInstrumentBasedrum
|
||||
case "snare":
|
||||
*n = NoteBlockInstrumentSnare
|
||||
case "hat":
|
||||
*n = NoteBlockInstrumentHat
|
||||
case "bass":
|
||||
*n = NoteBlockInstrumentBass
|
||||
case "flute":
|
||||
*n = NoteBlockInstrumentFlute
|
||||
case "bell":
|
||||
*n = NoteBlockInstrumentBell
|
||||
case "guitar":
|
||||
*n = NoteBlockInstrumentGuitar
|
||||
case "chime":
|
||||
*n = NoteBlockInstrumentChime
|
||||
case "xylophone":
|
||||
*n = NoteBlockInstrumentXylophone
|
||||
case "iron_xylophone":
|
||||
*n = NoteBlockInstrumentIronXylophone
|
||||
case "cow_bell":
|
||||
*n = NoteBlockInstrumentCowBell
|
||||
case "didgeridoo":
|
||||
*n = NoteBlockInstrumentDidgeridoo
|
||||
case "bit":
|
||||
*n = NoteBlockInstrumentBit
|
||||
case "banjo":
|
||||
*n = NoteBlockInstrumentBanjo
|
||||
case "pling":
|
||||
*n = NoteBlockInstrumentPling
|
||||
default:
|
||||
return errors.New("unknown NoteBlockInstrument: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PistonType byte
|
||||
|
||||
const (
|
||||
PistonTypeNormal PistonType = iota
|
||||
PistonTypeSticky
|
||||
)
|
||||
|
||||
var strPistonType = [...]string{"normal", "sticky"}
|
||||
|
||||
func (p PistonType) String() string {
|
||||
if int(p) < len(strPistonType) {
|
||||
return strPistonType[p]
|
||||
}
|
||||
return "invalid PistonType"
|
||||
}
|
||||
|
||||
func (p PistonType) MarshalText() (text []byte, err error) {
|
||||
if int(p) < len(strPistonType) {
|
||||
return []byte(strPistonType[p]), nil
|
||||
}
|
||||
return nil, errors.New("invalid PistonType: " + strconv.Itoa(int(p)))
|
||||
}
|
||||
|
||||
func (p *PistonType) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "normal":
|
||||
*p = PistonTypeNormal
|
||||
case "sticky":
|
||||
*p = PistonTypeSticky
|
||||
default:
|
||||
return errors.New("unknown PistonType: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RailShape byte
|
||||
|
||||
const (
|
||||
RailShapeNorthSouth RailShape = iota
|
||||
RailShapeEastWest
|
||||
RailShapeAscendingEast
|
||||
RailShapeAscendingWest
|
||||
RailShapeAscendingNorth
|
||||
RailShapeAscendingSouth
|
||||
RailShapeSouthEast
|
||||
RailShapeSouthWest
|
||||
RailShapeNorthWest
|
||||
RailShapeNorthEast
|
||||
)
|
||||
|
||||
var strRailShape = [...]string{"north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south", "south_east", "south_west", "north_west", "north_east"}
|
||||
|
||||
func (r RailShape) String() string {
|
||||
if int(r) < len(strRailShape) {
|
||||
return strRailShape[r]
|
||||
}
|
||||
return "invalid RailShape"
|
||||
}
|
||||
|
||||
func (r RailShape) MarshalText() (text []byte, err error) {
|
||||
if int(r) < len(strRailShape) {
|
||||
return []byte(strRailShape[r]), nil
|
||||
}
|
||||
return nil, errors.New("invalid RailShape: " + strconv.Itoa(int(r)))
|
||||
}
|
||||
|
||||
func (r *RailShape) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "north_south":
|
||||
*r = RailShapeNorthSouth
|
||||
case "east_west":
|
||||
*r = RailShapeEastWest
|
||||
case "ascending_east":
|
||||
*r = RailShapeAscendingEast
|
||||
case "ascending_west":
|
||||
*r = RailShapeAscendingWest
|
||||
case "ascending_north":
|
||||
*r = RailShapeAscendingNorth
|
||||
case "ascending_south":
|
||||
*r = RailShapeAscendingSouth
|
||||
case "south_east":
|
||||
*r = RailShapeSouthEast
|
||||
case "south_west":
|
||||
*r = RailShapeSouthWest
|
||||
case "north_west":
|
||||
*r = RailShapeNorthWest
|
||||
case "north_east":
|
||||
*r = RailShapeNorthEast
|
||||
default:
|
||||
return errors.New("unknown RailShape: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RedstoneSide byte
|
||||
|
||||
const (
|
||||
RedstoneSideUp RedstoneSide = iota
|
||||
RedstoneSideSide
|
||||
RedstoneSideNone
|
||||
)
|
||||
|
||||
var strRedstoneSide = [...]string{"up", "side", "none"}
|
||||
|
||||
func (r RedstoneSide) String() string {
|
||||
if int(r) < len(strRedstoneSide) {
|
||||
return strRedstoneSide[r]
|
||||
}
|
||||
return "invalid RedstoneSide"
|
||||
}
|
||||
|
||||
func (r RedstoneSide) MarshalText() (text []byte, err error) {
|
||||
if int(r) < len(strRedstoneSide) {
|
||||
return []byte(strRedstoneSide[r]), nil
|
||||
}
|
||||
return nil, errors.New("invalid RedstoneSide: " + strconv.Itoa(int(r)))
|
||||
}
|
||||
|
||||
func (r *RedstoneSide) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "up":
|
||||
*r = RedstoneSideUp
|
||||
case "side":
|
||||
*r = RedstoneSideSide
|
||||
case "none":
|
||||
*r = RedstoneSideNone
|
||||
default:
|
||||
return errors.New("unknown RedstoneSide: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SculkSensorPhase byte
|
||||
|
||||
const (
|
||||
SculkSensorPhaseInactive SculkSensorPhase = iota
|
||||
SculkSensorPhaseActive
|
||||
SculkSensorPhaseCooldown
|
||||
)
|
||||
|
||||
var strSculkSensorPhase = [...]string{"inactive", "active", "cooldown"}
|
||||
|
||||
func (s SculkSensorPhase) String() string {
|
||||
if int(s) < len(strSculkSensorPhase) {
|
||||
return strSculkSensorPhase[s]
|
||||
}
|
||||
return "invalid SculkSensorPhase"
|
||||
}
|
||||
|
||||
func (s SculkSensorPhase) MarshalText() (text []byte, err error) {
|
||||
if int(s) < len(strSculkSensorPhase) {
|
||||
return []byte(strSculkSensorPhase[s]), nil
|
||||
}
|
||||
return nil, errors.New("invalid SculkSensorPhase: " + strconv.Itoa(int(s)))
|
||||
}
|
||||
|
||||
func (s *SculkSensorPhase) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "inactive":
|
||||
*s = SculkSensorPhaseInactive
|
||||
case "active":
|
||||
*s = SculkSensorPhaseActive
|
||||
case "cooldown":
|
||||
*s = SculkSensorPhaseCooldown
|
||||
default:
|
||||
return errors.New("unknown SculkSensorPhase: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SlabType byte
|
||||
|
||||
const (
|
||||
SlabTypeTop SlabType = iota
|
||||
SlabTypeBottom
|
||||
SlabTypeDouble
|
||||
)
|
||||
|
||||
var strSlabType = [...]string{"top", "bottom", "double"}
|
||||
|
||||
func (s SlabType) String() string {
|
||||
if int(s) < len(strSlabType) {
|
||||
return strSlabType[s]
|
||||
}
|
||||
return "invalid SlabType"
|
||||
}
|
||||
|
||||
func (s SlabType) MarshalText() (text []byte, err error) {
|
||||
if int(s) < len(strSlabType) {
|
||||
return []byte(strSlabType[s]), nil
|
||||
}
|
||||
return nil, errors.New("invalid SlabType: " + strconv.Itoa(int(s)))
|
||||
}
|
||||
|
||||
func (s *SlabType) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "top":
|
||||
*s = SlabTypeTop
|
||||
case "bottom":
|
||||
*s = SlabTypeBottom
|
||||
case "double":
|
||||
*s = SlabTypeDouble
|
||||
default:
|
||||
return errors.New("unknown SlabType: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type StairsShape byte
|
||||
|
||||
const (
|
||||
StairsShapeStraight StairsShape = iota
|
||||
StairsShapeInnerLeft
|
||||
StairsShapeInnerRight
|
||||
StairsShapeOuterLeft
|
||||
StairsShapeOuterRight
|
||||
)
|
||||
|
||||
var strStairsShape = [...]string{"straight", "inner_left", "inner_right", "outer_left", "outer_right"}
|
||||
|
||||
func (s StairsShape) String() string {
|
||||
if int(s) < len(strStairsShape) {
|
||||
return strStairsShape[s]
|
||||
}
|
||||
return "invalid StairsShape"
|
||||
}
|
||||
|
||||
func (s StairsShape) MarshalText() (text []byte, err error) {
|
||||
if int(s) < len(strStairsShape) {
|
||||
return []byte(strStairsShape[s]), nil
|
||||
}
|
||||
return nil, errors.New("invalid StairsShape: " + strconv.Itoa(int(s)))
|
||||
}
|
||||
|
||||
func (s *StairsShape) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "straight":
|
||||
*s = StairsShapeStraight
|
||||
case "inner_left":
|
||||
*s = StairsShapeInnerLeft
|
||||
case "inner_right":
|
||||
*s = StairsShapeInnerRight
|
||||
case "outer_left":
|
||||
*s = StairsShapeOuterLeft
|
||||
case "outer_right":
|
||||
*s = StairsShapeOuterRight
|
||||
default:
|
||||
return errors.New("unknown StairsShape: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type StructureMode byte
|
||||
|
||||
const (
|
||||
StructureModeSave StructureMode = iota
|
||||
StructureModeLoad
|
||||
StructureModeCorner
|
||||
StructureModeData
|
||||
)
|
||||
|
||||
var strStructureMode = [...]string{"save", "load", "corner", "data"}
|
||||
|
||||
func (s StructureMode) String() string {
|
||||
if int(s) < len(strStructureMode) {
|
||||
return strStructureMode[s]
|
||||
}
|
||||
return "invalid StructureMode"
|
||||
}
|
||||
|
||||
func (s StructureMode) MarshalText() (text []byte, err error) {
|
||||
if int(s) < len(strStructureMode) {
|
||||
return []byte(strStructureMode[s]), nil
|
||||
}
|
||||
return nil, errors.New("invalid StructureMode: " + strconv.Itoa(int(s)))
|
||||
}
|
||||
|
||||
func (s *StructureMode) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "save":
|
||||
*s = StructureModeSave
|
||||
case "load":
|
||||
*s = StructureModeLoad
|
||||
case "corner":
|
||||
*s = StructureModeCorner
|
||||
case "data":
|
||||
*s = StructureModeData
|
||||
default:
|
||||
return errors.New("unknown StructureMode: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Tilt byte
|
||||
|
||||
const (
|
||||
TiltNone Tilt = iota
|
||||
TiltUnstable
|
||||
TiltPartial
|
||||
TiltFull
|
||||
)
|
||||
|
||||
var strTilt = [...]string{"none", "unstable", "partial", "full"}
|
||||
|
||||
func (t Tilt) String() string {
|
||||
if int(t) < len(strTilt) {
|
||||
return strTilt[t]
|
||||
}
|
||||
return "invalid Tilt"
|
||||
}
|
||||
|
||||
func (t Tilt) MarshalText() (text []byte, err error) {
|
||||
if int(t) < len(strTilt) {
|
||||
return []byte(strTilt[t]), nil
|
||||
}
|
||||
return nil, errors.New("invalid Tilt: " + strconv.Itoa(int(t)))
|
||||
}
|
||||
|
||||
func (t *Tilt) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "none":
|
||||
*t = TiltNone
|
||||
case "unstable":
|
||||
*t = TiltUnstable
|
||||
case "partial":
|
||||
*t = TiltPartial
|
||||
case "full":
|
||||
*t = TiltFull
|
||||
default:
|
||||
return errors.New("unknown Tilt: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type WallSide byte
|
||||
|
||||
const (
|
||||
WallSideNone WallSide = iota
|
||||
WallSideLow
|
||||
WallSideTall
|
||||
)
|
||||
|
||||
var strWallSide = [...]string{"none", "low", "tall"}
|
||||
|
||||
func (w WallSide) String() string {
|
||||
if int(w) < len(strWallSide) {
|
||||
return strWallSide[w]
|
||||
}
|
||||
return "invalid WallSide"
|
||||
}
|
||||
|
||||
func (w WallSide) MarshalText() (text []byte, err error) {
|
||||
if int(w) < len(strWallSide) {
|
||||
return []byte(strWallSide[w]), nil
|
||||
}
|
||||
return nil, errors.New("invalid WallSide: " + strconv.Itoa(int(w)))
|
||||
}
|
||||
|
||||
func (w *WallSide) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "none":
|
||||
*w = WallSideNone
|
||||
case "low":
|
||||
*w = WallSideLow
|
||||
case "tall":
|
||||
*w = WallSideTall
|
||||
default:
|
||||
return errors.New("unknown WallSide: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type FrontAndTop byte
|
||||
|
||||
const (
|
||||
DownEast FrontAndTop = iota
|
||||
DownNorth
|
||||
DownSouth
|
||||
DownWest
|
||||
UpEast
|
||||
UpNorth
|
||||
UpSouth
|
||||
UpWest
|
||||
WestUp
|
||||
EastUp
|
||||
NorthUp
|
||||
SouthUp
|
||||
)
|
||||
|
||||
var strFrontAndTop = [...]string{"down_east", "down_north", "down_south", "down_west", "up_east", "up_north", "up_south", "up_west", "west_up", "east_up", "north_up", "south_up"}
|
||||
|
||||
func (f FrontAndTop) String() string {
|
||||
if int(f) < len(strFrontAndTop) {
|
||||
return strFrontAndTop[f]
|
||||
}
|
||||
return "invalid FrontAndTop"
|
||||
}
|
||||
|
||||
func (f FrontAndTop) MarshalText() (text []byte, err error) {
|
||||
if int(f) < len(strFrontAndTop) {
|
||||
return []byte(strFrontAndTop[f]), nil
|
||||
}
|
||||
return nil, errors.New("invalid FrontAndTop: " + strconv.Itoa(int(f)))
|
||||
}
|
||||
|
||||
func (f *FrontAndTop) UnmarshalText(text []byte) error {
|
||||
switch str := string(text); str {
|
||||
case "down_east":
|
||||
*f = DownEast
|
||||
case "down_north":
|
||||
*f = DownNorth
|
||||
case "down_south":
|
||||
*f = DownSouth
|
||||
case "down_west":
|
||||
*f = DownWest
|
||||
case "up_east":
|
||||
*f = UpEast
|
||||
case "up_north":
|
||||
*f = UpNorth
|
||||
case "up_south":
|
||||
*f = UpSouth
|
||||
case "up_west":
|
||||
*f = UpWest
|
||||
case "west_up":
|
||||
*f = WestUp
|
||||
case "east_up":
|
||||
*f = EastUp
|
||||
case "north_up":
|
||||
*f = NorthUp
|
||||
case "south_up":
|
||||
*f = SouthUp
|
||||
default:
|
||||
return errors.New("unknown FrontAndTop: " + str)
|
||||
}
|
||||
return nil
|
||||
}
|
@ -23,6 +23,9 @@ func Unmarshal(data []byte, v interface{}) error {
|
||||
// For example, you can decode an NBT value which root tag is TagCompound(0x0a)
|
||||
// into a struct or map, but not a string.
|
||||
//
|
||||
// If v implement Unmarshaler, the method will be called and override the default behavior.
|
||||
// Else if v implement encoding.TextUnmarshaler, the value will be encoded as TagString.
|
||||
//
|
||||
// This method also return tag name of the root tag.
|
||||
// In real world, it is often empty, but the API should allow you to get it when ever you want.
|
||||
func (d *Decoder) Decode(v interface{}) (string, error) {
|
||||
|
@ -405,72 +405,3 @@ func TestDecoder_Decode_textUnmarshaler(t *testing.T) {
|
||||
t.Errorf("b should be true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRawMessage_Decode(t *testing.T) {
|
||||
data := []byte{
|
||||
TagCompound, 0, 2, 'a', 'b',
|
||||
TagInt, 0, 3, 'K', 'e', 'y', 0, 0, 0, 12,
|
||||
TagString, 0, 5, 'V', 'a', 'l', 'u', 'e', 0, 4, 'T', 'n', 'z', 'e',
|
||||
TagList, 0, 4, 'L', 'i', 's', 't', TagCompound, 0, 0, 0, 2, 0, 0,
|
||||
TagEnd,
|
||||
}
|
||||
var container struct {
|
||||
Key int32
|
||||
Value RawMessage
|
||||
List RawMessage
|
||||
}
|
||||
|
||||
if tag, err := NewDecoder(bytes.NewReader(data)).Decode(&container); err != nil {
|
||||
t.Fatal(tag)
|
||||
} else {
|
||||
if tag != "ab" {
|
||||
t.Fatalf("Decode tag name error: want %s, get: %s", "ab", tag)
|
||||
}
|
||||
if container.Key != 12 {
|
||||
t.Fatalf("Decode Key error: want %v, get: %v", 12, container.Key)
|
||||
}
|
||||
if !bytes.Equal(container.Value.Data, []byte{
|
||||
0, 4, 'T', 'n', 'z', 'e',
|
||||
}) {
|
||||
t.Fatalf("Decode Key error: get: %v", container.Value)
|
||||
}
|
||||
if !bytes.Equal(container.List.Data, []byte{
|
||||
TagCompound, 0, 0, 0, 2,
|
||||
0, 0,
|
||||
}) {
|
||||
t.Fatalf("Decode List error: get: %v", container.List)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringifiedMessage_Decode(t *testing.T) {
|
||||
data := []byte{
|
||||
TagCompound, 0, 2, 'a', 'b',
|
||||
TagInt, 0, 3, 'K', 'e', 'y', 0, 0, 0, 12,
|
||||
TagString, 0, 5, 'V', 'a', 'l', 'u', 'e', 0, 5, 'T', 'n', ' ', 'z', 'e',
|
||||
TagList, 0, 4, 'L', 'i', 's', 't', TagCompound, 0, 0, 0, 2, 0, 0,
|
||||
TagEnd,
|
||||
}
|
||||
var container struct {
|
||||
Key int32
|
||||
Value StringifiedMessage
|
||||
List StringifiedMessage
|
||||
}
|
||||
|
||||
if tag, err := NewDecoder(bytes.NewReader(data)).Decode(&container); err != nil {
|
||||
t.Fatal(tag, err)
|
||||
} else {
|
||||
if tag != "ab" {
|
||||
t.Fatalf("UnmarshalNBT tag name error: want %s, get: %s", "ab", tag)
|
||||
}
|
||||
if container.Key != 12 {
|
||||
t.Fatalf("UnmarshalNBT Key error: want %v, get: %v", 12, container.Key)
|
||||
}
|
||||
if container.Value != `"Tn ze"` {
|
||||
t.Fatalf("UnmarshalNBT Key error: get: %v", container.Value)
|
||||
}
|
||||
if container.List != "[{},{}]" {
|
||||
t.Fatalf("UnmarshalNBT List error: get: %v", container.List)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package nbt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -37,8 +38,8 @@ func NewEncoder(w io.Writer) *Encoder {
|
||||
// expect `[]int8`, `[]int32`, `[]int64`, `[]uint8`, `[]uint32` and `[]uint64`,
|
||||
// which TagByteArray, TagIntArray and TagLongArray.
|
||||
// To force encode them as TagList, add a struct field tag.
|
||||
// You haven't ability to encode them as TagList as root element at this time,
|
||||
// issue or pull-request is welcome.
|
||||
//
|
||||
//
|
||||
func (e *Encoder) Encode(v interface{}, tagName string) error {
|
||||
t, val := getTagType(reflect.ValueOf(v))
|
||||
return e.marshal(val, t, tagName)
|
||||
@ -129,10 +130,22 @@ func (e *Encoder) writeValue(val reflect.Value, tagType byte) error {
|
||||
}
|
||||
|
||||
case TagString:
|
||||
if err := e.writeInt16(int16(val.Len())); err != nil {
|
||||
var str []byte
|
||||
if val.NumMethod() > 0 && val.CanInterface() {
|
||||
if t, ok := val.Interface().(encoding.TextMarshaler); ok {
|
||||
var err error
|
||||
str, err = t.MarshalText()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
str = []byte(val.String())
|
||||
}
|
||||
if err := e.writeInt16(int16(len(str))); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := e.w.Write([]byte(val.String()))
|
||||
_, err := e.w.Write(str)
|
||||
return err
|
||||
|
||||
case TagCompound:
|
||||
@ -205,17 +218,23 @@ func getTagType(v reflect.Value) (byte, reflect.Value) {
|
||||
v.Set(reflect.New(v.Type().Elem()))
|
||||
}
|
||||
if v.Type().NumMethod() > 0 && v.CanInterface() {
|
||||
if u, ok := v.Interface().(Marshaler); ok {
|
||||
i := v.Interface()
|
||||
if u, ok := i.(Marshaler); ok {
|
||||
return u.TagType(), v
|
||||
} else if _, ok := i.(encoding.TextMarshaler); ok {
|
||||
return TagString, v
|
||||
}
|
||||
}
|
||||
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
if v.CanInterface() {
|
||||
if encoder, ok := v.Interface().(Marshaler); ok {
|
||||
return encoder.TagType(), v
|
||||
if v.Type().NumMethod() > 0 && v.CanInterface() {
|
||||
i := v.Interface()
|
||||
if u, ok := i.(Marshaler); ok {
|
||||
return u.TagType(), v
|
||||
} else if _, ok := i.(encoding.TextMarshaler); ok {
|
||||
return TagString, v
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,29 +208,6 @@ func TestEncoder_Encode_map(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRawMessage_Encode(t *testing.T) {
|
||||
data := []byte{
|
||||
TagCompound, 0, 2, 'a', 'b',
|
||||
TagInt, 0, 3, 'K', 'e', 'y', 0, 0, 0, 12,
|
||||
TagString, 0, 5, 'V', 'a', 'l', 'u', 'e', 0, 4, 'T', 'n', 'z', 'e',
|
||||
TagEnd,
|
||||
}
|
||||
var container struct {
|
||||
Key int32
|
||||
Value RawMessage
|
||||
}
|
||||
container.Key = 12
|
||||
container.Value.Type = TagString
|
||||
container.Value.Data = []byte{0, 4, 'T', 'n', 'z', 'e'}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := NewEncoder(&buf).Encode(container, "ab"); err != nil {
|
||||
t.Fatalf("Encode error: %v", err)
|
||||
} else if !bytes.Equal(data, buf.Bytes()) {
|
||||
t.Fatalf("Encode error: want %v, get: %v", data, buf.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncoder_Encode_interface(t *testing.T) {
|
||||
data := map[string]interface{}{
|
||||
"Key": int32(12),
|
||||
@ -253,3 +230,18 @@ func TestEncoder_Encode_interface(t *testing.T) {
|
||||
t.Fatalf("want: (%v, %v), but got (%v, %v)", 12, "Tnze", container.Key, container.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncoder_Encode_textMarshaler(t *testing.T) {
|
||||
var b TextBool = true
|
||||
data, err := Marshal(&b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wants := []byte{
|
||||
TagString, 0, 0,
|
||||
0, 4, 't', 'r', 'u', 'e',
|
||||
}
|
||||
if !bytes.Equal(data, wants) {
|
||||
t.Errorf("get %v, want %v", data, wants)
|
||||
}
|
||||
}
|
||||
|
66
nbt/rawmsg_test.go
Normal file
66
nbt/rawmsg_test.go
Normal file
@ -0,0 +1,66 @@
|
||||
package nbt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRawMessage_Encode(t *testing.T) {
|
||||
data := []byte{
|
||||
TagCompound, 0, 2, 'a', 'b',
|
||||
TagInt, 0, 3, 'K', 'e', 'y', 0, 0, 0, 12,
|
||||
TagString, 0, 5, 'V', 'a', 'l', 'u', 'e', 0, 4, 'T', 'n', 'z', 'e',
|
||||
TagEnd,
|
||||
}
|
||||
var container struct {
|
||||
Key int32
|
||||
Value RawMessage
|
||||
}
|
||||
container.Key = 12
|
||||
container.Value.Type = TagString
|
||||
container.Value.Data = []byte{0, 4, 'T', 'n', 'z', 'e'}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := NewEncoder(&buf).Encode(container, "ab"); err != nil {
|
||||
t.Fatalf("Encode error: %v", err)
|
||||
} else if !bytes.Equal(data, buf.Bytes()) {
|
||||
t.Fatalf("Encode error: want %v, get: %v", data, buf.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRawMessage_Decode(t *testing.T) {
|
||||
data := []byte{
|
||||
TagCompound, 0, 2, 'a', 'b',
|
||||
TagInt, 0, 3, 'K', 'e', 'y', 0, 0, 0, 12,
|
||||
TagString, 0, 5, 'V', 'a', 'l', 'u', 'e', 0, 4, 'T', 'n', 'z', 'e',
|
||||
TagList, 0, 4, 'L', 'i', 's', 't', TagCompound, 0, 0, 0, 2, 0, 0,
|
||||
TagEnd,
|
||||
}
|
||||
var container struct {
|
||||
Key int32
|
||||
Value RawMessage
|
||||
List RawMessage
|
||||
}
|
||||
|
||||
if tag, err := NewDecoder(bytes.NewReader(data)).Decode(&container); err != nil {
|
||||
t.Fatal(tag)
|
||||
} else {
|
||||
if tag != "ab" {
|
||||
t.Fatalf("Decode tag name error: want %s, get: %s", "ab", tag)
|
||||
}
|
||||
if container.Key != 12 {
|
||||
t.Fatalf("Decode Key error: want %v, get: %v", 12, container.Key)
|
||||
}
|
||||
if !bytes.Equal(container.Value.Data, []byte{
|
||||
0, 4, 'T', 'n', 'z', 'e',
|
||||
}) {
|
||||
t.Fatalf("Decode Key error: get: %v", container.Value)
|
||||
}
|
||||
if !bytes.Equal(container.List.Data, []byte{
|
||||
TagCompound, 0, 0, 0, 2,
|
||||
0, 0,
|
||||
}) {
|
||||
t.Fatalf("Decode List error: get: %v", container.List)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,38 @@
|
||||
package nbt
|
||||
|
||||
//TODO: Test SNBT encode
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStringifiedMessage_Decode(t *testing.T) {
|
||||
data := []byte{
|
||||
TagCompound, 0, 2, 'a', 'b',
|
||||
TagInt, 0, 3, 'K', 'e', 'y', 0, 0, 0, 12,
|
||||
TagString, 0, 5, 'V', 'a', 'l', 'u', 'e', 0, 5, 'T', 'n', ' ', 'z', 'e',
|
||||
TagList, 0, 4, 'L', 'i', 's', 't', TagCompound, 0, 0, 0, 2, 0, 0,
|
||||
TagEnd,
|
||||
}
|
||||
var container struct {
|
||||
Key int32
|
||||
Value StringifiedMessage
|
||||
List StringifiedMessage
|
||||
}
|
||||
|
||||
if tag, err := NewDecoder(bytes.NewReader(data)).Decode(&container); err != nil {
|
||||
t.Fatal(tag, err)
|
||||
} else {
|
||||
if tag != "ab" {
|
||||
t.Fatalf("UnmarshalNBT tag name error: want %s, get: %s", "ab", tag)
|
||||
}
|
||||
if container.Key != 12 {
|
||||
t.Fatalf("UnmarshalNBT Key error: want %v, get: %v", 12, container.Key)
|
||||
}
|
||||
if container.Value != `"Tn ze"` {
|
||||
t.Fatalf("UnmarshalNBT Key error: get: %v", container.Value)
|
||||
}
|
||||
if container.List != "[{},{}]" {
|
||||
t.Fatalf("UnmarshalNBT List error: get: %v", container.List)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,10 +45,10 @@ type PacketHandler struct {
|
||||
type packetHandlerFunc func(player *Player, packet Packet758) error
|
||||
|
||||
//go:embed DimensionCodec.snbt
|
||||
var dimensionCodecSNBT string
|
||||
var dimensionCodecSNBT nbt.StringifiedMessage
|
||||
|
||||
//go:embed Dimension.snbt
|
||||
var dimensionSNBT string
|
||||
var dimensionSNBT nbt.StringifiedMessage
|
||||
|
||||
func NewGame(dim Level, components ...Component) *Game {
|
||||
g := &Game{
|
||||
@ -91,8 +91,8 @@ func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net
|
||||
pk.Array([]pk.Identifier{
|
||||
pk.Identifier(dimInfo.Name),
|
||||
}),
|
||||
pk.NBT(nbt.StringifiedMessage(dimensionCodecSNBT)),
|
||||
pk.NBT(nbt.StringifiedMessage(dimensionSNBT)),
|
||||
pk.NBT(dimensionCodecSNBT),
|
||||
pk.NBT(dimensionSNBT),
|
||||
pk.Identifier(dimInfo.Name), // World Name
|
||||
pk.Long(dimInfo.HashedSeed), // Hashed seed
|
||||
pk.VarInt(0), // Max Players (Ignored by client)
|
||||
|
Reference in New Issue
Block a user