make worlds a proper handler

This commit is contained in:
olebeck 2023-04-04 02:42:17 +02:00
parent f1cb7df05e
commit 4e7cfeb3b4
19 changed files with 632 additions and 362 deletions

6
go.sum
View File

@ -10,6 +10,7 @@ git.wow.st/gmp/jni v0.0.0-20210610011705-34026c7e22d0 h1:bGG/g4ypjrCJoSvFrP5hafr
git.wow.st/gmp/jni v0.0.0-20210610011705-34026c7e22d0/go.mod h1:+axXBRUTIDlCeE73IKeD/os7LoEnTKdkp8/gQOFjqyo=
github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/TeaEntityLab/fpGo/v2 v2.3.2 h1:qlGjFzXukp9IgVQl32cz4PosbiFEnwXa2EpDbwddHS8=
github.com/TeaEntityLab/fpGo/v2 v2.3.2/go.mod h1:b06fRNLSnNiUwfSskBC3f3cocA4mAC2iySdtaP/T9uA=
github.com/benoitkugler/pstokenizer v1.0.0/go.mod h1:l1G2Voirz0q/jj0TQfabNxVsa8HZXh/VMxFSRALWTiE=
@ -19,6 +20,8 @@ github.com/benoitkugler/textlayout-testdata v0.1.1 h1:AvFxBxpfrQd8v55qH59mZOJOQj
github.com/benoitkugler/textlayout-testdata v0.1.1/go.mod h1:i/qZl09BbUOtd7Bu/W1CAubRwTWrEXWq6JwMkw8wYxo=
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/changkun/lockfree v0.0.1 h1:5WefVJLglY4IHRqOQmh6Ao6wkJYaJkarshKU8VUtId4=
github.com/changkun/lockfree v0.0.1/go.mod h1:3bKiaXn/iNzIPlSvSOMSVbRQUQtAp8qUAyBUtzU11s4=
github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:Yg2hDs4b13Evkpj42FU2idX2cVXVFqQSheXYKM86Qsk=
@ -102,6 +105,8 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/repeale/fp-go v0.11.1 h1:Q/e+gNyyHaxKAyfdbBqvip3DxhVWH453R+kthvSr9Mk=
github.com/repeale/fp-go v0.11.1/go.mod h1:4KrwQJB1VRY+06CA+jTc4baZetr6o2PeuqnKr5ybQUc=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/sanbornm/go-selfupdate v0.0.0-20210106163404-c9b625feac49 h1:LuxslTBxJrrNeKfqoywIERWWhH43TgiVAiPEVlhgNBA=
github.com/sanbornm/go-selfupdate v0.0.0-20210106163404-c9b625feac49/go.mod h1:fY313ZGG810aWruFYcyq3coFpHDrWJVoMfSRI81y1r4=
github.com/sandertv/go-raknet v1.12.0 h1:olUzZlIJyX/pgj/mrsLCZYjKLNDsYiWdvQ4NIm3z0DA=
@ -110,6 +115,7 @@ github.com/shirou/gopsutil/v3 v3.23.2 h1:PAWSuiAszn7IhPMBtXsbSCafej7PqUOvY6YywlQ
github.com/shirou/gopsutil/v3 v3.23.2/go.mod h1:gv0aQw33GLo3pG8SiWKiQrbDzbRY1K80RyZJ7V4Th1M=
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/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=

View File

