change: Finished loading command and added some scripts for extracting world saves

This commit is contained in:
Nicholas Novak 2023-11-13 22:56:20 -08:00
parent 6719b6e929
commit 4fd4b6112f
4 changed files with 141 additions and 57 deletions

21
Makefile Normal file
View File

@ -0,0 +1,21 @@
SAVES := imperial-save
SAVES += skygrid-save
SAVES += witchcraft-save
all: $(SAVES)
imperial-save:
mkdir imperial-save
./spatial-db load worldsave "saves/Imperialcity v14.1/region" --output "imperial-save"
skygrid-save:
mkdir skygrid-save
./spatial-db load worldsave "saves/SkyGrid/region" --output "skygrid-save"
witchcraft-save:
mkdir witchcraft-save
./spatial-db load worldsave "saves/Witchcraft/region" --output "witchcraft-save"
.PHONY: clean
clean:
rm -r $(SAVES)

View File

@ -1,71 +1,46 @@
package loading package loading
import ( import (
"encoding/json"
"fmt"
"log"
"os"
"path/filepath"
"git.nicholasnovak.io/nnovak/spatial-db/world" "git.nicholasnovak.io/nnovak/spatial-db/world"
"github.com/Tnze/go-mc/save" "github.com/Tnze/go-mc/save"
"github.com/Tnze/go-mc/save/region" "github.com/Tnze/go-mc/save/region"
"github.com/spf13/cobra"
) )
type SectorPos struct { // LoadRegionFile loads a single region file into an array of chunks
x, y int //
} // A region is a 32x32 grid of chunks, although the final output can store less
func LoadRegionFile(fileName string) ([]world.ChunkData, error) {
var outputDir string regionFile, err := region.Open(fileName)
func init() {
LoadRegionFileCommand.Flags().StringVar(&outputDir, "output", ".", "The output directory for the files")
}
var LoadRegionFileCommand = &cobra.Command{
Use: "load",
RunE: func(cmd *cobra.Command, args []string) error {
regionFile, err := region.Open(args[0])
if err != nil { if err != nil {
return err return nil, err
} }
defer regionFile.Close() defer regionFile.Close()
validSectors := []SectorPos{} // A region file is a 32x32 grid of chunks
chunks := []world.ChunkData{}
for i := 0; i < 32; i++ { for i := 0; i < 32; i++ {
for j := 0; j < 32; j++ { for j := 0; j < 32; j++ {
if regionFile.ExistSector(i, j) { if regionFile.ExistSector(i, j) {
validSectors = append(validSectors, SectorPos{i, j}) sectorFile, err := regionFile.ReadSector(i, j)
}
}
}
for _, sectorPos := range validSectors {
data, err := regionFile.ReadSector(sectorPos.x, sectorPos.y)
if err != nil { if err != nil {
return err return nil, err
} }
// Read each chunk from disk
var chunk save.Chunk var chunk save.Chunk
if err := chunk.Load(data); err != nil { if err := chunk.Load(sectorFile); err != nil {
return err return nil, err
} }
// Convert each chunk into the database's format
var chunkData world.ChunkData var chunkData world.ChunkData
chunkData.FromMCAChunk(chunk) chunkData.FromMCAChunk(chunk)
outfile, err := os.OpenFile(filepath.Join(outputDir, fmt.Sprintf("p.%d.%d.chunk", chunkData.Pos.X, chunkData.Pos.Z)), os.O_WRONLY|os.O_CREATE, 0644) chunks = append(chunks, chunkData)
if err != nil {
log.Fatal(err)
} }
if err := json.NewEncoder(outfile).Encode(chunkData); err != nil {
log.Fatal(err)
} }
outfile.Close()
} }
return nil return chunks, nil
},
} }

80
loading/load_save.go Normal file
View File

@ -0,0 +1,80 @@
package loading
import (
"encoding/json"
"os"
"path/filepath"
"strings"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
var (
saveOutputDir string
)
func init() {
LoadSaveDirCommand.Flags().StringVar(&saveOutputDir, "output", ".", "Where to place the converted save files")
}
var LoadSaveDirCommand = &cobra.Command{
Use: "worldsave <save-directory>",
Short: "Loads all the regions in the specified world's save directory",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
// First, fetch a list of all the files that are in the specified directory
regionFiles, err := os.ReadDir(args[0])
if err != nil {
return err
}
log.Infof("Loading save directory of %s", args[0])
for regionIndex, regionFile := range regionFiles {
if regionFile.IsDir() {
continue
}
if strings.HasSuffix(regionFile.Name(), ".mcr") {
log.Warnf("The file %s is in the MCRegion format, skipping", regionFile.Name())
continue
}
log.Infof("Converting region file %s, [%d/%d]",
regionFile.Name(),
regionIndex,
len(regionFiles),
)
filePath := filepath.Join(args[0], regionFile.Name())
// Load each region file
chunks, err := LoadRegionFile(filePath)
if err != nil {
return err
}
// Save each chunk to a separate file
for _, chunk := range chunks {
outfile, err := os.OpenFile(
filepath.Join(saveOutputDir, chunk.Pos.ToFileName()),
os.O_WRONLY|os.O_CREATE|os.O_APPEND,
0664,
)
if err != nil {
return err
}
if err := json.NewEncoder(outfile).Encode(chunk); err != nil {
return err
}
outfile.Close()
}
}
return nil
},
}

10
main.go
View File

@ -14,7 +14,15 @@ func main() {
rootCmd.AddCommand(visualization.VisualizeCommand) rootCmd.AddCommand(visualization.VisualizeCommand)
rootCmd.AddCommand(connector.ProxyPortCommand) rootCmd.AddCommand(connector.ProxyPortCommand)
rootCmd.AddCommand(loading.LoadRegionFileCommand)
loadCmd := &cobra.Command{
Use: "load",
Short: "Loads save files into the database's format",
}
loadCmd.AddCommand(loading.LoadSaveDirCommand)
rootCmd.AddCommand(loadCmd)
if err := rootCmd.Execute(); err != nil { if err := rootCmd.Execute(); err != nil {
panic(err) panic(err)