Make map-grids set TransformComponent.GridUid (#4040)

This commit is contained in:
Leon Friedrich
2023-05-15 14:39:45 +12:00
committed by GitHub
parent 5f5a2bade0
commit b422d8d3ca
10 changed files with 108 additions and 71 deletions

View File

@@ -17,6 +17,7 @@ namespace Robust.Client.GameObjects
base.Initialize();
SubscribeLocalEvent<ClientAppearanceComponent, ComponentInit>(OnAppearanceInit);
SubscribeLocalEvent<ClientAppearanceComponent, ComponentStartup>(OnAppearanceStartup);
SubscribeLocalEvent<ClientAppearanceComponent, ComponentHandleState>(OnAppearanceHandleState);
}
@@ -32,7 +33,10 @@ namespace Robust.Client.GameObjects
{
visual.InitializeEntity(uid);
}
}
private void OnAppearanceStartup(EntityUid uid, ClientAppearanceComponent component, ComponentStartup args)
{
MarkDirty(component);
}
@@ -103,10 +107,9 @@ namespace Robust.Client.GameObjects
var metaQuery = GetEntityQuery<MetaDataComponent>();
while (_queuedUpdates.TryDequeue(out var appearance))
{
if (appearance.Deleted)
continue;
appearance.AppearanceDirty = false;
if (!appearance.Running)
continue;
// If the entity is no longer within the clients PVS, don't bother updating.
if ((metaQuery.GetComponent(appearance.Owner).Flags & MetaDataFlags.Detached) != 0 && !appearance.UpdateDetached)

View File

@@ -16,6 +16,7 @@ using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Players;
using Robust.Shared.Threading;
using Robust.Shared.Timing;
@@ -253,8 +254,8 @@ internal sealed partial class PVSSystem : EntitySystem
private void OnEntityMove(ref MoveEvent ev)
{
// GriddUid is only set after init.
if (ev.Component.LifeStage < ComponentLifeStage.Initialized && ev.Component.GridUid == null)
_transform.SetGridId(ev.Component, ev.Component.FindGridEntityId(GetEntityQuery<TransformComponent>()));
if (!ev.Component._gridInitialized)
_transform.InitializeGridUid(ev.Sender, ev.Component, GetEntityQuery<TransformComponent>(), GetEntityQuery<MapGridComponent>());
// since elements are cached grid-/map-relative, we dont need to update a given grids/maps children
if (ev.Component.GridUid == ev.Sender)

View File

@@ -167,6 +167,9 @@ public abstract class ComponentTreeSystem<TTreeComp, TComp> : EntitySystem
var (comp, xform) = entry;
comp.TreeUpdateQueued = false;
if (!comp.Running)
continue;
if (!_updated.Add(comp.Owner))
continue;

View File

@@ -43,6 +43,8 @@ internal sealed class RecursiveMoveSystem : EntitySystem
TransformComponent xform,
EntityQuery<TransformComponent> xformQuery)
{
// TODO maybe use a c# event? This event gets raised a lot.
// Would probably help with server performance and is also the main bottleneck for replay scrubbing.
var ev = new TreeRecursiveMoveEvent(xform);
RaiseLocalEvent(uid, ref ev);

View File

@@ -94,6 +94,7 @@ namespace Robust.Shared.GameObjects
public MapId MapID { get; internal set; }
internal bool _mapIdInitialized;
internal bool _gridInitialized;
// TODO: Cache this.
/// <summary>
@@ -393,30 +394,6 @@ namespace Robust.Shared.GameObjects
[ViewVariables] internal EntityUid LerpParent { get; set; }
internal EntityUid? FindGridEntityId(EntityQuery<TransformComponent> xformQuery)
{
if (_entMan.HasComponent<MapComponent>(Owner))
{
return null;
}
if (_entMan.HasComponent<MapGridComponent>(Owner))
{
return Owner;
}
if (_parent.IsValid())
{
var parentXform = xformQuery.GetComponent(_parent);
if (parentXform.GridUid != null || parentXform.LifeStage >= ComponentLifeStage.Initialized)
return parentXform.GridUid;
else
return parentXform.FindGridEntityId(xformQuery);
}
return _mapManager.TryFindGridAt(MapID, WorldPosition, out var mapgrid) ? mapgrid.Owner : null;
}
/// <summary>
/// Detaches this entity from its parent.
/// </summary>

View File

@@ -92,11 +92,17 @@ namespace Robust.Shared.GameObjects
SubscribeLocalEvent<MoveEvent>(OnMove);
SubscribeLocalEvent<TransformComponent, PhysicsBodyTypeChangedEvent>(OnBodyTypeChange);
SubscribeLocalEvent<PhysicsComponent, ComponentStartup>(OnBodyStartup);
SubscribeLocalEvent<CollisionChangeEvent>(OnPhysicsUpdate);
EntityManager.EntityInitialized += OnEntityInit;
}
private void OnBodyStartup(EntityUid uid, PhysicsComponent component, ComponentStartup args)
{
UpdatePhysicsBroadphase(uid, Transform(uid), component);
}
public override void Shutdown()
{
base.Shutdown();
@@ -253,6 +259,7 @@ namespace Robust.Shared.GameObjects
// ensure that the cached broadphase is correct.
DebugTools.Assert(_timing.ApplyingState
|| xform.Broadphase == null
|| ev.Body.LifeStage <= ComponentLifeStage.Initializing
|| !xform.Broadphase.Value.IsValid()
|| ((xform.Broadphase.Value.CanCollide == ev.Body.CanCollide)
&& (xform.Broadphase.Value.Static == (ev.Body.BodyType == BodyType.Static))));
@@ -269,6 +276,9 @@ namespace Robust.Shared.GameObjects
private void UpdatePhysicsBroadphase(EntityUid uid, TransformComponent xform, PhysicsComponent body)
{
if (body.LifeStage <= ComponentLifeStage.Initializing)
return;
if (xform.GridUid == uid)
return;
DebugTools.Assert(!_mapManager.IsGrid(uid));

View File

@@ -289,7 +289,6 @@ public abstract partial class SharedMapSystem
private void OnGridAdd(EntityUid uid, MapGridComponent component, ComponentAdd args)
{
// GridID is not set yet so we don't include it.
var msg = new GridAddEvent(uid);
RaiseLocalEvent(uid, msg, true);
}
@@ -310,23 +309,8 @@ public abstract partial class SharedMapSystem
component.LastTileModifiedTick = curTick;
var mapId = xform.MapID;
if (MapManager.HasMapEntity(mapId))
{
var mapUid = MapManager.GetMapEntityIdOrThrow(mapId);
// Mapgrid moment
if (mapUid != uid)
_transform.SetParent(uid, xform, MapManager.GetMapEntityIdOrThrow(mapId), xformQuery);
_transform.SetGridIdNoRecursive(xform, uid);
}
else
{
// Just in case.
_transform.SetGridId(xform, uid, xformQuery);
}
if (xform.MapUid != null && xform.MapUid != uid)
_transform.SetParent(uid, xform, xform.MapUid.Value, xformQuery);
var msg = new GridInitializeEvent(uid);
RaiseLocalEvent(uid, msg, true);

View File

@@ -46,7 +46,7 @@ public abstract partial class SharedTransformSystem
xform._parent = newGridUid;
xform._anchored = true;
SetGridId(xform, newGridUid, xformQuery);
SetGridId(uid, xform, newGridUid, xformQuery);
var reParent = new EntParentChangedMessage(uid, oldGridUid, xform.MapID, xform);
RaiseLocalEvent(uid, ref reParent, true);
// TODO: Ideally shouldn't need to call the moveevent
@@ -241,7 +241,7 @@ public abstract partial class SharedTransformSystem
// Has to be done if _parent is set from ExposeData.
if (component.ParentUid.IsValid())
{
// Note that _children is a SortedSet<EntityUid>,
// Note that _children is a HashSet<EntityUid>,
// so duplicate additions (which will happen) don't matter.
var parentXform = xformQuery.GetComponent(component.ParentUid);
@@ -259,14 +259,14 @@ public abstract partial class SharedTransformSystem
parentXform._children.Add(uid);
}
if (component.GridUid == null)
SetGridId(component, component.FindGridEntityId(xformQuery));
InitializeGridUid(uid, component, xformQuery, GetEntityQuery<MapGridComponent>());
component.MatricesDirty = true;
DebugTools.Assert(component._gridUid == uid || !HasComp<MapGridComponent>(uid));
if (!component._anchored)
return;
DebugTools.Assert(component.ParentUid == component.GridUid && component.ParentUid.IsValid());
MapGridComponent? grid;
// First try find grid via parent:
@@ -292,6 +292,32 @@ public abstract partial class SharedTransformSystem
component._anchored = false;
}
internal void InitializeGridUid(
EntityUid uid,
TransformComponent xform,
EntityQuery<TransformComponent> xformQuery,
EntityQuery<MapGridComponent> gridQuery)
{
// Dont set pre-init, as the map grid component might not have been added yet.
if (xform._gridInitialized || xform.LifeStage < ComponentLifeStage.Initializing)
return;
xform._gridInitialized = true;
DebugTools.Assert(xform.GridUid == null);
if (gridQuery.HasComponent(uid))
{
xform._gridUid = uid;
return;
}
if (!xform._parent.IsValid())
return;
var parentXform = xformQuery.GetComponent(xform._parent);
InitializeGridUid(xform._parent, parentXform, xformQuery, gridQuery);
xform._gridUid = parentXform._gridUid;
}
private void OnCompStartup(EntityUid uid, TransformComponent xform, ComponentStartup args)
{
// TODO PERFORMANCE remove AnchorStateChangedEvent and EntParentChangedMessage events here.
@@ -324,38 +350,43 @@ public abstract partial class SharedTransformSystem
/// <summary>
/// Sets the <see cref="GridId"/> for the transformcomponent without updating its children. Does not Dirty it.
/// </summary>
internal void SetGridIdNoRecursive(TransformComponent xform, EntityUid? gridUid)
internal void SetGridIdNoRecursive(EntityUid uid, TransformComponent xform, EntityUid? gridUid)
{
DebugTools.Assert(gridUid == uid || !HasComp<MapGridComponent>(uid));
if (xform._gridUid == gridUid)
return;
DebugTools.Assert(gridUid == null || HasComp<MapGridComponent>(gridUid));
xform._gridUid = gridUid;
}
/// <summary>
/// Sets the <see cref="GridId"/> for the transformcomponent. Does not Dirty it.
/// </summary>
public void SetGridId(TransformComponent xform, EntityUid? gridId, EntityQuery<TransformComponent>? xformQuery = null)
public void SetGridId(EntityUid uid, TransformComponent xform, EntityUid? gridId, EntityQuery<TransformComponent>? xformQuery = null)
{
if (xform._gridUid == gridId)
if (!xform._gridInitialized || xform._gridUid == gridId || xform.GridUid == uid)
return;
DebugTools.Assert(!HasComp<MapGridComponent>(uid));
DebugTools.Assert(gridId == null || HasComp<MapGridComponent>(gridId));
xformQuery ??= GetEntityQuery<TransformComponent>();
SetGridIdRecursive(xform, gridId, xformQuery.Value);
SetGridIdRecursive(uid, xform, gridId, xformQuery.Value);
}
private static void SetGridIdRecursive(TransformComponent xform, EntityUid? gridId, EntityQuery<TransformComponent> xformQuery)
private void SetGridIdRecursive(EntityUid uid, TransformComponent xform, EntityUid? gridId, EntityQuery<TransformComponent> xformQuery)
{
if (!xform._gridInitialized || xform._gridUid == gridId || xform.GridUid == uid)
return;
DebugTools.Assert(!HasComp<MapGridComponent>(uid));
xform._gridUid = gridId;
var childEnumerator = xform.ChildEnumerator;
while (childEnumerator.MoveNext(out var child))
{
SetGridIdRecursive(xformQuery.GetComponent(child.Value), gridId, xformQuery);
SetGridIdRecursive(child.Value, xformQuery.GetComponent(child.Value), gridId, xformQuery);
}
}
@@ -473,6 +504,7 @@ public abstract partial class SharedTransformSystem
throw new InvalidOperationException($"Attempted to re-parent to a terminating object. Entity: {ToPrettyString(uid)}, new parent: {ToPrettyString(value.EntityId)}");
}
// Check for recursive/circular transform hierarchies.
if (xform.MapUid == newParent.MapUid)
{
var recursiveUid = value.EntityId;
@@ -511,14 +543,23 @@ public abstract partial class SharedTransformSystem
if (newParent != null)
{
xform.ChangeMapId(newParent.MapID, xformQuery);
if (xform.GridUid != uid)
SetGridId(xform, xform.FindGridEntityId(xformQuery), xformQuery);
if (!xform._gridInitialized)
InitializeGridUid(uid, xform, xformQuery, GetEntityQuery<MapGridComponent>());
else
{
if (!newParent._gridInitialized)
InitializeGridUid(value.EntityId, newParent, xformQuery, GetEntityQuery<MapGridComponent>());
SetGridId(uid, xform, newParent.GridUid);
}
}
else
{
xform.ChangeMapId(MapId.Nullspace, xformQuery);
if (xform.GridUid != uid)
SetGridId(xform, null, xformQuery);
if (!xform._gridInitialized)
InitializeGridUid(uid, xform, xformQuery, GetEntityQuery<MapGridComponent>());
else
SetGridId(uid, xform, null, xformQuery);
}
if (xform.Initialized)
@@ -1303,4 +1344,15 @@ public abstract partial class SharedTransformSystem
DebugTools.Assert((MetaData(uid).Flags & MetaDataFlags.InContainer) == 0x0);
}
#endregion
private void OnGridAdd(EntityUid uid, TransformComponent component, GridAddEvent args)
{
if (LifeStage(uid) > EntityLifeStage.Initialized)
{
SetGridId(uid, component, uid, GetEntityQuery<TransformComponent>());
return;
}
component._gridInitialized = true;
component._gridUid = uid;
}
}

View File

@@ -36,6 +36,7 @@ namespace Robust.Shared.GameObjects
SubscribeLocalEvent<TransformComponent, ComponentStartup>(OnCompStartup);
SubscribeLocalEvent<TransformComponent, ComponentGetState>(OnGetState);
SubscribeLocalEvent<TransformComponent, ComponentHandleState>(OnHandleState);
SubscribeLocalEvent<TransformComponent, GridAddEvent>(OnGridAdd);
SubscribeLocalEvent<EntParentChangedMessage>(OnParentChange);
}
@@ -145,8 +146,8 @@ namespace Robust.Shared.GameObjects
return xform.Coordinates;
// GriddUid is only set after init.
if (xform.LifeStage < ComponentLifeStage.Initialized && xform.GridUid == null)
SetGridId(xform, xform.FindGridEntityId(xformQuery));
if (!xform._gridInitialized)
InitializeGridUid(xform.Owner, xform, xformQuery, GetEntityQuery<MapGridComponent>());
// Is the entity directly parented to the grid?
if (xform.GridUid == xform.ParentUid)
@@ -176,8 +177,8 @@ namespace Robust.Shared.GameObjects
var parentXform = xformQuery.GetComponent(parentUid);
// GriddUid is only set after init.
if (parentXform.LifeStage < ComponentLifeStage.Initialized && parentXform.GridUid == null)
SetGridId(parentXform, parentXform.FindGridEntityId(xformQuery));
if (!parentXform._gridInitialized)
InitializeGridUid(parentUid, parentXform, xformQuery, GetEntityQuery<MapGridComponent>());
// Is the entity directly parented to the grid?
if (parentXform.GridUid == parentUid)
@@ -208,8 +209,8 @@ namespace Robust.Shared.GameObjects
return (xform.Coordinates, xform.LocalRotation);
// GriddUid is only set after init.
if (xform.LifeStage < ComponentLifeStage.Initialized && xform.GridUid == null)
SetGridId(xform, xform.FindGridEntityId(xformQuery));
if (!xform._gridInitialized)
InitializeGridUid(xform.Owner, xform, xformQuery, GetEntityQuery<MapGridComponent>());
// Is the entity directly parented to the grid?
if (xform.GridUid == xform.ParentUid)

View File

@@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Robust.Shared.GameObjects;
using Robust.Shared.Log;
using Robust.Shared.Map.Components;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
@@ -16,6 +14,7 @@ internal partial class MapManager
{
public IEnumerable<MapGridComponent> FindGridsIntersecting(MapId mapId, Box2Rotated bounds, bool approx = false)
{
DebugTools.Assert(mapId != MapId.Nullspace);
var aabb = bounds.CalcBoundingBox();
// TODO: We can do slower GJK checks to check if 2 bounds actually intersect, but WYCI.
return FindGridsIntersecting(mapId, aabb, approx);
@@ -23,6 +22,7 @@ internal partial class MapManager
public void FindGridsIntersectingApprox(MapId mapId, Box2 worldAABB, GridCallback callback)
{
DebugTools.Assert(mapId != MapId.Nullspace);
if (!_gridTrees.TryGetValue(mapId, out var gridTree))
return;
@@ -46,6 +46,7 @@ internal partial class MapManager
public void FindGridsIntersectingApprox<TState>(MapId mapId, Box2 worldAABB, ref TState state, GridCallback<TState> callback)
{
DebugTools.Assert(mapId != MapId.Nullspace);
if (!_gridTrees.TryGetValue(mapId, out var gridTree))
return;
@@ -71,6 +72,7 @@ internal partial class MapManager
public IEnumerable<MapGridComponent> FindGridsIntersecting(MapId mapId, Box2 worldAabb, bool approx = false)
{
DebugTools.Assert(mapId != MapId.Nullspace);
if (!_gridTrees.ContainsKey(mapId)) return Enumerable.Empty<MapGridComponent>();
var xformQuery = EntityManager.GetEntityQuery<TransformComponent>();
@@ -89,6 +91,7 @@ internal partial class MapManager
EntityQuery<PhysicsComponent> physicsQuery,
bool approx = false)
{
DebugTools.Assert(mapId != MapId.Nullspace);
if (!_gridTrees.TryGetValue(mapId, out var gridTree)) return Enumerable.Empty<MapGridComponent>();
DebugTools.Assert(grids.Count == 0);
@@ -161,6 +164,7 @@ internal partial class MapManager
EntityQuery<TransformComponent> xformQuery,
[NotNullWhen(true)] out MapGridComponent? grid)
{
DebugTools.Assert(mapId != MapId.Nullspace);
// Need to enlarge the AABB by at least the grid shrinkage size.
var aabb = new Box2(worldPos - 0.2f, worldPos + 0.2f);