@ -10,7 +10,7 @@ import (
"github.com/sirupsen/logrus"
)
func (w *worldsServer) processChangeDimension(pk *packet.ChangeDimension) {
func (w *worldsHandler) processChangeDimension(pk *packet.ChangeDimension) {
if len(w.worldState.chunks) > 0 {
w.SaveAndReset()
} else {
@ -18,13 +18,14 @@ func (w *worldsServer) processChangeDimension(pk *packet.ChangeDimension) {
w.Reset(w.CurrentName())
}
dimensionID := pk.Dimension
if w.serverState.ispre118 {
if w.serverState.ispre118 && dimensionID == 0 {
dimensionID += 10
}
w.worldState.Dim = dimensionIDMap[uint8(dimensionID)]
d, _ := world.DimensionByID(int(dimensionID))
w.worldState.dimension = d
}
func (w *worldsServer) processLevelChunk(pk *packet.LevelChunk) {
func (w *worldsHandler) processLevelChunk(pk *packet.LevelChunk) {
// ignore empty chunks THANKS WEIRD SERVER SOFTWARE DEVS
if len(pk.RawPayload) == 0 {
logrus.Info(locale.Loc("empty_chunk", nil))
@ -41,7 +42,7 @@ func (w *worldsServer) processLevelChunk(pk *packet.LevelChunk) {
subChunkCount = int(pk.SubChunkCount)
}
ch, blockNBTs, err := chunk.NetworkDecode(world.AirRID(), pk.RawPayload, subChunkCount, w.worldState.Dim.Range(), w.serverState.ispre118, w.bp.HasBlocks())
ch, blockNBTs, err := chunk.NetworkDecode(world.AirRID(), pk.RawPayload, subChunkCount, w.worldState.dimension.Range(), w.serverState.ispre118, w.bp.HasBlocks())
if err != nil {
logrus.Error(err)
return
@ -53,21 +54,19 @@ func (w *worldsServer) processLevelChunk(pk *packet.LevelChunk) {
}
w.worldState.chunks[pk.Position] = ch
max := w.worldState.Dim.Range().Height() / 16
max := w.worldState.dimension.Range().Height() / 16
switch pk.SubChunkCount {
case protocol.SubChunkRequestModeLimited:
max = int(pk.HighestSubChunk)
fallthrough
case protocol.SubChunkRequestModeLimitless:
var offsetTable []protocol.SubChunkOffset
r := w.worldState.Dim.Range()
r := w.worldState.dimension.Range()
for y := int8(r.Min() / 16); y < int8(r.Max()); y++ {
offsetTable = append(offsetTable, protocol.SubChunkOffset{0, y, 0})
}
dimId, ok := world.DimensionID(w.worldState.Dim)
_ = ok
dimId, _ := world.DimensionID(w.worldState.dimension)
w.proxy.Server.WritePacket(&packet.SubChunkRequest{
Dimension: int32(dimId),
Position: protocol.SubChunkPos{
@ -86,7 +85,7 @@ func (w *worldsServer) processLevelChunk(pk *packet.LevelChunk) {
}
}
func (w *worldsServer) processSubChunk(pk *packet.SubChunk) {
func (w *worldsHandler) processSubChunk(pk *packet.SubChunk) {
posToRedraw := make(map[protocol.ChunkPos]bool)
for _, sub := range pk.SubChunkEntries {
@ -124,14 +123,16 @@ func blockPosInChunk(pos protocol.BlockPos) (uint8, int16, uint8) {
return uint8(pos.X() & 0x0f), int16(pos.Y() & 0x0f), uint8(pos.Z() & 0x0f)
}
func (w *worldsServer) ProcessChunkPackets(pk packet.Packet) packet.Packet {
func (w *worldsHandler) ProcessChunkPackets(pk packet.Packet) packet.Packet {
switch pk := pk.(type) {
case *packet.ChangeDimension:
w.processChangeDimension(pk)
case *packet.LevelChunk:
w.processLevelChunk(pk)
w.proxy.SendPopup(locale.Locm("popup_chunk_count", locale.Strmap{"Count": len(w.worldState.chunks), "Name": w.worldState.Name}, len(w.worldState.chunks)))
w.proxy.SendPopup(locale.Locm("popup_chunk_count", locale.Strmap{
"Count": len(w.worldState.chunks),
"Name": w.worldState.Name,
}, len(w.worldState.chunks)))
case *packet.SubChunk:
w.processSubChunk(pk)
case *packet.BlockActorData:

View File

@ -61,7 +61,7 @@ func (e serverEntity) Type() world.EntityType {
return e.EntityType
}
func (w *worldsServer) processAddActor(pk *packet.AddActor) {
func (w *worldsHandler) processAddActor(pk *packet.AddActor) {
e, ok := w.worldState.entities[pk.EntityRuntimeID]
if !ok {
e = &entityState{
@ -141,47 +141,49 @@ func entityMetadataToNBT(metadata protocol.EntityMetadata, nbt map[string]any) {
}
}
if metadata.Flag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagNoAI) {
nbt["IsAutonomous"] = false
}
for k, v := range flagNames {
nbt[v] = metadata.Flag(protocol.EntityDataKeyFlags, k)
}
if _, ok := metadata[protocol.EntityDataKeyFlags]; ok {
if metadata.Flag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagNoAI) {
nbt["IsAutonomous"] = false
}
for k, v := range flagNames {
nbt[v] = metadata.Flag(protocol.EntityDataKeyFlags, k)
}
AlwaysShowName := metadata.Flag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagAlwaysShowName)
if AlwaysShowName {
nbt["CustomNameVisible"] = true
}
AlwaysShowName := metadata.Flag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagAlwaysShowName)
if AlwaysShowName {
nbt["CustomNameVisible"] = true
}
type effect struct {
Id byte
Amplifier byte
Duration int32
DurationEasy int32
DurationNormal int32
DurationHard int32
Ambient bool
ShowParticles bool
DisplayOnScreenTextureAnimation bool
}
type effect struct {
Id byte
Amplifier byte
Duration int32
DurationEasy int32
DurationNormal int32
DurationHard int32
Ambient bool
ShowParticles bool
DisplayOnScreenTextureAnimation bool
}
activeEffects := []effect{}
addEffect := func(id int, showParticles bool) {
activeEffects = append(activeEffects, effect{
Id: byte(id),
Amplifier: 1,
Duration: 10000000,
ShowParticles: false,
})
}
activeEffects := []effect{}
addEffect := func(id int, showParticles bool) {
activeEffects = append(activeEffects, effect{
Id: byte(id),
Amplifier: 1,
Duration: 10000000,
ShowParticles: false,
})
}
invisible := metadata.Flag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagInvisible)
if invisible {
addEffect(packet.EffectInvisibility, false)
}
invisible := metadata.Flag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagInvisible)
if invisible {
addEffect(packet.EffectInvisibility, false)
}
if len(activeEffects) > 0 {
nbt["ActiveEffects"] = activeEffects
if len(activeEffects) > 0 {
nbt["ActiveEffects"] = activeEffects
}
}
}
@ -214,7 +216,7 @@ func (s *entityState) ToServerEntity() serverEntity {
return e
}
func (w *worldsServer) ProcessEntityPackets(pk packet.Packet) packet.Packet {
func (w *worldsHandler) ProcessEntityPackets(pk packet.Packet) packet.Packet {
switch pk := pk.(type) {
case *packet.AddActor:
w.processAddActor(pk)

View File

@ -17,7 +17,7 @@ type itemContainer struct {
Content *packet.InventoryContent
}
func (w *worldsServer) processItemPacketsServer(pk packet.Packet) packet.Packet {
func (w *worldsHandler) processItemPacketsServer(pk packet.Packet) packet.Packet {
switch pk := pk.(type) {
case *packet.ContainerOpen:
// add to open containers
@ -116,7 +116,7 @@ func (w *worldsServer) processItemPacketsServer(pk packet.Packet) packet.Packet
return pk
}
func (w *worldsServer) processItemPacketsClient(pk packet.Packet, forward *bool) packet.Packet {
func (w *worldsHandler) processItemPacketsClient(pk packet.Packet, forward *bool) packet.Packet {
switch pk := pk.(type) {
case *packet.ItemStackRequest:
var requests []protocol.ItemStackRequest
@ -187,7 +187,7 @@ func stackToItem(it protocol.ItemStack) item.Stack {
return nbtconv.ReadItem(it.NBTData, &s)
}
func (w *worldsServer) playerData() (ret map[string]any) {
func (w *worldsHandler) playerData() (ret map[string]any) {
ret = map[string]any{
"format_version": "1.12.0",
"identifier": "minecraft:player",

View File

@ -10,6 +10,7 @@ import (
"github.com/bedrock-tool/bedrocktool/locale"
"github.com/bedrock-tool/bedrocktool/ui/messages"
"github.com/bedrock-tool/bedrocktool/utils"
"github.com/go-gl/mathgl/mgl32"
"golang.design/x/lockfree"
"github.com/df-mc/dragonfly/server/world/chunk"
@ -79,10 +80,10 @@ type MapUI struct {
l sync.RWMutex
ticker *time.Ticker
w *worldsServer
w *worldsHandler
}
func NewMapUI(w *worldsServer) *MapUI {
func NewMapUI(w *worldsHandler) *MapUI {
m := &MapUI{
img: image.NewRGBA(image.Rect(0, 0, 128, 128)),
zoomLevel: 16,
@ -265,14 +266,29 @@ func (m *MapUI) SetChunk(pos protocol.ChunkPos, ch *chunk.Chunk, complete bool)
m.SchedRedraw()
}
func (w *worldsServer) ProcessAnimate(pk *packet.Animate) {
func (w *worldsHandler) ProcessAnimate(pk *packet.Animate) {
if pk.ActionType == packet.AnimateActionSwingArm {
w.mapUI.ChangeZoom()
w.proxy.SendPopup(locale.Loc("zoom_level", locale.Strmap{"Level": w.mapUI.zoomLevel}))
}
}
func (w *worldsServer) processMapPacketsClient(pk packet.Packet, forward *bool) packet.Packet {
func (w *worldsHandler) SetPlayerPos(Position mgl32.Vec3, Pitch, Yaw, HeadYaw float32) {
last := w.serverState.PlayerPos
current := TPlayerPos{
Position: Position,
Pitch: Pitch,
Yaw: Yaw,
HeadYaw: HeadYaw,
}
w.serverState.PlayerPos = current
if int(last.Position.X()) != int(current.Position.X()) || int(last.Position.Z()) != int(current.Position.Z()) {
w.mapUI.SchedRedraw()
}
}
func (w *worldsHandler) processMapPacketsClient(pk packet.Packet, forward *bool) packet.Packet {
switch pk := pk.(type) {
case *packet.MovePlayer:
w.SetPlayerPos(pk.Position, pk.Pitch, pk.Yaw, pk.HeadYaw)

View File

@ -41,7 +41,7 @@ type TPlayerPos struct {
// the state used for drawing and saving
type worldSettings struct {
type WorldSettings struct {
// settings
voidGen bool
withPacks bool
@ -50,7 +50,7 @@ type worldSettings struct {
}
type worldState struct {
Dim world.Dimension
dimension world.Dimension
chunks map[protocol.ChunkPos]*chunk.Chunk
blockNBT map[protocol.SubChunkPos][]map[string]any
entities map[uint64]*entityState
@ -69,7 +69,7 @@ type serverState struct {
Name string
}
type worldsServer struct {
type worldsHandler struct {
ctx context.Context
proxy *utils.ProxyContext
mapUI *MapUI
@ -78,53 +78,10 @@ type worldsServer struct {
worldState worldState
serverState serverState
settings worldSettings
settings WorldSettings
}
func NewWorldsServer(ctx context.Context, proxy *utils.ProxyContext, ServerName string, ui utils.UI) *worldsServer {
w := &worldsServer{
ctx: ctx,
proxy: proxy,
mapUI: nil,
gui: ui,
bp: behaviourpack.New(ServerName),
serverState: serverState{
ispre118: false,
worldCounter: 0,
ChunkRadius: 0,
playerInventory: nil,
PlayerPos: TPlayerPos{},
Name: ServerName,
},
settings: worldSettings{},
}
w.mapUI = NewMapUI(w)
w.Reset(w.CurrentName())
w.gui.Message(messages.Init{
Handler: nil,
})
return w
}
var dimensionIDMap = map[uint8]world.Dimension{
0: world.Overworld,
1: world.Nether,
2: world.End,
// < 1.18
10: world.Overworld_legacy,
11: world.Nether,
12: world.End,
}
var (
black16x16 = image.NewRGBA(image.Rect(0, 0, 16, 16))
)
var black16x16 = image.NewRGBA(image.Rect(0, 0, 16, 16))
func init() {
for i := 3; i < len(black16x16.Pix); i += 4 {
@ -161,24 +118,87 @@ func (c *WorldCMD) Execute(ctx context.Context, ui utils.UI) error {
return err
}
w := NewWorldsServer(ctx, proxy, hostname, ui)
w.settings = worldSettings{
proxy.AlwaysGetPacks = true
proxy.AddHandler(NewWorldsHandler(ctx, ui, WorldSettings{
voidGen: c.EnableVoid,
withPacks: c.Packs,
saveImage: c.SaveImage,
}
}))
proxy.AlwaysGetPacks = true
proxy.GameDataModifier = func(gd *minecraft.GameData) {
gd.ClientSideGeneration = false
ui.Message(messages.SetUIState(messages.UIStateConnect))
err = proxy.Run(ctx, serverAddress, hostname)
if err != nil {
return err
}
ui.Message(messages.SetUIState(messages.UIStateFinished))
return nil
}
proxy.AddHandler(&utils.ProxyHandler{
Name: "Worlds",
ConnectCB: w.OnConnect,
func NewWorldsHandler(ctx context.Context, ui utils.UI, settings WorldSettings) *utils.ProxyHandler {
w := &worldsHandler{
ctx: ctx,
mapUI: nil,
gui: ui,
bp: nil,
serverState: serverState{
ispre118: false,
worldCounter: 0,
ChunkRadius: 0,
playerInventory: nil,
PlayerPos: TPlayerPos{},
},
settings: WorldSettings{},
}
w.mapUI = NewMapUI(w)
w.Reset(w.CurrentName())
return &utils.ProxyHandler{
Name: "Worlds",
ProxyRef: func(pc *utils.ProxyContext) {
w.proxy = pc
w.proxy.AddCommand(utils.IngameCommand{
Exec: func(cmdline []string) bool {
return w.setWorldName(strings.Join(cmdline, " "), false)
},
Cmd: protocol.Command{
Name: "setname",
Description: locale.Loc("setname_desc", nil),
Overloads: []protocol.CommandOverload{{
Parameters: []protocol.CommandParameter{{
Name: "name",
Type: protocol.CommandArgTypeString,
Optional: false,
}},
}},
},
})
w.proxy.AddCommand(utils.IngameCommand{
Exec: func(cmdline []string) bool {
return w.setVoidGen(!w.settings.voidGen, false)
},
Cmd: protocol.Command{
Name: "void",
Description: locale.Loc("void_desc", nil),
},
})
},
AddressAndName: func(address, hostname string) error {
w.bp = behaviourpack.New(hostname)
w.serverState.Name = hostname
return nil
},
OnClientConnect: func(conn *minecraft.Conn) {
w.gui.Message(messages.SetUIState(messages.UIStateConnecting))
},
GameDataModifier: func(gd *minecraft.GameData) {
gd.ClientSideGeneration = false
},
ConnectCB: w.OnConnect,
PacketCB: func(pk packet.Packet, toServer bool, timeReceived time.Time) (packet.Packet, error) {
forward := true
@ -203,34 +223,13 @@ func (c *WorldCMD) Execute(ctx context.Context, ui utils.UI) error {
}
return pk, nil
},
})
w.gui.Message(messages.SetUIState(messages.UIStateConnect))
err = w.proxy.Run(ctx, serverAddress, hostname)
if err != nil {
return err
}
w.SaveAndReset()
ui.Message(messages.SetUIState(messages.UIStateFinished))
return nil
}
func (w *worldsServer) SetPlayerPos(Position mgl32.Vec3, Pitch, Yaw, HeadYaw float32) {
last := w.serverState.PlayerPos
current := TPlayerPos{
Position: Position,
Pitch: Pitch,
Yaw: Yaw,
HeadYaw: HeadYaw,
}
w.serverState.PlayerPos = current
if int(last.Position.X()) != int(current.Position.X()) || int(last.Position.Z()) != int(current.Position.Z()) {
w.mapUI.SchedRedraw()
OnEnd: func() {
w.SaveAndReset()
},
}
}
func (w *worldsServer) setVoidGen(val bool, fromUI bool) bool {
func (w *worldsHandler) setVoidGen(val bool, fromUI bool) bool {
w.settings.voidGen = val
var s = locale.Loc("void_generator_false", nil)
if w.settings.voidGen {
@ -247,7 +246,7 @@ func (w *worldsServer) setVoidGen(val bool, fromUI bool) bool {
return true
}
func (w *worldsServer) setWorldName(val string, fromUI bool) bool {
func (w *worldsHandler) setWorldName(val string, fromUI bool) bool {
w.worldState.Name = val
w.proxy.SendMessage(locale.Loc("worldname_set", locale.Strmap{"Name": w.worldState.Name}))
@ -260,7 +259,7 @@ func (w *worldsServer) setWorldName(val string, fromUI bool) bool {
return true
}
func (w *worldsServer) CurrentName() string {
func (w *worldsHandler) CurrentName() string {
worldName := "world"
if w.serverState.worldCounter > 1 {
worldName = fmt.Sprintf("world-%d", w.serverState.worldCounter)
@ -268,9 +267,9 @@ func (w *worldsServer) CurrentName() string {
return worldName
}
func (w *worldsServer) Reset(newName string) {
func (w *worldsHandler) Reset(newName string) {
w.worldState = worldState{
Dim: nil,
dimension: nil,
chunks: make(map[protocol.ChunkPos]*chunk.Chunk),
blockNBT: make(map[protocol.SubChunkPos][]map[string]any),
entities: make(map[uint64]*entityState),
@ -280,23 +279,63 @@ func (w *worldsServer) Reset(newName string) {
w.mapUI.Reset()
}
// SaveAndReset writes the world to a folder, resets all the chunks
func (w *worldsServer) SaveAndReset() {
// cull empty chunks
keys := make([]protocol.ChunkPos, 0, len(w.worldState.chunks))
for cp := range w.worldState.chunks {
func (w *worldState) cullChunks() {
keys := make([]protocol.ChunkPos, 0, len(w.chunks))
for cp := range w.chunks {
keys = append(keys, cp)
}
for _, cp := range fp.Filter(func(cp protocol.ChunkPos) bool {
return !fp.Some(func(sc *chunk.SubChunk) bool {
return !sc.Empty()
})(w.worldState.chunks[cp].Sub())
})(w.chunks[cp].Sub())
})(keys) {
delete(w.worldState.chunks, cp)
delete(w.chunks, cp)
}
}
func (w *worldState) Save(folder string) (*mcdb.Provider, error) {
provider, err := mcdb.New(logrus.StandardLogger(), folder, opt.DefaultCompression)
if err != nil {
return nil, err
}
// save chunk data
for cp, c := range w.chunks {
provider.SaveChunk((world.ChunkPos)(cp), c, w.dimension)
}
// save block nbt data
blockNBT := make(map[world.ChunkPos][]map[string]any)
for scp, v := range w.blockNBT { // 3d to 2d
cp := world.ChunkPos{scp.X(), scp.Z()}
blockNBT[cp] = append(blockNBT[cp], v...)
}
for cp, v := range blockNBT {
err = provider.SaveBlockNBT(cp, v, w.dimension)
if err != nil {
logrus.Error(err)
}
}
// save entities
chunkEntities := make(map[world.ChunkPos][]world.Entity)
for _, es := range w.entities {
cp := world.ChunkPos{int32(es.Position.X()) >> 4, int32(es.Position.Z()) >> 4}
chunkEntities[cp] = append(chunkEntities[cp], es.ToServerEntity())
}
for cp, v := range chunkEntities {
err = provider.SaveEntities(cp, v, w.dimension)
if err != nil {
logrus.Error(err)
}
}
return provider, err
}
// SaveAndReset writes the world to a folder, resets all the chunks
func (w *worldsHandler) SaveAndReset() {
w.worldState.cullChunks()
if len(w.worldState.chunks) == 0 {
w.Reset(w.CurrentName())
return
@ -312,42 +351,10 @@ func (w *worldsServer) SaveAndReset() {
folder := path.Join("worlds", fmt.Sprintf("%s/%s", w.serverState.Name, w.worldState.Name))
os.RemoveAll(folder)
os.MkdirAll(folder, 0o777)
provider, err := mcdb.New(logrus.StandardLogger(), folder, opt.DefaultCompression)
provider, err := w.worldState.Save(folder)
if err != nil {
logrus.Fatal(err)
}
// save chunk data
for cp, c := range w.worldState.chunks {
provider.SaveChunk((world.ChunkPos)(cp), c, w.worldState.Dim)
}
// save block nbt data
blockNBT := make(map[world.ChunkPos][]map[string]any)
for scp, v := range w.worldState.blockNBT { // 3d to 2d
cp := world.ChunkPos{scp.X(), scp.Z()}
blockNBT[cp] = append(blockNBT[cp], v...)
}
for cp, v := range blockNBT {
err = provider.SaveBlockNBT(cp, v, w.worldState.Dim)
if err != nil {
logrus.Error(err)
}
}
// save entities
chunkEntities := make(map[world.ChunkPos][]world.Entity)
for _, es := range w.worldState.entities {
cp := world.ChunkPos{int32(es.Position.X()) >> 4, int32(es.Position.Z()) >> 4}
chunkEntities[cp] = append(chunkEntities[cp], es.ToServerEntity())
}
for cp, v := range chunkEntities {
err = provider.SaveEntities(cp, v, w.worldState.Dim)
if err != nil {
logrus.Error(err)
}
logrus.Error(err)
return
}
err = provider.SaveLocalPlayerData(w.playerData())
@ -366,6 +373,7 @@ func (w *worldsServer) SaveAndReset() {
// set gamerules
ld := provider.LevelDat()
gd := w.proxy.Server.GameData()
ld.RandomSeed = int64(gd.WorldSeed)
for _, gr := range gd.GameRules {
switch gr.Name {
case "commandblockoutput":
@ -434,8 +442,6 @@ func (w *worldsServer) SaveAndReset() {
}
}
ld.RandomSeed = int64(gd.WorldSeed)
// void world
if w.settings.voidGen {
ld.FlatWorldLayers = `{"biome_id":1,"block_layers":[{"block_data":0,"block_id":0,"count":1},{"block_data":0,"block_id":0,"count":2},{"block_data":0,"block_id":0,"count":1}],"encoding_version":3,"structure_options":null}`
@ -545,9 +551,8 @@ func (w *worldsServer) SaveAndReset() {
w.gui.Message(messages.SetUIState(messages.UIStateMain))
}
func (w *worldsServer) OnConnect(err error) bool {
func (w *worldsHandler) OnConnect(err error) bool {
w.gui.Message(messages.SetUIState(messages.UIStateMain))
if err != nil {
return false
}
@ -592,40 +597,14 @@ func (w *worldsServer) OnConnect(err error) bool {
dimensionID := gd.Dimension
if w.serverState.ispre118 {
logrus.Info(locale.Loc("using_under_118", nil))
dimensionID += 10
if dimensionID == 0 {
dimensionID += 10
}
}
w.worldState.Dim = dimensionIDMap[uint8(dimensionID)]
w.worldState.dimension, _ = world.DimensionByID(int(dimensionID))
}
w.proxy.SendMessage(locale.Loc("use_setname", nil))
w.proxy.AddCommand(utils.IngameCommand{
Exec: func(cmdline []string) bool {
return w.setWorldName(strings.Join(cmdline, " "), false)
},
Cmd: protocol.Command{
Name: "setname",
Description: locale.Loc("setname_desc", nil),
Overloads: []protocol.CommandOverload{{
Parameters: []protocol.CommandParameter{{
Name: "name",
Type: protocol.CommandArgTypeString,
Optional: false,
}},
}},
},
})
w.proxy.AddCommand(utils.IngameCommand{
Exec: func(cmdline []string) bool {
return w.setVoidGen(!w.settings.voidGen, false)
},
Cmd: protocol.Command{
Name: "void",
Description: locale.Loc("void_desc", nil),
},
})
w.mapUI.Start()
return true
}

View File

@ -102,7 +102,6 @@ func (p *Page) Layout(gtx C, th *material.Theme) D {
go func() {
defer p.Router.Wg.Done()
utils.InitDNS()
utils.InitExtraDebug(p.Router.Ctx)
err := cmd.Execute(p.Router.Ctx, utils.CurrentUI)
if err != nil {

View File

@ -28,12 +28,12 @@ func dumpPacket(f io.WriteCloser, toServer bool, payload []byte) {
f.Write([]byte{0xBB, 0xBB, 0xBB, 0xBB})
}
type PacketCapturer struct {
type packetCapturer struct {
proxy *utils.ProxyContext
fio *os.File
}
func (p *PacketCapturer) AddressAndName(address, hostname string) error {
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 {
@ -44,7 +44,7 @@ func (p *PacketCapturer) AddressAndName(address, hostname string) error {
return nil
}
func (p *PacketCapturer) PacketFunc(header packet.Header, payload []byte, src, dst net.Addr) {
func (p *packetCapturer) PacketFunc(header packet.Header, payload []byte, src, dst net.Addr) {
IsfromClient := utils.ClientAddr.String() == src.String()
buf := bytes.NewBuffer(nil)
@ -54,14 +54,14 @@ func (p *PacketCapturer) PacketFunc(header packet.Header, payload []byte, src, d
}
func NewPacketCapturer() *utils.ProxyHandler {
p := &PacketCapturer{}
p := &packetCapturer{}
return &utils.ProxyHandler{
Name: "Packet Capturer",
ProxyRef: func(pc *utils.ProxyContext) {
p.proxy = pc
},
PacketFunc: p.PacketFunc,
AddressAndName: p.AddressAndName,
PacketFunc: p.PacketFunc,
OnEnd: func() {
p.fio.Close()
},

View File

@ -10,22 +10,12 @@ import (
"github.com/sirupsen/logrus"
)
type ChatLogger struct {
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) {
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 {
@ -42,13 +32,21 @@ func (c *ChatLogger) PacketCB(pk packet.Packet, toServer bool, t time.Time) (pac
}
func NewChatLogger() *utils.ProxyHandler {
p := &ChatLogger{}
c := &chatLogger{}
return &utils.ProxyHandler{
Name: "Packet Capturer",
PacketCB: p.PacketCB,
AddressAndName: p.AddressAndName,
Name: "Packet Capturer",
PacketCB: c.PacketCB,
AddressAndName: func(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
},
OnEnd: func() {
p.fio.Close()
c.fio.Close()
},
}
}

View File

@ -0,0 +1,96 @@
package seconduser
import (
"github.com/bedrock-tool/bedrocktool/locale"
"github.com/df-mc/dragonfly/server/world"
"github.com/df-mc/dragonfly/server/world/chunk"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
"github.com/sirupsen/logrus"
)
func (s *secondaryUser) ResetWorld() {
s.chunks = make(map[world.ChunkPos]*chunk.Chunk)
s.blockNBT = make(map[protocol.SubChunkPos][]map[string]any)
}
func (s *secondaryUser) processChangeDimension(pk *packet.ChangeDimension) {
s.ResetWorld()
dimensionID := pk.Dimension
if s.ispre118 && dimensionID == 0 {
dimensionID += 10
}
s.dimension, _ = world.DimensionByID(int(dimensionID))
}
func (s *secondaryUser) processLevelChunk(pk *packet.LevelChunk) {
// ignore empty chunks THANKS WEIRD SERVER SOFTWARE DEVS
if len(pk.RawPayload) == 0 {
logrus.Info(locale.Loc("empty_chunk", nil))
return
}
var subChunkCount int
switch pk.SubChunkCount {
case protocol.SubChunkRequestModeLimited:
fallthrough
case protocol.SubChunkRequestModeLimitless:
subChunkCount = 0
default:
subChunkCount = int(pk.SubChunkCount)
}
ch, blockNBTs, err := chunk.NetworkDecode(world.AirRID(), pk.RawPayload, subChunkCount, s.dimension.Range(), s.ispre118, s.hasCustomBlocks)
if err != nil {
logrus.Error(err)
return
}
if blockNBTs != nil {
s.blockNBT[protocol.SubChunkPos{
pk.Position.X(), 0, pk.Position.Z(),
}] = blockNBTs
}
s.chunks[world.ChunkPos(pk.Position)] = ch
switch pk.SubChunkCount {
case protocol.SubChunkRequestModeLimited:
case protocol.SubChunkRequestModeLimitless:
default:
}
for _, p := range s.server.Players() {
p.Session().ViewChunk(world.ChunkPos(pk.Position), ch, nil)
}
}
func (s *secondaryUser) processSubChunk(pk *packet.SubChunk) {
offsets := make([]protocol.SubChunkOffset, 0, len(pk.SubChunkEntries))
for _, sub := range pk.SubChunkEntries {
offsets = append(offsets, sub.Offset)
var (
absX = pk.Position[0] + int32(sub.Offset[0])
absY = pk.Position[1] + int32(sub.Offset[1])
absZ = pk.Position[2] + int32(sub.Offset[2])
subPos = protocol.SubChunkPos{absX, absY, absZ}
pos = world.ChunkPos{absX, absZ}
)
ch, ok := s.chunks[pos]
if !ok {
logrus.Error(locale.Loc("subchunk_before_chunk", nil))
continue
}
blockNBT, err := ch.ApplySubChunkEntry(uint8(absY), &sub)
if err != nil {
logrus.Error(err)
}
if blockNBT != nil {
s.blockNBT[subPos] = blockNBT
}
chunk.LightArea([]*chunk.Chunk{ch}, 0, 0).Fill()
}
for _, p := range s.server.Players() {
p.Session().ViewSubChunks(world.SubChunkPos(pk.Position), offsets)
}
}

View File

@ -0,0 +1,19 @@
package seconduser
import "github.com/df-mc/dragonfly/server/session"
type fwdlistener struct {
Conn chan session.Conn
}
func (l *fwdlistener) Accept() (session.Conn, error) {
return <-l.Conn, nil
}
func (l *fwdlistener) Disconnect(conn session.Conn, reason string) error {
return conn.Close()
}
func (l *fwdlistener) Close() error {
return nil
}

View File

@ -0,0 +1,64 @@
package seconduser
import (
"sync"
"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/world"
"github.com/df-mc/dragonfly/server/world/chunk"
"github.com/google/uuid"
)
type provider struct {
s *secondaryUser
}
func (p *provider) Settings() *world.Settings {
return &world.Settings{
Mutex: sync.Mutex{},
Name: "world",
Spawn: cube.Pos{0, 0, 0},
DefaultGameMode: world.GameModeCreative,
Difficulty: world.DifficultyNormal,
}
}
func (p *provider) SaveSettings(*world.Settings) {
}
func (p *provider) Close() error {
return nil
}
func (p *provider) LoadPlayerSpawnPosition(uuid uuid.UUID) (pos cube.Pos, exists bool, err error) {
return cube.Pos{0, 0, 0}, false, nil
}
func (p *provider) SavePlayerSpawnPosition(uuid uuid.UUID, pos cube.Pos) error {
return nil
}
func (p *provider) LoadChunk(position world.ChunkPos, dim world.Dimension) (c *chunk.Chunk, exists bool, err error) {
c, ok := p.s.chunks[position]
return c, ok, nil
}
func (p *provider) SaveChunk(position world.ChunkPos, c *chunk.Chunk, dim world.Dimension) error {
return nil
}
func (p *provider) LoadEntities(position world.ChunkPos, dim world.Dimension, reg world.EntityRegistry) ([]world.Entity, error) {
return nil, nil
}
func (p *provider) SaveEntities(position world.ChunkPos, entities []world.Entity, dim world.Dimension) error {
return nil
}
func (p *provider) LoadBlockNBT(position world.ChunkPos, dim world.Dimension) ([]map[string]any, error) {
return nil, nil
}
func (p *provider) SaveBlockNBT(position world.ChunkPos, data []map[string]any, dim world.Dimension) error {
return nil
}

View File

@ -0,0 +1,104 @@
package seconduser
import (
"time"
"github.com/bedrock-tool/bedrocktool/utils"
"github.com/df-mc/dragonfly/server"
"github.com/df-mc/dragonfly/server/player"
"github.com/df-mc/dragonfly/server/player/skin"
"github.com/df-mc/dragonfly/server/session"
"github.com/df-mc/dragonfly/server/world"
"github.com/df-mc/dragonfly/server/world/chunk"
"github.com/go-gl/mathgl/mgl64"
"github.com/sandertv/gophertunnel/minecraft"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
"github.com/sirupsen/logrus"
)
type secondaryUser struct {
listener *fwdlistener
server *server.Server
ispre118 bool
hasCustomBlocks bool
chunks map[world.ChunkPos]*chunk.Chunk
blockNBT map[protocol.SubChunkPos][]map[string]any
dimension world.Dimension
mainPlayer *player.Player
}
func NewSecondUser() *utils.ProxyHandler {
s := &secondaryUser{
listener: &fwdlistener{
Conn: make(chan session.Conn),
},
chunks: make(map[world.ChunkPos]*chunk.Chunk),
blockNBT: make(map[protocol.SubChunkPos][]map[string]any),
dimension: world.Overworld,
}
s.server = server.Config{
Listeners: []func(conf server.Config) (server.Listener, error){
func(conf server.Config) (server.Listener, error) {
return s.listener, nil
},
},
Log: logrus.StandardLogger(),
Name: "Secondary",
Generator: func(dim world.Dimension) world.Generator { return &world.NopGenerator{} },
WorldProvider: &provider{s: s},
ReadOnlyWorld: true,
}.New()
go s.loop()
return &utils.ProxyHandler{
Name: "Secondary User",
SecondaryClientCB: s.SecondaryClientCB,
OnClientConnect: func(conn *minecraft.Conn) {
id := conn.IdentityData()
s.mainPlayer = player.New(id.DisplayName, skin.New(64, 64), mgl64.Vec3{0, 00})
},
PacketCB: func(pk packet.Packet, toServer bool, timeReceived time.Time) (packet.Packet, error) {
switch pk := pk.(type) {
case *packet.LevelChunk:
s.processLevelChunk(pk)
case *packet.SubChunk:
s.processSubChunk(pk)
case *packet.ChangeDimension:
s.processChangeDimension(pk)
case *packet.MovePlayer:
v := mgl64.Vec3{float64(pk.Position.X()), float64(pk.Position.Y()), float64(pk.Position.Z())}
s.mainPlayer.Teleport(v)
case *packet.PlayerAuthInput:
v := mgl64.Vec3{float64(pk.Position.X()), float64(pk.Position.Y()), float64(pk.Position.Z())}
s.mainPlayer.Teleport(v)
for _, p := range s.server.Players() {
p.Teleport(s.mainPlayer.Position())
}
}
return pk, nil
},
}
}
func (s *secondaryUser) SecondaryClientCB(conn *minecraft.Conn) {
s.listener.Conn <- conn
}
func (s *secondaryUser) loop() {
s.server.Listen()
for s.server.Accept(func(p *player.Player) {
logrus.Infof("%s Joined", p.Name())
p.Teleport(s.mainPlayer.Position())
}) {
}
}

View File

@ -60,7 +60,7 @@ func (s *SkinSaver) AddSkin(playerName string, playerID uuid.UUID, playerSkin *p
}
s.playerNames[playerID] = playerName
skin := &utils.Skin{playerSkin}
skin := &utils.Skin{Skin: playerSkin}
if s.OnlyIfHasGeometry && !skin.HaveGeometry() {
return "", nil, false
}

View File

@ -74,7 +74,6 @@ func (c *InteractiveCLI) Start(ctx context.Context, cancel context.CancelFunc) e
flag.Parse()
InitDNS()
InitExtraDebug(ctx)
subcommands.Execute(ctx)

View File

@ -1,15 +1,17 @@
package utils
import (
"bufio"
"bytes"
"fmt"
"io"
"net"
"os"
"reflect"
"strings"
"sync"
"github.com/bedrock-tool/bedrocktool/locale"
"github.com/bedrock-tool/bedrocktool/utils/crypt"
"github.com/fatih/color"
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
@ -182,52 +184,87 @@ func DumpStruct(data interface{}) {
var ClientAddr net.Addr
var pool = packet.NewPool()
func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) {
var pk packet.Packet
if pkFunc, ok := pool[header.PacketID]; ok {
pk = pkFunc()
} else {
pk = &packet.Unknown{PacketID: header.PacketID, Payload: payload}
}
func NewDebugLogger(extraVerbose bool) *ProxyHandler {
var logPlain, logCrypt, logCryptEnc io.WriteCloser
var packetsLogF *bufio.Writer
defer func() {
if recoveredErr := recover(); recoveredErr != nil {
logrus.Errorf("%T: %s", pk, recoveredErr.(error))
if extraVerbose {
// open plain text log
logPlain, err := os.Create("packets.log")
if err != nil {
logrus.Error(err)
}
}()
pk.Marshal(protocol.NewReader(bytes.NewBuffer(payload), 0))
if FLog != nil {
dmpLock.Lock()
FLog.Write([]byte(dmpStruct(0, pk, true, false) + "\n\n\n"))
dmpLock.Unlock()
}
pkName := reflect.TypeOf(pk).String()[1:]
if slices.Contains(MutedPackets, pkName) {
return
}
switch pk := pk.(type) {
case *packet.Disconnect:
logrus.Infof(locale.Loc("disconnect", locale.Strmap{"Pk": pk}))
}
dirS2C := color.GreenString("S") + "->" + color.CyanString("C")
dirC2S := color.CyanString("C") + "->" + color.GreenString("S")
var dir string = dirS2C
if ClientAddr != nil {
if src == ClientAddr {
dir = dirC2S
}
} else {
srcAddr, _, _ := net.SplitHostPort(src.String())
if IPPrivate(net.ParseIP(srcAddr)) {
dir = dirS2C
// open gpg log
logCrypt, err := os.Create("packets.log.gpg")
if err != nil {
logrus.Error(err)
} else {
// encrypter for the log
logCryptEnc, err = crypt.Encer("packets.log", logCrypt)
if err != nil {
logrus.Error(err)
}
}
packetsLogF = bufio.NewWriter(io.MultiWriter(logPlain, logCryptEnc))
}
logrus.Debugf("%s 0x%02x, %s", dir, pk.ID(), pkName)
return &ProxyHandler{
Name: "Debug",
PacketFunc: func(header packet.Header, payload []byte, src, dst net.Addr) {
var pk packet.Packet
if pkFunc, ok := pool[header.PacketID]; ok {
pk = pkFunc()
} else {
pk = &packet.Unknown{PacketID: header.PacketID, Payload: payload}
}
defer func() {
if recoveredErr := recover(); recoveredErr != nil {
logrus.Errorf("%T: %s", pk, recoveredErr.(error))
}
}()
pk.Marshal(protocol.NewReader(bytes.NewBuffer(payload), 0))
if extraVerbose {
dmpLock.Lock()
packetsLogF.Write([]byte(dmpStruct(0, pk, true, false) + "\n\n\n"))
dmpLock.Unlock()
}
pkName := reflect.TypeOf(pk).String()[1:]
if !slices.Contains(MutedPackets, pkName) {
dirS2C := color.GreenString("S") + "->" + color.CyanString("C")
dirC2S := color.CyanString("C") + "->" + color.GreenString("S")
var dir string = dirS2C
if ClientAddr != nil {
if src == ClientAddr {
dir = dirC2S
}
} else {
srcAddr, _, _ := net.SplitHostPort(src.String())
if IPPrivate(net.ParseIP(srcAddr)) {
dir = dirS2C
}
}
logrus.Debugf("%s 0x%02x, %s", dir, pk.ID(), pkName)
}
},
OnEnd: func() {
if packetsLogF != nil {
packetsLogF.Flush()
}
if logPlain != nil {
logPlain.Close()
}
if logCryptEnc != nil {
logCryptEnc.Close()
}
if logCrypt != nil {
logCrypt.Close()
}
},
}
}

View File

@ -55,7 +55,10 @@ type ProxyHandler struct {
Name string
ProxyRef func(*ProxyContext)
//
AddressAndName func(address, name string) error
AddressAndName func(address, hostname string) error
// called to change game data
GameDataModifier func(*minecraft.GameData)
// called for every packet
PacketFunc func(header packet.Header, payload []byte, src, dst net.Addr)
@ -85,9 +88,6 @@ type ProxyContext struct {
CustomClientData *login.ClientData
handlers []*ProxyHandler
// called to change game data
GameDataModifier func(*minecraft.GameData)
}
func NewProxy() (*ProxyContext, error) {
@ -284,6 +284,10 @@ func (p *ProxyContext) Run(ctx context.Context, serverAddress, name string) (err
}
}
if Options.Debug || Options.ExtraDebug {
p.AddHandler(NewDebugLogger(Options.ExtraDebug))
}
if strings.HasPrefix(serverAddress, "PCAP!") {
return createReplayConnection(ctx, serverAddress[5:], p)
}
@ -373,8 +377,10 @@ func (p *ProxyContext) Run(ctx context.Context, serverAddress, name string) (err
defer p.Server.Close()
gd := p.Server.GameData()
if p.GameDataModifier != nil {
p.GameDataModifier(&gd)
for _, handler := range p.handlers {
if handler.GameDataModifier != nil {
handler.GameDataModifier(&gd)
}
}
// spawn and start the game
@ -427,14 +433,16 @@ func (p *ProxyContext) Run(ctx context.Context, serverAddress, name string) (err
if len(wantSecondary) > 0 {
go func() {
c, err := p.Listener.Accept()
if err != nil {
logrus.Error(err)
return
}
for {
c, err := p.Listener.Accept()
if err != nil {
logrus.Error(err)
return
}
for _, handler := range wantSecondary {
go handler.SecondaryClientCB(c.(*minecraft.Conn))
for _, handler := range wantSecondary {
go handler.SecondaryClientCB(c.(*minecraft.Conn))
}
}
}()
}

View File

@ -141,10 +141,6 @@ func createReplayConnection(ctx context.Context, filename string, proxy *ProxyCo
dst = client
}
if Options.Debug {
PacketLogger(hdr, f.Bytes(), src, dst)
}
for _, handler := range proxy.handlers {
if handler.PacketFunc != nil {
handler.PacketFunc(hdr, f.Bytes(), src, dst)

View File

@ -2,14 +2,12 @@
package utils
import (
"bufio"
"bytes"
"context"
"crypto/aes"
"crypto/sha256"
"encoding/json"
"errors"
"io"
"net"
"os"
"path"
@ -18,7 +16,6 @@ import (
"sync"
"github.com/bedrock-tool/bedrocktool/locale"
"github.com/bedrock-tool/bedrocktool/utils/crypt"
"github.com/google/uuid"
"github.com/sandertv/gophertunnel/minecraft"
"github.com/sirupsen/logrus"
@ -72,10 +69,6 @@ func connectServer(ctx context.Context, address string, ClientData *login.Client
if header.PacketID == packet.IDRequestNetworkSettings {
ClientAddr = src
}
if Options.Debug {
PacketLogger(header, payload, src, dst)
}
if packetFunc != nil {
packetFunc(header, payload, src, dst)
}
@ -174,50 +167,3 @@ func CfbDecrypt(data []byte, key []byte) []byte {
}
return data
}
func InitExtraDebug(ctx context.Context) {
if !Options.ExtraDebug {
return
}
Options.Debug = true
var logPlain, logCryptEnc io.WriteCloser = nil, nil
// open plain text log
logPlain, err := os.Create("packets.log")
if err != nil {
logrus.Error(err)
}
// open gpg log
logCrypt, err := os.Create("packets.log.gpg")
if err != nil {
logrus.Error(err)
} else {
// encrypter for the log
logCryptEnc, err = crypt.Encer("packets.log", logCrypt)
if err != nil {
logrus.Error(err)
}
}
b := bufio.NewWriter(io.MultiWriter(logPlain, logCryptEnc))
FLog = b
if err != nil {
logrus.Error(err)
}
go func() {
<-ctx.Done()
b.Flush()
if logPlain != nil {
logPlain.Close()
}
if logCrypt != nil {
logCrypt.Close()
}
if logCryptEnc != nil {
logCryptEnc.Close()
}
}()
}