render queue
This commit is contained in:
parent
5484bbad52
commit
77f7d4d2d9
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue