You send commands that are post-dated into the future.
- Calculate the average-worse (right-ish side N-percentile of the bell curve) ping time in ticks with a small margin (eg: 10 tick ping +2 ticks variation)

- Client send input/command to the server scheduled for
(now_tick + ping_ticks)(eg: now 50 + ping 5 = tick 55) - Server receives the command
(ping_ticks / 2)later, relays it to the clients - Clients (hopefully) receive commands before they're due (eg: received on tick 53) and execute command on the tick that was calculated as the post-date (eg: tick 55) so everyone is in sync.
When packets are delayed there is two ways around it:
- all clients/servers agree that commands will be received at most every N ticks with a delay of M ticks and will simply wait if no packet is received (use an empty keep-alive packet when no commands are to be sent). More packets can be sent more frequently.
- Clients/servers will rewind in time and recalculate (fast-forward) once delayed packets are received. So all clients/servers keep a periodic backup of the entire game state at N ticks granularity for as far back as M (ping-delay) ticks can be accepted.
Usually a mix of both is used.