From 8dc133d917cbcc341b259c3bcd68b3659419fa05 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 19 Jul 2026 06:01:42 +0100 Subject: [PATCH] Publish gameplay state through hot entity bodies --- Aetheria.State.Daemon/Program.cs | 166 ++++++++++++++---- ...AetheriaRuntimeDaemonGameSurfaceBuilder.cs | 2 +- .../AetheriaRuntimeDaemonSoaDocuments.cs | 1 + .../AetheriaRuntimeDaemonSoaFramePublisher.cs | 29 ++- .../AetheriaRuntimeDaemonTickRunner.cs | 6 +- 5 files changed, 151 insertions(+), 53 deletions(-) diff --git a/Aetheria.State.Daemon/Program.cs b/Aetheria.State.Daemon/Program.cs index 0a974b76e..358cb1b23 100644 --- a/Aetheria.State.Daemon/Program.cs +++ b/Aetheria.State.Daemon/Program.cs @@ -50,6 +50,11 @@ using var physicsPersistence = await AetheriaYmirPersistenceCoordinator.OpenAsyn latestFrame).ConfigureAwait(false); using var cultMeshRudpHost = StartClientCultMeshHost(node, options, () => latestFrame); using var clientSubscriptions = new CultNetDatabaseSubscriptionServer(cultMeshRudpHost, node.Database); +if (traceClientRudp) + clientSubscriptions.DemandChanged += demand => Console.WriteLine( + $"CultMesh body demand consumer={demand.ConsumerRuntimeId} subscription={demand.SubscriptionId} " + + $"active={demand.Active} sameMachine={demand.SameMachine} " + + $"bodies=[{string.Join(",", demand.BodyIds)}] transports=[{string.Join(",", demand.SupportedBodyTransports)}]"); using var bodyDemand = new CultMeshBodyDemandTracker(clientSubscriptions); using var soaPublisher = new AetheriaRuntimeDaemonSoaFramePublisher( node.Cache, @@ -59,23 +64,23 @@ using var clientPumpCancellation = new CancellationTokenSource(); var clientPump = RunClientCultMeshPumpAsync(cultMeshRudpHost, clientPumpCancellation.Token); var nextApiPublicationUtc = DateTimeOffset.UtcNow; var ingressState = new AetheriaDaemonIngressState(); -var firstTick = await TickAsync(node, options, worldPhysics, soaPublisher, latestFrame, ingressState, buildPublications: false).ConfigureAwait(false); +var hotState = new AetheriaHotEntityPublicationState(); +var firstTick = await TickAsync(node, options, worldPhysics, latestFrame, ingressState, buildPublications: false).ConfigureAwait(false); ThrowIfClientPumpFaulted(clientPump); latestFrame = firstTick.Frame; var firstPublication = PreparePublication( node.StatePath, options, - soaPublisher, firstTick, ingressState, physicsPersistence); await PublishPreparedDocumentsAsync( node, options, - soaPublisher, physicsPersistence, firstPublication, publishTopology: true).ConfigureAwait(false); +await PublishHotEntityStateAsync(node, soaPublisher, hotState, firstTick.Frame, ingressState.Catalog).ConfigureAwait(false); nextApiPublicationUtc = DateTimeOffset.UtcNow.Add(options.ApiPublicationInterval); Console.WriteLine($"Aetheria Verse daemon published frame {firstTick.Frame.FrameId}."); Console.WriteLine($"Aetheria client CultMesh endpoint: rudp://{options.ClientCultMeshAdvertiseHost}:{cultMeshRudpHost.LocalEndPoint.Port}"); @@ -111,9 +116,10 @@ while (!stopped.Task.IsCompleted) } var buildPublications = DateTimeOffset.UtcNow >= nextApiPublicationUtc; - var tick = await TickAsync(node, options, worldPhysics, soaPublisher, latestFrame, ingressState, buildPublications: false).ConfigureAwait(false); + var tick = await TickAsync(node, options, worldPhysics, latestFrame, ingressState, buildPublications: false).ConfigureAwait(false); ThrowIfClientPumpFaulted(clientPump); latestFrame = tick.Frame; + await PublishHotEntityStateAsync(node, soaPublisher, hotState, tick.Frame, ingressState.Catalog).ConfigureAwait(false); nextTickUtc += options.TickInterval; if (nextTickUtc < DateTimeOffset.UtcNow - options.TickInterval) nextTickUtc = DateTimeOffset.UtcNow; @@ -124,14 +130,12 @@ while (!stopped.Task.IsCompleted) var publication = PreparePublication( node.StatePath, options, - soaPublisher, tick, ingressState, physicsPersistence); publicationTask = PublishPreparedDocumentsAsync( node, options, - soaPublisher, physicsPersistence, publication, publishTopology: false); @@ -167,7 +171,6 @@ static async Task TickAsync( AetheriaStateNode node, AetheriaDaemonHostOptions options, IAetheriaRuntimeWorldPhysics worldPhysics, - AetheriaRuntimeDaemonSoaFramePublisher soaPublisher, AetheriaRuntimeDaemonFrameDocument? currentFrame, AetheriaDaemonIngressState ingressState, bool buildPublications) @@ -286,7 +289,6 @@ static async Task TickAsync( StarbridgeScenario = starbridgeScenario, StarbridgeSession = starbridgeSession, BuildPublications = buildPublications, - SoaFramePublisher = soaPublisher, OperationContext = new AetheriaRuntimeDaemonOperationContext { LoadoutTemplates = loadoutTemplates @@ -341,7 +343,7 @@ static async Task TickAsync( if (buildPublications) { - await PublishDaemonApiDocumentsAsync(node, options, soaPublisher, result, publishTopology: true).ConfigureAwait(false); + await PublishDaemonApiDocumentsAsync(node, options, result, publishTopology: true).ConfigureAwait(false); TracePhase("api-publication"); await PublishStateSurfacesAsync(node, options, result.Frame.PublishedAtUtc).ConfigureAwait(false); TracePhase("state-surfaces"); @@ -355,7 +357,6 @@ static async Task TickAsync( static AetheriaPreparedPublication PreparePublication( string statePath, AetheriaDaemonHostOptions options, - AetheriaRuntimeDaemonSoaFramePublisher soaPublisher, AetheriaRuntimeDaemonTickResult tick, AetheriaDaemonIngressState ingressState, AetheriaYmirPersistenceCoordinator physicsPersistence) @@ -381,8 +382,7 @@ static AetheriaPreparedPublication PreparePublication( StarbridgeScenario = ingressState.StarbridgeScenario, StarbridgeSession = ingressState.StarbridgeSession, RenderSettings = options.RenderSettings, - SimulationSettings = options.SimulationSettings, - SoaFramePublisher = soaPublisher + SimulationSettings = options.SimulationSettings }, frame.AccountedCommandIds?.Count ?? 0); return new AetheriaPreparedPublication(publication, physics); @@ -391,7 +391,6 @@ static AetheriaPreparedPublication PreparePublication( static async Task PublishPreparedDocumentsAsync( AetheriaStateNode node, AetheriaDaemonHostOptions options, - AetheriaRuntimeDaemonSoaFramePublisher soaPublisher, AetheriaYmirPersistenceCoordinator physicsPersistence, AetheriaPreparedPublication prepared, bool publishTopology) @@ -400,7 +399,6 @@ static async Task PublishPreparedDocumentsAsync( await PublishDaemonApiDocumentsAsync( node, options, - soaPublisher, prepared.Publication, publishTopology).ConfigureAwait(false); if (publishTopology) @@ -1510,10 +1508,44 @@ static bool TryGetDouble( double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out value); } +static async Task PublishHotEntityStateAsync( + AetheriaStateNode node, + AetheriaRuntimeDaemonSoaFramePublisher publisher, + AetheriaHotEntityPublicationState state, + AetheriaRuntimeDaemonFrameDocument frame, + AetheriaRuntimeCatalogSnapshot? catalog) +{ + using var hotFrame = publisher.BuildCurrentZoneEntities(frame, catalog); + if (hotFrame == null) + return; + + var publication = await publisher.PublishAsync(hotFrame).ConfigureAwait(false); + var layoutChanged = !state.Matches(publication.View); + var publishesRemoteGeneration = publication.Body.Representations.Any( + value => value.TransportKind == CultMeshBodyTransportKind.Network); + if (layoutChanged || publishesRemoteGeneration) + { + if (layoutChanged && string.Equals(Environment.GetEnvironmentVariable("AETHERIA_TRACE_CLIENT_RUDP"), "1", StringComparison.Ordinal)) + Console.WriteLine( + $"CultMesh entity layout changed sequence={publication.View.Sequence} bytes={MessagePackSerializer.Serialize(publication.View).Length} " + + $"identities={publication.View.Identities.Length} representations=[{string.Join(",", publication.Body.Representations.Select(value => value.TransportKind))}]"); + await node.MutableDocument( + CultMeshBodyPublicationDocument.CreateLatestRecordKey(publication.Body.BodyId)) + .ReplaceAsync(publication.Body) + .ConfigureAwait(false); + } + if (layoutChanged) + { + await node.MutableDocument(AetheriaRuntimeVerseRecordKeys.EveEntitySoaViewLatest) + .ReplaceAsync(publication.View) + .ConfigureAwait(false); + state.Set(publication.View); + } +} + static async Task PublishDaemonApiDocumentsAsync( AetheriaStateNode node, AetheriaDaemonHostOptions options, - AetheriaRuntimeDaemonSoaFramePublisher soaPublisher, AetheriaRuntimeDaemonTickResult result, bool publishTopology) { @@ -1567,32 +1599,21 @@ static async Task PublishDaemonApiDocumentsAsync( var activeMainMenuSurfaceId = string.IsNullOrWhiteSpace(mainMenuState?.ActiveSurfaceId) ? AetheriaRuntimeMainMenuCommands.RootSurfaceId : mainMenuState.ActiveSurfaceId; - var gameSurface = AetheriaRuntimeDaemonGameSurfaceBuilder.Build( - result.Frame, - result.Health ?? new AetheriaRuntimeDaemonHealthDocument(), - result.CommandBoundary ?? AetheriaRuntimeDaemonCommandBoundaryDocument.Create(options.DaemonId), - activeMainMenuSurfaceId, - inputCatalog); - await node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonGameSurface) - .ReplaceAsync(AetheriaRuntimeSurfaceDocuments.ToPortableSurface(gameSurface)) - .ConfigureAwait(false); - await PublishDaemonSectorMapSurfaceAsync(node, result.Frame, inputCatalog).ConfigureAwait(false); - // Keep low-bandwidth control state ahead of the bulk entity frame on the ordered - // subscription stream. Commands and beam feedback must not wait behind SoA delivery. - if (result.SoaFrame != null && result.SoaView != null && - string.Equals(result.SoaView.Schema, AetheriaRuntimeDaemonSchemas.SoaView, StringComparison.Ordinal)) + if (publishTopology) { - await node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonSoaViewLatest) - .ReplaceAsync(result.SoaView) - .ConfigureAwait(false); - var soaPublication = await soaPublisher.PublishAsync(result.SoaFrame).ConfigureAwait(false); - await node.MutableDocument( - CultMeshBodyPublicationDocument.CreateLatestRecordKey(soaPublication.Body.BodyId)) - .ReplaceAsync(soaPublication.Body) - .ConfigureAwait(false); - await node.MutableDocument(AetheriaRuntimeVerseRecordKeys.EveEntitySoaViewLatest) - .ReplaceAsync(soaPublication.View) + var gameSurface = AetheriaRuntimeDaemonGameSurfaceBuilder.Build( + result.Frame, + result.Health ?? new AetheriaRuntimeDaemonHealthDocument(), + result.CommandBoundary ?? AetheriaRuntimeDaemonCommandBoundaryDocument.Create(options.DaemonId), + activeMainMenuSurfaceId, + inputCatalog); + var portableGameSurface = AetheriaRuntimeSurfaceDocuments.ToPortableSurface(gameSurface); + if (string.Equals(Environment.GetEnvironmentVariable("AETHERIA_TRACE_CLIENT_RUDP"), "1", StringComparison.Ordinal)) + Console.WriteLine($"Eve game topology bytes={MessagePackSerializer.Serialize(portableGameSurface).Length}"); + await node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonGameSurface) + .ReplaceAsync(portableGameSurface) .ConfigureAwait(false); + await PublishDaemonSectorMapSurfaceAsync(node, result.Frame, inputCatalog).ConfigureAwait(false); } if (!publishTopology) return; @@ -3126,6 +3147,73 @@ internal sealed record AetheriaPreparedPublication( AetheriaRuntimeDaemonTickResult Publication, IReadOnlyList Physics); +internal sealed class AetheriaHotEntityPublicationState +{ + private EveEntitySoaViewDocument? _layout; + + public void Set(EveEntitySoaViewDocument layout) => _layout = layout; + + public bool Matches(EveEntitySoaViewDocument next) + { + var current = _layout; + if (current == null || current.ProviderId != next.ProviderId || + current.BodySchemaId != next.BodySchemaId || current.LayoutVersion != next.LayoutVersion || + current.ProducerEpoch != next.ProducerEpoch || current.Capacity != next.Capacity || + current.Buffers.Length != next.Buffers.Length || + current.Columns.Length != next.Columns.Length || current.DirtyRanges.Length != next.DirtyRanges.Length || + current.RenderGroups.Length != next.RenderGroups.Length || current.Identities.Length != next.Identities.Length) + return false; + + for (var i = 0; i < current.Buffers.Length; i++) + { + var a = current.Buffers[i]; + var b = next.Buffers[i]; + if (a.BufferId != b.BufferId || a.ByteOffset != b.ByteOffset || a.ByteLength != b.ByteLength) + return false; + } + for (var i = 0; i < current.Columns.Length; i++) + { + var a = current.Columns[i]; + var b = next.Columns[i]; + if (a.ColumnId != b.ColumnId || a.Semantic != b.Semantic || a.BufferId != b.BufferId || + a.ScalarType != b.ScalarType || a.ByteOffset != b.ByteOffset || + a.ElementStride != b.ElementStride || a.ElementCount != b.ElementCount || + a.Unit != b.Unit || a.CoordinateSpace != b.CoordinateSpace) + return false; + } + for (var i = 0; i < current.DirtyRanges.Length; i++) + { + var a = current.DirtyRanges[i]; + var b = next.DirtyRanges[i]; + if (a.ColumnId != b.ColumnId || a.StartIndex != b.StartIndex || a.Count != b.Count) + return false; + } + for (var i = 0; i < current.RenderGroups.Length; i++) + { + var a = current.RenderGroups[i]; + var b = next.RenderGroups[i]; + if (a.GroupId != b.GroupId || a.MeshAssetRef != b.MeshAssetRef || + a.MaterialAssetRef != b.MaterialAssetRef || a.SubMeshIndex != b.SubMeshIndex || + a.Layer != b.Layer || a.InstanceCount != b.InstanceCount || a.DefaultScale != b.DefaultScale || + a.BoundsCenterX != b.BoundsCenterX || a.BoundsCenterY != b.BoundsCenterY || + a.BoundsCenterZ != b.BoundsCenterZ || a.BoundsSizeX != b.BoundsSizeX || + a.BoundsSizeY != b.BoundsSizeY || a.BoundsSizeZ != b.BoundsSizeZ || + a.ShadowMode != b.ShadowMode || a.ReceiveShadows != b.ReceiveShadows || a.Lod != b.Lod) + return false; + } + for (var i = 0; i < current.Identities.Length; i++) + { + var a = current.Identities[i]; + var b = next.Identities[i]; + if (a.Index != b.Index || a.EntityId != b.EntityId || a.EntityKind != b.EntityKind || + a.Label != b.Label || a.Faction != b.Faction || a.Selectable != b.Selectable || + a.Controllable != b.Controllable || a.AssetRef != b.AssetRef) + return false; + } + return true; + } +} + internal sealed class AetheriaDaemonIngressState { public int ObservedEveCommandCount { get; set; } = -1; diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonGameSurfaceBuilder.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonGameSurfaceBuilder.cs index 33c7aff9f..0d09e707a 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonGameSurfaceBuilder.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonGameSurfaceBuilder.cs @@ -1083,7 +1083,7 @@ namespace GameCult.Aetheria.State.Verse ("directionMode", "source-forward.v1"), ("renderChannel", "world.effects"), ("activationActionId", "pilot.scoop"), - ("power", FormatNumber(player.TractorPower)), + ("powerStateSemantic", AetheriaRuntimeDaemonSoaColumnKinds.BeamPower), ("activationThreshold", FormatNumber(AetheriaRuntimeTractorMechanics.ActivationThreshold)), ("radius", FormatNumber(AetheriaRuntimeTractorMechanics.Radius)), ("maximumDistance", FormatNumber(AetheriaRuntimeTractorMechanics.Distance)) diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonSoaDocuments.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonSoaDocuments.cs index c159bc45d..9ffad13ad 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonSoaDocuments.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonSoaDocuments.cs @@ -42,6 +42,7 @@ namespace GameCult.Aetheria.State.Verse public const string RenderVisibility = "render.visibility"; public const string RenderLod = "render.lod"; public const string CargoQuantity = "inventory.cargo.quantity"; + public const string BeamPower = "effect.beam.power"; } public static class AetheriaRuntimeDaemonRenderShadowModes diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonSoaFramePublisher.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonSoaFramePublisher.cs index adaaf0567..29cc1d877 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonSoaFramePublisher.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonSoaFramePublisher.cs @@ -69,7 +69,7 @@ namespace GameCult.Aetheria.State.Verse public const string BodyId = "eve:entity-soa:aetheria.daemon:pilot"; public const string ProducerId = "aetheria.daemon"; public const string BodySchemaId = "gamecult.eve.entity_soa.body.v2"; - public const int LayoutVersion = 2; + public const int LayoutVersion = 3; private const int Capacity = 4096; private const int EntityRenderGroupId = 1; private const int FloatStride = 4; @@ -366,7 +366,13 @@ namespace GameCult.Aetheria.State.Verse var maxX = positions.Max(position => (float)position.PositionX); var maxY = positions.Max(position => (float)position.PositionY); var maxZ = positions.Max(position => (float)position.PositionZ); - const float padding = 16.0f; + const float boundsCell = 1024.0f; + var boundsMinX = MathF.Floor((minX - 16.0f) / boundsCell) * boundsCell; + var boundsMinY = MathF.Floor((minY - 16.0f) / boundsCell) * boundsCell; + var boundsMinZ = MathF.Floor((minZ - 16.0f) / boundsCell) * boundsCell; + var boundsMaxX = MathF.Ceiling((maxX + 16.0f) / boundsCell) * boundsCell; + var boundsMaxY = MathF.Ceiling((maxY + 16.0f) / boundsCell) * boundsCell; + var boundsMaxZ = MathF.Ceiling((maxZ + 16.0f) / boundsCell) * boundsCell; return new[] { @@ -391,12 +397,12 @@ namespace GameCult.Aetheria.State.Verse DisplayName = "Daemon current-zone entities", InstanceCount = entities.Count + pickups.Count + payloads.Count + celestialBodies.Count + asteroidInstances.Count, - BoundsCenterX = (minX + maxX) * 0.5f, - BoundsCenterY = (minY + maxY) * 0.5f, - BoundsCenterZ = (minZ + maxZ) * 0.5f, - BoundsSizeX = Math.Max(maxX - minX + padding, padding), - BoundsSizeY = Math.Max(maxY - minY + padding, padding), - BoundsSizeZ = Math.Max(maxZ - minZ + padding, padding), + BoundsCenterX = (boundsMinX + boundsMaxX) * 0.5f, + BoundsCenterY = (boundsMinY + boundsMaxY) * 0.5f, + BoundsCenterZ = (boundsMinZ + boundsMaxZ) * 0.5f, + BoundsSizeX = Math.Max(boundsMaxX - boundsMinX, boundsCell), + BoundsSizeY = Math.Max(boundsMaxY - boundsMinY, boundsCell), + BoundsSizeZ = Math.Max(boundsMaxZ - boundsMinZ, boundsCell), ShadowMode = AetheriaRuntimeDaemonRenderShadowModes.On, ReceiveShadows = true, DefaultScale = 1.0f, @@ -415,6 +421,7 @@ namespace GameCult.Aetheria.State.Verse var entity = entities[index]; WriteInt32(bytes, layout.EntityIndex + index * IntStride, entity.EntityIndex); WriteInt32(bytes, layout.CargoQuantity + index * IntStride, AetheriaRuntimeCargoCapacityQueries.Quantity(entity)); + WriteFloat(bytes, layout.BeamPower, index, entity.TractorPower); WriteFloat3(bytes, layout.Position, index, entity.PositionX, entity.PositionY, entity.PositionZ); WriteFloat(bytes, layout.RotationRadians, index, Math.Atan2(entity.DirectionX, entity.DirectionY)); WriteFloat3(bytes, layout.Velocity, index, entity.VelocityX, 0.0, entity.VelocityY); @@ -767,6 +774,7 @@ namespace GameCult.Aetheria.State.Verse private EntityHotSlabLayout( long entityIndex, long cargoQuantity, + long beamPower, long position, long rotationRadians, long velocity, @@ -781,6 +789,7 @@ namespace GameCult.Aetheria.State.Verse { EntityIndex = entityIndex; CargoQuantity = cargoQuantity; + BeamPower = beamPower; Position = position; RotationRadians = rotationRadians; Velocity = velocity; @@ -796,6 +805,7 @@ namespace GameCult.Aetheria.State.Verse public long EntityIndex { get; } public long CargoQuantity { get; } + public long BeamPower { get; } public long Position { get; } public long RotationRadians { get; } public long Velocity { get; } @@ -814,6 +824,7 @@ namespace GameCult.Aetheria.State.Verse var offset = 0L; var entityIndex = Take(ref offset, count, IntStride); var cargoQuantity = Take(ref offset, count, IntStride); + var beamPower = Take(ref offset, count, FloatStride); var position = Take(ref offset, count, Float3Stride); var rotationRadians = Take(ref offset, count, FloatStride); var velocity = Take(ref offset, count, Float3Stride); @@ -828,6 +839,7 @@ namespace GameCult.Aetheria.State.Verse return new EntityHotSlabLayout( entityIndex, cargoQuantity, + beamPower, position, rotationRadians, velocity, @@ -847,6 +859,7 @@ namespace GameCult.Aetheria.State.Verse { Column("entity-index", AetheriaRuntimeDaemonSoaColumnKinds.EntityIndex, "int32", EntityIndex, IntStride, count, "index", "world"), Column("cargo-quantity", AetheriaRuntimeDaemonSoaColumnKinds.CargoQuantity, "int32", CargoQuantity, IntStride, count, "items", "entity"), + Column("beam-power", AetheriaRuntimeDaemonSoaColumnKinds.BeamPower, "float32", BeamPower, FloatStride, count, "normalized", "entity"), Column("position", AetheriaRuntimeDaemonSoaColumnKinds.Position, "float3", Position, Float3Stride, count, "world_units", "world"), Column("rotation-radians", AetheriaRuntimeDaemonSoaColumnKinds.RotationRadians, "float32", RotationRadians, FloatStride, count, "radians", "world"), Column("velocity", AetheriaRuntimeDaemonSoaColumnKinds.Velocity, "float3", Velocity, Float3Stride, count, "world_units_per_second", "world"), diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonTickRunner.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonTickRunner.cs index e8a3210d5..3e14c5b38 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonTickRunner.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonTickRunner.cs @@ -40,7 +40,6 @@ namespace GameCult.Aetheria.State.Verse public int SimulationStepCount { get; set; } = 1; public bool StopCompressedSimulationOnAttention { get; set; } public bool BuildPublications { get; set; } = true; - public AetheriaRuntimeDaemonSoaFramePublisher? SoaFramePublisher { get; set; } } public sealed class AetheriaRuntimeDaemonTickResult @@ -373,13 +372,10 @@ namespace GameCult.Aetheria.State.Verse int simulationStepsExecuted = 0, AetheriaRuntimeSimulationInterruption? attentionInterruption = null) { - var soaPublisher = options.SoaFramePublisher ?? - throw new InvalidOperationException("The daemon-lifetime Aetheria SoA publisher is required."); var catalog = options.Catalog ?? new AetheriaRuntimeCatalogSnapshot( Array.Empty(), Array.Empty(), Array.Empty()); - var soaFrame = soaPublisher.BuildCurrentZoneEntities(frame, catalog); var commandBoundary = AetheriaRuntimeDaemonCommandBoundaryDocument.Create(options.DaemonId); var providerAdvertisement = AetheriaRuntimeDaemonProviderAdvertisementDocument.Create( stateFilePath, @@ -429,7 +425,7 @@ namespace GameCult.Aetheria.State.Verse operationResult.Run, operationResult, frame, - soaFrame, + soaFrame: null, providerAdvertisement, health, commandBoundary,