A teleport in flight: logging out loses the arrival, and any future cancel freezes the caster #148

Closed
opened 2026-08-06 19:02:07 +00:00 by sickday · 1 comment
Owner

A teleport is three ticks long: the runes are spent at the click, Player.delay/2 locks the caster, and a strong queue entry moves them at tick 3. Interrupting that window is one of the first things a player will try, so it was measured rather than reasoned about.

Two of the three cases are already right and now have regression tests in World.TeleportWorldTest. The third is a divergence, and there is a latent trap behind all of them.

Measured, live, through the real tick

during the flight result verdict
click to walk still arrives at the destination correct — you cannot walk out of a teleport
die respawns normally, arrival does not fire afterwards correct — death wins
log out runes spent, arrival lost, wakes at the origin wrong

The death case needed care to measure at all. Cast from the Lumbridge spawn tile and "respawned" is indistinguishable from "never left", because they are the same coordinate — the first attempt fooled itself exactly that way. The test now casts from {0, 3000, 3300} so origin, destination and respawn tile are three different places.

The divergence: logging out mid-flight pays for nothing

The arrival is a queue entry on the session, so ending the session discards it. The player has spent the runes and has not moved.

In the real game the movement is server-side and completes regardless — a player who logs out mid-teleport is at the destination when they log back in. Ours leaves them where they started, out of pocket.

It harms the player rather than the economy, so it is not urgent, but it is the kind of thing that reads as a lost-item bug report. The fix is either to apply the destination at logout if a teleport entry is pending, or to persist the pending entry and run it on login.

The latent trap: an interrupted teleport freezes the caster

Sequence 714 is [6, 6, 6, 6, 20, 4, 4, 4, 4, 4, 4, 20000]. The animation is the first eleven frames — 68 cycles, about 2.27 ticks — and the last frame is a 20,000-cycle hold that parks the caster in the final pose. That is how a vanish is drawn, and it is fine today because the arrival plays 715 (the same frame archive, 207, run in reverse) and replaces it.

Nothing else clears it. Any future path that cancels a teleport mid-flight without animating the player leaves them frozen in the vanish pose until they next animate — which will read as a rendering bug and will be looked for in the client.

Concretely, anything added later that could interrupt one has to clear the animation:

  • a cancel on movement, if that is ever wanted (it should not be — see the table above);
  • teleblock, which is era content and is exactly a "refuse a teleport already in flight" mechanic;
  • any generic "clear the queue" path added for another reason.

World.Content.Teleport's moduledoc records this at the site, but it wants an issue because whoever adds a cancel will be working somewhere else entirely.

Not a bug, recorded so it is not re-litigated

Spending the runes at the click and moving at tick 3 is deliberate, and matches the rune altar's ordering. A player who logs out mid-flight has paid — that is the reading that cannot be farmed by disconnecting, and it is why the logout case above is a movement bug rather than a refund question.

A teleport is three ticks long: the runes are spent at the click, `Player.delay/2` locks the caster, and a strong queue entry moves them at tick 3. Interrupting that window is one of the first things a player will try, so it was measured rather than reasoned about. Two of the three cases are already right and now have regression tests in `World.TeleportWorldTest`. The third is a divergence, and there is a latent trap behind all of them. ## Measured, live, through the real tick | during the flight | result | verdict | |---|---|---| | click to walk | still arrives at the destination | correct — you cannot walk out of a teleport | | die | respawns normally, arrival does **not** fire afterwards | correct — death wins | | log out | runes spent, arrival lost, wakes at the origin | **wrong** | The death case needed care to measure at all. Cast from the Lumbridge spawn tile and "respawned" is indistinguishable from "never left", because they are the same coordinate — the first attempt fooled itself exactly that way. The test now casts from `{0, 3000, 3300}` so origin, destination and respawn tile are three different places. ## The divergence: logging out mid-flight pays for nothing The arrival is a queue entry on the session, so ending the session discards it. The player has spent the runes and has not moved. In the real game the movement is server-side and completes regardless — a player who logs out mid-teleport is at the destination when they log back in. Ours leaves them where they started, out of pocket. It harms the player rather than the economy, so it is not urgent, but it is the kind of thing that reads as a lost-item bug report. The fix is either to apply the destination at logout if a teleport entry is pending, or to persist the pending entry and run it on login. ## The latent trap: an interrupted teleport freezes the caster Sequence `714` is `[6, 6, 6, 6, 20, 4, 4, 4, 4, 4, 4, 20000]`. The animation is the first eleven frames — 68 cycles, about 2.27 ticks — and the last frame is a **20,000-cycle hold** that parks the caster in the final pose. That is how a vanish is drawn, and it is fine today because the arrival plays `715` (the same frame archive, `207`, run in reverse) and replaces it. **Nothing else clears it.** Any future path that cancels a teleport mid-flight without animating the player leaves them frozen in the vanish pose until they next animate — which will read as a rendering bug and will be looked for in the client. Concretely, anything added later that could interrupt one has to clear the animation: * a cancel on movement, if that is ever wanted (it should not be — see the table above); * teleblock, which is era content and is exactly a "refuse a teleport already in flight" mechanic; * any generic "clear the queue" path added for another reason. `World.Content.Teleport`'s moduledoc records this at the site, but it wants an issue because whoever adds a cancel will be working somewhere else entirely. ## Not a bug, recorded so it is not re-litigated Spending the runes at the click and moving at tick 3 is deliberate, and matches the rune altar's ordering. A player who logs out mid-flight has paid — that is the reading that cannot be farmed by disconnecting, and it is why the logout case above is a *movement* bug rather than a refund question.
Author
Owner
Moved to https://forge.home.arpa/Revenant/Server/issues/48
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Revenant/Server#148
No description provided.