Skip to main content

steel_core/player/movement/
teleport.rs

1//! Teleport state tracking for server-side position confirmation.
2//!
3//! When the server teleports a player, it assigns a teleport ID and waits for the
4//! client to acknowledge it via `SAcceptTeleportation`. Until acknowledged, movement
5//! packets are rejected. This struct manages that handshake.
6//!
7//! Vanilla: `ServerGamePacketListenerImpl.awaitingPositionFromClient`,
8//! `awaitingTeleport`, `awaitingTeleportTime`.
9
10use glam::DVec3;
11
12/// Tracks the state of a pending server-initiated teleport.
13pub struct TeleportState {
14    /// Position we're waiting for the client to confirm.
15    /// `Some` means we should reject movement packets until confirmed.
16    pub awaiting_position: Option<DVec3>,
17    /// Incrementing teleport ID counter (wraps at `i32::MAX`).
18    pub teleport_id: i32,
19    /// Tick count when last teleport was sent (for timeout/resend).
20    pub teleport_time: i32,
21}
22
23impl TeleportState {
24    #[must_use]
25    pub const fn new() -> Self {
26        Self {
27            awaiting_position: None,
28            teleport_id: 0,
29            teleport_time: 0,
30        }
31    }
32
33    /// Returns true if we're waiting for a teleport confirmation.
34    #[must_use]
35    pub const fn is_awaiting(&self) -> bool {
36        self.awaiting_position.is_some()
37    }
38
39    /// Advances the teleport ID, wrapping at `i32::MAX`. Returns the new ID.
40    pub const fn next_id(&mut self) -> i32 {
41        self.teleport_id = if self.teleport_id == i32::MAX {
42            0
43        } else {
44            self.teleport_id + 1
45        };
46        self.teleport_id
47    }
48
49    /// Accepts the teleport if the ID matches.
50    /// Returns the confirmed position, or `None` if the ID doesn't match.
51    pub const fn try_accept(&mut self, id: i32) -> Option<DVec3> {
52        if id == self.teleport_id {
53            self.awaiting_position.take()
54        } else {
55            None
56        }
57    }
58}