Gravity well improvements (#35027)

* Gravity well improvements

- Fixed persistence
- Removed dummy fields
- Performance

* Update Content.Server/Singularity/Components/GravityWellComponent.cs

---------

Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
This commit is contained in:
metalgearsloth
2025-02-10 16:18:24 +11:00
committed by GitHub
parent 0bb1dfc582
commit a269850a73
2 changed files with 26 additions and 38 deletions

View File

@@ -7,22 +7,20 @@ namespace Content.Server.Singularity.Components;
/// The server-side version of <see cref="SharedGravityWellComponent"/>. /// The server-side version of <see cref="SharedGravityWellComponent"/>.
/// Primarily managed by <see cref="GravityWellSystem"/>. /// Primarily managed by <see cref="GravityWellSystem"/>.
/// </summary> /// </summary>
[RegisterComponent] [RegisterComponent, AutoGenerateComponentPause]
public sealed partial class GravityWellComponent : Component public sealed partial class GravityWellComponent : Component
{ {
/// <summary> /// <summary>
/// The maximum range at which the gravity well can push/pull entities. /// The maximum range at which the gravity well can push/pull entities.
/// </summary> /// </summary>
[DataField("maxRange")] [DataField]
[ViewVariables(VVAccess.ReadWrite)]
public float MaxRange; public float MaxRange;
/// <summary> /// <summary>
/// The minimum range at which the gravity well can push/pull entities. /// The minimum range at which the gravity well can push/pull entities.
/// This is effectively hardfloored at <see cref="GravityWellSystem.MinGravPulseRange"/>. /// This is effectively hardfloored at <see cref="GravityWellSystem.MinGravPulseRange"/>.
/// </summary> /// </summary>
[DataField("minRange")] [DataField]
[ViewVariables(VVAccess.ReadWrite)]
public float MinRange = 0f; public float MinRange = 0f;
/// <summary> /// <summary>
@@ -30,8 +28,7 @@ public sealed partial class GravityWellComponent : Component
/// Negative values accelerate entities away from the gravity well. /// Negative values accelerate entities away from the gravity well.
/// Actual acceleration scales with the inverse of the distance to the singularity. /// Actual acceleration scales with the inverse of the distance to the singularity.
/// </summary> /// </summary>
[DataField("baseRadialAcceleration")] [DataField]
[ViewVariables(VVAccess.ReadWrite)]
public float BaseRadialAcceleration = 0.0f; public float BaseRadialAcceleration = 0.0f;
/// <summary> /// <summary>
@@ -39,8 +36,7 @@ public sealed partial class GravityWellComponent : Component
/// Positive tangential acceleration is counter-clockwise. /// Positive tangential acceleration is counter-clockwise.
/// Actual acceleration scales with the inverse of the distance to the singularity. /// Actual acceleration scales with the inverse of the distance to the singularity.
/// </summary> /// </summary>
[DataField("baseTangentialAcceleration")] [DataField]
[ViewVariables(VVAccess.ReadWrite)]
public float BaseTangentialAcceleration = 0.0f; public float BaseTangentialAcceleration = 0.0f;
#region Update Timing #region Update Timing
@@ -56,16 +52,14 @@ public sealed partial class GravityWellComponent : Component
/// <summary> /// <summary>
/// The next time at which this gravity well should pulse. /// The next time at which this gravity well should pulse.
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadOnly)] [DataField, Access(typeof(GravityWellSystem)), AutoPausedField]
[Access(typeof(GravityWellSystem))]
public TimeSpan NextPulseTime { get; internal set; } = default!; public TimeSpan NextPulseTime { get; internal set; } = default!;
/// <summary> /// <summary>
/// The last time this gravity well pulsed. /// The last time this gravity well pulsed.
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadOnly)] [ViewVariables(VVAccess.ReadOnly)]
[Access(typeof(GravityWellSystem))] public TimeSpan LastPulseTime => NextPulseTime - TargetPulsePeriod;
public TimeSpan LastPulseTime { get; internal set; } = default!;
#endregion Update Timing #endregion Update Timing
} }

View File

@@ -39,6 +39,8 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
private EntityQuery<MapGridComponent> _gridQuery; private EntityQuery<MapGridComponent> _gridQuery;
private EntityQuery<PhysicsComponent> _physicsQuery; private EntityQuery<PhysicsComponent> _physicsQuery;
private HashSet<EntityUid> _entSet = new();
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
@@ -46,12 +48,17 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
_mapQuery = GetEntityQuery<MapComponent>(); _mapQuery = GetEntityQuery<MapComponent>();
_gridQuery = GetEntityQuery<MapGridComponent>(); _gridQuery = GetEntityQuery<MapGridComponent>();
_physicsQuery = GetEntityQuery<PhysicsComponent>(); _physicsQuery = GetEntityQuery<PhysicsComponent>();
SubscribeLocalEvent<GravityWellComponent, ComponentStartup>(OnGravityWellStartup); SubscribeLocalEvent<GravityWellComponent, MapInitEvent>(OnGravityWellMapInit);
var vvHandle = _vvManager.GetTypeHandler<GravityWellComponent>(); var vvHandle = _vvManager.GetTypeHandler<GravityWellComponent>();
vvHandle.AddPath(nameof(GravityWellComponent.TargetPulsePeriod), (_, comp) => comp.TargetPulsePeriod, SetPulsePeriod); vvHandle.AddPath(nameof(GravityWellComponent.TargetPulsePeriod), (_, comp) => comp.TargetPulsePeriod, SetPulsePeriod);
} }
private void OnGravityWellMapInit(Entity<GravityWellComponent> ent, ref MapInitEvent args)
{
ent.Comp.NextPulseTime = _timing.CurTime + ent.Comp.TargetPulsePeriod;
}
public override void Shutdown() public override void Shutdown()
{ {
var vvHandle = _vvManager.GetTypeHandler<GravityWellComponent>(); var vvHandle = _vvManager.GetTypeHandler<GravityWellComponent>();
@@ -73,6 +80,7 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
while (query.MoveNext(out var uid, out var gravWell, out var xform)) while (query.MoveNext(out var uid, out var gravWell, out var xform))
{ {
var curTime = _timing.CurTime; var curTime = _timing.CurTime;
if (gravWell.NextPulseTime <= curTime) if (gravWell.NextPulseTime <= curTime)
Update(uid, curTime - gravWell.LastPulseTime, gravWell, xform); Update(uid, curTime - gravWell.LastPulseTime, gravWell, xform);
} }
@@ -103,8 +111,7 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
if(!Resolve(uid, ref gravWell)) if(!Resolve(uid, ref gravWell))
return; return;
gravWell.LastPulseTime = _timing.CurTime; gravWell.NextPulseTime += gravWell.TargetPulsePeriod;
gravWell.NextPulseTime = gravWell.LastPulseTime + gravWell.TargetPulsePeriod;
if (gravWell.MaxRange < 0.0f || !Resolve(uid, ref xform)) if (gravWell.MaxRange < 0.0f || !Resolve(uid, ref xform))
return; return;
@@ -195,15 +202,18 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
if (mapPos == MapCoordinates.Nullspace) if (mapPos == MapCoordinates.Nullspace)
return; // No gravpulses in nullspace please. return; // No gravpulses in nullspace please.
_entSet.Clear();
var epicenter = mapPos.Position; var epicenter = mapPos.Position;
var minRange2 = MathF.Max(minRange * minRange, MinGravPulseRange); // Cache square value for speed. Also apply a sane minimum value to the minimum value so that div/0s don't happen. var minRange2 = MathF.Max(minRange * minRange, MinGravPulseRange); // Cache square value for speed. Also apply a sane minimum value to the minimum value so that div/0s don't happen.
var bodyQuery = GetEntityQuery<PhysicsComponent>(); _lookup.GetEntitiesInRange(mapPos.MapId,
var xformQuery = GetEntityQuery<TransformComponent>(); epicenter,
maxRange,
_entSet,
flags: LookupFlags.Dynamic | LookupFlags.Sundries);
foreach(var entity in _lookup.GetEntitiesInRange(mapPos.MapId, epicenter, maxRange, flags: LookupFlags.Dynamic | LookupFlags.Sundries)) foreach (var entity in _entSet)
{ {
if (!bodyQuery.TryGetComponent(entity, out var physics) if (!_physicsQuery.TryGetComponent(entity, out var physics))
|| physics.BodyType == BodyType.Static)
{ {
continue; continue;
} }
@@ -214,7 +224,7 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
if(!CanGravPulseAffect(entity)) if(!CanGravPulseAffect(entity))
continue; continue;
var displacement = epicenter - _transform.GetWorldPosition(entity, xformQuery); var displacement = epicenter - _transform.GetWorldPosition(entity);
var distance2 = displacement.LengthSquared(); var distance2 = displacement.LengthSquared();
if (distance2 < minRange2) if (distance2 < minRange2)
continue; continue;
@@ -263,20 +273,4 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
} }
#endregion Getters/Setters #endregion Getters/Setters
#region Event Handlers
/// <summary>
/// Resets the pulse timings of the gravity well when the components starts up.
/// </summary>
/// <param name="uid">The uid of the gravity well to start up.</param>
/// <param name="comp">The state of the gravity well to start up.</param>
/// <param name="args">The startup prompt arguments.</param>
public void OnGravityWellStartup(EntityUid uid, GravityWellComponent comp, ComponentStartup args)
{
comp.LastPulseTime = _timing.CurTime;
comp.NextPulseTime = comp.LastPulseTime + comp.TargetPulsePeriod;
}
#endregion Event Handlers
} }