mirror of
https://github.com/lutris/lutris
synced 2024-07-01 06:34:26 +00:00
Launch games from local services directly
This commit is contained in:
parent
6f89bbe0fd
commit
b4234878f0
|
@ -1,10 +1,10 @@
|
|||
"""Handle the game, runner and global system configurations."""
|
||||
|
||||
# Standard Library
|
||||
import os
|
||||
import time
|
||||
|
||||
# Lutris Modules
|
||||
import yaml
|
||||
|
||||
from lutris import settings, sysoptions
|
||||
from lutris.runners import InvalidRunner, import_runner
|
||||
from lutris.util.log import logger
|
||||
|
@ -17,6 +17,17 @@ def make_game_config_id(game_slug):
|
|||
return "{}-{}".format(game_slug, int(time.time()))
|
||||
|
||||
|
||||
def write_game_config(game_slug, config):
|
||||
"""Writes a game config to disk"""
|
||||
configpath = make_game_config_id(game_slug)
|
||||
config_filename = os.path.join(settings.CONFIG_DIR, "games/%s.yml" % configpath)
|
||||
yaml_config = yaml.safe_dump(config, default_flow_style=False)
|
||||
with open(config_filename, "w") as config_file:
|
||||
logger.debug("Writing game config to %s", config_filename)
|
||||
config_file.write(yaml_config)
|
||||
return configpath
|
||||
|
||||
|
||||
class LutrisConfig:
|
||||
|
||||
"""Class where all the configuration handling happens.
|
||||
|
|
|
@ -130,12 +130,11 @@ def get_games_by_slug(slug):
|
|||
return sql.db_select(settings.PGA_DB, "games", condition=("slug", slug))
|
||||
|
||||
|
||||
def add_game(name, **game_data):
|
||||
def add_game(**game_data):
|
||||
"""Add a game to the PGA database."""
|
||||
game_data["name"] = name
|
||||
game_data["installed_at"] = int(time.time())
|
||||
if "slug" not in game_data:
|
||||
game_data["slug"] = slugify(name)
|
||||
game_data["slug"] = slugify(game_data["name"])
|
||||
return sql.db_insert(settings.PGA_DB, "games", game_data)
|
||||
|
||||
|
||||
|
|
|
@ -477,7 +477,10 @@ class Application(Gtk.Application):
|
|||
if game.service:
|
||||
service = get_services()[game.service]()
|
||||
db_game = ServiceGameCollection.get_game(service.id, game.appid)
|
||||
service.install(db_game)
|
||||
game_id = service.install(db_game)
|
||||
if game_id:
|
||||
game = Game(game_id)
|
||||
game.launch()
|
||||
return True
|
||||
|
||||
installers = get_installers(game_slug=game.slug)
|
||||
|
|
|
@ -792,26 +792,26 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
|
||||
def on_game_activated(self, view, game_id):
|
||||
"""Handles view activations (double click, enter press)"""
|
||||
if self.service and 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 self.service:
|
||||
if self.service.id != "lutris":
|
||||
db_game = games_db.get_game_for_service(self.service.id, game_id)
|
||||
if db_game:
|
||||
self.service.install(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 self.service and self.service.id == "lutris":
|
||||
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"]
|
||||
game = Game(game_id)
|
||||
game.emit("game-launch")
|
||||
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")
|
||||
|
|
|
@ -182,6 +182,9 @@ class GameBar(Gtk.Fixed):
|
|||
button.set_label(_("Install"))
|
||||
button.connect("clicked", self.game_actions.on_install_clicked)
|
||||
if self.service:
|
||||
if self.service.local:
|
||||
# Local services don't show an install dialog, they can be launched directly
|
||||
button.set_label(_("Play"))
|
||||
button.set_size_request(120, 32)
|
||||
return button
|
||||
button.set_size_request(84, 32)
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
import yaml
|
||||
|
||||
from lutris import settings
|
||||
from lutris.config import LutrisConfig, make_game_config_id
|
||||
from lutris.config import LutrisConfig, write_game_config
|
||||
from lutris.database.games import add_or_update, get_game_by_field
|
||||
from lutris.game import Game
|
||||
from lutris.installer import AUTO_ELF_EXE, AUTO_WIN32_EXE
|
||||
|
@ -215,16 +212,6 @@ class LutrisInstaller: # pylint: disable=too-many-instance-attributes
|
|||
|
||||
return config
|
||||
|
||||
def write_game_config(self):
|
||||
configpath = make_game_config_id(self.slug)
|
||||
config_filename = os.path.join(settings.CONFIG_DIR, "games/%s.yml" % configpath)
|
||||
config = self.get_game_config()
|
||||
yaml_config = yaml.safe_dump(config, default_flow_style=False)
|
||||
with open(config_filename, "w") as config_file:
|
||||
logger.debug("Writing game config to %s", config_filename)
|
||||
config_file.write(yaml_config)
|
||||
return configpath
|
||||
|
||||
def save(self):
|
||||
"""Write the game configuration in the DB and config file"""
|
||||
if self.extends:
|
||||
|
@ -233,7 +220,7 @@ class LutrisInstaller: # pylint: disable=too-many-instance-attributes
|
|||
self.extends,
|
||||
)
|
||||
return
|
||||
configpath = self.write_game_config()
|
||||
configpath = write_game_config(self.slug, self.get_game_config())
|
||||
runner_inst = import_runner(self.runner)()
|
||||
if self.service:
|
||||
service_id = self.service.id
|
||||
|
|
|
@ -5,8 +5,9 @@ import shutil
|
|||
from gi.repository import Gio, GObject
|
||||
|
||||
from lutris import api, settings
|
||||
from lutris.config import write_game_config
|
||||
from lutris.database import sql
|
||||
from lutris.database.games import get_games
|
||||
from lutris.database.games import add_game, get_games
|
||||
from lutris.database.services import ServiceGameCollection
|
||||
from lutris.game import Game
|
||||
from lutris.installer import fetch_script
|
||||
|
@ -117,6 +118,8 @@ class BaseService(GObject.Object):
|
|||
"""Install a service game"""
|
||||
appid = db_game["appid"]
|
||||
logger.debug("Installing %s from service %s", appid, self.id)
|
||||
if self.local:
|
||||
return self.simple_install(db_game)
|
||||
service_installers = self.get_installers_from_api(appid)
|
||||
# Check if the game is not already installed
|
||||
for service_installer in service_installers:
|
||||
|
@ -137,6 +140,27 @@ class BaseService(GObject.Object):
|
|||
application = Gio.Application.get_default()
|
||||
application.show_installer_window(service_installers, service=self, appid=appid)
|
||||
|
||||
def simple_install(self, db_game):
|
||||
"""A simplified version of the install method for local services"""
|
||||
installer = self.generate_installer(db_game)
|
||||
configpath = write_game_config(db_game["slug"], installer["script"])
|
||||
game_id = add_game(
|
||||
name=installer["name"],
|
||||
runner=installer["runner"],
|
||||
slug=installer["game_slug"],
|
||||
directory=self.get_game_directory(installer),
|
||||
installed=1,
|
||||
installer_slug=installer["slug"],
|
||||
configpath=configpath,
|
||||
service=self.id,
|
||||
service_id=db_game["appid"],
|
||||
)
|
||||
return game_id
|
||||
|
||||
def get_game_directory(self, _installer):
|
||||
"""Specific services should implement this"""
|
||||
return ""
|
||||
|
||||
|
||||
class OnlineService(BaseService):
|
||||
"""Base class for online gaming services"""
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import os
|
||||
import json
|
||||
import os
|
||||
from gettext import gettext as _
|
||||
|
||||
from lutris import settings
|
||||
|
@ -50,10 +50,15 @@ class DolphinService(BaseService):
|
|||
"script": {
|
||||
"game": {
|
||||
"main_file": details["path"],
|
||||
"platform": details["platform"]
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
def get_game_directory(self, installer):
|
||||
"""Pull install location from installer"""
|
||||
return os.path.dirname(installer["script"]["game"]["main_file"])
|
||||
|
||||
|
||||
class DolphinGame(ServiceGame):
|
||||
"""Game for the Dolphin emulator"""
|
||||
|
@ -66,11 +71,14 @@ class DolphinGame(ServiceGame):
|
|||
def new_from_cache(cls, cache_entry):
|
||||
"""Create a service game from an entry from the Dolphin cache"""
|
||||
service_game = cls()
|
||||
service_game.name = cls.get_game_name(cache_entry)
|
||||
service_game.appid = str(cache_entry["code_1"])
|
||||
service_game.slug = slugify(cls.get_game_name(cache_entry))
|
||||
service_game.name = cache_entry["real_name"]
|
||||
service_game.appid = str(cache_entry["game_id"])
|
||||
service_game.slug = slugify(cache_entry["real_name"])
|
||||
service_game.icon = ""
|
||||
service_game.details = json.dumps({"path": cache_entry["path"]})
|
||||
service_game.details = json.dumps({
|
||||
"path": cache_entry["path"],
|
||||
"platform": cache_entry["platform"][:-1]
|
||||
})
|
||||
return service_game
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -118,6 +118,10 @@ class XDGService(BaseService):
|
|||
}
|
||||
}
|
||||
|
||||
def get_game_directory(self, installer):
|
||||
"""Pull install location from installer"""
|
||||
return os.path.dirname(installer["script"]["game"]["exe"])
|
||||
|
||||
|
||||
class XDGGame(ServiceGame):
|
||||
"""XDG game (Linux game with a desktop launcher)"""
|
||||
|
|
|
@ -27,11 +27,12 @@ class DolphinCacheReader:
|
|||
'maker_short': 'a',
|
||||
'maker_long': 'a',
|
||||
'description': 'a',
|
||||
'some_other_name': 's',
|
||||
'code_1': 's',
|
||||
'code_2': 's',
|
||||
'field_c': 32,
|
||||
'field_d': 1,
|
||||
'real_name': 's',
|
||||
'game_id': 's',
|
||||
'game_tdbid': 's',
|
||||
'field_c': 6,
|
||||
'platform': 1,
|
||||
'field_d': 26,
|
||||
'rel_date': 's',
|
||||
'field_e': 8,
|
||||
'banner': 'i',
|
||||
|
@ -83,6 +84,7 @@ class DolphinCacheReader:
|
|||
if has_image:
|
||||
image = self.cache_content[self.offset:self.offset + 12288]
|
||||
self.offset += 12288
|
||||
image = ''
|
||||
return image
|
||||
|
||||
def get_raw(self, word_len):
|
||||
|
|
Loading…
Reference in New Issue
Block a user