Serialization and savegames

Hello. I’m interested in developing VCMI. I’ve been looking at bugs #601/#162 (hero sleep/wake function which is basically absent right now). To enable it, I’ve added bool mutable isSleeping to CGHeroInstance. I’d like a short overview on how saving/loading games works, as I intend to make this sleeping status save in savegames. So far I’ve tried adding “& isSleeping” to CGHeroInstance::serialize function, which did nothing but break compatibility with older savegames :blush:

Certainly adding new variables will break compatibility with old games, but it’s just the way to go.

Not sure about ‘mutable’ modifier, it may cause some weird issues with serializer.

Modifying game state variables (thus also heroes) is done by use of netpacks and callback (cb), especially cb->setObjProperty calling synchronous setProperty function for all players participating. That is true when you’re calling it from objects.
If you’re calling it from interface, then you need to send and apply the netpack directly, provided CGHeroInstance::setPropertyDer can handle it.

Though, if sleep mode is a part of interface, you may want to store that info here so it will be local only for player. Unless it should be persistent through save games?

Well, I’m not sure about anything multiplayer-related (I guess that could be tested in hotseat though?), but in single player HoMM3 Complete heroes’ sleep states are definitely saved. I even encountered a bug yesterday when sleep button ‘wake’ state wasn’t properly restored on loading a save with selected sleeping hero. Couldn’t reproduce it though. :unamused:

It’s not multiplayer-related. You need to use client-server architecture even for single player - every change in game state (here - change in parameters of heroes) needs to be propagated via sending net packs.

What I meant by “anything multiplayer-related” is that I’m not sure how entire save system works in HoMM3 multiplayer; I only played hotseat and still remember having to re-enter player names when you’re loading a hotseat savegame (why?). Though I guess you’re saying that if isSleeping is a part of advmapinterface, it doesn’t need to be sent to server or be known by other players? Sorry if I’m asking questions with obvious answers (instead of investigating source code myself :wink:), but is saving game always done from client, or server too?

It looks like wake/sleep is mechanically irrelevant and currently cannot be accessed by ERM scripts so it’s not necessary to keep this info synced. But then, it shouldn’t be kept in CGHeroInstance (mutable field looks like a hack to me, not a solution). So where it should be kept? Probably in CAdvMapInt, as a map by hero IDs or pointers to const CGHeroInstance. CAdvMapInt is not serialized, so you will probably want to save it in CClient::serialize.

Server and client are run even in single player, and they keep separate copies of state of the game that must be synchronized. Therefore server and client are serialized separately to different files (IIRC there is a third file for common things but it certainly will be removed since cheatproof multiplayer requires asymmetric gamestate).

PS: Sorry for not replying to your PM, I currently don’t have time to review patches properly.

Thanks for explanations, guys.

That one is reviewed already :slight_smile:

Change of subject: how come there’s sprites/IAM005L.DEF (sleep button for resolutions > 800x600), but there’s no sprites/IAM011L.DEF (wake button for said resolutions) in VCMI archive? Should I try to make one myself, or was it already done, just not included? :stuck_out_tongue:
It might also be true for some other DEFs (VCMI has 2 to 10 while original has 0 to 15).

The IAM buttons 0 and 1 are large on their own, no need for a separate “L” version. 12 - 15 are heroes and towns lists scrolling arrows, they also do not need bigger versions. The IAM011 however seems to be actually missing. Since Sleep feature hasn’t been implemented the button was not used and that’s probably the reason.

If it’s not a problem for you, you can prepare the L version yourself, otherwise you can just ignore the issue (and use small version) and wait for the creator of the rest of L versions to fix it. (Zamolxis if I remember correctly?)

I’m not confident with Photoshop and extracting objects from backgrounds. But I think I should try making the DEF anyway just for experience and criticisms :wink:
I finished the code patch anyway (will post today or tomorrow).

Damn, those DEFs are quirky! Anyway, here’s my patch for #162/#601 and DEF file. Patch adds wake button frame in config/resolutions.json, so it relies on having sprites/IAM011L.def if you’re on high resolution (by the way, why not commit to SVN all the sprites at least)… Also sleeping states are saved. Let me know what you think :slight_smile:
patch_162_201.zip (11.9 KB)

For a while, I actually thought we may end up having ‘S’ versions actually, for the 800x480 res. But given the way the project on one hand, and the smartphone technologies on the other hand are progressing, I’d say that by the time VCMI will be at v1.0, the ‘smartest’ smartphone will support x600+ resolutions already, so we may not need to bang our heads with shrinking solutions. :wink:

Anyway, for IAM011L.DEF, I wouldn’t have known immediately how to do it, as I believe it was Dru who did the others actually, so it’s good yupsi took the initiative for this.

They are indeed, but you seem to have done it. The .def and the .json updates look fine. If you want, have a look at my note to #162, just to double check you didn’t leave anything out. If the case, you may want to re-edit the code, or else advise in a note there how much of the full list of functionalities related to the button are handled by your fix, and what’s left.

Looking forward for the next release to test this, and thanks for the contribution. :slight_smile:

Well, the only thing I didn’t do was call Next Hero button blocking which I think should be done from its own code because I’m calling fnextHero() from fsleepWake() anyway :slight_smile: Actually, none of the hero-specific buttons are currently being blocked when they should (say, Quest Log on non-hero selection). So I only focused on Sleep button. There’s an old issue for non-blocking buttons anyway (#204, I think?).

Ehh, mind if I touch up the other DEF’s while I’m at it, then? :wink: No offense, but in my humble opinion the blocked frame of at least IAM005L looks nothing like the original.

Go ahead. I can see there’s a difference indeed between what we have now and H3 for the blocked frame. I guess we can say that what we had so far was “good enough”, but fine tuning is of course always welcome. :wink:

Hi Yupsi. I tried to apply your patch, but everyone of the changes got rejected. Also, why is resolutions.json replaced ? Your editor may be messing with tabs/spaces.
Could you regenerate your patch please ?

It worked fine for me. But won’t commit it as I have now a real mess in the making.

I cannot apply the patch on eitheir ubuntu or centos. I think the client that generated that diff is broken. Just look at the patch for config/resolutions.json. It’s rewritting everything but only a few lines have actually changed (and it’s actually the only one that applies).

Huh, the client is just the latest TortoiseSvn on Windows, never had problems with it. Json patch looks silly indeed (Tortoise probably doesn’t recognize it as text?), but it doesn’t mess with tabs/spaces, it changes just 6 lines… Here is the patch for latest revision (2392) - maybe that will work?
162_601_from2392.zip (11.9 KB)

There was an end of line mess (unix/dos). I converted back and forth and the patch eventually applied. I tested and it looks good. Thanks.

Tow, the zip file contains a DEF that needs to be added to the distribution.