2022-09-04 14:26:32 +00:00
|
|
|
package utils
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2023-01-25 12:51:00 +00:00
|
|
|
"fmt"
|
|
|
|
"io"
|
2022-09-04 14:26:32 +00:00
|
|
|
"net"
|
|
|
|
"reflect"
|
2023-01-25 12:51:00 +00:00
|
|
|
"strings"
|
|
|
|
"sync"
|
2022-09-04 14:26:32 +00:00
|
|
|
|
2023-01-23 12:40:12 +00:00
|
|
|
"github.com/bedrock-tool/bedrocktool/locale"
|
2022-09-04 23:40:55 +00:00
|
|
|
"github.com/fatih/color"
|
2022-09-04 14:26:32 +00:00
|
|
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
|
|
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"golang.org/x/exp/slices"
|
|
|
|
)
|
|
|
|
|
2022-09-05 11:13:43 +00:00
|
|
|
var MutedPackets = []string{
|
2022-09-04 23:40:55 +00:00
|
|
|
"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",
|
|
|
|
"packet.InventoryTransaction",
|
2022-09-05 11:35:18 +00:00
|
|
|
"packet.PlaySound",
|
2022-09-04 14:26:32 +00:00
|
|
|
}
|
|
|
|
|
2023-01-29 21:20:13 +00:00
|
|
|
var (
|
2023-03-30 11:48:03 +00:00
|
|
|
FLog io.Writer
|
|
|
|
dmpLock sync.Mutex
|
2023-01-29 21:20:13 +00:00
|
|
|
)
|
2023-01-25 12:51:00 +00:00
|
|
|
|
2023-03-11 18:50:13 +00:00
|
|
|
func dmpStruct(level int, inputStruct any, withType bool, isInList bool) (s string) {
|
2023-01-29 21:20:13 +00:00
|
|
|
tBase := strings.Repeat("\t", level)
|
2023-01-25 12:51:00 +00:00
|
|
|
|
2023-03-14 01:07:39 +00:00
|
|
|
if inputStruct == nil {
|
|
|
|
return "nil"
|
|
|
|
}
|
|
|
|
|
2023-03-11 18:50:13 +00:00
|
|
|
ii := reflect.Indirect(reflect.ValueOf(inputStruct))
|
|
|
|
typeName := reflect.TypeOf(inputStruct).String()
|
2023-03-30 11:48:03 +00:00
|
|
|
if typeName == "[]interface {}" {
|
|
|
|
typeName = "[]any"
|
|
|
|
}
|
2023-03-11 18:50:13 +00:00
|
|
|
typeString := ""
|
|
|
|
if withType {
|
|
|
|
if slices.Contains([]string{"bool", "string"}, typeName) {
|
|
|
|
} else {
|
2023-03-30 11:48:03 +00:00
|
|
|
typeString = typeName
|
2023-03-11 18:50:13 +00:00
|
|
|
}
|
2023-01-25 12:51:00 +00:00
|
|
|
}
|
|
|
|
|
2023-03-14 01:07:39 +00:00
|
|
|
if strings.HasPrefix(typeName, "protocol.Optional") {
|
|
|
|
v := ii.MethodByName("Value").Call(nil)
|
|
|
|
val, set := v[0], v[1]
|
|
|
|
if !set.Bool() {
|
|
|
|
s += typeName + " Not Set"
|
|
|
|
} else {
|
|
|
|
s += typeName + "{\n" + tBase + "\t"
|
|
|
|
s += dmpStruct(level+1, val.Interface(), false, false)
|
|
|
|
s += "\n" + tBase + "}"
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-03-30 11:48:03 +00:00
|
|
|
switch ii.Kind() {
|
|
|
|
case reflect.Struct:
|
2023-03-11 18:50:13 +00:00
|
|
|
if ii.NumField() == 0 {
|
|
|
|
s += typeName + "{}"
|
|
|
|
} else {
|
|
|
|
s += typeName + "{\n"
|
|
|
|
for i := 0; i < ii.NumField(); i++ {
|
|
|
|
fieldType := ii.Type().Field(i)
|
|
|
|
|
|
|
|
if fieldType.IsExported() {
|
2023-03-30 11:48:03 +00:00
|
|
|
s += fmt.Sprintf("%s\t%s: %s,\n", tBase, fieldType.Name, dmpStruct(level+1, ii.Field(i).Interface(), true, false))
|
2023-03-11 18:50:13 +00:00
|
|
|
} else {
|
|
|
|
s += tBase + " " + fieldType.Name + " (unexported)"
|
|
|
|
}
|
2023-01-25 12:51:00 +00:00
|
|
|
}
|
2023-03-11 18:50:13 +00:00
|
|
|
s += tBase + "}"
|
2023-01-25 12:51:00 +00:00
|
|
|
}
|
2023-03-30 11:48:03 +00:00
|
|
|
case reflect.Slice:
|
|
|
|
s += typeName + "{"
|
2023-03-11 18:50:13 +00:00
|
|
|
|
2023-01-25 12:51:00 +00:00
|
|
|
if ii.Len() > 1000 {
|
2023-03-30 11:48:03 +00:00
|
|
|
s += "<slice too long>"
|
2023-03-11 18:50:13 +00:00
|
|
|
} else if ii.Len() == 0 {
|
|
|
|
} else {
|
2023-03-30 11:48:03 +00:00
|
|
|
e := ii.Index(0)
|
|
|
|
t := reflect.TypeOf(e.Interface())
|
|
|
|
is_elem_struct := t.Kind() == reflect.Struct
|
|
|
|
|
2023-03-11 18:50:13 +00:00
|
|
|
if is_elem_struct {
|
|
|
|
s += "\n"
|
|
|
|
}
|
2023-01-25 12:51:00 +00:00
|
|
|
for i := 0; i < ii.Len(); i++ {
|
2023-03-11 18:50:13 +00:00
|
|
|
if is_elem_struct {
|
|
|
|
s += tBase + "\t"
|
|
|
|
}
|
2023-03-30 11:48:03 +00:00
|
|
|
s += dmpStruct(level+1, ii.Index(i).Interface(), false, true) + ","
|
2023-03-11 18:50:13 +00:00
|
|
|
if is_elem_struct {
|
|
|
|
s += "\n"
|
|
|
|
} else {
|
2023-03-30 11:48:03 +00:00
|
|
|
if i != ii.Len()-1 {
|
|
|
|
s += " "
|
|
|
|
}
|
2023-03-11 18:50:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if is_elem_struct {
|
2023-01-29 21:20:13 +00:00
|
|
|
s += tBase
|
2023-01-25 12:51:00 +00:00
|
|
|
}
|
|
|
|
}
|
2023-03-30 11:48:03 +00:00
|
|
|
s += "}"
|
|
|
|
case reflect.Map:
|
|
|
|
it := reflect.TypeOf(inputStruct)
|
|
|
|
valType := it.Elem().String()
|
|
|
|
if valType == "interface {}" {
|
|
|
|
valType = "any"
|
2023-01-25 12:51:00 +00:00
|
|
|
}
|
2023-03-30 11:48:03 +00:00
|
|
|
keyType := it.Key().String()
|
|
|
|
|
|
|
|
s += fmt.Sprintf("map[%s]%s{", keyType, valType)
|
|
|
|
if ii.Len() > 0 {
|
|
|
|
s += "\n"
|
|
|
|
}
|
|
|
|
|
|
|
|
iter := ii.MapRange()
|
|
|
|
for iter.Next() {
|
|
|
|
k := iter.Key()
|
|
|
|
v := iter.Value()
|
|
|
|
s += fmt.Sprintf("%s\t%#v: %s,\n", tBase, k.Interface(), dmpStruct(level+1, v.Interface(), true, false))
|
|
|
|
}
|
|
|
|
|
|
|
|
if ii.Len() > 0 {
|
|
|
|
s += tBase
|
|
|
|
}
|
|
|
|
s += "}"
|
|
|
|
default:
|
2023-03-14 01:07:39 +00:00
|
|
|
is_array := ii.Kind() == reflect.Array
|
2023-03-30 11:48:03 +00:00
|
|
|
add_type := !isInList && !is_array && len(typeString) > 0
|
|
|
|
if add_type {
|
|
|
|
s += typeString + "("
|
2023-03-11 18:50:13 +00:00
|
|
|
}
|
|
|
|
s += fmt.Sprintf("%#v", ii.Interface())
|
2023-03-30 11:48:03 +00:00
|
|
|
if add_type {
|
|
|
|
s += ")"
|
|
|
|
}
|
2023-01-25 12:51:00 +00:00
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|
2022-09-05 11:13:43 +00:00
|
|
|
|
2023-03-14 01:07:39 +00:00
|
|
|
func DumpStruct(data interface{}) {
|
|
|
|
if FLog == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
FLog.Write([]byte(dmpStruct(0, data, true, false)))
|
|
|
|
FLog.Write([]byte("\n\n\n"))
|
|
|
|
}
|
|
|
|
|
2023-03-23 19:39:47 +00:00
|
|
|
var ClientAddr net.Addr
|
2023-03-30 11:48:03 +00:00
|
|
|
var pool = packet.NewPool()
|
2023-03-23 19:39:47 +00:00
|
|
|
|
2022-09-04 14:26:32 +00:00
|
|
|
func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) {
|
2023-03-30 11:48:03 +00:00
|
|
|
if header.PacketID == packet.IDRequestNetworkSettings {
|
|
|
|
ClientAddr = src
|
|
|
|
}
|
|
|
|
|
2022-09-04 14:26:32 +00:00
|
|
|
var pk packet.Packet
|
2023-01-24 09:49:48 +00:00
|
|
|
if pkFunc, ok := pool[header.PacketID]; ok {
|
2022-09-04 14:26:32 +00:00
|
|
|
pk = pkFunc()
|
2022-09-04 23:40:55 +00:00
|
|
|
} else {
|
2023-03-30 11:48:03 +00:00
|
|
|
pk = &packet.Unknown{PacketID: header.PacketID, Payload: payload}
|
2023-03-09 13:58:54 +00:00
|
|
|
}
|
|
|
|
|
2022-09-05 11:35:18 +00:00
|
|
|
defer func() {
|
|
|
|
if recoveredErr := recover(); recoveredErr != nil {
|
2023-03-23 19:39:47 +00:00
|
|
|
logrus.Errorf("%T: %s", pk, recoveredErr.(error))
|
2022-09-05 11:35:18 +00:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2023-03-23 19:39:47 +00:00
|
|
|
pk.Marshal(protocol.NewReader(bytes.NewBuffer(payload), 0))
|
2022-09-04 14:26:32 +00:00
|
|
|
|
2023-01-29 21:20:13 +00:00
|
|
|
if FLog != nil {
|
|
|
|
dmpLock.Lock()
|
2023-03-30 11:48:03 +00:00
|
|
|
FLog.Write([]byte(dmpStruct(0, pk, true, false) + "\n\n\n"))
|
|
|
|
dmpLock.Unlock()
|
2023-01-25 12:51:00 +00:00
|
|
|
}
|
|
|
|
|
2023-01-29 21:20:13 +00:00
|
|
|
pkName := reflect.TypeOf(pk).String()[1:]
|
|
|
|
if slices.Contains(MutedPackets, pkName) {
|
2022-09-04 14:26:32 +00:00
|
|
|
return
|
|
|
|
}
|
2022-09-04 23:40:55 +00:00
|
|
|
|
2022-09-04 14:26:32 +00:00
|
|
|
switch pk := pk.(type) {
|
|
|
|
case *packet.Disconnect:
|
2023-01-23 12:40:12 +00:00
|
|
|
logrus.Infof(locale.Loc("disconnect", locale.Strmap{"Pk": pk}))
|
2022-09-04 14:26:32 +00:00
|
|
|
}
|
2022-09-04 23:40:55 +00:00
|
|
|
|
2023-01-29 21:20:13 +00:00
|
|
|
dirS2C := color.GreenString("S") + "->" + color.CyanString("C")
|
|
|
|
dirC2S := color.CyanString("C") + "->" + color.GreenString("S")
|
|
|
|
var dir string = dirS2C
|
2022-09-07 12:07:33 +00:00
|
|
|
|
2023-01-29 21:20:13 +00:00
|
|
|
if ClientAddr != nil {
|
|
|
|
if src == ClientAddr {
|
|
|
|
dir = dirC2S
|
2022-09-07 12:07:33 +00:00
|
|
|
}
|
|
|
|
} else {
|
2023-01-29 21:20:13 +00:00
|
|
|
srcAddr, _, _ := net.SplitHostPort(src.String())
|
|
|
|
if IPPrivate(net.ParseIP(srcAddr)) {
|
|
|
|
dir = dirS2C
|
2022-09-07 12:07:33 +00:00
|
|
|
}
|
2022-09-04 23:40:55 +00:00
|
|
|
}
|
|
|
|
|
2023-01-29 21:20:13 +00:00
|
|
|
logrus.Debugf("%s 0x%02x, %s", dir, pk.ID(), pkName)
|
2022-09-04 14:26:32 +00:00
|
|
|
}
|