diff --git a/tools/buildmap/cardmap.go b/tools/buildmap/cardmap.go new file mode 100644 index 0000000..c32469e --- /dev/null +++ b/tools/buildmap/cardmap.go @@ -0,0 +1,39 @@ +package main + +import ( + "log" + "strings" +) + +// GUID to Card ID map (or viceversa) +type cardMap map[string]string + +func buildMap(sets []xmlSet, reverse, tolc bool) cardMap { + cdb := make(cardMap) + for _, set := range sets { + log.Printf("Generating card map for \"%s\"...\n", set.Name) + for _, card := range set.Cards { + // Find card number + number := "" + for _, prop := range card.Properties { + if prop.Name == "Number" { + number = prop.Value + break + } + } + if number == "" { + continue + } + if tolc { + number = strings.ToLower(number) + } + if reverse { + cdb[number] = card.ID + } else { + cdb[card.ID] = number + } + } + } + log.Printf("Generated card map (%d cards total)\n", len(cdb)) + return cdb +} diff --git a/tools/buildmap/loadxml.go b/tools/buildmap/loadxml.go new file mode 100644 index 0000000..0b9eed5 --- /dev/null +++ b/tools/buildmap/loadxml.go @@ -0,0 +1,58 @@ +package main + +import ( + "encoding/xml" + "log" + "os" + "path/filepath" +) + +type xmlSet struct { + Name string `xml:"name,attr"` + Cards []xmlCard `xml:"cards>card"` +} + +type xmlCard struct { + ID string `xml:"id,attr"` + Properties []xmlProperty `xml:"property"` +} + +type xmlProperty struct { + Name string `xml:"name,attr"` + Value string `xml:"value,attr"` +} + +func loadSetCards(filename string) (xmlSet, error) { + file, err := os.Open(filename) + if err != nil { + return xmlSet{}, err + } + defer file.Close() + + var set xmlSet + err = xml.NewDecoder(file).Decode(&set) + return set, err +} + +func loadSets(basedir string) ([]xmlSet, error) { + var sets []xmlSet + err := filepath.Walk(basedir, func(path string, info os.FileInfo, err error) error { + if err != nil { + log.Printf("Error while scanning %s: %s\n", path, err.Error()) + return err + } + // Ignore non XML files + ext := filepath.Ext(path) + if info.IsDir() || ext != ".xml" { + return nil + } + set, err := loadSetCards(path) + if err != nil { + return err + } + log.Printf("Loaded set: %s (%d cards)\n", set.Name, len(set.Cards)) + sets = append(sets, set) + return nil + }) + return sets, err +} diff --git a/tools/buildmap/main.go b/tools/buildmap/main.go new file mode 100644 index 0000000..d7c46ad --- /dev/null +++ b/tools/buildmap/main.go @@ -0,0 +1,51 @@ +package main // import "git.fromouter.space/mcg/mlp-server-tools/tools/buildmap" + +import ( + "encoding/json" + "flag" + "log" + "os" + "path/filepath" + + "golang.org/x/sys/windows/registry" +) + +func main() { + doc := getDocumentDir() + defaultSetPath := filepath.Join(doc, "OCTGN", "GameDatabase", "65656467-b709-43b2-a5c6-80c2f216adf9", "Sets") + setpath := flag.String("set-path", defaultSetPath, "Path to sets") + reverse := flag.Bool("reverse", false, "Reverse mapping (GUID->ID)") + format := flag.Bool("format", false, "Format the output") + tolc := flag.Bool("lowercase", false, "Convert IDs to lowercase (for better ponyhead compatibility)") + flag.Parse() + + // Load sets + sets, err := loadSets(*setpath) + if err != nil { + log.Fatalf("Could not load all sets: %s\nClosing...\n", err.Error()) + } + + cmap := buildMap(sets, *reverse, *tolc) + enc := json.NewEncoder(os.Stdout) + if *format { + enc.SetIndent("", " ") + } + err = enc.Encode(cmap) + if err != nil { + log.Fatalf("Error while encoding to JSON: %s\n", err.Error()) + } +} + +func getDocumentDir() string { + k, err := registry.OpenKey(registry.CURRENT_USER, `SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders`, registry.QUERY_VALUE) + if err != nil { + return "" + } + defer k.Close() + + s, _, err := k.GetStringValue("Personal") + if err != nil { + return "" + } + return s +} diff --git a/tools/convertsets/convert.go b/tools/convertsets/convert.go new file mode 100644 index 0000000..54ad5d4 --- /dev/null +++ b/tools/convertsets/convert.go @@ -0,0 +1,103 @@ +package main + +import ( + "strconv" + "strings" +) + +type jsonSet struct { + Name string + Cards []jsonCard +} + +type jsonCard struct { + ID string + Name string + Element string + Keywords []string + Cost int + Power int + Type string + Text string +} + +func convert(xmlset xmlSet) (s jsonSet) { + s.Name = xmlset.Name + for _, xmlcard := range xmlset.Cards { + jsoncard := jsonCard{ + Name: xmlcard.Name, + } + for _, property := range xmlcard.Properties { + switch property.Name { + case "Cost": + if property.Value != "" { + jsoncard.Cost, _ = strconv.Atoi(property.Value) + } + case "Element": + if property.Value != "" { + jsoncard.Element = property.Value + } + case "Keywords": + if property.Value != "" { + jsoncard.Keywords = strings.Split(strings.TrimRight(property.Value, "."), ", ") + } + case "MultiPrimaryElement": + //todo + case "MultiSecondaryElement": + //todo + case "Number": + jsoncard.ID = strings.ToLower(property.Value) + case "PlayRequiredElement": + //todo + case "PlayRequiredPower": + //todo + case "Power": + if property.Value != "" { + jsoncard.Cost, _ = strconv.Atoi(property.Value) + } + case "ProblemBonus": + //todo + case "ProblemOpponentPower": + //todo + case "ProblemPlayerElement1": + //todo + case "ProblemPlayerElement1Power": + //todo + case "ProblemPlayerElement2": + //todo + case "ProblemPlayerElement2Power": + //todo + case "Rarity": + //todo + case "SecondaryPlayRequiredElement": + //todo + case "SecondaryPlayRequiredPower": + //todo + case "Subname": + //todo + case "TertiaryPlayRequiredElement": + //todo + case "TertiaryPlayRequiredPower": + //todo + case "Text": + jsoncard.Text = property.Value + case "Traits": + //todo + case "TriElement": + //todo + case "TriPrimaryElement": + //todo + case "TriSecondaryElement": + //todo + case "Type": + jsoncard.Type = property.Value + } + } + // Don't let empty arrays be null + if jsoncard.Keywords == nil { + jsoncard.Keywords = []string{} + } + s.Cards = append(s.Cards, jsoncard) + } + return +} diff --git a/tools/convertsets/go.mod b/tools/convertsets/go.mod new file mode 100644 index 0000000..9f9d1b5 --- /dev/null +++ b/tools/convertsets/go.mod @@ -0,0 +1 @@ +module git.fromouter.space/mcg/mlp-server-tools/tools/convertsets diff --git a/tools/convertsets/loadxml.go b/tools/convertsets/loadxml.go new file mode 100644 index 0000000..a3de0f2 --- /dev/null +++ b/tools/convertsets/loadxml.go @@ -0,0 +1,59 @@ +package main + +import ( + "encoding/xml" + "log" + "os" + "path/filepath" +) + +type xmlSet struct { + Name string `xml:"name,attr"` + Cards []xmlCard `xml:"cards>card"` +} + +type xmlCard struct { + ID string `xml:"id,attr"` + Name string `xml:"name,attr"` + Properties []xmlProperty `xml:"property"` +} + +type xmlProperty struct { + Name string `xml:"name,attr"` + Value string `xml:"value,attr"` +} + +func loadSetCards(filename string) (xmlSet, error) { + file, err := os.Open(filename) + if err != nil { + return xmlSet{}, err + } + defer file.Close() + + var set xmlSet + err = xml.NewDecoder(file).Decode(&set) + return set, err +} + +func loadSets(basedir string) ([]xmlSet, error) { + var sets []xmlSet + err := filepath.Walk(basedir, func(path string, info os.FileInfo, err error) error { + if err != nil { + log.Printf("Error while scanning %s: %s\n", path, err.Error()) + return err + } + // Ignore non XML files + ext := filepath.Ext(path) + if info.IsDir() || ext != ".xml" { + return nil + } + set, err := loadSetCards(path) + if err != nil { + return err + } + log.Printf("Loaded set: %s (%d cards)\n", set.Name, len(set.Cards)) + sets = append(sets, set) + return nil + }) + return sets, err +} diff --git a/tools/convertsets/main.go b/tools/convertsets/main.go new file mode 100644 index 0000000..3547c57 --- /dev/null +++ b/tools/convertsets/main.go @@ -0,0 +1,94 @@ +package main // import "git.fromouter.space/mcg/mlp-server-tools/tools/convertsets" + +import ( + "encoding/json" + "flag" + "log" + "os" + "path/filepath" + "strings" + + "golang.org/x/sys/windows/registry" +) + +var setfilenames = map[string]string{ + "Tokens": "tokens", + "Premiere": "pr", + "Promos": "promo", + "High Magic": "hm", + "Equestrian Odysseys": "eo", + "Marks in Time": "mt", + "Absolute Discord": "ad", + "Crystal Games": "cg", + "Rock and Rave": "rr", + "Celestial Solstice": "cs", + "Canterlot Nights": "cn", + "Defenders of Equestria": "de", + "Seaquestria and Beyond": "sb", + "Friends Forever": "ff", + "Sands in Time": "st", + "Villain Challenge": "villain", +} + +func main() { + doc := getDocumentDir() + defaultSetPath := filepath.Join(doc, "OCTGN", "GameDatabase", "65656467-b709-43b2-a5c6-80c2f216adf9", "Sets") + setpath := flag.String("set-path", defaultSetPath, "Path to sets") + format := flag.Bool("format", false, "Format the output") + outdir := flag.String("out-dir", "setdata", "Output directory") + flag.Parse() + + // Load sets + sets, err := loadSets(*setpath) + if err != nil { + log.Fatalf("Could not load all sets: %s\nClosing...\n", err.Error()) + } + + err = os.MkdirAll(*outdir, 0755) + if err != nil { + log.Fatalf("Error while creating output directory: %s\n", err.Error()) + } + + // Iterate for each set + for _, set := range sets { + // Get set shorthand + setname, ok := setfilenames[set.Name] + if !ok { + setname = strings.ToLower(set.Name) + } + + // Convert to MCG's JSON format + setdata := convert(set) + + // Create file + outpath := filepath.Join(*outdir, setname+".json") + file, err := os.Create(outpath) + if err != nil { + log.Fatalf("Error while creating output file for set \"%s\": %s\n", set.Name, err.Error()) + } + enc := json.NewEncoder(file) + if *format { + enc.SetIndent("", " ") + } + err = enc.Encode(setdata) + if err != nil { + log.Fatalf("Error while encoding to JSON: %s\n", err.Error()) + } + log.Printf("Saved converted set \"%s\" to: %s\n", set.Name, outpath) + } + +} + +func getDocumentDir() string { + k, err := registry.OpenKey(registry.CURRENT_USER, `SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders`, registry.QUERY_VALUE) + if err != nil { + return "" + } + defer k.Close() + + s, _, err := k.GetStringValue("Personal") + if err != nil { + return "" + } + return s +} diff --git a/tools/genpics/main.go b/tools/genpics/main.go index 0eb6f50..ae2a24f 100644 --- a/tools/genpics/main.go +++ b/tools/genpics/main.go @@ -1,4 +1,4 @@ -package main // import "git.fromouter.space/mcg/mcgserver/tools/genpics" +package main // import "git.fromouter.space/mcg/mlp-server-tools/tools/genpics" import ( "archive/zip"