DavidoTek / ProtonUp-Qt

Install and manage GE-Proton, Luxtorpeda & more for Steam and Wine-GE & more for Lutris with this graphical user interface.
https://davidotek.github.io/protonup-qt
GNU General Public License v3.0
1.18k stars 39 forks source link

Heroic: Add Wine-tkg and Proton-tkg sources #233

Closed sonic2kk closed 1 year ago

sonic2kk commented 1 year ago

Implements part of a request from #232 to add Wine-tkg sources to Heroic, and also includes Proton-tkg sources for Heroic as well.

Overview

Only Lutris supports Wine-tkg sources, and Steam only supports Proton-tkg sources. This PR enables Wine-tkg downloads for Heroic Wine, as well as Proton-tkg for Heroic Proton. Let the Heroic frogs be free! :frog:

I explained in #191 that Proton isn't really meant for use outside of Steam, but for Heroic Proton we already facilitate downloading GE-Proton. Heroic has been acting up a little for me and it's a bit late at time of writing so I haven't checked, but I think Heroic actually looks for the Steam Linux Runtime when using Proton (which is a little unconventional, but SteamTinkerLaunch does the same, so it should be fine). I am not certain that Lutris does it or if it does I didn't see it when I skimmed the options (running lutris-git from the AUR). Also, Proton-tkg was once upon a time not built against the Steam Linux Runtime. I'm not sure if that is still the case as I don't see the note on the Readme anymore and didn't check the git history on this file.

Implementation

The Wine-tkg extraction directory was hardcoded in #178 to refer to the Lutris install directory (../../runners/wine). Some changes were needed to facilitate Heroic support. The solution I came to was to check if install_dir has lutris/runners in the name and if it does, then use the existing logic to build the Lutris extract dir. Otherwise default to install_dir. This saves having to do any sort of passing of the current launcher, as it can be inferred.

I think this check is fine as I don't think the path to Heroic Wine could ever include lutris/runners. In other words I believe the only time this should be the case is if a user is installing Tkg for Lutris. I initially just checked for 'lutris' in install_dir and then I realised a given username might be or contain lutris, so I went with the more explicit check for this directory structure. Looking at the constants.py file this should work for Lutris Flatpak (~/.var/app/net.lutris.Lutris/data/lutris/runners) and AppImage/package manager Lutris (~/.local/share/lutris/runners/wine/).

Side note: A similar implementation may be possible for D8VK for Heroic as requested in #208, i.e. dxvk_dir = os.path.join(install_dir, '../../runtime/dxvk') if 'lutris/runtime' in install_dir else install_dir. I haven't tested this though and other considerations may be needed for that (i.e. heroictools` option, but that's a separate matter entirely).


Once the fallback to install_dir when installing outside of Lutris was in place, things seem to just work. In my brief testing I didn't encounter anything (though it is kinda late for me, might've missed something). I also haven't tested how these tools work with Heroic, but since Heroic can see them once downloaded and since the folder structure is correct (it should be able to find the Wine binary) I don't see why it would run into any issues :-)

Thanks!


P.S. - When testing I noticed that while the different Tkg builds have different naming conventions, it isn't always clear which version of Wine-tkg/Proton-tkg refers to which ctmod. This could be changed on our end but may not be absolutely necessary as I think generally we just stick to whatever the extracted archive name does, which is what would happen if a user installed the tool manually.

DavidoTek commented 1 year ago

but for Heroic Proton we already facilitate downloading GE-Proton [...] I think Heroic actually looks for the Steam Linux Runtime when using Proton

Yeah, Heroic seems to have better support for Proton that Lutris.

The solution I came to was to check if install_dir has lutris/runners in the name [...] I initially just checked for 'lutris' in install_dir and then I realised a given username might be or contain lutris

Good thought!

A similar implementation may be possible for D8VK for Heroic as requested in #208

That would be a simple solution for the problem. We should consider that.

it isn't always clear which version of Wine-tkg/Proton-tkg refers to which ctmod

As you said, sticking to the name of the archive seems to be the best. If it shouldn't be clear for some reason, there is still the CT_DESCRIPTION and a link in the ctmod.

sonic2kk commented 1 year ago

I am just thinking, if we are going to use this approach of inferring the launcher based on install_dir for this and for DXVK/D8VK/etc, maybe we should put this in a separate method call in the ctmod. Something like get_ext_dir? Not sure, just thinking this might be cleaner long-term and increase consistency between ctmods.

DavidoTek commented 1 year ago

maybe we should put this in a separate method call in the ctmod. Something like get_ext_dir?

Yeah, that would be a simple/good solution without needing to redesign the list of launchers in constants.py or install_loc.

It could accept the install_loc (install_dir and launcher type) and the compatibility tool (e.g. proton, wine, dxvk, d8vk, ...) and return a valid path to the folder. Example:

> install_loc = {'install_dir': '~/.config/heroic/tools/proton/', 'launcher': 'heroicproton', 'type': 'native'}
> nice_method (install_loc, 'dxvk')
'~/.config/heroic/tools/dxvk/'
sonic2kk commented 1 year ago

I was tinkering around and went with a more basic approach but I can refactor it to be how you described if needs be. It just takes the install_dir inside the ctmod and is called from get_tool, and does what the ternary previously did but with (hopefully) a bit more clarity.

The method is inside the ctmod and the idea is that each ctmod would implement this. I have a couple of reasons for this:

For Proton-tkg, there are currently only two cases: Lutris and Heroic. It currently only checks for Lutris since that's the only launcher with a custom path, and then else returns install_dir untouched. If we expand this to maybe Bottles or any other potential launcher in the future that might have a custom path, this method can be expanded.

Really the idea here is for some extra clarity and some flexibility + future-proofing :-)

DavidoTek commented 1 year ago

Thanks.

Yeah, I guess we can determine the launcher from the install_dir and if each ctmod implements it's own get_exact_dir method, that's fine too (and keeps the logic for one ctmod in it's file).

Subclasses of ctmods could override this method if they need it

Sounds reasonable.

It currently only checks for Lutris since that's the only launcher with a custom path if 'lutris/runners' in install_dir: tkg_dir = os.path.join(install_dir, '../../runners/wine')

Really the idea here is for some extra clarity and some flexibility + future-proofing :-)

I'm currently wondering, is there any instance for Wine-Tkg where install_dir wouldn't be .../lutris/runners/wine in the first place? But as you said, it is great for extending and should allow for something like D8VK for Heroic.


I think it can be merged for now, I will do that tomorrow.

sonic2kk commented 1 year ago

I'm currently wondering, is there any instance for Wine-Tkg where install_dir wouldn't be .../lutris/runners/wine in the first place?

Ah this is a good point. Since the launcher path is /path/to/lutris/runners/wine to begin with, we shouldn't actually need the os.path.join(install_dir, '../../runners/wine'). I just checked for Lutris at least and install_dir is correct without needing that ../...

From looking at the file history this seems to be something silly I introduced (6c99d0ee78da8a08144b0369e7b35694b93824e8). If I recall correctly I used an existing ctmod's extraction as a reference, maybe DXVK or something, and incorrectly copied the ../../runtime/dxvk.

For D8VK though it would make sense to have a method like this, so if nothing else this was a learning exercise :-)