use lockfree for the map
This commit is contained in:
parent
77f7d4d2d9
commit
146e8dc00d
1
go.mod
1
go.mod
|
@ -12,6 +12,7 @@ require (
|
|||
github.com/google/subcommands v1.2.0
|
||||
github.com/miekg/dns v1.1.50
|
||||
github.com/sandertv/gophertunnel v1.24.5
|
||||
golang.design/x/lockfree v0.0.1
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e
|
||||
golang.org/x/oauth2 v0.0.0-20220808172628-8227340efae7
|
||||
)
|
||||
|
|
4
go.sum
4
go.sum
|
@ -55,6 +55,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
|
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sandertv/go-raknet v1.11.1 h1:0auvhHoZNyC/Z1l5xqniE3JE+w3MGO3n3JXEGHzdlRE=
|
||||
github.com/sandertv/go-raknet v1.11.1/go.mod h1:Gx+WgZBMQ0V2UoouGoJ8Wj6CDrMBQ4SB2F/ggpl5/+Y=
|
||||
github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM=
|
||||
github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
|
@ -62,6 +64,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
golang.design/x/lockfree v0.0.1 h1:IHFNwZgM5bnZYWkEbzn5lWHMYr8WsRBdCJ/RBVY0xMM=
|
||||
golang.design/x/lockfree v0.0.1/go.mod h1:iaZUx6UgZaOdePjzI6wFd+seYMl1i0rsG8+xKvA8c4I=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
||||
|
|
|
@ -30,6 +30,9 @@ func blockColorAt(c *chunk.Chunk, x uint8, y int16, z uint8) (blockColor color.R
|
|||
bw := (&block.Water{}).Color()
|
||||
bw.A = uint8(utils.Clamp(int(150+depth*7), 255))
|
||||
blockColor = utils.BlendColors(blockColor, bw)
|
||||
blockColor.R -= uint8(depth * 2)
|
||||
blockColor.G -= uint8(depth * 2)
|
||||
blockColor.B -= uint8(depth * 2)
|
||||
} else {
|
||||
blockColor = b.Color()
|
||||
}
|
||||
|
|
|
@ -2,15 +2,14 @@ package world
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"image"
|
||||
"image/draw"
|
||||
"math"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/bedrock-tool/bedrocktool/utils"
|
||||
"golang.design/x/lockfree"
|
||||
|
||||
"github.com/df-mc/dragonfly/server/world/chunk"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||
|
@ -48,12 +47,11 @@ type RenderElem struct {
|
|||
}
|
||||
|
||||
type MapUI struct {
|
||||
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
|
||||
img *image.RGBA // rendered image
|
||||
zoomLevel int // pixels per chunk
|
||||
renderQueue *lockfree.Queue
|
||||
renderedChunks map[protocol.ChunkPos]*image.RGBA // prerendered chunks
|
||||
needRedraw bool // when the map has updated this is true
|
||||
|
||||
ticker *time.Ticker
|
||||
w *WorldState
|
||||
|
@ -61,13 +59,12 @@ type MapUI struct {
|
|||
|
||||
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),
|
||||
needRedraw: true,
|
||||
w: w,
|
||||
img: image.NewRGBA(image.Rect(0, 0, 128, 128)),
|
||||
zoomLevel: 16,
|
||||
renderQueue: lockfree.NewQueue(),
|
||||
renderedChunks: make(map[protocol.ChunkPos]*image.RGBA),
|
||||
needRedraw: true,
|
||||
w: w,
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
@ -77,12 +74,8 @@ func (m *MapUI) Start() {
|
|||
go func() {
|
||||
for range m.ticker.C {
|
||||
if m.needRedraw {
|
||||
if !m.render_lock.TryLock() {
|
||||
continue
|
||||
}
|
||||
m.needRedraw = false
|
||||
m.Redraw()
|
||||
m.render_lock.Unlock()
|
||||
|
||||
if m.w.proxy.Client != nil {
|
||||
if err := m.w.proxy.Client.WritePacket(&packet.ClientBoundMapItemData{
|
||||
|
@ -109,8 +102,8 @@ func (m *MapUI) Stop() {
|
|||
|
||||
// Reset resets the map to inital state
|
||||
func (m *MapUI) Reset() {
|
||||
m.chunks_images = make(map[protocol.ChunkPos]*image.RGBA)
|
||||
m.needRedraw = true
|
||||
m.renderedChunks = make(map[protocol.ChunkPos]*image.RGBA)
|
||||
m.SchedRedraw()
|
||||
}
|
||||
|
||||
// ChangeZoom adds to the zoom value and goes around to 32 once it hits 128
|
||||
|
@ -133,7 +126,6 @@ func draw_img_scaled_pos(dst *image.RGBA, src *image.RGBA, bottom_left image.Poi
|
|||
sby := src.Bounds().Dy()
|
||||
|
||||
ratio := float64(sbx) / float64(size_scaled)
|
||||
|
||||
for x_in := 0; x_in < sbx; x_in++ {
|
||||
for y_in := 0; y_in < sby; y_in++ {
|
||||
c := src.At(x_in, y_in)
|
||||
|
@ -147,23 +139,21 @@ 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 {
|
||||
r, ok := m.renderQueue.Dequeue().(*RenderElem)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
r := e.Value.(RenderElem)
|
||||
if r.ch != nil {
|
||||
m.chunks_images[r.pos] = Chunk2Img(r.ch)
|
||||
m.renderedChunks[r.pos] = Chunk2Img(r.ch)
|
||||
} else {
|
||||
m.chunks_images[r.pos] = black_16x16
|
||||
m.renderedChunks[r.pos] = black_16x16
|
||||
}
|
||||
m.render_queue.Remove(e)
|
||||
}
|
||||
|
||||
// get the chunk coord bounds
|
||||
min := protocol.ChunkPos{}
|
||||
max := protocol.ChunkPos{}
|
||||
for _ch := range m.chunks_images {
|
||||
for _ch := range m.renderedChunks {
|
||||
if _ch.X() < min.X() {
|
||||
min[0] = _ch.X()
|
||||
}
|
||||
|
@ -196,7 +186,7 @@ func (m *MapUI) Redraw() {
|
|||
m.img.Pix[i] = 0
|
||||
}
|
||||
|
||||
for _ch := range m.chunks_images {
|
||||
for _ch := range m.renderedChunks {
|
||||
relative_middle_x := float64(_ch.X()*16 - middle.X())
|
||||
relative_middle_z := float64(_ch.Z()*16 - middle.Z())
|
||||
px_pos := image.Point{ // bottom left corner of the chunk on the map
|
||||
|
@ -205,7 +195,7 @@ func (m *MapUI) Redraw() {
|
|||
}
|
||||
|
||||
if !m.img.Rect.Intersect(image.Rect(px_pos.X, px_pos.Y, px_pos.X+sz_chunk, px_pos.Y+sz_chunk)).Empty() {
|
||||
draw_img_scaled_pos(m.img, m.chunks_images[_ch], image.Point{
|
||||
draw_img_scaled_pos(m.img, m.renderedChunks[_ch], image.Point{
|
||||
px_pos.X, px_pos.Y,
|
||||
}, sz_chunk)
|
||||
}
|
||||
|
@ -219,17 +209,17 @@ func (m *MapUI) Redraw() {
|
|||
middle_block_x := chunks_x / 2 * 16
|
||||
middle_block_y := chunks_y / 2 * 16
|
||||
|
||||
for _ch := range m.chunks_images {
|
||||
for pos := range m.renderedChunks {
|
||||
px_pos := image.Point{
|
||||
X: int(_ch.X()*16) - middle_block_x + img2.Rect.Dx(),
|
||||
Y: int(_ch.Z()*16) - middle_block_y + img2.Rect.Dy(),
|
||||
X: int(pos.X()*16) - middle_block_x + img2.Rect.Dx(),
|
||||
Y: int(pos.Z()*16) - middle_block_y + img2.Rect.Dy(),
|
||||
}
|
||||
draw.Draw(img2, image.Rect(
|
||||
px_pos.X,
|
||||
px_pos.Y,
|
||||
px_pos.X+16,
|
||||
px_pos.Y+16,
|
||||
), m.chunks_images[_ch], image.Point{}, draw.Src)
|
||||
), m.renderedChunks[pos], image.Point{}, draw.Src)
|
||||
}
|
||||
buf := bytes.NewBuffer(nil)
|
||||
bmp.Encode(buf, img2)
|
||||
|
@ -238,8 +228,6 @@ func (m *MapUI) Redraw() {
|
|||
}
|
||||
|
||||
func (m *MapUI) SetChunk(pos protocol.ChunkPos, ch *chunk.Chunk) {
|
||||
m.render_lock.Lock()
|
||||
defer m.render_lock.Unlock()
|
||||
m.render_queue.PushBack(RenderElem{pos, ch})
|
||||
m.renderQueue.Enqueue(&RenderElem{pos, ch})
|
||||
m.SchedRedraw()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue