Merge remote-tracking branch 'upstream/master' into ed-21-06-2024-upstream-sync
# Conflicts: # Resources/Prototypes/Maps/europa.yml # Resources/Prototypes/Maps/train.yml
This commit is contained in:
56
Content.IntegrationTests/Tests/Buckle/BuckleDragTest.cs
Normal file
56
Content.IntegrationTests/Tests/Buckle/BuckleDragTest.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using Content.IntegrationTests.Tests.Interaction;
|
||||
using Content.Shared.Buckle;
|
||||
using Content.Shared.Buckle.Components;
|
||||
using Content.Shared.Input;
|
||||
using Content.Shared.Movement.Pulling.Components;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Buckle;
|
||||
|
||||
public sealed class BuckleDragTest : InteractionTest
|
||||
{
|
||||
// Check that dragging a buckled player unbuckles them.
|
||||
[Test]
|
||||
public async Task BucklePullTest()
|
||||
{
|
||||
var urist = await SpawnTarget("MobHuman");
|
||||
var sUrist = ToServer(urist);
|
||||
await SpawnTarget("Chair");
|
||||
|
||||
var buckle = Comp<BuckleComponent>(urist);
|
||||
var strap = Comp<StrapComponent>(Target);
|
||||
var puller = Comp<PullerComponent>(Player);
|
||||
var pullable = Comp<PullableComponent>(urist);
|
||||
|
||||
#pragma warning disable RA0002
|
||||
buckle.Delay = TimeSpan.Zero;
|
||||
#pragma warning restore RA0002
|
||||
|
||||
// Initially not buckled to the chair and not pulling anything
|
||||
Assert.That(buckle.Buckled, Is.False);
|
||||
Assert.That(buckle.BuckledTo, Is.Null);
|
||||
Assert.That(strap.BuckledEntities, Is.Empty);
|
||||
Assert.That(puller.Pulling, Is.Null);
|
||||
Assert.That(pullable.Puller, Is.Null);
|
||||
Assert.That(pullable.BeingPulled, Is.False);
|
||||
|
||||
// Strap the human to the chair
|
||||
Assert.That(Server.System<SharedBuckleSystem>().TryBuckle(sUrist, SPlayer, STarget.Value));
|
||||
await RunTicks(5);
|
||||
Assert.That(buckle.Buckled, Is.True);
|
||||
Assert.That(buckle.BuckledTo, Is.EqualTo(STarget));
|
||||
Assert.That(strap.BuckledEntities, Is.EquivalentTo(new[]{sUrist}));
|
||||
Assert.That(puller.Pulling, Is.Null);
|
||||
Assert.That(pullable.Puller, Is.Null);
|
||||
Assert.That(pullable.BeingPulled, Is.False);
|
||||
|
||||
// Start pulling, and thus unbuckle them
|
||||
await PressKey(ContentKeyFunctions.TryPullObject, cursorEntity:urist);
|
||||
await RunTicks(5);
|
||||
Assert.That(buckle.Buckled, Is.False);
|
||||
Assert.That(buckle.BuckledTo, Is.Null);
|
||||
Assert.That(strap.BuckledEntities, Is.Empty);
|
||||
Assert.That(puller.Pulling, Is.EqualTo(sUrist));
|
||||
Assert.That(pullable.Puller, Is.EqualTo(SPlayer));
|
||||
Assert.That(pullable.BeingPulled, Is.True);
|
||||
}
|
||||
}
|
||||
@@ -91,7 +91,6 @@ namespace Content.IntegrationTests.Tests.Buckle
|
||||
{
|
||||
Assert.That(strap, Is.Not.Null);
|
||||
Assert.That(strap.BuckledEntities, Is.Empty);
|
||||
Assert.That(strap.OccupiedSize, Is.Zero);
|
||||
});
|
||||
|
||||
// Side effects of buckling
|
||||
@@ -111,8 +110,6 @@ namespace Content.IntegrationTests.Tests.Buckle
|
||||
|
||||
// Side effects of buckling for the strap
|
||||
Assert.That(strap.BuckledEntities, Does.Contain(human));
|
||||
Assert.That(strap.OccupiedSize, Is.EqualTo(buckle.Size));
|
||||
Assert.That(strap.OccupiedSize, Is.Positive);
|
||||
});
|
||||
|
||||
#pragma warning disable NUnit2045 // Interdependent asserts.
|
||||
@@ -122,7 +119,7 @@ namespace Content.IntegrationTests.Tests.Buckle
|
||||
// Trying to unbuckle too quickly fails
|
||||
Assert.That(buckleSystem.TryUnbuckle(human, human, buckleComp: buckle), Is.False);
|
||||
Assert.That(buckle.Buckled);
|
||||
Assert.That(buckleSystem.ToggleBuckle(human, human, chair, buckle: buckle), Is.False);
|
||||
Assert.That(buckleSystem.TryUnbuckle(human, human), Is.False);
|
||||
Assert.That(buckle.Buckled);
|
||||
#pragma warning restore NUnit2045
|
||||
});
|
||||
@@ -149,7 +146,6 @@ namespace Content.IntegrationTests.Tests.Buckle
|
||||
|
||||
// Unbuckle, strap
|
||||
Assert.That(strap.BuckledEntities, Is.Empty);
|
||||
Assert.That(strap.OccupiedSize, Is.Zero);
|
||||
});
|
||||
|
||||
#pragma warning disable NUnit2045 // Interdependent asserts.
|
||||
@@ -160,9 +156,9 @@ namespace Content.IntegrationTests.Tests.Buckle
|
||||
// On cooldown
|
||||
Assert.That(buckleSystem.TryUnbuckle(human, human, buckleComp: buckle), Is.False);
|
||||
Assert.That(buckle.Buckled);
|
||||
Assert.That(buckleSystem.ToggleBuckle(human, human, chair, buckle: buckle), Is.False);
|
||||
Assert.That(buckleSystem.TryUnbuckle(human, human), Is.False);
|
||||
Assert.That(buckle.Buckled);
|
||||
Assert.That(buckleSystem.ToggleBuckle(human, human, chair, buckle: buckle), Is.False);
|
||||
Assert.That(buckleSystem.TryUnbuckle(human, human), Is.False);
|
||||
Assert.That(buckle.Buckled);
|
||||
#pragma warning restore NUnit2045
|
||||
});
|
||||
@@ -189,7 +185,6 @@ namespace Content.IntegrationTests.Tests.Buckle
|
||||
#pragma warning disable NUnit2045 // Interdependent asserts.
|
||||
Assert.That(buckleSystem.TryBuckle(human, human, chair, buckleComp: buckle), Is.False);
|
||||
Assert.That(buckleSystem.TryUnbuckle(human, human, buckleComp: buckle), Is.False);
|
||||
Assert.That(buckleSystem.ToggleBuckle(human, human, chair, buckle: buckle), Is.False);
|
||||
#pragma warning restore NUnit2045
|
||||
|
||||
// Move near the chair
|
||||
@@ -202,12 +197,10 @@ namespace Content.IntegrationTests.Tests.Buckle
|
||||
Assert.That(buckle.Buckled);
|
||||
Assert.That(buckleSystem.TryUnbuckle(human, human, buckleComp: buckle), Is.False);
|
||||
Assert.That(buckle.Buckled);
|
||||
Assert.That(buckleSystem.ToggleBuckle(human, human, chair, buckle: buckle), Is.False);
|
||||
Assert.That(buckle.Buckled);
|
||||
#pragma warning restore NUnit2045
|
||||
|
||||
// Force unbuckle
|
||||
Assert.That(buckleSystem.TryUnbuckle(human, human, true, buckleComp: buckle));
|
||||
buckleSystem.Unbuckle(human, human);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(buckle.Buckled, Is.False);
|
||||
@@ -311,7 +304,7 @@ namespace Content.IntegrationTests.Tests.Buckle
|
||||
// Break our guy's kneecaps
|
||||
foreach (var leg in legs)
|
||||
{
|
||||
xformSystem.DetachParentToNull(leg.Id, entityManager.GetComponent<TransformComponent>(leg.Id));
|
||||
entityManager.DeleteEntity(leg.Id);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -328,7 +321,8 @@ namespace Content.IntegrationTests.Tests.Buckle
|
||||
Assert.That(hand.HeldEntity, Is.Null);
|
||||
}
|
||||
|
||||
buckleSystem.TryUnbuckle(human, human, true, buckleComp: buckle);
|
||||
buckleSystem.Unbuckle(human, human);
|
||||
Assert.That(buckle.Buckled, Is.False);
|
||||
});
|
||||
|
||||
await pair.CleanReturnAsync();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#nullable enable
|
||||
using Content.IntegrationTests.Tests.Interaction;
|
||||
using Content.IntegrationTests.Tests.Movement;
|
||||
using Robust.Shared.Maths;
|
||||
using ClimbingComponent = Content.Shared.Climbing.Components.ClimbingComponent;
|
||||
using ClimbSystem = Content.Shared.Climbing.Systems.ClimbSystem;
|
||||
|
||||
@@ -59,11 +59,6 @@ public sealed class CraftingTests : InteractionTest
|
||||
await AssertEntityLookup((Rod, 2), (Cable, 7), (ShardGlass, 2), (Spear, 1));
|
||||
}
|
||||
|
||||
// The following is wrapped in an if DEBUG. This is because of cursed state handling bugs. Tests don't (de)serialize
|
||||
// net messages and just copy objects by reference. This means that the server will directly modify cached server
|
||||
// states on the client's end. Crude fix at the moment is to used modified state handling while in debug mode
|
||||
// Otherwise, this test cannot work.
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Cancel crafting a complex recipe.
|
||||
/// </summary>
|
||||
@@ -93,28 +88,22 @@ public sealed class CraftingTests : InteractionTest
|
||||
await RunTicks(1);
|
||||
|
||||
// DoAfter is in progress. Entity not spawned, stacks have been split and someingredients are in a container.
|
||||
Assert.Multiple(async () =>
|
||||
{
|
||||
Assert.That(ActiveDoAfters.Count(), Is.EqualTo(1));
|
||||
Assert.That(sys.IsEntityInContainer(shard), Is.True);
|
||||
Assert.That(sys.IsEntityInContainer(rods), Is.False);
|
||||
Assert.That(sys.IsEntityInContainer(wires), Is.False);
|
||||
Assert.That(rodStack, Has.Count.EqualTo(8));
|
||||
Assert.That(wireStack, Has.Count.EqualTo(7));
|
||||
Assert.That(ActiveDoAfters.Count(), Is.EqualTo(1));
|
||||
Assert.That(sys.IsEntityInContainer(shard), Is.True);
|
||||
Assert.That(sys.IsEntityInContainer(rods), Is.False);
|
||||
Assert.That(sys.IsEntityInContainer(wires), Is.False);
|
||||
Assert.That(rodStack, Has.Count.EqualTo(8));
|
||||
Assert.That(wireStack, Has.Count.EqualTo(7));
|
||||
|
||||
await FindEntity(Spear, shouldSucceed: false);
|
||||
});
|
||||
await FindEntity(Spear, shouldSucceed: false);
|
||||
|
||||
// Cancel the DoAfter. Should drop ingredients to the floor.
|
||||
await CancelDoAfters();
|
||||
Assert.Multiple(async () =>
|
||||
{
|
||||
Assert.That(sys.IsEntityInContainer(rods), Is.False);
|
||||
Assert.That(sys.IsEntityInContainer(wires), Is.False);
|
||||
Assert.That(sys.IsEntityInContainer(shard), Is.False);
|
||||
await FindEntity(Spear, shouldSucceed: false);
|
||||
await AssertEntityLookup((Rod, 10), (Cable, 10), (ShardGlass, 1));
|
||||
});
|
||||
Assert.That(sys.IsEntityInContainer(rods), Is.False);
|
||||
Assert.That(sys.IsEntityInContainer(wires), Is.False);
|
||||
Assert.That(sys.IsEntityInContainer(shard), Is.False);
|
||||
await FindEntity(Spear, shouldSucceed: false);
|
||||
await AssertEntityLookup((Rod, 10), (Cable, 10), (ShardGlass, 1));
|
||||
|
||||
// Re-attempt the do-after
|
||||
#pragma warning disable CS4014 // Legacy construction code uses DoAfterAwait. See above.
|
||||
@@ -123,24 +112,17 @@ public sealed class CraftingTests : InteractionTest
|
||||
await RunTicks(1);
|
||||
|
||||
// DoAfter is in progress. Entity not spawned, ingredients are in a container.
|
||||
Assert.Multiple(async () =>
|
||||
{
|
||||
Assert.That(ActiveDoAfters.Count(), Is.EqualTo(1));
|
||||
Assert.That(sys.IsEntityInContainer(shard), Is.True);
|
||||
await FindEntity(Spear, shouldSucceed: false);
|
||||
});
|
||||
Assert.That(ActiveDoAfters.Count(), Is.EqualTo(1));
|
||||
Assert.That(sys.IsEntityInContainer(shard), Is.True);
|
||||
await FindEntity(Spear, shouldSucceed: false);
|
||||
|
||||
// Finish the DoAfter
|
||||
await AwaitDoAfters();
|
||||
|
||||
// Spear has been crafted. Rods and wires are no longer contained. Glass has been consumed.
|
||||
Assert.Multiple(async () =>
|
||||
{
|
||||
await FindEntity(Spear);
|
||||
Assert.That(sys.IsEntityInContainer(rods), Is.False);
|
||||
Assert.That(sys.IsEntityInContainer(wires), Is.False);
|
||||
Assert.That(SEntMan.Deleted(shard));
|
||||
});
|
||||
await FindEntity(Spear);
|
||||
Assert.That(sys.IsEntityInContainer(rods), Is.False);
|
||||
Assert.That(sys.IsEntityInContainer(wires), Is.False);
|
||||
Assert.That(SEntMan.Deleted(shard));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -84,8 +84,9 @@ public abstract partial class InteractionTest
|
||||
/// <summary>
|
||||
/// Spawn an entity entity and set it as the target.
|
||||
/// </summary>
|
||||
[MemberNotNull(nameof(Target))]
|
||||
protected async Task SpawnTarget(string prototype)
|
||||
[MemberNotNull(nameof(Target), nameof(STarget), nameof(CTarget))]
|
||||
#pragma warning disable CS8774 // Member must have a non-null value when exiting.
|
||||
protected async Task<NetEntity> SpawnTarget(string prototype)
|
||||
{
|
||||
Target = NetEntity.Invalid;
|
||||
await Server.WaitPost(() =>
|
||||
@@ -95,7 +96,9 @@ public abstract partial class InteractionTest
|
||||
|
||||
await RunTicks(5);
|
||||
AssertPrototype(prototype);
|
||||
return Target!.Value;
|
||||
}
|
||||
#pragma warning restore CS8774 // Member must have a non-null value when exiting.
|
||||
|
||||
/// <summary>
|
||||
/// Spawn an entity in preparation for deconstruction
|
||||
@@ -1170,14 +1173,17 @@ public abstract partial class InteractionTest
|
||||
|
||||
#region Inputs
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Make the client press and then release a key. This assumes the key is currently released.
|
||||
/// This will default to using the <see cref="Target"/> entity and <see cref="TargetCoords"/> coordinates.
|
||||
/// </summary>
|
||||
protected async Task PressKey(
|
||||
BoundKeyFunction key,
|
||||
int ticks = 1,
|
||||
NetCoordinates? coordinates = null,
|
||||
NetEntity cursorEntity = default)
|
||||
NetEntity? cursorEntity = null)
|
||||
{
|
||||
await SetKey(key, BoundKeyState.Down, coordinates, cursorEntity);
|
||||
await RunTicks(ticks);
|
||||
@@ -1186,15 +1192,17 @@ public abstract partial class InteractionTest
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make the client press or release a key
|
||||
/// Make the client press or release a key.
|
||||
/// This will default to using the <see cref="Target"/> entity and <see cref="TargetCoords"/> coordinates.
|
||||
/// </summary>
|
||||
protected async Task SetKey(
|
||||
BoundKeyFunction key,
|
||||
BoundKeyState state,
|
||||
NetCoordinates? coordinates = null,
|
||||
NetEntity cursorEntity = default)
|
||||
NetEntity? cursorEntity = null)
|
||||
{
|
||||
var coords = coordinates ?? TargetCoords;
|
||||
var target = cursorEntity ?? Target ?? default;
|
||||
ScreenCoordinates screen = default;
|
||||
|
||||
var funcId = InputManager.NetworkBindMap.KeyFunctionID(key);
|
||||
@@ -1203,7 +1211,7 @@ public abstract partial class InteractionTest
|
||||
State = state,
|
||||
Coordinates = CEntMan.GetCoordinates(coords),
|
||||
ScreenCoordinates = screen,
|
||||
Uid = CEntMan.GetEntity(cursorEntity),
|
||||
Uid = CEntMan.GetEntity(target),
|
||||
};
|
||||
|
||||
await Client.WaitPost(() => InputSystem.HandleInputCommand(ClientSession, key, message));
|
||||
|
||||
@@ -84,6 +84,7 @@ public abstract partial class InteractionTest
|
||||
protected NetEntity? Target;
|
||||
|
||||
protected EntityUid? STarget => ToServer(Target);
|
||||
|
||||
protected EntityUid? CTarget => ToClient(Target);
|
||||
|
||||
/// <summary>
|
||||
@@ -128,7 +129,6 @@ public abstract partial class InteractionTest
|
||||
|
||||
public float TickPeriod => (float) STiming.TickPeriod.TotalSeconds;
|
||||
|
||||
|
||||
// Simple mob that has one hand and can perform misc interactions.
|
||||
[TestPrototypes]
|
||||
private const string TestPrototypes = @"
|
||||
@@ -142,6 +142,8 @@ public abstract partial class InteractionTest
|
||||
- type: ComplexInteraction
|
||||
- type: MindContainer
|
||||
- type: Stripping
|
||||
- type: Puller
|
||||
- type: Physics
|
||||
- type: Tag
|
||||
tags:
|
||||
- CanPilot
|
||||
@@ -207,8 +209,8 @@ public abstract partial class InteractionTest
|
||||
SEntMan.System<SharedMindSystem>().WipeMind(ServerSession.ContentData()?.Mind);
|
||||
|
||||
old = cPlayerMan.LocalEntity;
|
||||
Player = SEntMan.GetNetEntity(SEntMan.SpawnEntity(PlayerPrototype, SEntMan.GetCoordinates(PlayerCoords)));
|
||||
SPlayer = SEntMan.GetEntity(Player);
|
||||
SPlayer = SEntMan.SpawnEntity(PlayerPrototype, SEntMan.GetCoordinates(PlayerCoords));
|
||||
Player = SEntMan.GetNetEntity(SPlayer);
|
||||
Server.PlayerMan.SetAttachedEntity(ServerSession, SPlayer);
|
||||
Hands = SEntMan.GetComponent<HandsComponent>(SPlayer);
|
||||
DoAfters = SEntMan.GetComponent<DoAfterComponent>(SPlayer);
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Buckle.Components;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Movement;
|
||||
|
||||
public sealed class BuckleMovementTest : MovementTest
|
||||
{
|
||||
// Check that interacting with a chair straps you to it and prevents movement.
|
||||
[Test]
|
||||
public async Task ChairTest()
|
||||
{
|
||||
await SpawnTarget("Chair");
|
||||
|
||||
var cAlert = Client.System<AlertsSystem>();
|
||||
var sAlert = Server.System<AlertsSystem>();
|
||||
var buckle = Comp<BuckleComponent>(Player);
|
||||
var strap = Comp<StrapComponent>(Target);
|
||||
|
||||
#pragma warning disable RA0002
|
||||
buckle.Delay = TimeSpan.Zero;
|
||||
#pragma warning restore RA0002
|
||||
|
||||
// Initially not buckled to the chair, and standing off to the side
|
||||
Assert.That(Delta(), Is.InRange(0.9f, 1.1f));
|
||||
Assert.That(buckle.Buckled, Is.False);
|
||||
Assert.That(buckle.BuckledTo, Is.Null);
|
||||
Assert.That(strap.BuckledEntities, Is.Empty);
|
||||
Assert.That(cAlert.IsShowingAlert(CPlayer, strap.BuckledAlertType), Is.False);
|
||||
Assert.That(sAlert.IsShowingAlert(SPlayer, strap.BuckledAlertType), Is.False);
|
||||
|
||||
// Interact results in being buckled to the chair
|
||||
await Interact();
|
||||
Assert.That(Delta(), Is.InRange(-0.01f, 0.01f));
|
||||
Assert.That(buckle.Buckled, Is.True);
|
||||
Assert.That(buckle.BuckledTo, Is.EqualTo(STarget));
|
||||
Assert.That(strap.BuckledEntities, Is.EquivalentTo(new[]{SPlayer}));
|
||||
Assert.That(cAlert.IsShowingAlert(CPlayer, strap.BuckledAlertType), Is.True);
|
||||
Assert.That(sAlert.IsShowingAlert(SPlayer, strap.BuckledAlertType), Is.True);
|
||||
|
||||
// Attempting to walk away does nothing
|
||||
await Move(DirectionFlag.East, 1);
|
||||
Assert.That(Delta(), Is.InRange(-0.01f, 0.01f));
|
||||
Assert.That(buckle.Buckled, Is.True);
|
||||
Assert.That(buckle.BuckledTo, Is.EqualTo(STarget));
|
||||
Assert.That(strap.BuckledEntities, Is.EquivalentTo(new[]{SPlayer}));
|
||||
Assert.That(cAlert.IsShowingAlert(CPlayer, strap.BuckledAlertType), Is.True);
|
||||
Assert.That(sAlert.IsShowingAlert(SPlayer, strap.BuckledAlertType), Is.True);
|
||||
|
||||
// Interacting again will unbuckle the player
|
||||
await Interact();
|
||||
Assert.That(Delta(), Is.InRange(-0.5f, 0.5f));
|
||||
Assert.That(buckle.Buckled, Is.False);
|
||||
Assert.That(buckle.BuckledTo, Is.Null);
|
||||
Assert.That(strap.BuckledEntities, Is.Empty);
|
||||
Assert.That(cAlert.IsShowingAlert(CPlayer, strap.BuckledAlertType), Is.False);
|
||||
Assert.That(sAlert.IsShowingAlert(SPlayer, strap.BuckledAlertType), Is.False);
|
||||
|
||||
// And now they can move away
|
||||
await Move(DirectionFlag.SouthEast, 1);
|
||||
Assert.That(Delta(), Is.LessThan(-1));
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
#nullable enable
|
||||
using System.Numerics;
|
||||
using Content.IntegrationTests.Tests.Interaction;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Interaction;
|
||||
namespace Content.IntegrationTests.Tests.Movement;
|
||||
|
||||
/// <summary>
|
||||
/// This is a variation of <see cref="InteractionTest"/> that sets up the player with a normal human entity and a simple
|
||||
73
Content.IntegrationTests/Tests/Movement/PullingTest.cs
Normal file
73
Content.IntegrationTests/Tests/Movement/PullingTest.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
#nullable enable
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Input;
|
||||
using Content.Shared.Movement.Pulling.Components;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Movement;
|
||||
|
||||
public sealed class PullingTest : MovementTest
|
||||
{
|
||||
protected override int Tiles => 4;
|
||||
|
||||
[Test]
|
||||
public async Task PullTest()
|
||||
{
|
||||
var cAlert = Client.System<AlertsSystem>();
|
||||
var sAlert = Server.System<AlertsSystem>();
|
||||
await SpawnTarget("MobHuman");
|
||||
|
||||
var puller = Comp<PullerComponent>(Player);
|
||||
var pullable = Comp<PullableComponent>(Target);
|
||||
|
||||
// Player is initially to the left of the target and not pulling anything
|
||||
Assert.That(Delta(), Is.InRange(0.9f, 1.1f));
|
||||
Assert.That(puller.Pulling, Is.Null);
|
||||
Assert.That(pullable.Puller, Is.Null);
|
||||
Assert.That(pullable.BeingPulled, Is.False);
|
||||
Assert.That(cAlert.IsShowingAlert(CPlayer, puller.PullingAlert), Is.False);
|
||||
Assert.That(sAlert.IsShowingAlert(SPlayer, puller.PullingAlert), Is.False);
|
||||
|
||||
// Start pulling
|
||||
await PressKey(ContentKeyFunctions.TryPullObject);
|
||||
await RunTicks(5);
|
||||
Assert.That(puller.Pulling, Is.EqualTo(STarget));
|
||||
Assert.That(pullable.Puller, Is.EqualTo(SPlayer));
|
||||
Assert.That(pullable.BeingPulled, Is.True);
|
||||
Assert.That(cAlert.IsShowingAlert(CPlayer, puller.PullingAlert), Is.True);
|
||||
Assert.That(sAlert.IsShowingAlert(SPlayer, puller.PullingAlert), Is.True);
|
||||
|
||||
// Move to the left and check that the target moves with the player and is still being pulled.
|
||||
await Move(DirectionFlag.West, 1);
|
||||
Assert.That(Delta(), Is.InRange(0.9f, 1.3f));
|
||||
Assert.That(puller.Pulling, Is.EqualTo(STarget));
|
||||
Assert.That(pullable.Puller, Is.EqualTo(SPlayer));
|
||||
Assert.That(pullable.BeingPulled, Is.True);
|
||||
Assert.That(cAlert.IsShowingAlert(CPlayer, puller.PullingAlert), Is.True);
|
||||
Assert.That(sAlert.IsShowingAlert(SPlayer, puller.PullingAlert), Is.True);
|
||||
|
||||
// Move in the other direction
|
||||
await Move(DirectionFlag.East, 2);
|
||||
Assert.That(Delta(), Is.InRange(-1.3f, -0.9f));
|
||||
Assert.That(puller.Pulling, Is.EqualTo(STarget));
|
||||
Assert.That(pullable.Puller, Is.EqualTo(SPlayer));
|
||||
Assert.That(pullable.BeingPulled, Is.True);
|
||||
Assert.That(cAlert.IsShowingAlert(CPlayer, puller.PullingAlert), Is.True);
|
||||
Assert.That(sAlert.IsShowingAlert(SPlayer, puller.PullingAlert), Is.True);
|
||||
|
||||
// Stop pulling
|
||||
await PressKey(ContentKeyFunctions.ReleasePulledObject);
|
||||
await RunTicks(5);
|
||||
Assert.That(Delta(), Is.InRange(-1.3f, -0.9f));
|
||||
Assert.That(puller.Pulling, Is.Null);
|
||||
Assert.That(pullable.Puller, Is.Null);
|
||||
Assert.That(pullable.BeingPulled, Is.False);
|
||||
Assert.That(cAlert.IsShowingAlert(CPlayer, puller.PullingAlert), Is.False);
|
||||
Assert.That(sAlert.IsShowingAlert(SPlayer, puller.PullingAlert), Is.False);
|
||||
|
||||
// Move back to the left and ensure the target is no longer following us.
|
||||
await Move(DirectionFlag.West, 2);
|
||||
Assert.That(Delta(), Is.GreaterThan(2f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Slipping;
|
||||
namespace Content.IntegrationTests.Tests.Movement;
|
||||
|
||||
public sealed class SlippingTest : MovementTest
|
||||
{
|
||||
@@ -36,18 +36,14 @@ public sealed class SlippingTest : MovementTest
|
||||
Assert.That(modifier, Is.EqualTo(1), "Player is not moving at full speed.");
|
||||
|
||||
// Player is to the left of the banana peel and has not slipped.
|
||||
#pragma warning disable NUnit2045
|
||||
Assert.That(Delta(), Is.GreaterThan(0.5f));
|
||||
Assert.That(sys.Slipped, Does.Not.Contain(SEntMan.GetEntity(Player)));
|
||||
#pragma warning restore NUnit2045
|
||||
|
||||
// Walking over the banana slowly does not trigger a slip.
|
||||
await SetKey(EngineKeyFunctions.Walk, BoundKeyState.Down);
|
||||
await Move(DirectionFlag.East, 1f);
|
||||
#pragma warning disable NUnit2045
|
||||
Assert.That(Delta(), Is.LessThan(0.5f));
|
||||
Assert.That(sys.Slipped, Does.Not.Contain(SEntMan.GetEntity(Player)));
|
||||
#pragma warning restore NUnit2045
|
||||
AssertComp<KnockedDownComponent>(false, Player);
|
||||
|
||||
// Moving at normal speeds does trigger a slip.
|
||||
@@ -1,15 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Preferences.Loadouts;
|
||||
using Content.Shared.Roles.Jobs;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Preferences;
|
||||
|
||||
[TestFixture]
|
||||
[Ignore("HumanoidAppearance crashes upon loading default profiles.")]
|
||||
public sealed class LoadoutTests
|
||||
{
|
||||
[TestPrototypes]
|
||||
private const string Prototypes = @"
|
||||
- type: playTimeTracker
|
||||
id: PlayTimeLoadoutTester
|
||||
|
||||
- type: loadout
|
||||
id: TestJumpsuit
|
||||
equipment: TestJumpsuit
|
||||
|
||||
- type: startingGear
|
||||
id: TestJumpsuit
|
||||
equipment:
|
||||
jumpsuit: ClothingUniformJumpsuitColorGrey
|
||||
|
||||
- type: loadoutGroup
|
||||
id: LoadoutTesterJumpsuit
|
||||
name: generic-unknown
|
||||
loadouts:
|
||||
- TestJumpsuit
|
||||
|
||||
- type: roleLoadout
|
||||
id: JobLoadoutTester
|
||||
groups:
|
||||
- LoadoutTesterJumpsuit
|
||||
|
||||
- type: job
|
||||
id: LoadoutTester
|
||||
playTimeTracker: PlayTimeLoadoutTester
|
||||
";
|
||||
|
||||
private readonly Dictionary<string, EntProtoId> _expectedEquipment = new()
|
||||
{
|
||||
["jumpsuit"] = "ClothingUniformJumpsuitColorGrey"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Checks that an empty loadout still spawns with default gear and not naked.
|
||||
/// </summary>
|
||||
@@ -26,18 +63,38 @@ public sealed class LoadoutTests
|
||||
|
||||
// Check that an empty role loadout spawns gear
|
||||
var stationSystem = entManager.System<StationSpawningSystem>();
|
||||
var inventorySystem = entManager.System<InventorySystem>();
|
||||
var testMap = await pair.CreateTestMap();
|
||||
|
||||
// That's right I can't even spawn a dummy profile without station spawning / humanoidappearance code crashing.
|
||||
var profile = new HumanoidCharacterProfile();
|
||||
|
||||
profile.SetLoadout(new RoleLoadout("TestRoleLoadout"));
|
||||
|
||||
stationSystem.SpawnPlayerMob(testMap.GridCoords, job: new JobComponent()
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
// Sue me, there's so much involved in setting up jobs
|
||||
Prototype = "CargoTechnician"
|
||||
}, profile, station: null);
|
||||
var profile = new HumanoidCharacterProfile();
|
||||
|
||||
profile.SetLoadout(new RoleLoadout("LoadoutTester"));
|
||||
|
||||
var tester = stationSystem.SpawnPlayerMob(testMap.GridCoords, job: new JobComponent()
|
||||
{
|
||||
Prototype = "LoadoutTester"
|
||||
}, profile, station: null);
|
||||
|
||||
var slotQuery = inventorySystem.GetSlotEnumerator(tester);
|
||||
var checkedCount = 0;
|
||||
while (slotQuery.NextItem(out var item, out var slot))
|
||||
{
|
||||
// Make sure the slot is valid
|
||||
Assert.That(_expectedEquipment.TryGetValue(slot.Name, out var expectedItem), $"Spawned item in unexpected slot: {slot.Name}");
|
||||
|
||||
// Make sure that the item is the right one
|
||||
var meta = entManager.GetComponent<MetaDataComponent>(item);
|
||||
Assert.That(meta.EntityPrototype.ID, Is.EqualTo(expectedItem.Id), $"Spawned wrong item in slot {slot.Name}!");
|
||||
|
||||
checkedCount++;
|
||||
}
|
||||
// Make sure the number of items is the same
|
||||
Assert.That(checkedCount, Is.EqualTo(_expectedEquipment.Count), "Number of items does not match expected!");
|
||||
|
||||
entManager.DeleteEntity(tester);
|
||||
});
|
||||
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user