Example #1
0
 def test_game_with_same_slug_is_updated(self):
     games_db.add_game(name="some game", runner="linux")
     game = games_db.get_game_by_field("some-game", "slug")
     self.assertFalse(game['directory'])
     games_db.add_or_update(name="some game", runner='linux', directory="/foo")
     game = games_db.get_game_by_field("some-game", "slug")
     self.assertEqual(game['directory'], '/foo')
Example #2
0
    def _get_installed_dependency(dependency):
        """Return whether a dependency is installed"""
        game = get_game_by_field(dependency, field="installer_slug")

        if not game:
            game = get_game_by_field(dependency, "slug")
        if bool(game) and bool(game["directory"]):
            return game
Example #3
0
    def _get_game_dependency(dependency):
        """Return a game database row from a dependency name"""
        game = get_game_by_field(dependency, field="installer_slug")
        if not game:
            game = get_game_by_field(dependency, "slug")

        # Game must be installed and have a directory
        # set so we can use that as the destination
        if game and game["installed"] and game["directory"]:
            return game
Example #4
0
 def install_from_steam(self, manifest):
     """Create a new Lutris game based on an existing Steam install"""
     if not manifest.is_installed():
         return
     appid = manifest.steamid
     if appid in self.excluded_appids:
         return
     service_game = ServiceGameCollection.get_game(self.id, appid)
     if not service_game:
         return
     lutris_game_id = "%s-%s" % (self.id, appid)
     existing_game = get_game_by_field(lutris_game_id, "slug")
     if existing_game:
         return
     game_config = LutrisConfig().game_level
     game_config["game"]["appid"] = appid
     configpath = write_game_config(lutris_game_id, game_config)
     game_id = add_game(
         name=service_game["name"],
         runner="steam",
         slug=slugify(service_game["name"]),
         installed=1,
         installer_slug=lutris_game_id,
         configpath=configpath,
         platform="Linux",
         service=self.id,
         service_id=appid,
     )
     return game_id
Example #5
0
    def get_game_config(self):
        """Return the game configuration"""
        if self.requires:
            # Load the base game config
            required_game = get_game_by_field(self.requires, field="installer_slug")
            base_config = LutrisConfig(
                runner_slug=self.runner, game_config_id=required_game["configpath"]
            )
            config = base_config.game_level
        else:
            config = {"game": {}}

        # Config update
        if "system" in self.script:
            config["system"] = self._substitute_config(self.script["system"])
        if self.runner in self.script and self.script[self.runner]:
            config[self.runner] = self._substitute_config(self.script[self.runner])
        launcher, launcher_config = self.get_game_launcher_config(self.interpreter.game_files)
        if launcher:
            config["game"][launcher] = launcher_config

        if "game" in self.script:
            try:
                config["game"].update(self.script["game"])
            except ValueError:
                raise ScriptingError("Invalid 'game' section", self.script["game"])
            config["game"] = self._substitute_config(config["game"])
            if AUTO_ELF_EXE in config["game"].get("exe", ""):
                config["game"]["exe"] = find_linux_game_executable(self.interpreter.target_path,
                                                                   make_executable=True)
            elif AUTO_WIN32_EXE in config["game"].get("exe", ""):
                config["game"]["exe"] = find_windows_game_executable(self.interpreter.target_path)

        return config
Example #6
0
 def install_from_origin(self, origin_game, manifest):
     offer_id = manifest["id"].split("@")[0]
     logger.debug("Installing Origin game %s", offer_id)
     service_game = ServiceGameCollection.get_game("origin", offer_id)
     if not service_game:
         logger.error(
             "Aborting install, %s is not present in the game library.",
             offer_id)
         return
     lutris_game_id = slugify(service_game["name"]) + "-" + self.id
     existing_game = get_game_by_field(lutris_game_id, "installer_slug")
     if existing_game:
         return
     game_config = LutrisConfig(
         game_config_id=origin_game["configpath"]).game_level
     game_config["game"]["args"] = get_launch_arguments(manifest["id"])
     configpath = write_game_config(lutris_game_id, game_config)
     game_id = add_game(
         name=service_game["name"],
         runner=origin_game["runner"],
         slug=slugify(service_game["name"]),
         directory=origin_game["directory"],
         installed=1,
         installer_slug=lutris_game_id,
         configpath=configpath,
         service=self.id,
         service_id=offer_id,
     )
     return game_id
Example #7
0
 def get_game_id(self):
     """Return the ID of the game in the local DB if one exists"""
     # If the game is in the library and uninstalled, the first installation
     # updates it
     existing_game = get_game_by_field(self.game_slug, "slug")
     if existing_game and not existing_game["installed"]:
         return existing_game["id"]
Example #8
0
 def install_from_egs(self, egs_game, manifest):
     """Create a new Lutris game based on an existing EGS install"""
     app_name = manifest["AppName"]
     logger.debug("Installing EGS game %s", app_name)
     service_game = ServiceGameCollection.get_game("egs", app_name)
     if not service_game:
         logger.error("Aborting install, %s is not present in the game library.", app_name)
         return
     lutris_game_id = slugify(service_game["name"]) + "-" + self.id
     existing_game = get_game_by_field(lutris_game_id, "installer_slug")
     if existing_game:
         return
     game_config = LutrisConfig(game_config_id=egs_game["configpath"]).game_level
     game_config["game"]["args"] = get_launch_arguments(app_name)
     configpath = write_game_config(lutris_game_id, game_config)
     game_id = add_game(
         name=service_game["name"],
         runner=egs_game["runner"],
         slug=slugify(service_game["name"]),
         directory=egs_game["directory"],
         installed=1,
         installer_slug=lutris_game_id,
         configpath=configpath,
         service=self.id,
         service_id=app_name,
     )
     return game_id
Example #9
0
    def on_game_selection_changed(self, view, selection):
        if not selection:
            GLib.idle_add(self.update_revealer)
            return False
        game_id = view.get_model().get_value(selection, COL_ID)
        if not game_id:
            GLib.idle_add(self.update_revealer)
            return False
        if self.service:
            game = ServiceGameCollection.get_game(self.service.id, game_id)
        else:
            game = games_db.get_game_by_field(int(game_id), "id")
        if not game:
            game = {
                "id": game_id,
                "appid": game_id,
                "name": view.get_model().get_value(selection, COL_NAME),
                "slug": game_id,
                "service": self.service.id if self.service else None,
            }
            logger.warning("No game found. Replacing with placeholder %s",
                           game)

        GLib.idle_add(self.update_revealer, game)
        return False
Example #10
0
 def __init__(self, config=None):
     """Initialize runner."""
     self.config = config
     if config:
         self.game_data = get_game_by_field(self.config.game_config_id, "configpath")
     else:
         self.game_data = {}
Example #11
0
    def install_from_ubisoft(self, ubisoft_connect, game):
        app_name = game["name"]

        lutris_game_id = slugify(game["name"]) + "-" + self.id
        existing_game = get_game_by_field(lutris_game_id, "installer_slug")
        if existing_game:
            logger.debug("Ubisoft Connect game %s is already installed",
                         app_name)
            return
        logger.debug("Installing Ubisoft Connect game %s", app_name)
        game_config = LutrisConfig(
            game_config_id=ubisoft_connect["configpath"]).game_level
        game_config["game"]["args"] = f"uplay://launch/{game['appid']}"
        configpath = write_game_config(lutris_game_id, game_config)
        game_id = add_game(
            name=game["name"],
            runner=self.runner,
            slug=slugify(game["name"]),
            directory=ubisoft_connect["directory"],
            installed=1,
            installer_slug=lutris_game_id,
            configpath=configpath,
            service=self.id,
            service_id=game["appid"],
        )
        return game_id
Example #12
0
    def play(self):
        launch_info = {}
        launch_info["env"] = self.get_env(os_env=False)

        game_data = get_game_by_field(self.config.game_config_id, "configpath")

        command = self.launch_args

        if self.is_native:
            if not self.runner_config.get("splore"):
                command.append("-run")
            cartPath = self.cart_path
            if not os.path.exists(cartPath):
                return {"error": "FILE_NOT_FOUND", "file": cartPath}
            command.append(cartPath)

        else:
            command.append("--name")
            command.append(game_data.get("name") + " - PICO-8")

            # icon = datapath.get_icon_path(game_data.get("slug"))
            # if icon:
            #     command.append("--icon")
            #     command.append(icon)

            webargs = {
                "cartridge": self.cart_path,
                "engine": self.engine_path,
                "fullscreen": self.runner_config.get("fullscreen") is True,
            }
            command.append("--execjs")
            command.append("load_config(" + json.dumps(webargs) + ")")

        launch_info["command"] = command
        return launch_info
