10
data/README.md
Normal file
10
data/README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
## Updating `data`
|
||||||
|
|
||||||
|
1. Go to [https://github.com/PrismarineJS/minecraft-data/tree/master/data/pc/{version}](https://github.com/PrismarineJS/minecraft-data/tree/master/data/pc)
|
||||||
|
2. Update `version` in the following files if there is a new corresponding JSON file available:
|
||||||
|
- [gen_block.go](block/gen_block.go) - `blocks.json`
|
||||||
|
- [gen_entity.go](entity/gen_entity.go) - `entities.json`
|
||||||
|
- [gen_item.go](item/gen_item.go) - `items.json`
|
||||||
|
- [gen_packetid.go](packetid/gen_packetid.go) - `protocol.json`
|
||||||
|
3. Update the `URL` in [gen_soundid.go](soundid/gen_soundid.go) (verify the URL returns a response first)
|
||||||
|
4. Run `go generate ./...`
|
13472
data/block/block.go
13472
data/block/block.go
File diff suppressed because it is too large
Load Diff
151
data/block/gen_block.go
Normal file
151
data/block/gen_block.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
//+build generate
|
||||||
|
|
||||||
|
// gen_blocks.go generates block information.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/iancoleman/strcase"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
version = "1.17"
|
||||||
|
infoURL = "https://raw.githubusercontent.com/PrismarineJS/minecraft-data/master/data/pc/" + version + "/blocks.json"
|
||||||
|
//language=gohtml
|
||||||
|
blockTmpl = `// Code generated by gen_block.go; DO NOT EDIT.
|
||||||
|
|
||||||
|
// Package block stores information about blocks in Minecraft.
|
||||||
|
package block
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BitsPerBlock indicates how many bits are needed to represent all possible
|
||||||
|
// block states. This value is used to determine the size of the global palette.
|
||||||
|
var BitsPerBlock = int(math.Ceil(math.Log2(float64(len(StateID)))))
|
||||||
|
|
||||||
|
// ID describes the numeric ID of a block.
|
||||||
|
type ID uint32
|
||||||
|
|
||||||
|
// Block describes information about a type of block.
|
||||||
|
type Block struct {
|
||||||
|
ID ID
|
||||||
|
DisplayName string
|
||||||
|
Name string
|
||||||
|
|
||||||
|
Hardness float64
|
||||||
|
Diggable bool
|
||||||
|
DropIDs []uint32
|
||||||
|
NeedsTools map[uint32]bool
|
||||||
|
|
||||||
|
MinStateID uint32
|
||||||
|
MaxStateID uint32
|
||||||
|
|
||||||
|
Transparent bool
|
||||||
|
FilterLightLevel int
|
||||||
|
EmitLightLevel int
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
{{- range .}}
|
||||||
|
{{.CamelName}} = Block{
|
||||||
|
ID: {{.ID}},
|
||||||
|
DisplayName: "{{.DisplayName}}",
|
||||||
|
Name: "{{.Name}}",
|
||||||
|
Hardness: {{.Hardness}},
|
||||||
|
Diggable: {{.Diggable}},
|
||||||
|
DropIDs: []uint32{ {{- range .DropIDs}}{{.}},{{end -}} },
|
||||||
|
NeedsTools: map[uint32]bool{ {{- range $key, $val := .NeedsTools}}{{$key}}: {{$val}},{{end -}} },
|
||||||
|
MinStateID: {{.MinStateID}},
|
||||||
|
MaxStateID: {{.MaxStateID}},
|
||||||
|
Transparent: {{.Transparent}},
|
||||||
|
FilterLightLevel: {{.FilterLightLevel}},
|
||||||
|
EmitLightLevel: {{.EmitLightLevel}},
|
||||||
|
}{{end}}
|
||||||
|
)
|
||||||
|
|
||||||
|
// ByID is an index of minecraft blocks by their ID.
|
||||||
|
var ByID = map[ID]*Block{ {{range .}}
|
||||||
|
{{.ID}}: &{{.CamelName}},{{end}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StateID maps all possible state IDs to a corresponding block ID.
|
||||||
|
var StateID = map[uint32]ID{ {{range $block := .}}
|
||||||
|
{{- range .States}}
|
||||||
|
{{.}}: {{$block.ID}},
|
||||||
|
{{- end}}{{end}}
|
||||||
|
}`
|
||||||
|
)
|
||||||
|
|
||||||
|
type Block struct {
|
||||||
|
ID uint32 `json:"id"`
|
||||||
|
CamelName string `json:"-"`
|
||||||
|
DisplayName string `json:"displayName"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
Hardness float64 `json:"hardness"`
|
||||||
|
Diggable bool `json:"diggable"`
|
||||||
|
DropIDs []uint32 `json:"drops"`
|
||||||
|
NeedsTools map[uint32]bool `json:"harvestTools"`
|
||||||
|
|
||||||
|
MinStateID uint32 `json:"minStateId"`
|
||||||
|
MaxStateID uint32 `json:"maxStateId"`
|
||||||
|
|
||||||
|
Transparent bool `json:"transparent"`
|
||||||
|
FilterLightLevel int `json:"filterLight"`
|
||||||
|
EmitLightLevel int `json:"emitLight"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Block) States() []uint32 {
|
||||||
|
if b.MinStateID == b.MaxStateID {
|
||||||
|
return []uint32{b.MinStateID}
|
||||||
|
}
|
||||||
|
states := make([]uint32, 0)
|
||||||
|
for i := b.MinStateID; i <= b.MaxStateID; i++ {
|
||||||
|
states = append(states, i)
|
||||||
|
}
|
||||||
|
return states
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadInfo() ([]*Block, error) {
|
||||||
|
resp, err := http.Get(infoURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var data []*Block
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, d := range data {
|
||||||
|
d.CamelName = strcase.ToCamel(d.Name)
|
||||||
|
}
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:generate go run $GOFILE
|
||||||
|
//go:generate go fmt block.go
|
||||||
|
func main() {
|
||||||
|
fmt.Println("generating block.go")
|
||||||
|
blocks, err := downloadInfo()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create("block.go")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
if err := template.Must(template.New("").Parse(blockTmpl)).Execute(f, blocks); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
@ -1,201 +0,0 @@
|
|||||||
//+build ignore
|
|
||||||
|
|
||||||
// gen_blocks.go generates block information.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"go/ast"
|
|
||||||
"go/format"
|
|
||||||
"go/token"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/iancoleman/strcase"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
infoURL = "https://raw.githubusercontent.com/PrismarineJS/minecraft-data/master/data/pc/1.17/blocks.json"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Block struct {
|
|
||||||
ID uint32 `json:"id"`
|
|
||||||
DisplayName string `json:"displayName"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
|
|
||||||
Hardness float64 `json:"hardness"`
|
|
||||||
Diggable bool `json:"diggable"`
|
|
||||||
DropIDs []uint32 `json:"drops"`
|
|
||||||
NeedsTools map[uint32]bool `json:"harvestTools"`
|
|
||||||
|
|
||||||
MinStateID uint32 `json:"minStateId"`
|
|
||||||
MaxStateID uint32 `json:"maxStateId"`
|
|
||||||
|
|
||||||
Transparent bool `json:"transparent"`
|
|
||||||
FilterLightLevel int `json:"filterLight"`
|
|
||||||
EmitLightLevel int `json:"emitLight"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func downloadInfo() ([]Block, error) {
|
|
||||||
resp, err := http.Get(infoURL)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var data []Block
|
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeBlockDeclaration(blocks []Block) *ast.DeclStmt {
|
|
||||||
out := &ast.DeclStmt{Decl: &ast.GenDecl{Tok: token.VAR}}
|
|
||||||
|
|
||||||
for _, b := range blocks {
|
|
||||||
t := reflect.TypeOf(b)
|
|
||||||
fields := make([]ast.Expr, t.NumField())
|
|
||||||
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
|
||||||
ft := t.Field(i)
|
|
||||||
|
|
||||||
var val ast.Expr
|
|
||||||
switch ft.Type.Kind() {
|
|
||||||
case reflect.Uint32, reflect.Int:
|
|
||||||
val = &ast.BasicLit{Kind: token.INT, Value: fmt.Sprint(reflect.ValueOf(b).Field(i))}
|
|
||||||
case reflect.Float64:
|
|
||||||
val = &ast.BasicLit{Kind: token.FLOAT, Value: fmt.Sprint(reflect.ValueOf(b).Field(i))}
|
|
||||||
case reflect.String:
|
|
||||||
val = &ast.BasicLit{Kind: token.STRING, Value: strconv.Quote(reflect.ValueOf(b).Field(i).String())}
|
|
||||||
case reflect.Bool:
|
|
||||||
val = &ast.BasicLit{Kind: token.IDENT, Value: fmt.Sprint(reflect.ValueOf(b).Field(i).Bool())}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
val = &ast.CompositeLit{
|
|
||||||
Type: &ast.ArrayType{
|
|
||||||
Elt: &ast.BasicLit{Kind: token.IDENT, Value: ft.Type.Elem().Name()},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
v := reflect.ValueOf(b).Field(i)
|
|
||||||
switch ft.Type.Elem().Kind() {
|
|
||||||
case reflect.Uint32, reflect.Int:
|
|
||||||
for x := 0; x < v.Len(); x++ {
|
|
||||||
val.(*ast.CompositeLit).Elts = append(val.(*ast.CompositeLit).Elts, &ast.BasicLit{
|
|
||||||
Kind: token.INT,
|
|
||||||
Value: fmt.Sprint(v.Index(x)),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Map:
|
|
||||||
// Must be the NeedsTools map of type map[uint32]bool.
|
|
||||||
m := &ast.CompositeLit{
|
|
||||||
Type: &ast.MapType{
|
|
||||||
Key: &ast.BasicLit{Kind: token.IDENT, Value: ft.Type.Key().Name()},
|
|
||||||
Value: &ast.BasicLit{Kind: token.IDENT, Value: ft.Type.Elem().Name()},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
iter := reflect.ValueOf(b).Field(i).MapRange()
|
|
||||||
for iter.Next() {
|
|
||||||
m.Elts = append(m.Elts, &ast.KeyValueExpr{
|
|
||||||
Key: &ast.BasicLit{Kind: token.INT, Value: fmt.Sprint(iter.Key().Uint())},
|
|
||||||
Value: &ast.BasicLit{Kind: token.IDENT, Value: fmt.Sprint(iter.Value().Bool())},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
val = m
|
|
||||||
}
|
|
||||||
|
|
||||||
fields[i] = &ast.KeyValueExpr{
|
|
||||||
Key: &ast.Ident{Name: ft.Name},
|
|
||||||
Value: val,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out.Decl.(*ast.GenDecl).Specs = append(out.Decl.(*ast.GenDecl).Specs, &ast.ValueSpec{
|
|
||||||
Names: []*ast.Ident{{Name: strcase.ToCamel(b.Name)}},
|
|
||||||
Values: []ast.Expr{
|
|
||||||
&ast.CompositeLit{
|
|
||||||
Type: &ast.Ident{Name: reflect.TypeOf(b).Name()},
|
|
||||||
Elts: fields,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:generate go run $GOFILE > ./packetid.go
|
|
||||||
func main() {
|
|
||||||
blocks, err := downloadInfo()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(`// Code generated by gen_blocks.go; DO NOT EDIT.
|
|
||||||
|
|
||||||
// Package block stores information about blocks in Minecraft.
|
|
||||||
package block
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BitsPerBlock indicates how many bits are needed to represent all possible
|
|
||||||
// block states. This value is used to determine the size of the global palette.
|
|
||||||
var BitsPerBlock = int(math.Ceil(math.Log2(float64(len(StateID)))))
|
|
||||||
|
|
||||||
// ID describes the numeric ID of a block.
|
|
||||||
type ID uint32
|
|
||||||
|
|
||||||
// Block describes information about a type of block.
|
|
||||||
type Block struct {
|
|
||||||
ID ID
|
|
||||||
DisplayName string
|
|
||||||
Name string
|
|
||||||
|
|
||||||
Hardness float64
|
|
||||||
Diggable bool
|
|
||||||
DropIDs []uint32
|
|
||||||
NeedsTools map[uint32]bool
|
|
||||||
|
|
||||||
MinStateID uint32
|
|
||||||
MaxStateID uint32
|
|
||||||
|
|
||||||
Transparent bool
|
|
||||||
FilterLightLevel int
|
|
||||||
EmitLightLevel int
|
|
||||||
}
|
|
||||||
|
|
||||||
`)
|
|
||||||
format.Node(os.Stdout, token.NewFileSet(), makeBlockDeclaration(blocks))
|
|
||||||
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Println("// ByID is an index of minecraft blocks by their ID.")
|
|
||||||
fmt.Println("var ByID = map[ID]*Block{")
|
|
||||||
for _, b := range blocks {
|
|
||||||
fmt.Printf(" %d: &%s,\n", b.ID, strcase.ToCamel(b.Name))
|
|
||||||
}
|
|
||||||
fmt.Println("}")
|
|
||||||
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Println("// StateID maps all possible state IDs to a corresponding block ID.")
|
|
||||||
fmt.Println("var StateID = map[uint32]ID{")
|
|
||||||
for _, b := range blocks {
|
|
||||||
if b.MinStateID == b.MaxStateID {
|
|
||||||
fmt.Printf(" %d: %d,\n", b.MinStateID, b.ID)
|
|
||||||
} else {
|
|
||||||
for i := b.MinStateID; i <= b.MaxStateID; i++ {
|
|
||||||
fmt.Printf(" %d: %d,\n", i, b.ID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Println("}")
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,152 +0,0 @@
|
|||||||
// gen_entity.go generates entity information.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"go/ast"
|
|
||||||
"go/format"
|
|
||||||
"go/token"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/iancoleman/strcase"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
infoURL = "https://raw.githubusercontent.com/PrismarineJS/minecraft-data/master/data/pc/1.17/entities.json"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Entity struct {
|
|
||||||
ID uint32 `json:"id"`
|
|
||||||
InternalID uint32 `json:"internalId"`
|
|
||||||
DisplayName string `json:"displayName"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
|
|
||||||
Width float64 `json:"width"`
|
|
||||||
Height float64 `json:"height"`
|
|
||||||
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func downloadInfo() ([]Entity, error) {
|
|
||||||
resp, err := http.Get(infoURL)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var data []Entity
|
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeEntityDeclaration(entities []Entity) *ast.DeclStmt {
|
|
||||||
out := &ast.DeclStmt{Decl: &ast.GenDecl{Tok: token.VAR}}
|
|
||||||
|
|
||||||
for _, e := range entities {
|
|
||||||
t := reflect.TypeOf(e)
|
|
||||||
fields := make([]ast.Expr, t.NumField())
|
|
||||||
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
|
||||||
ft := t.Field(i)
|
|
||||||
|
|
||||||
var val ast.Expr
|
|
||||||
switch ft.Type.Kind() {
|
|
||||||
case reflect.Uint32, reflect.Int:
|
|
||||||
val = &ast.BasicLit{Kind: token.INT, Value: fmt.Sprint(reflect.ValueOf(e).Field(i))}
|
|
||||||
case reflect.Float64:
|
|
||||||
val = &ast.BasicLit{Kind: token.FLOAT, Value: fmt.Sprint(reflect.ValueOf(e).Field(i))}
|
|
||||||
case reflect.String:
|
|
||||||
val = &ast.BasicLit{Kind: token.STRING, Value: strconv.Quote(reflect.ValueOf(e).Field(i).String())}
|
|
||||||
case reflect.Bool:
|
|
||||||
val = &ast.BasicLit{Kind: token.IDENT, Value: fmt.Sprint(reflect.ValueOf(e).Field(i).Bool())}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
val = &ast.CompositeLit{
|
|
||||||
Type: &ast.ArrayType{
|
|
||||||
Elt: &ast.BasicLit{Kind: token.IDENT, Value: ft.Type.Elem().Name()},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
v := reflect.ValueOf(e).Field(i)
|
|
||||||
switch ft.Type.Elem().Kind() {
|
|
||||||
case reflect.Uint32, reflect.Int:
|
|
||||||
for x := 0; x < v.Len(); x++ {
|
|
||||||
val.(*ast.CompositeLit).Elts = append(val.(*ast.CompositeLit).Elts, &ast.BasicLit{
|
|
||||||
Kind: token.INT,
|
|
||||||
Value: fmt.Sprint(v.Index(x)),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fields[i] = &ast.KeyValueExpr{
|
|
||||||
Key: &ast.Ident{Name: ft.Name},
|
|
||||||
Value: val,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out.Decl.(*ast.GenDecl).Specs = append(out.Decl.(*ast.GenDecl).Specs, &ast.ValueSpec{
|
|
||||||
Names: []*ast.Ident{{Name: strcase.ToCamel(e.Name)}},
|
|
||||||
Values: []ast.Expr{
|
|
||||||
&ast.CompositeLit{
|
|
||||||
Type: &ast.Ident{Name: reflect.TypeOf(e).Name()},
|
|
||||||
Elts: fields,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:generate go run $GOFILE
|
|
||||||
//go:generate go fmt ../entity.go
|
|
||||||
func main() {
|
|
||||||
entities, err := downloadInfo()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Create("../entity.go")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
fmt.Fprintln(f, `// Code generated by gen_entity.go DO NOT EDIT.
|
|
||||||
// Package entity stores information about entities in Minecraft.
|
|
||||||
package entity
|
|
||||||
// ID describes the numeric ID of an entity.
|
|
||||||
type ID uint32
|
|
||||||
|
|
||||||
// Entity describes information about a type of entity.
|
|
||||||
type Entity struct {
|
|
||||||
ID ID
|
|
||||||
InternalID uint32
|
|
||||||
DisplayName string
|
|
||||||
Name string
|
|
||||||
Width float64
|
|
||||||
Height float64
|
|
||||||
Type string
|
|
||||||
}`)
|
|
||||||
format.Node(f, token.NewFileSet(), makeEntityDeclaration(entities))
|
|
||||||
|
|
||||||
fmt.Fprintln(f)
|
|
||||||
fmt.Fprintln(f)
|
|
||||||
fmt.Fprintln(f, "// ByID is an index of minecraft entities by their ID.")
|
|
||||||
fmt.Fprintln(f, "var ByID = map[ID]*Entity{")
|
|
||||||
for _, e := range entities {
|
|
||||||
fmt.Fprintf(f, " %d: &%s,\n", e.ID, strcase.ToCamel(e.Name))
|
|
||||||
}
|
|
||||||
fmt.Fprintln(f, "}")
|
|
||||||
|
|
||||||
fmt.Fprintln(f)
|
|
||||||
}
|
|
104
data/entity/gen_entity.go
Normal file
104
data/entity/gen_entity.go
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
//+build generate
|
||||||
|
|
||||||
|
// gen_entity.go generates entity information.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/iancoleman/strcase"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
version = "1.17"
|
||||||
|
infoURL = "https://raw.githubusercontent.com/PrismarineJS/minecraft-data/master/data/pc/" + version + "/entities.json"
|
||||||
|
//language=gohtml
|
||||||
|
entityTmpl = `// Code generated by gen_entity.go DO NOT EDIT.
|
||||||
|
// Package entity stores information about entities in Minecraft.
|
||||||
|
package entity
|
||||||
|
// ID describes the numeric ID of an entity.
|
||||||
|
type ID uint32
|
||||||
|
|
||||||
|
// Entity describes information about a type of entity.
|
||||||
|
type Entity struct {
|
||||||
|
ID ID
|
||||||
|
InternalID uint32
|
||||||
|
DisplayName string
|
||||||
|
Name string
|
||||||
|
Width float64
|
||||||
|
Height float64
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
{{- range .}}
|
||||||
|
{{.CamelName}} = Entity{
|
||||||
|
ID: {{.ID}},
|
||||||
|
InternalID: {{.InternalID}},
|
||||||
|
DisplayName: "{{.DisplayName}}",
|
||||||
|
Name: "{{.Name}}",
|
||||||
|
Width: {{.Width}},
|
||||||
|
Height: {{.Height}},
|
||||||
|
Type: "{{.Type}}",
|
||||||
|
}{{end}}
|
||||||
|
)
|
||||||
|
|
||||||
|
// ByID is an index of minecraft entities by their ID.
|
||||||
|
var ByID = map[ID]*Entity{ {{range .}}
|
||||||
|
{{.ID}}: &{{.CamelName}},{{end}}
|
||||||
|
}`
|
||||||
|
)
|
||||||
|
|
||||||
|
type Entity struct {
|
||||||
|
ID uint32 `json:"id"`
|
||||||
|
InternalID uint32 `json:"internalId"`
|
||||||
|
CamelName string `json:"-"`
|
||||||
|
DisplayName string `json:"displayName"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
Width float64 `json:"width"`
|
||||||
|
Height float64 `json:"height"`
|
||||||
|
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadInfo() ([]*Entity, error) {
|
||||||
|
resp, err := http.Get(infoURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var data []*Entity
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, d := range data {
|
||||||
|
d.CamelName = strcase.ToCamel(d.Name)
|
||||||
|
}
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:generate go run $GOFILE
|
||||||
|
//go:generate go fmt entity.go
|
||||||
|
func main() {
|
||||||
|
fmt.Println("generating entity.go")
|
||||||
|
entities, err := downloadInfo()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create("entity.go")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
if err := template.Must(template.New("").Parse(entityTmpl)).Execute(f, entities); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
@ -1,139 +1,26 @@
|
|||||||
// gen_blocks.go generates block information.
|
//+build generate
|
||||||
|
|
||||||
//+build ignore
|
|
||||||
|
|
||||||
|
// gen_item.go generates item information.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
|
||||||
"go/format"
|
|
||||||
"go/token"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"text/template"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/iancoleman/strcase"
|
"github.com/iancoleman/strcase"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
infoURL = "https://raw.githubusercontent.com/PrismarineJS/minecraft-data/master/data/pc/1.17/items.json"
|
version = "1.17"
|
||||||
)
|
infoURL = "https://raw.githubusercontent.com/PrismarineJS/minecraft-data/master/data/pc/" + version + "/items.json"
|
||||||
|
//language=gohtml
|
||||||
type Item struct {
|
itemTmpl = `// Code generated by gen_item.go DO NOT EDIT.
|
||||||
ID uint32 `json:"id"`
|
// Package item stores information about items in Minecraft.
|
||||||
DisplayName string `json:"displayName"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
StackSize uint `json:"stackSize"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func downloadInfo() ([]Item, error) {
|
|
||||||
resp, err := http.Get(infoURL)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var data []Item
|
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeItemDeclaration(blocks []Item) *ast.DeclStmt {
|
|
||||||
out := &ast.DeclStmt{Decl: &ast.GenDecl{Tok: token.VAR}}
|
|
||||||
|
|
||||||
for _, b := range blocks {
|
|
||||||
t := reflect.TypeOf(b)
|
|
||||||
fields := make([]ast.Expr, t.NumField())
|
|
||||||
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
|
||||||
ft := t.Field(i)
|
|
||||||
|
|
||||||
var val ast.Expr
|
|
||||||
switch ft.Type.Kind() {
|
|
||||||
case reflect.Uint32, reflect.Int, reflect.Uint:
|
|
||||||
val = &ast.BasicLit{Kind: token.INT, Value: fmt.Sprint(reflect.ValueOf(b).Field(i))}
|
|
||||||
case reflect.Float64:
|
|
||||||
val = &ast.BasicLit{Kind: token.FLOAT, Value: fmt.Sprint(reflect.ValueOf(b).Field(i))}
|
|
||||||
case reflect.String:
|
|
||||||
val = &ast.BasicLit{Kind: token.STRING, Value: strconv.Quote(reflect.ValueOf(b).Field(i).String())}
|
|
||||||
case reflect.Bool:
|
|
||||||
val = &ast.BasicLit{Kind: token.IDENT, Value: fmt.Sprint(reflect.ValueOf(b).Field(i).Bool())}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
val = &ast.CompositeLit{
|
|
||||||
Type: &ast.ArrayType{
|
|
||||||
Elt: &ast.BasicLit{Kind: token.IDENT, Value: ft.Type.Elem().Name()},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
v := reflect.ValueOf(b).Field(i)
|
|
||||||
switch ft.Type.Elem().Kind() {
|
|
||||||
case reflect.Uint32, reflect.Int:
|
|
||||||
for x := 0; x < v.Len(); x++ {
|
|
||||||
val.(*ast.CompositeLit).Elts = append(val.(*ast.CompositeLit).Elts, &ast.BasicLit{
|
|
||||||
Kind: token.INT,
|
|
||||||
Value: fmt.Sprint(v.Index(x)),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Map:
|
|
||||||
// Must be the NeedsTools map of type map[uint32]bool.
|
|
||||||
m := &ast.CompositeLit{
|
|
||||||
Type: &ast.MapType{
|
|
||||||
Key: &ast.BasicLit{Kind: token.IDENT, Value: ft.Type.Key().Name()},
|
|
||||||
Value: &ast.BasicLit{Kind: token.IDENT, Value: ft.Type.Elem().Name()},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
iter := reflect.ValueOf(b).Field(i).MapRange()
|
|
||||||
for iter.Next() {
|
|
||||||
m.Elts = append(m.Elts, &ast.KeyValueExpr{
|
|
||||||
Key: &ast.BasicLit{Kind: token.INT, Value: fmt.Sprint(iter.Key().Uint())},
|
|
||||||
Value: &ast.BasicLit{Kind: token.IDENT, Value: fmt.Sprint(iter.Value().Bool())},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
val = m
|
|
||||||
}
|
|
||||||
|
|
||||||
fields[i] = &ast.KeyValueExpr{
|
|
||||||
Key: &ast.Ident{Name: ft.Name},
|
|
||||||
Value: val,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out.Decl.(*ast.GenDecl).Specs = append(out.Decl.(*ast.GenDecl).Specs, &ast.ValueSpec{
|
|
||||||
Names: []*ast.Ident{{Name: strcase.ToCamel(b.Name)}},
|
|
||||||
Values: []ast.Expr{
|
|
||||||
&ast.CompositeLit{
|
|
||||||
Type: &ast.Ident{Name: reflect.TypeOf(b).Name()},
|
|
||||||
Elts: fields,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
items, err := downloadInfo()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(`// Package item stores information about items in Minecraft.
|
|
||||||
package item
|
package item
|
||||||
|
|
||||||
import (
|
|
||||||
"math"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ID describes the numeric ID of an item.
|
// ID describes the numeric ID of an item.
|
||||||
type ID uint32
|
type ID uint32
|
||||||
|
|
||||||
@ -145,24 +32,65 @@ type Item struct {
|
|||||||
StackSize uint
|
StackSize uint
|
||||||
}
|
}
|
||||||
|
|
||||||
`)
|
var (
|
||||||
format.Node(os.Stdout, token.NewFileSet(), makeItemDeclaration(items))
|
{{- range .}}
|
||||||
|
{{.CamelName}} = Item{
|
||||||
|
ID: {{.ID}},
|
||||||
|
DisplayName: "{{.DisplayName}}",
|
||||||
|
Name: "{{.Name}}",
|
||||||
|
StackSize: {{.StackSize}},
|
||||||
|
}{{end}}
|
||||||
|
)
|
||||||
|
|
||||||
fmt.Println()
|
// ByID is an index of minecraft items by their ID.
|
||||||
fmt.Println()
|
var ByID = map[ID]*Item{ {{range .}}
|
||||||
fmt.Println("// ByID is an index of minecraft items by their ID.")
|
{{.ID}}: &{{.CamelName}},{{end}}
|
||||||
fmt.Println("var ByID = map[ID]*Item{")
|
}`
|
||||||
for _, i := range items {
|
)
|
||||||
fmt.Printf(" %d: &%s,\n", i.ID, strcase.ToCamel(i.Name))
|
|
||||||
}
|
|
||||||
fmt.Println("}")
|
|
||||||
fmt.Println()
|
|
||||||
|
|
||||||
fmt.Println("// ByName is an index of minecraft items by their name.")
|
type Item struct {
|
||||||
fmt.Println("var ByName = map[string]*Item{")
|
ID uint32 `json:"id"`
|
||||||
for _, i := range items {
|
CamelName string `json:"-"`
|
||||||
fmt.Printf(" %q: &%s,\n", i.Name, strcase.ToCamel(i.Name))
|
DisplayName string `json:"displayName"`
|
||||||
}
|
Name string `json:"name"`
|
||||||
fmt.Println("}")
|
StackSize uint `json:"stackSize"`
|
||||||
fmt.Println()
|
}
|
||||||
|
|
||||||
|
func downloadInfo() ([]*Item, error) {
|
||||||
|
resp, err := http.Get(infoURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var data []*Item
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, d := range data {
|
||||||
|
d.CamelName = strcase.ToCamel(d.Name)
|
||||||
|
}
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:generate go run $GOFILE
|
||||||
|
//go:generate go fmt item.go
|
||||||
|
func main() {
|
||||||
|
fmt.Println("generating item.go")
|
||||||
|
items, err := downloadInfo()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create("item.go")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
if err := template.Must(template.New("").Parse(itemTmpl)).Execute(f, items); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
8800
data/item/item.go
8800
data/item/item.go
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,13 @@
|
|||||||
// This program can automatic download language.json file and convert into .go
|
//+build generate
|
||||||
|
|
||||||
|
// This program can automatically download language.json file and convert into .go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -15,9 +17,23 @@ import (
|
|||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//language=gohtml
|
||||||
|
langTmpl = `// Code generated by downloader.go; DO NOT EDIT.
|
||||||
|
package {{.Name}}
|
||||||
|
{{if ne .Name "en_us"}}
|
||||||
|
import "github.com/Tnze/go-mc/chat"
|
||||||
|
|
||||||
|
func init() { chat.SetLanguage(Map) }
|
||||||
|
{{end}}
|
||||||
|
var Map = {{.LangMap | printf "%#v"}}
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
//go:generate go run $GOFILE
|
//go:generate go run $GOFILE
|
||||||
//go:generate go fmt ./...
|
//go:generate go fmt ./...
|
||||||
func main() {
|
func main() {
|
||||||
|
fmt.Println("generating langs")
|
||||||
if len(os.Args) == 2 {
|
if len(os.Args) == 2 {
|
||||||
f, err := os.Open(os.Args[1])
|
f, err := os.Open(os.Args[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -27,17 +43,15 @@ func main() {
|
|||||||
readLang("en_us", f)
|
readLang("en_us", f)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Pseudo code for get versionURL:
|
|
||||||
// $manifest = {https://launchermeta.mojang.com/mc/game/version_manifest.json}
|
versionURL, err := assetIndexURL()
|
||||||
// $latest = $manifest.latest.release
|
if err != nil {
|
||||||
// $version = {$manifest.versions[where .id == $latest ].url}
|
panic(err)
|
||||||
// $versionURL = $version.assetIndex.url
|
}
|
||||||
versionURL := "https://launchermeta.mojang.com/v1/packages/e5af543d9b3ce1c063a97842c38e50e29f961f00/1.17.json"
|
|
||||||
log.Print("start generating lang packages")
|
|
||||||
|
|
||||||
resp, err := http.Get(versionURL)
|
resp, err := http.Get(versionURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
@ -50,7 +64,7 @@ func main() {
|
|||||||
|
|
||||||
err = json.NewDecoder(resp.Body).Decode(&list)
|
err = json.NewDecoder(resp.Body).Decode(&list)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks := make(chan string)
|
tasks := make(chan string)
|
||||||
@ -76,13 +90,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func lang(name, hash string) {
|
func lang(name, hash string) {
|
||||||
log.Print("generating ", name, " package")
|
|
||||||
|
|
||||||
//download language
|
//download language
|
||||||
LangURL := "http://resources.download.minecraft.net/" + hash[:2] + "/" + hash
|
LangURL := "http://resources.download.minecraft.net/" + hash[:2] + "/" + hash
|
||||||
resp, err := http.Get(LangURL)
|
resp, err := http.Get(LangURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
readLang(name, resp.Body)
|
readLang(name, resp.Body)
|
||||||
@ -93,7 +105,7 @@ func readLang(name string, r io.Reader) {
|
|||||||
var LangMap map[string]string
|
var LangMap map[string]string
|
||||||
err := json.NewDecoder(r).Decode(&LangMap)
|
err := json.NewDecoder(r).Decode(&LangMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("unmarshal json fail: ", err)
|
panic(err)
|
||||||
}
|
}
|
||||||
trans(LangMap)
|
trans(LangMap)
|
||||||
|
|
||||||
@ -102,12 +114,12 @@ func readLang(name string, r io.Reader) {
|
|||||||
// mkdir
|
// mkdir
|
||||||
err = os.Mkdir(pName, 0777)
|
err = os.Mkdir(pName, 0777)
|
||||||
if err != nil && !os.IsExist(err) {
|
if err != nil && !os.IsExist(err) {
|
||||||
log.Fatal(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.OpenFile(filepath.Join(pName, name+".go"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0666)
|
f, err := os.OpenFile(filepath.Join(pName, name+".go"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
@ -121,18 +133,9 @@ func readLang(name string, r io.Reader) {
|
|||||||
LangMap: LangMap,
|
LangMap: LangMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpl := template.Must(template.New("code_template").Parse(
|
tmpl := template.Must(template.New("").Parse(langTmpl))
|
||||||
`// Code generated by downloader.go; DO NOT EDIT.
|
|
||||||
package {{.Name}}
|
|
||||||
{{if ne .Name "en_us"}}
|
|
||||||
import "github.com/Tnze/go-mc/chat"
|
|
||||||
|
|
||||||
func init() { chat.SetLanguage(Map) }
|
|
||||||
{{end}}
|
|
||||||
var Map = {{.LangMap | printf "%#v"}}
|
|
||||||
`))
|
|
||||||
if err := tmpl.Execute(f, genData); err != nil {
|
if err := tmpl.Execute(f, genData); err != nil {
|
||||||
log.Fatal(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,10 +151,66 @@ func trans(m map[string]string) {
|
|||||||
var index int
|
var index int
|
||||||
_, err := fmt.Sscanf(s, "%%%d$s", &index)
|
_, err := fmt.Sscanf(s, "%%%d$s", &index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%%[%d]s", index)
|
return fmt.Sprintf("%%[%d]s", index)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func assetIndexURL() (string, error) {
|
||||||
|
// Pseudo code for get versionURL:
|
||||||
|
// $manifest = {https://launchermeta.mojang.com/mc/game/version_manifest.json}
|
||||||
|
// $latest = $manifest.latest.release
|
||||||
|
// $versionURL = {$manifest.versions[where .id == $latest ].url}
|
||||||
|
// $assetIndexURL = $version.assetIndex.url
|
||||||
|
var manifest struct {
|
||||||
|
Latest struct {
|
||||||
|
Release string `json:"release"`
|
||||||
|
} `json:"latest"`
|
||||||
|
Versions []struct{
|
||||||
|
ID string `json:"id"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"versions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
manifestRes, err := http.Get("https://launchermeta.mojang.com/mc/game/version_manifest.json")
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("could not reach version manifest: %w", err)
|
||||||
|
}
|
||||||
|
defer manifestRes.Body.Close()
|
||||||
|
|
||||||
|
if err := json.NewDecoder(manifestRes.Body).Decode(&manifest); err != nil {
|
||||||
|
return "", fmt.Errorf("could not decode manifest JSON: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var versionURL string
|
||||||
|
for _, v := range manifest.Versions {
|
||||||
|
if strings.EqualFold(manifest.Latest.Release, v.ID) {
|
||||||
|
versionURL = v.URL
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if versionURL == "" {
|
||||||
|
return "", errors.New("could not determine versionURL")
|
||||||
|
}
|
||||||
|
|
||||||
|
var version struct{
|
||||||
|
AssetIndex struct{
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"assetIndex"`
|
||||||
|
}
|
||||||
|
|
||||||
|
versionRes, err := http.Get(versionURL)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("could not reach versionURL: %w", err)
|
||||||
|
}
|
||||||
|
defer versionRes.Body.Close()
|
||||||
|
|
||||||
|
if err := json.NewDecoder(versionRes.Body).Decode(&version); err != nil {
|
||||||
|
return "", fmt.Errorf("could not decode version JSON: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return version.AssetIndex.URL, nil
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
// gen_packetIDs.go generates the enumeration of packet IDs used on the wire.
|
//+build generate
|
||||||
|
|
||||||
|
//gen_packetid.go generates the enumeration of packet IDs used on the wire.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -13,7 +15,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
protocolURL = "https://raw.githubusercontent.com/PrismarineJS/minecraft-data/master/data/pc/1.17.1/protocol.json"
|
version = "1.17.1"
|
||||||
|
protocolURL = "https://raw.githubusercontent.com/PrismarineJS/minecraft-data/master/data/pc/" + version + "/protocol.json"
|
||||||
|
//language=gohtml
|
||||||
packetidTmpl = `// This file is automatically generated by gen_packetIDs.go. DO NOT EDIT.
|
packetidTmpl = `// This file is automatically generated by gen_packetIDs.go. DO NOT EDIT.
|
||||||
|
|
||||||
package packetid
|
package packetid
|
||||||
@ -161,24 +165,22 @@ func downloadInfo() (*protocolIDs, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//go:generate go run $GOFILE
|
//go:generate go run $GOFILE
|
||||||
//go:generate go fmt ../packetid.go
|
//go:generate go fmt packetid.go
|
||||||
func main() {
|
func main() {
|
||||||
|
fmt.Println("generating packetid.go")
|
||||||
pIDs, err := downloadInfo()
|
pIDs, err := downloadInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
panic(err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.Create("../packetid.go")
|
f, err := os.Create("packetid.go")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
panic(err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
tmpl := template.Must(template.New("packetIDs").Parse(packetidTmpl))
|
tmpl := template.Must(template.New("packetIDs").Parse(packetidTmpl))
|
||||||
if err := tmpl.Execute(f, pIDs); err != nil {
|
if err := tmpl.Execute(f, pIDs); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
panic(err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,96 +0,0 @@
|
|||||||
//+build ignore
|
|
||||||
|
|
||||||
// gen_soundIDs.go generates the enumeration of sound IDs.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
protocolURL = "https://pokechu22.github.io/Burger/1.17.1.json"
|
|
||||||
)
|
|
||||||
|
|
||||||
type sound struct {
|
|
||||||
ID int64
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:generate go run $GOFILE
|
|
||||||
func main() {
|
|
||||||
sounds, err := downloadSoundInfo()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Create("soundid.go")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
fmt.Fprintln(f, "// Code generated by gen_soundIDs.go. DO NOT EDIT.")
|
|
||||||
fmt.Fprintln(f)
|
|
||||||
fmt.Fprintln(f, "package soundid")
|
|
||||||
fmt.Fprintln(f)
|
|
||||||
|
|
||||||
fmt.Fprintln(f, "// SoundID represents a sound ID used in the minecraft protocol.")
|
|
||||||
fmt.Fprintln(f, "type SoundID int32")
|
|
||||||
fmt.Fprintln(f)
|
|
||||||
fmt.Fprintln(f, "// SoundNames - map of ids to names for sounds.")
|
|
||||||
|
|
||||||
fmt.Fprintln(f, "var SoundNames map[SoundID]string = map[SoundID]string{")
|
|
||||||
for _, v := range sounds {
|
|
||||||
fmt.Fprintf(f, ` %d: "%s",`, v.ID, v.Name)
|
|
||||||
fmt.Fprintln(f)
|
|
||||||
}
|
|
||||||
fmt.Fprintln(f, "}")
|
|
||||||
fmt.Fprintln(f)
|
|
||||||
|
|
||||||
fmt.Fprintln(f, "// GetSoundNameByID helper method")
|
|
||||||
fmt.Fprintln(f, "func GetSoundNameByID(id SoundID) (string,bool) {")
|
|
||||||
fmt.Fprintln(f, " name, ok := SoundNames[id]")
|
|
||||||
fmt.Fprintln(f, " return name, ok")
|
|
||||||
fmt.Fprintln(f, "}")
|
|
||||||
}
|
|
||||||
|
|
||||||
func downloadSoundInfo() ([]sound, error) {
|
|
||||||
resp, err := http.Get(protocolURL)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
x := []map[string]interface{}{}
|
|
||||||
|
|
||||||
// if err := json.Unmarshal([]byte(data), &x); err != nil {
|
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&x); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
out := []sound{}
|
|
||||||
for i := range x {
|
|
||||||
if sounds, ok := x[i]["sounds"]; ok {
|
|
||||||
// fmt.Fprintf("sounds: %#v\n", sounds)
|
|
||||||
for _, value := range sounds.(map[string]interface{}) {
|
|
||||||
// fmt.Fprintf("%d: %s\n", int64(value.(map[string]interface{})["id"].(float64)), value.(map[string]interface{})["name"])
|
|
||||||
out = append(out, sound{ID: int64(value.(map[string]interface{})["id"].(float64)), Name: value.(map[string]interface{})["name"].(string)})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// fmt.Fprintf("NO SOUNDS FOUND IN DATA!")
|
|
||||||
return nil, fmt.Errorf("No sounds found in data from %s", protocolURL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.SliceStable(out, func(i, j int) bool {
|
|
||||||
return out[i].ID < out[j].ID
|
|
||||||
})
|
|
||||||
|
|
||||||
return out, nil
|
|
||||||
}
|
|
96
data/soundid/gen_soundid.go
Normal file
96
data/soundid/gen_soundid.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
//+build generate
|
||||||
|
|
||||||
|
// gen_soundid.go generates the enumeration of sound IDs.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"sort"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
version = "1.17.1"
|
||||||
|
protocolURL = "https://pokechu22.github.io/Burger/" + version + ".json"
|
||||||
|
//language=gohtml
|
||||||
|
soundTmpl = `// Code generated by gen_soundid.go. DO NOT EDIT.
|
||||||
|
|
||||||
|
package soundid
|
||||||
|
|
||||||
|
// SoundID represents a sound ID used in the minecraft protocol.
|
||||||
|
type SoundID int32
|
||||||
|
|
||||||
|
// SoundNames - map of ids to names for sounds.
|
||||||
|
var SoundNames = map[SoundID]string{ {{range .}}
|
||||||
|
{{.ID}}: "{{.Name}}",{{end}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSoundNameByID helper method
|
||||||
|
func GetSoundNameByID(id SoundID) (string, bool) {
|
||||||
|
name, ok := SoundNames[id]
|
||||||
|
return name, ok
|
||||||
|
}`
|
||||||
|
)
|
||||||
|
|
||||||
|
type Sound struct {
|
||||||
|
ID int64
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:generate go run $GOFILE
|
||||||
|
func main() {
|
||||||
|
fmt.Println("generating soundid.go")
|
||||||
|
sounds, err := downloadSoundInfo()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create("soundid.go")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
if err := template.Must(template.New("").Parse(soundTmpl)).Execute(f, sounds); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadSoundInfo() ([]*Sound, error) {
|
||||||
|
resp, err := http.Get(protocolURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// I'm not sure why the response returns a list, it appears to ever only have a single object...
|
||||||
|
var data []struct {
|
||||||
|
Sounds map[string]Sound `json:"sounds"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
out := make([]*Sound, 0)
|
||||||
|
for _, d := range data {
|
||||||
|
if has := len(d.Sounds); has > 0 {
|
||||||
|
for _, val := range d.Sounds {
|
||||||
|
out = append(out, &Sound{ID: val.ID, Name: val.Name})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("no sounds found in data from %s", protocolURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.SliceStable(out, func(i, j int) bool {
|
||||||
|
return out[i].ID < out[j].ID
|
||||||
|
})
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// Code generated by gen_soundIDs.go. DO NOT EDIT.
|
// Code generated by gen_soundid.go. DO NOT EDIT.
|
||||||
|
|
||||||
package soundid
|
package soundid
|
||||||
|
|
||||||
@ -6,7 +6,7 @@ package soundid
|
|||||||
type SoundID int32
|
type SoundID int32
|
||||||
|
|
||||||
// SoundNames - map of ids to names for sounds.
|
// SoundNames - map of ids to names for sounds.
|
||||||
var SoundNames map[SoundID]string = map[SoundID]string{
|
var SoundNames = map[SoundID]string{
|
||||||
0: "ambient.cave",
|
0: "ambient.cave",
|
||||||
1: "ambient.basalt_deltas.additions",
|
1: "ambient.basalt_deltas.additions",
|
||||||
2: "ambient.basalt_deltas.loop",
|
2: "ambient.basalt_deltas.loop",
|
||||||
|
Reference in New Issue
Block a user