Make DisposalUnitComponent.TryInsert ECS (#4959)

This commit is contained in:
Javier Guardia Fernández
2021-10-20 21:12:23 +02:00
committed by GitHub
parent ecbcab4824
commit 3e5a856948
5 changed files with 115 additions and 73 deletions

View File

@@ -1,5 +1,3 @@
#nullable enable
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Server.Disposal.Tube.Components; 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.Disposal.Unit.EntitySystems;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Shared.Coordinates; using Content.Shared.Coordinates;
using Content.Shared.Disposal;
using NUnit.Framework; using NUnit.Framework;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Reflection;
using Robust.Shared.Timing; using Robust.Shared.Timing;
namespace Content.IntegrationTests.Tests.Disposal namespace Content.IntegrationTests.Tests.Disposal
@@ -20,25 +20,33 @@ namespace Content.IntegrationTests.Tests.Disposal
[TestOf(typeof(DisposalUnitComponent))] [TestOf(typeof(DisposalUnitComponent))]
public class DisposalUnitTest : ContentIntegrationTest public class DisposalUnitTest : ContentIntegrationTest
{ {
private async Task UnitInsert(DisposalUnitComponent unit, bool result, params IEntity[] entities) [Reflect(false)]
private class DisposalUnitTestSystem : EntitySystem
{ {
List<Task> insertionTasks = new(); public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DoInsertDisposalUnitEvent>(ev =>
{
var (_, toInsert, unit) = ev;
var insertTransform = EntityManager.GetComponent<ITransformComponent>(toInsert);
var unitTransform = EntityManager.GetComponent<ITransformComponent>(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<DisposalUnitSystem>();
foreach (var entity in entities) foreach (var entity in entities)
{ {
Assert.That(EntitySystem.Get<DisposalUnitSystem>().CanInsert(unit, entity), Is.EqualTo(result)); Assert.That(system.CanInsert(unit, entity), Is.EqualTo(result));
var insertTask = unit.TryInsert(entity).ContinueWith(task => system.TryInsert(unit.Owner.Uid, entity.Uid, entity.Uid);
{
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);
} }
await Task.WhenAll(insertionTasks.ToArray());
} }
private void UnitContains(DisposalUnitComponent unit, bool result, params IEntity[] entities) 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); UnitContains(unit, result, entities);
} }
@@ -75,6 +83,7 @@ namespace Content.IntegrationTests.Tests.Disposal
damageContainer: Biological damageContainer: Biological
- type: Physics - type: Physics
bodyType: KinematicController bodyType: KinematicController
- type: DoAfter
- type: entity - type: entity
name: WrenchDummy name: WrenchDummy
@@ -86,12 +95,15 @@ namespace Content.IntegrationTests.Tests.Disposal
- Anchoring - Anchoring
- type: Physics - type: Physics
bodyType: Dynamic bodyType: Dynamic
- type: DoAfter
- type: entity - type: entity
name: DisposalUnitDummy name: DisposalUnitDummy
id: DisposalUnitDummy id: DisposalUnitDummy
components: components:
- type: DisposalUnit - type: DisposalUnit
entryDelay: 0
draggedEntryDelay: 0
- type: Anchorable - type: Anchorable
- type: ApcPowerReceiver - type: ApcPowerReceiver
- type: Physics - type: Physics
@@ -123,7 +135,6 @@ namespace Content.IntegrationTests.Tests.Disposal
var mapManager = server.ResolveDependency<IMapManager>(); var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>(); var entityManager = server.ResolveDependency<IEntityManager>();
var pauseManager = server.ResolveDependency<IPauseManager>(); var pauseManager = server.ResolveDependency<IPauseManager>();
var componentFactory = server.ResolveDependency<IComponentFactory>();
var tileDefinitionManager = server.ResolveDependency<ITileDefinitionManager>(); var tileDefinitionManager = server.ResolveDependency<ITileDefinitionManager>();
// Build up test environment // Build up test environment
@@ -206,7 +217,7 @@ namespace Content.IntegrationTests.Tests.Disposal
await server.WaitAssertion(() => await server.WaitAssertion(() =>
{ {
// Remove power need // Remove power need
Assert.True(disposalUnit.TryGetComponent(out ApcPowerReceiverComponent? power)); Assert.True(disposalUnit.TryGetComponent(out ApcPowerReceiverComponent power));
power!.NeedsPower = false; power!.NeedsPower = false;
Assert.True(unit.Powered); Assert.True(unit.Powered);

View File

@@ -1,11 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using Content.Server.Atmos; using Content.Server.Atmos;
using Content.Server.Disposal.Unit.EntitySystems; using Content.Server.Disposal.Unit.EntitySystems;
using Content.Server.DoAfter;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.UserInterface; using Content.Server.UserInterface;
using Content.Shared.ActionBlocker; using Content.Shared.ActionBlocker;
@@ -13,12 +10,10 @@ using Content.Shared.Acts;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Disposal.Components; using Content.Shared.Disposal.Components;
using Content.Shared.DragDrop; using Content.Shared.DragDrop;
using Content.Shared.Verbs;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Localization;
using Robust.Shared.Player; using Robust.Shared.Player;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -56,13 +51,13 @@ namespace Content.Server.Disposal.Unit.Components
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField("entryDelay")] [DataField("entryDelay")]
private float _entryDelay = 0.5f; public float EntryDelay = 0.5f;
/// <summary> /// <summary>
/// Delay from trying to shove someone else into disposals. /// Delay from trying to shove someone else into disposals.
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
private float _draggedEntryDelay = 0.5f; public float DraggedEntryDelay = 0.5f;
/// <summary> /// <summary>
/// Token used to cancel the automatic engage of a disposal unit /// 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); [ViewVariables] public BoundUserInterface? UserInterface => Owner.GetUIOrNull(DisposalUnitUiKey.Key);
[DataField("air")] [DataField("air")]
public GasMixture Air { get; set; } = new GasMixture(Atmospherics.CellVolume); public GasMixture Air { get; set; } = new(Atmospherics.CellVolume);
public async Task<bool> TryInsert(IEntity entity, IEntity? user = default)
{
if (!EntitySystem.Get<DisposalUnitSystem>().CanInsert(this, entity))
return false;
var delay = user == entity ? _entryDelay : _draggedEntryDelay;
if (user != null && delay > 0.0f)
{
var doAfterSystem = EntitySystem.Get<DoAfterSystem>();
// 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<DisposalUnitSystem>().AfterInsert(this, entity);
return true;
}
private bool PlayerCanUse(IEntity? player) private bool PlayerCanUse(IEntity? player)
{ {
@@ -189,7 +148,7 @@ namespace Content.Server.Disposal.Unit.Components
public override bool DragDropOn(DragDropEvent eventArgs) public override bool DragDropOn(DragDropEvent eventArgs)
{ {
_ = TryInsert(eventArgs.Dragged, eventArgs.User); EntitySystem.Get<DisposalUnitSystem>().TryInsert(Owner.Uid, eventArgs.Dragged.Uid, eventArgs.User.Uid);
return true; return true;
} }

View File

@@ -3,9 +3,10 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.EntitySystems;
using Content.Server.Disposal.Unit.Components;
using Content.Server.Construction.Components; using Content.Server.Construction.Components;
using Content.Server.Disposal.Tube.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.Hands.Components;
using Content.Server.Items; using Content.Server.Items;
using Content.Server.Power.Components; using Content.Server.Power.Components;
@@ -17,6 +18,7 @@ using Content.Shared.Interaction;
using Content.Shared.Movement; using Content.Shared.Movement;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Throwing; using Content.Shared.Throwing;
using Content.Shared.Verbs;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
@@ -26,7 +28,6 @@ using Robust.Shared.Log;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Random; using Robust.Shared.Random;
using Content.Shared.Verbs;
namespace Content.Server.Disposal.Unit.EntitySystems 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 IRobustRandom _robustRandom = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly AtmosphereSystem _atmosSystem = default!; [Dependency] private readonly AtmosphereSystem _atmosSystem = default!;
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
private readonly List<DisposalUnitComponent> _activeDisposals = new(); private readonly List<DisposalUnitComponent> _activeDisposals = new();
@@ -63,7 +65,11 @@ namespace Content.Server.Disposal.Unit.EntitySystems
// Verbs // Verbs
SubscribeLocalEvent<DisposalUnitComponent, GetAlternativeVerbsEvent>(AddFlushEjectVerbs); SubscribeLocalEvent<DisposalUnitComponent, GetAlternativeVerbsEvent>(AddFlushEjectVerbs);
SubscribeLocalEvent<DisposalUnitComponent, GetOtherVerbsEvent>(AddClimbInsideVerb); SubscribeLocalEvent<DisposalUnitComponent, GetOtherVerbsEvent>(AddClimbInsideVerb);
// Units
SubscribeLocalEvent<DoInsertDisposalUnitEvent>(DoInsertDisposalUnit);
} }
private void AddFlushEjectVerbs(EntityUid uid, DisposalUnitComponent component, GetAlternativeVerbsEvent args) private void AddFlushEjectVerbs(EntityUid uid, DisposalUnitComponent component, GetAlternativeVerbsEvent args)
{ {
if (!args.CanAccess || !args.CanInteract || component.ContainedEntities.Count == 0) if (!args.CanAccess || !args.CanInteract || component.ContainedEntities.Count == 0)
@@ -95,10 +101,12 @@ namespace Content.Server.Disposal.Unit.EntitySystems
!_actionBlockerSystem.CanMove(args.User)) !_actionBlockerSystem.CanMove(args.User))
return; return;
// Add verb to climb inside of the unit, // Add verb to climb inside of the unit,
Verb verb = new(); Verb verb = new()
verb.Act = () => component.TryInsert(args.User, args.User); {
verb.Text = Loc.GetString("disposal-self-insert-verb-get-data-text"); 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 VERN ICON
// TODO VERB CATEGORY // TODO VERB CATEGORY
// create a verb category for "enter"? // create a verb category for "enter"?
@@ -106,6 +114,23 @@ namespace Content.Server.Disposal.Unit.EntitySystems
args.Verbs.Add(verb); 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) public override void Update(float frameTime)
{ {
base.Update(frameTime); base.Update(frameTime);
@@ -376,6 +401,39 @@ namespace Content.Server.Disposal.Unit.EntitySystems
return true; 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) public bool TryFlush(DisposalUnitComponent component)
{ {
if (component.Deleted || !CanFlush(component)) if (component.Deleted || !CanFlush(component))

View File

@@ -0,0 +1,6 @@
using Robust.Shared.GameObjects;
namespace Content.Server.Disposal.Unit.EntitySystems
{
public record DoInsertDisposalUnitEvent(EntityUid User, EntityUid ToInsert, EntityUid Unit);
}

View File

@@ -63,11 +63,19 @@ namespace Content.Shared.Disposal
if (!entity.TryGetComponent(out IPhysBody? physics) || if (!entity.TryGetComponent(out IPhysBody? physics) ||
!physics.CanCollide && storable == null) !physics.CanCollide && storable == null)
{ {
if (!(entity.TryGetComponent(out IMobStateComponent? damageState) && damageState.IsDead())) { if (!(entity.TryGetComponent(out IMobStateComponent? damageState) && damageState.IsDead()))
{
return false; return false;
} }
} }
return true; return true;
} }
public bool CanInsert(SharedDisposalUnitComponent component, EntityUid entityId)
{
var entity = EntityManager.GetEntity(entityId);
return CanInsert(component, entity);
}
} }
} }