fix(portal): synchronize destination presentation state
This commit is contained in:
parent
4b1bceefbb
commit
e95f55f25b
42 changed files with 2815 additions and 288 deletions
|
|
@ -1,3 +1,4 @@
|
|||
using System.Numerics;
|
||||
using AcDream.App.Rendering;
|
||||
using AcDream.App.World;
|
||||
using AcDream.Content.Vfx;
|
||||
|
|
@ -57,7 +58,7 @@ public sealed class RecallTeleportAnimationTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void InstalledRecall_RetiresBeforeTeleportHiddenStateIsDispatched()
|
||||
public void InstalledRecall_HiddenEnterWorldPublishesFinishedCyclicPoseWithoutAdvancingTime()
|
||||
{
|
||||
string datDir = @"C:\Turbine\Asheron's Call";
|
||||
if (!File.Exists(Path.Combine(datDir, "client_portal.dat")))
|
||||
|
|
@ -81,38 +82,29 @@ public sealed class RecallTeleportAnimationTests
|
|||
aceDuration += (high - anim.LowFrame) / Math.Abs(anim.Framerate);
|
||||
}
|
||||
|
||||
const float updateStep = 1f / 60f;
|
||||
double elapsed = 0.0;
|
||||
bool hidden = false;
|
||||
bool hiddenPacketReady = false;
|
||||
var frame = new RetailLiveFrameCoordinator(
|
||||
dt =>
|
||||
{
|
||||
if (!hidden)
|
||||
sequencer.Advance(dt);
|
||||
},
|
||||
() =>
|
||||
{
|
||||
if (hiddenPacketReady)
|
||||
hidden = true;
|
||||
},
|
||||
() => { },
|
||||
() => { });
|
||||
|
||||
// The recall motion is dispatched after an object's UseTime phase.
|
||||
// On the first later frame whose timestamp reaches ACE's scheduled
|
||||
// teleport boundary, retail advances the PartArray and only then
|
||||
// consumes the Hidden SetState from the inbound queue.
|
||||
while (elapsed < aceDuration)
|
||||
{
|
||||
hiddenPacketReady = elapsed + updateStep >= aceDuration;
|
||||
frame.Tick(updateStep);
|
||||
elapsed += updateStep;
|
||||
}
|
||||
|
||||
Assert.True(hidden);
|
||||
Assert.True(
|
||||
// Advance returns a reusable scratch buffer; snapshot the authored tail
|
||||
// before HandleEnterWorld/SampleCurrentPose overwrites that buffer.
|
||||
PartTransform[] recallTail = sequencer.Advance((float)aceDuration).ToArray();
|
||||
Assert.False(
|
||||
sequencer.CurrentNodeDiag.IsLooping,
|
||||
"Recall must reach the Ready cyclic tail before Hidden freezes PartArray playback.");
|
||||
"At ACE's exact teleport boundary the authored recall link is still the current node.");
|
||||
|
||||
// set_hidden -> CPartArray::HandleEnterWorld ->
|
||||
// MotionTableManager::HandleEnterWorld removes link animations and
|
||||
// selects the first cyclic (Ready) node. Hidden then suppresses time
|
||||
// advance, but set_frame/UpdateParts still samples this new pose.
|
||||
sequencer.Manager.HandleEnterWorld();
|
||||
IReadOnlyList<PartTransform> finishedPose = sequencer.SampleCurrentPose();
|
||||
|
||||
Assert.True(sequencer.CurrentNodeDiag.IsLooping);
|
||||
Assert.Equal(recallTail.Length, finishedPose.Count);
|
||||
Assert.Contains(
|
||||
Enumerable.Range(0, finishedPose.Count),
|
||||
index => Vector3.DistanceSquared(
|
||||
recallTail[index].Origin,
|
||||
finishedPose[index].Origin) > 1e-6f
|
||||
|| MathF.Abs(Quaternion.Dot(
|
||||
Quaternion.Normalize(recallTail[index].Orientation),
|
||||
Quaternion.Normalize(finishedPose[index].Orientation))) < 0.999999f);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue