Load older game saves into updated game: Attempt 2

Started by Crimson Wizard, Tue 28/05/2024 01:43:22

Previous topic - Next topic

Crimson Wizard

#20
Quote from: eri0o on Fri 15/11/2024 03:05:07CW, you backported Length, so in 3.6.2 one can check the array Length property too. So it could use a prescan_slots.Length in that for clause.

Yes that's true, I did not mention Length in this example, because it is not reported as official feature yet.

The "data" arg may be used for another thing, passing a custom user parameter, if they need to distinguish different Scan calls. As you cannot receive the array itself as event argument with this existing callback.

Quote from: eri0o on Fri 15/11/2024 03:05:07Edit2: I think this function can replace the need to have hidden a listbox to retrieve the save slots if you are rendering your save/load GUI using something else, perhaps by even supporting FileSortStyle and SortDirection - but maybe this makes this too complicated. Just random idea.

No that's also true, and may be added, I realized that after committing.
In theory one could get necessary information for sorting using script commands, but then we don't have a sorting function in api, so one would also have to write one... which is going to be an extra complication for a user.

eri0o

I tried the build from the CI to check that if I call it in game start when the event would trigger - I guess if you have a scene in After fadein it would run either before or after but not during - which is alright but I was curious. Mostly because I do setup of my GUIs in game_start, but this is fine too, I can delay the final setup of the save GUI to happen after. I want to play a bit to think how I would use this. For instance, perhaps I would show valid saves, invalid saves appear with some invalid mark and have some option to purge it.

But I couldn't test because there is a bug in the in-draft PR. If you just load a new game from a Sierra Template you will see you can save things (they appear in Saved Games) but they don't appear in the GUI - so the thing that would fill the listbox appears to have the bug too.

Crimson Wizard

Quote from: eri0o on Fri 15/11/2024 20:57:59I tried the build from the CI to check that if I call it in game start when the event would trigger - I guess if you have a scene in After fadein it would run either before or after but not during - which is alright but I was curious

I'm sorry, i don't understand this sentence.

eri0o

The callback runs when no blocking action is happening, so if a character is speaking using regular Say and the event (eEventSavesScanComplete) would happen it triggers after the blocking sequence (a single or many Say calls for example).

If you have a GUI on Screen this means it would update after such blocking calls - at least I think, which is why I wanted to test.

This is not an issue, this is more me wanting to test this.

My interest on this API is because it looks like something that could be useful for a module for custom save/load UIs that I could make without depending on the user having a listbox or any GUIs at all. So it would be something easy to setup - pass a 9-slice graphic and set a few options and done.

Crimson Wizard

#24
Quote from: eri0o on Fri 15/11/2024 21:24:42But I couldn't test because there is a bug in the in-draft PR. If you just load a new game from a Sierra Template you will see you can save things (they appear in Saved Games) but they don't appear in the GUI - so the thing that would fill the listbox appears to have the bug too.

This was a problem with saving a game, description and screenshot image were lost somewhere in the process.

Crimson Wizard

Quote from: eri0o on Fri 15/11/2024 20:57:59I tried the build from the CI to check that if I call it in game start when the event would trigger - I guess if you have a scene in After fadein it would run either before or after but not during - which is alright but I was curious.

So, when Game.ScanSaveSlots is called the scanning is scheduled, and it is executed after the current script has finished, in a post-script step. This is where it schedules the event eEventSavesScanComplete.

But then the on_event is also run in the same post-script step, right after other scheduled actions were run.

So, the whole thing completes before any other script runs.

For example, if you call Game.ScanSaveSlots in game_start, room_Load and room_AfterFadeIn:

- game_start: call Game.ScanSaveSlots, scanning is scheduled
- after game_start exits, scanning is run
- on_event is run
- room_Load: call Game.ScanSaveSlots, scanning is scheduled
- after room_Load exits, scanning is run
- on_event is run
- room_AfterFadeIn: call Game.ScanSaveSlots, scanning is scheduled
- after room_AfterFadeIn exits, scanning is run
- on_event is run
- normal game loops begin to run.



Crimson Wizard

I've started to document loading older saves feature in the manual.
https://github.com/adventuregamestudio/ags-manual/wiki/UpgradeTo362#loading-old-saves-feature
https://github.com/adventuregamestudio/ags-manual/wiki/ValidateRestoredSave

And I wonder if using a "RestoredSaveInfo.Result" would be difficult to understand to users.
Right now it's a combination of bit flags, so you have to use bitwise operators in order to check specific values, like:

Code: ags
// If there's no missing data, then simply accept it and return.
if ((info.Result & eRestoredSave_MissingData) == 0)
{
    info.Cancel = false;
    return;
}

I wonder if it makes sense to find other way.

One method that I've seen somewhere else, is to instead make an boolean "array" property and use these flag values as index. In which case their tests would be coded like:

Code: ags
// If there's no missing data, then simply accept it and return.
if (!info.Result[eRestoredSave_MissingData])
{
    info.Cancel = false;
    return;
}

Crimson Wizard

#29
So, I opened a try-out PR for the change that I described in my previous post.
https://github.com/adventuregamestudio/ags/pull/2632

I'd really like to hear someones opinion on this.

BTW, maybe there's something wrong with the way how I look at this, because now I began to wonder why did I make this flags in script API at all, and not just a set of boolean properties...
There's not too much of them.

EDIT:
Opened an alternate PR, which replaces a Result flag set with 3 distinct properties (and removes enum with flags):
https://github.com/adventuregamestudio/ags/pull/2633

eri0o

Uhm, I noticed we need to have it documented similar to  DialogOptionsRenderingInfo, with its own page.

I guess the original flags make it easier to expand the result possibilities if needed and the latest approach with boolean properties make it easier to discover what is possible through auto complete.

Crimson Wizard

#31
Being able to restore a save in an update game was a long-time request for years.
Back when I tried to make this feature around 2016, there was an interest from AGS users, resulting in at least some conversation.

As I was making this second attempt, I've been posting my progress, and suggesting to try and see if the feature is actually useful in practice, and if it covers user demands.

It's more than a year as this topic exists, and more than a half of a year as it's a part of a AGS release. Yet in all this time there was virtually a single person who asked practical questions about this functionality, and tested this functionality with me (although these tests were limited to just checking if a save may be applied or not prior to restoring one).

This situation is frankly troubling me. Are AGS users not interested in this functionality anymore? Are they not aware of it? I did test it, but these were formal tests, and I still do not know if this feature will work for real users in real games. It's theoretically possible that it's missing important bits, but I don't know about these, as I don't make games myself.

Snarky

I think the thing is that this is mainly an issue for commercial games, and commercial devs will usually need to keep their focus on their game in development, not features that might be useful at some future date.

But given that both Grundislav Games and Wadjet Eye Games (to name two) released their games earlier this year and are now in early production for their next projects, perhaps they have more capacity to take a look now.

@Dave Gilbert @ThreeOhFour @JanetC @Grundislav @Postmodern Adventures @Laura Hunt

Laura Hunt

Quote from: Snarky on Sun 31/08/2025 19:17:42I think the thing is that this is mainly an issue for commercial games, and commercial devs will usually need to keep their focus on their game in development, not features that might be useful at some future date.

That's definitely part of the issue, at least in my case. Sometimes new QoL features are easy to incorporate into an ongoing development and test as you go, but stuff like this requires too much bandwidth which I just don't have right now between my day job, focusing on our current game, and other life obligations.

But also, another reason is that I tried to follow the thread and I'm having a hard time wrapping my head around this functionality. It feels like a very complex feature that would probably require a bunch of specific, real-world cases in order to figure out what it can and cannot do and how it would make sense to use it, and I'm sure many other users who have checked out the thread have been similarly overwhelmed by the amount of information on here.

