feat(headless): hydrate isolated collision worlds
This commit is contained in:
parent
9569dadb57
commit
b6547ff38c
20 changed files with 1960 additions and 101 deletions
|
|
@ -8,6 +8,7 @@ using AcDream.Core.Spells;
|
|||
using AcDream.Runtime.Entities;
|
||||
using AcDream.Runtime.Gameplay;
|
||||
using AcDream.Runtime.Session;
|
||||
using AcDream.Runtime.World;
|
||||
|
||||
namespace AcDream.Runtime.Tests.Session;
|
||||
|
||||
|
|
@ -102,6 +103,54 @@ public sealed class RuntimeLiveEntitySessionControllerTests
|
|||
Assert.Equal(0x01020001u, runtime.Portal.Snapshot.DestinationCell);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DirectSinkProjectsAcceptedLocalWorldStateThroughOneHostSeam()
|
||||
{
|
||||
using GameRuntime runtime = CreateRuntime();
|
||||
const uint playerGuid = 0x50000002u;
|
||||
runtime.PlayerIdentity.ServerGuid = playerGuid;
|
||||
using var session = new WorldSession(
|
||||
new IPEndPoint(IPAddress.Loopback, 9000),
|
||||
new FixtureTransport());
|
||||
session.GameActionCapture = _ => { };
|
||||
var projection = new FixtureWorldProjection();
|
||||
var controller = new RuntimeLiveEntitySessionController(
|
||||
runtime,
|
||||
session,
|
||||
worldProjection: projection);
|
||||
LiveEntitySessionSink sink = controller.CreateSink();
|
||||
WorldSession.EntitySpawn spawn =
|
||||
Spawn(playerGuid, incarnation: 1);
|
||||
|
||||
sink.Spawned(spawn);
|
||||
sink.TeleportStarted(1u);
|
||||
sink.PositionUpdated(new WorldSession.EntityPositionUpdate(
|
||||
playerGuid,
|
||||
spawn.Position!.Value with
|
||||
{
|
||||
LandblockId = 0x01020001u,
|
||||
PositionX = 30f,
|
||||
},
|
||||
Velocity: null,
|
||||
PlacementId: null,
|
||||
IsGrounded: true,
|
||||
InstanceSequence: 1,
|
||||
PositionSequence: 2,
|
||||
TeleportSequence: 1,
|
||||
ForcePositionSequence: 0));
|
||||
|
||||
Assert.Equal(1, projection.SpawnCount);
|
||||
Assert.Equal(1, projection.PositionCount);
|
||||
Assert.Equal(1, projection.TeleportStartCount);
|
||||
Assert.Equal(1, projection.PrepareCount);
|
||||
Assert.True(projection.LastSpawnWasLocal);
|
||||
Assert.True(projection.LastPositionWasLocal);
|
||||
Assert.Equal(playerGuid, projection.LastRecord?.ServerGuid);
|
||||
Assert.Equal(0x01020001u, projection.LastDestination.CellId);
|
||||
Assert.True(runtime.TransitOwner.CaptureOwnership().IsSessionIdle);
|
||||
Assert.True(runtime.Portal.Snapshot.Completed);
|
||||
}
|
||||
|
||||
private static GameRuntime CreateRuntime()
|
||||
{
|
||||
var operations = new FixtureGameplayOperations();
|
||||
|
|
@ -211,6 +260,57 @@ public sealed class RuntimeLiveEntitySessionControllerTests
|
|||
}
|
||||
}
|
||||
|
||||
private sealed class FixtureWorldProjection
|
||||
: IRuntimeDirectWorldProjection
|
||||
{
|
||||
public int SpawnCount { get; private set; }
|
||||
public int PositionCount { get; private set; }
|
||||
public int TeleportStartCount { get; private set; }
|
||||
public int PrepareCount { get; private set; }
|
||||
public bool LastSpawnWasLocal { get; private set; }
|
||||
public bool LastPositionWasLocal { get; private set; }
|
||||
public RuntimeEntityRecord? LastRecord { get; private set; }
|
||||
public RuntimeTeleportDestination LastDestination { get; private set; }
|
||||
|
||||
public void ProjectSpawn(
|
||||
RuntimeEntityRecord record,
|
||||
bool isLocalPlayer)
|
||||
{
|
||||
SpawnCount++;
|
||||
LastRecord = record;
|
||||
LastSpawnWasLocal = isLocalPlayer;
|
||||
}
|
||||
|
||||
public void ProjectPosition(
|
||||
RuntimeEntityRecord record,
|
||||
bool isLocalPlayer)
|
||||
{
|
||||
PositionCount++;
|
||||
LastRecord = record;
|
||||
LastPositionWasLocal = isLocalPlayer;
|
||||
}
|
||||
|
||||
public void BeginTeleport() => TeleportStartCount++;
|
||||
|
||||
public RuntimeDestinationReadiness PrepareDestination(
|
||||
long revealGeneration,
|
||||
RuntimeTeleportDestination destination)
|
||||
{
|
||||
PrepareCount++;
|
||||
LastDestination = destination;
|
||||
bool indoor = (destination.CellId & 0xFFFFu) >= 0x0100u;
|
||||
return new RuntimeDestinationReadiness(
|
||||
revealGeneration,
|
||||
destination.CellId,
|
||||
indoor,
|
||||
IsUnhydratable: false,
|
||||
RequiredRenderRadius: indoor ? 0 : 1,
|
||||
IsRenderNeighborhoodReady: true,
|
||||
AreCompositeTexturesReady: true,
|
||||
IsCollisionReady: true);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class FixtureGameplayOperations
|
||||
: IRuntimeCombatAttackOperations,
|
||||
IRuntimeCombatTargetOperations,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue