Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion misc/requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ setuptools-scm
requests < 3.0
PySide6-Essentials >= 6.8.1
QtAwesome
legendary-gl @ https://github.com/RareDevs/legendary/archive/rare-next.zip
legendary-gl @ https://github.com/RareDevs/legendary/archive/207b859ae4476ae77466d3c922efaba90e093f12.zip
orjson
vdf @ https://github.com/solsticegamestudios/vdf/archive/be1f7220238022f8b29fe747f0b643f280bfdb6e.zip
pywin32 ; platform_system == "Windows"
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ dependencies = [
"requests < 3.0",
"PySide6-Essentials >= 6.8.1",
"QtAwesome",
"legendary-gl @ git+https://github.com/RareDevs/legendary@rare-next",
"legendary-gl @ git+https://github.com/RareDevs/legendary@207b859ae4476ae77466d3c922efaba90e093f12",
"orjson",
"vdf @ https://github.com/solsticegamestudios/vdf/archive/be1f7220238022f8b29fe747f0b643f280bfdb6e.zip",
"pywin32 ; platform_system == 'Windows'",
Expand Down
2 changes: 1 addition & 1 deletion rare/commands/launcher/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ def launch_game(self, params: LaunchParams):
self.stop()
return

if platform.system() == 'Windows' and params.is_origin_game:
if platform.system() == 'Windows' and params.is_third_party_game:
# executable is a protocol link (link2ea://launchgame/...)
QDesktopServices.openUrl(QUrl(params.executable))
self.stop() # stop because it is not a subprocess
Expand Down
22 changes: 13 additions & 9 deletions rare/commands/launcher/lgd_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,28 +52,32 @@ class LaunchParams:
environment: dict[str, str] = field(default_factory=dict)
pre_launch_command: str = ''
pre_launch_wait: bool = False
is_origin_game: bool = False # only for windows to launch as url
is_third_party_game: bool = False # only for windows to launch as url

def __bool__(self):
return bool(self.executable)


def get_origin_params(rgame: RareGameSlim, init: InitParams, launch: LaunchParams) -> LaunchParams:
def get_third_party_params(rgame: RareGameSlim, init: InitParams, launch: LaunchParams) -> LaunchParams:
core = rgame.core
app_name = rgame.app_name

origin_uri = core.get_origin_uri(app_name, init.offline)
uri = (
core.get_origin_uri(app_name, init.offline)
if rgame.is_origin
else core.get_ubisoft_uri(app_name, init.offline)
)
if platform.system() == 'Windows':
command = [origin_uri]
command = [uri]
else:
command = core.get_app_launch_command(app_name)
if not os.path.exists(command[0]) and shutil.which(command[0]) is None:
return launch
command.append(origin_uri)
command.append(uri)

exe, args, env = prepare_process(command, core.get_app_environment(app_name))

launch.is_origin_game = True
launch.is_third_party_game = True
launch.executable = exe
launch.arguments = args
launch.environment = env
Expand Down Expand Up @@ -132,7 +136,7 @@ def get_launch_params(rgame: RareGameSlim, init: InitParams = None) -> LaunchPar
if not rgame.game:
raise GameArgsError(f'Could not find metadata for {rgame.app_title}')

if rgame.is_origin:
if rgame.is_third_party:
init.offline = False
else:
if not rgame.is_installed:
Expand All @@ -143,8 +147,8 @@ def get_launch_params(rgame: RareGameSlim, init: InitParams = None) -> LaunchPar
if not os.path.exists(rgame.install_path):
raise GameArgsError('Game path does not exist')

if rgame.is_origin:
resp = get_origin_params(rgame, init, resp)
if rgame.is_third_party:
resp = get_third_party_params(rgame, init, resp)
else:
resp = get_game_params(rgame, init, resp)

Expand Down
6 changes: 3 additions & 3 deletions rare/components/tabs/library/details/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ def update_game(self, rgame: RareGame):
self.details_tab.update_game(rgame)

self.game_settings_tab.load_settings(rgame)
self.game_settings_tab.launch.setEnabled(rgame.is_installed or rgame.is_origin)
self.game_settings_tab.launch.setEnabled(rgame.is_installed or rgame.is_third_party)

if pf.system() != 'Windows':
self.compat_settings_tab.load_settings(rgame)
self.compat_settings_tab.setEnabled(rgame.is_installed or rgame.is_origin)
self.compat_settings_tab.setEnabled(rgame.is_installed or rgame.is_third_party)

self.environ_tab.load_settings(rgame)
self.environ_tab.setEnabled(rgame.is_installed or rgame.is_origin)
self.environ_tab.setEnabled(rgame.is_installed or rgame.is_third_party)

self.dlcs_tab.update_dlcs(rgame)
self.dlcs_tab.setEnabled(rgame.is_installed and bool(rgame.owned_dlcs))
Expand Down
6 changes: 5 additions & 1 deletion rare/components/tabs/library/details/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ def load_settings(self, app_name: str):

def _get_compat_path(self, compat_location: ProtonSettings.CompatLocation):
folder_name = 'default'
local_folder_name = self.rcore.get_game(self.app_name).folder_name
rgame = self.rcore.get_game(self.app_name)
if rgame.is_third_party:
local_folder_name = "Origin" if rgame.is_origin else "Ubisoft"
else:
local_folder_name = rgame.folder_name
if compat_location == ProtonSettings.CompatLocation.NONE:
if wine_prefix_dir(local_folder_name).joinpath('system.reg').is_file():
compat_location = ProtonSettings.CompatLocation.ISOLATED
Expand Down
6 changes: 4 additions & 2 deletions rare/components/tabs/library/details/details.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,10 @@ def update_game(self, rgame: RareGame):
self.ui.app_name.setText(rgame.app_name)
self.ui.dev.setText(rgame.developer)

if rgame.is_non_asset:
self.ui.install_button.setText(self.tr('Link/Launch'))
if rgame.is_non_asset or rgame.is_third_party:
self.ui.install_button.setText(
self.tr('Launch in EA App') if rgame.is_origin else self.tr('Launch in Ubisoft Connect')
)
self.ui.actions_stack.setCurrentWidget(self.ui.uninstalled_page)
else:
self.ui.install_button.setText(self.tr('Install'))
Expand Down
9 changes: 6 additions & 3 deletions rare/components/tabs/library/widgets/game_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ def __init__(self, rgame: RareGame, parent=None):
'can_launch': self.tr('Launch game'),
'is_foreign': self.tr('Launch offline'),
'has_update': self.tr('Launch without version check'),
'is_origin': self.tr('Launch/Link'),
'is_origin': self.tr('Launch in EA App'),
'is_ubisoft': self.tr('Launch in Ubisoft Connect'),
'not_can_launch': self.tr("Can't launch"),
}

