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:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user