From 092fda75177aca7776474d43df87a29872e51d01 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 19 Jul 2026 03:28:22 +0100 Subject: [PATCH] Remove Unity hot-state snapshot polling --- .../EveUnityCultMeshLiveProviderTransport.cs | 198 +++--------------- .../org.gamecult.eve.unity-scene/package.json | 2 +- 2 files changed, 32 insertions(+), 168 deletions(-) diff --git a/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshLiveProviderTransport.cs b/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshLiveProviderTransport.cs index d3a7716..d07f237 100644 --- a/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshLiveProviderTransport.cs +++ b/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshLiveProviderTransport.cs @@ -67,13 +67,8 @@ namespace GameCult.Eve.UnityScene private EveProviderAdvertisementDocument? _advertisement; private EveAdvertisedSurface? _advertisedSurface; private CultMeshBodyPublicationResolver? _bodyResolver; - private DateTime _nextReceiptPollUtc; - private DateTime _nextEntityViewPollUtc; - private DateTime _nextFieldsPollUtc; private long _lastQueuedEntityViewEpoch = -1; private long _lastQueuedEntityViewSequence = -1; - private readonly Dictionary _lastFieldsFrameByRecord = new Dictionary(StringComparer.Ordinal); - private Task? _livePoll; private bool _disposed; public EveUnityCultMeshLiveProviderTransport( @@ -190,7 +185,6 @@ namespace GameCult.Eve.UnityScene public void PumpLiveEvents() { - CompleteLivePoll(); while (_liveDocuments.TryDequeue(out var document)) { if (document is EveEntitySoaViewDocument entityView) @@ -202,111 +196,6 @@ namespace GameCult.Eve.UnityScene else if (document is EveCommandReceiptDocument receipt) PublishReceipt(receipt); } - ScheduleLivePoll(); - } - - private void CompleteLivePoll() - { - if (_livePoll == null || !_livePoll.IsCompleted) - return; - var completed = _livePoll; - _livePoll = null; - var result = completed.GetAwaiter().GetResult(); - if (result.Error != null) - throw new InvalidOperationException("EveUnity live provider polling failed.", result.Error); - foreach (var entityView in result.EntityViews) - QueueEntityView(entityView); - foreach (var fields in result.Fields) - { - if (_lastFieldsFrameByRecord.TryGetValue(fields.RecordRef, out var frame) && fields.Document.FrameId <= frame) - continue; - _lastFieldsFrameByRecord[fields.RecordRef] = fields.Document.FrameId; - _liveDocuments.Enqueue(fields.Document); - } - foreach (var receipt in result.Receipts) - _liveDocuments.Enqueue(receipt); - } - - private void ScheduleLivePoll() - { - if (_disposed || _snapshot == null || _livePoll != null) - return; - var now = DateTime.UtcNow; - var pollEntityView = now >= _nextEntityViewPollUtc; - var pollFields = now >= _nextFieldsPollUtc; - var pollReceipts = _pendingCommandIds.Count > 0 && now >= _nextReceiptPollUtc; - if (!pollEntityView && !pollFields && !pollReceipts) - return; - if (pollEntityView) _nextEntityViewPollUtc = now.AddMilliseconds(250); - if (pollFields) _nextFieldsPollUtc = now.AddMilliseconds(250); - if (pollReceipts) _nextReceiptPollUtc = now.AddMilliseconds(250); - - var world = (pollEntityView || pollFields) - ? new EveUnitySceneSurfaceLowerer() - .Lower(CurrentSurfaceDocument.SurfaceDocument, CurrentSurfaceDocument.AdvertisedSurface) - .PlayableWorld - : null; - var entityViewRef = pollEntityView ? world?.EntityViewPointerId ?? "" : ""; - var fieldRefs = pollFields && world != null - ? world.FieldVolumes - .Select(field => field.DocumentRef) - .Where(value => !string.IsNullOrWhiteSpace(value)) - .Distinct(StringComparer.Ordinal) - .ToArray() - : Array.Empty(); - var receiptKeys = Array.Empty(); - if (pollReceipts) - { - var interaction = RequireWorldInteraction(); - if (!string.IsNullOrWhiteSpace(interaction.ReceiptRecordRef)) - receiptKeys = _pendingCommandIds - .Select(commandId => ChildRecordKey(interaction.ReceiptRecordRef, commandId)) - .ToArray(); - } - if (string.IsNullOrWhiteSpace(entityViewRef) && fieldRefs.Length == 0 && receiptKeys.Length == 0) - return; - _livePoll = PollLiveAsync(entityViewRef, fieldRefs, receiptKeys); - } - - private async Task PollLiveAsync( - string entityViewRef, - string[] fieldRefs, - string[] receiptKeys) - { - try - { - var entities = string.IsNullOrWhiteSpace(entityViewRef) - ? Array.Empty() - : (await _snapshot!.FetchDocumentsAsync( - recordKeys: new[] { entityViewRef }, - schemaIds: new[] { EveEntitySoaViewDocument.SchemaId }) - .ConfigureAwait(false)).ToArray(); - var fields = new List(); - foreach (var recordRef in fieldRefs) - { - var current = (await _snapshot!.FetchDocumentsAsync( - recordKeys: new[] { recordRef }, - schemaIds: new[] { EveFieldsSchemas.Splats }) - .ConfigureAwait(false)).FirstOrDefault(); - if (current != null) - fields.Add(new PolledFields(recordRef, current)); - } - var receipts = receiptKeys.Length == 0 - ? Array.Empty() - : (await _snapshot!.FetchDocumentsAsync( - recordKeys: receiptKeys, - schemaIds: new[] { EveCommandReceiptDocument.SchemaId }) - .ConfigureAwait(false)).ToArray(); - return new LivePollResult(entities, fields.ToArray(), receipts, null); - } - catch (Exception error) - { - return new LivePollResult( - Array.Empty(), - Array.Empty(), - Array.Empty(), - error); - } } private void QueueEntityView(EveEntitySoaViewDocument document) @@ -381,39 +270,6 @@ namespace GameCult.Eve.UnityScene _replicaShard = null; _pendingCommandIds.Clear(); _publishedReceiptIds.Clear(); - _lastFieldsFrameByRecord.Clear(); - } - - private sealed class LivePollResult - { - public LivePollResult( - EveEntitySoaViewDocument[] entityViews, - PolledFields[] fields, - EveCommandReceiptDocument[] receipts, - Exception? error) - { - EntityViews = entityViews; - Fields = fields; - Receipts = receipts; - Error = error; - } - - public EveEntitySoaViewDocument[] EntityViews { get; } - public PolledFields[] Fields { get; } - public EveCommandReceiptDocument[] Receipts { get; } - public Exception? Error { get; } - } - - private sealed class PolledFields - { - public PolledFields(string recordRef, EveFieldsSplatsDocument document) - { - RecordRef = recordRef; - Document = document; - } - - public string RecordRef { get; } - public EveFieldsSplatsDocument Document { get; } } public GameObject? ResolvePrefab(EveUnityPlayableWorldAssetBinding asset) @@ -717,40 +573,48 @@ namespace GameCult.Eve.UnityScene string entityBodyId = lowered.PlayableWorld == null ? "" : lowered.PlayableWorld.EntityBodyId; + var fieldRefs = lowered.PlayableWorld == null + ? Array.Empty() + : lowered.PlayableWorld.FieldVolumes + .Select(field => field.DocumentRef) + .Where(value => !string.IsNullOrWhiteSpace(value)) + .Distinct(StringComparer.Ordinal) + .ToArray(); + var liveRecordKeys = new List(fieldRefs); + var liveSchemaIds = new List(); + if (fieldRefs.Length > 0) + liveSchemaIds.Add(EveFieldsSchemas.Splats); if (!string.IsNullOrWhiteSpace(entityViewPointer)) { if (string.IsNullOrWhiteSpace(entityBodyId)) throw new InvalidOperationException( "The playable world advertises an entity-view pointer without its logical body id."); - _entitySubscriptions.SubscribeAsync( + liveRecordKeys.Insert(0, entityViewPointer); + liveRecordKeys.Insert(1, CultMeshBodyPublicationDocument.CreateLatestRecordKey(entityBodyId).Value); + liveSchemaIds.Insert(0, EveEntitySoaViewDocument.SchemaId); + liveSchemaIds.Insert(1, CultMeshBodyPublicationSchemaVersions.Publication); + } + if (liveRecordKeys.Count > 0) + { + var initial = _entitySubscriptions.SubscribeAsync( "eve-unity-entity-view", - recordKeys: new[] - { - entityViewPointer, - CultMeshBodyPublicationDocument.CreateLatestRecordKey( - entityBodyId).Value - }, - schemaIds: new[] - { - EveEntitySoaViewDocument.SchemaId, - CultMeshBodyPublicationSchemaVersions.Publication - }, + recordKeys: liveRecordKeys, + schemaIds: liveSchemaIds, consumerRuntimeId: _runtimeId, - bodyIds: new[] { entityBodyId }, - supportedBodyTransports: new[] + bodyIds: string.IsNullOrWhiteSpace(entityBodyId) ? null : new[] { entityBodyId }, + supportedBodyTransports: string.IsNullOrWhiteSpace(entityBodyId) ? null : new[] { CultMeshBodyTransportKind.SharedMemory.ToString(), CultMeshBodyTransportKind.Network.ToString() }) .GetAwaiter().GetResult(); - var current = _node!.Database.Cache.Get(new CultRecordKey(entityViewPointer)) as EveEntitySoaViewDocument - ?? _snapshot! - .FetchDocumentsAsync( - recordKeys: new[] { entityViewPointer }, - schemaIds: new[] { EveEntitySoaViewDocument.SchemaId }) - .GetAwaiter().GetResult().FirstOrDefault(); - if (current != null) - QueueEntityView(current); + foreach (var document in initial) + { + if (document is EveEntitySoaViewDocument current) + QueueEntityView(current); + else if (document is EveFieldsSplatsDocument fields) + _liveDocuments.Enqueue(fields); + } } _subscriptions.SubscribeAsync( "eve-unity-surface", @@ -785,7 +649,7 @@ namespace GameCult.Eve.UnityScene { if (change.Document is EveEntitySoaViewDocument entityView) QueueEntityView(entityView); - else if (change.Document is EveSurfaceDocument or EveCommandReceiptDocument) + else if (change.Document is EveSurfaceDocument or EveCommandReceiptDocument or EveFieldsSplatsDocument) _liveDocuments.Enqueue(change.Document); } diff --git a/packages/org.gamecult.eve.unity-scene/package.json b/packages/org.gamecult.eve.unity-scene/package.json index 322ad99..c6617e4 100644 --- a/packages/org.gamecult.eve.unity-scene/package.json +++ b/packages/org.gamecult.eve.unity-scene/package.json @@ -1,7 +1,7 @@ { "name": "org.gamecult.eve.unity-scene", "displayName": "Eve Unity Scene Lowering", - "version": "0.3.73", + "version": "0.3.74", "unity": "6000.0", "description": "Provider-agnostic Unity scene shell for gamecult.eve.surface.v1 interactive world surfaces.", "dependencies": {