From 2ab5bc92a8d5fb70fd5d12b5ec5f075540e11de7 Mon Sep 17 00:00:00 2001 From: mircearoata Date: Mon, 15 Apr 2024 18:45:02 +0200 Subject: [PATCH] Convert install finders tracking to self register --- backend/installfinders/common/wine_unix.go | 14 ++++ backend/installfinders/findinstalls.go | 13 ++- backend/installfinders/launchers/all/all.go | 9 ++ .../installfinders/launchers/all_darwin.go | 16 ---- backend/installfinders/launchers/all_linux.go | 18 ---- .../installfinders/launchers/all_windows.go | 18 ---- .../launchers/crossover/crossover_darwin.go | 13 +-- .../launchers/crossover/crossover_noop.go | 1 + backend/installfinders/launchers/epic/epic.go | 2 +- .../launchers/epic/epic_windows.go | 27 +++--- .../{epic_wine_linux.go => epic_wine_unix.go} | 7 +- .../launchers/heroic/heroic_darwin.go | 9 -- .../launchers/heroic/heroic_flatpak_linux.go | 22 +++++ .../launchers/heroic/heroic_linux.go | 67 --------------- .../launchers/heroic/heroic_native_all.go | 12 +++ .../launchers/heroic/heroic_snap_linux.go | 61 ++++++++++++++ .../launchers/heroic/heroic_windows.go | 9 -- .../launchers/legendary/legendary_all.go | 15 ++-- .../launchers/lutris/lutris_linux.go | 18 ++-- .../launchers/lutris/lutris_noop.go | 1 + backend/installfinders/launchers/registry.go | 19 +++++ .../installfinders/launchers/steam/steam.go | 4 +- .../launchers/steam/steam_flatpak_linux.go | 37 ++++++++ .../launchers/steam/steam_linux.go | 84 ------------------- .../launchers/steam/steam_native_unix.go | 38 +++++++++ .../launchers/steam/steam_snap_linux.go | 36 ++++++++ .../launchers/steam/steam_windows.go | 45 ++++++---- go.mod | 2 +- 28 files changed, 336 insertions(+), 281 deletions(-) create mode 100644 backend/installfinders/common/wine_unix.go create mode 100644 backend/installfinders/launchers/all/all.go delete mode 100644 backend/installfinders/launchers/all_darwin.go delete mode 100644 backend/installfinders/launchers/all_linux.go delete mode 100644 backend/installfinders/launchers/all_windows.go create mode 100644 backend/installfinders/launchers/crossover/crossover_noop.go rename backend/installfinders/launchers/epic/{epic_wine_linux.go => epic_wine_unix.go} (78%) delete mode 100644 backend/installfinders/launchers/heroic/heroic_darwin.go create mode 100644 backend/installfinders/launchers/heroic/heroic_flatpak_linux.go delete mode 100644 backend/installfinders/launchers/heroic/heroic_linux.go create mode 100644 backend/installfinders/launchers/heroic/heroic_native_all.go create mode 100644 backend/installfinders/launchers/heroic/heroic_snap_linux.go delete mode 100644 backend/installfinders/launchers/heroic/heroic_windows.go create mode 100644 backend/installfinders/launchers/lutris/lutris_noop.go create mode 100644 backend/installfinders/launchers/registry.go create mode 100644 backend/installfinders/launchers/steam/steam_flatpak_linux.go delete mode 100644 backend/installfinders/launchers/steam/steam_linux.go create mode 100644 backend/installfinders/launchers/steam/steam_native_unix.go create mode 100644 backend/installfinders/launchers/steam/steam_snap_linux.go diff --git a/backend/installfinders/common/wine_unix.go b/backend/installfinders/common/wine_unix.go new file mode 100644 index 00000000..780b850e --- /dev/null +++ b/backend/installfinders/common/wine_unix.go @@ -0,0 +1,14 @@ +//go:build unix + +package common + +import ( + "path/filepath" + "strings" +) + +func WinePathProcessor(winePrefix string) func(string) string { + return func(path string) string { + return filepath.Join(winePrefix, "dosdevices", strings.ToLower(path[0:1])+strings.ReplaceAll(path[1:], "\\", "/")) + } +} diff --git a/backend/installfinders/findinstalls.go b/backend/installfinders/findinstalls.go index 74d8180b..dadbe32a 100644 --- a/backend/installfinders/findinstalls.go +++ b/backend/installfinders/findinstalls.go @@ -1,10 +1,21 @@ package installfinders import ( + "log/slog" + "strings" + + "golang.org/x/exp/maps" + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers" + + _ "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/all" // register all launchers ) func FindInstallations() ([]*common.Installation, []error) { - return common.FindAll(launchers.GetInstallFinders()...) + registrations := launchers.GetInstallFinders() + + slog.Debug("finding installations", slog.String("launchers", strings.Join(maps.Keys(registrations), ","))) + + return common.FindAll(maps.Values(registrations)...) } diff --git a/backend/installfinders/launchers/all/all.go b/backend/installfinders/launchers/all/all.go new file mode 100644 index 00000000..a3e2403e --- /dev/null +++ b/backend/installfinders/launchers/all/all.go @@ -0,0 +1,9 @@ +package all + +import ( + _ "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/crossover" // register crossover + _ "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/epic" // register epic + _ "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/heroic" // register heroic + _ "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/legendary" // register legendary + _ "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/steam" // register steam +) diff --git a/backend/installfinders/launchers/all_darwin.go b/backend/installfinders/launchers/all_darwin.go deleted file mode 100644 index 8b968c5e..00000000 --- a/backend/installfinders/launchers/all_darwin.go +++ /dev/null @@ -1,16 +0,0 @@ -package launchers - -import ( - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/crossover" - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/heroic" - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/legendary" -) - -func GetInstallFinders() []common.InstallFinderFunc { - return []common.InstallFinderFunc{ - heroic.FindInstallations, - legendary.FindInstallations, - crossover.FindInstallations, - } -} diff --git a/backend/installfinders/launchers/all_linux.go b/backend/installfinders/launchers/all_linux.go deleted file mode 100644 index 6f21b51b..00000000 --- a/backend/installfinders/launchers/all_linux.go +++ /dev/null @@ -1,18 +0,0 @@ -package launchers - -import ( - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/heroic" - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/legendary" - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/lutris" - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/steam" -) - -func GetInstallFinders() []common.InstallFinderFunc { - return []common.InstallFinderFunc{ - heroic.FindInstallations, - legendary.FindInstallations, - lutris.FindInstallations, - steam.FindInstallations, - } -} diff --git a/backend/installfinders/launchers/all_windows.go b/backend/installfinders/launchers/all_windows.go deleted file mode 100644 index 878db9cb..00000000 --- a/backend/installfinders/launchers/all_windows.go +++ /dev/null @@ -1,18 +0,0 @@ -package launchers - -import ( - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/epic" - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/heroic" - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/legendary" - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/steam" -) - -func GetInstallFinders() []common.InstallFinderFunc { - return []common.InstallFinderFunc{ - epic.FindInstallations, - heroic.FindInstallations, - legendary.FindInstallations, - steam.FindInstallations, - } -} diff --git a/backend/installfinders/launchers/crossover/crossover_darwin.go b/backend/installfinders/launchers/crossover/crossover_darwin.go index 4edc6a3b..bcf5b59d 100644 --- a/backend/installfinders/launchers/crossover/crossover_darwin.go +++ b/backend/installfinders/launchers/crossover/crossover_darwin.go @@ -5,9 +5,9 @@ import ( "log/slog" "os" "path/filepath" - "strings" "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers" "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/steam" ) @@ -16,7 +16,11 @@ var ( crossoverSteamPath = filepath.Join("c:", "Program Files (x86)", "Steam") // Will get run through processPath, so it will be added to the dosdevices path ) -func FindInstallations() ([]*common.Installation, []error) { +func init() { + launchers.Add("CrossOver", crossover) +} + +func crossover() ([]*common.Installation, []error) { homeDir, err := os.UserHomeDir() if err != nil { return nil, []error{fmt.Errorf("failed to get user home dir: %w", err)} @@ -37,10 +41,7 @@ func FindInstallations() ([]*common.Installation, []error) { continue } bottleRoot := filepath.Join(bottlesPath, bottle.Name()) - - processPath := func(path string) string { - return filepath.Join(bottleRoot, "dosdevices", strings.ToLower(path[0:1])+strings.ReplaceAll(path[1:], "\\", "/")) - } + processPath := common.WinePathProcessor(bottleRoot) if _, err := os.Stat(processPath(crossoverSteamPath)); os.IsNotExist(err) { slog.Debug("Skipping bottle without Steam", slog.String("bottle", bottle.Name())) diff --git a/backend/installfinders/launchers/crossover/crossover_noop.go b/backend/installfinders/launchers/crossover/crossover_noop.go new file mode 100644 index 00000000..573ea5ed --- /dev/null +++ b/backend/installfinders/launchers/crossover/crossover_noop.go @@ -0,0 +1 @@ +package crossover diff --git a/backend/installfinders/launchers/epic/epic.go b/backend/installfinders/launchers/epic/epic.go index 99b50dca..2989306f 100644 --- a/backend/installfinders/launchers/epic/epic.go +++ b/backend/installfinders/launchers/epic/epic.go @@ -57,7 +57,7 @@ func FindInstallationsEpic(epicManifestsPath string, launcher string, launchPath } if _, err := os.Stat(epicManifestsPath); os.IsNotExist(err) { - return nil, []error{fmt.Errorf("Epic is not installed")} + return nil, []error{fmt.Errorf("epic is not installed")} } manifests, err := os.ReadDir(epicManifestsPath) diff --git a/backend/installfinders/launchers/epic/epic_windows.go b/backend/installfinders/launchers/epic/epic_windows.go index ddd40f8e..6c46e6d0 100644 --- a/backend/installfinders/launchers/epic/epic_windows.go +++ b/backend/installfinders/launchers/epic/epic_windows.go @@ -5,20 +5,23 @@ import ( "path/filepath" "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers" ) var epicManifestsFolder = filepath.Join(os.Getenv("PROGRAMDATA"), "Epic", "EpicGamesLauncher", "Data", "Manifests") -func FindInstallations() ([]*common.Installation, []error) { - return FindInstallationsEpic(epicManifestsFolder, "Epic Games", func(appName string) []string { - return []string{ - "cmd", - "/C", - `start`, - ``, - // The extra space at the end is required for exec to escape the argument with double quotes - // Otherwise, the & is interpreted as a command sequence - `com.epicgames.launcher://apps/` + appName + `?action=launch&silent=true `, - } - }, nil) +func init() { + launchers.Add("EpicGames", func() ([]*common.Installation, []error) { + return FindInstallationsEpic(epicManifestsFolder, "Epic Games", func(appName string) []string { + return []string{ + "cmd", + "/C", + `start`, + ``, + // The extra space at the end is required for exec to escape the argument with double quotes + // Otherwise, the & is interpreted as a command sequence + `com.epicgames.launcher://apps/` + appName + `?action=launch&silent=true `, + } + }, nil) + }) } diff --git a/backend/installfinders/launchers/epic/epic_wine_linux.go b/backend/installfinders/launchers/epic/epic_wine_unix.go similarity index 78% rename from backend/installfinders/launchers/epic/epic_wine_linux.go rename to backend/installfinders/launchers/epic/epic_wine_unix.go index 09ec595e..645248d6 100644 --- a/backend/installfinders/launchers/epic/epic_wine_linux.go +++ b/backend/installfinders/launchers/epic/epic_wine_unix.go @@ -1,10 +1,11 @@ +//go:build unix + package epic import ( "fmt" "os" "path/filepath" - "strings" "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" ) @@ -19,7 +20,5 @@ func FindInstallationsWine(winePrefix string, launcher string, launchPath []stri return nil, []error{fmt.Errorf("Epic is not installed in " + winePrefix)} } - return FindInstallationsEpic(epicManifestsPath, launcher, func(appName string) []string { return launchPath }, func(path string) string { - return filepath.Join(wineWindowsRoot, strings.ToLower(path[0:1])+strings.ReplaceAll(path[1:], "\\", "/")) - }) + return FindInstallationsEpic(epicManifestsPath, launcher, func(appName string) []string { return launchPath }, common.WinePathProcessor(winePrefix)) } diff --git a/backend/installfinders/launchers/heroic/heroic_darwin.go b/backend/installfinders/launchers/heroic/heroic_darwin.go deleted file mode 100644 index a7cfcfc2..00000000 --- a/backend/installfinders/launchers/heroic/heroic_darwin.go +++ /dev/null @@ -1,9 +0,0 @@ -package heroic - -import ( - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" -) - -func FindInstallations() ([]*common.Installation, []error) { - return findInstallationsHeroic(false, "", "Heroic") -} diff --git a/backend/installfinders/launchers/heroic/heroic_flatpak_linux.go b/backend/installfinders/launchers/heroic/heroic_flatpak_linux.go new file mode 100644 index 00000000..e0aa9eeb --- /dev/null +++ b/backend/installfinders/launchers/heroic/heroic_flatpak_linux.go @@ -0,0 +1,22 @@ +package heroic + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers" +) + +func init() { + launchers.Add("Heroic-flatpak", func() ([]*common.Installation, []error) { + homeDir, err := os.UserHomeDir() + if err != nil { + return nil, []error{fmt.Errorf("failed to get user home dir: %w", err)} + } + flatpakXdgConfigHome := filepath.Join(homeDir, ".var", "app", "com.heroicgameslauncher.hgl", "config") + + return findInstallationsHeroic(false, flatpakXdgConfigHome, "Heroic") + }) +} diff --git a/backend/installfinders/launchers/heroic/heroic_linux.go b/backend/installfinders/launchers/heroic/heroic_linux.go deleted file mode 100644 index 82d041db..00000000 --- a/backend/installfinders/launchers/heroic/heroic_linux.go +++ /dev/null @@ -1,67 +0,0 @@ -package heroic - -import ( - "fmt" - "os" - "path/filepath" - "strconv" - - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" -) - -func FindInstallations() ([]*common.Installation, []error) { - return common.FindAll(findInstallationsNative, findInstallationsFlatpak, findInstallationsSnap) -} - -func findInstallationsNative() ([]*common.Installation, []error) { - return findInstallationsHeroic(false, "", "Heroic") -} - -func findInstallationsFlatpak() ([]*common.Installation, []error) { - homeDir, err := os.UserHomeDir() - if err != nil { - return nil, []error{fmt.Errorf("failed to get user home dir: %w", err)} - } - flatpakXdgConfigHome := filepath.Join(homeDir, ".var", "app", "com.heroicgameslauncher.hgl", "config") - return findInstallationsHeroic(false, flatpakXdgConfigHome, "Heroic") -} - -func findInstallationsSnap() ([]*common.Installation, []error) { - homeDir, err := os.UserHomeDir() - if err != nil { - return nil, []error{fmt.Errorf("failed to get user home dir: %w", err)} - } - snapAppDir := filepath.Join(homeDir, "snap", "heroic") - var latestSnapRevision int - var latestSnapDirName string - items, err := os.ReadDir(snapAppDir) - if err != nil { - return nil, []error{fmt.Errorf("failed to read heroic snap dir: %w", err)} - } - for _, item := range items { - if item.IsDir() { - folderName := item.Name() - var revision int - if folderName[0] == 'x' { - revision, err = strconv.Atoi(folderName[1:]) - if err != nil { - continue - } - } else { - revision, err = strconv.Atoi(folderName) - if err != nil { - continue - } - } - if latestSnapDirName == "" || revision > latestSnapRevision { - latestSnapRevision = revision - latestSnapDirName = folderName - } - } - } - if latestSnapDirName == "" { - return nil, []error{fmt.Errorf("no heroic snap folders found")} - } - - return findInstallationsHeroic(true, filepath.Join(snapAppDir, latestSnapDirName, ".config"), "Heroic") -} diff --git a/backend/installfinders/launchers/heroic/heroic_native_all.go b/backend/installfinders/launchers/heroic/heroic_native_all.go new file mode 100644 index 00000000..6fd71673 --- /dev/null +++ b/backend/installfinders/launchers/heroic/heroic_native_all.go @@ -0,0 +1,12 @@ +package heroic + +import ( + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers" +) + +func init() { + launchers.Add("Heroic", func() ([]*common.Installation, []error) { + return findInstallationsHeroic(false, "", "Heroic") + }) +} diff --git a/backend/installfinders/launchers/heroic/heroic_snap_linux.go b/backend/installfinders/launchers/heroic/heroic_snap_linux.go new file mode 100644 index 00000000..f3f5d9c4 --- /dev/null +++ b/backend/installfinders/launchers/heroic/heroic_snap_linux.go @@ -0,0 +1,61 @@ +package heroic + +import ( + "fmt" + "os" + "path/filepath" + "strconv" + + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers" +) + +func init() { + launchers.Add("Heroic-snap", func() ([]*common.Installation, []error) { + snapPath, err := getSnapPath() + if err != nil { + return nil, []error{fmt.Errorf("failed to get snap path: %w", err)} + } + + return findInstallationsHeroic(true, filepath.Join(snapPath, ".config"), "Heroic") + }) +} + +func getSnapPath() (string, error) { + homeDir, err := os.UserHomeDir() + if err != nil { + return "", fmt.Errorf("failed to get user home dir: %w", err) + } + snapAppDir := filepath.Join(homeDir, "snap", "heroic") + var latestSnapRevision int + var latestSnapDirName string + items, err := os.ReadDir(snapAppDir) + if err != nil { + return "", fmt.Errorf("failed to read heroic snap dir: %w", err) + } + for _, item := range items { + if item.IsDir() { + folderName := item.Name() + var revision int + if folderName[0] == 'x' { + revision, err = strconv.Atoi(folderName[1:]) + if err != nil { + continue + } + } else { + revision, err = strconv.Atoi(folderName) + if err != nil { + continue + } + } + if latestSnapDirName == "" || revision > latestSnapRevision { + latestSnapRevision = revision + latestSnapDirName = folderName + } + } + } + if latestSnapDirName == "" { + return "", fmt.Errorf("no heroic snap folders found") + } + return filepath.Join(snapAppDir, latestSnapDirName), nil +} diff --git a/backend/installfinders/launchers/heroic/heroic_windows.go b/backend/installfinders/launchers/heroic/heroic_windows.go deleted file mode 100644 index a7cfcfc2..00000000 --- a/backend/installfinders/launchers/heroic/heroic_windows.go +++ /dev/null @@ -1,9 +0,0 @@ -package heroic - -import ( - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" -) - -func FindInstallations() ([]*common.Installation, []error) { - return findInstallationsHeroic(false, "", "Heroic") -} diff --git a/backend/installfinders/launchers/legendary/legendary_all.go b/backend/installfinders/launchers/legendary/legendary_all.go index 7bd5bab6..8f430982 100644 --- a/backend/installfinders/launchers/legendary/legendary_all.go +++ b/backend/installfinders/launchers/legendary/legendary_all.go @@ -4,12 +4,15 @@ import ( "fmt" "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers" ) -func FindInstallations() ([]*common.Installation, []error) { - legendaryDataPath, err := getGlobalLegendaryDataPath("") - if err != nil { - return nil, []error{fmt.Errorf("failed to get legendary config path: %w", err)} - } - return FindInstallationsIn(legendaryDataPath, "Legendary") +func init() { + launchers.Add("Legendary", func() ([]*common.Installation, []error) { + legendaryDataPath, err := getGlobalLegendaryDataPath("") + if err != nil { + return nil, []error{fmt.Errorf("failed to get legendary config path: %w", err)} + } + return FindInstallationsIn(legendaryDataPath, "Legendary") + }) } diff --git a/backend/installfinders/launchers/lutris/lutris_linux.go b/backend/installfinders/launchers/lutris/lutris_linux.go index c5ca7cf3..36ee23fa 100644 --- a/backend/installfinders/launchers/lutris/lutris_linux.go +++ b/backend/installfinders/launchers/lutris/lutris_linux.go @@ -6,6 +6,7 @@ import ( "os/exec" "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers" "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers/epic" ) @@ -17,16 +18,13 @@ type Game struct { Directory string `json:"directory"` } -func FindInstallations() ([]*common.Installation, []error) { - return common.FindAll(findInstallationsNative, findInstallationsFlatpak) -} - -func findInstallationsNative() ([]*common.Installation, []error) { - return findInstallations([]string{"lutris"}, "Lutris") -} - -func findInstallationsFlatpak() ([]*common.Installation, []error) { - return findInstallations([]string{"flatpak", "run", "net.lutris.Lutris"}, "Lutris") +func init() { + launchers.Add("Lutris", func() ([]*common.Installation, []error) { + return findInstallations([]string{"lutris"}, "Lutris") + }) + launchers.Add("Lutris-flatpak", func() ([]*common.Installation, []error) { + return findInstallations([]string{"flatpak", "run", "net.lutris.Lutris"}, "Lutris") + }) } func findInstallations(lutrisCmd []string, launcher string) ([]*common.Installation, []error) { diff --git a/backend/installfinders/launchers/lutris/lutris_noop.go b/backend/installfinders/launchers/lutris/lutris_noop.go new file mode 100644 index 00000000..44d3c388 --- /dev/null +++ b/backend/installfinders/launchers/lutris/lutris_noop.go @@ -0,0 +1 @@ +package lutris diff --git a/backend/installfinders/launchers/registry.go b/backend/installfinders/launchers/registry.go new file mode 100644 index 00000000..16f22992 --- /dev/null +++ b/backend/installfinders/launchers/registry.go @@ -0,0 +1,19 @@ +package launchers + +import "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" + +var finders map[string]common.InstallFinderFunc + +func Add(id string, f common.InstallFinderFunc) { + if finders == nil { + finders = make(map[string]common.InstallFinderFunc) + } + if _, ok := finders[id]; ok { + panic("launcher already registered") + } + finders[id] = f +} + +func GetInstallFinders() map[string]common.InstallFinderFunc { + return finders +} diff --git a/backend/installfinders/launchers/steam/steam.go b/backend/installfinders/launchers/steam/steam.go index c1a5e9a7..91cd1238 100644 --- a/backend/installfinders/launchers/steam/steam.go +++ b/backend/installfinders/launchers/steam/steam.go @@ -95,7 +95,7 @@ func FindInstallationsSteam(steamPath string, launcher string, launchPath func(s } if _, ok := manifest["AppState"]; !ok { - findErrors = append(findErrors, fmt.Errorf("Failed to find AppState in manifest %s", manifestPath)) + findErrors = append(findErrors, fmt.Errorf("failed to find AppState in manifest %s", manifestPath)) continue } @@ -119,7 +119,7 @@ func FindInstallationsSteam(steamPath string, launcher string, launchPath func(s if betakey == "experimental" { branch = common.BranchExperimental } else { - findErrors = append(findErrors, fmt.Errorf("Unknown beta key %s", betakey)) + findErrors = append(findErrors, fmt.Errorf("unknown beta key %s", betakey)) } } diff --git a/backend/installfinders/launchers/steam/steam_flatpak_linux.go b/backend/installfinders/launchers/steam/steam_flatpak_linux.go new file mode 100644 index 00000000..0a793128 --- /dev/null +++ b/backend/installfinders/launchers/steam/steam_flatpak_linux.go @@ -0,0 +1,37 @@ +package steam + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers" +) + +func init() { + launchers.Add("Steam-flatpak", func() ([]*common.Installation, []error) { + homeDir, err := os.UserHomeDir() + if err != nil { + return nil, []error{fmt.Errorf("failed to get user home dir: %w", err)} + } + + steamPath := filepath.Join(homeDir, ".var", "app", "com.valvesoftware.Steam", ".steam", "steam") + if _, err := os.Stat(steamPath); os.IsNotExist(err) { + return nil, []error{fmt.Errorf("steam-flatpak not installed")} + } + return FindInstallationsSteam( + steamPath, + "Steam", + func(steamApp string) []string { + return []string{ + "flatpak", + "run", + "com.valvesoftware.Steam", + steamApp, + } + }, + nil, + ) + }) +} diff --git a/backend/installfinders/launchers/steam/steam_linux.go b/backend/installfinders/launchers/steam/steam_linux.go deleted file mode 100644 index 7dad4c57..00000000 --- a/backend/installfinders/launchers/steam/steam_linux.go +++ /dev/null @@ -1,84 +0,0 @@ -package steam - -import ( - "fmt" - "os" - "path/filepath" - - "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" -) - -func FindInstallations() ([]*common.Installation, []error) { - return common.FindAll(findInstallationsNative, findInstallationsFlatpak, findInstallationsSnap) -} - -func findInstallationsNative() ([]*common.Installation, []error) { - homeDir, err := os.UserHomeDir() - if err != nil { - return nil, []error{fmt.Errorf("failed to get user home dir: %w", err)} - } - steamPath := filepath.Join(homeDir, ".steam", "steam") - if _, err := os.Stat(steamPath); os.IsNotExist(err) { - return nil, []error{fmt.Errorf("steam not installed")} - } - return FindInstallationsSteam( - steamPath, - "Steam", - func(steamApp string) []string { - return []string{ - "steam", - steamApp, - } - }, - nil, - ) -} - -func findInstallationsSnap() ([]*common.Installation, []error) { - homeDir, err := os.UserHomeDir() - if err != nil { - return nil, []error{fmt.Errorf("failed to get user home dir: %w", err)} - } - steamPath := filepath.Join(homeDir, "snap", "steam", "common", ".local", "share", "Steam") - if _, err := os.Stat(steamPath); os.IsNotExist(err) { - return nil, []error{fmt.Errorf("steam-snap not installed")} - } - return FindInstallationsSteam( - steamPath, - "Steam", - func(steamApp string) []string { - return []string{ - "snap", - "run", - "steam", - steamApp, - } - }, - nil, - ) -} - -func findInstallationsFlatpak() ([]*common.Installation, []error) { - homeDir, err := os.UserHomeDir() - if err != nil { - return nil, []error{fmt.Errorf("failed to get user home dir: %w", err)} - } - - steamPath := filepath.Join(homeDir, ".var", "app", "com.valvesoftware.Steam", ".steam", "steam") - if _, err := os.Stat(steamPath); os.IsNotExist(err) { - return nil, []error{fmt.Errorf("steam-flatpak not installed")} - } - return FindInstallationsSteam( - steamPath, - "Steam", - func(steamApp string) []string { - return []string{ - "flatpak", - "run", - "com.valvesoftware.Steam", - steamApp, - } - }, - nil, - ) -} diff --git a/backend/installfinders/launchers/steam/steam_native_unix.go b/backend/installfinders/launchers/steam/steam_native_unix.go new file mode 100644 index 00000000..faf2e31e --- /dev/null +++ b/backend/installfinders/launchers/steam/steam_native_unix.go @@ -0,0 +1,38 @@ +//go:build unix + +package steam + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers" +) + +func init() { + launchers.Add("Steam", func() ([]*common.Installation, []error) { + homeDir, err := os.UserHomeDir() + if err != nil { + return nil, []error{fmt.Errorf("failed to get user home dir: %w", err)} + } + + steamPath := filepath.Join(homeDir, ".steam", "steam") + if _, err := os.Stat(steamPath); os.IsNotExist(err) { + return nil, []error{fmt.Errorf("steam not installed")} + } + + return FindInstallationsSteam( + steamPath, + "Steam", + func(steamApp string) []string { + return []string{ + "steam", + steamApp, + } + }, + nil, + ) + }) +} diff --git a/backend/installfinders/launchers/steam/steam_snap_linux.go b/backend/installfinders/launchers/steam/steam_snap_linux.go new file mode 100644 index 00000000..161c68f3 --- /dev/null +++ b/backend/installfinders/launchers/steam/steam_snap_linux.go @@ -0,0 +1,36 @@ +package steam + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers" +) + +func init() { + launchers.Add("Steam-snap", func() ([]*common.Installation, []error) { + homeDir, err := os.UserHomeDir() + if err != nil { + return nil, []error{fmt.Errorf("failed to get user home dir: %w", err)} + } + steamPath := filepath.Join(homeDir, "snap", "steam", "common", ".local", "share", "Steam") + if _, err := os.Stat(steamPath); os.IsNotExist(err) { + return nil, []error{fmt.Errorf("steam-snap not installed")} + } + return FindInstallationsSteam( + steamPath, + "Steam", + func(steamApp string) []string { + return []string{ + "snap", + "run", + "steam", + steamApp, + } + }, + nil, + ) + }) +} diff --git a/backend/installfinders/launchers/steam/steam_windows.go b/backend/installfinders/launchers/steam/steam_windows.go index 821d16d1..ae83e1d8 100644 --- a/backend/installfinders/launchers/steam/steam_windows.go +++ b/backend/installfinders/launchers/steam/steam_windows.go @@ -7,12 +7,37 @@ import ( "golang.org/x/sys/windows/registry" "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common" + "github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers" ) -func FindInstallations() ([]*common.Installation, []error) { +func init() { + launchers.Add("Steam", func() ([]*common.Installation, []error) { + steamPath, err := getSteamPath() + if err != nil { + return nil, []error{err} + } + + return FindInstallationsSteam( + steamPath, + "Steam", + func(steamApp string) []string { + return []string{ + "cmd", + "/C", + "start", + "", + steamApp, + } + }, + nil, + ) + }) +} + +func getSteamPath() (string, error) { key, err := registry.OpenKey(registry.CURRENT_USER, `Software\Valve\Steam`, registry.QUERY_VALUE) if err != nil { - return nil, []error{fmt.Errorf("failed to open Steam registry key: %w", err)} + return "", fmt.Errorf("failed to open Steam registry key: %w", err) } defer key.Close() @@ -21,19 +46,5 @@ func FindInstallations() ([]*common.Installation, []error) { steamExePath = `C:\Program Files (x86)\Steam\steam.exe` } - steamPath := filepath.Dir(steamExePath) - return FindInstallationsSteam( - steamPath, - "Steam", - func(steamApp string) []string { - return []string{ - "cmd", - "/C", - "start", - "", - steamApp, - } - }, - nil, - ) + return filepath.Dir(steamExePath), nil } diff --git a/go.mod b/go.mod index b158d316..8bddefc6 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/wailsapp/wails/v2 v2.8.0 github.com/zishang520/engine.io v1.5.12 github.com/zishang520/socket.io v1.3.2 + golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 golang.org/x/sys v0.16.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) @@ -85,7 +86,6 @@ require ( github.com/zishang520/socket.io-go-parser v1.0.4 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.18.0 // indirect - golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect golang.org/x/net v0.20.0 // indirect golang.org/x/sync v0.5.0 // indirect golang.org/x/text v0.14.0 // indirect