diff --git a/cmd/init.go b/cmd/init.go index 080165b..68a9dba 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -47,22 +47,22 @@ var initCmd = &cobra.Command{ if directoryName != "." && len(directoryName) > 0 { // Turn directory name into a space-seperated proper name name = titlecase.Title(strings.ReplaceAll(strings.ReplaceAll(strings.Join(camelcase.Split(directoryName), " "), " - ", " "), " _ ", " ")) - fmt.Print("Modpack name [" + name + "]: ") + name = initReadValue("Modpack name ["+name+"]: ", name) } else { - fmt.Print("Modpack name: ") - } - readName, err := bufio.NewReader(os.Stdin).ReadString('\n') - if err != nil { - fmt.Printf("Error reading input: %s\n", err) - os.Exit(1) - } - // Trims both CR and LF - readName = strings.TrimSpace(strings.TrimRight(readName, "\r\n")) - if len(readName) > 0 { - name = readName + name = initReadValue("Modpack name: ", "") } } + author, err := cmd.Flags().GetString("author") + if err != nil || len(author) == 0 { + author = initReadValue("Author: ", "") + } + + version, err := cmd.Flags().GetString("version") + if err != nil || len(version) == 0 { + version = initReadValue("Version [1.0.0]: ", "1.0.0") + } + mcVersions, err := getValidMCVersions() if err != nil { fmt.Printf("Failed to get latest minecraft versions: %s\n", err) @@ -80,36 +80,14 @@ var initCmd = &cobra.Command{ if viper.GetBool("init.latest") { mcVersion = latestVersion } else { - fmt.Print("Minecraft version [" + latestVersion + "]: ") - mcVersion, err = bufio.NewReader(os.Stdin).ReadString('\n') - if err != nil { - fmt.Printf("Error reading input: %s\n", err) - os.Exit(1) - } - // Trims both CR and LF - mcVersion = strings.TrimSpace(strings.TrimRight(mcVersion, "\r\n")) - if len(mcVersion) == 0 { - mcVersion = latestVersion - } + mcVersion = initReadValue("Minecraft version ["+latestVersion+"]: ", latestVersion) } } mcVersions.checkValid(mcVersion) - // TODO: minecraft modloader modLoaderName := viper.GetString("init.modloader") if len(modLoaderName) == 0 { - defaultLoader := "fabric" - fmt.Print("Mod loader [" + defaultLoader + "]: ") - modLoaderName, err = bufio.NewReader(os.Stdin).ReadString('\n') - if err != nil { - fmt.Printf("Error reading input: %s\n", err) - os.Exit(1) - } - // Trims both CR and LF - modLoaderName = strings.ToLower(strings.TrimSpace(strings.TrimRight(modLoaderName, "\r\n"))) - if len(modLoaderName) == 0 { - modLoaderName = defaultLoader - } + modLoaderName = initReadValue("Mod loader [fabric]: ", "fabric") } _, ok := modLoaders[modLoaderName] if modLoaderName != "none" && !ok { @@ -140,17 +118,7 @@ var initCmd = &cobra.Command{ if viper.GetBool("init." + component.Name + "-latest") { componentVersion = latestVersion } else { - fmt.Print(component.FriendlyName + " version [" + latestVersion + "]: ") - componentVersion, err = bufio.NewReader(os.Stdin).ReadString('\n') - if err != nil { - fmt.Printf("Error reading input: %s\n", err) - os.Exit(1) - } - // Trims both CR and LF - componentVersion = strings.ToLower(strings.TrimSpace(strings.TrimRight(componentVersion, "\r\n"))) - if len(componentVersion) == 0 { - componentVersion = latestVersion - } + componentVersion = initReadValue(component.FriendlyName+" version ["+latestVersion+"]: ", latestVersion) } } found := false @@ -185,7 +153,9 @@ var initCmd = &cobra.Command{ // Create the pack pack := core.Pack{ - Name: name, + Name: name, + Author: author, + Version: version, Index: struct { File string `toml:"file"` HashFormat string `toml:"hash-format"` @@ -237,6 +207,8 @@ func init() { rootCmd.AddCommand(initCmd) initCmd.Flags().String("name", "", "The name of the modpack (omit to define interactively)") + initCmd.Flags().String("author", "", "The author of the modpack (omit to define interactively)") + initCmd.Flags().String("version", "", "The version of the modpack (omit to define interactively)") initCmd.Flags().String("index-file", "index.toml", "The index file to use") _ = viper.BindPFlag("init.index-file", initCmd.Flags().Lookup("index-file")) initCmd.Flags().String("mc-version", "", "The Minecraft version to use (omit to define interactively)") @@ -261,6 +233,21 @@ func init() { } } +func initReadValue(prompt string, def string) string { + fmt.Print(prompt) + value, err := bufio.NewReader(os.Stdin).ReadString('\n') + if err != nil { + fmt.Printf("Error reading input: %s\n", err) + os.Exit(1) + } + // Trims both CR and LF + value = strings.TrimSpace(strings.TrimRight(value, "\r\n")) + if len(value) > 0 { + return value + } + return def +} + type mcVersionManifest struct { Latest struct { Release string `json:"release"` diff --git a/core/pack.go b/core/pack.go index e534929..4410788 100644 --- a/core/pack.go +++ b/core/pack.go @@ -13,16 +13,19 @@ import ( // Pack stores the modpack metadata, usually in pack.toml type Pack struct { - Name string `toml:"name"` - Index struct { + Name string `toml:"name"` + Author string `toml:"author"` + Version string `toml:"version"` + Index struct { // Path is stored in forward slash format relative to pack.toml File string `toml:"file"` HashFormat string `toml:"hash-format"` Hash string `toml:"hash"` } `toml:"index"` - Versions map[string]string `toml:"versions"` - Client map[string]toml.Primitive `toml:"client"` - Server map[string]toml.Primitive `toml:"server"` + Versions map[string]string `toml:"versions"` + Client map[string]toml.Primitive `toml:"client"` + Server map[string]toml.Primitive `toml:"server"` + Export map[string]map[string]interface{} `toml:"export"` } // LoadPack loads the modpack metadata to a Pack struct @@ -105,3 +108,13 @@ func (pack Pack) GetMCVersion() (string, error) { } return mcVersion, nil } + +func (pack Pack) GetPackName() string { + if pack.Name == "" { + return "export" + } else if pack.Version == "" { + return pack.Name + } else { + return pack.Name + "-" + pack.Version + } +} diff --git a/curseforge/curseforge.go b/curseforge/curseforge.go index 86a4cf0..0f1312b 100644 --- a/curseforge/curseforge.go +++ b/curseforge/curseforge.go @@ -346,3 +346,19 @@ func (u cfUpdater) DoUpdate(mods []*core.Mod, cachedState []interface{}) error { return nil } + +type cfExportData struct { + ProjectID int `mapstructure:"project-id"` +} + +func (e cfExportData) ToMap() (map[string]interface{}, error) { + newMap := make(map[string]interface{}) + err := mapstructure.Decode(e, &newMap) + return newMap, err +} + +func parseExportData(from map[string]interface{}) (cfExportData, error) { + var exportData cfExportData + err := mapstructure.Decode(from, &exportData) + return exportData, err +} diff --git a/curseforge/export.go b/curseforge/export.go index 0af646e..693b22c 100644 --- a/curseforge/export.go +++ b/curseforge/export.go @@ -19,8 +19,7 @@ import ( var exportCmd = &cobra.Command{ Use: "export", Short: "Export the current modpack into a .zip for curseforge", - // TODO: arguments for file name, author? projectID? - Args: cobra.NoArgs, + Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { side := viper.GetString("curseforge.export.side") if len(side) == 0 || (side != core.UniversalSide && side != core.ServerSide && side != core.ClientSide) { @@ -78,7 +77,19 @@ var exportCmd = &cobra.Command{ } mods = mods[:i] - expFile, err := os.Create("export.zip") + var exportData cfExportData + exportDataUnparsed, ok := pack.Export["curseforge"] + if ok { + exportData, err = parseExportData(exportDataUnparsed) + if err != nil { + fmt.Printf("Failed to parse export metadata: %s\n", err.Error()) + os.Exit(1) + } + } + + var fileName = pack.GetPackName() + ".zip" + + expFile, err := os.Create(fileName) if err != nil { fmt.Printf("Failed to create zip: %s\n", err.Error()) os.Exit(1) @@ -135,7 +146,7 @@ var exportCmd = &cobra.Command{ os.Exit(1) } - err = packinterop.WriteManifestFromPack(pack, cfFileRefs, manifestFile) + err = packinterop.WriteManifestFromPack(pack, cfFileRefs, exportData.ProjectID, manifestFile) if err != nil { _ = exp.Close() _ = expFile.Close() @@ -188,7 +199,8 @@ var exportCmd = &cobra.Command{ os.Exit(1) } - fmt.Println("Modpack exported to export.zip!") + fmt.Println("Modpack exported to " + fileName) + fmt.Println("Make sure you remove this file before running packwiz refresh, or add it to .packwizignore") }, } diff --git a/curseforge/packinterop/translation.go b/curseforge/packinterop/translation.go index ce5b84b..03b4236 100644 --- a/curseforge/packinterop/translation.go +++ b/curseforge/packinterop/translation.go @@ -69,7 +69,7 @@ type AddonFileReference struct { OptionalDisabled bool } -func WriteManifestFromPack(pack core.Pack, fileRefs []AddonFileReference, out io.Writer) error { +func WriteManifestFromPack(pack core.Pack, fileRefs []AddonFileReference, projectID int, out io.Writer) error { files := make([]struct { ProjectID int `json:"projectID"` FileID int `json:"fileID"` @@ -103,9 +103,9 @@ func WriteManifestFromPack(pack core.Pack, fileRefs []AddonFileReference, out io ManifestType: "minecraftModpack", ManifestVersion: 1, NameInternal: pack.Name, - Version: "", // TODO: store or take this? - Author: "", // TODO: store or take this? - ProjectID: 0, // TODO: store or take this? + Version: pack.Version, + Author: pack.Author, + ProjectID: projectID, Files: files, Overrides: "overrides", }