diff --git a/docs/cultnet-transport-parity.md b/docs/cultnet-transport-parity.md
index 15b0e3d9..2f792d33 100644
--- a/docs/cultnet-transport-parity.md
+++ b/docs/cultnet-transport-parity.md
@@ -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
diff --git a/src/GameCult.Networking/CultNetTransport.cs b/src/GameCult.Networking/CultNetTransport.cs
index 4aa4719c..9c0f44ca 100644
--- a/src/GameCult.Networking/CultNetTransport.cs
+++ b/src/GameCult.Networking/CultNetTransport.cs
@@ -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
}
}
+ ///
+ /// Channel-aware send adapter for the C# LiteNetLib production lane.
+ ///
+ public sealed class LiteNetLibTransportConnection
+ {
+ private readonly NetPeer _peer;
+ private readonly CultNetTransportStats _stats = new CultNetTransportStats();
+
+ ///
+ /// Initializes a new channel-aware adapter around a LiteNetLib peer.
+ ///
+ public LiteNetLibTransportConnection(NetPeer peer, CultNetTransportProfile? profile = null)
+ {
+ _peer = peer ?? throw new ArgumentNullException(nameof(peer));
+ Profile = profile ?? CultNetTransportProfiles.CreateLiteNetLib("csharp-litenetlib-peer");
+ }
+
+ ///
+ /// Gets the transport profile this adapter implements.
+ ///
+ public CultNetTransportProfile Profile { get; }
+
+ ///
+ /// Gets a snapshot of outbound transfer counters.
+ ///
+ public CultNetTransportStats Stats => _stats.Snapshot();
+
+ ///
+ /// Sends a payload over a supported LiteNetLib transport channel.
+ ///
+ 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++;
+ }
+
+ ///
+ /// Serializes and sends a legacy GameCult.Networking union message.
+ ///
+ public void SendLegacy(T message)
+ where T : Message
+ {
+ if (message == null) throw new ArgumentNullException(nameof(message));
+ Send("legacy", MessageSerialization.Serialize(message));
+ }
+
+ ///
+ /// Serializes and sends a CultNet schema-v0 message.
+ ///
+ public void SendSchema(T message)
+ where T : ICultNetSchemaMessage
+ {
+ if (message == null) throw new ArgumentNullException(nameof(message));
+ Send("schema", CultNetSchemaMessageSerialization.Serialize(message));
+ }
+ }
+
///
/// Transport connection for the current TCP length-prefixed CultNet schema lane.
///
diff --git a/src/GameCult.Networking/NetPeerExtensions.cs b/src/GameCult.Networking/NetPeerExtensions.cs
index 4b4470c8..6f691a28 100644
--- a/src/GameCult.Networking/NetPeerExtensions.cs
+++ b/src/GameCult.Networking/NetPeerExtensions.cs
@@ -1,5 +1,4 @@
using LiteNetLib;
-using MessagePack;
namespace GameCult.Networking
{
@@ -16,7 +15,7 @@ namespace GameCult.Networking
/// The message to serialize and send.
public static void Send(this NetPeer peer, T message) where T : Message
{
- peer.Send(MessageSerialization.Serialize(message), DeliveryMethod.ReliableOrdered);
+ new LiteNetLibTransportConnection(peer).SendLegacy(message);
}
///
@@ -27,7 +26,7 @@ namespace GameCult.Networking
/// The schema-v0 message to serialize and send.
public static void SendCultNet(this NetPeer peer, T message) where T : ICultNetSchemaMessage
{
- peer.Send(CultNetSchemaMessageSerialization.Serialize(message), DeliveryMethod.ReliableOrdered);
+ new LiteNetLibTransportConnection(peer).SendSchema(message);
}
}
}
diff --git a/src/GameCult.Networking/README.md b/src/GameCult.Networking/README.md
index 08f68cd1..4bde0919 100644
--- a/src/GameCult.Networking/README.md
+++ b/src/GameCult.Networking/README.md
@@ -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