update gophertunnel, add void toggle, fix map zoom
This commit is contained in:
parent
90b3ef2604
commit
57e1ab483f
2
go.mod
2
go.mod
|
@ -21,7 +21,7 @@ require (
|
|||
|
||||
//replace github.com/df-mc/dragonfly => ./dragonfly
|
||||
|
||||
replace github.com/sandertv/gophertunnel => github.com/olebeck/gophertunnel v1.24.8-2
|
||||
replace github.com/sandertv/gophertunnel => github.com/olebeck/gophertunnel v1.24.8-3
|
||||
|
||||
replace github.com/df-mc/dragonfly => github.com/olebeck/dragonfly v0.8.2-6
|
||||
|
||||
|
|
2
go.sum
2
go.sum
|
@ -51,6 +51,8 @@ github.com/olebeck/gophertunnel v1.24.8-1 h1:ECZs6y/ZtvUjhIPlu3RjJr8c5QkOdxdQnoO
|
|||
github.com/olebeck/gophertunnel v1.24.8-1/go.mod h1:dMOw79FHxr2azEqiGH20AwdljisAN1kqwu5SjPBnZ5k=
|
||||
github.com/olebeck/gophertunnel v1.24.8-2 h1:T7WY2M/GrKTOgcH1RcDiB8LNlhK+PEzGdHSaYP4V518=
|
||||
github.com/olebeck/gophertunnel v1.24.8-2/go.mod h1:dMOw79FHxr2azEqiGH20AwdljisAN1kqwu5SjPBnZ5k=
|
||||
github.com/olebeck/gophertunnel v1.24.8-3 h1:qR5PCFWUAcUureCt36tLqaXWOjHVsFx66PiKm1obtkY=
|
||||
github.com/olebeck/gophertunnel v1.24.8-3/go.mod h1:dMOw79FHxr2azEqiGH20AwdljisAN1kqwu5SjPBnZ5k=
|
||||
github.com/olebeck/gophertunnel v1.24.8 h1:jdqBOABDAE1yISqzm9IxIrI+/lJApLBjTieynXUSalw=
|
||||
github.com/olebeck/gophertunnel v1.24.8/go.mod h1:dMOw79FHxr2azEqiGH20AwdljisAN1kqwu5SjPBnZ5k=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
|
|
39
map_item.go
39
map_item.go
|
@ -3,7 +3,6 @@ package main
|
|||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"math"
|
||||
"os"
|
||||
|
@ -40,7 +39,7 @@ var MAP_ITEM_PACKET packet.InventoryContent = packet.InventoryContent{
|
|||
|
||||
type MapUI struct {
|
||||
img *image.RGBA // rendered image
|
||||
zoom int // chunks per row
|
||||
minZoom bool // 1 pixel per block
|
||||
chunks_images map[protocol.ChunkPos]*image.RGBA // prerendered chunks
|
||||
needRedraw bool // when the map has updated this is true
|
||||
send_lock *sync.Mutex
|
||||
|
@ -49,7 +48,7 @@ type MapUI struct {
|
|||
func NewMapUI() MapUI {
|
||||
return MapUI{
|
||||
img: image.NewRGBA(image.Rect(0, 0, 128, 128)),
|
||||
zoom: 64,
|
||||
minZoom: true,
|
||||
chunks_images: make(map[protocol.ChunkPos]*image.RGBA),
|
||||
needRedraw: true,
|
||||
send_lock: &sync.Mutex{},
|
||||
|
@ -64,11 +63,7 @@ func (m *MapUI) Reset() {
|
|||
|
||||
// ChangeZoom adds to the zoom value and goes around to 32 once it hits 128
|
||||
func (m *MapUI) ChangeZoom() {
|
||||
if m.zoom >= 128 {
|
||||
m.zoom = 32 // min
|
||||
} else {
|
||||
m.zoom += 32
|
||||
}
|
||||
m.minZoom = !m.minZoom
|
||||
m.SchedRedraw()
|
||||
}
|
||||
|
||||
|
@ -121,15 +116,17 @@ func (m *MapUI) Redraw(w *WorldState) {
|
|||
|
||||
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 := math.Min(16*math.Ceil(math.Min(float64(chunks_x), float64(m.zoom))/16), 32) // either zoom or how many there actually are
|
||||
px_per_block := float64(128 / chunks_per_line / 16) // how many pixels per block
|
||||
chunks_per_line := 16 * math.Ceil(math.Min(float64(chunks_x), 32)/16)
|
||||
if m.minZoom {
|
||||
chunks_per_line = 8
|
||||
}
|
||||
px_per_block := float64(128 / chunks_per_line / 16) // how many pixels per block
|
||||
sz_chunk := int(math.Ceil(px_per_block * 16))
|
||||
|
||||
for i := 0; i < len(m.img.Pix); i++ { // clear canvas
|
||||
m.img.Pix[i] = 0
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
for _ch := range m.chunks_images {
|
||||
relative_middle_x := float64(_ch.X()*16 - middle.X())
|
||||
relative_middle_z := float64(_ch.Z()*16 - middle.Z())
|
||||
|
@ -137,9 +134,8 @@ func (m *MapUI) Redraw(w *WorldState) {
|
|||
X: int(math.Floor(relative_middle_x*px_per_block)) + 64,
|
||||
Y: int(math.Floor(relative_middle_z*px_per_block)) + 64,
|
||||
}
|
||||
sz_chunk := int(math.Ceil(px_per_block * 16))
|
||||
px_upper := px_pos.Add(image.Point{sz_chunk, sz_chunk})
|
||||
if px_pos.In(m.img.Rect) || px_upper.In(m.img.Rect) {
|
||||
|
||||
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{
|
||||
px_pos.X, px_pos.Y,
|
||||
}, sz_chunk)
|
||||
|
@ -168,7 +164,7 @@ func (m *MapUI) Redraw(w *WorldState) {
|
|||
}
|
||||
buf := bytes.NewBuffer(nil)
|
||||
bmp.Encode(buf, img2)
|
||||
os.WriteFile("test.bmp", buf.Bytes(), 0777)
|
||||
os.WriteFile("test.bmp", buf.Bytes(), 0o777)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,21 +180,12 @@ func (m *MapUI) Send(w *WorldState) error {
|
|||
m.Redraw(w)
|
||||
}
|
||||
|
||||
// (ugh)
|
||||
pixels := make([][]color.RGBA, 128)
|
||||
for y := 0; y < 128; y++ {
|
||||
pixels[y] = make([]color.RGBA, 128)
|
||||
for x := 0; x < 128; x++ {
|
||||
pixels[y][x] = m.img.At(x, y).(color.RGBA)
|
||||
}
|
||||
}
|
||||
|
||||
m.send_lock.Unlock()
|
||||
return w.ClientConn.WritePacket(&packet.ClientBoundMapItemData{
|
||||
MapID: VIEW_MAP_ID,
|
||||
Width: 128,
|
||||
Height: 128,
|
||||
Pixels: pixels,
|
||||
Pixels: img2rgba(m.img),
|
||||
UpdateFlags: 2,
|
||||
})
|
||||
}
|
||||
|
|
38
utils.go
38
utils.go
|
@ -8,6 +8,8 @@ import (
|
|||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"io"
|
||||
"io/fs"
|
||||
"log"
|
||||
|
@ -18,7 +20,7 @@ import (
|
|||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/sandertv/gophertunnel/minecraft"
|
||||
//"github.com/sandertv/gophertunnel/minecraft/gatherings"
|
||||
|
@ -179,6 +181,7 @@ func (p dummyProto) Packets() packet.Pool { return packet.NewPool() }
|
|||
func (p dummyProto) ConvertToLatest(pk packet.Packet, _ *minecraft.Conn) []packet.Packet {
|
||||
return []packet.Packet{pk}
|
||||
}
|
||||
|
||||
func (p dummyProto) ConvertFromLatest(pk packet.Packet, _ *minecraft.Conn) []packet.Packet {
|
||||
return []packet.Packet{pk}
|
||||
}
|
||||
|
@ -241,17 +244,17 @@ func create_proxy(ctx context.Context, server_address string) (l *minecraft.List
|
|||
clientConn.Close()
|
||||
l.Close()
|
||||
})
|
||||
|
||||
go func() {
|
||||
for i := 0; i < 10; i++ {
|
||||
time.Sleep(1 * time.Second)
|
||||
clientConn.WritePacket(&packet.Text{
|
||||
TextType: packet.TextTypeTip,
|
||||
Message: a + "\n\n\n\n\n\n",
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
/*
|
||||
go func() {
|
||||
for i := 0; i < 10; i++ {
|
||||
time.Sleep(1 * time.Second)
|
||||
clientConn.WritePacket(&packet.Text{
|
||||
TextType: packet.TextTypeTip,
|
||||
Message: a + "\n\n\n\n\n\n",
|
||||
})
|
||||
}
|
||||
}()
|
||||
*/
|
||||
return l, clientConn, serverConn, nil
|
||||
}
|
||||
|
||||
|
@ -337,9 +340,9 @@ func unpack_zip(r io.ReaderAt, size int64, unpack_folder string) {
|
|||
for _, src_file := range zr.File {
|
||||
out_path := path.Join(unpack_folder, src_file.Name)
|
||||
if src_file.Mode().IsDir() {
|
||||
os.Mkdir(out_path, 0755)
|
||||
os.Mkdir(out_path, 0o755)
|
||||
} else {
|
||||
os.MkdirAll(path.Dir(out_path), 0755)
|
||||
os.MkdirAll(path.Dir(out_path), 0o755)
|
||||
fr, _ := src_file.Open()
|
||||
f, _ := os.Create(path.Join(unpack_folder, src_file.Name))
|
||||
io.Copy(f, fr)
|
||||
|
@ -428,3 +431,10 @@ func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) {
|
|||
}
|
||||
fmt.Printf("%s 0x%x, %s\n", dir, pk.ID(), pk_name)
|
||||
}
|
||||
|
||||
func img2rgba(img *image.RGBA) []color.RGBA {
|
||||
header := *(*reflect.SliceHeader)(unsafe.Pointer(&img.Pix))
|
||||
header.Len /= 4
|
||||
header.Cap /= 4
|
||||
return *(*[]color.RGBA)(unsafe.Pointer(&header))
|
||||
}
|
||||
|
|
97
world.go
97
world.go
|
@ -72,25 +72,60 @@ func NewWorldState() *WorldState {
|
|||
}
|
||||
}
|
||||
|
||||
var setname_command = protocol.Command{
|
||||
Name: "setname",
|
||||
Description: "set user defined name for this world",
|
||||
Overloads: []protocol.CommandOverload{
|
||||
{
|
||||
Parameters: []protocol.CommandParameter{
|
||||
type IngameCommand struct {
|
||||
exec func(w *WorldState, cmdline []string) bool
|
||||
cmd protocol.Command
|
||||
}
|
||||
|
||||
var IngameCommands = map[string]IngameCommand{
|
||||
"setname": {
|
||||
exec: setnameCommand,
|
||||
cmd: protocol.Command{
|
||||
Name: "setname",
|
||||
Description: "set user defined name for this world",
|
||||
Overloads: []protocol.CommandOverload{
|
||||
{
|
||||
Name: "name",
|
||||
Type: protocol.CommandArgTypeFilepath,
|
||||
Optional: false,
|
||||
Parameters: []protocol.CommandParameter{
|
||||
{
|
||||
Name: "name",
|
||||
Type: protocol.CommandArgTypeFilepath,
|
||||
Optional: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"void": {
|
||||
exec: toggleVoid,
|
||||
cmd: protocol.Command{
|
||||
Name: "void",
|
||||
Description: "toggle if void generator should be used",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var black_16x16 = image.NewRGBA(image.Rect(0, 0, 16, 16))
|
||||
func setnameCommand(w *WorldState, cmdline []string) bool {
|
||||
w.WorldName = strings.Join(cmdline, " ")
|
||||
send_message(w.ClientConn, fmt.Sprintf("worldName is now: %s", w.WorldName))
|
||||
return true
|
||||
}
|
||||
|
||||
func toggleVoid(w *WorldState, cmdline []string) bool {
|
||||
w.voidgen = !w.voidgen
|
||||
send_message(w.ClientConn, fmt.Sprintf("using void generator: %t", w.voidgen))
|
||||
return true
|
||||
}
|
||||
|
||||
var (
|
||||
black_16x16 = image.NewRGBA(image.Rect(0, 0, 16, 16))
|
||||
Offset_table [24]protocol.SubChunkOffset
|
||||
)
|
||||
|
||||
func init() {
|
||||
for i := range Offset_table {
|
||||
Offset_table[i] = protocol.SubChunkOffset{0, int8(i), 0}
|
||||
}
|
||||
draw.Draw(black_16x16, image.Rect(0, 0, 16, 16), image.Black, image.Point{}, draw.Src)
|
||||
cs := crc32.ChecksumIEEE([]byte(a))
|
||||
if cs != 0x9747c04f {
|
||||
|
@ -100,9 +135,9 @@ func init() {
|
|||
}
|
||||
|
||||
type WorldCMD struct {
|
||||
server_address string
|
||||
packs bool
|
||||
enableGenerator bool
|
||||
server_address string
|
||||
packs bool
|
||||
enableVoid bool
|
||||
}
|
||||
|
||||
func (*WorldCMD) Name() string { return "worlds" }
|
||||
|
@ -111,8 +146,9 @@ func (*WorldCMD) Synopsis() string { return "download a world from a server" }
|
|||
func (p *WorldCMD) SetFlags(f *flag.FlagSet) {
|
||||
f.StringVar(&p.server_address, "address", "", "remote server address")
|
||||
f.BoolVar(&p.packs, "packs", false, "save resourcepacks to the worlds")
|
||||
f.BoolVar(&p.enableGenerator, "gen", false, "if true, doesnt make the saved world a void world")
|
||||
f.BoolVar(&p.enableVoid, "void", true, "if false, saves with default flat generator")
|
||||
}
|
||||
|
||||
func (c *WorldCMD) Usage() string {
|
||||
return c.Name() + ": " + c.Synopsis() + "\n" + SERVER_ADDRESS_HELP
|
||||
}
|
||||
|
@ -168,16 +204,7 @@ func (w *WorldState) ProcessLevelChunk(pk *packet.LevelChunk) {
|
|||
} else {
|
||||
// request all the subchunks
|
||||
|
||||
var Offset_table = []protocol.SubChunkOffset{
|
||||
{0, 0, 0}, {0, 1, 0}, {0, 2, 0}, {0, 3, 0},
|
||||
{0, 4, 0}, {0, 5, 0}, {0, 6, 0}, {0, 7, 0},
|
||||
{0, 8, 0}, {0, 9, 0}, {0, 10, 0}, {0, 11, 0},
|
||||
{0, 12, 0}, {0, 13, 0}, {0, 14, 0}, {0, 15, 0},
|
||||
{0, 16, 0}, {0, 17, 0}, {0, 18, 0}, {0, 19, 0},
|
||||
{0, 20, 0}, {0, 21, 0}, {0, 22, 0}, {0, 23, 0},
|
||||
}
|
||||
|
||||
max := len(Offset_table) - 1
|
||||
max := w.Dim.Range().Height() / 16
|
||||
if pk.SubChunkRequestMode == protocol.SubChunkRequestModeLimited {
|
||||
max = int(pk.HighestSubChunk)
|
||||
}
|
||||
|
@ -227,7 +254,6 @@ func (w *WorldState) ProcessSubChunk(pk *packet.SubChunk) {
|
|||
func (w *WorldState) ProcessAnimate(pk *packet.Animate) {
|
||||
if pk.ActionType == packet.AnimateActionSwingArm {
|
||||
w.ui.ChangeZoom()
|
||||
send_popup(w.ClientConn, fmt.Sprintf("Zoom: %d", w.ui.zoom))
|
||||
w.ui.Send(w)
|
||||
}
|
||||
}
|
||||
|
@ -249,10 +275,9 @@ func (w *WorldState) ProcessChangeDimension(pk *packet.ChangeDimension) {
|
|||
|
||||
func (w *WorldState) ProcessCommand(pk *packet.CommandRequest) bool {
|
||||
cmd := strings.Split(pk.CommandLine, " ")
|
||||
if cmd[0] == "/setname" && len(cmd) >= 2 {
|
||||
w.WorldName = strings.Join(cmd[1:], " ")
|
||||
send_message(w.ClientConn, fmt.Sprintf("worldName is now: %s", w.WorldName))
|
||||
return true
|
||||
name := cmd[0][1:]
|
||||
if h, ok := IngameCommands[name]; ok {
|
||||
return h.exec(w, cmd[1:])
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -284,7 +309,9 @@ func (w *WorldState) SaveAndReset() {
|
|||
|
||||
// open world
|
||||
folder := path.Join("worlds", fmt.Sprintf("%s/%s", w.ServerName, w.WorldName))
|
||||
os.MkdirAll(folder, 0777)
|
||||
os.RemoveAll(folder)
|
||||
os.MkdirAll(folder, 0o777)
|
||||
|
||||
provider, err := mcdb.New(folder, opt.DefaultCompression)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -296,7 +323,7 @@ func (w *WorldState) SaveAndReset() {
|
|||
}
|
||||
|
||||
// save block nbt data
|
||||
var blockNBT = make(map[protocol.ChunkPos][]map[string]any)
|
||||
blockNBT := make(map[protocol.ChunkPos][]map[string]any)
|
||||
for scp, v := range w.blockNBT { // 3d to 2d
|
||||
cp := protocol.ChunkPos{scp.X(), scp.Z()}
|
||||
blockNBT[cp] = append(blockNBT[cp], v...)
|
||||
|
@ -403,7 +430,7 @@ func (w *WorldState) SaveAndReset() {
|
|||
for k, p := range w.packs {
|
||||
fmt.Printf("Adding resource pack: %s\n", k)
|
||||
pack_folder := path.Join(folder, "resource_packs", k)
|
||||
os.MkdirAll(pack_folder, 0755)
|
||||
os.MkdirAll(pack_folder, 0o755)
|
||||
data := make([]byte, p.Len())
|
||||
p.ReadAt(data, 0)
|
||||
unpack_zip(bytes.NewReader(data), int64(len(data)), pack_folder)
|
||||
|
@ -426,7 +453,7 @@ func (c *WorldCMD) handleConn(ctx context.Context, l *minecraft.Listener, cc, sc
|
|||
w.ServerName = server_name
|
||||
w.ClientConn = cc
|
||||
w.ServerConn = sc
|
||||
w.voidgen = !c.enableGenerator
|
||||
w.voidgen = c.enableVoid
|
||||
|
||||
if c.packs {
|
||||
fmt.Println("reformatting packs")
|
||||
|
@ -545,7 +572,9 @@ func (c *WorldCMD) handleConn(ctx context.Context, l *minecraft.Listener, cc, sc
|
|||
case *packet.SubChunk:
|
||||
w.ProcessSubChunk(pk)
|
||||
case *packet.AvailableCommands:
|
||||
pk.Commands = append(pk.Commands, setname_command)
|
||||
for _, ic := range IngameCommands {
|
||||
pk.Commands = append(pk.Commands, ic.cmd)
|
||||
}
|
||||
}
|
||||
|
||||
if err := w.ClientConn.WritePacket(pk); err != nil {
|
||||
|
|
Loading…
Reference in New Issue