Resolve live bodies through negotiated sessions
This commit is contained in:
parent
c39bcd0cec
commit
6aeb416cf1
3 changed files with 12 additions and 69 deletions
|
|
@ -35,7 +35,6 @@ namespace GameCult.Eve.UnityScene
|
|||
typeof(EveEntitySoaViewDocument),
|
||||
typeof(EveFieldsSplatsDocument),
|
||||
typeof(CultMeshBodyPublicationDocument),
|
||||
typeof(CultMeshNetworkBodyDocument),
|
||||
typeof(CultMeshCdnArtifactManifest),
|
||||
typeof(CultMeshContentTransferStateDocument)
|
||||
};
|
||||
|
|
@ -501,13 +500,20 @@ namespace GameCult.Eve.UnityScene
|
|||
private CultMeshBodyPublicationResolver CreateBodyResolver()
|
||||
{
|
||||
var producerIds = RequireAdvertisedBodyProducerIds(_advertisement);
|
||||
if (string.IsNullOrWhiteSpace(_advertisement!.ServiceId))
|
||||
throw new InvalidOperationException(
|
||||
$"Eve provider '{_advertisement.ProviderId}' has no service-instance identity for body transport.");
|
||||
var mappedRoot = Path.GetDirectoryName(_replicaPath) ?? ".";
|
||||
var networkBodies = _meshClient!.BodyProvider(
|
||||
_advertisement.ProviderId,
|
||||
_advertisement.ServiceId,
|
||||
new CultMeshSessionBodyProviderOptions { ResponseTimeout = TimeSpan.FromSeconds(2) });
|
||||
return new CultMeshBodyPublicationResolver(new CultMeshBodyTransportService(
|
||||
new ICultMeshBodyTransportAdapter[]
|
||||
{
|
||||
new CultMeshSharedMemoryBodyAdapter(),
|
||||
new CultMeshMappedBodyAdapter(mappedRoot),
|
||||
new CultMeshNetworkBodyAdapter(ReadNetworkBody)
|
||||
new CultMeshNetworkBodyAdapter(networkBodies)
|
||||
},
|
||||
(candidateProducerId, _) => IsAdvertisedBodyProducer(producerIds, candidateProducerId)));
|
||||
}
|
||||
|
|
@ -532,47 +538,6 @@ namespace GameCult.Eve.UnityScene
|
|||
return producerIds;
|
||||
}
|
||||
|
||||
private byte[] ReadNetworkBody(CultMeshBodyDescriptor descriptor)
|
||||
{
|
||||
var binding = _snapshot!
|
||||
.FetchDocumentsAsync<CultMeshNetworkBodyDocument>(
|
||||
recordKeys: new[] { CultMeshNetworkBodyDocument.CreateRecordKey(descriptor.CapabilityToken).Value },
|
||||
schemaIds: new[] { CultMeshBodyPublicationSchemaVersions.NetworkBody })
|
||||
.GetAwaiter().GetResult().SingleOrDefault()
|
||||
?? throw new FileNotFoundException("Provider network body capability is missing.", descriptor.CapabilityToken);
|
||||
var manifest = _snapshot
|
||||
.FetchDocumentsAsync<CultMeshCdnArtifactManifest>(
|
||||
recordKeys: new[] { binding.ManifestRecordKey },
|
||||
schemaIds: new[] { CultMeshCdnSchemaVersions.ArtifactManifest })
|
||||
.GetAwaiter().GetResult().SingleOrDefault()
|
||||
?? throw new FileNotFoundException("Provider network body manifest is missing.", binding.ManifestRecordKey);
|
||||
ValidateNetworkBody(descriptor, binding, manifest);
|
||||
var path = ContentTransfer().FetchAsync(manifest).GetAwaiter().GetResult();
|
||||
return File.ReadAllBytes(path);
|
||||
}
|
||||
|
||||
private static void ValidateNetworkBody(
|
||||
CultMeshBodyDescriptor descriptor,
|
||||
CultMeshNetworkBodyDocument binding,
|
||||
CultMeshCdnArtifactManifest manifest)
|
||||
{
|
||||
if (!string.Equals(binding.CapabilityToken, descriptor.CapabilityToken, StringComparison.Ordinal) ||
|
||||
!string.Equals(binding.BodyId, descriptor.BodyId, StringComparison.Ordinal) ||
|
||||
!string.Equals(binding.SchemaId, descriptor.SchemaId, StringComparison.Ordinal) ||
|
||||
binding.LayoutVersion != descriptor.LayoutVersion || binding.ByteSize != descriptor.ByteSize ||
|
||||
binding.Capacity != descriptor.Capacity || binding.ProducerEpoch != descriptor.ProducerEpoch ||
|
||||
binding.Sequence != descriptor.Sequence || binding.Synchronization != descriptor.Synchronization ||
|
||||
binding.LeaseExpiresAtUnixMs != descriptor.LeaseExpiresAtUnixMs ||
|
||||
!string.Equals(binding.SemanticHash, descriptor.SemanticHash, StringComparison.Ordinal))
|
||||
throw new InvalidDataException("CultMesh network body descriptor disagrees with its capability binding.");
|
||||
if (!string.Equals(CultMeshCdnArtifactManifest.CreateRecordKey(manifest).Value,
|
||||
binding.ManifestRecordKey, StringComparison.Ordinal) ||
|
||||
manifest.SizeBytes != binding.ByteSize ||
|
||||
!string.Equals(NormalizeContentHash(manifest.ContentHash),
|
||||
binding.SemanticHash, StringComparison.Ordinal))
|
||||
throw new InvalidDataException("CultMesh network body manifest disagrees with its capability binding.");
|
||||
}
|
||||
|
||||
private static string NormalizeContentHash(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
|
|
|
|||
|
|
@ -200,36 +200,14 @@ namespace GameCult.Eve.UnityScene.Tests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public async System.Threading.Tasks.Task LiveTransportValidatesNetworkBodyControlDocumentsWithoutSnapshotChunks()
|
||||
public void LiveTransportDoesNotRegisterBodyBytesAsSnapshotDocuments()
|
||||
{
|
||||
var view = EntityLeaseDocument();
|
||||
var bytes = Enumerable.Range(0, 32).Select(value => (byte)value).ToArray();
|
||||
var source = new CultCache();
|
||||
var generation = new CultMeshBodyGeneration
|
||||
{
|
||||
BodyId = view.Buffers[0].BufferId,
|
||||
ProducerId = view.ProviderId,
|
||||
SchemaId = view.BodySchemaId,
|
||||
LayoutVersion = view.LayoutVersion,
|
||||
Capacity = view.Capacity,
|
||||
ProducerEpoch = view.ProducerEpoch,
|
||||
Sequence = view.Sequence,
|
||||
Synchronization = CultMeshBodySynchronization.TripleBuffer,
|
||||
LeaseExpiresAtUnixMs = DateTimeOffset.UtcNow.AddMinutes(1).ToUnixTimeMilliseconds()
|
||||
};
|
||||
var descriptor = await new CultMeshNetworkBodyPublisher(source, _ => true).PublishAsync(generation, bytes);
|
||||
var binding = source.Get<CultMeshNetworkBodyDocument>(
|
||||
CultMeshNetworkBodyDocument.CreateRecordKey(descriptor.CapabilityToken))!;
|
||||
var manifest = source.Get<CultMeshCdnArtifactManifest>(new CultRecordKey(binding.ManifestRecordKey))!;
|
||||
var method = typeof(EveUnityCultMeshLiveProviderTransport)
|
||||
.GetMethod("ValidateNetworkBody", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||
|
||||
method.Invoke(null, new object[] { descriptor, binding, manifest });
|
||||
var wireTypes = (Type[])typeof(EveUnityCultMeshLiveProviderTransport)
|
||||
.GetField("WireDocumentTypes", BindingFlags.NonPublic | BindingFlags.Static)!
|
||||
.GetValue(null)!;
|
||||
|
||||
Assert.That(wireTypes.Any(type => type == typeof(CultMeshCdnArtifactChunk)), Is.False);
|
||||
Assert.That(wireTypes.Any(type => type.Name == "CultMeshNetworkBodyDocument"), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "org.gamecult.eve.unity-scene",
|
||||
"displayName": "Eve Unity Scene Lowering",
|
||||
"version": "0.3.88",
|
||||
"version": "0.3.89",
|
||||
"unity": "6000.0",
|
||||
"description": "Provider-agnostic Unity scene shell for gamecult.eve.surface.v1 interactive world surfaces.",
|
||||
"dependencies": {
|
||||
"org.gamecult.cultlib": "1.0.30",
|
||||
"org.gamecult.cultlib": "1.0.31",
|
||||
"org.gamecult.eve.plugin-fields": "0.2.3",
|
||||
"org.gamecult.eve.surface": "0.2.4",
|
||||
"com.unity.mathematics": "1.3.2",
|
||||
|
|
|
|||
Reference in a new issue