Fix hardcoded install path for game
This commit is contained in:
parent
603bc59a88
commit
85a941de81
160
main.go
160
main.go
|
@ -34,16 +34,22 @@ var commands = []Command{
|
||||||
requiredArguments[0], requiredArguments[1])
|
requiredArguments[0], requiredArguments[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
if gameError := WithGame(providedArguments[0], func(game *Game) error {
|
var game, gameOpenError = OpenGame(providedArguments[0])
|
||||||
for _, archivePath := range providedArguments[1:] {
|
|
||||||
if installError := game.InstallMod(archivePath); installError != nil {
|
|
||||||
return installError
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
if gameOpenError != nil {
|
||||||
}); gameError != nil {
|
return "", gameOpenError
|
||||||
return "", gameError
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if closeError := game.Close(); closeError != nil {
|
||||||
|
panic(closeError)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for _, archivePath := range providedArguments[1:] {
|
||||||
|
if installError := game.InstallMod(archivePath); installError != nil {
|
||||||
|
return "", installError
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "mods installed", nil
|
return "mods installed", nil
|
||||||
|
@ -62,10 +68,20 @@ var commands = []Command{
|
||||||
requiredArguments[0], requiredArguments[1])
|
requiredArguments[0], requiredArguments[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
if gameError := WithGame(providedArguments[0], func(game *Game) error {
|
var game, gameOpenError = OpenGame(providedArguments[0])
|
||||||
return game.RemoveMods(providedArguments[1:])
|
|
||||||
}); gameError != nil {
|
if gameOpenError != nil {
|
||||||
return "", gameError
|
return "", gameOpenError
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if closeError := game.Close(); closeError != nil {
|
||||||
|
panic(closeError)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if removeModsError := game.RemoveMods(providedArguments[1:]); removeModsError != nil {
|
||||||
|
return "", removeModsError
|
||||||
}
|
}
|
||||||
|
|
||||||
return "removed mods", nil
|
return "removed mods", nil
|
||||||
|
@ -84,19 +100,25 @@ var commands = []Command{
|
||||||
requiredArguments[0], requiredArguments[1], requiredArguments[2])
|
requiredArguments[0], requiredArguments[1], requiredArguments[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
if gameError := WithGame(providedArguments[0], func(game *Game) error {
|
var game, gameOpenError = OpenGame(providedArguments[0])
|
||||||
if removeError := game.RenameMod(providedArguments[1],
|
|
||||||
providedArguments[2]); removeError != nil {
|
|
||||||
|
|
||||||
return removeError
|
if gameOpenError != nil {
|
||||||
}
|
return "", gameOpenError
|
||||||
|
|
||||||
return nil
|
|
||||||
}); gameError != nil {
|
|
||||||
return "", gameError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", nil
|
defer func() {
|
||||||
|
if closeError := game.Close(); closeError != nil {
|
||||||
|
panic(closeError)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if renameError := game.RenameMod(
|
||||||
|
providedArguments[1], providedArguments[2]); renameError != nil {
|
||||||
|
|
||||||
|
return "", renameError
|
||||||
|
}
|
||||||
|
|
||||||
|
return "renamed", nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -112,30 +134,32 @@ var commands = []Command{
|
||||||
requiredArguments[0], requiredArguments[1])
|
requiredArguments[0], requiredArguments[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
var modManifest = ""
|
var game, gameOpenError = OpenGame(providedArguments[0])
|
||||||
|
|
||||||
if gameError := WithGame(providedArguments[0], func(game *Game) error {
|
if gameOpenError != nil {
|
||||||
var format = providedArguments[1]
|
return "", gameOpenError
|
||||||
var formatter, formatterExists = formatters[format]
|
|
||||||
|
|
||||||
if !(formatterExists) {
|
|
||||||
return fmt.Errorf("unsupported format: `%s`", format)
|
|
||||||
}
|
|
||||||
|
|
||||||
var manifestBuilder = strings.Builder{}
|
|
||||||
|
|
||||||
if formatError := formatter(&manifestBuilder, game.Mods); formatError != nil {
|
|
||||||
return formatError
|
|
||||||
}
|
|
||||||
|
|
||||||
modManifest = manifestBuilder.String()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}); gameError != nil {
|
|
||||||
return "", gameError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return modManifest, nil
|
defer func() {
|
||||||
|
if closeError := game.Close(); closeError != nil {
|
||||||
|
panic(closeError)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var format = providedArguments[1]
|
||||||
|
var formatter, formatterExists = formatters[format]
|
||||||
|
|
||||||
|
if !(formatterExists) {
|
||||||
|
return "", fmt.Errorf("unsupported format: `%s`", format)
|
||||||
|
}
|
||||||
|
|
||||||
|
var manifestBuilder = strings.Builder{}
|
||||||
|
|
||||||
|
if formatError := formatter(&manifestBuilder, game.Mods); formatError != nil {
|
||||||
|
return "", formatError
|
||||||
|
}
|
||||||
|
|
||||||
|
return manifestBuilder.String(), nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -151,20 +175,26 @@ var commands = []Command{
|
||||||
requiredArguments[0], requiredArguments[1])
|
requiredArguments[0], requiredArguments[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
if gameError := WithGame(arguments[0], func(game *Game) error {
|
var game, gameOpenError = OpenGame(arguments[0])
|
||||||
if cleanError := game.CleanDeployedMods(); cleanError != nil {
|
|
||||||
return cleanError
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, modName := range arguments[1:] {
|
if gameOpenError != nil {
|
||||||
if deployError := game.DeployMod(modName); deployError != nil {
|
return "", gameOpenError
|
||||||
return deployError
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
defer func() {
|
||||||
}); gameError != nil {
|
if closeError := game.Close(); closeError != nil {
|
||||||
return "", gameError
|
panic(closeError)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if cleanError := game.CleanDeployedMods(); cleanError != nil {
|
||||||
|
return "", cleanError
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, modName := range arguments[1:] {
|
||||||
|
if deployError := game.DeployMod(modName); deployError != nil {
|
||||||
|
return "", deployError
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "deployed", nil
|
return "deployed", nil
|
||||||
|
@ -182,10 +212,20 @@ var commands = []Command{
|
||||||
return "", fmt.Errorf("expected %s", requiredArguments[0])
|
return "", fmt.Errorf("expected %s", requiredArguments[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if gameError := WithGame(arguments[0], func(game *Game) error {
|
var game, gameOpenError = OpenGame(arguments[0])
|
||||||
return game.CleanDeployedMods()
|
|
||||||
}); gameError != nil {
|
if gameOpenError != nil {
|
||||||
return "", gameError
|
return "", gameOpenError
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if closeError := game.Close(); closeError != nil {
|
||||||
|
panic(closeError)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if cleanDeployedModsError := game.CleanDeployedMods(); cleanDeployedModsError != nil {
|
||||||
|
return "", cleanDeployedModsError
|
||||||
}
|
}
|
||||||
|
|
||||||
return "cleaned", nil
|
return "cleaned", nil
|
||||||
|
|
250
manager.go
250
manager.go
|
@ -47,6 +47,92 @@ func (game *Game) CleanDeployedMods() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (game *Game) Close() error {
|
||||||
|
// Write deployed files to disk.
|
||||||
|
var deployedListPath, deployedListPathError = game.cachePath("deployed.txt")
|
||||||
|
|
||||||
|
if deployedListPathError != nil {
|
||||||
|
return deployedListPathError
|
||||||
|
}
|
||||||
|
|
||||||
|
var deployedListFile, deployedListCreateError = os.Create(deployedListPath)
|
||||||
|
|
||||||
|
if deployedListCreateError != nil {
|
||||||
|
return deployedListCreateError
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if syncError := deployedListFile.Sync(); syncError != nil {
|
||||||
|
panic(syncError)
|
||||||
|
}
|
||||||
|
|
||||||
|
if closeError := deployedListFile.Close(); closeError != nil {
|
||||||
|
panic(closeError)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var deployedListWriter = bufio.NewWriter(deployedListFile)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if flushError := deployedListWriter.Flush(); flushError != nil {
|
||||||
|
panic(flushError)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for _, filePath := range game.DeployedFilePaths {
|
||||||
|
if _, writeError := deployedListWriter.WriteString(filePath); writeError != nil {
|
||||||
|
return writeError
|
||||||
|
}
|
||||||
|
|
||||||
|
if writeError := deployedListWriter.WriteByte('\n'); writeError != nil {
|
||||||
|
return writeError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read mod info from disk.
|
||||||
|
var modInfoPath, modInfoPathError = game.configPath("mods.ini")
|
||||||
|
|
||||||
|
if modInfoPathError != nil {
|
||||||
|
return modInfoPathError
|
||||||
|
}
|
||||||
|
|
||||||
|
var modInfoFile, modInfoCreateError = os.Create(modInfoPath)
|
||||||
|
|
||||||
|
if modInfoCreateError != nil {
|
||||||
|
return modInfoCreateError
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if closeError := modInfoFile.Close(); closeError != nil {
|
||||||
|
panic(closeError)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var modInfoEntries = make([]ini.Entry, 0, len(game.Mods)*3)
|
||||||
|
|
||||||
|
for name, mod := range game.Mods {
|
||||||
|
modInfoEntries = append(modInfoEntries, ini.Entry{
|
||||||
|
Section: name,
|
||||||
|
Key: "source",
|
||||||
|
Value: mod.Source,
|
||||||
|
})
|
||||||
|
|
||||||
|
modInfoEntries = append(modInfoEntries, ini.Entry{
|
||||||
|
Section: name,
|
||||||
|
Key: "format",
|
||||||
|
Value: mod.Format,
|
||||||
|
})
|
||||||
|
|
||||||
|
modInfoEntries = append(modInfoEntries, ini.Entry{
|
||||||
|
Section: name,
|
||||||
|
Key: "version",
|
||||||
|
Value: mod.Version,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return ini.Write(modInfoFile, modInfoEntries)
|
||||||
|
}
|
||||||
|
|
||||||
func (game *Game) DeployMod(name string) error {
|
func (game *Game) DeployMod(name string) error {
|
||||||
var mod, exists = game.Mods[name]
|
var mod, exists = game.Mods[name]
|
||||||
|
|
||||||
|
@ -154,7 +240,7 @@ func (game *Game) DeployMod(name string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Game struct {
|
type Game struct {
|
||||||
ID string
|
Name string
|
||||||
DeployedFilePaths []string
|
DeployedFilePaths []string
|
||||||
OverwrittenFilePaths []string
|
OverwrittenFilePaths []string
|
||||||
Mods map[string]Mod
|
Mods map[string]Mod
|
||||||
|
@ -313,6 +399,46 @@ type Mod struct {
|
||||||
Version string
|
Version string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OpenGame(name string) (Game, error) {
|
||||||
|
var configPath, configPathError = os.UserConfigDir()
|
||||||
|
|
||||||
|
if configPathError != nil {
|
||||||
|
return Game{}, configPathError
|
||||||
|
}
|
||||||
|
|
||||||
|
var gamesFile, gamesOpenError = os.Open(filepath.Join(configPath, "modman", "games.ini"))
|
||||||
|
|
||||||
|
if gamesOpenError != nil {
|
||||||
|
if os.IsNotExist(gamesOpenError) {
|
||||||
|
return Game{}, fmt.Errorf("no games registered")
|
||||||
|
}
|
||||||
|
|
||||||
|
return Game{}, gamesOpenError
|
||||||
|
}
|
||||||
|
|
||||||
|
var gamesParser = ini.NewParser(gamesFile)
|
||||||
|
|
||||||
|
for entry := gamesParser.Parse(); !(gamesParser.IsEnd()); entry = gamesParser.Parse() {
|
||||||
|
if (entry.Key == "path") && (entry.Section == name) {
|
||||||
|
var game = Game{
|
||||||
|
Name: name,
|
||||||
|
OverwrittenFilePaths: make([]string, 0, 512),
|
||||||
|
DeployedFilePaths: make([]string, 0, 512),
|
||||||
|
Mods: make(map[string]Mod),
|
||||||
|
Path: "/home/kayomn/.steam/steam/steamapps/common/Fallout 4/Data",
|
||||||
|
}
|
||||||
|
|
||||||
|
if loadError := game.Load(); loadError != nil {
|
||||||
|
return Game{}, loadError
|
||||||
|
}
|
||||||
|
|
||||||
|
return game, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Game{}, fmt.Errorf("game not registered: %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
func (game *Game) RemoveMods(names []string) error {
|
func (game *Game) RemoveMods(names []string) error {
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
if _, exists := game.Mods[name]; !(exists) {
|
if _, exists := game.Mods[name]; !(exists) {
|
||||||
|
@ -369,124 +495,6 @@ func (game *Game) RenameMod(modName string, newName string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (game *Game) Save() error {
|
|
||||||
// Write deployed files to disk.
|
|
||||||
var deployedListPath, deployedListPathError = game.cachePath("deployed.txt")
|
|
||||||
|
|
||||||
if deployedListPathError != nil {
|
|
||||||
return deployedListPathError
|
|
||||||
}
|
|
||||||
|
|
||||||
var deployedListFile, deployedListCreateError = os.Create(deployedListPath)
|
|
||||||
|
|
||||||
if deployedListCreateError != nil {
|
|
||||||
return deployedListCreateError
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if syncError := deployedListFile.Sync(); syncError != nil {
|
|
||||||
panic(syncError)
|
|
||||||
}
|
|
||||||
|
|
||||||
if closeError := deployedListFile.Close(); closeError != nil {
|
|
||||||
panic(closeError)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var deployedListWriter = bufio.NewWriter(deployedListFile)
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if flushError := deployedListWriter.Flush(); flushError != nil {
|
|
||||||
panic(flushError)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
for _, filePath := range game.DeployedFilePaths {
|
|
||||||
if _, writeError := deployedListWriter.WriteString(filePath); writeError != nil {
|
|
||||||
return writeError
|
|
||||||
}
|
|
||||||
|
|
||||||
if writeError := deployedListWriter.WriteByte('\n'); writeError != nil {
|
|
||||||
return writeError
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read mod info from disk.
|
|
||||||
var modInfoPath, modInfoPathError = game.configPath("mods.ini")
|
|
||||||
|
|
||||||
if modInfoPathError != nil {
|
|
||||||
return modInfoPathError
|
|
||||||
}
|
|
||||||
|
|
||||||
var modInfoFile, modInfoCreateError = os.Create(modInfoPath)
|
|
||||||
|
|
||||||
if modInfoCreateError != nil {
|
|
||||||
return modInfoCreateError
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if closeError := modInfoFile.Close(); closeError != nil {
|
|
||||||
panic(closeError)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var modInfoEntries = make([]ini.Entry, 0, len(game.Mods)*3)
|
|
||||||
|
|
||||||
for name, mod := range game.Mods {
|
|
||||||
modInfoEntries = append(modInfoEntries, ini.Entry{
|
|
||||||
Section: name,
|
|
||||||
Key: "source",
|
|
||||||
Value: mod.Source,
|
|
||||||
})
|
|
||||||
|
|
||||||
modInfoEntries = append(modInfoEntries, ini.Entry{
|
|
||||||
Section: name,
|
|
||||||
Key: "format",
|
|
||||||
Value: mod.Format,
|
|
||||||
})
|
|
||||||
|
|
||||||
modInfoEntries = append(modInfoEntries, ini.Entry{
|
|
||||||
Section: name,
|
|
||||||
Key: "version",
|
|
||||||
Value: mod.Version,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return ini.Write(modInfoFile, modInfoEntries)
|
|
||||||
}
|
|
||||||
|
|
||||||
func WithGame(gameName string, action func(*Game) error) error {
|
|
||||||
var supportedGames = []string{"fallout4", "falloutnv", "skyrim"}
|
|
||||||
|
|
||||||
for _, supportedGame := range supportedGames {
|
|
||||||
if gameName == supportedGame {
|
|
||||||
var game = Game{
|
|
||||||
ID: supportedGame,
|
|
||||||
OverwrittenFilePaths: make([]string, 0, 512),
|
|
||||||
DeployedFilePaths: make([]string, 0, 512),
|
|
||||||
Mods: make(map[string]Mod),
|
|
||||||
Path: "/home/kayomn/.steam/steam/steamapps/common/Fallout 4/Data",
|
|
||||||
}
|
|
||||||
|
|
||||||
if loadError := game.Load(); loadError != nil {
|
|
||||||
return loadError
|
|
||||||
}
|
|
||||||
|
|
||||||
if actionError := action(&game); actionError != nil {
|
|
||||||
return actionError
|
|
||||||
}
|
|
||||||
|
|
||||||
if saveError := game.Save(); saveError != nil {
|
|
||||||
return saveError
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Errorf("%s: game not supported", gameName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (game *Game) cachePath(path string) (string, error) {
|
func (game *Game) cachePath(path string) (string, error) {
|
||||||
var dirPath, pathError = os.UserCacheDir()
|
var dirPath, pathError = os.UserCacheDir()
|
||||||
|
|
||||||
|
@ -494,7 +502,7 @@ func (game *Game) cachePath(path string) (string, error) {
|
||||||
return "", pathError
|
return "", pathError
|
||||||
}
|
}
|
||||||
|
|
||||||
dirPath = filepath.Join(dirPath, "modman", game.ID)
|
dirPath = filepath.Join(dirPath, "modman", game.Name)
|
||||||
|
|
||||||
if mkdirError := os.MkdirAll(dirPath, 0755); mkdirError != nil {
|
if mkdirError := os.MkdirAll(dirPath, 0755); mkdirError != nil {
|
||||||
return "", mkdirError
|
return "", mkdirError
|
||||||
|
@ -510,7 +518,7 @@ func (game *Game) configPath(path string) (string, error) {
|
||||||
return "", pathError
|
return "", pathError
|
||||||
}
|
}
|
||||||
|
|
||||||
dirPath = filepath.Join(dirPath, "modman", game.ID)
|
dirPath = filepath.Join(dirPath, "modman", game.Name)
|
||||||
|
|
||||||
if mkdirError := os.MkdirAll(dirPath, 0755); mkdirError != nil {
|
if mkdirError := os.MkdirAll(dirPath, 0755); mkdirError != nil {
|
||||||
return "", mkdirError
|
return "", mkdirError
|
||||||
|
|
Loading…
Reference in New Issue