diff --git a/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs b/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs index 8f435ea1c5..e055fda883 100644 --- a/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs +++ b/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs @@ -1,5 +1,3 @@ -#nullable enable -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Content.Server.Disposal.Tube.Components; @@ -7,9 +5,11 @@ using Content.Server.Disposal.Unit.Components; using Content.Server.Disposal.Unit.EntitySystems; using Content.Server.Power.Components; using Content.Shared.Coordinates; +using Content.Shared.Disposal; using NUnit.Framework; using Robust.Shared.GameObjects; using Robust.Shared.Map; +using Robust.Shared.Reflection; using Robust.Shared.Timing; namespace Content.IntegrationTests.Tests.Disposal @@ -20,25 +20,33 @@ namespace Content.IntegrationTests.Tests.Disposal [TestOf(typeof(DisposalUnitComponent))] public class DisposalUnitTest : ContentIntegrationTest { - private async Task UnitInsert(DisposalUnitComponent unit, bool result, params IEntity[] entities) + [Reflect(false)] + private class DisposalUnitTestSystem : EntitySystem { - List insertionTasks = new(); + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(ev => + { + var (_, toInsert, unit) = ev; + var insertTransform = EntityManager.GetComponent(toInsert); + var unitTransform = EntityManager.GetComponent(unit); + // Not in a tube yet + Assert.That(insertTransform.Parent, Is.EqualTo(unitTransform)); + }, after: new[] {typeof(SharedDisposalUnitSystem)}); + } + } + + private void UnitInsert(DisposalUnitComponent unit, bool result, params IEntity[] entities) + { + var system = EntitySystem.Get(); + foreach (var entity in entities) { - Assert.That(EntitySystem.Get().CanInsert(unit, entity), Is.EqualTo(result)); - var insertTask = unit.TryInsert(entity).ContinueWith(task => - { - Assert.That(task.Result, Is.EqualTo(result)); - if (result) - { - // Not in a tube yet - Assert.That(entity.Transform.Parent, Is.EqualTo(unit.Owner.Transform)); - } - }); - insertionTasks.Add(insertTask); + Assert.That(system.CanInsert(unit, entity), Is.EqualTo(result)); + system.TryInsert(unit.Owner.Uid, entity.Uid, entity.Uid); } - - await Task.WhenAll(insertionTasks.ToArray()); } private void UnitContains(DisposalUnitComponent unit, bool result, params IEntity[] entities) @@ -49,9 +57,9 @@ namespace Content.IntegrationTests.Tests.Disposal } } - private async void UnitInsertContains(DisposalUnitComponent unit, bool result, params IEntity[] entities) + private void UnitInsertContains(DisposalUnitComponent unit, bool result, params IEntity[] entities) { - await UnitInsert(unit, result, entities); + UnitInsert(unit, result, entities); UnitContains(unit, result, entities); } @@ -75,6 +83,7 @@ namespace Content.IntegrationTests.Tests.Disposal damageContainer: Biological - type: Physics bodyType: KinematicController + - type: DoAfter - type: entity name: WrenchDummy @@ -86,12 +95,15 @@ namespace Content.IntegrationTests.Tests.Disposal - Anchoring - type: Physics bodyType: Dynamic + - type: DoAfter - type: entity name: DisposalUnitDummy id: DisposalUnitDummy components: - type: DisposalUnit + entryDelay: 0 + draggedEntryDelay: 0 - type: Anchorable - type: ApcPowerReceiver - type: Physics @@ -123,7 +135,6 @@ namespace Content.IntegrationTests.Tests.Disposal var mapManager = server.ResolveDependency(); var entityManager = server.ResolveDependency(); var pauseManager = server.ResolveDependency(); - var componentFactory = server.ResolveDependency(); var tileDefinitionManager = server.ResolveDependency(); // Build up test environment @@ -206,7 +217,7 @@ namespace Content.IntegrationTests.Tests.Disposal await server.WaitAssertion(() => { // Remove power need - Assert.True(disposalUnit.TryGetComponent(out ApcPowerReceiverComponent? power)); + Assert.True(disposalUnit.TryGetComponent(out ApcPowerReceiverComponent power)); power!.NeedsPower = false; Assert.True(unit.Powered); diff --git a/Content.Server/Disposal/Unit/Components/DisposalUnitComponent.cs b/Content.Server/Disposal/Unit/Components/DisposalUnitComponent.cs index 37ffb69a57..9ed5858546 100644 --- a/Content.Server/Disposal/Unit/Components/DisposalUnitComponent.cs +++ b/Content.Server/Disposal/Unit/Components/DisposalUnitComponent.cs @@ -1,11 +1,8 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading; -using System.Threading.Tasks; using Content.Server.Atmos; using Content.Server.Disposal.Unit.EntitySystems; -using Content.Server.DoAfter; using Content.Server.Power.Components; using Content.Server.UserInterface; using Content.Shared.ActionBlocker; @@ -13,12 +10,10 @@ using Content.Shared.Acts; using Content.Shared.Atmos; using Content.Shared.Disposal.Components; using Content.Shared.DragDrop; -using Content.Shared.Verbs; using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.GameObjects; -using Robust.Shared.Localization; using Robust.Shared.Player; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; @@ -56,13 +51,13 @@ namespace Content.Server.Disposal.Unit.Components /// [ViewVariables(VVAccess.ReadWrite)] [DataField("entryDelay")] - private float _entryDelay = 0.5f; + public float EntryDelay = 0.5f; /// /// Delay from trying to shove someone else into disposals. /// [ViewVariables(VVAccess.ReadWrite)] - private float _draggedEntryDelay = 0.5f; + public float DraggedEntryDelay = 0.5f; /// /// Token used to cancel the automatic engage of a disposal unit @@ -90,43 +85,7 @@ namespace Content.Server.Disposal.Unit.Components [ViewVariables] public BoundUserInterface? UserInterface => Owner.GetUIOrNull(DisposalUnitUiKey.Key); [DataField("air")] - public GasMixture Air { get; set; } = new GasMixture(Atmospherics.CellVolume); - - public async Task TryInsert(IEntity entity, IEntity? user = default) - { - if (!EntitySystem.Get().CanInsert(this, entity)) - return false; - - var delay = user == entity ? _entryDelay : _draggedEntryDelay; - - if (user != null && delay > 0.0f) - { - var doAfterSystem = EntitySystem.Get(); - - // Can't check if our target AND disposals moves currently so we'll just check target. - // if you really want to check if disposals moves then add a predicate. - var doAfterArgs = new DoAfterEventArgs(user, delay, default, entity) - { - BreakOnDamage = true, - BreakOnStun = true, - BreakOnTargetMove = true, - BreakOnUserMove = true, - NeedHand = false, - }; - - var result = await doAfterSystem.WaitDoAfter(doAfterArgs); - - if (result == DoAfterStatus.Cancelled) - return false; - } - - if (!Container.Insert(entity)) - return false; - - EntitySystem.Get().AfterInsert(this, entity); - - return true; - } + public GasMixture Air { get; set; } = new(Atmospherics.CellVolume); private bool PlayerCanUse(IEntity? player) { @@ -189,7 +148,7 @@ namespace Content.Server.Disposal.Unit.Components public override bool DragDropOn(DragDropEvent eventArgs) { - _ = TryInsert(eventArgs.Dragged, eventArgs.User); + EntitySystem.Get().TryInsert(Owner.Uid, eventArgs.Dragged.Uid, eventArgs.User.Uid); return true; } diff --git a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs index a8cd0c5935..561420b541 100644 --- a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs +++ b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs @@ -3,9 +3,10 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using Content.Server.Atmos.EntitySystems; -using Content.Server.Disposal.Unit.Components; using Content.Server.Construction.Components; using Content.Server.Disposal.Tube.Components; +using Content.Server.Disposal.Unit.Components; +using Content.Server.DoAfter; using Content.Server.Hands.Components; using Content.Server.Items; using Content.Server.Power.Components; @@ -17,6 +18,7 @@ using Content.Shared.Interaction; using Content.Shared.Movement; using Content.Shared.Popups; using Content.Shared.Throwing; +using Content.Shared.Verbs; using Robust.Server.GameObjects; using Robust.Shared.Containers; using Robust.Shared.GameObjects; @@ -26,7 +28,6 @@ using Robust.Shared.Log; using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Random; -using Content.Shared.Verbs; namespace Content.Server.Disposal.Unit.EntitySystems { @@ -36,6 +37,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; [Dependency] private readonly AtmosphereSystem _atmosSystem = default!; + [Dependency] private readonly DoAfterSystem _doAfterSystem = default!; private readonly List _activeDisposals = new(); @@ -63,7 +65,11 @@ namespace Content.Server.Disposal.Unit.EntitySystems // Verbs SubscribeLocalEvent(AddFlushEjectVerbs); SubscribeLocalEvent(AddClimbInsideVerb); + + // Units + SubscribeLocalEvent(DoInsertDisposalUnit); } + private void AddFlushEjectVerbs(EntityUid uid, DisposalUnitComponent component, GetAlternativeVerbsEvent args) { if (!args.CanAccess || !args.CanInteract || component.ContainedEntities.Count == 0) @@ -95,10 +101,12 @@ namespace Content.Server.Disposal.Unit.EntitySystems !_actionBlockerSystem.CanMove(args.User)) return; - // Add verb to climb inside of the unit, - Verb verb = new(); - verb.Act = () => component.TryInsert(args.User, args.User); - verb.Text = Loc.GetString("disposal-self-insert-verb-get-data-text"); + // Add verb to climb inside of the unit, + Verb verb = new() + { + Act = () => TryInsert(component.Owner.Uid, args.User.Uid, args.User.Uid), + Text = Loc.GetString("disposal-self-insert-verb-get-data-text") + }; // TODO VERN ICON // TODO VERB CATEGORY // create a verb category for "enter"? @@ -106,6 +114,23 @@ namespace Content.Server.Disposal.Unit.EntitySystems args.Verbs.Add(verb); } + private void DoInsertDisposalUnit(DoInsertDisposalUnitEvent ev) + { + var toInsert = EntityManager.GetEntity(ev.ToInsert); + + if (!EntityManager.TryGetComponent(ev.Unit, out DisposalUnitComponent? unit)) + { + return; + } + + if (!unit.Container.Insert(toInsert)) + { + return; + } + + AfterInsert(unit, toInsert); + } + public override void Update(float frameTime) { base.Update(frameTime); @@ -376,6 +401,39 @@ namespace Content.Server.Disposal.Unit.EntitySystems return true; } + public void TryInsert(EntityUid unitId, EntityUid toInsertId, EntityUid userId, DisposalUnitComponent? unit = null) + { + if (!Resolve(unitId, ref unit)) + return; + + if (!CanInsert(unit, toInsertId)) + return; + + var delay = userId == toInsertId ? unit.EntryDelay : unit.DraggedEntryDelay; + var ev = new DoInsertDisposalUnitEvent(userId, toInsertId, unitId); + + if (delay <= 0) + { + DoInsertDisposalUnit(ev); + return; + } + + // Can't check if our target AND disposals moves currently so we'll just check target. + // if you really want to check if disposals moves then add a predicate. + var doAfterArgs = new DoAfterEventArgs(userId, delay, default, toInsertId) + { + BreakOnDamage = true, + BreakOnStun = true, + BreakOnTargetMove = true, + BreakOnUserMove = true, + NeedHand = false, + BroadcastFinishedEvent = ev + }; + + _doAfterSystem.DoAfter(doAfterArgs); + } + + public bool TryFlush(DisposalUnitComponent component) { if (component.Deleted || !CanFlush(component)) diff --git a/Content.Server/Disposal/Unit/EntitySystems/DoInsertDisposalUnitEvent.cs b/Content.Server/Disposal/Unit/EntitySystems/DoInsertDisposalUnitEvent.cs new file mode 100644 index 0000000000..986df4121a --- /dev/null +++ b/Content.Server/Disposal/Unit/EntitySystems/DoInsertDisposalUnitEvent.cs @@ -0,0 +1,6 @@ +using Robust.Shared.GameObjects; + +namespace Content.Server.Disposal.Unit.EntitySystems +{ + public record DoInsertDisposalUnitEvent(EntityUid User, EntityUid ToInsert, EntityUid Unit); +} diff --git a/Content.Shared/Disposal/SharedDisposalUnitSystem.cs b/Content.Shared/Disposal/SharedDisposalUnitSystem.cs index e3aa904c2f..b1bcca3bae 100644 --- a/Content.Shared/Disposal/SharedDisposalUnitSystem.cs +++ b/Content.Shared/Disposal/SharedDisposalUnitSystem.cs @@ -63,11 +63,19 @@ namespace Content.Shared.Disposal if (!entity.TryGetComponent(out IPhysBody? physics) || !physics.CanCollide && storable == null) { - if (!(entity.TryGetComponent(out IMobStateComponent? damageState) && damageState.IsDead())) { + if (!(entity.TryGetComponent(out IMobStateComponent? damageState) && damageState.IsDead())) + { return false; } } + return true; } + + public bool CanInsert(SharedDisposalUnitComponent component, EntityUid entityId) + { + var entity = EntityManager.GetEntity(entityId); + return CanInsert(component, entity); + } } }