Sign in to follow this  
roadkillguy

Data Coordination Between Server & Client

Recommended Posts

roadkillguy    100
I'm working on a game in c++. I've got all the connection stuff set up, client, server, etc., and it runs rather nicely.

Now, I need to know how to best not only coordinate player positions, but when to send what packets as well. So far, I tween player positions when the x,y,z coordinate is close enough, and do a hard set when it's far away. The player data is sent every several milliseconds. Should I be sending key presses to animate the players better? (My game has gravity) What if somebody forges packets and is able to warp to the other side of the map? I need a way to prevent this.

My game also involves bullets, and guns. (It's kind of a FPS) I'd like to make my game fast [img]http://public.gamedev.net/public/style_emoticons/default/rolleyes.gif[/img], so I'd like to avoid sqrt(x*x + y*y + z*z) for every bullet, every update. Is there any other way to get around this? I currently keep track of inventory, so packet forging on bullets wont be an issue. (I'm kind of paranoid of this due to the fact that other games have failed miserably from client side programming and cheaters)

Some general pointers or websites would be great.

Thanks.

Share this post


Link to post
Share on other sites
Sappharos    140
I can help with one question.

When comparing two distances simply to see which is the larger, you don't need the square root. [font="Arial"]Use [/font][font="Arial"][code]if (x1*x1 + y1*y1 + z1*z1 > x2*x2 + y2*y2 + z2*z2)[/code] instead of [/font][font="Arial"][code]if (sqrt(x1*x1 + y1*y1 + z1*z1) > sqrt(x2*x2 + y2*y2 + z2*z2))[/code]

[/font]It may speed up some calculations - in theory. :)

As for forged packets, [b][url="http://www.raphkoster.com/gaming/laws.shtml"]never trust the client[/url][/b]. That is all.

Share this post


Link to post
Share on other sites
hplus0603    11348
Sappharos is right: Never trust the client.

A mechanism that a lot of games use is to send a "baseline" snapshot every 5-10 seconds, and just sending keypresses in between, from the server to all viewing clients.
Meanwhile, for the controlling client to server, only send key presses, and have the server do the simulation and send out the results.
The client can also do the simulation and display to the user, to reduce lag; however, it needs to detect when the server came to a different conclusion than itself, and "snap" the player to the appropriate point.

Typically, this can be done with the periodic baseline updates, if they have a global step number timestep, for example.

Share this post


Link to post
Share on other sites
Kazzahdrane    122
Are your clients connecting only to one another (Peer-2-Peer)?

I'm not sure how far along you are with the packet sending but a good system to include is a simple debug slider that lets you alter how frequently the "base" update packets are sent (your player positions, etc). This makes it easy to observe how correct your game looks as you add more network traffic - ideally you want to find the lowest frequency of sending data that still looks good. It's possible you may want to have immediate sending of packets with crucial data in them (firing a rocket, end of a game round, etc).

Share this post


Link to post
Share on other sites
roadkillguy    100
I apologize for the long delay.. I actually got distracted working on my game :D

@Kazzahdrane No, it's not peer2peer, I believe server-client works better in my situation. I currently send packets every 500ms, and it seems to work ok. I'm not sure if this is fast or slow compared to the industry standard.

@hplus0603 What exactly do you mean by baseline? I have my data wrapped up for keypresses, but I'm not exactly sure what to do. Do i send a packet every time a key is pressed, or do I simply update every 500ms or so?

@ApochPIQ Thank you, I'm rather new here.

@Sappharos I've always tried to follow Never Trust the Client. Sometimes I feel as though I'm a bit paranoid. For example, can the client ignore packets? I currently implement a strike system. If someone were to use cheatengine (It's scary stuff for developers) to hack their inventory, and the player tries to use that item, they are dealt a strike. After 5 strikes, the server gives end of stream and disconnects the player. Is that okay?

Also, that algorithm is exellent.. I cant believe I didn't think of that.

Share this post


Link to post
Share on other sites
Sappharos    140
[quote]What if somebody forges packets and is able to warp to the other side of the map?[/quote]

If you let them, it's safe to assume they will. Any data which could be manipulated to give the player an advantage in the game (position, health, ammo, money or other resources) is sensitive. My personal approach would be not to ban people for hacking the client (as you get more players this becomes less practical, and there's always a possibility of mistakes) but to simply make it impossible for it to confer an advantage to them. So yes, I'd just send a snapshot of the player position every few seconds for the server to check, if it's too far away then correct it. Don't allow the player's ammo to go up unless they've just picked up some, or they're in a shop and there is an appropriate deduction from their money. That sort of thing.

Share this post


