Fix & speed up explosion lookup (#9526)
* Speed up explosion lookup * Ah. Fuck.
This commit is contained in:
@@ -202,30 +202,16 @@ public sealed partial class ExplosionSystem : EntitySystem
|
|||||||
|
|
||||||
// get the entities on a tile. Note that we cannot process them directly, or we get
|
// get the entities on a tile. Note that we cannot process them directly, or we get
|
||||||
// enumerator-changed-while-enumerating errors.
|
// enumerator-changed-while-enumerating errors.
|
||||||
List<(EntityUid, TransformComponent?) > list = new();
|
List<TransformComponent> list = new();
|
||||||
|
var state = (list, processed, xformQuery);
|
||||||
|
|
||||||
void AddIntersecting(List<(EntityUid, TransformComponent?)> listy)
|
// get entities:
|
||||||
{
|
lookup.Tree.QueryAabb(ref state, GridQueryCallback, gridBox, true);
|
||||||
// TODO directly query lookup.Tree
|
|
||||||
foreach (var uid in _entityLookup.GetLocalEntitiesIntersecting(lookup, ref gridBox, flags))
|
|
||||||
{
|
|
||||||
if (processed.Contains(uid))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!xformQuery.TryGetComponent(uid, out var xform))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
listy.Add((uid, xform));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AddIntersecting(list);
|
|
||||||
|
|
||||||
// process those entities
|
// process those entities
|
||||||
foreach (var (entity, xform) in list)
|
foreach (var xform in list)
|
||||||
{
|
{
|
||||||
processed.Add(entity);
|
ProcessEntity(xform.Owner, epicenter, damage, throwForce, id, damageQuery, physicsQuery, xform);
|
||||||
ProcessEntity(entity, epicenter, damage, throwForce, id, damageQuery, physicsQuery, xform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// process anchored entities
|
// process anchored entities
|
||||||
@@ -261,18 +247,28 @@ public sealed partial class ExplosionSystem : EntitySystem
|
|||||||
return !tileBlocked;
|
return !tileBlocked;
|
||||||
|
|
||||||
list.Clear();
|
list.Clear();
|
||||||
AddIntersecting(list);
|
lookup.Tree.QueryAabb(ref state, GridQueryCallback, gridBox, true);
|
||||||
|
|
||||||
foreach (var (entity, xform) in list)
|
foreach (var xform in list)
|
||||||
{
|
{
|
||||||
// Here we only throw, no dealing damage. Containers n such might drop their entities after being destroyed, but
|
// Here we only throw, no dealing damage. Containers n such might drop their entities after being destroyed, but
|
||||||
// they should handle their own damage pass-through, with their own damage reduction calculation.
|
// they should handle their own damage pass-through, with their own damage reduction calculation.
|
||||||
ProcessEntity(entity, epicenter, null, throwForce, id, damageQuery, physicsQuery, xform);
|
ProcessEntity(xform.Owner, epicenter, null, throwForce, id, damageQuery, physicsQuery, xform);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !tileBlocked;
|
return !tileBlocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool GridQueryCallback(
|
||||||
|
ref (List<TransformComponent> List, HashSet<EntityUid> Processed, EntityQuery<TransformComponent> XformQuery) state,
|
||||||
|
in EntityUid uid)
|
||||||
|
{
|
||||||
|
if (state.Processed.Add(uid) && state.XformQuery.TryGetComponent(uid, out var xform))
|
||||||
|
state.List.Add(xform);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Same as <see cref="ExplodeTile"/>, but for SPAAAAAAACE.
|
/// Same as <see cref="ExplodeTile"/>, but for SPAAAAAAACE.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -290,44 +286,18 @@ public sealed partial class ExplosionSystem : EntitySystem
|
|||||||
EntityQuery<PhysicsComponent> physicsQuery,
|
EntityQuery<PhysicsComponent> physicsQuery,
|
||||||
LookupFlags flags)
|
LookupFlags flags)
|
||||||
{
|
{
|
||||||
var gridBox = new Box2(tile * DefaultTileSize, (DefaultTileSize, DefaultTileSize));
|
var gridBox = Box2.FromDimensions(tile * DefaultTileSize, (DefaultTileSize, DefaultTileSize));
|
||||||
var worldBox = spaceMatrix.TransformBox(gridBox);
|
var worldBox = spaceMatrix.TransformBox(gridBox);
|
||||||
List<(EntityUid, TransformComponent)> list = new();
|
var list = new List<TransformComponent>();
|
||||||
|
var state = (list, processed, invSpaceMatrix, lookup.Owner, xformQuery, gridBox);
|
||||||
|
|
||||||
void AddIntersecting(List<(EntityUid, TransformComponent)> listy)
|
// get entities:
|
||||||
|
lookup.Tree.QueryAabb(ref state, SpaceQueryCallback, worldBox, true);
|
||||||
|
|
||||||
|
foreach (var xform in state.Item1)
|
||||||
{
|
{
|
||||||
// TODO directly query lookup.Tree
|
processed.Add(xform.Owner);
|
||||||
foreach (var uid in _entityLookup.GetEntitiesIntersecting(lookup, ref worldBox, flags))
|
ProcessEntity(xform.Owner, epicenter, damage, throwForce, id, damageQuery, physicsQuery, xform);
|
||||||
{
|
|
||||||
if (processed.Contains(uid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var xform = xformQuery.GetComponent(uid);
|
|
||||||
|
|
||||||
if (xform.ParentUid == lookup.Owner)
|
|
||||||
{
|
|
||||||
// parented directly to the map, use local position
|
|
||||||
if (gridBox.Contains(invSpaceMatrix.Transform(xform.LocalPosition)))
|
|
||||||
listy.Add((uid, xform));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// "worldPos" should be the space/map local position.
|
|
||||||
var worldPos = _transformSystem.GetWorldPosition(xform, xformQuery);
|
|
||||||
|
|
||||||
// finally check if it intersects our tile
|
|
||||||
if (gridBox.Contains(invSpaceMatrix.Transform(worldPos)))
|
|
||||||
listy.Add((uid, xform));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AddIntersecting(list);
|
|
||||||
|
|
||||||
foreach (var (entity, xform) in list)
|
|
||||||
{
|
|
||||||
processed.Add(entity);
|
|
||||||
ProcessEntity(entity, epicenter, damage, throwForce, id, damageQuery, physicsQuery, xform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (throwForce <= 0)
|
if (throwForce <= 0)
|
||||||
@@ -336,13 +306,39 @@ public sealed partial class ExplosionSystem : EntitySystem
|
|||||||
// Also, throw any entities that were spawned as shrapnel. Compared to entity spawning & destruction, this extra
|
// Also, throw any entities that were spawned as shrapnel. Compared to entity spawning & destruction, this extra
|
||||||
// lookup is relatively minor computational cost, and throwing is disabled for nukes anyways.
|
// lookup is relatively minor computational cost, and throwing is disabled for nukes anyways.
|
||||||
list.Clear();
|
list.Clear();
|
||||||
AddIntersecting(list);
|
lookup.Tree.QueryAabb(ref state, SpaceQueryCallback, worldBox, true);
|
||||||
foreach (var (entity, xform) in list)
|
|
||||||
|
foreach (var xform in list)
|
||||||
{
|
{
|
||||||
ProcessEntity(entity, epicenter, null, throwForce, id, damageQuery, physicsQuery, xform);
|
ProcessEntity(xform.Owner, epicenter, null, throwForce, id, damageQuery, physicsQuery, xform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool SpaceQueryCallback(
|
||||||
|
ref (List<TransformComponent> List, HashSet<EntityUid> Processed, Matrix3 InvSpaceMatrix, EntityUid LookupOwner, EntityQuery<TransformComponent> XformQuery, Box2 GridBox) state,
|
||||||
|
in EntityUid uid)
|
||||||
|
{
|
||||||
|
if (state.Processed.Contains(uid))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var xform = state.XformQuery.GetComponent(uid);
|
||||||
|
|
||||||
|
if (xform.ParentUid == state.LookupOwner)
|
||||||
|
{
|
||||||
|
// parented directly to the map, use local position
|
||||||
|
if (state.GridBox.Contains(state.InvSpaceMatrix.Transform(xform.LocalPosition)))
|
||||||
|
state.List.Add(xform);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally check if it intersects our tile
|
||||||
|
if (state.GridBox.Contains(state.InvSpaceMatrix.Transform(_transformSystem.GetWorldPosition(xform, state.XformQuery))))
|
||||||
|
state.List.Add(xform);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This function actually applies the explosion affects to an entity.
|
/// This function actually applies the explosion affects to an entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -497,7 +493,7 @@ sealed class Explosion
|
|||||||
public readonly MapCoordinates Epicenter;
|
public readonly MapCoordinates Epicenter;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The matrix that defines the referance frame for the explosion in space.
|
/// The matrix that defines the reference frame for the explosion in space.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Matrix3 _spaceMatrix;
|
private readonly Matrix3 _spaceMatrix;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user