How To Deal With Time for Entity Interpolation for Multiplayer Games
I am currently trying to make a simple multiplayer game but had a little bit of trouble implementing client-side entity interpolation for entity movement. For some context, I am aiming to make a server-authoritative entity interpolation system using the method outlined in the famous Source article from Valve: https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking (The entity interpolation section)
What I am currently doing is I buffer the packets that I receive from the server and use the bounding states of the time calculated by current_client_time - cl_interp
and use the fractional value between the two bounding packet times as the lerp value. However, this is where I face a problem. How do I record the time/timestamp of the packets?
Currently, I am storing and using the client timestamp of the game time I received the packets to compare. However, this led to the problem of the movement looking smooth, yet, slightly "wobbly". This was because although the server sends packet information at a stable rate, the times that the client receives them aren't perfectly stable. This means that there are times when the interval between two packets is short or sometimes longer, leading to a slower or faster interpolation between two states. This was the case even for sending the information through the local host.
I found a post with a similar question on reddit: https://www.reddit.com/r/gamedev/comments/85ndvx/implementation_specifics_for_entity_interpolation/ and the answer suggests using the servers' timestamp instead. However, based on my understanding (please correct me if I am wrong), this would mean that I would have to include the server timestamp in the packet. When I looked up the packet structures for other multiplayer indie games (Terraria, old Minecraft), I noticed that they do not include the timestamp, yet they have relatively smooth movements with no noticeable wobble.
My main question is how do they do it if they do not include the server timestamp included in the packets? Or is there something that I am misunderstanding or is there an alternative approach? If my approach/understanding is wrong, here is some more context of what I want: I don't need client-side prediction as much because I am trying to use a top-down click-to-move system like League of Legends or Starcraft. I just mainly need smooth movement and the latency is less of an issue. I hope someone can point me in the right direction.
I don't know if this will help, but here is the structure of my game. I currently have a separate fixed logic update loop and unfixed loop (mostly for rendering) for the client and a single fixed update loop for the server. The server runs at a rate of 60 ticks per second and periodically sends the positions of moving entities at a stable 20 times per second. The client polls and processes network events at an unfixed rate (though I can easily move this to a fixed one. I'm not sure where to put this but neither really helped with the wobbly behavior). The client's fixed update is also at a rate of 60 ticks per second and an unfixed rate of about 165 times per second (vsync).
Thanks!