Files
go-mc/server/dimension.go
2021-12-17 18:45:06 +08:00

105 lines
2.0 KiB
Go

package server
import (
"bytes"
"github.com/Tnze/go-mc/data/packetid"
pk "github.com/Tnze/go-mc/net/packet"
"github.com/Tnze/go-mc/save"
"io"
"sync"
)
type Dimension interface {
Info() DimInfo
PlayerJoin(p *Player)
PlayerQuit(p *Player)
}
type DimInfo struct {
Name string
HashedSeed uint64
}
type SimpleDim struct {
Columns map[struct{ X, Z int }]*struct {
sync.Mutex
}
}
type chunkData struct {
HeightMaps save.BitStorage
BlockState save.BitStorage
Biomes save.BitStorage
}
func (c *chunkData) WriteTo(w io.Writer) (int64, error) {
return pk.Tuple{
// Heightmaps
pk.NBT(struct {
MotionBlocking []uint64 `nbt:"MOTION_BLOCKING"`
}{c.HeightMaps.Longs()}),
pk.ByteArray(c.Data()), // TODO: Chunk Data
pk.VarInt(0), // TODO: Block Entity
}.WriteTo(w)
}
func (c *chunkData) Data() []byte {
var buff bytes.Buffer
_, _ = pk.Short(0).WriteTo(&buff)
return buff.Bytes()
}
type lightData struct {
SkyLightMask pk.BitSet
BlockLightMask pk.BitSet
SkyLight []pk.ByteArray
BlockLight []pk.ByteArray
}
func bitSetRev(set pk.BitSet) pk.BitSet {
rev := make(pk.BitSet, len(set))
for i := range rev {
rev[i] = ^set[i]
}
return rev
}
func (l *lightData) WriteTo(w io.Writer) (int64, error) {
return pk.Tuple{
pk.Boolean(true), // Trust Edges
l.SkyLightMask,
l.BlockLightMask,
bitSetRev(l.SkyLightMask),
bitSetRev(l.BlockLightMask),
pk.Array(l.SkyLight),
pk.Array(l.BlockLight),
}.WriteTo(w)
}
func (s *SimpleDim) PlayerJoin(p *Player) {
for pos, column := range s.Columns {
column.Lock()
packet := pk.Marshal(
packetid.ClientboundLevelChunkWithLight,
pk.Int(pos.X), pk.Int(pos.Z),
&chunkData{},
&lightData{
SkyLightMask: make(pk.BitSet, (16*16*16-1)>>6+1),
BlockLightMask: make(pk.BitSet, (16*16*16-1)>>6+1),
SkyLight: []pk.ByteArray{},
BlockLight: []pk.ByteArray{},
},
)
column.Unlock()
err := p.WritePacket(Packet757(packet))
if err != nil {
return
}
}
}
func (s *SimpleDim) PlayerQuit(p *Player) {
}