215 lines
5.4 KiB
Go
Executable File
215 lines
5.4 KiB
Go
Executable File
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"mccl/cmd/mccl/commands"
|
|
mcclprofile "mccl/internal/mccl_profile"
|
|
"os"
|
|
)
|
|
|
|
var programVersion string
|
|
|
|
func main() {
|
|
args, err := parseArguments(os.Args[1:])
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
usage()
|
|
os.Exit(1)
|
|
}
|
|
|
|
if args.ShowVersion {
|
|
version()
|
|
}
|
|
|
|
if args.ShowHelp {
|
|
usage()
|
|
}
|
|
|
|
if args.ShowHelp || args.ShowVersion {
|
|
os.Exit(0)
|
|
}
|
|
|
|
if len(os.Args) < 2 {
|
|
usage()
|
|
os.Exit(1)
|
|
}
|
|
|
|
var cmd commands.Command
|
|
|
|
switch args.Command {
|
|
case "install":
|
|
fallthrough
|
|
case "i":
|
|
cmd = commands.NewInstallCommand(args.GameVersion, args.Directory)
|
|
case "run":
|
|
fallthrough
|
|
case "r":
|
|
cmd = commands.NewRunCommand(args.GameVersion, args.Directory,
|
|
args.Username, args.Uuid, args.JavaXmx, args.UseProfile)
|
|
case "list":
|
|
fallthrough
|
|
case "l":
|
|
cmd = commands.NewListCommand(args.Directory)
|
|
default:
|
|
usage()
|
|
os.Exit(0)
|
|
}
|
|
|
|
exitCode := 0
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
fmt.Println(err)
|
|
exitCode = 1
|
|
}
|
|
|
|
if args.DemandPressEnter {
|
|
fmt.Fprint(os.Stderr, "Press the enter key to continue...")
|
|
fmt.Scanln()
|
|
}
|
|
|
|
os.Exit(exitCode)
|
|
}
|
|
|
|
func version() {
|
|
fmt.Fprintf(os.Stderr, "mccl ver. %s\nCopyright (c) 2023 Alexander \"Arav\" Andreev <me@arav.su>\n", programVersion)
|
|
fmt.Fprintln(os.Stderr, "URL: https://git.arav.su/Arav/mccl")
|
|
fmt.Fprintln(os.Stderr, "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.")
|
|
}
|
|
|
|
func usage() {
|
|
fmt.Fprintln(os.Stderr, "Usage: mccl [<common options>]... command arguments... [options]...")
|
|
fmt.Fprintln(os.Stderr, "Common options:\n"+
|
|
" -h,--help show help\n"+
|
|
" -v,--version show version\n"+
|
|
" --demand-press-enter\n"+
|
|
" ask to press the enter key before closing\n"+
|
|
"Commands:\n"+
|
|
" \033[1minstall|i\033[0m version directory\n"+
|
|
" Install any vanilla version (for mod loaders use theirs installers)\n"+
|
|
" \033[1mrun|r\033[0m version directory [-u username] [-U UUID] [-java-Xmx memory] [--profile]\n"+
|
|
" Run vanilla, forge, fabric, quilt, the others aren't tested\n"+
|
|
" \033[1mlist|l\033[0m directory\n"+
|
|
" List all installed versions in directory\n"+
|
|
"Explanation of arguments and options for commands:\n"+
|
|
" version version of a game (name of a dir inside versions dir)\n"+
|
|
" directory a path to where Minecraft will be installed / or will be runned from\n"+
|
|
" -u,--username username\n"+
|
|
" player's username (Anonymous by default)\n"+
|
|
" -U,--uuid UUID\n"+
|
|
" player's account UUID (all zeroes by default)\n"+
|
|
" --java-Xmx memory\n"+
|
|
" java's -Xmx param, e.g. 4G\n"+
|
|
" --profile\n"+
|
|
" load/save username, UUID, and -Xmx from/to a file.\n"+
|
|
" Once saved, you can ommit -u,-U and --java-Xmx,\n"+
|
|
" since they will be stored in", mcclprofile.ProfileFileName)
|
|
}
|
|
|
|
type arguments struct {
|
|
ShowVersion bool
|
|
ShowHelp bool
|
|
DemandPressEnter bool
|
|
|
|
Command string
|
|
GameVersion string
|
|
Directory string
|
|
Username string
|
|
Uuid string
|
|
JavaXmx string
|
|
|
|
UseProfile bool
|
|
}
|
|
|
|
type errNoOptArg struct {
|
|
ArgName string
|
|
}
|
|
|
|
func (e errNoOptArg) Error() string {
|
|
return fmt.Sprintf("%s option demands an argument, but it wasn't provided", e.ArgName)
|
|
}
|
|
|
|
func parseArguments(args []string) (parsed arguments, err error) {
|
|
parsed.Username = "Anonymous"
|
|
parsed.Directory = "."
|
|
parsed.Uuid = "00000000-0000-0000-0000-000000000000"
|
|
|
|
for i := 0; i < len(args); i++ {
|
|
if args[i][0] != '-' {
|
|
if parsed.Command != "" {
|
|
return parsed, fmt.Errorf("there is already a command %s, but a second one (%s) was provided",
|
|
parsed.Command, args[i])
|
|
}
|
|
parsed.Command = args[i]
|
|
switch parsed.Command {
|
|
case "i":
|
|
fallthrough
|
|
case "install":
|
|
fallthrough
|
|
case "r":
|
|
fallthrough
|
|
case "run":
|
|
if i+3 > len(args) || args[i+1][0] == '-' {
|
|
return parsed, fmt.Errorf("a command %s is missing its version and directory arguments",
|
|
parsed.Command)
|
|
}
|
|
parsed.GameVersion = args[i+1]
|
|
parsed.Directory = args[i+2]
|
|
i += 2
|
|
case "l":
|
|
fallthrough
|
|
case "list":
|
|
if i+1 >= len(args) || args[i+1][0] == '-' {
|
|
return parsed, fmt.Errorf("a command list is missing its directory argument")
|
|
}
|
|
parsed.Directory = args[i+1]
|
|
i++
|
|
}
|
|
continue
|
|
}
|
|
|
|
switch args[i] {
|
|
case "-v":
|
|
fallthrough
|
|
case "--version":
|
|
parsed.ShowVersion = true
|
|
case "-h":
|
|
fallthrough
|
|
case "--help":
|
|
parsed.ShowHelp = true
|
|
case "--demand-press-enter":
|
|
parsed.DemandPressEnter = true
|
|
case "-u":
|
|
fallthrough
|
|
case "--username":
|
|
if len(args) == i+1 || args[i+1][0] == '-' {
|
|
err = errNoOptArg{ArgName: args[i]}
|
|
return
|
|
}
|
|
parsed.Username = args[i+1]
|
|
i++
|
|
case "-U":
|
|
fallthrough
|
|
case "--uuid":
|
|
if len(args) == i+1 || args[i+1][0] == '-' {
|
|
err = errNoOptArg{ArgName: args[i]}
|
|
return
|
|
}
|
|
parsed.Uuid = args[i+1]
|
|
i++
|
|
case "--java-Xmx":
|
|
if len(args) == i+1 || args[i+1][0] == '-' {
|
|
err = errNoOptArg{ArgName: args[i]}
|
|
return
|
|
}
|
|
parsed.JavaXmx = args[i+1]
|
|
i++
|
|
case "--profile":
|
|
parsed.UseProfile = true
|
|
default:
|
|
err = fmt.Errorf("an unknown option %s was provided", args[i])
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|