121 lines
2.7 KiB
Go
121 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"compress/gzip"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/Tnze/go-mc/nbt"
|
|
"github.com/Tnze/go-mc/nbt/dynbt"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
func readPlayerdata(dir string, m map[uuid.UUID]UserCache) {
|
|
entries, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Failed to open playerdata folder: %v", err)
|
|
return
|
|
}
|
|
for _, files := range entries {
|
|
filename := files.Name()
|
|
if ext := filepath.Ext(filename); ext != ".dat" {
|
|
fmt.Fprintf(os.Stderr, "Unkown file type: %s\n", ext)
|
|
continue
|
|
}
|
|
|
|
// Parse old UUID from filename
|
|
oldID, err := uuid.Parse(strings.TrimSuffix(filename, ".dat"))
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Unable to parse filename as uuid: %v\n", err)
|
|
continue
|
|
}
|
|
|
|
nbtdata, err := readNbtData(filepath.Join(dir, filename))
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Failed to read %s nbt data\n", filename)
|
|
continue
|
|
}
|
|
|
|
// Read old UUID from nbt
|
|
uuidInts := nbtdata.Get("UUID").IntArray()
|
|
uuidBytes, err := intArrayToUUID(uuidInts)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Failed to read %s UUID\n", filename)
|
|
continue
|
|
}
|
|
|
|
// Does they matche?
|
|
if oldID != uuidBytes {
|
|
fmt.Fprintf(os.Stderr, "UUID in filename and nbt data don't match, what happend?\n")
|
|
}
|
|
|
|
if ver := uuidBytes.Version(); ver != 3 { // v3 is for offline players
|
|
fmt.Printf("Ignoring UUID: %v version: %d\n", uuidBytes, ver)
|
|
continue
|
|
}
|
|
|
|
newUser, ok := m[oldID]
|
|
if !ok {
|
|
fmt.Printf("Skip user: %v\n", oldID)
|
|
continue
|
|
}
|
|
|
|
// Update UUID
|
|
ints := uuidToIntArray(newUser.UUID)
|
|
nbtdata.Set("UUID", dynbt.NewIntArray(ints[:]))
|
|
|
|
// Create new .dat file
|
|
err = writeNbtData(dir, newUser.UUID.String(), &nbtdata)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Unable to write %s's .dat file: %v\n", newUser.Name, err)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
func readNbtData(filepath string) (nbtdata dynbt.Value, err error) {
|
|
file, err := os.Open(filepath)
|
|
if err != nil {
|
|
return nbtdata, fmt.Errorf("failed to open userdata: %w", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
r, err := gzip.NewReader(file)
|
|
if err != nil {
|
|
return nbtdata, fmt.Errorf("failed to decompress userdata: %w", err)
|
|
}
|
|
|
|
_, err = nbt.NewDecoder(r).Decode(&nbtdata)
|
|
if err != nil {
|
|
return nbtdata, fmt.Errorf("failed to parse userdata: %w", err)
|
|
}
|
|
return nbtdata, nil
|
|
}
|
|
|
|
func writeNbtData(dir string, id string, nbtdata *dynbt.Value) error {
|
|
newDatFilePath := filepath.Join(dir, id+".dat")
|
|
file, err := os.Create(newDatFilePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
w := gzip.NewWriter(file)
|
|
err = nbt.NewEncoder(w).Encode(&nbtdata, "")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = w.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = file.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|