Expand Down Expand Up @@ -169,7 +170,7 @@ def update_actions(self):
for action in self.actions():
self.removeAction(action)

if self.rgame.is_installed or self.rgame.is_origin:
if self.rgame.is_installed or self.rgame.is_third_party:
self.addAction(self.launch_action)
else:
self.addAction(self.install_action)
Expand All @@ -194,7 +195,7 @@ def update_actions(self):
self.addAction(self.steam_shortcut_action)

self.addAction(self.reload_action)
if self.rgame.is_installed and not self.rgame.is_origin:
if self.rgame.is_installed and not self.rgame.is_third_party:
self.addAction(self.uninstall_action)

def eventFilter(self, a0: QObject, a1: QEvent) -> bool:
Expand All @@ -216,6 +217,8 @@ def eventFilter(self, a0: QObject, a1: QEvent) -> bool:
self.ui.tooltip_label.setText(self.hover_strings['not_can_launch'])
elif self.rgame.is_origin:
self.ui.tooltip_label.setText(self.hover_strings['is_origin'])
elif self.rgame.is_ubisoft:
self.ui.tooltip_label.setText(self.hover_strings['is_ubisoft'])
elif self.rgame.has_update:
self.ui.tooltip_label.setText(self.hover_strings['has_update'])
elif self.rgame.is_foreign and self.rgame.can_run_offline:
Expand Down
6 changes: 5 additions & 1 deletion rare/components/tabs/library/widgets/list_game_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ def __init__(self, rgame: RareGame, parent=None):

self.ui.launch_btn.setEnabled(self.rgame.can_launch)

self.ui.launch_btn.setText(self.tr('Launch') if not self.rgame.is_origin else self.tr('Link/Play'))
if not self.rgame.is_third_party:
self.ui.launch_btn.setText(self.tr('Launch'))
else:
self.ui.launch_btn.setText(self.tr('Launch in EA App') if self.rgame.is_origin else self.tr('Launch in Ubisoft Connect'))

