Skip to content

Commit ebb697e

Browse files
Remove references to IComponent.Owner in physics island processing
Basically just converts a bunch of places where PhysicsComponent is being stored to instead store Entity<PhysicsComponent> and fixes the resulting errors
1 parent c4a5752 commit ebb697e

File tree

8 files changed

+56
-52
lines changed

8 files changed

+56
-52
lines changed

Robust.Client/Physics/DebugPhysicsIslandSystem.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ internal sealed class DebugPhysicsIslandSystem : EntitySystem
4747
* This will draw above every body involved in a particular island solve.
4848
*/
4949

50-
public readonly Queue<(TimeSpan Time, List<PhysicsComponent> Bodies)> IslandSolve = new();
50+
public readonly Queue<(TimeSpan Time, List<Entity<PhysicsComponent>> Bodies)> IslandSolve = new();
5151
public const float SolveDuration = 0.1f;
5252

5353
public override void Initialize()

Robust.Client/Physics/PhysicsSystem.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ protected override void Cleanup(PhysicsMapComponent component, float frameTime)
3131
// (and serializing it over the network isn't necessary?)
3232
// This is a client-only problem.
3333
// Also need to suss out having the client build the island anyway and just... not solving it?
34-
foreach (var body in component.AwakeBodies)
34+
foreach (var (uid, body) in component.AwakeBodies)
3535
{
3636
if (!body.SleepingAllowed || body.LinearVelocity.Length() > LinearToleranceSqr / 2f || body.AngularVelocity * body.AngularVelocity > AngularToleranceSqr / 2f) continue;
3737
body.SleepTime += frameTime;
3838
if (body.SleepTime > TimeToSleep)
3939
{
40-
toRemove.Add(new Entity<PhysicsComponent>(body.Owner, body));
40+
toRemove.Add(new Entity<PhysicsComponent>(uid, body));
4141
}
4242
}
4343

@@ -49,19 +49,19 @@ protected override void Cleanup(PhysicsMapComponent component, float frameTime)
4949
base.Cleanup(component, frameTime);
5050
}
5151

