refactor(runtime): own world reveal generation
This commit is contained in:
parent
4ab98b080e
commit
a6860d5563
26 changed files with 1294 additions and 502 deletions
|
|
@ -3,7 +3,9 @@ using AcDream.App.Audio;
|
|||
using AcDream.App.Streaming;
|
||||
using AcDream.Core.Selection;
|
||||
using AcDream.Core.World;
|
||||
using AcDream.Runtime;
|
||||
using AcDream.Runtime.Entities;
|
||||
using AcDream.Runtime.World;
|
||||
using DatReaderWriter.DBObjs;
|
||||
|
||||
namespace AcDream.App.Tests.Streaming;
|
||||
|
|
@ -11,12 +13,14 @@ namespace AcDream.App.Tests.Streaming;
|
|||
public sealed class WorldGenerationQuiescenceTests
|
||||
{
|
||||
private const uint LandblockId = 0x1010FFFFu;
|
||||
private const uint DestinationCell = 0x10100001u;
|
||||
private const uint ServerGuid = 0x70000001u;
|
||||
|
||||
[Fact]
|
||||
public void ActiveGeneration_HidesWorldQueriesButRetainsCanonicalOwners()
|
||||
public void RuntimeGeneration_HidesWorldQueriesButRetainsCanonicalOwners()
|
||||
{
|
||||
var availability = new WorldGenerationAvailabilityState();
|
||||
var transit = new RuntimeWorldTransitState();
|
||||
var availability = new WorldGenerationAvailabilityState(transit);
|
||||
var world = new GpuWorldState(availability: availability);
|
||||
WorldEntity entity = Entity();
|
||||
world.AddLandblock(new LoadedLandblock(
|
||||
|
|
@ -32,10 +36,12 @@ public sealed class WorldGenerationQuiescenceTests
|
|||
Assert.Single(world.LandblockEntries);
|
||||
Assert.Single(world.LandblockBounds);
|
||||
|
||||
availability.Begin(17);
|
||||
long generation =
|
||||
transit.BeginReveal(RuntimePortalKind.Portal, DestinationCell);
|
||||
world.CopyLiveEntitiesNearLandblock(LandblockId, 0, nearby);
|
||||
|
||||
Assert.False(availability.IsWorldAvailable);
|
||||
Assert.Equal(generation, availability.QuiescedGeneration);
|
||||
Assert.False(world.IsLiveEntityVisible(key));
|
||||
Assert.Empty(world.LandblockEntries);
|
||||
Assert.Empty(world.LandblockBounds);
|
||||
|
|
@ -43,17 +49,25 @@ public sealed class WorldGenerationQuiescenceTests
|
|||
Assert.Same(entity, Assert.Single(world.Entities));
|
||||
Assert.True(world.IsLoaded(LandblockId));
|
||||
|
||||
Assert.False(availability.End(16));
|
||||
Assert.False(transit.Complete(generation + 1));
|
||||
Assert.False(availability.IsWorldAvailable);
|
||||
Assert.True(availability.End(17));
|
||||
Assert.True(transit.AcknowledgeDestinationReadiness(
|
||||
Ready(generation, DestinationCell)));
|
||||
Assert.True(transit.AcknowledgeMaterialized(
|
||||
generation,
|
||||
DestinationCell));
|
||||
Assert.True(transit.Complete(generation));
|
||||
Assert.True(world.IsLiveEntityVisible(key));
|
||||
Assert.Same(entity, Assert.Single(world.LandblockEntries).Entities.Single());
|
||||
Assert.Same(
|
||||
entity,
|
||||
Assert.Single(world.LandblockEntries).Entities.Single());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SupersededReveal_StaysContinuouslySilentAndOnlyLatestGenerationReopens()
|
||||
public void SupersededReveal_StaysSilentAndOnlyLatestRuntimeEdgeResumesAudio()
|
||||
{
|
||||
var availability = new WorldGenerationAvailabilityState();
|
||||
var transit = new RuntimeWorldTransitState();
|
||||
var availability = new WorldGenerationAvailabilityState(transit);
|
||||
var world = new GpuWorldState(availability: availability);
|
||||
world.AddLandblock(new LoadedLandblock(
|
||||
LandblockId,
|
||||
|
|
@ -65,23 +79,36 @@ public sealed class WorldGenerationQuiescenceTests
|
|||
selection.Select(ServerGuid, SelectionChangeSource.World);
|
||||
var audio = new RecordingAudioQuiescence();
|
||||
var quiescence = new WorldGenerationQuiescence(
|
||||
availability,
|
||||
selection,
|
||||
world,
|
||||
guid => guid == ServerGuid ? Key(entity) : null,
|
||||
audio);
|
||||
|
||||
quiescence.Begin(1);
|
||||
quiescence.Begin(2);
|
||||
quiescence.End(1);
|
||||
WorldGenerationQuiescenceEdge firstEdge =
|
||||
quiescence.CaptureBegin();
|
||||
long first =
|
||||
transit.BeginReveal(RuntimePortalKind.Login, DestinationCell);
|
||||
quiescence.CommitBegin(firstEdge);
|
||||
WorldGenerationQuiescenceEdge secondEdge =
|
||||
quiescence.CaptureBegin();
|
||||
long second =
|
||||
transit.BeginReveal(RuntimePortalKind.Portal, DestinationCell);
|
||||
quiescence.CommitBegin(secondEdge);
|
||||
|
||||
Assert.False(transit.Complete(first));
|
||||
Assert.False(availability.IsWorldAvailable);
|
||||
Assert.Equal(2, availability.QuiescedGeneration);
|
||||
Assert.Equal(second, availability.QuiescedGeneration);
|
||||
Assert.Null(selection.SelectedObjectId);
|
||||
Assert.Equal(1, audio.SuspendCalls);
|
||||
Assert.Equal(0, audio.ResumeCalls);
|
||||
|
||||
quiescence.End(2);
|
||||
Assert.True(transit.AcknowledgeDestinationReadiness(
|
||||
Ready(second, DestinationCell)));
|
||||
Assert.True(transit.AcknowledgeMaterialized(
|
||||
second,
|
||||
DestinationCell));
|
||||
Assert.True(transit.Complete(second));
|
||||
quiescence.ObserveReleased();
|
||||
|
||||
Assert.True(availability.IsWorldAvailable);
|
||||
Assert.Equal(1, audio.ResumeCalls);
|
||||
|
|
@ -91,22 +118,37 @@ public sealed class WorldGenerationQuiescenceTests
|
|||
public void Quiesce_PreservesNonWorldInventorySelection()
|
||||
{
|
||||
const uint inventoryGuid = 0x80000001u;
|
||||
var availability = new WorldGenerationAvailabilityState();
|
||||
var transit = new RuntimeWorldTransitState();
|
||||
var availability = new WorldGenerationAvailabilityState(transit);
|
||||
var world = new GpuWorldState(availability: availability);
|
||||
var selection = new SelectionState();
|
||||
selection.Select(inventoryGuid, SelectionChangeSource.Inventory);
|
||||
var quiescence = new WorldGenerationQuiescence(
|
||||
availability,
|
||||
selection,
|
||||
world,
|
||||
_ => null,
|
||||
audio: null);
|
||||
|
||||
quiescence.Begin(3);
|
||||
WorldGenerationQuiescenceEdge edge = quiescence.CaptureBegin();
|
||||
transit.BeginReveal(RuntimePortalKind.Portal, DestinationCell);
|
||||
quiescence.CommitBegin(edge);
|
||||
|
||||
Assert.Equal(inventoryGuid, selection.SelectedObjectId);
|
||||
}
|
||||
|
||||
private static RuntimeDestinationReadiness Ready(
|
||||
long generation,
|
||||
uint destinationCell) =>
|
||||
new(
|
||||
generation,
|
||||
destinationCell,
|
||||
IsIndoor: false,
|
||||
IsUnhydratable: false,
|
||||
RequiredRenderRadius: 1,
|
||||
IsRenderNeighborhoodReady: true,
|
||||
AreCompositeTexturesReady: true,
|
||||
IsCollisionReady: true);
|
||||
|
||||
private static WorldEntity Entity() => new()
|
||||
{
|
||||
Id = 1,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue