diff --git a/src/AcDream.App/Physics/LiveEntityMotionRuntimeController.cs b/src/AcDream.App/Physics/LiveEntityMotionRuntimeController.cs
index db8a635b..37d631ab 100644
--- a/src/AcDream.App/Physics/LiveEntityMotionRuntimeController.cs
+++ b/src/AcDream.App/Physics/LiveEntityMotionRuntimeController.cs
@@ -45,6 +45,8 @@ internal sealed class LiveEntityMotionRuntimeController
rm.Sink = new AcDream.Core.Physics.Motion.MotionTableDispatchSink(sequencer);
rm.Motion.DefaultSink = rm.Sink;
}
+ // #270 probe identity — strip with the probes.
+ rm.Motion.DiagnosticGuid = serverGuid;
// #174 (2026-07-05): the RemoveLinkAnimations seam is retail
// CPhysicsObj::RemoveLinkAnimations 0x0050fe20 — a TAILCALL to
// CPartArray::HandleEnterWorld 0x00517d70 →
diff --git a/src/AcDream.App/Physics/LiveEntityNetworkUpdateController.cs b/src/AcDream.App/Physics/LiveEntityNetworkUpdateController.cs
index d71387ea..c7a5ca44 100644
--- a/src/AcDream.App/Physics/LiveEntityNetworkUpdateController.cs
+++ b/src/AcDream.App/Physics/LiveEntityNetworkUpdateController.cs
@@ -190,6 +190,12 @@ internal sealed class LiveEntityNetworkUpdateController
| AcDream.Core.Physics.ObjectInfoState.EdgeSlide
: AcDream.Core.Physics.ObjectInfoState.EdgeSlide,
movingEntityId: entity.Id);
+ if (AcDream.Core.Physics.PhysicsDiagnostics.DumpMotionEnabled)
+ {
+ Console.WriteLine(
+ $"[SPAWN-PLACE] guid={serverGuid:X8} cell=0x{cellId:X8} ok={placement.Ok} "
+ + $"contact={placement.InContact} walkable={placement.OnWalkable}");
+ }
if (!placement.Ok)
return; // unplaceable — stays airborne, like a failed retail placement
@@ -720,15 +726,24 @@ internal sealed class LiveEntityNetworkUpdateController
update.Guid);
remote.Body.Orientation = entity.Rotation;
remote.Body.Position = entity.Position;
- // #270: run the retail spawn placement so the fresh body has
- // real ground contact BEFORE the funnel below dispatches this
- // packet's actions — a first-ever-UM attack swing needs
- // contact_allows_move true to animate.
+ }
+ // #270: run the retail spawn placement so the body has real ground
+ // contact BEFORE the funnel below dispatches this packet's actions —
+ // an attack swing needs contact_allows_move true to animate. Retried
+ // (not creation-only) while the body has never been successfully
+ // placed: creation during the login flood can precede streaming
+ // residency or the entity's cell hydration, and retail's own answer
+ // to "object addressed before its cell exists" is the
+ // CObjectMaint lost-cell list — park it, re-place when the cell is
+ // available. The no-contact-and-no-plane predicate is exactly
+ // "never placed"; one success ends the retries.
+ if (!remote.Body.InContact && !remote.Body.ContactPlaneValid)
+ {
SeedRemoteSpawnPlacement(
remote,
update.Guid,
entity,
- entity.Position,
+ remote.Body.Position,
// Interior live entities carry ParentCellId; outdoor live
// entities carry the outdoor landcell in EffectCellId (see
// WorldEntity's cell-field docs). 0 → helper no-ops.
diff --git a/src/AcDream.Core/Physics/MotionInterpreter.cs b/src/AcDream.Core/Physics/MotionInterpreter.cs
index a176564b..0e6ed006 100644
--- a/src/AcDream.Core/Physics/MotionInterpreter.cs
+++ b/src/AcDream.Core/Physics/MotionInterpreter.cs
@@ -678,6 +678,14 @@ public sealed class MotionInterpreter : IMotionDoneSink
///
public Action? RemoveLinkAnimations { get; set; }
+ ///
+ /// #270 diagnostic identity (2026-07-30): the owning entity's server
+ /// guid, stamped by the binding layer so [UM-ACT]/[MT-FAIL] probe lines
+ /// are attributable (probe-identity-attribution lesson). 0 = unset.
+ /// Strip with the #270 probes.
+ ///
+ public uint DiagnosticGuid { get; set; }
+
///
/// R3-W4 no-op seam standing in for retail
/// CPhysicsObj::InitializeMotionTables, called from
@@ -2779,7 +2787,7 @@ public sealed class MotionInterpreter : IMotionDoneSink
if (PhysicsDiagnostics.DumpMotionEnabled)
{
Console.WriteLine(
- $"[UM-ACT] cmd=0x{a.Command:X8} stamp={incoming} stored={stored} "
+ $"[UM-ACT] guid={DiagnosticGuid:X8} cmd=0x{a.Command:X8} stamp={incoming} stored={stored} "
+ $"newer={newer} auton={a.Autonomous} localSkip={IsLocalPlayer && a.Autonomous}");
}
@@ -3038,8 +3046,10 @@ public sealed class MotionInterpreter : IMotionDoneSink
if (!dispatchOk && PhysicsDiagnostics.DumpMotionEnabled)
{
Console.WriteLine(
- $"[MT-FAIL] motion=0x{motion:X8} speed={p.Speed:F2} "
- + $"style=0x{InterpretedState.CurrentStyle:X8} substate=0x{InterpretedState.ForwardCommand:X8}");
+ $"[MT-FAIL] guid={DiagnosticGuid:X8} motion=0x{motion:X8} speed={p.Speed:F2} "
+ + $"style=0x{InterpretedState.CurrentStyle:X8} substate=0x{InterpretedState.ForwardCommand:X8} "
+ + $"contact={PhysicsObj.TransientState.HasFlag(TransientStateFlags.Contact)} "
+ + $"walkable={PhysicsObj.TransientState.HasFlag(TransientStateFlags.OnWalkable)}");
}
if (!dispatchOk)