Files
RobustToolbox/Robust.Shared/GameObjects/Systems/SharedTransformSystem.cs
T

110 lines
3.6 KiB
C#

using System.Collections.Generic;
using System.Linq;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
namespace Robust.Shared.GameObjects
{
public abstract class SharedTransformSystem : EntitySystem
{
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IEntityLookup _entityLookup = default!;
private readonly Queue<MoveEvent> _gridMoves = new();
private readonly Queue<MoveEvent> _otherMoves = new();
public override void Initialize()
{
base.Initialize();
UpdatesOutsidePrediction = true;
_mapManager.TileChanged += MapManagerOnTileChanged;
SubscribeLocalEvent<TransformComponent, EntityDirtyEvent>(OnTransformDirty);
}
private void OnTransformDirty(EntityUid uid, TransformComponent component, ref EntityDirtyEvent args)
{
if (!component.Anchored ||
!component.ParentUid.IsValid() ||
MetaData(uid).EntityLifeStage < EntityLifeStage.Initialized)
return;
// Anchor dirty
// May not even need this in future depending what happens with chunk anchoring (paulVS plz).
var gridComp = EntityManager.GetComponent<IMapGridComponent>(component.ParentUid);
var grid = (IMapGridInternal) gridComp.Grid;
DebugTools.Assert(component.GridID == gridComp.GridIndex);
grid.AnchoredEntDirty(grid.TileIndicesFor(component.Coordinates));
}
public override void Shutdown()
{
_mapManager.TileChanged -= MapManagerOnTileChanged;
base.Shutdown();
}
private void MapManagerOnTileChanged(object? sender, TileChangedEventArgs e)
{
if(e.NewTile.Tile != Tile.Empty)
return;
DeparentAllEntsOnTile(e.NewTile.GridIndex, e.NewTile.GridIndices);
}
/// <summary>
/// De-parents and unanchors all entities on a grid-tile.
/// </summary>
private void DeparentAllEntsOnTile(GridId gridId, Vector2i tileIndices)
{
var mapId = _mapManager.GetGrid(gridId).ParentMapId;
var mapTransform = Transform(_mapManager.GetMapEntityId(mapId));
foreach (var uid in _entityLookup.GetEntitiesIntersecting(gridId, tileIndices).ToList())
{
// Attach parent will automatically set anchored=false;
Transform(uid).AttachParent(mapTransform);
}
}
public void DeferMoveEvent(ref MoveEvent moveEvent)
{
if (EntityManager.HasComponent<IMapGridComponent>(moveEvent.Sender))
_gridMoves.Enqueue(moveEvent);
else
_otherMoves.Enqueue(moveEvent);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
// Process grid moves first.
Process(_gridMoves);
Process(_otherMoves);
void Process(Queue<MoveEvent> queue)
{
while (queue.TryDequeue(out var ev))
{
if (EntityManager.Deleted(ev.Sender))
{
continue;
}
// Hopefully we can remove this when PVS gets updated to not use NaNs
if (!ev.NewPosition.IsValid(EntityManager))
{
continue;
}
RaiseLocalEvent(ev.Sender, ref ev);
}
}
}
}
}