Commit graph

2 commits

Author SHA1 Message Date
Erik
daef7c9835 fix(inventory): reset a split result's movement timestamps so recovery cannot throw (#314)
Found by C4 route 6's integration tests (1b484937) and split out of that
zero-production closure per the standing split-on-discovery rule.

PendingSplitToWorldProjection.BuildSpawn zeroes the top-level
MovementSequence/ServerControlSequence, but its Physics.Timestamps `with`
block overrode only Position/Teleport/ForcePosition/Instance — leaving
Timestamps.Movement and .ServerControlledMove at the SOURCE item's values.
RuntimeEntityObjectLifetime.HasConsistentCreateIdentityAndParent requires the
PhysicsDesc timestamps and their flattened projections to agree, so the
synthetic spawn failed the predicate and TryRecoverUnknownPosition threw
`CreateObject 0x… has inconsistent instance or parent projections` instead of
completing the canonical create-placement transaction.

Reachable in ordinary play: retail's per-object update_times channels are
monotonic and do not reset when an item re-enters a container, so any item
that ever had world presence — dropped once, picked back up, then split —
carries nonzero values in exactly those two fields. The split pile then never
appears.

Fix is the honest value, not a placation of the predicate: a fresh split GUID
has no movement history by construction, so both channels are zero in both
projections. Deliberately NOT fixed by loosening
HasConsistentCreateIdentityAndParent — the predicate was right and the
producer was wrong.

The route-6 test that documented the throw
(SplitSourceWithRetainedMovementTimestamps_ThrowsInsteadOfRecovering) is
renamed to …_StillRecovers and now pins the fix. It asserts more than "no
throw": the result's movement channels must be ZERO in both projections, so
the test cannot pass against a lenient-predicate workaround. Sabotage-verified
in both directions — restoring the old BuildSpawn reproduces the exact
original InvalidOperationException.

Notable for the campaign record: this is a crash in the precise mechanism
route 6's scoping cited as EVIDENCE that drops already converge on the
canonical transaction. Reading the code said the path converges; driving it
said it throws. The zero-production route was still correct — and building its
tests anyway is what found this.

Complete Release suite 11,020 passed / 4 skipped / 0 failed, unchanged from
1b484937 (the test flipped its assertion rather than being added). Neither
known flake fired.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 16:48:41 +02:00
Erik
921712f412 fix(interaction): restore retail loot placement and world-drop projection 2026-07-27 00:03:15 +02:00