diff --git a/.gitignore b/.gitignore index 102fbfb..5d94bc2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -mapcleaner \ No newline at end of file +mapcleaner +dist \ No newline at end of file diff --git a/go.mod b/go.mod index 680a368..fc8895e 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/hashicorp/golang-lru/v2 v2.0.7 - github.com/minetest-go/areasparser v1.0.0 + github.com/minetest-go/areasparser v1.0.5 github.com/minetest-go/mapparser v0.1.8 github.com/minetest-go/mtdb v1.1.46 github.com/sirupsen/logrus v1.9.3 @@ -12,25 +12,24 @@ require ( require ( github.com/dustin/go-humanize v1.0.1 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/klauspost/compress v1.15.4 // indirect + github.com/klauspost/compress v1.17.4 // indirect github.com/lib/pq v1.10.9 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect - github.com/mattn/go-sqlite3 v1.14.18 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - golang.org/x/mod v0.3.0 // indirect - golang.org/x/sys v0.11.0 // indirect - golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - lukechampine.com/uint128 v1.2.0 // indirect - modernc.org/cc/v3 v3.40.0 // indirect - modernc.org/ccgo/v3 v3.16.13 // indirect - modernc.org/libc v1.29.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/tools v0.16.0 // indirect + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect + lukechampine.com/uint128 v1.3.0 // indirect + modernc.org/cc/v3 v3.41.0 // indirect + modernc.org/ccgo/v3 v3.16.15 // indirect + modernc.org/libc v1.37.0 // indirect modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.7.2 // indirect modernc.org/opt v0.1.3 // indirect modernc.org/sqlite v1.27.0 // indirect - modernc.org/strutil v1.1.3 // indirect - modernc.org/token v1.0.1 // indirect + modernc.org/strutil v1.2.0 // indirect + modernc.org/token v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index 549eb4b..0287402 100644 --- a/go.sum +++ b/go.sum @@ -7,20 +7,27 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= 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.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/klauspost/compress v1.15.4 h1:1kn4/7MepF/CHmYub99/nNX8az0IJjfSOU/jbnTVfqQ= github.com/klauspost/compress v1.15.4/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-sqlite3 v1.14.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI= -github.com/mattn/go-sqlite3 v1.14.18/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/minetest-go/areasparser v1.0.0 h1:2XFVUwAWRcbkg1OV7qQQHmhx8gEY85crKIxqNxh5Dbo= github.com/minetest-go/areasparser v1.0.0/go.mod h1:NvohBk60WBrAbfvgmJccCEblz9I/Ygba4k9V81rwoNc= +github.com/minetest-go/areasparser v1.0.5 h1:kyfb7mk4S7Gvx5N42uJK8ze3BAbfj8uyLsv2Tuy43MQ= +github.com/minetest-go/areasparser v1.0.5/go.mod h1:NvohBk60WBrAbfvgmJccCEblz9I/Ygba4k9V81rwoNc= github.com/minetest-go/mapparser v0.1.8 h1:tmkno1Qi8nIdjQXJLlnq38uVGygZWA8i3ilre/bB9W8= github.com/minetest-go/mapparser v0.1.8/go.mod h1:TcjEkPY9n0rBM+beSstw+Jje8nGl+LqFhiC00J6ihNw= github.com/minetest-go/mtdb v1.1.46 h1:TGzHmvKnFOp49dgFVGO53qyzDS2guQXpjFONA5O+IZ8= @@ -40,6 +47,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -50,31 +59,46 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs= golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= +golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= +lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= +modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q= +modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= +modernc.org/ccgo/v3 v3.16.15 h1:KbDR3ZAVU+wiLyMESPtbtE/Add4elztFyfsWoNTgxS0= +modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI= modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= modernc.org/libc v1.29.0 h1:tTFRFq69YKCF2QyGNuRUQxKBm1uZZLubf6Cjh/pVHXs= modernc.org/libc v1.29.0/go.mod h1:DaG/4Q3LRRdqpiLyP0C2m1B8ZMGkQ+cCgOIjEtQlYhQ= +modernc.org/libc v1.37.0 h1:WerjebcsP6A7Jy+f2lCnHAkiSTLf7IaSftBYUtoswak= +modernc.org/libc v1.37.0/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= @@ -85,7 +109,11 @@ modernc.org/sqlite v1.27.0 h1:MpKAHoyYB7xqcwnUwkuD+npwEa0fojF0B5QRbN+auJ8= modernc.org/sqlite v1.27.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0= modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= +modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY= modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY= diff --git a/main.go b/main.go index 4cbf9c3..8c058b4 100644 --- a/main.go +++ b/main.go @@ -21,6 +21,8 @@ func main() { help := flag.Bool("help", false, "show help") debug := flag.Bool("debug", false, "set the loglevel to debug") mode := flag.String("mode", "prune_unproteced", "set the working mode [prune_unproteced|export_protected]") + exportAllProtected := flag.Bool("export-all", false, "when mode=export_protected, parse all blocks to also preserve mapcleaner_protect.txt alongside areas") + flag.IntVar(&block.IteratorBatchSize, "batch-size", block.IteratorBatchSize, "iterator batch size") flag.Parse() if *help { @@ -73,7 +75,11 @@ func main() { case "prune_unproteced": err = ProcessRemoveUnprotected() case "export_protected": - err = ProcessExportProtected(areas) + if *exportAllProtected { + err = ProccessExportAllProtected() + } else { + err = ProcessExportProtected(areas) + } default: panic(fmt.Sprintf("mode not implemented: '%s'", *mode)) } diff --git a/process_export_protected.go b/process_export_protected.go index 257f5bc..0dbcded 100644 --- a/process_export_protected.go +++ b/process_export_protected.go @@ -4,41 +4,53 @@ import ( "fmt" "os" "path" + "time" "github.com/minetest-go/areasparser" "github.com/minetest-go/mtdb" + "github.com/minetest-go/mtdb/block" "github.com/sirupsen/logrus" ) -func ProcessExportProtected(areas []*areasparser.Area) error { - export_dir := path.Join(wd, "area-export") - logrus.WithFields(logrus.Fields{ - "export_dir": export_dir, - "area-count": len(areas), - }).Info("exporting area-protected chunks") - - if len(areas) == 0 { - return fmt.Errorf("no areas found, aborting") - } - - err := os.MkdirAll(export_dir, 0777) +// initializeExportDirectory initializes the output directory for exporting. +func initializeExportDirectory(export_dir string) (export_db block.BlockRepository, err error) { + err = os.MkdirAll(export_dir, 0777) if err != nil { - return fmt.Errorf("could not create directory '%s': %v", export_dir, err) + return nil, fmt.Errorf("could not create export-db: %v", err) } worldmt_file, err := os.Create(path.Join(export_dir, "world.mt")) if err != nil { - return fmt.Errorf("could not open 'world.mt': %v", err) + return nil, fmt.Errorf("could not create export-db: %v", err) } _, err = worldmt_file.WriteString("backend = sqlite3\n") if err != nil { - return fmt.Errorf("could not write to 'world.mt': %v", err) + return nil, fmt.Errorf("could not create export-db: %v", err) } worldmt_file.Close() - export_db, err := mtdb.NewBlockDB(export_dir) + export_db, err = mtdb.NewBlockDB(export_dir) + if err != nil { + return nil, fmt.Errorf("could not create export-db: %v", err) + } + return export_db, nil +} + +func ProcessExportProtected(areas []*areasparser.Area) error { + if len(areas) == 0 { + return fmt.Errorf("no areas found, aborting") + } + + export_dir := path.Join(wd, "area-export") + + logrus.WithFields(logrus.Fields{ + "export_dir": export_dir, + "area-count": len(areas), + }).Info("exporting area-protected chunks") + + export_db, err := initializeExportDirectory(export_dir) if err != nil { - return fmt.Errorf("could not create export-db: %v", err) + return err } defer export_db.Close() @@ -102,3 +114,105 @@ func ProcessExportProtected(areas []*areasparser.Area) error { return nil } + +func ProccessExportAllProtected() error { + // syntax suggar + type f logrus.Fields + I := func(msg string, f f) { logrus.WithFields(logrus.Fields(f)).Info(msg) } + D := func(msg string, f f) { logrus.WithFields(logrus.Fields(f)).Debug(msg) } + W := func(msg string, f f) { logrus.WithFields(logrus.Fields(f)).Warning(msg) } + + // Load protected nodes + if err := LoadProtectedNodes(); err != nil { + return err + } + + export_dir := path.Join(wd, "area-export") + export_info := f{ + "export_dir": export_dir, + "area_count": len(protected_areas), + "export_all": true, + "protected_nodes": protected_nodenames, + } + I("exporting all protected areas; parsing the entire map", export_info) + + export_db, err := initializeExportDirectory(export_dir) + if err != nil { + return err + } + defer export_db.Close() + D("export_db initialized", f{"export_dir": export_dir}) + + // Check source size + total_blocks, err := block_repo.Count() + if err != nil { + return err + } + + // Initialize variables + D("initializing iterator from source", f{"total_blocks": total_blocks}) + it, closer, err := block_repo.Iterator(block.AsBlockPos(-33000, -33000, -33000)) + if err != nil { + return err + } + defer closer.Close() + + // Stats + exported_chunks := map[string]bool{} + chunk_count := 0 + block_count := 0 + start := time.Now() + D("parsing all blocks", f{}) + for b := range it { + block_count++ + + protected, err := IsBlockProtected(b) + if err != nil { + W("error detecting if block is protected", f{"block": b}) + return err + } + + if protected { + chunkx, chunky, chunkz := GetChunkPosFromMapblock(b.PosX, b.PosY, b.PosZ) + + // Export surounding chunks as protected elements can be inside a construction that is + // at the edge of a mapblock/mapchunk. + for x := chunkx - 1; x <= chunkx+1; x++ { + for y := chunky - 1; y <= chunky+1; y++ { + for z := chunkz - 1; z <= chunkz+1; z++ { + key := GetChunkKey(x, y, z) + if exported_chunks[key] { + D("chunk already exported, skipping", f{"key": key}) + continue + } + + I("exporting chunk", f{"x": x, "y": y, "z": z}) + err = ExportChunk(block_repo, export_db, x, y, z) + if err != nil { + return fmt.Errorf("export error in chunk %d/%d/%d: %v", x, y, z, err) + } + + // mark as exported + exported_chunks[key] = true + chunk_count++ + } + } + } + } + + // Report progress every 100 blocks + if block_count%1000 == 0 { + progress := 100 * float64(block_count) / float64(total_blocks) + stats := f{ + "expo_chunks": chunk_count, + "proc_blocks": block_count, + "progress": fmt.Sprintf("%.02f%%", progress), + "elapsed": time.Since(start).String(), + } + I("processing blocks", stats) + } + } + + I("export finished", f{"exported_chunks": chunk_count, "processed_blocks": block_count}) + return nil +} diff --git a/protected.go b/protected.go index 90613fe..a489133 100644 --- a/protected.go +++ b/protected.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/golang-lru/v2/expirable" "github.com/minetest-go/areasparser" "github.com/minetest-go/mapparser" + "github.com/minetest-go/mtdb/block" "github.com/sirupsen/logrus" ) @@ -187,3 +188,29 @@ func IsProtectedWithNeighbors(chunk_x, chunk_y, chunk_z int) (bool, error) { } return false, nil } + +// IsBlockProtected checks if the block is protected either by areas mod or by the +// user provided nodes. +func IsBlockProtected(b *block.Block) (protected bool, err error) { + // Is this block protected by areas mod? + key := GetChunkKey(GetChunkPosFromMapblock(b.PosX, b.PosY, b.PosZ)) + protected = protected_areas[key] + if protected { + return true, nil + } + + // Is this block protected by the user selected nodes? + parsedBlock, err := mapparser.Parse(b.Data) + if err != nil { + return false, err + } + for _, name := range parsedBlock.BlockMapping { + if protected_nodenames[name] { + logrus.WithFields(logrus.Fields{"block_mapping": parsedBlock.BlockMapping, "found": name}).Debug("block is protected") + // protected block here + protected = true + break + } + } + return protected, nil +} diff --git a/test/entrypoint.sh b/test/entrypoint.sh index c58bd87..0ae3fc6 100755 --- a/test/entrypoint.sh +++ b/test/entrypoint.sh @@ -3,23 +3,29 @@ set -e set -x minetestserver --config /minetest.conf - sqlite3 map.sqlite "select count(*) from blocks" # prune mode /mapcleaner - sqlite3 map.sqlite "select count(*) from blocks" - retained=$(cat mapcleaner.json | jq -r ".retained_chunks") - # 4x3x3 chunks remain test "${retained}" == "36" || exit 1 # export mode /mapcleaner -mode export_protected - test -d area-export test -f area-export/map.sqlite - sqlite3 area-export/map.sqlite "select count(*) from blocks" + +# export mode including user specified protected nodes +rm -rf area-export +/mapcleaner -mode export_protected -export-all +test -d area-export +test -f area-export/map.sqlite +# Two chunks are preserved (one with bones and one with areas protection) +# 3x3x3 chunks around each are exported as well, but since they are next +# to each other, some mapblocks are shared and should not be counted twice: +# 3x3x4 chunks should be exported. Each has 5x5x5 mapblocks = 4500 total exported mapblocks. +exported_blocks="$(sqlite3 area-export/map.sqlite "select count(*) from blocks")" +test "${exported_blocks}" == "4500" || exit 1 diff --git a/test/testmod/init.lua b/test/testmod/init.lua index 80f94fb..39da48f 100644 --- a/test/testmod/init.lua +++ b/test/testmod/init.lua @@ -1,6 +1,6 @@ -- emerge all chunks around the two "protected" chunks in (0,0,0) and (1,0,0) -mtt.emerge_area({x=-100,y=0,z=-100}, {x=200,y=100,z=100}) +mtt.emerge_area({x=-400,y=-400,z=-400}, {x=400,y=400,z=400}) mtt.register("setup", function(callback)