bedrocktool/subcommands/merge.go

145 lines
3.4 KiB
Go
Raw Permalink Normal View History

//go:build false
2022-09-04 14:53:21 +00:00
package subcommands
2022-08-16 15:34:55 +00:00
import (
"context"
"errors"
"flag"
"os"
2022-08-16 15:53:28 +00:00
"time"
2022-08-16 15:34:55 +00:00
"github.com/bedrock-tool/bedrocktool/locale"
2022-09-04 14:53:21 +00:00
"github.com/bedrock-tool/bedrocktool/utils"
2022-09-04 14:26:32 +00:00
"github.com/df-mc/dragonfly/server/entity"
2022-08-16 15:34:55 +00:00
"github.com/df-mc/dragonfly/server/world/mcdb"
"github.com/df-mc/goleveldb/leveldb/opt"
"github.com/google/subcommands"
2022-08-16 15:53:28 +00:00
"github.com/jinzhu/copier"
2022-09-02 16:25:07 +00:00
"github.com/sirupsen/logrus"
2022-08-16 15:34:55 +00:00
)
type MergeCMD struct {
worlds []string
legacy bool
}
func (*MergeCMD) Name() string { return "merge" }
func (*MergeCMD) Synopsis() string { return locale.Loc("merge_synopsis", nil) }
2022-08-16 15:34:55 +00:00
func (c *MergeCMD) SetFlags(f *flag.FlagSet) {
f.BoolVar(&c.legacy, "legacy", false, "if the worlds are before 1.18")
}
2022-09-02 16:25:07 +00:00
2022-08-16 15:34:55 +00:00
func (c *MergeCMD) Usage() string {
return c.Name() + ": " + c.Synopsis() + "\n"
}
func (c *MergeCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
if f.NArg() == 0 {
logrus.Error(locale.Loc("need_to_specify_multiple_worlds", nil))
2022-08-16 15:34:55 +00:00
return 1
}
c.worlds = f.Args()
2023-01-29 21:20:13 +00:00
outName := c.worlds[0] + "-merged"
2022-08-16 15:34:55 +00:00
2023-01-29 21:20:13 +00:00
provOut, err := mcdb.New(logrus.StandardLogger(), outName, opt.DefaultCompression)
2022-08-16 15:34:55 +00:00
if err != nil {
logrus.Errorf(locale.Loc("failed_to_open_output", locale.Strmap{"Err": err}))
2022-09-07 12:07:33 +00:00
return 1
2022-08-16 15:34:55 +00:00
}
2023-01-29 21:20:13 +00:00
for i, worldName := range c.worlds {
2022-08-16 15:53:28 +00:00
first := i == 0
2023-01-29 21:20:13 +00:00
logrus.Infof(locale.Loc("adding_world", locale.Strmap{"World": worldName}))
s, err := os.Stat(worldName)
2022-08-16 15:34:55 +00:00
if errors.Is(err, os.ErrNotExist) {
2023-01-29 21:20:13 +00:00
logrus.Fatalf(locale.Loc("not_found", locale.Strmap{"Name": worldName}), worldName)
2022-08-16 15:34:55 +00:00
}
2022-08-17 18:04:13 +00:00
if !s.IsDir() { // if its a zip temporarily unpack it to read it
2023-01-29 21:20:13 +00:00
f, _ := os.Open(worldName)
worldName += "_unpack"
utils.UnpackZip(f, s.Size(), worldName)
2022-08-16 15:34:55 +00:00
}
2022-08-17 18:04:13 +00:00
// merge it into the state
2023-01-29 21:20:13 +00:00
err = c.mergeWorlds(provOut, worldName, first)
2022-08-16 15:34:55 +00:00
if err != nil {
2023-01-29 21:20:13 +00:00
logrus.Errorf("%s %s", worldName, err)
2022-09-07 12:07:33 +00:00
return 1
2022-08-16 15:34:55 +00:00
}
2022-08-17 18:04:13 +00:00
if !s.IsDir() { // remove temp folder again
2023-01-29 21:20:13 +00:00
os.RemoveAll(worldName)
2022-08-16 15:53:28 +00:00
}
2022-08-16 15:34:55 +00:00
}
2022-08-16 15:53:28 +00:00
2023-01-29 21:20:13 +00:00
if err = provOut.Close(); err != nil {
2022-09-07 12:07:33 +00:00
logrus.Error(err)
2022-08-16 15:53:28 +00:00
return 1
}
time.Sleep(1 * time.Second)
2023-01-29 21:20:13 +00:00
if err := utils.ZipFolder(outName+".mcworld", outName); err != nil {
2022-09-04 13:24:55 +00:00
logrus.Infof("zipping: %s", err)
2022-08-16 15:53:28 +00:00
return 1
}
2023-01-29 21:20:13 +00:00
os.RemoveAll(outName)
2022-08-16 15:34:55 +00:00
return 0
}
2023-01-29 21:20:13 +00:00
func (c *MergeCMD) mergeWorlds(provOut *mcdb.Provider, folder string, first bool) error {
provIn, err := mcdb.New(logrus.StandardLogger(), folder, opt.DefaultCompression)
2022-08-16 15:34:55 +00:00
if err != nil {
return err
}
count := 0
2023-01-29 21:20:13 +00:00
existing := provOut.Chunks(c.legacy)
new := provIn.Chunks(c.legacy)
2022-08-16 15:34:55 +00:00
for i := range new {
if _, ok := existing[i]; !ok {
d := i.D
// chunks
2023-01-29 21:20:13 +00:00
ch, _, err := provIn.LoadChunk(i.P, d)
2022-08-16 15:34:55 +00:00
if err != nil {
return err
}
2023-01-29 21:20:13 +00:00
if err := provOut.SaveChunk(i.P, ch, i.D); err != nil {
2022-08-16 15:34:55 +00:00
return err
}
// blockNBT
2023-01-29 21:20:13 +00:00
n, err := provIn.LoadBlockNBT(i.P, i.D)
2022-08-16 15:34:55 +00:00
if err != nil {
return err
}
2023-01-29 21:20:13 +00:00
if err := provOut.SaveBlockNBT(i.P, n, i.D); err != nil {
2022-08-16 15:34:55 +00:00
return err
}
// entities
2023-01-29 21:20:13 +00:00
entities, err := provIn.LoadEntities(i.P, i.D, entity.DefaultRegistry)
2022-08-16 15:34:55 +00:00
if err != nil {
return err
}
2023-01-29 21:20:13 +00:00
if err := provOut.SaveEntities(i.P, entities, i.D); err != nil {
2022-08-16 15:34:55 +00:00
return err
}
count += 1
}
}
2022-08-16 15:53:28 +00:00
if first {
2022-09-04 00:24:58 +00:00
logrus.Debug("Applying Settings and level.dat")
2023-01-29 21:20:13 +00:00
provOut.SaveSettings(provIn.Settings())
outLd := provOut.LevelDat()
copier.Copy(outLd, provIn.LevelDat())
2022-08-16 15:53:28 +00:00
}
2022-09-04 00:24:58 +00:00
logrus.Infof("Added: %d", count)
2022-08-16 15:34:55 +00:00
return nil
}
func init() {
2022-09-04 14:26:32 +00:00
utils.RegisterCommand(&MergeCMD{})
2022-08-16 15:34:55 +00:00
}