Skip to content

Commit 25640cf

Browse files
committed
tech: use callRunner to launch steam
1 parent 5fdcdf5 commit 25640cf

File tree

6 files changed

+111
-17
lines changed

6 files changed

+111
-17
lines changed

src/backend/constants.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,13 @@ const cachedUbisoftInstallerPath = join(
8080
const ipdtPatcher = join(toolsPath, 'ipdt')
8181
const ipdtManifestsPath = join(appConfigFolder, 'manifests')
8282

83-
const { currentLogFile, lastLogFile, legendaryLogFile, gogdlLogFile } =
84-
createNewLogFileAndClearOldOnes()
83+
const {
84+
currentLogFile,
85+
lastLogFile,
86+
legendaryLogFile,
87+
gogdlLogFile,
88+
steamLogFile
89+
} = createNewLogFileAndClearOldOnes()
8590

8691
const gogdlAuthConfig = join(app.getPath('userData'), 'gog_store', 'auth.json')
8792
const iconDark = fixAsarPath(join(publicDir, 'trayIconDark24x24.png'))
@@ -251,6 +256,7 @@ export {
251256
lastLogFile,
252257
legendaryLogFile,
253258
gogdlLogFile,
259+
steamLogFile,
254260
discordLink,
255261
twitterLink,
256262
execOptions,

src/backend/logger/logfile.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ interface createLogFileReturn {
1616
lastLogFile: string
1717
legendaryLogFile: string
1818
gogdlLogFile: string
19+
steamLogFile: string
1920
}
2021

2122
let longestPrefix = 0
@@ -47,10 +48,12 @@ export function createNewLogFileAndClearOldOnes(): createLogFileReturn {
4748
const newLogFile = join(logDir, `hyperplay-${fmtDate}.log`)
4849
const newLegendaryLogFile = join(logDir, `legendary-${fmtDate}.log`)
4950
const newGogdlLogFile = join(logDir, `gogdl-${fmtDate}.log`)
51+
const newSteamLogFile = join(logDir, `steam-${fmtDate}.log`)
5052

5153
createLogFile(newLogFile)
5254
createLogFile(newLegendaryLogFile)
5355
createLogFile(newGogdlLogFile)
56+
createLogFile(newSteamLogFile)
5457

5558
// Clean out logs that are more than a month old
5659
if (existsSync(logDir)) {
@@ -88,7 +91,8 @@ export function createNewLogFileAndClearOldOnes(): createLogFileReturn {
8891
currentLogFile: '',
8992
lastLogFile: '',
9093
legendaryLogFile: '',
91-
gogdlLogFile: ''
94+
gogdlLogFile: '',
95+
steamLogFile: ''
9296
})
9397

9498
if (!isNewInstance) {
@@ -99,6 +103,7 @@ export function createNewLogFileAndClearOldOnes(): createLogFileReturn {
99103
logs.currentLogFile = newLogFile
100104
logs.legendaryLogFile = newLegendaryLogFile
101105
logs.gogdlLogFile = newGogdlLogFile
106+
logs.steamLogFile = newSteamLogFile
102107
configStore.set('general-logs', logs)
103108

104109
// get longest prefix to log lines in a kind of table
@@ -121,7 +126,8 @@ export function getLogFile(appNameOrRunner: string): string {
121126
currentLogFile: '',
122127
lastLogFile: '',
123128
legendaryLogFile: '',
124-
gogdlLogFile: ''
129+
gogdlLogFile: '',
130+
steamLogFile: ''
125131
})
126132

127133
switch (appNameOrRunner) {

src/backend/storeManagers/steam/games.ts

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
/* eslint-disable @typescript-eslint/no-unused-vars */
2+
3+
import { dirname, join } from 'node:path'
4+
import { GlobalConfig } from 'backend/config'
5+
import { isWindows, steamLogFile, userHome } from 'backend/constants'
6+
27
import { getGameInfo as getSteamLibraryGameInfo } from './library'
3-
import { logError, LogPrefix } from 'backend/logger/logger'
8+
import { logError, logInfo, LogPrefix, logWarning } from 'backend/logger/logger'
49
import {
510
GameInfo,
611
GameSettings,
@@ -13,6 +18,8 @@ import {
1318
import { existsSync } from 'graceful-fs'
1419
import { GOGCloudSavesLocation } from 'common/types/gog'
1520
import { InstallResult, RemoveArgs } from 'common/types/game_manager'
21+
import { callRunner, setupEnvVars } from 'backend/launcher'
22+
import { createAbortController } from 'backend/utils/aborthandler/aborthandler'
1623

1724
export function getGameInfo(appName: string): GameInfo {
1825
const info = getSteamLibraryGameInfo(appName)
@@ -88,8 +95,8 @@ export async function install(
8895
}
8996

9097
export function isNative(appName: string): boolean {
91-
// not used
92-
return false
98+
// Steam games are considered native if they run on the Steam client
99+
return true
93100
}
94101

95102
export async function addShortcuts(
@@ -107,8 +114,59 @@ export async function launch(
107114
appName: string,
108115
launchArguments?: string
109116
): Promise<boolean> {
110-
// not used
111-
return false
117+
const gameInfo = getGameInfo(appName)
118+
if (!gameInfo || !gameInfo.is_installed) {
119+
logWarning(`Game ${appName} is not installed or does not exist`, {
120+
prefix: LogPrefix.Steam
121+
})
122+
return false
123+
}
124+
125+
const steamBinaryPath = getSteamBinaryPath()
126+
if (!existsSync(steamBinaryPath)) {
127+
logError('Steam binary not found', { prefix: LogPrefix.Steam })
128+
return false
129+
}
130+
131+
const bin = getSteamBinaryPath()
132+
const dir = dirname(bin)
133+
const commandParts = [bin, '-applaunch', gameInfo.app_name]
134+
const gameSettings = await getSettings(appName)
135+
const commandEnv = isWindows
136+
? process.env
137+
: { ...process.env, ...setupEnvVars(gameSettings) }
138+
const options = {
139+
env: {
140+
...commandEnv
141+
},
142+
logMessagePrefix: `Launching ${gameInfo.title}`
143+
}
144+
const abortController = createAbortController(appName)
145+
146+
const { error, abort } = await callRunner(
147+
[...commandParts],
148+
{ name: 'steam', logPrefix: LogPrefix.Steam, bin, dir },
149+
abortController,
150+
{
151+
...options,
152+
verboseLogFile: steamLogFile
153+
},
154+
gameInfo
155+
)
156+
157+
if (error) {
158+
logError(`Failed to launch game ${appName}: ${error}`, {
159+
prefix: LogPrefix.Steam
160+
})
161+
return false
162+
}
163+
164+
if (abort) {
165+
logWarning(`Game ${appName} launch aborted`, { prefix: LogPrefix.Steam })
166+
return false
167+
}
168+
logInfo(`Game ${appName} launched successfully`, { prefix: LogPrefix.Steam })
169+
return true
112170
}
113171

114172
export async function moveInstall(
@@ -158,3 +216,33 @@ export async function stop(appName: string): Promise<void> {
158216
export async function pause(appName: string): Promise<void> {
159217
// not used
160218
}
219+
220+
function getSteamBinaryPath(): string {
221+
const { defaultSteamPath } = GlobalConfig.get().getSettings()
222+
const steamPath = defaultSteamPath.replaceAll("'", '')
223+
224+
if (process.platform === 'win32') {
225+
return join(steamPath, 'steam.exe')
226+
} else if (process.platform === 'darwin') {
227+
const steamApp = join('/Applications', 'Steam.app')
228+
if (existsSync(steamApp)) {
229+
return join(steamApp, 'Contents', 'MacOS', 'steam_osx')
230+
}
231+
} else {
232+
// For Linux it could be on /usr/bin/steam or in the flatpak path from home/.var/app/com.valvesoftware.Steam/.steam/steam
233+
const flatpakSteamPath = join(
234+
userHome,
235+
'.var',
236+
'app',
237+
'com.valvesoftware.Steam',
238+
'.steam',
239+
'steam'
240+
)
241+
242+
if (existsSync(flatpakSteamPath)) {
243+
return flatpakSteamPath
244+
}
245+
return join('/usr', 'bin', 'steam')
246+
}
247+
return ''
248+
}

src/common/types/electron_store.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export interface StoreStructure {
3939
lastLogFile: string
4040
legendaryLogFile: string
4141
gogdlLogFile: string
42+
steamLogFile: string
4243
}
4344
'window-props': Electron.Rectangle
4445
settings: AppSettings

src/frontend/helpers/library.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,6 @@ const launch = async ({
153153
showDialogModal,
154154
isNotNative
155155
}: LaunchOptions): Promise<{ status: 'done' | 'error' | 'abort' }> => {
156-
if (runner === 'steam') {
157-
return new Promise((resolve) => {
158-
window.api.openExternalUrl(`steam://run/${appName}`)
159-
resolve({ status: 'done' })
160-
})
161-
}
162-
163156
const showCompatibilityWarningDialog: boolean =
164157
isNotNative &&
165158
JSON.parse(

src/frontend/screens/Game/GamePage/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ export default observer(function GamePage(): React.JSX.Element | null {
702702
runner={runner}
703703
/>
704704
)}
705-
{is_installed && !isSteam && (
705+
{is_installed && (
706706
<span
707707
onClick={() => setIsSettingsModalOpen(true, 'log', gameInfo)}
708708
className="clickable reportProblem"

0 commit comments

Comments
 (0)