From a0c0a42dc34b0986322ccc138a5a34e0b7b153f4 Mon Sep 17 00:00:00 2001 From: TGRCDev Date: Sun, 10 Nov 2024 00:30:51 -0800 Subject: [PATCH 1/4] Added ZeroGravityArea component for objects with zero-gravity areas around them --- .../Gravity/IsInZeroGravityAreaComponent.cs | 10 ++ .../Gravity/ZeroGravityAreaSystem.cs | 32 ++++++ .../Gravity/IsInZeroGravityAreaComponent.cs | 12 ++ .../Gravity/ZeroGravityAreaComponent.cs | 15 +++ .../Gravity/ZeroGravityAreaSystem.cs | 108 ++++++++++++++++++ .../Gravity/IsInZeroGravityAreaState.cs | 13 +++ .../CosmicCult/Objects/structures.yml | 53 +++++++++ 7 files changed, 243 insertions(+) create mode 100644 Content.Client/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs create mode 100644 Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs create mode 100644 Content.Server/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs create mode 100644 Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs create mode 100644 Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs create mode 100644 Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs create mode 100644 Resources/Prototypes/_Impstation/CosmicCult/Objects/structures.yml diff --git a/Content.Client/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs b/Content.Client/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs new file mode 100644 index 00000000000000..48354482dbe7ad --- /dev/null +++ b/Content.Client/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs @@ -0,0 +1,10 @@ +using Robust.Shared.GameStates; + +namespace Content.Client.Gravity; + +[RegisterComponent, NetworkedComponent] +public sealed partial class IsInZeroGravityAreaComponent : Component +{ + [DataField, ViewVariables(VVAccess.ReadOnly)] + public bool IsWeightless = false; +} diff --git a/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs b/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs new file mode 100644 index 00000000000000..8408024b5ba64d --- /dev/null +++ b/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs @@ -0,0 +1,32 @@ +using Content.Shared.Gravity; +using Robust.Shared.GameStates; + +namespace Content.Client.Gravity; + +public sealed partial class ZeroGravityAreaSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnCheckWeightless); + SubscribeLocalEvent(OnHandleState); + } + + private void OnHandleState(EntityUid uid, IsInZeroGravityAreaComponent comp, ComponentHandleState args) + { + if (args.Current is not IsInZeroGravityAreaState state) + return; + + comp.IsWeightless = state.IsWeightless; + } + + private void OnCheckWeightless(EntityUid uid, IsInZeroGravityAreaComponent comp, ref IsWeightlessEvent args) + { + if (args.Handled) + return; + + args.IsWeightless = comp.IsWeightless; + args.Handled = comp.IsWeightless; + } +} diff --git a/Content.Server/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs b/Content.Server/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs new file mode 100644 index 00000000000000..d27af37a759d6a --- /dev/null +++ b/Content.Server/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs @@ -0,0 +1,12 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Server._Impstation.Gravity; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(ZeroGravityAreaSystem))] +public sealed partial class IsInZeroGravityAreaComponent : Component +{ + [DataField, ViewVariables(VVAccess.ReadOnly)] + public HashSet> AffectingAreas = new(); +} diff --git a/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs b/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs new file mode 100644 index 00000000000000..8144df7abe5ee2 --- /dev/null +++ b/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs @@ -0,0 +1,15 @@ +namespace Content.Server._Impstation.Gravity; + +[RegisterComponent] +[Access(typeof(ZeroGravityAreaSystem))] +public sealed partial class ZeroGravityAreaComponent : Component +{ + [DataField, ViewVariables(VVAccess.ReadWrite)] + public string Fixture = "antiGravity"; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public bool Enabled = true; + + [DataField, ViewVariables(VVAccess.ReadOnly)] + public HashSet> AffectedEntities = new(); +} diff --git a/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs b/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs new file mode 100644 index 00000000000000..19c6c99d3f8dd1 --- /dev/null +++ b/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs @@ -0,0 +1,108 @@ +using System.Linq; +using Content.Shared.Gravity; +using Robust.Shared.GameStates; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Events; + +namespace Content.Server._Impstation.Gravity; + +public sealed partial class ZeroGravityAreaSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnStartCollision); + SubscribeLocalEvent(OnEndCollision); + SubscribeLocalEvent(OnShutdown); + + SubscribeLocalEvent(OnCheckWeightless); + SubscribeLocalEvent(OnGetState); + } + + public bool IsEnabled(EntityUid uid, ZeroGravityAreaComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return false; + + return comp.Enabled; + } + + public void SetEnabled(EntityUid uid, bool enabled, ZeroGravityAreaComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return; + + comp.Enabled = enabled; + } + + private void StartAffecting(Entity area, Entity entity) + { + area.Comp.AffectedEntities.Add(entity); + entity.Comp.AffectingAreas.Add(area); + Dirty(entity); + } + + private void StopAffecting(Entity area, Entity entity) + { + area.Comp.AffectedEntities.Remove(entity); + entity.Comp.AffectingAreas.Remove(area); + Dirty(entity); + } + + private void OnStartCollision(EntityUid uid, ZeroGravityAreaComponent comp, StartCollideEvent args) + { + if ( + args.OurFixtureId == comp.Fixture && + TryComp(args.OtherEntity, out var physics) && + (physics.BodyType & (BodyType.Kinematic | BodyType.Static)) == 0 + ) + { + var antiGrav = EnsureComp(args.OtherEntity); + StartAffecting((uid, comp), (args.OtherEntity, antiGrav)); + } + } + + private void OnEndCollision(EntityUid uid, ZeroGravityAreaComponent comp, EndCollideEvent args) + { + if (args.OurFixtureId == comp.Fixture) + { + if (!TryComp(args.OtherEntity, out var antiGrav)) + return; + + StopAffecting((uid, comp), (args.OtherEntity, antiGrav)); + } + } + + private void OnShutdown(EntityUid uid, ZeroGravityAreaComponent comp, ComponentShutdown args) + { + foreach (var ent in comp.AffectedEntities) + { + ent.Comp.AffectingAreas.Remove((uid, comp)); + Dirty(ent); + } + } + + private bool EntityIsWeightless(Entity ent) + { + return ent.Comp.AffectingAreas.Any(area => area.Comp.Enabled); + } + + private void OnCheckWeightless(EntityUid uid, IsInZeroGravityAreaComponent comp, ref IsWeightlessEvent args) + { + if (args.Handled) + return; + + if (EntityIsWeightless((uid, comp))) + { + args.IsWeightless = true; + args.Handled = true; + } + } + + private void OnGetState(EntityUid uid, IsInZeroGravityAreaComponent comp, ref ComponentGetState args) + { + args.State = new IsInZeroGravityAreaState(EntityIsWeightless((uid, comp))); + } +} diff --git a/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs b/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs new file mode 100644 index 00000000000000..907990efb468c4 --- /dev/null +++ b/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs @@ -0,0 +1,13 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared.Gravity; + +[Serializable, NetSerializable] +public sealed partial class IsInZeroGravityAreaState : ComponentState +{ + public IsInZeroGravityAreaState(bool weightless) + { + IsWeightless = weightless; + } + public bool IsWeightless; +} diff --git a/Resources/Prototypes/_Impstation/CosmicCult/Objects/structures.yml b/Resources/Prototypes/_Impstation/CosmicCult/Objects/structures.yml new file mode 100644 index 00000000000000..e35a591a66d6fd --- /dev/null +++ b/Resources/Prototypes/_Impstation/CosmicCult/Objects/structures.yml @@ -0,0 +1,53 @@ +- type: entity + name: anti-gravity pylon + id: AntiGravityPylon + parent: BaseMachine + description: "A mysterious construct that makes the area around it weightless..." + components: + - type: ZeroGravityArea + fixture: antiGravity + - type: Sprite + sprite: Objects/Misc/Lights/lights.rsi + layers: + - state: floodlight + - state: floodlight_on + shader: unshaded + visible: false + map: [ "light" ] + - type: Physics + canCollide: true + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.2, -0.5, 0.2, 0.5" + density: 50 + mask: + - HighImpassable + antiGravity: + shape: + !type:PhysShapeCircle + radius: 3 + hard: false + layer: + - Impassable + - type: PointLight + radius: 3 + energy: 2 + color: "#7700FFFF" + mask: /Textures/Effects/LightMasks/double_cone.png + - type: RotatingLight + speed: 100 + - type: Anchorable + - type: Damageable + damageContainer: StructuralInorganic + damageModifierSet: Metallic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] From 8944dadef497b70e365ab7312a0e00eaa49a6ca3 Mon Sep 17 00:00:00 2001 From: TGRCDev Date: Sun, 10 Nov 2024 02:17:13 -0800 Subject: [PATCH 2/4] Fixed magboots not working in anti-gravity areas --- .../Gravity/ZeroGravityAreaSystem.cs | 7 +-- .../Gravity/ZeroGravityAreaComponent.cs | 6 +-- .../Gravity/ZeroGravityAreaSystem.cs | 52 +++++++++++-------- .../Gravity/IsInZeroGravityAreaState.cs | 4 +- .../CosmicCult/Objects/structures.yml | 4 +- 5 files changed, 41 insertions(+), 32 deletions(-) diff --git a/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs b/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs index 8408024b5ba64d..94518ec123ad62 100644 --- a/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs +++ b/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs @@ -1,3 +1,4 @@ +using Content.Shared.Clothing; using Content.Shared.Gravity; using Robust.Shared.GameStates; @@ -9,11 +10,11 @@ public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnCheckWeightless); - SubscribeLocalEvent(OnHandleState); + SubscribeLocalEvent(OnCheckWeightless, after: [typeof(SharedMagbootsSystem)]); + SubscribeLocalEvent(OnHandleEntityState); } - private void OnHandleState(EntityUid uid, IsInZeroGravityAreaComponent comp, ComponentHandleState args) + private void OnHandleEntityState(EntityUid uid, IsInZeroGravityAreaComponent comp, ComponentHandleState args) { if (args.Current is not IsInZeroGravityAreaState state) return; diff --git a/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs b/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs index 8144df7abe5ee2..200b89cfc1f70d 100644 --- a/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs +++ b/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs @@ -4,12 +4,12 @@ namespace Content.Server._Impstation.Gravity; [Access(typeof(ZeroGravityAreaSystem))] public sealed partial class ZeroGravityAreaComponent : Component { + [DataField, ViewVariables(VVAccess.ReadOnly)] + public HashSet> AffectedEntities = new(); + [DataField, ViewVariables(VVAccess.ReadWrite)] public string Fixture = "antiGravity"; [DataField, ViewVariables(VVAccess.ReadWrite)] public bool Enabled = true; - - [DataField, ViewVariables(VVAccess.ReadOnly)] - public HashSet> AffectedEntities = new(); } diff --git a/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs b/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs index 19c6c99d3f8dd1..91e1a2a47a4964 100644 --- a/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs +++ b/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs @@ -1,4 +1,5 @@ using System.Linq; +using Content.Shared.Clothing; using Content.Shared.Gravity; using Robust.Shared.GameStates; using Robust.Shared.Physics; @@ -17,8 +18,8 @@ public override void Initialize() SubscribeLocalEvent(OnEndCollision); SubscribeLocalEvent(OnShutdown); - SubscribeLocalEvent(OnCheckWeightless); - SubscribeLocalEvent(OnGetState); + SubscribeLocalEvent(OnCheckWeightless, after: [typeof(SharedMagbootsSystem)]); + SubscribeLocalEvent(OnGetEntityState); } public bool IsEnabled(EntityUid uid, ZeroGravityAreaComponent? comp = null) @@ -35,6 +36,11 @@ public void SetEnabled(EntityUid uid, bool enabled, ZeroGravityAreaComponent? co return; comp.Enabled = enabled; + foreach (var ent in comp.AffectedEntities) + { + // Update entity states to see if they're no longer weightless + Dirty(ent); + } } private void StartAffecting(Entity area, Entity entity) @@ -53,26 +59,28 @@ private void StopAffecting(Entity area, Entity(args.OtherEntity, out var physics) && - (physics.BodyType & (BodyType.Kinematic | BodyType.Static)) == 0 - ) - { - var antiGrav = EnsureComp(args.OtherEntity); - StartAffecting((uid, comp), (args.OtherEntity, antiGrav)); - } + if (args.OurFixtureId != comp.Fixture) + return; + + if (!TryComp(args.OtherEntity, out var physics)) + return; + + if ((physics.BodyType & (BodyType.Kinematic | BodyType.Static)) != 0) + return; + + var antiGrav = EnsureComp(args.OtherEntity); + StartAffecting((uid, comp), (args.OtherEntity, antiGrav)); } private void OnEndCollision(EntityUid uid, ZeroGravityAreaComponent comp, EndCollideEvent args) { - if (args.OurFixtureId == comp.Fixture) - { - if (!TryComp(args.OtherEntity, out var antiGrav)) - return; + if (args.OurFixtureId != comp.Fixture) + return; - StopAffecting((uid, comp), (args.OtherEntity, antiGrav)); - } + if (!TryComp(args.OtherEntity, out var antiGrav)) + return; + + StopAffecting((uid, comp), (args.OtherEntity, antiGrav)); } private void OnShutdown(EntityUid uid, ZeroGravityAreaComponent comp, ComponentShutdown args) @@ -84,9 +92,9 @@ private void OnShutdown(EntityUid uid, ZeroGravityAreaComponent comp, ComponentS } } - private bool EntityIsWeightless(Entity ent) + private bool EntityIsWeightless(IsInZeroGravityAreaComponent ent) { - return ent.Comp.AffectingAreas.Any(area => area.Comp.Enabled); + return ent.AffectingAreas.Any(area => area.Comp.Enabled); } private void OnCheckWeightless(EntityUid uid, IsInZeroGravityAreaComponent comp, ref IsWeightlessEvent args) @@ -94,15 +102,15 @@ private void OnCheckWeightless(EntityUid uid, IsInZeroGravityAreaComponent comp, if (args.Handled) return; - if (EntityIsWeightless((uid, comp))) + if (EntityIsWeightless(comp)) { args.IsWeightless = true; args.Handled = true; } } - private void OnGetState(EntityUid uid, IsInZeroGravityAreaComponent comp, ref ComponentGetState args) + private void OnGetEntityState(EntityUid uid, IsInZeroGravityAreaComponent comp, ref ComponentGetState args) { - args.State = new IsInZeroGravityAreaState(EntityIsWeightless((uid, comp))); + args.State = new IsInZeroGravityAreaState(EntityIsWeightless(comp)); } } diff --git a/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs b/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs index 907990efb468c4..1255f2f07faf7c 100644 --- a/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs +++ b/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs @@ -5,9 +5,9 @@ namespace Content.Shared.Gravity; [Serializable, NetSerializable] public sealed partial class IsInZeroGravityAreaState : ComponentState { - public IsInZeroGravityAreaState(bool weightless) + public IsInZeroGravityAreaState(bool isWeightless) { - IsWeightless = weightless; + IsWeightless = isWeightless; } public bool IsWeightless; } diff --git a/Resources/Prototypes/_Impstation/CosmicCult/Objects/structures.yml b/Resources/Prototypes/_Impstation/CosmicCult/Objects/structures.yml index e35a591a66d6fd..01b4b510e1f56d 100644 --- a/Resources/Prototypes/_Impstation/CosmicCult/Objects/structures.yml +++ b/Resources/Prototypes/_Impstation/CosmicCult/Objects/structures.yml @@ -33,8 +33,8 @@ layer: - Impassable - type: PointLight - radius: 3 - energy: 2 + radius: 4 + energy: 5 color: "#7700FFFF" mask: /Textures/Effects/LightMasks/double_cone.png - type: RotatingLight From 4e981f57a36d5211c6c1bb6ea7ee3a3cfe284f3e Mon Sep 17 00:00:00 2001 From: TGRCDev Date: Sun, 10 Nov 2024 03:30:03 -0800 Subject: [PATCH 3/4] Partially improved prediction on zero gravity areas --- .../Gravity/ZeroGravityAreaComponent.cs | 11 +++++ .../Gravity/ZeroGravityAreaSystem.cs | 45 +++++++++++++++++++ .../Gravity/ZeroGravityAreaComponent.cs | 10 ++--- .../Gravity/ZeroGravityAreaSystem.cs | 8 ++++ .../Gravity/ZeroGravityAreaComponent.cs | 22 +++++++++ 5 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 Content.Client/_Impstation/Gravity/ZeroGravityAreaComponent.cs create mode 100644 Content.Shared/_Impstation/Gravity/ZeroGravityAreaComponent.cs diff --git a/Content.Client/_Impstation/Gravity/ZeroGravityAreaComponent.cs b/Content.Client/_Impstation/Gravity/ZeroGravityAreaComponent.cs new file mode 100644 index 00000000000000..829df3259b8808 --- /dev/null +++ b/Content.Client/_Impstation/Gravity/ZeroGravityAreaComponent.cs @@ -0,0 +1,11 @@ +using Content.Client.Gravity; +using Content.Shared._Impstation.Gravity; +using Robust.Shared.GameStates; + +namespace Content.Client._Impstation.Gravity; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(ZeroGravityAreaSystem))] +public sealed partial class ZeroGravityAreaComponent : SharedZeroGravityAreaComponent +{ +} diff --git a/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs b/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs index 94518ec123ad62..379236ccc065c4 100644 --- a/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs +++ b/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs @@ -1,6 +1,13 @@ +using System.Linq; +using Content.Client._Impstation.Gravity; +using Content.Shared._Impstation.Gravity; using Content.Shared.Clothing; using Content.Shared.Gravity; +using Robust.Client.Physics; using Robust.Shared.GameStates; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Events; namespace Content.Client.Gravity; @@ -12,6 +19,16 @@ public override void Initialize() SubscribeLocalEvent(OnCheckWeightless, after: [typeof(SharedMagbootsSystem)]); SubscribeLocalEvent(OnHandleEntityState); + SubscribeLocalEvent(OnHandleAreaState); + SubscribeLocalEvent(OnStartCollide); + } + + public bool IsEnabled(EntityUid uid, ZeroGravityAreaComponent? comp = null) + { + if (!Resolve(uid, ref comp)) + return false; + + return comp.Enabled; } private void OnHandleEntityState(EntityUid uid, IsInZeroGravityAreaComponent comp, ComponentHandleState args) @@ -22,6 +39,34 @@ private void OnHandleEntityState(EntityUid uid, IsInZeroGravityAreaComponent com comp.IsWeightless = state.IsWeightless; } + private void OnHandleAreaState(EntityUid uid, ZeroGravityAreaComponent comp, ComponentHandleState args) + { + if (args.Current is not ZeroGravityAreaState state) + return; + + comp.Enabled = state.Enabled; + } + + private void OnStartCollide(EntityUid uid, ZeroGravityAreaComponent comp, StartCollideEvent args) + { + var other = args.OtherEntity; + + if (args.OurFixtureId != comp.Fixture) + return; + + if (!TryComp(other, out var physics)) + return; + + if (!physics.Predict || (physics.BodyType & (BodyType.Static | BodyType.Kinematic)) != 0) + return; + + Log.Debug($"Predicting that {args.OtherEntity} enters anti-grav area {uid}"); + + var antiGrav = EnsureComp(other); + antiGrav.IsWeightless = true; + Dirty(other, antiGrav); + } + private void OnCheckWeightless(EntityUid uid, IsInZeroGravityAreaComponent comp, ref IsWeightlessEvent args) { if (args.Handled) diff --git a/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs b/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs index 200b89cfc1f70d..6fab3b1ceee5c8 100644 --- a/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs +++ b/Content.Server/_Impstation/Gravity/ZeroGravityAreaComponent.cs @@ -1,15 +1,11 @@ +using Content.Shared._Impstation.Gravity; + namespace Content.Server._Impstation.Gravity; [RegisterComponent] [Access(typeof(ZeroGravityAreaSystem))] -public sealed partial class ZeroGravityAreaComponent : Component +public sealed partial class ZeroGravityAreaComponent : SharedZeroGravityAreaComponent { [DataField, ViewVariables(VVAccess.ReadOnly)] public HashSet> AffectedEntities = new(); - - [DataField, ViewVariables(VVAccess.ReadWrite)] - public string Fixture = "antiGravity"; - - [DataField, ViewVariables(VVAccess.ReadWrite)] - public bool Enabled = true; } diff --git a/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs b/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs index 91e1a2a47a4964..e993ca4da79eb6 100644 --- a/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs +++ b/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs @@ -1,4 +1,5 @@ using System.Linq; +using Content.Shared._Impstation.Gravity; using Content.Shared.Clothing; using Content.Shared.Gravity; using Robust.Shared.GameStates; @@ -17,6 +18,7 @@ public override void Initialize() SubscribeLocalEvent(OnStartCollision); SubscribeLocalEvent(OnEndCollision); SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnGetAreaState); SubscribeLocalEvent(OnCheckWeightless, after: [typeof(SharedMagbootsSystem)]); SubscribeLocalEvent(OnGetEntityState); @@ -36,6 +38,7 @@ public void SetEnabled(EntityUid uid, bool enabled, ZeroGravityAreaComponent? co return; comp.Enabled = enabled; + Dirty(uid, comp); foreach (var ent in comp.AffectedEntities) { // Update entity states to see if they're no longer weightless @@ -92,6 +95,11 @@ private void OnShutdown(EntityUid uid, ZeroGravityAreaComponent comp, ComponentS } } + private void OnGetAreaState(Entity ent, ref ComponentGetState args) + { + args.State = new ZeroGravityAreaState(ent.Comp); + } + private bool EntityIsWeightless(IsInZeroGravityAreaComponent ent) { return ent.AffectingAreas.Any(area => area.Comp.Enabled); diff --git a/Content.Shared/_Impstation/Gravity/ZeroGravityAreaComponent.cs b/Content.Shared/_Impstation/Gravity/ZeroGravityAreaComponent.cs new file mode 100644 index 00000000000000..7756362b0b4d78 --- /dev/null +++ b/Content.Shared/_Impstation/Gravity/ZeroGravityAreaComponent.cs @@ -0,0 +1,22 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared._Impstation.Gravity; +public abstract partial class SharedZeroGravityAreaComponent : Component +{ + [DataField(readOnly: true), ViewVariables(VVAccess.ReadWrite)] + public string Fixture = "antiGravity"; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public bool Enabled = true; +} + +[Serializable, NetSerializable] +public sealed partial class ZeroGravityAreaState : ComponentState +{ + public ZeroGravityAreaState(SharedZeroGravityAreaComponent comp) + { + Enabled = comp.Enabled; + } + + public bool Enabled; +} From fb77a81b8efb5780c9c2cbf2e33a979526490857 Mon Sep 17 00:00:00 2001 From: TGRCDev Date: Sun, 10 Nov 2024 04:00:43 -0800 Subject: [PATCH 4/4] Utilized some silly bitmask tricks to make zero gravity fields seamless --- .../Gravity/IsInZeroGravityAreaComponent.cs | 20 +++++++++++++++- .../Gravity/ZeroGravityAreaSystem.cs | 23 +++++++++++++++---- .../Gravity/ZeroGravityAreaSystem.cs | 7 +++++- .../Gravity/IsInZeroGravityAreaState.cs | 6 ++--- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/Content.Client/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs b/Content.Client/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs index 48354482dbe7ad..36120b0171ce48 100644 --- a/Content.Client/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs +++ b/Content.Client/_Impstation/Gravity/IsInZeroGravityAreaComponent.cs @@ -5,6 +5,24 @@ namespace Content.Client.Gravity; [RegisterComponent, NetworkedComponent] public sealed partial class IsInZeroGravityAreaComponent : Component { + /// + /// When this number is non-zero, the entity is most likely weightless. + /// + /// + /// This is a bitmask of all the entity IDs of the affecting areas bitwise-OR'd together. + /// Prediction calculation of movement needs to be blistering fast to remain seamless, so I + /// am utilizing some bitwise tricks to try and estimate whether or not the player is being + /// affected by a ZeroGravityArea. + /// + /// When a player enters a ZeroGravityArea, the area's NetEntity ID will be bitwise-OR'd into + /// the fingerprint. + /// When a player leaves a ZeroGravityArea, the fingerprint will be bitwise-AND'ed with the + /// negation of the area's NetEntity ID. + /// This leaves us with an extremely rough approximate idea of whether or not we are still + /// being affected by an area. Theoretically, it should guarantee correctness in the case + /// of two overlapping ZeroGravityAreas, and decently high chance of correctness with + /// three overlapping areas. + /// If there's more, fuck it. I tried. [DataField, ViewVariables(VVAccess.ReadOnly)] - public bool IsWeightless = false; + public int AreaFingerprint = 0; } diff --git a/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs b/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs index 379236ccc065c4..4c52c8ddd8ff69 100644 --- a/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs +++ b/Content.Client/_Impstation/Gravity/ZeroGravityAreaSystem.cs @@ -21,6 +21,7 @@ public override void Initialize() SubscribeLocalEvent(OnHandleEntityState); SubscribeLocalEvent(OnHandleAreaState); SubscribeLocalEvent(OnStartCollide); + SubscribeLocalEvent(OnEndCollide); } public bool IsEnabled(EntityUid uid, ZeroGravityAreaComponent? comp = null) @@ -36,7 +37,7 @@ private void OnHandleEntityState(EntityUid uid, IsInZeroGravityAreaComponent com if (args.Current is not IsInZeroGravityAreaState state) return; - comp.IsWeightless = state.IsWeightless; + comp.AreaFingerprint = state.AreaFingerprint; } private void OnHandleAreaState(EntityUid uid, ZeroGravityAreaComponent comp, ComponentHandleState args) @@ -63,7 +64,21 @@ private void OnStartCollide(EntityUid uid, ZeroGravityAreaComponent comp, StartC Log.Debug($"Predicting that {args.OtherEntity} enters anti-grav area {uid}"); var antiGrav = EnsureComp(other); - antiGrav.IsWeightless = true; + antiGrav.AreaFingerprint |= other.Id; + Dirty(other, antiGrav); + } + + private void OnEndCollide(EntityUid uid, ZeroGravityAreaComponent comp, EndCollideEvent args) + { + var other = args.OtherEntity; + + if (args.OurFixtureId != comp.Fixture) + return; + + if (!TryComp(other, out var antiGrav)) + return; + + antiGrav.AreaFingerprint &= ~GetNetEntity(uid).Id; Dirty(other, antiGrav); } @@ -72,7 +87,7 @@ private void OnCheckWeightless(EntityUid uid, IsInZeroGravityAreaComponent comp, if (args.Handled) return; - args.IsWeightless = comp.IsWeightless; - args.Handled = comp.IsWeightless; + args.IsWeightless = comp.AreaFingerprint != 0; + args.Handled = args.IsWeightless; } } diff --git a/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs b/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs index e993ca4da79eb6..924dd309defe09 100644 --- a/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs +++ b/Content.Server/_Impstation/Gravity/ZeroGravityAreaSystem.cs @@ -119,6 +119,11 @@ private void OnCheckWeightless(EntityUid uid, IsInZeroGravityAreaComponent comp, private void OnGetEntityState(EntityUid uid, IsInZeroGravityAreaComponent comp, ref ComponentGetState args) { - args.State = new IsInZeroGravityAreaState(EntityIsWeightless(comp)); + args.State = new IsInZeroGravityAreaState(comp.AffectingAreas.Aggregate(0, (fingerprint, area) => + { + if (area.Comp.Enabled) + fingerprint |= GetNetEntity(area.Owner).Id; + return fingerprint; + })); } } diff --git a/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs b/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs index 1255f2f07faf7c..640d2a5319d46d 100644 --- a/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs +++ b/Content.Shared/_Impstation/Gravity/IsInZeroGravityAreaState.cs @@ -5,9 +5,9 @@ namespace Content.Shared.Gravity; [Serializable, NetSerializable] public sealed partial class IsInZeroGravityAreaState : ComponentState { - public IsInZeroGravityAreaState(bool isWeightless) + public IsInZeroGravityAreaState(int areaFingerprint) { - IsWeightless = isWeightless; + AreaFingerprint = areaFingerprint; } - public bool IsWeightless; + public int AreaFingerprint; }