I do have one very specific use case in mind but I don't know if it's covered by these changes. With the current save implementation, if I save my game while testing and then I decide to make some in-editor changes such as e.g., changing audioclip volumes, initial room object positions, or changing some frame-linked sounds (because I realized they weren't correctly synced, for example), those changes will not be present in my save, and I'll have to run a new game from the start in order for them to be re-initialized.

If I understand correctly, it would now be possible to force a game restart before loading a save? Or would this only happen if an inconsistency is detected?

Crimson Wizard

Quote from: Laura Hunt on Mon 01/09/2025 07:56:58
Quote from: Snarky on Sun 31/08/2025 19:17:42I think the thing is that this is mainly an issue for commercial games, and commercial devs will usually need to keep their focus on their game in development, not features that might be useful at some future date.

That's definitely part of the issue, at least in my case. Sometimes new QoL features are easy to incorporate into an ongoing development and test as you go, but stuff like this requires too much bandwidth which I just don't have right now

Perhaps it will be more convenient and productive to have a discussion with an opposite approach, where game developers tell about their issues and situations they have with game saves, and engine developers would tell which solution exists, or may be designed?




Quote from: Laura Hunt on Mon 01/09/2025 07:56:58But also, another reason is that I tried to follow the thread and I'm having a hard time wrapping my head around this functionality. It feels like a very complex feature that would probably require a bunch of specific, real-world cases in order to figure out what it can and cannot do and how it would make sense to use it, and I'm sure many other users who have checked out the thread have been similarly overwhelmed by the amount of information on here.

This feature is now documented in the AGS manual, split into few topics, with examples:
https://adventuregamestudio.github.io/ags-manual/UpgradeTo362.html#loading-old-saves-feature

Unfortunately, I completely forgot to update the "Game saves compatibility" topic, which describes the saves problem and known workarounds. It must mention this new feature, but it currently does not.



Quote from: Laura Hunt on Mon 01/09/2025 07:56:58I do have one very specific use case in mind but I don't know if it's covered by these changes. With the current save implementation, if I save my game while testing and then I decide to make some in-editor changes such as e.g., changing audioclip volumes, initial room object positions, or changing some frame-linked sounds (because I realized they weren't correctly synced, for example), those changes will not be present in my save, and I'll have to run a new game from the start in order for them to be re-initialized.

If I understand correctly, it would now be possible to force a game restart before loading a save? Or would this only happen if an inconsistency is detected?

Restarting a game before loading a save will not help at all in your case, because loading a save will overwrite the starting positions and frame sounds anyway.

Skipping certain save components, like skipping restoring Views completely, may help to some extent. (Actually, you may fully remove Views from saves using a separate functionality: https://adventuregamestudio.github.io/ags-manual/UpgradeTo362.html#restricting-the-data-read-or-written-in-a-save).

Room object positions may be fixed by resetting rooms (ResetRoom command), but that also resets all other room states including variables.

This leaves a room state fixup in script to be the main option. I.e. you may script your rooms to reposition objects depending on a story progress in its "room load" event.

Snarky

One thing I imagine will be a fairly common use case is to make some change to the game, try to load a save from an earlier version, find that it breaks, and then try to work out what sort of fixup is needed to make it compatible.

I'm not quite clear on whether this will be possible, or if you have to know which breaking changes have been made by some obscure dark magic. (Diffing game versions in source control and consulting documentation about the sort of changes that break savegames, I suppose.)

Crimson Wizard

#36
Quote from: Snarky on Mon 01/09/2025 18:24:02One thing I imagine will be a fairly common use case is to make some change to the game, try to load a save from an earlier version, find that it breaks, and then try to work out what sort of fixup is needed to make it compatible.

I'm not quite clear on whether this will be possible, or if you have to know which breaking changes have been made by some obscure dark magic. (Diffing game versions in source control and consulting documentation about the sort of changes that break savegames, I suppose.)

The existing functionality allows 2 things:

1. Have new game versions have MORE items of each type ADDED to the end of the list (not removed, not inserted in the middle). In this case the old save will restore, run "validate_restored_save" callback, and let you check the numbers of items that engine has read from the save. What you do then is up to you entirely, because engine has no way to guess what's the right thing. You may decide that the save is incompatible and make game error. You may tell it to proceed, display error in your custom way, and then suggest user to either quit to main menu or restore the previously saved game, etc. You may decide that it can be fixed up and do necessary changes in script.

2. Prescan the save (or range of saves). The difference between restore and prescan is that prescan does not overwrite game data, but only gathers records of mismatches. Prescan can be used to identify "bad" saves and hide them from the list of saves in "restore game" menu, for example. It may be used to check any save before loading, and take action preemptively (before game data gets overwritten with something incompatible).

But in any case, it's up to developer to figure out what to do with old or bad saves, as engine cannot know, of course, which changes did you do and how the old save state may be applied over.

How to detect that a game has changed? At the very least you may check numbers of items.

One may use "game version" variable which gets saved, and then you know its value. But this requires to restore the save of course.

Currently I'm working on a better solution which works with prescanning:
https://github.com/adventuregamestudio/ags/pull/2828

SMF spam blocked by CleanTalk