make subcommands more modular
This commit is contained in:
parent
9b3a31879a
commit
f1cb7df05e
|
@ -1,41 +1,18 @@
|
||||||
package subcommands
|
package subcommands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
"github.com/bedrock-tool/bedrocktool/utils"
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
|
"github.com/bedrock-tool/bedrocktool/utils/handlers"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
utils.RegisterCommand(&CaptureCMD{})
|
utils.RegisterCommand(&CaptureCMD{})
|
||||||
}
|
}
|
||||||
|
|
||||||
var dumpLock sync.Mutex
|
|
||||||
|
|
||||||
func dumpPacket(f io.WriteCloser, toServer bool, payload []byte) {
|
|
||||||
dumpLock.Lock()
|
|
||||||
defer dumpLock.Unlock()
|
|
||||||
f.Write([]byte{0xAA, 0xAA, 0xAA, 0xAA})
|
|
||||||
packetSize := uint32(len(payload))
|
|
||||||
binary.Write(f, binary.LittleEndian, packetSize)
|
|
||||||
binary.Write(f, binary.LittleEndian, toServer)
|
|
||||||
binary.Write(f, binary.LittleEndian, time.Now().UnixMilli())
|
|
||||||
f.Write(payload)
|
|
||||||
f.Write([]byte{0xBB, 0xBB, 0xBB, 0xBB})
|
|
||||||
}
|
|
||||||
|
|
||||||
type CaptureCMD struct {
|
type CaptureCMD struct {
|
||||||
ServerAddress string
|
ServerAddress string
|
||||||
}
|
}
|
||||||
|
@ -52,26 +29,10 @@ func (c *CaptureCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Mkdir("captures", 0o775)
|
|
||||||
fio, err := os.Create(fmt.Sprintf("captures/%s-%s.pcap2", hostname, time.Now().Format("2006-01-02_15-04-05")))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer fio.Close()
|
|
||||||
utils.WriteReplayHeader(fio)
|
|
||||||
|
|
||||||
proxy, err := utils.NewProxy()
|
proxy, err := utils.NewProxy()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
proxy.PacketFunc = func(header packet.Header, payload []byte, src, dst net.Addr) {
|
proxy.AddHandler(handlers.NewPacketCapturer())
|
||||||
IsfromClient := src.String() == proxy.Client.LocalAddr().String()
|
return proxy.Run(ctx, address, hostname)
|
||||||
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
header.Write(buf)
|
|
||||||
buf.Write(payload)
|
|
||||||
dumpPacket(fio, IsfromClient, buf.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
return proxy.Run(ctx, address)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,15 +3,10 @@ package subcommands
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
"github.com/bedrock-tool/bedrocktool/utils"
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
|
"github.com/bedrock-tool/bedrocktool/utils/handlers"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChatLogCMD struct {
|
type ChatLogCMD struct {
|
||||||
|
@ -32,34 +27,12 @@ func (c *ChatLogCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
filename := fmt.Sprintf("%s_%s_chat.log", hostname, time.Now().Format("2006-01-02_15-04-05_Z07"))
|
|
||||||
f, err := os.Create(filename)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
proxy, err := utils.NewProxy()
|
proxy, err := utils.NewProxy()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
proxy.PacketCB = func(pk packet.Packet, toServer bool, t time.Time) (packet.Packet, error) {
|
proxy.AddHandler(handlers.NewChatLogger())
|
||||||
if text, ok := pk.(*packet.Text); ok {
|
return proxy.Run(ctx, address, hostname)
|
||||||
logLine := text.Message
|
|
||||||
if c.Verbose {
|
|
||||||
logLine += fmt.Sprintf(" (TextType: %d | XUID: %s | PlatformChatID: %s)", text.TextType, text.XUID, text.PlatformChatID)
|
|
||||||
}
|
|
||||||
f.WriteString(fmt.Sprintf("[%s] ", t.Format(time.RFC3339)))
|
|
||||||
logrus.Info(logLine)
|
|
||||||
if toServer {
|
|
||||||
f.WriteString("SENT: ")
|
|
||||||
}
|
|
||||||
f.WriteString(logLine + "\n")
|
|
||||||
}
|
|
||||||
return pk, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return proxy.Run(ctx, address)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -19,7 +19,7 @@ func (c *DebugProxyCMD) SetFlags(f *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *DebugProxyCMD) Execute(ctx context.Context, ui utils.UI) error {
|
func (c *DebugProxyCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
address, _, err := utils.ServerInput(ctx, c.ServerAddress)
|
address, hostname, err := utils.ServerInput(ctx, c.ServerAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ func (c *DebugProxyCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return proxy.Run(ctx, address)
|
return proxy.Run(ctx, address, hostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
Binary file not shown.
|
@ -3,126 +3,16 @@ package skins
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
"github.com/bedrock-tool/bedrocktool/ui/messages"
|
"github.com/bedrock-tool/bedrocktool/ui/messages"
|
||||||
"github.com/bedrock-tool/bedrocktool/utils"
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
|
"github.com/bedrock-tool/bedrocktool/utils/handlers"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/sandertv/gophertunnel/minecraft"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SkinMeta struct {
|
|
||||||
SkinID string
|
|
||||||
PlayFabID string
|
|
||||||
PremiumSkin bool
|
|
||||||
PersonaSkin bool
|
|
||||||
CapeID string
|
|
||||||
SkinColour string
|
|
||||||
ArmSize string
|
|
||||||
Trusted bool
|
|
||||||
PersonaPieces []protocol.PersonaPiece
|
|
||||||
}
|
|
||||||
|
|
||||||
type skinsSession struct {
|
type skinsSession struct {
|
||||||
PlayerNameFilter string
|
|
||||||
OnlyIfHasGeometry bool
|
|
||||||
ServerName string
|
|
||||||
Proxy *utils.ProxyContext
|
|
||||||
fpath string
|
|
||||||
|
|
||||||
playerSkinPacks map[uuid.UUID]*SkinPack
|
|
||||||
playerNames map[uuid.UUID]string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSkinsSession(proxy *utils.ProxyContext, serverName, fpath string) *skinsSession {
|
|
||||||
return &skinsSession{
|
|
||||||
ServerName: serverName,
|
|
||||||
Proxy: proxy,
|
|
||||||
fpath: fpath,
|
|
||||||
|
|
||||||
playerSkinPacks: make(map[uuid.UUID]*SkinPack),
|
|
||||||
playerNames: make(map[uuid.UUID]string),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *skinsSession) AddPlayerSkin(playerID uuid.UUID, playerName string, skin *Skin) (added bool) {
|
|
||||||
p, ok := s.playerSkinPacks[playerID]
|
|
||||||
if !ok {
|
|
||||||
creating := fmt.Sprintf("Creating Skinpack for %s", playerName)
|
|
||||||
s.Proxy.SendPopup(creating)
|
|
||||||
logrus.Info(creating)
|
|
||||||
p = NewSkinPack(playerName, s.fpath)
|
|
||||||
s.playerSkinPacks[playerID] = p
|
|
||||||
}
|
|
||||||
if p.AddSkin(skin) {
|
|
||||||
if ok {
|
|
||||||
addedStr := fmt.Sprintf("Added a skin to %s", playerName)
|
|
||||||
s.Proxy.SendPopup(addedStr)
|
|
||||||
logrus.Info(addedStr)
|
|
||||||
}
|
|
||||||
added = true
|
|
||||||
}
|
|
||||||
if err := p.Save(path.Join(s.fpath, playerName), s.ServerName); err != nil {
|
|
||||||
logrus.Error(err)
|
|
||||||
}
|
|
||||||
return added
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *skinsSession) AddSkin(playerName string, playerID uuid.UUID, playerSkin *protocol.Skin) (string, *Skin, bool) {
|
|
||||||
if playerName == "" {
|
|
||||||
playerName = s.playerNames[playerID]
|
|
||||||
if playerName == "" {
|
|
||||||
playerName = playerID.String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(playerName, s.PlayerNameFilter) {
|
|
||||||
return "", nil, false
|
|
||||||
}
|
|
||||||
s.playerNames[playerID] = playerName
|
|
||||||
|
|
||||||
skin := &Skin{playerSkin}
|
|
||||||
if s.OnlyIfHasGeometry && !skin.HaveGeometry() {
|
|
||||||
return "", nil, false
|
|
||||||
}
|
|
||||||
wasAdded := s.AddPlayerSkin(playerID, playerName, skin)
|
|
||||||
|
|
||||||
return playerName, skin, wasAdded
|
|
||||||
}
|
|
||||||
|
|
||||||
type skinAdd struct {
|
|
||||||
PlayerName string
|
|
||||||
Skin *protocol.Skin
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *skinsSession) ProcessPacket(pk packet.Packet) (out []skinAdd) {
|
|
||||||
switch pk := pk.(type) {
|
|
||||||
case *packet.PlayerList:
|
|
||||||
if pk.ActionType == 1 { // remove
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
for _, player := range pk.Entries {
|
|
||||||
playerName, skin, wasAdded := s.AddSkin(utils.CleanupName(player.Username), player.UUID, &player.Skin)
|
|
||||||
if wasAdded {
|
|
||||||
out = append(out, skinAdd{
|
|
||||||
PlayerName: playerName,
|
|
||||||
Skin: skin.Skin,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case *packet.AddPlayer:
|
|
||||||
if _, ok := s.playerNames[pk.UUID]; !ok {
|
|
||||||
s.playerNames[pk.UUID] = utils.CleanupName(pk.Username)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type SkinCMD struct {
|
type SkinCMD struct {
|
||||||
|
@ -148,41 +38,25 @@ func (c *SkinCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
|
|
||||||
proxy, _ := utils.NewProxy()
|
proxy, _ := utils.NewProxy()
|
||||||
proxy.WithClient = !c.NoProxy
|
proxy.WithClient = !c.NoProxy
|
||||||
proxy.OnClientConnect = func(hasClient bool) {
|
proxy.AddHandler(handlers.NewSkinSaver(func(sa handlers.SkinAdd) {
|
||||||
ui.Message(messages.SetUIState(messages.UIStateConnecting))
|
ui.Message(messages.NewSkin{
|
||||||
}
|
PlayerName: sa.PlayerName,
|
||||||
proxy.ConnectCB = func(err error) bool {
|
Skin: sa.Skin,
|
||||||
if err != nil {
|
})
|
||||||
return false
|
}))
|
||||||
}
|
proxy.AddHandler(&utils.ProxyHandler{
|
||||||
ui.Message(messages.SetUIState(messages.UIStateMain))
|
Name: "Skin CMD",
|
||||||
logrus.Info(locale.Loc("ctrl_c_to_exit", nil))
|
OnClientConnect: func(conn *minecraft.Conn) {
|
||||||
return true
|
ui.Message(messages.SetUIState(messages.UIStateConnecting))
|
||||||
}
|
},
|
||||||
|
})
|
||||||
outPathBase := fmt.Sprintf("skins/%s", hostname)
|
|
||||||
os.MkdirAll(outPathBase, 0o755)
|
|
||||||
|
|
||||||
s := NewSkinsSession(proxy, hostname, outPathBase)
|
|
||||||
|
|
||||||
proxy.PacketCB = func(pk packet.Packet, toServer bool, _ time.Time) (packet.Packet, error) {
|
|
||||||
if !toServer {
|
|
||||||
for _, s := range s.ProcessPacket(pk) {
|
|
||||||
ui.Message(messages.NewSkin{
|
|
||||||
PlayerName: s.PlayerName,
|
|
||||||
Skin: s.Skin,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pk, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if proxy.WithClient {
|
if proxy.WithClient {
|
||||||
ui.Message(messages.SetUIState(messages.UIStateConnect))
|
ui.Message(messages.SetUIState(messages.UIStateConnect))
|
||||||
} else {
|
} else {
|
||||||
ui.Message(messages.SetUIState(messages.UIStateConnecting))
|
ui.Message(messages.SetUIState(messages.UIStateConnecting))
|
||||||
}
|
}
|
||||||
err = proxy.Run(ctx, address)
|
err = proxy.Run(ctx, address, hostname)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,37 +172,41 @@ func (c *WorldCMD) Execute(ctx context.Context, ui utils.UI) error {
|
||||||
proxy.GameDataModifier = func(gd *minecraft.GameData) {
|
proxy.GameDataModifier = func(gd *minecraft.GameData) {
|
||||||
gd.ClientSideGeneration = false
|
gd.ClientSideGeneration = false
|
||||||
}
|
}
|
||||||
proxy.ConnectCB = w.OnConnect
|
|
||||||
proxy.OnClientConnect = func(hasClient bool) {
|
|
||||||
w.gui.Message(messages.SetUIState(messages.UIStateConnecting))
|
|
||||||
}
|
|
||||||
proxy.PacketCB = func(pk packet.Packet, toServer bool, _ time.Time) (packet.Packet, error) {
|
|
||||||
forward := true
|
|
||||||
|
|
||||||
if toServer {
|
proxy.AddHandler(&utils.ProxyHandler{
|
||||||
// from client
|
Name: "Worlds",
|
||||||
pk = w.processItemPacketsClient(pk, &forward)
|
ConnectCB: w.OnConnect,
|
||||||
pk = w.processMapPacketsClient(pk, &forward)
|
OnClientConnect: func(conn *minecraft.Conn) {
|
||||||
} else {
|
w.gui.Message(messages.SetUIState(messages.UIStateConnecting))
|
||||||
// from server
|
},
|
||||||
switch pk := pk.(type) {
|
PacketCB: func(pk packet.Packet, toServer bool, timeReceived time.Time) (packet.Packet, error) {
|
||||||
case *packet.ChunkRadiusUpdated:
|
forward := true
|
||||||
w.serverState.ChunkRadius = int(pk.ChunkRadius)
|
|
||||||
pk.ChunkRadius = 80
|
if toServer {
|
||||||
|
// from client
|
||||||
|
pk = w.processItemPacketsClient(pk, &forward)
|
||||||
|
pk = w.processMapPacketsClient(pk, &forward)
|
||||||
|
} else {
|
||||||
|
// from server
|
||||||
|
switch pk := pk.(type) {
|
||||||
|
case *packet.ChunkRadiusUpdated:
|
||||||
|
w.serverState.ChunkRadius = int(pk.ChunkRadius)
|
||||||
|
pk.ChunkRadius = 80
|
||||||
|
}
|
||||||
|
pk = w.processItemPacketsServer(pk)
|
||||||
|
pk = w.ProcessChunkPackets(pk)
|
||||||
|
pk = w.ProcessEntityPackets(pk)
|
||||||
}
|
}
|
||||||
pk = w.processItemPacketsServer(pk)
|
|
||||||
pk = w.ProcessChunkPackets(pk)
|
|
||||||
pk = w.ProcessEntityPackets(pk)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !forward {
|
if !forward {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return pk, nil
|
return pk, nil
|
||||||
}
|
},
|
||||||
|
})
|
||||||
|
|
||||||
w.gui.Message(messages.SetUIState(messages.UIStateConnect))
|
w.gui.Message(messages.SetUIState(messages.UIStateConnect))
|
||||||
err = w.proxy.Run(ctx, serverAddress)
|
err = w.proxy.Run(ctx, serverAddress, hostname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
var dumpLock sync.Mutex
|
||||||
|
|
||||||
|
func dumpPacket(f io.WriteCloser, toServer bool, payload []byte) {
|
||||||
|
dumpLock.Lock()
|
||||||
|
defer dumpLock.Unlock()
|
||||||
|
f.Write([]byte{0xAA, 0xAA, 0xAA, 0xAA})
|
||||||
|
packetSize := uint32(len(payload))
|
||||||
|
binary.Write(f, binary.LittleEndian, packetSize)
|
||||||
|
binary.Write(f, binary.LittleEndian, toServer)
|
||||||
|
binary.Write(f, binary.LittleEndian, time.Now().UnixMilli())
|
||||||
|
f.Write(payload)
|
||||||
|
f.Write([]byte{0xBB, 0xBB, 0xBB, 0xBB})
|
||||||
|
}
|
||||||
|
|
||||||
|
type PacketCapturer struct {
|
||||||
|
proxy *utils.ProxyContext
|
||||||
|
fio *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PacketCapturer) AddressAndName(address, hostname string) error {
|
||||||
|
os.Mkdir("captures", 0o775)
|
||||||
|
fio, err := os.Create(fmt.Sprintf("captures/%s-%s.pcap2", hostname, time.Now().Format("2006-01-02_15-04-05")))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
utils.WriteReplayHeader(fio)
|
||||||
|
p.fio = fio
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PacketCapturer) PacketFunc(header packet.Header, payload []byte, src, dst net.Addr) {
|
||||||
|
IsfromClient := utils.ClientAddr.String() == src.String()
|
||||||
|
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
header.Write(buf)
|
||||||
|
buf.Write(payload)
|
||||||
|
dumpPacket(p.fio, IsfromClient, buf.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPacketCapturer() *utils.ProxyHandler {
|
||||||
|
p := &PacketCapturer{}
|
||||||
|
return &utils.ProxyHandler{
|
||||||
|
Name: "Packet Capturer",
|
||||||
|
ProxyRef: func(pc *utils.ProxyContext) {
|
||||||
|
p.proxy = pc
|
||||||
|
},
|
||||||
|
PacketFunc: p.PacketFunc,
|
||||||
|
AddressAndName: p.AddressAndName,
|
||||||
|
OnEnd: func() {
|
||||||
|
p.fio.Close()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ChatLogger struct {
|
||||||
|
Verbose bool
|
||||||
|
fio *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChatLogger) AddressAndName(address, hostname string) error {
|
||||||
|
filename := fmt.Sprintf("%s_%s_chat.log", hostname, time.Now().Format("2006-01-02_15-04-05_Z07"))
|
||||||
|
f, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.fio = f
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChatLogger) PacketCB(pk packet.Packet, toServer bool, t time.Time) (packet.Packet, error) {
|
||||||
|
if text, ok := pk.(*packet.Text); ok {
|
||||||
|
logLine := text.Message
|
||||||
|
if c.Verbose {
|
||||||
|
logLine += fmt.Sprintf(" (TextType: %d | XUID: %s | PlatformChatID: %s)", text.TextType, text.XUID, text.PlatformChatID)
|
||||||
|
}
|
||||||
|
c.fio.WriteString(fmt.Sprintf("[%s] ", t.Format(time.RFC3339)))
|
||||||
|
logrus.Info(logLine)
|
||||||
|
if toServer {
|
||||||
|
c.fio.WriteString("SENT: ")
|
||||||
|
}
|
||||||
|
c.fio.WriteString(logLine + "\n")
|
||||||
|
}
|
||||||
|
return pk, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewChatLogger() *utils.ProxyHandler {
|
||||||
|
p := &ChatLogger{}
|
||||||
|
return &utils.ProxyHandler{
|
||||||
|
Name: "Packet Capturer",
|
||||||
|
PacketCB: p.PacketCB,
|
||||||
|
AddressAndName: p.AddressAndName,
|
||||||
|
OnEnd: func() {
|
||||||
|
p.fio.Close()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/bedrock-tool/bedrocktool/utils"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SkinSaver struct {
|
||||||
|
PlayerNameFilter string
|
||||||
|
OnlyIfHasGeometry bool
|
||||||
|
ServerName string
|
||||||
|
Proxy *utils.ProxyContext
|
||||||
|
fpath string
|
||||||
|
|
||||||
|
playerSkinPacks map[uuid.UUID]*utils.SkinPack
|
||||||
|
playerNames map[uuid.UUID]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkinSaver) AddPlayerSkin(playerID uuid.UUID, playerName string, skin *utils.Skin) (added bool) {
|
||||||
|
p, ok := s.playerSkinPacks[playerID]
|
||||||
|
if !ok {
|
||||||
|
creating := fmt.Sprintf("Creating Skinpack for %s", playerName)
|
||||||
|
s.Proxy.SendPopup(creating)
|
||||||
|
logrus.Info(creating)
|
||||||
|
p = utils.NewSkinPack(playerName, s.fpath)
|
||||||
|
s.playerSkinPacks[playerID] = p
|
||||||
|
}
|
||||||
|
if p.AddSkin(skin) {
|
||||||
|
if ok {
|
||||||
|
addedStr := fmt.Sprintf("Added a skin to %s", playerName)
|
||||||
|
s.Proxy.SendPopup(addedStr)
|
||||||
|
logrus.Info(addedStr)
|
||||||
|
}
|
||||||
|
added = true
|
||||||
|
}
|
||||||
|
if err := p.Save(path.Join(s.fpath, playerName), s.ServerName); err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
}
|
||||||
|
return added
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkinSaver) AddSkin(playerName string, playerID uuid.UUID, playerSkin *protocol.Skin) (string, *utils.Skin, bool) {
|
||||||
|
if playerName == "" {
|
||||||
|
playerName = s.playerNames[playerID]
|
||||||
|
if playerName == "" {
|
||||||
|
playerName = playerID.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(playerName, s.PlayerNameFilter) {
|
||||||
|
return "", nil, false
|
||||||
|
}
|
||||||
|
s.playerNames[playerID] = playerName
|
||||||
|
|
||||||
|
skin := &utils.Skin{playerSkin}
|
||||||
|
if s.OnlyIfHasGeometry && !skin.HaveGeometry() {
|
||||||
|
return "", nil, false
|
||||||
|
}
|
||||||
|
wasAdded := s.AddPlayerSkin(playerID, playerName, skin)
|
||||||
|
|
||||||
|
return playerName, skin, wasAdded
|
||||||
|
}
|
||||||
|
|
||||||
|
type SkinAdd struct {
|
||||||
|
PlayerName string
|
||||||
|
Skin *protocol.Skin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkinSaver) ProcessPacket(pk packet.Packet) (out []SkinAdd) {
|
||||||
|
switch pk := pk.(type) {
|
||||||
|
case *packet.PlayerList:
|
||||||
|
if pk.ActionType == 1 { // remove
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, player := range pk.Entries {
|
||||||
|
playerName, skin, wasAdded := s.AddSkin(utils.CleanupName(player.Username), player.UUID, &player.Skin)
|
||||||
|
if wasAdded {
|
||||||
|
out = append(out, SkinAdd{
|
||||||
|
PlayerName: playerName,
|
||||||
|
Skin: skin.Skin,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *packet.AddPlayer:
|
||||||
|
if _, ok := s.playerNames[pk.UUID]; !ok {
|
||||||
|
s.playerNames[pk.UUID] = utils.CleanupName(pk.Username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSkinSaver(skinCB func(SkinAdd)) *utils.ProxyHandler {
|
||||||
|
s := &SkinSaver{
|
||||||
|
playerSkinPacks: make(map[uuid.UUID]*utils.SkinPack),
|
||||||
|
playerNames: make(map[uuid.UUID]string),
|
||||||
|
}
|
||||||
|
return &utils.ProxyHandler{
|
||||||
|
Name: "Skin Saver",
|
||||||
|
ProxyRef: func(pc *utils.ProxyContext) {
|
||||||
|
s.Proxy = pc
|
||||||
|
},
|
||||||
|
AddressAndName: func(address, hostname string) error {
|
||||||
|
outPathBase := fmt.Sprintf("skins/%s", hostname)
|
||||||
|
os.MkdirAll(outPathBase, 0o755)
|
||||||
|
s.fpath = outPathBase
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
PacketCB: func(pk packet.Packet, toServer bool, timeReceived time.Time) (packet.Packet, error) {
|
||||||
|
if !toServer {
|
||||||
|
for _, s := range s.ProcessPacket(pk) {
|
||||||
|
if skinCB != nil {
|
||||||
|
skinCB(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pk, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -183,10 +183,6 @@ var ClientAddr net.Addr
|
||||||
var pool = packet.NewPool()
|
var pool = packet.NewPool()
|
||||||
|
|
||||||
func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) {
|
func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) {
|
||||||
if header.PacketID == packet.IDRequestNetworkSettings {
|
|
||||||
ClientAddr = src
|
|
||||||
}
|
|
||||||
|
|
||||||
var pk packet.Packet
|
var pk packet.Packet
|
||||||
if pkFunc, ok := pool[header.PacketID]; ok {
|
if pkFunc, ok := pool[header.PacketID]; ok {
|
||||||
pk = pkFunc()
|
pk = pkFunc()
|
||||||
|
|
156
utils/proxy.go
156
utils/proxy.go
|
@ -8,11 +8,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bedrock-tool/bedrocktool/locale"
|
"github.com/bedrock-tool/bedrocktool/locale"
|
||||||
|
"github.com/repeale/fp-go"
|
||||||
"github.com/sandertv/gophertunnel/minecraft"
|
"github.com/sandertv/gophertunnel/minecraft"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol/login"
|
"github.com/sandertv/gophertunnel/minecraft/protocol/login"
|
||||||
|
@ -42,16 +44,36 @@ func (p dummyProto) ConvertFromLatest(pk packet.Packet, _ *minecraft.Conn) []pac
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type (
|
type (
|
||||||
PacketFunc func(header packet.Header, payload []byte, src, dst net.Addr)
|
PacketFunc func(header packet.Header, payload []byte, src, dst net.Addr)
|
||||||
PacketCallback func(pk packet.Packet, toServer bool, timeReceived time.Time) (packet.Packet, error)
|
IngameCommand struct {
|
||||||
ClientConnectCallback func(hasClient bool)
|
|
||||||
ConnectCallback func(err error) bool
|
|
||||||
IngameCommand struct {
|
|
||||||
Exec func(cmdline []string) bool
|
Exec func(cmdline []string) bool
|
||||||
Cmd protocol.Command
|
Cmd protocol.Command
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ProxyHandler struct {
|
||||||
|
Name string
|
||||||
|
ProxyRef func(*ProxyContext)
|
||||||
|
//
|
||||||
|
AddressAndName func(address, name string) error
|
||||||
|
|
||||||
|
// called for every packet
|
||||||
|
PacketFunc func(header packet.Header, payload []byte, src, dst net.Addr)
|
||||||
|
|
||||||
|
// called on every packet after login
|
||||||
|
PacketCB func(pk packet.Packet, toServer bool, timeReceived time.Time) (packet.Packet, error)
|
||||||
|
|
||||||
|
// called after client connected
|
||||||
|
OnClientConnect func(conn *minecraft.Conn)
|
||||||
|
SecondaryClientCB func(conn *minecraft.Conn)
|
||||||
|
|
||||||
|
// called after game started
|
||||||
|
ConnectCB func(err error) bool
|
||||||
|
|
||||||
|
// called when the proxy stops
|
||||||
|
OnEnd func()
|
||||||
|
}
|
||||||
|
|
||||||
type ProxyContext struct {
|
type ProxyContext struct {
|
||||||
Server *minecraft.Conn
|
Server *minecraft.Conn
|
||||||
Client *minecraft.Conn
|
Client *minecraft.Conn
|
||||||
|
@ -62,14 +84,8 @@ type ProxyContext struct {
|
||||||
IgnoreDisconnect bool
|
IgnoreDisconnect bool
|
||||||
CustomClientData *login.ClientData
|
CustomClientData *login.ClientData
|
||||||
|
|
||||||
// called for every packet
|
handlers []*ProxyHandler
|
||||||
PacketFunc PacketFunc
|
|
||||||
// called after client connected
|
|
||||||
OnClientConnect ClientConnectCallback
|
|
||||||
// called after game started
|
|
||||||
ConnectCB ConnectCallback
|
|
||||||
// called on every packet after login
|
|
||||||
PacketCB PacketCallback
|
|
||||||
// called to change game data
|
// called to change game data
|
||||||
GameDataModifier func(*minecraft.GameData)
|
GameDataModifier func(*minecraft.GameData)
|
||||||
}
|
}
|
||||||
|
@ -186,6 +202,10 @@ func (p *ProxyContext) SendPopup(text string) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *ProxyContext) AddHandler(handler *ProxyHandler) {
|
||||||
|
p.handlers = append(p.handlers, handler)
|
||||||
|
}
|
||||||
|
|
||||||
func (p *ProxyContext) CommandHandlerPacketCB(pk packet.Packet, toServer bool, _ time.Time) (packet.Packet, error) {
|
func (p *ProxyContext) CommandHandlerPacketCB(pk packet.Packet, toServer bool, _ time.Time) (packet.Packet, error) {
|
||||||
switch _pk := pk.(type) {
|
switch _pk := pk.(type) {
|
||||||
case *packet.CommandRequest:
|
case *packet.CommandRequest:
|
||||||
|
@ -209,7 +229,7 @@ func (p *ProxyContext) CommandHandlerPacketCB(pk packet.Packet, toServer bool, _
|
||||||
return pk, nil
|
return pk, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ProxyContext) proxyLoop(ctx context.Context, toServer bool, packetCBs []PacketCallback) error {
|
func (p *ProxyContext) proxyLoop(ctx context.Context, toServer bool) error {
|
||||||
var c1, c2 *minecraft.Conn
|
var c1, c2 *minecraft.Conn
|
||||||
if toServer {
|
if toServer {
|
||||||
c1 = p.Client
|
c1 = p.Client
|
||||||
|
@ -229,10 +249,17 @@ func (p *ProxyContext) proxyLoop(ctx context.Context, toServer bool, packetCBs [
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, packetCB := range packetCBs {
|
pkName := reflect.TypeOf(pk).String()
|
||||||
pk, err = packetCB(pk, toServer, time.Now())
|
for _, handler := range p.handlers {
|
||||||
if err != nil {
|
if handler.PacketCB != nil {
|
||||||
return err
|
pk, err = handler.PacketCB(pk, toServer, time.Now())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if pk == nil {
|
||||||
|
logrus.Tracef("Dropped Packet: %s", pkName)
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +274,16 @@ func (p *ProxyContext) proxyLoop(ctx context.Context, toServer bool, packetCBs [
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ProxyContext) Run(ctx context.Context, serverAddress string) (err error) {
|
func (p *ProxyContext) Run(ctx context.Context, serverAddress, name string) (err error) {
|
||||||
|
for _, handler := range p.handlers {
|
||||||
|
if handler.AddressAndName != nil {
|
||||||
|
handler.AddressAndName(serverAddress, name)
|
||||||
|
}
|
||||||
|
if handler.ProxyRef != nil {
|
||||||
|
handler.ProxyRef(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(serverAddress, "PCAP!") {
|
if strings.HasPrefix(serverAddress, "PCAP!") {
|
||||||
return createReplayConnection(ctx, serverAddress[5:], p)
|
return createReplayConnection(ctx, serverAddress[5:], p)
|
||||||
}
|
}
|
||||||
|
@ -279,9 +315,7 @@ func (p *ProxyContext) Run(ctx context.Context, serverAddress string) (err error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
go func() {
|
|
||||||
<-ctx.Done()
|
|
||||||
if p.Client != nil {
|
if p.Client != nil {
|
||||||
p.Listener.Disconnect(p.Client, DisconnectReason)
|
p.Listener.Disconnect(p.Client, DisconnectReason)
|
||||||
}
|
}
|
||||||
|
@ -300,22 +334,40 @@ func (p *ProxyContext) Run(ctx context.Context, serverAddress string) (err error
|
||||||
cdp = &cd
|
cdp = &cd
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.OnClientConnect != nil {
|
for _, handler := range p.handlers {
|
||||||
p.OnClientConnect(p.WithClient)
|
if handler.OnClientConnect == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
handler.OnClientConnect(p.Client)
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.CustomClientData != nil {
|
if p.CustomClientData != nil {
|
||||||
cdp = p.CustomClientData
|
cdp = p.CustomClientData
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Server, err = connectServer(ctx, serverAddress, cdp, p.AlwaysGetPacks, p.PacketFunc)
|
p.Server, err = connectServer(ctx, serverAddress, cdp, p.AlwaysGetPacks, func(header packet.Header, payload []byte, src, dst net.Addr) {
|
||||||
|
for _, handler := range p.handlers {
|
||||||
|
if handler.PacketFunc == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
handler.PacketFunc(header, payload, src, dst)
|
||||||
|
}
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if p.ConnectCB != nil {
|
for _, handler := range p.handlers {
|
||||||
if p.ConnectCB(err) {
|
if handler.ConnectCB == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ignore := handler.ConnectCB(err)
|
||||||
|
if ignore {
|
||||||
err = nil
|
err = nil
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = fmt.Errorf(locale.Loc("failed_to_connect", locale.Strmap{"Address": serverAddress, "Err": err}))
|
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf(locale.Loc("failed_to_connect", locale.Strmap{"Address": serverAddress, "Err": err}))
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer p.Server.Close()
|
defer p.Server.Close()
|
||||||
|
@ -331,25 +383,27 @@ func (p *ProxyContext) Run(ctx context.Context, serverAddress string) (err error
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.ConnectCB != nil {
|
for _, handler := range p.handlers {
|
||||||
if !p.ConnectCB(nil) {
|
if handler.ConnectCB == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !handler.ConnectCB(nil) {
|
||||||
return errors.New("Cancelled")
|
return errors.New("Cancelled")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// append self to handlers for commands
|
||||||
|
p.handlers = append(p.handlers, &ProxyHandler{
|
||||||
|
Name: "Commands",
|
||||||
|
PacketCB: p.CommandHandlerPacketCB,
|
||||||
|
})
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
|
|
||||||
var cbs []PacketCallback
|
|
||||||
cbs = append(cbs, p.CommandHandlerPacketCB)
|
|
||||||
if p.PacketCB != nil {
|
|
||||||
cbs = append(cbs, p.PacketCB)
|
|
||||||
}
|
|
||||||
|
|
||||||
// server to client
|
// server to client
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if err := p.proxyLoop(ctx, false, cbs); err != nil {
|
if err := p.proxyLoop(ctx, false); err != nil {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -360,13 +414,37 @@ func (p *ProxyContext) Run(ctx context.Context, serverAddress string) (err error
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if err := p.proxyLoop(ctx, true, cbs); err != nil {
|
if err := p.proxyLoop(ctx, true); err != nil {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wantSecondary := fp.Filter(func(handler *ProxyHandler) bool {
|
||||||
|
return handler.SecondaryClientCB != nil
|
||||||
|
})(p.handlers)
|
||||||
|
|
||||||
|
if len(wantSecondary) > 0 {
|
||||||
|
go func() {
|
||||||
|
c, err := p.Listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, handler := range wantSecondary {
|
||||||
|
go handler.SecondaryClientCB(c.(*minecraft.Conn))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
|
for _, handler := range p.handlers {
|
||||||
|
if handler.OnEnd != nil {
|
||||||
|
handler.OnEnd()
|
||||||
|
}
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,13 @@ func createReplayConnection(ctx context.Context, filename string, proxy *ProxyCo
|
||||||
f.Seek(-4, io.SeekCurrent)
|
f.Seek(-4, io.SeekCurrent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server, client := &net.UDPAddr{
|
||||||
|
IP: net.IPv4(1, 1, 1, 1),
|
||||||
|
}, &net.UDPAddr{
|
||||||
|
IP: net.IPv4(2, 2, 2, 2),
|
||||||
|
}
|
||||||
|
ClientAddr = client
|
||||||
|
|
||||||
proxy.Server = minecraft.NewConn()
|
proxy.Server = minecraft.NewConn()
|
||||||
|
|
||||||
gameStarted := false
|
gameStarted := false
|
||||||
|
@ -123,13 +130,32 @@ func createReplayConnection(ctx context.Context, filename string, proxy *ProxyCo
|
||||||
b := protocol.NewWriter(f, 0)
|
b := protocol.NewWriter(f, 0)
|
||||||
pk.Marshal(b)
|
pk.Marshal(b)
|
||||||
|
|
||||||
|
hdr := packet.Header{PacketID: pk.ID()}
|
||||||
|
|
||||||
|
var src, dst net.Addr
|
||||||
|
if toServer {
|
||||||
|
src = client
|
||||||
|
dst = server
|
||||||
|
} else {
|
||||||
|
src = server
|
||||||
|
dst = client
|
||||||
|
}
|
||||||
|
|
||||||
if Options.Debug {
|
if Options.Debug {
|
||||||
PacketLogger(packet.Header{PacketID: pk.ID()}, f.Bytes(), &net.UDPAddr{}, &net.UDPAddr{})
|
PacketLogger(hdr, f.Bytes(), src, dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, handler := range proxy.handlers {
|
||||||
|
if handler.PacketFunc != nil {
|
||||||
|
handler.PacketFunc(hdr, f.Bytes(), src, dst)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if gameStarted {
|
if gameStarted {
|
||||||
if proxy.PacketCB != nil {
|
for _, handler := range proxy.handlers {
|
||||||
proxy.PacketCB(pk, toServer, timeReceived)
|
if handler.PacketCB != nil {
|
||||||
|
handler.PacketCB(pk, toServer, timeReceived)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch pk := pk.(type) {
|
switch pk := pk.(type) {
|
||||||
|
@ -164,11 +190,19 @@ func createReplayConnection(ctx context.Context, filename string, proxy *ProxyCo
|
||||||
DisablePlayerInteractions: pk.DisablePlayerInteractions,
|
DisablePlayerInteractions: pk.DisablePlayerInteractions,
|
||||||
})
|
})
|
||||||
gameStarted = true
|
gameStarted = true
|
||||||
if proxy.ConnectCB != nil {
|
for _, handler := range proxy.handlers {
|
||||||
proxy.ConnectCB(nil)
|
if handler.ConnectCB != nil {
|
||||||
|
handler.ConnectCB(nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, handler := range proxy.handlers {
|
||||||
|
if handler.OnEnd != nil {
|
||||||
|
handler.OnEnd()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package skins
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
|
@ -1,4 +1,4 @@
|
||||||
package skins
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -6,12 +6,24 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
"github.com/bedrock-tool/bedrocktool/utils"
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/resource"
|
"github.com/sandertv/gophertunnel/minecraft/resource"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type SkinMeta struct {
|
||||||
|
SkinID string
|
||||||
|
PlayFabID string
|
||||||
|
PremiumSkin bool
|
||||||
|
PersonaSkin bool
|
||||||
|
CapeID string
|
||||||
|
SkinColour string
|
||||||
|
ArmSize string
|
||||||
|
Trusted bool
|
||||||
|
PersonaPieces []protocol.PersonaPiece
|
||||||
|
}
|
||||||
|
|
||||||
type _skinWithIndex struct {
|
type _skinWithIndex struct {
|
||||||
i int
|
i int
|
||||||
skin *Skin
|
skin *Skin
|
||||||
|
@ -144,7 +156,7 @@ func (s *SkinPack) Save(fpath, serverName string) error {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := utils.WriteManifest(&manifest, fpath); err != nil {
|
if err := WriteManifest(&manifest, fpath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -69,6 +69,10 @@ func connectServer(ctx context.Context, address string, ClientData *login.Client
|
||||||
TokenSource: GetTokenSource(),
|
TokenSource: GetTokenSource(),
|
||||||
ClientData: cd,
|
ClientData: cd,
|
||||||
PacketFunc: func(header packet.Header, payload []byte, src, dst net.Addr) {
|
PacketFunc: func(header packet.Header, payload []byte, src, dst net.Addr) {
|
||||||
|
if header.PacketID == packet.IDRequestNetworkSettings {
|
||||||
|
ClientAddr = src
|
||||||
|
}
|
||||||
|
|
||||||
if Options.Debug {
|
if Options.Debug {
|
||||||
PacketLogger(header, payload, src, dst)
|
PacketLogger(header, payload, src, dst)
|
||||||
}
|
}
|
||||||
|
@ -85,7 +89,6 @@ func connectServer(ctx context.Context, address string, ClientData *login.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debug(locale.Loc("connected", nil))
|
logrus.Debug(locale.Loc("connected", nil))
|
||||||
ClientAddr = serverConn.LocalAddr()
|
|
||||||
return serverConn, nil
|
return serverConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue