feat(runtime): own SetPosition collision reports
This commit is contained in:
parent
ec627c13a2
commit
237d1184d2
19 changed files with 3744 additions and 103 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue