Move Position, Vector, State, Movement, and equal-generation CreateObject routing out of GameWindow while preserving per-channel authority, ForcePosition acknowledgement, and motion-runtime ownership. Add adversarial authority and exact-wire coverage so reentrant updates and GUID reuse cannot publish stale state.
96 lines
2.8 KiB
C#
96 lines
2.8 KiB
C#
using AcDream.App.Physics;
|
|
|
|
namespace AcDream.App.Tests.Physics;
|
|
|
|
public sealed class LiveEntityNetworkBranchRoutingTests
|
|
{
|
|
[Fact]
|
|
public void Vector_ProjectileStopsCanonicalAndOrdinaryRoutes()
|
|
{
|
|
var calls = new List<string>();
|
|
|
|
LiveEntityVectorRoute route = LiveEntityVectorRouter.Route(
|
|
() => { calls.Add("projectile"); return true; },
|
|
() => { calls.Add("canonical"); return true; },
|
|
() => calls.Add("ordinary"));
|
|
|
|
Assert.Equal(LiveEntityVectorRoute.Projectile, route);
|
|
Assert.Equal(["projectile"], calls);
|
|
}
|
|
|
|
[Fact]
|
|
public void Vector_CanonicalBodyRunsOnlyAfterProjectileDeclines()
|
|
{
|
|
var calls = new List<string>();
|
|
|
|
LiveEntityVectorRoute route = LiveEntityVectorRouter.Route(
|
|
() => { calls.Add("projectile"); return false; },
|
|
() => { calls.Add("canonical"); return true; },
|
|
() => calls.Add("ordinary"));
|
|
|
|
Assert.Equal(LiveEntityVectorRoute.CanonicalBody, route);
|
|
Assert.Equal(["projectile", "canonical"], calls);
|
|
}
|
|
|
|
[Fact]
|
|
public void Vector_OrdinaryRemoteIsTheLastFallback()
|
|
{
|
|
var calls = new List<string>();
|
|
|
|
LiveEntityVectorRoute route = LiveEntityVectorRouter.Route(
|
|
() => { calls.Add("projectile"); return false; },
|
|
() => { calls.Add("canonical"); return false; },
|
|
() => calls.Add("ordinary"));
|
|
|
|
Assert.Equal(LiveEntityVectorRoute.OrdinaryRemote, route);
|
|
Assert.Equal(["projectile", "canonical", "ordinary"], calls);
|
|
}
|
|
|
|
[Fact]
|
|
public void ForcePosition_BlipsAndAcknowledgesExactlyOnce()
|
|
{
|
|
int currentChecks = 0;
|
|
int blips = 0;
|
|
int acknowledgements = 0;
|
|
|
|
bool completed = LocalForcePositionTransaction.Apply(
|
|
isForcePosition: true,
|
|
() => { currentChecks++; return true; },
|
|
() => blips++,
|
|
() => acknowledgements++);
|
|
|
|
Assert.True(completed);
|
|
Assert.Equal(2, currentChecks);
|
|
Assert.Equal(1, blips);
|
|
Assert.Equal(1, acknowledgements);
|
|
}
|
|
|
|
[Fact]
|
|
public void ForcePosition_AcknowledgementInvalidationStopsTheTail()
|
|
{
|
|
bool current = true;
|
|
int acknowledgements = 0;
|
|
|
|
bool completed = LocalForcePositionTransaction.Apply(
|
|
isForcePosition: true,
|
|
() => current,
|
|
() => { },
|
|
() => { acknowledgements++; current = false; });
|
|
|
|
Assert.False(completed);
|
|
Assert.Equal(1, acknowledgements);
|
|
}
|
|
|
|
[Fact]
|
|
public void OrdinaryPositionDoesNotBlipOrAcknowledge()
|
|
{
|
|
int calls = 0;
|
|
|
|
Assert.True(LocalForcePositionTransaction.Apply(
|
|
isForcePosition: false,
|
|
() => { calls++; return false; },
|
|
() => calls++,
|
|
() => calls++));
|
|
Assert.Equal(0, calls);
|
|
}
|
|
}
|