Skip to content

Commit

Permalink
[Tech] Refactor Game Managers (#2578)
Browse files Browse the repository at this point in the history
* [Tech] Refactor game managers (#183)

* init

* refactor gog, legendary, hyperplay games.ts

* update submodule to latest main commits

* refactor game manager games module

* update types, refactor library manager

* fix diskWrite merge

* fix more types

* rm bin exec override

* move store managers into storeManagers folder

* fix data types for hp games, add listUpdateableGames

* refactor library refresh

* refactor runWineCommand and hasGame

* rm hasUpdate, fix hp store install version

* rm refreshInstalled from library interface

* rm unused updateAllGames

* fix stop, add unzipping status, add inject process name

* change unzipping to extracting, add process names, fix restricted char bugs

* fix legendary and gog download status

* fix gog install, uninstall

* fix default install path setting

* fix proton/wine

* fix gog and legendary import

* update gameInfo and use gameInfo to inject HP Games

* move storeManager maps and fxns out of main

* fix legendary moveInstall and changeInstallPath

* refresh gog when app is ready

* fix changeGameInstallPath

* fix uninstall when gog game is already moved

* fix remaining merge conflicts

* add one conditional method call

* fix merge errors

* fix build errors

* rm unused vars

* prettier

* fix merge errors

* change back to import folder

* prettier fix

* revert importPath translation

* fix isNative check in main

* gog fixes

* fix download manager successive installs

* fix gog import

* fix deadcode

* check anticheat on mac

* rm main import

* add skip test on windows

* update games launch with merge changes

* fix dead code

* move removeFolder to utils

* import removeFolder fxn

* chore: make variables names more generic

* tests: updated tests

---------

Co-authored-by: Flavio F Lima <[email protected]>
  • Loading branch information
BrettCleary and flavioislima authored Apr 6, 2023
1 parent 2bc130b commit 48d2787
Show file tree
Hide file tree
Showing 80 changed files with 4,975 additions and 4,765 deletions.
2 changes: 1 addition & 1 deletion .ts-prunerc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"ignore": "src/common/typedefs"
}
}
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"editor.bracketPairColorization.enabled": true,
"prettier.configPath": "${fileDirname}/../.prettierrc.json",
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "esbenp.prettier-vscode",
"files.insertFinalNewline": true
}
2 changes: 2 additions & 0 deletions public/locales/en/gamepage.json
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@
},
"status": {
"clickToUpdate": "Click to Update",
"downloading": "Downloading",
"extracting": "Extracting",
"gameNotAvailable": "Game not available",
"hasUpdates": "New Version Available!",
"installed": "Installed",
Expand Down
2 changes: 2 additions & 0 deletions src/backend/__tests__/skip.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export const describeSkipOnWindows =
process.platform === 'win32' ? describe.skip : describe

export const testSkipOnWindows = process.platform === 'win32' ? test.skip : test
11 changes: 7 additions & 4 deletions src/backend/anticheat/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { heroicAnticheatDataPath, isWindows } from '../constants'
import { anticheatDataPath, isWindows } from '../constants'
import * as axios from 'axios'
import { logInfo, LogPrefix, logWarning } from '../logger/logger'
import { readFileSync, writeFileSync } from 'graceful-fs'
Expand All @@ -13,7 +13,7 @@ async function downloadAntiCheatData() {
const { data } = await axios.default.get(
'https://raw.githubusercontent.com/Starz0r/AreWeAntiCheatYet/HEAD/games.json'
)
writeFileSync(heroicAnticheatDataPath, JSON.stringify(data, null, 2))
writeFileSync(anticheatDataPath, JSON.stringify(data, null, 2))
logInfo(`AreWeAntiCheatYet data downloaded`, LogPrefix.Backend)
} catch (error) {
logWarning(
Expand All @@ -24,10 +24,13 @@ async function downloadAntiCheatData() {
})
}

function gameAnticheatInfo(appNamespace: string): AntiCheatInfo | null {
function gameAnticheatInfo(
appNamespace: string | undefined
): AntiCheatInfo | null {
if (appNamespace === undefined) return null
if (isWindows) return null

const data = readFileSync(heroicAnticheatDataPath)
const data = readFileSync(anticheatDataPath)
const jsonData = JSON.parse(data.toString())
return jsonData.find((info: AntiCheatInfo) => {
const namespace = info.storeIds.epic?.namespace
Expand Down
16 changes: 8 additions & 8 deletions src/backend/api/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import {
Runner,
InstallParams,
LaunchParams,
SideloadGame,
ImportGameArgs,
GameStatus
GameStatus,
GameInfo
} from 'common/types'

export const removeFolder = (args: [path: string, folderName: string]) =>
Expand All @@ -21,7 +21,11 @@ export const uninstall = async (
shouldRemoveSetting: boolean
) => {
if (runner === 'sideload') {
return ipcRenderer.invoke('removeApp', { appName, shouldRemovePrefix })
return ipcRenderer.invoke('removeApp', {
appName,
shouldRemovePrefix,
runner
})
} else {
return ipcRenderer.invoke(
'uninstall',
Expand Down Expand Up @@ -87,8 +91,4 @@ export const handleRecentGamesChanged = (callback: any) => {
}
}

export const addNewApp = (args: SideloadGame) =>
ipcRenderer.send('addNewApp', args)

export const launchApp = async (appName: string): Promise<boolean> =>
ipcRenderer.invoke('launchApp', appName)
export const addNewApp = (args: GameInfo) => ipcRenderer.send('addNewApp', args)
6 changes: 2 additions & 4 deletions src/backend/api/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,8 @@ export const authGOG = async (token: string) =>
export const logoutGOG = () => ipcRenderer.send('logoutGOG')
export const checkGameUpdates = async () =>
ipcRenderer.invoke('checkGameUpdates')
export const refreshLibrary = async (
fullRefresh?: boolean,
library?: Runner | 'all'
) => ipcRenderer.invoke('refreshLibrary', fullRefresh, library)
export const refreshLibrary = async (library?: Runner | 'all') =>
ipcRenderer.invoke('refreshLibrary', library)

export const gamepadAction = async (args: GamepadActionArgs) =>
ipcRenderer.invoke('gamepadAction', args)
Expand Down
4 changes: 4 additions & 0 deletions src/backend/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,8 @@ export default class CacheStore<ValueType, KeyType extends string = string> {
}

public clear = () => this.store.clear()

public has(key: string) {
return this.store.has(key)
}
}
53 changes: 26 additions & 27 deletions src/backend/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,21 @@ import {
GlobalConfigVersion,
WineInstallation
} from 'common/types'
import { LegendaryUser } from './legendary/user'
import { LegendaryUser } from 'backend/storeManagers/legendary/user'
import {
currentGlobalConfigVersion,
heroicConfigPath,
heroicDefaultWinePrefixDir,
heroicGamesConfigPath,
configPath,
defaultWinePrefix,
gamesConfigPath,
heroicInstallPath,
heroicToolsPath,
toolsPath,
userHome,
isFlatpak,
isMac,
isWindows,
getSteamLibraries,
getSteamCompatFolder,
configStore,
heroicDefaultWinePrefix
configStore
} from './constants'
import { execAsync } from './utils'
import { execSync } from 'child_process'
Expand Down Expand Up @@ -63,17 +62,17 @@ abstract class GlobalConfig {
let version: GlobalConfigVersion

// Config file doesn't already exist, make one with the current version.
if (!existsSync(heroicConfigPath)) {
if (!existsSync(configPath)) {
version = currentGlobalConfigVersion
}
// Config file exists, detect its version.
else {
// Check version field in the config.
try {
version = JSON.parse(readFileSync(heroicConfigPath, 'utf-8'))['version']
version = JSON.parse(readFileSync(configPath, 'utf-8'))['version']
} catch (error) {
logError(
`Config file is corrupted, please check ${heroicConfigPath}`,
`Config file is corrupted, please check ${configPath}`,
LogPrefix.Backend
)
version = 'v0'
Expand Down Expand Up @@ -171,7 +170,7 @@ abstract class GlobalConfig {
const winePaths = new Set<string>()

// search for wine installed on $HOME/Library/Application Support/heroic/tools/wine
const wineToolsPath = `${heroicToolsPath}/wine/`
const wineToolsPath = `${toolsPath}/wine/`
if (existsSync(wineToolsPath)) {
readdirSync(wineToolsPath).forEach((path) => {
winePaths.add(join(wineToolsPath, path))
Expand Down Expand Up @@ -311,18 +310,18 @@ abstract class GlobalConfig {
return [...macOsWineSet]
}

if (!existsSync(`${heroicToolsPath}/wine`)) {
mkdirSync(`${heroicToolsPath}/wine`, { recursive: true })
if (!existsSync(`${toolsPath}/wine`)) {
mkdirSync(`${toolsPath}/wine`, { recursive: true })
}

if (!existsSync(`${heroicToolsPath}/proton`)) {
mkdirSync(`${heroicToolsPath}/proton`, { recursive: true })
if (!existsSync(`${toolsPath}/proton`)) {
mkdirSync(`${toolsPath}/proton`, { recursive: true })
}

const altWine = new Set<WineInstallation>()

readdirSync(`${heroicToolsPath}/wine/`).forEach((version) => {
const wineBin = join(heroicToolsPath, 'wine', version, 'bin', 'wine')
readdirSync(`${toolsPath}/wine/`).forEach((version) => {
const wineBin = join(toolsPath, 'wine', version, 'bin', 'wine')
altWine.add({
bin: wineBin,
name: `Wine - ${version}`,
Expand All @@ -348,7 +347,7 @@ abstract class GlobalConfig {
})
}

const protonPaths = [`${heroicToolsPath}/proton/`]
const protonPaths = [`${toolsPath}/proton/`]

await getSteamLibraries().then((libs) => {
libs.forEach((path) => {
Expand Down Expand Up @@ -478,7 +477,7 @@ abstract class GlobalConfig {
public abstract resetToDefaults(): void

protected writeToFile(config: Record<string, unknown>) {
return writeFileSync(heroicConfigPath, JSON.stringify(config, null, 2))
return writeFileSync(configPath, JSON.stringify(config, null, 2))
}

/**
Expand All @@ -495,7 +494,7 @@ abstract class GlobalConfig {
*/
protected load() {
// Config file doesn't exist, make one.
if (!existsSync(heroicConfigPath)) {
if (!existsSync(configPath)) {
this.resetToDefaults()
}
// Always upgrade before loading to avoid errors.
Expand Down Expand Up @@ -530,15 +529,15 @@ class GlobalConfigV0 extends GlobalConfig {
return this.config
}

if (!existsSync(heroicGamesConfigPath)) {
mkdirSync(heroicGamesConfigPath, { recursive: true })
if (!existsSync(gamesConfigPath)) {
mkdirSync(gamesConfigPath, { recursive: true })
}

if (!existsSync(heroicConfigPath)) {
if (!existsSync(configPath)) {
return this.getFactoryDefaults()
}

let settings = JSON.parse(readFileSync(heroicConfigPath, 'utf-8'))
let settings = JSON.parse(readFileSync(configPath, 'utf-8'))
const defaultSettings = settings.defaultSettings as AppSettings

// fix relative paths
Expand All @@ -565,7 +564,7 @@ class GlobalConfigV0 extends GlobalConfig {
public getCustomWinePaths(): Set<WineInstallation> {
const customPaths = new Set<WineInstallation>()
// skips this on new installations to avoid infinite loops
if (existsSync(heroicConfigPath)) {
if (existsSync(configPath)) {
const { customWinePaths = [] } = this.getSettings()
customWinePaths.forEach((path: string) => {
if (path.endsWith('proton')) {
Expand Down Expand Up @@ -607,7 +606,7 @@ class GlobalConfigV0 extends GlobalConfig {
defaultInstallPath: heroicInstallPath,
libraryTopSection: 'disabled',
defaultSteamPath: getSteamCompatFolder(),
defaultWinePrefix: heroicDefaultWinePrefixDir,
defaultWinePrefix: defaultWinePrefix,
hideChangelogsOnStartup: false,
language: 'en',
maxWorkers: 0,
Expand All @@ -622,7 +621,7 @@ class GlobalConfigV0 extends GlobalConfig {
name: userName
},
wineCrossoverBottle: 'Heroic',
winePrefix: isWindows ? '' : heroicDefaultWinePrefix,
winePrefix: isWindows ? '' : defaultWinePrefix,
wineVersion: defaultWine
} as AppSettings
}
Expand Down
49 changes: 20 additions & 29 deletions src/backend/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,20 @@ const configFolder = app.getPath('appData')
const legendaryConfigPath = isLinux
? join(configFolder, 'legendary')
: join(userHome, '.config', 'legendary')
const heroicFolder = join(configFolder, 'heroic')
const heroicConfigPath = join(heroicFolder, 'config.json')
const heroicGamesConfigPath = join(heroicFolder, 'GamesConfig')
const heroicToolsPath = join(heroicFolder, 'tools')
const heroicIconFolder = join(heroicFolder, 'icons')
const runtimePath = join(heroicToolsPath, 'runtimes')
const appFolder = join(configFolder, 'heroic')
const configPath = join(appFolder, 'config.json')
const gamesConfigPath = join(appFolder, 'GamesConfig')
const toolsPath = join(appFolder, 'tools')
const heroicIconFolder = join(appFolder, 'icons')
const runtimePath = join(toolsPath, 'runtimes')
const userInfo = join(legendaryConfigPath, 'user.json')
const heroicInstallPath = join(homedir(), 'Games', 'Heroic')
const heroicDefaultWinePrefixDir = join(
homedir(),
'Games',
'Heroic',
'Prefixes'
)
const heroicDefaultWinePrefix = join(heroicDefaultWinePrefixDir, 'default')
const heroicAnticheatDataPath = join(heroicFolder, 'areweanticheatyet.json')
const imagesCachePath = join(heroicFolder, 'images-cache')
const defaultWinePrefixDir = join(homedir(), 'Games', 'Heroic', 'Prefixes')
const defaultWinePrefix = join(defaultWinePrefixDir, 'default')
const anticheatDataPath = join(appFolder, 'areweanticheatyet.json')
const imagesCachePath = join(appFolder, 'images-cache')
const cachedUbisoftInstallerPath = join(
heroicFolder,
appFolder,
'tools',
'UbisoftConnectInstaller.exe'
)
Expand Down Expand Up @@ -186,16 +181,12 @@ const execOptions = {
shell: getShell()
}

const defaultFolders = [
heroicGamesConfigPath,
heroicIconFolder,
imagesCachePath
]
const defaultFolders = [gamesConfigPath, heroicIconFolder, imagesCachePath]

const necessaryFoldersByPlatform = {
win32: [...defaultFolders],
linux: [...defaultFolders, heroicToolsPath],
darwin: [...defaultFolders, heroicToolsPath]
linux: [...defaultFolders, toolsPath],
darwin: [...defaultFolders, toolsPath]
}

export function createNecessaryFolders() {
Expand All @@ -217,15 +208,15 @@ export {
execOptions,
fixAsarPath,
configStore,
heroicConfigPath,
heroicGamesConfigPath,
configPath,
gamesConfigPath,
heroicGithubURL,
heroicIconFolder,
heroicInstallPath,
heroicToolsPath,
heroicDefaultWinePrefixDir,
heroicDefaultWinePrefix,
heroicAnticheatDataPath,
toolsPath,
defaultWinePrefixDir,
defaultWinePrefix,
anticheatDataPath,
imagesCachePath,
userHome,
flatPakHome,
Expand Down
Loading

0 comments on commit 48d2787

Please sign in to comment.