How should "player A shot box/ground/player B/enemyY" handled in multiplayer game?

Started by
16 comments, last by Kal_Torak 15 years, 5 months ago
Hi, I'm working on my multiplayer code, and have currently approached the network issues by having a bit similar idea that Quake 3 uses (http://trac.bookofhook.com/bookofhook/trac.cgi/wiki/Quake3Networking). I use UDP: client are sending inputs to server, server is updating the world and sending packets containing state info to clients - and so far things work pretty nicely. I can adjust health, positions, player classes, carried objects etc. but there's still bit mystery when it comes to shooting stuff. Currently I have class called 'netobject' which state's are put in a packet that's sent to client. Netobject can be things like 'building', 'box', 'player' etc. Anything there is in the world. For health/movement/stuff-mentioned-above I use 'object state'. When object is at position A, and has health N - then it's easy for clients to set up the values after getting state updates from the server. (1) I wonder how shooting objects should be done? Should it be tied somehow into 'user input'? or 'object state'? Or perhaps some sort of 'event message'? Or what? I was considering doing some sort of 'event' messages, that would be put inside packets. In these events one could say that "player A is shooting from location X/Y/Z and hits object 'ground' in location X/Y/Z at time [millisecs]" Then clients could ACK these events, and server would keep sending them until they are ACKed (or perhaps after certain period of time they could be deleted: no point sending info that 'player A shot something 3 seconds ago'.) (2) I haven't decided whether to give client authority over shooting (I'm making a cooperative game, so cheating wouldn't perhaps be that big issue, and it could mean better performance for clients even with slower network), but that's not a big deal. Either I (a) send client input to server, which will tell from which position the client really shot stuff, or (b) I will tell server (when sending input packet) from which location the shot was done, and whether it hit something. Just want to mention this here. (3) What about throwing objects? Or picking up? Would it make sense to do 'throwing event' or 'picking up event' kind of messages as well? Currently I do 'picking up' so that I change the netobject state ('netobject A is attached to netobject B') and when client receives the 'netobject A's state, he can immediately attach the netobject to B if it isn't already attached). Picking up could be handled with events, but not sure if 'events' is reasonable thing to do in a first place. Help me out people. How would you suggest handling shooting (and for example throwing) things? I'm especially concerned on my question #1. (Oh, and my game is not super-fast paced FPS, but rather a top-downish view pretty-fastish done shooting game where you also barricade and pile up stuff - and kill zombies :))
---Polycount Productions - An Indie Online Multiplayer Games CompanyGameProducer.net - Daily Ideas, Hints and Inspiration for Indie Game DevelopersIndie Game Sales Statistics - downloads, sales and other figures
Advertisement
I would just use it as a Object State, just update it every time the player shoots, something or someone

I would set the shooting like this

Client: Can I shoot this?
-Sends Packet-
Server: Sorry that's a Wall
-Sends Packet-
Client: Oh ok how about this?
-Sends Packet-
Server: Sure can here is the [XYZ]
-Sends Packet-

Basicly the Server just keeps the Shootable values on the server an the client just asks whether or not it can be shot or thrown at.

Don't get mad at me if this is not what you were looking for or if I completely just screwed up lol, I know the theory behind the thing not how to program it directly =p

~ARC
Hmm, I'm afraid this approach would kill the bandwidth. Consider player who is shooting with a machine gun... there would be just too many packets to send (...and anyways, I'm sending max 20 packets per sec)

Thanks for the help though.
---Polycount Productions - An Indie Online Multiplayer Games CompanyGameProducer.net - Daily Ideas, Hints and Inspiration for Indie Game DevelopersIndie Game Sales Statistics - downloads, sales and other figures
the way quake3 works on that subject is prediction and server corrections. Clients stack their inputs and send them to the server, who reconstruct the client movement / aim. Then the server can detect if a client accurately shot something or not. if the client movement is invalid (i.e. client bumped into another player), the server sends a correction packet, and the client rewinds his stack and playback the inputs from there.

to combat packet loss, clients send duplicates of inputs. Look at gaffer's article on networked physics.

[Edited by - oliii on October 23, 2008 6:14:11 PM]

Everything is better with Metal.

Quote:Original post by oliii
the way quake3 works on that subject is prediction and server corrections. Clients stack their inputs and send them to the server, who reconstruct the client movement / aim. Then the server can detect if a client accurately shot something or not. if the client movement is invalid (i.e. client bumped into another player), the server sends a correction packet, and the client rewinds his stack and playback the inputs from there.

to combat packet loss, clients send duplicates of inputs. Look at gaffer's article on networked physics.

Thanks oliii.

So everything is input based? State + inputs => new state + inputs => and so on...

I think in Gaffer's article it was mentioned that you will ignore old input / dropped packets. Basically, would this would that if guy who shoots 5 times (like frames 1-5), and 1 packet is dropped, first packet arrives too late, then server will update only the 3 shots?

Still not sure how those '3 shots' should be told to other clients? If server send a world state snapshot, then it means server is not sending state for every frame - but rather for example once per 5 frames (or similar). If client shoots 5 times in 5 frames (and 3 shots are successfully got by the server), then server's snapshot will contain only the latest state ("5th frame", not "frames 1-5") which server broadcasts to clients. <= End result would be that client who shot 5 times could see 5 shots (since it can predict the result), server would simulate 3 shots, but the rest of the players would see only 1 shot since the server's latest state.

