From 18a579947ffbe5cca9a687bba4c018fd7e29532f Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Tue, 10 Jan 2023 22:23:49 +1100 Subject: [PATCH] Move gravity to a controller (#3617) --- .../Console/Commands/TestbedCommand.cs | 3 +- .../Physics/Components/Gravity2DComponent.cs | 17 +++ .../Controllers/Gravity2DController.cs | 119 ++++++++++++++++++ .../Shared/Physics/Stack_Test.cs | 5 +- 4 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 Robust.Shared/Physics/Components/Gravity2DComponent.cs create mode 100644 Robust.Shared/Physics/Controllers/Gravity2DController.cs diff --git a/Robust.Server/Console/Commands/TestbedCommand.cs b/Robust.Server/Console/Commands/TestbedCommand.cs index a193695f6..95bd6b3d7 100644 --- a/Robust.Server/Console/Commands/TestbedCommand.cs +++ b/Robust.Server/Console/Commands/TestbedCommand.cs @@ -31,6 +31,7 @@ using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Physics.Collision.Shapes; using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Controllers; using Robust.Shared.Physics.Dynamics; using Robust.Shared.Physics.Dynamics.Joints; using Robust.Shared.Physics.Systems; @@ -117,7 +118,7 @@ namespace Robust.Server.Console.Commands _map.SetMapPaused(mapId, false); var mapUid = _map.GetMapEntityIdOrThrow(mapId); - _ent.GetComponent(mapUid).Gravity = new Vector2(0, -9.8f); + _ent.System().SetGravity(mapUid, new Vector2(0, -9.8f)); shell.ExecuteCommand("aghost"); shell.ExecuteCommand($"tp 0 0 {mapId}"); diff --git a/Robust.Shared/Physics/Components/Gravity2DComponent.cs b/Robust.Shared/Physics/Components/Gravity2DComponent.cs new file mode 100644 index 000000000..bdf69f986 --- /dev/null +++ b/Robust.Shared/Physics/Components/Gravity2DComponent.cs @@ -0,0 +1,17 @@ +using Robust.Shared.GameObjects; +using Robust.Shared.GameStates; +using Robust.Shared.Maths; +using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.ViewVariables; + +namespace Robust.Shared.Physics.Components; + +[RegisterComponent, NetworkedComponent] +public sealed class Gravity2DComponent : Component +{ + /// + /// Applies side-view gravity to the map. + /// + [ViewVariables(VVAccess.ReadWrite), DataField("gravity")] + public Vector2 Gravity; +} diff --git a/Robust.Shared/Physics/Controllers/Gravity2DController.cs b/Robust.Shared/Physics/Controllers/Gravity2DController.cs new file mode 100644 index 000000000..b01fb0fd6 --- /dev/null +++ b/Robust.Shared/Physics/Controllers/Gravity2DController.cs @@ -0,0 +1,119 @@ +using System; +using Robust.Shared.GameObjects; +using Robust.Shared.GameStates; +using Robust.Shared.IoC; +using Robust.Shared.Log; +using Robust.Shared.Map; +using Robust.Shared.Map.Components; +using Robust.Shared.Maths; +using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Dynamics; +using Robust.Shared.Physics.Systems; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; + +namespace Robust.Shared.Physics.Controllers; + +public sealed class Gravity2DController : VirtualController +{ + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; + + private ISawmill _sawmill = default!; + + public override void Initialize() + { + base.Initialize(); + _sawmill = Logger.GetSawmill("physics"); + SubscribeLocalEvent(OnGetState); + SubscribeLocalEvent(OnHandleState); + } + + private void OnGetState(EntityUid uid, Gravity2DComponent component, ref ComponentGetState args) + { + args.State = new Gravity2DComponentState() { Gravity = component.Gravity }; + } + + private void OnHandleState(EntityUid uid, Gravity2DComponent component, ref ComponentHandleState args) + { + if (args.Current is not Gravity2DComponentState state) + return; + + component.Gravity = state.Gravity; + } + + public void SetGravity(EntityUid uid, Vector2 value) + { + if (!HasComp(uid)) + { + _sawmill.Error($"Tried to set 2D gravity for an entity that isn't a map?"); + DebugTools.Assert(false); + return; + } + + var gravity = EnsureComp(uid); + + if (gravity.Gravity.Equals(value)) + return; + + gravity.Gravity = value; + WakeBodiesRecursive(uid, GetEntityQuery(), GetEntityQuery()); + Dirty(gravity); + } + + public void SetGravity(MapId mapId, Vector2 value) + { + var mapUid = _mapManager.GetMapEntityId(mapId); + var gravity = EnsureComp(mapUid); + + if (gravity.Gravity.Equals(value)) + return; + + gravity.Gravity = value; + WakeBodiesRecursive(mapUid, GetEntityQuery(), GetEntityQuery()); + Dirty(gravity); + } + + public override void UpdateBeforeSolve(bool prediction, float frameTime) + { + base.UpdateBeforeSolve(prediction, frameTime); + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var gravity, out var mapComp)) + { + if (gravity.Gravity == Vector2.Zero) + continue; + + foreach (var body in mapComp.AwakeBodies) + { + if (body.BodyType != BodyType.Dynamic || body.IgnoreGravity) + continue; + + _physics.SetLinearVelocity(body, body.LinearVelocity + gravity.Gravity * frameTime); + } + } + } + + private void WakeBodiesRecursive(EntityUid uid, EntityQuery xformQuery, EntityQuery bodyQuery) + { + if (bodyQuery.TryGetComponent(uid, out var body) && + body.BodyType == BodyType.Dynamic) + { + _physics.WakeBody(uid, body); + } + + var xform = xformQuery.GetComponent(uid); + var childEnumerator = xform.ChildEnumerator; + + while (childEnumerator.MoveNext(out var child)) + { + WakeBodiesRecursive(child.Value, xformQuery, bodyQuery); + } + } + + [Serializable, NetSerializable] + private sealed class Gravity2DComponentState : ComponentState + { + public Vector2 Gravity; + } +} diff --git a/Robust.UnitTesting/Shared/Physics/Stack_Test.cs b/Robust.UnitTesting/Shared/Physics/Stack_Test.cs index c325cad07..5cf450dad 100644 --- a/Robust.UnitTesting/Shared/Physics/Stack_Test.cs +++ b/Robust.UnitTesting/Shared/Physics/Stack_Test.cs @@ -34,6 +34,7 @@ using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Physics.Collision.Shapes; using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Controllers; using Robust.Shared.Physics.Dynamics; using Robust.Shared.Physics.Systems; @@ -65,7 +66,7 @@ namespace Robust.UnitTesting.Shared.Physics mapId = mapManager.CreateMap(); EntityUid tempQualifier2 = mapManager.GetMapEntityId(mapId); - entityManager.GetComponent(tempQualifier2).Gravity = new Vector2(0, -9.8f); + entitySystemManager.GetEntitySystem().SetGravity(tempQualifier2, new Vector2(0f, -9.8f)); EntityUid tempQualifier = entityManager.SpawnEntity(null, new MapCoordinates(0, 0, mapId)); var ground = entityManager.AddComponent(tempQualifier); @@ -183,7 +184,7 @@ namespace Robust.UnitTesting.Shared.Physics { mapId = mapManager.CreateMap(); EntityUid tempQualifier2 = mapManager.GetMapEntityId(mapId); - entityManager.GetComponent(tempQualifier2).Gravity = new Vector2(0, -9.8f); + entitySystemManager.GetEntitySystem().SetGravity(tempQualifier2, new Vector2(0f, -9.8f)); EntityUid tempQualifier = entityManager.SpawnEntity(null, new MapCoordinates(0, 0, mapId)); var ground = entityManager.AddComponent(tempQualifier);