diff --git a/Content.Server/Shuttles/Components/DockingComponent.cs b/Content.Server/Shuttles/Components/DockingComponent.cs index 35c0374d31..bad7a60896 100644 --- a/Content.Server/Shuttles/Components/DockingComponent.cs +++ b/Content.Server/Shuttles/Components/DockingComponent.cs @@ -1,7 +1,8 @@ -using Content.Shared.Shuttles; using Content.Shared.Shuttles.Components; using Robust.Shared.GameObjects; using Robust.Shared.Physics.Dynamics.Joints; +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; namespace Content.Server.Shuttles.Components @@ -10,7 +11,8 @@ namespace Content.Server.Shuttles.Components public sealed class DockingComponent : SharedDockingComponent { [ViewVariables] - public DockingComponent? DockedWith; + [DataField("dockedWith")] + public EntityUid? DockedWith; [ViewVariables] public Joint? DockJoint; diff --git a/Content.Server/Shuttles/EntitySystems/DockingSystem.cs b/Content.Server/Shuttles/EntitySystems/DockingSystem.cs index 771e833db1..0984d3f04b 100644 --- a/Content.Server/Shuttles/EntitySystems/DockingSystem.cs +++ b/Content.Server/Shuttles/EntitySystems/DockingSystem.cs @@ -1,3 +1,4 @@ +using System; using Content.Server.Doors.Components; using Content.Server.Power.Components; using Content.Server.Shuttles.Components; @@ -12,6 +13,7 @@ using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Physics.Collision.Shapes; using Robust.Shared.Physics.Dynamics; +using Robust.Shared.Physics.Dynamics.Joints; using Robust.Shared.Utility; namespace Content.Server.Shuttles.EntitySystems @@ -54,8 +56,8 @@ namespace Content.Server.Shuttles.EntitySystems // TODO: Have it open the UI and have the UI do this. if (!component.Docked && - EntityManager.TryGetComponent(uid, out PhysicsComponent? body) && - EntityManager.TryGetComponent(uid, out TransformComponent? xform)) + TryComp(uid, out PhysicsComponent? body) && + TryComp(uid, out TransformComponent? xform)) { DockingComponent? otherDock = null; @@ -102,7 +104,7 @@ namespace Content.Server.Shuttles.EntitySystems // Assume the docking port itself (and its body) is valid if (!_mapManager.TryGetGrid(dockingXform.GridID, out var grid) || - !EntityManager.HasComponent(grid.GridEntityId)) return null; + !HasComp(grid.GridEntityId)) return null; var transform = body.GetTransform(); var dockingFixture = _fixtureSystem.GetFixtureOrNull(body, DockingFixture); @@ -134,9 +136,9 @@ namespace Content.Server.Shuttles.EntitySystems foreach (var ent in otherGrid.GetAnchoredEntities(enlargedAABB)) { - if (!EntityManager.TryGetComponent(ent, out DockingComponent? otherDocking) || + if (!TryComp(ent, out DockingComponent? otherDocking) || !otherDocking.Enabled || - !EntityManager.TryGetComponent(ent, out PhysicsComponent? otherBody)) continue; + !TryComp(ent, out PhysicsComponent? otherBody)) continue; var otherTransform = otherBody.GetTransform(); var otherDockingFixture = _fixtureSystem.GetFixtureOrNull(otherBody, DockingFixture); @@ -176,12 +178,14 @@ namespace Content.Server.Shuttles.EntitySystems { _jointSystem.RemoveJoint(dockA.DockJoint!); - var dockB = dockA.DockedWith; + var dockBUid = dockA.DockedWith; - if (dockB == null || dockA.DockJoint == null) + if (dockBUid == null || + dockA.DockJoint == null || + !TryComp(dockBUid, out DockingComponent? dockB)) { DebugTools.Assert(false); - Logger.Error("docking", $"Tried to cleanup {(dockA).Owner} but not docked?"); + Logger.Error("docking", $"Tried to cleanup {dockA.Owner} but not docked?"); dockA.DockedWith = null; if (dockA.DockJoint != null) @@ -200,8 +204,8 @@ namespace Content.Server.Shuttles.EntitySystems dockA.DockedWith = null; // If these grids are ever invalid then need to look at fixing ordering for unanchored events elsewhere. - var gridAUid = _mapManager.GetGrid(EntityManager.GetComponent((dockA).Owner).GridID).GridEntityId; - var gridBUid = _mapManager.GetGrid(EntityManager.GetComponent((dockB).Owner).GridID).GridEntityId; + var gridAUid = _mapManager.GetGrid(EntityManager.GetComponent(dockA.Owner).GridID).GridEntityId; + var gridBUid = _mapManager.GetGrid(EntityManager.GetComponent(dockB.Owner).GridID).GridEntityId; var msg = new UndockEvent { @@ -211,8 +215,8 @@ namespace Content.Server.Shuttles.EntitySystems GridBUid = gridBUid, }; - EntityManager.EventBus.RaiseLocalEvent((dockA).Owner, msg, false); - EntityManager.EventBus.RaiseLocalEvent((dockB).Owner, msg, false); + EntityManager.EventBus.RaiseLocalEvent(dockA.Owner, msg, false); + EntityManager.EventBus.RaiseLocalEvent(dockB.Owner, msg, false); EntityManager.EventBus.RaiseEvent(EventSource.Local, msg); } @@ -222,6 +226,19 @@ namespace Content.Server.Shuttles.EntitySystems if (!EntityManager.GetComponent(uid).Anchored) return; EnableDocking(uid, component); + + // This little gem is for docking deserialization + if (component.DockedWith != null) + { + // They're still initialising so we'll just wait for both to be ready. + if (MetaData(component.DockedWith.Value).EntityLifeStage < EntityLifeStage.Initialized) return; + + var otherDock = EntityManager.GetComponent(component.DockedWith.Value); + DebugTools.Assert(otherDock.DockedWith != null); + + Dock(component, otherDock); + DebugTools.Assert(component.Docked && otherDock.Docked); + } } private void OnAnchorChange(EntityUid uid, DockingComponent component, ref AnchorStateChangedEvent args) @@ -238,6 +255,9 @@ namespace Content.Server.Shuttles.EntitySystems private void OnPowerChange(EntityUid uid, DockingComponent component, PowerChangedEvent args) { + // This is because power can change during startup for and undock + if (MetaData(uid).EntityLifeStage < EntityLifeStage.MapInitialized) return; + if (args.Powered) { EnableDocking(uid, component); @@ -259,7 +279,7 @@ namespace Content.Server.Shuttles.EntitySystems Undock(component); } - if (!EntityManager.TryGetComponent(uid, out PhysicsComponent? physicsComponent)) + if (!TryComp(uid, out PhysicsComponent? physicsComponent)) { return; } @@ -272,7 +292,7 @@ namespace Content.Server.Shuttles.EntitySystems if (component.Enabled) return; - if (!EntityManager.TryGetComponent(uid, out PhysicsComponent? physicsComponent)) + if (!TryComp(uid, out PhysicsComponent? physicsComponent)) return; component.Enabled = true; @@ -308,8 +328,8 @@ namespace Content.Server.Shuttles.EntitySystems // We could also potentially use a prismatic joint? Depending if we want clamps that can extend or whatever - var dockAXform = EntityManager.GetComponent((dockA).Owner); - var dockBXform = EntityManager.GetComponent((dockB).Owner); + var dockAXform = EntityManager.GetComponent(dockA.Owner); + var dockBXform = EntityManager.GetComponent(dockB.Owner); var gridA = _mapManager.GetGrid(dockAXform.GridID).GridEntityId; var gridB = _mapManager.GetGrid(dockBXform.GridID).GridEntityId; @@ -324,7 +344,8 @@ namespace Content.Server.Shuttles.EntitySystems // These need playing around with // Could also potentially have collideconnected false and stiffness 0 but it was a bit more suss??? - var joint = _jointSystem.CreateWeldJoint(gridA, gridB, DockingJoint + (dockA).Owner); + + var joint = _jointSystem.GetOrCreateWeldJoint(gridA, gridB, DockingJoint + dockA.Owner); var gridAXform = EntityManager.GetComponent(gridA); var gridBXform = EntityManager.GetComponent(gridB); @@ -339,18 +360,18 @@ namespace Content.Server.Shuttles.EntitySystems joint.Stiffness = stiffness; joint.Damping = damping; - dockA.DockedWith = dockB; - dockB.DockedWith = dockA; + dockA.DockedWith = dockB.Owner; + dockB.DockedWith = dockA.Owner; dockA.DockJoint = joint; dockB.DockJoint = joint; - if (EntityManager.TryGetComponent((dockA).Owner, out ServerDoorComponent? doorA)) + if (TryComp(dockA.Owner, out ServerDoorComponent? doorA)) { doorA.ChangeAirtight = false; doorA.Open(); } - if (EntityManager.TryGetComponent((dockB).Owner, out ServerDoorComponent? doorB)) + if (TryComp(dockB.Owner, out ServerDoorComponent? doorB)) { doorB.ChangeAirtight = false; doorB.Open(); @@ -364,8 +385,8 @@ namespace Content.Server.Shuttles.EntitySystems GridBUid = gridB, }; - EntityManager.EventBus.RaiseLocalEvent((dockA).Owner, msg, false); - EntityManager.EventBus.RaiseLocalEvent((dockB).Owner, msg, false); + EntityManager.EventBus.RaiseLocalEvent(dockA.Owner, msg, false); + EntityManager.EventBus.RaiseLocalEvent(dockB.Owner, msg, false); EntityManager.EventBus.RaiseEvent(EventSource.Local, msg); } @@ -374,10 +395,12 @@ namespace Content.Server.Shuttles.EntitySystems /// private void TryDock(DockingComponent dockA, DockingComponent dockB) { - if (!EntityManager.TryGetComponent((dockA).Owner, out PhysicsComponent? bodyA) || - !EntityManager.TryGetComponent((dockB).Owner, out PhysicsComponent? bodyB) || + if (!TryComp(dockA.Owner, out PhysicsComponent? bodyA) || + !TryComp(dockB.Owner, out PhysicsComponent? bodyB) || !dockA.Enabled || - !dockB.Enabled) + !dockB.Enabled || + dockA.DockedWith != null || + dockB.DockedWith != null) { return; } @@ -425,13 +448,13 @@ namespace Content.Server.Shuttles.EntitySystems return; } - if (EntityManager.TryGetComponent((dock).Owner, out ServerDoorComponent? doorA)) + if (TryComp(dock.Owner, out ServerDoorComponent? doorA)) { doorA.ChangeAirtight = true; doorA.Close(); } - if (EntityManager.TryGetComponent((dock.DockedWith).Owner, out ServerDoorComponent? doorB)) + if (TryComp(dock.DockedWith, out ServerDoorComponent? doorB)) { doorB.ChangeAirtight = true; doorB.Close();