Separate Eve control and entity subscriptions
This commit is contained in:
parent
a2ad6bfaf5
commit
edaf3b1e3b
4 changed files with 87 additions and 18 deletions
|
|
@ -255,6 +255,29 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
surfaceId,
|
||||
requiredSurfaceKind: "interactive-world",
|
||||
clientRuntimeId: $"eve-unity-test-{Guid.NewGuid():N}");
|
||||
var preparationDeadline = Time.realtimeSinceStartup + 30f;
|
||||
while (true)
|
||||
{
|
||||
var preparation = provider.PrepareAsync();
|
||||
while (!preparation.IsCompleted && Time.realtimeSinceStartup < preparationDeadline)
|
||||
yield return new WaitForSecondsRealtime(0.1f);
|
||||
if (!preparation.IsCompleted)
|
||||
throw new TimeoutException("Timed out preparing the advertised Eve provider.");
|
||||
var prepared = false;
|
||||
try
|
||||
{
|
||||
preparation.GetAwaiter().GetResult();
|
||||
prepared = true;
|
||||
}
|
||||
catch (InvalidOperationException) when (Time.realtimeSinceStartup < preparationDeadline)
|
||||
{
|
||||
}
|
||||
catch (TimeoutException) when (Time.realtimeSinceStartup < preparationDeadline)
|
||||
{
|
||||
}
|
||||
if (prepared) break;
|
||||
yield return new WaitForSecondsRealtime(0.1f);
|
||||
}
|
||||
var publicationDeadline = Time.realtimeSinceStartup + 30f;
|
||||
while (true)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -255,6 +255,29 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
surfaceId,
|
||||
requiredSurfaceKind: "interactive-world",
|
||||
clientRuntimeId: $"eve-unity-test-{Guid.NewGuid():N}");
|
||||
var preparationDeadline = Time.realtimeSinceStartup + 30f;
|
||||
while (true)
|
||||
{
|
||||
var preparation = provider.PrepareAsync();
|
||||
while (!preparation.IsCompleted && Time.realtimeSinceStartup < preparationDeadline)
|
||||
yield return new WaitForSecondsRealtime(0.1f);
|
||||
if (!preparation.IsCompleted)
|
||||
throw new TimeoutException("Timed out preparing the advertised Eve provider.");
|
||||
var prepared = false;
|
||||
try
|
||||
{
|
||||
preparation.GetAwaiter().GetResult();
|
||||
prepared = true;
|
||||
}
|
||||
catch (InvalidOperationException) when (Time.realtimeSinceStartup < preparationDeadline)
|
||||
{
|
||||
}
|
||||
catch (TimeoutException) when (Time.realtimeSinceStartup < preparationDeadline)
|
||||
{
|
||||
}
|
||||
if (prepared) break;
|
||||
yield return new WaitForSecondsRealtime(0.1f);
|
||||
}
|
||||
var publicationDeadline = Time.realtimeSinceStartup + 30f;
|
||||
while (true)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ namespace GameCult.Eve.UnityScene
|
|||
private CultNetDocumentRegistry? _networkRegistry;
|
||||
private CultNetShardDescriptor? _replicaShard;
|
||||
private CultNetDatabaseSubscriptionClient? _subscriptions;
|
||||
private CultNetDatabaseSubscriptionClient? _entitySubscriptions;
|
||||
private CultMeshClient? _meshClient;
|
||||
private CultMeshContentTransferService? _contentTransfer;
|
||||
private CultMeshVerifiedBodyMappingBroker? _assetBodyMappings;
|
||||
|
|
@ -364,13 +365,15 @@ namespace GameCult.Eve.UnityScene
|
|||
_prefabs.Clear();
|
||||
_nativeAssets.Clear();
|
||||
_nativeAssetMetadata.Clear();
|
||||
_subscriptions?.Dispose();
|
||||
_entitySubscriptions?.Dispose();
|
||||
_node?.Dispose();
|
||||
_snapshot?.Dispose();
|
||||
_subscriptions?.Dispose();
|
||||
_meshClient?.Dispose();
|
||||
_node = null;
|
||||
_snapshot = null;
|
||||
_subscriptions = null;
|
||||
_entitySubscriptions = null;
|
||||
_meshClient = null;
|
||||
_contentTransfer = null;
|
||||
_assetBodyMappings = null;
|
||||
|
|
@ -689,21 +692,27 @@ namespace GameCult.Eve.UnityScene
|
|||
|
||||
private void EnsureLiveSubscriptions()
|
||||
{
|
||||
if (_subscriptions != null) return;
|
||||
var endpoint = new Uri(_endpoint);
|
||||
var client = CultNetSchemaClients.CreateForEndpoint(_endpoint);
|
||||
client.Connect(endpoint.Host, endpoint.Port);
|
||||
var deadline = DateTime.UtcNow + TimeSpan.FromSeconds(5);
|
||||
while (!client.Connected && DateTime.UtcNow < deadline)
|
||||
System.Threading.Thread.Sleep(1);
|
||||
if (!client.Connected)
|
||||
if (_subscriptions != null && _entitySubscriptions != null) return;
|
||||
_subscriptions?.Dispose();
|
||||
_entitySubscriptions?.Dispose();
|
||||
_subscriptions = null;
|
||||
_entitySubscriptions = null;
|
||||
try
|
||||
{
|
||||
client.Dispose();
|
||||
throw new TimeoutException($"Timed out connecting live Eve state subscription to '{_endpoint}'.");
|
||||
_subscriptions = CreateSubscriptionClient();
|
||||
_entitySubscriptions = CreateSubscriptionClient();
|
||||
}
|
||||
catch
|
||||
{
|
||||
_subscriptions?.Dispose();
|
||||
_entitySubscriptions?.Dispose();
|
||||
_subscriptions = null;
|
||||
_entitySubscriptions = null;
|
||||
throw;
|
||||
}
|
||||
|
||||
_subscriptions = new CultNetDatabaseSubscriptionClient(client, _node!.Database.Cache, _networkRegistry!);
|
||||
_subscriptions.Changed += OnReplicatedDocumentChanged;
|
||||
_entitySubscriptions.Changed += OnReplicatedDocumentChanged;
|
||||
|
||||
var lowered = new EveUnitySceneSurfaceLowerer()
|
||||
.Lower(CurrentSurfaceDocument.SurfaceDocument, CurrentSurfaceDocument.AdvertisedSurface);
|
||||
string entityViewPointer = lowered.PlayableWorld == null
|
||||
|
|
@ -711,12 +720,12 @@ namespace GameCult.Eve.UnityScene
|
|||
: lowered.PlayableWorld.EntityViewPointerId;
|
||||
if (!string.IsNullOrWhiteSpace(entityViewPointer))
|
||||
{
|
||||
_subscriptions.SubscribeAsync(
|
||||
_entitySubscriptions.SubscribeAsync(
|
||||
"eve-unity-entity-view",
|
||||
recordKeys: new[] { entityViewPointer },
|
||||
schemaIds: new[] { EveEntitySoaViewDocument.SchemaId })
|
||||
.GetAwaiter().GetResult();
|
||||
var current = _node.Database.Cache.Get(new CultRecordKey(entityViewPointer)) as EveEntitySoaViewDocument
|
||||
var current = _node!.Database.Cache.Get(new CultRecordKey(entityViewPointer)) as EveEntitySoaViewDocument
|
||||
?? _snapshot!
|
||||
.FetchDocumentsAsync<EveEntitySoaViewDocument>(
|
||||
recordKeys: new[] { entityViewPointer },
|
||||
|
|
@ -731,8 +740,6 @@ namespace GameCult.Eve.UnityScene
|
|||
schemaIds: new[] { EveSurfaceDocument.SchemaId },
|
||||
includeSnapshot: false)
|
||||
.GetAwaiter().GetResult();
|
||||
// Entity views name one immutable body generation. PublishEntityView fetches that
|
||||
// exact publication; a schema-wide subscription would import every retained frame.
|
||||
_subscriptions.SubscribeAsync(
|
||||
"eve-unity-receipts",
|
||||
schemaIds: new[] { EveCommandReceiptDocument.SchemaId },
|
||||
|
|
@ -740,6 +747,22 @@ namespace GameCult.Eve.UnityScene
|
|||
.GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private CultNetDatabaseSubscriptionClient CreateSubscriptionClient()
|
||||
{
|
||||
var endpoint = new Uri(_endpoint);
|
||||
var client = CultNetSchemaClients.CreateForEndpoint(_endpoint);
|
||||
client.Connect(endpoint.Host, endpoint.Port);
|
||||
var deadline = DateTime.UtcNow + TimeSpan.FromSeconds(5);
|
||||
while (!client.Connected && DateTime.UtcNow < deadline)
|
||||
System.Threading.Thread.Sleep(1);
|
||||
if (!client.Connected)
|
||||
{
|
||||
client.Dispose();
|
||||
throw new TimeoutException($"Timed out connecting live Eve state subscription to '{_endpoint}'.");
|
||||
}
|
||||
return new CultNetDatabaseSubscriptionClient(client, _node!.Database.Cache, _networkRegistry!);
|
||||
}
|
||||
|
||||
private void OnReplicatedDocumentChanged(CultNetReplicatedDocumentChange change)
|
||||
{
|
||||
if (change.Document is EveEntitySoaViewDocument entityView)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "org.gamecult.eve.unity-scene",
|
||||
"displayName": "Eve Unity Scene Lowering",
|
||||
"version": "0.3.71",
|
||||
"version": "0.3.72",
|
||||
"unity": "6000.0",
|
||||
"description": "Provider-agnostic Unity scene shell for gamecult.eve.surface.v1 interactive world surfaces.",
|
||||
"dependencies": {
|
||||
|
|
|
|||
Reference in a new issue