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 (
"bytes"
"container/list"
"image"
"image/draw"
"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 {
img *image.RGBA // rendered image
zoomLevel int // pixels per chunk
img *image.RGBA // rendered image
zoomLevel int // pixels per chunk
render_queue *list.List
render_lock *sync.Mutex
chunks_images map[protocol.ChunkPos]*image.RGBA // prerendered chunks
needRedraw bool // when the map has updated this is true
image_lock *sync.Mutex
ticker *time.Ticker
w *WorldState
}
func NewMapUI(w *WorldState) MapUI {
return MapUI{
func NewMapUI(w *WorldState) *MapUI {
m := &MapUI{
img: image.NewRGBA(image.Rect(0, 0, 128, 128)),
zoomLevel: 16,
render_queue: list.New(),
render_lock: &sync.Mutex{},
chunks_images: make(map[protocol.ChunkPos]*image.RGBA),
image_lock: &sync.Mutex{},
needRedraw: true,
w: w,
}
return m
}
func (m *MapUI) Start() {
@ -68,12 +77,12 @@ func (m *MapUI) Start() {
go func() {
for range m.ticker.C {
if m.needRedraw {
if !m.image_lock.TryLock() {
continue // dont send if send is in progress
if !m.render_lock.TryLock() {
continue
}
m.needRedraw = false
m.Redraw()
m.image_lock.Unlock()
m.render_lock.Unlock()
if m.w.proxy.Client != nil {
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
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
min := protocol.ChunkPos{}
max := protocol.ChunkPos{}
@ -215,12 +238,8 @@ func (m *MapUI) Redraw() {
}
func (m *MapUI) SetChunk(pos protocol.ChunkPos, ch *chunk.Chunk) {
var img *image.RGBA = black_16x16
if ch != nil {
img = Chunk2Img(ch)
}
m.image_lock.Lock() // dont send while adding a chunk
m.chunks_images[pos] = img
m.image_lock.Unlock()
m.render_lock.Lock()
defer m.render_lock.Unlock()
m.render_queue.PushBack(RenderElem{pos, ch})
m.SchedRedraw()
}

View File

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