feat(runtime): own SetPosition collision reports

This commit is contained in:
Erik 2026-08-01 00:15:11 +02:00
parent ec627c13a2
commit 237d1184d2
19 changed files with 3744 additions and 103 deletions

View file

@ -213,6 +213,25 @@ internal sealed class RuntimeSetPositionState : IDisposable
}
}
private sealed class ContactCommitGuard(
RuntimeSetPositionState owner,
Operation operation,
RuntimeEntityRecord record,
PhysicsBody body,
ulong placementCommitVersion,
uint fullCellId)
{
internal bool IsCurrent() =>
owner.IsCanonicalPlacementCommitCurrent(
operation,
record,
body,
placementCommitVersion,
fullCellId,
requireSpatialRoot: false)
&& owner.IsCollisionReportingEligible(record, body);
}
private readonly RuntimePhysicsState _physics;
private readonly RuntimeEntityDirectory _entities;
private readonly Dictionary<RuntimeEntityKey, Operation> _operations = [];
@ -549,9 +568,12 @@ internal sealed class RuntimeSetPositionState : IDisposable
operation.PositionAuthorityVersion,
operation.SourceSpatialAuthorityVersion,
operation.SourceVelocityAuthorityVersion,
canonicalCommand.GameTime,
operation.PreviousContact,
operation.PreviousOnWalkable,
report));
if (!IsCurrent(operation))
return Outcome(RuntimeSetPositionStatus.Cancelled, result, default);
operation.Result = result;
if (!result.IsSuccessful)
{
@ -1236,11 +1258,14 @@ internal sealed class RuntimeSetPositionState : IDisposable
operation.PositionAuthorityVersion,
operation.SpatialAuthorityVersion,
operation.SourceVelocityAuthorityVersion,
operation.Command.GameTime,
operation.PreviousContact,
operation.PreviousOnWalkable,
report))
: InvalidResult(operation.Command.Physics);
operation.CollisionGenerationReady = false;
if (!IsCurrent(operation))
return;
if (result.IsDeferred)
{
operation.Result = result;
@ -1320,18 +1345,6 @@ internal sealed class RuntimeSetPositionState : IDisposable
body.TransientState |= TransientStateFlags.Sliding;
else
body.TransientState &= ~TransientStateFlags.Sliding;
body.FramesStationaryFall = result.FramesStationaryFall;
body.TransientState &= ~(TransientStateFlags.StationaryFall
| TransientStateFlags.StationaryStop
| TransientStateFlags.StationaryStuck);
body.TransientState |= result.FramesStationaryFall switch
{
1 => TransientStateFlags.StationaryFall,
2 => TransientStateFlags.StationaryStop,
3 => TransientStateFlags.StationaryStuck,
_ => TransientStateFlags.None,
};
IRuntimeRemotePlacement? remote =
record.RemoteMotion as IRuntimeRemotePlacement;
if (record.FullCellId != result.CellId)
@ -1354,6 +1367,109 @@ internal sealed class RuntimeSetPositionState : IDisposable
remote.LastShadowSyncOrientation = result.Orientation;
}
uint committedCellId = result.CellId;
bool collidedWithEnvironment = result.CollidedWithEnvironment;
System.Collections.Immutable.ImmutableArray<uint> collidedObjectIds =
result.CollidedObjectIds;
if (!IsCanonicalPlacementCommitCurrent(
operation,
record,
body,
canonicalCommitVersion,
committedCellId,
requireSpatialRoot: false))
return false;
bool contactCommitted;
if (remote is null)
{
contactCommitted = PhysicsObjUpdate.CommitSetPositionContactTransition(
body,
result.InContact,
result.OnWalkable,
operation.PreviousOnWalkable);
}
else
{
var guard = new ContactCommitGuard(
this,
operation,
record,
body,
canonicalCommitVersion,
committedCellId);
contactCommitted = PhysicsObjUpdate.CommitSetPositionContactTransition(
body,
result.InContact,
result.OnWalkable,
operation.PreviousOnWalkable,
remote.HitGround,
remote.LeaveGround,
guard.IsCurrent);
}
if (!contactCommitted
|| !IsCanonicalPlacementCommitCurrent(
operation,
record,
body,
canonicalCommitVersion,
committedCellId,
requireSpatialRoot: false)
|| !IsCollisionReportingEligible(record, body))
{
return false;
}
bool reportingCurrent = _physics.HandleSetPositionCollisionReports(
record,
operation.PositionAuthorityVersion,
operation.SpatialAuthorityVersion,
operation.Command.GameTime,
operation.PreviousContact,
operation.PreviousOnWalkable,
collidedWithEnvironment,
collidedObjectIds,
out _);
if (!reportingCurrent
|| !IsCanonicalPlacementCommitCurrent(
operation,
record,
body,
canonicalCommitVersion,
committedCellId,
requireSpatialRoot: false)
|| !IsCollisionReportingEligible(record, body))
return false;
body.FramesStationaryFall = result.FramesStationaryFall;
if (IsVelocityCurrent(operation))
{
PhysicsObjUpdate.HandleAllCollisions(
body,
result.CollisionNormalValid,
result.CollisionNormal,
operation.PreviousContact,
operation.PreviousOnWalkable,
body.OnWalkable);
}
body.TransientState &= ~(TransientStateFlags.StationaryFall
| TransientStateFlags.StationaryStop
| TransientStateFlags.StationaryStuck);
body.TransientState |= result.FramesStationaryFall switch
{
1 => TransientStateFlags.StationaryFall,
2 => TransientStateFlags.StationaryStop,
3 => TransientStateFlags.StationaryStuck,
_ => TransientStateFlags.None,
};
if (remote is not null)
remote.Airborne = !body.OnWalkable;
if (!IsCanonicalPlacementCommitCurrent(
operation,
record,
body,
canonicalCommitVersion,
committedCellId,
requireSpatialRoot: false))
return false;
_physics.Engine.ShadowObjects.CommitSetPosition(
operation.Key.LocalEntityId,
result.Position,
@ -1370,39 +1486,44 @@ internal sealed class RuntimeSetPositionState : IDisposable
operation.EnteringWorldFromCelllessResidence = false;
CancelLostFamilyDeadlines(operation);
uint committedCellId = result.CellId;
bool IsCanonicalCommitCurrent() =>
_entities.IsCurrent(record)
&& ReferenceEquals(record.PhysicsBody, body)
&& record.PlacementCommitVersion == canonicalCommitVersion
&& record.FullCellId == committedCellId
&& _physics.IsSpatialRoot(record);
Action? hitGround = remote is null ? null : remote.HitGround;
Action? leaveGround = remote is null ? null : remote.LeaveGround;
if (!PhysicsObjUpdate.CommitSetPositionTransition(
body,
result.InContact,
result.OnWalkable,
result.CollisionNormalValid,
result.CollisionNormal,
operation.PreviousContact,
operation.PreviousOnWalkable,
hitGround,
leaveGround,
IsCanonicalCommitCurrent,
() => IsCanonicalCommitCurrent()
&& IsVelocityCurrent(operation)))
{
return false;
}
if (remote is not null)
remote.Airborne = !body.OnWalkable;
return IsCurrent(operation)
&& IsCanonicalCommitCurrent();
&& IsCanonicalPlacementCommitCurrent(
operation,
record,
body,
canonicalCommitVersion,
committedCellId,
requireSpatialRoot: true);
}
private bool IsCanonicalPlacementCommitCurrent(
Operation operation,
RuntimeEntityRecord record,
PhysicsBody body,
ulong placementCommitVersion,
uint fullCellId,
bool requireSpatialRoot) =>
_entities.IsCurrent(record)
&& ReferenceEquals(record.PhysicsBody, body)
&& record.PositionAuthorityVersion
== operation.PositionAuthorityVersion
&& record.SpatialAuthorityVersion
== operation.SpatialAuthorityVersion
&& record.PlacementCommitVersion == placementCommitVersion
&& record.FullCellId == fullCellId
&& (!requireSpatialRoot || _physics.IsSpatialRoot(record));
private bool IsCollisionReportingEligible(
RuntimeEntityRecord record,
PhysicsBody body) =>
_entities.IsCurrent(record)
&& ReferenceEquals(record.PhysicsBody, body)
&& body.InWorld
&& (body.State & PhysicsStateFlags.Hidden) == 0;
private void WithdrawCanonical(RuntimeEntityRecord record)
{
_physics.CollisionReports.LeaveWorld(record);
_physics.RemoveSpatialProjection(record);
if (record.Key is { } key)
_physics.Engine.ShadowObjects.Suspend(key.LocalEntityId);