Route LiteNetLib sends through transport adapter

This commit is contained in:
Meta Vens 2026-06-16 07:41:29 +01:00
commit 6f2c52170c
4 changed files with 74 additions and 5 deletions

View file

@ -150,7 +150,9 @@ Current progress:
`Client`/`Server` expose profiles for the LiteNetLib lane. The profile names
both the modern reliable ordered `schema` channel and the legacy reliable
ordered `legacy` union-message channel, so LiteNetLib is described as an
adapter instead of remaining the hidden default.
adapter instead of remaining the hidden default. `NetPeer` send helpers now
route through `LiteNetLibTransportConnection`, so outbound schema and legacy
messages share one channel-aware ReliableOrdered adapter surface.
- TypeScript has the first narrow transport connection port:
`TcpFramedTransportConnection` owns length-prefixed frame delivery, exposes
frame/close/error events, `send(channel, payload)`, `close`, and transfer

View file

@ -8,6 +8,7 @@ using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using LiteNetLib;
namespace GameCult.Networking
{
@ -2044,6 +2045,71 @@ namespace GameCult.Networking
}
}
/// <summary>
/// Channel-aware send adapter for the C# LiteNetLib production lane.
/// </summary>
public sealed class LiteNetLibTransportConnection
{
private readonly NetPeer _peer;
private readonly CultNetTransportStats _stats = new CultNetTransportStats();
/// <summary>
/// Initializes a new channel-aware adapter around a LiteNetLib peer.
/// </summary>
public LiteNetLibTransportConnection(NetPeer peer, CultNetTransportProfile? profile = null)
{
_peer = peer ?? throw new ArgumentNullException(nameof(peer));
Profile = profile ?? CultNetTransportProfiles.CreateLiteNetLib("csharp-litenetlib-peer");
}
/// <summary>
/// Gets the transport profile this adapter implements.
/// </summary>
public CultNetTransportProfile Profile { get; }
/// <summary>
/// Gets a snapshot of outbound transfer counters.
/// </summary>
public CultNetTransportStats Stats => _stats.Snapshot();
/// <summary>
/// Sends a payload over a supported LiteNetLib transport channel.
/// </summary>
public void Send(string channelId, byte[] payload)
{
if (payload == null) throw new ArgumentNullException(nameof(payload));
if (!string.Equals(channelId, "schema", StringComparison.Ordinal)
&& !string.Equals(channelId, "legacy", StringComparison.Ordinal))
{
throw new InvalidOperationException($"litenetlib transport only supports schema and legacy channels, got \"{channelId}\".");
}
_peer.Send(payload, DeliveryMethod.ReliableOrdered);
_stats.BytesSent += payload.Length;
_stats.FramesSent++;
}
/// <summary>
/// Serializes and sends a legacy GameCult.Networking union message.
/// </summary>
public void SendLegacy<T>(T message)
where T : Message
{
if (message == null) throw new ArgumentNullException(nameof(message));
Send("legacy", MessageSerialization.Serialize(message));
}
/// <summary>
/// Serializes and sends a CultNet schema-v0 message.
/// </summary>
public void SendSchema<T>(T message)
where T : ICultNetSchemaMessage
{
if (message == null) throw new ArgumentNullException(nameof(message));
Send("schema", CultNetSchemaMessageSerialization.Serialize(message));
}
}
/// <summary>
/// Transport connection for the current TCP length-prefixed CultNet schema lane.
/// </summary>

View file

@ -1,5 +1,4 @@
using LiteNetLib;
using MessagePack;
namespace GameCult.Networking
{
@ -16,7 +15,7 @@ namespace GameCult.Networking
/// <param name="message">The message to serialize and send.</param>
public static void Send<T>(this NetPeer peer, T message) where T : Message
{
peer.Send(MessageSerialization.Serialize(message), DeliveryMethod.ReliableOrdered);
new LiteNetLibTransportConnection(peer).SendLegacy(message);
}
/// <summary>
@ -27,7 +26,7 @@ namespace GameCult.Networking
/// <param name="message">The schema-v0 message to serialize and send.</param>
public static void SendCultNet<T>(this NetPeer peer, T message) where T : ICultNetSchemaMessage
{
peer.Send(CultNetSchemaMessageSerialization.Serialize(message), DeliveryMethod.ReliableOrdered);
new LiteNetLibTransportConnection(peer).SendSchema(message);
}
}
}

View file

@ -369,7 +369,9 @@ The client:
`Client.TransportProfile` and `Server.TransportProfile` describe the production
LiteNetLib lane as a `litenetlib` transport adapter with reliable ordered
`schema` and `legacy` channels. Discovery and operators can inspect the active
pipe without treating LiteNetLib as an implicit protocol truth.
pipe without treating LiteNetLib as an implicit protocol truth. `NetPeer`
send helpers route through `LiteNetLibTransportConnection`, keeping outbound
schema and legacy messages behind that channel-aware adapter surface.
The native RUDP socket path also exposes `CultNetRudpReconnectLoop` for
caller-owned game or service loops. The caller reports closure, calls