ValveSoftware / halflife

Half-Life 1 engine based games
Other
3.74k stars 631 forks source link

Improve netcode to that of CS 1.3 or below #188

Closed dwhy83 closed 11 years ago

dwhy83 commented 11 years ago

The CS 1.3 netcode was more responsive than later versions of the game. We saw evidence of this change of behavior as top tournament players lost their ability to effective spray weapons accurately with later releases.

I read a white paper about the netcode by Yahn W. Bernier (yahn@valvesoftware.com), and it seems this change was made in order to mitigate cheating.

Here is a relevant excerpt from the paper (bolded sentences to get the gist):

https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization#Client-Side_Prediction_of_Weapon_Firing

Client-Side Prediction of Weapon Firing

Layering prediction of the firing effects of weapons onto the above system is straightforward. Additional state information is needed for the local player on the client, of course, including which weapons are being held, which one is active, and how much ammo each of these weapons has remaining. With this information, the firing logic can be layered on top of the movement logic because, once again, the state of the firing buttons is included in the user command data structure that is shared between the client and the server. Of course, this can get complicated if the actual weapon logic is different between client and server. In Half-Life, we chose to avoid this complication by moving the implementation of a weapon's firing logic into "shared code" just like the player movement code. All of the variables that contribute to determining weapon state (e.g., ammo, when the next firing of the weapon can occur, what weapon animation is playing, etc.), are then part of the authoritative server state and are replicated to the client so that they can be used on the client for prediction of weapon state there.

But it goes on to say that this was done in order to mitigate cheating:

Umm, This is a Lot of Work

Replicating the necessary fields to the client and handling all of the intermediate state is a fair amount of work. At this point, you may be asking, why not eliminate all of the server stuff and just have the client report where s/he is after each movement? In other words, why not ditch the server stuff and just run the movement and weapons purely on the client-side? Then, the client would just send results to the server along the lines of, "I'm now at position x and, by the way, I just shot player 2 in the head." This is fine if you can trust the client. This is how a lot of the military simulation systems work (i.e., they are a closed system and they trust all of the clients). This is how peer-to-peer games generally work. For Half-Life, this mechanism is unworkable because of realistic concerns about cheating. If we encapsulated absolute state data in this fashion, we'd raise the motivation to hack the client even higher than it already is3. For our games, this risk is too high and we fall back to requiring an authoritative server.

The problem is that the user experience has suffered, but people still cheat. Since cheaters will invariably cheat, why not optimize the netcode experience for everyone else and allow them to manually police cheaters the way they must already do now in tournaments, competitive leagues, and public servers?

Players want to feel empowered, not restricted. A more responsive game is more fun and addictive. Please please please do anything you can to optimize the netcode to what it was in CS 1.3 and earlier versions! Or even improve it beyond that.

dwhy83 commented 11 years ago

P.S. Years ago, I have fond memories of going home for the summer from college and playing CS with 300-400 ping on AOL dialup. That's how performant the game and netcode was. That isn't possible today (I've tried it).

MPNumB commented 11 years ago

Client side isn't predicting recoil if what. https://github.com/ValveSoftware/halflife/issues/82

jukkhop commented 11 years ago

I think what you both want is client-side recoil prediction. And I agree wholeheartedly. Malicious people will do malicious things no matter what.

Antoweif commented 11 years ago

The problem is getting synced with the server. Use net_graph 1 to determine how much in sync you are. The green line shows how stable your download is, the line under is for upload. For a perfect example, use "New Game" and watch how the line is dead stable, just like the green one.

The trick with net_graph 1 is that the blue/purple line (below green one) shows how off sync you are with the server (why I don't know ...net_graph is a strange debugger tool - not even VALVE understand how it works). For example, if a server is running 125FPS, the client is forced to use 62.5FPS in order to become correctly synced. In other words, it is completely impossible to become correctly synced if the server is running anything but 100FPS, 200FPS 300FPS ...1000FPS+. I think it has to do with how cl_cmdrate is linked with FPS.

A (slight) workaround is using a nasty alias trick alias "+damage" "fps_max 62.5; wait; +attack; fps_max 100" alias "-damage" "-attack" bind "mouse1" "+damage"

The interesting part about this is that the higher ping you have, the worse prediction you will get. This is not true if you are able to sync properly, but the netcode has its limits. Recoil is client-side, not server-side. However, bullet spray is server-side. DON'T CONFUSE THE TWO. This is why it's so confusing when you suddenly aren't hitting your shots. Workaround for this is to simply change weapons to reset your bullet prediction. Doesn't matter if you wait for recoil, your bullet prediction may be off by miles.

Why this is a issue is beyond me. I also vote for client side prediction if a cvar is enabled on the server sv_client_prediction 1!

Edit: The recoil is just an effect to make the game harder and add realism. It's there to emulate the bullet pattern, but does a horrible job in some cases, because the bullet pattern varies from server to server.

MPNumB commented 11 years ago

Actually recoil (by how much angle your angle changes) is completely server side, and client doesn't even predict it. Cause of this alone, the higher ping you get, the less recoil you feel you have, but the worse reg it seems to be.

For example lets say you have 250 ping. You are firing 2 bullets (lets pretend recoil doesn't cool down, and rate of fire is 0.1 seconds). You made 1 shot what goes in center of crosshair. You send information to the server that you made a shot (250ms). Now server gets that information, gets your angle, rechecks speed/ground/and many more condition. Fires the bullet by its own values, but relocates player origins during that shot due to ex_interp and ping (though that doesn't matter in this subject). Now bullet is fired, and lets say it gives you +5 vertical angle. Afterwords it sends the information that it made a shot, and where it really did hit (it matters to client only if cl_lw is 0). This information transfer took 250ms as well. So now you receive the +1 degree angle update only 0.5 seconds after you made a shot (250ms + 250ms = 0.5sec). But wait... Rate of fire is only 0.1... So 4 other bullets you fired during the 0.4 seconds... What about them. On your screen they are still in angle 0... Only now, oh, god... 0.1 seconds later your angle goes up again, then again, and again, and again. Though on your screen you weren't holding attack button anymore. RESULT: Actual bullet location on the server: each bullet is 1 degree higher than previous one. But what do we see on the client: all bullets are in the same location. CONCLUSION: Recoil isn't predicted by client-side at all, and is server-based. And this is just in case if we also pretend that bullet spread is disabled.

Now talking about bullet spread... It has nothing to do with how much your angle changes. It's based on time - how far away from your (angle + recoil) bullet can and will go (kind of randomly). Client-side doesn't seem to have no pattern to it, but when you write cl_lw 0, you can start to notice patterns (I recommend to test with g3sg1 - most visible). Funny thing is, that it's server-side what actually matters, cause it's the side what deals the damage made. But even more funny thing is, that spread calculation isn't only different server-side / client-side, but also that the actual mathematical calculation code of it is wrong. Bullets use accuracy of previous shots made - spread accuracy is updated after the variable is used for it's purpose, not before, what creates "random shot after spraying bug", what you can test with ak47 (cl_lw 0, spray 20 bullets non-stop, wait for recoil to cool down, don't move, stand on ground and make 1 shot - you should see bullet is really away from where it should be). Not even to mention that for sg550 and g3sg1 spread is calculated the backwards way - the longer you fire, the more accurate the weapon becomes. And that some weapons don't even have/use the spread calculation. But I've already reported it as well here: https://github.com/ValveSoftware/halflife/issues/83 In fact I've even created amxmodx plugin what fixes some of this spread-based issues some time ago.

My point is, where client-side bullet is going doesn't even matter for the server, and as far as the damage goes. Only thing what makes a difference here is ex_interp and how far back in time hitboxes are moved when shot is made. Client-side doesn't match server side in both bullet spread (makes people think reg is wrong), and client-side doesn't even have pev->punchangle (recoil) prediction, what makes it even worse to control your recoil the higher the ping goes, cause you must predict how recoil will be your_ping*2 milliseconds into the future (and guess what, nobody does that, even worse many don't even know about it, what makes people think reg is even worse). Eventually people blame it on the plugins installed, or that server is bad, when really they were just unlucky enough that their spread prediction was way different, and that their ping is bad, so they are having recoil issues. Here you can see the spread plugin-fix what I've done (also uploaded demo examples if you want): http://forums.alliedmods.net/showthread.php?p=1549133

Antoweif commented 11 years ago

cl_lw 0 is indeed 'bugged'. What you didn't explain is why the bullets go in the same hole if you watch others do the same task. You only explained client-side.

Antoweif commented 11 years ago

I tested the delay thingy (again) with both cl_lw 1 and 0 at 0 - 500ms. Like I said, recoil is not related to the bullet pattern the server predicts in any way.

Bullet pattern (server-side) is static I guess, while the recoil (client-side) adds a dynamic picture. This is why when you shoot 1 and 1 bullet instead of holding down your fire button, you skip the recoil entirely and thus you get 1 bullet hole.

alfred-valve commented 11 years ago

Such major changes to the net code are beyond the scope of this update.

MPNumB commented 11 years ago

Cause for others, it's server info you are using regardless of cl_lw. How should it predict what others are doing. Better yet, why should it even do that - you are connected to a server, not to them? You don't ever need to predict weapon things of anyone else but yourself.

cl_lw is client-side cvar. It makes a visual difference only for the person who is alive and preforming an action. There is no difference whenever you are spectating a person who has it 0 or 1. As far as server is considered, for you it sends it's own information, and as far as your client-side is concerned, once you are dead there is no need to predict no weapon actions, and just use server-side info.

Oh, and in that post I did explain what server-side is doing, and what client-side thinks server-side is doing.

So cl_lw 0. You made a shot at 0ms and you noticed the instant recoil reaction, but somehow at ping 250 you didn't notice half a second delay for your angle to kick up?

Also server doesn't predict anything ever. It updates it's information only on commands, velocity request (what is later on calculated to be proven to be possible), framerate, button updates, and new angle.

Plus I really don't want go be technical, but you also just said that recoil (angle change; aka pev->punchangle engine variable) has nothing to do where your bullets go, and it doesn't even matter if it's there. You probably won't understand this, but check out line number 183 over here: http://pastebin.com/3zGeRCha . That is code from server-side what determines in what angle the bullet should 'fly' (without the spread calculation, what doesn't matter right now). As you can see it is using the pev->punchangle variable. And whatever this traceline ('bullet') hits while 'flying' in server-side takes damage, and a black dot appears there for everybody to see except the attacker (unless attacker has cl_lw 0 - in this case for the attacker it's also in that position).

dwhy83 commented 11 years ago

Is there a way to get confirmation of what changed in versions after CS 1.3 that might be pertinent to this issue? That would at least allow us to better pursue this issue in the future.

jukkhop commented 11 years ago

I'm not sure it will do much good -- I doubt Valve is willing to invest that much time into the game or make big changes like that. I think they just wanted to fix small things while making the game cross-platform. At best, I think they would've adapted Source's netcode to GoldSrc but even that would probably require too much coding and testing.

Another thing is that CS 1.6 has long since gained a classic status -- have you seen people's reactions about the new changes? The steam forums are going silly. You have people making petitions for a revert and people saying Valve is making the game bad on purpose. Personally I like the updates, the game runs great, I've had very little problems.

I'm not saying the vocal minority has much affect on the developers, but I doubt it's making them happy and willing to invest even more time to the game than originally intended.

di57inct commented 11 years ago

Better leave it the way it is. We don't need it to become worse.

cenitr commented 8 years ago

Everything client sided would have been much better. The recoil is a must to be client sided. Counter strike is so much ping based game now that it is not competitive at all. Low pingers have huge, huge advantage to high pingers. Recoil gets totally wrong if you have higher ping than 20ms. If you got 50ms it's not even fun to even play the game. CS 1.6 is a LAN game unless you have a really, really good internet connection, period.

Great that this is being highlighted somewhere since it have to change or fps is just not fun to play any more.

di57inct commented 8 years ago

Everything client-sided = cheated. Play on servers with low ping. I don't care about players with high ping.

cenitr commented 8 years ago

With everything client sided we would always have something real to hit and a working spray pattern and bullets. From there we want to develop the net code to render players position as correct as possible. The server admin would set a maximum ping that would be allowed. For example a higher ping of 30 would not be allowed by the admin and the player would be banned for x hours.