179 lines
3.1 KiB
Go
179 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/zlib"
|
|
"encoding/binary"
|
|
"io"
|
|
"sync"
|
|
)
|
|
|
|
var nodedef []byte
|
|
|
|
const (
|
|
ContentUnknown = 125
|
|
ContentAir = 126
|
|
ContentIgnore = 127
|
|
)
|
|
|
|
type NodeDef struct {
|
|
id uint16
|
|
name string
|
|
data []byte
|
|
}
|
|
|
|
var nodeDefsMu sync.RWMutex
|
|
var nodeDefs map[string]map[uint16]*NodeDef
|
|
|
|
// NodeDefByName returns the NodeDef that has the specified name on a
|
|
// minetest server
|
|
func NodeDefByName(srv, name string) *NodeDef {
|
|
for _, def := range nodeDefs[srv] {
|
|
if def.Name() == name {
|
|
return def
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ID returns the content ID of a NodeDef
|
|
func (n *NodeDef) ID() uint16 {
|
|
if n == nil {
|
|
return ContentUnknown
|
|
}
|
|
return n.id
|
|
}
|
|
|
|
// Name returns the name of a NodeDef
|
|
func (n *NodeDef) Name() string {
|
|
if n == nil {
|
|
return ""
|
|
}
|
|
return n.name
|
|
}
|
|
|
|
// Data returns the actual definition
|
|
func (n *NodeDef) Data() []byte {
|
|
if n == nil {
|
|
return []byte{}
|
|
}
|
|
return n.data
|
|
}
|
|
|
|
// NodeDefs returns all node definitions
|
|
func NodeDefs() map[string]map[uint16]*NodeDef {
|
|
nodeDefsMu.RLock()
|
|
defer nodeDefsMu.RUnlock()
|
|
|
|
return nodeDefs
|
|
}
|
|
|
|
func mergeNodedefs(mgrs map[string][]byte) error {
|
|
var total uint16
|
|
|
|
nodeDefsMu.Lock()
|
|
defer nodeDefsMu.Unlock()
|
|
|
|
if nodeDefs == nil {
|
|
nodeDefs = make(map[string]map[uint16]*NodeDef)
|
|
}
|
|
|
|
var nextID uint16
|
|
|
|
// Extract definitions from NodeDefManagers
|
|
for srv, compressedMgr := range mgrs {
|
|
if nodeDefs[srv] == nil {
|
|
nodeDefs[srv] = make(map[uint16]*NodeDef)
|
|
}
|
|
|
|
zr, err := zlib.NewReader(bytes.NewReader(compressedMgr))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
buf := &bytes.Buffer{}
|
|
_, err = io.Copy(buf, zr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
zr.Close()
|
|
|
|
r := bytes.NewReader(buf.Bytes())
|
|
r.Seek(1, io.SeekStart)
|
|
|
|
count := ReadUint16(r)
|
|
r.Seek(4, io.SeekCurrent)
|
|
|
|
NodeLoop:
|
|
for i := uint16(0); i < count; i++ {
|
|
id := ReadUint16(r)
|
|
defb := ReadBytes16(r)
|
|
|
|
dr := bytes.NewReader(defb)
|
|
dr.Seek(1, io.SeekStart)
|
|
|
|
nodeName := string(ReadBytes16(dr))
|
|
|
|
for _, srvdefs := range nodeDefs {
|
|
for _, def := range srvdefs {
|
|
if def.Name() == nodeName {
|
|
nodeDefs[srv][id] = &NodeDef{id: def.ID()}
|
|
continue NodeLoop
|
|
}
|
|
}
|
|
}
|
|
|
|
if def := NodeDefByName(srv, nodeName); def != nil {
|
|
nodeDefs[srv][id] = &NodeDef{
|
|
id: def.ID(),
|
|
name: nodeName,
|
|
data: defb,
|
|
}
|
|
}
|
|
|
|
nodeDefs[srv][id] = &NodeDef{
|
|
id: nextID,
|
|
name: nodeName,
|
|
data: defb,
|
|
}
|
|
|
|
total++
|
|
|
|
nextID++
|
|
if nextID == ContentUnknown {
|
|
nextID = ContentIgnore + 1
|
|
}
|
|
}
|
|
}
|
|
|
|
// Merge definitions into new NodeDefManager
|
|
mgr := &bytes.Buffer{}
|
|
mgr.WriteByte(1)
|
|
WriteUint16(mgr, total)
|
|
|
|
var allDefs []byte
|
|
for _, srvdefs := range nodeDefs {
|
|
for _, def := range srvdefs {
|
|
if len(def.Data()) > 0 {
|
|
defData := make([]byte, 4+len(def.Data()))
|
|
binary.BigEndian.PutUint16(defData[0:2], def.ID())
|
|
binary.BigEndian.PutUint16(defData[2:4], uint16(len(def.Data())))
|
|
copy(defData[4:], def.Data())
|
|
allDefs = append(allDefs, defData...)
|
|
}
|
|
}
|
|
}
|
|
|
|
WriteBytes32(mgr, allDefs)
|
|
|
|
var compressedMgr bytes.Buffer
|
|
zw := zlib.NewWriter(&compressedMgr)
|
|
zw.Write(mgr.Bytes())
|
|
zw.Close()
|
|
|
|
nodedef = compressedMgr.Bytes()
|
|
|
|
return nil
|
|
}
|