neon-sprawl/server/NeonSprawl.Server.Tests/Game/Npc/AggroOperationsTests.cs

124 lines
5.2 KiB
C#

using Microsoft.Extensions.Options;
using NeonSprawl.Server.Game.Npc;
using NeonSprawl.Server.Game.PositionState;
using Xunit;
namespace NeonSprawl.Server.Tests.Game.Npc;
public sealed class AggroOperationsTests
{
private static InMemoryPositionStateStore CreatePositionStoreAt(double x, double y, double z)
{
var store = new InMemoryPositionStateStore(Options.Create(new GamePositionOptions
{
DevPlayerId = "dev-local-1",
DefaultPosition = new DefaultPositionOptions { X = x, Y = y, Z = z },
}));
return store;
}
[Fact]
public void TryAcquire_ShouldSetHolder_WhenRowEmpty()
{
// Arrange
var threatStore = new InMemoryThreatStateStore();
// Act
var acquired = AggroOperations.TryAcquire(
PrototypeNpcRegistry.PrototypeNpcMeleeId,
"dev-local-1",
threatStore);
threatStore.TryGet(PrototypeNpcRegistry.PrototypeNpcMeleeId, out var snapshot);
// Assert
Assert.True(acquired);
Assert.Equal("dev-local-1", snapshot.AggroHolderPlayerId);
}
[Fact]
public void TryAcquire_ShouldNoOp_WhenHolderAlreadySet()
{
// Arrange
var threatStore = new InMemoryThreatStateStore();
_ = AggroOperations.TryAcquire(PrototypeNpcRegistry.PrototypeNpcMeleeId, "dev-local-1", threatStore);
// Act
var secondAcquire = AggroOperations.TryAcquire(
PrototypeNpcRegistry.PrototypeNpcMeleeId,
"dev-local-1",
threatStore);
threatStore.TryGet(PrototypeNpcRegistry.PrototypeNpcMeleeId, out var snapshot);
// Assert
Assert.False(secondAcquire);
Assert.Equal("dev-local-1", snapshot.AggroHolderPlayerId);
}
[Fact]
public void TryClearOnLeashForPlayer_ShouldClearHolder_WhenPlayerBeyondLeashRadius()
{
// Arrange
var behaviorRegistry = PrototypeNpcTestFixtures.CreateBehaviorRegistry();
var threatStore = new InMemoryThreatStateStore();
var positions = CreatePositionStoreAt(0, 0, 0);
_ = AggroOperations.TryAcquire(PrototypeNpcRegistry.PrototypeNpcMeleeId, "dev-local-1", threatStore);
positions.TryApplyMoveTarget("dev-local-1", 12, 0, 12, out _);
// Act
AggroOperations.TryClearOnLeashForPlayer("dev-local-1", positions, behaviorRegistry, threatStore);
threatStore.TryGet(PrototypeNpcRegistry.PrototypeNpcMeleeId, out var snapshot);
// Assert
Assert.Null(snapshot.AggroHolderPlayerId);
}
[Fact]
public void TryClearOnLeashForPlayer_ShouldKeepHolder_WhenPlayerInsideLeashRadius()
{
// Arrange
var behaviorRegistry = PrototypeNpcTestFixtures.CreateBehaviorRegistry();
var threatStore = new InMemoryThreatStateStore();
var positions = CreatePositionStoreAt(0, 0, 0);
_ = AggroOperations.TryAcquire(PrototypeNpcRegistry.PrototypeNpcMeleeId, "dev-local-1", threatStore);
positions.TryApplyMoveTarget("dev-local-1", 1, 0, 1, out _);
// Act
AggroOperations.TryClearOnLeashForPlayer("dev-local-1", positions, behaviorRegistry, threatStore);
threatStore.TryGet(PrototypeNpcRegistry.PrototypeNpcMeleeId, out var snapshot);
// Assert
Assert.Equal("dev-local-1", snapshot.AggroHolderPlayerId);
}
[Fact]
public void TryClearOnLeashForPlayer_ShouldKeepHolder_WhenPlayerAtExactLeashRadius()
{
// Arrange
var behaviorRegistry = PrototypeNpcTestFixtures.CreateBehaviorRegistry();
var threatStore = new InMemoryThreatStateStore();
var positions = CreatePositionStoreAt(0, 0, 0);
_ = AggroOperations.TryAcquire(PrototypeNpcRegistry.PrototypeNpcMeleeId, "dev-local-1", threatStore);
// Melee anchor (-3, -3); leash 16.0 — X = 13 is exactly 16 m horizontal from anchor.
positions.TryApplyMoveTarget("dev-local-1", 13, 0, -3, out _);
// Act
AggroOperations.TryClearOnLeashForPlayer("dev-local-1", positions, behaviorRegistry, threatStore);
threatStore.TryGet(PrototypeNpcRegistry.PrototypeNpcMeleeId, out var snapshot);
// Assert
Assert.Equal("dev-local-1", snapshot.AggroHolderPlayerId);
}
[Fact]
public void TryAcquire_ShouldSetHolderAgain_AfterLeashClear()
{
// Arrange
var behaviorRegistry = PrototypeNpcTestFixtures.CreateBehaviorRegistry();
var threatStore = new InMemoryThreatStateStore();
var positions = CreatePositionStoreAt(0, 0, 0);
_ = AggroOperations.TryAcquire(PrototypeNpcRegistry.PrototypeNpcMeleeId, "dev-local-1", threatStore);
positions.TryApplyMoveTarget("dev-local-1", 12, 0, 12, out _);
AggroOperations.TryClearOnLeashForPlayer("dev-local-1", positions, behaviorRegistry, threatStore);
positions.TryApplyMoveTarget("dev-local-1", 0, 0, 0, out _);
// Act
var reacquired = AggroOperations.TryAcquire(
PrototypeNpcRegistry.PrototypeNpcMeleeId,
"dev-local-1",
threatStore);
threatStore.TryGet(PrototypeNpcRegistry.PrototypeNpcMeleeId, out var snapshot);
// Assert
Assert.True(reacquired);
Assert.Equal("dev-local-1", snapshot.AggroHolderPlayerId);
}
}