public sealed class NetworkSimulationWraps a transport and makes it worse, on purpose and reproducibly: latency, jitter, loss, duplication, and the reordering that falls out of jitter.
No guide page documents this yet — the page shows what the code says about itself.
Remarks
Netcode developed on localhost is netcode that has never been tested. This is the thing that fixes it, and it is a decorator rather than an option on each transport so that there is exactly one implementation of "bad network" to trust, and it applies to the in-process transport as readily as to a socket.
It is a pure function of the calls made to it. The delay budget is spent against the virtual clock Poll advances, never against a wall clock, and every random decision comes from a seed the caller supplies. The same seed, the same profile and the same sequence of sends and polls produce the same deliveries on every machine and every run — which is what makes "the bug that only happens at 20 % loss" a test rather than an anecdote.
Channel contracts are respected. A Reliable payload is delayed but never lost, never duplicated, and never overtaken by a later one; a Sequenced one may be lost but not reordered. The simulation only does what the real world is allowed to do to that channel, so the layer above is exercised against its contract and not against a violation of it.
Fields and properties (9)
public ITransport InnerThe transport being made worse.
public NetworkSimulationProfile ProfileHow bad it is currently pretending to be. May be changed while running.
public long SentPayloadCountPayloads handed to the inner transport so far.
public long DroppedPayloadCountPayloads thrown away so far.
public long DuplicatedPayloadCountExtra copies sent so far.
public int PendingPayloadCountPayloads waiting out their delay right now.
public TransportCapabilities Capabilitiespublic TransportState ServerStateWhether the server half is listening.
public TransportState ClientStateWhether the client half is connected.
Methods (10)
public NetworkSimulation(ITransport inner, NetworkSimulationProfile profile, ulong seed, bool ownsInner = true)Wraps a transport.
public void StartServer()Starts listening. Where — a port, an address, a relay — was fixed when the transport was constructed, which is what keeps this interface free of anything socket-shaped.
public void StopServer()Stops listening and disconnects everyone, reporting ServerStopped to both sides. Does nothing if the server half is already stopped.
public void StartClient()Begins connecting. Completion is reported to OnConnected on a later Poll, or refusal to OnDisconnected — never inline, so the caller has one code path for "connected in a microsecond over loopback" and "connected in 90 ms over the Atlantic".
public void StopClient()Disconnects the client half, reporting Requested to this side and RemoteRequested to the server. Does nothing if the client half is already stopped.
public void Disconnect(ConnectionId connection)public void SendToClient(ConnectionId connection, ReadOnlySpan<byte> payload, Channel channel)Sends to one connected client. Does nothing if the connection is not ours.
public void SendToServer(ReadOnlySpan<byte> payload, Channel channel)Sends to the server. Does nothing if the client half is not connected.
public void Poll(TimeSpan elapsed, ITransportEvents events)Advances the transport by and reports everything that has happened since the last call, in the order it happened, to .
public void Dispose()Drops everything still in flight and disposes the inner transport if it owns it.
Used by (5)
- LocalMatchMultiplayer
- HarnessVixen.Net.Tests
- NetworkSimulationTestsVixen.Net.Tests
- SessionTestsVixen.Net.Tests
- SimulatedTransportConformanceTestsVixen.Net.Tests