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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Locate and use anticheat runtimes from Steam with Proton #455

Merged
merged 4 commits into from
Sep 19, 2024
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 rare/components/tabs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from rare.utils.misc import qta_icon, ExitCodes
from .account import AccountWidget
from .downloads import DownloadsTab
from .games import GamesLibrary
from .library import GamesLibrary
from .settings import SettingsTab
from .store import StoreTab
from .tab_widgets import MainTabBar, TabButtonWidget
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@
)
from rare.shared import RareCore
from rare.models.options import options
from .game_info import GameInfoTabs
from .game_widgets import LibraryWidgetController, LibraryFilter, LibraryOrder, LibraryView
from .game_widgets.icon_game_widget import IconGameWidget
from .game_widgets.list_game_widget import ListGameWidget
from .details import GameInfoTabs
from .widgets import LibraryWidgetController, LibraryFilter, LibraryOrder, LibraryView
from .head_bar import LibraryHeadBar
from .integrations import IntegrationsTabs

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from rare.shared.workers.wine_resolver import WinePathResolver
from rare.ui.components.tabs.games.integrations.egl_sync_group import Ui_EGLSyncGroup
from rare.ui.components.tabs.games.integrations.egl_sync_list_group import Ui_EGLSyncListGroup
from rare.utils.compat import utils as compat_utils
from rare.widgets.elide_label import ElideLabel
from rare.widgets.indicator_edit import PathEdit, IndicatorReasonsCommon

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
QPushButton,
)

from rare.utils.misc import qta_icon, widget_object_name
from rare.utils.misc import qta_icon
from rare.widgets.elide_label import ElideLabel


Expand Down
2 changes: 2 additions & 0 deletions rare/components/tabs/settings/rare.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ def __init__(self, parent=None):
self.ui.confirm_start.stateChanged.connect(
lambda: self.settings.setValue(options.confirm_start.key, self.ui.confirm_start.isChecked())
)
# TODO: implement use when starting game, disable for now
self.ui.confirm_start.setDisabled(True)

