fix(vfx): bind effects after canonical placement

C3c created graphical effect, projectile, and static-animation sidecars before Runtime finished the entity's first SetPosition. One-shot F754/F755 packets could be discarded, projectiles could adopt a cell-less body, and animated statics could compete for body ownership. Keep effects behind an exact-incarnation presentation barrier, retry projectile/static binding on the committed visibility edge, and keep effect cells synchronized with canonical rebuckets. User verified spell, recall, arrow, projectile, portal, and static presentation; 90 focused App tests and the Release build pass.
This commit is contained in:
Erik 2026-08-03 12:10:21 +02:00
parent 1fc529cdcb
commit f24532adf3
11 changed files with 417 additions and 50 deletions

View file

@ -837,12 +837,24 @@ internal sealed class DatLiveEntityProjectionMaterializer
expectedCreateIntegrationVersion)
|| !ReferenceEquals(expectedRecord.WorldEntity, entity))
return false;
_projectiles.TryBind(
expectedRecord,
setup,
_gameTime.CurrentScriptTime,
_origin.CenterX,
_origin.CenterY);
bool initialResidenceActive =
_runtime.HasActiveInitialCreateResidence(expectedCanonical);
// C3c first entry owns CPhysicsObj construction and SetPosition for a
// residence-managed Create. Eager projectile classification used to
// acquire that same body here, before the conductor ran; the
// conductor then correctly rejected the unexpected owner and the
// missile remained permanently cell-less. The committed projection
// visibility edge retries TryBind after Runtime has constructed and
// placed the one canonical body.
if (!initialResidenceActive)
{
_projectiles.TryBind(
expectedRecord,
setup,
_gameTime.CurrentScriptTime,
_origin.CenterX,
_origin.CenterY);
}
if (!_runtime.IsCurrentCreateIntegration(
expectedRecord,
@ -1033,6 +1045,15 @@ internal sealed class DatLiveEntityProjectionMaterializer
return;
}
if (_runtime.HasActiveInitialCreateResidence(expectedRecord.Canonical))
{
// RuntimeRemoteFirstEntryState owns CPhysicsObj construction and
// SetPosition until the Create residence completes. The static
// scheduler retains this pending animation owner and binds the
// canonical body after projection becomes spatially visible.
return;
}
PhysicsBody body = _runtime.GetOrCreatePhysicsBody(
spawn.Guid,
incarnation =>