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:
parent
f7ff9f4eea
commit
d9446030e6
32 changed files with 2777 additions and 92 deletions
68
src/AcDream.App/Physics/LiveCollisionAssetPublisher.cs
Normal file
68
src/AcDream.App/Physics/LiveCollisionAssetPublisher.cs
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
using AcDream.Content;
|
||||
using AcDream.Core.Physics;
|
||||
using DatReaderWriter.DBObjs;
|
||||
|
||||
namespace AcDream.App.Physics;
|
||||
|
||||
/// <summary>
|
||||
/// Publishes the graph and prepared collision views for DAT objects discovered
|
||||
/// through the live-object path. Streamed statics carry their prepared closure
|
||||
/// on <c>LandblockBuild</c>; live CreateObject/appearance data arrives outside
|
||||
/// that transaction and therefore uses this matching strict publisher.
|
||||
/// </summary>
|
||||
internal sealed class LiveCollisionAssetPublisher
|
||||
{
|
||||
private readonly PhysicsDataCache _cache;
|
||||
private readonly IPreparedCollisionSource _source;
|
||||
|
||||
public LiveCollisionAssetPublisher(
|
||||
PhysicsDataCache cache,
|
||||
IPreparedCollisionSource source)
|
||||
{
|
||||
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
|
||||
_source = source ?? throw new ArgumentNullException(nameof(source));
|
||||
}
|
||||
|
||||
public void CacheGfxObj(uint id, GfxObj gfxObj)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(gfxObj);
|
||||
FlatGfxObjCollisionAsset? prepared =
|
||||
_cache.GetFlatGfxObj(id) is not null
|
||||
? null
|
||||
: Require(
|
||||
_source.ReadGfxObjCollision(id),
|
||||
"GfxObj collision",
|
||||
id);
|
||||
_cache.CacheGfxObj(id, gfxObj, prepared);
|
||||
}
|
||||
|
||||
public void CacheSetup(uint id, Setup setup)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(setup);
|
||||
FlatSetupCollision? prepared =
|
||||
_cache.GetFlatSetup(id) is not null
|
||||
? null
|
||||
: Require(
|
||||
_source.ReadSetupCollision(id),
|
||||
"Setup collision",
|
||||
id);
|
||||
_cache.CacheSetup(id, setup, prepared);
|
||||
}
|
||||
|
||||
private static T Require<T>(
|
||||
PreparedCollisionReadResult<T> result,
|
||||
string kind,
|
||||
uint id)
|
||||
where T : class
|
||||
{
|
||||
if (result.Status == PreparedAssetReadStatus.Loaded &&
|
||||
result.Data is not null)
|
||||
{
|
||||
return result.Data;
|
||||
}
|
||||
|
||||
throw new InvalidDataException(
|
||||
$"{kind} 0x{id:X8} is {result.Status}. " +
|
||||
"Live collision cannot publish only one representation.");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue