2
\$\begingroup\$

I'm making a multiplayer game with basic linear movement and interpolation. I've read gabriel's article about client-side prediction and server reconciliation and have tried applying it to my own. My server is supposed to be authoritative, but I am worried clients can still exploit the system.

The system works like this:

  1. the client sends timestamped input to the server at 60hz
  2. the server runs at 30hz. Each tick it applies all the input since last tick and uses a time delta calculated from the client side input packets to determine movement (e.g. entity.x += message.delta * speed). The server then sends a timestamped state back to all clients.
  3. the client receives a timed state from the server and applies the "authoritative" positions.

My concern is with step #2. Because player movement relies on the client's delta time, I'm afraid they can cheat by sending a "fake delta time" to the server and additionaly spam input messages quicker to make them move faster in-game. If I remove the delta time altogether, the game will appear "jumpy". How can I resolve this issue?

\$\endgroup\$
8
  • \$\begingroup\$ When a client moves too fast, the server rolls back the client's position. There is only the way. \$\endgroup\$
    – whoo24
    Nov 13, 2017 at 2:31
  • \$\begingroup\$ How do I know if someone's moving too fast? Should my server calculate its own delta time and compare it with what the client sent to see if it's within a reasonable range? What about people who send more than 60 messages per second? Should I only accept the only the first 60 messages between ticks? What if I wanted to adjust the frame rate on the client? \$\endgroup\$
    – tim
    Nov 13, 2017 at 4:18
  • \$\begingroup\$ Why does your server care about your client's framerate? Your timestep for network simulation purposes should be fixed so it's fair and consistent for all clients. If a client needs to locally interpolate using frame time to get a smooth appearance, this should affect the client's visuals only, and not impact the game state in any way at all. \$\endgroup\$
    – DMGregory
    Nov 13, 2017 at 4:24
  • \$\begingroup\$ @Henrik Server can know when a client starts moving. And server already has speed and position of a client. Then you can know how long the client move. \$\endgroup\$
    – whoo24
    Nov 13, 2017 at 5:02
  • \$\begingroup\$ @DMGregory Thanks, I think I understand it better. All final calculations should rely on the server's own delta time and the client's delta only for their own interpolation. I suppose this works if I'm dealing with constant velocity and deterministic movement. \$\endgroup\$
    – tim
    Nov 13, 2017 at 5:43

2 Answers 2

2
\$\begingroup\$

If you are relying on client information to calculate position, YES this can be cheated. =(

Since you didn't sent information about what kind of game is this and you didn't mention fixed timestep, I'm assuming you are doing some kind of FPS that doesn't require that every client, runs the same frame, at the same time.

I think a good solution is to use PING to sincronize position between server and client. I'll explain:

  • Server needs to run without waiting for clients, he is authoritative.
  • If needed, server can implement a controlled delay of 1, 2 or 3 frames (at 60fps, 1 frame = 16ms).
  • Client should PING server to check latency between him and server.
  • Client calculate his current position + N frames ahead using last control input. So he will predict his position and update locally.
  • Client also needs to calculate other players position using same method (according to his own ping, no to them).

If latency is low (<100ms) and your players are not moving too fast, this method works great. With latency > 250ms or player is really fast, your prediction starts to jump from place to place.

Another solution would be to calculate at server the maximum distance this client can move from frame to frame, if it's higher than this, apply some anti-cheat measure.

Anyway, need more information!

\$\endgroup\$
3
  • \$\begingroup\$ First, let me say you're all correct. I shouldn't be relying on the client's delta-time. I acted like an idiot and for some odd reason I kept thinking the "timestamp" my article referred to was supposed to be the delta-time, but really it's just an index used for server reconciliation. I'm only supposed to send it to the server and then send it back to the clients so they know to ignore old states. \$\endgroup\$
    – tim
    Nov 13, 2017 at 16:27
  • \$\begingroup\$ My game movement is like a top-down rpg, where players move kinda slow and have no acceleration. Using extrapolation in my case wouldn't be too useful since players can change directions instantly. However, I realize that if there is a discrepancy between the client's and server's position, I can interpolate between the two instead of assuming the server's position instantly. This resolves the "jumpy" movement. I believe my problems are solved, but you all did push me to the right direction \$\endgroup\$
    – tim
    Nov 13, 2017 at 16:30
  • \$\begingroup\$ If my answer is correct, please mark it as Accepted =) \$\endgroup\$
    – Danielzt
    Mar 7, 2018 at 15:11
0
\$\begingroup\$

If you treat each move message as a move unit, you don't need delta in this message at all. Whenever server receives a move message, apply it with a hardcoded delta (say 15ms in your case).

However this is still vulnerable to message "spam" hack. Such that a client can send double or triple the amount of move messages. If the server unconditionally handles them all, the player will get 2x/3x speed.

Server side check like maximum location delta involves RTT measurement. Eg, max_input_message = (RTT/2 + 1000.0) / SERVER_FRAME When RTT is high this check is very loose, and a cheater can try to manipulate the RTT ping to yield higher RTT.

Maybe you can try to model your message as full state snapshot, while you are still able to adapt the prediction/reconciliation/interpolation demonstrated in Gabriel's tutorial.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .