performance optimizations

This commit is contained in:
olebeck 2023-03-30 13:48:03 +02:00
parent d3a8219d99
commit 1e990d7fcb
15 changed files with 320 additions and 263 deletions

View File

@ -41,6 +41,15 @@ func (c *CLI) Start(ctx context.Context, cancel context.CancelFunc) error {
}
func main() {
/*
cf, _ := os.Create("cpu.pprof")
err := pprof.StartCPUProfile(cf)
if err != nil {
logrus.Error(err)
}
defer pprof.StopCPUProfile()
*/
defer func() {
if err := recover(); err != nil {
logrus.Errorf(locale.Loc("fatal_error", nil))

5
go.mod
View File

@ -6,7 +6,7 @@ go 1.20
replace github.com/sandertv/gophertunnel => github.com/olebeck/gophertunnel v1.28.1-1
//replace github.com/df-mc/dragonfly => ./dragonfly
replace github.com/df-mc/dragonfly => github.com/olebeck/dragonfly v0.9.3-10
replace github.com/df-mc/dragonfly => github.com/olebeck/dragonfly v0.9.4-3
//replace gioui.org => ./gio
replace gioui.org => github.com/olebeck/gio v0.0.0-20230321105529-d424f1a59af9
@ -15,7 +15,7 @@ require (
gioui.org v0.0.0-20230323230841-d7b1c7c33b33
gioui.org/x v0.0.0-20230313161557-05b40af72ed0
github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
github.com/df-mc/dragonfly v0.9.3
github.com/df-mc/dragonfly v0.9.4
github.com/df-mc/goleveldb v1.1.9
github.com/fatih/color v1.15.0
github.com/flytam/filenamify v1.1.2
@ -48,6 +48,7 @@ require (
github.com/changkun/lockfree v0.0.1 // indirect
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 // indirect
github.com/df-mc/atomic v1.10.0 // indirect
github.com/df-mc/worldupgrader v1.0.3 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-text/typesetting v0.0.0-20221214153724-0399769901d5 // indirect
github.com/golang/protobuf v1.5.2 // indirect

6
go.sum
View File

@ -30,6 +30,8 @@ github.com/df-mc/atomic v1.10.0 h1:0ZuxBKwR/hxcFGorKiHIp+hY7hgY+XBTzhCYD2NqSEg=
github.com/df-mc/atomic v1.10.0/go.mod h1:Gw9rf+rPIbydMjA329Jn4yjd/O2c/qusw3iNp4tFGSc=
github.com/df-mc/goleveldb v1.1.9 h1:ihdosZyy5jkQKrxucTQmN90jq/2lUwQnJZjIYIC/9YU=
github.com/df-mc/goleveldb v1.1.9/go.mod h1:+NHCup03Sci5q84APIA21z3iPZCuk6m6ABtg4nANCSk=
github.com/df-mc/worldupgrader v1.0.3 h1:3nbthy6vfSNQZdqHBR+E5Fh3mCeWmCwLtqrYDiPUG5I=
github.com/df-mc/worldupgrader v1.0.3/go.mod h1:6ybkJ/BV9b0XkcPzcLmvgT9Nv/xgBXdDQTmRhu7b8zQ=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/flytam/filenamify v1.1.2 h1:dGlfWU4zrhDlsmvob4IFcfgjG5vIjfo4UwLyec6Wx94=
@ -83,6 +85,10 @@ github.com/nicksnyder/go-i18n/v2 v2.2.1 h1:aOzRCdwsJuoExfZhoiXHy4bjruwCMdt5otbYo
github.com/nicksnyder/go-i18n/v2 v2.2.1/go.mod h1:fF2++lPHlo+/kPaj3nB0uxtPwzlPm+BlgwGX7MkeGj0=
github.com/olebeck/dragonfly v0.9.3-10 h1:USruaK+8c3gsX9CtDzInLbwsdoZxcYjmnC8t/H4/Zjw=
github.com/olebeck/dragonfly v0.9.3-10/go.mod h1:nnnmYWgSTNQb9x33nBthqN/2vyHlUaijfo+e2y3W5j4=
github.com/olebeck/dragonfly v0.9.4-1 h1:AvP0JALUJqkDBTCT/7tOrIndKIrIol1rX6XFcbOwpLI=
github.com/olebeck/dragonfly v0.9.4-1/go.mod h1:Iu46xugbkTQ9CcUj+zPC4VvKP94CmxxLGtW8pHgAPr4=
github.com/olebeck/dragonfly v0.9.4-2 h1:e1bzsTxcPMaUUs2B6wnCbc1FE96XcdBbL7mp1LE92NI=
github.com/olebeck/dragonfly v0.9.4-2/go.mod h1:k8OQvjmfj+JbrwQf1qHfMETlFHOp0WJLjILN+QVqh+c=
github.com/olebeck/gio v0.0.0-20230321105529-d424f1a59af9 h1:TqDsMHwjW5ZYfh+RE8ussT62m0qXqo+QjzSXb7BCVA4=
github.com/olebeck/gio v0.0.0-20230321105529-d424f1a59af9/go.mod h1:+W1Kpf96YcfissZocFqIp6O42FDTuphkObbEybp+Ffc=
github.com/olebeck/gophertunnel v1.28.1-1 h1:bw2jeMz94YHF5qQYhq1Yq/6fALkklGu7k26YbPI4DSs=

View File

@ -3,7 +3,6 @@ package subcommands
import (
"context"
"flag"
"strings"
"github.com/bedrock-tool/bedrocktool/locale"
"github.com/bedrock-tool/bedrocktool/utils"
@ -11,14 +10,12 @@ import (
type DebugProxyCMD struct {
ServerAddress string
Filter string
}
func (*DebugProxyCMD) Name() string { return "debug-proxy" }
func (*DebugProxyCMD) Synopsis() string { return locale.Loc("debug_proxy_synopsis", nil) }
func (c *DebugProxyCMD) SetFlags(f *flag.FlagSet) {
f.StringVar(&c.ServerAddress, "address", "", locale.Loc("remote_address", nil))
f.StringVar(&c.Filter, "filter", "", locale.Loc("packet_filter", nil))
}
func (c *DebugProxyCMD) Execute(ctx context.Context, ui utils.UI) error {
@ -29,27 +26,11 @@ func (c *DebugProxyCMD) Execute(ctx context.Context, ui utils.UI) error {
utils.Options.Debug = true
filters := strings.Split(c.Filter, ",")
if len(filters) > 0 {
for _, v := range filters {
if len(v) == 0 {
continue
}
if string(v[0]) == "*" {
v = v[1:]
}
v = strings.TrimPrefix(v, "packet.")
v = "packet." + v
utils.ExtraVerbose = append(utils.ExtraVerbose, v)
}
}
proxy, err := utils.NewProxy()
if err != nil {
return err
}
err = proxy.Run(ctx, address)
return err
return proxy.Run(ctx, address)
}
func init() {

View File

@ -9,21 +9,21 @@ import (
"github.com/sirupsen/logrus"
)
func (w *WorldState) processChangeDimension(pk *packet.ChangeDimension) {
if len(w.chunks) > 0 {
func (w *worldsServer) processChangeDimension(pk *packet.ChangeDimension) {
if len(w.worldState.chunks) > 0 {
w.SaveAndReset()
} else {
logrus.Info(locale.Loc("not_saving_empty", nil))
w.Reset()
w.Reset(w.CurrentName())
}
dimensionID := pk.Dimension
if w.ispre118 {
if w.serverState.ispre118 {
dimensionID += 10
}
w.Dim = dimensionIDMap[uint8(dimensionID)]
w.worldState.Dim = dimensionIDMap[uint8(dimensionID)]
}
func (w *WorldState) processLevelChunk(pk *packet.LevelChunk) {
func (w *worldsServer) processLevelChunk(pk *packet.LevelChunk) {
// ignore empty chunks THANKS WEIRD SERVER SOFTWARE DEVS
if len(pk.RawPayload) == 0 {
logrus.Info(locale.Loc("empty_chunk", nil))
@ -40,32 +40,35 @@ func (w *WorldState) processLevelChunk(pk *packet.LevelChunk) {
subChunkCount = int(pk.SubChunkCount)
}
ch, blockNBTs, err := chunk.NetworkDecode(world.AirRID(), pk.RawPayload, subChunkCount, w.Dim.Range(), w.ispre118, w.bp.HasBlocks())
ch, blockNBTs, err := chunk.NetworkDecode(world.AirRID(), pk.RawPayload, subChunkCount, w.worldState.Dim.Range(), w.serverState.ispre118, w.bp.HasBlocks())
if err != nil {
logrus.Error(err)
return
}
if blockNBTs != nil {
w.blockNBT[protocol.SubChunkPos{
w.worldState.blockNBT[protocol.SubChunkPos{
pk.Position.X(), 0, pk.Position.Z(),
}] = blockNBTs
}
w.chunks[pk.Position] = ch
w.worldState.chunks[pk.Position] = ch
max := w.Dim.Range().Height() / 16
max := w.worldState.Dim.Range().Height() / 16
switch pk.SubChunkCount {
case protocol.SubChunkRequestModeLimited:
max = int(pk.HighestSubChunk)
fallthrough
case protocol.SubChunkRequestModeLimitless:
var offsetTable []protocol.SubChunkOffset
r := w.Dim.Range()
r := w.worldState.Dim.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
w.proxy.Server.WritePacket(&packet.SubChunkRequest{
Dimension: int32(w.Dim.EncodeDimension()),
Dimension: int32(dimId),
Position: protocol.SubChunkPos{
pk.Position.X(), 0, pk.Position.Z(),
},
@ -86,7 +89,7 @@ func (w *WorldState) processLevelChunk(pk *packet.LevelChunk) {
}
}
func (w *WorldState) processSubChunk(pk *packet.SubChunk) {
func (w *worldsServer) processSubChunk(pk *packet.SubChunk) {
posToRedraw := make(map[protocol.ChunkPos]bool)
for _, sub := range pk.SubChunkEntries {
@ -97,7 +100,7 @@ func (w *WorldState) processSubChunk(pk *packet.SubChunk) {
subPos = protocol.SubChunkPos{absX, absY, absZ}
pos = protocol.ChunkPos{absX, absZ}
)
ch, ok := w.chunks[pos]
ch, ok := w.worldState.chunks[pos]
if !ok {
logrus.Error(locale.Loc("subchunk_before_chunk", nil))
continue
@ -107,7 +110,7 @@ func (w *WorldState) processSubChunk(pk *packet.SubChunk) {
logrus.Error(err)
}
if blockNBT != nil {
w.blockNBT[subPos] = blockNBT
w.worldState.blockNBT[subPos] = blockNBT
}
posToRedraw[pos] = true
@ -115,7 +118,7 @@ func (w *WorldState) processSubChunk(pk *packet.SubChunk) {
// redraw the chunks
for pos := range posToRedraw {
w.mapUI.SetChunk(pos, w.chunks[pos], true)
w.mapUI.SetChunk(pos, w.worldState.chunks[pos], true)
}
w.mapUI.SchedRedraw()
}
@ -124,22 +127,22 @@ func blockPosInChunk(pos protocol.BlockPos) (uint8, int16, uint8) {
return uint8(pos.X() & 0x0f), int16(pos.Y() & 0x0f), uint8(pos.Z() & 0x0f)
}
func (w *WorldState) ProcessChunkPackets(pk packet.Packet) packet.Packet {
func (w *worldsServer) 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.chunks), "Name": w.WorldName}, len(w.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:
if w.blockUpdates {
if w.settings.blockUpdates {
sp := protocol.SubChunkPos{pk.Position.X() << 4, 0, pk.Position.Z() << 4}
b, ok := w.blockNBT[sp]
b, ok := w.worldState.blockNBT[sp]
if !ok {
w.blockNBT[sp] = []map[string]any{pk.NBTData}
w.worldState.blockNBT[sp] = []map[string]any{pk.NBTData}
} else {
for i, v := range b {
x, y, z := v["x"].(int32), v["y"].(int32), v["z"].(int32)
@ -151,19 +154,19 @@ func (w *WorldState) ProcessChunkPackets(pk packet.Packet) packet.Packet {
}
}
case *packet.UpdateBlock:
if w.blockUpdates {
if w.settings.blockUpdates {
cp := protocol.ChunkPos{pk.Position.X() >> 4, pk.Position.Z() >> 4}
c, ok := w.chunks[cp]
c, ok := w.worldState.chunks[cp]
if ok {
x, y, z := blockPosInChunk(pk.Position)
c.SetBlock(x, y, z, uint8(pk.Layer), pk.NewBlockRuntimeID)
w.mapUI.SetChunk(cp, w.chunks[cp], true)
w.mapUI.SetChunk(cp, w.worldState.chunks[cp], true)
}
}
case *packet.UpdateSubChunkBlocks:
if w.blockUpdates {
if w.settings.blockUpdates {
cp := protocol.ChunkPos{pk.Position.X(), pk.Position.Z()}
c, ok := w.chunks[cp]
c, ok := w.worldState.chunks[cp]
if ok {
for _, bce := range pk.Blocks {
x, y, z := blockPosInChunk(bce.BlockPos)
@ -173,7 +176,7 @@ func (w *WorldState) ProcessChunkPackets(pk packet.Packet) packet.Packet {
c.SetBlock(x, y, z, 0, bce.BlockRuntimeID)
}
}
w.mapUI.SetChunk(cp, w.chunks[cp], true)
w.mapUI.SetChunk(cp, w.worldState.chunks[cp], true)
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 B

After

Width:  |  Height:  |  Size: 432 B

View File

@ -3,6 +3,7 @@ package world_test
import (
"image/png"
"os"
"runtime/pprof"
"testing"
"github.com/bedrock-tool/bedrocktool/subcommands/world"
@ -21,19 +22,32 @@ func Test(t *testing.T) {
func Benchmark_chunk_decode(b *testing.B) {
data, _ := os.ReadFile("chunk.bin")
cf, _ := os.Create("cpu.pprof")
err := pprof.StartCPUProfile(cf)
if err != nil {
b.Error(err)
}
for i := 0; i < b.N; i++ {
_, _, err := chunk.NetworkDecode(33, data, 6, cube.Range{0, 255}, true, false)
if err != nil {
b.Error(err)
}
}
pprof.StopCPUProfile()
}
func Benchmark_render_chunk(b *testing.B) {
data, _ := os.ReadFile("chunk.bin")
ch, _, _ := chunk.NetworkDecode(33, data, 6, cube.Range{0, 255}, true, false)
cf, _ := os.Create("cpu.pprof")
err := pprof.StartCPUProfile(cf)
if err != nil {
b.Error(err)
}
for i := 0; i < b.N; i++ {
world.Chunk2Img(ch, true)
}
pprof.StopCPUProfile()
}

View File

@ -61,8 +61,8 @@ func (e serverEntity) Type() world.EntityType {
return e.EntityType
}
func (w *WorldState) processAddActor(pk *packet.AddActor) {
e, ok := w.entities[pk.EntityRuntimeID]
func (w *worldsServer) processAddActor(pk *packet.AddActor) {
e, ok := w.worldState.entities[pk.EntityRuntimeID]
if !ok {
e = &entityState{
RuntimeID: pk.EntityRuntimeID,
@ -71,7 +71,7 @@ func (w *WorldState) processAddActor(pk *packet.AddActor) {
Inventory: make(map[byte]map[byte]protocol.ItemInstance),
Metadata: make(map[uint32]any),
}
w.entities[pk.EntityRuntimeID] = e
w.worldState.entities[pk.EntityRuntimeID] = e
w.bp.AddEntity(behaviourpack.EntityIn{
Identifier: pk.EntityType,
@ -211,25 +211,25 @@ func (s *entityState) ToServerEntity() serverEntity {
return e
}
func (w *WorldState) ProcessEntityPackets(pk packet.Packet) packet.Packet {
func (w *worldsServer) ProcessEntityPackets(pk packet.Packet) packet.Packet {
switch pk := pk.(type) {
case *packet.AddActor:
w.processAddActor(pk)
case *packet.RemoveActor:
case *packet.SetActorData:
e, ok := w.entities[pk.EntityRuntimeID]
e, ok := w.worldState.entities[pk.EntityRuntimeID]
if ok {
for k, v := range pk.EntityMetadata {
e.Metadata[k] = v
}
}
case *packet.SetActorMotion:
e, ok := w.entities[pk.EntityRuntimeID]
e, ok := w.worldState.entities[pk.EntityRuntimeID]
if ok {
e.Velocity = pk.Velocity
}
case *packet.MoveActorDelta:
e, ok := w.entities[pk.EntityRuntimeID]
e, ok := w.worldState.entities[pk.EntityRuntimeID]
if ok {
if pk.Flags&packet.MoveActorDeltaFlagHasX != 0 {
e.Position[0] = pk.Position[0]
@ -251,14 +251,14 @@ func (w *WorldState) ProcessEntityPackets(pk packet.Packet) packet.Packet {
//}
}
case *packet.MoveActorAbsolute:
e, ok := w.entities[pk.EntityRuntimeID]
e, ok := w.worldState.entities[pk.EntityRuntimeID]
if ok {
e.Position = pk.Position
e.Pitch = pk.Rotation.X()
e.Yaw = pk.Rotation.Y()
}
case *packet.MobEquipment:
e, ok := w.entities[pk.EntityRuntimeID]
e, ok := w.worldState.entities[pk.EntityRuntimeID]
if ok {
w, ok := e.Inventory[pk.WindowID]
if !ok {
@ -268,7 +268,7 @@ func (w *WorldState) ProcessEntityPackets(pk packet.Packet) packet.Packet {
w[pk.HotBarSlot] = pk.NewItem
}
case *packet.MobArmourEquipment:
e, ok := w.entities[pk.EntityRuntimeID]
e, ok := w.worldState.entities[pk.EntityRuntimeID]
if ok {
e.Helmet = &pk.Helmet
e.Chestplate = &pk.Chestplate

View File

@ -17,25 +17,25 @@ type itemContainer struct {
Content *packet.InventoryContent
}
func (w *WorldState) processItemPacketsServer(pk packet.Packet) packet.Packet {
func (w *worldsServer) processItemPacketsServer(pk packet.Packet) packet.Packet {
switch pk := pk.(type) {
case *packet.ContainerOpen:
// add to open containers
existing, ok := w.openItemContainers[pk.WindowID]
existing, ok := w.worldState.openItemContainers[pk.WindowID]
if !ok {
existing = &itemContainer{}
}
w.openItemContainers[pk.WindowID] = &itemContainer{
w.worldState.openItemContainers[pk.WindowID] = &itemContainer{
OpenPacket: pk,
Content: existing.Content,
}
case *packet.InventoryContent:
if pk.WindowID == 0x0 { // inventory
w.playerInventory = pk.Content
w.serverState.playerInventory = pk.Content
} else {
// save content
existing, ok := w.openItemContainers[byte(pk.WindowID)]
existing, ok := w.worldState.openItemContainers[byte(pk.WindowID)]
if ok {
existing.Content = pk
}
@ -43,10 +43,10 @@ func (w *WorldState) processItemPacketsServer(pk packet.Packet) packet.Packet {
case *packet.InventorySlot:
if pk.WindowID == 0x0 {
w.playerInventory[pk.Slot] = pk.NewItem
w.serverState.playerInventory[pk.Slot] = pk.NewItem
} else {
// save content
existing, ok := w.openItemContainers[byte(pk.WindowID)]
existing, ok := w.worldState.openItemContainers[byte(pk.WindowID)]
if ok {
existing.Content.Content[pk.Slot] = pk.NewItem
}
@ -56,7 +56,7 @@ func (w *WorldState) processItemPacketsServer(pk packet.Packet) packet.Packet {
case *packet.ContainerClose:
// find container info
existing, ok := w.openItemContainers[byte(pk.WindowID)]
existing, ok := w.worldState.openItemContainers[byte(pk.WindowID)]
switch pk.WindowID {
case protocol.WindowIDArmour: // todo handle
@ -88,11 +88,11 @@ func (w *WorldState) processItemPacketsServer(pk packet.Packet) packet.Packet {
}
// put into subchunk
nbts := w.blockNBT[cp]
nbts := w.worldState.blockNBT[cp]
for i, v := range nbts {
NBTPos := protocol.BlockPos{v["x"].(int32), v["y"].(int32), v["z"].(int32)}
if NBTPos == pos {
w.blockNBT[cp][i]["Items"] = nbtconv.InvToNBT(inv)
w.worldState.blockNBT[cp][i]["Items"] = nbtconv.InvToNBT(inv)
break
}
}
@ -100,7 +100,7 @@ func (w *WorldState) processItemPacketsServer(pk packet.Packet) packet.Packet {
w.proxy.SendMessage(locale.Loc("saved_block_inv", nil))
// remove it again
delete(w.openItemContainers, byte(pk.WindowID))
delete(w.worldState.openItemContainers, byte(pk.WindowID))
}
case *packet.ItemComponent:
@ -113,7 +113,7 @@ func (w *WorldState) processItemPacketsServer(pk packet.Packet) packet.Packet {
return pk
}
func (w *WorldState) processItemPacketsClient(pk packet.Packet, forward *bool) packet.Packet {
func (w *worldsServer) processItemPacketsClient(pk packet.Packet, forward *bool) packet.Packet {
switch pk := pk.(type) {
case *packet.ItemStackRequest:
var requests []protocol.ItemStackRequest
@ -184,15 +184,15 @@ func stackToItem(it protocol.ItemStack) item.Stack {
return nbtconv.ReadItem(it.NBTData, &s)
}
func (w *WorldState) playerData() (ret map[string]any) {
func (w *worldsServer) playerData() (ret map[string]any) {
ret = map[string]any{
"format_version": "1.12.0",
"identifier": "minecraft:player",
}
if len(w.playerInventory) > 0 {
inv := inventory.New(len(w.playerInventory), nil)
for i, ii := range w.playerInventory {
if len(w.serverState.playerInventory) > 0 {
inv := inventory.New(len(w.serverState.playerInventory), nil)
for i, ii := range w.serverState.playerInventory {
inv.SetItem(i, stackToItem(ii.Stack))
}
ret["Inventory"] = nbtconv.InvToNBT(inv)
@ -373,8 +373,8 @@ func (w *WorldState) playerData() (ret map[string]any) {
}
ret["Rotation"] = []float32{
w.PlayerPos.Pitch,
w.PlayerPos.Yaw,
w.serverState.PlayerPos.Pitch,
w.serverState.PlayerPos.Yaw,
}
return

View File

@ -79,10 +79,10 @@ type MapUI struct {
l sync.RWMutex
ticker *time.Ticker
w *WorldState
w *worldsServer
}
func NewMapUI(w *WorldState) *MapUI {
func NewMapUI(w *worldsServer) *MapUI {
m := &MapUI{
img: image.NewRGBA(image.Rect(0, 0, 128, 128)),
zoomLevel: 16,
@ -198,8 +198,8 @@ func (m *MapUI) Redraw() {
m.l.Unlock()
middle := protocol.ChunkPos{
int32(m.w.PlayerPos.Position.X()),
int32(m.w.PlayerPos.Position.Z()),
int32(m.w.serverState.PlayerPos.Position.X()),
int32(m.w.serverState.PlayerPos.Position.Z()),
}
chunksPerLine := float64(128 / m.zoomLevel)
@ -227,7 +227,7 @@ func (m *MapUI) Redraw() {
min, max := m.GetBounds()
m.w.gui.Message(messages.UpdateMap, messages.UpdateMapPayload{
ChunkCount: len(m.renderedChunks),
Rotation: m.w.PlayerPos.Yaw,
Rotation: m.w.serverState.PlayerPos.Yaw,
UpdatedTiles: updatedChunks,
Tiles: m.renderedChunks,
BoundsMin: min,
@ -265,14 +265,14 @@ func (m *MapUI) SetChunk(pos protocol.ChunkPos, ch *chunk.Chunk, complete bool)
m.SchedRedraw()
}
func (w *WorldState) ProcessAnimate(pk *packet.Animate) {
func (w *worldsServer) 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 *WorldState) processMapPacketsClient(pk packet.Packet, forward *bool) packet.Packet {
func (w *worldsServer) 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

@ -1,7 +1,6 @@
package world
import (
"bytes"
"context"
"encoding/json"
"flag"
@ -41,53 +40,69 @@ type TPlayerPos struct {
// the state used for drawing and saving
type WorldState struct {
type worldSettings struct {
// settings
voidGen bool
withPacks bool
saveImage bool
blockUpdates bool
}
type worldState struct {
Dim world.Dimension
chunks map[protocol.ChunkPos]*chunk.Chunk
blockNBT map[protocol.SubChunkPos][]map[string]any
entities map[uint64]*entityState
openItemContainers map[byte]*itemContainer
Name string
}
type serverState struct {
ChunkRadius int
ispre118 bool
worldCounter int
playerInventory []protocol.ItemInstance
PlayerPos TPlayerPos
Name string
}
type worldsServer struct {
ctx context.Context
proxy *utils.ProxyContext
mapUI *MapUI
gui utils.UI
bp *behaviourpack.BehaviourPack
// save state
ChunkRadius int
chunks map[protocol.ChunkPos]*chunk.Chunk
blockNBT map[protocol.SubChunkPos][]map[string]any
openItemContainers map[byte]*itemContainer
playerInventory []protocol.ItemInstance
entities map[uint64]*entityState
Dim world.Dimension
PlayerPos TPlayerPos
worldCounter int
WorldName string
ServerName string
ispre118 bool
// settings
voidGen bool
withPacks bool
saveImage bool
experimentInventory bool
blockUpdates bool
worldState worldState
serverState serverState
settings worldSettings
}
func NewWorldState(ctx context.Context, proxy *utils.ProxyContext, ServerName string, ui utils.UI) *WorldState {
w := &WorldState{
ctx: ctx,
proxy: proxy,
mapUI: nil,
gui: ui,
bp: behaviourpack.New(ServerName),
ServerName: ServerName,
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),
chunks: make(map[protocol.ChunkPos]*chunk.Chunk),
blockNBT: make(map[protocol.SubChunkPos][]map[string]any),
openItemContainers: make(map[byte]*itemContainer),
entities: make(map[uint64]*entityState),
Dim: nil,
WorldName: "world",
PlayerPos: TPlayerPos{},
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, messages.InitPayload{
Handler: w.uiMessage,
@ -118,11 +133,10 @@ func init() {
}
type WorldCMD struct {
ServerAddress string
Packs bool
EnableVoid bool
SaveImage bool
ExperimentInventory bool
ServerAddress string
Packs bool
EnableVoid bool
SaveImage bool
}
func (*WorldCMD) Name() string { return "worlds" }
@ -133,7 +147,6 @@ func (c *WorldCMD) SetFlags(f *flag.FlagSet) {
f.BoolVar(&c.Packs, "packs", false, locale.Loc("save_packs_with_world", nil))
f.BoolVar(&c.EnableVoid, "void", true, locale.Loc("enable_void", nil))
f.BoolVar(&c.SaveImage, "image", false, locale.Loc("save_image", nil))
f.BoolVar(&c.ExperimentInventory, "inv", false, locale.Loc("test_block_inv", nil))
}
func (c *WorldCMD) Execute(ctx context.Context, ui utils.UI) error {
@ -147,11 +160,12 @@ func (c *WorldCMD) Execute(ctx context.Context, ui utils.UI) error {
return err
}
w := NewWorldState(ctx, proxy, hostname, ui)
w.voidGen = c.EnableVoid
w.withPacks = c.Packs
w.saveImage = c.SaveImage
w.experimentInventory = c.ExperimentInventory
w := NewWorldsServer(ctx, proxy, hostname, ui)
w.settings = worldSettings{
voidGen: c.EnableVoid,
withPacks: c.Packs,
saveImage: c.SaveImage,
}
proxy.AlwaysGetPacks = true
proxy.GameDataModifier = func(gd *minecraft.GameData) {
@ -172,7 +186,7 @@ func (c *WorldCMD) Execute(ctx context.Context, ui utils.UI) error {
// from server
switch pk := pk.(type) {
case *packet.ChunkRadiusUpdated:
w.ChunkRadius = int(pk.ChunkRadius)
w.serverState.ChunkRadius = int(pk.ChunkRadius)
pk.ChunkRadius = 80
}
pk = w.processItemPacketsServer(pk)
@ -196,7 +210,7 @@ func (c *WorldCMD) Execute(ctx context.Context, ui utils.UI) error {
return nil
}
func (w *WorldState) uiMessage(name string, data interface{}) messages.MessageResponse {
func (w *worldsServer) uiMessage(name string, data interface{}) messages.MessageResponse {
r := messages.MessageResponse{
Ok: false,
Data: nil,
@ -212,24 +226,25 @@ func (w *WorldState) uiMessage(name string, data interface{}) messages.MessageRe
return r
}
func (w *WorldState) SetPlayerPos(Position mgl32.Vec3, Pitch, Yaw, HeadYaw float32) {
last := w.PlayerPos
w.PlayerPos = TPlayerPos{
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(w.PlayerPos.Position.X()) || int(last.Position.Z()) != int(w.PlayerPos.Position.Z()) {
if int(last.Position.X()) != int(current.Position.X()) || int(last.Position.Z()) != int(current.Position.Z()) {
w.mapUI.SchedRedraw()
}
}
func (w *WorldState) setVoidGen(val bool, fromUI bool) bool {
w.voidGen = val
func (w *worldsServer) setVoidGen(val bool, fromUI bool) bool {
w.settings.voidGen = val
var s string
if w.voidGen {
if w.settings.voidGen {
s = locale.Loc("void_generator_true", nil)
} else {
s = locale.Loc("void_generator_false", nil)
@ -238,68 +253,79 @@ func (w *WorldState) setVoidGen(val bool, fromUI bool) bool {
if !fromUI {
w.gui.Message(messages.SetVoidGen, messages.SetVoidGenPayload{
Value: w.voidGen,
Value: w.settings.voidGen,
})
}
return true
}
func (w *WorldState) setWorldName(val string, fromUI bool) bool {
w.WorldName = val
w.proxy.SendMessage(locale.Loc("worldname_set", locale.Strmap{"Name": w.WorldName}))
func (w *worldsServer) setWorldName(val string, fromUI bool) bool {
w.worldState.Name = val
w.proxy.SendMessage(locale.Loc("worldname_set", locale.Strmap{"Name": w.worldState.Name}))
if !fromUI {
w.gui.Message(messages.SetWorldName, messages.SetWorldNamePayload{
WorldName: w.WorldName,
WorldName: w.worldState.Name,
})
}
return true
}
func (w *WorldState) Reset() {
w.chunks = make(map[protocol.ChunkPos]*chunk.Chunk)
w.entities = make(map[uint64]*entityState)
w.blockNBT = make(map[protocol.SubChunkPos][]map[string]any)
w.openItemContainers = make(map[byte]*itemContainer)
w.WorldName = fmt.Sprintf("world-%d", w.worldCounter)
func (w *worldsServer) CurrentName() string {
worldName := "world"
if w.serverState.worldCounter > 1 {
worldName = fmt.Sprintf("world-%d", w.serverState.worldCounter)
}
return worldName
}
func (w *worldsServer) Reset(newName string) {
w.worldState = worldState{
Dim: nil,
chunks: make(map[protocol.ChunkPos]*chunk.Chunk),
blockNBT: make(map[protocol.SubChunkPos][]map[string]any),
entities: make(map[uint64]*entityState),
openItemContainers: make(map[byte]*itemContainer),
Name: newName,
}
w.mapUI.Reset()
}
// SaveAndReset writes the world to a folder, resets all the chunks
func (w *WorldState) SaveAndReset() {
func (w *worldsServer) SaveAndReset() {
// cull empty chunks
keys := make([]protocol.ChunkPos, 0, len(w.chunks))
for cp := range w.chunks {
keys := make([]protocol.ChunkPos, 0, len(w.worldState.chunks))
for cp := range w.worldState.chunks {
keys = append(keys, cp)
}
for _, cp := range keys {
has_any := false
for _, sc := range w.chunks[cp].Sub() {
for _, sc := range w.worldState.chunks[cp].Sub() {
has_any = !sc.Empty()
if has_any {
break
}
}
if !has_any {
delete(w.chunks, cp)
delete(w.worldState.chunks, cp)
}
}
if len(w.chunks) == 0 {
w.Reset()
if len(w.worldState.chunks) == 0 {
w.Reset(w.CurrentName())
return
}
logrus.Infof(locale.Loc("saving_world", locale.Strmap{"Name": w.WorldName, "Count": len(w.chunks)}))
logrus.Infof(locale.Loc("saving_world", locale.Strmap{"Name": w.worldState.Name, "Count": len(w.worldState.chunks)}))
w.gui.Message(messages.SavingWorld, messages.SavingWorldPayload{
Name: w.WorldName,
Chunks: len(w.chunks),
Name: w.worldState.Name,
Chunks: len(w.worldState.chunks),
})
// open world
folder := path.Join("worlds", fmt.Sprintf("%s/%s", w.ServerName, w.WorldName))
folder := path.Join("worlds", fmt.Sprintf("%s/%s", w.serverState.Name, w.worldState.Name))
os.RemoveAll(folder)
os.MkdirAll(folder, 0o777)
@ -309,18 +335,18 @@ func (w *WorldState) SaveAndReset() {
}
// save chunk data
for cp, c := range w.chunks {
provider.SaveChunk((world.ChunkPos)(cp), c, w.Dim)
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.blockNBT { // 3d to 2d
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.Dim)
err = provider.SaveBlockNBT(cp, v, w.worldState.Dim)
if err != nil {
logrus.Error(err)
}
@ -328,30 +354,30 @@ func (w *WorldState) SaveAndReset() {
// save entities
chunkEntities := make(map[world.ChunkPos][]world.Entity)
for _, es := range w.entities {
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.Dim)
err = provider.SaveEntities(cp, v, w.worldState.Dim)
if err != nil {
logrus.Error(err)
}
}
playerPos := w.proxy.Server.GameData().PlayerPosition
spawnPos := cube.Pos{int(playerPos.X()), int(playerPos.Y()), int(playerPos.Z())}
err = provider.SaveLocalPlayerData(w.playerData())
if err != nil {
logrus.Error(err)
}
playerPos := w.proxy.Server.GameData().PlayerPosition
spawnPos := cube.Pos{int(playerPos.X()), int(playerPos.Y()), int(playerPos.Z())}
// write metadata
s := provider.Settings()
s.Spawn = spawnPos
s.Name = w.WorldName
s.Name = w.worldState.Name
// set gamerules
ld := provider.LevelDat()
@ -427,7 +453,7 @@ func (w *WorldState) SaveAndReset() {
ld.RandomSeed = int64(gd.WorldSeed)
// void world
if w.voidGen {
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}`
ld.Generator = 2
}
@ -446,7 +472,7 @@ func (w *WorldState) SaveAndReset() {
logrus.Error(err)
}
w.worldCounter += 1
w.serverState.worldCounter += 1
type dep struct {
PackID string `json:"pack_id"`
@ -467,7 +493,7 @@ func (w *WorldState) SaveAndReset() {
// save behaviourpack
if w.bp.HasContent() {
name := strings.ReplaceAll(w.ServerName, "./", "")
name := strings.ReplaceAll(w.serverState.Name, "./", "")
name = strings.ReplaceAll(name, "/", "-")
packFolder := path.Join(folder, "behavior_packs", name)
os.MkdirAll(packFolder, 0o755)
@ -484,16 +510,16 @@ func (w *WorldState) SaveAndReset() {
}})
// force resource packs for worlds with custom blocks
w.withPacks = true
w.settings.withPacks = true
}
// add resource packs
if w.withPacks {
if w.settings.withPacks {
packs, err := utils.GetPacks(w.proxy.Server)
if err != nil {
logrus.Error(err)
} else {
//var rdeps []dep
var rdeps []dep
for k, p := range packs {
if p.Encrypted() && !p.CanDecrypt() {
logrus.Warnf("Cant add %s, it is encrypted", p.Name())
@ -502,17 +528,14 @@ func (w *WorldState) SaveAndReset() {
logrus.Infof(locale.Loc("adding_pack", locale.Strmap{"Name": k}))
packFolder := path.Join(folder, "resource_packs", p.Name())
os.MkdirAll(packFolder, 0o755)
data := make([]byte, p.Len())
p.ReadAt(data, 0)
utils.UnpackZip(bytes.NewReader(data), int64(len(data)), packFolder)
utils.UnpackZip(p, int64(p.Len()), packFolder)
/*
rdeps = append(rdeps, dep{
PackID: p.Manifest().Header.UUID,
Version: p.Manifest().Header.Version,
})
*/
rdeps = append(rdeps, dep{
PackID: p.Manifest().Header.UUID,
Version: p.Manifest().Header.Version,
})
}
_ = rdeps
/*
if len(rdeps) > 0 {
addPacksJSON("world_resource_packs.json", rdeps)
@ -521,7 +544,7 @@ func (w *WorldState) SaveAndReset() {
}
}
if w.saveImage {
if w.settings.saveImage {
f, _ := os.Create(folder + ".png")
png.Encode(f, w.mapUI.ToImage())
f.Close()
@ -532,25 +555,27 @@ func (w *WorldState) SaveAndReset() {
// zip it
filename := folder + ".mcworld"
if err := utils.ZipFolder(filename, folder); err != nil {
fmt.Println(err)
logrus.Error(err)
}
logrus.Info(locale.Loc("saved", locale.Strmap{"Name": filename}))
//os.RemoveAll(folder)
w.Reset()
w.Reset(w.CurrentName())
w.gui.Message(messages.SetUIState, messages.UIStateMain)
}
func (w *WorldState) OnConnect(err error) bool {
func (w *worldsServer) OnConnect(err error) bool {
w.gui.Message(messages.SetUIState, messages.UIStateMain)
if err != nil {
return false
}
gd := w.proxy.Server.GameData()
w.ChunkRadius = int(gd.ChunkRadius)
w.serverState.ChunkRadius = int(gd.ChunkRadius)
w.proxy.ClientWritePacket(&packet.ChunkRadiusUpdated{
ChunkRadius: 80,
})
world.InsertCustomItems(gd.Items)
for _, ie := range gd.Items {
w.bp.AddItem(ie)
}
@ -576,18 +601,18 @@ func (w *WorldState) OnConnect(err error) bool {
if len(gv) > 1 {
var ver int
ver, err = strconv.Atoi(gv[1])
w.ispre118 = ver < 18
w.serverState.ispre118 = ver < 18
}
if err != nil || len(gv) <= 1 {
logrus.Info(locale.Loc("guessing_version", nil))
}
dimensionID := gd.Dimension
if w.ispre118 {
if w.serverState.ispre118 {
logrus.Info(locale.Loc("using_under_118", nil))
dimensionID += 10
}
w.Dim = dimensionIDMap[uint8(dimensionID)]
w.worldState.Dim = dimensionIDMap[uint8(dimensionID)]
}
w.proxy.SendMessage(locale.Loc("use_setname", nil))
@ -611,7 +636,7 @@ func (w *WorldState) OnConnect(err error) bool {
w.proxy.AddCommand(utils.IngameCommand{
Exec: func(cmdline []string) bool {
return w.setVoidGen(!w.voidGen, false)
return w.setVoidGen(!w.settings.voidGen, false)
},
Cmd: protocol.Command{
Name: "void",
@ -620,9 +645,5 @@ func (w *WorldState) OnConnect(err error) bool {
})
w.mapUI.Start()
w.proxy.ClientWritePacket(&packet.ChunkRadiusUpdated{
ChunkRadius: 80,
})
return true
}

View File

@ -2,7 +2,6 @@ package utils
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net"
@ -18,8 +17,6 @@ import (
"golang.org/x/exp/slices"
)
var pool = packet.NewPool()
var MutedPackets = []string{
"packet.UpdateBlock",
"packet.MoveActorAbsolute",
@ -49,9 +46,8 @@ var MutedPackets = []string{
}
var (
ExtraVerbose []string
FLog io.Writer
dmpLock sync.Mutex
FLog io.Writer
dmpLock sync.Mutex
)
func dmpStruct(level int, inputStruct any, withType bool, isInList bool) (s string) {
@ -63,11 +59,14 @@ func dmpStruct(level int, inputStruct any, withType bool, isInList bool) (s stri
ii := reflect.Indirect(reflect.ValueOf(inputStruct))
typeName := reflect.TypeOf(inputStruct).String()
if typeName == "[]interface {}" {
typeName = "[]any"
}
typeString := ""
if withType {
if slices.Contains([]string{"bool", "string"}, typeName) {
} else {
typeString = typeName + " "
typeString = typeName
}
}
@ -84,7 +83,8 @@ func dmpStruct(level int, inputStruct any, withType bool, isInList bool) (s stri
return
}
if ii.Kind() == reflect.Struct {
switch ii.Kind() {
case reflect.Struct:
if ii.NumField() == 0 {
s += typeName + "{}"
} else {
@ -93,30 +93,24 @@ func dmpStruct(level int, inputStruct any, withType bool, isInList bool) (s stri
fieldType := ii.Type().Field(i)
if fieldType.IsExported() {
field := ii.Field(i).Interface()
d := dmpStruct(level+1, field, true, false)
s += tBase + fmt.Sprintf("\t%s = %s\n", fieldType.Name, d)
s += fmt.Sprintf("%s\t%s: %s,\n", tBase, fieldType.Name, dmpStruct(level+1, ii.Field(i).Interface(), true, false))
} else {
s += tBase + " " + fieldType.Name + " (unexported)"
}
}
s += tBase + "}"
}
} else if ii.Kind() == reflect.Slice {
var t reflect.Type
is_elem_struct := false
if ii.Len() > 0 {
e := ii.Index(0)
t = reflect.TypeOf(e.Interface())
is_elem_struct = t.Kind() == reflect.Struct
}
case reflect.Slice:
s += typeName + "{"
if ii.Len() > 1000 {
s += "[<slice too long>]"
s += "<slice too long>"
} else if ii.Len() == 0 {
s += fmt.Sprintf("[0%s", typeName[1:])
} else {
s += fmt.Sprintf("[%d%s{", ii.Len(), typeString[1:])
e := ii.Index(0)
t := reflect.TypeOf(e.Interface())
is_elem_struct := t.Kind() == reflect.Struct
if is_elem_struct {
s += "\n"
}
@ -124,32 +118,55 @@ func dmpStruct(level int, inputStruct any, withType bool, isInList bool) (s stri
if is_elem_struct {
s += tBase + "\t"
}
s += dmpStruct(level+1, ii.Index(i).Interface(), false, true)
s += dmpStruct(level+1, ii.Index(i).Interface(), false, true) + ","
if is_elem_struct {
s += "\n"
} else {
s += " "
if i != ii.Len()-1 {
s += " "
}
}
}
if is_elem_struct {
s += tBase
}
s += "]"
}
} else if ii.Kind() == reflect.Map {
j, err := json.MarshalIndent(ii.Interface(), tBase, "\t")
if err != nil {
s += err.Error()
s += "}"
case reflect.Map:
it := reflect.TypeOf(inputStruct)
valType := it.Elem().String()
if valType == "interface {}" {
valType = "any"
}
s += string(j)
} else {
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:
is_array := ii.Kind() == reflect.Array
if !isInList && !is_array {
s += typeString
add_type := !isInList && !is_array && len(typeString) > 0
if add_type {
s += typeString + "("
}
s += fmt.Sprintf("%#v", ii.Interface())
if add_type {
s += ")"
}
}
return s
}
@ -163,17 +180,18 @@ func DumpStruct(data interface{}) {
}
var ClientAddr net.Addr
var pool = packet.NewPool()
func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) {
if header.PacketID == packet.IDRequestNetworkSettings {
ClientAddr = src
}
var pk packet.Packet
if pkFunc, ok := pool[header.PacketID]; ok {
pk = pkFunc()
} else {
pk = &packet.Unknown{PacketID: header.PacketID}
}
if pk.ID() == packet.IDRequestNetworkSettings {
ClientAddr = src
pk = &packet.Unknown{PacketID: header.PacketID, Payload: payload}
}
defer func() {
@ -186,9 +204,8 @@ func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) {
if FLog != nil {
dmpLock.Lock()
defer dmpLock.Unlock()
FLog.Write([]byte(dmpStruct(0, pk, true, false)))
FLog.Write([]byte("\n\n\n"))
FLog.Write([]byte(dmpStruct(0, pk, true, false) + "\n\n\n"))
dmpLock.Unlock()
}
pkName := reflect.TypeOf(pk).String()[1:]
@ -217,8 +234,4 @@ func PacketLogger(header packet.Header, payload []byte, src, dst net.Addr) {
}
logrus.Debugf("%s 0x%02x, %s", dir, pk.ID(), pkName)
if slices.Contains(ExtraVerbose, pkName) {
logrus.Debugf("%+v", pk)
}
}

View File

@ -2,6 +2,7 @@
package utils
import (
"bufio"
"bytes"
"context"
"crypto/aes"
@ -207,11 +208,6 @@ func InitExtraDebug(ctx context.Context) {
logPlain, err := os.Create("packets.log")
if err != nil {
logrus.Error(err)
} else {
go func() {
<-ctx.Done()
logPlain.Close()
}()
}
// open gpg log
@ -219,24 +215,30 @@ func InitExtraDebug(ctx context.Context) {
if err != nil {
logrus.Error(err)
} else {
go func() {
<-ctx.Done()
logCrypt.Close()
}()
// encrypter for the log
logCryptEnc, err = crypt.Encer("packets.log", logCrypt)
if err != nil {
logrus.Error(err)
} else {
go func() {
<-ctx.Done()
logCryptEnc.Close()
}()
}
}
FLog = io.MultiWriter(logPlain, logCryptEnc)
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()
}
}()
}

View File

@ -2,6 +2,7 @@ package utils
import (
"archive/zip"
"compress/flate"
"io"
"io/fs"
"os"
@ -36,6 +37,12 @@ func ZipFolder(filename, folder string) error {
logrus.Fatal(err)
}
zw := zip.NewWriter(f)
// Register a custom Deflate compressor.
zw.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) {
return flate.NewWriter(out, flate.NoCompression)
})
err = filepath.WalkDir(folder, func(path string, d fs.DirEntry, err error) error {
if !d.Type().IsDir() {
rel := path[len(folder)+1:]