improvements to interactive input, more reliable skins
This commit is contained in:
parent
a771b5f1d8
commit
8b24744f85
|
@ -7,7 +7,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"regexp"
|
||||
"runtime/debug"
|
||||
"syscall"
|
||||
|
||||
"github.com/bedrock-tool/bedrocktool/utils"
|
||||
|
@ -29,6 +29,7 @@ func main() {
|
|||
logrus.Infof("Version: %s", utils.Version)
|
||||
logrus.Infof("Cmdline: %s", os.Args)
|
||||
logrus.Errorf("Error: %s", err)
|
||||
fmt.Println("stacktrace from panic: \n" + string(debug.Stack()))
|
||||
println("--END COPY HERE--")
|
||||
println("")
|
||||
println("if you want to report this error, please open an issue at")
|
||||
|
@ -81,12 +82,11 @@ func main() {
|
|||
}
|
||||
fmt.Printf("Use '%s <command>' to run a command\n", os.Args[0])
|
||||
|
||||
fmt.Printf("Input Command: ")
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
target, _ := reader.ReadString('\n')
|
||||
r, _ := regexp.Compile(`[\n\r]`)
|
||||
target = string(r.ReplaceAll([]byte(target), []byte("")))
|
||||
os.Args = append(os.Args, target)
|
||||
cmd, cancelled := utils.User_input(ctx, "Input Command: ")
|
||||
if cancelled {
|
||||
return
|
||||
}
|
||||
os.Args = append(os.Args, cmd)
|
||||
utils.G_interactive = true
|
||||
}
|
||||
}
|
||||
|
@ -103,6 +103,7 @@ func main() {
|
|||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-sigs
|
||||
println("cancelling")
|
||||
cancel()
|
||||
}()
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ func (c *CaptureCMD) Usage() string {
|
|||
}
|
||||
|
||||
func (c *CaptureCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
||||
address, hostname, err := utils.ServerInput(c.server_address)
|
||||
address, hostname, err := utils.ServerInput(ctx, c.server_address)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
return 1
|
||||
|
|
|
@ -32,7 +32,7 @@ func (c *ChatLogCMD) Usage() string {
|
|||
}
|
||||
|
||||
func (c *ChatLogCMD) Execute(ctx context.Context, flags *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
||||
address, hostname, err := utils.ServerInput(c.Address)
|
||||
address, hostname, err := utils.ServerInput(ctx, c.Address)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return 1
|
||||
|
|
|
@ -29,7 +29,7 @@ func (c *DebugProxyCMD) Usage() string {
|
|||
}
|
||||
|
||||
func (c *DebugProxyCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
||||
address, _, err := utils.ServerInput(c.Address)
|
||||
address, _, err := utils.ServerInput(ctx, c.Address)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return 1
|
||||
|
|
|
@ -14,8 +14,9 @@ import (
|
|||
)
|
||||
|
||||
type SkinProxyCMD struct {
|
||||
server_address string
|
||||
filter string
|
||||
server_address string
|
||||
filter string
|
||||
only_with_geometry bool
|
||||
}
|
||||
|
||||
func (*SkinProxyCMD) Name() string { return "skins-proxy" }
|
||||
|
@ -24,6 +25,7 @@ func (*SkinProxyCMD) Synopsis() string { return "download skins from players on
|
|||
func (c *SkinProxyCMD) SetFlags(f *flag.FlagSet) {
|
||||
f.StringVar(&c.server_address, "address", "", "remote server address")
|
||||
f.StringVar(&c.filter, "filter", "", "player name filter prefix")
|
||||
f.BoolVar(&c.only_with_geometry, "only-geom", false, "only save skins with geometry")
|
||||
}
|
||||
|
||||
func (c *SkinProxyCMD) Usage() string {
|
||||
|
@ -31,7 +33,7 @@ func (c *SkinProxyCMD) Usage() string {
|
|||
}
|
||||
|
||||
func (c *SkinProxyCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
||||
address, hostname, err := utils.ServerInput(c.server_address)
|
||||
address, hostname, err := utils.ServerInput(ctx, c.server_address)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return 1
|
||||
|
@ -42,7 +44,7 @@ func (c *SkinProxyCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interf
|
|||
proxy := utils.NewProxy(logrus.StandardLogger())
|
||||
proxy.PacketCB = func(pk packet.Packet, proxy *utils.ProxyContext, toServer bool) (packet.Packet, error) {
|
||||
if !toServer {
|
||||
process_packet_skins(proxy.Client, out_path, pk, c.filter)
|
||||
process_packet_skins(proxy.Client, out_path, pk, c.filter, c.only_with_geometry)
|
||||
}
|
||||
return pk, nil
|
||||
}
|
||||
|
|
|
@ -27,6 +27,18 @@ type Skin struct {
|
|||
protocol.Skin
|
||||
}
|
||||
|
||||
type SkinMeta struct {
|
||||
SkinID string
|
||||
PlayFabID string
|
||||
PremiumSkin bool
|
||||
PersonaSkin bool
|
||||
CapeID string
|
||||
SkinColour string
|
||||
ArmSize string
|
||||
Trusted bool
|
||||
PersonaPieces []protocol.PersonaPiece
|
||||
}
|
||||
|
||||
// WriteGeometry writes the geometry json for the skin to output_path
|
||||
func (skin *Skin) WriteGeometry(output_path string) error {
|
||||
f, err := os.Create(output_path)
|
||||
|
@ -96,17 +108,7 @@ func (skin *Skin) WriteMeta(output_path string) error {
|
|||
return fmt.Errorf("failed to write Tint %s: %s", output_path, err)
|
||||
}
|
||||
defer f.Close()
|
||||
d, err := json.MarshalIndent(struct {
|
||||
SkinID string
|
||||
PlayFabID string
|
||||
PremiumSkin bool
|
||||
PersonaSkin bool
|
||||
CapeID string
|
||||
SkinColour string
|
||||
ArmSize string
|
||||
Trusted bool
|
||||
PersonaPieces []protocol.PersonaPiece
|
||||
}{
|
||||
d, err := json.MarshalIndent(SkinMeta{
|
||||
skin.SkinID,
|
||||
skin.PlayFabID,
|
||||
skin.PremiumSkin,
|
||||
|
@ -124,13 +126,17 @@ func (skin *Skin) WriteMeta(output_path string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (skin *Skin) Complex() bool {
|
||||
have_geometry, have_cape, have_animations, have_tint := len(skin.SkinGeometry) > 0, len(skin.CapeData) > 0, len(skin.Animations) > 0, len(skin.PieceTintColours) > 0
|
||||
return have_geometry || have_cape || have_animations || have_tint
|
||||
}
|
||||
|
||||
// Write writes all data for this skin to a folder
|
||||
func (skin *Skin) Write(output_path, name string) error {
|
||||
name, _ = filenamify.FilenamifyV2(name)
|
||||
skin_dir := path.Join(output_path, name)
|
||||
|
||||
have_geometry, have_cape, have_animations, have_tint := len(skin.SkinGeometry) > 0, len(skin.CapeData) > 0, len(skin.Animations) > 0, len(skin.PieceTintColours) > 0
|
||||
|
||||
os.MkdirAll(skin_dir, 0o755)
|
||||
if have_geometry {
|
||||
if err := skin.WriteGeometry(path.Join(skin_dir, "geometry.json")); err != nil {
|
||||
|
@ -157,17 +163,14 @@ func (skin *Skin) Write(output_path, name string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return skin.WriteTexture(path.Join(skin_dir, "skin.png"))
|
||||
return skin.WriteTexture(skin_dir + "/skin.png")
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
func write_skin(output_path, name string, skin *protocol.Skin) {
|
||||
logrus.Infof("Writing skin for %s\n", name)
|
||||
_skin := &Skin{skin}
|
||||
_skin := &Skin{*skin}
|
||||
if err := _skin.Write(output_path, name); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error writing skin: %s\n", err)
|
||||
}
|
||||
|
@ -176,37 +179,73 @@ func write_skin(output_path, name string, skin protocol.Skin, filter string) {
|
|||
var (
|
||||
skin_players = make(map[string]string)
|
||||
skin_player_counts = make(map[string]int)
|
||||
processed_skins = make(map[string]bool)
|
||||
)
|
||||
|
||||
func process_packet_skins(conn *minecraft.Conn, out_path string, pk packet.Packet, filter string) {
|
||||
func popup_skin_saved(conn *minecraft.Conn, name string) {
|
||||
if conn != nil {
|
||||
(&utils.ProxyContext{Client: conn}).SendPopup(fmt.Sprintf("%s Skin was Saved", name))
|
||||
}
|
||||
}
|
||||
|
||||
func skin_meta_get_skinid(path string) string {
|
||||
cont, err := os.ReadFile(fmt.Sprintf("%s/metadata.json", path))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
var meta SkinMeta
|
||||
if err := json.Unmarshal(cont, &meta); err != nil {
|
||||
return ""
|
||||
}
|
||||
return meta.SkinID
|
||||
}
|
||||
|
||||
func save_player_skin(conn *minecraft.Conn, out_path, player_name string, skin *protocol.Skin) {
|
||||
count := skin_player_counts[player_name]
|
||||
if count > 0 {
|
||||
meta_id := skin_meta_get_skinid(fmt.Sprintf("%s/%s_%d", out_path, player_name, count-1))
|
||||
if meta_id == skin.SkinID {
|
||||
return // skin same as before
|
||||
}
|
||||
}
|
||||
|
||||
skin_player_counts[player_name]++
|
||||
count++
|
||||
write_skin(out_path, fmt.Sprintf("%s_%d", player_name, count), skin)
|
||||
popup_skin_saved(conn, player_name)
|
||||
}
|
||||
|
||||
func process_packet_skins(conn *minecraft.Conn, out_path string, pk packet.Packet, filter string, only_if_geom bool) {
|
||||
switch _pk := pk.(type) {
|
||||
case *packet.PlayerSkin:
|
||||
name := skin_players[_pk.UUID.String()]
|
||||
if name == "" {
|
||||
name = _pk.UUID.String()
|
||||
player_name := skin_players[_pk.UUID.String()]
|
||||
if player_name == "" {
|
||||
player_name = _pk.UUID.String()
|
||||
}
|
||||
skin_player_counts[name]++
|
||||
name = fmt.Sprintf("%s_%d", name, skin_player_counts[name])
|
||||
write_skin(out_path, name, _pk.Skin, filter)
|
||||
if !strings.HasPrefix(player_name, filter) {
|
||||
return
|
||||
}
|
||||
if only_if_geom && len(_pk.Skin.SkinGeometry) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
save_player_skin(conn, out_path, player_name, &_pk.Skin)
|
||||
case *packet.PlayerList:
|
||||
if _pk.ActionType == 1 { // remove
|
||||
return
|
||||
}
|
||||
for _, player := range _pk.Entries {
|
||||
name := utils.CleanupName(player.Username)
|
||||
if name == "" {
|
||||
name = player.UUID.String()
|
||||
player_name := utils.CleanupName(player.Username)
|
||||
if player_name == "" {
|
||||
player_name = player.UUID.String()
|
||||
}
|
||||
if _, ok := processed_skins[name]; ok {
|
||||
continue
|
||||
if !strings.HasPrefix(player_name, filter) {
|
||||
return
|
||||
}
|
||||
write_skin(out_path, name, player.Skin, filter)
|
||||
skin_players[player.UUID.String()] = name
|
||||
processed_skins[name] = true
|
||||
if conn != nil {
|
||||
(&utils.ProxyContext{Client: conn}).SendPopup(fmt.Sprintf("%s Skin was Saved", name))
|
||||
if only_if_geom && len(player.Skin.SkinGeometry) == 0 {
|
||||
return
|
||||
}
|
||||
skin_players[player.UUID.String()] = player_name
|
||||
save_player_skin(conn, out_path, player_name, &player.Skin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -229,7 +268,7 @@ func (c *SkinCMD) Usage() string {
|
|||
}
|
||||
|
||||
func (c *SkinCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
|
||||
address, hostname, err := utils.ServerInput(c.server_address)
|
||||
address, hostname, err := utils.ServerInput(ctx, c.server_address)
|
||||
if err != nil {
|
||||
fmt.Fprint(os.Stderr, err)
|
||||
return 1
|
||||
|
@ -259,7 +298,7 @@ func (c *SkinCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}
|
|||
if err != nil {
|
||||
return 1
|
||||
}
|
||||
process_packet_skins(nil, out_path, pk, c.filter)
|
||||
process_packet_skins(nil, out_path, pk, c.filter, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ func (c *WorldCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{
|
|||
}()
|
||||
*/
|
||||
|
||||
server_address, hostname, err := utils.ServerInput(c.Address)
|
||||
server_address, hostname, err := utils.ServerInput(ctx, c.Address)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return 1
|
||||
|
|
|
@ -12,6 +12,25 @@ import (
|
|||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func User_input(ctx context.Context, q string) (string, bool) {
|
||||
c := make(chan string)
|
||||
go func() {
|
||||
fmt.Print(q)
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
answer, _ := reader.ReadString('\n')
|
||||
r, _ := regexp.Compile(`[\n\r]`)
|
||||
answer = string(r.ReplaceAll([]byte(answer), []byte("")))
|
||||
c <- answer
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return "", true
|
||||
case a := <-c:
|
||||
return a, false
|
||||
}
|
||||
}
|
||||
|
||||
func server_url_to_name(server string) string {
|
||||
host, _, err := net.SplitHostPort(server)
|
||||
if err != nil {
|
||||
|
@ -20,13 +39,13 @@ func server_url_to_name(server string) string {
|
|||
return host
|
||||
}
|
||||
|
||||
func ServerInput(server string) (address, name string, err error) {
|
||||
func ServerInput(ctx context.Context, server string) (address, name string, err error) {
|
||||
if server == "" { // no arg provided, interactive input
|
||||
fmt.Printf("Enter Server: ")
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
server, _ = reader.ReadString('\n')
|
||||
r, _ := regexp.Compile(`[\n\r]`)
|
||||
server = string(r.ReplaceAll([]byte(server), []byte("")))
|
||||
var cancelled bool
|
||||
server, cancelled = User_input(ctx, "Enter Server: ")
|
||||
if cancelled {
|
||||
return "", "", context.Canceled
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(server, "realm:") { // for realms use api to get ip address
|
||||
|
|
175
utils/proxy.go
175
utils/proxy.go
|
@ -156,94 +156,109 @@ func NewProxy(log *logrus.Logger) *ProxyContext {
|
|||
var Client_addr net.Addr
|
||||
|
||||
func (p *ProxyContext) Run(ctx context.Context, server_address string) (err error) {
|
||||
c := make(chan struct{})
|
||||
|
||||
if strings.HasSuffix(server_address, ".pcap") {
|
||||
return fmt.Errorf("not supported anymore!")
|
||||
return fmt.Errorf("not supported anymore")
|
||||
}
|
||||
if strings.HasSuffix(server_address, ".pcap2") {
|
||||
return create_replay_connection(ctx, p.log, server_address, p.ConnectCB, p.PacketCB)
|
||||
}
|
||||
|
||||
GetTokenSource() // ask for login before listening
|
||||
|
||||
var packs []*resource.Pack
|
||||
if G_preload_packs {
|
||||
p.log.Info("Preloading resourcepacks")
|
||||
serverConn, err := ConnectServer(ctx, server_address, nil, true, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect to %s: %s", server_address, err)
|
||||
go func() {
|
||||
defer func() { c <- struct{}{} }()
|
||||
GetTokenSource() // ask for login before listening
|
||||
var packs []*resource.Pack
|
||||
if G_preload_packs {
|
||||
p.log.Info("Preloading resourcepacks")
|
||||
var serverConn *minecraft.Conn
|
||||
serverConn, err = ConnectServer(ctx, server_address, nil, true, nil)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to connect to %s: %s", server_address, err)
|
||||
return
|
||||
}
|
||||
serverConn.Close()
|
||||
packs = serverConn.ResourcePacks()
|
||||
p.log.Infof("%d packs loaded", len(packs))
|
||||
}
|
||||
serverConn.Close()
|
||||
packs = serverConn.ResourcePacks()
|
||||
p.log.Infof("%d packs loaded", len(packs))
|
||||
}
|
||||
|
||||
_status := minecraft.NewStatusProvider("Server")
|
||||
p.Listener, err = minecraft.ListenConfig{
|
||||
StatusProvider: _status,
|
||||
ResourcePacks: packs,
|
||||
AcceptedProtocols: []minecraft.Protocol{
|
||||
dummyProto{id: 544, ver: "1.19.20"},
|
||||
},
|
||||
}.Listen("raknet", ":19132")
|
||||
if err != nil {
|
||||
_status := minecraft.NewStatusProvider("Server")
|
||||
p.Listener, err = minecraft.ListenConfig{
|
||||
StatusProvider: _status,
|
||||
ResourcePacks: packs,
|
||||
AcceptedProtocols: []minecraft.Protocol{
|
||||
dummyProto{id: 544, ver: "1.19.20"},
|
||||
},
|
||||
}.Listen("raknet", ":19132")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer p.Listener.Close()
|
||||
|
||||
p.log.Infof("Listening on %s", p.Listener.Addr())
|
||||
|
||||
var c net.Conn
|
||||
c, err = p.Listener.Accept()
|
||||
if err != nil {
|
||||
p.log.Fatal(err)
|
||||
}
|
||||
p.Client = c.(*minecraft.Conn)
|
||||
|
||||
cd := p.Client.ClientData()
|
||||
p.Server, err = ConnectServer(ctx, server_address, &cd, false, p.PacketFunc)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to connect to %s: %s", server_address, err)
|
||||
return
|
||||
}
|
||||
// spawn and start the game
|
||||
if err = spawn_conn(ctx, p.Client, p.Server); err != nil {
|
||||
err = fmt.Errorf("failed to spawn: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer p.Server.Close()
|
||||
defer p.Listener.Disconnect(p.Client, G_disconnect_reason)
|
||||
|
||||
if p.ConnectCB != nil {
|
||||
p.ConnectCB(p)
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
cbs := []PacketCallback{
|
||||
p.CommandHandlerPacketCB,
|
||||
}
|
||||
if p.PacketCB != nil {
|
||||
cbs = append(cbs, p.PacketCB)
|
||||
}
|
||||
|
||||
// server to client
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := proxyLoop(ctx, p, false, cbs); err != nil {
|
||||
p.log.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
// client to server
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := proxyLoop(ctx, p, true, cbs); err != nil {
|
||||
p.log.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
println("Cancelled")
|
||||
return context.Canceled
|
||||
case <-c:
|
||||
return err
|
||||
}
|
||||
defer p.Listener.Close()
|
||||
|
||||
p.log.Infof("Listening on %s", p.Listener.Addr())
|
||||
|
||||
c, err := p.Listener.Accept()
|
||||
if err != nil {
|
||||
p.log.Fatal(err)
|
||||
}
|
||||
p.Client = c.(*minecraft.Conn)
|
||||
|
||||
cd := p.Client.ClientData()
|
||||
p.Server, err = ConnectServer(ctx, server_address, &cd, false, p.PacketFunc)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect to %s: %s", server_address, err)
|
||||
}
|
||||
|
||||
// spawn and start the game
|
||||
if err := spawn_conn(ctx, p.Client, p.Server); err != nil {
|
||||
return fmt.Errorf("failed to spawn: %s", err)
|
||||
}
|
||||
|
||||
defer p.Server.Close()
|
||||
defer p.Listener.Disconnect(p.Client, G_disconnect_reason)
|
||||
|
||||
if p.ConnectCB != nil {
|
||||
p.ConnectCB(p)
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
cbs := []PacketCallback{
|
||||
p.CommandHandlerPacketCB,
|
||||
}
|
||||
if p.PacketCB != nil {
|
||||
cbs = append(cbs, p.PacketCB)
|
||||
}
|
||||
|
||||
// server to client
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := proxyLoop(ctx, p, false, cbs); err != nil {
|
||||
p.log.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
// client to server
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := proxyLoop(ctx, p, true, cbs); err != nil {
|
||||
p.log.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/binary"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
"github.com/sandertv/gophertunnel/minecraft"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||
|
@ -31,7 +32,9 @@ func create_replay_connection(ctx context.Context, log *logrus.Logger, filename
|
|||
proxy.Server = minecraft.NewConn()
|
||||
|
||||
game_started := false
|
||||
i := 0
|
||||
for {
|
||||
i += 1
|
||||
var magic uint32 = 0
|
||||
var packet_length uint32 = 0
|
||||
var toServer bool = false
|
||||
|
@ -55,7 +58,7 @@ func create_replay_connection(ctx context.Context, log *logrus.Logger, filename
|
|||
return nil
|
||||
}
|
||||
if n != int(packet_length) {
|
||||
log.Errorf("Truncated")
|
||||
log.Errorf("Truncated %d", i)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -76,6 +79,8 @@ func create_replay_connection(ctx context.Context, log *logrus.Logger, filename
|
|||
}
|
||||
|
||||
for _, pk := range pks {
|
||||
logrus.Printf("%s", reflect.TypeOf(pk).String()[1:])
|
||||
|
||||
if game_started {
|
||||
if packetCB != nil {
|
||||
packetCB(pk, proxy, toServer)
|
||||
|
|
Loading…
Reference in New Issue