Hey, good question!
So starting from first principles, the server needs to let the client know these events:
a) The game starting
b) When cash outs happen
c) When the game ends
And let's remember, there is a certain amount of time it takes for the server to communicate with the client (latency).
So the most naive solution is simply to broadcast all the events in real time. That will work fine, but the first issue you'll run into is when there's a network connection the client won't (immediately) realize and it'll look like the multiplier is going super high. When the network connection issues resolve, the user will be disappointed to learn that it didn't really go that high.
So we're going to need to broadcast a "heartbeat" (or game tick). Ideally multiple times per second, so if the client doesn't get the heart-beat it knows immediately something is up.
That's going to work fine now, and we're in business. But each message we send/process incurs overhead, and with a lot of events it's going to cause issues on both the server and client. Bustabit v1 was notorious for this. So there's a whole slew of optimizations we can make.
So let's go through a few that bustabit v2 employs:
A) Sends the client the (auto) cashout of the other players. That way the client can "predict" other players cashing out, and there's no need for the server to say the player cashed out at that point. This way the server only tells clients when a player manually cashed out.
B) Batch cash out events. If people cash out at the same time (or close to it), just send it in a big message.
c) Combine heart-beats with cashout events. If the server sends a cashout event, obviously the network connection is fine. No need for a heartbeat in that time.
---
And your question regarding synchronization is a little tricky. So two things to remember: there is always latency between the server and client. It's not possible for the server to tell the client the exact time the game will crash (until it actually crashes) or people would hack the client to easily cheat.
So the client basically has two options. One is to try show the multiplier that is CURRENTLY on the server. The other is to show the multiplier that the player would get if they hit the cashout button. The first solution is better for when you lose (it shows a lot smoother). The second solution is better for when you win (players are a lot less affected by latency. But the multiplier will overshoot the actual crash, i.e. the player will see 1.92x and then see "busted at 1.90x").
So bustabit tries to go more with the first approach. And each heartbeat it tells the client how much time has elapsed, which the client can use to correct its idea of when the game started (i.e. latency is not necessarily constant. It might get better and worse ). You can see how bustabit v1 did this:
https://github.com/kungfuant/webserver/blob/master/client_new/scripts/game-logic/GameEngineStore.js#L192-L195--
Hope that makes sense!
Hey Ryan, thanks a lot for your answer!
"So bustabit tries to go more with the first approach. And each heartbeat it tells the client how much time has elapsed, which the client can use to correct its idea of when the game started "
Why is it necessary to correct the start time on each heartbeat? How does the start time change? Lets say the client somehow decided the start time to be 5000 but the server actually started at 5001 it will correct this start time on the very first tick it receives, where can it go wrong from there? Why would the client suddenly change the start time?
"So the client basically has two options..." Could you perhaps elaborate more on this? I don't really understand what you ment.