clean code

This commit is contained in:
olebeck 2022-08-17 20:04:13 +02:00
parent eb4125b8c1
commit cd126dff3d
12 changed files with 225 additions and 240 deletions

View File

@ -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)_%)

78
auth.go Normal file
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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())

View File

@ -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)

View File

@ -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
}

View File

@ -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 {

View File

@ -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

View File

@ -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
View File

@ -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)
}

View File

@ -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