Skip to content

fix(unlockmode): Exit Without Saving now reverts a moved fallback anchor - #1233

Merged
EllesmereGaming merged 1 commit into
EllesmereGaming:mainfrom
dfrisone:Fallback-Ancor-Bug
Aug 7, 2026
Merged

fix(unlockmode): Exit Without Saving now reverts a moved fallback anchor#1233
EllesmereGaming merged 1 commit into
EllesmereGaming:mainfrom
dfrisone:Fallback-Ancor-Bug

Conversation

@dfrisone

@dfrisone dfrisone commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Reported by @grouch on 8.7.6: throw a fallback anchor far away to reach something underneath it, then Exit Without Saving, and it stays where it was thrown. This is ours, not an interaction with another addon.

Cause

RevertPositions restored nine anchor fields from the snapshot and then deliberately re-attached the LIVE fallback on top.

That carry-over existed for a good reason: SnapshotPositions never captured fallback, so without it a revert would have destroyed every fallback, including ones set in earlier sessions. The side effect was that a fallback edited during the session also survived the discard, which is exactly the report. The anchor reverts, and then the edited fallback is put back over it.

Fix

Snapshot fallback by copy, restore it from the snapshot by copy, and drop the carry-over it made redundant.

The copy is load-bearing. Fallbacks are positional, and _NudgeSelectedFallbackGhost does

fb.offsetX = (fb.offsetX or 0) + dx
fb.offsetY = (fb.offsetY or 0) + dy

so it mutates the table in place. A snapshot holding a reference would be dragged along by the edit and the revert would be a silent no-op. The restore copies for the same reason in the other direction, so the next session's nudges cannot reach back into the snapshot.

Pre-session fallbacks are still preserved, which is all the carry-over was protecting. Session edits now revert like every other position.

Why dropping the carry-over is safe

Both the old carry-over and the new snapshot iterate pairs(anchorDB), so coverage is identical rather than merely similar. Entries created during the session are dropped by both, since an entry with no snapshot is not recreated at all, which preserves the existing rule that a link reverting away takes its fallback with it. Pre-session fallbacks survive in both.

fallback only ever holds four scalars (target, side, offsetX, offsetY), with no frame references and no nesting, so CopyTable has nothing deep or cyclic to walk.

One deliberate widening

Removing a fallback mid-session now reverts too. Previously that survived Exit Without Saving, because the carry-over simply had nothing to re-attach. It is now discarded like any other session edit, which is what Exit Without Saving is supposed to mean, but it is behaviour beyond the reported case and worth knowing about.

Performance

SnapshotPositions has one caller, at unlock-mode entry. Not per frame, no timers, nothing added to any update loop. The change costs one four-field table copy per anchored element, once, when unlock mode opens. The same function already copies the whole unlockAnchors, unlockWidthMatch, unlockHeightMatch, and phantomBounds tables a few lines later, so this is a rounding error against work already being done, and CopyTable is the established idiom in this file.

Ghost visuals need no extra handling: RevertPositions already ends by hiding the fallback ghosts, and they recompute from fb.offsetX/offsetY whenever they are next shown.

Notes

One file, net 16 insertions and 20 deletions, so it removes more than it adds. No new strings, no options changes, no saved-variable format changes.

Tested in game: a fallback anchor thrown during a session now returns to where it was on Exit Without Saving.

Country Music Australia GIF by Dylan Yeandle

Reported by @grouch on 8.7.6: throw a fallback anchor far away to reach
something underneath it, then Exit Without Saving, and it stays where it was
thrown.

This is ours, not an interaction with another addon.

RevertPositions restored nine anchor fields from the snapshot and then
deliberately re-attached the LIVE fallback on top. That carry-over existed
because the snapshot never captured `fallback`, so without it a revert would
have destroyed every fallback including ones from earlier sessions. It also
meant a fallback edited during the session survived the discard, which is
exactly the report: the anchor reverts, and then the edited fallback is put
back over it.

Fallbacks are positional. _NudgeSelectedFallbackGhost does

    fb.offsetX = (fb.offsetX or 0) + dx
    fb.offsetY = (fb.offsetY or 0) + dy

so it mutates the table IN PLACE. The snapshot therefore has to copy it, not
reference it, or the edit would drag the snapshot along and the revert would
be a no-op.

Snapshot `fallback` by copy, restore it from the snapshot by copy, and drop
the carry-over it made redundant. Pre-session fallbacks are still preserved,
which is what the carry-over was protecting; session edits now revert like
every other position. The existing rule that a link reverting away takes its
fallback with it still holds, because an entry with no snapshot is not
recreated at all.
@EllesmereGaming
EllesmereGaming merged commit a25e767 into EllesmereGaming:main Aug 7, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants