render queue

This commit is contained in:
olebeck 2022-09-05 17:40:03 +02:00
parent 5484bbad52
commit 77f7d4d2d9
3 changed files with 65 additions and 33 deletions

View File

@ -2,6 +2,7 @@ package world
import ( import (
"bytes" "bytes"
"container/list"
"image" "image"
"image/draw" "image/draw"
"math" "math"
@ -41,26 +42,34 @@ var MAP_ITEM_PACKET packet.InventoryContent = packet.InventoryContent{
}, },
} }
type RenderElem struct {
pos protocol.ChunkPos
ch *chunk.Chunk
}
type MapUI struct { type MapUI struct {
img *image.RGBA // rendered image img *image.RGBA // rendered image
zoomLevel int // pixels per chunk zoomLevel int // pixels per chunk
render_queue *list.List
render_lock *sync.Mutex
chunks_images map[protocol.ChunkPos]*image.RGBA // prerendered chunks chunks_images map[protocol.ChunkPos]*image.RGBA // prerendered chunks
needRedraw bool // when the map has updated this is true needRedraw bool // when the map has updated this is true
image_lock *sync.Mutex
ticker *time.Ticker ticker *time.Ticker
w *WorldState w *WorldState
} }
func NewMapUI(w *WorldState) MapUI { func NewMapUI(w *WorldState) *MapUI {
return MapUI{ m := &MapUI{
img: image.NewRGBA(image.Rect(0, 0, 128, 128)), img: image.NewRGBA(image.Rect(0, 0, 128, 128)),
zoomLevel: 16, zoomLevel: 16,
render_queue: list.New(),
render_lock: &sync.Mutex{},
chunks_images: make(map[protocol.ChunkPos]*image.RGBA), chunks_images: make(map[protocol.ChunkPos]*image.RGBA),
image_lock: &sync.Mutex{},
needRedraw: true, needRedraw: true,
w: w, w: w,
} }
return m
} }
func (m *MapUI) Start() { func (m *MapUI) Start() {
@ -68,12 +77,12 @@ func (m *MapUI) Start() {
go func() { go func() {
for range m.ticker.C { for range m.ticker.C {
if m.needRedraw { if m.needRedraw {
if !m.image_lock.TryLock() { if !m.render_lock.TryLock() {
continue // dont send if send is in progress continue
} }
m.needRedraw = false m.needRedraw = false
m.Redraw() m.Redraw()
m.image_lock.Unlock() m.render_lock.Unlock()
if m.w.proxy.Client != nil { if m.w.proxy.Client != nil {
if err := m.w.proxy.Client.WritePacket(&packet.ClientBoundMapItemData{ if err := m.w.proxy.Client.WritePacket(&packet.ClientBoundMapItemData{
@ -137,6 +146,20 @@ func draw_img_scaled_pos(dst *image.RGBA, src *image.RGBA, bottom_left image.Poi
// draw chunk images to the map image // draw chunk images to the map image
func (m *MapUI) Redraw() { func (m *MapUI) Redraw() {
for {
e := m.render_queue.Back()
if e == nil {
break
}
r := e.Value.(RenderElem)
if r.ch != nil {
m.chunks_images[r.pos] = Chunk2Img(r.ch)
} else {
m.chunks_images[r.pos] = black_16x16
}
m.render_queue.Remove(e)
}
// get the chunk coord bounds // get the chunk coord bounds
min := protocol.ChunkPos{} min := protocol.ChunkPos{}
max := protocol.ChunkPos{} max := protocol.ChunkPos{}
@ -215,12 +238,8 @@ func (m *MapUI) Redraw() {
} }
func (m *MapUI) SetChunk(pos protocol.ChunkPos, ch *chunk.Chunk) { func (m *MapUI) SetChunk(pos protocol.ChunkPos, ch *chunk.Chunk) {
var img *image.RGBA = black_16x16 m.render_lock.Lock()
if ch != nil { defer m.render_lock.Unlock()
img = Chunk2Img(ch) m.render_queue.PushBack(RenderElem{pos, ch})
}
m.image_lock.Lock() // dont send while adding a chunk
m.chunks_images[pos] = img
m.image_lock.Unlock()
m.SchedRedraw() m.SchedRedraw()
} }

View File

@ -59,7 +59,7 @@ type WorldState struct {
proxy *utils.ProxyContext proxy *utils.ProxyContext
// ui // ui
ui MapUI ui *MapUI
} }
func NewWorldState() *WorldState { func NewWorldState() *WorldState {
@ -143,10 +143,14 @@ func (c *WorldCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{
proxy := utils.NewProxy(logrus.StandardLogger()) proxy := utils.NewProxy(logrus.StandardLogger())
proxy.ConnectCB = w.OnConnect proxy.ConnectCB = w.OnConnect
proxy.PacketCB = func(pk packet.Packet, proxy *utils.ProxyContext, toServer bool) (packet.Packet, error) { proxy.PacketCB = func(pk packet.Packet, proxy *utils.ProxyContext, toServer bool) (packet.Packet, error) {
var forward bool
if toServer { if toServer {
pk = w.ProcessPacketClient(pk) pk, forward = w.ProcessPacketClient(pk)
} else { } else {
pk = w.ProcessPacketServer(pk) pk, forward = w.ProcessPacketServer(pk)
}
if !forward {
return nil, nil
} }
return pk, nil return pk, nil
} }
@ -320,10 +324,11 @@ func (w *WorldState) SaveAndReset() {
// write metadata // write metadata
s := provider.Settings() s := provider.Settings()
player := w.proxy.Client.GameData().PlayerPosition
s.Spawn = cube.Pos{ s.Spawn = cube.Pos{
int(w.PlayerPos.Position[0]), int(player.X()),
int(w.PlayerPos.Position[1]), int(player.Y()),
int(w.PlayerPos.Position[2]), int(player.Z()),
} }
s.Name = w.WorldName s.Name = w.WorldName
@ -432,6 +437,16 @@ func (w *WorldState) SaveAndReset() {
func (w *WorldState) OnConnect(proxy *utils.ProxyContext) { func (w *WorldState) OnConnect(proxy *utils.ProxyContext) {
w.proxy = proxy w.proxy = proxy
gd := w.proxy.Server.GameData()
/*
if len(gd.CustomBlocks) > 0 {
for _, be := range gd.CustomBlocks {
b := block.ServerCustomBlock(be)
world.RegisterBlock(b)
}
}
*/
if w.withPacks { if w.withPacks {
fmt.Println("reformatting packs") fmt.Println("reformatting packs")
@ -441,7 +456,6 @@ func (w *WorldState) OnConnect(proxy *utils.ProxyContext) {
} }
{ // check game version { // check game version
gd := w.proxy.Server.GameData()
gv := strings.Split(gd.BaseGameVersion, ".") gv := strings.Split(gd.BaseGameVersion, ".")
var err error var err error
if len(gv) > 1 { if len(gv) > 1 {
@ -475,8 +489,8 @@ func (w *WorldState) OnConnect(proxy *utils.ProxyContext) {
case <-w.ctx.Done(): case <-w.ctx.Done():
return return
default: default:
t := time.NewTimer(1 * time.Second) for {
for range t.C { time.Sleep(1 * time.Second)
if w.proxy.Client != nil { if w.proxy.Client != nil {
err := w.proxy.Client.WritePacket(&MAP_ITEM_PACKET) err := w.proxy.Client.WritePacket(&MAP_ITEM_PACKET)
if err != nil { if err != nil {
@ -515,7 +529,8 @@ func (w *WorldState) OnConnect(proxy *utils.ProxyContext) {
}) })
} }
func (w *WorldState) ProcessPacketClient(pk packet.Packet) packet.Packet { func (w *WorldState) ProcessPacketClient(pk packet.Packet) (packet.Packet, bool) {
forward := true
switch pk := pk.(type) { switch pk := pk.(type) {
case *packet.MovePlayer: case *packet.MovePlayer:
w.SetPlayerPos(pk.Position, pk.Pitch, pk.Yaw, pk.HeadYaw) w.SetPlayerPos(pk.Position, pk.Pitch, pk.Yaw, pk.HeadYaw)
@ -524,19 +539,19 @@ func (w *WorldState) ProcessPacketClient(pk packet.Packet) packet.Packet {
case *packet.MapInfoRequest: case *packet.MapInfoRequest:
if pk.MapID == VIEW_MAP_ID { if pk.MapID == VIEW_MAP_ID {
w.ui.SchedRedraw() w.ui.SchedRedraw()
pk = nil forward = false
} }
case *packet.MobEquipment: case *packet.MobEquipment:
if pk.NewItem.Stack.NBTData["map_uuid"] == int64(VIEW_MAP_ID) { if pk.NewItem.Stack.NBTData["map_uuid"] == int64(VIEW_MAP_ID) {
pk = nil forward = false
} }
case *packet.Animate: case *packet.Animate:
w.ProcessAnimate(pk) w.ProcessAnimate(pk)
} }
return pk return pk, forward
} }
func (w *WorldState) ProcessPacketServer(pk packet.Packet) packet.Packet { func (w *WorldState) ProcessPacketServer(pk packet.Packet) (packet.Packet, bool) {
switch pk := pk.(type) { switch pk := pk.(type) {
case *packet.ChangeDimension: case *packet.ChangeDimension:
w.ProcessChangeDimension(pk) w.ProcessChangeDimension(pk)
@ -546,5 +561,5 @@ func (w *WorldState) ProcessPacketServer(pk packet.Packet) packet.Packet {
case *packet.SubChunk: case *packet.SubChunk:
w.ProcessSubChunk(pk) w.ProcessSubChunk(pk)
} }
return pk return pk, true
} }

View File

@ -68,8 +68,6 @@ func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) {
switch pk := pk.(type) { switch pk := pk.(type) {
case *packet.Disconnect: case *packet.Disconnect:
logrus.Infof("Disconnect: %s", pk.Message) logrus.Infof("Disconnect: %s", pk.Message)
case *packet.Event:
logrus.Infof("Event %d %+v", pk.EventType, pk.EventData)
} }
dir := color.GreenString("S") + "->" + color.CyanString("C") dir := color.GreenString("S") + "->" + color.CyanString("C")