Vixen
02b45cc4
csharp
public sealed class InputBuffer<T> where T : struct, IPredictedInput<T>

Holds one client's inputs until the tick they belong to comes round. Server-side.

No guide page documents this yet — the page shows what the code says about itself.

Remarks

A jitter buffer, and the reason a predicting client runs ahead of the server. An input has to be in the server's hands before the tick it is for, or the server simulates that tick without it — so the client stamps its inputs with a tick a little in the future and the server holds them until it gets there. TargetDepth is how much slack that is, and the whole of prediction's latency budget is in it: too little and the buffer starves on every jitter spike, too much and the player's own actions take longer to reach the world than they need to.

Starvation repeats the last input rather than zeroing. The tick has to be simulated with something, and zero is the worst available choice: a player holding forward would stop dead for one tick on the server while their own client predicted them still moving, which turns a dropped packet into a guaranteed correction. Repeating is usually exactly what the client predicted, so most starvation costs nothing at all — and StarvedCount is how anybody finds out it is happening.

The counters are a control signal, not diagnostics. Depth against TargetDepth is what the server sends back so the client can adjust its lead — a buffer that keeps starving means "run further ahead", and one that keeps growing means "you are further ahead than you need to be, and paying for it in input latency".

Fields and properties (13)

  • public int TargetDepth

    How many ticks of input the server would like to be holding.

  • public int Capacity

    The most ticks of input to hold before refusing the ones furthest ahead.

  • public Tick Newest

    The newest tick an input is held for.

  • public bool HasAny

    Whether anything is held.

  • public int Depth

    How many ticks of input are waiting to be used.

  • public long StarvedCount

    Ticks simulated with no input, which repeated the last one.

  • public long LateCount

    Inputs that arrived for a tick already simulated, and could not be used.

  • public long DuplicateCount

    Inputs already held when they arrived. Redundancy working, not a problem.

  • public long RefusedCount

    Inputs refused because the client was running further ahead than the buffer holds.

  • public long MalformedCount

    Payloads that did not decode.

  • public Tick Acknowledged

    The newest tick this buffer has an input for, for telling the client.

  • public bool HasAcknowledged

    Whether anything has been received at all.

  • public InputHealth Health

    Everything worth reporting back, in one value.

Methods (4)

  • public bool TryReceive(ReadOnlySpan<byte> payload, Tick simulated)

    Takes a payload of inputs.

  • public void Offer(Tick tick, in T input, Tick simulated)

    Files one input directly, for a server that is also the client.

  • public bool TryTake(Tick tick, out T input)

    Takes the input for a tick, so the tick can be simulated.

  • public void Clear()

    Forgets everything, for a player who has gone.

Used by (2)

  • InputBufferTargetVixen.Net.Fuzz
  • PredictedInputTestsVixen.Net.Tests