Entity storage now holds air (#11355)
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Server.Atmos;
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
using Content.Shared.Whitelist;
|
using Content.Shared.Whitelist;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
@@ -6,9 +7,10 @@ using Robust.Shared.Containers;
|
|||||||
namespace Content.Server.Storage.Components;
|
namespace Content.Server.Storage.Components;
|
||||||
|
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class EntityStorageComponent : Component
|
public sealed class EntityStorageComponent : Component, IGasMixtureHolder
|
||||||
{
|
{
|
||||||
public readonly float MaxSize = 1.0f; // maximum width or height of an entity allowed inside the storage.
|
public readonly float MaxSize = 1.0f; // maximum width or height of an entity allowed inside the storage.
|
||||||
|
public const float GasMixVolume = 70f;
|
||||||
|
|
||||||
public static readonly TimeSpan InternalOpenAttemptDelay = TimeSpan.FromSeconds(0.5);
|
public static readonly TimeSpan InternalOpenAttemptDelay = TimeSpan.FromSeconds(0.5);
|
||||||
public TimeSpan LastInternalOpenAttempt;
|
public TimeSpan LastInternalOpenAttempt;
|
||||||
@@ -77,6 +79,13 @@ public sealed class EntityStorageComponent : Component
|
|||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public bool IsWeldedShut;
|
public bool IsWeldedShut;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gas currently contained in this entity storage.
|
||||||
|
/// None while open. Grabs gas from the atmosphere when closed, and exposes any entities inside to it.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public GasMixture Air { get; set; } = new (GasMixVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class InsertIntoEntityStorageAttemptEvent : CancellableEntityEventArgs { }
|
public sealed class InsertIntoEntityStorageAttemptEvent : CancellableEntityEventArgs { }
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Content.Server.Storage.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Added to entities contained within entity storage, for directed event purposes.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class InsideEntityStorageComponent : Component
|
||||||
|
{
|
||||||
|
public EntityUid Storage;
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.Construction;
|
using Content.Server.Construction;
|
||||||
using Content.Server.Construction.Components;
|
using Content.Server.Construction.Components;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
@@ -29,6 +30,8 @@ public sealed class EntityStorageSystem : EntitySystem
|
|||||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||||
[Dependency] private readonly PlaceableSurfaceSystem _placeableSurface = default!;
|
[Dependency] private readonly PlaceableSurfaceSystem _placeableSurface = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
|
[Dependency] private readonly AtmosphereSystem _atmos = default!;
|
||||||
|
[Dependency] private readonly IMapManager _map = default!;
|
||||||
|
|
||||||
public const string ContainerName = "entity_storage";
|
public const string ContainerName = "entity_storage";
|
||||||
|
|
||||||
@@ -41,6 +44,10 @@ public sealed class EntityStorageSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<EntityStorageComponent, WeldableAttemptEvent>(OnWeldableAttempt);
|
SubscribeLocalEvent<EntityStorageComponent, WeldableAttemptEvent>(OnWeldableAttempt);
|
||||||
SubscribeLocalEvent<EntityStorageComponent, WeldableChangedEvent>(OnWelded);
|
SubscribeLocalEvent<EntityStorageComponent, WeldableChangedEvent>(OnWelded);
|
||||||
SubscribeLocalEvent<EntityStorageComponent, DestructionEventArgs>(OnDestroy);
|
SubscribeLocalEvent<EntityStorageComponent, DestructionEventArgs>(OnDestroy);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<InsideEntityStorageComponent, InhaleLocationEvent>(OnInsideInhale);
|
||||||
|
SubscribeLocalEvent<InsideEntityStorageComponent, ExhaleLocationEvent>(OnInsideExhale);
|
||||||
|
SubscribeLocalEvent<InsideEntityStorageComponent, AtmosExposedGetAirEvent>(OnInsideExposed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInit(EntityUid uid, EntityStorageComponent component, ComponentInit args)
|
private void OnInit(EntityUid uid, EntityStorageComponent component, ComponentInit args)
|
||||||
@@ -54,6 +61,13 @@ public sealed class EntityStorageSystem : EntitySystem
|
|||||||
|
|
||||||
if (TryComp<PlaceableSurfaceComponent>(uid, out var placeable))
|
if (TryComp<PlaceableSurfaceComponent>(uid, out var placeable))
|
||||||
_placeableSurface.SetPlaceable(uid, component.Open, placeable);
|
_placeableSurface.SetPlaceable(uid, component.Open, placeable);
|
||||||
|
|
||||||
|
if (!component.Open)
|
||||||
|
{
|
||||||
|
// If we're closed on spawn, we need to pull some air into our environment from where we spawned,
|
||||||
|
// so that we have -something-. For example, if you bought an animal crate or something.
|
||||||
|
TakeGas(uid, component);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInteract(EntityUid uid, EntityStorageComponent component, ActivateInWorldEvent args)
|
private void OnInteract(EntityUid uid, EntityStorageComponent component, ActivateInWorldEvent args)
|
||||||
@@ -117,13 +131,14 @@ public sealed class EntityStorageSystem : EntitySystem
|
|||||||
var containedArr = component.Contents.ContainedEntities.ToArray();
|
var containedArr = component.Contents.ContainedEntities.ToArray();
|
||||||
foreach (var contained in containedArr)
|
foreach (var contained in containedArr)
|
||||||
{
|
{
|
||||||
if (component.Contents.Remove(contained))
|
if (!component.Contents.Remove(contained))
|
||||||
{
|
continue;
|
||||||
|
|
||||||
|
RemComp<InsideEntityStorageComponent>(contained);
|
||||||
Transform(contained).WorldPosition =
|
Transform(contained).WorldPosition =
|
||||||
uidXform.WorldPosition + uidXform.WorldRotation.RotateVec(component.EnteringOffset);
|
uidXform.WorldPosition + uidXform.WorldRotation.RotateVec(component.EnteringOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenStorage(EntityUid uid, EntityStorageComponent? component = null)
|
public void OpenStorage(EntityUid uid, EntityStorageComponent? component = null)
|
||||||
{
|
{
|
||||||
@@ -134,6 +149,7 @@ public sealed class EntityStorageSystem : EntitySystem
|
|||||||
EmptyContents(uid, component);
|
EmptyContents(uid, component);
|
||||||
ModifyComponents(uid, component);
|
ModifyComponents(uid, component);
|
||||||
SoundSystem.Play(component.OpenSound.GetSound(), Filter.Pvs(component.Owner), component.Owner);
|
SoundSystem.Play(component.OpenSound.GetSound(), Filter.Pvs(component.Owner), component.Owner);
|
||||||
|
ReleaseGas(uid, component);
|
||||||
RaiseLocalEvent(uid, new StorageAfterOpenEvent());
|
RaiseLocalEvent(uid, new StorageAfterOpenEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,11 +177,15 @@ public sealed class EntityStorageSystem : EntitySystem
|
|||||||
if (!AddToContents(entity, uid, component))
|
if (!AddToContents(entity, uid, component))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
var inside = EnsureComp<InsideEntityStorageComponent>(entity);
|
||||||
|
inside.Storage = uid;
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
if (count >= component.Capacity)
|
if (count >= component.Capacity)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TakeGas(uid, component);
|
||||||
ModifyComponents(uid, component);
|
ModifyComponents(uid, component);
|
||||||
SoundSystem.Play(component.CloseSound.GetSound(), Filter.Pvs(uid), uid);
|
SoundSystem.Play(component.CloseSound.GetSound(), Filter.Pvs(uid), uid);
|
||||||
component.LastInternalOpenAttempt = default;
|
component.LastInternalOpenAttempt = default;
|
||||||
@@ -365,4 +385,70 @@ public sealed class EntityStorageSystem : EntitySystem
|
|||||||
appearance.SetData(StorageVisuals.HasContents, component.Contents.ContainedEntities.Any());
|
appearance.SetData(StorageVisuals.HasContents, component.Contents.ContainedEntities.Any());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TakeGas(EntityUid uid, EntityStorageComponent component)
|
||||||
|
{
|
||||||
|
var tile = GetOffsetTileRef(uid, component);
|
||||||
|
|
||||||
|
if (tile != null && _atmos.GetTileMixture(tile.Value.GridUid, null, tile.Value.GridIndices, true) is {} environment)
|
||||||
|
{
|
||||||
|
_atmos.Merge(component.Air, environment.RemoveVolume(EntityStorageComponent.GasMixVolume));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReleaseGas(EntityUid uid, EntityStorageComponent component)
|
||||||
|
{
|
||||||
|
var tile = GetOffsetTileRef(uid, component);
|
||||||
|
|
||||||
|
if (tile != null && _atmos.GetTileMixture(tile.Value.GridUid, null, tile.Value.GridIndices, true) is {} environment)
|
||||||
|
{
|
||||||
|
_atmos.Merge(environment, component.Air);
|
||||||
|
component.Air.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TileRef? GetOffsetTileRef(EntityUid uid, EntityStorageComponent component)
|
||||||
|
{
|
||||||
|
var targetCoordinates = new EntityCoordinates(uid, component.EnteringOffset).ToMap(EntityManager);
|
||||||
|
|
||||||
|
if (_map.TryFindGridAt(targetCoordinates, out var grid))
|
||||||
|
{
|
||||||
|
return grid.GetTileRef(targetCoordinates);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Gas mix event handlers
|
||||||
|
|
||||||
|
private void OnInsideInhale(EntityUid uid, InsideEntityStorageComponent component, InhaleLocationEvent args)
|
||||||
|
{
|
||||||
|
if (TryComp<EntityStorageComponent>(component.Storage, out var storage))
|
||||||
|
{
|
||||||
|
args.Gas = storage.Air;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInsideExhale(EntityUid uid, InsideEntityStorageComponent component, ExhaleLocationEvent args)
|
||||||
|
{
|
||||||
|
if (TryComp<EntityStorageComponent>(component.Storage, out var storage))
|
||||||
|
{
|
||||||
|
args.Gas = storage.Air;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInsideExposed(EntityUid uid, InsideEntityStorageComponent component, ref AtmosExposedGetAirEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (TryComp<EntityStorageComponent>(component.Storage, out var storage))
|
||||||
|
{
|
||||||
|
args.Gas = storage.Air;
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user