self.ui.auto_sync_cloud.setChecked(self.settings.value(*options.auto_sync_cloud))
self.ui.auto_sync_cloud.stateChanged.connect(
Expand Down
6 changes: 3 additions & 3 deletions rare/models/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from rare.shared.image_manager import ImageManager
from rare.utils.paths import data_dir, get_rare_executable
from rare.utils.steam_grades import get_rating
from rare.utils.config_helper import set_envvar
from rare.utils.config_helper import set_envvar, get_option

logger = getLogger("RareGame")

Expand Down Expand Up @@ -567,9 +567,9 @@ def launch(
cmd_line = get_rare_executable()
executable, args = cmd_line[0], cmd_line[1:]
args.extend(["launch", self.app_name])
if offline:
if offline or get_option(self.app_name, "offline", fallback=None):
args.append("--offline")
if skip_update_check:
if skip_update_check or get_option(self.app_name, "skip_update_check", fallback=None):
args.append("--skip-update-check")
if wine_bin:
args.extend(["--wine-bin", wine_bin])
Expand Down
2 changes: 1 addition & 1 deletion rare/resources/static_css/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x1a\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x906&\x0a\x17\
\x00\x00\x01\x92\x09g[\xe6\
"

def qInitResources():
Expand Down
8 changes: 4 additions & 4 deletions rare/resources/static_css/stylesheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def css_name(widget: Union[wrappertype, QObject, Type], subwidget: str = ""):


# ProgressLabel
from rare.components.tabs.games.game_widgets.library_widget import ProgressLabel
from rare.components.tabs.library.widgets.library_widget import ProgressLabel
css.QLabel[css_name(ProgressLabel)].setValues(
borderWidth="1px",
borderRadius="5%",
Expand All @@ -93,7 +93,7 @@ def css_name(widget: Union[wrappertype, QObject, Type], subwidget: str = ""):


# IconGameWidget
from rare.components.tabs.games.game_widgets.icon_widget import IconWidget
from rare.components.tabs.library.widgets.icon_widget import IconWidget
icon_background_props = {
"backgroundColor": "rgba(0, 0, 0, 65%)",
}
Expand Down Expand Up @@ -135,7 +135,7 @@ def css_name(widget: Union[wrappertype, QObject, Type], subwidget: str = ""):


# ListGameWidget
from rare.components.tabs.games.game_widgets.list_widget import ListWidget
from rare.components.tabs.library.widgets.list_widget import ListWidget
css.QLabel[css_name(ListWidget, "TitleLabel")].fontWeight.setValue("bold")
list_status_label_props = {
"color": "white",
Expand All @@ -155,7 +155,7 @@ def css_name(widget: Union[wrappertype, QObject, Type], subwidget: str = ""):


# SelectViewWidget
from rare.components.tabs.games.head_bar import SelectViewWidget
from rare.components.tabs.library.head_bar import SelectViewWidget
css.QPushButton[css_name(SelectViewWidget, "Button")].setValues(
border="none",
backgroundColor="transparent",
Expand Down
70 changes: 68 additions & 2 deletions rare/utils/compat/steam.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,32 @@ def appid(self) -> str:
return self.appmanifest["AppState"]["appid"]


@dataclass
class SteamAntiCheat:
steam_path: str
tool_path: str
steam_library: str
appmanifest: Dict

def __eq__(self, other):
return self.tool_path == other.tool_path

def __hash__(self):
return hash(self.tool_path)

@property
def name(self) -> str:
return self.appmanifest["AppState"]["name"]

@property
def appid(self) -> str:
return self.appmanifest["AppState"]["appid"]


@dataclass
class ProtonTool(SteamRuntime):
runtime: SteamRuntime = None
anticheat: Dict[str, SteamAntiCheat] = None

def __bool__(self) -> bool:
if appid := self.required_tool:
Expand All @@ -121,6 +144,7 @@ def command(self, verb: SteamVerb = SteamVerb.DEFAULT) -> List[str]:
class CompatibilityTool(SteamBase):
compatibilitytool: Dict
runtime: SteamRuntime = None
anticheat: Dict[str, SteamAntiCheat] = None

def __bool__(self) -> bool:
if appid := self.required_tool:
Expand All @@ -147,6 +171,33 @@ def find_appmanifests(library: str) -> List[dict]:
return appmanifests


ANTICHEAT_RUNTIMES = {
"eac_runtime": "1826330",
"battleye_runtime": "1161040",
}


def find_anticheat(steam_path: str, library: str):
runtimes = {}
appmanifests = find_appmanifests(library)
common = os.path.join(library, "common")
for appmanifest in appmanifests:
if appmanifest["AppState"]["appid"] not in ANTICHEAT_RUNTIMES.values():
continue
folder = appmanifest["AppState"]["installdir"]
runtimes.update(
{
appmanifest["AppState"]["appid"]: SteamAntiCheat(
steam_path=steam_path,
steam_library=library,
appmanifest=appmanifest,
tool_path=os.path.join(common, folder),
)
}
)
return runtimes


def find_runtimes(steam_path: str, library: str) -> Dict[str, SteamRuntime]:
runtimes = {}
appmanifests = find_appmanifests(library)
Expand Down Expand Up @@ -257,7 +308,7 @@ def get_runtime(
return runtimes.get(required_tool, None)


def get_ulwgl_environment(
def get_umu_environment(
tool: Optional[ProtonTool] = None, compat_path: Optional[str] = None
) -> Dict:
# If the tool is unset, return all affected env variable names
Expand Down Expand Up @@ -287,6 +338,8 @@ def get_steam_environment(
environ["STEAM_COMPAT_LIBRARY_PATHS"] = ""
environ["STEAM_COMPAT_MOUNTS"] = ""
environ["STEAM_COMPAT_TOOL_PATHS"] = ""
environ["PROTON_EAC_RUNTIME"] = ""
environ["PROTON_BATTLEYE_RUNTIME"] = ""
return environ

environ["STEAM_COMPAT_CLIENT_INSTALL_PATH"] = tool.steam_path
Expand All @@ -299,6 +352,11 @@ def get_steam_environment(
if tool.runtime is not None:
tool_paths.append(tool.runtime.tool_path)
environ["STEAM_COMPAT_TOOL_PATHS"] = ":".join(tool_paths)
if tool.anticheat is not None:
if (appid := ANTICHEAT_RUNTIMES["eac_runtime"]) in tool.anticheat.keys():
environ["PROTON_EAC_RUNTIME"] = tool.anticheat[appid].tool_path
if (appid := ANTICHEAT_RUNTIMES["battleye_runtime"]) in tool.anticheat.keys():
environ["PROTON_BATTLEYE_RUNTIME"] = tool.anticheat[appid].tool_path
return environ


Expand All @@ -317,6 +375,10 @@ def _find_tools() -> List[Union[ProtonTool, CompatibilityTool]]:
for library in steam_libraries:
runtimes.update(find_runtimes(steam_path, library))

anticheat = {}
for library in steam_libraries:
anticheat.update(find_anticheat(steam_path, library))

tools = []
for library in steam_libraries:
tools.extend(find_protons(steam_path, library))
Expand All @@ -325,6 +387,8 @@ def _find_tools() -> List[Union[ProtonTool, CompatibilityTool]]:
for tool in tools:
runtime = get_runtime(tool, runtimes)
tool.runtime = runtime
if tool.layer == "proton":
tool.anticheat = anticheat

tools = list(filter(lambda t: bool(t), tools))

Expand Down Expand Up @@ -353,10 +417,12 @@ def find_umu_launcher() -> Optional[CompatibilityTool]:
from pprint import pprint

tools = find_tools()
pprint(tools)
for tool in tools:
pprint(tool)
umu = find_umu_launcher()
pprint(umu)


for tool in tools:
print(get_steam_environment(tool))
print(tool.name)
Expand Down