Publish prepared GfxObj, Setup, CellStruct, and EnvCell collision records without retaining their parsed DAT BSP, polygon, vertex, or shape graphs. Strip temporary physics bundles at stable world commit, keep graph traversal only as an explicit test/tooling oracle, and report graph residency from actual retained fields. Validated by 115 focused collision/streaming tests, a zero-warning Release build, and 8,413 passing Release tests with five pre-existing skips. Co-authored-by: Codex <codex@openai.com>
70 lines
2.3 KiB
C#
70 lines
2.3 KiB
C#
using AcDream.Content;
|
|
using AcDream.Core.Physics;
|
|
using DatReaderWriter.DBObjs;
|
|
|
|
namespace AcDream.App.Physics;
|
|
|
|
/// <summary>
|
|
/// Publishes package-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. The
|
|
/// production cache consumes source metadata transiently and never retains its
|
|
/// parsed collision graph.
|
|
/// </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.");
|
|
}
|
|
}
|