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 be4862b..1b06585 100644 --- a/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshLiveProviderTransport.cs +++ b/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshLiveProviderTransport.cs @@ -4,6 +4,8 @@ using System.IO; using System.Linq; using System.Security.Cryptography; using System.Collections.Concurrent; +using System.Threading; +using System.Threading.Tasks; using GameCult.Caching; using GameCult.Caching.MessagePack; using GameCult.Eve.Surface; @@ -348,13 +350,20 @@ namespace GameCult.Eve.UnityScene { var bytes = new byte[checked((int)manifest.SizeBytes)]; var references = manifest.Chunks.OrderBy(chunk => chunk.Offset).ToArray(); - for (var index = 0; index < references.Length; index += 2) + var batches = references.Select((reference, index) => new { reference, index }) + .GroupBy(value => value.index / 2) + .Select(group => group.Select(value => value.reference).ToArray()) + .ToArray(); + using var concurrency = new SemaphoreSlim(2, 2); + var downloads = batches.Select(async batch => { - var batch = references.Skip(index).Take(2).ToArray(); - var chunks = batch.Select(reference => _mesh - .ReadAsync(_endpointId, reference.RecordKey) - .GetAwaiter().GetResult()) - .ToArray(); + await concurrency.WaitAsync().ConfigureAwait(false); + try + { + var chunks = await _mesh.ReadManyAsync( + _endpointId, + batch.Select(reference => reference.RecordKey).ToArray()) + .ConfigureAwait(false); foreach (var reference in batch) { var chunk = chunks.FirstOrDefault(candidate => @@ -365,7 +374,13 @@ namespace GameCult.Eve.UnityScene throw new InvalidDataException($"Provider asset chunk '{reference.RecordKey}' size did not match its manifest."); Buffer.BlockCopy(chunk.Payload, 0, bytes, checked((int)reference.Offset), reference.SizeBytes); } - } + } + finally + { + concurrency.Release(); + } + }).ToArray(); + Task.WhenAll(downloads).GetAwaiter().GetResult(); return bytes; } diff --git a/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshPlayableWorldProvider.cs b/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshPlayableWorldProvider.cs index c606e19..1373276 100644 --- a/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshPlayableWorldProvider.cs +++ b/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshPlayableWorldProvider.cs @@ -92,6 +92,8 @@ namespace GameCult.Eve.UnityScene Bridge.Refresh(); else Bridge.Connect(); + _transport?.PumpLiveEvents(); + DrainEntityViews(); } public void Submit(EveSurfaceCommandRequest request) @@ -134,6 +136,11 @@ namespace GameCult.Eve.UnityScene { CompleteDiscoveryOnMainThread(); _transport?.PumpLiveEvents(); + DrainEntityViews(); + } + + private void DrainEntityViews() + { EveEntitySoaViewDocument? latest = null; while (_pendingEntityViews.TryDequeue(out var next)) latest = next; if (latest == null) return; diff --git a/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshProviderDiscovery.cs b/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshProviderDiscovery.cs index c08809e..8354c2d 100644 --- a/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshProviderDiscovery.cs +++ b/packages/org.gamecult.eve.unity-scene/Runtime/CultMesh/EveUnityCultMeshProviderDiscovery.cs @@ -41,9 +41,9 @@ namespace GameCult.Eve.UnityScene { if (string.IsNullOrWhiteSpace(rendezvousEndpoint)) throw new ArgumentException("Rendezvous endpoint must be non-empty.", nameof(rendezvousEndpoint)); - var endpointId = !string.IsNullOrWhiteSpace(verseId) ? verseId : providerId; - if (string.IsNullOrWhiteSpace(endpointId)) - throw new ArgumentException("Provider or Verse identity must be supplied for CultMesh discovery.", nameof(providerId)); + var endpointId = !string.IsNullOrWhiteSpace(verseId) + ? verseId + : !string.IsNullOrWhiteSpace(providerId) ? providerId : "eve.providers"; var mesh = new CultMeshClient(new CultMeshClientOptions {