add multiple zoom levels

This commit is contained in:
olebeck 2022-09-04 13:13:45 +02:00
parent 1415bdc9c6
commit 081a89a8f6
5 changed files with 66 additions and 65 deletions

View File

@ -36,21 +36,12 @@ jobs:
- uses: actions-ecosystem/action-get-latest-tag@v1
id: get-latest-tag
- name: Create Release
if: startsWith(github.ref, 'refs/tags/v')
uses: ncipollo/release-action@v1.10.0
with:
allowUpdates: true
artifacts: dist/*
tag: ${{ steps.get-latest-tag.outputs.tag }}
- name: update latest Release
if: "!(startsWith(github.ref, 'refs/tags/v'))"
uses: ncipollo/release-action@v1.10.0
with:
allowUpdates: true
artifacts: dist/*
tag: latest
tag: ${{ steps.get-latest-tag.outputs.tag }}
prerelease: true
removeArtifacts: true

View File

@ -7,10 +7,12 @@ import (
"math"
"os"
"sync"
"time"
"github.com/df-mc/dragonfly/server/world/chunk"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
"github.com/sirupsen/logrus"
"golang.org/x/image/bmp"
)
@ -39,19 +41,58 @@ var MAP_ITEM_PACKET packet.InventoryContent = packet.InventoryContent{
type MapUI struct {
img *image.RGBA // rendered image
minZoom bool // 1 pixel per block
zoomLevel int // pixels per chunk
chunks_images map[protocol.ChunkPos]*image.RGBA // prerendered chunks
needRedraw bool // when the map has updated this is true
send_lock *sync.Mutex
image_lock *sync.Mutex
ticker *time.Ticker
w *WorldState
}
func NewMapUI() MapUI {
func NewMapUI(w *WorldState) MapUI {
return MapUI{
img: image.NewRGBA(image.Rect(0, 0, 128, 128)),
minZoom: true,
zoomLevel: 16,
chunks_images: make(map[protocol.ChunkPos]*image.RGBA),
image_lock: &sync.Mutex{},
needRedraw: true,
send_lock: &sync.Mutex{},
w: w,
}
}
func (m *MapUI) Start() {
m.ticker = time.NewTicker(66 * time.Millisecond)
go func() {
for range m.ticker.C {
if m.needRedraw {
if !m.image_lock.TryLock() {
continue // dont send if send is in progress
}
m.needRedraw = false
m.Redraw()
m.image_lock.Unlock()
if m.w.proxy.client != nil {
if err := m.w.proxy.client.WritePacket(&packet.ClientBoundMapItemData{
MapID: VIEW_MAP_ID,
Width: 128,
Height: 128,
Pixels: img2rgba(m.img),
UpdateFlags: 2,
}); err != nil {
logrus.Error(err)
return
}
}
}
}
}()
}
func (m *MapUI) Stop() {
if m.ticker != nil {
m.ticker.Stop()
}
}
@ -63,7 +104,10 @@ func (m *MapUI) Reset() {
// ChangeZoom adds to the zoom value and goes around to 32 once it hits 128
func (m *MapUI) ChangeZoom() {
m.minZoom = !m.minZoom
m.zoomLevel /= 2
if m.zoomLevel == 0 {
m.zoomLevel = 16
}
m.SchedRedraw()
}
@ -90,7 +134,7 @@ 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(w *WorldState) {
func (m *MapUI) Redraw() {
// get the chunk coord bounds
min := protocol.ChunkPos{}
max := protocol.ChunkPos{}
@ -110,16 +154,16 @@ func (m *MapUI) Redraw(w *WorldState) {
}
middle := protocol.ChunkPos{
int32(w.PlayerPos.Position.X()),
int32(w.PlayerPos.Position.Z()),
int32(m.w.PlayerPos.Position.X()),
int32(m.w.PlayerPos.Position.Z()),
}
chunks_x := int(max[0] - min[0] + 1) // how many chunk lengths is x coordinate
chunks_y := int(max[1] - min[1] + 1)
chunks_per_line := 16 * math.Ceil(math.Min(float64(chunks_x), 32)/16)
if m.minZoom {
chunks_per_line = 8
}
total_width := 16 * math.Ceil(float64(chunks_x)/16)
chunks_per_line := math.Min(total_width, float64(128/m.zoomLevel))
px_per_block := float64(128 / chunks_per_line / 16) // how many pixels per block
sz_chunk := int(math.Ceil(px_per_block * 16))
@ -168,31 +212,6 @@ func (m *MapUI) Redraw(w *WorldState) {
}
}
// send
func (m *MapUI) Send(w *WorldState) error {
if !m.send_lock.TryLock() {
return nil // dont send if send is in progress
}
// redraw if needed
if m.needRedraw {
m.needRedraw = false
m.Redraw(w)
}
m.send_lock.Unlock()
if w.proxy.client != nil {
return w.proxy.client.WritePacket(&packet.ClientBoundMapItemData{
MapID: VIEW_MAP_ID,
Width: 128,
Height: 128,
Pixels: img2rgba(m.img),
UpdateFlags: 2,
})
}
return nil
}
func (m *MapUI) SetChunk(pos protocol.ChunkPos, ch *chunk.Chunk) {
var img *image.RGBA
if ch != nil {
@ -200,8 +219,8 @@ func (m *MapUI) SetChunk(pos protocol.ChunkPos, ch *chunk.Chunk) {
} else {
img = black_16x16
}
m.send_lock.Lock() // dont send while adding a chunk
m.image_lock.Lock() // dont send while adding a chunk
m.chunks_images[pos] = img
m.send_lock.Unlock()
m.image_lock.Unlock()
m.SchedRedraw()
}

View File

@ -8,7 +8,6 @@ import (
"time"
"unsafe"
"github.com/google/gopacket"
"github.com/google/gopacket/pcapgo"
"github.com/sandertv/gophertunnel/minecraft"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
@ -21,14 +20,6 @@ func SetUnexportedField(field reflect.Value, value interface{}) {
Set(reflect.ValueOf(value))
}
type PayloadDecoder struct {
Payload []byte
}
func (d PayloadDecoder) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
return nil
}
func create_replay_connection(ctx context.Context, log *logrus.Logger, filename string, onConnect ConnectCallback, packetCB PacketCallback) error {
log.Infof("Reading replay %s", filename)

Binary file not shown.

View File

@ -61,15 +61,16 @@ type WorldState struct {
}
func NewWorldState() *WorldState {
return &WorldState{
w := &WorldState{
chunks: make(map[protocol.ChunkPos]*chunk.Chunk),
blockNBT: make(map[protocol.SubChunkPos][]map[string]any),
entities: make(map[int64]world.SaveableEntity),
Dim: nil,
WorldName: "world",
PlayerPos: TPlayerPos{},
ui: NewMapUI(),
}
w.ui = NewMapUI(w)
return w
}
var dimension_ids = map[uint8]world.Dimension{
@ -233,7 +234,7 @@ func (w *WorldState) ProcessSubChunk(pk *packet.SubChunk) {
func (w *WorldState) ProcessAnimate(pk *packet.Animate) {
if pk.ActionType == packet.AnimateActionSwingArm {
w.ui.ChangeZoom()
w.ui.Send(w)
w.proxy.sendPopup(fmt.Sprintf("Zoom: %d", w.ui.zoomLevel))
}
}
@ -262,7 +263,6 @@ func (w *WorldState) SetPlayerPos(Position mgl32.Vec3, Pitch, Yaw, HeadYaw float
if int(last.Position.X()) != int(w.PlayerPos.Position.X()) || int(last.Position.Z()) != int(w.PlayerPos.Position.Z()) {
w.ui.SchedRedraw()
w.ui.Send(w)
}
}
@ -455,6 +455,7 @@ func (w *WorldState) OnConnect(proxy *ProxyContext) {
w.SaveAndReset()
})
w.ui.Start()
go func() { // send map item
select {
case <-w.ctx.Done():
@ -508,7 +509,7 @@ func (w *WorldState) ProcessPacketClient(pk packet.Packet) packet.Packet {
w.SetPlayerPos(pk.Position, pk.Pitch, pk.Yaw, pk.HeadYaw)
case *packet.MapInfoRequest:
if pk.MapID == VIEW_MAP_ID {
w.ui.Send(w)
w.ui.SchedRedraw()
pk = nil
}
case *packet.MobEquipment:
@ -527,7 +528,6 @@ func (w *WorldState) ProcessPacketServer(pk packet.Packet) packet.Packet {
w.ProcessChangeDimension(pk)
case *packet.LevelChunk:
w.ProcessLevelChunk(pk)
w.ui.Send(w)
w.proxy.sendPopup(fmt.Sprintf("%d chunks loaded\nname: %s", len(w.chunks), w.WorldName))
case *packet.SubChunk:
w.ProcessSubChunk(pk)