bot can receive chunks now

This commit is contained in:
Tnze
2022-03-13 11:57:02 +08:00
parent d8695636b6
commit 2aace6b51a
17 changed files with 452 additions and 78 deletions

View File

@ -7,6 +7,7 @@ import (
)
type Level interface {
Init(g *Game)
Info() LevelInfo
PlayerJoin(p *Player)
PlayerQuit(p *Player)
@ -19,18 +20,20 @@ type LevelInfo struct {
type SimpleDim struct {
numOfSection int
Columns map[level.ChunkPos]*level.Chunk
columns map[level.ChunkPos]*level.Chunk
}
func (s *SimpleDim) Init(*Game) {}
func NewSimpleDim(secs int) *SimpleDim {
return &SimpleDim{
numOfSection: secs,
Columns: make(map[level.ChunkPos]*level.Chunk),
columns: make(map[level.ChunkPos]*level.Chunk),
}
}
func (s *SimpleDim) LoadChunk(pos level.ChunkPos, c *level.Chunk) {
s.Columns[pos] = c
s.columns[pos] = c
}
func (s *SimpleDim) Info() LevelInfo {
@ -41,28 +44,16 @@ func (s *SimpleDim) Info() LevelInfo {
}
func (s *SimpleDim) PlayerJoin(p *Player) {
for pos, column := range s.Columns {
for pos, column := range s.columns {
column.Lock()
packet := pk.Marshal(
packetid.ClientboundLevelChunkWithLight,
pk.Int(pos.X), pk.Int(pos.Z),
column,
pos, column,
)
column.Unlock()
p.WritePacket(Packet758(packet))
}
p.WritePacket(Packet758(pk.Marshal(
packetid.ClientboundPlayerPosition,
pk.Double(0), pk.Double(143), pk.Double(0),
pk.Float(0), pk.Float(0),
pk.Byte(0),
pk.VarInt(0),
pk.Boolean(true),
)))
}
func (s *SimpleDim) PlayerQuit(p *Player) {
}
func (s *SimpleDim) PlayerQuit(*Player) {}

View File

@ -56,6 +56,7 @@ func NewGame(dim Level, components ...Component) *Game {
components: components,
handlers: make(map[int32][]*PacketHandler),
}
dim.Init(g)
for _, v := range components {
v.Init(g)
}

View File

@ -48,12 +48,11 @@ func NewKeepAlive() (k *KeepAlive) {
}
}
func (k *KeepAlive) AddPlayerDelayUpdateHandler(f func(p *Player, delay time.Duration)) *KeepAlive {
func (k *KeepAlive) AddPlayerDelayUpdateHandler(f func(p *Player, delay time.Duration)) {
if k.updatePlayerDelay != nil {
panic("add player update handler twice")
}
k.updatePlayerDelay = f
return k
}
// Init implement Component for KeepAlive

148
server/playerinfo.go Normal file
View File

@ -0,0 +1,148 @@
package server
import (
"context"
"io"
"time"
"github.com/google/uuid"
"github.com/Tnze/go-mc/data/packetid"
pk "github.com/Tnze/go-mc/net/packet"
)
type PlayerInfo struct {
updateDelay chan playerInfo
join chan *Player
quit chan *Player
ticker *time.Ticker
}
type playerInfo struct {
player *Player
delay time.Duration
}
func (p *playerInfo) WriteTo(w io.Writer) (n int64, err error) {
return pk.Tuple{
pk.UUID(p.player.UUID),
pk.String(p.player.Name),
pk.Array([]pk.FieldEncoder{}),
pk.VarInt(p.player.Gamemode),
pk.VarInt(p.delay),
pk.Boolean(false),
}.WriteTo(w)
}
type playerInfoList struct {
list map[uuid.UUID]playerInfo
}
func (p *playerInfoList) WriteTo(w io.Writer) (n int64, err error) {
n, err = pk.VarInt(len(p.list)).WriteTo(w)
if err != nil {
return
}
var n1 int64
for _, p := range p.list {
n1, err = p.WriteTo(w)
n += n1
if err != nil {
return
}
}
return
}
type playerDelayUpdate playerInfo
func (p playerDelayUpdate) WriteTo(w io.Writer) (n int64, err error) {
return pk.Tuple{
pk.UUID(p.player.UUID),
pk.VarInt(p.delay.Milliseconds()),
}.WriteTo(w)
}
const (
actionAddPlayer = iota
actionUpdateGamemode
actionUpdateLatency
actionUpdateDisplayName
actionRemovePlayer
)
type PlayerDelaySource interface {
AddPlayerDelayUpdateHandler(f func(p *Player, delay time.Duration))
}
func NewPlayerInfo(updateFreq time.Duration, delaySource PlayerDelaySource) *PlayerInfo {
p := &PlayerInfo{
updateDelay: make(chan playerInfo),
join: make(chan *Player),
quit: make(chan *Player),
ticker: time.NewTicker(updateFreq),
}
if delaySource != nil {
delaySource.AddPlayerDelayUpdateHandler(p.onPlayerDelayUpdate)
}
return p
}
func (p *PlayerInfo) Init(*Game) {}
func (p *PlayerInfo) Run(ctx context.Context) {
players := &playerInfoList{list: make(map[uuid.UUID]playerInfo)}
var delayBuffer []playerDelayUpdate
for {
select {
case player := <-p.join:
info := playerInfo{player: player, delay: 0}
pack := Packet758(pk.Marshal(
packetid.ClientboundPlayerInfo,
pk.VarInt(actionAddPlayer),
pk.VarInt(1),
&info,
))
players.list[player.UUID] = info
for _, p := range players.list {
p.player.WritePacket(pack)
}
player.WritePacket(Packet758(pk.Marshal(
packetid.ClientboundPlayerInfo,
pk.VarInt(actionAddPlayer),
players,
)))
case player := <-p.quit:
delete(players.list, player.UUID)
pack := Packet758(pk.Marshal(
packetid.ClientboundPlayerInfo,
pk.VarInt(actionRemovePlayer),
pk.VarInt(1),
pk.UUID(player.UUID),
))
for _, p := range players.list {
p.player.WritePacket(pack)
}
case change := <-p.updateDelay:
delayBuffer = append(delayBuffer, playerDelayUpdate(change))
case <-p.ticker.C:
pack := Packet758(pk.Marshal(
packetid.ClientboundPlayerInfo,
pk.VarInt(actionUpdateLatency),
pk.Array(&delayBuffer),
))
for _, p := range players.list {
p.player.WritePacket(pack)
}
delayBuffer = delayBuffer[:0]
case <-ctx.Done():
break
}
}
}
func (p *PlayerInfo) AddPlayer(player *Player) { p.join <- player }
func (p *PlayerInfo) RemovePlayer(player *Player) { p.quit <- player }
func (p *PlayerInfo) onPlayerDelayUpdate(player *Player, delay time.Duration) {
p.updateDelay <- playerInfo{player: player, delay: delay}
}

14
server/playermove.go Normal file
View File

@ -0,0 +1,14 @@
package server
type EntitySet struct {
}
type entityPosition struct {
player *Player
x, y, z float64
yaw, pitch float32
}
func NewEntitySet() *EntitySet {
return &EntitySet{}
}