Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SteamTinkerLaunch Source #119

Merged
merged 4 commits into from Sep 16, 2022

Conversation

sonic2kk
Copy link
Contributor

@sonic2kk sonic2kk commented Aug 31, 2022

Implements #86.

Overview

Adds Frostworx's SteamTinkerLaunch utility as a ctmod to allow for streamlined installation and uninstallation across distros and on Steam Deck. Stable releases and the latest git (gated behind ProtonUp-Qt's "Advanced Mode") can be installed. Stable releases show a list of versions in its dropdown whereas the git release shows branches in the interest of potential future-proofing. Currently, SteamTinkerLaunch only has a master branch, but if there are any very experimental features that a user wants/needs, they will be able to install it.

SteamTinkerLaunch Flatpak installation (only for Flatpak Steam) is also supported.

image

Note: I am not the creator of SteamTinkerLaunch, I just contribute to it every so often and try to help out with the community around it.

SteamTinkerLaunch is installed following the "manual (non-root)" installation method, but we do all the heavy lifting for the user to get them set up, such as setting up the language files and adding SteamTinkerLaunch to PATH. We also manage full uninstallation of SteamTinkerLaunch. This not only makes a manual non-root install a few button clicks, but also makes uninstallation a single click! There's no worry of bloating up your Steam Deck for example with a bunch of miscellaneous files, or having to fumble around with the on-screen keyboard to edit your path.

Features

  • Steam Deck support
  • Very fast installation with all manual steps taken care of
  • Can be easily uninstalled
  • Can be updated without clearing the $HOME/.config/steamtinkerlaunch folder, which is important as that's where Vortex/MO2 mods live.
  • SteamTinkerLaunch is automatically set as a compatibility tool *and added to all of the user's shell PATHs, meaning SteamTinkerLaunch can be used as a launch option from Steam for Native Linux games. Currently the user will have to enter the absolute path as just typing steamtinkerlaunch %command% doesn't work. There's probably a way to use something like $(which steamtinkerlaunch) %command% but I haven't found it yet.
  • As SteamTinkerLaunch is added to the PATH users can run steamtinkerlaunch commands, taking advantage of some of the command line features like steamtinkerlaunch addnonsteamgame.
  • From within ProtonUp-Qt, SteamTinkerLaunch can be set as a compatibility tool via the Game List by selecting the Proton-stl option. This is the internal name for SteamTinkerLaunch.
  • Users can see which apps and how many are using SteamTinkerLaunch from the About Compatibility Tool window.

Okay, enough advertising, now onto the technical bits!

How It's Installed

The installation steps on Desktop and Steam Deck are very similar. The main difference is that SteamTinkerLaunch will manage downloading its dependencies itself on Steam Deck, and it will also configure its language files correctly.

  1. If not on Steam Deck, Check that all the SteamTinkerLaunch Hard Dependencies are installed.
  2. The SteamTinkerLaunch tarball is downloaded from GitHub to and extracted inside of $HOME/stl.
  3. If not on Steam Deck, we set up the language files automatically based on a map of locales and corresponding SteamTinkerLaunch language files. We get the user's locale (defaults to en_US) and copy the mapped language text file to $HOME/.config/steamtinkerlaunch/lang.
  4. The steamtinkerlaunch script downloaded earlier is given an initial run to set up its $HOME/.config/steamtinkerlaunch configuration structure.
  5. Add SteamTinkerLaunch to the Shell path for Bash (.bashrc), Zsh (.zshrc), Ksh (.kshrc) and Fish shell ($HOME/.config/fish_variables) if it isn't already present - Yes, this even works on Steam Deck! Any opened terminal sessions and the like will probably need restarted so they can reload their Shell RC files, but this is general shell behaviour.
    • For every shell, a note is placed above the path line to say that it was # Added by ProtonUp-Qt on %d-%m-%Y %H:%M:%S for transparency.
    • For Bash, Zsh and Ksh, if [ -d "<stl_path>" ]; then export PATH="$PATH:<stl_path>"; fi is added to the appropriate Shell RC files.
    • For Fish shell, the fish_variables file is edited to either prepend the <stl_path> to the fish_user_paths variable, or create this variable if it doesn't exist and set it to<stl_path>.
  6. Adds SteamTinkerLaunch as a compatibility tool using its built-in command ./steamtinkerlaunch compat add. This creates $HOME/.local/share/Steam/compatibilitytools.d/SteamTinkerLaunch, which has a couple of .vdffiles and asteamtinkerlaunch` symlink file which points to the download location of the earlier SteamTinkerLaunch download.

The whole thing takes less than 15 seconds to download and install on my laptop. On my Steam Deck it's a little longer, still less than a minute, as SteamTinkerLaunch downloads various dependencies on Deck from the Arch repos and Valve's Arch mirrors. Of course, these times can vary and the main factor here will be internet speed and server speed 馃檪

How It's Uninstalled

The uninstallation steps are virtually the installation steps in reverse. We remove the compatibility tool from compatibilitytools.d, we remove $HOME/.config/steamtinkerlaunch and we remove the entire $HOME/stl folder. We also remove SteamTinkerLaunch from the shell paths, for Fish path we take extra care preserving any existing user paths while also removing the note that the paths were modified by ProtonUp-Qt.

Flatpak Paths

The Flatpak will probably need permission for the following paths:

  • $HOME/ - For the Shell RC files and to create $HOME/stl if it doesn't exist.
  • $HOME/stl/ - All SteamTinkerLaunch install files live here, included the dependencies it downloads for Steam Deck.
  • $HOME/.config/steamtinkerlaunch/ - SteamTinkerLaunch configuration folder, this is where the language files go and where SteamTinkerLaunch config stuff goes.
  • $HOME/.config/fish/ - We check if this folder exists (to see if Fish is installed, since we can't use shutil.which('Fish') with ProtonUp-Qt Flatpak) and if it does we edit the fish_variables file to add SteamTInkerLaunch to the Fish shell user paths.
  • $HOME/.local/share/Steam/compatibilitytools.d/ - Where SteamTinkerLaunch sets up its compatibility tool folder and creates the symlink.

Testing

Right now I have only tested when running my fork of ProtonUp-Qt from source on my laptop (Arch Linux running KDE Plasma Wayland Session) and on my Steam Deck. I have not tested running via an AppImage or via Flatpak. I also have not tested installing SteamTinkerLaunch Flatpak for Flatpak Steam, as I don't have Flatpak Steam installed on any of my systems.

For testing AppImage, I think it would be a case of following the instructions to build an AppImage and then trying it out. For Flatpak though, I'm totally lost 馃槄

Considerations

There are some concerns I have currently:

How To Deal With SteamTinkerLaunch Dependencies In ProtonUp-Qt Flatpak

Following discussion in #86, I'm not sure how to handle conveying to the user that SteamTinkerLaunch has a number of dependencies that need to be satisfied before it'll work. To mitigate this I have included a list of the Hard Dependencies in the Description field, also including a message that on Steam Deck the dependencies are managed.

Installing Versions Incompatible With Steam Deck

A realization I had is that a user might, for any reason, try to install an older version of SteamTinkerLaunch on Steam Deck. However, only SteamTinkerLaunch >= v10.0 support Steam Deck. I was wondering if maybe we should show a warning prompt when the user is on Deck tries to install an unsupported version of SteamTinkerLaunch.

Feedback

This ended up being a fair bit more complex than I initially intended, so please let me know if there's anything I messed up or anything that could be implemented better. I did my best to implement all the functionality needed to install SteamTinkerLaunch in the most efficient way I could, but I'm happy to clarify any decisions I made and change anything to meet the code standards of the project.

The commits aren't squashed yet as I wanted to do that after discussion and code review... and I might need some help with how to do that 馃槗

Huge thanks for all the patience, guidance and advice. It was vital and is very much appreciated 馃槃

@DavidoTek
Copy link
Owner

First of all thank you very much for the implementation! 馃帀馃帀馃帀

I had a look at the code, looks very good. I will have a closer look and comment if there's anything.

How To Deal With SteamTinkerLaunch Dependencies In ProtonUp-Qt Flatpak
To mitigate this I have included a list of the Hard Dependencies in the Description field, also including a message that on Steam Deck the dependencies are managed.

We can't do anything about it anyway.
I'm wondering, does the Steam Deck version of STL bring its own dependencies? Maybe STL could do the same for non-Steam Deck installs...

However, only SteamTinkerLaunch >= v10.0 support Steam Deck. I was wondering if maybe we should show a warning prompt when the user is on Deck tries to install an unsupported version of SteamTinkerLaunch.

You can add it if you want to. I'm not sure if there are reasons to use an older version of STL, in that case a warning may be helpful.

I have not tested running via an AppImage or via Flatpak.

AppImage should be the same as running ProtonUp-Qt from source, for Flatpak, the package can be built using flatpak-builder using the ProtonUp-Qt Flatpak source. I will do some testing before releasing the STL installer over there.

Huge thanks for all the patience, guidance and advice. It was vital and is very much appreciated 馃槃

No problem, thanks for your help! Would've taken me years to implement this otherwise 馃槈

"""

try:
os.chdir(os.path.expanduser('~'))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed?

Copy link
Contributor Author

@sonic2kk sonic2kk Aug 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was more of a fail-safe. I ran into some problems during development where certain files couldn't be found because the current directory wasn't the home folder. In case it's ever changed anywhere else, this ensures the uninstall script always starts from the home directory (since STL is installed to ~/stl).

I can remove it if it's preferred, as the code has changed since I put that in and the paths to the shell files should be absolute now, I can do some tests and remove it if its safe. But this was put in to be sure that we're working in the home directory, just in case it's ever changed. (https://github.com/sonic2kk/ProtonUp-Qt/blob/add-steamtinkerlaunch/pupgui2/steamutil.py#L334-L336)

However the compat_folder path may not be absolute(?) so that line may be needed to remove that folder. Not sure, I'll need to test.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, the current dir shouldn't be changed anywhere else though I'm not sure if it could break something in the future as this changes the current dir for the whole app.

However the compat_folder path may not be absolute(?)

It should be absolute, works fine with shutil.rmtree here https://github.com/sonic2kk/ProtonUp-Qt/blob/add-steamtinkerlaunch/pupgui2/util.py#L249-L252

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

though I'm not sure if it could break something in the future as this changes the current dir for the whole app.

No problem, I can remove it in other places too if needs be, such as in the ctmod itself.

pupgui2/util.py Outdated
@@ -244,7 +245,10 @@ def remove_ctool(ver: str, install_dir: str) -> bool:
Return Type: bool
"""
target = os.path.join(install_dir, ver.split(' - ')[0])
if os.path.exists(target):
# Special case hack to remove SteamTinkerLaunch
if 'steamtinkerlaunch' in [t.lower() for t in target.split('/')]:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also work:

if 'steamtinkerlaunch' in target.lower():

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good catch! I'll fix that now.

@DavidoTek
Copy link
Owner

I found a small bug, I think the language (file) needs to be specified in ~/.config/steamtinkerlaunch/global.conf to work correct, else there will be an error message. Not sure what's the best way to do it, does the command steamtinkerlaunch --language=PATH save it?

e.g. STLLANG="german"

@sonic2kk
Copy link
Contributor Author

sonic2kk commented Sep 1, 2022

Hmm, I'll try adding that to the initial STL run. First though, you check in ~/.config/steamtinkerlaunch/lang and see if the correct language file is copied over for you? That way we can rule out the issue being with the locale checking logic.

I would've thought that STL would set the language based on the file in lang/<name of file>.txt but maybe not. If the correct file is copied over, we can just change the initial run to subprocess.run([f'./steamtinkerlaunch lang=lang/{stllang}']). No worries either way, but if the code in place for copying the language file doesn't work, I'll need to address that first.

@DavidoTek
Copy link
Owner

First though, you check in ~/.config/steamtinkerlaunch/lang and see if the correct language file is copied over for you?

Yes, the correct language files were copied.

When I changed the line STLLANG="english" in global.conf to STLLANG="german" it worked. Running steamtinkerlaunch lang=lang/german (nor using a relative/absolute path) did work.

@DavidoTek
Copy link
Owner

Sorry for the late reply,
Regarding the Steam Flatpak, I think we'll need to disable installing STL as the Steam Flatpak cannot run commands outside the Flatpak sandbox and stl compat add will only install STL for non-Flatpak Steam. For this, we have the STL Flatpak, that works like an add-on for Steam Flatpak.

There's also a Snap version of Steam, but it's in early access and things may change, we probably need to wait for STL to support it officially.

@sonic2kk
Copy link
Contributor Author

sonic2kk commented Sep 4, 2022

When I changed the line STLLANG="english" in global.conf to STLLANG="german" it worked. Running steamtinkerlaunch lang=lang/german (nor using a relative/absolute path) did work.

Ah, excellent! I'll fix the command now then, thank you for checking! 馃槃

Regarding the Steam Flatpak, I think we'll need to disable installing STL as the Steam Flatpak cannot run commands outside the Flatpak sandbox and stl compat add will only install STL for non-Flatpak Steam. For this, we have the STL Flatpak, that works like an add-on for Steam Flatpak.

Ah, no problem. So don't run that command when we're running in a Flatpak. The installation process for STL for Steam Flatpak shouldn't really follow any of this install script, none of the steps should be necessary. If you wanted to install STL Flatpak, you can just download and install it with one click from software centers like Discover. Maybe I need to rework how the install/uninstall script runs to exclude Flatpak?


I thought of a potential problem with the current way STL is uninstalled. Intentionally, I set the uninstall script to remove ~/.config/steamtinkerlaunch, and I think this is the right decision overall because if a user wants to uninstall STL, they're going to want it fully cleaned up from their system. But I thought of a potential case where a user might uninstall STL because they want to update. They might not be able to tell that STL simply overwrites previous installs when you download a new one. With GE-Proton, a user (like me) might uninstall the old version using ProtonUp-Qt before downloading the new one. This could be annoying, sure, if a user has a bunch of games already configured, but it could be dreadful if they have hundreds of mods installed for games! I still think removing STL's config files is the right decision, but maybe we should:

  1. Warn the user when they're removing STL that this will remove their STL config folder which includes game config files and mods
  2. Tell them that they don't need to uninstall STL to update
  3. Ask with a checkbox (unchecked by default) when they're uninstalling STL if they want to remove the STL config folder (the uninstall function already has an argument to optionally disable removing the config folder, which is used during updates)
  4. Add a note in the tool description that downloading STL will update the old install

I want to avoid a case where a user might end up losing dozens of hours worth of modding a game with STL. But equally there would be cases where a user does want to remove all of these mods by uninstalling STL. Mods can be pretty big, my own current New Vegas and Oblivion mod installs total almost 90gb! If it was me and I uninstalled STL thinking I could just reinstall and update, I would be really disheartened.

The solution I proposed might not be very clean, so I'm open to discussion on this point 馃槃

@DavidoTek
Copy link
Owner

DavidoTek commented Sep 4, 2022

First though, you check in ~/.config/steamtinkerlaunch/lang and see if the correct language file is copied over for you?
Ah, excellent! I'll fix the command now then, thank you for checking!

  • I think we should copy the english.txt as well, as it is used as a fallback.
  • Then we can change the config file, I just noticed the command doesn't actually change anything...

Maybe I need to rework how the install/uninstall script runs to exclude Flatpak?

  • We probably should just exclude STL from the install list for Flatpak. (Maybe we can set CT_LAUNCHERS to e.g. ['steam-no-flatpak'] and implement it in the ctloader...)

I thought of a potential problem with the current way STL is uninstalled.

  • Asking the user using a checkbox should work. This way the user knows exactly what will happen and it probably can be easily done in the ctmod file.

@sonic2kk
Copy link
Contributor Author

sonic2kk commented Sep 4, 2022

I think we should copy the english.txt as well, as it is used as a fallback.

Good idea!

Then we can change the config file, I just noticed the command doesn't actually change anything...

Hmm, this sounds like a bug. I'll have to look into this. In my config file on desktop (where I installed STL from source) my global config correctly sets the language. So STL is meant to set the language but doesn't for some reason. Thanks for pointing this out!

We probably should just exclude STL from the install list for Flatpak. (Maybe we can set CT_LAUNCHERS to e.g. ['steam-no-flatpak'] and implement it in the ctloader...)

So if a user is on Flatpak Steam it'll exclude STL. I guess they can just install it from their software center then? Though I thought the appstream command did that, I was under the impression that ProtonUp-Qt basically acted as a frontend to install/uninstall it.

Asking the user using a checkbox should work. This way the user knows exactly what will happen and it probably can be easily done in the ctmod file.

Should be very easy to implement, hopefully 馃槄

Oh, and as for Steam Snap support, STL doesn't currently support it and no one is currently working to support it as far a I know, so no plans in the immediate future for that. That's not something we'll need to worry about right now I think then 馃槃

@DavidoTek
Copy link
Owner

So if a user is on Flatpak Steam it'll exclude STL. I guess they can just install it from their software center then? Though I thought the appstream command did that, I was under the impression that ProtonUp-Qt basically acted as a frontend to install/uninstall it.

Yes, when Steam Flatpak is selected in ProtonUp-Qt, STL will not be displayed in the Install Compatibility Tool dialog.
Instead, STL can be installed by selecting it in the Get tool from Flathub dialog which will open the users default software center with the STL page open.

Should be very easy to implement, hopefully

Okay, just ping me if something is not clear. Something like this should work:

mb = QMessageBox()
cb = QCheckBox('Delete STL configuration')
mb.setWindowTitle('Uninstall Steam Tinker Launch')
mb.setText('STL will be removed from your system.\nDo you want the configuration to be removed?')
mb.setCheckBox(cb)
mb.exec()
delete_stl = cb.isChecked()

@sonic2kk
Copy link
Contributor Author

sonic2kk commented Sep 6, 2022

Sorry for the delay, I haven't forgotten about this PR I've just been a little busy. I'll get back around to working on it ASAP and investigating the language issues 馃憤

@DavidoTek
Copy link
Owner

I added few features and did some testing, I think the STL patch is ready now. I will merge it soon and release a new AppImage for further testing. When it is tested, I have to see which permissions are needed for the Flatpak and add them.

Thanks again for your extensive help and the PR @sonic2kk !!! 馃帀 馃帀

@sonic2kk
Copy link
Contributor Author

sonic2kk commented Sep 14, 2022

Thank you for your contributions! I had a look at the changes and I agree that it looks ready. The issue with the language not being set in the global config might be an STL bug but I'm not sure, so I think writing it in is the best solution for now. I didn't have as much time to work on the remaining issues as I would've liked due to personal matters so thanks a bunch for implementing the remaining tasks 馃憤

I'm glad we could get this into such a good state, thanks for allowing me the opportunity to contribute! 馃槃

EDIT: Asked about the locale thing to see what might be causing the issue

@sonic2kk
Copy link
Contributor Author

Ah and before I forget, there were a couple of things I wanted to mention about this way of installing STL (I'll also update the STL wiki once I have time and a way to phrase this more cleanly heh):

  • When installing on Steam Deck, STL currently seems to always automatically updates to the latest git. This might not always be the case but in my tests it seems to be.
  • Unfortunately due to a limitation of Steam, there isn't a great way to pass environment variables to Steam. So if someone wants to use STL as a launch option, they'll have to enter the path to the script manually. I wonder if it's worth the effort for us to try changing the name of the folder where stl is installed to to always be the same, so the user only has to enter /home/user/stl/blah/steamtinkerlaunch %command%. Maybe since Steam Deck always uses prefix we could just rename the folder to prefix? Not sure if its worth the effort.
    • On Steam Deck running regular SteamOS 3, the path will always be /home/deck/stl/prefix/steamtinkerlaunch, so it's not a big worry there.
    • I did investigate this issue rather deeply and even asked around to see if there's a way to run something like $(which steamtinkerlaunch) %command% but it seems like Steam simply doesn't allow for this in launch options.

Very minor details imo but for documentation purposes I wanted to mention these 馃槃

@DavidoTek
Copy link
Owner

DavidoTek commented Sep 14, 2022

Unfortunately due to a limitation of Steam, there isn't a great way to pass environment variables to Steam. So if someone wants to use STL as a launch option, they'll have to enter the path to the script manually.

Won't Steam recognize the command if it's on the system's path?

Maybe since Steam Deck always uses prefix we could just rename the folder to prefix?

We probably should do that.

PS: I have squashed all commits

@sonic2kk
Copy link
Contributor Author

Won't Steam recognize the command if it's on the system's path?

In my tests, it seems not. And from what I could ascertain this was a change made on Steam's side. I tried adding some other vars to my systems path including the .profile and Steam didn't see them. Very strange, I guess it has a hardcoded list of paths.

If you launch Steam from a terminal with those vars on your path, Steam will see them, but not otherwise. This doesn't seem specific to this PR and I'm not sure if we can do much about that 馃槂 At best it could be a regression on Valve's side, maybe I'll open a ticket at some point.

Having STL on the path is still useful for running STL from the command line e.g. adding Non-Steam games, installing Vortex/MO2 and some other stuff.

Thanks for squashing the commits! Frostworx recently pushed a commit that changes some of the language-loading logic for STL so our language problem could be fixed upstream. Though I think keeping the logic we have in place for setting the language is fine to keep to be extra safe :)

@DavidoTek
Copy link
Owner

In my tests, it seems not. And from what I could ascertain this was a change made on Steam's side. I tried adding some other vars to my systems path including the .profile and Steam didn't see them. Very strange, I guess it has a hardcoded list of paths.

Okay, then we probably can't do anything for now. Maybe adding a rule in /etc/X11/Xsession would work, but not sure about Wayland.
I will change the install dir to ~/stl/prefix then.

Frostworx recently pushed a commit that changes some of the language-loading logic for STL so our language problem could be fixed upstream.

I changed the command so that STL will change the language. Works fine.

@frostworx
Copy link

Amazing work! Thank you very much! 馃憤

@DavidoTek DavidoTek merged commit 7ce49a5 into DavidoTek:main Sep 16, 2022
@sonic2kk sonic2kk deleted the add-steamtinkerlaunch branch October 9, 2022 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants