clean code
This commit is contained in:
parent
eb4125b8c1
commit
cd126dff3d
4
Makefile
4
Makefile
|
@ -21,10 +21,12 @@ endif
|
|||
BUILDS=\
|
||||
windows_amd64.exe\
|
||||
windows_arm64.exe\
|
||||
windows_arm32.exe\
|
||||
darwin_amd64\
|
||||
darwin_arm64\
|
||||
linux_amd64\
|
||||
linux_arm64
|
||||
linux_arm64\
|
||||
linux_arm32
|
||||
|
||||
|
||||
DISTS=$(BUILDS:%=$(NAME)_%)
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/sandertv/gophertunnel/minecraft/auth"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
var G_token_src oauth2.TokenSource
|
||||
|
||||
func GetTokenSource() oauth2.TokenSource {
|
||||
if G_token_src != nil {
|
||||
return G_token_src
|
||||
}
|
||||
token := get_token()
|
||||
G_token_src = auth.RefreshTokenSource(&token)
|
||||
new_token, err := G_token_src.Token()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !token.Valid() {
|
||||
fmt.Println("Refreshed token")
|
||||
write_token(new_token)
|
||||
}
|
||||
|
||||
return G_token_src
|
||||
}
|
||||
|
||||
var _G_xbl_token *auth.XBLToken
|
||||
|
||||
func GetXBLToken(ctx context.Context) *auth.XBLToken {
|
||||
if _G_xbl_token != nil {
|
||||
return _G_xbl_token
|
||||
}
|
||||
_token, err := GetTokenSource().Token()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_G_xbl_token, err = auth.RequestXBLToken(ctx, _token, "https://pocket.realms.minecraft.net/")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return _G_xbl_token
|
||||
}
|
||||
|
||||
func write_token(token *oauth2.Token) {
|
||||
buf, err := json.Marshal(token)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
os.WriteFile(TOKEN_FILE, buf, 0755)
|
||||
}
|
||||
|
||||
func get_token() oauth2.Token {
|
||||
var token oauth2.Token
|
||||
if _, err := os.Stat(TOKEN_FILE); err == nil {
|
||||
f, err := os.Open(TOKEN_FILE)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
if err := json.NewDecoder(f).Decode(&token); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
_token, err := auth.RequestLiveToken()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
write_token(_token)
|
||||
token = *_token
|
||||
}
|
||||
return token
|
||||
}
|
9
go.mod
9
go.mod
|
@ -10,10 +10,8 @@ require (
|
|||
github.com/google/subcommands v1.2.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/miekg/dns v1.1.50
|
||||
github.com/pidurentry/buttplug-go v0.0.0-20190410200554-0b2e068d769a
|
||||
github.com/sandertv/gophertunnel v1.24.0
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e
|
||||
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539
|
||||
golang.org/x/oauth2 v0.0.0-20220808172628-8227340efae7
|
||||
)
|
||||
|
||||
|
@ -23,22 +21,21 @@ require (
|
|||
|
||||
replace github.com/sandertv/gophertunnel => github.com/olebeck/gophertunnel v1.24.5
|
||||
|
||||
replace github.com/df-mc/dragonfly => github.com/olebeck/dragonfly v0.8.2-4
|
||||
replace github.com/df-mc/dragonfly => github.com/olebeck/dragonfly v0.8.2-5
|
||||
|
||||
require (
|
||||
github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/df-mc/atomic v1.10.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/gorilla/websocket v1.4.0 // indirect
|
||||
github.com/jinzhu/copier v0.3.5 // indirect
|
||||
github.com/jinzhu/copier v0.3.5
|
||||
github.com/klauspost/compress v1.15.9 // indirect
|
||||
github.com/muhammadmuzzammil1998/jsonc v1.0.0 // indirect
|
||||
github.com/sandertv/go-raknet v1.11.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
|
||||
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||
golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
|
||||
|
|
20
go.sum
20
go.sum
|
@ -1,8 +1,5 @@
|
|||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9 h1:/G0ghZwrhou0Wq21qc1vXXMm/t/aKWkALWwITptKbE0=
|
||||
github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9/go.mod h1:TOk10ahXejq9wkEaym3KPRNeuR/h5Jx+s8QRWIa2oTM=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -29,8 +26,6 @@ github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN
|
|||
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
|
||||
|
@ -42,16 +37,8 @@ github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
|||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/muhammadmuzzammil1998/jsonc v1.0.0 h1:8o5gBQn4ZA3NBA9DlTujCj2a4w0tqWrPVjDwhzkgTIs=
|
||||
github.com/muhammadmuzzammil1998/jsonc v1.0.0/go.mod h1:saF2fIVw4banK0H4+/EuqfFLpRnoy5S+ECwTOCcRcSU=
|
||||
github.com/olebeck/dragonfly v0.8.2-1 h1:hC0iWH7WFOpsvR3XeTwJSRKtKO+GhEcMq+H+DHUwHWc=
|
||||
github.com/olebeck/dragonfly v0.8.2-1/go.mod h1:xgpCDhHoP03RygPaTrzzDwsSTcEZhxNPMV3CAxETj+I=
|
||||
github.com/olebeck/dragonfly v0.8.2-2 h1:rIUAEJx2ZeQhsRFNkHXrfYR3Zl85WB5spS/SZEH91ag=
|
||||
github.com/olebeck/dragonfly v0.8.2-2/go.mod h1:xgpCDhHoP03RygPaTrzzDwsSTcEZhxNPMV3CAxETj+I=
|
||||
github.com/olebeck/dragonfly v0.8.2-3 h1:qzcNc76U1E8RXpg98Fv02kxFulhsR/TWcKArqRY+xdY=
|
||||
github.com/olebeck/dragonfly v0.8.2-3/go.mod h1:xgpCDhHoP03RygPaTrzzDwsSTcEZhxNPMV3CAxETj+I=
|
||||
github.com/olebeck/dragonfly v0.8.2-4 h1:K//DtE5R4DjcVB791y6Nx1Vg0/KzQwYoBb72ukUbdBA=
|
||||
github.com/olebeck/dragonfly v0.8.2-4/go.mod h1:xgpCDhHoP03RygPaTrzzDwsSTcEZhxNPMV3CAxETj+I=
|
||||
github.com/olebeck/gophertunnel v1.24.4 h1:nX7Std61XpXW4VP7KKd2RvinRwx1nGB5l8QnbwrArLE=
|
||||
github.com/olebeck/gophertunnel v1.24.4/go.mod h1:dMOw79FHxr2azEqiGH20AwdljisAN1kqwu5SjPBnZ5k=
|
||||
github.com/olebeck/dragonfly v0.8.2-5 h1:0G9dhTQ1Oae1KnmgRjNeqYPQ/PsLFGwMWtQYAJkPICI=
|
||||
github.com/olebeck/dragonfly v0.8.2-5/go.mod h1:xgpCDhHoP03RygPaTrzzDwsSTcEZhxNPMV3CAxETj+I=
|
||||
github.com/olebeck/gophertunnel v1.24.5 h1:FtpHzfp833qQGBSJtKysSmRzFzsSheq5l61d5gTp03s=
|
||||
github.com/olebeck/gophertunnel v1.24.5/go.mod h1:dMOw79FHxr2azEqiGH20AwdljisAN1kqwu5SjPBnZ5k=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
|
@ -59,15 +46,12 @@ github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
|||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pidurentry/buttplug-go v0.0.0-20190410200554-0b2e068d769a h1:DIcuKv1jCe8vf10lqdD/5hZ2nnb3qYn0JycyXSnvE4s=
|
||||
github.com/pidurentry/buttplug-go v0.0.0-20190410200554-0b2e068d769a/go.mod h1:oJXeBWse2BXoaZYRQFJ5p1Ut69KYf6SfiUJ/oaYnOhQ=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
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/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
|
|
85
main.go
85
main.go
|
@ -2,23 +2,15 @@ package main
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"syscall"
|
||||
|
||||
"github.com/google/subcommands"
|
||||
"github.com/sandertv/gophertunnel/minecraft/auth"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
const TOKEN_FILE = "token.json"
|
||||
|
@ -27,63 +19,6 @@ var G_debug bool
|
|||
var G_preload_packs bool
|
||||
var G_exit []func() = []func(){}
|
||||
|
||||
var pool = packet.NewPool()
|
||||
|
||||
var muted_packets = []string{
|
||||
"*packet.UpdateBlock",
|
||||
"*packet.MoveActorAbsolute",
|
||||
"*packet.SetActorMotion",
|
||||
"*packet.SetTime",
|
||||
"*packet.RemoveActor",
|
||||
"*packet.AddActor",
|
||||
"*packet.UpdateAttributes",
|
||||
"*packet.Interact",
|
||||
"*packet.LevelEvent",
|
||||
"*packet.SetActorData",
|
||||
"*packet.MoveActorDelta",
|
||||
"*packet.MovePlayer",
|
||||
"*packet.BlockActorData",
|
||||
"*packet.PlayerAuthInput",
|
||||
"*packet.LevelChunk",
|
||||
"*packet.LevelSoundEvent",
|
||||
"*packet.ActorEvent",
|
||||
"*packet.NetworkChunkPublisherUpdate",
|
||||
"*packet.UpdateSubChunkBlocks",
|
||||
"*packet.SubChunk",
|
||||
"*packet.SubChunkRequest",
|
||||
"*packet.Animate",
|
||||
"*packet.NetworkStackLatency",
|
||||
}
|
||||
|
||||
func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) {
|
||||
var pk packet.Packet
|
||||
buf := bytes.NewBuffer(payload)
|
||||
r := protocol.NewReader(buf, 0)
|
||||
pkFunc, ok := pool[header.PacketID]
|
||||
if !ok {
|
||||
pk = &packet.Unknown{PacketID: header.PacketID}
|
||||
} else {
|
||||
pk = pkFunc()
|
||||
}
|
||||
pk.Unmarshal(r)
|
||||
|
||||
dir := "S->C"
|
||||
src_addr, _, _ := net.SplitHostPort(src.String())
|
||||
if IPPrivate(net.ParseIP(src_addr)) {
|
||||
dir = "C->S"
|
||||
}
|
||||
|
||||
pk_name := reflect.TypeOf(pk).String()
|
||||
if slices.Contains(muted_packets, pk_name) {
|
||||
return
|
||||
}
|
||||
switch pk := pk.(type) {
|
||||
case *packet.Disconnect:
|
||||
fmt.Printf("Disconnect: %s", pk.Message)
|
||||
}
|
||||
fmt.Printf("%s 0x%x, %s\n", dir, pk.ID(), pk_name)
|
||||
}
|
||||
|
||||
func exit() {
|
||||
fmt.Printf("\nExiting\n")
|
||||
for i := len(G_exit) - 1; i >= 0; i-- { // go through cleanup functions reversed
|
||||
|
@ -99,26 +34,6 @@ func register_command(sub subcommands.Command) {
|
|||
valid_cmds[sub.Name()] = sub.Synopsis()
|
||||
}
|
||||
|
||||
var G_token_src oauth2.TokenSource
|
||||
|
||||
func GetTokenSource() oauth2.TokenSource {
|
||||
if G_token_src != nil {
|
||||
return G_token_src
|
||||
}
|
||||
token := get_token()
|
||||
G_token_src = auth.RefreshTokenSource(&token)
|
||||
new_token, err := G_token_src.Token()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !token.Valid() {
|
||||
fmt.Println("Refreshed token")
|
||||
write_token(new_token)
|
||||
}
|
||||
|
||||
return G_token_src
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
|
|
36
map_item.go
36
map_item.go
|
@ -1,22 +1,20 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"math"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/df-mc/dragonfly/server/world/chunk"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||
"golang.org/x/image/bmp"
|
||||
)
|
||||
|
||||
const VIEW_MAP_ID = 0x424242
|
||||
|
||||
// packet to tell the client that it has a map with id 0x424242 in the offhand
|
||||
var MAP_ITEM_PACKET packet.InventoryContent = packet.InventoryContent{
|
||||
WindowID: 119,
|
||||
Content: []protocol.ItemInstance{
|
||||
|
@ -38,10 +36,10 @@ var MAP_ITEM_PACKET packet.InventoryContent = packet.InventoryContent{
|
|||
}
|
||||
|
||||
type MapUI struct {
|
||||
img *image.RGBA
|
||||
zoom int
|
||||
chunks_images map[protocol.ChunkPos]*image.RGBA // rendered those chunks
|
||||
needRedraw bool
|
||||
img *image.RGBA // rendered image
|
||||
zoom int // chunks per row
|
||||
chunks_images map[protocol.ChunkPos]*image.RGBA // prerendered chunks
|
||||
needRedraw bool // when the map has updated this is true
|
||||
send_lock *sync.Mutex
|
||||
}
|
||||
|
||||
|
@ -55,11 +53,13 @@ func NewMapUI() MapUI {
|
|||
}
|
||||
}
|
||||
|
||||
// Reset resets the map to inital state
|
||||
func (m *MapUI) Reset() {
|
||||
m.chunks_images = make(map[protocol.ChunkPos]*image.RGBA)
|
||||
m.needRedraw = true
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -69,6 +69,7 @@ func (m *MapUI) ChangeZoom() {
|
|||
m.SchedRedraw()
|
||||
}
|
||||
|
||||
// SchedRedraw tells the map to redraw the next time its sent
|
||||
func (m *MapUI) SchedRedraw() {
|
||||
m.needRedraw = true
|
||||
}
|
||||
|
@ -97,8 +98,8 @@ func (m *MapUI) Redraw(w *WorldState) {
|
|||
}
|
||||
}
|
||||
|
||||
chunks_x := int(max[0] - min[0] + 1) // how many chunk lengths is x
|
||||
chunks_per_line := math.Min(float64(chunks_x), float64(m.zoom)) // at max 64 chunks per line
|
||||
chunks_x := int(max[0] - min[0] + 1) // how many chunk lengths is x coordinate
|
||||
chunks_per_line := math.Min(float64(chunks_x), float64(m.zoom)) // either zoom or how many there actually are
|
||||
px_per_chunk := int(128 / chunks_per_line) // how many pixels does every chunk get
|
||||
|
||||
for i := 0; i < len(m.img.Pix); i++ { // clear canvas
|
||||
|
@ -106,7 +107,7 @@ func (m *MapUI) Redraw(w *WorldState) {
|
|||
}
|
||||
|
||||
for _ch := range m.chunks_images {
|
||||
px_pos := image.Point{
|
||||
px_pos := image.Point{ // bottom left corner of the chunk on the map
|
||||
X: (int(_ch.X()-middle.X()) * px_per_chunk) + 64,
|
||||
Y: (int(_ch.Z()-middle.Z()) * px_per_chunk) + 64,
|
||||
}
|
||||
|
@ -125,12 +126,13 @@ func (m *MapUI) Redraw(w *WorldState) {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
buf := bytes.NewBuffer(nil)
|
||||
bmp.Encode(buf, m.img)
|
||||
os.WriteFile("test.bmp", buf.Bytes(), 0777)
|
||||
}
|
||||
/*
|
||||
{
|
||||
buf := bytes.NewBuffer(nil)
|
||||
bmp.Encode(buf, m.img)
|
||||
os.WriteFile("test.bmp", buf.Bytes(), 0777)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// send
|
||||
|
@ -139,11 +141,13 @@ func (m *MapUI) Send(w *WorldState) error {
|
|||
return nil // dont send if send is in progress
|
||||
}
|
||||
|
||||
// redraw if needed
|
||||
if m.needRedraw {
|
||||
m.needRedraw = false
|
||||
m.Redraw(w)
|
||||
}
|
||||
|
||||
// (ugh)
|
||||
pixels := make([][]color.RGBA, 128)
|
||||
for y := 0; y < 128; y++ {
|
||||
pixels[y] = make([]color.RGBA, 128)
|
||||
|
|
7
merge.go
7
merge.go
|
@ -49,16 +49,17 @@ func (c *MergeCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{
|
|||
if errors.Is(err, os.ErrNotExist) {
|
||||
fmt.Fprintf(os.Stderr, "%s not found\n", world_name)
|
||||
}
|
||||
if !s.IsDir() {
|
||||
if !s.IsDir() { // if its a zip temporarily unpack it to read it
|
||||
f, _ := os.Open(world_name)
|
||||
world_name += "_unpack"
|
||||
unpack_zip(f, s.Size(), world_name)
|
||||
}
|
||||
// merge it into the state
|
||||
err = c.merge_worlds(prov_out, world_name, first)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s %s\n", world_name, err)
|
||||
}
|
||||
if !s.IsDir() {
|
||||
if !s.IsDir() { // remove temp folder again
|
||||
os.RemoveAll(world_name)
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +75,7 @@ func (c *MergeCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{
|
|||
return 1
|
||||
}
|
||||
|
||||
//os.RemoveAll(out_name)
|
||||
os.RemoveAll(out_name)
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
18
realms.go
18
realms.go
|
@ -11,7 +11,6 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/google/subcommands"
|
||||
"github.com/sandertv/gophertunnel/minecraft/auth"
|
||||
)
|
||||
|
||||
type Realm struct {
|
||||
|
@ -22,23 +21,6 @@ type Realm struct {
|
|||
State string `json:"state"`
|
||||
}
|
||||
|
||||
var _G_xbl_token *auth.XBLToken
|
||||
|
||||
func GetXBLToken(ctx context.Context) *auth.XBLToken {
|
||||
if _G_xbl_token != nil {
|
||||
return _G_xbl_token
|
||||
}
|
||||
_token, err := GetTokenSource().Token()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_G_xbl_token, err = auth.RequestXBLToken(ctx, _token, "https://pocket.realms.minecraft.net/")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return _G_xbl_token
|
||||
}
|
||||
|
||||
func realms_get(path string) ([]byte, error) {
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("https://pocket.realms.minecraft.net/%s", path), nil)
|
||||
if err != nil {
|
||||
|
|
|
@ -60,7 +60,7 @@ func (c *SkinProxyCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interf
|
|||
}
|
||||
return
|
||||
}
|
||||
process_packet_skins(clientConn, out_path, pk)
|
||||
process_packet_skins(clientConn, out_path, pk, c.filter)
|
||||
|
||||
if err = clientConn.WritePacket(pk); err != nil {
|
||||
return
|
||||
|
|
77
skins.go
77
skins.go
|
@ -24,9 +24,9 @@ type Skin struct {
|
|||
protocol.Skin
|
||||
}
|
||||
|
||||
// WriteGeometry writes the geometry json for the skin to output_path
|
||||
func (skin *Skin) WriteGeometry(output_path string) error {
|
||||
os.Mkdir(output_path, 0755)
|
||||
f, err := os.Create(path.Join(output_path, "geometry.json"))
|
||||
f, err := os.Create(output_path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write Geometry %s: %s", output_path, err)
|
||||
}
|
||||
|
@ -35,9 +35,9 @@ func (skin *Skin) WriteGeometry(output_path string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// WriteCape writes the cape as a png at output_path
|
||||
func (skin *Skin) WriteCape(output_path string) error {
|
||||
os.Mkdir(output_path, 0755)
|
||||
f, err := os.Create(path.Join(output_path, "cape.png"))
|
||||
f, err := os.Create(output_path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write Cape %s: %s", output_path, err)
|
||||
}
|
||||
|
@ -51,13 +51,15 @@ func (skin *Skin) WriteCape(output_path string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// WriteAnimations writes skin animations to the folder
|
||||
func (skin *Skin) WriteAnimations(output_path string) error {
|
||||
os.Mkdir(output_path, 0755)
|
||||
return fmt.Errorf("%s has animations (unimplemented)", output_path)
|
||||
fmt.Printf("Warn: %s has animations (unimplemented)", output_path)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteTexture writes the main texture for this skin to a file
|
||||
func (skin *Skin) WriteTexture(output_path string) error {
|
||||
f, err := os.Create(output_path + ".png")
|
||||
f, err := os.Create(output_path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing Texture: %s", err)
|
||||
}
|
||||
|
@ -71,39 +73,39 @@ func (skin *Skin) WriteTexture(output_path string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Write writes all data for this skin to a folder
|
||||
func (skin *Skin) Write(output_path, name string) error {
|
||||
complex := false
|
||||
skin_dir := path.Join(output_path, name)
|
||||
if len(skin.SkinGeometry) > 0 {
|
||||
if err := skin.WriteGeometry(skin_dir); err != nil {
|
||||
return err
|
||||
}
|
||||
complex = true
|
||||
}
|
||||
if len(skin.CapeData) > 0 {
|
||||
if err := skin.WriteCape(skin_dir); err != nil {
|
||||
return err
|
||||
}
|
||||
complex = true
|
||||
}
|
||||
if len(skin.Animations) > 0 {
|
||||
if err := skin.WriteAnimations(skin_dir); err != nil {
|
||||
return err
|
||||
}
|
||||
complex = true
|
||||
}
|
||||
|
||||
var err error
|
||||
have_geometry, have_cape, have_animations := len(skin.SkinGeometry) > 0, len(skin.CapeData) > 0, len(skin.Animations) > 0
|
||||
complex := have_geometry || have_cape || have_animations
|
||||
|
||||
if complex {
|
||||
err = skin.WriteTexture(path.Join(skin_dir, "skin"))
|
||||
os.MkdirAll(skin_dir, 0755)
|
||||
if have_geometry {
|
||||
if err := skin.WriteGeometry(path.Join(skin_dir, "geometry.json")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if have_cape {
|
||||
if err := skin.WriteCape(path.Join(skin_dir, "cape.png")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if have_animations {
|
||||
if err := skin.WriteAnimations(skin_dir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return skin.WriteTexture(path.Join(skin_dir, "skin.png"))
|
||||
} else {
|
||||
err = skin.WriteTexture(skin_dir)
|
||||
return skin.WriteTexture(skin_dir + ".png")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
var name_regexp = regexp.MustCompile(`§.`)
|
||||
|
||||
// cleans name so it can be used as a filename
|
||||
func cleanup_name(name string) string {
|
||||
name = strings.Split(name, "\n")[0]
|
||||
var _tmp struct {
|
||||
|
@ -118,8 +120,10 @@ func cleanup_name(name string) string {
|
|||
return name
|
||||
}
|
||||
|
||||
func write_skin(output_path, name string, skin protocol.Skin) {
|
||||
if !strings.HasPrefix(name, skin_filter_player) {
|
||||
// puts the skin at output_path if the filter matches it
|
||||
// internally converts the struct so it can use the extra methods
|
||||
func write_skin(output_path, name string, skin protocol.Skin, filter string) {
|
||||
if !strings.HasPrefix(name, filter) {
|
||||
return
|
||||
}
|
||||
fmt.Printf("Writing skin for %s\n", name)
|
||||
|
@ -129,12 +133,11 @@ func write_skin(output_path, name string, skin protocol.Skin) {
|
|||
}
|
||||
}
|
||||
|
||||
var skin_filter_player string // who to filter
|
||||
var skin_players = make(map[string]string)
|
||||
var skin_player_counts = make(map[string]int)
|
||||
var processed_skins = make(map[string]bool)
|
||||
|
||||
func process_packet_skins(conn *minecraft.Conn, out_path string, pk packet.Packet) {
|
||||
func process_packet_skins(conn *minecraft.Conn, out_path string, pk packet.Packet, filter string) {
|
||||
switch _pk := pk.(type) {
|
||||
case *packet.PlayerSkin:
|
||||
name := skin_players[_pk.UUID.String()]
|
||||
|
@ -143,7 +146,7 @@ func process_packet_skins(conn *minecraft.Conn, out_path string, pk packet.Packe
|
|||
}
|
||||
skin_player_counts[name]++
|
||||
name = fmt.Sprintf("%s_%d", name, skin_player_counts[name])
|
||||
write_skin(out_path, name, _pk.Skin)
|
||||
write_skin(out_path, name, _pk.Skin, filter)
|
||||
case *packet.PlayerList:
|
||||
if _pk.ActionType == 1 { // remove
|
||||
return
|
||||
|
@ -156,7 +159,7 @@ func process_packet_skins(conn *minecraft.Conn, out_path string, pk packet.Packe
|
|||
if _, ok := processed_skins[name]; ok {
|
||||
continue
|
||||
}
|
||||
write_skin(out_path, name, player.Skin)
|
||||
write_skin(out_path, name, player.Skin, filter)
|
||||
skin_players[player.UUID.String()] = name
|
||||
processed_skins[name] = true
|
||||
if conn != nil {
|
||||
|
@ -213,7 +216,7 @@ func (c *SkinCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}
|
|||
if err != nil {
|
||||
return 1
|
||||
}
|
||||
process_packet_skins(nil, out_path, pk)
|
||||
process_packet_skins(nil, out_path, pk, c.filter)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
112
utils.go
112
utils.go
|
@ -7,7 +7,6 @@ import (
|
|||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
|
@ -16,18 +15,17 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-gl/mathgl/mgl32"
|
||||
"github.com/go-gl/mathgl/mgl64"
|
||||
"github.com/sandertv/gophertunnel/minecraft"
|
||||
"github.com/sandertv/gophertunnel/minecraft/auth"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol/login"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||
"github.com/sandertv/gophertunnel/minecraft/resource"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
const SERVER_ADDRESS_HELP = `accepted server address formats:
|
||||
|
@ -45,42 +43,11 @@ func send_popup(conn *minecraft.Conn, text string) {
|
|||
})
|
||||
}
|
||||
|
||||
func v32tov64(in mgl32.Vec3) mgl64.Vec3 {
|
||||
return mgl64.Vec3{
|
||||
float64(in[0]),
|
||||
float64(in[1]),
|
||||
float64(in[2]),
|
||||
}
|
||||
}
|
||||
|
||||
func write_token(token *oauth2.Token) {
|
||||
buf, err := json.Marshal(token)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
os.WriteFile(TOKEN_FILE, buf, 0755)
|
||||
}
|
||||
|
||||
func get_token() oauth2.Token {
|
||||
var token oauth2.Token
|
||||
if _, err := os.Stat(TOKEN_FILE); err == nil {
|
||||
f, err := os.Open(TOKEN_FILE)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
if err := json.NewDecoder(f).Decode(&token); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
_token, err := auth.RequestLiveToken()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
write_token(_token)
|
||||
token = *_token
|
||||
}
|
||||
return token
|
||||
func send_message(conn *minecraft.Conn, text string) {
|
||||
conn.WritePacket(&packet.Text{
|
||||
TextType: packet.TextTypeSystem,
|
||||
Message: "§8[§bBedrocktool§8]§r " + text,
|
||||
})
|
||||
}
|
||||
|
||||
func server_input(server string) (address, name string, err error) {
|
||||
|
@ -128,6 +95,8 @@ func init() {
|
|||
a = string(d)
|
||||
}
|
||||
|
||||
// connections
|
||||
|
||||
func server_url_to_name(server string) string {
|
||||
host, _, err := net.SplitHostPort(server)
|
||||
if err != nil {
|
||||
|
@ -261,6 +230,8 @@ var PrivateIPNetworks = []net.IPNet{
|
|||
},
|
||||
}
|
||||
|
||||
// strings & ips
|
||||
|
||||
// check if ip is private
|
||||
func IPPrivate(ip net.IP) bool {
|
||||
for _, ipNet := range PrivateIPNetworks {
|
||||
|
@ -358,3 +329,62 @@ func zip_folder(filename, folder string) error {
|
|||
f.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
// debug
|
||||
|
||||
var pool = packet.NewPool()
|
||||
|
||||
var muted_packets = []string{
|
||||
"*packet.UpdateBlock",
|
||||
"*packet.MoveActorAbsolute",
|
||||
"*packet.SetActorMotion",
|
||||
"*packet.SetTime",
|
||||
"*packet.RemoveActor",
|
||||
"*packet.AddActor",
|
||||
"*packet.UpdateAttributes",
|
||||
"*packet.Interact",
|
||||
"*packet.LevelEvent",
|
||||
"*packet.SetActorData",
|
||||
"*packet.MoveActorDelta",
|
||||
"*packet.MovePlayer",
|
||||
"*packet.BlockActorData",
|
||||
"*packet.PlayerAuthInput",
|
||||
"*packet.LevelChunk",
|
||||
"*packet.LevelSoundEvent",
|
||||
"*packet.ActorEvent",
|
||||
"*packet.NetworkChunkPublisherUpdate",
|
||||
"*packet.UpdateSubChunkBlocks",
|
||||
"*packet.SubChunk",
|
||||
"*packet.SubChunkRequest",
|
||||
"*packet.Animate",
|
||||
"*packet.NetworkStackLatency",
|
||||
}
|
||||
|
||||
func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) {
|
||||
var pk packet.Packet
|
||||
buf := bytes.NewBuffer(payload)
|
||||
r := protocol.NewReader(buf, 0)
|
||||
pkFunc, ok := pool[header.PacketID]
|
||||
if !ok {
|
||||
pk = &packet.Unknown{PacketID: header.PacketID}
|
||||
} else {
|
||||
pk = pkFunc()
|
||||
}
|
||||
pk.Unmarshal(r)
|
||||
|
||||
dir := "S->C"
|
||||
src_addr, _, _ := net.SplitHostPort(src.String())
|
||||
if IPPrivate(net.ParseIP(src_addr)) {
|
||||
dir = "C->S"
|
||||
}
|
||||
|
||||
pk_name := reflect.TypeOf(pk).String()
|
||||
if slices.Contains(muted_packets, pk_name) {
|
||||
return
|
||||
}
|
||||
switch pk := pk.(type) {
|
||||
case *packet.Disconnect:
|
||||
fmt.Printf("Disconnect: %s", pk.Message)
|
||||
}
|
||||
fmt.Printf("%s 0x%x, %s\n", dir, pk.ID(), pk_name)
|
||||
}
|
||||
|
|
17
world.go
17
world.go
|
@ -247,18 +247,11 @@ func (w *WorldState) ProcessChangeDimension(pk *packet.ChangeDimension) {
|
|||
w.Dim = dimension_ids[uint8(dim_id)]
|
||||
}
|
||||
|
||||
func (w *WorldState) SendMessage(text string) {
|
||||
w.ClientConn.WritePacket(&packet.Text{
|
||||
TextType: packet.TextTypeSystem,
|
||||
Message: "§8[§bBedrocktool§8]§r " + text,
|
||||
})
|
||||
}
|
||||
|
||||
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:], " ")
|
||||
w.SendMessage(fmt.Sprintf("worldName is now: %s", w.WorldName))
|
||||
send_message(w.ClientConn, fmt.Sprintf("worldName is now: %s", w.WorldName))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -430,7 +423,7 @@ func (c *WorldCMD) handleConn(ctx context.Context, l *minecraft.Listener, cc, sc
|
|||
}()
|
||||
}
|
||||
|
||||
{
|
||||
{ // check game version
|
||||
gd := w.ServerConn.GameData()
|
||||
gv := strings.Split(gd.BaseGameVersion, ".")
|
||||
if len(gv) > 1 {
|
||||
|
@ -446,7 +439,7 @@ func (c *WorldCMD) handleConn(ctx context.Context, l *minecraft.Listener, cc, sc
|
|||
}
|
||||
}
|
||||
|
||||
w.SendMessage("use /setname <worldname>\nto set the world name")
|
||||
send_message(w.ClientConn, "use /setname <worldname>\nto set the world name")
|
||||
|
||||
G_exit = append(G_exit, func() {
|
||||
w.SaveAndReset()
|
||||
|
@ -473,10 +466,6 @@ func (c *WorldCMD) handleConn(ctx context.Context, l *minecraft.Listener, cc, sc
|
|||
w.ui.Send(w)
|
||||
skip = true
|
||||
}
|
||||
case *packet.ClientCacheStatus:
|
||||
pk.Enabled = false
|
||||
w.ServerConn.WritePacket(pk)
|
||||
skip = true
|
||||
case *packet.MobEquipment:
|
||||
if pk.NewItem.Stack.NBTData["map_uuid"] == int64(VIEW_MAP_ID) {
|
||||
skip = true
|
||||
|
|
Loading…
Reference in New Issue