refactor(world): establish live entity composition seams
This commit is contained in:
parent
db5a11707d
commit
d68c83d1a5
5 changed files with 357 additions and 21 deletions
|
|
@ -1007,8 +1007,9 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
|
|||
private AcDream.App.Net.LiveSessionController? _liveSessionController;
|
||||
private AcDream.Core.Net.WorldSession? LiveSession =>
|
||||
_liveSessionController?.CurrentSession;
|
||||
private int _liveCenterX;
|
||||
private int _liveCenterY;
|
||||
private readonly AcDream.App.World.LiveWorldOriginState _liveWorldOrigin = new();
|
||||
private int _liveCenterX => _liveWorldOrigin.CenterX;
|
||||
private int _liveCenterY => _liveWorldOrigin.CenterY;
|
||||
// #192 (2026-07-09): true once the player's first canonical Position has
|
||||
// been accepted — i.e. _liveCenterX/Y reflects a real, server-confirmed
|
||||
// position, not the Holtburg startup placeholder. Renderability is not a
|
||||
|
|
@ -1019,7 +1020,7 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
|
|||
// AcDream.Core.World.StreamingReadinessGate for the full mechanism this
|
||||
// closes (stale-centered geometry built during the InWorld-but-not-yet-
|
||||
// located window, applied late once its build finished).
|
||||
private bool _liveCenterKnown;
|
||||
private bool _liveCenterKnown => _liveWorldOrigin.IsKnown;
|
||||
|
||||
// K-fix1 (2026-04-26): cached at startup so per-frame branches are
|
||||
// single-flag reads instead of env-var lookups. True iff
|
||||
|
|
@ -2535,6 +2536,8 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
|
|||
_worldState,
|
||||
AdvanceLandblockPresentationRetirement);
|
||||
|
||||
var liveEntityComponentLifecycle =
|
||||
new AcDream.App.World.DeferredLiveEntityRuntimeComponentLifecycle();
|
||||
_liveEntities = new AcDream.App.World.LiveEntityRuntime(
|
||||
_worldState,
|
||||
new AcDream.App.World.CompositeLiveEntityResourceLifecycle(
|
||||
|
|
@ -2544,7 +2547,10 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
|
|||
new(
|
||||
entityScriptActivator.OnCreate,
|
||||
entityScriptActivator.OnRemove)),
|
||||
TearDownLiveEntityRuntimeComponents);
|
||||
liveEntityComponentLifecycle);
|
||||
liveEntityComponentLifecycle.Bind(
|
||||
new AcDream.App.World.DelegateLiveEntityRuntimeComponentLifecycle(
|
||||
TearDownLiveEntityRuntimeComponents));
|
||||
_liveEntities.ProjectionVisibilityChanged += (record, visible) =>
|
||||
{
|
||||
if (record.WorldEntity is { } entity)
|
||||
|
|
@ -2844,8 +2850,7 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
|
|||
// enter the world as the first character on the account, and stream
|
||||
// CreateObject messages into _worldGameState as they arrive. Entirely
|
||||
// gated behind ACDREAM_LIVE=1 so the default run path is unchanged.
|
||||
_liveCenterX = centerX;
|
||||
_liveCenterY = centerY;
|
||||
_liveWorldOrigin.SetPlaceholder(centerX, centerY);
|
||||
_liveSessionController = new AcDream.App.Net.LiveSessionController();
|
||||
AcDream.App.Net.LiveSessionStartResult liveStart =
|
||||
_liveSessionController.Start(
|
||||
|
|
@ -3010,7 +3015,7 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
|
|||
// X/Y are ignored until the next logical player CreateObject claims a
|
||||
// new origin. Keeping the last values avoids inventing a synthetic
|
||||
// landblock while still forcing first-spawn initialization.
|
||||
_liveCenterKnown = false;
|
||||
_liveWorldOrigin.Reset();
|
||||
}
|
||||
|
||||
private void ResetSessionLiveRuntime()
|
||||
|
|
@ -3409,21 +3414,22 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
|
|||
private void TryInitializeLiveCenter(
|
||||
AcDream.Core.Net.WorldSession.EntitySpawn spawn)
|
||||
{
|
||||
if (_liveCenterKnown
|
||||
|| spawn.Guid != _playerServerGuid
|
||||
if (spawn.Guid != _playerServerGuid
|
||||
|| spawn.Position is not { } position)
|
||||
return;
|
||||
|
||||
int lbX = (int)((position.LandblockId >> 24) & 0xFFu);
|
||||
int lbY = (int)((position.LandblockId >> 16) & 0xFFu);
|
||||
_liveCenterKnown = true;
|
||||
if (lbX != _liveCenterX || lbY != _liveCenterY)
|
||||
int oldCenterX = _liveWorldOrigin.CenterX;
|
||||
int oldCenterY = _liveWorldOrigin.CenterY;
|
||||
if (!_liveWorldOrigin.TryInitialize(lbX, lbY))
|
||||
return;
|
||||
|
||||
if (lbX != oldCenterX || lbY != oldCenterY)
|
||||
{
|
||||
Console.WriteLine(
|
||||
$"live: first player position — recentering streaming from ({_liveCenterX},{_liveCenterY}) " +
|
||||
$"live: first player position — recentering streaming from ({oldCenterX},{oldCenterY}) " +
|
||||
$"to ({lbX},{lbY}) @0x{position.LandblockId:X8}");
|
||||
_liveCenterX = lbX;
|
||||
_liveCenterY = lbY;
|
||||
}
|
||||
|
||||
if (_streamingController is not null && _dats is not null)
|
||||
|
|
@ -7337,8 +7343,7 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
|
|||
// can be the abandoned first destination, not the unplaced player's source.
|
||||
_physicsEngine.RemoveLandblock(streamingOriginLandblockId);
|
||||
|
||||
_liveCenterX = lbX;
|
||||
_liveCenterY = lbY;
|
||||
_liveWorldOrigin.Recenter(lbX, lbY);
|
||||
newWorldPos = new System.Numerics.Vector3(
|
||||
p.PositionX, p.PositionY, p.PositionZ);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue