diff --git a/docs/cultnet-transport-parity.md b/docs/cultnet-transport-parity.md
index c9532444..578f4571 100644
--- a/docs/cultnet-transport-parity.md
+++ b/docs/cultnet-transport-parity.md
@@ -154,7 +154,11 @@ Current progress:
route through `LiteNetLibTransportConnection`; `Client` and `Server` now keep
a per-peer adapter and route their own schema/legacy sends through it as
well. Inbound payload classification and transfer stats also belong to that
- channel-aware adapter before dispatching schema-v0 or legacy messages.
+ channel-aware adapter before dispatching schema-v0 or legacy messages. The
+ C# database, simulation-observation, Verse-discovery, and peer-exchange
+ service wrappers now send responses through `Server.SendCultNet(...)`, so
+ server-owned service bodies no longer reach around the per-peer adapter with
+ direct `NetPeer` extension sends.
- 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.Mesh/CultMeshPeerExchange.cs b/src/GameCult.Mesh/CultMeshPeerExchange.cs
index 85b959ac..d0c1d3a1 100644
--- a/src/GameCult.Mesh/CultMeshPeerExchange.cs
+++ b/src/GameCult.Mesh/CultMeshPeerExchange.cs
@@ -281,7 +281,7 @@ namespace GameCult.Mesh
private Task HandleRequestAsync(CultMeshPeerExchangeRequestMessage request, NetPeer peer)
{
- peer.SendCultNet(CreateResponse(request));
+ _server.SendCultNet(peer, CreateResponse(request));
return Task.CompletedTask;
}
}
diff --git a/src/GameCult.Mesh/CultMeshVerseDiscovery.cs b/src/GameCult.Mesh/CultMeshVerseDiscovery.cs
index b441eeb8..7a845492 100644
--- a/src/GameCult.Mesh/CultMeshVerseDiscovery.cs
+++ b/src/GameCult.Mesh/CultMeshVerseDiscovery.cs
@@ -127,7 +127,7 @@ namespace GameCult.Mesh
private Task HandleRequestAsync(CultMeshVerseCatalogRequestMessage request, NetPeer peer)
{
- peer.SendCultNet(CreateResponse(request));
+ _server.SendCultNet(peer, CreateResponse(request));
return Task.CompletedTask;
}
}
diff --git a/src/GameCult.Networking/CultNetDatabaseServer.cs b/src/GameCult.Networking/CultNetDatabaseServer.cs
index df8e2e72..a9844f62 100644
--- a/src/GameCult.Networking/CultNetDatabaseServer.cs
+++ b/src/GameCult.Networking/CultNetDatabaseServer.cs
@@ -209,13 +209,13 @@ namespace GameCult.Networking
private Task HandleSnapshotRequestAsync(CultNetSnapshotRequestMessage request, NetPeer peer)
{
- peer.SendCultNet(CreateSnapshotResponse(request));
+ _server.SendCultNet(peer, CreateSnapshotResponse(request));
return Task.CompletedTask;
}
private Task HandleShardCatalogRequestAsync(CultNetShardCatalogRequestMessage request, NetPeer peer)
{
- peer.SendCultNet(CreateShardCatalogResponse(request));
+ _server.SendCultNet(peer, CreateShardCatalogResponse(request));
return Task.CompletedTask;
}
@@ -223,11 +223,11 @@ namespace GameCult.Networking
{
try
{
- peer.SendCultNet(CreateShardLogResponse(request));
+ _server.SendCultNet(peer, CreateShardLogResponse(request));
}
catch (Exception ex)
{
- peer.SendCultNet(new CultNetErrorMessage { Error = ex.Message });
+ _server.SendCultNet(peer, new CultNetErrorMessage { Error = ex.Message });
}
return Task.CompletedTask;
@@ -244,13 +244,13 @@ namespace GameCult.Networking
if (!await TryForwardPutAsync(ex, message).ConfigureAwait(false))
{
_server.Logger.LogError($"CultNet raw put authority failed: {ex.Message}");
- peer.SendCultNet(CreateRoutingError(ex));
+ _server.SendCultNet(peer, CreateRoutingError(ex));
}
}
catch (Exception ex)
{
_server.Logger.LogError($"CultNet raw put failed: {ex.Message}");
- peer.SendCultNet(new CultNetErrorMessage { Error = ex.Message });
+ _server.SendCultNet(peer, new CultNetErrorMessage { Error = ex.Message });
}
}
@@ -264,12 +264,12 @@ namespace GameCult.Networking
{
if (!await TryForwardDeleteAsync(ex, message).ConfigureAwait(false))
{
- peer.SendCultNet(CreateRoutingError(ex));
+ _server.SendCultNet(peer, CreateRoutingError(ex));
}
}
catch (Exception ex)
{
- peer.SendCultNet(new CultNetErrorMessage { Error = ex.Message });
+ _server.SendCultNet(peer, new CultNetErrorMessage { Error = ex.Message });
}
}
@@ -280,7 +280,7 @@ namespace GameCult.Networking
: message.SubscriptionId;
if (string.IsNullOrWhiteSpace(subscriptionId))
{
- peer.SendCultNet(new CultNetErrorMessage { Error = "Database subscription requires a subscriptionId or messageId." });
+ _server.SendCultNet(peer, new CultNetErrorMessage { Error = "Database subscription requires a subscriptionId or messageId." });
return Task.CompletedTask;
}
@@ -296,7 +296,7 @@ namespace GameCult.Networking
if (message.IncludeSnapshot)
{
- peer.SendCultNet(CreateSnapshotResponse(new CultNetSnapshotRequestMessage
+ _server.SendCultNet(peer, CreateSnapshotResponse(new CultNetSnapshotRequestMessage
{
MessageId = message.MessageId,
SchemaIds = message.SchemaIds,
@@ -331,7 +331,7 @@ namespace GameCult.Networking
var outbound = CreateChangeMessage(change, subscriptionId, request);
if (outbound != null)
{
- peer.SendCultNet(outbound);
+ _server.SendCultNet(peer, outbound);
}
});
}
diff --git a/src/GameCult.Networking/CultNetSimulationObservationServer.cs b/src/GameCult.Networking/CultNetSimulationObservationServer.cs
index 2b301197..307493c1 100644
--- a/src/GameCult.Networking/CultNetSimulationObservationServer.cs
+++ b/src/GameCult.Networking/CultNetSimulationObservationServer.cs
@@ -65,12 +65,12 @@ namespace GameCult.Networking
{
foreach (var candidate in CreateCandidateMessages(message))
{
- peer.SendCultNet(candidate);
+ _server.SendCultNet(peer, candidate);
}
}
catch (Exception ex)
{
- peer.SendCultNet(new CultNetErrorMessage { Error = ex.Message });
+ _server.SendCultNet(peer, new CultNetErrorMessage { Error = ex.Message });
}
return Task.CompletedTask;
diff --git a/src/GameCult.Networking/Server.cs b/src/GameCult.Networking/Server.cs
index ec2c35b5..3315750e 100644
--- a/src/GameCult.Networking/Server.cs
+++ b/src/GameCult.Networking/Server.cs
@@ -176,6 +176,23 @@ namespace GameCult.Networking
AddCultNetMessageListener(callback);
}
+ ///
+ /// Sends a legacy GameCult.Networking union message through this server's per-peer LiteNetLib adapter.
+ ///
+ public void Send(NetPeer? peer, Message message)
+ {
+ SendLegacy(peer, message);
+ }
+
+ ///
+ /// Sends a CultNet schema-v0 message through this server's per-peer LiteNetLib adapter.
+ ///
+ public void SendCultNet(NetPeer? peer, T message)
+ where T : ICultNetSchemaMessage
+ {
+ SendSchema(peer, message);
+ }
+
///
/// Removes a previously registered listener for a specific message type.
///