Lookup changes (#18416)
This commit is contained in:
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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,53 +239,61 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
@@ -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!;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user