Spreaders travels across connected grids and SpreaderIgnore tag (#15419)

This commit is contained in:
metalgearsloth
2023-04-25 06:04:49 +10:00
committed by GitHub
parent 028c363608
commit 1cde3ff112
8 changed files with 85 additions and 58 deletions

View File

@@ -86,14 +86,6 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
return; return;
} }
var xform = Transform(uid);
if (!TryComp<MapGridComponent>(xform.GridUid, out var grid))
{
RemCompDeferred<EdgeSpreaderComponent>(uid);
return;
}
var puddleQuery = GetEntityQuery<PuddleComponent>(); var puddleQuery = GetEntityQuery<PuddleComponent>();
// For overflows, we never go to a fully evaporative tile just to avoid continuously having to mop it. // For overflows, we never go to a fully evaporative tile just to avoid continuously having to mop it.
@@ -152,10 +144,10 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
spillCount = Math.Min(args.NeighborFreeTiles.Count, spillCount); spillCount = Math.Min(args.NeighborFreeTiles.Count, spillCount);
var spillAmount = overflow.Volume / spillCount; var spillAmount = overflow.Volume / spillCount;
foreach (var tile in args.NeighborFreeTiles) foreach (var neighbor in args.NeighborFreeTiles)
{ {
var split = overflow.SplitSolution(spillAmount); var split = overflow.SplitSolution(spillAmount);
TrySpillAt(grid.GridTileToLocal(tile), split, out _, false); TrySpillAt(neighbor.Grid.GridTileToLocal(neighbor.Tile), split, out _, false);
args.Updates--; args.Updates--;
if (args.Updates <= 0) if (args.Updates <= 0)

View File

@@ -73,7 +73,6 @@ public sealed class SmokeSystem : EntitySystem
private void OnSmokeSpread(EntityUid uid, SmokeComponent component, ref SpreadNeighborsEvent args) private void OnSmokeSpread(EntityUid uid, SmokeComponent component, ref SpreadNeighborsEvent args)
{ {
if (component.SpreadAmount == 0 || if (component.SpreadAmount == 0 ||
args.Grid == null ||
!_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution) || !_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution) ||
args.NeighborFreeTiles.Count == 0) args.NeighborFreeTiles.Count == 0)
{ {
@@ -94,9 +93,9 @@ public sealed class SmokeSystem : EntitySystem
var smokePerSpread = component.SpreadAmount / args.NeighborFreeTiles.Count; var smokePerSpread = component.SpreadAmount / args.NeighborFreeTiles.Count;
component.SpreadAmount -= smokePerSpread; component.SpreadAmount -= smokePerSpread;
foreach (var tile in args.NeighborFreeTiles) foreach (var neighbor in args.NeighborFreeTiles)
{ {
var coords = args.Grid.GridTileToLocal(tile); var coords = neighbor.Grid.GridTileToLocal(neighbor.Tile);
var ent = Spawn(prototype.ID, coords.SnapToGrid()); var ent = Spawn(prototype.ID, coords.SnapToGrid());
var neighborSmoke = EnsureComp<SmokeComponent>(ent); var neighborSmoke = EnsureComp<SmokeComponent>(ent);
neighborSmoke.SpreadAmount = Math.Max(0, smokePerSpread - 1); neighborSmoke.SpreadAmount = Math.Max(0, smokePerSpread - 1);

View File

@@ -28,7 +28,7 @@ public sealed class KudzuSystem : EntitySystem
return; return;
} }
if (args.NeighborFreeTiles.Count == 0 || args.Grid == null) if (args.NeighborFreeTiles.Count == 0)
{ {
RemCompDeferred<EdgeSpreaderComponent>(uid); RemCompDeferred<EdgeSpreaderComponent>(uid);
return; return;
@@ -47,7 +47,7 @@ public sealed class KudzuSystem : EntitySystem
foreach (var neighbor in args.NeighborFreeTiles) foreach (var neighbor in args.NeighborFreeTiles)
{ {
var neighborUid = Spawn(prototype, args.Grid.GridTileToLocal(neighbor)); var neighborUid = Spawn(prototype, neighbor.Grid.GridTileToLocal(neighbor.Tile));
EnsureComp<EdgeSpreaderComponent>(neighborUid); EnsureComp<EdgeSpreaderComponent>(neighborUid);
args.Updates--; args.Updates--;

View File

@@ -10,9 +10,7 @@ namespace Content.Server.Spreader;
[ByRefEvent] [ByRefEvent]
public record struct SpreadNeighborsEvent public record struct SpreadNeighborsEvent
{ {
public MapGridComponent? Grid; public ValueList<(MapGridComponent Grid, Vector2i Tile)> NeighborFreeTiles;
public ValueList<Vector2i> NeighborFreeTiles;
public ValueList<Vector2i> NeighborOccupiedTiles;
public ValueList<EntityUid> Neighbors; public ValueList<EntityUid> Neighbors;
/// <summary> /// <summary>

View File

@@ -2,8 +2,10 @@ using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.EntitySystems;
using Content.Server.NodeContainer; using Content.Server.NodeContainer;
using Content.Server.NodeContainer.NodeGroups; using Content.Server.NodeContainer.NodeGroups;
using Content.Server.Shuttles.Components;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Spreader; using Content.Shared.Spreader;
using Content.Shared.Tag;
using Robust.Shared.Collections; using Robust.Shared.Collections;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Map.Components; using Robust.Shared.Map.Components;
@@ -27,6 +29,8 @@ public sealed class SpreaderSystem : EntitySystem
private readonly List<string> _spreaderGroups = new(); private readonly List<string> _spreaderGroups = new();
private const string IgnoredTag = "SpreaderIgnore";
/// <inheritdoc/> /// <inheritdoc/>
public override void Initialize() public override void Initialize()
{ {
@@ -178,15 +182,11 @@ public sealed class SpreaderSystem : EntitySystem
private void Spread(EntityUid uid, SpreaderNode node, INodeGroup group, ref int updates) private void Spread(EntityUid uid, SpreaderNode node, INodeGroup group, ref int updates)
{ {
GetNeighbors(uid, node.Name, out var freeTiles, out var occupiedTiles, out var neighbors); GetNeighbors(uid, node.Name, out var freeTiles, out _, out var neighbors);
TryComp<MapGridComponent>(Transform(uid).GridUid, out var grid);
var ev = new SpreadNeighborsEvent() var ev = new SpreadNeighborsEvent()
{ {
Grid = grid,
NeighborFreeTiles = freeTiles, NeighborFreeTiles = freeTiles,
NeighborOccupiedTiles = occupiedTiles,
Neighbors = neighbors, Neighbors = neighbors,
Updates = updates, Updates = updates,
}; };
@@ -198,9 +198,9 @@ public sealed class SpreaderSystem : EntitySystem
/// <summary> /// <summary>
/// Gets the neighboring node data for the specified entity and the specified node group. /// Gets the neighboring node data for the specified entity and the specified node group.
/// </summary> /// </summary>
public void GetNeighbors(EntityUid uid, string groupName, out ValueList<Vector2i> freeTiles, out ValueList<Vector2i> occupiedTiles, out ValueList<EntityUid> neighbors) public void GetNeighbors(EntityUid uid, string groupName, out ValueList<(MapGridComponent Grid, Vector2i Tile)> freeTiles, out ValueList<Vector2i> occupiedTiles, out ValueList<EntityUid> neighbors)
{ {
freeTiles = new ValueList<Vector2i>(); freeTiles = new ValueList<(MapGridComponent Grid, Vector2i Tile)>();
occupiedTiles = new ValueList<Vector2i>(); occupiedTiles = new ValueList<Vector2i>();
neighbors = new ValueList<EntityUid>(); neighbors = new ValueList<EntityUid>();
@@ -213,55 +213,90 @@ public sealed class SpreaderSystem : EntitySystem
var tile = grid.TileIndicesFor(transform.Coordinates); var tile = grid.TileIndicesFor(transform.Coordinates);
var nodeQuery = GetEntityQuery<NodeContainerComponent>(); var nodeQuery = GetEntityQuery<NodeContainerComponent>();
var airtightQuery = GetEntityQuery<AirtightComponent>(); var airtightQuery = GetEntityQuery<AirtightComponent>();
var dockQuery = GetEntityQuery<DockingComponent>();
var xformQuery = GetEntityQuery<TransformComponent>();
var tagQuery = GetEntityQuery<TagComponent>();
var blockedAtmosDirs = AtmosDirection.Invalid;
for (var i = 0; i < 4; i++) // Due to docking ports they may not necessarily be opposite directions.
var neighborTiles = new ValueList<(MapGridComponent grid, Vector2i Indices, AtmosDirection OtherDir, AtmosDirection OurDir)>();
// Check if anything on our own tile blocking that direction.
var ourEnts = grid.GetAnchoredEntitiesEnumerator(tile);
while (ourEnts.MoveNext(out var ent))
{ {
var direction = (Direction) (i * 2); // Spread via docks in a special-case.
var neighborPos = SharedMapSystem.GetDirection(tile, direction); if (dockQuery.TryGetComponent(ent, out var dock) &&
dock.Docked &&
xformQuery.TryGetComponent(ent, out var xform) &&
xformQuery.TryGetComponent(dock.DockedWith, out var dockedXform) &&
TryComp<MapGridComponent>(dockedXform.GridUid, out var dockedGrid))
{
neighborTiles.Add((dockedGrid, dockedGrid.CoordinatesToTile(dockedXform.Coordinates), xform.LocalRotation.ToAtmosDirection(), dockedXform.LocalRotation.ToAtmosDirection()));
}
if (!grid.TryGetTileRef(neighborPos, out var tileRef) || tileRef.Tile.IsEmpty) // If we're on a blocked tile work out which directions we can go.
if (!airtightQuery.TryGetComponent(ent, out var airtight) || !airtight.AirBlocked ||
tagQuery.TryGetComponent(ent, out var tags) && tags.Tags.Contains(IgnoredTag))
{
continue; continue;
}
var directionEnumerator = foreach (var value in new[] { AtmosDirection.North, AtmosDirection.East, AtmosDirection.South, AtmosDirection.West})
grid.GetAnchoredEntitiesEnumerator(neighborPos);
var occupied = false;
while (directionEnumerator.MoveNext(out var ent))
{
if (airtightQuery.TryGetComponent(ent, out var airtight) && airtight.AirBlocked)
{
// Check if air direction matters.
var blocked = false;
foreach (var value in new[] { AtmosDirection.North, AtmosDirection.East})
{ {
if ((value & airtight.AirBlockedDirection) == 0x0) if ((value & airtight.AirBlockedDirection) == 0x0)
continue; continue;
var airDirection = value.ToDirection(); blockedAtmosDirs |= value;
var oppositeDirection = value.ToDirection().GetOpposite(); break;
}
if (direction != airDirection && direction != oppositeDirection)
continue;
blocked = true;
break; break;
} }
if (!blocked) // Add the normal neighbors.
for (var i = 0; i < 4; i++)
{
var direction = (Direction) (i * 2);
var atmosDir = direction.ToAtmosDirection();
var neighborPos = SharedMapSystem.GetDirection(tile, direction);
neighborTiles.Add((grid, neighborPos, atmosDir, atmosDir.GetOpposite()));
}
foreach (var (neighborGrid, neighborPos, ourAtmosDir, otherAtmosDir) in neighborTiles)
{
// This tile is blocked to that direction.
if ((blockedAtmosDirs & ourAtmosDir) != 0x0)
continue;
if (!neighborGrid.TryGetTileRef(neighborPos, out var tileRef) || tileRef.Tile.IsEmpty)
continue;
var directionEnumerator =
neighborGrid.GetAnchoredEntitiesEnumerator(neighborPos);
var occupied = false;
while (directionEnumerator.MoveNext(out var ent))
{
if (!airtightQuery.TryGetComponent(ent, out var airtight) || !airtight.AirBlocked ||
tagQuery.TryGetComponent(ent, out var tags) && tags.Tags.Contains(IgnoredTag))
{
continue;
}
if ((airtight.AirBlockedDirection & otherAtmosDir) == 0x0)
continue; continue;
occupied = true; occupied = true;
break; break;
} }
}
if (occupied) if (occupied)
continue; continue;
var oldCount = occupiedTiles.Count; var oldCount = occupiedTiles.Count;
directionEnumerator = directionEnumerator =
grid.GetAnchoredEntitiesEnumerator(neighborPos); neighborGrid.GetAnchoredEntitiesEnumerator(neighborPos);
while (directionEnumerator.MoveNext(out var ent)) while (directionEnumerator.MoveNext(out var ent))
{ {
@@ -277,7 +312,7 @@ public sealed class SpreaderSystem : EntitySystem
} }
if (oldCount == occupiedTiles.Count) if (oldCount == occupiedTiles.Count)
freeTiles.Add(neighborPos); freeTiles.Add((neighborGrid, neighborPos));
} }
} }

View File

@@ -43,10 +43,7 @@
path: /Audio/Machines/airlock_deny.ogg path: /Audio/Machines/airlock_deny.ogg
- type: Airtight - type: Airtight
fixVacuum: true fixVacuum: true
airBlockedDirection: noAirWhenFullyAirBlocked: false
- East
- West
- South
- type: Tag - type: Tag
tags: tags:
- ForceNoFixRotations - ForceNoFixRotations

View File

@@ -22,3 +22,6 @@
- type: Airtight - type: Airtight
noAirWhenFullyAirBlocked: false noAirWhenFullyAirBlocked: false
- type: Clickable - type: Clickable
- type: Tag
tags:
- SpreaderIgnore

View File

@@ -607,6 +607,9 @@
- type: Tag - type: Tag
id: SpeedLoaderRifle id: SpeedLoaderRifle
- type: Tag
id: SpreaderIgnore
- type: Tag - type: Tag
id: StringInstrument id: StringInstrument