Soul Spectre got it right. That's the way to go, mostly!
As for the UT2k4 keypresses thing... welllll, I suppose they're sending them for things where you need to hold a key down for a continuous effect. Essentially such a "keypress" is nothing but a vector, though! When you press the forward key, you send to the server "moving forward", when you release it, you send "not moving anymore" ... those, of course, are just wishes, the server will apply speed and physics to you and send you the game state, the "truth", so to speak. You certainly won't move forward if you tell the server to and there's a wall right in front of you!
How to Sync a multiplayer actiongame?
"collate" means, loosely, mash together. Thus, if each player sends his input to the server, and the server sends one packet back to each player, contaning the input for ALL the players in the single packet, then the server collates the input. This is the way to go.
In addition to that input, you could add the full state (position/direction/velocity and possible AI state) for one or two players/units to each packet that you send out, after all the inputs.
When you receive the packet, you apply the keypresses (commands, really) to each local copy of the players/entities, and for the entity that you got a full update for, you apply the full update.
That way you know that each entity will be in sync within some number of packets sent.
If you have only 8 players, but send 20 packets per second, you probably don't want to send one player full data in each packet; you only want to tack on the full data for some player once every three packets or so.
Assuming position is 9 bytes, velocity is 6 bytes, direction is 2 bytes, and played/entity Id is 1 byte, this means 18 bytes for a single entity update. (Bullets are entities, too, right?) Assuming you only have 8 commands, that's one byte of command data per player per packet.
Thus, with this scheme, each packet would be 28 bytes UDP overhead, plus 8 bytes for 8 player commands, plus 18 bytes for a single entity update, for a total of 54 byte packets -- that's tiny! You probably want to add some management overhead (time stamp, or whatnot) so say 60 bytes per packet. Sending 20 of those to the player per second means only 1200 bytes per second; that's very easy to get over even a crappy modem connection.
In addition to that input, you could add the full state (position/direction/velocity and possible AI state) for one or two players/units to each packet that you send out, after all the inputs.
When you receive the packet, you apply the keypresses (commands, really) to each local copy of the players/entities, and for the entity that you got a full update for, you apply the full update.
That way you know that each entity will be in sync within some number of packets sent.
If you have only 8 players, but send 20 packets per second, you probably don't want to send one player full data in each packet; you only want to tack on the full data for some player once every three packets or so.
Assuming position is 9 bytes, velocity is 6 bytes, direction is 2 bytes, and played/entity Id is 1 byte, this means 18 bytes for a single entity update. (Bullets are entities, too, right?) Assuming you only have 8 commands, that's one byte of command data per player per packet.
Thus, with this scheme, each packet would be 28 bytes UDP overhead, plus 8 bytes for 8 player commands, plus 18 bytes for a single entity update, for a total of 54 byte packets -- that's tiny! You probably want to add some management overhead (time stamp, or whatnot) so say 60 bytes per packet. Sending 20 of those to the player per second means only 1200 bytes per second; that's very easy to get over even a crappy modem connection.
enum Bool { True, False, FileNotFound };
Great! I got a lot of questions answered. The thing about Server-Client vs Client-Client. To have a Client Client system seems soo much better (except for security), but what I don't get is how anyone could(or want to) cheat this if they don't have my code ;)
In the system I have now I send all data to all others. This means that new clients can connect to anyone in game. And if one player lefts the others keep playing. Each client handle all collisions with all other objects ingame, including other players. The latency is also better in Peer to Peer, right?
So what I'll do is that I'll add stateupdates. What is best:
1. To send these updates with each keypresspacket, what I mean is, Send keypress+X then send Keypress+Y then Keypress+Dir..
2 Or should I wait between them so I send 2 Keypresspackets, then in the third I send Keypresses+X,Y,Dir,..
In the system I have now I send all data to all others. This means that new clients can connect to anyone in game. And if one player lefts the others keep playing. Each client handle all collisions with all other objects ingame, including other players. The latency is also better in Peer to Peer, right?
So what I'll do is that I'll add stateupdates. What is best:
1. To send these updates with each keypresspacket, what I mean is, Send keypress+X then send Keypress+Y then Keypress+Dir..
2 Or should I wait between them so I send 2 Keypresspackets, then in the third I send Keypresses+X,Y,Dir,..
If you have client-client, then each client needs to send packets to all other clients, which scales really poorly with number of players.
"Server" does not necessarily mean "securely hosted server" :-)
You can still be server-client (architecturally), and just let one of the players host the server, either within the game, or as a separate process. That's what pretty much all the FPS games do these days.
"Server" does not necessarily mean "securely hosted server" :-)
You can still be server-client (architecturally), and just let one of the players host the server, either within the game, or as a separate process. That's what pretty much all the FPS games do these days.
enum Bool { True, False, FileNotFound };
Could you explain in what way you get more data send/recieved if you use Client-Client instead of Client-Server. And how big is the difference over time?
If you have 8 players, then each client needs to send 7 update packets each frame, and you will receive 7 update packets each frame, for a total of 14 packets.
If you have 8 players, all talking to a server, they will each send one packet, and receive one packet, per frame.
Assuming packet overhead is O, and update size is S, then peer-to-peer costs you, per frame, for N players other than the client: N * ((O+S) + (O+S)) or 2*N*(O+S) bytes.
If you use a server/reflector, then each frame costs you: (O+S)+(O+N*S) bytes, or 2*O+(N+1)*S, which is significantly smaller.
In a typical UDP based FPS style game, O == 28 and S =~ 16 and N varies from 1 to 31. A modem can usually reliably sustain 3000 bytes per second. A good FPS runs at 20 network frames per second. You plug in the numbers and do the math :-)
If you have 8 players, all talking to a server, they will each send one packet, and receive one packet, per frame.
Assuming packet overhead is O, and update size is S, then peer-to-peer costs you, per frame, for N players other than the client: N * ((O+S) + (O+S)) or 2*N*(O+S) bytes.
If you use a server/reflector, then each frame costs you: (O+S)+(O+N*S) bytes, or 2*O+(N+1)*S, which is significantly smaller.
In a typical UDP based FPS style game, O == 28 and S =~ 16 and N varies from 1 to 31. A modem can usually reliably sustain 3000 bytes per second. A good FPS runs at 20 network frames per second. You plug in the numbers and do the math :-)
enum Bool { True, False, FileNotFound };
Hello Permafried.
I have a quick question about symbol communication between client/server. This is sort of along the lines of sending information and frame rates etc. I have a working client/server system in place and now am wondering the best route to communicate game events via client and server. Is this done via symbol communication? I.E ** means you used your gun, !@ means you are walking forward, etc. Is there a set standard of symbol communication, or a standard form of communication, for multiplay action games? If not, can you briefly explain how you handle this in your game? Any input on this would be greatly appreciated. I don't want to code something that is wrong, leaves me open to hackers, and so on. Am just trying to research this prior to starting it.
thanks.
//Frekster
I have a quick question about symbol communication between client/server. This is sort of along the lines of sending information and frame rates etc. I have a working client/server system in place and now am wondering the best route to communicate game events via client and server. Is this done via symbol communication? I.E ** means you used your gun, !@ means you are walking forward, etc. Is there a set standard of symbol communication, or a standard form of communication, for multiplay action games? If not, can you briefly explain how you handle this in your game? Any input on this would be greatly appreciated. I don't want to code something that is wrong, leaves me open to hackers, and so on. Am just trying to research this prior to starting it.
thanks.
//Frekster
Quote:
Original post by Permafried-
Hey,
The reason behind me sending out key presses at such a huge interval is because I'm sending them out as unreliable, basically I toss it out and if it gets there it gets there, if it doesn't it doesn't that way if say 3/85 get lost I'm really not that concered. As far as sending key presses goes I do the following:
static const char BUTTON_FWRD = 0x00000001;
static const char BUTTON_BACK = 0x00000010;
static const char BUTTON_RGHT = 0x00000100;
etc.
As I'm sure you can see with the pattern you manage to pack 8 key presses into a single byte using:
*** Source Snippet Removed ***
In this way I can extract them on the server side using a bitwise &= and comparing vs the buttons defined above. I also send along with that the client's current view angles (for spawning weapon fire via the cross-product).
Really the advantages here are not only is my packet size incredibly small, but if I lose one here and there it's really not gonna break the game....if mass packet loss is a problem with the connection than no matter how you send the data there's going to be problems. As well, I feel having the client keep track of where they are kinda defeats the purpose of the server in general since it makes your program much easier to hack, especially if the server really has no way of validating that this information is invalid.Quote:
What if p2 did not move like predicted? what am I supposed to do with the next update that proves to be wrong.
The one major thing that I left out of the previous post was gamestate updates, especially since it was getting way too long as it was. Basically I send out a gamestate update every 200ms or so which says "I don't care where you think the stuff is this is where you're going to put it at time X." Just imagine if you predict wrong 2 frames out of 85 though how much can you really be off unless you're moving your player a disgustingly large amount every frame....this is something you should sit down and figure out mathematically how often you should force a position change and how far off you can afford to be based on mondel sizes, etc.
As far as your final question goes, this kind of math is really not my strong suit and I'm not even going to attempt to pretend I know....hopefully someone else can help you with this because I'd hate to mislead you on it ^_^.
Permafried-
There is not a standard for multiplayer action games; each engine uses its own protocol.
Typically, the protocol will be based on binary data, packed structs, and specific byte values, rather than text-based.
Typically, the protocol will be based on binary data, packed structs, and specific byte values, rather than text-based.
enum Bool { True, False, FileNotFound };
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement