Remix.run Logo
shdh a day ago

There are a number of issues with the Q3 netcode.

When entities are culled due to Potentially Visible Sets (PVS), a player moving fast enough near a vis brush may appear to pop into existence out of thin air. This occurs because of latency. A simple fix would be for the QVM code to extrapolate the player’s position into future frames to determine whether the entity should be culled.

The original Q3 netcode lacked lag compensation for hitscan weapons. As a result, players often had to "lead" their crosshair to register proper hits. This issue was later addressed by the Unlagged mod, which introduced lag compensation.

Input commands had a back buffer to handle lost input frames, but instead of applying them with a delay, the inputs were applied to entities instantly. Consequently, other players' entities sometimes appeared "choppy" when the respective player had a poor connection.

That being said, they got almost everything right:

* Snapshots with entities: Efficiently delivering game state updates to clients.

* Lerping entities: Smoothing movement on the client side using a snapshot buffer.

* Delta encoding: Transmitting only changes in entity states within snapshots.

* Huffman encoding: Compressing snapshots for reduced bandwidth usage.

monkburger a day ago | parent | next [-]

Also; The server calculated projectile trajectories independently of client-side predictions.It was buggy on certain? versions. We (OSP) noticed this on earlier Quake 3 releases and it may have been fixed.

This results in visible "misfires" where projectiles didn't behave as expected

BoingBoomTschak a day ago | parent | prev [-]

Talking about Unlagged, I would kill for a clear explanation (with diagrams!) of various netcode improvements in it, CPMA and QL.

I'm forced to try to piece together a mental model by finding crumbs on the web, with the current situation:

https://github.com/minism/fps-netcode

https://playmorepromode.com/guides/cpma-client-settings

https://www.esreality.com/?a=post&id=2548041#pid2548771

https://old.reddit.com/r/QuakeChampions/comments/9jd3wv/for_...

PS: the modern way of enjoying Q3 is https://github.com/ec-/Quake3e or CNQ3, these days. Don't know about https://github.com/ioquake/ioq3

monkburger a day ago | parent [-]

I can't speak for CMPA or QL, but I can speak a little bit on Unlagged:

- w/ Unlagged, the Server now stores a history buffer (g_activeSnapshots[]) of player states. When processing a action shot, it uses the timestamp sent by the client (cmd.serverTime) to interpolate or rewind states for collision checks (G_EvaluateTrajectory()). This allows the server rewinds player positions to the moment a client action occurred (eg: firing a shot)

- Unlagged reduces choppy movements by making clients use a snapshot buffer (cg.snap, cg.nextSnap) to interpolate positions with CG_InterpolateEntityPosition(). Extrapolation uses velocity vectors from the last known snapshot (currentState.pos.trDelta).

- Unlagged tries to compensate for high latency by rewinding entities to their positions at the time of the shot (ClientThink_real() and G_RewindEntities()). Uses a circular buffer (via lagometerSnapshot_t) to store past states.

- Position corrections (cg.predictedPlayerState) are interpolated over several frames using VectorLerp() to fix prediction mismatches between client and server.

- Commands are stored in a circular buffer (ucmds[]) and replayed when missing packets are detected (ClientThink_cmd()). This attempts to mitigate packet loss by buffering input commands for later execution