Or... would it mean that server also ties 'user input' commands into these state messages, so that the other clients can run the 3 (successfully got) shooting inputs?
---Polycount Productions - An Indie Online Multiplayer Games CompanyGameProducer.net - Daily Ideas, Hints and Inspiration for Indie Game DevelopersIndie Game Sales Statistics - downloads, sales and other figures
Quote:Original post by PolycountProductions
Still not sure how those '3 shots' should be told to other clients? If server send a world state snapshot, then it means server is not sending state for every frame - but rather for example once per 5 frames (or similar). If client shoots 5 times in 5 frames (and 3 shots are successfully got by the server), then server's snapshot will contain only the latest state ("5th frame", not "frames 1-5") which server broadcasts to clients. <= End result would be that client who shot 5 times could see 5 shots (since it can predict the result), server would simulate 3 shots, but the rest of the players would see only 1 shot since the server's latest state.

The state is not whether someone has fired during that frame. That's an instantaneous event, which changes the state. The state itself would include all projectiles in the environment, in this case 3 of them. If the projectiles don't typically live long enough to appear in a state snapshot, either you need to update more often or you just treat them as instantaneous events that need propagating independently.

Quote:Original post by Kylotan
The state is not whether someone has fired during that frame. That's an instantaneous event, which changes the state. The state itself would include all projectiles in the environment, in this case 3 of them. If the projectiles don't typically live long enough to appear in a state snapshot, either you need to update more often or you just treat them as instantaneous events that need propagating independently.


Thanks for the help. I'm not quite sure how those events should be treated on the client side though...

Let's suppose one bullet lives for 1 frame (instant hit), and let's suppose that during 50 millisecs period there's 3 bullets. State update that occurs at 50 millisecs, so basically server does the shooting of those 3 bullets.

Next, in these 'world state snapshots', server would include '3 bullets' ("shots by player A from position P to position T at time N" etc.)

How would client then treat this info? He gets the snapshot, updates the world, and then realizes that "3 bullets were shot within the last 50+lag milliseconds". Would it mean that client would just simply launch all bullets simultaneously from correct positions, meanwhile the player character is running 1 meter (the distance he can move in 50+ milliseconds) away?

(I'm reading source networking over and over but I'm missing something :) - the movement alone sounds understandable, but the moment shooting begins, I start to wonder how it should be done to get those events play correctly.)
---Polycount Productions - An Indie Online Multiplayer Games CompanyGameProducer.net - Daily Ideas, Hints and Inspiration for Indie Game DevelopersIndie Game Sales Statistics - downloads, sales and other figures
Quote:Original post by PolycountProductions

(I'm reading source networking over and over but I'm missing something :) - the movement alone sounds understandable, but the moment shooting begins, I start to wonder how it should be done to get those events play correctly.)


You can't play them correctly since everything has already happened. You try to show something reasonable.

To validate correctness, instead of inplace simulation advancement, server keeps track of past states. So whenever simulation is advanced by one tick, you store old state and keep it around for a while. After all clients have been shown to have advanced past a certain state, you can discard it.

When player's action arrives, you find when that action was triggered, then find matching old state at that time. Then, calculate everything based on that state. If needed, restart entire simulation from that state to update for changes (may lead to warping or other inconsistencies).

Meanwhile, client may choose to simulate actions regardless of whether they are valid or not (showing blood, bullets, etc.), but not getting the results. So shooting something will show damage on screen, but it will take a while until this damage is applied (or it may be simulated, and later compensated/confirmed after server gives its ok).

This model isn't entirely accurate and may not even be entirely fair under certain circumstances, but it's simple and relatively light-weight.

When it comes to displaying other players' actions, one way is to speed up their time to catch up with local view. So if you receive actions from a player that is 200ms behind, you could replay all those actions over 20ms. This isn't accurate, but tends to keep things reasonable.

Sometimes, actions that can be performed are designed with this in mind (time between shots, projectile behavior, etc.).

[Edited by - Antheus on October 24, 2008 8:39:34 AM]
The client is just a console, that only send a stream of inputs to the server, who has full authority on everything.

What the client can do is predict events.

1) He thinks he fired 10 bullets, so let the bullet fly on the client, except they will not produce damage, they are just for show. Similarly, he thinks he moved to the right, then let him move to the right instantly.

2) When the server received the command 'move right', he will move the player right if he can. If the player cannot move right (blocked), then a correction packet is sent to re-sync the client.

the case 1) can be demonstrated in Counterstrike. You have a special command that stops client prediction on gun firing. That's what really happens on the server side when you fire your gun. If you allow prediction, your gun will fire normally, *but* what you shoot may not be the same on the server. Hence the glitches such as firing through walls, shooting someone but it's not registering (at least straight away), ect...

The case 2) can also be demonstrated in CS. If you bump into another player, you will see yourself wobble about, this is the server correction kicking in. This is because you cannot predict accurately the position of OTHER players on clients and server.

all this is done via stacking inputs and client-side predictions on the client, sending those inputs and predictions to the server to be verified.

The server re-runs those inputs locally, and compare the predictions with what he calculated.

If there is a mismatch, he sends a correction packet.

Client receives the correction, apply the correction to the offending state, and re-calculate his states stored in his stack from that point forward.

Everything is better with Metal.

Yeh, I'm aware that client is pretty dumb and 'thinks' what occured.

Number #1 is clear, no problem with that...

...but what about if there's server + two players. How can player A know when player B was shooting (think the '3 shots' example above)?

Thanks again!
---Polycount Productions - An Indie Online Multiplayer Games CompanyGameProducer.net - Daily Ideas, Hints and Inspiration for Indie Game DevelopersIndie Game Sales Statistics - downloads, sales and other figures

This topic is closed to new replies.

Advertisement