0
\$\begingroup\$

I'm using a structure, where client sends his inputs every 20ms in one packet and server parses his inputs every update(20ms aswell). I've got a problem, since player can send me more than one inputs packet per tick(if he uses cheats), so he can move faster than others. The thing is that I don't know how to check if his messages aren't too frequent. Before, I've been doing like this: Clients copy his inputs in buffer every 20ms and sends the buffer to server every 100ms. Server parse 1/5 of this buffer every 20ms and sends client's state to client. The problem was the thing that there was a big delay, and client's state on his screen was unstable since he sends message on 100ms and waits for server to parse it(100ms more) and it stacks so delay will be bigger with every client's message. I've been using this since server parses only one input message per 100ms, so even if client tries to cheat his speed will be the same. My question is, how do other game developers do, how they can be sure that the server won't parse too much client messages and delay will be little? I'm sure I miss something, since I don't see other questions like this one, it should be easy to fix, so please tell me if I'm wrong.

\$\endgroup\$
  • \$\begingroup\$ In other words, first my idea is to parse all player's inputs in one tick, so I have no delay, but it's possible to cheat. Second idea is to parse only a part of inputs every tick, so it's not possible to cheat but there is a big delay, since player's inputs can stack in inputs' buffer. \$\endgroup\$ – Basea Basilia Mar 16 at 16:44
3
\$\begingroup\$

It sounds like your problem arises from processing players' input eagerly, the moment it comes in. In this situation, it's harder to keep track of the context of the input and its timing/frequency with respect to other players and your own primary/authoritative update time step.

Instead, try thinking of your game as though it were turn-based, just with very fast, auto-advancing turns.

Every time your server receives input from a player, assign it a timestamp that represents the moment in game time when it should be applied (this could be the time or receipt, or a backdated time to try to compensate for latency) and stuff it in a priority queue to process all at once.

Every fixed timestep on your server, advance the game by one turn, using the inputs gathered for that turn. That means you run one update pass, updating the authoritative game state to a new stamped time. In this pass, process all the inputs in the queue that occur in this slice of game time.

Because you're running all your server logic for the turn in one pass, you can make sure you never double-process any one player's input for a single turn, or let them combine/spam actions that shouldn't be allowed.

(eg. maybe "I pressed right" and "I pressed jump" both stack, and can both execute in one update turn, but "I pressed right" and "I pressed right" just collapse down to a single rightward input for this turn. Or maybe you re-stamp the second input and stuff it back in the queue to enforce it happening in a later turn instead)

You can also use this pass to look at how many inputs you've gotten from each player in this update window, to keep track of deviations, and flag cases that look like cheating rather than ordinary timing fluctuations.

\$\endgroup\$
  • \$\begingroup\$ Thank you for such a detailed answer, I'll try your approach. \$\endgroup\$ – Basea Basilia Mar 16 at 18:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.