small cleanup

This commit is contained in:
olebeck 2023-04-12 14:10:45 +02:00
parent aa73c86d11
commit 87cd32e280
7 changed files with 188 additions and 168 deletions

View File

@ -8,7 +8,8 @@ assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
A clear and concise description of what the bug is,
and what server it occurs on.
**To Reproduce**
Steps to reproduce the behavior:
@ -24,15 +25,20 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
- OS: [e.g. windows]
- Version [e.g. 1.28.0-36]
- Minecraft Version [e.g. 1.19.73]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
- OS: [e.g. iOS12]
- Version [e.g. 1.28.0-36]
**Additional context**
Add any other context about the problem here.
**attach packets.log.gpg (not always necessary)**
this file can be helpful for debugging without having to connect to the server.
it can be created by running with -extra-debug [e.g. bedrocktool.exe -extra-debug worlds -address play.mojang.com ]
be sure to only attach the .gpg file which is not publicly readable.

View File

@ -231,6 +231,7 @@ func NewDebugLogger(extraVerbose bool) *utils.ProxyHandler {
}
},
OnEnd: func() {
dmpLock.Lock()
if packetsLogF != nil {
packetsLogF.Flush()
}
@ -243,6 +244,7 @@ func NewDebugLogger(extraVerbose bool) *utils.ProxyHandler {
if logCrypt != nil {
logCrypt.Close()
}
dmpLock.Unlock()
},
}
}

View File

@ -11,12 +11,7 @@ import (
)
func (w *worldsHandler) processChangeDimension(pk *packet.ChangeDimension) {
if len(w.worldState.chunks) > 0 {
w.SaveAndReset()
} else {
logrus.Info(locale.Loc("not_saving_empty", nil))
w.Reset(w.CurrentName())
}
w.SaveAndReset()
dimensionID := pk.Dimension
if w.serverState.ispre118 && dimensionID == 0 {
dimensionID += 10

View File

@ -22,7 +22,7 @@ import (
const ViewMapID = 0x424242
// MapItemPacket tells the client that it has a map with id 0x424242 in the offhand
var MapItemPacket packet.InventoryContent = packet.InventoryContent{
var MapItemPacket = packet.InventoryContent{
WindowID: 119,
Content: []protocol.ItemInstance{
{
@ -112,9 +112,6 @@ func (m *MapUI) Start() {
MapID: ViewMapID,
Scale: 4,
MapsIncludedIn: []int64{ViewMapID},
Width: 0,
Height: 0,
Pixels: nil,
UpdateFlags: packet.MapUpdateFlagInitialisation,
})
if err != nil {
@ -248,7 +245,7 @@ func (m *MapUI) ToImage() *image.RGBA {
chunksX := int(max[0] - min[0] + 1) // how many chunk lengths is x coordinate
chunksY := int(max[1] - min[1] + 1)
img2 := image.NewRGBA(image.Rect(0, 0, chunksX*16, chunksY*16))
img := image.NewRGBA(image.Rect(0, 0, chunksX*16, chunksY*16))
m.l.RLock()
for pos, tile := range m.renderedChunks {
@ -256,13 +253,13 @@ func (m *MapUI) ToImage() *image.RGBA {
int((pos.X()-min.X())*16),
int((pos.Z()-min.Z())*16),
)
draw.Draw(img2, image.Rect(
draw.Draw(img, image.Rect(
px.X, px.Y,
px.X+16, px.Y+16,
), tile, image.Point{}, draw.Src)
}
m.l.RUnlock()
return img2
return img
}
func (m *MapUI) SetChunk(pos protocol.ChunkPos, ch *chunk.Chunk, complete bool) {

View File

@ -4,12 +4,14 @@ import (
"context"
"encoding/json"
"fmt"
"image"
"image/png"
"math/rand"
"os"
"path"
"strconv"
"strings"
"sync"
"time"
"github.com/bedrock-tool/bedrocktool/locale"
@ -72,6 +74,7 @@ type serverState struct {
type worldsHandler struct {
ctx context.Context
wg sync.WaitGroup
proxy *utils.ProxyContext
mapUI *MapUI
gui utils.UI
@ -97,7 +100,7 @@ func NewWorldsHandler(ctx context.Context, ui utils.UI, settings WorldSettings)
settings: settings,
}
w.mapUI = NewMapUI(w)
w.Reset(w.CurrentName())
w.Reset()
return &utils.ProxyHandler{
Name: "Worlds",
@ -169,6 +172,7 @@ func NewWorldsHandler(ctx context.Context, ui utils.UI, settings WorldSettings)
},
OnEnd: func() {
w.SaveAndReset()
w.wg.Wait()
},
}
}
@ -203,7 +207,7 @@ func (w *worldsHandler) setWorldName(val string, fromUI bool) bool {
return true
}
func (w *worldsHandler) CurrentName() string {
func (w *worldsHandler) currentName() string {
worldName := "world"
if w.serverState.worldCounter > 0 {
worldName = fmt.Sprintf("world-%d", w.serverState.worldCounter)
@ -211,14 +215,14 @@ func (w *worldsHandler) CurrentName() string {
return worldName
}
func (w *worldsHandler) Reset(newName string) {
func (w *worldsHandler) Reset() {
w.worldState = worldState{
dimension: w.worldState.dimension,
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,
Name: w.currentName(),
}
w.mapUI.Reset()
}
@ -280,155 +284,171 @@ func (w *worldState) Save(folder string) (*mcdb.DB, error) {
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())
w.Reset()
return
}
logrus.Infof(locale.Loc("saving_world", locale.Strmap{"Name": w.worldState.Name, "Count": len(w.worldState.chunks)}))
w.gui.Message(messages.SavingWorld{
Name: w.worldState.Name,
Chunks: len(w.worldState.chunks),
})
// open world
folder := path.Join("worlds", fmt.Sprintf("%s/%s", w.serverState.Name, w.worldState.Name))
os.RemoveAll(folder)
os.MkdirAll(folder, 0o777)
provider, err := w.worldState.Save(folder)
if err != nil {
logrus.Error(err)
return
}
err = provider.SaveLocalPlayerData(w.playerData())
if err != nil {
logrus.Error(err)
}
worldStateCopy := w.worldState
playerData := w.playerData()
playerPos := w.serverState.PlayerPos.Position
spawnPos := cube.Pos{int(playerPos.X()), int(playerPos.Y()), int(playerPos.Z())}
// write metadata
s := provider.Settings()
s.Spawn = spawnPos
s.Name = w.worldState.Name
// 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":
ld.CommandBlockOutput = gr.Value.(bool)
case "maxcommandchainlength":
ld.MaxCommandChainLength = int32(gr.Value.(uint32))
case "commandblocksenabled":
ld.CommandsEnabled = gr.Value.(bool)
case "dodaylightcycle":
ld.DoDayLightCycle = gr.Value.(bool)
case "doentitydrops":
ld.DoEntityDrops = gr.Value.(bool)
case "dofiretick":
ld.DoFireTick = gr.Value.(bool)
case "domobloot":
ld.DoMobLoot = gr.Value.(bool)
case "domobspawning":
ld.DoMobSpawning = gr.Value.(bool)
case "dotiledrops":
ld.DoTileDrops = gr.Value.(bool)
case "doweathercycle":
ld.DoWeatherCycle = gr.Value.(bool)
case "drowningdamage":
ld.DrowningDamage = gr.Value.(bool)
case "doinsomnia":
ld.DoInsomnia = gr.Value.(bool)
case "falldamage":
ld.FallDamage = gr.Value.(bool)
case "firedamage":
ld.FireDamage = gr.Value.(bool)
case "keepinventory":
ld.KeepInventory = gr.Value.(bool)
case "mobgriefing":
ld.MobGriefing = gr.Value.(bool)
case "pvp":
ld.PVP = gr.Value.(bool)
case "showcoordinates":
ld.ShowCoordinates = gr.Value.(bool)
case "naturalregeneration":
ld.NaturalRegeneration = gr.Value.(bool)
case "tntexplodes":
ld.TNTExplodes = gr.Value.(bool)
case "sendcommandfeedback":
ld.SendCommandFeedback = gr.Value.(bool)
case "randomtickspeed":
ld.RandomTickSpeed = int32(gr.Value.(uint32))
case "doimmediaterespawn":
ld.DoImmediateRespawn = gr.Value.(bool)
case "showdeathmessages":
ld.ShowDeathMessages = gr.Value.(bool)
case "functioncommandlimit":
ld.FunctionCommandLimit = int32(gr.Value.(uint32))
case "spawnradius":
ld.SpawnRadius = int32(gr.Value.(uint32))
case "showtags":
ld.ShowTags = gr.Value.(bool)
case "freezedamage":
ld.FreezeDamage = gr.Value.(bool)
case "respawnblocksexplode":
ld.RespawnBlocksExplode = gr.Value.(bool)
case "showbordereffect":
ld.ShowBorderEffect = gr.Value.(bool)
// todo
default:
logrus.Warnf(locale.Loc("unknown_gamerule", locale.Strmap{"Name": gr.Name}))
}
}
// 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}`
ld.Generator = 2
}
if w.bp.HasContent() {
if ld.Experiments == nil {
ld.Experiments = map[string]any{}
}
ld.Experiments["data_driven_items"] = true
ld.Experiments["experiments_ever_used"] = true
ld.Experiments["saved_with_toggled_experiments"] = true
}
ld.RandomTickSpeed = 0
s.CurrentTick = 0
provider.SaveSettings(s)
if err = provider.Close(); err != nil {
logrus.Error(err)
var img image.Image
if w.settings.SaveImage {
img = w.mapUI.ToImage()
}
w.serverState.worldCounter += 1
w.Reset()
w.wg.Add(1)
go func() {
defer w.wg.Done()
logrus.Infof(locale.Loc("saving_world", locale.Strmap{"Name": worldStateCopy.Name, "Count": len(worldStateCopy.chunks)}))
w.gui.Message(messages.SavingWorld{
Name: w.worldState.Name,
Chunks: len(w.worldState.chunks),
})
if w.settings.SaveImage {
f, _ := os.Create(folder + ".png")
png.Encode(f, w.mapUI.ToImage())
f.Close()
}
// open world
folder := fmt.Sprintf("worlds/%s/%s", w.serverState.Name, worldStateCopy.Name)
os.RemoveAll(folder)
os.MkdirAll(folder, 0o777)
provider, err := worldStateCopy.Save(folder)
if err != nil {
logrus.Error(err)
return
}
w.AddPacks(folder)
err = provider.SaveLocalPlayerData(playerData)
if err != nil {
logrus.Error(err)
return
}
// zip it
filename := folder + ".mcworld"
if err := utils.ZipFolder(filename, folder); err != nil {
logrus.Error(err)
}
logrus.Info(locale.Loc("saved", locale.Strmap{"Name": filename}))
//os.RemoveAll(folder)
w.Reset(w.CurrentName())
w.gui.Message(messages.SetUIState(messages.UIStateMain))
// write metadata
s := provider.Settings()
s.Spawn = spawnPos
s.Name = worldStateCopy.Name
// 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":
ld.CommandBlockOutput = gr.Value.(bool)
case "maxcommandchainlength":
ld.MaxCommandChainLength = int32(gr.Value.(uint32))
case "commandblocksenabled":
ld.CommandsEnabled = gr.Value.(bool)
case "dodaylightcycle":
ld.DoDayLightCycle = gr.Value.(bool)
case "doentitydrops":
ld.DoEntityDrops = gr.Value.(bool)
case "dofiretick":
ld.DoFireTick = gr.Value.(bool)
case "domobloot":
ld.DoMobLoot = gr.Value.(bool)
case "domobspawning":
ld.DoMobSpawning = gr.Value.(bool)
case "dotiledrops":
ld.DoTileDrops = gr.Value.(bool)
case "doweathercycle":
ld.DoWeatherCycle = gr.Value.(bool)
case "drowningdamage":
ld.DrowningDamage = gr.Value.(bool)
case "doinsomnia":
ld.DoInsomnia = gr.Value.(bool)
case "falldamage":
ld.FallDamage = gr.Value.(bool)
case "firedamage":
ld.FireDamage = gr.Value.(bool)
case "keepinventory":
ld.KeepInventory = gr.Value.(bool)
case "mobgriefing":
ld.MobGriefing = gr.Value.(bool)
case "pvp":
ld.PVP = gr.Value.(bool)
case "showcoordinates":
ld.ShowCoordinates = gr.Value.(bool)
case "naturalregeneration":
ld.NaturalRegeneration = gr.Value.(bool)
case "tntexplodes":
ld.TNTExplodes = gr.Value.(bool)
case "sendcommandfeedback":
ld.SendCommandFeedback = gr.Value.(bool)
case "randomtickspeed":
ld.RandomTickSpeed = int32(gr.Value.(uint32))
case "doimmediaterespawn":
ld.DoImmediateRespawn = gr.Value.(bool)
case "showdeathmessages":
ld.ShowDeathMessages = gr.Value.(bool)
case "functioncommandlimit":
ld.FunctionCommandLimit = int32(gr.Value.(uint32))
case "spawnradius":
ld.SpawnRadius = int32(gr.Value.(uint32))
case "showtags":
ld.ShowTags = gr.Value.(bool)
case "freezedamage":
ld.FreezeDamage = gr.Value.(bool)
case "respawnblocksexplode":
ld.RespawnBlocksExplode = gr.Value.(bool)
case "showbordereffect":
ld.ShowBorderEffect = gr.Value.(bool)
// todo
default:
logrus.Warnf(locale.Loc("unknown_gamerule", locale.Strmap{"Name": gr.Name}))
}
}
// 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}`
ld.Generator = 2
}
ld.RandomTickSpeed = 0
s.CurrentTick = 0
if w.bp.HasContent() {
if ld.Experiments == nil {
ld.Experiments = map[string]any{}
}
ld.Experiments["data_driven_items"] = true
ld.Experiments["experiments_ever_used"] = true
ld.Experiments["saved_with_toggled_experiments"] = true
}
provider.SaveSettings(s)
err = provider.Close()
if err != nil {
logrus.Error(err)
return
}
if w.settings.SaveImage {
f, _ := os.Create(folder + ".png")
png.Encode(f, img)
f.Close()
}
w.AddPacks(folder)
// zip it
filename := folder + ".mcworld"
err = utils.ZipFolder(filename, folder)
if err != nil {
logrus.Error(err)
return
}
logrus.Info(locale.Loc("saved", locale.Strmap{"Name": filename}))
//os.RemoveAll(folder)
w.gui.Message(messages.SetUIState(messages.UIStateMain))
}()
}
func (w *worldsHandler) AddPacks(folder string) {

View File

@ -21,7 +21,7 @@ func loadPng(path string) (*image.RGBA, error) {
if err != nil {
return nil, err
}
return (*image.RGBA)(img.(*image.NRGBA)), err
return (*image.RGBA)(img.(*image.NRGBA)), nil
}
// LERP is a linear interpolation function

View File

@ -53,12 +53,12 @@ type (
type ProxyHandler struct {
Name string
ProxyRef func(*ProxyContext)
ProxyRef func(pc *ProxyContext)
//
AddressAndName func(address, hostname string) error
// called to change game data
GameDataModifier func(*minecraft.GameData)
GameDataModifier func(gd *minecraft.GameData)
// called for every packet
PacketFunc func(header packet.Header, payload []byte, src, dst net.Addr)
@ -210,9 +210,9 @@ func (p *ProxyContext) AddHandler(handler *ProxyHandler) {
}
func (p *ProxyContext) CommandHandlerPacketCB(pk packet.Packet, toServer bool, _ time.Time) (packet.Packet, error) {
switch _pk := pk.(type) {
switch pk := pk.(type) {
case *packet.CommandRequest:
cmd := strings.Split(_pk.CommandLine, " ")
cmd := strings.Split(pk.CommandLine, " ")
name := cmd[0][1:]
if h, ok := p.commands[name]; ok {
if h.Exec(cmd[1:]) {
@ -220,13 +220,13 @@ func (p *ProxyContext) CommandHandlerPacketCB(pk packet.Packet, toServer bool, _
}
}
case *packet.AvailableCommands:
cmds := make([]protocol.Command, len(p.commands))
cmds := make([]protocol.Command, 0, len(p.commands))
for _, ic := range p.commands {
cmds = append(cmds, ic.Cmd)
}
pk = &packet.AvailableCommands{
Constraints: _pk.Constraints,
Commands: append(_pk.Commands, cmds...),
Constraints: pk.Constraints,
Commands: append(pk.Commands, cmds...),
}
}
return pk, nil
@ -321,9 +321,9 @@ func (p *ProxyContext) Run(ctx context.Context, serverAddress, name string) (err
logrus.Infof(locale.Locm("pack_count_loaded", locale.Strmap{"Count": len(packs)}, len(packs)))
}
_status := minecraft.NewStatusProvider("Server")
status := minecraft.NewStatusProvider(fmt.Sprintf("%s Proxy", name))
p.Listener, err = minecraft.ListenConfig{
StatusProvider: _status,
StatusProvider: status,
ResourcePacks: packs,
AcceptedProtocols: []minecraft.Protocol{
//dummyProto{id: 567, ver: "1.19.60"},