From 83d1bb13e4c479010799f6c626bce1231b31eb19 Mon Sep 17 00:00:00 2001 From: VinPropane Date: Wed, 27 May 2026 23:26:17 -0400 Subject: [PATCH] NEO-93: Reset LastAdvancedUtc on dev fixture runtime clear. Fixture reset cleared NPC rows but left a stale lazy-tick marker, causing catch-up bursts after re-acquire. Reset to MinValue with prototype rows. Co-authored-by: Cursor --- .../Npc/InMemoryNpcRuntimeStateStoreTests.cs | 2 ++ .../Game/Npc/NpcRuntimeOperationsTests.cs | 19 +++++++++++++++++++ .../Game/Npc/InMemoryNpcRuntimeStateStore.cs | 2 ++ 3 files changed, 23 insertions(+) diff --git a/server/NeonSprawl.Server.Tests/Game/Npc/InMemoryNpcRuntimeStateStoreTests.cs b/server/NeonSprawl.Server.Tests/Game/Npc/InMemoryNpcRuntimeStateStoreTests.cs index c54a31a..c4984a4 100644 --- a/server/NeonSprawl.Server.Tests/Game/Npc/InMemoryNpcRuntimeStateStoreTests.cs +++ b/server/NeonSprawl.Server.Tests/Game/Npc/InMemoryNpcRuntimeStateStoreTests.cs @@ -78,6 +78,8 @@ public sealed class InMemoryNpcRuntimeStateStoreTests Assert.Equal(NpcBehaviorState.Idle, snapshot.BehaviorState); Assert.Null(snapshot.ActiveTelegraph); } + + Assert.Equal(DateTimeOffset.MinValue, store.LastAdvancedUtc); } [Fact] diff --git a/server/NeonSprawl.Server.Tests/Game/Npc/NpcRuntimeOperationsTests.cs b/server/NeonSprawl.Server.Tests/Game/Npc/NpcRuntimeOperationsTests.cs index eeb1107..430e108 100644 --- a/server/NeonSprawl.Server.Tests/Game/Npc/NpcRuntimeOperationsTests.cs +++ b/server/NeonSprawl.Server.Tests/Game/Npc/NpcRuntimeOperationsTests.cs @@ -258,4 +258,23 @@ public sealed class NpcRuntimeOperationsTests Assert.Equal(NpcBehaviorState.Recover, snapshot.BehaviorState); Assert.Equal(T0.AddSeconds(9), snapshot.PhaseStartedUtc); } + + [Fact] + public void ResetAllPrototypeRows_ShouldClearLastAdvancedUtc_ForFreshAdvanceBaseline() + { + // Arrange + var (runtime, threat, behavior) = CreateFixture(); + SetHolder(threat, PrototypeNpcRegistry.PrototypeNpcMeleeId); + Advance(T0, runtime, threat, behavior); + runtime.LastAdvancedUtc = T0.AddHours(1); + NpcRuntimeOperations.ResetAllPrototypeRows(runtime); + SetHolder(threat, PrototypeNpcRegistry.PrototypeNpcMeleeId); + // Act + Advance(T0.AddHours(1).AddSeconds(10), runtime, threat, behavior, maxDeltaSeconds: 5); + // Assert + runtime.TryGet(PrototypeNpcRegistry.PrototypeNpcMeleeId, out var snapshot); + Assert.Equal(NpcBehaviorState.Aggro, snapshot.BehaviorState); + Assert.Equal(T0.AddHours(1).AddSeconds(10), snapshot.PhaseStartedUtc); + Assert.Equal(T0.AddHours(1).AddSeconds(10), runtime.LastAdvancedUtc); + } } diff --git a/server/NeonSprawl.Server/Game/Npc/InMemoryNpcRuntimeStateStore.cs b/server/NeonSprawl.Server/Game/Npc/InMemoryNpcRuntimeStateStore.cs index 6a9d712..7ee4883 100644 --- a/server/NeonSprawl.Server/Game/Npc/InMemoryNpcRuntimeStateStore.cs +++ b/server/NeonSprawl.Server/Game/Npc/InMemoryNpcRuntimeStateStore.cs @@ -69,6 +69,8 @@ public sealed class InMemoryNpcRuntimeStateStore : INpcRuntimeStateStore { _ = TryResetPrototypeRow(npcInstanceId); } + + LastAdvancedUtc = DateTimeOffset.MinValue; } private static string NormalizeNpcInstanceId(string? npcInstanceId) =>