Merge branch 'master' into expl_int_analyzer

This commit is contained in:
Pieter-Jan Briers
2021-02-08 22:46:28 +01:00
140 changed files with 3622 additions and 1208 deletions

View File

@@ -80,6 +80,9 @@ namespace Content.IntegrationTests
// Avoid funny race conditions with the database.
options.CVarOverrides[CCVars.DatabaseSynchronous.Name] = "true";
// Avoid loading a large map by default for integration tests.
options.CVarOverrides[CCVars.GameMap.Name] = "Maps/Test/empty.yml";
return base.StartServer(options);
}

View File

@@ -6,7 +6,6 @@ using Content.Server.GameObjects.Components.Strap;
using Content.Shared.GameObjects.Components.Body;
using Content.Shared.GameObjects.Components.Body.Part;
using Content.Shared.GameObjects.Components.Buckle;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.EntitySystems.EffectBlocker;
using Content.Shared.Utility;
@@ -45,7 +44,7 @@ namespace Content.IntegrationTests.Tests.Buckle
public async Task BuckleUnbuckleCooldownRangeTest()
{
var options = new ServerIntegrationOptions {ExtraPrototypes = PROTOTYPES};
var server = StartServerDummyTicker(options);
var server = StartServer(options);
IEntity human = null;
IEntity chair = null;
@@ -55,13 +54,14 @@ namespace Content.IntegrationTests.Tests.Buckle
await server.WaitAssertion(() =>
{
var mapManager = IoCManager.Resolve<IMapManager>();
mapManager.CreateNewMapEntity(MapId.Nullspace);
var entityManager = IoCManager.Resolve<IEntityManager>();
human = entityManager.SpawnEntity("BuckleDummy", MapCoordinates.Nullspace);
chair = entityManager.SpawnEntity("StrapDummy", MapCoordinates.Nullspace);
var gridId = new GridId(1);
var grid = mapManager.GetGrid(gridId);
var coordinates = grid.GridEntityId.ToCoordinates();
human = entityManager.SpawnEntity("BuckleDummy", coordinates);
chair = entityManager.SpawnEntity("StrapDummy", coordinates);
// Default state, unbuckled
Assert.True(human.TryGetComponent(out buckle));
@@ -197,31 +197,24 @@ namespace Content.IntegrationTests.Tests.Buckle
var options = new ServerIntegrationOptions {ExtraPrototypes = PROTOTYPES};
var server = StartServer(options);
IEntity human;
IEntity chair;
IEntity human = null;
BuckleComponent buckle = null;
HandsComponent hands = null;
IBody body = null;
await server.WaitIdleAsync();
await server.WaitAssertion(() =>
{
var mapManager = IoCManager.Resolve<IMapManager>();
var mapId = new MapId(1);
mapManager.CreateNewMapEntity(mapId);
var entityManager = IoCManager.Resolve<IEntityManager>();
var gridId = new GridId(1);
var grid = mapManager.CreateGrid(mapId, gridId);
var coordinates = grid.GridEntityId.ToCoordinates();
var tileManager = IoCManager.Resolve<ITileDefinitionManager>();
var tileId = tileManager["underplating"].TileId;
var tile = new Tile(tileId);
grid.SetTile(coordinates, tile);
var gridId = new GridId(1);
var grid = mapManager.GetGrid(gridId);
var coordinates = grid.GridEntityId.ToCoordinates();
human = entityManager.SpawnEntity("BuckleDummy", coordinates);
chair = entityManager.SpawnEntity("StrapDummy", coordinates);
IEntity chair = entityManager.SpawnEntity("StrapDummy", coordinates);
// Component sanity check
Assert.True(human.TryGetComponent(out buckle));
@@ -279,6 +272,8 @@ namespace Content.IntegrationTests.Tests.Buckle
{
Assert.Null(hands.GetItem(slot));
}
buckle.TryUnbuckle(human, true);
});
}
@@ -295,19 +290,11 @@ namespace Content.IntegrationTests.Tests.Buckle
await server.WaitAssertion(() =>
{
var mapManager = IoCManager.Resolve<IMapManager>();
var mapId = new MapId(1);
mapManager.CreateNewMapEntity(mapId);
var entityManager = IoCManager.Resolve<IEntityManager>();
var gridId = new GridId(1);
var grid = mapManager.CreateGrid(mapId, gridId);
var coordinates = grid.GridEntityId.ToCoordinates();
var tileManager = IoCManager.Resolve<ITileDefinitionManager>();
var tileId = tileManager["underplating"].TileId;
var tile = new Tile(tileId);
grid.SetTile(coordinates, tile);
var gridId = new GridId(1);
var grid = mapManager.GetGrid(gridId);
var coordinates = grid.GridEntityId.ToCoordinates();
human = entityManager.SpawnEntity("BuckleDummy", coordinates);
chair = entityManager.SpawnEntity("StrapDummy", coordinates);

View File

@@ -0,0 +1,170 @@
using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Destructible.Thresholds.Triggers;
using Content.Shared.Damage;
using Content.Shared.GameObjects.Components.Damage;
using NUnit.Framework;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using static Content.IntegrationTests.Tests.Destructible.DestructibleTestPrototypes;
namespace Content.IntegrationTests.Tests.Destructible
{
[TestFixture]
[TestOf(typeof(TotalDamageClassesTrigger))]
public class DestructibleDamageClassTest : ContentIntegrationTest
{
[Test]
public async Task Test()
{
var server = StartServerDummyTicker(new ServerContentIntegrationOption
{
ExtraPrototypes = Prototypes,
ContentBeforeIoC = () =>
{
IoCManager.Resolve<IComponentFactory>().Register<TestThresholdListenerComponent>();
}
});
await server.WaitIdleAsync();
var sEntityManager = server.ResolveDependency<IEntityManager>();
var sMapManager = server.ResolveDependency<IMapManager>();
IEntity sDestructibleEntity;
IDamageableComponent sDamageableComponent = null;
TestThresholdListenerComponent sThresholdListenerComponent = null;
await server.WaitPost(() =>
{
var mapId = new MapId(1);
var coordinates = new MapCoordinates(0, 0, mapId);
sMapManager.CreateMap(mapId);
sDestructibleEntity = sEntityManager.SpawnEntity(DestructibleDamageClassEntityId, coordinates);
sDamageableComponent = sDestructibleEntity.GetComponent<IDamageableComponent>();
sThresholdListenerComponent = sDestructibleEntity.GetComponent<TestThresholdListenerComponent>();
});
await server.WaitRunTicks(5);
await server.WaitAssertion(() =>
{
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
});
await server.WaitAssertion(() =>
{
// Raise brute damage to 5
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Brute, 5, true));
// No thresholds reached yet, the earliest one is at 10 damage
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise brute damage to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Brute, 5, true));
// No threshold reached, burn needs to be 10 as well
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise burn damage to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Burn, 10, true));
// One threshold reached, brute 10 + burn 10
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
// Threshold brute 10 + burn 10
var msg = sThresholdListenerComponent.ThresholdsReached[0];
var threshold = msg.Threshold;
// Check that it matches the YAML prototype
Assert.That(threshold.Behaviors, Is.Empty);
Assert.NotNull(threshold.Trigger);
Assert.That(threshold.Triggered, Is.True);
Assert.IsInstanceOf<TotalDamageClassesTrigger>(threshold.Trigger);
sThresholdListenerComponent.ThresholdsReached.Clear();
// Raise brute damage to 20
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Brute, 10, true));
// No new thresholds reached
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise burn damage to 20
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Burn, 10, true));
// No new thresholds reached
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Lower brute damage to 0
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Brute, -20, true));
// No new thresholds reached, healing should not trigger it
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise brute damage back up to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Brute, 10, true));
// 10 brute + 10 burn threshold reached, brute was healed and brought back to its threshold amount and slash stayed the same
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
sThresholdListenerComponent.ThresholdsReached.Clear();
// Heal both classes of damage to 0
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Brute, -10, true));
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Burn, -20, true));
// No new thresholds reached, healing should not trigger it
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise brute damage to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Brute, 10, true));
// No new thresholds reached
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise burn damage to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Burn, 10, true));
// Both classes of damage were healed and then raised again, the threshold should have been reached as triggers once is default false
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
// Threshold brute 10 + burn 10
msg = sThresholdListenerComponent.ThresholdsReached[0];
threshold = msg.Threshold;
// Check that it matches the YAML prototype
Assert.That(threshold.Behaviors, Is.Empty);
Assert.NotNull(threshold.Trigger);
Assert.That(threshold.Triggered, Is.True);
Assert.IsInstanceOf<TotalDamageClassesTrigger>(threshold.Trigger);
sThresholdListenerComponent.ThresholdsReached.Clear();
// Change triggers once to true
threshold.TriggersOnce = true;
// Heal brute and burn back to 0
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Brute, -10, true));
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Burn, -10, true));
// No new thresholds reached from healing
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise brute damage to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Brute, 10, true));
// No new thresholds reached
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise burn damage to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Burn, 10, true));
// No new thresholds reached as triggers once is set to true and it already triggered before
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
});
}
}
}

