Content changes for SetTiles change (#37229)

* Content changes for SetTiles change

* Retest with new engine changes

* Derp

* Update for new engine PR changes
This commit is contained in:
Tayrtahn
2025-05-15 06:26:47 -04:00
committed by GitHub
parent 715165f9cc
commit 4dc1c4c3d6
9 changed files with 187 additions and 161 deletions

View File

@@ -81,7 +81,10 @@ public sealed partial class AtmosphereSystem : SharedAtmosphereSystem
private void OnTileChanged(ref TileChangedEvent ev)
{
InvalidateTile(ev.NewTile.GridUid, ev.NewTile.GridIndices);
foreach (var change in ev.Changes)
{
InvalidateTile(ev.Entity.Owner, change.GridIndices);
}
}
private void OnPrototypesReloaded(PrototypesReloadedEventArgs ev)

View File

@@ -23,29 +23,32 @@ public sealed class AutomaticAtmosSystem : EntitySystem
private void OnTileChanged(ref TileChangedEvent ev)
{
// Only if a atmos-holding tile has been added or removed.
// Also, these calls are surprisingly slow.
// TODO: Make tiledefmanager cache the IsSpace property, and turn this lookup-through-two-interfaces into
// TODO: a simple array lookup, as tile IDs are likely contiguous, and there's at most 2^16 possibilities anyway.
var oldSpace = ev.OldTile.IsSpace(_tileDefinitionManager);
var newSpace = ev.NewTile.IsSpace(_tileDefinitionManager);
if (!(oldSpace && !newSpace ||
!oldSpace && newSpace) ||
_atmosphereSystem.HasAtmosphere(ev.Entity))
return;
if (!TryComp<PhysicsComponent>(ev.Entity, out var physics))
return;
// We can't actually count how many tiles there are efficiently, so instead estimate with the mass.
if (physics.Mass / ShuttleSystem.TileMassMultiplier >= 7.0f)
foreach (var change in ev.Changes)
{
AddComp<GridAtmosphereComponent>(ev.Entity);
Log.Info($"Giving grid {ev.Entity} GridAtmosphereComponent.");
// Only if a atmos-holding tile has been added or removed.
// Also, these calls are surprisingly slow.
// TODO: Make tiledefmanager cache the IsSpace property, and turn this lookup-through-two-interfaces into
// TODO: a simple array lookup, as tile IDs are likely contiguous, and there's at most 2^16 possibilities anyway.
var oldSpace = change.OldTile.IsSpace(_tileDefinitionManager);
var newSpace = change.NewTile.IsSpace(_tileDefinitionManager);
if (!(oldSpace && !newSpace ||
!oldSpace && newSpace) ||
_atmosphereSystem.HasAtmosphere(ev.Entity))
continue;
if (!TryComp<PhysicsComponent>(ev.Entity, out var physics))
return;
// We can't actually count how many tiles there are efficiently, so instead estimate with the mass.
if (physics.Mass / ShuttleSystem.TileMassMultiplier >= 7.0f)
{
AddComp<GridAtmosphereComponent>(ev.Entity);
Log.Info($"Giving grid {ev.Entity} GridAtmosphereComponent.");
}
// It's not super important to remove it should the grid become too small again.
// If explosions ever gain the ability to outright shatter grids, do rethink this.
}
// It's not super important to remove it should the grid become too small again.
// If explosions ever gain the ability to outright shatter grids, do rethink this.
}
}

View File

@@ -160,38 +160,41 @@ namespace Content.Server.Decals
private void OnTileChanged(ref TileChangedEvent args)
{
if (!args.NewTile.IsSpace(_tileDefMan))
return;
if (!TryComp(args.Entity, out DecalGridComponent? grid))
return;
var indices = GetChunkIndices(args.NewTile.GridIndices);
var toDelete = new HashSet<uint>();
if (!grid.ChunkCollection.ChunkCollection.TryGetValue(indices, out var chunk))
return;
foreach (var (uid, decal) in chunk.Decals)
foreach (var change in args.Changes)
{
if (new Vector2((int) Math.Floor(decal.Coordinates.X), (int) Math.Floor(decal.Coordinates.Y)) ==
args.NewTile.GridIndices)
if (!change.NewTile.IsSpace(_tileDefMan))
return;
if (!TryComp(args.Entity, out DecalGridComponent? grid))
return;
var indices = GetChunkIndices(change.GridIndices);
var toDelete = new HashSet<uint>();
if (!grid.ChunkCollection.ChunkCollection.TryGetValue(indices, out var chunk))
return;
foreach (var (uid, decal) in chunk.Decals)
{
toDelete.Add(uid);
if (new Vector2((int)Math.Floor(decal.Coordinates.X), (int)Math.Floor(decal.Coordinates.Y)) ==
change.GridIndices)
{
toDelete.Add(uid);
}
}
if (toDelete.Count == 0)
return;
foreach (var decalId in toDelete)
{
grid.DecalIndex.Remove(decalId);
chunk.Decals.Remove(decalId);
}
DirtyChunk(args.Entity, indices, chunk);
if (chunk.Decals.Count == 0)
grid.ChunkCollection.ChunkCollection.Remove(indices);
}
if (toDelete.Count == 0)
return;
foreach (var decalId in toDelete)
{
grid.DecalIndex.Remove(decalId);
chunk.Decals.Remove(decalId);
}
DirtyChunk(args.Entity, indices, chunk);
if (chunk.Decals.Count == 0)
grid.ChunkCollection.ChunkCollection.Remove(indices);
}
private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)

View File

@@ -233,65 +233,66 @@ public sealed partial class ExplosionSystem
/// </summary>
private void OnTileChanged(ref TileChangedEvent ev)
{
// only need to update the grid-edge map if a tile was added or removed from the grid.
if (!ev.NewTile.Tile.IsEmpty && !ev.OldTile.IsEmpty)
return;
if (!TryComp(ev.Entity, out MapGridComponent? grid))
return;
var tileRef = ev.NewTile;
if (!_gridEdges.TryGetValue(tileRef.GridUid, out var edges))
foreach (var change in ev.Changes)
{
edges = new();
_gridEdges[tileRef.GridUid] = edges;
}
// only need to update the grid-edge map if a tile was added or removed from the grid.
if (!change.NewTile.IsEmpty && !change.OldTile.IsEmpty)
return;
if (tileRef.Tile.IsEmpty)
{
// if the tile is empty, it cannot itself be an edge tile.
edges.Remove(tileRef.GridIndices);
if (!TryComp(ev.Entity, out MapGridComponent? grid))
return;
// add any valid neighbours to the list of edge-tiles
if (!_gridEdges.TryGetValue(ev.Entity, out var edges))
{
edges = new();
_gridEdges[ev.Entity] = edges;
}
if (change.NewTile.IsEmpty)
{
// if the tile is empty, it cannot itself be an edge tile.
edges.Remove(change.GridIndices);
// add any valid neighbours to the list of edge-tiles
for (var i = 0; i < NeighbourVectors.Length; i++)
{
var neighbourIndex = change.GridIndices + NeighbourVectors[i];
if (_mapSystem.TryGetTileRef(ev.Entity, grid, neighbourIndex, out var neighbourTile) && !neighbourTile.Tile.IsEmpty)
{
var oppositeDirection = (NeighborFlag)(1 << ((i + 4) % 8));
edges[neighbourIndex] = edges.GetValueOrDefault(neighbourIndex) | oppositeDirection;
}
}
return;
}
// the tile is not empty space, but was previously. So update directly adjacent neighbours, which may no longer
// be edge tiles.
for (var i = 0; i < NeighbourVectors.Length; i++)
{
var neighbourIndex = tileRef.GridIndices + NeighbourVectors[i];
var neighbourIndex = change.GridIndices + NeighbourVectors[i];
if (_mapSystem.TryGetTileRef(ev.Entity, grid, neighbourIndex, out var neighbourTile) && !neighbourTile.Tile.IsEmpty)
if (edges.TryGetValue(neighbourIndex, out var neighborSpaceDir))
{
var oppositeDirection = (NeighborFlag) (1 << ((i + 4) % 8));
edges[neighbourIndex] = edges.GetValueOrDefault(neighbourIndex) | oppositeDirection;
var oppositeDirection = (NeighborFlag)(1 << ((i + 4) % 8));
neighborSpaceDir &= ~oppositeDirection;
if (neighborSpaceDir == NeighborFlag.Invalid)
{
// no longer an edge tile
edges.Remove(neighbourIndex);
continue;
}
edges[neighbourIndex] = neighborSpaceDir;
}
}
return;
// finally check if the new tile is itself an edge tile
if (IsEdge(grid, change.GridIndices, out var spaceDir))
edges.Add(change.GridIndices, spaceDir);
}
// the tile is not empty space, but was previously. So update directly adjacent neighbours, which may no longer
// be edge tiles.
for (var i = 0; i < NeighbourVectors.Length; i++)
{
var neighbourIndex = tileRef.GridIndices + NeighbourVectors[i];
if (edges.TryGetValue(neighbourIndex, out var neighborSpaceDir))
{
var oppositeDirection = (NeighborFlag) (1 << ((i + 4) % 8));
neighborSpaceDir &= ~oppositeDirection;
if (neighborSpaceDir == NeighborFlag.Invalid)
{
// no longer an edge tile
edges.Remove(neighbourIndex);
continue;
}
edges[neighbourIndex] = neighborSpaceDir;
}
}
// finally check if the new tile is itself an edge tile
if (IsEdge(grid, tileRef.GridIndices, out var spaceDir))
edges.Add(tileRef.GridIndices, spaceDir);
}
/// <summary>

