/* SaveDescriptor could be a representation of descriptor.xml (btw, syntax highlighter doesn't like double-slash comments, it comments out the rest of the code block */
abstract void beforeGameLoad(SaveDescriptor saveDescriptor);
/* or, more simply */
abstract void beforeGameLoad(String lastSavedModVersion);
@Override
void beforeGameLoad(String lastSavedModVersion) {
/* Version.java is left as an exercise to the reader */
Version oldVer = Version.parse(lastSavedModVersion);
Version currentVer = Version.parse(Global.getSettings().getModManager().getModSpec("myMod").getVersion());
if(oldVer.getMajor() < currentVer.getMajor()) {
throw new RuntimeException("Updating from version " + oldVer.toString() + " of MyMod to version " + currentVer.toString() + " requires a new game. Please downgrade MyMod to " + oldVer.toString() + " or start a new game to continue.");
}
}
The game already shows a "mod compatibility warning" when you try to load the game (I'm not 100% sure if this is in 0.9.1a, actually), and will also show the saved with/current versions for all the mods involved in the save game's tooltip, so I think this should be covered?
What are the odds of having a `beforeGameLoad` hook added to `ModPlugin`?
The use case I'm thinking of is detecting save-breaking mod updates and showing an user-friendly message before the save file is deserialized and blows up.
The game already shows a "mod compatibility warning" when you try to load the game (I'm not 100% sure if this is in 0.9.1a, actually), and will also show the saved with/current versions for all the mods involved in the save game's tooltip, so I think this should be covered?
Ah - the way it works in 0.95a is the tooltip will show whether it's a minor or major mismatch, based on what part of the version changed, so e.g. 0.1.1.1 -> 0.1.2.2 = minor warning ("it might not work"), while 0.1.1.1 -> 0.2.1.1 = major warning ("it probably won't work, expect it not to load").
The second number is a feature update bump, and the third is for bugfixes. So, in that case, going from 1.1.1 -> 1.2.2 should always be compatible.
Yeah - this is largely due to having version dependency checking for mods in the launcher, which, kind of need to choose a specific scheme (any scheme, really, point being that one has to be chosen) for that to work. And if that same scheme works for estimating save compatibility, too...
Ah - the way it works in 0.95a is the tooltip will show whether it's a minor or major mismatch, based on what part of the version changed, so e.g. 0.1.1.1 -> 0.1.2.2 = minor warning ("it might not work"), while 0.1.1.1 -> 0.2.1.1 = major warning ("it probably won't work, expect it not to load").Could we have one or both of these?
- Could we have a mod_info.json field (optional) to make a major mismatch save unloadable as opposed to just warnings (false by default)?
- If you will be forcing a versioning scheme - please disregard this. In the discussion linked here (https://fractalsoftworks.com/forum/index.php?topic=19277.0), many people do not feel comfortable with SemVer (or any forced versioning scheme it seems) - could we have a mod_info.json field (optional) to specify backwards-incompatible (if not present default to normal logic, so major/minor mismatch shows warning)?
Hmm, if this is optional, then you'd get different behavior from mod version conflicts that look like they should be the same type of conflict to the player.Not for dependency checks, but for self. So if I, as a mod author know my upgrade will break saves, I would like to be able to stop save-game loading altogether (by bumping Major and enabling this optional mod_info field). It should stay optional, as not everyone will bump Major when save-breaking changes are made. In other words, if there is a Red tick for my mod on new tooltip (which looks great btw), I want to be able to make this save unloadable.
[version=17.2.1] balance patch
[version=17.3.0] Added 12 ships, 6 weapons, complete campaign rework.
[version=18.0.0] fixed miss-placed mount.
[version=17.2.1][compatibility=13] balance patch
[version=18.0.0][compatibility=13] Added 12 ships, 6 weapons, complete campaign rework.
[version=18.0.1][compatibility=14] fixed miss-placed mount.
Well - primarily the system is there for managing mod dependencies and it's based on what version checker was already using...
Edit: what I'm trying to say is that it's not really *required* to version it to provide the most accurate save compatibility message. Whether it's a "might not load" or "likely to not load" message, there's still room for either outcome.
The important thing here is consistency and user expectation though.
If that is correct, the big problem which I brought up in the other thread is that the actuality of that information isn't guaranteed to be correct.
(Tartiflette's separation of versioning and compatibility control is the best way to do this, I'd say, since it removes the additional issue about versioning clarity through always incrementing Major if unsure about save compatibility. But mark my words, it will still open up a can of worms the first time anyone is wrong should it be implemented! )
I would also add user experience and value to business (modder in this case).
User experience (as a user) - being consistent and meeting expectations. My experience is good when I upgrade the mod and my game does not break.
If that is correct, the big problem which I brought up in the other thread is that the actuality of that information isn't guaranteed to be correct.
I would have to disagree with you on that. This could be said about any software that does not have a full suite regression tests in place. At this point you are trying to accurately infer backward compatibility based on the changes you did to your software and your understanding of its interaction with other software. Best effort is enough.
Going further, it does not need to be correct, it only needs to be enforced correctly. If I mark my new version 1.5.2 as incompatible upgrade even though it might be compatible with 1.4.0+ that's not a big issue (will only prevent users from upgrading mid-game), and something I as a modder can do.
(Tartiflette's separation of versioning and compatibility control is the best way to do this, I'd say, since it removes the additional issue about versioning clarity through always incrementing Major if unsure about save compatibility. But mark my words, it will still open up a can of worms the first time anyone is wrong should it be implemented! )
This is a huge can of worms. Let's go back to initial requirements: "consistency", "user expectation" and "user experience".
Modder releases a new version, 2.0.0 (internal 23), that comes after 1.4.5 (internal 23), that comes after 1.4.4 (internal 22). User can no longer upgrade from <=1.4.4. If we prevent user from loading the game, what do we show? Please downgrade? User goes back to 1.4.5 (which he skipped). Same problem. We can say "Downgrade to internal build 22 (it also need to be stored in a savegame, because internal might not be simply current - 1). But internal version is being hidden, which makes user go straight back to forum thread, which tells user "open mod_info and find one with 22", which means "keep downloading previous versions until you find one matching" (as internal is not published). Also this does not solve consistency, as you can't tell from version alone which versions are safe to replace current version.
Right, in general I agree, but it wouldn't be the case for everyone because of knowledge requirements for Best Effort. Because of that, the above benefit is illusory to a user in the actual modding scene. Again a "business" has the expectations of quality control that you are speaking to because they have infrastructure dedicated to acquiring talented and knowledgeable staff to interpret and implement the requirements. That is simply not the case here, and so enforcing helps some and hurts some - with it causing the most problems for those just starting out. It certainly brings value to a modder who understands all the requirements, no argument there - it is just that it is disingenuous to assume that all do. That wouldn't be a problem in and of itself, but as those who understand the requirements raise user expectation in this way, those who don't suffer a larger penalty of "user disappointment" that they don't.
I really fail to see a difference except the key one: best effort isn't a guarantee. Your example, of course, has no downsides because marking an update incompatible when it is, in fact, compatible leaves the user none the wiser. What about the reverse? You mark it compatible and it is not. Keep in mind, a user won't always know this when trying to load the save. Off the top of my head, they have a ship with a hullmod equipped in storage on some market somewhere and that hullmod was removed in the current (supposedly compatible) update. They won't get a crash until probably interacting with that market, etc. (Not really sure if this is true anymore, but it was at one time.)
??? Maybe I'm missing something here? I don't see how having internal exposed in the version, itself, helps make it more clear to the end user what their course of action should be. Like, if you release 23.1.3.4 and one user has 22.4.1.0 and another 23.0.8.5 there is still a lack of clarity what version to revert to unless the version of the save itself is exposed to the user (which it is already, right?). If you are speaking to the idea that the version is stored in the save file and the user can be pointed to it explicitly that way, then why does internal even need to be exposed? It would point to the version the user was last using regardless, and that version is guaranteed to be at the compatible internal level of the save...
If a user's save is 1.4.4 (internal 22) and the release is 2.0.0 (internal 23), it doesn't matter whether a 1.4.5 (internal 23) exists or not, the message would still point the user back to the save's version (1.4.4 internal 22). Trying to be extra smart and say "Hey there is a 1.4.5 (internal 23) - go try that first!" - wouldn't be possible even if the versions were, respectively: 23.2.0.0 - 22.1.4.5 - 22.1.3.0. The message is still going to be pointing the user to their save's version - 22.1.3.0 even if, via the version control, 22.1.4.5 would technically be compatible.
I don't think "at a glance" compatibility via the suffix implementation is worth entangling content and compatibility into the same number. That, I believe, was Tartiflette's point. What you at least seem to be thinking of in this case, is when a user asks why their save isn't loading and all they have is their current version number. It would would be useful, in some ways I suppose, to have at-a-glance compatibility then. Even that is a little suspect, come to think of it, because you'd still need to know the version the save is trying to reference - so you're back at square one. But when considering the warning message when trying to load a save? All pertinent information is already available from the perspective of what such a feature is trying to accomplish.
"Hey there is a 1.4.5 (internal 23) - go try that first!" is wrong, user is on 1.4.4 (internal 22) so he can only use internal 22 (1.4.4).Also, same as above, we can get Major from save and tell user to user downgrade to the latest Major release.
User with 22.4.1.0 that upgraded to 23.1.3.4 should revert to latest 22.x.x.x.
User with 23.0.8.5 does not need to revert, as line 23.x.x.x is save compatible with any previous versions in that line.
In both cases we can present user correct version to downgrade (download latest Z.x.x.x, where Z is already stored in a save-game).
That's a headache for everyone when the simpler solution was to just paste the original save's version in the message. Errr, is this making sense? lol It's hard to translate brain to text sometimes and I'm fairly sleepy atm. :P
In short: it was one of the easiest games I could find to mod at the time.For me it was a game I could create the most complicated mods at the time. There are not many games where you can create mods in the same language (usually you are given some scripting language or Lua) as the game (or even other languages, like Kotlin), has proper API exposed, and the only ceiling is your imagination (and API to an extent). At the same time, as I was musing to my wife a while back, it is the only game that I know that has so low level entry barrier to modding. There are people that try to create mods (scripts included) that have no idea about Java or haven't seen an IDE in their live. It's beautiful.
That's a headache for everyone when the simpler solution was to just paste the original save's version in the message. Errr, is this making sense? lol It's hard to translate brain to text sometimes and I'm fairly sleepy atm. :PMost often the simplest solutions are the best ones in the long run. Prevent any upgrade mid-game, force downgrade to the exact version used before... But what about hotfixes/patches then? As a modder I can always re-release my mod with a hotfix, and keep the old version in modinfo to workaround version mismatch prevention. But I can make a mistake and make it save incompatible - back to square one.
I reread this and just in case it came across as sarcastic: I'm genuinely trying to think of ways that this kind of feature can backfireNone at all, I do appreciate all the edge cases and reservations you raise. Without them, we couldn't try to understand the (larger) problem.