self.ui.developer_label.setText(self.rgame.developer)
# self.version_label.setVisible(self.is_installed)
if self.rgame.igame:
Expand Down
3 changes: 2 additions & 1 deletion rare/components/tabs/settings/widgets/proton.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,9 @@ def _on_tool_changed(self, index: int):
steam_environ = steam.get_steam_environment(steam_tool, self.compat_edit.text())
library_paths = steam_environ.get('STEAM_COMPAT_LIBRARY_PATHS', '')
if self.app_name != 'default' and (install_path := self.rcore.get_game(self.app_name).install_path):
game_library = os.path.dirname(install_path)
library_paths = (
':'.join([library_paths, os.path.dirname(install_path)]) if library_paths else os.path.dirname(install_path)
':'.join([library_paths, game_library]) if library_paths else game_library
)
# https://gitlab.steamos.cloud/steamrt/steam-runtime-tools/-/blob/main/docs/steam-compat-tool-interface.md#non-steam-games
steam_environ['STEAM_COMPAT_INSTALL_PATH'] = install_path
Expand Down
34 changes: 15 additions & 19 deletions rare/models/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ def __init__(
game: Game,
):
super(RareGame, self).__init__(settings, legendary_core, game)
self.__origin_install_path: str | None = None
self.__origin_install_size: int | None = None
self._third_party_install_path: str | None = None
self._third_party_install_size: int | None = None

self.image_manager = image_manager

Expand Down Expand Up @@ -251,24 +251,24 @@ def install_size(self) -> int:

@return int The size of the installation
"""
if self.is_origin:
return self.__origin_install_size if self.__origin_install_size is not None else 0
if self.is_third_party:
return self._third_party_install_size if self._third_party_install_size is not None else 0
return self.igame.install_size if self.igame is not None else 0

@property
def install_path(self) -> str | None:
if self.is_origin:
if self.is_third_party:
# TODO Linux is also C:\\...
return self.__origin_install_path
return self._third_party_install_path
return super(RareGame, self).install_path

@install_path.setter
def install_path(self, path: str) -> None:
if self.igame:
self.igame.install_path = path
self.store_igame()
elif self.is_origin:
self.__origin_install_path = path
elif self.is_third_party:
self._third_party_install_path = path

@property
def remote_version(self) -> str:
Expand Down Expand Up @@ -314,7 +314,7 @@ def is_installed(self) -> bool:

@return bool If the game should be considered installed
"""
return (self.igame is not None) or (self.is_origin and self.__origin_install_path is not None)
return (self.igame is not None) or self.is_ubisoft or self.is_origin

def set_installed(self, installed: bool) -> None:
"""!
Expand Down Expand Up @@ -450,18 +450,14 @@ def is_non_asset(self) -> bool:

@return bool If the game doesn't have assets
"""

# Asset infos are usually None, but there was a bug, that it was an empty GameAsset class
return not self.game.asset_infos or not next(iter(self.game.asset_infos.values())).app_name

return not self.game.asset_infos or not next(iter(self.game.asset_infos.values())).app_name or self.is_third_party

@property
def is_android_only(self) -> bool:
return self.is_non_asset and self.is_android

@property
def is_ubisoft(self) -> bool:
return self.game.partner_link_type == 'ubisoft'