View File

@@ -50,10 +50,13 @@ public sealed partial class PathfindingSystem
private void OnTileChange(ref TileChangedEvent ev)
{
if (ev.OldTile.IsEmpty == ev.NewTile.Tile.IsEmpty)
return;
foreach (var change in ev.Changes)
{
if (change.OldTile.IsEmpty == change.NewTile.IsEmpty)
return;
DirtyChunk(ev.Entity, Comp<MapGridComponent>(ev.Entity).GridTileToLocal(ev.NewTile.GridIndices));
DirtyChunk(ev.Entity, _maps.GridTileToLocal(ev.Entity, ev.Entity.Comp, change.GridIndices));
}
}

View File

@@ -101,30 +101,33 @@ public sealed partial class NavMapSystem : SharedNavMapSystem
private void OnTileChanged(ref TileChangedEvent ev)
{
if (!ev.EmptyChanged || !_navQuery.TryComp(ev.NewTile.GridUid, out var navMap))
return;
var tile = ev.NewTile.GridIndices;
var chunkOrigin = SharedMapSystem.GetChunkIndices(tile, ChunkSize);
var chunk = EnsureChunk(navMap, chunkOrigin);
// This could be easily replaced in the future to accommodate diagonal tiles
var relative = SharedMapSystem.GetChunkRelative(tile, ChunkSize);
ref var tileData = ref chunk.TileData[GetTileIndex(relative)];
if (ev.NewTile.IsSpace(_tileDefManager))
foreach (var change in ev.Changes)
{
tileData = 0;
if (PruneEmpty((ev.NewTile.GridUid, navMap), chunk))
if (!change.EmptyChanged || !_navQuery.TryComp(ev.Entity, out var navMap))
return;
}
else
{
tileData = FloorMask;
}
DirtyChunk((ev.NewTile.GridUid, navMap), chunk);
var tile = change.GridIndices;
var chunkOrigin = SharedMapSystem.GetChunkIndices(tile, ChunkSize);
var chunk = EnsureChunk(navMap, chunkOrigin);
// This could be easily replaced in the future to accommodate diagonal tiles
var relative = SharedMapSystem.GetChunkRelative(tile, ChunkSize);
ref var tileData = ref chunk.TileData[GetTileIndex(relative)];
if (change.NewTile.IsSpace(_tileDefManager))
{
tileData = 0;
if (PruneEmpty((ev.Entity, navMap), chunk))
return;
}
else
{
tileData = FloorMask;
}
DirtyChunk((ev.Entity, navMap), chunk);
}
}
private void DirtyChunk(Entity<NavMapComponent> entity, NavMapChunk chunk)

View File

@@ -94,41 +94,45 @@ public sealed class ThrusterSystem : EntitySystem
private void OnShuttleTileChange(EntityUid uid, ShuttleComponent component, ref TileChangedEvent args)
{
// If the old tile was space but the new one isn't then disable all adjacent thrusters
if (args.NewTile.IsSpace(_tileDefManager) || !args.OldTile.IsSpace(_tileDefManager))
return;
var tilePos = args.NewTile.GridIndices;
var grid = Comp<MapGridComponent>(uid);
var xformQuery = GetEntityQuery<TransformComponent>();
var thrusterQuery = GetEntityQuery<ThrusterComponent>();
for (var x = -1; x <= 1; x++)
foreach (var change in args.Changes)
{
for (var y = -1; y <= 1; y++)
// If the old tile was space but the new one isn't then disable all adjacent thrusters
if (change.NewTile.IsSpace(_tileDefManager) || !change.OldTile.IsSpace(_tileDefManager))
return;
var tilePos = change.GridIndices;
var grid = Comp<MapGridComponent>(uid);
var xformQuery = GetEntityQuery<TransformComponent>();
var thrusterQuery = GetEntityQuery<ThrusterComponent>();
for (var x = -1; x <= 1; x++)
{
if (x != 0 && y != 0)
continue;
var checkPos = tilePos + new Vector2i(x, y);
var enumerator = _mapSystem.GetAnchoredEntitiesEnumerator(uid, grid, checkPos);
while (enumerator.MoveNext(out var ent))
for (var y = -1; y <= 1; y++)
{
if (!thrusterQuery.TryGetComponent(ent.Value, out var thruster) || !thruster.RequireSpace)
if (x != 0 && y != 0)
continue;
// Work out if the thruster is facing this direction
var xform = xformQuery.GetComponent(ent.Value);
var direction = xform.LocalRotation.ToWorldVec();
var checkPos = tilePos + new Vector2i(x, y);
var enumerator = _mapSystem.GetAnchoredEntitiesEnumerator(uid, grid, checkPos);
if (new Vector2i((int)direction.X, (int)direction.Y) != new Vector2i(x, y))
continue;
while (enumerator.MoveNext(out var ent))
{
if (!thrusterQuery.TryGetComponent(ent.Value, out var thruster) || !thruster.RequireSpace)
continue;
DisableThruster(ent.Value, thruster, xform.GridUid);
// Work out if the thruster is facing this direction
var xform = xformQuery.GetComponent(ent.Value);
var direction = xform.LocalRotation.ToWorldVec();
if (new Vector2i((int)direction.X, (int)direction.Y) != new Vector2i(x, y))
continue;
DisableThruster(ent.Value, thruster, xform.GridUid);
}
}
}
}
}
private void OnActivateThruster(EntityUid uid, ThrusterComponent component, ActivateInWorldEvent args)

View File

@@ -26,16 +26,19 @@ public sealed class RequiresTileSystem : EntitySystem
if (!TryComp<MapGridComponent>(ev.Entity, out var grid))
return;
var anchored = _maps.GetAnchoredEntitiesEnumerator(ev.Entity, grid, ev.NewTile.GridIndices);
if (anchored.Equals(AnchoredEntitiesEnumerator.Empty))
return;
while (anchored.MoveNext(out var ent))
foreach (var change in ev.Changes)
{
if (!_tilesQuery.HasComponent(ent.Value))
continue;
var anchored = _maps.GetAnchoredEntitiesEnumerator(ev.Entity, grid, change.GridIndices);
if (anchored.Equals(AnchoredEntitiesEnumerator.Empty))
return;
QueueDel(ent.Value);
while (anchored.MoveNext(out var ent))
{
if (!_tilesQuery.HasComponent(ent.Value))
continue;
QueueDel(ent.Value);
}
}
}
}

View File

@@ -122,13 +122,16 @@ namespace Content.Shared.SubFloor
private void OnTileChanged(ref TileChangedEvent args)
{
if (args.OldTile.IsEmpty)
return; // Nothing is anchored here anyways.
foreach (var change in args.Changes)
{
if (change.OldTile.IsEmpty)
return; // Nothing is anchored here anyways.
if (args.NewTile.Tile.IsEmpty)
return; // Anything that was here will be unanchored anyways.
if (change.NewTile.IsEmpty)
return; // Anything that was here will be unanchored anyways.
UpdateTile(args.NewTile.GridUid, args.Entity.Comp, args.NewTile.GridIndices);
UpdateTile(args.Entity, args.Entity.Comp, change.GridIndices);
}
}
/// <summary>