feat(streaming): shadow-publish flat collision assets

Carry one immutable prepared collision closure with each accepted near-tier generation and install graph plus flat views through the same retained publication receipt. Apply the same strict package-only rule to live entities, add exact sampled graph-authoritative comparison artifacts and lifecycle counters, and prove cancellation, demotion, rehydrate, revisit, teardown, reconnect, and the nine-stop route with 14,064 zero-mismatch samples.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-25 16:38:54 +02:00
parent f7ff9f4eea
commit d9446030e6
32 changed files with 2777 additions and 92 deletions

View file

@ -30,6 +30,7 @@ internal sealed record ContentEffectsAudioResult(
MagicCatalog MagicCatalog,
IAnimationLoader AnimationLoader,
LiveEntityCollisionBuilder CollisionBuilder,
LiveCollisionAssetPublisher CollisionAssets,
EmitterDescRegistry EmitterRegistry,
ParticleSystem ParticleSystem,
ParticleHookSink ParticleSink,
@ -95,6 +96,9 @@ internal interface IContentEffectsAudioCompositionFactory
IDatReaderWriter dats,
IAnimationLoader animationLoader,
bool dumpMotionEnabled);
LiveCollisionAssetPublisher CreateLiveCollisionAssetPublisher(
PhysicsDataCache physicsData,
IPreparedAssetSource preparedAssets);
EmitterDescRegistry CreateEmitterRegistry(IDatReaderWriter dats);
ParticleSystem CreateParticleSystem(EmitterDescRegistry emitters);
ParticleHookSink CreateParticleSink(
@ -165,6 +169,15 @@ internal sealed class RetailContentEffectsAudioCompositionFactory
animationLoader,
dumpMotionEnabled));
public LiveCollisionAssetPublisher CreateLiveCollisionAssetPublisher(
PhysicsDataCache physicsData,
IPreparedAssetSource preparedAssets) =>
new(
physicsData,
preparedAssets as IPreparedCollisionSource
?? throw new NotSupportedException(
"Production prepared assets must expose collision data."));
public EmitterDescRegistry CreateEmitterRegistry(IDatReaderWriter dats) =>
new(dats);
@ -332,6 +345,10 @@ internal sealed class ContentEffectsAudioCompositionPhase :
_dependencies.DumpMotionEnabled);
_publication.PublishLiveEntityCollisionBuilder(collision);
Fault(ContentEffectsAudioCompositionPoint.CollisionBuilderPublished);
LiveCollisionAssetPublisher collisionAssets =
_factory.CreateLiveCollisionAssetPublisher(
_dependencies.PhysicsDataCache,
preparedAssets);
EmitterDescRegistry emitters = _factory.CreateEmitterRegistry(dats);
_publication.PublishEmitterRegistry(emitters);
@ -403,6 +420,7 @@ internal sealed class ContentEffectsAudioCompositionPhase :
magic,
animations,
collision,
collisionAssets,
emitters,
particles,
particleSink,

View file

@ -441,6 +441,9 @@ internal sealed class FrameRootCompositionPhase
d.FrameProfiler,
content.Dats,
foundation.Residency,
d.PhysicsEngine.DataCache
?? throw new InvalidOperationException(
"Lifecycle automation requires the canonical physics cache."),
currentRenderSceneOracle,
renderSceneShadowComparison,
renderFrameProduct);

View file

@ -12,6 +12,7 @@ using AcDream.App.Settings;
using AcDream.App.Streaming;
using AcDream.App.Update;
using AcDream.App.World;
using AcDream.Content;
using AcDream.Core.Combat;
using AcDream.Core.Items;
using AcDream.Core.Chat;
@ -252,11 +253,16 @@ internal sealed class SessionPlayerCompositionPhase
$"(window={2 * farRadius + 1}x{2 * farRadius + 1})");
Fault(SessionPlayerCompositionPoint.StreamingRadiiResolved);
IPreparedCollisionSource preparedCollisions =
content.PreparedAssets as IPreparedCollisionSource ??
throw new NotSupportedException(
"Production prepared assets must expose the matching " +
"prepared-collision catalog.");
var landblockBuildFactory = new LandblockBuildFactory(
content.Dats,
preparedCollisions,
d.DatLock,
world.TerrainBuild.HeightTable,
d.PhysicsDataCache,
d.Options.DumpSceneryZ);
var streamerLease = scope.Acquire(
"landblock streamer",
@ -399,7 +405,7 @@ internal sealed class SessionPlayerCompositionPhase
d.Options,
content.Dats,
live.LiveEntities,
d.PhysicsDataCache,
content.CollisionAssets,
content.AnimationLoader,
live.EntitySpawnAdapter,
world.Foundation.TextureCache,
@ -689,7 +695,7 @@ internal sealed class SessionPlayerCompositionPhase
d.MotionBindings,
content.Dats,
d.DatLock,
d.PhysicsDataCache,
content.CollisionAssets,
d.AnimatedEntities,
localPlayerAnimation,
localPlayerShadow,