Link to post
Share on other sites
smasherprog    568
I am writing my own game server now as well, and I was thinking of going the same route as you with the strike system. I would log when a player tried to do something impossible, and after so many times, ban the account. However, after thinking about it more, I think that is a bad idea; let me explain why. If the server is checking all requests from clients (as it should), then a client should not be able to cheat. So, I would be banning accounts for probing my server for vulnerabilities. Yes, I would be a bit upset that someone is doing this, but as long as no damage occurs, I should continue to let the client probe --as long as its not causing damage to my system --after all, the client should be paying me money to play. So, as long as I am getting paid, and no damage to the server occurs, let them probe all they want, right? If I ban them, I am out money. If I let them continue, I get money. Better to get paid than not ... right?

Share this post


Link to post
Share on other sites
ApochPiQ    23011
When clients do something they shouldn't, log it, and discard their input.

Then, patrol the logs periodically. You can even write tools to help with this. If you see a particular client doing suspicious stuff consistently, [i]then[/i] you can think about taking action. Until then, the best policy is to just ignore things that shouldn't be done. That way, people can't tell the difference between sending garbage to the server (which should do nothing) and sending legitimate but "illegal" input to the server (which, if they knew it was legit but illegal, could tell them how to further exploit your system).

Share this post


Link to post
Share on other sites
roadkillguy    100
[color="#1C2837"][size="2"][quote]When clients do something they shouldn't, log it, and discard their input.

Then, patrol the logs periodically. You can even write tools to help with this. If you see a particular client doing suspicious stuff consistently, [i]then[/i] you can think about taking action. Until then, the best policy is to just ignore things that shouldn't be done. That way, people can't tell the difference between sending garbage to the server (which should do nothing) and sending legitimate but "illegal" input to the server (which, if they knew it was legit but illegal, could tell them how to further exploit your system). [/size][/color][color="#1C2837"][size="2"][/quote][/size][/color]
[size="2"]
[/size][size="2"][color="#1c2837"]Sort of like Darwinian Evolution...[/color][/size]
[color="#1C2837"][size="2"]That's what I do essentially. Maybe after x number of strikes the server should start making warnings to the admin.[/size][/color]
[color="#1C2837"][size="2"]Should I consider basic packet encryption, such as XOR?[/size][/color]

Share this post


