refactor(runtime): extract the live object frame
This commit is contained in:
parent
99a3e819c4
commit
4e4aac2c5a
27 changed files with 1217 additions and 371 deletions
|
|
@ -1,9 +1,11 @@
|
|||
using System.Numerics;
|
||||
using AcDream.App.Rendering;
|
||||
using AcDream.App.Streaming;
|
||||
using AcDream.App.Update;
|
||||
using AcDream.App.World;
|
||||
using AcDream.Content.Vfx;
|
||||
using AcDream.Core.Physics;
|
||||
using AcDream.Core.World;
|
||||
using DatReaderWriter;
|
||||
using DatReaderWriter.DBObjs;
|
||||
using DatReaderWriter.Options;
|
||||
|
|
@ -25,10 +27,11 @@ public sealed class RecallTeleportAnimationTests
|
|||
{
|
||||
var calls = new List<string>();
|
||||
var frame = new RetailLiveFrameCoordinator(
|
||||
_ => calls.Add("objects"),
|
||||
() => calls.Add("network"),
|
||||
() => calls.Add("commands"),
|
||||
() => calls.Add("spatial"));
|
||||
new TestLiveObjectFramePhase(_ => calls.Add("objects")),
|
||||
new GpuWorldState(),
|
||||
new TestLiveSessionFramePhase(() => calls.Add("network")),
|
||||
new TestPostNetworkCommandFramePhase(() => calls.Add("commands")),
|
||||
new TestLiveSpatialReconcilePhase(() => calls.Add("spatial")));
|
||||
|
||||
frame.Tick(1f / 60f);
|
||||
|
||||
|
|
@ -39,25 +42,96 @@ public sealed class RecallTeleportAnimationTests
|
|||
public void LiveFrame_InvalidHostDeltaCannotBlockNetworkDispatch()
|
||||
{
|
||||
var deltas = new List<float>();
|
||||
int networkDispatches = 0;
|
||||
var calls = new List<string>();
|
||||
var frame = new RetailLiveFrameCoordinator(
|
||||
deltas.Add,
|
||||
() => networkDispatches++,
|
||||
() => { },
|
||||
() => { });
|
||||
new TestLiveObjectFramePhase(delta =>
|
||||
{
|
||||
deltas.Add(delta);
|
||||
calls.Add("objects");
|
||||
}),
|
||||
new GpuWorldState(),
|
||||
new TestLiveSessionFramePhase(() => calls.Add("network")),
|
||||
new TestPostNetworkCommandFramePhase(() => calls.Add("commands")),
|
||||
new TestLiveSpatialReconcilePhase(() => calls.Add("spatial")));
|
||||
|
||||
frame.Tick(float.NaN);
|
||||
frame.Tick(float.PositiveInfinity);
|
||||
frame.Tick(-1f);
|
||||
|
||||
Assert.Equal([0f, 0f, 0f], deltas);
|
||||
Assert.Equal(3, networkDispatches);
|
||||
Assert.Equal(
|
||||
Enumerable.Repeat(new[] { "objects", "network", "commands", "spatial" }, 3)
|
||||
.SelectMany(static frameCalls => frameCalls),
|
||||
calls);
|
||||
Assert.Equal(0.0, UpdateFrameClock.NormalizeDeltaSeconds(double.NaN));
|
||||
Assert.Equal(0.0, UpdateFrameClock.NormalizeDeltaSeconds(double.NegativeInfinity));
|
||||
Assert.Equal(0.0, UpdateFrameClock.NormalizeDeltaSeconds(double.PositiveInfinity));
|
||||
Assert.Equal(0.0, UpdateFrameClock.NormalizeDeltaSeconds(double.MaxValue));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LiveFrame_CommitsTheInboundMutationBatchBeforeCommandsAndReconcile()
|
||||
{
|
||||
const uint landblock = 0x0101FFFFu;
|
||||
var calls = new List<string>();
|
||||
var world = new GpuWorldState();
|
||||
long before = world.VisibilityCommitCount;
|
||||
var frame = new RetailLiveFrameCoordinator(
|
||||
new TestLiveObjectFramePhase(_ => calls.Add("objects")),
|
||||
world,
|
||||
new TestLiveSessionFramePhase(() =>
|
||||
{
|
||||
calls.Add("network");
|
||||
world.PlaceLiveEntityProjection(landblock, Entity(1));
|
||||
Assert.Equal(before, world.VisibilityCommitCount);
|
||||
}),
|
||||
new TestPostNetworkCommandFramePhase(() =>
|
||||
{
|
||||
calls.Add("commands");
|
||||
Assert.Equal(before + 1, world.VisibilityCommitCount);
|
||||
}),
|
||||
new TestLiveSpatialReconcilePhase(() =>
|
||||
{
|
||||
calls.Add("spatial");
|
||||
Assert.Equal(before + 1, world.VisibilityCommitCount);
|
||||
}));
|
||||
|
||||
frame.Tick(1f / 60f);
|
||||
|
||||
Assert.Equal(["objects", "network", "commands", "spatial"], calls);
|
||||
Assert.Equal(before + 1, world.VisibilityCommitCount);
|
||||
Assert.Equal(1, world.PendingLiveEntityCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LiveFrame_SessionFailureDisposesMutationBatchAndSuppressesLaterPhases()
|
||||
{
|
||||
const uint landblock = 0x0101FFFFu;
|
||||
var calls = new List<string>();
|
||||
var world = new GpuWorldState();
|
||||
long before = world.VisibilityCommitCount;
|
||||
var frame = new RetailLiveFrameCoordinator(
|
||||
new TestLiveObjectFramePhase(_ => calls.Add("objects")),
|
||||
world,
|
||||
new TestLiveSessionFramePhase(() =>
|
||||
{
|
||||
calls.Add("network");
|
||||
world.PlaceLiveEntityProjection(landblock, Entity(2));
|
||||
Assert.Equal(before, world.VisibilityCommitCount);
|
||||
throw new InvalidOperationException("inbound failure");
|
||||
}),
|
||||
new TestPostNetworkCommandFramePhase(() => calls.Add("commands")),
|
||||
new TestLiveSpatialReconcilePhase(() => calls.Add("spatial")));
|
||||
|
||||
InvalidOperationException error = Assert.Throws<InvalidOperationException>(
|
||||
() => frame.Tick(1f / 60f));
|
||||
|
||||
Assert.Equal("inbound failure", error.Message);
|
||||
Assert.Equal(["objects", "network"], calls);
|
||||
Assert.Equal(before + 1, world.VisibilityCommitCount);
|
||||
Assert.Equal(1, world.PendingLiveEntityCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InstalledRecall_HiddenEnterWorldPublishesFinishedCyclicPoseWithoutAdvancingTime()
|
||||
{
|
||||
|
|
@ -108,4 +182,14 @@ public sealed class RecallTeleportAnimationTests
|
|||
Quaternion.Normalize(recallTail[index].Orientation),
|
||||
Quaternion.Normalize(finishedPose[index].Orientation))) < 0.999999f);
|
||||
}
|
||||
|
||||
private static WorldEntity Entity(uint id) => new()
|
||||
{
|
||||
Id = id,
|
||||
ServerGuid = 0x70000000u + id,
|
||||
SourceGfxObjOrSetupId = 0x02000001u,
|
||||
Position = Vector3.Zero,
|
||||
Rotation = Quaternion.Identity,
|
||||
MeshRefs = Array.Empty<MeshRef>(),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue