mirror of
https://github.com/lutris/lutris
synced 2024-09-05 07:23:32 +00:00
Build a cache with game paths
This commit is contained in:
parent
cbec00994f
commit
021a687fea
|
@ -12,7 +12,7 @@ from lutris.config import duplicate_game_config
|
|||
from lutris.database.games import add_game, get_game_by_field, get_unusued_game_name
|
||||
from lutris.game import Game
|
||||
from lutris.gui import dialogs
|
||||
from lutris.gui.config.add_game import AddGameDialog
|
||||
from lutris.gui.config.add_game_dialog import AddGameDialog
|
||||
from lutris.gui.config.edit_game import EditGameConfigDialog
|
||||
from lutris.gui.dialogs import QuestionDialog
|
||||
from lutris.gui.dialogs.log import LogWindow
|
||||
|
|
|
@ -5,7 +5,7 @@ from gi.repository import Gio, GLib, Gtk
|
|||
|
||||
from lutris import api
|
||||
from lutris.exceptions import watch_errors
|
||||
from lutris.gui.config.add_game import AddGameDialog
|
||||
from lutris.gui.config.add_game_dialog import AddGameDialog
|
||||
from lutris.gui.dialogs import ErrorDialog
|
||||
from lutris.gui.dialogs.game_import import ImportGameDialog
|
||||
from lutris.gui.widgets.common import FileChooserEntry
|
||||
|
|
|
@ -2,18 +2,19 @@ from collections import OrderedDict
|
|||
from copy import deepcopy
|
||||
from gettext import gettext as _
|
||||
|
||||
from gi.repository import Gtk, GLib
|
||||
from gi.repository import GLib, Gtk
|
||||
|
||||
from lutris.config import write_game_config
|
||||
from lutris.database.games import add_game, get_games
|
||||
from lutris.database.games import add_game
|
||||
from lutris.game import Game
|
||||
from lutris.gui.dialogs import ModalDialog
|
||||
from lutris.scanners.default_installers import DEFAULT_INSTALLERS
|
||||
from lutris.scanners.lutris import add_to_path_cache, get_path_cache
|
||||
from lutris.scanners.tosec import clean_rom_name, guess_platform, search_tosec_by_md5
|
||||
from lutris.services.lutris import download_lutris_media
|
||||
from lutris.util.jobs import AsyncCall
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.strings import slugify, gtk_safe
|
||||
from lutris.util.strings import gtk_safe, slugify
|
||||
from lutris.util.system import get_md5_hash, get_md5_in_zip
|
||||
|
||||
|
||||
|
@ -87,17 +88,7 @@ class ImportGameDialog(ModalDialog):
|
|||
logger.debug('Game not launched')
|
||||
|
||||
def search_checksums(self):
|
||||
all_games = get_games()
|
||||
|
||||
def find_game(filepath):
|
||||
for db_game in all_games:
|
||||
g = Game(db_game["id"])
|
||||
if not g.config:
|
||||
continue
|
||||
for _key, value in g.config.game_config.items():
|
||||
if value == filepath:
|
||||
logger.debug("Found %s", g)
|
||||
return g
|
||||
game_path_cache = get_path_cache()
|
||||
|
||||
def show_progress(filepath, message):
|
||||
# It's not safe to directly update labels from a worker thread, so
|
||||
|
@ -108,11 +99,13 @@ class ImportGameDialog(ModalDialog):
|
|||
for filename in self.files:
|
||||
try:
|
||||
show_progress(filename, _("Looking for installed game..."))
|
||||
game = find_game(filename)
|
||||
if game:
|
||||
# Found a game to launch instead of installing, but we can't safely
|
||||
# do this on this thread.
|
||||
result = [{"name": game.name, "game": game, "roms": []}]
|
||||
if filename in game_path_cache.values():
|
||||
for game_id in game_path_cache:
|
||||
if game_path_cache[game_id] == filename:
|
||||
# Found a game to launch instead of installing, but we can't safely
|
||||
# do this on this thread.
|
||||
game = Game(game_id)
|
||||
result = [{"name": game.name, "game": game, "roms": []}]
|
||||
else:
|
||||
show_progress(filename, _("Calculating checksum..."))
|
||||
if filename.lower().endswith(".zip"):
|
||||
|
@ -206,4 +199,5 @@ class ImportGameDialog(ModalDialog):
|
|||
configpath=configpath
|
||||
)
|
||||
download_lutris_media(slug)
|
||||
add_to_path_cache(Game(game_id))
|
||||
return game_id
|
||||
|
|
|
@ -5,10 +5,11 @@ from gi.repository import Gtk, Pango
|
|||
from lutris.database.games import get_games
|
||||
from lutris.game import Game
|
||||
from lutris.gui.dialogs import ModalDialog, QuestionDialog
|
||||
from lutris.scanners.lutris import remove_from_path_cache
|
||||
from lutris.util.jobs import AsyncCall
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.strings import gtk_safe, human_size
|
||||
from lutris.util.system import get_disk_size, is_removeable, reverse_expanduser, path_exists
|
||||
from lutris.util.system import get_disk_size, is_removeable, path_exists, reverse_expanduser
|
||||
|
||||
|
||||
class UninstallGameDialog(ModalDialog):
|
||||
|
@ -99,6 +100,7 @@ class UninstallGameDialog(ModalDialog):
|
|||
self.folder_label.set_markup(_("Uninstalling game and deleting files..."))
|
||||
else:
|
||||
self.folder_label.set_markup(_("Uninstalling game..."))
|
||||
remove_from_path_cache(self.game)
|
||||
self.game.remove(self.delete_files)
|
||||
self.destroy()
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ from lutris.gui.widgets.game_bar import GameBar
|
|||
from lutris.gui.widgets.gi_composites import GtkTemplate
|
||||
from lutris.gui.widgets.sidebar import LutrisSidebar
|
||||
from lutris.gui.widgets.utils import load_icon_theme, open_uri
|
||||
from lutris.scanners.lutris import remove_from_path_cache
|
||||
# pylint: disable=no-member
|
||||
from lutris.services.base import BaseService
|
||||
from lutris.services.lutris import LutrisService
|
||||
|
@ -132,7 +133,7 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
GObject.add_emission_hook(BaseService, "service-games-loaded", self.on_service_games_updated)
|
||||
GObject.add_emission_hook(Game, "game-updated", self.on_game_updated)
|
||||
GObject.add_emission_hook(Game, "game-stopped", self.on_game_stopped)
|
||||
GObject.add_emission_hook(Game, "game-removed", self.on_game_collection_changed)
|
||||
GObject.add_emission_hook(Game, "game-removed", self.on_game_removed)
|
||||
GObject.add_emission_hook(Game, "game-unhandled_error", self.on_game_unhandled_error)
|
||||
|
||||
def _init_actions(self):
|
||||
|
@ -874,9 +875,11 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
self.game_store.remove_game(game.id)
|
||||
return True
|
||||
|
||||
def on_game_collection_changed(self, _sender):
|
||||
def on_game_removed(self, game):
|
||||
"""Simple method used to refresh the view"""
|
||||
remove_from_path_cache(game)
|
||||
self.emit("view-updated")
|
||||
|
||||
return True
|
||||
|
||||
@watch_errors()
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
import json
|
||||
import os
|
||||
import time
|
||||
|
||||
from lutris import settings
|
||||
from lutris.api import get_api_games, get_game_installers
|
||||
from lutris.database.games import get_games
|
||||
from lutris.game import Game
|
||||
from lutris.installer.errors import MissingGameDependency
|
||||
from lutris.installer.interpreter import ScriptInterpreter
|
||||
from lutris.services.lutris import download_lutris_media
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.strings import slugify
|
||||
|
||||
GAME_PATH_CACHE_PATH = os.path.join(settings.CACHE_DIR, "game-paths.json")
|
||||
|
||||
|
||||
def get_game_slugs_and_folders(dirname):
|
||||
"""Scan a directory for games previously installed with lutris"""
|
||||
|
@ -95,3 +101,67 @@ def scan_directory(dirname):
|
|||
installed_map = {slug: folder for slug, folder in slugs_map.items() if slug in slugs_installed}
|
||||
missing_map = {slug: folder for slug, folder in slugs_map.items() if slug not in slugs_installed}
|
||||
return installed_map, missing_map
|
||||
|
||||
|
||||
def get_path_from_config(game):
|
||||
"""Return the path of the main entry point for a game"""
|
||||
if not game.config:
|
||||
logger.warning("Game %s has no configuration", game)
|
||||
return ""
|
||||
for key in ["exe", "main_file", "iso", "rom"]:
|
||||
if key in game.config.game_config:
|
||||
path = game.config.game_config[key]
|
||||
if not path.startswith("/"):
|
||||
path = os.path.join(game.directory, path)
|
||||
return path
|
||||
logger.warning("No path found in %s", game.config)
|
||||
return ""
|
||||
|
||||
|
||||
def get_game_paths():
|
||||
game_paths = {}
|
||||
all_games = get_games(filters={'installed': 1})
|
||||
for db_game in all_games:
|
||||
game = Game(db_game["id"])
|
||||
path = get_path_from_config(game)
|
||||
if not path:
|
||||
logger.warning("Game %s has no path", game)
|
||||
continue
|
||||
game_paths[db_game["id"]] = path
|
||||
return game_paths
|
||||
|
||||
|
||||
def build_path_cache():
|
||||
"""Generate a new cache path"""
|
||||
start_time = time.time()
|
||||
with open(GAME_PATH_CACHE_PATH, "w", encoding="utf-8") as cache_file:
|
||||
game_paths = get_game_paths()
|
||||
json.dump(game_paths, cache_file, indent=2)
|
||||
end_time = time.time()
|
||||
logger.debug("Game path cache built in %0.2f seconds", end_time - start_time)
|
||||
|
||||
|
||||
def add_to_path_cache(game):
|
||||
path = get_path_from_config(game)
|
||||
if not path:
|
||||
logger.warning("No path for %s", game)
|
||||
return
|
||||
current_cache = get_path_cache()
|
||||
current_cache[game.id] = path
|
||||
with open(GAME_PATH_CACHE_PATH, "w", encoding="utf-8") as cache_file:
|
||||
json.dump(current_cache, cache_file, indent=2)
|
||||
|
||||
|
||||
def remove_from_path_cache(game):
|
||||
current_cache = get_path_cache()
|
||||
if game.id not in current_cache:
|
||||
return
|
||||
del current_cache[game.id]
|
||||
with open(GAME_PATH_CACHE_PATH, "w", encoding="utf-8") as cache_file:
|
||||
json.dump(current_cache, cache_file, indent=2)
|
||||
|
||||
|
||||
def get_path_cache():
|
||||
"""Return the contents of the path cache file"""
|
||||
with open(GAME_PATH_CACHE_PATH, encoding="utf-8") as cache_file:
|
||||
return json.load(cache_file)
|
||||
|
|
|
@ -17,6 +17,7 @@ from lutris.game import Game
|
|||
from lutris.gui.dialogs import DontShowAgainDialog
|
||||
from lutris.runners.json import load_json_runners
|
||||
from lutris.runtime import RuntimeUpdater
|
||||
from lutris.scanners.lutris import build_path_cache
|
||||
from lutris.services import DEFAULT_SERVICES
|
||||
from lutris.services.lutris import sync_media
|
||||
from lutris.util.graphics import drivers, vkquery
|
||||
|
@ -202,6 +203,7 @@ def init_lutris():
|
|||
if not settings.read_setting(service, section="services"):
|
||||
settings.write_setting(service, True, section="services")
|
||||
cleanup_games()
|
||||
build_path_cache()
|
||||
|
||||
|
||||
class StartupRuntimeUpdater(RuntimeUpdater):
|
||||
|
|
|
@ -2,7 +2,7 @@ from unittest import TestCase
|
|||
|
||||
from lutris import runners
|
||||
from lutris.gui.application import Application
|
||||
from lutris.gui.config.add_game import AddGameDialog
|
||||
from lutris.gui.config.add_game_dialog import AddGameDialog
|
||||
# from lutris import settings
|
||||
from lutris.gui.config.common import GameDialogCommon
|
||||
from lutris.gui.views.store import sort_func
|
||||
|
|
Loading…
Reference in a new issue