diff --git a/Content.Client/Gravity/GravitySystem.cs b/Content.Client/Gravity/GravitySystem.cs new file mode 100644 index 0000000000..2bcf53d146 --- /dev/null +++ b/Content.Client/Gravity/GravitySystem.cs @@ -0,0 +1,9 @@ +using Content.Shared.Gravity; + +namespace Content.Client.Gravity +{ + internal sealed class GravitySystem : SharedGravitySystem + { + + } +} diff --git a/Content.IntegrationTests/Tests/GravityGridTest.cs b/Content.IntegrationTests/Tests/GravityGridTest.cs index c828324fdb..6e1d3bc859 100644 --- a/Content.IntegrationTests/Tests/GravityGridTest.cs +++ b/Content.IntegrationTests/Tests/GravityGridTest.cs @@ -1,4 +1,4 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Content.Server.Gravity; using Content.Server.Power.Components; using Content.Shared.Coordinates; @@ -62,8 +62,12 @@ namespace Content.IntegrationTests.Tests Assert.That(generatorComponent.Status, Is.EqualTo(GravityGeneratorStatus.On)); - Assert.That(!grid1.HasGravity); - Assert.That(grid2.HasGravity); + var entityMan = IoCManager.Resolve(); + var grid1Entity = entityMan.GetEntity(grid1.GridEntityId); + var grid2Entity = entityMan.GetEntity(grid2.GridEntityId); + + Assert.That(!grid1Entity.HasComponent()); + Assert.That(grid2Entity.HasComponent()); }); await server.WaitIdleAsync(); diff --git a/Content.Server/Gravity/EntitySystems/GravitySystem.cs b/Content.Server/Gravity/EntitySystems/GravitySystem.cs index 406b3b260c..9fbb1776ef 100644 --- a/Content.Server/Gravity/EntitySystems/GravitySystem.cs +++ b/Content.Server/Gravity/EntitySystems/GravitySystem.cs @@ -15,7 +15,7 @@ using Robust.Shared.Random; namespace Content.Server.Gravity.EntitySystems { [UsedImplicitly] - internal sealed class GravitySystem : EntitySystem + internal sealed class GravitySystem : SharedGravitySystem { [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; @@ -29,59 +29,95 @@ namespace Content.Server.Gravity.EntitySystems private float _internalTimer = 0.0f; + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(HandleGravityInitialize); + SubscribeLocalEvent(HandleGeneratorUpdate); + } + + private void HandleGeneratorUpdate(GravityGeneratorUpdateEvent ev) + { + if (ev.GridId == GridId.Invalid) return; + + var gravity = ComponentManager.GetComponent(_mapManager.GetGrid(ev.GridId).GridEntityId); + + if (ev.Status == GravityGeneratorStatus.On) + { + EnableGravity(gravity); + } + else + { + DisableGravity(gravity); + } + } + + private void HandleGravityInitialize(EntityUid uid, GravityComponent component, ComponentInit args) + { + // Incase there's already a generator on the grid we'll just set it now. + var gridId = component.Owner.Transform.GridID; + + foreach (var generator in ComponentManager.EntityQuery(true)) + { + if (generator.Owner.Transform.GridID == gridId && generator.Status == GravityGeneratorStatus.On) + { + component.Enabled = true; + return; + } + } + + component.Enabled = false; + } + public override void Update(float frameTime) { - _internalTimer += frameTime; - var gridsWithGravity = new List(); + // TODO: Pointless iteration, just make both of these event-based PLEASE foreach (var generator in ComponentManager.EntityQuery(true)) { if (generator.NeedsUpdate) { generator.UpdateState(); } - - if (generator.Status == GravityGeneratorStatus.On) - { - gridsWithGravity.Add(generator.Owner.Transform.GridID); - } } - foreach (var grid in _mapManager.GetAllGrids()) + if (_gridsToShake.Count > 0) { - if (grid.HasGravity && !gridsWithGravity.Contains(grid.Index)) + _internalTimer += frameTime; + + if (_internalTimer > 0.2f) { - DisableGravity(grid); - } - else if (!grid.HasGravity && gridsWithGravity.Contains(grid.Index)) - { - EnableGravity(grid); + // TODO: Could just have clients do this themselves via event and save bandwidth. + ShakeGrids(); + _internalTimer -= 0.2f; } } - - if (_internalTimer > 0.2f) + else { - ShakeGrids(); _internalTimer = 0.0f; } } - private void EnableGravity(IMapGrid grid) + private void EnableGravity(GravityComponent comp) { - grid.HasGravity = true; - ScheduleGridToShake(grid.Index, ShakeTimes); + if (comp.Enabled) return; + comp.Enabled = true; - var message = new GravityChangedMessage(grid); + var gridId = comp.Owner.Transform.GridID; + ScheduleGridToShake(gridId, ShakeTimes); + var message = new GravityChangedMessage(gridId, true); RaiseLocalEvent(message); } - private void DisableGravity(IMapGrid grid) + private void DisableGravity(GravityComponent comp) { - grid.HasGravity = false; - ScheduleGridToShake(grid.Index, ShakeTimes); + if (!comp.Enabled) return; + comp.Enabled = false; - var message = new GravityChangedMessage(grid); + var gridId = comp.Owner.Transform.GridID; + ScheduleGridToShake(gridId, ShakeTimes); + var message = new GravityChangedMessage(gridId, false); RaiseLocalEvent(message); } diff --git a/Content.Server/Gravity/EntitySystems/WeightlessSystem.cs b/Content.Server/Gravity/EntitySystems/WeightlessSystem.cs index 9f601434ff..f1c1861175 100644 --- a/Content.Server/Gravity/EntitySystems/WeightlessSystem.cs +++ b/Content.Server/Gravity/EntitySystems/WeightlessSystem.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Content.Server.Alert; using Content.Shared.Alert; using Content.Shared.GameTicking; @@ -40,7 +40,8 @@ namespace Content.Server.Gravity.EntitySystems if (_mapManager.TryGetGrid(status.Owner.Transform.GridID, out var grid)) { - if (grid.HasGravity) + var gridEntity = EntityManager.GetEntity(grid.GridEntityId); + if (gridEntity.HasComponent()) { RemoveWeightless(status); } @@ -64,7 +65,7 @@ namespace Content.Server.Gravity.EntitySystems private void GravityChanged(GravityChangedMessage ev) { - if (!_alerts.TryGetValue(ev.Grid.Index, out var statuses)) + if (!_alerts.TryGetValue(ev.ChangedGridIndex, out var statuses)) { return; } diff --git a/Content.Server/Gravity/GravityGeneratorComponent.cs b/Content.Server/Gravity/GravityGeneratorComponent.cs index 882d5790fe..207f032697 100644 --- a/Content.Server/Gravity/GravityGeneratorComponent.cs +++ b/Content.Server/Gravity/GravityGeneratorComponent.cs @@ -7,6 +7,7 @@ using Content.Shared.Interaction; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.GameObjects; +using Robust.Shared.Map; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; @@ -108,6 +109,9 @@ namespace Content.Server.Gravity { MakeOn(); } + + var msg = new GravityGeneratorUpdateEvent(Owner.Transform.GridID, Status); + Owner.EntityManager.EventBus.RaiseLocalEvent(Owner.Uid, msg); } private void HandleUIMessage(ServerBoundUserInterfaceMessage message) @@ -163,4 +167,16 @@ namespace Content.Server.Gravity _appearance?.SetData(GravityGeneratorVisuals.CoreVisible, true); } } + + public sealed class GravityGeneratorUpdateEvent : EntityEventArgs + { + public GridId GridId { get; } + public GravityGeneratorStatus Status { get; } + + public GravityGeneratorUpdateEvent(GridId gridId, GravityGeneratorStatus status) + { + GridId = gridId; + Status = status; + } + } } diff --git a/Content.Shared/Gravity/GravityChangedMessage.cs b/Content.Shared/Gravity/GravityChangedMessage.cs index 4433701c5b..de07cb39af 100644 --- a/Content.Shared/Gravity/GravityChangedMessage.cs +++ b/Content.Shared/Gravity/GravityChangedMessage.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using Robust.Shared.GameObjects; using Robust.Shared.Map; @@ -6,13 +6,14 @@ namespace Content.Shared.Gravity { public class GravityChangedMessage : EntityEventArgs { - public GravityChangedMessage(IMapGrid grid) + public GravityChangedMessage(GridId changedGridIndex, bool newGravityState) { - Grid = grid; + HasGravity = newGravityState; + ChangedGridIndex = changedGridIndex; } - public IMapGrid Grid { get; } + public GridId ChangedGridIndex { get; } - public bool HasGravity => Grid.HasGravity; + public bool HasGravity { get; } } } diff --git a/Content.Shared/Gravity/GravityComponent.cs b/Content.Shared/Gravity/GravityComponent.cs new file mode 100644 index 0000000000..3dae237516 --- /dev/null +++ b/Content.Shared/Gravity/GravityComponent.cs @@ -0,0 +1,62 @@ +using System; +using Content.Shared.NetIDs; +using Robust.Shared.GameObjects; +using Robust.Shared.Log; +using Robust.Shared.Players; +using Robust.Shared.Serialization; +using Robust.Shared.ViewVariables; + +namespace Content.Shared.Gravity +{ + [RegisterComponent] + public sealed class GravityComponent : Component + { + public override string Name => "Gravity"; + public override uint? NetID => ContentNetIDs.GRAVITY; + + [ViewVariables(VVAccess.ReadWrite)] + public bool Enabled + { + get => _enabled; + set + { + if (_enabled == value) return; + _enabled = value; + if (_enabled) + { + Logger.Info($"Enabled gravity for {Owner}"); + } + else + { + Logger.Info($"Disabled gravity for {Owner}"); + } + Dirty(); + } + } + + private bool _enabled; + + public override ComponentState GetComponentState(ICommonSession player) + { + return new GravityComponentState(_enabled); + } + + public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) + { + base.HandleComponentState(curState, nextState); + if (curState is not GravityComponentState state) return; + Enabled = state.Enabled; + } + + [Serializable, NetSerializable] + protected sealed class GravityComponentState : ComponentState + { + public bool Enabled { get; } + + public GravityComponentState(bool enabled) : base(ContentNetIDs.GRAVITY) + { + Enabled = enabled; + } + } + } +} diff --git a/Content.Shared/Gravity/SharedGravitySystem.cs b/Content.Shared/Gravity/SharedGravitySystem.cs new file mode 100644 index 0000000000..61a5d4870e --- /dev/null +++ b/Content.Shared/Gravity/SharedGravitySystem.cs @@ -0,0 +1,19 @@ +using Robust.Shared.GameObjects; + +namespace Content.Shared.Gravity +{ + public abstract class SharedGravitySystem : EntitySystem + { + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(HandleGridInitialize); + } + + private void HandleGridInitialize(GridInitializedEvent ev) + { + var gridEnt = EntityManager.GetEntity(ev.EntityUid); + gridEnt.EnsureComponent(); + } + } +} diff --git a/Content.Shared/Movement/Components/MovementIgnoreGravityComponent.cs b/Content.Shared/Movement/Components/MovementIgnoreGravityComponent.cs index b444e43543..f206517966 100644 --- a/Content.Shared/Movement/Components/MovementIgnoreGravityComponent.cs +++ b/Content.Shared/Movement/Components/MovementIgnoreGravityComponent.cs @@ -1,4 +1,5 @@ #nullable enable +using Content.Shared.Gravity; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; @@ -14,7 +15,7 @@ namespace Content.Shared.Movement.Components public static class GravityExtensions { - public static bool IsWeightless(this IEntity entity, PhysicsComponent? body = null, EntityCoordinates? coords = null, IMapManager? mapManager = null) + public static bool IsWeightless(this IEntity entity, PhysicsComponent? body = null, EntityCoordinates? coords = null, IMapManager? mapManager = null, IEntityManager? entityManager = null) { if (body == null) entity.TryGetComponent(out body); @@ -34,8 +35,11 @@ namespace Content.Shared.Movement.Components mapManager ??= IoCManager.Resolve(); var grid = mapManager.GetGrid(gridId); + var gridEntityId = grid.GridEntityId; + entityManager ??= IoCManager.Resolve(); + var gridEntity = entityManager.GetEntity(gridEntityId); - if (!grid.HasGravity) + if (!gridEntity.GetComponent().Enabled) { return true; } diff --git a/Content.Shared/NetIDs/ContentNetIDs.cs b/Content.Shared/NetIDs/ContentNetIDs.cs index e4f5c8766e..3a253444d0 100644 --- a/Content.Shared/NetIDs/ContentNetIDs.cs +++ b/Content.Shared/NetIDs/ContentNetIDs.cs @@ -99,6 +99,7 @@ namespace Content.Shared.NetIDs public const uint DISASSEMBLE_ON_ACTIVATE = 1089; public const uint LIGHT_REPLACER = 1090; public const uint SINGULARITY_DISTORTION = 1091; + public const uint GRAVITY = 1092; // Net IDs for integration tests. public const uint PREDICTION_TEST = 10001;