Example #13
0
    def on_game_duplicate(self, _widget):
        confirm_dlg = QuestionDialog({
            "parent":
            self.window,
            "question":
            _("Do you wish to duplicate %s?\nThe configuration will be duplicated, "
              "but the games files will <b>not be duplicated</b>.") %
            gtk_safe(self.game.name),
            "title":
            _("Duplicate game?"),
        })
        if confirm_dlg.result != Gtk.ResponseType.YES:
            return

        assigned_name = get_unusued_game_name(self.game.name)
        old_config_id = self.game.game_config_id
        if old_config_id:
            new_config_id = duplicate_game_config(self.game.slug,
                                                  old_config_id)
        else:
            new_config_id = None

        db_game = get_game_by_field(self.game.id, "id")
        db_game["name"] = assigned_name
        db_game["configpath"] = new_config_id
        db_game.pop("id")
        # Disconnect duplicate from service- there should be at most
        # 1 PGA game for a service game.
        db_game.pop("service", None)
        db_game.pop("service_id", None)

        game_id = add_game(**db_game)
        new_game = Game(game_id)
        new_game.save()
Example #14
0
 def on_game_activated(self, view, game_id):
     """Handles view activations (double click, enter press)"""
     if self.service:
         if self.service.id != "lutris":
             db_game = games_db.get_game_for_service(
                 self.service.id, game_id)
             if db_game:
                 game_id = db_game["id"]
             else:
                 db_game = ServiceGameCollection.get_game(
                     self.service.id, game_id)
                 if db_game:
                     game_id = self.service.install(db_game)
                 else:
                     game_id = self.service.install(game_id)
         else:
             db_game = games_db.get_game_by_field(game_id)
             if not db_game:
                 self.service.install(game_id)
                 return
             if db_game["installed"] != 1:
                 self.service.install(game_id)
                 return
             game_id = db_game["id"]
     if game_id:
         game = Game(game_id)
         game.emit("game-launch")
Example #15
0
 def on_game_install_dlc(self, game):
     service = get_enabled_services()[game.service]()
     db_game = games_db.get_game_by_field(game.id, "id")
     installers = service.get_dlc_installers(db_game)
     if installers:
         self.show_installer_window(installers, service, game.appid)
     else:
         ErrorDialog(_("No DLC found"))
     return True
Example #16
0
 def on_game_selection_changed(self, view, game_id):
     if not game_id:
         GLib.idle_add(self.update_revealer)
         return False
     if self.service:
         game = ServiceGameCollection.get_game(self.service.id, game_id)
     else:
         game = games_db.get_game_by_field(int(game_id), "id")
     GLib.idle_add(self.update_revealer, game)
     return False
Example #17
0
 def on_game_updated(self, game):
     if game.appid and self.service:
         db_game = ServiceGameCollection.get_game(self.service.id,
                                                  game.appid)
     else:
         db_game = games_db.get_game_by_field(game.id, "id")
     updated = self.game_store.update(db_game)
     if not updated:
         self.game_store.add_game(db_game)
     return True
Example #18
0
    def __init__(self, db_game, game_actions, application):
        """Create the game bar with a database row"""
        super().__init__(orientation=Gtk.Orientation.VERTICAL,
                         visible=True,
                         margin_top=12,
                         margin_left=12,
                         margin_bottom=12,
                         margin_right=12,
                         spacing=6)
        self.game_start_hook_id = GObject.add_emission_hook(
            Game, "game-start", self.on_game_state_changed)
        self.game_started_hook_id = GObject.add_emission_hook(
            Game, "game-started", self.on_game_state_changed)
        self.game_stopped_hook_id = GObject.add_emission_hook(
            Game, "game-stopped", self.on_game_state_changed)
        self.game_updated_hook_id = GObject.add_emission_hook(
            Game, "game-updated", self.on_game_state_changed)
        self.game_removed_hook_id = GObject.add_emission_hook(
            Game, "game-removed", self.on_game_state_changed)
        self.game_installed_hook_id = GObject.add_emission_hook(
            Game, "game-installed", self.on_game_state_changed)
        self.connect("destroy", self.on_destroy)

        self.set_margin_bottom(12)
        self.game_actions = game_actions
        self.db_game = db_game
        self.service = None
        if db_game.get("service"):
            try:
                self.service = services.SERVICES[db_game["service"]]()
            except KeyError:
                pass

        game_id = None
        if "service_id" in db_game:
            self.appid = db_game["service_id"]
            game_id = db_game["id"]
        elif self.service:
            self.appid = db_game["appid"]
            if self.service.id == "lutris":
                game = get_game_by_field(self.appid, field="slug")
            else:
                game = get_game_for_service(self.service.id, self.appid)
            if game:
                game_id = game["id"]
        if game_id:
            self.game = application.get_game_by_id(game_id) or Game(game_id)
        else:
            self.game = Game()
            self.game.name = db_game["name"]
            self.game.slug = db_game["slug"]
            self.game.appid = self.appid
            self.game.service = self.service.id if self.service else None
        game_actions.set_game(self.game)
        self.update_view()
Example #19
0
 def install(self, db_game):
     egs_game = get_game_by_field(self.client_installer, "installer_slug")
     application = Gio.Application.get_default()
     if not egs_game or not egs_game["installed"]:
         installers = get_installers(game_slug=self.client_installer, )
         application.show_installer_window(installers)
     else:
         application.show_installer_window(
             [self.generate_installer(db_game, egs_game)],
             service=self,
             appid=db_game["appid"])
Example #20
0
 def get_configurations(self):
     ubi_game = get_game_by_field("ubisoft-connect", "slug")
     if not ubi_game:
         return
     base_dir = ubi_game["directory"]
     configurations_path = os.path.join(
         base_dir,
         "drive_c/Program Files (x86)/Ubisoft/Ubisoft Game Launcher/"
         "cache/configuration/configurations")
     with open(configurations_path, "rb") as config_file:
         content = config_file.read()
     return content
Example #21
0
 def add_installed_games(self):
     origin_game = get_game_by_field("origin", "slug")
     if not origin_game:
         logger.error("Origin is not installed")
     origin_prefix = origin_game["directory"].split("drive_c")[0]
     if not os.path.exists(os.path.join(origin_prefix, "drive_c")):
         logger.error("Invalid install of Origin at %s", origin_prefix)
         return
     origin_launcher = OriginLauncher(origin_prefix)
     for manifest in origin_launcher.iter_manifests():
         self.install_from_origin(origin_game, manifest)
     logger.debug("All EGS games imported")
Example #22
0
 def install(self, db_game):
     origin_game = get_game_by_field(self.client_installer, "slug")
     application = Gio.Application.get_default()
     if not origin_game or not origin_game["installed"]:
         logger.warning("Installing the Origin client")
         installers = get_installers(game_slug=self.client_installer)
         application.show_installer_window(installers)
     else:
         application.show_installer_window(
             [self.generate_installer(db_game, origin_game)],
             service=self,
             appid=db_game["appid"])
Example #23
0
 def add_installed_games(self):
     ubisoft_connect = get_game_by_field(self.client_installer, "slug")
     if not ubisoft_connect:
         logger.warning("Ubisoft Connect not installed")
         return
     prefix_path = ubisoft_connect["directory"].split("drive_c")[0]
     prefix = WinePrefixManager(prefix_path)
     for game in ServiceGameCollection.get_for_service(self.id):
         details = json.loads(game["details"])
         install_path = get_ubisoft_registry(prefix,
                                             details.get("registryPath"))
         exe = get_ubisoft_registry(prefix, details.get("exe"))
         if install_path and exe:
             self.install_from_ubisoft(ubisoft_connect, game)
Example #24
0
 def install(self, db_game):
     """Install a game or Ubisoft Connect if not already installed"""
     ubisoft_connect = get_game_by_field(self.client_installer, "slug")
     application = Gio.Application.get_default()
     if not ubisoft_connect or not ubisoft_connect["installed"]:
         logger.warning("Ubisoft Connect (%s) not installed",
                        self.client_installer)
         installers = get_installers(game_slug=self.client_installer)
         application.show_installer_window(installers)
     else:
         application.show_installer_window(
             [self.generate_installer(db_game, ubisoft_connect)],
             service=self,
             appid=db_game["appid"])
Example #25
0
 def on_game_updated(self, game):
     """Updates an individual entry in the view when a game is updated"""
     if game.appid and self.service:
         db_game = ServiceGameCollection.get_game(self.service.id,
                                                  game.appid)
     else:
         db_game = games_db.get_game_by_field(game.id, "id")
     if not self.is_game_displayed(game):
         self.game_store.remove_game(db_game["id"])
         return True
     updated = self.game_store.update(db_game)
     if not updated:
         self.update_store()
     return True
Example #26
0
 def _get_runner_version(self):
     """Return the version of the runner used for the installer"""
     if self.installer.runner == "wine":
         # If a version is specified in the script choose this one
         if self.installer.script.get(self.installer.runner):
             return self.installer.script[self.installer.runner].get(
                 "version")
         # If the installer is a extension, use the wine version from the base game
         if self.installer.requires:
             db_game = get_game_by_field(self.installer.requires,
                                         field="installer_slug")
             if not db_game:
                 db_game = get_game_by_field(self.installer.requires,
                                             field="slug")
             if not db_game:
                 logger.warning("Can't find game %s",
                                self.installer.requires)
                 return None
             game = Game(db_game["id"])
             return game.config.runner_config["version"]
     if self.installer.runner == "libretro":
         return self.installer.script["game"]["core"]
     return None
