fix(physics): seal collision generations before activation
This commit is contained in:
parent
be94bc9b06
commit
d94145e6b8
15 changed files with 1556 additions and 410 deletions
|
|
@ -18,6 +18,77 @@ internal interface IHeadlessCollisionNeighborhood
|
|||
bool IsReady(uint fullCellId);
|
||||
}
|
||||
|
||||
internal static class HeadlessCollisionGenerationTransaction
|
||||
{
|
||||
internal static RuntimeCollisionGenerationCommit Execute(
|
||||
RuntimePhysicsState physics,
|
||||
uint landblockId,
|
||||
Action<RuntimeCollisionAdmission>? afterAdmission,
|
||||
Action<RuntimeCollisionAdmission,
|
||||
PreparedLandblockCollisionGeneration> stage)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(physics);
|
||||
ArgumentNullException.ThrowIfNull(stage);
|
||||
|
||||
RuntimeCollisionAdmission admission =
|
||||
physics.BeginCollisionAdmission(landblockId);
|
||||
PreparedLandblockCollisionGeneration? prepared = null;
|
||||
bool committed = false;
|
||||
try
|
||||
{
|
||||
// This hook exists so the exact post-admission/pre-prepare failure
|
||||
// boundary remains covered. Production does not install one.
|
||||
afterAdmission?.Invoke(admission);
|
||||
prepared = physics.PrepareCollisionGeneration(admission);
|
||||
stage(admission, prepared);
|
||||
|
||||
RuntimeCollisionOwnerCaptureStep ownerCapture;
|
||||
do
|
||||
{
|
||||
ownerCapture = physics.AdvanceCollisionRetainedOwnerCapture(
|
||||
admission,
|
||||
prepared);
|
||||
}
|
||||
while (!ownerCapture.Completed);
|
||||
foreach (uint ownerId in prepared.RetainedOwnerIds)
|
||||
{
|
||||
physics.RefreshCollisionRetainedOwner(
|
||||
admission,
|
||||
prepared,
|
||||
ownerId);
|
||||
}
|
||||
RuntimeCollisionSealStep seal;
|
||||
do
|
||||
{
|
||||
seal = physics.AdvanceCollisionGenerationSeal(
|
||||
admission,
|
||||
prepared);
|
||||
}
|
||||
while (!seal.Completed && !seal.Restarted);
|
||||
if (!seal.Completed)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Headless collision owner set changed during synchronous sealing.");
|
||||
}
|
||||
|
||||
RuntimeCollisionGenerationCommit result =
|
||||
physics.CommitCollisionGeneration(admission, prepared);
|
||||
if (!result.Committed)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Headless collision generation changed during synchronous publication.");
|
||||
}
|
||||
committed = true;
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!committed)
|
||||
physics.CancelCollisionGeneration(admission, prepared);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Per-session mutable collision publication over process-shared immutable
|
||||
/// DAT and pak inputs. Every session retains its own engine, data cache,
|
||||
|
|
@ -172,81 +243,58 @@ internal sealed class HeadlessCollisionNeighborhood
|
|||
_content.PreparedCollision,
|
||||
landblock);
|
||||
|
||||
RuntimePhysicsState physics =
|
||||
_runtime.EntityObjects.Physics;
|
||||
RuntimeCollisionAdmission admission =
|
||||
physics.BeginCollisionAdmission(landblockId);
|
||||
using PreparedLandblockCollisionGeneration prepared =
|
||||
physics.PrepareCollisionGeneration(admission);
|
||||
prepared.SetAssetClosure(
|
||||
[.. collisions.GfxObjIds],
|
||||
[.. collisions.SetupIds]);
|
||||
PhysicsDataCache cache = prepared.DataCache;
|
||||
TerrainSurface terrain =
|
||||
LandblockPhysicsContentBuilder.BuildTerrainSurface(
|
||||
landblock,
|
||||
_content.HeightTable.AsSpan());
|
||||
var cellSurfaces = new List<CellSurface>();
|
||||
var portalPlanes = new List<PortalPlane>();
|
||||
LandblockPhysicsContentBuilder.PublishPreparedCells(
|
||||
cache,
|
||||
landblock,
|
||||
collisions,
|
||||
origin,
|
||||
cellSurfaces,
|
||||
portalPlanes);
|
||||
LandblockPhysicsContentBuilder.CacheBuildings(
|
||||
cache,
|
||||
landblock,
|
||||
terrain,
|
||||
origin);
|
||||
LandblockPhysicsContentBuilder.CachePreparedObjects(
|
||||
cache,
|
||||
collisions);
|
||||
|
||||
try
|
||||
{
|
||||
physics.StageCollisionAssets(
|
||||
admission,
|
||||
prepared,
|
||||
new RuntimeLandblockCollisionAssets(
|
||||
landblockId,
|
||||
terrain,
|
||||
cellSurfaces,
|
||||
portalPlanes,
|
||||
origin.X,
|
||||
origin.Y,
|
||||
currentCellId));
|
||||
_ = LandblockPhysicsContentBuilder
|
||||
.PublishStaticCollision(
|
||||
prepared.Engine,
|
||||
RuntimePhysicsState physics = _runtime.EntityObjects.Physics;
|
||||
_ = HeadlessCollisionGenerationTransaction.Execute(
|
||||
physics,
|
||||
landblockId,
|
||||
afterAdmission: null,
|
||||
(admission, prepared) =>
|
||||
{
|
||||
prepared.SetAssetClosure(
|
||||
[.. collisions.GfxObjIds],
|
||||
[.. collisions.SetupIds]);
|
||||
PhysicsDataCache cache = prepared.DataCache;
|
||||
TerrainSurface terrain =
|
||||
LandblockPhysicsContentBuilder.BuildTerrainSurface(
|
||||
landblock,
|
||||
_content.HeightTable.AsSpan());
|
||||
var cellSurfaces = new List<CellSurface>();
|
||||
var portalPlanes = new List<PortalPlane>();
|
||||
LandblockPhysicsContentBuilder.PublishPreparedCells(
|
||||
cache,
|
||||
landblock,
|
||||
collisions,
|
||||
origin,
|
||||
cellSurfaces,
|
||||
portalPlanes);
|
||||
LandblockPhysicsContentBuilder.CacheBuildings(
|
||||
cache,
|
||||
landblock,
|
||||
terrain,
|
||||
origin);
|
||||
foreach (uint ownerId in physics.CaptureCollisionDynamicOwners(
|
||||
admission,
|
||||
prepared))
|
||||
{
|
||||
physics.RefreshCollisionDynamicOwner(
|
||||
LandblockPhysicsContentBuilder.CachePreparedObjects(
|
||||
cache,
|
||||
collisions);
|
||||
physics.StageCollisionAssets(
|
||||
admission,
|
||||
prepared,
|
||||
ownerId);
|
||||
}
|
||||
RuntimeCollisionGenerationCommit commit =
|
||||
physics.CommitCollisionGeneration(admission, prepared);
|
||||
if (!commit.Committed)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Headless collision generation changed during synchronous publication.");
|
||||
}
|
||||
_resident.Add(CanonicalLandblock(landblockId));
|
||||
}
|
||||
catch
|
||||
{
|
||||
_ = physics.WithdrawCollision(landblockId);
|
||||
throw;
|
||||
}
|
||||
new RuntimeLandblockCollisionAssets(
|
||||
landblockId,
|
||||
terrain,
|
||||
cellSurfaces,
|
||||
portalPlanes,
|
||||
origin.X,
|
||||
origin.Y,
|
||||
currentCellId));
|
||||
_ = LandblockPhysicsContentBuilder
|
||||
.PublishStaticCollision(
|
||||
prepared.Engine,
|
||||
cache,
|
||||
landblock,
|
||||
collisions,
|
||||
origin);
|
||||
});
|
||||
_resident.Add(CanonicalLandblock(landblockId));
|
||||
}
|
||||
|
||||
private void RetireAll()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue