Fix hardcoded install path for game

This commit is contained in:
kayomn 2022-12-21 23:32:30 +00:00
parent 603bc59a88
commit 85a941de81
2 changed files with 229 additions and 181 deletions

160
main.go
View File

@ -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

View File

@ -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