pk.Ary and pk.Array using generic now

This commit is contained in:
Tnze
2022-03-20 01:17:25 +08:00
parent 7997a5faea
commit 4c2510565d
15 changed files with 95 additions and 155 deletions

View File

@ -56,15 +56,13 @@ type ServInfo struct {
} }
func (p *Player) handleLoginPacket(packet pk.Packet) error { func (p *Player) handleLoginPacket(packet pk.Packet) error {
var WorldCount pk.VarInt
var WorldNames = make([]pk.Identifier, 0) var WorldNames = make([]pk.Identifier, 0)
err := packet.Scan( err := packet.Scan(
(*pk.Int)(&p.EID), (*pk.Int)(&p.EID),
(*pk.Boolean)(&p.Hardcore), (*pk.Boolean)(&p.Hardcore),
(*pk.UnsignedByte)(&p.Gamemode), (*pk.UnsignedByte)(&p.Gamemode),
(*pk.Byte)(&p.PrevGamemode), (*pk.Byte)(&p.PrevGamemode),
&WorldCount, pk.Ary[pk.VarInt, *pk.VarInt]{Ary: &WorldNames},
pk.Ary{Len: &WorldCount, Ary: &WorldNames},
pk.NBT(&p.WorldInfo.DimensionCodec), pk.NBT(&p.WorldInfo.DimensionCodec),
pk.NBT(&p.WorldInfo.Dimension), pk.NBT(&p.WorldInfo.Dimension),
(*pk.Identifier)(&p.WorldName), (*pk.Identifier)(&p.WorldName),

View File

@ -96,15 +96,13 @@ func (m *Manager) onSetContentPacket(p pk.Packet) error {
var ( var (
ContainerID pk.UnsignedByte ContainerID pk.UnsignedByte
StateID pk.VarInt StateID pk.VarInt
Count pk.VarInt
SlotData []Slot SlotData []Slot
CarriedItem Slot CarriedItem Slot
) )
if err := p.Scan( if err := p.Scan(
&ContainerID, &ContainerID,
&StateID, &StateID,
&Count, pk.Ary{ pk.Ary[pk.VarInt, *pk.VarInt]{
Len: &Count,
Ary: &SlotData, Ary: &SlotData,
}, },
&CarriedItem, &CarriedItem,

View File

@ -162,12 +162,11 @@ var dimensionSNBT string
func joinGame(conn net.Conn) error { func joinGame(conn net.Conn) error {
return conn.WritePacket(pk.Marshal(JoinGame, return conn.WritePacket(pk.Marshal(JoinGame,
pk.Int(0), // EntityID pk.Int(0), // EntityID
pk.Boolean(false), // Is hardcore pk.Boolean(false), // Is hardcore
pk.UnsignedByte(1), // Gamemode pk.UnsignedByte(1), // Gamemode
pk.Byte(1), // Previous Gamemode pk.Byte(1), // Previous Gamemode
pk.VarInt(1), // World Count pk.Array([]pk.Identifier{"world"}), // World Names
pk.Ary{Len: 1, Ary: []pk.Identifier{"world"}}, // World Names
pk.NBT(nbt.StringifiedMessage(dimensionCodecSNBT)), // Dimension codec pk.NBT(nbt.StringifiedMessage(dimensionCodecSNBT)), // Dimension codec
pk.NBT(nbt.StringifiedMessage(dimensionSNBT)), // Dimension pk.NBT(nbt.StringifiedMessage(dimensionSNBT)), // Dimension
pk.Identifier("world"), // World Name pk.Identifier("world"), // World Name

View File

@ -40,9 +40,8 @@ func NewBitStorage(bits, length int, data []uint64) (b *BitStorage) {
} }
b = &BitStorage{ b = &BitStorage{
mask: 1<<bits - 1, mask: 1<<bits - 1,
bits: bits, bits: bits, length: length,
length: length,
valuesPerLong: 64 / bits, valuesPerLong: 64 / bits,
} }
dataLen := calcBitStorageSize(bits, length) dataLen := calcBitStorageSize(bits, length)

View File

@ -2,11 +2,9 @@ package level
import ( import (
"bytes" "bytes"
"fmt"
"io" "io"
"math/bits" "math/bits"
"strings" "strings"
"sync"
"unsafe" "unsafe"
"github.com/Tnze/go-mc/level/block" "github.com/Tnze/go-mc/level/block"
@ -40,7 +38,6 @@ func (c *ChunkPos) ReadFrom(r io.Reader) (n int64, err error) {
} }
type Chunk struct { type Chunk struct {
sync.Mutex
Sections []Section Sections []Section
HeightMaps HeightMaps HeightMaps HeightMaps
BlockEntity []BlockEntity BlockEntity []BlockEntity
@ -135,18 +132,21 @@ func ChunkFromSave(c *save.Chunk, secs int) *Chunk {
statePalette := v.BlockStates.Palette statePalette := v.BlockStates.Palette
stateRawPalette := make([]int, len(statePalette)) stateRawPalette := make([]int, len(statePalette))
for i, v := range statePalette { for i, v := range statePalette {
b := v.Block() b, ok := block.FromID[v.Name]
if b == nil { if !ok {
panic(fmt.Errorf("block not found: %#v", v)) return nil
} }
if !isAir(b) { if v.Properties.Data != nil {
err := v.Properties.Unmarshal(&b)
if err != nil {
return nil
}
}
s := block.ToStateID[b]
if !isAir(s) {
blockCount++ blockCount++
} }
var ok bool stateRawPalette[i] = s
stateRawPalette[i], ok = block.ToStateID[b]
if !ok {
panic(fmt.Errorf("state id not found: %#v", b))
}
} }
biomesData := *(*[]uint64)((unsafe.Pointer)(&v.Biomes.Data)) biomesData := *(*[]uint64)((unsafe.Pointer)(&v.Biomes.Data))
@ -156,7 +156,7 @@ func ChunkFromSave(c *save.Chunk, secs int) *Chunk {
biomesRawPalette[i] = biomesIDs[strings.TrimPrefix(v, "minecraft:")] biomesRawPalette[i] = biomesIDs[strings.TrimPrefix(v, "minecraft:")]
} }
i := int32(int8(v.Y)) - c.YPos i := int32(v.Y) - c.YPos
sections[i].blockCount = blockCount sections[i].blockCount = blockCount
sections[i].States = NewStatesPaletteContainerWithData(16*16*16, stateData, stateRawPalette) sections[i].States = NewStatesPaletteContainerWithData(16*16*16, stateData, stateRawPalette)
sections[i].Biomes = NewBiomesPaletteContainerWithData(4*4*4, biomesData, biomesRawPalette) sections[i].Biomes = NewBiomesPaletteContainerWithData(4*4*4, biomesData, biomesRawPalette)
@ -297,11 +297,7 @@ func (s *Section) GetBlock(i int) int {
return s.States.Get(i) return s.States.Get(i)
} }
func (s *Section) SetBlock(i int, v int) { func (s *Section) SetBlock(i int, v int) {
var b block.Block if isAir(s.States.Get(i)) {
if stateID := s.States.Get(i); stateID >= 0 && stateID < len(block.StateList) {
b = block.StateList[stateID]
}
if isAir(b) {
s.blockCount-- s.blockCount--
} }
if v != 0 { if v != 0 {
@ -367,8 +363,8 @@ func (l *lightData) ReadFrom(r io.Reader) (int64, error) {
}.ReadFrom(r) }.ReadFrom(r)
} }
func isAir(b block.Block) bool { func isAir(s int) bool {
switch b.(type) { switch block.StateList[s].(type) {
case block.Air, block.CaveAir, block.VoidAir: case block.Air, block.CaveAir, block.VoidAir:
return true return true
default: default:

View File

@ -140,6 +140,14 @@ func (p *PaletteContainer) ReadFrom(r io.Reader) (n int64, err error) {
return n, nil return n, nil
} }
func (p *PaletteContainer) WriteTo(w io.Writer) (n int64, err error) {
return pk.Tuple{
pk.UnsignedByte(p.bits),
p.palette,
p.data,
}.WriteTo(w)
}
type paletteCfg interface { type paletteCfg interface {
bits(int) int bits(int) int
create(bits int) palette create(bits int) palette
@ -197,14 +205,6 @@ func (b biomesCfg) create(bits int) palette {
} }
} }
func (p *PaletteContainer) WriteTo(w io.Writer) (n int64, err error) {
return pk.Tuple{
pk.UnsignedByte(p.bits),
p.palette,
p.data,
}.WriteTo(w)
}
type palette interface { type palette interface {
pk.Field pk.Field
id(v state) (int, bool) id(v state) (int, bool)

View File

@ -109,7 +109,6 @@ func ExamplePacket_Scan_joinGame() {
Hardcore pk.Boolean Hardcore pk.Boolean
Gamemode pk.UnsignedByte Gamemode pk.UnsignedByte
PreGamemode pk.Byte PreGamemode pk.Byte
WorldCount pk.VarInt
WorldNames = make([]pk.Identifier, 0) // This cannot replace with "var WorldNames []pk.Identifier" because "nil" has no type information WorldNames = make([]pk.Identifier, 0) // This cannot replace with "var WorldNames []pk.Identifier" because "nil" has no type information
DimensionCodec struct { DimensionCodec struct {
DimensionType interface{} `nbt:"minecraft:dimension_type"` DimensionType interface{} `nbt:"minecraft:dimension_type"`
@ -127,9 +126,7 @@ func ExamplePacket_Scan_joinGame() {
&Hardcore, &Hardcore,
&Gamemode, &Gamemode,
&PreGamemode, &PreGamemode,
&WorldCount, pk.Ary[pk.VarInt, *pk.VarInt]{
pk.Ary{
Len: &WorldCount,
Ary: &WorldNames, Ary: &WorldNames,
}, },
pk.NBT(&DimensionCodec), pk.NBT(&DimensionCodec),

View File

@ -17,20 +17,29 @@ import (
// In some special cases, you might want to read an "Array of X" with a fix length. // In some special cases, you might want to read an "Array of X" with a fix length.
// So it's allowed to directly set an integer type Len, but not a pointer. // So it's allowed to directly set an integer type Len, but not a pointer.
// //
// Note that Ary DO NOT read or write the Len. You are controlling it manually. // Note that Ary DO read or write the Len. You aren't need to do so by your self.
type Ary struct { type Ary[T VarInt | VarLong | Byte | UnsignedByte | Short | UnsignedShort | Int | Long, L interface {
Len interface{} // Value or Pointer of any integer type, only needed in ReadFrom *T
ReadFrom(r io.Reader) (n int64, err error)
WriteTo(w io.Writer) (n int64, err error)
}] struct {
Ary interface{} // Slice or Pointer of Slice of FieldEncoder, FieldDecoder or both (Field) Ary interface{} // Slice or Pointer of Slice of FieldEncoder, FieldDecoder or both (Field)
} }
func (a Ary) WriteTo(r io.Writer) (n int64, err error) { func (a Ary[T, L]) WriteTo(w io.Writer) (n int64, err error) {
array := reflect.ValueOf(a.Ary) array := reflect.ValueOf(a.Ary)
for array.Kind() == reflect.Ptr { for array.Kind() == reflect.Ptr {
array = array.Elem() array = array.Elem()
} }
Len := T(array.Len())
if nn, err := L(&Len).WriteTo(w); err != nil {
return n, err
} else {
n += nn
}
for i := 0; i < array.Len(); i++ { for i := 0; i < array.Len(); i++ {
elem := array.Index(i) elem := array.Index(i)
nn, err := elem.Interface().(FieldEncoder).WriteTo(r) nn, err := elem.Interface().(FieldEncoder).WriteTo(w)
n += nn n += nn
if err != nil { if err != nil {
return n, err return n, err
@ -39,24 +48,14 @@ func (a Ary) WriteTo(r io.Writer) (n int64, err error) {
return n, nil return n, nil
} }
func (a Ary) length() int { func (a Ary[T, L]) ReadFrom(r io.Reader) (n int64, err error) {
v := reflect.ValueOf(a.Len) var Len T
for { if nn, err := L(&Len).ReadFrom(r); err != nil {
switch v.Kind() { return nn, err
case reflect.Ptr: } else {
v = v.Elem() n += nn
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return int(v.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return int(v.Uint())
default:
panic(errors.New("unsupported Len value: " + v.Type().String()))
}
} }
}
func (a Ary) ReadFrom(r io.Reader) (n int64, err error) {
length := a.length()
array := reflect.ValueOf(a.Ary) array := reflect.ValueOf(a.Ary)
for array.Kind() == reflect.Ptr { for array.Kind() == reflect.Ptr {
array = array.Elem() array = array.Elem()
@ -64,10 +63,12 @@ func (a Ary) ReadFrom(r io.Reader) (n int64, err error) {
if !array.CanAddr() { if !array.CanAddr() {
panic(errors.New("the contents of the Ary are not addressable")) panic(errors.New("the contents of the Ary are not addressable"))
} }
if array.Cap() < length { if array.Cap() < int(Len) {
array.Set(reflect.MakeSlice(array.Type(), length, length)) array.Set(reflect.MakeSlice(array.Type(), int(Len), int(Len)))
} else {
array.Slice(0, int(Len))
} }
for i := 0; i < length; i++ { for i := 0; i < int(Len); i++ {
elem := array.Index(i) elem := array.Index(i)
nn, err := elem.Addr().Interface().(FieldDecoder).ReadFrom(r) nn, err := elem.Addr().Interface().(FieldDecoder).ReadFrom(r)
n += nn n += nn
@ -78,27 +79,8 @@ func (a Ary) ReadFrom(r io.Reader) (n int64, err error) {
return n, err return n, err
} }
// Array return an Ary but handled the previous Length field func Array(ary interface{}) Field {
// return Ary[VarInt, *VarInt]{Ary: ary}
// Warning: unstable API, may change in later version
func Array(array interface{}) Field {
var length VarInt
value := reflect.ValueOf(array)
for value.Kind() == reflect.Ptr {
value = value.Elem()
}
if array != nil {
length = VarInt(value.Len())
}
return Tuple{
&length,
Ary{
Len: &length,
Ary: array,
},
}
} }
type Opt struct { type Opt struct {

View File

@ -13,28 +13,18 @@ func ExampleAry_WriteTo() {
// The length is inferred from the length of Ary. // The length is inferred from the length of Ary.
pk.Marshal( pk.Marshal(
0x00, 0x00,
// It's important to remember that pk.Ary[pk.VarInt, *pk.VarInt]{
// typically the responsibility of
// sending the length field
// is on you.
pk.VarInt(len(data)),
pk.Ary{
Len: len(data), // this line can be removed
Ary: data, Ary: data,
}, },
) )
} }
func ExampleAry_ReadFrom() { func ExampleAry_ReadFrom() {
var length pk.VarInt
var data []pk.String var data []pk.String
var p pk.Packet // = conn.ReadPacket() var p pk.Packet // = conn.ReadPacket()
if err := p.Scan( if err := p.Scan(
pk.Ary[pk.VarInt, *pk.VarInt]{ // then decode Ary according to length
&length, // decode length first
pk.Ary{ // then decode Ary according to length
Len: &length,
Ary: &data, Ary: &data,
}, },
); err != nil { ); err != nil {
@ -43,18 +33,18 @@ func ExampleAry_ReadFrom() {
} }
func TestAry_ReadFrom(t *testing.T) { func TestAry_ReadFrom(t *testing.T) {
var num pk.Int = 2
var ary []pk.String var ary []pk.String
var bin = []byte{ var bin = []byte{
0, 0, 0, 2,
4, 'T', 'n', 'z', 'e', 4, 'T', 'n', 'z', 'e',
0, 0,
} }
var data = pk.Ary{Len: &num, Ary: &ary} var data = pk.Ary[pk.Int, *pk.Int]{Ary: &ary}
if _, err := data.ReadFrom(bytes.NewReader(bin)); err != nil { if _, err := data.ReadFrom(bytes.NewReader(bin)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if len(ary) != int(num) { if len(ary) != 2 {
t.Fatalf("length not match: %d != %d", len(ary), num) t.Fatalf("length not match: %d != %d", len(ary), 2)
} }
for i, v := range []string{"Tnze", ""} { for i, v := range []string{"Tnze", ""} {
if string(ary[i]) != v { if string(ary[i]) != v {
@ -70,23 +60,22 @@ func TestAry_WriteTo(t *testing.T) {
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03,
} }
int3, long3, varint3, varlong3 := pk.Int(3), pk.Long(3), pk.VarInt(3), pk.VarLong(3) for _, item := range [...]pk.FieldEncoder{
for _, item := range [...]pk.Ary{ pk.Ary[pk.Int, *pk.Int]{Ary: []pk.Int{1, 2, 3}},
{Len: 3, Ary: []pk.Int{1, 2, 3}}, pk.Ary[pk.Int, *pk.Int]{Ary: []pk.Int{1, 2, 3}},
{Len: int3, Ary: []pk.Int{1, 2, 3}}, pk.Ary[pk.Long, *pk.Long]{Ary: []pk.Int{1, 2, 3}},
{Len: long3, Ary: []pk.Int{1, 2, 3}}, pk.Ary[pk.VarInt, *pk.VarInt]{Ary: []pk.Int{1, 2, 3}},
{Len: varint3, Ary: []pk.Int{1, 2, 3}}, pk.Ary[pk.VarLong, *pk.VarLong]{Ary: []pk.Int{1, 2, 3}},
{Len: varlong3, Ary: []pk.Int{1, 2, 3}}, pk.Ary[pk.Int, *pk.Int]{Ary: []pk.Int{1, 2, 3}},
{Len: &int3, Ary: []pk.Int{1, 2, 3}}, pk.Ary[pk.Long, *pk.Long]{Ary: []pk.Int{1, 2, 3}},
{Len: &long3, Ary: []pk.Int{1, 2, 3}}, pk.Ary[pk.VarInt, *pk.VarInt]{Ary: []pk.Int{1, 2, 3}},
{Len: &varint3, Ary: []pk.Int{1, 2, 3}}, pk.Ary[pk.VarLong, *pk.VarLong]{Ary: []pk.Int{1, 2, 3}},
{Len: &varlong3, Ary: []pk.Int{1, 2, 3}},
} { } {
_, err := item.WriteTo(&buf) _, err := item.WriteTo(&buf)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if !bytes.Equal(buf.Bytes(), want) { if !bytes.Equal(buf.Bytes()[buf.Len()-3*4:], want) {
t.Fatalf("Ary encoding error: got %#v, want %#v", buf.Bytes(), want) t.Fatalf("Ary encoding error: got %#v, want %#v", buf.Bytes(), want)
} }
buf.Reset() buf.Reset()
@ -96,11 +85,12 @@ func TestAry_WriteTo(t *testing.T) {
func TestAry_WriteTo_pointer(t *testing.T) { func TestAry_WriteTo_pointer(t *testing.T) {
var buf bytes.Buffer var buf bytes.Buffer
want := []byte{ want := []byte{
0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03,
} }
data := pk.Ary{Ary: &[]pk.Int{1, 2, 3}} data := pk.Ary[pk.Int, *pk.Int]{Ary: &[]pk.Int{1, 2, 3}}
_, err := data.WriteTo(&buf) _, err := data.WriteTo(&buf)
if err != nil { if err != nil {
@ -184,7 +174,6 @@ func ExampleOpt_ReadFrom_func() {
func ExampleTuple_ReadFrom() { func ExampleTuple_ReadFrom() {
// When you need to read an "Optional Array of X": // When you need to read an "Optional Array of X":
var has pk.Boolean var has pk.Boolean
var arylen pk.Int
var ary []pk.String var ary []pk.String
var p pk.Packet // = conn.ReadPacket() var p pk.Packet // = conn.ReadPacket()
@ -193,9 +182,7 @@ func ExampleTuple_ReadFrom() {
pk.Opt{ pk.Opt{
Has: &has, Has: &has,
Field: pk.Tuple{ Field: pk.Tuple{
&arylen, pk.Ary[pk.Int, *pk.Int]{
pk.Ary{
Len: &arylen,
Ary: &ary, Ary: &ary,
}, },
}, },

View File

@ -7,7 +7,6 @@ import (
"errors" "errors"
"io" "io"
"github.com/Tnze/go-mc/level/block"
"github.com/Tnze/go-mc/nbt" "github.com/Tnze/go-mc/nbt"
) )
@ -47,19 +46,6 @@ type BlockState struct {
Properties nbt.RawMessage Properties nbt.RawMessage
} }
func (s *BlockState) Block() block.Block {
b, ok := block.FromID[s.Name]
if !ok {
return nil
}
if s.Properties.Type != nbt.TagEnd {
if err := s.Properties.Unmarshal(&b); err != nil {
return nil
}
}
return b
}
// Load read column data from []byte // Load read column data from []byte
func (c *Chunk) Load(data []byte) (err error) { func (c *Chunk) Load(data []byte) (err error) {
var r io.Reader = bytes.NewReader(data[1:]) var r io.Reader = bytes.NewReader(data[1:])

View File

@ -45,13 +45,10 @@ func (s *SimpleDim) Info() LevelInfo {
func (s *SimpleDim) PlayerJoin(p *Player) { func (s *SimpleDim) PlayerJoin(p *Player) {
for pos, column := range s.columns { for pos, column := range s.columns {
column.Lock()
packet := pk.Marshal( packet := pk.Marshal(
packetid.ClientboundLevelChunkWithLight, packetid.ClientboundLevelChunkWithLight,
pos, column, pos, column,
) )
column.Unlock()
p.WritePacket(Packet758(packet)) p.WritePacket(Packet758(packet))
} }
} }

1
server/entities.go Normal file
View File

@ -0,0 +1 @@
package server

View File

@ -191,7 +191,7 @@ func TouchPoint[Vec any, B interface{ WithIn(Vec) bool }](point Vec) func(bound
} }
} }
func TouchBound[Vec any, B interface{ Touch(B) bool }](other B) func(bound B) bool { func TouchBound[B interface{ Touch(B) bool }](other B) func(bound B) bool {
return func(bound B) bool { return func(bound B) bool {
return bound.Touch(other) return bound.Touch(other)
} }

View File

@ -56,9 +56,9 @@ func TestTree2_Find_vec(t *testing.T) {
t.Log(find(TouchPoint[Vec2d, AABBVec2d](Vec2d{1.5, 1.5}))) t.Log(find(TouchPoint[Vec2d, AABBVec2d](Vec2d{1.5, 1.5})))
t.Log(find(TouchPoint[Vec2d, AABBVec2d](Vec2d{-1.5, 0}))) t.Log(find(TouchPoint[Vec2d, AABBVec2d](Vec2d{-1.5, 0})))
t.Log(find(TouchBound[Vec2d, AABBVec2d](AABBVec2d{Upper: Vec2d{1, 1}, Lower: Vec2d{-1, -1}}))) t.Log(find(TouchBound[AABBVec2d](AABBVec2d{Upper: Vec2d{1, 1}, Lower: Vec2d{-1, -1}})))
t.Log(find(TouchBound[Vec2d, AABBVec2d](AABBVec2d{Upper: Vec2d{1, 1}, Lower: Vec2d{1.5, 1.5}}))) t.Log(find(TouchBound[AABBVec2d](AABBVec2d{Upper: Vec2d{1, 1}, Lower: Vec2d{1.5, 1.5}})))
t.Log(find(TouchBound[Vec2d, AABBVec2d](AABBVec2d{Upper: Vec2d{-1.5, 0.5}, Lower: Vec2d{-2.5, -0.5}}))) t.Log(find(TouchBound[AABBVec2d](AABBVec2d{Upper: Vec2d{-1.5, 0.5}, Lower: Vec2d{-2.5, -0.5}})))
} }
func BenchmarkTree_Insert(b *testing.B) { func BenchmarkTree_Insert(b *testing.B) {

View File

@ -12,18 +12,18 @@ import (
) )
type PlayerInfo struct { type PlayerInfo struct {
updateDelay chan playerInfo updateDelay chan playerDelayInfo
join chan *Player join chan *Player
quit chan *Player quit chan *Player
ticker *time.Ticker ticker *time.Ticker
} }
type playerInfo struct { type playerDelayInfo struct {
player *Player player *Player
delay time.Duration delay time.Duration
} }
func (p *playerInfo) WriteTo(w io.Writer) (n int64, err error) { func (p *playerDelayInfo) WriteTo(w io.Writer) (n int64, err error) {
return pk.Tuple{ return pk.Tuple{
pk.UUID(p.player.UUID), pk.UUID(p.player.UUID),
pk.String(p.player.Name), pk.String(p.player.Name),
@ -35,7 +35,7 @@ func (p *playerInfo) WriteTo(w io.Writer) (n int64, err error) {
} }
type playerInfoList struct { type playerInfoList struct {
list map[uuid.UUID]playerInfo list map[uuid.UUID]playerDelayInfo
} }
func (p *playerInfoList) WriteTo(w io.Writer) (n int64, err error) { func (p *playerInfoList) WriteTo(w io.Writer) (n int64, err error) {
@ -54,7 +54,7 @@ func (p *playerInfoList) WriteTo(w io.Writer) (n int64, err error) {
return return
} }
type playerDelayUpdate playerInfo type playerDelayUpdate playerDelayInfo
func (p playerDelayUpdate) WriteTo(w io.Writer) (n int64, err error) { func (p playerDelayUpdate) WriteTo(w io.Writer) (n int64, err error) {
return pk.Tuple{ return pk.Tuple{
@ -77,7 +77,7 @@ type PlayerDelaySource interface {
func NewPlayerInfo(updateFreq time.Duration, delaySource PlayerDelaySource) *PlayerInfo { func NewPlayerInfo(updateFreq time.Duration, delaySource PlayerDelaySource) *PlayerInfo {
p := &PlayerInfo{ p := &PlayerInfo{
updateDelay: make(chan playerInfo), updateDelay: make(chan playerDelayInfo),
join: make(chan *Player), join: make(chan *Player),
quit: make(chan *Player), quit: make(chan *Player),
ticker: time.NewTicker(updateFreq), ticker: time.NewTicker(updateFreq),
@ -91,12 +91,12 @@ func NewPlayerInfo(updateFreq time.Duration, delaySource PlayerDelaySource) *Pla
func (p *PlayerInfo) Init(*Game) {} func (p *PlayerInfo) Init(*Game) {}
func (p *PlayerInfo) Run(ctx context.Context) { func (p *PlayerInfo) Run(ctx context.Context) {
players := &playerInfoList{list: make(map[uuid.UUID]playerInfo)} players := &playerInfoList{list: make(map[uuid.UUID]playerDelayInfo)}
var delayBuffer []playerDelayUpdate var delayBuffer []playerDelayUpdate
for { for {
select { select {
case player := <-p.join: case player := <-p.join:
info := playerInfo{player: player, delay: 0} info := playerDelayInfo{player: player, delay: 0}
pack := Packet758(pk.Marshal( pack := Packet758(pk.Marshal(
packetid.ClientboundPlayerInfo, packetid.ClientboundPlayerInfo,
pk.VarInt(actionAddPlayer), pk.VarInt(actionAddPlayer),
@ -144,5 +144,5 @@ func (p *PlayerInfo) Run(ctx context.Context) {
func (p *PlayerInfo) AddPlayer(player *Player) { p.join <- player } func (p *PlayerInfo) AddPlayer(player *Player) { p.join <- player }
func (p *PlayerInfo) RemovePlayer(player *Player) { p.quit <- player } func (p *PlayerInfo) RemovePlayer(player *Player) { p.quit <- player }
func (p *PlayerInfo) onPlayerDelayUpdate(player *Player, delay time.Duration) { func (p *PlayerInfo) onPlayerDelayUpdate(player *Player, delay time.Duration) {
p.updateDelay <- playerInfo{player: player, delay: delay} p.updateDelay <- playerDelayInfo{player: player, delay: delay}
} }