178 lines
5.1 KiB
Go
178 lines
5.1 KiB
Go
package mapping
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"github.com/sandertv/gophertunnel/minecraft/nbt"
|
|
"sync"
|
|
)
|
|
|
|
type Item interface {
|
|
// ItemRuntimeIDToName converts an item runtime ID to a string ID.
|
|
ItemRuntimeIDToName(int32) (string, bool)
|
|
// ItemNameToRuntimeID converts a string ID to an item runtime ID.
|
|
ItemNameToRuntimeID(string) (int32, bool)
|
|
// ItemRuntimeIDToVersion converts an item runtime ID to its version.
|
|
ItemRuntimeIDToVersion(int32) (uint8, bool)
|
|
// ItemRuntimeIDToData converts an item runtime ID to its data.
|
|
ItemRuntimeIDToData(int32) (map[string]any, bool)
|
|
RegisterEntry(string) int32
|
|
RegisterEntryRID(string, int32, uint8, map[string]any)
|
|
Air() int32
|
|
ItemVersion() uint16
|
|
ItemEntries() []ItemEntry
|
|
}
|
|
|
|
type ItemEntry struct {
|
|
Name string
|
|
RuntimeID int16
|
|
ComponentBased bool
|
|
Version uint8
|
|
Data map[string]any
|
|
}
|
|
|
|
type DefaultItemMapping struct {
|
|
mu sync.Mutex
|
|
// itemRuntimeIDsToNames holds a map to translate item runtime IDs to string IDs.
|
|
itemRuntimeIDsToNames map[int32]string
|
|
// itemNamesToRuntimeIDs holds a map to translate item string IDs to runtime IDs.
|
|
itemNamesToRuntimeIDs map[string]int32
|
|
// itemRuntimeIDToVersion holds a map to translate item runtime IDs to versions.
|
|
itemRuntimeIDToVersion map[int32]uint8
|
|
// itemRuntimeIDToData holds a map to translate item runtime IDs to data.
|
|
itemRuntimeIDToData map[int32]map[string]any
|
|
// itemEntries holds a map to translate item string IDs to runtime IDs.
|
|
itemEntries []ItemEntry
|
|
airRID int32
|
|
itemVersion uint16
|
|
}
|
|
|
|
func NewItemMapping(requiredItemList []byte, itemVersion uint16) *DefaultItemMapping {
|
|
itemRuntimeIDsToNames := make(map[int32]string)
|
|
itemNamesToRuntimeIDs := make(map[string]int32)
|
|
itemRuntimeIDToVersion := make(map[int32]uint8)
|
|
itemRuntimeIDToData := make(map[int32]map[string]any)
|
|
itemEntries := make([]ItemEntry, 0, 1600)
|
|
var airRID *int32
|
|
|
|
var m map[string]struct {
|
|
RuntimeID int16 `json:"runtime_id"`
|
|
ComponentBased bool `json:"component_based"`
|
|
Version *uint8 `json:"version"`
|
|
Data string `json:"component_nbt,omitempty"`
|
|
}
|
|
if err := json.Unmarshal(requiredItemList, &m); err != nil {
|
|
panic(err)
|
|
}
|
|
for name, data := range m {
|
|
rid := int32(data.RuntimeID)
|
|
if name == "minecraft:air" {
|
|
airRID = &rid
|
|
}
|
|
|
|
entry := ItemEntry{
|
|
Name: name,
|
|
RuntimeID: data.RuntimeID,
|
|
ComponentBased: data.ComponentBased,
|
|
}
|
|
itemNamesToRuntimeIDs[name] = rid
|
|
itemRuntimeIDsToNames[rid] = name
|
|
if data.Version != nil {
|
|
itemRuntimeIDToVersion[rid] = *data.Version
|
|
entry.Version = *data.Version
|
|
}
|
|
if data.Data != "" {
|
|
var nbtData map[string]any
|
|
nbtBytes, err := base64.StdEncoding.DecodeString(data.Data)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if err := nbt.Unmarshal(nbtBytes, &nbtData); err != nil {
|
|
panic(err)
|
|
}
|
|
itemRuntimeIDToData[rid] = nbtData
|
|
entry.Data = nbtData
|
|
}
|
|
itemEntries = append(itemEntries, entry)
|
|
}
|
|
|
|
if airRID == nil {
|
|
panic("couldn't find air")
|
|
}
|
|
|
|
return &DefaultItemMapping{itemRuntimeIDsToNames: itemRuntimeIDsToNames, itemNamesToRuntimeIDs: itemNamesToRuntimeIDs, itemRuntimeIDToVersion: itemRuntimeIDToVersion, airRID: *airRID, itemVersion: itemVersion, itemRuntimeIDToData: itemRuntimeIDToData, itemEntries: itemEntries}
|
|
}
|
|
|
|
func (m *DefaultItemMapping) ItemRuntimeIDToName(runtimeID int32) (name string, found bool) {
|
|
defer m.mu.Unlock()
|
|
m.mu.Lock()
|
|
name, ok := m.itemRuntimeIDsToNames[runtimeID]
|
|
return name, ok
|
|
}
|
|
|
|
func (m *DefaultItemMapping) ItemNameToRuntimeID(name string) (runtimeID int32, found bool) {
|
|
defer m.mu.Unlock()
|
|
m.mu.Lock()
|
|
rid, ok := m.itemNamesToRuntimeIDs[name]
|
|
return rid, ok
|
|
}
|
|
|
|
func (m *DefaultItemMapping) ItemRuntimeIDToVersion(runtimeID int32) (version uint8, found bool) {
|
|
defer m.mu.Unlock()
|
|
m.mu.Lock()
|
|
v, ok := m.itemRuntimeIDToVersion[runtimeID]
|
|
return v, ok
|
|
}
|
|
|
|
func (m *DefaultItemMapping) ItemRuntimeIDToData(runtimeID int32) (data map[string]any, found bool) {
|
|
defer m.mu.Unlock()
|
|
m.mu.Lock()
|
|
d, ok := m.itemRuntimeIDToData[runtimeID]
|
|
return d, ok
|
|
}
|
|
|
|
func (m *DefaultItemMapping) RegisterEntry(name string) int32 {
|
|
defer m.mu.Unlock()
|
|
m.mu.Lock()
|
|
if rid, ok := m.itemNamesToRuntimeIDs[name]; ok {
|
|
return rid
|
|
}
|
|
nextRID := int32(len(m.itemRuntimeIDsToNames))
|
|
m.itemNamesToRuntimeIDs[name] = nextRID
|
|
m.itemRuntimeIDsToNames[nextRID] = name
|
|
return nextRID
|
|
}
|
|
|
|
func (m *DefaultItemMapping) RegisterEntryRID(name string, rid int32, version uint8, data map[string]any) {
|
|
defer m.mu.Unlock()
|
|
m.mu.Lock()
|
|
if _, ok := m.itemNamesToRuntimeIDs[name]; !ok {
|
|
m.itemNamesToRuntimeIDs[name] = rid
|
|
m.itemRuntimeIDsToNames[rid] = name
|
|
m.itemRuntimeIDToVersion[rid] = version
|
|
if data != nil {
|
|
m.itemRuntimeIDToData[rid] = data
|
|
}
|
|
}
|
|
}
|
|
|
|
func (m *DefaultItemMapping) Air() int32 {
|
|
defer m.mu.Unlock()
|
|
m.mu.Lock()
|
|
return m.airRID
|
|
}
|
|
|
|
func (m *DefaultItemMapping) ItemVersion() uint16 {
|
|
defer m.mu.Unlock()
|
|
m.mu.Lock()
|
|
return m.itemVersion
|
|
}
|
|
|
|
func (m *DefaultItemMapping) ItemEntries() []ItemEntry {
|
|
defer m.mu.Unlock()
|
|
m.mu.Lock()
|
|
entries := make([]ItemEntry, len(m.itemEntries))
|
|
copy(entries, m.itemEntries)
|
|
return entries
|
|
}
|