mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Combine TileChangedEvents in SetTiles (#5912)
* Combine TileChangedEvents in SetTiles * Raise event after regenerating collision * continue, not return * No need for GetComponent * Swap TileRef for Tile + Vector2i * Estimate size of tileChanges
This commit is contained in:
@@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
@@ -833,7 +834,7 @@ public abstract partial class SharedMapSystem
|
||||
}
|
||||
|
||||
var offset = chunk.GridTileToChunkTile(gridIndices);
|
||||
SetChunkTile(uid, grid, chunk, (ushort)offset.X, (ushort)offset.Y, tile);
|
||||
SetChunkTile(uid, grid, chunk, (ushort)offset.X, (ushort)offset.Y, tile, out _);
|
||||
}
|
||||
|
||||
public void SetTiles(EntityUid uid, MapGridComponent grid, List<(Vector2i GridIndices, Tile Tile)> tiles)
|
||||
@@ -842,6 +843,11 @@ public abstract partial class SharedMapSystem
|
||||
return;
|
||||
|
||||
var modified = new HashSet<MapChunk>(Math.Max(1, tiles.Count / grid.ChunkSize));
|
||||
var tileChanges = new ValueList<TileChangedEntry>(tiles.Count);
|
||||
|
||||
// Suppress sending out events for each tile changed
|
||||
// We're going to send them all out together at the end
|
||||
MapManager.SuppressOnTileChanged = true;
|
||||
|
||||
foreach (var (gridIndices, tile) in tiles)
|
||||
{
|
||||
@@ -859,8 +865,11 @@ public abstract partial class SharedMapSystem
|
||||
|
||||
var offset = chunk.GridTileToChunkTile(gridIndices);
|
||||
chunk.SuppressCollisionRegeneration = true;
|
||||
if (SetChunkTile(uid, grid, chunk, (ushort)offset.X, (ushort)offset.Y, tile))
|
||||
if (SetChunkTile(uid, grid, chunk, (ushort)offset.X, (ushort)offset.Y, tile, out var oldTile))
|
||||
{
|
||||
modified.Add(chunk);
|
||||
tileChanges.Add(new TileChangedEntry(tile, oldTile, offset, gridIndices));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var chunk in modified)
|
||||
@@ -869,6 +878,13 @@ public abstract partial class SharedMapSystem
|
||||
}
|
||||
|
||||
RegenerateCollision(uid, grid, modified);
|
||||
|
||||
// Notify of all tile changes in one event
|
||||
var ev = new TileChangedEvent((uid, grid), tileChanges.ToArray());
|
||||
RaiseLocalEvent(uid, ref ev, true);
|
||||
|
||||
// Back to normal
|
||||
MapManager.SuppressOnTileChanged = false;
|
||||
}
|
||||
|
||||
public TilesEnumerator GetLocalTilesEnumerator(EntityUid uid, MapGridComponent grid, Box2 aabb,
|
||||
|
||||
@@ -14,9 +14,9 @@ public abstract partial class SharedMapSystem
|
||||
/// <param name="xIndex">The X tile index relative to the chunk.</param>
|
||||
/// <param name="yIndex">The Y tile index relative to the chunk.</param>
|
||||
/// <param name="tile">The new tile to insert.</param>
|
||||
internal bool SetChunkTile(EntityUid uid, MapGridComponent grid, MapChunk chunk, ushort xIndex, ushort yIndex, Tile tile)
|
||||
internal bool SetChunkTile(EntityUid uid, MapGridComponent grid, MapChunk chunk, ushort xIndex, ushort yIndex, Tile tile, out Tile oldTile)
|
||||
{
|
||||
if (!chunk.TrySetTile(xIndex, yIndex, tile, out var oldTile, out var shapeChanged))
|
||||
if (!chunk.TrySetTile(xIndex, yIndex, tile, out oldTile, out var shapeChanged))
|
||||
return false;
|
||||
|
||||
var tileIndices = new Vector2i(xIndex, yIndex);
|
||||
|
||||
@@ -173,45 +173,61 @@ namespace Robust.Shared.GameObjects
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for when a single tile on a grid is changed locally or remotely.
|
||||
/// Raised directed at the grid when tiles are changed locally or remotely.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public readonly record struct TileChangedEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of this class.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="TileChangedEvent(Entity{MapGridComponent}, Tile, Tile, Vector2i, Vector2i)"/>
|
||||
public TileChangedEvent(Entity<MapGridComponent> entity, TileRef newTile, Tile oldTile, Vector2i chunkIndex)
|
||||
: this(entity, newTile.Tile, oldTile, chunkIndex, newTile.GridIndices) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of this event for a single changed tile.
|
||||
/// </summary>
|
||||
/// <param name="entity">The grid entity containing the changed tile(s)</param>
|
||||
/// <param name="newTile">New tile that replaced the old one.</param>
|
||||
/// <param name="oldTile">Old tile that was replaced.</param>
|
||||
/// <param name="chunkIndex">The index of the grid-chunk that this tile belongs to.</param>
|
||||
/// <param name="gridIndices">The positional indices of this tile on the grid.</param>
|
||||
public TileChangedEvent(Entity<MapGridComponent> entity, Tile newTile, Tile oldTile, Vector2i chunkIndex, Vector2i gridIndices)
|
||||
{
|
||||
Entity = entity;
|
||||
NewTile = newTile;
|
||||
OldTile = oldTile;
|
||||
ChunkIndex = chunkIndex;
|
||||
Changes = [new TileChangedEntry(newTile, oldTile, chunkIndex, gridIndices)];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Was the tile previously empty or is it now empty.
|
||||
/// Creates a new instance of this event for multiple changed tiles.
|
||||
/// </summary>
|
||||
public bool EmptyChanged => OldTile.IsEmpty != NewTile.Tile.IsEmpty;
|
||||
public TileChangedEvent(Entity<MapGridComponent> entity, TileChangedEntry[] changes)
|
||||
{
|
||||
Entity = entity;
|
||||
Changes = changes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Entity of the grid with the tile-change. TileRef stores the GridId.
|
||||
/// Entity of the grid with the tile-change. TileRef stores the GridId.
|
||||
/// </summary>
|
||||
public readonly Entity<MapGridComponent> Entity;
|
||||
|
||||
/// <summary>
|
||||
/// New tile that replaced the old one.
|
||||
/// An array of all the tiles that were changed.
|
||||
/// </summary>
|
||||
public readonly TileRef NewTile;
|
||||
public readonly TileChangedEntry[] Changes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Data about a single tile that was changed as part of a <see cref="TileChangedEvent"/>.
|
||||
/// </summary>
|
||||
/// <param name="NewTile">New tile that replaced the old one.</param>
|
||||
/// <param name="OldTile">Old tile that was replaced.</param>
|
||||
/// <param name="ChunkIndex">The index of the grid-chunk that this tile belongs to.</param>
|
||||
/// <param name="GridIndices">The positional indices of this tile on the grid.</param>
|
||||
public readonly record struct TileChangedEntry(Tile NewTile, Tile OldTile, Vector2i ChunkIndex, Vector2i GridIndices)
|
||||
{
|
||||
/// <summary>
|
||||
/// Old tile that was replaced.
|
||||
/// Was the tile previously empty or is it now empty.
|
||||
/// </summary>
|
||||
public readonly Tile OldTile;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the grid-chunk that this tile belongs to.
|
||||
/// </summary>
|
||||
public readonly Vector2i ChunkIndex;
|
||||
public bool EmptyChanged => OldTile.IsEmpty != NewTile.IsEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,11 +70,14 @@ namespace Robust.Shared.GameObjects
|
||||
|
||||
private void MapManagerOnTileChanged(ref TileChangedEvent e)
|
||||
{
|
||||
if(e.NewTile.Tile != Tile.Empty)
|
||||
return;
|
||||
foreach (var change in e.Changes)
|
||||
{
|
||||
if(change.NewTile != Tile.Empty)
|
||||
continue;
|
||||
|
||||
// TODO optimize this for when multiple tiles get empties simultaneously (e.g., explosions).
|
||||
DeparentAllEntsOnTile(e.NewTile.GridUid, e.NewTile.GridIndices);
|
||||
// TODO optimize this for when multiple tiles get empties simultaneously (e.g., explosions).
|
||||
DeparentAllEntsOnTile(e.Entity, change.GridIndices);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user