CatStation/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs
chromiumboy 2ca5d9d81a
Disposals refactor (#40540)
* Initial commit

* Added pods

* Transit tubes should no longer connect with disposal pipes

* Updated the transit tube sprites

* Revisited how the transit tubes work

* Fixing merge conflict

* Updated sprites

* Simplified disposal component collections and updated yaml

* Moved the majority of the disposals code to Shared

* Move disposed ents via physics

* Disposal unit now use generic visualizers

* Followers of disposed entities have predicted movement

* Made BeingDisposedSystem shared

* Added documentation for some components

* Code clean up

* Removed unneeded container entries, tubes use directions instead of angles

* Many EntityUid/Comp -> Entity<Comp> changes

* Updated DisposableSystem

* Review of DisposalTubeSystem

* Review of DisposalUnitSystem

* Review of DisposalSignalRouterSystem

* Unit updates

* Fixing merge conflict

* Merge conflict resolved

* Re-organization of systems and components

* Allow trapped entities to escape endless loops

* Fix for item ejection

* UI updates

* Minor tweak

* Fixes for transit tubes

* Removed placeholder sprite

* Removed transit tubes (for now)

* Moved exit stun time to DisposalHolderComponent

* Added a limit on the amount of damage that can sustained from disposals travel

* Fix for PVS-related sound issues

* Added a limit on the number of entities that can be inserted into units

* Clean up

* Undid file scoping

* Fixed test fail

* Fixed test fail

* Increased min default capacity of disposal units

* Fixed audio spam occurring when dumping multiple items into a disposal unit

* Tile prying now occurs whenever exiting an open pipe

* Prevent attacking and interactions while traveling through disposals

* Added generic verbs for entering/exiting disposal units

* Fixed UI prediction bug

* Bug fixes

* Small improvements

* Moved the disposal holder prototype from the disposal entry to the unit

* Minor clean up

* Added support for a disposal holder despawn effect

* Added prediction guard

* Test fail fix

* Re-added new escape behavior

* Removed outdated PVS code

* Clean up

* More escape behavior changes

* More clean up

* Updated exit selection logic

* Bug fix

* More clean up

* Split up disposal unit code

* Cleaned up disposal units some more

* Adjusted exit throw distance

* Capitalized disposal and mailing unit window titles

* Bug fixes

* Taggers and routers show existing tags when the UI opens

* Fixed test fail

* test fail fix

* Minor performance improvement

* Minor improvement in pathing

* merge conflicts

* Fix heisentest

* Fixed mispredict

* Updated system referencing conventions

* Updated to account for changes made to the code

* Attempting to fix submodule issue

* Addressing test fails

* Additional fixes for tests

* Addressing reviewer comments

* Cleaned up exit randomization

* T-ray can see disposal pipes when in 'pipe' mode

* Fix for flush animation flickering

* mild thing

* fix both

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
2026-05-27 04:38:03 +00:00

238 lines
7.9 KiB
C#

#nullable enable annotations
using System.Linq;
using System.Numerics;
using Content.IntegrationTests.Fixtures;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.Disposal.Components;
using Content.Shared.Disposal.Tube;
using Content.Shared.Disposal.Unit;
using Robust.Shared.GameObjects;
using Robust.Shared.Reflection;
namespace Content.IntegrationTests.Tests.Disposal
{
[TestFixture]
[TestOf(typeof(DisposalHolderComponent))]
[TestOf(typeof(DisposalEntryComponent))]
[TestOf(typeof(DisposalUnitComponent))]
public sealed class DisposalUnitTest : GameTest
{
[Reflect(false)]
private sealed class DisposalUnitTestSystem : EntitySystem
{
}
private static void UnitInsert(EntityUid uid, DisposalUnitComponent unit, bool result, SharedDisposalUnitSystem disposalSystem, params EntityUid[] entities)
{
foreach (var entity in entities)
{
Assert.That(disposalSystem.TryInsert((uid, unit), entity, null), Is.EqualTo(result));
}
}
private static void UnitContains(DisposalUnitComponent unit, bool result, params EntityUid[] entities)
{
foreach (var entity in entities)
{
Assert.That(unit.Container.ContainedEntities.Contains(entity), Is.EqualTo(result));
}
}
private static void UnitInsertContains(EntityUid uid, DisposalUnitComponent unit, bool result, SharedDisposalUnitSystem disposalSystem, params EntityUid[] entities)
{
UnitInsert(uid, unit, result, disposalSystem, entities);
UnitContains(unit, result, entities);
}
private static void Flush(EntityUid unitEntity, DisposalUnitComponent unit, bool result, SharedDisposalUnitSystem disposalSystem, params EntityUid[] entities)
{
Assert.Multiple(() =>
{
Assert.That(unit.Container.ContainedEntities, Is.SupersetOf(entities));
Assert.That(entities, Has.Length.EqualTo(unit.Container.ContainedEntities.Count));
Assert.That(result, Is.EqualTo(disposalSystem.TryFlush((unitEntity, unit))));
Assert.That(result || entities.Length == 0, Is.EqualTo(unit.Container.ContainedEntities.Count == 0));
});
}
[TestPrototypes]
private const string Prototypes = @"
- type: entity
name: HumanDisposalDummy
id: HumanDisposalDummy
components:
- type: Body
prototype: Human
- type: MobState
- type: MobThresholds
thresholds:
0: Alive
200: Dead
- type: Damageable
- type: Injurable
damageContainer: Biological
- type: Physics
bodyType: KinematicController
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeCircle
radius: 0.35
- type: DoAfter
- type: entity
name: WrenchDummy
id: WrenchDummy
components:
- type: Item
- type: Tool
qualities:
- Anchoring
- type: Physics
bodyType: Dynamic
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeCircle
radius: 0.35
- type: DoAfter
- type: entity
name: DisposalUnitDummy
id: DisposalUnitDummy
components:
- type: DisposalUnit
entryDelay: 0
draggedEntryDelay: 0
flushTime: 0
whitelist:
components:
- Item
- Body
- type: Anchorable
- type: ApcPowerReceiver
- type: Physics
bodyType: Static
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeCircle
radius: 0.35
- type: entity
name: DisposalTrunkDummy
id: DisposalTrunkDummy
components:
- type: DisposalEntry
- type: DisposalTube
- type: Transform
anchored: true
";
[Test]
public async Task Test()
{
var pair = Pair;
var server = pair.Server;
var testMap = await pair.CreateTestMap();
EntityUid human = default!;
EntityUid wrench = default!;
EntityUid disposalUnit = default!;
EntityUid disposalTrunk = default!;
EntityUid unitUid = default;
DisposalUnitComponent unitComponent = default!;
var entityManager = server.ResolveDependency<IEntityManager>();
var xformSystem = entityManager.System<SharedTransformSystem>();
var disposalSystem = entityManager.System<SharedDisposalUnitSystem>();
var power = entityManager.System<PowerReceiverSystem>();
await server.WaitAssertion(() =>
{
// Spawn the entities
var coordinates = testMap.GridCoords;
human = entityManager.SpawnEntity("HumanDisposalDummy", coordinates);
wrench = entityManager.SpawnEntity("WrenchDummy", coordinates);
disposalUnit = entityManager.SpawnEntity("DisposalUnitDummy", coordinates);
disposalTrunk = entityManager.SpawnEntity("DisposalTrunkDummy", coordinates);
// Test for components existing
unitUid = disposalUnit;
Assert.Multiple(() =>
{
Assert.That(entityManager.TryGetComponent(disposalUnit, out unitComponent));
Assert.That(entityManager.HasComponent<DisposalEntryComponent>(disposalTrunk));
});
// Can't insert, unanchored and unpowered
xformSystem.Unanchor(unitUid, entityManager.GetComponent<TransformComponent>(unitUid));
UnitInsertContains(disposalUnit, unitComponent, false, disposalSystem, human, wrench, disposalUnit, disposalTrunk);
});
await server.WaitAssertion(() =>
{
// Anchor the disposal unit
xformSystem.AnchorEntity(unitUid, entityManager.GetComponent<TransformComponent>(unitUid));
// No power
Assert.That(power.IsPowered(unitUid), Is.False);
// Can't insert the trunk or the unit into itself
UnitInsertContains(unitUid, unitComponent, false, disposalSystem, disposalUnit, disposalTrunk);
// Can insert mobs and items
UnitInsertContains(unitUid, unitComponent, true, disposalSystem, human, wrench);
});
await server.WaitAssertion(() =>
{
var worldPos = xformSystem.GetWorldPosition(disposalTrunk);
// Move the disposal trunk away
xformSystem.SetWorldPosition(disposalTrunk, worldPos + new Vector2(1, 0));
// Fail to flush with a mob and an item
Flush(disposalUnit, unitComponent, false, disposalSystem, human, wrench);
});
await server.WaitAssertion(() =>
{
var xform = entityManager.GetComponent<TransformComponent>(disposalTrunk);
var worldPos = xformSystem.GetWorldPosition(disposalUnit);
// Move the disposal trunk back
xformSystem.SetWorldPosition(disposalTrunk, worldPos);
xformSystem.AnchorEntity((disposalTrunk, xform));
// Fail to flush with a mob and an item, no power
Flush(disposalUnit, unitComponent, false, disposalSystem, human, wrench);
});
await server.WaitAssertion(() =>
{
// Remove power need
Assert.That(entityManager.TryGetComponent(disposalUnit, out ApcPowerReceiverComponent powerComp));
power.SetNeedsPower(disposalUnit, false);
powerComp.Powered = true;
// Flush with a mob and an item
Flush(disposalUnit, unitComponent, true, disposalSystem, human, wrench);
});
await server.WaitAssertion(() =>
{
// Re-pressurizing
Flush(disposalUnit, unitComponent, false, disposalSystem);
});
}
}
}