As of last week, network multiplayer worked in moment-to-moment gameplay, but still had sharp edges.
And to talk about those sharp edges, I need you to meet John.
Meet John
John loves this game I'm making, and plays it regularly with his friends. 1
Like his friends, John lives in rural Australia, so he is fortunate to be blessed with all the blistering speed that ADSL1 offers. 2
Unlike his friends, John uses a wifi connection to play online video games.
Silly John.
Predicting the Future
Per the rollback networking model, the game needs to receive controller inputs from all players - including John - in order to simulate a tick (slice of time) of the game.
If those inputs don't arrive in time, then a prediction will be generated: something like "if John was pressing X last time we heard from him, assume John is still pressing X".
That works surprisingly well! Humans aren't that quick at pressing buttons, and while John is enthusiastic, he doesn't exactly have the fastest hands in the west either.
Now, if the prediction later turns out to be wrong, the game rolls back (undoes) all the N simulations it did, incorporates the real input from John, and re-simulates the game N times to catch up to the present; that takes a lot of time, so we'd like to avoid it if possible.
But some inputs, like a command to add John's sister as a new local player,3 are "one time" things: once they happen, they're super unlikely to happen in the next tick, which means that with the default prediction approach we'd be guaranteeing to have to always roll back and resimulate the ticks after those commands - yuck.
So I added support for custom predictions to the rollback library I'm using and now that sort of thing doesn't happen anymore.
Prediction Limits
If the game doesn't receive any input from John for a while, there's no point making predictions anymore because the predictions are almost guaranteed to be incorrect. 4
So the game has to freeze and wait, and previously that happened without any user feedback.
But now all other players can see that they're waiting for John's grandma to finish microwaving her tea so John's connection can be restored: 5
We give John's internet 5 seconds to recover, and after that we assume that he's gone for good & kick him.6
Network Stats
But John's little brother is really into sharing Linux ISOs,7 and that can also impact John's connection quality.
Accordingly, John would really like to know when he needs to initiate a stern discussion on the topic of ethics.
So I added some network statistics for John:
- Ping is the time it takes to send data to a client and get some data back again. 8
- John's mates will see their ping to John's client ping increase if John's connection gets bad.
- Send queue length is the amount of "inputs" that the remote client hasn't acknowledged receiving.
- If this goes up, John is limited by his connection's upload (e.g. congestion) and needs to go talk to his little brother.
- Kbps sent is the upload data usage per second, per client.
- Yes, only 12kbps upload per client means John should be able to play this game over a (stable) dialup connection with 1 friend! 9
- Local and remote 'advantage' tracks how far this client is "behind" other clients, based on its own estimation and remote reports (respectively).
- Those other clients will now also slow down their game simulation proportionately more if they get too far ahead.
Unfortunately I didn't quite get around to using this new overlay to test performance in bad network conditions (ideally with lots of activity happening in the game), but I intend to simulate that soon.
No Web Build Still
The playable web build is unfortunately still out of action!
I want to (see if I can) get the desktop multiplayer into a decent state before I introduce more complications.
John currently does not exist, but hopefully someday he will.
Perhaps when I get back to actually trying to make this game fun, instead of getting lost in the weeds making multiplayer decent?
Which is to say, almost certainly less than 8mbps - somewhere between 2G and 3G mobile phone internet speed, if that helps you.
Though, really, this story would work better if John lived in the city, because a lot of rural towns in Australia actually managed to get upgraded to fibre internet ahead of major suburban areas. But I digress.
Traditionally in rollback networking, you only send "controller inputs", as in "buttons pressed and such". But as I wrote about a little last week, I abuse the "send inputs" model a bit by sending higher level commands like "add new local player" occasionally.
Partly this is because games can only store so many "past game states" in memory (currently we can store well over 100 past game-states), but mostly it's because we don't have enough time available to simulate more than say 8 ticks (given you only have around 2ms to simulate a tick at 60hz).
Yes, not only is John gaming on a wifi connection (shock! horror!), but he's behind 2 walls so he isn't able to get a 5ghz signal from his router, so he's forced to connect using the 2.4ghz spectrum: the same as that used by microwaves.
Probably it just started raining again near John.
(And if you don't get that reference, be grateful that you were never subjected to an ADSL connection running through flood prone areas over old copper lines neglected by the government granted monopoly that was meant to maintain them!)
See Linux ISO.
You might notice that the ping is always close to a multiple of 16ms, when in theory clients on the same computer should have latency less than 1ms.
I believe (but haven't verified) that's probably an artifact of driving the networking from the main game thread right now: the networking code only gets a chance to read and write data once per monitor-refresh, which is 60 times a second - or once every 16ms.
Which is probably good for John, as many ADSL providers in Australia have decided that ADSL isn't worth the hassle & are phasing it out (regardless of whether their affected customers actually have access to any alternative internet via the Aussie government's newish National Broadband Network).