Thread CultMesh trust through Unity provider discovery

This commit is contained in:
Meta Vens 2026-08-18 19:41:25 +02:00
commit ae48ea031d
4 changed files with 29 additions and 11 deletions

View file

@ -30,8 +30,8 @@ namespace GameCult.Eve.UnityScene
private readonly string _providerId;
private readonly string _surfaceId;
private readonly string _runtimeId;
private readonly CultMeshAuthorityTrustPolicy _authorityTrust;
private readonly HashSet<string> _pendingCommandIds = new HashSet<string>(StringComparer.Ordinal);
private readonly HashSet<string> _publishedReceiptIds = new HashSet<string>(StringComparer.Ordinal);
private readonly Dictionary<string, Task<ReceiptSubscription>> _receiptSubscriptions =
new Dictionary<string, Task<ReceiptSubscription>>(StringComparer.Ordinal);
private readonly Dictionary<string, GameObject> _prefabs = new Dictionary<string, GameObject>(StringComparer.Ordinal);
@ -95,7 +95,8 @@ namespace GameCult.Eve.UnityScene
string providerId,
string surfaceId,
string runtimeId = "eve-unity",
CultMeshBodyPublicationResolver? bodyResolver = null)
CultMeshBodyPublicationResolver? bodyResolver = null,
CultMeshAuthorityTrustPolicy? authorityTrust = null)
{
_cachePath = string.IsNullOrWhiteSpace(cachePath)
? throw new ArgumentException("Cache path must be non-empty.", nameof(cachePath))
@ -112,6 +113,8 @@ namespace GameCult.Eve.UnityScene
: surfaceId.Trim();
_runtimeId = string.IsNullOrWhiteSpace(runtimeId) ? "eve-unity" : runtimeId.Trim();
_bodyResolver = bodyResolver;
_authorityTrust = authorityTrust ?? new CultMeshAuthorityTrustPolicy(
CultMeshAuthorityTrustMode.AuthenticatedRemote);
CurrentSurfaceDocument = EmptySurfaceDocument();
CurrentAssetManifestDocument = EmptyAssetManifest();
CurrentInputCapability = new EveInputCapabilityDocument();
@ -459,7 +462,6 @@ namespace GameCult.Eve.UnityScene
lock (_pendingCommandIds)
{
_pendingCommandIds.Clear();
_publishedReceiptIds.Clear();
foreach (var subscription in _receiptSubscriptions.Values)
DisposeReceiptSubscription(subscription);
_receiptSubscriptions.Clear();
@ -511,6 +513,7 @@ namespace GameCult.Eve.UnityScene
_meshClient = new CultMeshClient(new CultMeshClientOptions
{
RendezvousEndpoints = new[] { _rendezvousEndpoint },
Sessions = new CultMeshSessionManagerOptions { Trust = _authorityTrust },
RealtimeConnectors = new ICultMeshRealtimeTransportConnector[]
{
new CultMeshNativeQuicRealtimeTransportConnector()
@ -1570,7 +1573,7 @@ namespace GameCult.Eve.UnityScene
{
lock (_pendingCommandIds)
{
if (!_pendingCommandIds.Contains(receipt.CommandId) || !_publishedReceiptIds.Add(receipt.ReceiptId))
if (!_pendingCommandIds.Remove(receipt.CommandId))
return;
}
_commandOutbox?.Acknowledge(receipt.CommandId);

View file

@ -40,6 +40,8 @@ namespace GameCult.Eve.UnityScene
[FormerlySerializedAs("replicaPath")]
[SerializeField] private string cacheDirectory = "";
[SerializeField] private string runtimeId = "eve-unity";
private CultMeshAuthorityTrustPolicy _authorityTrust = new CultMeshAuthorityTrustPolicy(
CultMeshAuthorityTrustMode.AuthenticatedRemote);
private EveUnityCultMeshLiveProviderTransport? _transport;
private EveUnitySceneLiveProviderBridge? _bridge;
@ -87,7 +89,8 @@ namespace GameCult.Eve.UnityScene
string surfaceId = "",
string verseId = "",
string requiredSurfaceKind = "interactive-world",
string clientRuntimeId = "eve-unity")
string clientRuntimeId = "eve-unity",
CultMeshAuthorityTrustPolicy? authorityTrust = null)
{
if (_bridge != null || _preparation != null)
throw new InvalidOperationException("Disconnect the active provider before changing discovery configuration.");
@ -99,6 +102,8 @@ namespace GameCult.Eve.UnityScene
verseFilter = verseId ?? "";
surfaceKind = string.IsNullOrWhiteSpace(requiredSurfaceKind) ? "interactive-world" : requiredSurfaceKind;
runtimeId = string.IsNullOrWhiteSpace(clientRuntimeId) ? "eve-unity" : clientRuntimeId;
_authorityTrust = authorityTrust ?? new CultMeshAuthorityTrustPolicy(
CultMeshAuthorityTrustMode.AuthenticatedRemote);
}
public void Connect()
@ -245,7 +250,7 @@ namespace GameCult.Eve.UnityScene
if (string.IsNullOrWhiteSpace(rendezvousEndpoint))
throw new InvalidOperationException("EveUnity requires a CultMesh rendezvous endpoint.");
Selection = await new EveUnityCultMeshProviderDiscovery().DiscoverAsync(
Selection = await new EveUnityCultMeshProviderDiscovery(_authorityTrust).DiscoverAsync(
rendezvousEndpoint,
providerFilter,
surfaceFilter,
@ -264,7 +269,8 @@ namespace GameCult.Eve.UnityScene
Selection.AuthorityRuntimeId,
Selection.ProviderId,
Selection.SurfaceId,
runtimeId);
runtimeId,
authorityTrust: _authorityTrust);
try
{
await transport.PrepareAsync(cancellationToken);

View file

@ -39,6 +39,14 @@ namespace GameCult.Eve.UnityScene
public sealed class EveUnityCultMeshProviderDiscovery
{
private readonly CultMeshAuthorityTrustPolicy _authorityTrust;
public EveUnityCultMeshProviderDiscovery(CultMeshAuthorityTrustPolicy? authorityTrust = null)
{
_authorityTrust = authorityTrust ?? new CultMeshAuthorityTrustPolicy(
CultMeshAuthorityTrustMode.AuthenticatedRemote);
}
public async Task<EveUnityCultMeshProviderSelection> DiscoverAsync(
string rendezvousEndpoint,
string providerId = "",
@ -85,7 +93,8 @@ namespace GameCult.Eve.UnityScene
var observed = new List<string>();
using var mesh = new CultMeshClient(new CultMeshClientOptions
{
RendezvousEndpoints = new[] { rendezvousEndpoint }
RendezvousEndpoints = new[] { rendezvousEndpoint },
Sessions = new CultMeshSessionManagerOptions { Trust = _authorityTrust }
});
foreach (var candidate in candidates)
{

View file

@ -1,13 +1,13 @@
{
"name": "org.gamecult.eve.unity-scene",
"displayName": "Eve Unity Scene Lowering",
"version": "0.3.109",
"version": "0.3.110",
"unity": "6000.0",
"description": "Provider-agnostic Unity scene shell for gamecult.eve.surface.v1 interactive world surfaces.",
"dependencies": {
"org.gamecult.cultlib": "1.0.47",
"org.gamecult.cultlib": "1.0.48",
"org.gamecult.eve.plugin-fields": "0.2.3",
"org.gamecult.eve.surface": "0.3.2",
"org.gamecult.eve.surface": "0.3.3",
"org.gamecult.eve.unity-uitoolkit": "0.1.4",
"com.unity.mathematics": "1.3.2",
"com.unity.render-pipelines.universal": "17.4.0",