I think the only way to do this smooth is predicting and correcting. (That might cause some jumpyness in movement if the
network update is slow)
I would do this that way (conceptual too):
Server I.
1. server sends a ping with minimal data to the client, and saves the time when it happenes.
2. server recives the answer for the pings, saves the actual networking delay in msec.
Client I.
1. if recived a ping, answer to it.
Client II
1. if client start to move or rotate, you have to send it to the server, send direction current positions, angles and movement described with a vector. Meanwhile, on acting client side you can smoothly plays these effects. Other players avatar moves as described in the last packet from the server.
2. if recives data from the server, it upgrades the position of the avatars. That might cause some rollback in avatar positions.
Using the new avatar movement angles and speed data, start playing their movement until next correction.
Server II.
1. Server recives movement data and player positions and angles.
We know, when we recive that data, and the player is in move, then it wont be actually there because of the latency. Server sends data to the other clients ( movement direction, speed, angles, rotation vector and speed ) and an updated position data modified with the latency value, predicted where will be the other avatars, when the packet arrives to the specified clients.
====IDEAS:
With UDP, you can update the network loop more frequently. To avoid flood, you can optimize the sent data. 8 pressed key state fit in one byte. If you dont need float data for angles, then it will fit in one byte too using a conversion. (byte value 0=degree 0, byte value 255=degree 360) (that way, you only update the avatars angle value, if their float angles differs more than a critical value.)
I hope you will find at least one useful thing in my description.
(and sorry for my english, its not the best.)
No place like 127.0.0.1 .