refactor(streaming): centralize world reveal lifetime
Compose destination readiness and lifecycle telemetry behind one App-layer coordinator so login and portal begin, preparation, materialization, visibility, completion, and cancellation cannot drift apart in GameWindow wiring.
This commit is contained in:
parent
68578fa5fa
commit
a4ef57885c
4 changed files with 213 additions and 30 deletions
117
tests/AcDream.App.Tests/Streaming/WorldRevealCoordinatorTests.cs
Normal file
117
tests/AcDream.App.Tests/Streaming/WorldRevealCoordinatorTests.cs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
using AcDream.App.Streaming;
|
||||
|
||||
namespace AcDream.App.Tests.Streaming;
|
||||
|
||||
public sealed class WorldRevealCoordinatorTests
|
||||
{
|
||||
private sealed class State
|
||||
{
|
||||
public bool RenderReady { get; set; }
|
||||
public bool CollisionReady { get; set; }
|
||||
public bool CompositesReady { get; set; }
|
||||
public int InvalidateCount { get; private set; }
|
||||
public int PrepareCount { get; private set; }
|
||||
|
||||
public WorldRevealCoordinator Build(List<string>? logs = null) => new(
|
||||
isRenderNeighborhoodReady: (_, _) => RenderReady,
|
||||
isSpawnCellReady: _ => CollisionReady,
|
||||
isTerrainNeighborhoodReady: (_, _) => CollisionReady,
|
||||
areCompositeTexturesReady: () => CompositesReady,
|
||||
prepareCompositeTextures: (_, _) => PrepareCount++,
|
||||
invalidateCompositeTextures: () =>
|
||||
{
|
||||
InvalidateCount++;
|
||||
CompositesReady = false;
|
||||
},
|
||||
isSpawnClaimUnhydratable: _ => false,
|
||||
log: logs is null ? null : new Action<string>(logs.Add));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Begin_InvalidatesPriorDestinationAndStartsOneGeneration()
|
||||
{
|
||||
var state = new State { CompositesReady = true };
|
||||
WorldRevealCoordinator coordinator = state.Build();
|
||||
|
||||
long generation = coordinator.Begin(WorldRevealKind.Login);
|
||||
|
||||
Assert.Equal(1, generation);
|
||||
Assert.Equal(1, state.InvalidateCount);
|
||||
Assert.False(state.CompositesReady);
|
||||
Assert.Equal(WorldRevealKind.Login, coordinator.Snapshot.Kind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PrepareAndEvaluate_UsesOneCanonicalSnapshotForLifecycle()
|
||||
{
|
||||
const uint outdoorCell = 0x11340021u;
|
||||
var state = new State
|
||||
{
|
||||
RenderReady = true,
|
||||
CollisionReady = true,
|
||||
};
|
||||
WorldRevealCoordinator coordinator = state.Build();
|
||||
coordinator.Begin(WorldRevealKind.Login);
|
||||
|
||||
WorldRevealReadinessSnapshot first = coordinator.PrepareAndEvaluate(outdoorCell);
|
||||
state.CompositesReady = true;
|
||||
WorldRevealReadinessSnapshot ready = coordinator.PrepareAndEvaluate(outdoorCell);
|
||||
|
||||
Assert.False(first.IsReady);
|
||||
Assert.True(ready.IsReady);
|
||||
Assert.Equal(2, state.PrepareCount);
|
||||
Assert.Equal(ready, coordinator.Snapshot.Readiness);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PortalLifecycle_CountsMaterializationAndCompletesVisibleGeneration()
|
||||
{
|
||||
const uint outdoorCell = 0x3032001Cu;
|
||||
var logs = new List<string>();
|
||||
var state = new State
|
||||
{
|
||||
RenderReady = true,
|
||||
CollisionReady = true,
|
||||
CompositesReady = true,
|
||||
};
|
||||
WorldRevealCoordinator coordinator = state.Build(logs);
|
||||
coordinator.Begin(WorldRevealKind.Portal);
|
||||
state.CompositesReady = true;
|
||||
|
||||
Assert.True(coordinator.Evaluate(outdoorCell).IsReady);
|
||||
coordinator.ObserveMaterialized();
|
||||
coordinator.ObserveMaterialized();
|
||||
coordinator.ObserveWorldViewportVisible();
|
||||
coordinator.Complete();
|
||||
|
||||
Assert.Equal(1, coordinator.PortalMaterializationCount);
|
||||
Assert.True(coordinator.Snapshot.Materialized);
|
||||
Assert.True(coordinator.Snapshot.WorldViewportObserved);
|
||||
Assert.True(coordinator.Snapshot.Completed);
|
||||
Assert.Equal(0, coordinator.Snapshot.InvariantFailureCount);
|
||||
Assert.Single(logs, line => line.Contains("event=materialized", StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Cancel_PreventsLateDestinationWorkFromMutatingLifecycle()
|
||||
{
|
||||
var state = new State
|
||||
{
|
||||
RenderReady = true,
|
||||
CollisionReady = true,
|
||||
CompositesReady = true,
|
||||
};
|
||||
WorldRevealCoordinator coordinator = state.Build();
|
||||
coordinator.Begin(WorldRevealKind.Portal);
|
||||
coordinator.Cancel();
|
||||
|
||||
coordinator.PrepareAndEvaluate(0x11340021u);
|
||||
coordinator.ObserveMaterialized();
|
||||
coordinator.ObserveWorldViewportVisible();
|
||||
coordinator.Complete();
|
||||
|
||||
Assert.True(coordinator.Snapshot.Cancelled);
|
||||
Assert.Equal(default, coordinator.Snapshot.Readiness);
|
||||
Assert.Equal(0, coordinator.PortalMaterializationCount);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue