refactor(world): canonicalize live physics host ownership
This commit is contained in:
parent
5882b308c1
commit
fcb66198fc
21 changed files with 1546 additions and 323 deletions
|
|
@ -76,7 +76,9 @@ public sealed class TargetManagerTests
|
|||
int before = self.HandleUpdateTargetCalls.Count;
|
||||
|
||||
var p = new Position(1u, Vector3.Zero, Quaternion.Identity);
|
||||
self.TargetManager.ReceiveUpdate(new TargetInfo(999u, TargetStatus.Ok, p, p));
|
||||
self.TargetManager.ReceiveUpdate(
|
||||
new TargetInfo(999u, TargetStatus.Ok, p, p),
|
||||
target);
|
||||
|
||||
Assert.Equal(before, self.HandleUpdateTargetCalls.Count);
|
||||
}
|
||||
|
|
@ -88,7 +90,9 @@ public sealed class TargetManagerTests
|
|||
self.TargetManager.SetTarget(0, target.Id, 1.0f, 0.0);
|
||||
|
||||
var p = new Position(1u, Vector3.Zero, Quaternion.Identity);
|
||||
self.TargetManager.ReceiveUpdate(new TargetInfo(target.Id, TargetStatus.ExitWorld, p, p));
|
||||
self.TargetManager.ReceiveUpdate(
|
||||
new TargetInfo(target.Id, TargetStatus.ExitWorld, p, p),
|
||||
target);
|
||||
|
||||
Assert.Null(self.TargetManager.TargetInfo); // cleared
|
||||
Assert.False(target.TargetManager.VoyeurTable!.ContainsKey(self.Id)); // unsubscribed
|
||||
|
|
@ -102,7 +106,9 @@ public sealed class TargetManagerTests
|
|||
self.TargetManager.SetTarget(0, target.Id, 1.0f, 0.0);
|
||||
|
||||
var tp = new Position(1u, new Vector3(0f, 5f, 0f), Quaternion.Identity);
|
||||
self.TargetManager.ReceiveUpdate(new TargetInfo(target.Id, TargetStatus.Ok, tp, tp));
|
||||
self.TargetManager.ReceiveUpdate(
|
||||
new TargetInfo(target.Id, TargetStatus.Ok, tp, tp),
|
||||
target);
|
||||
|
||||
// self→target interp position (0,5,0) normalized = +Y.
|
||||
var heading = self.TargetManager.TargetInfo!.Value.InterpolatedHeading;
|
||||
|
|
@ -110,6 +116,46 @@ public sealed class TargetManagerTests
|
|||
Assert.Equal(1f, heading.Y, 3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReceiveUpdate_SameGuidReplacementSender_IsIgnored()
|
||||
{
|
||||
var (self, originalTarget, world) = TwoHosts();
|
||||
self.TargetManager.SetTarget(0, originalTarget.Id, 1.0f, 0.0);
|
||||
self.HandleUpdateTargetCalls.Clear();
|
||||
var replacement = new R5Host(originalTarget.Id, world);
|
||||
var p = new Position(1u, new Vector3(99f, 0f, 0f), Quaternion.Identity);
|
||||
|
||||
self.ReceiveTargetUpdate(
|
||||
new TargetInfo(originalTarget.Id, TargetStatus.ExitWorld, p, p),
|
||||
replacement);
|
||||
|
||||
Assert.Empty(self.HandleUpdateTargetCalls);
|
||||
Assert.NotNull(self.TargetManager.TargetInfo);
|
||||
Assert.Same(
|
||||
originalTarget,
|
||||
self.TargetManager.GetRelationshipTarget(originalTarget.Id));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StickyAdjustOffset_UsesExactTargetInsteadOfSameGuidReplacement()
|
||||
{
|
||||
var (self, originalTarget, world) = TwoHosts();
|
||||
self.SetOrigin(Vector3.Zero);
|
||||
originalTarget.SetOrigin(new Vector3(5f, 0f, 0f));
|
||||
self.PositionManager.StickTo(originalTarget.Id, 0.5f, 1f);
|
||||
var replacement = new R5Host(originalTarget.Id, world);
|
||||
replacement.SetOrigin(new Vector3(10f, 0f, 0f));
|
||||
originalTarget.SetOrigin(new Vector3(-5f, 0f, 0f));
|
||||
var delta = new MotionDeltaFrame();
|
||||
|
||||
self.PositionManager.AdjustOffset(delta, 0.1);
|
||||
|
||||
Assert.True(delta.Origin.X < 0f);
|
||||
Assert.Same(
|
||||
originalTarget,
|
||||
self.TargetManager.GetRelationshipTarget(originalTarget.Id));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HandleTargetting_UndefinedTarget_TimesOutAfter10Seconds()
|
||||
{
|
||||
|
|
@ -133,9 +179,8 @@ public sealed class TargetManagerTests
|
|||
public void HandleTargetting_Throttles_Within500ms()
|
||||
{
|
||||
var (self, target, _) = TwoHosts();
|
||||
var w = new TargettedVoyeurInfo(self.Id, radius: 0.1f, quantum: 0.0);
|
||||
// seed a voyeur directly + advance so a sweep WOULD send if not throttled.
|
||||
target.TargetManager.AddVoyeur(self.Id, 0.1f, 0.0);
|
||||
target.TargetManager.AddVoyeur(self, 0.1f, 0.0);
|
||||
target.SetOrigin(new Vector3(10f, 0f, 0f)); // far past radius
|
||||
|
||||
target.PhysicsTimerTime = 0.3; // < 0.5 throttle
|
||||
|
|
@ -186,12 +231,12 @@ public sealed class TargetManagerTests
|
|||
{
|
||||
var (self, target, _) = TwoHosts();
|
||||
target.SetOrigin(Vector3.Zero);
|
||||
target.TargetManager.AddVoyeur(self.Id, radius: 1.0f, quantum: 0.0);
|
||||
target.TargetManager.AddVoyeur(self, radius: 1.0f, quantum: 0.0);
|
||||
var voyeur = target.TargetManager.VoyeurTable![self.Id];
|
||||
Assert.Equal(Vector3.Zero, voyeur.LastSentPosition.Frame.Origin);
|
||||
|
||||
target.SetOrigin(new Vector3(5f, 0f, 0f));
|
||||
target.TargetManager.AddVoyeur(self.Id, radius: 2.5f, quantum: 0.3); // existing → update only
|
||||
target.TargetManager.AddVoyeur(self, radius: 2.5f, quantum: 0.3); // existing → update only
|
||||
|
||||
Assert.Equal(2.5f, voyeur.Radius);
|
||||
Assert.Equal(0.3, voyeur.Quantum);
|
||||
|
|
@ -202,10 +247,27 @@ public sealed class TargetManagerTests
|
|||
public void RemoveVoyeur_RemovesEntry()
|
||||
{
|
||||
var (self, target, _) = TwoHosts();
|
||||
target.TargetManager.AddVoyeur(self.Id, 1.0f, 0.0);
|
||||
Assert.True(target.TargetManager.RemoveVoyeur(self.Id));
|
||||
target.TargetManager.AddVoyeur(self, 1.0f, 0.0);
|
||||
Assert.True(target.TargetManager.RemoveVoyeur(self.Id, self));
|
||||
Assert.False(target.TargetManager.VoyeurTable!.ContainsKey(self.Id));
|
||||
Assert.False(target.TargetManager.RemoveVoyeur(self.Id)); // already gone
|
||||
Assert.False(target.TargetManager.RemoveVoyeur(self.Id, self)); // already gone
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HiddenWatcher_GuidReuseCannotRedirectOrRemoveExactSubscription()
|
||||
{
|
||||
var (watcher, target, world) = TwoHosts();
|
||||
watcher.TargetManager.SetTarget(0, target.Id, 1.0f, 0.0);
|
||||
watcher.HandleUpdateTargetCalls.Clear();
|
||||
watcher.Resolvable = false;
|
||||
var replacement = new R5Host(watcher.Id, world);
|
||||
|
||||
target.TargetManager.NotifyVoyeurOfEvent(TargetStatus.Teleported);
|
||||
|
||||
Assert.Single(watcher.HandleUpdateTargetCalls);
|
||||
Assert.Empty(replacement.HandleUpdateTargetCalls);
|
||||
Assert.False(target.TargetManager.RemoveVoyeur(watcher.Id, replacement));
|
||||
Assert.True(target.TargetManager.RemoveVoyeur(watcher.Id, watcher));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue