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

STL immediately closes on launching games with symlinked directory #1132

Closed ElWombat01 closed 1 day ago

ElWombat01 commented 2 days ago

System Information

Issue Description

When trying to launch a game that has its directory symlinked in 'steamapps' folder, Steam Tinker Launcher will close immediately on startup. Will work correctly again when directory is moved into 'steamapps' folder and is no longer symlinked to elsewhere.

Logs

steamtinkerlaunch.log

sonic2kk commented 2 days ago

Sounds interesting. I don't know why it wouldn't work (maybe STL isn't expanding the realpaths or something) but I don't remember anyone trying this before.

I could see there being issues with finding the compatdata properly if we're not using the realpaths which could cause the game to crash, and in general would produce unintended behaviour.

I will look into fixing games crashing but I think using a symlinked steamapps folder is going to cause other issues with SteamTinkerLaunch that are not accounted for.

sonic2kk commented 1 day ago

Is the log you provided definitely from a full game execution? If so, is Steam able to launch the game without SteamTinkerLaunch?

I ask because your log file ends abruptly right after it begins to try to parse the start command:

Sun 30 Jun 14:02:59 BST 2024 INFO - main - Checking command line: incoming arguments 'waitforexitandrun /mnt/hdd-6tb-001-p1/home/rexkwndo/Games/PC/Bethesda/SkyrimSE/Versions/2024ModdedMO2/Game/SkyrimSELauncher.exe'
Sun 30 Jun 14:02:59 BST 2024 INFO - main - Checking command line: first argument 'waitforexitandrun'

And it looks like it's expanding the symlinked path properly. Perhaps it's having trouble finding a compatdata folder or something.


Also, how are you symlinking this? I assumed earlier that your steamapps folder was a symlink, but if you're trying to symlink a game folder into steamapps, how are you doing that? Are you not using the Steam release of a game?

I assumed you had a path like /path/to/steamapps, where steamapps itself was a symlink from one library folder to another (since Steam can only install games inside of library folders). But looking at your log file, it looks as though the game folder is the symlink, as in you have something like /path/to/steamapps/common/Skyrim, where Skyrim is the symlink to a skyrim folder somewhere else.

If you installed the game from Steam, moved it, and tried to symlink it into your steamapps/common folder, that probably won't work. I'm not sure what this accomplishes either, if you want the game on another drive, couldn't you make a separate library folder on that drive?

I'm not sure what this accomplishes either way, as you are launching SkyrimSE from Steam, so I assume this is a legitimate copy of Skyrim.

I would like to better understand what you've set up here so that I can replicate it.


So overall I am not sure why SteamTinkerLaunch is crashing but I can see that it is expanding the path as expected, and that the path it is expanding to is not a Steam library folder. I have no idea how SteamTinkerLaunch would handle this and where it would look for the compatdata, hopefully it does it by AppID. But there is no indication from the log alone what is going on. If you can elaborate a bit on what you're doing and what you're trying to achieve I can try to replicate it on my end. What folders exactly are you symlinking, is it a full steamapps, is it the common folder, or is it a single game folder that is symlinked?

If your log is just incomplete, please upload a complete one.

It might also help to run Steam from the commandline and take a look at the standard output, in case SteamTinkerLaunch is somehow crashing.


Also, just in case I read the issue template wrong, please make sure that you are only using SteamTinkerLaunch from master. Make sure to uninstall from the AUR and then install from the master branch.

sonic2kk commented 1 day ago

I am still not sure if it's the same thing you're doing, but I tried moving a game from my steamapps/common folder and then symlinking that game's folder. I was able to replicate the abrupt log ending.

The expanded symlink path comes from Steam itself, it appears that Steam resolves the symlink before passing it to SteamTinkerLaunch, so SteamTinkerLaunch never sees the steamapps/common path!

The issue is probably caused by the way we handle start command assuming the Steam launch commands will always have steamapps/common.

One approach to possibly fix this is to instead assume that Steam start commands may always have waitforexitandrun as their first command, which should be the case when launched from Steam for Proton games. I am unsure if this will have any side-effects though. I don't think it will but I will need to think about it more. We could always keep it as a fallback "or" clause meaning it shouldn't get prioritised if we hit steamapps/common first. For what it's worth, SteamTinkerLaunch was able to properly find the compatdata, so that wasn't an issue (I guess this comes from Steam).

For native titles, we have no such luxury. I don't think we have any solid way here. The first argument with and without the Steam Linux Runtime is the path to reaper but I don't know if this is guaranteed.

My assumption is that we checked steamapps/common because it was the most straightforward way to handle native and Proton games. While Proton games should always have waitforexitandrun this is not guaranteed for older Proton versions that may use run, and we can't check for run as the first command as this is far too broad. It was probably also assumed that the start directory wouldn't be a symlink.

Non-Steam Games are handled by checking if the $SteamAppId environment variable from Steam is defined as zero. But we can't assume that we have a Steam game if SteamAppId is defined because it may be defined when SteamTinkerLaunch calls itself to run commands when it is launched as part of a Steam game. Performing certain actions actually gets SteamTinkerLaunch to call itself again and in that case the SteamAppId would be set but we would actually want to run the commandline function.


So in summary: this is caused because SteamTinkerLaunch doesn't handle a game launch if the incoming path for a game purchased on Steam (one that has SteamAppId defined) does not have steamapps/common in its launch command. We check this because it was historically the easiest way to determine if we had a Steam game launch -- If the incoming command to SteamTinkerLaunch was coming from Steam, had SteamAppId defined, and had steamapps/common in its start command, it was a pretty safe assumption that this was a game launch, and this worked for native and Proton games, unlike checking for something like waitforexitandrun which may not apply to older Proton versions and which does not apply to native titles.

But when using a symlink, Steam only passes the resolved symlink path to SteamTinkerLaunch, so we do not get to see the steamapps/common path. We only get the real path.

I am not sure how to resolve this.

I am not sure if this is worth the effort to try and resolve because it could end up causing further problems and introducing brittle logic, for something that I believe could be solved much more simply by creating a separate library folder and moving the game there. I am unsure why you would need to put a symlink to a game or even a full libraryfolder into another libraryfolder.


I hope this explanation made a bit of sense. If you have any ideas I'd love to hear them, in particular I'd be interested in hearing more about your use-case here for using a symlink over simply creating another libraryfolder. But ultimately this may not be a feasible issue to resolve as there is not a clean path to doing so that accomodates both native and Proton games and that does so in a robust way.

ElWombat01 commented 1 day ago

Also, how are you symlinking this?

Yeah sorry I wasn't clear about that, it is specifically the Skyrim Special Edition game folder, not steamapps or common or anything. It also is the Steam version of Skyrim SE. The Skyrim Special Edition folder in steamapps/common is symlinked to the full path of the actual game folder (tried ln -s and creating a symlink in Dolphin too).

I would like to better understand what you've set up here so that I can replicate it.

I tried moving a game from my steamapps/common folder and then symlinking that game's folder. I was able to replicate the abrupt log ending.

That's exactly how I've set it up. Symlink and actual game directory are on the save hard drive and under the same mount point as well if that matters.

The reason I've symlinked it is because I try and keep separated modded versions of games (GTA V made me start doing this because I wanted a separate clean version for online and since then I have just stuck to doing stuff like that. In this instance, I have an older modded Skyrim SE in another directory that I don't want to accidentally mess around with).

It might also help to run Steam from the commandline and take a look at the standard output, in case SteamTinkerLaunch is somehow crashing.

Looked at it, nothing of note really, I can upload if you want.

Also, just in case I read the issue template wrong, please make sure that you are only using SteamTinkerLaunch from master. Make sure to uninstall from the AUR and then install from the master branch.

Did this just to make sure (although pretty confident the original log was the master branch version) and no change, virtually the same log file (apart from timestamps obviously).

I hope this explanation made a bit of sense.

I'm not the most technical person but I pretty much understand your explanation and understand why you don't want to mess around with it in case of anything breaking for a fringe use-case (which is more than fair).

Something of interest for this use-case, I read the bit about it expecting steamapps/common and tried symlinking a game to another folder in the same common folder and as expected it launched. Also tried symlinks into subdirectories of directories in common (e.g. symlinked steamapps/common/Grand Theft Auto V/ to steamapps/common/New Folder/Grand Theft Auto V with full filepaths) and also worked. Relative paths seem to work too (I'm guessing because that path gets converted to the full path and thus steamapps/common gets detected in execution).

I'm probably going to do the above and I think that's a fair compromise. Very thankful you explained everything otherwise I would have never thought about doing this 👍.

sonic2kk commented 1 day ago

Awesome news! The reason your example works is because we only check for steamapps/common. As in, as long as that string is anywhere in the launch command, it assumes a game launch. This was a little problematic as it would interrupt custom commands (#1125), so there are a couple of catches and exceptions to this logic.

That was a creative solution without creating a new library folder! Although I should mention you can have multiple Steam library folders on the same drive, if you ever need to do that.

I think this is a fair compromise too. Apologies there was not a cleaner solution. If anyone reads this in future and has an approach to fix this please comment / open a PR!


Closing in favour of the compromise above.