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

YAML and JSON-based detection for games and RCS. #11

Merged
merged 5 commits into from
Oct 10, 2020
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 LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2020 urwrstkn8mare
Copyright (c) 2020 Samit Shaikh

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
requests==2.22.0
pyyaml==5.3.1
galaxy.plugin.api==0.65.1
galaxyutils==0.1.5
3 changes: 2 additions & 1 deletion src/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ class GameID:


GAME_IDS = [GameID.legends_of_runeterra, GameID.league_of_legends, GameID.valorant]
# Registry info is still needed to detect Vanguard.
REGISTRY_START_PATHS = [winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE]
SOFTWARE_PATHS = ["SOFTWARE\\", "SOFTWARE\\WOW6432Node\\"]
UNINSTALL_REGISTRY_PATH = "Microsoft\\Windows\\CurrentVersion\\Uninstall\\"
GAME_REGISTY_PATH = {
GAME_REGISTRY_PATH = {
GameID.league_of_legends: "Riot Game league_of_legends.live",
GameID.legends_of_runeterra: "Riot Game bacon.live",
GameID.valorant: "Riot Game valorant.live",
Expand Down
107 changes: 48 additions & 59 deletions src/local.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
import winreg
import json, os, winreg

import os
from yaml import load, FullLoader

import utils.misc
from consts import (
GameID,
GAME_IDS,
REGISTRY_START_PATHS,
SOFTWARE_PATHS,
UNINSTALL_REGISTRY_PATH,
GAME_REGISTY_PATH,
GAME_REGISTRY_PATH,
UNINSTALL_STRING_KEY,
INSTALL_LOCATION_KEY,
)
import utils


class LocalClient:
def __init__(self):
self.process = dict.fromkeys(GAME_IDS, None)
self.install_location = dict.fromkeys(list(GAME_REGISTY_PATH.keys()), None)
self.riot_client_services_path = None
self._vangaurd_uninstall_path = None
self.install_location = dict.fromkeys(
list(GAME_REGISTRY_PATH.keys()), None)
self.riot_client_services_path = self.get_rcs_path()
if not os.path.isfile(self.riot_client_services_path):
self.riot_client_services_path = None
self._vanguard_uninstall_path = None

def game_running(self, game_id) -> bool:
rp = self.process[game_id] # Just an alias
Expand All @@ -35,7 +38,7 @@ def game_installed(self, game_id):
return self.install_location[game_id] is not None

def launch(self, game_id, *, save_process=True):
p = utils.open_path(
p = utils.misc.open_path(
self.riot_client_services_path,
[f"--launch-product={game_id}", "--launch-patchline=live"],
)
Expand All @@ -44,60 +47,46 @@ def launch(self, game_id, *, save_process=True):
return p

def uninstall(self, game_id):
utils.open_path(
utils.misc.open_path(
self.riot_client_services_path,
[f"--uninstall-product={game_id}", "--uninstall-patchline=live"],
)

def update_installed(self):
def get_riot_client_services_path_from_cmd(cmd):
pth = ""
found_char = False
for char in cmd.strip():
if char == '"':
if found_char:
break
else:
found_char = True
elif found_char:
pth += char
return pth
if self.riot_client_services_path == None:
self.riot_client_services_path = self.get_rcs_path()
self._vanguard_uninstall_path = None

games = list(GAME_REGISTY_PATH.keys())
if self.riot_client_services_path is not None and not os.path.isfile(
self.riot_client_services_path
):
self.riot_client_services_path = None
self._vangaurd_uninstall_path = None
for start_path in REGISTRY_START_PATHS:
for software_path in SOFTWARE_PATHS:
for game_id in games.copy():
try:
reg = winreg.ConnectRegistry(None, start_path)
with winreg.OpenKey(
reg,
software_path + UNINSTALL_REGISTRY_PATH + GAME_REGISTY_PATH[game_id],
) as key:
if (
game_id != GameID.vanguard
and self.riot_client_services_path is None
):
path = get_riot_client_services_path_from_cmd(
winreg.QueryValueEx(key, UNINSTALL_STRING_KEY)[0]
)
if not os.path.isfile(path):
path = None
self.riot_client_services_path = path
elif game_id == GameID.vanguard:
self._vangaurd_uninstall_path = os.path.abspath(
winreg.QueryValueEx(key, UNINSTALL_STRING_KEY)[0].strip('"')
)
self.install_location[game_id] = os.path.abspath(
winreg.QueryValueEx(key, INSTALL_LOCATION_KEY)[0]
)
except OSError:
continue
else:
games.remove(game_id)
for game_id in games:
self.install_location[game_id] = None
for game_id in GAME_IDS:
# Vanguard doesn't have a settings.yaml file. Need to use old registry method.
if game_id == GameID.vanguard:
for start_path in REGISTRY_START_PATHS:
for software_path in SOFTWARE_PATHS:
try:
reg = winreg.ConnectRegistry(None, start_path)
with winreg.OpenKey(reg, software_path + UNINSTALL_REGISTRY_PATH + GAME_REGISTRY_PATH[game_id]) as key:
self._vanguard_uninstall_path = os.path.abspath(
winreg.QueryValueEx(key, UNINSTALL_STRING_KEY)[0].strip('"'))
except OSError:
log.error(OSError)
continue
# Read product_install_full_path from yaml.
else:
try:
with open(utils.misc.get_product_settings_path(game_id), 'r') as file:
product_settings = load(file, Loader=FullLoader)
install_path = product_settings['product_install_full_path']
self.install_location[game_id] = os.path.abspath(
install_path)
except:
self.install_location[game_id] = None

def get_rcs_path(self):
try:
with open(utils.misc.get_riot_client_installs_path(), 'r') as file:
client_installs = json.load(file)
rcs_path = os.path.abspath(client_installs['rc_default'])
except:
rcs_path = None
pass
return rcs_path
15 changes: 8 additions & 7 deletions src/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from consts import GameID, DOWNLOAD_URL, GAME_IDS, LOCAL_FILE_CACHE
from local import LocalClient
import utils
import utils.misc
from version import __version__

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -63,11 +63,11 @@ async def get_local_games(self):
async def prepare_local_size_context(self, game_ids):
sizes = []
for game_id in GAME_IDS:
size = await utils.get_size_at_path(
size = await utils.misc.get_size_at_path(
self.local_client.install_location[game_id], if_none=0
)
if game_id == GameID.valorant:
size += await utils.get_size_at_path(
size += await utils.misc.get_size_at_path(
self.local_client.install_location[GameID.vanguard], if_none=0
)
if size == 0:
Expand All @@ -81,10 +81,11 @@ async def get_local_size(self, game_id: str, context):
async def uninstall_game(self, game_id):
self.local_client.update_installed()
self.local_client.uninstall(game_id)
if game_id == GameID.valorant and self.local_client._vangaurd_uninstall_path is not None:
utils.open_path(self.local_client._vangaurd_uninstall_path)
if game_id == GameID.valorant and self.local_client._vanguard_uninstall_path is not None:
utils.misc.open_path(self.local_client._vanguard_uninstall_path)

async def launch_game(self, game_id):
log.debug("RCS location: "+ self.local_client.riot_client_services_path)
self.local_client.update_installed()
self.local_client.launch(game_id)

Expand All @@ -101,7 +102,7 @@ async def install_game(self, game_id):
log.info("Installing game")
self.local_client.update_installed()
if self.local_client.riot_client_services_path is None:
utils.open_path(utils.download(DOWNLOAD_URL[game_id]))
utils.misc.open_path(utils.misc.download(DOWNLOAD_URL[game_id]))
else:
self.local_client.launch(game_id, save_process=False)

Expand Down Expand Up @@ -145,7 +146,7 @@ async def get_game_time(self, game_id, context):
return None

def handshake_complete(self):
utils.cleanup()
utils.misc.cleanup()
if "game_time_cache" in self.persistent_cache:
self.game_time_cache = pickle.loads(
bytes.fromhex(self.persistent_cache["game_time_cache"])
Expand Down
7 changes: 7 additions & 0 deletions src/utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ async def get_size_at_path(start_path, *, if_none=None):
log.debug(f"Size: {total_size} bytes - {start_path}")
return total_size # in bytes

def get_product_settings_path(game_id):
# Given the game ID, returns the path of the product settings yaml file.
return os.path.expandvars("%PROGRAMDATA%\\Riot Games\\Metadata\\{0}.live\\{0}.live.product_settings.yaml".format(game_id))

def get_riot_client_installs_path():
# Returns the path of the Riot Client settings yaml file.
return os.path.expandvars("%PROGRAMDATA%\\Riot Games\\RiotClientInstalls.json")

def run(cmd, *, shell=False):
log.info(f"Running: {cmd}")
Expand Down