52-
protected override void UpdateLerpData(PhysicsMapComponent component, List<PhysicsComponent> bodies, EntityQuery<TransformComponent> xformQuery)
52+
protected override void UpdateLerpData(PhysicsMapComponent component, List<Entity<PhysicsComponent>> bodies, EntityQuery<TransformComponent> xformQuery)
5353
{
5454
foreach (var body in bodies)
5555
{
56-
if (body.BodyType == BodyType.Static ||
56+
if (body.Comp.BodyType == BodyType.Static ||
5757
component.LerpData.TryGetValue(body.Owner, out var lerpData) ||
5858
!xformQuery.TryGetComponent(body.Owner, out var xform) ||
5959
lerpData.ParentUid == xform.ParentUid)
6060
{
6161
continue;
6262
}
6363

64-
component.LerpData[xform.Owner] = (xform.ParentUid, xform.LocalPosition, xform.LocalRotation);
64+
component.LerpData[body.Owner] = (xform.ParentUid, xform.LocalPosition, xform.LocalRotation);
6565
}
6666
}
6767

Robust.Shared/Physics/Dynamics/PhysicsMapComponent.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public sealed partial class PhysicsMapComponent : Component
5151
/// All awake bodies on this map.
5252
/// </summary>
5353
[ViewVariables]
54-
public readonly HashSet<PhysicsComponent> AwakeBodies = new();
54+
public readonly HashSet<Entity<PhysicsComponent>> AwakeBodies = new();
5555

5656
/// <summary>
5757
/// Store last tick's invDT

Robust.Shared/Physics/IslandSolveMessage.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ namespace Robust.Shared.Physics
66
{
77
internal sealed class IslandSolveMessage : EntityEventArgs
88
{
9-
public List<PhysicsComponent> Bodies { get; }
9+
public List<Entity<PhysicsComponent>> Bodies { get; }
1010

11-
public IslandSolveMessage(List<PhysicsComponent> bodies)
11+
public IslandSolveMessage(List<Entity<PhysicsComponent>> bodies)
1212
{
1313
Bodies = bodies;
1414
}

Robust.Shared/Physics/Systems/SharedPhysicsSystem.Island.cs

+42-38
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ public abstract partial class SharedPhysicsSystem
125125
*/
126126
private const int MaxIslands = 256;
127127

128-
private readonly ObjectPool<List<PhysicsComponent>> _islandBodyPool =
129-
new DefaultObjectPool<List<PhysicsComponent>>(new ListPolicy<PhysicsComponent>(), MaxIslands);
128+
private readonly ObjectPool<List<Entity<PhysicsComponent>>> _islandBodyPool =
129+
new DefaultObjectPool<List<Entity<PhysicsComponent>>>(new ListPolicy<Entity<PhysicsComponent>>(), MaxIslands);
130130

131131
private readonly ObjectPool<List<Contact>> _islandContactPool =
132132
new DefaultObjectPool<List<Contact>>(new ListPolicy<Contact>(), MaxIslands);
@@ -140,7 +140,7 @@ public abstract partial class SharedPhysicsSystem
140140
internal record struct IslandData(
141141
int Index,
142142
bool LoneIsland,
143-
List<PhysicsComponent> Bodies,
143+
List<Entity<PhysicsComponent>> Bodies,
144144
List<Contact> Contacts,
145145
List<(Joint Original, Joint Joint)> Joints,
146146
List<(Joint Joint, float Error)> BrokenJoints)
@@ -161,17 +161,17 @@ internal record struct IslandData(
161161
/// </summary>
162162
public int Offset = 0;
163163

164-
public readonly List<PhysicsComponent> Bodies = Bodies;
164+
public readonly List<Entity<PhysicsComponent>> Bodies = Bodies;
165165
public readonly List<Contact> Contacts = Contacts;
166166
public readonly List<(Joint Original, Joint Joint)> Joints = Joints;
167167
public bool PositionSolved = false;
168168
public readonly List<(Joint Joint, float Error)> BrokenJoints = BrokenJoints;
169169
}
170170

171171
// Caching for island generation.
172-
private readonly HashSet<PhysicsComponent> _islandSet = new(64);
173-
private readonly Stack<PhysicsComponent> _bodyStack = new(64);
174-
private readonly List<PhysicsComponent> _awakeBodyList = new(256);
172+
private readonly HashSet<Entity<PhysicsComponent>> _islandSet = new(64);
173+
private readonly Stack<Entity<PhysicsComponent>> _bodyStack = new(64);
174+
private readonly List<Entity<PhysicsComponent>> _awakeBodyList = new(256);
175175

176176
// Config
177177
private bool _warmStarting;
@@ -282,7 +282,7 @@ public void Step(EntityUid uid, PhysicsMapComponent component, float frameTime,
282282

283283
private void ClearForces(PhysicsMapComponent component)
284284
{
285-
foreach (var body in component.AwakeBodies)
285+
foreach (var (_, body) in component.AwakeBodies)
286286
{
287287
// TODO: Netsync
288288
body.Force = Vector2.Zero;
@@ -315,13 +315,12 @@ private void Solve(EntityUid uid, PhysicsMapComponent component, float frameTime
315315
var islandJoints = new List<(Joint Original, Joint Joint)>();
316316

317317
// Build the relevant islands / graphs for all bodies.
318-
foreach (var seed in _awakeBodyList)
318+
foreach (var (seedUid, seed) in _awakeBodyList)
319319
{
320320
// I tried not running prediction for non-contacted entities but unfortunately it looked like shit
321321
// when contact broke so if you want to try that then GOOD LUCK.
322-
if (seed.Island) continue;
323-
324-
var seedUid = seed.Owner;
322+
if (seed.Island)
323+
continue;
325324

326325
if (!metaQuery.TryGetComponent(seedUid, out var metadata))
327326
{
@@ -342,19 +341,21 @@ private void Solve(EntityUid uid, PhysicsMapComponent component, float frameTime
342341
var bodies = _islandBodyPool.Get();
343342
var contacts = _islandContactPool.Get();
344343
var joints = _islandJointPool.Get();
345-
_bodyStack.Push(seed);
344+
_bodyStack.Push((seedUid, seed));
346345

347346
seed.Island = true;
348347

349-
while (_bodyStack.TryPop(out var body))
348+
while (_bodyStack.TryPop(out var bodyEnt))
350349
{
351-
var bodyUid = body.Owner;
350+
var bodyUid = bodyEnt.Owner;
351+
var body = bodyEnt.Comp;
352352

353-
bodies.Add(body);
354-
_islandSet.Add(body);
353+
bodies.Add(bodyEnt);
354+
_islandSet.Add(bodyEnt);
355355

356356
// Static bodies don't propagate islands
357-
if (body.BodyType == BodyType.Static) continue;
357+
if (body.BodyType == BodyType.Static)
358+
continue;
358359

359360
// As static bodies can never be awake (unlike Farseer) we'll set this after the check.
360361
SetAwake(bodyUid, body, true, updateSleepTime: false);
@@ -383,9 +384,10 @@ private void Solve(EntityUid uid, PhysicsMapComponent component, float frameTime
383384
var other = bodyA == body ? bodyB : bodyA;
384385

385386
// Was the other body already added to this island?
386-
if (other.Island) continue;
387+
if (other.Island)
388+
continue;
387389

388-
_bodyStack.Push(other);
390+
_bodyStack.Push(bodyEnt);
389391
other.Island = true;
390392
}
391393

@@ -468,13 +470,13 @@ private void Solve(EntityUid uid, PhysicsMapComponent component, float frameTime
468470

469471
if (!bodyA.Island)
470472
{
471-
_bodyStack.Push(bodyA);
473+
_bodyStack.Push((joint.BodyAUid, bodyA));
472474
bodyA.Island = true;
473475
}
474476

475477
if (!bodyB.Island)
476478
{
477-
_bodyStack.Push(bodyB);
479+
_bodyStack.Push((joint.BodyBUid, bodyB));
478480
bodyB.Island = true;
479481
}
480482
}
@@ -487,7 +489,7 @@ private void Solve(EntityUid uid, PhysicsMapComponent component, float frameTime
487489
// Bodies not touching anything, hence we can just add it to the lone island.
488490
if (contacts.Count == 0 && joints.Count == 0)
489491
{
490-
DebugTools.Assert(bodies.Count == 1 && bodies[0].BodyType != BodyType.Static);
492+
DebugTools.Assert(bodies.Count == 1 && bodies[0].Comp.BodyType != BodyType.Static);
491493
loneIsland.Bodies.Add(bodies[0]);
492494
idx = loneIsland.Index;
493495
}
@@ -501,7 +503,7 @@ private void Solve(EntityUid uid, PhysicsMapComponent component, float frameTime
501503
// Allow static bodies to be re-used in other islands
502504
for (var i = 0; i < bodies.Count; i++)
503505
{
504-
var body = bodies[i];
506+
var body = bodies[i].Comp;
505507

506508
// Static bodies can participate in other islands
507509
if (body.BodyType == BodyType.Static)
@@ -537,8 +539,8 @@ private void ReturnIsland(IslandData island)
537539
{
538540
foreach (var body in island.Bodies)
539541
{
540-
DebugTools.Assert(body.IslandIndex.ContainsKey(island.Index));
541-
body.IslandIndex.Remove(island.Index);
542+
DebugTools.Assert(body.Comp.IslandIndex.ContainsKey(island.Index));
543+
body.Comp.IslandIndex.Remove(island.Index);
542544
}
543545

544546
_islandBodyPool.Return(island.Bodies);
@@ -561,7 +563,7 @@ private void ReturnIsland(IslandData island)
561563

562564
protected virtual void Cleanup(PhysicsMapComponent component, float frameTime)
563565
{
564-
foreach (var body in _islandSet)
566+
foreach (var (_, body) in _islandSet)
565567
{
566568
if (!body.Island || body.Deleted)
567569
{
@@ -679,7 +681,7 @@ private void SolveIslands(EntityUid uid, PhysicsMapComponent component, List<Isl
679681
/// If this is the first time a body has been updated this tick update its position for lerping.
680682
/// Due to substepping we have to check it every time.
681683
/// </summary>
682-
protected virtual void UpdateLerpData(PhysicsMapComponent component, List<PhysicsComponent> bodies, EntityQuery<TransformComponent> xformQuery)
684+
protected virtual void UpdateLerpData(PhysicsMapComponent component, List<Entity<PhysicsComponent>> bodies, EntityQuery<TransformComponent> xformQuery)
683685
{
684686

685687
}
@@ -718,9 +720,9 @@ private void SolveIsland(
718720

719721
for (var i = 0; i < island.Bodies.Count; i++)
720722
{
721-
var body = island.Bodies[i];
723+
var (bodyUid, body) = island.Bodies[i];
722724
var (worldPos, worldRot) =
723-
_transform.GetWorldPositionRotation(xformQuery.GetComponent(body.Owner), xformQuery);
725+
_transform.GetWorldPositionRotation(xformQuery.GetComponent(bodyUid), xformQuery);
724726

725727
var transform = new Transform(worldPos, worldRot);
726728
var position = Physics.Transform.Mul(transform, body.LocalCenter);
@@ -899,7 +901,7 @@ private void SolveIsland(
899901
{
900902
for (var i = 0; i < bodyCount; i++)
901903
{
902-
var body = island.Bodies[i];
904+
var body = island.Bodies[i].Comp;
903905

904906
if (body.BodyType == BodyType.Static) continue;
905907

@@ -930,9 +932,10 @@ private void SolveIsland(
930932

931933
for (var i = 0; i < bodyCount; i++)
932934
{
933-
var body = island.Bodies[i];
935+
var body = island.Bodies[i].Comp;
934936

935-
if (body.BodyType == BodyType.Static) continue;
937+
if (body.BodyType == BodyType.Static)
938+
continue;
936939

937940
if (!body.SleepingAllowed ||
938941
body.AngularVelocity * body.AngularVelocity > data.AngTolSqr ||
@@ -965,16 +968,16 @@ private void SolveIsland(
965968
ArrayPool<ContactPositionConstraint>.Shared.Return(positionConstraints);
966969
}
967970

968-
private void FinalisePositions(int start, int end, int offset, List<PhysicsComponent> bodies, EntityQuery<TransformComponent> xformQuery, Vector2[] positions, float[] angles, Vector2[] solvedPositions, float[] solvedAngles)
971+
private void FinalisePositions(int start, int end, int offset, List<Entity<PhysicsComponent>> bodies, EntityQuery<TransformComponent> xformQuery, Vector2[] positions, float[] angles, Vector2[] solvedPositions, float[] solvedAngles)
969972
{
970973
for (var i = start; i < end; i++)
971974
{
972-
var body = bodies[i];
975+
var (bodyUid, body) = bodies[i];
973976

974977
if (body.BodyType == BodyType.Static)
975978
continue;
976979

977-
var xform = xformQuery.GetComponent(body.Owner);
980+
var xform = xformQuery.GetComponent(bodyUid);
978981
var parentXform = xformQuery.GetComponent(xform.ParentUid);
979982
var (_, parentRot, parentInvMatrix) = parentXform.GetWorldPositionRotationInvMatrix(xformQuery);
980983
var worldRot = (float) (parentRot + xform._localRotation);
@@ -1019,7 +1022,8 @@ private void UpdateBodies(
10191022

10201023
// So technically we don't /need/ to skip static bodies here but it saves us having to check for deferred updates so we'll do it anyway.
10211024
// Plus calcing worldpos can be costly so we skip that too which is nice.
1022-
if (body.BodyType == BodyType.Static) continue;
1025+
if (body.Comp.BodyType == BodyType.Static)
1026+
continue;
10231027

10241028
var uid = body.Owner;
10251029
var position = positions[offset + i];
@@ -1048,7 +1052,7 @@ private void UpdateBodies(
10481052
}
10491053

10501054
if (physicsDirtied)
1051-
Dirty(uid, body);
1055+
Dirty(body);
10521056
}
10531057
}
10541058

Robust.Shared/Physics/Systems/SharedPhysicsSystem.Map.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ internal void AddAwakeBody(EntityUid uid, PhysicsComponent body, PhysicsMapCompo
2929
}
3030

3131
DebugTools.Assert(body.Awake);
32-
map.AwakeBodies.Add(body);
32+
map.AwakeBodies.Add((uid, body));
3333
}
3434

3535
internal void AddAwakeBody(EntityUid uid, PhysicsComponent body, EntityUid mapUid, PhysicsMapComponent? map = null)
@@ -40,7 +40,7 @@ internal void AddAwakeBody(EntityUid uid, PhysicsComponent body, EntityUid mapUi
4040

4141
internal void RemoveSleepBody(EntityUid uid, PhysicsComponent body, PhysicsMapComponent? map = null)
4242
{
43-
map?.AwakeBodies.Remove(body);
43+
map?.AwakeBodies.Remove((uid, body));
4444
}
4545

4646
internal void RemoveSleepBody(EntityUid uid, PhysicsComponent body, EntityUid mapUid, PhysicsMapComponent? map = null)

Robust.Shared/Physics/Systems/SharedPhysicsSystem.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ private void RecursiveMapUpdate(
238238
DebugTools.Assert(body.Awake);
239239
}
240240
else
241-
DebugTools.Assert(oldMap?.AwakeBodies.Contains(body) != true);
241+
DebugTools.Assert(oldMap?.AwakeBodies.Contains((uid, body)) != true);
242242
}
243243

244244
_joints.ClearJoints(uid);

Robust.UnitTesting/Shared/Physics/PhysicsMap_Test.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public void RecursiveMapChange()
4545
physSystem.SetSleepingAllowed(parent, parentBody, false);
4646
fixtureSystem.CreateFixture(parent, "fix1", new Fixture(new PhysShapeCircle(0.5f), 0, 0, false), body: parentBody);
4747
physSystem.WakeBody(parent);
48-
Assert.That(physicsMap.AwakeBodies, Does.Contain(parentBody));
48+
Assert.That(physicsMap.AwakeBodies, Does.Contain(new Entity<PhysicsComponent>(parent, parentBody)));
4949

5050
var child = entManager.SpawnEntity(null, new EntityCoordinates(parent, Vector2.Zero));
5151
var childBody = entManager.AddComponent<PhysicsComponent>(child);
@@ -55,7 +55,7 @@ public void RecursiveMapChange()
5555
fixtureSystem.CreateFixture(child, "fix1", new Fixture(new PhysShapeCircle(0.5f), 0, 0, false), body: childBody);
5656
physSystem.WakeBody(child, body: childBody);
5757

58-
Assert.That(physicsMap.AwakeBodies, Does.Contain(childBody));
58+
Assert.That(physicsMap.AwakeBodies, Does.Contain(new Entity<PhysicsComponent>(child, childBody)));
5959

6060
xformSystem.SetParent(parent, parentXform, mapUid2);
6161

0 commit comments

Comments
 (0)