Skip to content

Commit

Permalink
Refactor install finder platform wrapper methods into struct
Browse files Browse the repository at this point in the history
  • Loading branch information
mircearoata committed May 14, 2024
1 parent 12c1450 commit 86f4e9b
Show file tree
Hide file tree
Showing 18 changed files with 196 additions and 135 deletions.
22 changes: 22 additions & 0 deletions backend/installfinders/common/launcherplatform.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package common

type Platform interface {
ProcessPath(path string) string
Os() string
}

type LauncherPlatform struct {
Platform
launcherCommand func(arg string) []string
}

func MakeLauncherPlatform(platform Platform, launcherCommand func(arg string) []string) LauncherPlatform {
return LauncherPlatform{Platform: platform, launcherCommand: launcherCommand}
}

func (p LauncherPlatform) LauncherCommand(arg string) []string {
if p.launcherCommand != nil {
return p.launcherCommand(arg)
}
return nil
}
19 changes: 19 additions & 0 deletions backend/installfinders/common/launcherplatform_native.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package common

import (
"runtime"
)

type nativePlatform struct{}

func NativePlatform() Platform {
return nativePlatform{}
}

func (p nativePlatform) ProcessPath(path string) string {
return path
}

func (p nativePlatform) Os() string {
return runtime.GOOS
}
24 changes: 24 additions & 0 deletions backend/installfinders/common/launcherplatform_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//go:build unix

package common

import (
"path/filepath"
"strings"
)

type winePlatform struct {
winePrefix string
}

func WineLauncherPlatform(winePrefix string) Platform {
return winePlatform{winePrefix: winePrefix}
}

func (p winePlatform) ProcessPath(path string) string {
return filepath.Join(p.winePrefix, "dosdevices", strings.ToLower(path[0:1])+strings.ReplaceAll(path[1:], "\\", "/"))
}

func (p winePlatform) Os() string {
return "windows"
}
14 changes: 0 additions & 14 deletions backend/installfinders/common/wine_unix.go

This file was deleted.

16 changes: 1 addition & 15 deletions backend/installfinders/launchers/crossover/crossover_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
var (
crossoverConfigRelativePath = filepath.Join("Library", "Preferences", "com.codeweavers.CrossOver.plist")
crossoverDefaultBottlesRelativePath = filepath.Join("Library", "Application Support", "Crossover", "Bottles")
crossoverSteamPath = filepath.Join("c:", "Program Files (x86)", "Steam") // Will get run through processPath, so it will be added to the dosdevices path
)

func init() {
Expand Down Expand Up @@ -45,20 +44,7 @@ func crossover() ([]*common.Installation, []error) {
continue
}
bottleRoot := filepath.Join(bottlesPath, bottle.Name())
processPath := common.WinePathProcessor(bottleRoot)

if _, err := os.Stat(processPath(crossoverSteamPath)); os.IsNotExist(err) {
slog.Debug("Skipping bottle without Steam", slog.String("bottle", bottle.Name()))
continue
}
bottleInstalls, bottleErrs := steam.FindInstallationsSteam(
crossoverSteamPath,
"CrossOver",
func(steamApp string) []string {
return nil
},
processPath,
)
bottleInstalls, bottleErrs := steam.FindInstallationsWine(bottleRoot, "CrossOver", nil)
installations = append(installations, bottleInstalls...)
if bottleErrs != nil {
errors = append(errors, bottleErrs...)
Expand Down
20 changes: 6 additions & 14 deletions backend/installfinders/launchers/epic/epic.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,12 @@ func GetEpicBranch(appName string) (common.GameBranch, error) {
}
}

func FindInstallationsEpic(epicManifestsPath string, launcher string, launchPath func(appName string) []string, processPath func(path string) string) ([]*common.Installation, []error) {
if launchPath == nil {
launchPath = func(appName string) []string { return nil }
}

if processPath == nil {
processPath = func(path string) string { return path }
}

if _, err := os.Stat(epicManifestsPath); os.IsNotExist(err) {
func FindInstallationsEpic(epicManifestsPath string, launcher string, platform common.LauncherPlatform) ([]*common.Installation, []error) {
if _, err := os.Stat(platform.ProcessPath(epicManifestsPath)); os.IsNotExist(err) {
return nil, []error{fmt.Errorf("epic is not installed")}
}

manifests, err := os.ReadDir(epicManifestsPath)
manifests, err := os.ReadDir(platform.ProcessPath(epicManifestsPath))
if err != nil {
return nil, []error{fmt.Errorf("failed to list Epic manifests: %w", err)}
}
Expand Down Expand Up @@ -92,10 +84,10 @@ func FindInstallationsEpic(epicManifestsPath string, launcher string, launchPath
continue
}

installLocation := processPath(epicManifest.InstallLocation)
installLocation := platform.ProcessPath(epicManifest.InstallLocation)

gameManifestName := fmt.Sprintf("%s.mancpn", epicManifest.InstallationGUID)
gameManifestPath := processPath(filepath.Join(epicManifest.ManifestLocation, gameManifestName))
gameManifestPath := platform.ProcessPath(filepath.Join(epicManifest.ManifestLocation, gameManifestName))
gameManifestData, err := os.ReadFile(gameManifestPath)
if err != nil {
findErrors = append(findErrors, fmt.Errorf("failed to read Epic game manifest %s: %w", gameManifestName, err))
Expand Down Expand Up @@ -155,7 +147,7 @@ func FindInstallationsEpic(epicManifestsPath string, launcher string, launchPath
Location: common.LocationTypeLocal,
Branch: branch,
Launcher: launcher,
LaunchPath: launchPath(epicManifest.MainGameAppName),
LaunchPath: platform.LauncherCommand(epicManifest.MainGameAppName),
})
}

Expand Down
29 changes: 18 additions & 11 deletions backend/installfinders/launchers/epic/epic_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,23 @@ var epicManifestsFolder = filepath.Join(os.Getenv("PROGRAMDATA"), "Epic", "EpicG

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)
return FindInstallationsEpic(
epicManifestsFolder,
"Epic Games",
common.MakeLauncherPlatform(
common.NativePlatform(),
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 `,
}
},
),
)
})
}
11 changes: 7 additions & 4 deletions backend/installfinders/launchers/epic/epic_wine_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ import (
var epicWineManifestPath = filepath.Join("c:", "ProgramData", "Epic", "EpicGamesLauncher", "Data", "Manifests")

func FindInstallationsWine(winePrefix string, launcher string, launchPath []string) ([]*common.Installation, []error) {
wineWindowsRoot := filepath.Join(winePrefix, "dosdevices")
epicManifestsPath := filepath.Join(wineWindowsRoot, epicWineManifestPath)
platform := common.WineLauncherPlatform(winePrefix)

if _, err := os.Stat(epicManifestsPath); os.IsNotExist(err) {
if _, err := os.Stat(platform.ProcessPath(epicWineManifestPath)); os.IsNotExist(err) {
return nil, []error{fmt.Errorf("Epic is not installed in " + winePrefix)}
}

return FindInstallationsEpic(epicManifestsPath, launcher, func(appName string) []string { return launchPath }, common.WinePathProcessor(winePrefix))
return FindInstallationsEpic(
epicWineManifestPath,
launcher,
common.MakeLauncherPlatform(platform, func(_ string) []string { return launchPath }),
)
}
2 changes: 1 addition & 1 deletion backend/installfinders/launchers/heroic/heroic.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func findInstallationsHeroic(snap bool, xdgConfigHomeEnv string, launcher string
return nil, []error{fmt.Errorf("failed to get heroic legendary config paths: %w", err)}
}

return legendary.FindInstallationsIn(legendaryDataPath, launcher)
return legendary.FindInstallationsIn(legendaryDataPath, launcher, common.MakeLauncherPlatform(common.NativePlatform(), nil))
}

func getHeroicLegendaryConfigPath(snap bool, xdgConfigHomeEnv string) (string, error) {
Expand Down
22 changes: 8 additions & 14 deletions backend/installfinders/launchers/legendary/legendary.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"

"github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common"
Expand All @@ -31,7 +30,7 @@ type Game struct {

type Data = map[string]Game

func FindInstallationsIn(legendaryDataPath string, launcher string) ([]*common.Installation, []error) {
func FindInstallationsIn(legendaryDataPath string, launcher string, platform common.LauncherPlatform) ([]*common.Installation, []error) {
legendaryInstalledPath := filepath.Join(legendaryDataPath, "installed.json")
if _, err := os.Stat(legendaryInstalledPath); os.IsNotExist(err) {
return nil, []error{fmt.Errorf("%s not installed", launcher)}
Expand All @@ -46,17 +45,16 @@ func FindInstallationsIn(legendaryDataPath string, launcher string) ([]*common.I
return nil, []error{fmt.Errorf("failed to parse legendary installed.json output: %w", err)}
}

_, err = exec.LookPath("legendary")
canLaunchLegendary := err == nil

installs := make([]*common.Installation, 0)
var findErrors []error

for _, legendaryGame := range legendaryData {
installType, version, err := common.GetGameInfo(legendaryGame.InstallPath)
installLocation := filepath.Clean(legendaryGame.InstallPath)

installType, version, err := common.GetGameInfo(installLocation)
if err != nil {
findErrors = append(findErrors, common.InstallFindError{
Path: legendaryGame.InstallPath,
Path: installLocation,
Inner: err,
})
continue
Expand All @@ -65,24 +63,20 @@ func FindInstallationsIn(legendaryDataPath string, launcher string) ([]*common.I
branch, err := epic.GetEpicBranch(legendaryGame.AppName)
if err != nil {
findErrors = append(findErrors, common.InstallFindError{
Path: legendaryGame.InstallPath,
Path: installLocation,
Inner: err,
})
continue
}

var launchPath []string
if canLaunchLegendary {
launchPath = []string{"legendary", "launch", legendaryGame.AppName}
}
installs = append(installs, &common.Installation{
Path: filepath.Clean(legendaryGame.InstallPath),
Path: installLocation,
Version: version,
Type: installType,
Location: common.LocationTypeLocal,
Branch: branch,
Launcher: launcher,
LaunchPath: launchPath,
LaunchPath: platform.LauncherCommand(legendaryGame.AppName),
})
}
return installs, findErrors
Expand Down
19 changes: 18 additions & 1 deletion backend/installfinders/launchers/legendary/legendary_all.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package legendary

import (
"fmt"
"os/exec"

"github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/common"
"github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders/launchers"
Expand All @@ -13,6 +14,22 @@ func init() {
if err != nil {
return nil, []error{fmt.Errorf("failed to get legendary config path: %w", err)}
}
return FindInstallationsIn(legendaryDataPath, "Legendary")

_, err = exec.LookPath("legendary")
canLaunchLegendary := err == nil

return FindInstallationsIn(
legendaryDataPath,
"Legendary",
common.MakeLauncherPlatform(
common.NativePlatform(),
func(appName string) []string {
if !canLaunchLegendary {
return nil
}
return []string{"legendary", "launch", appName}
},
),
)
})
}
16 changes: 4 additions & 12 deletions backend/installfinders/launchers/steam/steam.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,9 @@ import (

var manifests = []string{"appmanifest_526870.acf", "appmanifest_1690800.acf"}

func FindInstallationsSteam(steamPath string, launcher string, launchPath func(steamApp string) []string, processPath func(path string) string) ([]*common.Installation, []error) {
if launchPath == nil {
launchPath = func(appName string) []string { return nil }
}

if processPath == nil {
processPath = func(path string) string { return path }
}

func FindInstallationsSteam(steamPath string, launcher string, platform common.LauncherPlatform) ([]*common.Installation, []error) {
steamAppsPath := filepath.Join(steamPath, "steamapps")
libraryFoldersManifestPath := processPath(filepath.Join(steamAppsPath, "libraryfolders.vdf"))
libraryFoldersManifestPath := platform.ProcessPath(filepath.Join(steamAppsPath, "libraryfolders.vdf"))

libraryFoldersF, err := os.Open(libraryFoldersManifestPath)
if err != nil {
Expand Down Expand Up @@ -75,7 +67,7 @@ func FindInstallationsSteam(steamPath string, launcher string, launchPath func(s

for _, libraryFolder := range libraryFolders {
for _, manifest := range manifests {
manifestPath := processPath(filepath.Join(libraryFolder, "steamapps", manifest))
manifestPath := platform.ProcessPath(filepath.Join(libraryFolder, "steamapps", manifest))

if _, err := os.Stat(manifestPath); os.IsNotExist(err) {
continue
Expand Down Expand Up @@ -130,7 +122,7 @@ func FindInstallationsSteam(steamPath string, launcher string, launchPath func(s
Location: common.LocationTypeLocal,
Branch: branch,
Launcher: launcher,
LaunchPath: launchPath(`steam://rungameid/526870`),
LaunchPath: platform.LauncherCommand(`steam://rungameid/526870`),
})
}
}
Expand Down
19 changes: 10 additions & 9 deletions backend/installfinders/launchers/steam/steam_flatpak_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ func init() {
return FindInstallationsSteam(
steamPath,
"Steam",
func(steamApp string) []string {
return []string{
"flatpak",
"run",
"com.valvesoftware.Steam",
steamApp,
}
},
nil,
common.MakeLauncherPlatform(
common.NativePlatform(),
func(steamApp string) []string {
return []string{
"flatpak",
"run",
"com.valvesoftware.Steam",
steamApp,
}
}),
)
})
}
Loading

0 comments on commit 86f4e9b

Please sign in to comment.