Add support for dimension ranges and network hashes
This commit is contained in:
@@ -21,6 +21,8 @@ type Block interface {
|
||||
DowngradeBlockActorData(map[string]any)
|
||||
// UpgradeBlockActorData upgrades the input sub chunk to the latest block actor.
|
||||
UpgradeBlockActorData(map[string]any)
|
||||
HashToRuntimeID(hash uint32) (rid uint32, ok bool)
|
||||
RuntimeIDToHash(rid uint32) (hash uint32, ok bool)
|
||||
// Adjust adjusts the latest mappings to account for custom states.
|
||||
Adjust([]protocol.BlockEntry)
|
||||
Air() uint32
|
||||
@@ -41,6 +43,9 @@ type DefaultBlockMapping struct {
|
||||
|
||||
// infoUpdateRID is the runtime ID of the info_update block in the latest version of the game.
|
||||
infoUpdateBlockRID uint32
|
||||
|
||||
networkhashToRids map[uint32]uint32
|
||||
ridsToNetworkhash map[uint32]uint32
|
||||
}
|
||||
|
||||
func NewBlockMapping(raw []byte) *DefaultBlockMapping {
|
||||
@@ -51,6 +56,8 @@ func NewBlockMapping(raw []byte) *DefaultBlockMapping {
|
||||
runtimeIDToState := make(map[uint32]blockupgrader.BlockState)
|
||||
var airRID *uint32
|
||||
var infoUpdateBlockRID *uint32
|
||||
networkhashToRids := make(map[uint32]uint32)
|
||||
ridsToNetworkhash := make(map[uint32]uint32)
|
||||
|
||||
var s blockupgrader.BlockState
|
||||
for {
|
||||
@@ -67,8 +74,11 @@ func NewBlockMapping(raw []byte) *DefaultBlockMapping {
|
||||
infoUpdateBlockRID = &rid
|
||||
}
|
||||
|
||||
stateRuntimeIDs[internal.HashState(blockupgrader.Upgrade(s))] = rid
|
||||
upgradedStates := blockupgrader.Upgrade(s)
|
||||
stateRuntimeIDs[internal.HashState(upgradedStates)] = rid
|
||||
runtimeIDToState[rid] = s
|
||||
networkhashToRids[networkBlockHash(upgradedStates.Name, upgradedStates.Properties)] = rid
|
||||
ridsToNetworkhash[rid] = networkBlockHash(s.Name, s.Properties)
|
||||
}
|
||||
if airRID == nil {
|
||||
panic("couldn't find air")
|
||||
@@ -83,6 +93,8 @@ func NewBlockMapping(raw []byte) *DefaultBlockMapping {
|
||||
runtimeIDToState: runtimeIDToState,
|
||||
airRID: *airRID,
|
||||
infoUpdateBlockRID: *infoUpdateBlockRID,
|
||||
networkhashToRids: networkhashToRids,
|
||||
ridsToNetworkhash: ridsToNetworkhash,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +126,16 @@ func (m *DefaultBlockMapping) UpgradeBlockActorData(actorData map[string]any) {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *DefaultBlockMapping) RuntimeIDToHash(rid uint32) (uint32, bool) {
|
||||
hash, found := m.ridsToNetworkhash[rid]
|
||||
return hash, found
|
||||
}
|
||||
|
||||
func (m *DefaultBlockMapping) HashToRuntimeID(hash uint32) (uint32, bool) {
|
||||
rid, found := m.networkhashToRids[hash]
|
||||
return rid, found
|
||||
}
|
||||
|
||||
func (m *DefaultBlockMapping) Adjust(entries []protocol.BlockEntry) {
|
||||
if len(entries) == 0 {
|
||||
return
|
||||
|
||||
97
mapping/network_block_hash.go
Normal file
97
mapping/network_block_hash.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package mapping
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"hash/fnv"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var bufNetworkhash []byte = make([]byte, 0xff)
|
||||
|
||||
func networkBlockHash(name string, properties map[string]any) uint32 {
|
||||
if name == "minecraft:unknown" {
|
||||
return 0xfffffffe // -2
|
||||
}
|
||||
|
||||
keys := make([]string, 0, len(properties))
|
||||
for k := range properties {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
bufNetworkhash = bufNetworkhash[:0]
|
||||
var data = bufNetworkhash
|
||||
writeString := func(str string) {
|
||||
data = binary.LittleEndian.AppendUint16(data, uint16(len(str)))
|
||||
data = append(data, []byte(str)...)
|
||||
}
|
||||
|
||||
data = append(data, 10) // compound
|
||||
data = append(data, 0)
|
||||
data = append(data, 0)
|
||||
|
||||
data = append(data, 8) // string
|
||||
writeString("name")
|
||||
writeString(name)
|
||||
|
||||
data = append(data, 10) // compound
|
||||
writeString("states")
|
||||
for _, k := range keys {
|
||||
v := properties[k]
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
data = append(data, 8) // string
|
||||
writeString(k)
|
||||
writeString(v)
|
||||
|
||||
case uint8:
|
||||
data = append(data, 1) // tagByte
|
||||
writeString(k)
|
||||
data = append(data, byte(v))
|
||||
case int8:
|
||||
data = append(data, 1) // tagByte
|
||||
writeString(k)
|
||||
data = append(data, byte(v))
|
||||
case bool:
|
||||
b := 0
|
||||
if v {
|
||||
b = 1
|
||||
}
|
||||
data = append(data, 1) // tagByte
|
||||
writeString(k)
|
||||
data = append(data, byte(b))
|
||||
|
||||
case uint16:
|
||||
data = append(data, 2) // tagInt16
|
||||
writeString(k)
|
||||
data = binary.LittleEndian.AppendUint16(data, uint16(v))
|
||||
case int16:
|
||||
data = append(data, 2) // tagInt16
|
||||
writeString(k)
|
||||
data = binary.LittleEndian.AppendUint16(data, uint16(v))
|
||||
|
||||
case uint32:
|
||||
data = append(data, 3) // tagInt32
|
||||
writeString(k)
|
||||
data = binary.LittleEndian.AppendUint32(data, uint32(v))
|
||||
case int32:
|
||||
data = append(data, 3) // tagInt32
|
||||
writeString(k)
|
||||
data = binary.LittleEndian.AppendUint32(data, uint32(v))
|
||||
default:
|
||||
panic("unhandled nbt type")
|
||||
}
|
||||
}
|
||||
data = append(data, 0) // end
|
||||
data = append(data, 0) // end
|
||||
|
||||
h := fnv.New32a()
|
||||
h.Write(data)
|
||||
return h.Sum32()
|
||||
}
|
||||
|
||||
func splitNamespace(identifier string) (ns, name string) {
|
||||
ns_name := strings.Split(identifier, ":")
|
||||
return ns_name[0], ns_name[len(ns_name)-1]
|
||||
}
|
||||
Reference in New Issue
Block a user