Allow protected grids to be repaired (#36989)

* Allow protected grids to be repaired

* Probably implement it

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
Nemanja
2025-05-16 21:54:27 -04:00
committed by GitHub
parent 2f4a364876
commit 6f809d1ad6
5 changed files with 84 additions and 9 deletions

View File

@@ -395,7 +395,7 @@ public sealed class RCDSystem : EntitySystem
if (prototype.Mode == RcdMode.ConstructTile)
{
// Check rule: Tile placement is valid
if (!_floors.CanPlaceTile(gridUid, mapGrid, out var reason))
if (!_floors.CanPlaceTile(gridUid, mapGrid, tile.GridIndices, out var reason))
{
if (popMsgs)
_popup.PopupClient(reason, uid, user);

View File

@@ -4,4 +4,4 @@ namespace Content.Shared.Tiles;
/// Raised directed on a grid when attempting a floor tile placement.
/// </summary>
[ByRefEvent]
public record struct FloorTileAttemptEvent(bool Cancelled);
public record struct FloorTileAttemptEvent(Vector2i GridIndices, bool Cancelled = false);

View File

@@ -126,14 +126,14 @@ public sealed class FloorTileSystem : EntitySystem
if (mapGrid != null)
{
var gridUid = location.EntityId;
var tile = _map.GetTileRef(gridUid, mapGrid, location);
if (!CanPlaceTile(gridUid, mapGrid, out var reason))
if (!CanPlaceTile(gridUid, mapGrid, tile.GridIndices, out var reason))
{
_popup.PopupClient(reason, args.User, args.User);
return;
}
var tile = _map.GetTileRef(gridUid, mapGrid, location);
var baseTurf = (ContentTileDefinition) _tileDefinitionManager[tile.Tile.TypeId];
if (HasBaseTurf(currentTileDefinition, baseTurf.ID))
@@ -182,12 +182,12 @@ public sealed class FloorTileSystem : EntitySystem
_audio.PlayPredicted(placeSound, location, user);
}
public bool CanPlaceTile(EntityUid gridUid, MapGridComponent component, [NotNullWhen(false)] out string? reason)
public bool CanPlaceTile(EntityUid gridUid, MapGridComponent component, Vector2i gridIndices, [NotNullWhen(false)] out string? reason)
{
var ev = new FloorTileAttemptEvent();
var ev = new FloorTileAttemptEvent(gridIndices);
RaiseLocalEvent(gridUid, ref ev);
if (HasComp<ProtectedGridComponent>(gridUid) || ev.Cancelled)
if (ev.Cancelled)
{
reason = Loc.GetString("invalid-floor-placement");
return false;

View File

@@ -5,8 +5,13 @@ namespace Content.Shared.Tiles;
/// <summary>
/// Prevents floor tile updates when attached to a grid.
/// </summary>
[RegisterComponent, NetworkedComponent]
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(ProtectedGridSystem))]
public sealed partial class ProtectedGridComponent : Component
{
/// <summary>
/// A bitmask of all the initial tiles on this grid.
/// </summary>
[DataField, AutoNetworkedField]
public Dictionary<Vector2i, ulong> BaseIndices = new();
}

View File

@@ -0,0 +1,70 @@
using System.Linq;
using Robust.Shared.Map.Components;
using Robust.Shared.Map.Enumerators;
namespace Content.Shared.Tiles;
public sealed class ProtectedGridSystem : EntitySystem
{
[Dependency] private readonly SharedMapSystem _map = default!;
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<ProtectedGridComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<ProtectedGridComponent, FloorTileAttemptEvent>(OnFloorTileAttempt);
}
private void OnMapInit(Entity<ProtectedGridComponent> ent, ref MapInitEvent args)
{
if (!TryComp<MapGridComponent>(ent, out var grid))
return;
// Engine default is currently 16x size chunks which means we can't just easily have 64bit flags.
var chunkEnumerator = new ChunkIndicesEnumerator(grid.LocalAABB, 8);
while (chunkEnumerator.MoveNext(out var chunk))
{
ulong flag = 0;
for (var x = 0; x < 8; x++)
{
for (var y = 0; y < 8; y++)
{
var index = new Vector2i(x + chunk.Value.X * 8, y + chunk.Value.Y * 8);
var tile = _map.GetTileRef(ent.Owner, grid, index);
if (tile.Tile.IsEmpty)
continue;
var data = SharedMapSystem.ToBitmask(new Vector2i(x, y));
flag |= data;
}
}
if (flag == 0)
continue;
ent.Comp.BaseIndices[chunk.Value] = flag;
}
Dirty(ent);
}
private void OnFloorTileAttempt(Entity<ProtectedGridComponent> ent, ref FloorTileAttemptEvent args)
{
var chunkOrigin = SharedMapSystem.GetChunkIndices(args.GridIndices, 8);
if (!ent.Comp.BaseIndices.TryGetValue(chunkOrigin, out var data))
{
args.Cancelled = true;
return;
}
if (SharedMapSystem.FromBitmask(args.GridIndices, data))
{
args.Cancelled = true;
}
}
}