I'm sorry, I will try my best to explain the current logic of the implementation I have, with all the details, so you can tell me if I'm doing anything wrong.
Client logic, main loop:
// Called every 30hz
void OnUpdate()
{
var input = GetCurrentInput(); // Returns a struct with things like: 'w pressed', 'space pressed' etc
SendInput(input, _seqNumber); // Sends the input to the server
MoveLocally(input); // Moves the player locally, for Client Side Prediction
_seqNumber++;
}
Client logic, when a package comes back from the server:
void OnPackageReceived(Snapshot snapshot)
{
_snapshotInterpolator.PushSnapshot(snapshot); // This will interpolate the entities in the world, except for the local player
Reconciliate(snapshot); // Will check if the game snapshot returned and the predicted state match
}
This is all there is for the client, I know that the Client Side Prediction and Entity Interpolation work just fine.
Server logic, main loop:
void OnUpdate() // Called every 30hz
{
// Move all players and clear the queue
foreach (Input inputReceived in _inputsQueue)
{
var player = GetPlayer(inputReceived.PlayerId);
player.Move(inputReceived);
player.LastInputProcessed = inputReceived.SeqNumber;
}
_inputsQueue.Clear();
// Now that all players have been moved, return the current game state to clients
var snapshot = new Snapshot
{
Time = TicksMilliseconds(),
PlayerStates = GetPlayerStates() // Returns an array of players and their positions, as well as the last seqstamp processed
};
SerializeAndBroadcast(snapshot);
}
Server logic, on input received:
void OnInputReceived(Input input)
{
_inputsQueue.Enqueue(input);
}
That is all the logic, I believe the problem is in the fact that on the server loop, if a packets gets delayed, the loop will not update the player position, but it will still send a snapshot, saying that the client didn't move on that tick, when that snapshot gets back to the client, the client will interpolate correctly to it, and stop, (because that is actually what the client can see) but on the next server tick, the player will move again, since the delayed packet finally got to the server, and in that snapshot you will see a movement again. So from a clients perspective, the entities will go on for a few ticks, then stop, then go on again, then stop, etc, etc. But again, I believe this is not an interpolation problem, since the actual snapshots received by the client tell that the entity has stopped, it is supposed to stop. There is no velocity involved yet in the game and I don't want to include it, I want to keep this as simple as possible.
Also, the local player feels just fine! Thanks to CSP, no problem there.
One way I managed to mitigate the problem, (actually it solved it, but I know I'm not implementing it right) is to have a buffer on the server, every time an input gets to the server the server stores it in a buffer and waits till it was 2 / 3, this way, when the main loop ticks, the foreach that applies movements will always have some input to work with, and the jittering disappears, still this adds latency and I'm not really sure how to do it right. Thank you very much for helping again!