* InitialCommit (Broken) * Fixes compile errors * PR comments. More doc comments. Fixes * Makes a singularity/event horizon without radiation/physics a valid state to be in * VV 'fake' setters, fixes the visualizer, fixes the singularity trying to eat itself instead of nearby things. * Removes unused dependency from Content.Client.GravityWellSystem * Testing containment and fake VV setters for SingularityGeneratorComponent * Fixes gravity wells (broken due to LookupFlags.None). Adds recursive Event Horizon consumption * Fix merge skew * Fixes for the master merge * Fix engine commit * Dirty is obsolete * Switch over dirty * Fix requested changes * ambiant -> ambient * Moves EventHorionComponent to Shared * Proper container handling * Fixes master merge. Fixes post insertion assertions for singularities. Extends proper container handling to gravity wells and the distortion shader. * Better support for admemes throwing singularities. * Moves update timing from accumulators to target times * Update doc comments
207 lines
9.0 KiB
C#
207 lines
9.0 KiB
C#
using Robust.Shared.Map.Components;
|
|
using Robust.Shared.Physics.Collision.Shapes;
|
|
using Robust.Shared.Physics.Components;
|
|
using Robust.Shared.Physics.Events;
|
|
using Robust.Shared.Physics.Systems;
|
|
|
|
using Content.Shared.Ghost;
|
|
using Content.Shared.Singularity.Components;
|
|
|
|
namespace Content.Shared.Singularity.EntitySystems;
|
|
|
|
/// <summary>
|
|
/// The entity system primarily responsible for managing <see cref="EventHorizonComponent"/>s.
|
|
/// </summary>
|
|
public abstract class SharedEventHorizonSystem : EntitySystem
|
|
{
|
|
#region Dependencies
|
|
[Dependency] private readonly FixtureSystem _fixtures = default!;
|
|
[Dependency] protected readonly IViewVariablesManager Vvm = default!;
|
|
#endregion Dependencies
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
// Allows for predicted collisions with singularities.
|
|
SubscribeLocalEvent<EventHorizonComponent, ComponentStartup>(OnEventHorizonStartup);
|
|
SubscribeLocalEvent<EventHorizonComponent, PreventCollideEvent>(OnPreventCollide);
|
|
|
|
var vvHandle = Vvm.GetTypeHandler<EventHorizonComponent>();
|
|
vvHandle.AddPath(nameof(EventHorizonComponent.Radius), (_, comp) => comp.Radius, (uid, value, comp) => SetRadius(uid, value, eventHorizon: comp));
|
|
vvHandle.AddPath(nameof(EventHorizonComponent.CanBreachContainment), (_, comp) => comp.CanBreachContainment, (uid, value, comp) => SetCanBreachContainment(uid, value, eventHorizon: comp));
|
|
vvHandle.AddPath(nameof(EventHorizonComponent.HorizonFixtureId), (_, comp) => comp.HorizonFixtureId, (uid, value, comp) => SetHorizonFixtureId(uid, value, eventHorizon: comp));
|
|
}
|
|
|
|
public override void Shutdown()
|
|
{
|
|
var vvHandle = Vvm.GetTypeHandler<EventHorizonComponent>();
|
|
vvHandle.RemovePath(nameof(EventHorizonComponent.Radius));
|
|
vvHandle.RemovePath(nameof(EventHorizonComponent.CanBreachContainment));
|
|
vvHandle.RemovePath(nameof(EventHorizonComponent.HorizonFixtureId));
|
|
|
|
base.Shutdown();
|
|
}
|
|
|
|
#region Getters/Setters
|
|
|
|
/// <summary>
|
|
/// Setter for <see cref="EventHorizonComponent.Radius"/>
|
|
/// May also update the fixture associated with the event horizon.
|
|
/// </summary>
|
|
/// <param name="uid">The uid of the event horizon to change the radius of.</param>
|
|
/// <param name="value">The new radius of the event horizon.</param>
|
|
/// <param name="updateFixture">Whether to update the associated fixture upon changing the radius of the event horizon.</param>
|
|
/// <param name="eventHorizon">The state of the event horizon to change the radius of.</param>
|
|
public void SetRadius(EntityUid uid, float value, bool updateFixture = true, EventHorizonComponent? eventHorizon = null)
|
|
{
|
|
if(!Resolve(uid, ref eventHorizon))
|
|
return;
|
|
|
|
var oldValue = eventHorizon.Radius;
|
|
if (value == oldValue)
|
|
return;
|
|
|
|
eventHorizon.Radius = value;
|
|
EntityManager.Dirty(eventHorizon);
|
|
if (updateFixture)
|
|
UpdateEventHorizonFixture(uid, eventHorizon: eventHorizon);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setter for <see cref="EventHorizonComponent.CanBreachContainment"/>
|
|
/// May also update the fixture associated with the event horizon.
|
|
/// </summary>
|
|
/// <param name="uid">The uid of the event horizon to make (in)capable of breaching containment.</param>
|
|
/// <param name="value">Whether the event horizon should be able to breach containment.</param>
|
|
/// <param name="updateFixture">Whether to update the associated fixture upon changing whether the event horizon can breach containment.</param>
|
|
/// <param name="eventHorizon">The state of the event horizon to make (in)capable of breaching containment.</param>
|
|
public void SetCanBreachContainment(EntityUid uid, bool value, bool updateFixture = true, EventHorizonComponent? eventHorizon = null)
|
|
{
|
|
if(!Resolve(uid, ref eventHorizon))
|
|
return;
|
|
|
|
var oldValue = eventHorizon.CanBreachContainment;
|
|
if (value == oldValue)
|
|
return;
|
|
|
|
eventHorizon.CanBreachContainment = value;
|
|
EntityManager.Dirty(eventHorizon);
|
|
if (updateFixture)
|
|
UpdateEventHorizonFixture(uid, eventHorizon: eventHorizon);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setter for <see cref="EventHorizonComponent.HorizonFixtureId"/>
|
|
/// May also update the fixture associated with the event horizon.
|
|
/// </summary>
|
|
/// <param name="uid">The uid of the event horizon with the fixture ID to change.</param>
|
|
/// <param name="value">The new fixture ID to associate the event horizon with.</param>
|
|
/// <param name="updateFixture">Whether to update the associated fixture upon changing whether the event horizon can breach containment.</param>
|
|
/// <param name="eventHorizon">The state of the event horizon with the fixture ID to change.</param>
|
|
public void SetHorizonFixtureId(EntityUid uid, string? value, bool updateFixture = true, EventHorizonComponent? eventHorizon = null)
|
|
{
|
|
if(!Resolve(uid, ref eventHorizon))
|
|
return;
|
|
|
|
var oldValue = eventHorizon.HorizonFixtureId;
|
|
if (value == oldValue)
|
|
return;
|
|
|
|
eventHorizon.HorizonFixtureId = value;
|
|
EntityManager.Dirty(eventHorizon);
|
|
if (updateFixture)
|
|
UpdateEventHorizonFixture(uid, eventHorizon: eventHorizon);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the state of the fixture associated with the event horizon.
|
|
/// </summary>
|
|
/// <param name="eventHorizon">The uid of the event horizon associated with the fixture to update.</param>
|
|
/// <param name="fixtures">The physics component containing the fixture to update.</param>
|
|
/// <param name="eventHorizon">The state of the event horizon associated with the fixture to update.</param>
|
|
public void UpdateEventHorizonFixture(EntityUid uid, PhysicsComponent? fixtures = null, EventHorizonComponent? eventHorizon = null)
|
|
{
|
|
if(!Resolve(uid, ref eventHorizon))
|
|
return;
|
|
|
|
var fixtureId = eventHorizon.HorizonFixtureId;
|
|
if (fixtureId == null || !Resolve(eventHorizon.Owner, ref fixtures, logMissing: false))
|
|
return;
|
|
|
|
var fixture = _fixtures.GetFixtureOrNull(fixtures, fixtureId);
|
|
if (fixture == null)
|
|
return;
|
|
|
|
var shape = (PhysShapeCircle)fixture.Shape;
|
|
shape.Radius = eventHorizon.Radius;
|
|
fixture.Hard = !eventHorizon.CanBreachContainment;
|
|
EntityManager.Dirty(fixtures);
|
|
}
|
|
|
|
#endregion Getters/Setters
|
|
|
|
|
|
#region EventHandlers
|
|
|
|
/// <summary>
|
|
/// Syncs the state of the fixture associated with the event horizon upon startup.
|
|
/// </summary>
|
|
/// <param name="uid">The entity that has just gained an event horizon component.</param>
|
|
/// <param name="comp">The event horizon component that is starting up.</param>
|
|
/// <param name="args">The event arguments.</param>
|
|
private void OnEventHorizonStartup(EntityUid uid, EventHorizonComponent comp, ComponentStartup args)
|
|
{
|
|
UpdateEventHorizonFixture(uid, eventHorizon: comp);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prevents the event horizon from colliding with anything it cannot consume.
|
|
/// Most notably map grids and ghosts.
|
|
/// Also makes event horizons phase through containment if it can breach.
|
|
/// </summary>
|
|
/// <param name="uid">The entity that is trying to collide with another entity.</param>
|
|
/// <param name="comp">The event horizon of the former.</param>
|
|
/// <param name="args">The event arguments.</param>
|
|
private void OnPreventCollide(EntityUid uid, EventHorizonComponent comp, ref PreventCollideEvent args)
|
|
{
|
|
if(!args.Cancelled)
|
|
PreventCollide(uid, comp, ref args);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The actual, functional part of SharedEventHorizonSystem.OnPreventCollide.
|
|
/// The return value allows for overrides to early return if the base successfully handles collision prevention.
|
|
/// </summary>
|
|
/// <param name="uid">The entity that is trying to collide with another entity.</param>
|
|
/// <param name="comp">The event horizon of the former.</param>
|
|
/// <param name="args">The event arguments.</param>
|
|
/// <returns>A bool indicating whether the collision prevention has been handled.</return>
|
|
protected virtual bool PreventCollide(EntityUid uid, EventHorizonComponent comp, ref PreventCollideEvent args)
|
|
{
|
|
var otherUid = args.BodyB.Owner;
|
|
|
|
// For prediction reasons always want the client to ignore these.
|
|
if (EntityManager.HasComponent<MapGridComponent>(otherUid) ||
|
|
EntityManager.HasComponent<SharedGhostComponent>(otherUid))
|
|
{
|
|
args.Cancelled = true;
|
|
return true;
|
|
}
|
|
|
|
// If we can, breach containment
|
|
// otherwise, check if it's containment and just keep the collision
|
|
if (EntityManager.HasComponent<SharedContainmentFieldComponent>(otherUid) ||
|
|
EntityManager.HasComponent<SharedContainmentFieldGeneratorComponent>(otherUid))
|
|
{
|
|
if (comp.CanBreachContainment)
|
|
args.Cancelled = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#endregion EventHandlers
|
|
}
|