Remove SpreaderNodeGroup (#20230)

* Remove SpreaderNodeGroup

* Fix airtight updates

* more smoke stuff

* more smoke fixes

* wtf is smoke code

* Fix merge

* Fix divide by zero
This commit is contained in:
Leon Friedrich
2023-10-02 07:56:41 +11:00
committed by GitHub
parent 824484c6ac
commit fc034dd9d1
18 changed files with 224 additions and 322 deletions

View File

@@ -1,8 +1,5 @@
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.NodeGroups;
using Content.Server.Shuttles.Components;
using Content.Shared.Atmos;
using Content.Shared.Spreader;
@@ -13,6 +10,7 @@ using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Server.Spreader;
@@ -25,11 +23,20 @@ public sealed class SpreaderSystem : EntitySystem
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;
[Dependency] private readonly NodeContainerSystem _nodeContainer = default!;
private static readonly TimeSpan SpreadCooldown = TimeSpan.FromSeconds(1);
private static readonly TimeSpan SpreadCooldown = TimeSpan.FromSeconds(SpreadCooldownSeconds);
private readonly List<string> _spreaderGroups = new();
/// <summary>
/// Cached maximum number of updates per spreader prototype. This is applied per-grid.
/// </summary>
private Dictionary<string, int> _prototypeUpdates = default!;
/// <summary>
/// Remaining number of updates per grid & prototype.
/// </summary>
private Dictionary<EntityUid, Dictionary<string, int>> _gridUpdates = new();
private const float SpreadCooldownSeconds = 1;
[ValidatePrototypeId<TagPrototype>]
private const string IgnoredTag = "SpreaderIgnore";
@@ -42,6 +49,7 @@ public sealed class SpreaderSystem : EntitySystem
SubscribeLocalEvent<SpreaderGridComponent, EntityUnpausedEvent>(OnGridUnpaused);
SubscribeLocalEvent<EdgeSpreaderComponent, EntityTerminatingEvent>(OnTerminating);
SetupPrototypes();
_prototype.PrototypesReloaded += OnPrototypeReload;
}
@@ -62,21 +70,20 @@ public sealed class SpreaderSystem : EntitySystem
private void SetupPrototypes()
{
_spreaderGroups.Clear();
foreach (var id in _prototype.EnumeratePrototypes<EdgeSpreaderPrototype>())
_prototypeUpdates = new Dictionary<string, int>();
foreach (var proto in _prototype.EnumeratePrototypes<EdgeSpreaderPrototype>())
{
_spreaderGroups.Add(id.ID);
_prototypeUpdates.Add(proto.ID, proto.UpdatesPerSecond);
}
}
private void OnAirtightChanged(ref AirtightChanged ev)
{
var neighbors = GetNeighbors(ev.Entity, ev.Airtight);
var neighbors = GetSpreadableNeighbors(ev.Entity, ev.Airtight, ev.Position);
foreach (var neighbor in neighbors)
{
EnsureComp<EdgeSpreaderComponent>(neighbor);
EnsureComp<ActiveEdgeSpreaderComponent>(neighbor);
}
}
@@ -87,7 +94,17 @@ public sealed class SpreaderSystem : EntitySystem
private void OnGridInit(GridInitializeEvent ev)
{
var comp = EnsureComp<SpreaderGridComponent>(ev.EntityUid);
EnsureComp<SpreaderGridComponent>(ev.EntityUid);
}
private void OnTerminating(EntityUid uid, EdgeSpreaderComponent component, ref EntityTerminatingEvent args)
{
var neighbors = GetSpreadableNeighbors(uid);
foreach (var neighbor in neighbors)
{
EnsureComp<ActiveEdgeSpreaderComponent>(neighbor);
}
}
/// <inheritdoc/>
@@ -96,31 +113,26 @@ public sealed class SpreaderSystem : EntitySystem
var curTime = _timing.CurTime;
// Check which grids are valid for spreading
var spreadable = new ValueList<EntityUid>();
var spreadGrids = EntityQueryEnumerator<SpreaderGridComponent>();
_gridUpdates.Clear();
while (spreadGrids.MoveNext(out var uid, out var grid))
{
if (grid.NextUpdate > curTime)
continue;
spreadable.Add(uid);
_gridUpdates[uid] = _prototypeUpdates.ShallowClone();
grid.NextUpdate += SpreadCooldown;
}
if (spreadable.Count == 0)
if (_gridUpdates.Count == 0)
return;
var query = EntityQueryEnumerator<EdgeSpreaderComponent>();
var nodeQuery = GetEntityQuery<NodeContainerComponent>();
var xformQuery = GetEntityQuery<TransformComponent>();
var gridQuery = GetEntityQuery<SpreaderGridComponent>();
var query = EntityQueryEnumerator<ActiveEdgeSpreaderComponent>();
var xforms = GetEntityQuery<TransformComponent>();
var spreaderQuery = GetEntityQuery<EdgeSpreaderComponent>();
// Each INode group has a certain number of updates
// allowed per SpreadCooldown
var groupUpdates = new Dictionary<INodeGroup, int>();
var spreaders = new List<(EntityUid Uid, EdgeSpreaderComponent Comp)>(Count<EdgeSpreaderComponent>());
var spreaders = new List<(EntityUid Uid, ActiveEdgeSpreaderComponent Comp)>(Count<ActiveEdgeSpreaderComponent>());
// Build a list of all existing Edgespreaders, shuffle them
while (query.MoveNext(out var uid, out var comp))
@@ -134,64 +146,43 @@ public sealed class SpreaderSystem : EntitySystem
// that doesn't meet a few trivial prerequisites
foreach (var (uid, comp) in spreaders)
{
if (!xformQuery.TryGetComponent(uid, out var xform) ||
xform.GridUid == null ||
!gridQuery.HasComponent(xform.GridUid.Value))
// Get xform first, as entity may have been deleted due to interactions triggered by other spreaders.
if (!xforms.TryGetComponent(uid, out var xform))
continue;
if (xform.GridUid == null)
{
RemCompDeferred<EdgeSpreaderComponent>(uid);
RemComp(uid, comp);
continue;
}
foreach (var sGroup in _spreaderGroups)
if (!_gridUpdates.TryGetValue(xform.GridUid.Value, out var groupUpdates))
continue;
if (!spreaderQuery.TryGetComponent(uid, out var spreader))
{
// Get the NodeContainer and Node from every EdgeSpreader entity found
if (!nodeQuery.TryGetComponent(uid, out var nodeContainer))
{
RemCompDeferred<EdgeSpreaderComponent>(uid);
continue;
}
if (!_nodeContainer.TryGetNode<SpreaderNode>(nodeContainer, sGroup, out var node))
{
continue;
}
// Not allowed this tick?
if (node.NodeGroup == null ||
!spreadable.Contains(xform.GridUid.Value))
{
continue;
}
// Try get an integer update rate associated with a node group,
// getting it instead from the spreader itself on failure
if (!groupUpdates.TryGetValue(node.NodeGroup, out var updates))
{
var spreadEv = new SpreadGroupUpdateRate(node.Name);
RaiseLocalEvent(ref spreadEv);
updates = (int) (spreadEv.UpdatesPerSecond * SpreadCooldown / TimeSpan.FromSeconds(1));
}
// "updates" integer dictates the amount of nodes that
// are to be spawned around a NodeGroup
if (updates <= 0)
{
continue;
}
// Edge detection logic is to be handled
// by the subscribing system, see KudzuSystem
// for a simple example
Spread(uid, node, node.NodeGroup, ref updates);
groupUpdates[node.NodeGroup] = updates;
RemComp(uid, comp);
continue;
}
if (!groupUpdates.TryGetValue(spreader.Id, out var updates) || updates < 1)
continue;
// Edge detection logic is to be handled
// by the subscribing system, see KudzuSystem
// for a simple example
Spread(uid, xform, spreader.Id, ref updates);
if (updates < 1)
groupUpdates.Remove(spreader.Id);
else
groupUpdates[spreader.Id] = updates;
}
}
private void Spread(EntityUid uid, SpreaderNode node, INodeGroup group, ref int updates)
private void Spread(EntityUid uid, TransformComponent xform, string prototype, ref int updates)
{
GetNeighbors(uid, node.Name, out var freeTiles, out _, out var neighbors);
GetNeighbors(uid, xform, prototype, out var freeTiles, out _, out var neighbors);
var ev = new SpreadNeighborsEvent()
{
@@ -207,20 +198,19 @@ public sealed class SpreaderSystem : EntitySystem
/// <summary>
/// Gets the neighboring node data for the specified entity and the specified node group.
/// </summary>
public void GetNeighbors(EntityUid uid, string groupName, out ValueList<(MapGridComponent Grid, Vector2i Tile)> freeTiles, out ValueList<Vector2i> occupiedTiles, out ValueList<EntityUid> neighbors)
public void GetNeighbors(EntityUid uid, TransformComponent transform, string prototype, out ValueList<(MapGridComponent Grid, Vector2i Tile)> freeTiles, out ValueList<Vector2i> occupiedTiles, out ValueList<EntityUid> neighbors)
{
// TODO remove occupiedTiles -- its currently unused and just slows this method down.
DebugTools.Assert(_prototype.HasIndex<EdgeSpreaderPrototype>(prototype));
freeTiles = new ValueList<(MapGridComponent Grid, Vector2i Tile)>();
occupiedTiles = new ValueList<Vector2i>();
neighbors = new ValueList<EntityUid>();
if (!EntityManager.TryGetComponent<TransformComponent>(uid, out var transform))
return;
if (!_mapManager.TryGetGrid(transform.GridUid, out var grid))
return;
var tile = grid.TileIndicesFor(transform.Coordinates);
var nodeQuery = GetEntityQuery<NodeContainerComponent>();
var spreaderQuery = GetEntityQuery<EdgeSpreaderComponent>();
var airtightQuery = GetEntityQuery<AirtightComponent>();
var dockQuery = GetEntityQuery<DockingComponent>();
var xformQuery = GetEntityQuery<TransformComponent>();
@@ -309,10 +299,10 @@ public sealed class SpreaderSystem : EntitySystem
while (directionEnumerator.MoveNext(out var ent))
{
if (!nodeQuery.TryGetComponent(ent, out var nodeContainer))
if (!spreaderQuery.TryGetComponent(ent, out var spreader))
continue;
if (!nodeContainer.Nodes.ContainsKey(groupName))
if (spreader.Id != prototype)
continue;
neighbors.Add(ent.Value);
@@ -325,23 +315,38 @@ public sealed class SpreaderSystem : EntitySystem
}
}
public List<EntityUid> GetNeighbors(EntityUid uid, AirtightComponent comp)
/// <summary>
/// Given an entity, this returns a list of all adjacent entities with a <see cref="EdgeSpreaderComponent"/>.
/// </summary>
public List<EntityUid> GetSpreadableNeighbors(EntityUid uid, AirtightComponent? comp = null,
(EntityUid Grid, Vector2i Tile)? position = null)
{
Resolve(uid, ref comp, false);
var neighbors = new List<EntityUid>();
if (!EntityManager.TryGetComponent<TransformComponent>(uid, out var transform))
return neighbors; // how did we get here?
Vector2i tile;
MapGridComponent? grid;
if (!_mapManager.TryGetGrid(transform.GridUid, out var grid))
return neighbors;
if (position == null)
{
var transform = Transform(uid);
if (!_mapManager.TryGetGrid(transform.GridUid, out grid))
return neighbors;
tile = grid.TileIndicesFor(transform.Coordinates);
}
else
{
if (!_mapManager.TryGetGrid(position.Value.Grid, out grid))
return neighbors;
tile = position.Value.Tile;
}
var tile = grid.TileIndicesFor(transform.Coordinates);
var nodeQuery = GetEntityQuery<NodeContainerComponent>();
var spreaderQuery = GetEntityQuery<EdgeSpreaderComponent>();
for (var i = 0; i < Atmospherics.Directions; i++)
{
var direction = (AtmosDirection) (1 << i);
if (!comp.AirBlockedDirection.IsFlagSet(direction))
if (comp != null && !comp.AirBlockedDirection.IsFlagSet(direction))
continue;
var directionEnumerator =
@@ -349,17 +354,9 @@ public sealed class SpreaderSystem : EntitySystem
while (directionEnumerator.MoveNext(out var ent))
{
if (!nodeQuery.TryGetComponent(ent, out var nodeContainer))
continue;
foreach (var name in _spreaderGroups)
{
if (!nodeContainer.Nodes.ContainsKey(name))
continue;
DebugTools.Assert(Transform(ent.Value).Anchored);
if (spreaderQuery.HasComponent(ent))
neighbors.Add(ent.Value);
break;
}
}
}