View File

@@ -0,0 +1,170 @@
using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Destructible.Thresholds.Triggers;
using Content.Shared.Damage;
using Content.Shared.GameObjects.Components.Damage;
using NUnit.Framework;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using static Content.IntegrationTests.Tests.Destructible.DestructibleTestPrototypes;
namespace Content.IntegrationTests.Tests.Destructible
{
[TestFixture]
[TestOf(typeof(TotalDamageTypesTrigger))]
public class DestructibleDamageTypeTest : ContentIntegrationTest
{
[Test]
public async Task Test()
{
var server = StartServerDummyTicker(new ServerContentIntegrationOption
{
ExtraPrototypes = Prototypes,
ContentBeforeIoC = () =>
{
IoCManager.Resolve<IComponentFactory>().Register<TestThresholdListenerComponent>();
}
});
await server.WaitIdleAsync();
var sEntityManager = server.ResolveDependency<IEntityManager>();
var sMapManager = server.ResolveDependency<IMapManager>();
IEntity sDestructibleEntity;
IDamageableComponent sDamageableComponent = null;
TestThresholdListenerComponent sThresholdListenerComponent = null;
await server.WaitPost(() =>
{
var mapId = new MapId(1);
var coordinates = new MapCoordinates(0, 0, mapId);
sMapManager.CreateMap(mapId);
sDestructibleEntity = sEntityManager.SpawnEntity(DestructibleDamageTypeEntityId, coordinates);
sDamageableComponent = sDestructibleEntity.GetComponent<IDamageableComponent>();
sThresholdListenerComponent = sDestructibleEntity.GetComponent<TestThresholdListenerComponent>();
});
await server.WaitRunTicks(5);
await server.WaitAssertion(() =>
{
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
});
await server.WaitAssertion(() =>
{
// Raise blunt damage to 5
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, 5, true));
// No thresholds reached yet, the earliest one is at 10 damage
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise blunt damage to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, 5, true));
// No threshold reached, slash needs to be 10 as well
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise slash damage to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Slash, 10, true));
// One threshold reached, blunt 10 + slash 10
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
// Threshold blunt 10 + slash 10
var msg = sThresholdListenerComponent.ThresholdsReached[0];
var threshold = msg.Threshold;
// Check that it matches the YAML prototype
Assert.That(threshold.Behaviors, Is.Empty);
Assert.NotNull(threshold.Trigger);
Assert.That(threshold.Triggered, Is.True);
Assert.IsInstanceOf<TotalDamageTypesTrigger>(threshold.Trigger);
sThresholdListenerComponent.ThresholdsReached.Clear();
// Raise blunt damage to 20
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, 10, true));
// No new thresholds reached
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise slash damage to 20
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Slash, 10, true));
// No new thresholds reached
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Lower blunt damage to 0
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, -20, true));
// No new thresholds reached, healing should not trigger it
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise blunt damage back up to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, 10, true));
// 10 blunt + 10 slash threshold reached, blunt was healed and brought back to its threshold amount and slash stayed the same
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
sThresholdListenerComponent.ThresholdsReached.Clear();
// Heal both types of damage to 0
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, -10, true));
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Slash, -20, true));
// No new thresholds reached, healing should not trigger it
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise blunt damage to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, 10, true));
// No new thresholds reached
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise slash damage to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Slash, 10, true));
// Both types of damage were healed and then raised again, the threshold should have been reached as triggers once is default false
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
// Threshold blunt 10 + slash 10
msg = sThresholdListenerComponent.ThresholdsReached[0];
threshold = msg.Threshold;
// Check that it matches the YAML prototype
Assert.That(threshold.Behaviors, Is.Empty);
Assert.NotNull(threshold.Trigger);
Assert.That(threshold.Triggered, Is.True);
Assert.IsInstanceOf<TotalDamageTypesTrigger>(threshold.Trigger);
sThresholdListenerComponent.ThresholdsReached.Clear();
// Change triggers once to true
threshold.TriggersOnce = true;
// Heal blunt and slash back to 0
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, -10, true));
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Slash, -10, true));
// No new thresholds reached from healing
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise blunt damage to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, 10, true));
// No new thresholds reached
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Raise slash damage to 10
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Slash, 10, true));
// No new thresholds reached as triggers once is set to true and it already triggered before
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
});
}
}
}

View File

@@ -0,0 +1,95 @@
using System.Linq;
using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Destructible.Thresholds;
using Content.Server.GameObjects.Components.Destructible.Thresholds.Behaviors;
using Content.Shared.Damage;
using Content.Shared.GameObjects.Components.Damage;
using NUnit.Framework;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using static Content.IntegrationTests.Tests.Destructible.DestructibleTestPrototypes;
namespace Content.IntegrationTests.Tests.Destructible
{
public class DestructibleDestructionTest : ContentIntegrationTest
{
[Test]
public async Task Test()
{
var server = StartServerDummyTicker(new ServerContentIntegrationOption
{
ExtraPrototypes = Prototypes,
ContentBeforeIoC = () =>
{
IoCManager.Resolve<IComponentFactory>().Register<TestThresholdListenerComponent>();
}
});
await server.WaitIdleAsync();
var sEntityManager = server.ResolveDependency<IEntityManager>();
var sMapManager = server.ResolveDependency<IMapManager>();
IEntity sDestructibleEntity = null;
IDamageableComponent sDamageableComponent = null;
TestThresholdListenerComponent sThresholdListenerComponent = null;
await server.WaitPost(() =>
{
var mapId = new MapId(1);
var coordinates = new MapCoordinates(0, 0, mapId);
sMapManager.CreateMap(mapId);
sDestructibleEntity = sEntityManager.SpawnEntity(DestructibleDestructionEntityId, coordinates);
sDamageableComponent = sDestructibleEntity.GetComponent<IDamageableComponent>();
sThresholdListenerComponent = sDestructibleEntity.GetComponent<TestThresholdListenerComponent>();
});
await server.WaitAssertion(() =>
{
var coordinates = sDestructibleEntity.Transform.Coordinates;
Assert.DoesNotThrow(() =>
{
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Brute, 50, true));
});
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
var threshold = sThresholdListenerComponent.ThresholdsReached[0].Threshold;
Assert.That(threshold.Triggered, Is.True);
Assert.That(threshold.Behaviors.Count, Is.EqualTo(3));
var spawnEntitiesBehavior = (SpawnEntitiesBehavior) threshold.Behaviors.Single(b => b is SpawnEntitiesBehavior);
Assert.That(spawnEntitiesBehavior.Spawn.Count, Is.EqualTo(1));
Assert.That(spawnEntitiesBehavior.Spawn.Keys.Single(), Is.EqualTo(SpawnedEntityId));
Assert.That(spawnEntitiesBehavior.Spawn.Values.Single(), Is.EqualTo(new MinMax {Min = 1, Max = 1}));
var entitiesInRange = sEntityManager.GetEntitiesInRange(coordinates, 2);
var found = false;
foreach (var entity in entitiesInRange)
{
if (entity.Prototype == null)
{
continue;
}
if (entity.Prototype.Name != SpawnedEntityId)
{
continue;
}
found = true;
break;
}
Assert.That(found, Is.True);
});
}
}
}

View File

@@ -0,0 +1,94 @@
namespace Content.IntegrationTests.Tests.Destructible
{
public static class DestructibleTestPrototypes
{
public const string SpawnedEntityId = "DestructibleTestsSpawnedEntity";
public const string DestructibleEntityId = "DestructibleTestsDestructibleEntity";
public const string DestructibleDestructionEntityId = "DestructibleTestsDestructibleDestructionEntity";
public const string DestructibleDamageTypeEntityId = "DestructibleTestsDestructibleDamageTypeEntity";
public const string DestructibleDamageClassEntityId = "DestructibleTestsDestructibleDamageClassEntity";
public static readonly string Prototypes = $@"
- type: entity
id: {SpawnedEntityId}
name: {SpawnedEntityId}
- type: entity
id: {DestructibleEntityId}
name: {DestructibleEntityId}
components:
- type: Damageable
- type: Destructible
thresholds:
- trigger:
!type:TotalDamageTrigger
damage: 20
triggersOnce: false
- trigger:
!type:TotalDamageTrigger
damage: 50
triggersOnce: false
behaviors:
- !type:PlaySoundBehavior
sound: /Audio/Effects/woodhit.ogg
- !type:SpawnEntitiesBehavior
spawn:
{SpawnedEntityId}:
min: 1
max: 1
- !type:DoActsBehavior
acts: [""Breakage""]
- type: TestThresholdListener
- type: entity
id: {DestructibleDestructionEntityId}
name: {DestructibleDestructionEntityId}
components:
- type: Damageable
- type: Destructible
thresholds:
- trigger:
!type:TotalDamageTrigger
damage: 50
behaviors:
- !type:PlaySoundBehavior
sound: /Audio/Effects/woodhit.ogg
- !type:SpawnEntitiesBehavior
spawn:
{SpawnedEntityId}:
min: 1
max: 1
- !type:DoActsBehavior # This must come last as it destroys the entity.
acts: [""Destruction""]
- type: TestThresholdListener
- type: entity
id: {DestructibleDamageTypeEntityId}
name: {DestructibleDamageTypeEntityId}
components:
- type: Damageable
- type: Destructible
thresholds:
- trigger:
!type:TotalDamageTypesTrigger
damage:
Blunt: 10
Slash: 10
- type: TestThresholdListener
- type: entity
id: {DestructibleDamageClassEntityId}
name: {DestructibleDamageClassEntityId}
components:
- type: Damageable
- type: Destructible
thresholds:
- trigger:
!type:TotalDamageClassesTrigger
damage:
Brute: 10
Burn: 10
- type: TestThresholdListener";
}
}

View File

@@ -1,99 +1,27 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Destructible;
using Content.Server.GameObjects.Components.Destructible.Thresholds;
using Content.Server.GameObjects.Components.Destructible.Thresholds.Behavior;
using Content.Server.GameObjects.Components.Destructible.Thresholds.Behaviors;
using Content.Server.GameObjects.Components.Destructible.Thresholds.Triggers;
using Content.Shared.Damage;
using Content.Shared.GameObjects.Components.Damage;
using NUnit.Framework;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using static Content.IntegrationTests.Tests.Destructible.DestructibleTestPrototypes;
namespace Content.IntegrationTests.Tests.Destructible
{
[TestFixture]
[TestOf(typeof(DestructibleComponent))]
[TestOf(typeof(Threshold))]
public class DestructibleTests : ContentIntegrationTest
public class DestructibleThresholdActivationTest : ContentIntegrationTest
{
private static readonly string SpawnedEntityId = "DestructibleTestsSpawnedEntity";
private static readonly string DestructibleEntityId = "DestructibleTestsDestructibleEntity";
private static readonly string DestructibleDestructionEntityId = "DestructibleTestsDestructibleDestructionEntity";
private static readonly string Prototypes = $@"
- type: entity
id: {SpawnedEntityId}
name: {SpawnedEntityId}
- type: entity
id: {DestructibleEntityId}
name: {DestructibleEntityId}
components:
- type: Damageable
- type: Destructible
thresholds:
20:
triggersOnce: false
50:
triggersOnce: false
behaviors:
- !type:PlaySoundBehavior
sound: /Audio/Effects/woodhit.ogg
- !type:SpawnEntitiesBehavior
spawn:
{SpawnedEntityId}:
min: 1
max: 1
- !type:DoActsBehavior
acts: [""Breakage""]
- type: TestThresholdListener
- type: entity
id: {DestructibleDestructionEntityId}
name: {DestructibleDestructionEntityId}
components:
- type: Damageable
- type: Destructible
thresholds:
50:
behaviors:
- !type:PlaySoundBehavior
sound: /Audio/Effects/woodhit.ogg
- !type:SpawnEntitiesBehavior
spawn:
{SpawnedEntityId}:
min: 1
max: 1
- !type:DoActsBehavior # This must come last as it destroys the entity.
acts: [""Destruction""]
- type: TestThresholdListener
";
private class TestThresholdListenerComponent : Component
{
public override string Name => "TestThresholdListener";
public List<DestructibleThresholdReachedMessage> ThresholdsReached { get; } = new();
public override void HandleMessage(ComponentMessage message, IComponent component)
{
base.HandleMessage(message, component);
switch (message)
{
case DestructibleThresholdReachedMessage msg:
ThresholdsReached.Add(msg);
break;
}
}
}
[Test]
public async Task TestThresholdActivation()
public async Task Test()
{
var server = StartServerDummyTicker(new ServerContentIntegrationOption
{
@@ -130,7 +58,7 @@ namespace Content.IntegrationTests.Tests.Destructible
await server.WaitAssertion(() =>
{
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.Zero);
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
});
await server.WaitAssertion(() =>
@@ -138,36 +66,31 @@ namespace Content.IntegrationTests.Tests.Destructible
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, 10, true));
// No thresholds reached yet, the earliest one is at 20 damage
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.Zero);
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, 10, true));
// Only one threshold reached, 20
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
// Threshold 20
var msg = sThresholdListenerComponent.ThresholdsReached[0];
// Check that it matches the total damage dealt
Assert.That(msg.TotalDamage, Is.EqualTo(20));
var threshold = msg.Threshold;
// Check that it matches the YAML prototype
Assert.That(threshold.Behaviors, Is.Empty);
Assert.NotNull(threshold.Trigger);
Assert.That(threshold.Triggered, Is.True);
sThresholdListenerComponent.ThresholdsReached.Clear();
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, 30, true));
// Only one threshold reached, 50, since 20 was already reached before
// One threshold reached, 50, since 20 already triggered before and it has not been healed below that amount
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
// Threshold 50
msg = sThresholdListenerComponent.ThresholdsReached[0];
// Check that it matches the total damage dealt
Assert.That(msg.TotalDamage, Is.EqualTo(50));
threshold = msg.Threshold;
// Check that it matches the YAML prototype
@@ -184,6 +107,7 @@ namespace Content.IntegrationTests.Tests.Destructible
Assert.That(spawnThreshold.Spawn.Single().Key, Is.EqualTo(SpawnedEntityId));
Assert.That(spawnThreshold.Spawn.Single().Value.Min, Is.EqualTo(1));
Assert.That(spawnThreshold.Spawn.Single().Value.Max, Is.EqualTo(1));
Assert.NotNull(threshold.Trigger);
Assert.That(threshold.Triggered, Is.True);
sThresholdListenerComponent.ThresholdsReached.Clear();
@@ -191,8 +115,19 @@ namespace Content.IntegrationTests.Tests.Destructible
// Damage for 50 again, up to 100 now
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, 50, true));
// No new thresholds reached as even though they don't only trigger once, the entity was not healed below the threshold
Assert.That(sThresholdListenerComponent.ThresholdsReached, Is.Empty);
// No thresholds reached as they weren't healed below the trigger amount
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
// Heal down to 0
sDamageableComponent.Heal();
// Damage for 100, up to 100
Assert.True(sDamageableComponent.ChangeDamage(DamageType.Blunt, 100, true));
// Two thresholds reached as damage increased past the previous, 20 and 50
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(2));
sThresholdListenerComponent.ThresholdsReached.Clear();
// Heal the entity for 40 damage, down to 60
sDamageableComponent.ChangeDamage(DamageType.Blunt, -40, true);
@@ -219,10 +154,6 @@ namespace Content.IntegrationTests.Tests.Destructible
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
msg = sThresholdListenerComponent.ThresholdsReached[0];
// Check that it matches the total damage dealt
Assert.That(msg.TotalDamage, Is.EqualTo(50));
threshold = msg.Threshold;
// Check that it matches the YAML prototype
@@ -240,6 +171,7 @@ namespace Content.IntegrationTests.Tests.Destructible
Assert.That(spawnThreshold.Spawn.Single().Key, Is.EqualTo(SpawnedEntityId));
Assert.That(spawnThreshold.Spawn.Single().Value.Min, Is.EqualTo(1));
Assert.That(spawnThreshold.Spawn.Single().Value.Max, Is.EqualTo(1));
Assert.NotNull(threshold.Trigger);
Assert.That(threshold.Triggered, Is.True);
// Reset thresholds reached
@@ -259,10 +191,9 @@ namespace Content.IntegrationTests.Tests.Destructible
// Verify the first one, should be the lowest one (20)
msg = sThresholdListenerComponent.ThresholdsReached[0];
Assert.That(msg.ThresholdAmount, Is.EqualTo(20));
// The total damage should be 50
Assert.That(msg.TotalDamage, Is.EqualTo(50));
var trigger = (TotalDamageTrigger) msg.Threshold.Trigger;
Assert.NotNull(trigger);
Assert.That(trigger.Damage, Is.EqualTo(20));
threshold = msg.Threshold;
@@ -271,10 +202,9 @@ namespace Content.IntegrationTests.Tests.Destructible
// Verify the second one, should be the highest one (50)
msg = sThresholdListenerComponent.ThresholdsReached[1];
Assert.That(msg.ThresholdAmount, Is.EqualTo(50));
// Check that it matches the total damage dealt
Assert.That(msg.TotalDamage, Is.EqualTo(50));
trigger = (TotalDamageTrigger) msg.Threshold.Trigger;
Assert.NotNull(trigger);
Assert.That(trigger.Damage, Is.EqualTo(50));
threshold = msg.Threshold;
@@ -292,6 +222,7 @@ namespace Content.IntegrationTests.Tests.Destructible
Assert.That(spawnThreshold.Spawn.Single().Key, Is.EqualTo(SpawnedEntityId));
Assert.That(spawnThreshold.Spawn.Single().Value.Min, Is.EqualTo(1));
Assert.That(spawnThreshold.Spawn.Single().Value.Max, Is.EqualTo(1));
Assert.NotNull(threshold.Trigger);
Assert.That(threshold.Triggered, Is.True);
// Reset thresholds reached
@@ -304,8 +235,9 @@ namespace Content.IntegrationTests.Tests.Destructible
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(0));
// Set both thresholds to only trigger once
foreach (var destructibleThreshold in sDestructibleComponent.LowestToHighestThresholds.Values)
foreach (var destructibleThreshold in sDestructibleComponent.Thresholds)
{
Assert.NotNull(destructibleThreshold.Trigger);
destructibleThreshold.TriggersOnce = true;
}
@@ -319,8 +251,9 @@ namespace Content.IntegrationTests.Tests.Destructible
Assert.That(sThresholdListenerComponent.ThresholdsReached, Is.Empty);
// Set both thresholds to trigger multiple times
foreach (var destructibleThreshold in sDestructibleComponent.LowestToHighestThresholds.Values)
foreach (var destructibleThreshold in sDestructibleComponent.Thresholds)
{
Assert.NotNull(destructibleThreshold.Trigger);
destructibleThreshold.TriggersOnce = false;
}
@@ -331,84 +264,5 @@ namespace Content.IntegrationTests.Tests.Destructible
Assert.That(sThresholdListenerComponent.ThresholdsReached, Is.Empty);
});
}
[Test]
public async Task DestructibleDestructionTest()
{
var server = StartServerDummyTicker(new ServerContentIntegrationOption
{
ExtraPrototypes = Prototypes,
ContentBeforeIoC = () =>
{
IoCManager.Resolve<IComponentFactory>().Register<TestThresholdListenerComponent>();
}
});
await server.WaitIdleAsync();
var sEntityManager = server.ResolveDependency<IEntityManager>();
var sMapManager = server.ResolveDependency<IMapManager>();
IEntity sDestructibleEntity = null;
IDamageableComponent sDamageableComponent = null;
DestructibleComponent sDestructibleComponent = null;
TestThresholdListenerComponent sThresholdListenerComponent = null;
await server.WaitPost(() =>
{
var mapId = new MapId(1);
var coordinates = new MapCoordinates(0, 0, mapId);
sMapManager.CreateMap(mapId);
sDestructibleEntity = sEntityManager.SpawnEntity(DestructibleDestructionEntityId, coordinates);
sDamageableComponent = sDestructibleEntity.GetComponent<IDamageableComponent>();
sDestructibleComponent = sDestructibleEntity.GetComponent<DestructibleComponent>();
sThresholdListenerComponent = sDestructibleEntity.GetComponent<TestThresholdListenerComponent>();
});
await server.WaitAssertion(() =>
{
var coordinates = sDestructibleEntity.Transform.Coordinates;
Assert.DoesNotThrow(() =>
{
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Brute, 50, true));
});
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
var threshold = sThresholdListenerComponent.ThresholdsReached[0].Threshold;
Assert.That(threshold.Triggered, Is.True);
Assert.That(threshold.Behaviors.Count, Is.EqualTo(3));
var spawnEntitiesBehavior = (SpawnEntitiesBehavior) threshold.Behaviors.Single(b => b is SpawnEntitiesBehavior);
Assert.That(spawnEntitiesBehavior.Spawn.Count, Is.EqualTo(1));
Assert.That(spawnEntitiesBehavior.Spawn.Keys.Single(), Is.EqualTo(SpawnedEntityId));
Assert.That(spawnEntitiesBehavior.Spawn.Values.Single(), Is.EqualTo(new MinMax {Min = 1, Max = 1}));
var entitiesInRange = sEntityManager.GetEntitiesInRange(coordinates, 2);
var found = false;
foreach (var entity in entitiesInRange)
{
if (entity.Prototype == null)
{
continue;
}
if (entity.Prototype.Name != SpawnedEntityId)
{
continue;
}
found = true;
break;
}
Assert.That(found, Is.True);
});
}
}
}

View File

@@ -0,0 +1,26 @@
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Destructible;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.IntegrationTests.Tests.Destructible
{
public class TestThresholdListenerComponent : Component
{
public override string Name => "TestThresholdListener";
public List<DestructibleThresholdReachedMessage> ThresholdsReached { get; } = new();
public override void HandleMessage(ComponentMessage message, IComponent component)
{
base.HandleMessage(message, component);
switch (message)
{
case DestructibleThresholdReachedMessage msg:
ThresholdsReached.Add(msg);
break;
}
}
}
}

View File

@@ -18,7 +18,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.ActionBlocking
[TestFixture]
[TestOf(typeof(CuffableComponent))]
[TestOf(typeof(HandcuffComponent))]
public class CuffUnitTest : ContentIntegrationTest
public class HandCuffTest : ContentIntegrationTest
{
private const string PROTOTYPES = @"
- type: entity
@@ -77,7 +77,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.ActionBlocking
Assert.True(secondCuffs.TryGetComponent(out secondHandcuff!), $"Second handcuffs has no {nameof(HandcuffComponent)}");
// Test to ensure cuffed players register the handcuffs
cuffed.AddNewCuffs(cuffs);
cuffed.TryAddNewCuffs(human, cuffs);
Assert.True(cuffed.CuffedHandCount > 0, "Handcuffing a player did not result in their hands being cuffed");
// Test to ensure a player with 4 hands will still only have 2 hands cuffed
@@ -86,7 +86,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.ActionBlocking
Assert.True(cuffed.CuffedHandCount == 2 && hands.Hands.Count() == 4, "Player doesn't have correct amount of hands cuffed");
// Test to give a player with 4 hands 2 sets of cuffs
cuffed.AddNewCuffs(secondCuffs);
cuffed.TryAddNewCuffs(human, secondCuffs);
Assert.True(cuffed.CuffedHandCount == 4, "Player doesn't have correct amount of hands cuffed");
});

View File

@@ -16,7 +16,6 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Mobs
[TestOf(typeof(ServerAlertsComponent))]
public class AlertsComponentTests : ContentIntegrationTest
{
[Test]
public async Task AlertsTest()
{
@@ -61,11 +60,11 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Mobs
Assert.NotNull(alertsUI);
// we should be seeing 3 alerts - our health, and the 2 debug alerts, in a specific order.
Assert.That(alertsUI.Grid.ChildCount, Is.EqualTo(3));
var alertControls = alertsUI.Grid.Children.Select(c => c as AlertControl);
Assert.That(alertsUI.Grid.ChildCount, Is.GreaterThanOrEqualTo(3));
var alertControls = alertsUI.Grid.Children.Select(c => (AlertControl) c);
var alertIDs = alertControls.Select(ac => ac.Alert.AlertType).ToArray();
var expectedIDs = new [] {AlertType.HumanHealth, AlertType.Debug1, AlertType.Debug2};
Assert.That(alertIDs, Is.EqualTo(expectedIDs));
Assert.That(alertIDs, Is.SupersetOf(expectedIDs));
});
await server.WaitAssertion(() =>
@@ -96,12 +95,12 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Mobs
clientUIMgr.StateRoot.Children.FirstOrDefault(c => c is AlertsUI) as AlertsUI;
Assert.NotNull(alertsUI);
// we should be seeing only 2 alerts now because one was cleared
Assert.That(alertsUI.Grid.ChildCount, Is.EqualTo(2));
var alertControls = alertsUI.Grid.Children.Select(c => c as AlertControl);
// we should be seeing 2 alerts now because one was cleared
Assert.That(alertsUI.Grid.ChildCount, Is.GreaterThanOrEqualTo(2));
var alertControls = alertsUI.Grid.Children.Select(c => (AlertControl) c);
var alertIDs = alertControls.Select(ac => ac.Alert.AlertType).ToArray();
var expectedIDs = new [] {AlertType.HumanHealth, AlertType.Debug2};
Assert.That(alertIDs, Is.EqualTo(expectedIDs));
Assert.That(alertIDs, Is.SupersetOf(expectedIDs));
});
}
}

View File

@@ -2,7 +2,6 @@
using Content.Server.GameObjects.Components.Gravity;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Alert;
using Content.Shared.GameObjects.Components.Gravity;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Utility;
@@ -45,10 +44,7 @@ namespace Content.IntegrationTests.Tests.Gravity
await server.WaitAssertion(() =>
{
var mapId = mapManager.CreateMap();
pauseManager.AddUninitializedMap(mapId);
var mapId = new MapId(1);
var gridId = new GridId(1);
if (!mapManager.TryGetGrid(gridId, out var grid))
@@ -56,14 +52,7 @@ namespace Content.IntegrationTests.Tests.Gravity
grid = mapManager.CreateGrid(mapId, gridId);
}
var tileDefinition = tileDefinitionManager["underplating"];
var tile = new Tile(tileDefinition.TileId);
var coordinates = grid.ToCoordinates();
grid.SetTile(coordinates, tile);
pauseManager.DoMapInitialize(mapId);
human = entityManager.SpawnEntity("HumanDummy", coordinates);
Assert.True(human.TryGetComponent(out alerts));
@@ -98,7 +87,7 @@ namespace Content.IntegrationTests.Tests.Gravity
await server.WaitAssertion(() =>
{
Assert.False(alerts.IsShowingAlert(AlertType.Weightless));
Assert.True(alerts.IsShowingAlert(AlertType.Weightless));
});
}
}