From 004dccc97061d4336a98031b7e5a74508b079b85 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Tue, 16 Jun 2026 11:29:15 +0100 Subject: [PATCH] Route service responses through server adapter --- docs/cultnet-transport-parity.md | 6 ++++- src/GameCult.Mesh/CultMeshPeerExchange.cs | 2 +- src/GameCult.Mesh/CultMeshVerseDiscovery.cs | 2 +- .../CultNetDatabaseServer.cs | 22 +++++++++---------- .../CultNetSimulationObservationServer.cs | 4 ++-- src/GameCult.Networking/Server.cs | 17 ++++++++++++++ 6 files changed, 37 insertions(+), 16 deletions(-) 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. ///