diff --git a/cmd/root.go b/cmd/root.go index 105ff6d..e41c35d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" "github.com/packwiz/packwiz/core" + "github.com/spf13/pflag" "os" "path/filepath" @@ -11,7 +12,6 @@ import ( ) var packFile string -var modsFolder string var cfgFile string // rootCmd represents the base command when called without any subcommands @@ -38,8 +38,22 @@ func init() { rootCmd.PersistentFlags().StringVar(&packFile, "pack-file", "pack.toml", "The modpack metadata file to use") _ = viper.BindPFlag("pack-file", rootCmd.PersistentFlags().Lookup("pack-file")) - rootCmd.PersistentFlags().StringVar(&modsFolder, "mods-folder", "mods", "The default folder to store mod metadata files in") - _ = viper.BindPFlag("mods-folder", rootCmd.PersistentFlags().Lookup("mods-folder")) + // Make mods-folder an alias for meta-folder + viper.RegisterAlias("mods-folder", "meta-folder") + rootCmd.SetGlobalNormalizationFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName { + if name == "mods-folder" { + return "meta-folder" + } + return pflag.NormalizedName(name) + }) + + var metaFolder string + rootCmd.PersistentFlags().StringVar(&metaFolder, "meta-folder", "", "The folder in which new metadata files will be added, defaulting to a folder based on the category (mods, resourcepacks, etc; if the category is unknown the current directory is used)") + _ = viper.BindPFlag("meta-folder", rootCmd.PersistentFlags().Lookup("meta-folder")) + + var metaFolderBase string + rootCmd.PersistentFlags().StringVar(&metaFolderBase, "meta-folder-base", ".", "The base folder from which meta-folder will be resolved, defaulting to the current directory (so you can put all mods/etc in a subfolder while still using the default behaviour)") + _ = viper.BindPFlag("meta-folder-base", rootCmd.PersistentFlags().Lookup("meta-folder-base")) file, err := core.GetPackwizLocalStore() if err != nil { diff --git a/core/index.go b/core/index.go index 5777271..3095de3 100644 --- a/core/index.go +++ b/core/index.go @@ -150,16 +150,9 @@ func (in *Index) updateFile(path string) error { } mod := false - // If the file has an extension of toml and is in the mods folder, set mod to true - absFileDir, err := filepath.Abs(filepath.Dir(path)) - if err == nil { - modsDir := filepath.Join(in.GetPackRoot(), viper.GetString("mods-folder")) - absModsDir, err := filepath.Abs(modsDir) - if err == nil { - if absFileDir == absModsDir && strings.HasSuffix(filepath.Base(path), ".toml") { - mod = true - } - } + // If the file has an extension of pw.toml, set mod to true + if strings.HasSuffix(filepath.Base(path), MetaExtension) { + mod = true } return in.updateFileHashGiven(path, "sha256", hashString, mod) @@ -341,7 +334,7 @@ func (in Index) FindMod(modName string) (string, bool) { for _, v := range in.Files { if v.MetaFile { _, file := filepath.Split(v.File) - fileTrimmed := strings.TrimSuffix(file, ModExtension) + fileTrimmed := strings.TrimSuffix(file, MetaExtension) if fileTrimmed == modName { return filepath.Join(filepath.Dir(in.indexFile), filepath.FromSlash(v.File)), true } diff --git a/core/mod.go b/core/mod.go index 9afa4e3..73a0274 100644 --- a/core/mod.go +++ b/core/mod.go @@ -72,9 +72,9 @@ func LoadMod(modFile string) (Mod, error) { return mod, nil } -// SetMetaName sets the mod metadata file from a given file name (to be put in the mods folder) -func (m *Mod) SetMetaName(metaName string, index Index) string { - m.metaFile = ResolveMod(metaName, index) +// SetMetaPath sets the file path of a metadata file +func (m *Mod) SetMetaPath(metaFile string) string { + m.metaFile = metaFile return m.metaFile } diff --git a/core/resolve.go b/core/resolve.go index 571d343..19494f5 100644 --- a/core/resolve.go +++ b/core/resolve.go @@ -1,19 +1,5 @@ package core -import ( - "path/filepath" - "strings" - - "github.com/spf13/viper" -) - -// ModExtension is the file extension of the mod metadata files -const ModExtension = ".toml" - -// ResolveMod returns the path to a mod file from it's name -func ResolveMod(modName string, index Index) string { - // TODO: should this work for any metadata file? - fileName := strings.ToLower(strings.TrimSuffix(modName, ModExtension)) + ModExtension - modsDir := filepath.Join(index.GetPackRoot(), viper.GetString("mods-folder")) - return filepath.Join(modsDir, fileName) -} +// MetaExtension is the file extension of the mod metadata files +// Note that this is currently not required; it will only be used for new files. +const MetaExtension = ".pw.toml" diff --git a/curseforge/curseforge.go b/curseforge/curseforge.go index 4843275..7972fef 100644 --- a/curseforge/curseforge.go +++ b/curseforge/curseforge.go @@ -4,6 +4,7 @@ import ( "errors" "github.com/spf13/viper" "golang.org/x/exp/slices" + "path/filepath" "regexp" "strconv" "strings" @@ -136,8 +137,7 @@ func parseSlugOrUrl(url string) (game string, category string, slug string, file return } -// TODO: put projects into folders based on these -var defaultFolders = map[int]map[int]string{ +var defaultFolders = map[uint32]map[uint32]string{ 432: { // Minecraft 5: "plugins", // Bukkit Plugins 12: "resourcepacks", @@ -146,6 +146,21 @@ var defaultFolders = map[int]map[int]string{ }, } +func getPathForFile(gameID uint32, classID uint32, categoryID uint32, slug string) string { + metaFolder := viper.GetString("meta-folder") + if metaFolder == "" { + if m, ok := defaultFolders[gameID]; ok { + if folder, ok := m[classID]; ok { + return filepath.Join(viper.GetString("meta-folder-base"), folder, slug+core.MetaExtension) + } else if folder, ok := m[categoryID]; ok { + return filepath.Join(viper.GetString("meta-folder-base"), folder, slug+core.MetaExtension) + } + } + metaFolder = "." + } + return filepath.Join(viper.GetString("meta-folder-base"), metaFolder, slug+core.MetaExtension) +} + func createModFile(modInfo modInfo, fileInfo modFileInfo, index *core.Index, optionalDisabled bool) error { updateMap := make(map[string]map[string]interface{}) var err error @@ -179,7 +194,7 @@ func createModFile(modInfo modInfo, fileInfo modFileInfo, index *core.Index, opt Option: optional, Update: updateMap, } - path := modMeta.SetMetaName(modInfo.Slug, *index) + path := modMeta.SetMetaPath(getPathForFile(modInfo.GameID, modInfo.ClassID, modInfo.PrimaryCategoryID, modInfo.Slug)) // If the file already exists, this will overwrite it!!! // TODO: Should this be improved? diff --git a/curseforge/import.go b/curseforge/import.go index 8b8bb91..b20ebb1 100644 --- a/curseforge/import.go +++ b/curseforge/import.go @@ -266,8 +266,7 @@ var importCmd = &cobra.Command{ os.Exit(1) } - // TODO: just use mods-folder directly? does texture pack importing affect this? - modFilePath := core.ResolveMod(modInfoValue.Slug, index) + modFilePath := getPathForFile(modInfoValue.GameID, modInfoValue.ClassID, modInfoValue.PrimaryCategoryID, modInfoValue.Slug) ref, err := filepath.Abs(filepath.Join(filepath.Dir(modFilePath), modFileInfoValue.FileName)) if err == nil { referencedModPaths = append(referencedModPaths, ref) diff --git a/curseforge/request.go b/curseforge/request.go index 5154f95..e8a3ba6 100644 --- a/curseforge/request.go +++ b/curseforge/request.go @@ -134,6 +134,9 @@ type modInfo struct { Summary string `json:"summary"` Slug string `json:"slug"` ID int `json:"id"` + GameID uint32 `json:"gameId"` + PrimaryCategoryID uint32 `json:"primaryCategoryId"` + ClassID uint32 `json:"classId"` LatestFiles []modFileInfo `json:"latestFiles"` GameVersionLatestFiles []struct { // TODO: check how twitch launcher chooses which one to use, when you are on beta/alpha channel?! diff --git a/modrinth/install.go b/modrinth/install.go index b405d50..796fdb7 100644 --- a/modrinth/install.go +++ b/modrinth/install.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/viper" "os" + "path/filepath" "regexp" "strings" @@ -207,10 +208,14 @@ func installVersion(mod Mod, version Version, pack core.Pack) error { Update: updateMap, } var path string + folder := viper.GetString("meta-folder") + if folder == "" { + folder = "mods" + } if mod.Slug != "" { - path = modMeta.SetMetaName(mod.Slug, index) + path = modMeta.SetMetaPath(filepath.Join(viper.GetString("meta-folder-base"), folder, mod.Slug+core.MetaExtension)) } else { - path = modMeta.SetMetaName(mod.Title, index) + path = modMeta.SetMetaPath(filepath.Join(viper.GetString("meta-folder-base"), folder, mod.Title+core.MetaExtension)) } // If the file already exists, this will overwrite it!!!