sonic2kk / steamtinkerlaunch

Linux wrapper tool for use with the Steam client for custom launch options and 3rd party programs
GNU General Public License v3.0
2.03k stars 69 forks source link

misc: Fix commands being interpreted as game launch if command included `steamapps/common` #1125

Closed sonic2kk closed 2 weeks ago

sonic2kk commented 2 weeks ago

If commands to SteamTinkerLaunch include steamapps/common, we incorrectly interpret this as an attempted game launch. This is because SteamTinkerLaunch assumes if a path contains the path to a Steam game that it should be a game launch. An incoming start command might look like this from Proton: waitforexitandrun "/home/gaben/.local/share/Steam/steamapps/common/Half-Life 3/hl3.exe. So to detect game launches, SteamTinkerLaunch looks for steamapps/common using grep -q "$SAC" (where SA="steamapps"; SAC="$SA/common").

For native Linux games, because they can be launched with and without a Steam Linux Runtime - not to mention Proton games can use whacky incoming things for things like link2ea, Ubisoft, etc - there is no way I can think of currently to know when the incoming command to SteamTinkerLaunch is a game launch, and when it is a command, other than to hardcode cases where an incoming command may reasonably contain steamapps/common.

One-Time Run suffers quite badly from this bug, where the --exe path may contain a steamapps path. The following command would fail: steamtinkerlaunch otr --exe="/home/gaben/.local/share/Steam/steamapps/common/Half-Life 3/hl3.exe" --proton="GE-Proton9-7" -- It fails because the path contains steamapps/common.


Commands which can include "steamapps/common" will fail because SteamTinkerLaunch interprets them as game launches even if they are not, because this is the most straightforward way to detect game launches.

This PR fixes the issue by introducing a check on the first incoming argument (the actual command, for example with steamtinkerlaunch otr, $1 is otr) to see if it contains a hardcoded list of grep values. For now, we only check for otr. The reason we only check on $1 is because we only care to check if the first command is a known SteamTinkerLaunch command; we wouldn't want to exclude commands containing otr anywhere from being ran as game processes, we only want to skip launching as a game process if the incoming command's first parameter is a known command that is NOT a game process, i.e. a command defined by SteamTinkerLaunch. steamtinkerlaunch otr blah blah will never come from anywhere except someone wanting to run the otr command, but steamtinkerlaunch waitforexitandrun /run/media/gaben/otr/ could conceivably be a path, so we don't account for those kinds of cases.

In other words:

There is no reason why all custom commands shouldn't be exluded, other than it would take time to add them all, and most won't encounter this issue.


I did some testing with Proton games and native Linux games and it seems to work fine.

TODO:

sonic2kk commented 2 weeks ago

The current solution would match /home/onetimerun/games/OneTimeRun/otr.exe, where the username is onetimerun and the exe is otr, if ths was in the first argument.

This is a problem, we'll need stricter checking to ignore such cases. Perhaps we can check if there is a slash anywhere in the string as well, as none of our first arguments should ever start with a slash. We could do this with && [[ "${1}" != *"/"* ]].

sonic2kk commented 2 weeks ago

Tested To the Moon (native title) with and without the Steam Linux Runtime (including the Steam Linux Runtime coming from the Scout 1.0 runtime forced as a compatibility tool).

Tested Sonic Adventure 2 (Proton title) with and without the Steam Linux Runtime and tested it with a custom command (SA Mod Manager) both with the Steam Linux Runtime for custom commands enabled and disabled.

This appears to work without breaking game launch functionality, and I spot-checked a few commands (steamtinkerlaunch vortex start). Not that it should have broken


This check happens very early in the SteamTinkerLaunch startup, it is specific to the first argument given to the program before it calls prepareLaunch, which means the testing done here should be sufficient. There is no case where the first argument should ever be otr without any spaces or slashes, and where that does not refer to One-Time Run.

Other commands can be given as well in future if I or someone else notices that they are broken by this, but for now, I think the testing done here has been fine. I have been using this branch without explicitly testing for a bit now, on top of the explicit testing mentioned above, and everything is fine.

I will merge and if it really ends up being disastrous, it can be reverted.