frameworkServer works perfect now
This commit is contained in:
@ -5,6 +5,7 @@ import (
|
||||
"compress/zlib"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"math/bits"
|
||||
|
||||
"github.com/Tnze/go-mc/nbt"
|
||||
)
|
||||
@ -17,21 +18,20 @@ type Block interface {
|
||||
//go:embed block_states.nbt
|
||||
var blockStates []byte
|
||||
|
||||
var toStateID = make(map[Block]int)
|
||||
var toStateID map[Block]int
|
||||
var fromStateID []Block
|
||||
|
||||
// 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
|
||||
|
||||
type State struct {
|
||||
Name string
|
||||
Properties nbt.RawMessage
|
||||
}
|
||||
|
||||
func init() {
|
||||
regState := func(s Block) {
|
||||
if _, ok := toStateID[s]; ok {
|
||||
panic(fmt.Errorf("state %#v already exist", s))
|
||||
}
|
||||
toStateID[s] = len(fromStateID)
|
||||
fromStateID = append(fromStateID, s)
|
||||
}
|
||||
var states []struct {
|
||||
Name string
|
||||
Properties nbt.RawMessage
|
||||
}
|
||||
var states []State
|
||||
// decompress
|
||||
z, err := zlib.NewReader(bytes.NewReader(blockStates))
|
||||
if err != nil {
|
||||
@ -41,6 +41,8 @@ func init() {
|
||||
if _, err = nbt.NewDecoder(z).Decode(&states); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
toStateID = make(map[Block]int, len(states))
|
||||
fromStateID = make([]Block, 0, len(states))
|
||||
for _, state := range states {
|
||||
block := fromID[state.Name]
|
||||
if state.Properties.Type != nbt.TagEnd {
|
||||
@ -49,14 +51,29 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
regState(block)
|
||||
if _, ok := toStateID[block]; ok {
|
||||
panic(fmt.Errorf("state %#v already exist", block))
|
||||
}
|
||||
toStateID[block] = len(fromStateID)
|
||||
fromStateID = append(fromStateID, block)
|
||||
}
|
||||
BitsPerBlock = bits.Len(uint(len(fromStateID)))
|
||||
}
|
||||
|
||||
func FromStateID(stateID int) Block {
|
||||
return fromStateID[stateID]
|
||||
func FromStateID(stateID int) (b Block, ok bool) {
|
||||
if stateID >= 0 && stateID < len(fromStateID) {
|
||||
b = fromStateID[stateID]
|
||||
ok = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ToStateID(b Block) int {
|
||||
return toStateID[b]
|
||||
func DefaultBlock(id string) (b Block, ok bool) {
|
||||
b, ok = fromID[id]
|
||||
return
|
||||
}
|
||||
|
||||
func ToStateID(b Block) (i int, ok bool) {
|
||||
i, ok = toStateID[b]
|
||||
return
|
||||
}
|
||||
|
@ -2,13 +2,14 @@ package level
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/bits"
|
||||
"strings"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Tnze/go-mc/data/block"
|
||||
"github.com/Tnze/go-mc/level/block"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
"github.com/Tnze/go-mc/save"
|
||||
)
|
||||
@ -113,11 +114,18 @@ func ChunkFromSave(c *save.Chunk, secs int) *Chunk {
|
||||
statePalette := v.BlockStates.Palette
|
||||
stateRawPalette := make([]int, len(statePalette))
|
||||
for i, v := range statePalette {
|
||||
// TODO: Consider the properties of block, not only index the block name
|
||||
stateRawPalette[i] = int(stateIDs[strings.TrimPrefix(v.Name, "minecraft:")])
|
||||
if v.Name != "minecraft:air" {
|
||||
b := v.Block()
|
||||
if b == nil {
|
||||
panic(fmt.Errorf("block not found: %#v", v))
|
||||
}
|
||||
if !isAir(b) {
|
||||
blockCount++
|
||||
}
|
||||
var ok bool
|
||||
stateRawPalette[i], ok = block.ToStateID(b)
|
||||
if !ok {
|
||||
panic(fmt.Errorf("state id not found: %#v", b))
|
||||
}
|
||||
}
|
||||
|
||||
biomesData := *(*[]uint64)((unsafe.Pointer)(&v.Biomes.Data))
|
||||
@ -153,18 +161,6 @@ func ChunkFromSave(c *save.Chunk, secs int) *Chunk {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This map should be moved to data/block.
|
||||
var stateIDs = make(map[string]uint32)
|
||||
|
||||
func init() {
|
||||
for i, v := range block.StateID {
|
||||
name := block.ByID[v].Name
|
||||
if _, ok := stateIDs[name]; !ok {
|
||||
stateIDs[name] = i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Chunk) WriteTo(w io.Writer) (int64, error) {
|
||||
data, err := c.Data()
|
||||
if err != nil {
|
||||
@ -211,8 +207,8 @@ func (s *Section) GetBlock(i int) int {
|
||||
return s.States.Get(i)
|
||||
}
|
||||
func (s *Section) SetBlock(i int, v int) {
|
||||
// TODO: Handle cave air and void air
|
||||
if s.States.Get(i) != 0 {
|
||||
b, _ := block.FromStateID(s.States.Get(i))
|
||||
if isAir(b) {
|
||||
s.blockCount--
|
||||
}
|
||||
if v != 0 {
|
||||
@ -263,3 +259,12 @@ func (l *lightData) WriteTo(w io.Writer) (int64, error) {
|
||||
pk.Array(l.BlockLight),
|
||||
}.WriteTo(w)
|
||||
}
|
||||
|
||||
func isAir(b block.Block) bool {
|
||||
switch b.(type) {
|
||||
case block.Air, block.CaveAir, block.VoidAir:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user