fix(headless): complete connected movement gate

This commit is contained in:
Erik 2026-07-27 10:26:44 +02:00
parent fd9559a063
commit 3f3401257c
11 changed files with 756 additions and 48 deletions

View file

@ -3,6 +3,7 @@ using AcDream.Core.Net;
using AcDream.Core.Net.Messages;
using AcDream.Core.Physics;
using AcDream.Runtime.Entities;
using AcDream.Runtime.Gameplay;
using AcDream.Runtime.World;
namespace AcDream.Runtime.Session;
@ -15,7 +16,8 @@ public interface IRuntimeDirectWorldProjection
void ProjectPosition(
RuntimeEntityRecord record,
bool isLocalPlayer);
bool isLocalPlayer,
PositionTimestampDisposition disposition);
void BeginTeleport();
@ -36,6 +38,8 @@ public sealed class RuntimeLiveEntitySessionController
private readonly WorldSession _session;
private readonly Action<string> _log;
private readonly IRuntimeDirectWorldProjection? _worldProjection;
private readonly LocalPlayerOutboundController _localPlayerOutbound =
new((_, _, _, _, _, _) => { });
public RuntimeLiveEntitySessionController(
GameRuntime runtime,
@ -135,11 +139,13 @@ public sealed class RuntimeLiveEntitySessionController
{
bool isLocal =
update.Guid == _runtime.PlayerIdentity.ServerGuid;
PlayerMovementController? localController =
isLocal ? _runtime.MovementOwner.Controller : null;
bool known = Entities.TryApplyPosition(
update,
isLocal,
forcePositionRotation: null,
currentLocalVelocity: null,
forcePositionRotation: localController?.BodyOrientation,
currentLocalVelocity: localController?.BodyVelocity,
projectionRequiresTeleportHook: false,
acknowledgeProjection: null,
out PositionTimestampDisposition disposition,
@ -152,34 +158,44 @@ public sealed class RuntimeLiveEntitySessionController
return;
}
var position = update.Position;
var destination = new RuntimeTeleportDestination(
update.Guid,
update.InstanceSequence,
update.PositionSequence,
update.TeleportSequence,
update.ForcePositionSequence,
new Position(
position.LandblockId,
new Vector3(
position.PositionX,
position.PositionY,
position.PositionZ),
new Quaternion(
position.RotationX,
position.RotationY,
position.RotationZ,
position.RotationW)));
_runtime.TransitOwner.OfferTeleportDestination(
destination,
timestamps.TeleportAdvanced);
if (disposition is PositionTimestampDisposition.Apply)
{
var position = update.Position;
var destination = new RuntimeTeleportDestination(
update.Guid,
update.InstanceSequence,
update.PositionSequence,
update.TeleportSequence,
update.ForcePositionSequence,
new Position(
position.LandblockId,
new Vector3(
position.PositionX,
position.PositionY,
position.PositionZ),
new Quaternion(
position.RotationX,
position.RotationY,
position.RotationZ,
position.RotationW)));
_runtime.TransitOwner.OfferTeleportDestination(
destination,
timestamps.TeleportAdvanced);
}
if (Entities.Entities.TryGetActive(
update.Guid,
out RuntimeEntityRecord record))
{
_worldProjection?.ProjectPosition(
record,
isLocalPlayer: true);
isLocalPlayer: true,
disposition);
}
if (disposition is PositionTimestampDisposition.ForcePosition)
{
_localPlayerOutbound.SendImmediatePosition(
_session,
_runtime.MovementOwner.Controller);
}
TryCompletePortal();
}