refactor(runtime): close simulation ownership
Move remote-motion construction, CreateObject vector initialization, final simulation-component retirement, and the combined J5 ownership ledger into Runtime. Delete App compatibility views and moved-state reconstruction while preserving the existing graphical projection and retail update order.
This commit is contained in:
parent
c30a3efeb0
commit
cdee7a4b49
57 changed files with 1013 additions and 410 deletions
|
|
@ -41,7 +41,6 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
private readonly ProjectileController _projectileController;
|
||||
private readonly RemoteTeleportController _remoteTeleportController;
|
||||
private readonly LiveEntityAnimationRuntimeView<LiveEntityAnimationState> _animatedEntities;
|
||||
private readonly LiveEntityRemoteMotionRuntimeView<RemoteMotion> _remoteDeadReckon;
|
||||
private readonly RemoteMovementObservationTracker _remoteMovementObservations;
|
||||
private readonly RemotePhysicsUpdater _remotePhysicsUpdater;
|
||||
private readonly RemoteInboundMotionDispatcher _remoteInboundMotion;
|
||||
|
|
@ -53,7 +52,7 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
private readonly LiveWorldOriginState _origin;
|
||||
private readonly AcDream.App.Streaming.ILocalPlayerTeleportNetworkSink
|
||||
_localPlayerTeleport;
|
||||
private readonly ILocalPlayerControllerSource _playerControllerSource;
|
||||
private readonly IRuntimeLocalPlayerControllerSource _playerControllerSource;
|
||||
private readonly LocalPlayerOutboundController _localPlayerOutbound;
|
||||
private readonly ILocalPlayerPhysicsHostSource _playerHostSource;
|
||||
private readonly ILocalPlayerIdentitySource _playerIdentity;
|
||||
|
|
@ -83,7 +82,6 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
ProjectileController projectileController,
|
||||
RemoteTeleportController remoteTeleportController,
|
||||
LiveEntityAnimationRuntimeView<LiveEntityAnimationState> animatedEntities,
|
||||
LiveEntityRemoteMotionRuntimeView<RemoteMotion> remoteDeadReckon,
|
||||
RemoteMovementObservationTracker remoteMovementObservations,
|
||||
RemotePhysicsUpdater remotePhysicsUpdater,
|
||||
RemoteInboundMotionDispatcher remoteInboundMotion,
|
||||
|
|
@ -94,7 +92,7 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
RuntimeCombatTargetState? combatTargetController,
|
||||
LiveWorldOriginState origin,
|
||||
AcDream.App.Streaming.ILocalPlayerTeleportNetworkSink localPlayerTeleport,
|
||||
ILocalPlayerControllerSource playerControllerSource,
|
||||
IRuntimeLocalPlayerControllerSource playerControllerSource,
|
||||
LocalPlayerOutboundController localPlayerOutbound,
|
||||
ILocalPlayerPhysicsHostSource playerHostSource,
|
||||
ILocalPlayerIdentitySource playerIdentity,
|
||||
|
|
@ -113,7 +111,6 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
_projectileController = projectileController ?? throw new ArgumentNullException(nameof(projectileController));
|
||||
_remoteTeleportController = remoteTeleportController ?? throw new ArgumentNullException(nameof(remoteTeleportController));
|
||||
_animatedEntities = animatedEntities ?? throw new ArgumentNullException(nameof(animatedEntities));
|
||||
_remoteDeadReckon = remoteDeadReckon ?? throw new ArgumentNullException(nameof(remoteDeadReckon));
|
||||
_remoteMovementObservations = remoteMovementObservations ?? throw new ArgumentNullException(nameof(remoteMovementObservations));
|
||||
_remotePhysicsUpdater = remotePhysicsUpdater ?? throw new ArgumentNullException(nameof(remotePhysicsUpdater));
|
||||
_remoteInboundMotion = remoteInboundMotion ?? throw new ArgumentNullException(nameof(remoteInboundMotion));
|
||||
|
|
@ -151,7 +148,10 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
uint localEntityId,
|
||||
Func<bool> isCurrent)
|
||||
{
|
||||
_remoteDeadReckon.TryGetValue(serverGuid, out RemoteMotion? remote);
|
||||
_liveEntities.TryGetRemoteMotionRuntime(
|
||||
serverGuid,
|
||||
out IRuntimeRemoteMotion? remoteRuntime);
|
||||
RemoteMotion? remote = remoteRuntime as RemoteMotion;
|
||||
EntityPhysicsHost? host =
|
||||
_liveEntities.TryGetPhysicsHost(serverGuid, out var registered)
|
||||
? registered as EntityPhysicsHost
|
||||
|
|
@ -570,7 +570,10 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
_remoteMovementObservations[motionKey] =
|
||||
(prev.Pos, refreshedTime);
|
||||
}
|
||||
if (_remoteDeadReckon.TryGetValue(update.Guid, out var dr))
|
||||
if (_liveEntities.TryGetRemoteMotionRuntime(
|
||||
update.Guid,
|
||||
out IRuntimeRemoteMotion? remoteRuntime)
|
||||
&& remoteRuntime is RemoteMotion dr)
|
||||
dr.LastServerPosTime = (refreshedTime - System.DateTime.UnixEpoch).TotalSeconds;
|
||||
}
|
||||
|
||||
|
|
@ -635,12 +638,15 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
if (!IsCurrentOwner())
|
||||
return default;
|
||||
|
||||
if (!_remoteDeadReckon.TryGetValue(update.Guid, out var remote))
|
||||
if (!_liveEntities.TryGetRemoteMotionRuntime(
|
||||
update.Guid,
|
||||
out IRuntimeRemoteMotion? remoteRuntime)
|
||||
|| remoteRuntime is not RemoteMotion remote)
|
||||
{
|
||||
remote = CreateRemoteMotion(update.Guid);
|
||||
remote = _liveEntities.GetOrCreateRemoteMotionRuntime(
|
||||
update.Guid);
|
||||
remote.Body.Orientation = entity.Rotation;
|
||||
remote.Body.Position = entity.Position;
|
||||
_remoteDeadReckon[update.Guid] = remote;
|
||||
}
|
||||
if (!IsCurrentOwner(remote))
|
||||
return default;
|
||||
|
|
@ -719,43 +725,6 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
&& runtime.IsCurrentSpatialRemoteMotion(record, remote);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the optional MovementManager companion for one live object.
|
||||
/// A retained projectile or static-animation owner contributes the
|
||||
/// already-owned CPhysicsObj body; an ordinary remote gets local storage.
|
||||
/// </summary>
|
||||
private RemoteMotion CreateRemoteMotion(uint serverGuid)
|
||||
{
|
||||
LiveEntityRecord? record = null;
|
||||
if (_liveEntities is { } liveEntities
|
||||
&& liveEntities.TryGetRecord(serverGuid, out var currentRecord))
|
||||
{
|
||||
record = currentRecord;
|
||||
}
|
||||
|
||||
RemoteMotion remote;
|
||||
if (record?.PhysicsBody is { } canonicalBody)
|
||||
{
|
||||
// Retail has one CPhysicsObj. A projectile or Physics-Static
|
||||
// animation workset can create it before the MovementManager;
|
||||
// adopt its current frame/vectors without replaying CreateObject.
|
||||
remote = new RemoteMotion(canonicalBody);
|
||||
}
|
||||
else
|
||||
{
|
||||
remote = new RemoteMotion();
|
||||
if (record is not null)
|
||||
AcDream.App.Physics.RemotePhysicsBodyInitializer.Initialize(
|
||||
remote.Body,
|
||||
record);
|
||||
}
|
||||
|
||||
RemoteMotion incarnation = remote;
|
||||
remote.Movement.ActivatePhysicsObject = () =>
|
||||
_liveEntities?.TryActivateOrdinaryObject(serverGuid, incarnation);
|
||||
return remote;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// K-fix9 (2026-04-26): handle 0xF74E VectorUpdate from remote jumps.
|
||||
/// The payload seeds the world-space launch velocity and angular velocity.
|
||||
|
|
@ -822,7 +791,13 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
if (!_liveEntities.ContainsWorldEntity(update.Guid)) return;
|
||||
|
||||
if (update.Guid == _playerServerGuid) return; // local jump uses our own physics
|
||||
if (!_remoteDeadReckon.TryGetValue(update.Guid, out var rm)) return;
|
||||
if (!_liveEntities.TryGetRemoteMotionRuntime(
|
||||
update.Guid,
|
||||
out IRuntimeRemoteMotion? remoteRuntime)
|
||||
|| remoteRuntime is not RemoteMotion rm)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LiveEntityRecord remoteRecord = acceptedVectorRecord;
|
||||
|
||||
// World-space velocity. Apply directly to the body — the per-tick
|
||||
|
|
@ -1249,10 +1224,14 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
// small. When HasVelocity is set, we also seed PhysicsBody
|
||||
// velocity (matches retail's set_velocity call in the same
|
||||
// dispatcher).
|
||||
if (!_remoteDeadReckon.TryGetValue(update.Guid, out var rmState))
|
||||
if (!_liveEntities.TryGetRemoteMotionRuntime(
|
||||
update.Guid,
|
||||
out IRuntimeRemoteMotion? remoteRuntime)
|
||||
|| remoteRuntime is not RemoteMotion rmState)
|
||||
{
|
||||
rmState = CreateRemoteMotion(update.Guid);
|
||||
_remoteDeadReckon[update.Guid] = rmState;
|
||||
rmState =
|
||||
_liveEntities.GetOrCreateRemoteMotionRuntime(
|
||||
update.Guid);
|
||||
// Hard-snap orientation on first spawn so the per-tick
|
||||
// slerp doesn't visibly rotate from Identity to truth.
|
||||
rmState.Body.Orientation = rot;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue