mirror of
https://github.com/CosmicStar98/bedrocktool.git
synced 2024-06-18 04:59:45 +00:00
add merge command *not really tested*
This commit is contained in:
parent
471b595e1b
commit
3477b0eab5
5
go.mod
5
go.mod
|
@ -10,6 +10,7 @@ require (
|
||||||
github.com/google/subcommands v1.2.0
|
github.com/google/subcommands v1.2.0
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/miekg/dns v1.1.50
|
github.com/miekg/dns v1.1.50
|
||||||
|
github.com/pidurentry/buttplug-go v0.0.0-20190410200554-0b2e068d769a
|
||||||
github.com/sandertv/gophertunnel v1.24.0
|
github.com/sandertv/gophertunnel v1.24.0
|
||||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e
|
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e
|
||||||
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539
|
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539
|
||||||
|
@ -22,13 +23,15 @@ require (
|
||||||
|
|
||||||
replace github.com/sandertv/gophertunnel => github.com/olebeck/gophertunnel v1.24.5
|
replace github.com/sandertv/gophertunnel => github.com/olebeck/gophertunnel v1.24.5
|
||||||
|
|
||||||
replace github.com/df-mc/dragonfly => github.com/olebeck/dragonfly v0.8.2-3
|
replace github.com/df-mc/dragonfly => github.com/olebeck/dragonfly v0.8.2-4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9 // indirect
|
github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9 // indirect
|
||||||
|
github.com/cespare/xxhash v1.1.0 // indirect
|
||||||
github.com/df-mc/atomic v1.10.0 // indirect
|
github.com/df-mc/atomic v1.10.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
|
github.com/gorilla/websocket v1.4.0 // indirect
|
||||||
github.com/klauspost/compress v1.15.9 // indirect
|
github.com/klauspost/compress v1.15.9 // indirect
|
||||||
github.com/muhammadmuzzammil1998/jsonc v1.0.0 // indirect
|
github.com/muhammadmuzzammil1998/jsonc v1.0.0 // indirect
|
||||||
github.com/sandertv/go-raknet v1.11.1 // indirect
|
github.com/sandertv/go-raknet v1.11.1 // indirect
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -1,5 +1,8 @@
|
||||||
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9 h1:/G0ghZwrhou0Wq21qc1vXXMm/t/aKWkALWwITptKbE0=
|
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/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/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -26,6 +29,8 @@ github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN
|
||||||
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||||
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
|
@ -41,6 +46,8 @@ github.com/olebeck/dragonfly v0.8.2-2 h1:rIUAEJx2ZeQhsRFNkHXrfYR3Zl85WB5spS/SZEH
|
||||||
github.com/olebeck/dragonfly v0.8.2-2/go.mod h1:xgpCDhHoP03RygPaTrzzDwsSTcEZhxNPMV3CAxETj+I=
|
github.com/olebeck/dragonfly v0.8.2-2/go.mod h1:xgpCDhHoP03RygPaTrzzDwsSTcEZhxNPMV3CAxETj+I=
|
||||||
github.com/olebeck/dragonfly v0.8.2-3 h1:qzcNc76U1E8RXpg98Fv02kxFulhsR/TWcKArqRY+xdY=
|
github.com/olebeck/dragonfly v0.8.2-3 h1:qzcNc76U1E8RXpg98Fv02kxFulhsR/TWcKArqRY+xdY=
|
||||||
github.com/olebeck/dragonfly v0.8.2-3/go.mod h1:xgpCDhHoP03RygPaTrzzDwsSTcEZhxNPMV3CAxETj+I=
|
github.com/olebeck/dragonfly v0.8.2-3/go.mod h1:xgpCDhHoP03RygPaTrzzDwsSTcEZhxNPMV3CAxETj+I=
|
||||||
|
github.com/olebeck/dragonfly v0.8.2-4 h1:K//DtE5R4DjcVB791y6Nx1Vg0/KzQwYoBb72ukUbdBA=
|
||||||
|
github.com/olebeck/dragonfly v0.8.2-4/go.mod h1:xgpCDhHoP03RygPaTrzzDwsSTcEZhxNPMV3CAxETj+I=
|
||||||
github.com/olebeck/gophertunnel v1.24.4 h1:nX7Std61XpXW4VP7KKd2RvinRwx1nGB5l8QnbwrArLE=
|
github.com/olebeck/gophertunnel v1.24.4 h1:nX7Std61XpXW4VP7KKd2RvinRwx1nGB5l8QnbwrArLE=
|
||||||
github.com/olebeck/gophertunnel v1.24.4/go.mod h1:dMOw79FHxr2azEqiGH20AwdljisAN1kqwu5SjPBnZ5k=
|
github.com/olebeck/gophertunnel v1.24.4/go.mod h1:dMOw79FHxr2azEqiGH20AwdljisAN1kqwu5SjPBnZ5k=
|
||||||
github.com/olebeck/gophertunnel v1.24.5 h1:FtpHzfp833qQGBSJtKysSmRzFzsSheq5l61d5gTp03s=
|
github.com/olebeck/gophertunnel v1.24.5 h1:FtpHzfp833qQGBSJtKysSmRzFzsSheq5l61d5gTp03s=
|
||||||
|
@ -50,12 +57,15 @@ github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
|
github.com/pidurentry/buttplug-go v0.0.0-20190410200554-0b2e068d769a h1:DIcuKv1jCe8vf10lqdD/5hZ2nnb3qYn0JycyXSnvE4s=
|
||||||
|
github.com/pidurentry/buttplug-go v0.0.0-20190410200554-0b2e068d769a/go.mod h1:oJXeBWse2BXoaZYRQFJ5p1Ut69KYf6SfiUJ/oaYnOhQ=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sandertv/go-raknet v1.11.1 h1:0auvhHoZNyC/Z1l5xqniE3JE+w3MGO3n3JXEGHzdlRE=
|
github.com/sandertv/go-raknet v1.11.1 h1:0auvhHoZNyC/Z1l5xqniE3JE+w3MGO3n3JXEGHzdlRE=
|
||||||
github.com/sandertv/go-raknet v1.11.1/go.mod h1:Gx+WgZBMQ0V2UoouGoJ8Wj6CDrMBQ4SB2F/ggpl5/+Y=
|
github.com/sandertv/go-raknet v1.11.1/go.mod h1:Gx+WgZBMQ0V2UoouGoJ8Wj6CDrMBQ4SB2F/ggpl5/+Y=
|
||||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
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.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
|
112
merge.go
Normal file
112
merge.go
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/df-mc/dragonfly/server/world/mcdb"
|
||||||
|
"github.com/df-mc/goleveldb/leveldb/opt"
|
||||||
|
"github.com/google/subcommands"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MergeCMD struct {
|
||||||
|
worlds []string
|
||||||
|
legacy bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*MergeCMD) Name() string { return "merge" }
|
||||||
|
func (*MergeCMD) Synopsis() string { return "merge 2 or more worlds" }
|
||||||
|
|
||||||
|
func (c *MergeCMD) SetFlags(f *flag.FlagSet) {
|
||||||
|
f.BoolVar(&c.legacy, "legacy", false, "if the worlds are before 1.18")
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
fmt.Println("you need to specify 1 or more worlds")
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
c.worlds = f.Args()
|
||||||
|
out_name := c.worlds[0] + "-merged"
|
||||||
|
|
||||||
|
prov_out, err := mcdb.New(out_name, opt.DefaultCompression)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to open output %s\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, world_name := range c.worlds {
|
||||||
|
fmt.Printf("Adding %s\n", world_name)
|
||||||
|
s, err := os.Stat(world_name)
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s not found\n", world_name)
|
||||||
|
}
|
||||||
|
if !s.IsDir() {
|
||||||
|
f, _ := os.Open(world_name)
|
||||||
|
world_name += "_unpack"
|
||||||
|
unpack_zip(f, s.Size(), world_name)
|
||||||
|
}
|
||||||
|
err = c.merge_worlds(prov_out, world_name, i == 0)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s %s\n", world_name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MergeCMD) merge_worlds(prov_out *mcdb.Provider, folder string, first bool) error {
|
||||||
|
prov_in, err := mcdb.New(folder, opt.DefaultCompression)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
count := 0
|
||||||
|
existing := prov_out.Chunks(c.legacy)
|
||||||
|
new := prov_in.Chunks(c.legacy)
|
||||||
|
for i := range new {
|
||||||
|
if _, ok := existing[i]; !ok {
|
||||||
|
d := i.D
|
||||||
|
// chunks
|
||||||
|
ch, _, err := prov_in.LoadChunk(i.P, d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := prov_out.SaveChunk(i.P, ch, i.D); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// blockNBT
|
||||||
|
n, err := prov_in.LoadBlockNBT(i.P, i.D)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := prov_out.SaveBlockNBT(i.P, n, i.D); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// entities
|
||||||
|
entities, err := prov_in.LoadEntities(i.P, i.D)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := prov_out.SaveEntities(i.P, entities, i.D); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if first {
|
||||||
|
prov_out.SaveSettings(prov_in.Settings())
|
||||||
|
}
|
||||||
|
count += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf("Added: %d\n", count)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
register_command(&MergeCMD{})
|
||||||
|
}
|
|
@ -1 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
func (w *WorldState) getPacks() (packs map[string]*resource.Pack, err error) {
|
||||||
|
for _, pack := range w.ServerConn.ResourcePacks() {
|
||||||
|
packs[pack.Name()] = pack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
26
utils.go
26
utils.go
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/zip"
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
|
@ -17,6 +18,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-gl/mathgl/mgl32"
|
||||||
|
"github.com/go-gl/mathgl/mgl64"
|
||||||
"github.com/sandertv/gophertunnel/minecraft"
|
"github.com/sandertv/gophertunnel/minecraft"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/auth"
|
"github.com/sandertv/gophertunnel/minecraft/auth"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol/login"
|
"github.com/sandertv/gophertunnel/minecraft/protocol/login"
|
||||||
|
@ -40,6 +43,14 @@ func send_popup(conn *minecraft.Conn, text string) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func v32tov64(in mgl32.Vec3) mgl64.Vec3 {
|
||||||
|
return mgl64.Vec3{
|
||||||
|
float64(in[0]),
|
||||||
|
float64(in[1]),
|
||||||
|
float64(in[2]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func write_token(token *oauth2.Token) {
|
func write_token(token *oauth2.Token) {
|
||||||
buf, err := json.Marshal(token)
|
buf, err := json.Marshal(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -307,3 +318,18 @@ func splitext(filename string) (name, ext string) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unpack_zip(r io.ReaderAt, size int64, unpack_folder string) {
|
||||||
|
zr, _ := zip.NewReader(r, size)
|
||||||
|
for _, src_file := range zr.File {
|
||||||
|
out_path := path.Join(unpack_folder, src_file.Name)
|
||||||
|
if src_file.Mode().IsDir() {
|
||||||
|
os.Mkdir(out_path, 0755)
|
||||||
|
} else {
|
||||||
|
os.MkdirAll(path.Dir(out_path), 0755)
|
||||||
|
fr, _ := src_file.Open()
|
||||||
|
f, _ := os.Create(path.Join(unpack_folder, src_file.Name))
|
||||||
|
io.Copy(f, fr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
82
world.go
82
world.go
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
|
@ -19,18 +20,16 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/df-mc/dragonfly/server/block/cube"
|
"github.com/df-mc/dragonfly/server/block/cube"
|
||||||
"github.com/df-mc/dragonfly/server/entity"
|
|
||||||
"github.com/df-mc/dragonfly/server/item"
|
|
||||||
"github.com/df-mc/dragonfly/server/world"
|
"github.com/df-mc/dragonfly/server/world"
|
||||||
"github.com/df-mc/dragonfly/server/world/chunk"
|
"github.com/df-mc/dragonfly/server/world/chunk"
|
||||||
"github.com/df-mc/dragonfly/server/world/mcdb"
|
"github.com/df-mc/dragonfly/server/world/mcdb"
|
||||||
"github.com/df-mc/goleveldb/leveldb/opt"
|
"github.com/df-mc/goleveldb/leveldb/opt"
|
||||||
"github.com/go-gl/mathgl/mgl32"
|
"github.com/go-gl/mathgl/mgl32"
|
||||||
"github.com/go-gl/mathgl/mgl64"
|
|
||||||
"github.com/google/subcommands"
|
"github.com/google/subcommands"
|
||||||
"github.com/sandertv/gophertunnel/minecraft"
|
"github.com/sandertv/gophertunnel/minecraft"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||||
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
||||||
|
"github.com/sandertv/gophertunnel/minecraft/resource"
|
||||||
|
|
||||||
_ "github.com/df-mc/dragonfly/server/block" // to load blocks
|
_ "github.com/df-mc/dragonfly/server/block" // to load blocks
|
||||||
)
|
)
|
||||||
|
@ -53,6 +52,7 @@ type WorldState struct {
|
||||||
WorldName string
|
WorldName string
|
||||||
ServerName string
|
ServerName string
|
||||||
worldCounter int
|
worldCounter int
|
||||||
|
packs map[string]*resource.Pack
|
||||||
|
|
||||||
PlayerPos TPlayerPos
|
PlayerPos TPlayerPos
|
||||||
ClientConn *minecraft.Conn
|
ClientConn *minecraft.Conn
|
||||||
|
@ -103,6 +103,7 @@ func init() {
|
||||||
|
|
||||||
type WorldCMD struct {
|
type WorldCMD struct {
|
||||||
server_address string
|
server_address string
|
||||||
|
packs bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*WorldCMD) Name() string { return "worlds" }
|
func (*WorldCMD) Name() string { return "worlds" }
|
||||||
|
@ -110,6 +111,7 @@ func (*WorldCMD) Synopsis() string { return "download a world from a server" }
|
||||||
|
|
||||||
func (p *WorldCMD) SetFlags(f *flag.FlagSet) {
|
func (p *WorldCMD) SetFlags(f *flag.FlagSet) {
|
||||||
f.StringVar(&p.server_address, "address", "", "remote server address")
|
f.StringVar(&p.server_address, "address", "", "remote server address")
|
||||||
|
f.BoolVar(&p.packs, "packs", false, "save resourcepacks to the worlds")
|
||||||
}
|
}
|
||||||
func (c *WorldCMD) Usage() string {
|
func (c *WorldCMD) Usage() string {
|
||||||
return c.Name() + ": " + c.Synopsis() + "\n" + SERVER_ADDRESS_HELP
|
return c.Name() + ": " + c.Synopsis() + "\n" + SERVER_ADDRESS_HELP
|
||||||
|
@ -127,30 +129,18 @@ func (c *WorldCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
handleConn(ctx, listener, clientConn, serverConn, hostname)
|
|
||||||
|
c.handleConn(ctx, listener, clientConn, serverConn, hostname)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// overworld with 0 - 255 height
|
var dimension_ids = map[uint8]world.Dimension{
|
||||||
type overworld_legacy struct{}
|
|
||||||
|
|
||||||
func (overworld_legacy) Range() cube.Range { return cube.Range{0, 255} }
|
|
||||||
func (overworld_legacy) EncodeDimension() int { return 0 }
|
|
||||||
func (overworld_legacy) WaterEvaporates() bool { return false }
|
|
||||||
func (overworld_legacy) LavaSpreadDuration() time.Duration { return time.Second * 3 / 2 }
|
|
||||||
func (overworld_legacy) WeatherCycle() bool { return true }
|
|
||||||
func (overworld_legacy) TimeCycle() bool { return true }
|
|
||||||
func (overworld_legacy) String() string { return "Overworld" }
|
|
||||||
|
|
||||||
var Overworld_legacy overworld_legacy
|
|
||||||
|
|
||||||
var dimension_ids = map[int32]world.Dimension{
|
|
||||||
0: world.Overworld,
|
0: world.Overworld,
|
||||||
1: world.Nether,
|
1: world.Nether,
|
||||||
2: world.End,
|
2: world.End,
|
||||||
// < 1.18
|
// < 1.18
|
||||||
10: Overworld_legacy,
|
10: world.Overworld_legacy,
|
||||||
11: world.Nether,
|
11: world.Nether,
|
||||||
12: world.End,
|
12: world.End,
|
||||||
}
|
}
|
||||||
|
@ -245,19 +235,6 @@ func (w *WorldState) ProcessAnimate(pk *packet.Animate) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WorldState) ProcessAddItemActor(pk *packet.AddItemActor) {
|
|
||||||
it, ok := world.ItemByRuntimeID(pk.Item.StackNetworkID, int16(pk.Item.Stack.MetadataValue))
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
stack := item.NewStack(it, int(pk.Item.Stack.Count))
|
|
||||||
w.entities[pk.EntityUniqueID] = entity.NewItem(stack, mgl64.Vec3{
|
|
||||||
float64(pk.Position[0]),
|
|
||||||
float64(pk.Position[1]),
|
|
||||||
float64(pk.Position[2]),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WorldState) ProcessChangeDimension(pk *packet.ChangeDimension) {
|
func (w *WorldState) ProcessChangeDimension(pk *packet.ChangeDimension) {
|
||||||
fmt.Printf("ChangeDimension %d\n", pk.Dimension)
|
fmt.Printf("ChangeDimension %d\n", pk.Dimension)
|
||||||
if len(w.chunks) > 0 {
|
if len(w.chunks) > 0 {
|
||||||
|
@ -270,7 +247,7 @@ func (w *WorldState) ProcessChangeDimension(pk *packet.ChangeDimension) {
|
||||||
if w.ispre118 {
|
if w.ispre118 {
|
||||||
dim_id += 10
|
dim_id += 10
|
||||||
}
|
}
|
||||||
w.Dim = dimension_ids[dim_id]
|
w.Dim = dimension_ids[uint8(dim_id)]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WorldState) SendMessage(text string) {
|
func (w *WorldState) SendMessage(text string) {
|
||||||
|
@ -307,13 +284,15 @@ func (w *WorldState) Reset() {
|
||||||
|
|
||||||
// writes the world to a folder, resets all the chunks
|
// writes the world to a folder, resets all the chunks
|
||||||
func (w *WorldState) SaveAndReset() {
|
func (w *WorldState) SaveAndReset() {
|
||||||
fmt.Println("Saving world")
|
|
||||||
var world_name string
|
var world_name string
|
||||||
if w.WorldName == "world" {
|
if w.WorldName == "world" {
|
||||||
world_name = fmt.Sprintf("%s-%d", w.WorldName, w.worldCounter)
|
world_name = fmt.Sprintf("%s-%d", w.WorldName, w.worldCounter)
|
||||||
} else {
|
} else {
|
||||||
world_name = w.WorldName
|
world_name = w.WorldName
|
||||||
}
|
}
|
||||||
|
fmt.Printf("Saving world %s\n", world_name)
|
||||||
|
|
||||||
|
// open world
|
||||||
folder := path.Join("worlds", fmt.Sprintf("%s/%s", w.ServerName, world_name))
|
folder := path.Join("worlds", fmt.Sprintf("%s/%s", w.ServerName, world_name))
|
||||||
os.MkdirAll(folder, 0777)
|
os.MkdirAll(folder, 0777)
|
||||||
provider, err := mcdb.New(folder, opt.DefaultCompression)
|
provider, err := mcdb.New(folder, opt.DefaultCompression)
|
||||||
|
@ -321,17 +300,17 @@ func (w *WorldState) SaveAndReset() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// save chunk data
|
||||||
for cp, c := range w.chunks {
|
for cp, c := range w.chunks {
|
||||||
provider.SaveChunk((world.ChunkPos)(cp), c, w.Dim)
|
provider.SaveChunk((world.ChunkPos)(cp), c, w.Dim)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// save block nbt data
|
||||||
var blockNBT = make(map[protocol.ChunkPos][]map[string]any)
|
var blockNBT = make(map[protocol.ChunkPos][]map[string]any)
|
||||||
|
|
||||||
for scp, v := range w.blockNBT { // 3d to 2d
|
for scp, v := range w.blockNBT { // 3d to 2d
|
||||||
cp := protocol.ChunkPos{scp.X(), scp.Z()}
|
cp := protocol.ChunkPos{scp.X(), scp.Z()}
|
||||||
blockNBT[cp] = append(blockNBT[cp], v...)
|
blockNBT[cp] = append(blockNBT[cp], v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
for cp, v := range blockNBT {
|
for cp, v := range blockNBT {
|
||||||
err = provider.SaveBlockNBT((world.ChunkPos)(cp), v, w.Dim)
|
err = provider.SaveBlockNBT((world.ChunkPos)(cp), v, w.Dim)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -339,8 +318,7 @@ func (w *WorldState) SaveAndReset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//provider.SaveEntities(w.entities)
|
// write metadata
|
||||||
|
|
||||||
s := provider.Settings()
|
s := provider.Settings()
|
||||||
s.Spawn = cube.Pos{
|
s.Spawn = cube.Pos{
|
||||||
int(w.PlayerPos.Position[0]),
|
int(w.PlayerPos.Position[0]),
|
||||||
|
@ -349,6 +327,7 @@ func (w *WorldState) SaveAndReset() {
|
||||||
}
|
}
|
||||||
s.Name = w.WorldName
|
s.Name = w.WorldName
|
||||||
|
|
||||||
|
// set gamerules
|
||||||
ld := provider.LevelDat()
|
ld := provider.LevelDat()
|
||||||
for _, gr := range w.ServerConn.GameData().GameRules {
|
for _, gr := range w.ServerConn.GameData().GameRules {
|
||||||
switch gr.Name {
|
switch gr.Name {
|
||||||
|
@ -418,7 +397,7 @@ func (w *WorldState) SaveAndReset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dont generate
|
// void world
|
||||||
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.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.Generator = 2
|
||||||
|
|
||||||
|
@ -426,6 +405,16 @@ func (w *WorldState) SaveAndReset() {
|
||||||
provider.Close()
|
provider.Close()
|
||||||
w.worldCounter += 1
|
w.worldCounter += 1
|
||||||
|
|
||||||
|
for k, p := range w.packs {
|
||||||
|
fmt.Printf("Adding resource pack: %s\n", k)
|
||||||
|
pack_folder := path.Join(folder, "resource_packs", k)
|
||||||
|
os.MkdirAll(pack_folder, 0755)
|
||||||
|
data := make([]byte, p.Len())
|
||||||
|
p.ReadAt(data, 0)
|
||||||
|
unpack_zip(bytes.NewReader(data), int64(len(data)), pack_folder)
|
||||||
|
}
|
||||||
|
|
||||||
|
// zip it
|
||||||
filename := folder + ".mcworld"
|
filename := folder + ".mcworld"
|
||||||
f, err := os.Create(filename)
|
f, err := os.Create(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -454,14 +443,21 @@ func (w *WorldState) SaveAndReset() {
|
||||||
w.Reset()
|
w.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleConn(ctx context.Context, l *minecraft.Listener, cc, sc *minecraft.Conn, server_name string) {
|
func (c *WorldCMD) handleConn(ctx context.Context, l *minecraft.Listener, cc, sc *minecraft.Conn, server_name string) {
|
||||||
|
var err error
|
||||||
w := NewWorldState()
|
w := NewWorldState()
|
||||||
w.ServerName = server_name
|
w.ServerName = server_name
|
||||||
w.ClientConn = cc
|
w.ClientConn = cc
|
||||||
w.ServerConn = sc
|
w.ServerConn = sc
|
||||||
|
|
||||||
|
if c.packs {
|
||||||
|
fmt.Println("reformatting packs")
|
||||||
|
go func() {
|
||||||
|
w.packs, err = w.getPacks()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
gv := strings.Split(w.ServerConn.GameData().BaseGameVersion, ".")
|
gv := strings.Split(w.ServerConn.GameData().BaseGameVersion, ".")
|
||||||
var err error
|
|
||||||
if len(gv) > 1 {
|
if len(gv) > 1 {
|
||||||
var ver int
|
var ver int
|
||||||
ver, err = strconv.Atoi(gv[1])
|
ver, err = strconv.Atoi(gv[1])
|
||||||
|
@ -551,7 +547,7 @@ func handleConn(ctx context.Context, l *minecraft.Listener, cc, sc *minecraft.Co
|
||||||
if w.ispre118 {
|
if w.ispre118 {
|
||||||
dim_id += 10
|
dim_id += 10
|
||||||
}
|
}
|
||||||
w.Dim = dimension_ids[dim_id]
|
w.Dim = dimension_ids[uint8(dim_id)]
|
||||||
|
|
||||||
for {
|
for {
|
||||||
pk, err := w.ServerConn.ReadPacket()
|
pk, err := w.ServerConn.ReadPacket()
|
||||||
|
@ -571,8 +567,6 @@ func handleConn(ctx context.Context, l *minecraft.Listener, cc, sc *minecraft.Co
|
||||||
send_popup(w.ClientConn, fmt.Sprintf("%d chunks loaded\nname: %s", len(w.chunks), w.WorldName))
|
send_popup(w.ClientConn, fmt.Sprintf("%d chunks loaded\nname: %s", len(w.chunks), w.WorldName))
|
||||||
case *packet.SubChunk:
|
case *packet.SubChunk:
|
||||||
w.ProcessSubChunk(pk)
|
w.ProcessSubChunk(pk)
|
||||||
case *packet.AddItemActor:
|
|
||||||
w.ProcessAddItemActor(pk)
|
|
||||||
case *packet.AvailableCommands:
|
case *packet.AvailableCommands:
|
||||||
pk.Commands = append(pk.Commands, setname_command)
|
pk.Commands = append(pk.Commands, setname_command)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user