@property
def folder_name(self) -> str:
return (
Expand Down Expand Up @@ -632,9 +628,9 @@ def tags(self, tags: tuple[str, ...]) -> None:
self.logger.debug(f'Saving tags for {self.game.app_title}: {self.metadata.tags}')
self.__save_metadata()

def set_origin_attributes(self, path: str, size: int = 0) -> None:
self.__origin_install_path = path
self.__origin_install_size = size
def set_third_party_attributes(self, path: str, size: int = 0) -> None:
self._third_party_install_path = path
self._third_party_install_size = size
if self.install_path and self.install_size:
self.signals.game.installed.emit(self.app_name)
else:
Expand All @@ -643,7 +639,7 @@ def set_origin_attributes(self, path: str, size: int = 0) -> None:

@property
def can_launch(self) -> bool:
if self.is_idle and self.is_origin:
if self.is_idle and self.is_third_party:
return True
if self.is_installed:
if (not self.is_idle) or self.needs_verification:
Expand Down
17 changes: 8 additions & 9 deletions rare/models/game_slim.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,15 @@ def is_win32(self) -> bool:

@property
def is_origin(self) -> bool:
"""!
@brief Property to report if a Game is an Origin game
return bool(self.game.is_origin_game)

Legendary and by extenstion Rare can't launch Origin games directly,
it just launches the Origin client and thus requires a bit of a special
handling to let the user know.
@property
def is_ubisoft(self) -> bool:
return bool(self.game.is_ubisoft_game)

@return bool If the game is an Origin game
"""
return self.game.third_party_store in {'Origin', 'the EA app'}
@property
def is_third_party(self) -> bool:
return self.is_origin or self.is_ubisoft

@property
def is_android(self) -> bool:
Expand Down Expand Up @@ -230,7 +229,7 @@ def __init__(self, settings: RareAppSettings, legendary_core: LegendaryCore, gam

@property
def is_installed(self) -> bool:
if self.is_origin:
if self.is_third_party:
return True
return self.igame is not None

Expand Down
14 changes: 7 additions & 7 deletions rare/shared/rare_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def __add_games_and_dlcs(self, games: list[Game], dlcs_dict: dict[str, list]) ->
# lk: since loading has to know about the game's state,
# validate installation just by trying to add each RareGame
# TODO: this should probably be moved into RareGame
if rgame.is_installed and not (rgame.is_dlc or rgame.is_non_asset):
if rgame.is_installed and not rgame.is_third_party and not (rgame.is_dlc or rgame.is_non_asset):
try:
self.__validate_install(rgame)
except FileNotFoundError as e:
Expand Down Expand Up @@ -435,14 +435,14 @@ def fetch_saves(self):
saves_worker = QRunnable.create(self.__fetch_saves)
QThreadPool.globalInstance().start(saves_worker)

def resolve_origin(self) -> None:
def resolve_third_party(self) -> None:
origin_worker = OriginWineWorker(self.__core, list(self.origin_games))
QThreadPool.globalInstance().start(origin_worker)

def __post_init(self) -> None:
if not self.__args.offline:
self.fetch_saves()
self.resolve_origin()
self.resolve_third_party()

@property
def game_tags(self) -> tuple[str, ...]:
Expand All @@ -460,19 +460,19 @@ def games_and_dlcs(self) -> Iterator[RareGame]:

@property
def games(self) -> Iterator[RareGame]:
return self.__filter_games(lambda game: not game.is_dlc or game.is_launchable_addon)
return self.__filter_games(lambda rgame: not rgame.is_dlc or rgame.is_launchable_addon)

@property
def installed_games(self) -> Iterator[RareGame]:
return self.__filter_games(lambda game: game.is_installed and not game.is_dlc)
return self.__filter_games(lambda rgame: rgame.is_installed and not rgame.is_dlc)

@property
def origin_games(self) -> Iterator[RareGame]:
return self.__filter_games(lambda game: game.is_origin and not game.is_dlc)
return self.__filter_games(lambda rgame: rgame.is_origin and not rgame.is_dlc)

@property
def ubisoft_games(self) -> Iterator[RareGame]:
return self.__filter_games(lambda game: game.is_ubisoft and not game.is_dlc)
return self.__filter_games(lambda rgame: rgame.is_ubisoft and not rgame.is_dlc)

@property
def game_list(self) -> Iterator[Game]:
Expand Down
2 changes: 1 addition & 1 deletion rare/shared/workers/wine_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def run_real(self) -> None:
if install_dir:
if os.path.isdir(install_dir):
install_size = path_size(install_dir)
rgame.set_origin_attributes(install_dir, install_size)
rgame.set_third_party_attributes(install_dir, install_size)
self.logger.info(
"Origin game '%s' (%s, %s)",
rgame.app_title,
Expand Down
1 change: 1 addition & 0 deletions rare/utils/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ def create_desktop_link(app_name: str, app_title: str = '', link_name: str = '',
desktop_file.write(
'[Desktop Entry]\n'
f'Name={app_title}\n'
f'Comment={app_title} (Rare)\n'
'Type=Application\n'
'Categories=Game;\n'
f'Icon={icon_path}\n'
Expand Down
3 changes: 2 additions & 1 deletion rare/widgets/rare_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ def __init__(self, args: Namespace, log_file: str):
self.logger = logging.getLogger(type(self).__name__)
self._hook = RareAppException(self)
self.setQuitOnLastWindowClosed(False)
self.setAttribute(Qt.ApplicationAttribute.AA_DontUseNativeDialogs, True)
use_qt_dialogs = not os.environ.get('SNAP')
self.setAttribute(Qt.ApplicationAttribute.AA_DontUseNativeDialogs, use_qt_dialogs)

self.setDesktopFileName('rare')
self.setApplicationName('Rare')
Expand Down
Loading