Link to post
Share on other sites
ApochPiQ    23011
If you're going to encrypt network traffic, do it right (public key systems, preferably on top of an existing SSL style implementation) or don't mess with it. XOR mangling (I wouldn't even call it encryption) only serves to annoy the people you're trying to protect against, and when they get annoyed by your security measures, they tend to redouble their efforts to break those measures.

Share this post


Link to post
Share on other sites
roadkillguy    100
[quote name='ApochPiQ' timestamp='1310489502' post='4834381']
If you're going to encrypt network traffic, do it right (public key systems, preferably on top of an existing SSL style implementation) or don't mess with it. XOR mangling (I wouldn't even call it encryption) only serves to annoy the people you're trying to protect against, and when they get annoyed by your security measures, they tend to redouble their efforts to break those measures.
[/quote]

Well, I probably wont. Given that I write the server correctly, I shouldn't need to encrypt anything, right?

Share this post


Link to post
Share on other sites
ApochPiQ    23011
I wouldn't consider it necessary [i]unless[/i] you are transmitting personal or identifying information about your users, including (but not limited to) emails, passwords, billing information, etc. If you transmit anything that your users don't want stolen from them, spring for encryption.

Share this post


Link to post
Share on other sites
hplus0603    11348
[quote name='roadkillguy' timestamp='1310438760' post='4834107']
@hplus0603 What exactly do you mean by baseline? I have my data wrapped up for keypresses, but I'm not exactly sure what to do. Do i send a packet every time a key is pressed, or do I simply update every 500ms or so?
[/quote]

Baselining is when you send occasional full state snapshots, and then send input commands in the meanwhile. From the client, you really don't need to send snapshots. From the server, you do, to correct for the unforeseen. Typically, all state snapshots and commands will be tagged with the game step number that they're intended for. Note that sending commands needs that everyone needs to simulate the world at the same rate of steps per second (but can render at different rates).


[quote]If someone were to use cheatengine (It's scary stuff for developers) to hack their inventory, and the player tries to use that item, they are dealt a strike. After 5 strikes, the server gives end of stream and disconnects the player. Is that okay?
[/quote]

One strike and you're out, in my book! And a mark is made on your account that you're a cheater. Perhaps even insta-banned. Just make sure you don't have bugs that cause bad-bans :-)

Or perhaps you mark the account for hell-ban. The next time it logs on, it will never find any open servers, or only fake open servers on IP addresses that never actually answer. Or only servers operated by other cheaters -- let them play together!

Share this post


Link to post
Share on other sites
roadkillguy    100
Alright then, I probably wont.

What would be the best way to handle bullets? I know I need x, y, z, and velocity, but what should I do after that? How should the server handle when somebody is hit? Should the server report to the client that the client was hit, or should the client report to the server that he hit somebody? I've actually seen the second in games --as iffy as it could be.

[quote][color=#1C2837][size=2]Baselining is when you send occasional full state snapshots, and then send input commands in the meanwhile. From the client, you really don't need to send snapshots. From the server, you do, to correct for the unforeseen. Typically, all state snapshots and commands will be tagged with the game step number that they're intended for. Note that sending commands needs that everyone needs to simulate the world at the same rate of steps per second (but can render at different rates).[/size][/color][/quote]

So essentially the client needs to be counting steps? I'm not doing that. What happens when an incoming step doesn't match the current step?

Share this post


Link to post
Share on other sites
roadkillguy    100
I implemented the base + input as suggested, but it's rather choppy (for both clients) every 2 seconds when the data is sent. Should I be tweening rather than hard-setting? Maybe I should only set it when the expected value and the actual value are far apart.

Share this post


Link to post
Share on other sites
hplus0603    11348
[quote name='roadkillguy' timestamp='1310594828' post='4835025']
I implemented the base + input as suggested, but it's rather choppy (for both clients) every 2 seconds when the data is sent. Should I be tweening rather than hard-setting? Maybe I should only set it when the expected value and the actual value are far apart.
[/quote]

Yes, tweening for baseline updates is good. Also, some systems run the displayed clients behind in time, such that you will always have the right data for the simulation of each player. You see exactly what they did, but at some point later in time. If that is implemented properly, there should be no snapping, as each baseline should just send you information you already calculated yourself.

As for "who hit whom," that's an entire sub-genre on its own. There are various trade-offs between complexity, response time, what the user sees vs what happens, and openness to cheating. There are links in the FAQ that talk about how various games deal with this (Source and Quake III among the more prominent).

Share this post


Link to post
Share on other sites
roadkillguy    100
I read through Quake III and Source (I've played both) and it seems pretty straightforward.

One thing I realized is that TCP was a bad idea from the start (it's slow for this). There's only one problem I have with UDP, however. If two clients are connected to a router, how does the server choose to send data to either one of them given that they're not on the same IP as the server? I followed the Quake III doc and have implemented a random ID generated by each client so that the server can tell their data apart, but I'm not sure how to go the other way. The only thing I can think of is for the client(s) to manually port forward everything on a specific port to their machine, but that's a hassle [img]http://public.gamedev.net/public/style_emoticons/default/dry.gif[/img] and the games I've played don't seem to do that.

Basically, I don't know what happens once the packet gets to a router. If it gets sent to both clients I should be fine thanks to the random ID.
[s]
[/s]
EDIT: Ironically, halfway through attempting to implement UDP, I realized my game must sync large amounts of terrain data, and thus, must have a reliable connection to do so... [img]http://public.gamedev.net/public/style_emoticons/default/unsure.gif[/img] Do I need to remain with TCP? Or should I implement my own method for packet-confirmation? Bullets are something that cannot be spammed (packet wise), and yet other FPS games continue to use UDP. I've branched my source at this point, so I can go either way.

Share this post


Link to post
Share on other sites
hplus0603    11348
[quote name='roadkillguy' timestamp='1310680359' post='4835448']
EDIT: Ironically, halfway through attempting to implement UDP, I realized my game must sync large amounts of terrain data, and thus, must have a reliable connection to do so... [img]http://public.gamedev.net/public/style_emoticons/default/unsure.gif[/img] Do I need to remain with TCP? Or should I implement my own method for packet-confirmation? Bullets are something that cannot be spammed (packet wise), and yet other FPS games continue to use UDP. I've branched my source at this point, so I can go either way.
[/quote]

An UDP destination is an IP address and a port number, just like for TCP (but UDP port X is independent of TCP port X). Thus, the router can tell the two apart.

You can do your own reliability if you want, or you can use both a TCP connection and a UDP packet stream. The Enet library does reliability over UDP if you want to use that.

Share this post


Link to post
Share on other sites
roadkillguy    100
[quote name='hplus0603' timestamp='1310690765' post='4835505']
You can do your own reliability if you want, or you can use both a TCP connection and a UDP packet stream. The Enet library does reliability over UDP if you want to use that.
[/quote]

Is Enet easily compiled with mingw? I currently cross compile to windows from linux. I'm using SDL_Net.

Do I need variable reception ports on the client? My qualm is that a packet might be on port 2000 and be going to IP 203.53.100.10, but will never make it to 192.168.1.108 like it was supposed to. Each client on the same IP could then have a different reception port and the same sending port, but would have to be port forwarded manually. Maybe I'm not understanding something.

Share this post


Link to post
Share on other sites
rip-off    10976
[quote]
Maybe I'm not understanding something.
[/quote]
I think so.

[quote]
Do I need variable reception ports on the client?
[/quote]
You don't [b]need[/b] them, but it is better to use them. The server should certainly not expect the client to use a particular port. That assumption would break with most NAT setups.

[quote]
My qualm is that a packet might be on port 2000 and be going to IP 203.53.100.10, but will never make it to 192.168.1.108 like it was supposed to.
[/quote]
Packets aren't on ports. They have two ports, their source and destination. I assume you're saying "The packet is sent to port $DESTINATION_PORT and I want it to get to $SERVER_IP_ADDRESS but it doesn't even make it to $LOCAL_ROUTER_IP_ADDRESS". Yes, with UDP you have to deal with packet loss. So your client must keep sending until either enough time has passed to convince you there is no point continuing, or until it is successful. That isn't the only problem with UDP, you need to be able to handle duplicate and out-of-order packets too.

[quote]
Each client on the same IP could then have a different reception port and the same sending port, but would have to be port forwarded manually.
[/quote]
Forget port forwarding. Port forwarding is mostly used for taking a [b]listening service[/b] on a machine with a [b]given private IP address[/b] and (typically) [b]well known port[/b], and making it available by instructing the router/firewall/NAT/whatever to make [b]incoming messages[/b] on the [b]public IP address[/b] and [b]well known port[/b] get to the private machine.

For a client, it simply shouldn't be required at all.

Share this post


Link to post
Share on other sites
roadkillguy    100
Hmm I didn't know there were different destination and host ports. Either way, how does a packet tell the router which local ip address to send it to? Does it send it to every local ip?

In SDL_Net, there is a UDPpacket struct. It has two destination fields --Address, and port. You then call SDL_Net_UDP_Send(UDPsocket socket, UDPpacket packet) to send the data (which is also in that struct). Unfortunately, a UDPsocket is basically a port binding, and I'm not sure where else a local IP address would come into play.

Share this post


Link to post
Share on other sites
hplus0603    11348
[quote name='roadkillguy' timestamp='1310701846' post='4835554']
Is Enet easily compiled with mingw? I currently cross compile to windows from linux. I'm using SDL_Net.
[/quote]

I believe so, as it started out on Linux. However, if your target is Windows, you should download and install Visual C++ Express 2010. It's a vastly better development environment for Win32 applications.

[quote]

Do I need variable reception ports on the client? My qualm is that a packet might be on port 2000 and be going to IP 203.53.100.10, but will never make it to 192.168.1.108 like it was supposed to. Each client on the same IP could then have a different reception port and the same sending port, but would have to be port forwarded manually. Maybe I'm not understanding something.
[/quote]

You apparently need to learn a bit more about how NAT works. Once you understand that, you need to understand what port forwarding does, and what NAT punch-through is, and when it's needed. There are links in the FAQ that might help you. In brief, your router will translate the "from" part of outgoing packets from 192.165.whatever:whatever to some-ip:some-port. It will then re-translate incoming packets to some-ip:some-port back to 192.168.whatever:whatever and send them back in. The key is that the first packet has to be outgoing, so that the translation table can be established. Also, the server needs to use recvfrom() to receive the address that it should return packets to, rather than try to put addressing data as part of the payload of the application-layer protocol (like FTP and the H. VoIP protocols do).

Share this post


Link to post
Share on other sites
roadkillguy    100
Subconsciously I was being told that there was data being lost.. I guess I'll just have to trust the routers then? I'll definitely read more into that.

I've now designed a pretty cool packet checking system using a list of packets and a pthread. I resend packets every 2 seconds if no response is seen from them. Is that a good number? I think I'll remain with UDP.

Also, I'm really liking makefiles and command line g++. I run Ubuntu on a netbook, so VC++ would be rather difficult to install and use (I have used it before). I'm not really one for windows [img]http://public.gamedev.net/public/style_emoticons/default/wink.gif[/img].

I think I have a pretty good Idea of what to do now. Thanks to everyone who answered my questions.

Share this post


Link to post
Share on other sites
rip-off    10976
2 seconds might as well be 2 years for most fast paced action games (e.g. the kind it makes sense to use UDP for at all). You'll want to be resending data within a handful of network "ticks", the exact value is something you're going to have to tune to your game.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this