I know there are many posts on this topic, but none of them answered the problems I have, or I don't have enough knowledge to comprehend them. I have client/server architecture, with server being authoritative. I implemented fixed timestep "physics" (for now its just moving) on both, client and server. I read about clien side prediction and server reconciliation, and I think I understand these concepts. What I don't get is how should input be handled. I read many posts about de-jitter buffers, packing many input samples into single packet and so on. But I never found a straightforward explanation how input plays with simulation.
I use RakNet, so I have quite high level networking lib that does all the magic for me like packing many similar messages into single packet, it has reliable UDP layer if I need it, I can have it ordered, reliable, unreliable etc. so its not a problem.
What I don't get is - when do I actually sample and send input data? Client ticks simulation at some rate, server ticks at another (but I guess its usually the same tick rate, right?). I use events for input so when key forward is pressed on the client, I receive event and set player state to "moving forward" and on next simulation step I move him forward one time (according to the current state). But when should that information be sent to the server? Should I send input state every simulation step? At the beginning? At the end? At different rate? I tried using different rate (like 20 input updates each second) but then client and server are getting out of sync because client logic sometimes does more steps (for example, pressing forward and releasing it quickly allowed for one simulation step on client, but server never received that input, the same for releasing key after some time - server did less steps than client).
If I send input every simulation frame and stick some frame id to it I should be able to have it synced but what if input stops arriving at the server (packet loss or something)? Does the server keep with the information it had on previous tick, or it does nothing? I mean, if player holds "FORWARD" do I move player forward on server until message arrives that says key is no longer held? Or rather other way around - I move player only if the server receives input tick that says to move player forward? First case will move player even if he stopped holding forward for the time until late packets arrive (if they do), second will stop player even if it should be moving (because packets didn't reach the server). What solution is most commonly used and why?
So, to reiterate - I have big problem understanding how simulation ticks on client/server work with client input - most tutorials I read never mention how input is actually sampled and sent to the server, they just mention it is and explain in more detail problems with lag compensation. I'd like to use server reconciliation but I can't until I understand how to mark input, keep it on client and still be able to refer to it when server sends update (that would be tied to some input it received, otherwise I won't be able to confirm it on client-side).