Skip to content

Commit

Permalink
[Linux] Use Steam Runtime with Proton (#1296)
Browse files Browse the repository at this point in the history
* feat: add steamRuntimeSoldier to proton command

* chore: updated local flatpak scripts

* use v2 entrypoint instead of run

* feat: add types and logic for native games

* chore: pr comments

* feat: add setting to enable/disable for proton

* chore: enable runtime by default for proton

* fix: both runtimes being called
  • Loading branch information
flavioislima authored May 21, 2022
1 parent 251df3b commit 405fe93
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 29 deletions.
20 changes: 15 additions & 5 deletions electron/gog/games.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import {
isLinux
} from '../constants'
import { configStore, installedGamesStore } from '../gog/electronStores'
import { logError, logInfo, LogPrefix } from '../logger/logger'
import { execAsync, getFileSize } from '../utils'
import { logError, logInfo, LogPrefix, logWarning } from '../logger/logger'
import { execAsync, getFileSize, getSteamRuntime } from '../utils'
import { GOGUser } from './user'
import {
launchCleanup,
Expand Down Expand Up @@ -331,12 +331,22 @@ class GOGGame extends Game {
steamRuntime
)

const { wineVersion, winePrefix, launcherArgs } = gameSettings
const { wineVersion, winePrefix, launcherArgs, useSteamRuntime } =
gameSettings
let wineFlag = ['--wine', wineVersion.bin]
let winePrefixFlag = ['--wine-prefix', winePrefix]
if (wineVersion.type === 'proton') {
wineFlag = ['--no-wine', '--wrapper', `'${wineVersion.bin}' run`]
winePrefixFlag = []
const runtime = useSteamRuntime ? getSteamRuntime('soldier') : null

if (runtime?.path) {
const runWithRuntime = `${runtime.path} -- '${wineVersion.bin}' waitforexitandrun`
wineFlag = ['--no-wine', '--wrapper', runWithRuntime]
winePrefixFlag = []
} else {
logWarning('No Steam runtime found')
wineFlag = ['--no-wine', '--wrapper', `'${wineVersion.bin}' run`]
winePrefixFlag = []
}
}

commandParts = [
Expand Down
21 changes: 14 additions & 7 deletions electron/launcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,22 +105,28 @@ async function prepareLaunch(

// If the Steam Runtime is enabled, find a valid one
let steamRuntime = ''
if (gameSettings.useSteamRuntime) {
const runtime = getSteamRuntime()
const isLinuxNative =
gameInfo?.install?.platform &&
gameInfo?.install?.platform.toLowerCase() === 'linux'

if (gameSettings.useSteamRuntime && isLinuxNative) {
// for native games lets use scout for now
const runtime = getSteamRuntime('scout')
if (!runtime.path) {
logWarning(`Couldn't find a valid Steam runtime path`, LogPrefix.Backend)
} else {
logInfo(`Using ${runtime.type} Steam runtime`, LogPrefix.Backend)
steamRuntime = runtime.path
steamRuntime =
runtime.version === 'soldier' ? `${runtime.path} -- ` : runtime.path
}
}

return {
success: true,
rpcClient: rpcClient,
mangoHudCommand: mangoHudCommand,
gameModeBin: gameModeBin,
steamRuntime: steamRuntime
rpcClient,
mangoHudCommand,
gameModeBin,
steamRuntime
}
}

Expand Down Expand Up @@ -363,6 +369,7 @@ async function runWineCommand(
if (wineVersion.type === 'proton') {
command = 'run ' + command
// TODO: Respect 'wait' here. Not sure if Proton can even do that
// TODO: Use Steamruntime here in the future
} else {
// This is only allowed for Wine since Proton only has one binary (the 'proton' script)
if (altWineBin) {
Expand Down
21 changes: 15 additions & 6 deletions electron/legendary/games.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { GameConfig } from '../game_config'
import { GlobalConfig } from '../config'
import { getLegendaryCommand, LegendaryLibrary } from './library'
import { LegendaryUser } from './user'
import { execAsync, isOnline } from '../utils'
import { execAsync, getSteamRuntime, isOnline } from '../utils'
import {
execOptions,
heroicGamesConfigPath,
Expand All @@ -17,7 +17,7 @@ import {
isMac,
isWindows
} from '../constants'
import { logError, logInfo, LogPrefix } from '../logger/logger'
import { logError, logInfo, LogPrefix, logWarning } from '../logger/logger'
import { spawn } from 'child_process'
import {
prepareLaunch,
Expand Down Expand Up @@ -609,7 +609,8 @@ class LegendaryGame extends Game {
steamRuntime
)

const { wineVersion, winePrefix, launcherArgs } = gameSettings
const { wineVersion, winePrefix, launcherArgs, useSteamRuntime } =
gameSettings

// Fix for people with old config
const wineBin =
Expand All @@ -620,8 +621,17 @@ class LegendaryGame extends Game {
let wineFlag = ['--wine', wineBin]
let winePrefixFlag = ['--wine-prefix', winePrefix]
if (wineVersion.type === 'proton') {
wineFlag = ['--no-wine', '--wrapper', `'${wineBin}' run`]
winePrefixFlag = []
const runtime = useSteamRuntime ? getSteamRuntime('soldier') : null

if (runtime?.path) {
const runWithRuntime = `${runtime.path} -- '${wineVersion.bin}' waitforexitandrun`
wineFlag = ['--no-wine', '--wrapper', runWithRuntime]
winePrefixFlag = []
} else {
logWarning('No Steam runtime found')
wineFlag = ['--no-wine', '--wrapper', `'${wineVersion.bin}' run`]
winePrefixFlag = []
}
}

commandParts = [
Expand All @@ -638,7 +648,6 @@ class LegendaryGame extends Game {
const command = getLegendaryCommand(commandParts, commandEnv, wrappers)

logInfo([`Launching ${gameInfo.title}:`, command], LogPrefix.Legendary)

const { error, stderr, stdout } = await runLegendaryCommand(commandParts, {
env: commandEnv,
wrappers: wrappers
Expand Down
1 change: 1 addition & 0 deletions electron/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ export interface GamepadInputEventMouse {
export interface SteamRuntime {
type: 'unpackaged' | 'flatpak'
path: string
version: 'soldier' | 'scout'
}

export interface LaunchPreperationResult {
Expand Down
36 changes: 28 additions & 8 deletions electron/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -448,23 +448,43 @@ async function searchForExecutableOnPath(executable: string): Promise<string> {
}
}

function getSteamRuntime(): SteamRuntime {
function getSteamRuntime(version: 'scout' | 'soldier'): SteamRuntime {
const possibleRuntimes: Array<SteamRuntime> = [
{
path: `${userHome}/.local/share/Steam/steamapps/common/SteamLinuxRuntime_soldier/_v2-entry-point`,
type: 'unpackaged',
version: 'soldier'
},
{
path: `${userHome}/.local/share/Steam/ubuntu12_32/steam-runtime/run.sh`,
type: 'unpackaged'
type: 'unpackaged',
version: 'scout'
},
{
path: `${userHome}/.var/app/com.valvesoftware.Steam/steamapps/common/SteamLinuxRuntime_soldier/_v2-entry-point`,
type: 'flatpak',
version: 'soldier'
},
{
path: `${userHome}/.var/app/com.valvesoftware.Steam/data/Steam/ubuntu12_32/steam-runtime/run.sh`,
type: 'flatpak'
type: 'flatpak',
version: 'scout'
}
]
for (const runtime of possibleRuntimes) {
if (existsSync(runtime.path)) {
return runtime
}

// try to get requested runtime first
let runtimes = possibleRuntimes.filter(
(r) => r.version === version && existsSync(r.path)
)
if (runtimes.length) {
return runtimes[0]
}
return { path: '', type: 'unpackaged' }
runtimes = possibleRuntimes.filter((r) => existsSync(r.path))
if (runtimes.length) {
return runtimes[0]
}

return { path: '', type: 'unpackaged', version: 'scout' }
}

function constructAndUpdateRPC(gameName: string): RpcClient {
Expand Down
27 changes: 27 additions & 0 deletions flatpak/local.heroic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ finish-args:
- --persist=.wine
- --filesystem=host
- --env=PATH=/app/bin:/usr/bin:/usr/lib/extensions/vulkan/MangoHud/bin/
- --env=GST_PLUGIN_SYSTEM_PATH=/app/lib/gstreamer-1.0:/app/lib32/gstreamer-1.0:/usr/lib/extensions/gstreamer-1.0:/usr/lib/x86_64-linux-gnu/gstreamer-1.0:/usr/lib/i386-linux-gnu/gstreamer-1.0


add-extensions:
org.freedesktop.Platform.Compat.i386:
Expand All @@ -46,7 +48,30 @@ add-extensions:
merge-dirs: vulkan/icd.d;glvnd/egl_vendor.d;OpenCL/vendors;lib/dri;lib/d3d;vulkan/explicit_layer.d;vulkan/implicit_layer.d
download-if: active-gl-driver
enable-if: active-gl-driver

org.freedesktop.Platform.ffmpeg-full:
directory: lib/ffmpeg
add-ld-path: .
version: '21.08'
no-autodownload: true
autodelete: false

org.freedesktop.Platform.ffmpeg_full.i386:
directory: lib32/ffmpeg
add-ld-path: .
version: '21.08'
no-autodownload: true
autodelete: false

org.freedesktop.Platform.VAAPI.Intel.i386:
directory: lib/i386-linux-gnu/dri/intel-vaapi-driver
version: '21.08'
versions: '21.08'
autodelete: false
no-autodownload: true
add-ld-path: lib
download-if: have-intel-gpu
autoprune-unless: have-intel-gpu

modules:
- name: unappimage
Expand Down Expand Up @@ -120,6 +145,8 @@ modules:
- |
set -e
mkdir -p /app/bin
mkdir -p /app/lib/ffmpeg
mkdir -p /app/lib32/ffmpeg
mkdir -p /app/lib/i386-linux-gnu
mkdir -p /app/lib/debug/lib/i386-linux-gnu
mkdir -p /app/lib/i386-linux-gnu/GL
Expand Down
8 changes: 8 additions & 0 deletions src/components/UI/SelectField/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,11 @@
.selectFieldWrapper.isRTL option {
direction: rtl;
}

.selectFieldWrapper button {
min-width: 130px;
max-width: 50%;
align-self: center;
justify-self: center;
margin: 12px;
}
7 changes: 5 additions & 2 deletions src/screens/Settings/components/OtherSettings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ interface Props {
useGameMode: boolean
useSteamRuntime: boolean
toggleUseSteamRuntime: () => void
isProton: boolean
}

export default function OtherSettings({
Expand Down Expand Up @@ -84,7 +85,8 @@ export default function OtherSettings({
isMacNative,
isLinuxNative,
toggleUseSteamRuntime,
useSteamRuntime
useSteamRuntime,
isProton
}: Props) {
const handleOtherOptions = (event: ChangeEvent<HTMLInputElement>) =>
setOtherOptions(event.currentTarget.value)
Expand All @@ -96,6 +98,7 @@ export default function OtherSettings({
const isLinux = platform === 'linux'
const supportsShortcuts = isWin || isLinux
const shouldRenderFpsOption = !isMacNative && !isWin && !isLinuxNative
const showSteamRuntime = isLinuxNative || isProton

const info = (
<InfoBox text="infobox.help">
Expand Down Expand Up @@ -184,7 +187,7 @@ export default function OtherSettings({
handleChange={toggleMangoHud}
title={t('setting.mangohud')}
/>
{isLinuxNative && (
{showSteamRuntime && (
<ToggleSwitch
htmlId="steamruntime"
value={useSteamRuntime}
Expand Down
5 changes: 4 additions & 1 deletion src/screens/Settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,9 @@ function Settings() {
setAltGogdlBin(config.altGogdlBin || '')
setShowUnrealMarket(config.showUnrealMarket)
setDefaultWinePrefix(config.defaultWinePrefix)
setUseSteamRuntime(config.useSteamRuntime || false)
setUseSteamRuntime(
config.useSteamRuntime || wineVersion.type === 'proton' ? true : false
)
setDisableController(config.disableController || false)

if (!isDefault) {
Expand Down Expand Up @@ -437,6 +439,7 @@ function Settings() {
toggleUseSteamRuntime={toggleUseSteamRuntime}
isMacNative={isMacNative}
isLinuxNative={isLinuxNative}
isProton={wineVersion.type === 'proton'}
/>
)}
{isSyncSettings && (
Expand Down

0 comments on commit 405fe93

Please sign in to comment.