Example #27
0
    def add_installed_games(self):
        """Scan an existing EGS install for games"""
        egs_game = get_game_by_field("epic-games-store", "slug")
        if not egs_game:
            logger.error("EGS is not installed in Lutris")
            return

        egs_prefix = egs_game["directory"].split("drive_c")[0]
        logger.info("EGS detected in %s", egs_prefix)
        if not system.path_exists(os.path.join(egs_prefix, "drive_c")):
            logger.error("Invalid install of EGS at %s", egs_prefix)
            return
        egs_launcher = EGSLauncher(egs_prefix)
        for manifest in egs_launcher.iter_manifests():
            self.install_from_egs(egs_game, manifest)
        logger.debug("All EGS games imported")
Example #28
0
    def __init__(self, db_game, game_actions, application):
        """Create the game bar with a database row"""
        super().__init__(visible=True)
        GObject.add_emission_hook(Game, "game-start",
                                  self.on_game_state_changed)
        GObject.add_emission_hook(Game, "game-started",
                                  self.on_game_state_changed)
        GObject.add_emission_hook(Game, "game-stopped",
                                  self.on_game_state_changed)
        GObject.add_emission_hook(Game, "game-updated",
                                  self.on_game_state_changed)
        GObject.add_emission_hook(Game, "game-removed",
                                  self.on_game_state_changed)
        GObject.add_emission_hook(Game, "game-installed",
                                  self.on_game_state_changed)

        self.set_margin_bottom(12)
        self.game_actions = game_actions
        self.db_game = db_game
        self.service = None
        if db_game.get("service"):
            try:
                self.service = services.get_services()[db_game["service"]]()
            except KeyError:
                logger.warning("Non existent service '%s'", db_game["service"])

        game_id = None
        if "service_id" in db_game:
            self.appid = db_game["service_id"]
            game_id = db_game["id"]
        elif self.service:
            self.appid = db_game["appid"]
            if self.service.id == "lutris":
                game = get_game_by_field(self.appid, field="slug")
            else:
                game = get_game_for_service(self.service.id, self.appid)
            if game:
                game_id = game["id"]
        if game_id:
            self.game = application.get_game_by_id(game_id) or Game(game_id)
            game_actions.set_game(self.game)
        else:
            self.game = Game()
        self.game_name = db_game["name"]
        self.game_slug = db_game["slug"]
        self.update_view()
Example #29
0
 def download(self, slug, url):
     if url.startswith("http"):
         return super().download(slug, url)
     if not url.endswith(".jpg"):
         return
     ubi_game = get_game_by_field("ubisoft-connect", "slug")
     if not ubi_game:
         return
     base_dir = ubi_game["directory"]
     asset_file = os.path.join(
         base_dir,
         "drive_c/Program Files (x86)/Ubisoft/Ubisoft Game Launcher/cache/assets",
         url)
     cache_path = os.path.join(self.dest_path, self.get_filename(slug))
     if os.path.exists(asset_file):
         shutil.copy(asset_file, cache_path)
     else:
         logger.warning("No thumbnail in %s", asset_file)
Example #30
0
    def __init__(self, game_id=None):
        super().__init__()
        self.id = game_id  # pylint: disable=invalid-name
        self.runner = None
        self.config = None

        # Load attributes from database
        game_data = games_db.get_game_by_field(game_id, "id")
        self.slug = game_data.get("slug") or ""
        self.runner_name = game_data.get("runner") or ""
        self.directory = game_data.get("directory") or ""
        self.name = game_data.get("name") or ""

        self.game_config_id = game_data.get("configpath") or ""
        self.is_installed = bool(
            game_data.get("installed") and self.game_config_id)
        self.is_hidden = bool(game_data.get("hidden"))
        self.platform = game_data.get("platform") or ""
        self.year = game_data.get("year") or ""
        self.lastplayed = game_data.get("lastplayed") or 0
        self.has_custom_banner = bool(game_data.get("has_custom_banner"))
        self.has_custom_icon = bool(game_data.get("has_custom_icon"))
        self.service = game_data.get("service")
        self.appid = game_data.get("service_id")
        self.discord_presence = DiscordPresence()
        self.playtime = game_data.get("playtime") or 0.0

        if self.game_config_id:
            self.load_config()
        self.game_uuid = None
        self.game_thread = None
        self.prelaunch_pids = []
        self.prelaunch_executor = None
        self.heartbeat = None
        self.killswitch = None
        self.state = self.STATE_STOPPED
        self.game_runtime_config = {}
        self.resolution_changed = False
        self.compositor_disabled = False
        self.original_outputs = None
        self._log_buffer = None
        self.timer = Timer()
        self.screen_saver_inhibitor_cookie = None