Skip to content

Instantly share code, notes, and snippets.

@nessus42
Last active August 8, 2017 19:09
Show Gist options
  • Save nessus42/17c433143c68bc4500c5637616557e86 to your computer and use it in GitHub Desktop.
Save nessus42/17c433143c68bc4500c5637616557e86 to your computer and use it in GitHub Desktop.
The Past, The Present, and Destiny

The Past, The Present, and Destiny

Let's take a little break from the current day to discuss some of the history of FPS networking.

In the early days of FPS PvP games (i.e., back in the days of Quake), they were sometimes implemented using a pure client/server networking model. In a pure client/server model, all of the calculations about the game are done on the dedicated server and your console is relegated to being mostly a 3D rendering engine.

This is not how things work in either Destiny 1 or 2. In both games, every console is calculating all of the physics for an entire Bubble all of the time. The reason for this is that you want a first-person shooter to be very snappy. You want the bullets that you shoot from your gun to hit the target now and not half-a-second from now. When you cancel your jump, you want it cancelled now and not half-a-second from now. This is very important for an FPS game to feel visceral, real, and snappy. I.e., for it to feel the same way that it would feel if you were playing the story mode of a single-player FPS game.

And Bungie has explicitly stated that this was one of their primary goals in making Destiny: They wanted it to "feel like a single-player shooter".

With a pure client/server model, on the other hand, every time a bullet is fired from your gun, to see the damage done to your enemy, you have to wait for notification of that bullet to travel across the Internet to the server. The server then needs to determine if the bullets intersected with the target of the bullets. Damage from those bullets then needs to be calculated on the server. Then the server needs to send information back across the Internet to your console telling your console the new health of your enemy. Once all of this has happened, finally your console can render the damage. All of this needs to happen before you will see any damage register. Likewise, when you push on your thumbstick to move, you have to wait for that thumb-stick information to be transmitted to the dedicated server, then you have to wait for the server to calculate the effects of that thumbstick movement on your game character's body. And then you have to wait for that information to be received by your console. And then you need to wait for your console to render that information to your TV.

Unless your network connection to the server is very, very fast, this will not feel as immediate and visceral as playing a non-networked FPS game.

It should be noted, however, that no popular first-person shooter has implemented this pure of a client/server model in probably more than 15 years. Client/server implementations for first-person shooters have used techniques like "client-side prediction", etc., for quite some time, in order to mitigate the problems just described. (In Halo Reach, however, co-op play did suffer these issues. Not because it used a pure client/server model, but rather because it used lockstep P2P networking, which has similar issues.)

What happens instead with Destiny's networking, is that your console calculates the damage you do to an enemy immediately or it calculates your character's movement resulting from your controller actions immediately, without consulting with the Physics Host. (Assuming that your host is not the Physics Host.) You see the damage or movement reflected immediately. Periodically, your console and the Physics Host reconcile with each other. The Physics Host is taken to be authoritative regarding damage, etc., but your console is taken to be authoritative about your "movement and abilities". Upon reconciliation, the state of your console-specific Bubble will updated to reflect what the Physics host says it should be, taking into account the information about your character that is authoritative to your console.

If you want to know more about the trade-offs between client/server models and having all the physics simulation done by each console, you might be interested in this article: What every programmer needs to know about game networking.

John Carmack (of Doom & Quake fame) is quoted in this article as saying the following about the pure client/server model:

While I can remember and justify all of my decisions about networking from DOOM through Quake, the bottom line is that I was working with the wrong basic assumptions for doing a good internet game. My original design was targeted at < 200ms connection latencies. People that have a digital connection to the internet through a good provider get a pretty good game experience. Unfortunately, 99% of the world gets on with a slip or ppp connection over a modem, often through a crappy overcrowded ISP. This gives 300+ ms latencies, minimum. Client. User's modem. ISP's modem. Server. ISP's modem. User's modem. Client. God, that sucks.

Ok, I made a bad call. I have a T1 to my house, so I just wasn't familliar with PPP life. I'm addressing it now.

To rectify the problems with the pure client/server model, Carmack implemented a more sophisticated client/server approach, and this is what he had to say about this more sophisticated approach:

I am now allowing the client to guess at the results of the users movement until the authoritative response from the server comes through. This is a biiiig architectural change. The client now needs to know about solidity of objects, friction, gravity, etc. I am sad to see the elegant client-as-terminal setup go away, but I am practical above idealistic.

The article goes on to say:

So now in order to remove the latency, the client runs more code than it previously did. It is no longer a dumb terminal sending inputs to the server and interpolating between state sent back. Instead it is able to predict the movement of your character locally and immediately in response to your input, running a subset of the game code for your player character on the client machine.

Now as soon as you press forward, there is no wait for a round trip between client and server – your character start moving forward right away.

The quotes from Carmack are quite old at this point, and so you may think that they are no longer relevant. E.g., no one is trying to play Destiny using a dial-up modem. (Or so I hope.) But many sources of latency still exist. In Destiny, for instance, your fireteam may consist of players from all over the world. I routinely play with people who live in England or Australia or Hong Kong, etc., while I live near Boston, MA. Having a fireteam distributed all over the world is a distinct source of lag. Additionally, many players opt for slow DSL Internet connections because they are very cheap. And perhaps worst of all, most people probably connect their console to the Internet using WiFi, which is prone to packet loss, which is often more problematic than latency. I have even played with a few people whose only Internet connection is via a WiFi hotspot coming from their cell phone! One would think that playing Destiny through a cell phone hot-spot could not possibly work well at all! And yet, from my perspective, this didn't cause any problems. The people who do this have also claimed that it works mostly without issue for them.

So, going back a paragraph or two, we see that there's a spectrum between having a completely authoritative pure client/server model where the server does all the calculations and relegates your console to being basically just a dumb terminal that is only responsible for 3D rendering, to having a server that delegates more of the authority to each console and lets each console do more sophisticated calculations, so that the console can render the player's actions with less lag.

Destiny has gone to the extreme end with this second approach. So much so that each console does all the very same physics calculations that the server does.

The upside of this is that your personal actions are rendered just as immediately as if you were playing a single-player first-person shooter. The downside of this approach is that if packets representing damage from your gun unfortunately never make it from your console to the Physics Host for some reason, or other network traffic is delayed or goes missing, you may end up seeing glitches, such as enemies that inexplicably heal, or refuse to die, even when it seems that you've killed them, etc.

If packets go missing or are delayed in the other direction, i.e,, from the Physics Host to you, then you may end shooting at adds that seem to be immortal, but are really already dead. And you may see adds and other players teleport around the map, since you are only updated about their authoritative locations infrequently or with too much latency.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment