![]() |
|
Client prediction and scripts |
SiegeLord
Member #7,827
October 2006
![]() |
So I've been thinking of how to implement multiplayer in my vapourware ARPG. The best way (or so I thought) appeared to me to be just doing client prediction by running the same game code on both client and server, but then sending updates from the server and correcting the client. This way there would be no lag on the player movements, but an occasional reset when multiple players interact with the same objects. Delta compression combined with things like room/view clipping (objects that the player can't interact with or see wouldn't be sent to the client, thus preventing things like wallhacks and whatnot) would be used to reduce the bandwidth usage. I thought about this some more, I realized that this method is complicated immensely if I add scripting into this game. Scripts can add non-obvious and far reaching object dependencies... e.g. I might have a global script that does something depending on the state of an object quite far away from where a player is, which means that the clipping idea I described above wouldn't work: it just is no longer obvious how I would determine what parts of the world need synchronization when I allow scripts with a global view of the world. The only thing that is guaranteed to work is updating the entire playable world, and that might be infeasible. So yeah... anyone who coded multiplayer games with scripts have any advice? Did you scrap full client side prediction, and settle for a more limited kind? Or the bandwidth requirement ended up not being an issue? Note that this is an ARPG, and I decided that the latency requirements are similar to those of an FPS... so client side prediction pretty much has to be there in some way. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Stas B.
Member #9,615
March 2008
|
Well, in most FPS games, the client acts like a dumb terminal. The only game code it runs is for player movement. Scripts run on the server. |
jmasterx
Member #11,410
October 2009
|
Yeah, for example, a script might cause the player to shoot a bullet (player 'movement') and after that, knowing the vector of the bullet, the client can predict where it might head and interpolate its position. I do not think that a script would ever do anything that would not result in some sort of primitive command. If yours needs to then make those special cases that the client cannot predict, but in cases like that it probably results in an animation execution, where prediction is easy then. Agui GUI API -> https://github.com/jmasterx/Agui |
Oscar Giner
Member #2,207
April 2002
![]() |
What Stas B. says. I can also confirmm after playing Guild Wars for a long time so I'm being used to how it works when you lag, that it also works that way. The only things that gets predicted by the client are player movements (so when you lag too much you see other people and yourself jumping because of bad predictions) and health/mana regeneration and degeneration (but not death! even if a predicted health degeneration gets you to 0 health while you're lagging, your character won't die (you may have been healed while you where lagged, for example, so it's better to not preddict a death, that would look worse)). All AI is also done entirely only by the server, and not predicted (so if you lag all enemies and npc's just stand still). The same happens with any scripted driven object. Even the casting of your own skills is not "predicted". If you try to cast a skill while you're lagged, the skill icon in your skill bar will anymate as it does when you cast a skill, but your character won't cast anything. Diablo III seems to work in a very similar way. So the client is very "stupid". -- |
Stas B.
Member #9,615
March 2008
|
Oscar Giner said: (so when you lag too much you see other people and yourself jumping because of bad predictions)
Why would they make jumping and other people's movement subject to prediction? [EDIT] Oh. You don't mean actual jumping... I'm slow sometimes. |
Elias
Member #358
May 2000
|
SiegeLord said: The only thing that is guaranteed to work is updating the entire playable world, and that might be infeasible. You always know what needs synchronization - anything your script touched on the local game state. For example I opted for something like this: class GameState: Tile map[1000*1000] Entity entities[1000] GameState server GameState local Now if your script does anything, it will do two things:
The server will process your requests (and those by any other clients) and send the result back to you (and everyone else). Now you update your server gamestate with the data from the server (a list of tiles and entities to update) and then also update the local gamestate. (Just local.map[x] = server.map[x] and local.entities[y] = server.entities[y] for any x/y updates, resetting the modified flags they possibly had in the local copy.) If your modification list has any changes not confirmed by the server now (tiles/entities with the modified flag), revert those back to your server state. -- |
SiegeLord
Member #7,827
October 2006
![]() |
Oscar Giner said: so when you lag too much you see other people and yourself jumping because of bad predictions Yes, that's what I wanted to prevent (well, at least in terms of NPCs jumping). Elias said: Tell the server what it does. I don't trust the client with anything other than keyboard/mouse input. Here's an illustration of my issue. I have 3 objects, A, B and C. A is directly visible by the player, while B and C are in a different room and their data would not normally be sent to the client. Now, I have a script that affects A given B's state. B's state also depends on C indirectly and in a way unknown to the script. Now, the original idea was to run the same script both on the client and on the server, and for there to be any hope that it runs the same (without player's input) then we need to send data about A, B and C to the client. The question is... how do I know, given the script, that B and C need to be updated. Now, I guess the server might know because it can check whether the script is accessing any object's data. Then it can run the same culling algorithm that was run on the player to get other potential objects that might be of interest. I guess that could be done. The bigger issue is then the client knowing everything there is to know about the world... now there can be things like wallhacks because the client is given all this information that it ostensibly needs for prediction to work, but something that the player shouldn't really know directly. So yeah... at the end of the day it seems that perfect prediction can only work if you trust the client quite a bit more than I think I am willing to. I'll probably use dumb prediction as was described in this thread... if it's good enough for AAA games, it's good enough for my vapourware. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Stas B.
Member #9,615
March 2008
|
SiegeLord said: Yes, that's what I wanted to prevent (well, at least in terms of NPCs jumping). You won't have NPCs "jumping" if you don't try to predict them. You'll just see delayed reactions when the latency is significant. If you try to predict them, you may end up having them jump all over the place because small differences between server and client object states may result in them making different decisions. |
SiegeLord
Member #7,827
October 2006
![]() |
Stas B. said: You'll just see delayed reactions when the latency is significant. If latency wasn't significant, then I wouldn't be doing prediction. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Stas B.
Member #9,615
March 2008
|
Define significant... A latency of 100ms is horrific without movement prediction but doesn't matter too much for NPCs. If by significant you mean around 500ms, good luck making an action game playable, with or without prediction. |
SiegeLord
Member #7,827
October 2006
![]() |
So you're making a claim that games that use client prediction only do that prediction on the local player characters and not NPCs and remote players? That seems really unlikely to me. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Stas B.
Member #9,615
March 2008
|
I can't make any claims regarding all games, but I know that Quake and Source engine based games predict only local player movement. Trying to predict other players doesn't really make sense. If no prediction is good enough for human players, it's probably good enough for NPCs. With other players and NPCs eliminated, you don't really have any things left to predict. Items don't move much and don't need to react quickly to the player. Makes your life so much easier. |
Elias
Member #358
May 2000
|
In my game I only predict the local player as well. In my limited testing that's all that's needed. Without any prediction it feels very unresponsive (I do something and it only happens half a second later). With the prediction it feels completely smooth even with 300ms-500ms (400ms + 100ms jitter, that's what I experimented with in my lag simulation as worst case). Other players are of course not exactly where they are, but in a 2D RPG that doesn't matter at all. In an FPS I could see more need for also predicting other players (so you know where to aim). -- |
Stas B.
Member #9,615
March 2008
|
Elias said: In an FPS I could see more need for also predicting other players (so you know where to aim).
That's the funny part. There isn't any prediction going on. When a player shoots, they shoot things that simply aren't there any more as far as the server is concerned. To compensate for that, the server stores the game states from the past couple of seconds, goes back in time and checks if there's a hit. |
weapon_S
Member #7,859
October 2006
![]() |
Uneducated opininion. |
SiegeLord
Member #7,827
October 2006
![]() |
Stas B. said: you don't really have any things left to predict. Projectiles. Think SHUMP. I really would like to add some skill (as opposed to stat) gameplay to my game which tends to imply ability to move and dodge effectively. Another idea I had would be have the server simulate ahead and send clients states that would be current from the client's point of view. Two issues come to mind:
This idea seems complicated, but it wins out over the original idea in terms of bandwidth requirements (everything fancy is done server-side). I think the number of paradoxes should be about the same too. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Stas B.
Member #9,615
March 2008
|
SiegeLord said: Projectiles. Think SHUMP. I really would like to add some skill (as opposed to stat) gameplay to my game which tends to imply ability to move and dodge effectively. It's a shame that you don't actually read my posts. The client will always lag behind the server and there is nothing you can do about it. If anything, trying to predict the future will only cause more errors and paradoxes, especially when dealing with unpredictable humans. I actually described how real shmups handle projectiles in a previous post. The server buffers all the game states from the last second or so. When it receives a time-stamped shoot command from a client, it estimates the state on the client at the time of the shot and checks if there was a hit from the client's point of view. I'm not just pulling things out of my ass. I know that this is how real shooters work from multiplayer modding experience and from having implemented a few of these techniques myself. |
SiegeLord
Member #7,827
October 2006
![]() |
Neither you nor any other literature I read on the topic mention the need to re-simulate the server state in response to player input The paradoxes I mentioned earlier can be mitigated by introducing artificial lag in the client, such that the client never uses a server game state that is more recent than 2x the lag... but in exchange for the elimination of paradoxes, you introduce quite a bit more lag. Now I know Source engine games use artificial lag, but I don't think they use it for the purposes of paradox prevention, rather using it to get interpolation working in the first place. Now, you're saying that you've implemented this and that, and that's how SHUMPs work, but then I see stuff like this where they are forced to use duplicated logic code (just like the idea in my original post) in both clients (no server in their method) to solve the issues I'm raising and you're dismissing. How do you reconcile this with your expert knowledge? "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Stas B.
Member #9,615
March 2008
|
SiegeLord said: Neither you nor any other literature I read on the topic mention the need to re-simulate the server state in response to player input . You mention lag compensation, but not what actually happens when the server detects a hit. You're talking as if recently-arrived player input changes the past and you need to "re-simulate" everything to account for that. Player input only affects the currently simulated state. When the server detects a hit, it damages the player who has been hit. What else could it do? Quote: Now I know Source engine games use artificial lag, but I don't think they use it for the purposes of paradox prevention, rather using it to get interpolation working in the first place. It's just the only way to get the motion of other players and the props they interact with to look smooth on the client, unless you want to extrapolate their old motion while waiting for the new info to arrive. I guess they do use it to prevent paradoxes. It wouldn't be cool to see a player moving towards you only to see them ducking in a corner the next frame, or to see a player bumping into the wall when they try to pass though a doorway and disappearing from sight on the next frame. And what will you do when the clients shoot these "ghosts"? Quote: Now, you're saying that you've implemented this and that, and that's how SHUMPs work, but then I see stuff like this[ggpo.net] where they are forced to use duplicated logic code (just like the idea in my original post) in both clients (no server in their method) to solve the issues I'm raising and you're dismissing. How do you reconcile this with your expert knowledge?
I never claimed to know how every game in existance works. I've already made it clear what games I'm referring to when I say that "real" SHMUPs do this and that, so I don't need to reconcile every counter-example with my "expert" knowledge. It's nice that you bring up this particular example, though. This is exactly what arcade emulators do, mainly because they can't do it any other way. Download MAME and Kaillera and see how well it works in practice. Then consider how much better it would work with 20 players instead of 2. Anyway, I wanted to help and ended up arguing with you, which is kind of ridiculous. I guess all I wanted to say is that if you want FPS-grade performance, check out the time-tested techniques used in games like Quake and Counter-Strike. I'm not saying we should all just stick to that and not try to come up with anything better. I'm just saying that the ideas you mentioned here are neither new nor that great in practice (and I explained why) and it's going to take you a hell of a lot more thought and experimentation to 1up the standard techniques. If your goal is to come up with a revolutionary networking engine, by all means stick to it! If you just want to make a playable game, don't reinvent the square wheel. |
SiegeLord
Member #7,827
October 2006
![]() |
Stas B. said: What else could it do? Move the player? Cause a script to execute which creates some objects? Make the bullet disappear? There are far more things that could happen than a simple decrease of hitpoints. Quote: I've already made it clear what games I'm referring to when I say that "real" SHMUPs do this and that Umm, you only mentioned Source games and Quake, neither of which is a SHUMP. I honestly am not sure what games you're referring to. Quote: Anyway, I wanted to help and ended up arguing with you, which is kind of ridiculous. Trust me, it's not me, it's you. Threads where you and the OP end up in a shouting match are disturbingly common Quote: the time-tested techniques used in games like Quake and Counter-Strike Those time tested techniques have a great many issues like requiring lag-dependent target leading (Quake) and not working with non-hitscan weapons (Counter-Strike). The key point is that the techniques they use arise from the gameplay that FPSs use, which tends to revolve around NPC-less worlds full of hitscan weapons with limited scripting support. Just because an FPS uses some technique doesn't mean that that technique is applicable to other game types, specifically my case where NPCs are common and hitscan weapons are non-existent. Quote: I'm just saying that the ideas you mentioned here are neither new nor that great in practice If they are not new, then why are they not mentioned in the Source engine literature (both on it's developer's wiki and in the academic papers?). All places I've read specifically don't do anything with non-hitscan weapons and don't mention NPCs whatsoever. They specifically say that server side lag compensation does not work for projectile weapons. Now... I just did some more research and found this video:
Nevermind, it doesn't do what I thought it did. It does illustrate the problem I'd like to mitigate somehow though. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Stas B.
Member #9,615
March 2008
|
SiegeLord said: Move the player? Cause a script to execute which creates some objects? Make the bullet disappear? There are far more things that could happen than a simple decrease of hitpoints. I described a general method to detect a hit. It's irrelevant exactly what the server does when it detects one. Quote: Umm, you only mentioned Source games and Quake, neither of which is a SHUMP. I honestly am not sure what games you're referring to. My bad. I thought "shoot em' up" refers to games focused on shooting things up in general. I was talking about Quake and Source derivatives. You mentioned somewhere that your requirements are similar to those of a FPS, so it stuck. Quote: Trust me, it's not me, it's you. Threads where you and the OP end up in a shouting match are disturbingly common . I think it's because all too often, when people here ask how to do something, they're just looking for approval of their own predetermined ideas. If you're convinced that your original idea is the way to go, just say so and let's call it quits. You have more context to decide what's better for you anyway. Quote: Just because an FPS uses some technique doesn't mean that that technique is applicable to other game types, specifically my case where NPCs are common and hitscan weapons are non-existent. Agreed. If you don't have hitscan weapons, all my hitscan-specific talk is irrelevant. I'm sorry. I think other things may still apply, though. Quote: If they are not new, then why are they not mentioned in the Source engine literature (both on it's developer's wiki and in the academic papers?). All places I've read specifically don't do anything with non-hitscan weapons and don't mention NPCs whatsoever Because these things are irrelevant for most Source MP games. Anyway, the problem with your ideas is that they all involve trying to predict the future. You obviously can't predict the future of other players with any reasonable degree accuracy and consequently, you can't predict the future of things that have complex interactions with players, like NPCs. Not only is it logically impossible to solve the problems you want to solve that way, but you are likely to make them worse by: 1. Showing the player a discontinuous and inconsistent world due the synchonization errors |
SiegeLord
Member #7,827
October 2006
![]() |
Stas B. said: If you're convinced that your original idea is the way to go, just say so and let's call it quits. You have more context to decide what's better for you anyway. I think the original idea is bonkers, and my "new" idea is simply a restatement of what the modern FPS games do. I think my questions can't really be answered without actually putting them into code. The trick will be do so without marrying to one specific idea but retaining the flexibility to switch to other ideas easily (perhaps even leaving this option up to the player). Thanks everyone for motivating some fruitful thinking on my part. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
|