mirror of
				https://github.com/packwiz/packwiz.git
				synced 2025-10-31 02:34:31 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			241 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package cmd
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"fmt"
 | |
| 	"github.com/fatih/camelcase"
 | |
| 	"github.com/igorsobreira/titlecase"
 | |
| 	"github.com/packwiz/packwiz/cmdshared"
 | |
| 	"github.com/packwiz/packwiz/core"
 | |
| 	"github.com/spf13/cobra"
 | |
| 	"github.com/spf13/viper"
 | |
| 	"golang.org/x/exp/slices"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| // initCmd represents the init command
 | |
| var initCmd = &cobra.Command{
 | |
| 	Use:   "init",
 | |
| 	Short: "Initialise a packwiz modpack",
 | |
| 	Args:  cobra.NoArgs,
 | |
| 	Run: func(cmd *cobra.Command, args []string) {
 | |
| 		_, err := os.Stat(viper.GetString("pack-file"))
 | |
| 		if err == nil && !viper.GetBool("init.reinit") {
 | |
| 			fmt.Println("Modpack metadata file already exists, use -r to override!")
 | |
| 			os.Exit(1)
 | |
| 		} else if err != nil && !os.IsNotExist(err) {
 | |
| 			fmt.Printf("Error checking pack file: %s\n", err)
 | |
| 			os.Exit(1)
 | |
| 		}
 | |
| 
 | |
| 		name, err := cmd.Flags().GetString("name")
 | |
| 		if err != nil || len(name) == 0 {
 | |
| 			// Get current file directory name
 | |
| 			wd, err := os.Getwd()
 | |
| 			directoryName := "."
 | |
| 			if err == nil {
 | |
| 				directoryName = filepath.Base(wd)
 | |
| 			}
 | |
| 			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), " "), " - ", " "), " _ ", " "))
 | |
| 				name = initReadValue("Modpack name ["+name+"]: ", name)
 | |
| 			} else {
 | |
| 				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 := cmdshared.GetValidMCVersions()
 | |
| 		if err != nil {
 | |
| 			fmt.Printf("Failed to get latest minecraft versions: %s\n", err)
 | |
| 			os.Exit(1)
 | |
| 		}
 | |
| 
 | |
| 		mcVersion := viper.GetString("init.mc-version")
 | |
| 		if len(mcVersion) == 0 {
 | |
| 			var latestVersion string
 | |
| 			if viper.GetBool("init.snapshot") {
 | |
| 				latestVersion = mcVersions.Latest.Snapshot
 | |
| 			} else {
 | |
| 				latestVersion = mcVersions.Latest.Release
 | |
| 			}
 | |
| 			if viper.GetBool("init.latest") {
 | |
| 				mcVersion = latestVersion
 | |
| 			} else {
 | |
| 				mcVersion = initReadValue("Minecraft version ["+latestVersion+"]: ", latestVersion)
 | |
| 			}
 | |
| 		}
 | |
| 		mcVersions.CheckValid(mcVersion)
 | |
| 
 | |
| 		modLoaderName := strings.ToLower(viper.GetString("init.modloader"))
 | |
| 		if len(modLoaderName) == 0 {
 | |
| 			modLoaderName = strings.ToLower(initReadValue("Mod loader [quilt]: ", "quilt"))
 | |
| 		}
 | |
| 
 | |
| 		loader, ok := core.ModLoaders[modLoaderName]
 | |
| 		modLoaderVersions := make(map[string]string)
 | |
| 		if modLoaderName != "none" {
 | |
| 			if ok {
 | |
| 				versions, latestVersion, err := loader.VersionListGetter(mcVersion)
 | |
| 				if err != nil {
 | |
| 					fmt.Printf("Error loading versions: %s\n", err)
 | |
| 					os.Exit(1)
 | |
| 				}
 | |
| 				componentVersion := viper.GetString("init." + loader.Name + "-version")
 | |
| 				if len(componentVersion) == 0 {
 | |
| 					if viper.GetBool("init." + loader.Name + "-latest") {
 | |
| 						componentVersion = latestVersion
 | |
| 					} else {
 | |
| 						componentVersion = initReadValue(loader.FriendlyName+" version ["+latestVersion+"]: ", latestVersion)
 | |
| 					}
 | |
| 				}
 | |
| 				v := componentVersion
 | |
| 				if loader.Name == "forge" || loader.Name == "neoforge" {
 | |
| 					v = cmdshared.GetRawForgeVersion(componentVersion)
 | |
| 				}
 | |
| 				if !slices.Contains(versions, v) {
 | |
| 					fmt.Println("Given " + loader.FriendlyName + " version cannot be found!")
 | |
| 					os.Exit(1)
 | |
| 				}
 | |
| 				modLoaderVersions[loader.Name] = v
 | |
| 			} else {
 | |
| 				fmt.Println("Given mod loader is not supported! Use \"none\" to specify no modloader, or to configure one manually.")
 | |
| 				fmt.Print("The following mod loaders are supported: ")
 | |
| 				keys := make([]string, len(core.ModLoaders))
 | |
| 				i := 0
 | |
| 				for k := range core.ModLoaders {
 | |
| 					keys[i] = k
 | |
| 					i++
 | |
| 				}
 | |
| 				fmt.Println(strings.Join(keys, ", "))
 | |
| 				os.Exit(1)
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		indexFilePath := viper.GetString("init.index-file")
 | |
| 		_, err = os.Stat(indexFilePath)
 | |
| 		if os.IsNotExist(err) {
 | |
| 			// Create file
 | |
| 			err = os.WriteFile(indexFilePath, []byte{}, 0644)
 | |
| 			if err != nil {
 | |
| 				fmt.Printf("Error creating index file: %s\n", err)
 | |
| 				os.Exit(1)
 | |
| 			}
 | |
| 			fmt.Println(indexFilePath + " created!")
 | |
| 		} else if err != nil {
 | |
| 			fmt.Printf("Error checking index file: %s\n", err)
 | |
| 			os.Exit(1)
 | |
| 		}
 | |
| 
 | |
| 		// Create the pack
 | |
| 		pack := core.Pack{
 | |
| 			Name:       name,
 | |
| 			Author:     author,
 | |
| 			Version:    version,
 | |
| 			PackFormat: core.CurrentPackFormat,
 | |
| 			Index: struct {
 | |
| 				File       string `toml:"file"`
 | |
| 				HashFormat string `toml:"hash-format"`
 | |
| 				Hash       string `toml:"hash,omitempty"`
 | |
| 			}{
 | |
| 				File: indexFilePath,
 | |
| 			},
 | |
| 			Versions: map[string]string{
 | |
| 				"minecraft": mcVersion,
 | |
| 			},
 | |
| 		}
 | |
| 		if modLoaderName != "none" {
 | |
| 			for k, v := range modLoaderVersions {
 | |
| 				pack.Versions[k] = v
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// Refresh the index and pack
 | |
| 		index, err := pack.LoadIndex()
 | |
| 		if err != nil {
 | |
| 			fmt.Println(err)
 | |
| 			os.Exit(1)
 | |
| 		}
 | |
| 		err = index.Refresh()
 | |
| 		if err != nil {
 | |
| 			fmt.Println(err)
 | |
| 			os.Exit(1)
 | |
| 		}
 | |
| 		err = index.Write()
 | |
| 		if err != nil {
 | |
| 			fmt.Println(err)
 | |
| 			os.Exit(1)
 | |
| 		}
 | |
| 		err = pack.UpdateIndexHash()
 | |
| 		if err != nil {
 | |
| 			fmt.Println(err)
 | |
| 			os.Exit(1)
 | |
| 		}
 | |
| 		err = pack.Write()
 | |
| 		if err != nil {
 | |
| 			fmt.Println(err)
 | |
| 			os.Exit(1)
 | |
| 		}
 | |
| 		fmt.Println(viper.GetString("pack-file") + " created!")
 | |
| 	},
 | |
| }
 | |
| 
 | |
| 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)")
 | |
| 	_ = viper.BindPFlag("init.mc-version", initCmd.Flags().Lookup("mc-version"))
 | |
| 	initCmd.Flags().BoolP("latest", "l", false, "Automatically select the latest version of Minecraft")
 | |
| 	_ = viper.BindPFlag("init.latest", initCmd.Flags().Lookup("latest"))
 | |
| 	initCmd.Flags().BoolP("snapshot", "s", false, "Use the latest snapshot version with --latest")
 | |
| 	_ = viper.BindPFlag("init.snapshot", initCmd.Flags().Lookup("snapshot"))
 | |
| 	initCmd.Flags().BoolP("reinit", "r", false, "Recreate the pack file if it already exists, rather than exiting")
 | |
| 	_ = viper.BindPFlag("init.reinit", initCmd.Flags().Lookup("reinit"))
 | |
| 	initCmd.Flags().String("modloader", "", "The mod loader to use (omit to define interactively)")
 | |
| 	_ = viper.BindPFlag("init.modloader", initCmd.Flags().Lookup("modloader"))
 | |
| 
 | |
| 	// ok this is epic
 | |
| 	for _, loader := range core.ModLoaders {
 | |
| 		initCmd.Flags().String(loader.Name+"-version", "", "The "+loader.FriendlyName+" version to use (omit to define interactively)")
 | |
| 		_ = viper.BindPFlag("init."+loader.Name+"-version", initCmd.Flags().Lookup(loader.Name+"-version"))
 | |
| 		initCmd.Flags().Bool(loader.Name+"-latest", false, "Automatically select the latest version of "+loader.FriendlyName)
 | |
| 		_ = viper.BindPFlag("init."+loader.Name+"-latest", initCmd.Flags().Lookup(loader.Name+"-latest"))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func initReadValue(prompt string, def string) string {
 | |
| 	fmt.Print(prompt)
 | |
| 	if viper.GetBool("non-interactive") {
 | |
| 		fmt.Printf("%s\n", def)
 | |
| 		return def
 | |
| 	}
 | |
| 	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
 | |
| }
 |