Skip to main content

steel_core/player/
health_sync.rs

1//! Delta-tracking state for `CSetHealth` packet deduplication.
2//!
3//! Tracks the last health/food/saturation values sent to the client so we only
4//! send `CSetHealth` when something actually changes.
5
6use crate::player::Player;
7
8/// Tracks the last health/food/saturation values sent to the client.
9pub struct HealthSyncState {
10    /// Last health value sent to the client.
11    pub last_health: f32,
12    /// Last food level sent to the client.
13    pub last_food: i32,
14    /// Whether saturation was zero last time we sent health.
15    pub saturation_zero: bool,
16}
17
18impl HealthSyncState {
19    /// Creates a new state that will trigger a send on the first tick.
20    #[must_use]
21    pub const fn new() -> Self {
22        Self {
23            last_health: -1.0,
24            last_food: -1,
25            saturation_zero: true,
26        }
27    }
28
29    /// Returns true if the given values differ from what was last sent.
30    #[expect(
31        clippy::float_cmp,
32        reason = "intentional exact comparison: we only want to send updates when the value changes from what we last sent"
33    )]
34    #[must_use]
35    pub fn needs_update(&self, health: f32, food: i32, saturation_zero: bool) -> bool {
36        self.last_health != health
37            || self.last_food != food
38            || self.saturation_zero != saturation_zero
39    }
40
41    /// Records that we just sent the given values to the client.
42    pub const fn record_sent(&mut self, health: f32, food: i32, saturation_zero: bool) {
43        self.last_health = health;
44        self.last_food = food;
45        self.saturation_zero = saturation_zero;
46    }
47
48    /// Invalidates the state so the next tick will re-send.
49    pub const fn invalidate(&mut self) {
50        self.last_health = -1.0e8;
51    }
52}
53
54impl Player {
55    /// Invalidates the delta-tracking state so that the next `tick()` will send
56    /// `CSetHealth` to the client (vanilla: `resetSentInfo`).
57    pub fn reset_sent_info(&self) {
58        self.health_sync.lock().invalidate();
59    }
60}