Half-Life Netcode Explained Written by Andreas Thorstensson December 23, 2001 Introduction I think Counter-Strike should be played as much default as possible. The colors, the textures, the shadows etc are all essential parts of a Counter-Strike map. Every corner and dark spot is taken into consideration when you create your tactics and your positions. That should not change. But I still believe that the personal aim skills should pay off and that you really hit where you actually aim. The more random the game gets the more frustrating it is for people that put alot of time into it to escalate on the skill ladder. Behind the netcode The server or gameworld gathers everything that is going on in the multiplayer game. The client sends information or packets with actions issued by the player, movement, firing and so on. The server receives the packets, calculates the information, is it a hit? is it a headshot? and then sends that information back to the client (player). The goal of the netcode is to make it work with every connection and to behave as smooth as possible. The flaws of the netcode in HL Everyone who played games with the Half-Life engine before the new netcode (before 1.1.0.0) remembers the game to be super accurate for players with low ping, and that you had alot higher ping with ISDN and modem compared to the new engine. In the new netcode Valve wanted the game to use less bandwidth to lower the pingtimes for ISDN and modem. To do this they changed the time the client sends updates to the server and the time the server sends the updates to the clients. With less client-server and server-client communication a smaller amount of bandwidth needs to be used. But because of that, the server-client and client-server communication is delayed. With delayed server-client communication the players would move extremely jerky on screen. So they added interpolation. Interpolation takes the position of the semi-last known position of a player and moves it to the last known position during a period of time, interpolation time. On the other hand (and what Valve likes) with delayed server-client communication packetloss does not feel as bad. In the old Half-Life netcode the client-server communication was based on client FPS (frames per second). The FPS decided how many updates were sent to the server. In the new netcode the case is not so. And with default settings the Half-Life engine bases the updates on a 30 FPS average. The flaws of the HL server There is a flaw of the HL server which makes it idle between every serverframe (update to the clients). This causes the game to be less responsive and adds higher pingtimes. Default added lag How much lag do I get by default settings? Lets do some simple math here: Server-client lag An average HL server runs with about 20 fps (server frames) and default server-client update is 20: 1000ms / 20 = 50ms Client-server lag The default client-server update is 30 1000ms / 30 = 33ms Interpolation lag The default interpolation is 100ms 100ms Total 50+33+100 = 183ms Conclusion So your actual latency is your ping + 183ms (in the worst case). A ISDN player will average about 230 ping. Why do I hit at all? Because Valve has added lag compensation. With lag compensation every packet received to the server is examined and its latency is reduced by the engine. So in this way it still "works" even with high ping. And it also (of course) works the same with low ping. Why does it feel so smooth on my client even with high ping? If you have played on a server with very high ping you feel that the weapons still are dead instant, when you hit that fire button the weapon reacts immediately and is being fired. In the new engine much of the multiplayer information is calculated on the client for visual effects. The client estimates were players are, it adds blood when you hit and also adds those bullet holes and marks on walls. But those are not true, they are only estimations and you never know if they are real. Only the server knows, and when you receive the correct update from the server the player that you aimed at will eventually die. And then you know for sure. QuakeWorld worked great The QuakeWorld server is very different compared to the HL server. It always sits waiting for packets to be sent to it. As soon as it gets one, it calculates the data and immediately sends it back to the client. Because of this QuakeWorld does not need interpolation. The only lag caused by QuakeWorld is the client-server updates (which are based on FPS as in the old Half-Life engine). So lets compare added lag with other games: Half-Life As we said before adds up to 183ms lag. QuakeWorld No server frame delay and no server-client delay Client-server communication is decided by client FPS which has a maximum of 72 in QW 1000ms / 72 = 14ms No server-client delay No interpolation Total 0+14+0+0 = 14ms Quake 3 The default server fps is 20 and default server-client update is 20 1000ms / 20 = 50ms The default client-server update is 30 1000ms / 30 = 33ms The default interpolation is 50ms 50ms Total 50+33+50 = 133ms What can I do? So do I have to play another game to get accurate netcode? No you do not, the good part of all this is that you can tweak, or better put, "fix" those flaws. Lets start with client commands: cl_updaterate Default: 20 Suggested: 20-100 depending on bandwidth, if your net_graph is falling and rising decrease this value. cl_cmdrate Default: 30 Suggested: Equal to your average framerate (remember max FPS in Half-Life is 99/100) or a divisor of it if your bandwith doesnt handle it. If you have a steady FPS near 99, make sure to put this value above 100. ex_interp Default 0.1 Suggested 0.05-0.1 Decreases the interpolation time, i.e the smoothing of the movement. The players will move more jerkily but more accurately. cl_lc Default: 1 Suggested: 1 Set to 0 removes the lag compensation totally, only works on LAN and with a very low ping. cl_lw Default: 1 Suggested: 1/0 Set to 0 removes the client-side behaviour of weapons and hits. A fired bullet (packet) is sent to the server and then returned to verify if it was a hit or not. Now you know for sure you did hit. But it only works fine on LAN and with low ping. Now to server problems: Thanks to Zibbo from UDPSoft who has released HLDS Ping Booster a fixed version of the HL server, you can increase the server fps heavily. The only drawback is that the server requires alot more CPU. You can then limit the server-client traffic with sv_maxupdaterate, default is 100. So how much can I reduce the added lag? Lets do the same maths again. Now we use the HLDS Ping Booster (maxupdaterate 100), we use cl_updaterate 100, cl_cmdrate 100 and ex_interp 0. Server-client lag A ping boosted HL server (with maxupdaterate 100) and server-client updates with cl_updaterate 100 1000ms / 100 = 10ms Client-server lag Client-server updates with cl_cmdrate 100 1000ms / 100 = 10ms Interpolation lag No interpolation 0ms Total 10+10+0 = 20ms Conclusion From 183ms to 20ms with settings and the HLDS Ping Booster. Quite impressive. Note: Using ex_interp 0 is not really recommended and is alot about personal taste, try values around 0.05. Conclusion I dont want to be a netcode/config cheater! Lets face it, why is it a cheat to make sure that what you see is also what the server sees? Take a basic example, with default cl_cmdrate and with an avg fps of 90 (quite common for the average player), only every 3rd frame you see on screen is true, the two other frames are totally ignored by the server (it does not know about them). How accurate is that? No wonder alot of people randomly says "useless game" while they are playing. The commands are here, now just use them in a correct way. And last but not least, lets play the game as it was intended, with default graphics, sounds and models but with accuracy!