111 lines
2.9 KiB
Go
111 lines
2.9 KiB
Go
package item
|
|
|
|
import (
|
|
"bytes"
|
|
"embed"
|
|
"encoding/json"
|
|
"github.com/df-mc/worldupgrader/blockupgrader"
|
|
"github.com/sandertv/gophertunnel/minecraft/nbt"
|
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
|
"regexp"
|
|
"sort"
|
|
"strconv"
|
|
)
|
|
|
|
var (
|
|
//go:embed schemas/*.json
|
|
schemasFS embed.FS
|
|
//go:embed 1.12.0_item_id_to_block_id_map.json
|
|
rawItemToBlockIdMap []byte
|
|
//go:embed 1.12.0_to_1.18.10_blockstate_map.bin
|
|
rawblockStateMap []byte
|
|
// schemaIDs is a list of ids from all registered schemas.
|
|
schemaIDs []int
|
|
// schemas is a map of all registered item upgrade schemas.
|
|
schemas map[uint16]schema
|
|
// itemToBlockIdMap is a list of all registered item upgrade schemas.
|
|
itemToBlockIdMap map[string]string
|
|
// blockStateMap is a list of all legacy block states mapped to an upgraded version of it.
|
|
blockStateMap map[stateHash]blockupgrader.BlockState
|
|
|
|
filenameRegex = regexp.MustCompile(`(\d{4})_[\w.]+\.json`)
|
|
)
|
|
|
|
// stateHash is a struct that may be used as a map key for block states.
|
|
type stateHash struct {
|
|
// Name is the name of the block. It looks like 'minecraft:stone'.
|
|
Name string
|
|
// Metadata is the metadata value of the block. A lot of blocks only have 0 as data value, but some blocks
|
|
// carry specific variants or properties encoded in the metadata.
|
|
Metadata uint32
|
|
}
|
|
|
|
// init ...
|
|
func init() {
|
|
schemas = make(map[uint16]schema)
|
|
files, err := schemasFS.ReadDir("schemas")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
for _, f := range files {
|
|
if f.IsDir() {
|
|
continue
|
|
}
|
|
subMatches := filenameRegex.FindStringSubmatch(f.Name())
|
|
if subMatches == nil {
|
|
continue
|
|
}
|
|
id, err := strconv.Atoi(subMatches[1])
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
buf, err := schemasFS.ReadFile("schemas/" + f.Name())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
var s schema
|
|
if err = json.Unmarshal(buf, &s); err != nil {
|
|
panic(err)
|
|
}
|
|
schemas[uint16(id)] = s
|
|
}
|
|
schemaIDs = make([]int, 0, len(schemas))
|
|
for k := range schemas {
|
|
schemaIDs = append(schemaIDs, int(k))
|
|
}
|
|
sort.Sort(sort.Reverse(sort.IntSlice(schemaIDs)))
|
|
|
|
if err = json.Unmarshal(rawItemToBlockIdMap, &itemToBlockIdMap); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
blockStateMap = make(map[stateHash]blockupgrader.BlockState)
|
|
buf := protocol.NewReader(bytes.NewBuffer(rawblockStateMap), 0, false)
|
|
var length uint32
|
|
buf.Varuint32(&length)
|
|
for i := uint32(0); i < length; i++ {
|
|
var legacyStringId string
|
|
buf.String(&legacyStringId)
|
|
|
|
var pairs uint32
|
|
buf.Varuint32(&pairs)
|
|
for y := uint32(0); y < pairs; y++ {
|
|
var meta uint32
|
|
buf.Varuint32(&meta)
|
|
|
|
var blockStateRaw map[string]any
|
|
buf.NBT(&blockStateRaw, nbt.LittleEndian)
|
|
latestBlockState := blockupgrader.Upgrade(blockupgrader.BlockState{
|
|
Name: blockStateRaw["name"].(string),
|
|
Properties: blockStateRaw["states"].(map[string]any),
|
|
Version: blockStateRaw["version"].(int32),
|
|
})
|
|
blockStateMap[stateHash{
|
|
Name: legacyStringId,
|
|
Metadata: meta,
|
|
}] = latestBlockState
|
|
}
|
|
}
|
|
}
|