-
-
Notifications
You must be signed in to change notification settings - Fork 58
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
Automatic backup after playing a game #211
Comments
Hello, I am not currently a user of ludusavi (but I plan to use it very soon). It is to modify the launch options of the launcher entry, and make ludusavi manage the game process. It has several advantages and disadvantages:
The main disadvantage is that it require to edit the steam entry. And some of them are generated and managed by other tools (ex: emudeck) This can be used in combination with a process watcher, for the best of both worlds. Of course this is just an idea, I did not do any proof of concept and I don't know if it is possible implement in ludusavi. |
I just finished configure ludusavi on my Windows but used it with playnite and loved this hability to backup the save after I close the game. It will be nice if you find a way to make possible "just" with ludusavi cause with my steam deck it will be nice to have to install playnite just for that. Sry for my English it's not my first language. |
I use this approach to "hook" ludusavi into the game launching process with Heroic. It allows to set a wrapper command which receives the actual command to launch the game, including all parameters. This way, my wrapper can do some checks and restore backups before the game is launched and do a backup once it has finished. The actual command contains enough information to determine the game name used in ludusavi, for example:
Unfortunately this heavily depends on how Heroic launches a game and which parameters are used. Using mangohud for example results in parameters being shifted. |
This is the script (not working if mangohud is used!), also found here: https://github.com/sluedecke/ludusavi-launcher #!/bin/sh
# -- ABOUT --
#
# Wrapper script to use ludusavi for savegame backup / restoration.
#
# Assumes that $5 is the directory with the game install which contains the file
# `gameinfo`.
#
# This file comes without warranty, use at your own risk!
#
# License: MIT License
# Author: Sascha Lüdecke <sascha@meta-x.de>
# -- BUGS --
#
# - does not work if mangohud is used
# -- HISTORY --
#
# Version: 0.X - WIP
#
#
# Version: 0.2 - 2022-09-29
#
# . use zenity to tell user that we back up / restore
#
# Version: 0.1 - 2022-09-27
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
LOGFILE=$SCRIPT_DIR/ludusavi-cloud.log
# Standard paths
## LUDUSAVI=/usr/bin/ludusavi
LUDUSAVI=$HOME/Projekte/contributing/ludusavi/target/debug/ludusavi
ZENITY=/usr/bin/zenity
TEE=/usr/bin/tee
JQ=/usr/bin/jq
HEAD=/usr/bin/head
DATE=/usr/bin/date
ECHO=/usr/bin/echo
GAMENAME=""
if [ -r "$5/gameinfo" ]
then
GAMENAME=`$HEAD -1 "$5/gameinfo"`
else
GAMENAME=`$JQ -r .name "$5/goggame-$6.info"`
fi
# Path on steam deck if installed via flatpack
if [ $USER == deck ]
then
LUDUSAVI=/home/.steamos/offload/var/lib/flatpak/exports/bin/com.github.mtkennerly.ludusavi
fi
{
$ECHO ==================================================
$ECHO
$ECHO Gamename is: $GAMENAME
$ECHO Start time: `$DATE`
$ECHO Parameters: $@
# restore savegame
$ECHO $LUDUSAVI restore --force "$GAMENAME"
(
$ECHO "# Restoring savegame for $GAMENAME"
# bypass STDOUT
$LUDUSAVI restore --force "$GAMENAME" 1>&2
) | $ZENITY --progress \
--title="Savegame restore" \
--no-cancel \
--auto-close \
--pulsate
# run game
$ECHO Game run command:
$ECHO $@
"$@"
# backup savegame
$ECHO $LUDUSAVI backup --merge --force "$GAMENAME"
(
$ECHO "# Backing up savegames for $GAMENAME"
# bypass STDOUT
$LUDUSAVI backup --merge --force "$GAMENAME" 1>&2
) | $ZENITY --progress \
--title="Savegame backup" \
--no-cancel \
--auto-close \
--pulsate
$ECHO End time: `$DATE`
$ECHO
$ECHO ==================================================
} 2>&1 | $TEE -a $LOGFILE
|
…a game Reflects the core function of ludusavi-launcher.sh minus the UI message and logging. Please consider this a proof of concept.
I have added a first shot at implementing a launcher command. It is based on the shell script above and currently needs to be invoked as (note the double dash after launcher, they are needed ATM):
Currently only gogdl based launches (if installed from heroic) are implemented. See here: https://github.com/sluedecke/ludusavi/tree/feature/launcher |
Thanks for looking into this :D The only reservation I have is about how hard it may be to maintain this approach when Heroic/etc make changes to how they launch games. That said, if we can make the implementation safe and robust, then I think it's worth incorporating as an option. Some initial feedback:
We could support these two styles:
I think we should make it required to pass either a name or an |
Thanks for the feedback!
Recent commit is about:
|
Could look like this: cargo run -- wrap --help
Compiling ludusavi v0.19.0 (/home/saschal/Projekte/contributing/ludusavi)
Finished dev [optimized + debuginfo] target(s) in 13.10s
Running `target/debug/ludusavi wrap --help`
ludusavi-wrap
Wrap restore/backup around game execution
USAGE:
ludusavi wrap [OPTIONS] [COMMANDS]...
ARGS:
<COMMANDS>... Commands to launch the game
OPTIONS:
-h, --help Print help information
--infer <LAUNCHER> Infer game name from commands based on launcher
type [possible values: heroic]
--name <NAME> Directly set game name as known to ludusavi
|
Ah, I guess Clap can't mark the name as "positional, but only if it comes before --". That looks fine then 👍 Feel free to open a draft PR, and we can move the implementation discussion there. |
This would be beneficial alongside #90 |
An alternative solution would be to run ludusavi as a daemon and set up a file system event watcher (e.g. inotifywait) for all the known paths. Then the savegames could be copied whenever a new savegame is made even while playing the game and not just after the game has been stopped. |
After merging #235, is this still an open issue? |
I think there's still room to explore the monitoring options in the first message. There could be different pros/cons between monitoring and the |
I have a proposition to add to You'd get something like Second idea: add more options to |
That sounds fine to me :) I'd be open to
This one's a bit tricky. How do we know which argument is the game exe? We might have cases with wrapper scripts like That said, maybe Lutris sets some environment variables that we could check, or they might be open to adding some (like I did for Heroic). |
It is indeed tricky, but I was just thining of Lutris in this case. Lutris has a setting where you can set a command prefix, that is where you'd set But investigating the env vars it sets is also a good idea. EDIT: I could ofcourse also have a look at what it would take to make an official integration between lutris and ludusavi, but I'm not a Python dev :) I think if they could just set some env vars that'd be specific to ludusavi, that could be enough? |
@kekonn I've inquired about adding some environment variables here: lutris/lutris#5407 |
@kekonn I've pushed a branch called |
I might have some time tonight or tomorrow evening (CEST). |
@mtkennerly good news and bad news: it is able to pick up the game, but I can't set the backup location this way and so it is looking in the wrong place 😅 This shouldn't be a problem when not running from a target folder in a branch though, no?
Incidentally the line breaks added in the error dialog are not translated: |
Nice 🎉
If you normally run Ludusavi via Flatpak, then there might be an issue with
Oh, that's weird. It looks like it's coming from the native-dialog crate when it invokes kdialog. Thanks for letting me know. What version of kdialog do you have? |
I think this is because I run ludusavi from the flatpak, but I run lutris from the system. Guess I should start thinking about packaging ludusavi for OpenSUSE 😅 . Adding --config did the trick though, so barring the little formatting bug with KDialog, this is just fine for me.
kdialog --version returns 24.02.1. I am currently on OpenSUSE Tumbleweed. |
Found a ticket for the formatting issue (native-dialog-rs/native-dialog-rs#41) and added a comment with some more info. It looks like downgrading the native-dialog version might help, although I'm not sure what else changed between the versions. |
Just to confirm, it worked when I set the $XDG_DATA_HOME. I know you're busy, but any idea when this would hit main? Using infer I could simply add ludusavi to my standard Lutris Wine settings and not have to do game per game settings. |
@kekonn I've merged the |
So there are a few solutions here that work today and get pretty close to this functionality:
Given the technical challenges with detecting game events without hooking into a launcher, and given that the above options are probably "good enough" for most cases, I think I'll refrain from implementing a process monitor in Ludusavi. |
What's your idea?
This would require some research to see if we can do it accurately enough. The manifest
launch
section has executable paths/names, which may be useful for this. Some potential options:My first choice would probably be by process path, as long as it ends up being accurate enough, since it would be one implementation that could work generically.
The text was updated successfully, but these errors were encountered: