The problem: Let's say we want to create top down MMORPG in browser, and we started with implementing movement of your character. Okay, so how it works?
- Character gets inputs and compares if they are the same with the old frame, if they are different it sends to the server that inputs change. So if you press D and release after 0.1sec it will send 2 packets, when you pressed D and when you released it.
So far so good, but now on the server. How do we sync the server with a client? Okay
2 Options
- Fixed timestep, we just process inputs in a while loop which will run at 60fps so it will be using the same fixed timestep as a client, but we need somehow fix the issue when you don't receive inputs.
- We just store input A with client Tick, and wait for next input, if we receive next input we know it's a start so we know how many times we should play input A. Using B.clientTick - A.clientTick we know how many times we should process this input, but what if client modifies the clientTick on input B? perhaps 1) is better in this case.
The problem, we never know in advance when player releases D and in networking behavior it is not guaranteed that if the client press D and after 0.1sec release it, it will be same for server, in this case server will move more or less, if you receive release packet after 0.15sec, you can play one more frame and your positions on client and server will be not synced.
What are possible solutions? This is why i am asking you, i can't find proper solution.
Solutions i know:
Run client at fixed timestep (60fps) and send 60 packets a sec (or as fast as possible). This is not the best especially on TCP connection. This is why i want send only packets when player inputs change.
All packets the client send can play at max 3 times and client will send packet if you change inputs or every 3rd frame (considering it is in fixed timestep). Server will store last 3 inputs in buffer so if let's say you receive: CTick: 0 - Input D - Server Tick 0 CTick: 3 - Input D - Server Tick 3 CTick: 5 - Release D - Server Tick 6 (it will must rewind one frame because Release D was released after 2 frames from last packet not 3 frames)
But problem can be here Tick: 0 - Input D - Serve Tick 0 Tick: 3 - Input D - Server Tick 4 (Now we have gap and one frame is not played on server)
- To overcome this problem we can replay "last received input" and if we get same input next, we can just throw it. If we get different input we rewind the position
I feel like whole this implementation is quite more complex than it should be and I am not sure if this is proper solution, what are your thoughts or suggestions?