refactor(runtime): own world reveal generation
This commit is contained in:
parent
4ab98b080e
commit
a6860d5563
26 changed files with 1294 additions and 502 deletions
|
|
@ -1,6 +1,8 @@
|
|||
using AcDream.App.Streaming;
|
||||
using AcDream.App.World;
|
||||
using AcDream.Core.Selection;
|
||||
using AcDream.Runtime;
|
||||
using AcDream.Runtime.World;
|
||||
|
||||
namespace AcDream.App.Tests.Streaming;
|
||||
|
||||
|
|
@ -17,21 +19,27 @@ public sealed class WorldRevealCoordinatorTests
|
|||
public WorldRevealCoordinator Build(
|
||||
List<string>? logs = null,
|
||||
IWorldRevealStreamingScheduler? streaming = null,
|
||||
IWorldRevealRenderResourceScheduler? renderResources = 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),
|
||||
streaming: streaming,
|
||||
renderResources: renderResources);
|
||||
IWorldRevealRenderResourceScheduler? renderResources = null,
|
||||
RuntimeWorldTransitState? transit = null)
|
||||
{
|
||||
transit ??= new RuntimeWorldTransitState(
|
||||
logs is null ? null : new Action<string>(logs.Add));
|
||||
return new WorldRevealCoordinator(
|
||||
transit,
|
||||
isRenderNeighborhoodReady: (_, _) => RenderReady,
|
||||
isSpawnCellReady: _ => CollisionReady,
|
||||
isTerrainNeighborhoodReady: (_, _) => CollisionReady,
|
||||
areCompositeTexturesReady: () => CompositesReady,
|
||||
prepareCompositeTextures: (_, _) => PrepareCount++,
|
||||
invalidateCompositeTextures: () =>
|
||||
{
|
||||
InvalidateCount++;
|
||||
CompositesReady = false;
|
||||
},
|
||||
isSpawnClaimUnhydratable: _ => false,
|
||||
streaming: streaming,
|
||||
renderResources: renderResources);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -40,12 +48,12 @@ public sealed class WorldRevealCoordinatorTests
|
|||
var state = new State { CompositesReady = true };
|
||||
WorldRevealCoordinator coordinator = state.Build();
|
||||
|
||||
long generation = coordinator.Begin(WorldRevealKind.Login, 0x11340021u);
|
||||
long generation = coordinator.Begin(RuntimePortalKind.Login, 0x11340021u);
|
||||
|
||||
Assert.Equal(1, generation);
|
||||
Assert.Equal(1, state.InvalidateCount);
|
||||
Assert.False(state.CompositesReady);
|
||||
Assert.Equal(WorldRevealKind.Login, coordinator.Snapshot.Kind);
|
||||
Assert.Equal(RuntimePortalKind.Login, coordinator.Snapshot.Kind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -58,7 +66,7 @@ public sealed class WorldRevealCoordinatorTests
|
|||
CollisionReady = true,
|
||||
};
|
||||
WorldRevealCoordinator coordinator = state.Build();
|
||||
coordinator.Begin(WorldRevealKind.Login, outdoorCell);
|
||||
coordinator.Begin(RuntimePortalKind.Login, outdoorCell);
|
||||
|
||||
WorldRevealReadinessSnapshot first = coordinator.PrepareAndEvaluate(outdoorCell);
|
||||
state.CompositesReady = true;
|
||||
|
|
@ -67,7 +75,8 @@ public sealed class WorldRevealCoordinatorTests
|
|||
Assert.False(first.IsReady);
|
||||
Assert.True(ready.IsReady);
|
||||
Assert.Equal(2, state.PrepareCount);
|
||||
Assert.Equal(ready, coordinator.Snapshot.Readiness);
|
||||
Assert.Equal(ready.DestinationCell, coordinator.Snapshot.DestinationCell);
|
||||
Assert.Equal(ready.IsReady, coordinator.Snapshot.IsReady);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -82,7 +91,7 @@ public sealed class WorldRevealCoordinatorTests
|
|||
CompositesReady = true,
|
||||
};
|
||||
WorldRevealCoordinator coordinator = state.Build(logs);
|
||||
coordinator.Begin(WorldRevealKind.Portal, outdoorCell);
|
||||
coordinator.Begin(RuntimePortalKind.Portal, outdoorCell);
|
||||
state.CompositesReady = true;
|
||||
|
||||
Assert.True(coordinator.Evaluate(outdoorCell).IsReady);
|
||||
|
|
@ -109,7 +118,7 @@ public sealed class WorldRevealCoordinatorTests
|
|||
CompositesReady = true,
|
||||
};
|
||||
WorldRevealCoordinator coordinator = state.Build();
|
||||
coordinator.Begin(WorldRevealKind.Portal, 0x11340021u);
|
||||
coordinator.Begin(RuntimePortalKind.Portal, 0x11340021u);
|
||||
coordinator.Cancel();
|
||||
|
||||
coordinator.PrepareAndEvaluate(0x11340021u);
|
||||
|
|
@ -118,23 +127,25 @@ public sealed class WorldRevealCoordinatorTests
|
|||
coordinator.Complete();
|
||||
|
||||
Assert.True(coordinator.Snapshot.Cancelled);
|
||||
Assert.Equal(default, coordinator.Snapshot.Readiness);
|
||||
Assert.Equal(0x11340021u, coordinator.Snapshot.DestinationCell);
|
||||
Assert.False(coordinator.Snapshot.IsReady);
|
||||
Assert.Equal(0, coordinator.PortalMaterializationCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RevealLifetime_QuiescesContinuouslyAndOnlyActiveGenerationReopens()
|
||||
{
|
||||
var availability = new WorldGenerationAvailabilityState();
|
||||
var transit = new RuntimeWorldTransitState();
|
||||
var availability = new WorldGenerationAvailabilityState(transit);
|
||||
var world = new GpuWorldState(availability: availability);
|
||||
var audio = new RecordingAudioQuiescence();
|
||||
var quiescence = new WorldGenerationQuiescence(
|
||||
availability,
|
||||
new SelectionState(),
|
||||
world,
|
||||
_ => null,
|
||||
audio);
|
||||
var coordinator = new WorldRevealCoordinator(
|
||||
transit,
|
||||
isRenderNeighborhoodReady: (_, _) => true,
|
||||
isSpawnCellReady: _ => true,
|
||||
isTerrainNeighborhoodReady: (_, _) => true,
|
||||
|
|
@ -144,12 +155,14 @@ public sealed class WorldRevealCoordinatorTests
|
|||
isSpawnClaimUnhydratable: _ => false,
|
||||
quiescence: quiescence);
|
||||
|
||||
Assert.Equal(1, coordinator.Begin(WorldRevealKind.Login, 0x11340021u));
|
||||
Assert.Equal(2, coordinator.Begin(WorldRevealKind.Portal, 0x11340021u));
|
||||
Assert.Equal(1, coordinator.Begin(RuntimePortalKind.Login, 0x11340021u));
|
||||
Assert.Equal(2, coordinator.Begin(RuntimePortalKind.Portal, 0x11340021u));
|
||||
Assert.False(availability.IsWorldAvailable);
|
||||
Assert.Equal(2, availability.QuiescedGeneration);
|
||||
Assert.Equal(1, audio.SuspendCalls);
|
||||
|
||||
Assert.True(coordinator.Evaluate(0x11340021u).IsReady);
|
||||
coordinator.ObserveMaterialized();
|
||||
coordinator.Complete();
|
||||
|
||||
Assert.True(availability.IsWorldAvailable);
|
||||
|
|
@ -159,17 +172,18 @@ public sealed class WorldRevealCoordinatorTests
|
|||
[Fact]
|
||||
public void Materialization_ReopensWorldBeforePortalViewportRelease()
|
||||
{
|
||||
var availability = new WorldGenerationAvailabilityState();
|
||||
var transit = new RuntimeWorldTransitState();
|
||||
var availability = new WorldGenerationAvailabilityState(transit);
|
||||
var world = new GpuWorldState(availability: availability);
|
||||
var audio = new RecordingAudioQuiescence();
|
||||
var quiescence = new WorldGenerationQuiescence(
|
||||
availability,
|
||||
new SelectionState(),
|
||||
world,
|
||||
_ => null,
|
||||
audio);
|
||||
var scheduler = new RecordingDestinationScheduler();
|
||||
var coordinator = new WorldRevealCoordinator(
|
||||
transit,
|
||||
isRenderNeighborhoodReady: (_, _) => true,
|
||||
isSpawnCellReady: _ => true,
|
||||
isTerrainNeighborhoodReady: (_, _) => true,
|
||||
|
|
@ -180,10 +194,11 @@ public sealed class WorldRevealCoordinatorTests
|
|||
quiescence: quiescence,
|
||||
streaming: scheduler);
|
||||
long generation = coordinator.Begin(
|
||||
WorldRevealKind.Portal,
|
||||
RuntimePortalKind.Portal,
|
||||
0x3032001Cu);
|
||||
|
||||
Assert.False(availability.IsWorldAvailable);
|
||||
Assert.True(coordinator.Evaluate(0x3032001Cu).IsReady);
|
||||
|
||||
coordinator.ObserveMaterialized();
|
||||
|
||||
|
|
@ -211,16 +226,17 @@ public sealed class WorldRevealCoordinatorTests
|
|||
[Fact]
|
||||
public void TunnelContinue_TicksDestinationObjectsBehindPortalViewport()
|
||||
{
|
||||
var availability = new WorldGenerationAvailabilityState();
|
||||
var transit = new RuntimeWorldTransitState();
|
||||
var availability = new WorldGenerationAvailabilityState(transit);
|
||||
var world = new GpuWorldState(availability: availability);
|
||||
var quiescence = new WorldGenerationQuiescence(
|
||||
availability,
|
||||
new SelectionState(),
|
||||
world,
|
||||
_ => null,
|
||||
audio: null);
|
||||
var scheduler = new RecordingDestinationScheduler();
|
||||
var coordinator = new WorldRevealCoordinator(
|
||||
transit,
|
||||
isRenderNeighborhoodReady: (_, _) => true,
|
||||
isSpawnCellReady: _ => true,
|
||||
isTerrainNeighborhoodReady: (_, _) => true,
|
||||
|
|
@ -243,11 +259,12 @@ public sealed class WorldRevealCoordinatorTests
|
|||
() => calls.Add("spatial")),
|
||||
availability);
|
||||
|
||||
coordinator.Begin(WorldRevealKind.Portal, 0x3032001Cu);
|
||||
coordinator.Begin(RuntimePortalKind.Portal, 0x3032001Cu);
|
||||
frame.Tick(1f / 60f);
|
||||
Assert.Equal(["network", "commands"], calls);
|
||||
|
||||
calls.Clear();
|
||||
Assert.True(coordinator.Evaluate(0x3032001Cu).IsReady);
|
||||
coordinator.ObserveMaterialized();
|
||||
frame.Tick(1f / 60f);
|
||||
|
||||
|
|
@ -256,6 +273,43 @@ public sealed class WorldRevealCoordinatorTests
|
|||
Assert.False(coordinator.Snapshot.WorldViewportObserved);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SessionReset_ReleasesHostEdgesAndClearsRuntimeSnapshot()
|
||||
{
|
||||
var transit = new RuntimeWorldTransitState();
|
||||
var availability = new WorldGenerationAvailabilityState(transit);
|
||||
var world = new GpuWorldState(availability: availability);
|
||||
var audio = new RecordingAudioQuiescence();
|
||||
var quiescence = new WorldGenerationQuiescence(
|
||||
new SelectionState(),
|
||||
world,
|
||||
_ => null,
|
||||
audio);
|
||||
var scheduler = new RecordingDestinationScheduler();
|
||||
var coordinator = new WorldRevealCoordinator(
|
||||
transit,
|
||||
isRenderNeighborhoodReady: (_, _) => false,
|
||||
isSpawnCellReady: _ => false,
|
||||
isTerrainNeighborhoodReady: (_, _) => false,
|
||||
areCompositeTexturesReady: () => false,
|
||||
prepareCompositeTextures: (_, _) => { },
|
||||
invalidateCompositeTextures: () => { },
|
||||
isSpawnClaimUnhydratable: _ => false,
|
||||
quiescence: quiescence,
|
||||
streaming: scheduler);
|
||||
long generation = coordinator.Begin(
|
||||
RuntimePortalKind.Portal,
|
||||
0x3032001Cu);
|
||||
|
||||
coordinator.ResetSession();
|
||||
|
||||
Assert.Equal(RuntimePortalSnapshot.Idle, coordinator.Snapshot);
|
||||
Assert.True(availability.IsWorldAvailable);
|
||||
Assert.Equal(1, audio.SuspendCalls);
|
||||
Assert.Equal(1, audio.ResumeCalls);
|
||||
Assert.Equal([generation], scheduler.Ends);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RevealGeneration_OwnsExactDestinationReservationUntilCompletion()
|
||||
{
|
||||
|
|
@ -264,10 +318,10 @@ public sealed class WorldRevealCoordinatorTests
|
|||
WorldRevealCoordinator coordinator = state.Build(streaming: scheduler);
|
||||
|
||||
long first = coordinator.Begin(
|
||||
WorldRevealKind.Portal,
|
||||
RuntimePortalKind.Portal,
|
||||
0x11340021u);
|
||||
long second = coordinator.Begin(
|
||||
WorldRevealKind.Portal,
|
||||
RuntimePortalKind.Portal,
|
||||
0x20210123u);
|
||||
|
||||
Assert.Equal(
|
||||
|
|
@ -289,10 +343,10 @@ public sealed class WorldRevealCoordinatorTests
|
|||
state.Build(renderResources: resources);
|
||||
|
||||
long first = coordinator.Begin(
|
||||
WorldRevealKind.Portal,
|
||||
RuntimePortalKind.Portal,
|
||||
0x11340021u);
|
||||
long second = coordinator.Begin(
|
||||
WorldRevealKind.Portal,
|
||||
RuntimePortalKind.Portal,
|
||||
0x20210123u);
|
||||
|
||||
Assert.Equal([first, second], resources.Begins);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue