step trigger fix + optimization (#8503)

This commit is contained in:
Leon Friedrich
2022-05-29 11:31:43 +12:00
committed by GitHub
parent 0d17626e22
commit 55565ea22a
2 changed files with 32 additions and 26 deletions

View File

@@ -1,4 +1,4 @@
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
namespace Content.Shared.StepTrigger; namespace Content.Shared.StepTrigger;
@@ -11,12 +11,14 @@ public sealed class StepTriggerComponent : Component
/// <summary> /// <summary>
/// List of entities that are currently colliding with the entity. /// List of entities that are currently colliding with the entity.
/// </summary> /// </summary>
[ViewVariables]
public readonly HashSet<EntityUid> Colliding = new(); public readonly HashSet<EntityUid> Colliding = new();
/// <summary> /// <summary>
/// The list of entities that are standing on this entity, /// The list of entities that are standing on this entity,
/// which shouldn't be able to trigger it again until stepping off. /// which shouldn't be able to trigger it again until stepping off.
/// </summary> /// </summary>
[ViewVariables]
public readonly HashSet<EntityUid> CurrentlySteppedOn = new(); public readonly HashSet<EntityUid> CurrentlySteppedOn = new();
/// <summary> /// <summary>
@@ -50,13 +52,17 @@ public sealed class StepTriggerComponentState : ComponentState
{ {
public float IntersectRatio { get; } public float IntersectRatio { get; }
public float RequiredTriggerSpeed { get; } public float RequiredTriggerSpeed { get; }
public readonly EntityUid[] CurrentlySteppedOn; public readonly HashSet<EntityUid> CurrentlySteppedOn;
public readonly HashSet<EntityUid> Colliding;
public readonly bool Active;
public StepTriggerComponentState(float intersectRatio, EntityUid[] currentlySteppedOn, float requiredTriggerSpeed) public StepTriggerComponentState(float intersectRatio, HashSet<EntityUid> currentlySteppedOn, HashSet<EntityUid> colliding, float requiredTriggerSpeed, bool active)
{ {
IntersectRatio = intersectRatio; IntersectRatio = intersectRatio;
CurrentlySteppedOn = currentlySteppedOn; CurrentlySteppedOn = currentlySteppedOn;
RequiredTriggerSpeed = requiredTriggerSpeed; RequiredTriggerSpeed = requiredTriggerSpeed;
Active = active;
Colliding = colliding;
} }
} }

View File

@@ -1,4 +1,4 @@
using System.Linq; using System.Linq;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Physics.Dynamics; using Robust.Shared.Physics.Dynamics;
@@ -18,25 +18,25 @@ public sealed class StepTriggerSystem : EntitySystem
public override void Update(float frameTime) public override void Update(float frameTime)
{ {
foreach (var (_, trigger, transform) in EntityQuery<StepTriggerActiveComponent, StepTriggerComponent, TransformComponent>()) var query = GetEntityQuery<PhysicsComponent>();
foreach (var (active, trigger, transform) in EntityQuery<StepTriggerActiveComponent, StepTriggerComponent, TransformComponent>())
{ {
if (!Update(trigger, transform)) if (!Update(trigger, transform, query))
continue; continue;
RemComp<StepTriggerActiveComponent>(trigger.Owner); RemComp(trigger.Owner, active);
} }
} }
private bool Update(StepTriggerComponent component, TransformComponent transform) private bool Update(StepTriggerComponent component, TransformComponent transform, EntityQuery<PhysicsComponent> query)
{ {
if (!component.Active || if (!component.Active ||
component.Colliding.Count == 0) component.Colliding.Count == 0)
return true; return true;
foreach (var otherUid in component.Colliding.ToArray()) foreach (var otherUid in component.Colliding.ToArray())
{ {
var shouldRemoveFromColliding = UpdateColliding(component, transform, otherUid); var shouldRemoveFromColliding = UpdateColliding(component, transform, otherUid, query);
if (!shouldRemoveFromColliding) continue; if (!shouldRemoveFromColliding) continue;
component.Colliding.Remove(otherUid); component.Colliding.Remove(otherUid);
@@ -46,16 +46,11 @@ public sealed class StepTriggerSystem : EntitySystem
return false; return false;
} }
private bool UpdateColliding(StepTriggerComponent component, TransformComponent ownerTransform, EntityUid otherUid) private bool UpdateColliding(StepTriggerComponent component, TransformComponent ownerTransform, EntityUid otherUid, EntityQuery<PhysicsComponent> query)
{ {
if (!TryComp(otherUid, out PhysicsComponent? otherPhysics)) if (!query.TryGetComponent(otherUid, out var otherPhysics))
return true; return true;
if (component.CurrentlySteppedOn.Contains(otherUid) ||
!CanTrigger(component.Owner, otherUid, component) ||
otherPhysics.LinearVelocity.Length < component.RequiredTriggerSpeed)
return false;
// TODO: This shouldn't be calculating based on world AABBs. // TODO: This shouldn't be calculating based on world AABBs.
var ourAabb = _entityLookup.GetWorldAABB(component.Owner, ownerTransform); var ourAabb = _entityLookup.GetWorldAABB(component.Owner, ownerTransform);
var otherAabb = _entityLookup.GetWorldAABB(otherUid); var otherAabb = _entityLookup.GetWorldAABB(otherUid);
@@ -63,8 +58,10 @@ public sealed class StepTriggerSystem : EntitySystem
if (!ourAabb.Intersects(otherAabb)) if (!ourAabb.Intersects(otherAabb))
return true; return true;
var percentage = otherAabb.IntersectPercentage(ourAabb); if (otherPhysics.LinearVelocity.Length < component.RequiredTriggerSpeed
if (percentage < component.IntersectRatio) || component.CurrentlySteppedOn.Contains(otherUid)
|| otherAabb.IntersectPercentage(ourAabb) < component.IntersectRatio
|| !CanTrigger(component.Owner, otherUid, component))
return false; return false;
var ev = new StepTriggeredEvent { Source = component.Owner, Tripper = otherUid }; var ev = new StepTriggeredEvent { Source = component.Owner, Tripper = otherUid };
@@ -106,20 +103,23 @@ public sealed class StepTriggerSystem : EntitySystem
component.RequiredTriggerSpeed = state.RequiredTriggerSpeed; component.RequiredTriggerSpeed = state.RequiredTriggerSpeed;
component.IntersectRatio = state.IntersectRatio; component.IntersectRatio = state.IntersectRatio;
component.CurrentlySteppedOn.Clear(); component.Active = state.Active;
foreach (var slipped in state.CurrentlySteppedOn) component.CurrentlySteppedOn.Clear();
{ component.Colliding.Clear();
component.CurrentlySteppedOn.Add(slipped);
} component.CurrentlySteppedOn.UnionWith(state.CurrentlySteppedOn);
component.Colliding.UnionWith(state.Colliding);
} }
private static void TriggerGetState(EntityUid uid, StepTriggerComponent component, ref ComponentGetState args) private static void TriggerGetState(EntityUid uid, StepTriggerComponent component, ref ComponentGetState args)
{ {
args.State = new StepTriggerComponentState( args.State = new StepTriggerComponentState(
component.IntersectRatio, component.IntersectRatio,
component.CurrentlySteppedOn.ToArray(), component.CurrentlySteppedOn,
component.RequiredTriggerSpeed); component.Colliding,
component.RequiredTriggerSpeed,
component.Active);
} }
public void SetIntersectRatio(EntityUid uid, float ratio, StepTriggerComponent? component = null) public void SetIntersectRatio(EntityUid uid, float ratio, StepTriggerComponent? component = null)