Lookup changes (#18416)

This commit is contained in:
metalgearsloth
2023-08-06 12:44:05 +10:00
committed by GitHub
parent 066ec55525
commit d3aece12cb
10 changed files with 76 additions and 58 deletions

View File

@@ -84,7 +84,7 @@ namespace Content.Server.Abilities.Mime
} }
// Check there are no mobs there // Check there are no mobs there
foreach (var entity in _lookupSystem.GetEntitiesIntersecting(tile.Value)) foreach (var entity in _lookupSystem.GetEntitiesIntersecting(tile.Value, 0f))
{ {
if (HasComp<MobStateComponent>(entity) && entity != uid) if (HasComp<MobStateComponent>(entity) && entity != uid)
{ {

View File

@@ -138,7 +138,7 @@ namespace Content.Server.Atmos.EntitySystems
tile.PressureSpecificTarget = curTile; tile.PressureSpecificTarget = curTile;
} }
foreach (var entity in _lookup.GetEntitiesIntersecting(tile.GridIndex, tile.GridIndices)) foreach (var entity in _lookup.GetEntitiesIntersecting(tile.GridIndex, tile.GridIndices, 0f))
{ {
// Ideally containers would have their own EntityQuery internally or something given recursively it may need to slam GetComp<T> anyway. // Ideally containers would have their own EntityQuery internally or something given recursively it may need to slam GetComp<T> anyway.
// Also, don't care about static bodies (but also due to collisionwakestate can't query dynamic directly atm). // Also, don't care about static bodies (but also due to collisionwakestate can't query dynamic directly atm).

View File

@@ -167,9 +167,9 @@ namespace Content.Server.Atmos.EntitySystems
var fireEvent = new TileFireEvent(tile.Hotspot.Temperature, tile.Hotspot.Volume); var fireEvent = new TileFireEvent(tile.Hotspot.Temperature, tile.Hotspot.Volume);
foreach (var entity in _lookup.GetEntitiesIntersecting(tile.GridIndex, tile.GridIndices)) foreach (var entity in _lookup.GetEntitiesIntersecting(tile.GridIndex, tile.GridIndices, 0f))
{ {
RaiseLocalEvent(entity, ref fireEvent, false); RaiseLocalEvent(entity, ref fireEvent);
} }
} }
} }

View File

@@ -34,7 +34,7 @@ public sealed class CleanTileReaction : ITileReaction
FixedPoint2 ITileReaction.TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume) FixedPoint2 ITileReaction.TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume)
{ {
var entMan = IoCManager.Resolve<IEntityManager>(); var entMan = IoCManager.Resolve<IEntityManager>();
var entities = entMan.System<EntityLookupSystem>().GetEntitiesIntersecting(tile).ToArray(); var entities = entMan.System<EntityLookupSystem>().GetEntitiesIntersecting(tile, 0f).ToArray();
var puddleQuery = entMan.GetEntityQuery<PuddleComponent>(); var puddleQuery = entMan.GetEntityQuery<PuddleComponent>();
var solutionContainerSystem = entMan.System<SolutionContainerSystem>(); var solutionContainerSystem = entMan.System<SolutionContainerSystem>();
// Multiply as the amount we can actually purge is higher than the react amount. // Multiply as the amount we can actually purge is higher than the react amount.

View File

@@ -208,7 +208,7 @@ public sealed class SmokeSystem : EntitySystem
var tile = mapGrid.GetTileRef(xform.Coordinates.ToVector2i(EntityManager, _mapManager)); var tile = mapGrid.GetTileRef(xform.Coordinates.ToVector2i(EntityManager, _mapManager));
var solutionFraction = 1 / Math.Floor(frameTime); var solutionFraction = 1 / Math.Floor(frameTime);
var ents = _lookup.GetEntitiesIntersecting(tile, LookupFlags.Uncontained).ToArray(); var ents = _lookup.GetEntitiesIntersecting(tile, 0f, flags: LookupFlags.Uncontained).ToArray();
foreach (var reagentQuantity in solution.Contents.ToArray()) foreach (var reagentQuantity in solution.Contents.ToArray())
{ {

View File

@@ -50,6 +50,7 @@ public sealed partial class PathfindingSystem
SubscribeLocalEvent<GridPathfindingComponent, EntityUnpausedEvent>(OnGridPathPause); SubscribeLocalEvent<GridPathfindingComponent, EntityUnpausedEvent>(OnGridPathPause);
SubscribeLocalEvent<GridPathfindingComponent, ComponentShutdown>(OnGridPathShutdown); SubscribeLocalEvent<GridPathfindingComponent, ComponentShutdown>(OnGridPathShutdown);
SubscribeLocalEvent<CollisionChangeEvent>(OnCollisionChange); SubscribeLocalEvent<CollisionChangeEvent>(OnCollisionChange);
SubscribeLocalEvent<CollisionLayerChangeEvent>(OnCollisionLayerChange);
SubscribeLocalEvent<PhysicsBodyTypeChangedEvent>(OnBodyTypeChange); SubscribeLocalEvent<PhysicsBodyTypeChangedEvent>(OnBodyTypeChange);
SubscribeLocalEvent<TileChangedEvent>(OnTileChange); SubscribeLocalEvent<TileChangedEvent>(OnTileChange);
SubscribeLocalEvent<MoveEvent>(OnMoveEvent); SubscribeLocalEvent<MoveEvent>(OnMoveEvent);
@@ -95,7 +96,7 @@ public sealed partial class PathfindingSystem
_stopwatch.Restart(); _stopwatch.Restart();
var options = new ParallelOptions() var options = new ParallelOptions()
{ {
MaxDegreeOfParallelism = _parallel.ParallelProcessCount, MaxDegreeOfParallelism = 1,
}; };
// We defer chunk updates because rebuilding a navmesh is hella costly // We defer chunk updates because rebuilding a navmesh is hella costly
@@ -238,17 +239,18 @@ public sealed partial class PathfindingSystem
} }
} }
private bool IsBodyRelevant(PhysicsComponent body) private bool IsBodyRelevant(FixturesComponent fixtures)
{ {
if (!body.Hard || body.BodyType != BodyType.Static) foreach (var fixture in fixtures.Fixtures.Values)
{ {
return false; if (!fixture.Hard)
} continue;
if ((body.CollisionMask & PathfindingCollisionLayer) != 0x0 || if ((fixture.CollisionMask & PathfindingCollisionLayer) != 0x0 ||
(body.CollisionLayer & PathfindingCollisionMask) != 0x0) (fixture.CollisionLayer & PathfindingCollisionMask) != 0x0)
{ {
return true; return true;
}
} }
return false; return false;
@@ -256,35 +258,42 @@ public sealed partial class PathfindingSystem
private void OnCollisionChange(ref CollisionChangeEvent ev) private void OnCollisionChange(ref CollisionChangeEvent ev)
{ {
if (!IsBodyRelevant(ev.Body))
return;
var xform = Transform(ev.Body.Owner); var xform = Transform(ev.Body.Owner);
if (xform.GridUid == null) if (xform.GridUid == null)
return; return;
// This will also rebuild on door open / closes which I think is good? // This will also rebuild on door open / closes which I think is good?
DirtyChunk(xform.GridUid.Value, xform.Coordinates); var aabb = _lookup.GetAABBNoContainer(ev.Body.Owner, xform.Coordinates.Position, xform.LocalRotation);
DirtyChunkArea(xform.GridUid.Value, aabb);
}
private void OnCollisionLayerChange(ref CollisionLayerChangeEvent ev)
{
var xform = Transform(ev.Body.Owner);
if (xform.GridUid == null)
return;
var aabb = _lookup.GetAABBNoContainer(ev.Body.Owner, xform.Coordinates.Position, xform.LocalRotation);
DirtyChunkArea(xform.GridUid.Value, aabb);
} }
private void OnBodyTypeChange(ref PhysicsBodyTypeChangedEvent ev) private void OnBodyTypeChange(ref PhysicsBodyTypeChangedEvent ev)
{ {
if (ev.Component.CanCollide && if (TryComp<TransformComponent>(ev.Entity, out var xform) &&
IsBodyRelevant(ev.Component) &&
TryComp<TransformComponent>(ev.Entity, out var xform) &&
xform.GridUid != null) xform.GridUid != null)
{ {
DirtyChunk(xform.GridUid.Value, xform.Coordinates); var aabb = _lookup.GetAABBNoContainer(ev.Entity, xform.Coordinates.Position, xform.LocalRotation);
DirtyChunkArea(xform.GridUid.Value, aabb);
} }
} }
private void OnMoveEvent(ref MoveEvent ev) private void OnMoveEvent(ref MoveEvent ev)
{ {
if (!TryComp<PhysicsComponent>(ev.Sender, out var body) || if (!TryComp<FixturesComponent>(ev.Sender, out var fixtures) ||
body.BodyType != BodyType.Static || !IsBodyRelevant(fixtures) ||
HasComp<MapGridComponent>(ev.Sender) || HasComp<MapGridComponent>(ev.Sender))
ev.OldPosition.Equals(ev.NewPosition))
{ {
return; return;
} }
@@ -294,34 +303,16 @@ public sealed partial class PathfindingSystem
? gridUid ? gridUid
: ev.OldPosition.GetGridUid(EntityManager); : ev.OldPosition.GetGridUid(EntityManager);
// Not on a grid at all so just ignore. if (oldGridUid != null && oldGridUid != gridUid)
if (oldGridUid == gridUid && oldGridUid == null)
{ {
return; var aabb = _lookup.GetAABBNoContainer(ev.Sender, ev.OldPosition.Position, ev.OldRotation);
} DirtyChunkArea(oldGridUid.Value, aabb);
if (oldGridUid != null && gridUid != null)
{
// If the chunk hasn't changed then just dirty that one.
var oldOrigin = GetOrigin(ev.OldPosition, oldGridUid.Value);
var origin = GetOrigin(ev.NewPosition, gridUid.Value);
if (oldOrigin == origin)
{
// TODO: Don't need to transform again numpty.
DirtyChunk(oldGridUid.Value, ev.NewPosition);
return;
}
}
if (oldGridUid != null)
{
DirtyChunk(oldGridUid.Value, ev.OldPosition);
} }
if (gridUid != null) if (gridUid != null)
{ {
DirtyChunk(gridUid.Value, ev.NewPosition); var aabb = _lookup.GetAABBNoContainer(ev.Sender, ev.NewPosition.Position, ev.NewRotation);
DirtyChunkArea(gridUid.Value, aabb);
} }
} }
@@ -364,6 +355,30 @@ public sealed partial class PathfindingSystem
chunks.Add(GetOrigin(coordinates, gridUid)); chunks.Add(GetOrigin(coordinates, gridUid));
} }
private void DirtyChunkArea(EntityUid gridUid, Box2 aabb)
{
if (!TryComp<GridPathfindingComponent>(gridUid, out var comp))
return;
var currentTime = _timing.CurTime;
if (comp.NextUpdate < currentTime)
comp.NextUpdate = currentTime + UpdateCooldown;
var chunks = comp.DirtyChunks;
// This assumes you never have bounds equal to or larger than 2 * ChunkSize.
var corners = new Vector2[] { aabb.BottomLeft, aabb.TopRight, aabb.BottomRight, aabb.TopLeft };
foreach (var corner in corners)
{
var sampledPoint = new Vector2i(
(int) Math.Floor((corner.X) / ChunkSize),
(int) Math.Floor((corner.Y) / ChunkSize));
chunks.Add(sampledPoint);
}
}
private GridPathfindingChunk GetChunk(Vector2i origin, EntityUid uid, GridPathfindingComponent? component = null) private GridPathfindingChunk GetChunk(Vector2i origin, EntityUid uid, GridPathfindingComponent? component = null)
{ {
if (!Resolve(uid, ref component)) if (!Resolve(uid, ref component))
@@ -445,18 +460,18 @@ public sealed partial class PathfindingSystem
// var isBorder = x < 0 || y < 0 || x == ChunkSize - 1 || y == ChunkSize - 1; // var isBorder = x < 0 || y < 0 || x == ChunkSize - 1 || y == ChunkSize - 1;
tileEntities.Clear(); tileEntities.Clear();
var anchored = grid.GetAnchoredEntitiesEnumerator(tilePos); var available = _lookup.GetEntitiesIntersecting(tile);
while (anchored.MoveNext(out var ent)) foreach (var ent in available)
{ {
// Irrelevant for pathfinding // Irrelevant for pathfinding
if (!physicsQuery.TryGetComponent(ent, out var body) || if (!fixturesQuery.TryGetComponent(ent, out var fixtures) ||
!IsBodyRelevant(body)) !IsBodyRelevant(fixtures))
{ {
continue; continue;
} }
tileEntities.Add(ent.Value); tileEntities.Add(ent);
} }
for (var subX = 0; subX < SubStep; subX++) for (var subX = 0; subX < SubStep; subX++)
@@ -485,7 +500,9 @@ public sealed partial class PathfindingSystem
if (!fixture.Hard || if (!fixture.Hard ||
(collisionMask & fixture.CollisionMask) == fixture.CollisionMask && (collisionMask & fixture.CollisionMask) == fixture.CollisionMask &&
(collisionLayer & fixture.CollisionLayer) == fixture.CollisionLayer) (collisionLayer & fixture.CollisionLayer) == fixture.CollisionLayer)
{
continue; continue;
}
// Do an AABB check first as it's probably faster, then do an actual point check. // Do an AABB check first as it's probably faster, then do an actual point check.
var intersects = false; var intersects = false;

View File

@@ -45,6 +45,7 @@ namespace Content.Server.NPC.Pathfinding
[Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly DestructibleSystem _destructible = default!; [Dependency] private readonly DestructibleSystem _destructible = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly FixtureSystem _fixtures = default!; [Dependency] private readonly FixtureSystem _fixtures = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!;

View File

@@ -254,7 +254,7 @@ public sealed partial class NPCSteeringSystem : SharedNPCSteeringSystem
// Dependency issues across threads. // Dependency issues across threads.
var options = new ParallelOptions var options = new ParallelOptions
{ {
MaxDegreeOfParallelism = 1, MaxDegreeOfParallelism = _parallel.ParallelProcessCount,
}; };
var curTime = _timing.CurTime; var curTime = _timing.CurTime;

View File

@@ -125,7 +125,7 @@ public sealed class ConveyorController : SharedConveyorController
if (beltTileRef != null) if (beltTileRef != null)
{ {
var intersecting = Lookup.GetEntitiesIntersecting(beltTileRef.Value); var intersecting = Lookup.GetEntitiesIntersecting(beltTileRef.Value, 0f);
foreach (var entity in intersecting) foreach (var entity in intersecting)
{ {

View File

@@ -172,7 +172,7 @@ public sealed partial class BlockingSystem : EntitySystem
var playerTileRef = xform.Coordinates.GetTileRef(); var playerTileRef = xform.Coordinates.GetTileRef();
if (playerTileRef != null) if (playerTileRef != null)
{ {
var intersecting = _lookup.GetEntitiesIntersecting(playerTileRef.Value); var intersecting = _lookup.GetEntitiesIntersecting(playerTileRef.Value, 0f);
var mobQuery = GetEntityQuery<MobStateComponent>(); var mobQuery = GetEntityQuery<MobStateComponent>();
foreach (var uid in intersecting) foreach (var uid in intersecting)
{ {