bedrocktool/replay.go

134 lines
3.6 KiB
Go
Raw Normal View History

2022-09-03 22:56:40 +00:00
package main
import (
2022-09-04 00:24:58 +00:00
"bytes"
2022-09-03 22:56:40 +00:00
"context"
"os"
"reflect"
"time"
"unsafe"
"github.com/google/gopacket/pcapgo"
"github.com/sandertv/gophertunnel/minecraft"
2022-09-04 00:24:58 +00:00
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
2022-09-03 22:56:40 +00:00
"github.com/sirupsen/logrus"
)
func SetUnexportedField(field reflect.Value, value interface{}) {
reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).
Elem().
Set(reflect.ValueOf(value))
}
func create_replay_connection(ctx context.Context, log *logrus.Logger, filename string, onConnect ConnectCallback, packetCB PacketCallback) error {
2022-09-04 00:24:58 +00:00
log.Infof("Reading replay %s", filename)
2022-09-04 13:24:55 +00:00
OLD_BROKEN := false
2022-09-03 22:56:40 +00:00
f, err := os.Open(filename)
if err != nil {
return err
}
reader, err := pcapgo.NewReader(f)
if err != nil {
return err
}
SetUnexportedField(reflect.ValueOf(reader).Elem().Field(5), uint32(0xFFFFFFFF))
2022-09-04 13:24:55 +00:00
proxy := NewProxy(logrus.StandardLogger())
proxy.server = minecraft.NewConn()
2022-09-03 22:56:40 +00:00
2022-09-04 00:24:58 +00:00
var fake_header []byte
if OLD_BROKEN {
// FOR OLD BROKEN CAPTURES
fake_head := packet.Header{
PacketID: packet.IDLevelChunk,
}
fake_header_w := bytes.NewBuffer(nil)
fake_head.Write(fake_header_w)
fake_header = fake_header_w.Bytes()
2022-09-03 22:56:40 +00:00
}
2022-09-04 13:24:55 +00:00
game_started := false
2022-09-03 22:56:40 +00:00
start := time.Time{}
for {
data, ci, err := reader.ReadPacketData()
if err != nil {
return err
}
if start.Unix() == 0 {
start = ci.Timestamp
}
2022-09-04 13:24:55 +00:00
if len(data) < 0x14 {
2022-09-03 22:56:40 +00:00
continue
}
2022-09-04 13:24:55 +00:00
var payload []byte
var toServer bool
2022-09-04 00:24:58 +00:00
if OLD_BROKEN {
2022-09-04 13:24:55 +00:00
payload = append(fake_header, data[0x14:]...)
toServer = data[0x10] != 127
} else {
prefix := data[0:6]
payload = data[6:]
toServer = bytes.Equal(prefix, []byte("client"))
2022-09-04 00:24:58 +00:00
}
2022-09-03 22:56:40 +00:00
2022-09-04 13:24:55 +00:00
pk_data, err := minecraft.ParseData(payload, proxy.server)
2022-09-03 22:56:40 +00:00
if err != nil {
return err
}
2022-09-04 13:24:55 +00:00
pks, err := pk_data.Decode(proxy.server)
2022-09-03 22:56:40 +00:00
if err != nil {
log.Error(err)
continue
}
for _, pk := range pks {
2022-09-04 13:24:55 +00:00
if game_started || OLD_BROKEN {
if packetCB != nil {
packetCB(pk, proxy, toServer)
}
2022-09-03 22:56:40 +00:00
} else {
2022-09-04 13:24:55 +00:00
switch pk := pk.(type) {
case *packet.StartGame:
proxy.server.SetGameData(minecraft.GameData{
WorldName: pk.WorldName,
WorldSeed: pk.WorldSeed,
Difficulty: pk.Difficulty,
EntityUniqueID: pk.EntityUniqueID,
EntityRuntimeID: pk.EntityRuntimeID,
PlayerGameMode: pk.PlayerGameMode,
PersonaDisabled: pk.PersonaDisabled,
CustomSkinsDisabled: pk.CustomSkinsDisabled,
BaseGameVersion: pk.BaseGameVersion,
PlayerPosition: pk.PlayerPosition,
Pitch: pk.Pitch,
Yaw: pk.Yaw,
Dimension: pk.Dimension,
WorldSpawn: pk.WorldSpawn,
EditorWorld: pk.EditorWorld,
WorldGameMode: pk.WorldGameMode,
GameRules: pk.GameRules,
Time: pk.Time,
ServerBlockStateChecksum: pk.ServerBlockStateChecksum,
CustomBlocks: pk.Blocks,
Items: pk.Items,
PlayerMovementSettings: pk.PlayerMovementSettings,
ServerAuthoritativeInventory: pk.ServerAuthoritativeInventory,
Experiments: pk.Experiments,
ClientSideGeneration: pk.ClientSideGeneration,
ChatRestrictionLevel: pk.ChatRestrictionLevel,
DisablePlayerInteractions: pk.DisablePlayerInteractions,
})
game_started = true
if onConnect != nil {
onConnect(proxy)
}
}
2022-09-03 22:56:40 +00:00
}
}
}
}