Huge glaring BOOM/MBF bug

So yeah, Lee Killough made the size of the "bodyque", the list of player corpses in deathmatch, a variable. It can behave like vanilla, with 32 slots, or have any number of custom slots including zero, or it can not exist at all by having its size set less than 0.

TOO BAD that...

  • bodyquesize is not treated as a network variable. If the setting differs between nodes in a netgame, the game may desync.
  • bodyquesize is not saved in demos, so, netdemos need to be played back with the same value of bodyquesize with which they were recorded...
Oops?

Share this post


Link to post

That's what you get when you overanalyze a feature that nobody (ab)used enough for it to be a real issue.

Share this post


Link to post
Maes said:

That's what you get when you overanalyze a feature that nobody (ab)used enough for it to be a real issue.

I just get stuck trying to fix it in EE :/

Share this post


Link to post
Quasar said:

I just get stuck trying to fix it in EE :/

Just revert to a fixed size queue -- DONE.

Share this post


Link to post

Do you have some known thing about bodyque corpses that affects the demo sync ?
I thought that corpses could not affect player movement, nor monster movement, and they don't use random numbers, so how are they making a demo desync ??

Share this post


Link to post

Probably to do with the mobj list shrinking and expanding. As I assume Doom assigns each mobj on a map a number.

The demo expects mobj X to be number Y. If the corpse que differs on the computer of the person playing the demo back, to the demo recorders computer, a different mobj may be that number.

Share this post


Link to post

I don't think you can fix it. You need more than ticcmds to see when a body should be removed. Even if you get a demo that desyncs, you have to:

- prove that it's due to bodyquesize mismatch
- figure out what the mismatch is (out of what, 1,000,000 possibilities?)

You can't put a hook in. For example, I first thought you could just have a client notify all the other clients that it's removing a body out of the body queue, but all that does is sync the client body queue sizes to the largest one. It doesn't sync the demo (it can't, because that information isn't there, and if it was you could just sync at the beginning).

Fixing the bug in the current netcode is basically just adding that field to D_ArbitrateNetStart in d_net.cpp right? Clients already get data like skill, nomonsters, etc.

Share this post


Link to post
Vermil said:

Probably to do with the mobj list shrinking and expanding. As I assume Doom assigns each mobj on a map a number.


The mobj list is totally dynamic in all known Doom implementations, using a doubly-linked list. And, surprisingly enough, there's no dynamic mobj number: ports that require this functionality for e.g. debugging or internal optimizations, gotta add it themselves. Do not confuse the (optional/implied) mobj number with the THING number (which is implied by the order THINGS are stored in the map lumps on-disk) and the doomednum, which is a (non-unique) code that simply identifies the type of thing.

But yeah, if something does NOT use the generator or is NOT able to affect movement, line checking etc. in any way, it should not be causing desyncs by definition, EXCEPT as the result of overflows. Overflowing a non-existing/too small list would certainly do things you don't want.

In any case, can corpses:

  • Affect intercepts?
  • Affect blockmap iterators?
  • Affect movement?
  • Activate linedefs?
if the answer to any of the above is YES, then yeah, there might be a problem. I can only think of a concrete scenario for the last item, though: imagine a sliding corpse that activates a linedef, as in the infamous Killough REVENGE.WAD demo. If that corpse is removed or not even spawned at all due to zero queue size, then of course it will cause sync problems (e.g. removed before it completes the slide).

I presume that (player) corpses are however skipped/NOT counted when e.g. tracing hitscan weapon attacks, when an archvile is looking for corpses to re-animate, when blast-damage is computed etc.

Share this post


Link to post

Heh, very interesting find! I avoid this problem in KBDoom, because I don't allow the changing of the queue size, but I do provide an option to turn it off, and show all corpses. And, yes, that var is synced in demos, and across network nodes.

I'm not sure how the corpse could affect sync. Maybe a lost soul will stop it's charge when it passes over a non-removed corpse?

Here's how you can fix the demo/network sync:
1. In vanilla, do vanilla (32).
2. In non-vanilla, change the code to, instead of removing the corpse, just hide it. You'd still use the queue, but now, you use it to hide the corpse (by setting some new MF_HIDEME flag, and respecting the flag in the renderer). The performance hit for keeping a few hundred invisible mobjs around is nothing. But, if it bothers you, you could start removing them from ALL clients when the queue hits a certain FIXED size. There is a maximum limit on that option, even in MBF, right?

In other words, each client has their own threshold for when to start *hiding* corpses vs. removing them. So all clients stay the same, it's just that, on some systems the human player can see a corpse, which is hidden on others. (kinda difficult to type up, but I think you get it :)

Please reply with your progress - it's an interesting issue!

Share this post


Link to post

I have to allow the "host" to control the size of the corpse queue during netgames. It's old demos that are fucked - since they never recorded the value, and didn't require it to be consistent between nodes, old netdemos recorded with BOOM or MBF (if any exist) may not work. Even worse, vanilla deathmatch netdemos might desync if the default value is changed from 32, which is what the size of the queue was in vanilla.

For vanilla demos I can force the value. For BOOM/MBF, nothing can be done.

Another problem for EE right now though is that we have expended the pre-ordained space for transmission and serialization of sync-critical variables - "GAME_OPTION_SIZE", which was set at 64 bytes by BOOM. Most cleverly, they don't send or record the size of GAME_OPTION_SIZE. So now I will have to add some non-trivial code that special-cases GAME_OPTION_SIZE based on demo_version when reading demos.

Share this post


Link to post
Quasar said:

I have to allow the "host" to control the size of the corpse queue during netgames.

...Or, try my plan, which means you don't have to sync the value.

Quasar said:

It's old demos that are fucked - since they never recorded the value, and didn't require it to be consistent between nodes, old netdemos recorded with BOOM or MBF (if any exist) may not work. Even worse, vanilla deathmatch netdemos might desync if the default value is changed from 32, which is what the size of the queue was in vanilla.

Yeah, that's just ugly. No sense in worrying about it, though. There's nothing that can be done about it, unless you make vars: Player1CorpseQueueSize, Player2CorpseQueueSize, etc. Nobody is going to try to manually set those to play a demo (well, I take back "nobody", there's always the exception).

Quasar said:

For vanilla demos I can force the value. For BOOM/MBF, nothing can be done.

This is true. Just assume 32 - does anyone change that shit, anyway? Sorry, but, what a dumb feature! Again, I support 32, or all, as my only options, and, if a node changes it, it changes for ALL nodes. This works really well, as long as you read the local change the same way the nodes do, and not a tick early. Also, the option change needs to be recorded in the demo also. Yikes.

Quasar said:

Another problem for EE right now though is that we have expended the pre-ordained space for transmission and serialization of sync-critical variables - "GAME_OPTION_SIZE", which was set at 64 bytes by BOOM. Most cleverly, they don't send or record the size of GAME_OPTION_SIZE. So now I will have to add some non-trivial code that special-cases GAME_OPTION_SIZE based on demo_version when reading demos.

Heh, it never ends. I just use my own scheme for appending options to demos. Even though you have to support BOOM/MBF method for those demos, you can always use your own scheme for EE demos.
Again, though, if you change the corpse queue number from "remove" to "hide", you don't have to store the number, because everyone will be using the same code. I'm sure the whole purpose of it was to prevent slowdowns/flashing sprites from there being 3,000 dead marines :)

Now you know why id did not have a bunch of gameplay settings - it's a pain in the ass to synchronize!

Do you have a demo that desyncs because of this? If so, can you share it? Curious to see it.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now