PaletteContainer
This commit is contained in:
@ -6,6 +6,7 @@ import (
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
"github.com/Tnze/go-mc/save"
|
||||
"io"
|
||||
"math/bits"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@ -20,33 +21,74 @@ type DimInfo struct {
|
||||
HashedSeed uint64
|
||||
}
|
||||
|
||||
type SimpleDim struct {
|
||||
Columns map[struct{ X, Z int }]*struct {
|
||||
sync.Mutex
|
||||
type ChunkPos struct{ X, Z int }
|
||||
type Chunk struct {
|
||||
sync.Mutex
|
||||
sections []Section
|
||||
HeightMaps *save.BitStorage
|
||||
}
|
||||
|
||||
type Section struct {
|
||||
blockCount int16
|
||||
States *save.PaletteContainer
|
||||
Biomes *save.PaletteContainer
|
||||
}
|
||||
|
||||
func (s *Section) WriteTo(w io.Writer) (int64, error) {
|
||||
return pk.Tuple{
|
||||
pk.Short(s.blockCount),
|
||||
s.States,
|
||||
s.Biomes,
|
||||
}.WriteTo(w)
|
||||
}
|
||||
|
||||
func (s *Section) ReadFrom(r io.Reader) (int64, error) {
|
||||
return pk.Tuple{
|
||||
pk.Short(s.blockCount),
|
||||
s.States,
|
||||
s.Biomes,
|
||||
}.ReadFrom(r)
|
||||
}
|
||||
|
||||
func EmptyChunk(secs int) *Chunk {
|
||||
sections := make([]Section, secs)
|
||||
for i := range sections {
|
||||
sections[i] = Section{
|
||||
blockCount: 0,
|
||||
States: save.NewStatesPaletteContainer(nil, 16*16*16),
|
||||
Biomes: save.NewBiomesPaletteContainer(nil, 4*4*4),
|
||||
}
|
||||
}
|
||||
return &Chunk{
|
||||
sections: sections,
|
||||
HeightMaps: save.NewBitStorage(bits.Len(uint(secs)*16), 16*16, nil),
|
||||
}
|
||||
}
|
||||
|
||||
type chunkData struct {
|
||||
HeightMaps save.BitStorage
|
||||
BlockState save.BitStorage
|
||||
Biomes save.BitStorage
|
||||
}
|
||||
|
||||
func (c *chunkData) WriteTo(w io.Writer) (int64, error) {
|
||||
func (c *Chunk) WriteTo(w io.Writer) (int64, error) {
|
||||
data, err := c.Data()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return pk.Tuple{
|
||||
// Heightmaps
|
||||
pk.NBT(struct {
|
||||
MotionBlocking []uint64 `nbt:"MOTION_BLOCKING"`
|
||||
}{c.HeightMaps.Raw()}),
|
||||
pk.ByteArray(c.Data()), // TODO: Chunk Data
|
||||
pk.VarInt(0), // TODO: Block Entity
|
||||
pk.ByteArray(data),
|
||||
pk.VarInt(0), // TODO: Block Entity
|
||||
}.WriteTo(w)
|
||||
}
|
||||
|
||||
func (c *chunkData) Data() []byte {
|
||||
func (c *Chunk) Data() ([]byte, error) {
|
||||
var buff bytes.Buffer
|
||||
_, _ = pk.Short(0).WriteTo(&buff)
|
||||
return buff.Bytes()
|
||||
for _, section := range c.sections {
|
||||
_, err := section.WriteTo(&buff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return buff.Bytes(), nil
|
||||
}
|
||||
|
||||
type lightData struct {
|
||||
@ -76,13 +118,36 @@ func (l *lightData) WriteTo(w io.Writer) (int64, error) {
|
||||
}.WriteTo(w)
|
||||
}
|
||||
|
||||
type SimpleDim struct {
|
||||
numOfSection int
|
||||
Columns map[ChunkPos]*Chunk
|
||||
}
|
||||
|
||||
func NewSimpleDim(secs int) *SimpleDim {
|
||||
return &SimpleDim{
|
||||
numOfSection: secs,
|
||||
Columns: make(map[ChunkPos]*Chunk),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SimpleDim) LoadChunk(pos ChunkPos, c *Chunk) {
|
||||
s.Columns[pos] = c
|
||||
}
|
||||
|
||||
func (s *SimpleDim) Info() DimInfo {
|
||||
return DimInfo{
|
||||
Name: "minecraft:overworld",
|
||||
HashedSeed: 0,
|
||||
}
|
||||
}
|
||||
|
||||
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{},
|
||||
column,
|
||||
&lightData{
|
||||
SkyLightMask: make(pk.BitSet, (16*16*16-1)>>6+1),
|
||||
BlockLightMask: make(pk.BitSet, (16*16*16-1)>>6+1),
|
||||
@ -97,6 +162,18 @@ func (s *SimpleDim) PlayerJoin(p *Player) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err := p.WritePacket(Packet757(pk.Marshal(
|
||||
packetid.ClientboundPlayerPosition,
|
||||
pk.Double(0), pk.Double(0), pk.Double(0),
|
||||
pk.Float(0), pk.Float(0),
|
||||
pk.Byte(0),
|
||||
pk.VarInt(0),
|
||||
pk.Boolean(true),
|
||||
)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SimpleDim) PlayerQuit(p *Player) {
|
||||
|
@ -2,6 +2,7 @@ package server
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"github.com/Tnze/go-mc/chat"
|
||||
"github.com/Tnze/go-mc/nbt"
|
||||
"sync/atomic"
|
||||
|
||||
@ -23,6 +24,7 @@ type GamePlay interface {
|
||||
type Game struct {
|
||||
eid int32
|
||||
Dim Dimension
|
||||
*PlayerList
|
||||
}
|
||||
|
||||
//go:embed DimensionCodec.snbt
|
||||
@ -32,6 +34,18 @@ var dimensionCodecSNBT string
|
||||
var dimensionSNBT string
|
||||
|
||||
func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net.Conn) {
|
||||
remove := g.PlayerList.TryInsert(PlayerSample{
|
||||
Name: name,
|
||||
ID: id,
|
||||
})
|
||||
if remove == nil {
|
||||
_ = conn.WritePacket(pk.Marshal(
|
||||
packetid.ClientboundDisconnect,
|
||||
chat.TranslateMsg("multiplayer.disconnect.server_full"),
|
||||
))
|
||||
return
|
||||
}
|
||||
defer remove()
|
||||
p := &Player{
|
||||
Conn: conn,
|
||||
EntityID: g.newEID(),
|
||||
@ -61,6 +75,21 @@ func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net
|
||||
return
|
||||
}
|
||||
g.Dim.PlayerJoin(p)
|
||||
defer g.Dim.PlayerQuit(p)
|
||||
|
||||
var packet pk.Packet
|
||||
for {
|
||||
err := p.ReadPacket(&packet)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, ph := range p.handlers[packet.ID] {
|
||||
err = ph(p, Packet757(packet))
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Game) newEID() int32 {
|
||||
|
@ -9,6 +9,7 @@ type Player struct {
|
||||
*net.Conn
|
||||
EntityID int32
|
||||
Gamemode byte
|
||||
handlers map[int32][]packetHandlerFunc
|
||||
}
|
||||
|
||||
// Packet757 is a packet in protocol 757.
|
||||
@ -19,3 +20,17 @@ type Packet757 pk.Packet
|
||||
func (p *Player) WritePacket(packet Packet757) error {
|
||||
return p.Conn.WritePacket(pk.Packet(packet))
|
||||
}
|
||||
|
||||
type PacketHandler struct {
|
||||
ID int32
|
||||
F packetHandlerFunc
|
||||
}
|
||||
|
||||
type packetHandlerFunc func(player *Player, packet Packet757) error
|
||||
|
||||
func (p *Player) Add(ph PacketHandler) {
|
||||
if p.handlers == nil {
|
||||
p.handlers = make(map[int32][]packetHandlerFunc)
|
||||
}
|
||||
p.handlers[ph.ID] = append(p.handlers[ph.ID], ph.F)
|
||||
}
|
||||
|
Reference in New Issue
Block a user