basalt_api/player.rs
1//! Player identity for event dispatch contexts.
2
3use basalt_types::Uuid;
4
5use crate::components::{Position, Rotation};
6
7/// Identity and state of the player who triggered an action.
8///
9/// Constructed by the server when creating a dispatch context.
10/// Plugin handlers access this via `ctx.player()`.
11#[derive(Debug, Clone)]
12pub struct PlayerInfo {
13 /// Player UUID (from Mojang or offline-mode).
14 pub uuid: Uuid,
15 /// Protocol entity ID.
16 pub entity_id: i32,
17 /// Player display name.
18 pub username: String,
19 /// Current facing direction.
20 pub rotation: Rotation,
21 /// Current world position. Read at context-construction time, so
22 /// it reflects the player's location when the event fired —
23 /// stale by the next tick.
24 pub position: Position,
25}
26
27impl PlayerInfo {
28 /// Returns a sentinel [`PlayerInfo`] for system-level dispatches.
29 ///
30 /// Used during plugin loading when the dispatch context exists but
31 /// no player is involved (e.g. recipe registry lifecycle events).
32 /// The `entity_id` is `-1`, the username is `"<system>"`, and all
33 /// position / rotation fields are zero. Plugin handlers receiving
34 /// these dispatches must not rely on `ctx.player()` data — the
35 /// event payload carries everything they need.
36 pub fn stub() -> Self {
37 Self {
38 uuid: Uuid::default(),
39 entity_id: -1,
40 username: String::from("<system>"),
41 rotation: Rotation {
42 yaw: 0.0,
43 pitch: 0.0,
44 },
45 position: Position {
46 x: 0.0,
47 y: 0.0,
48 z: 0.0,
49 },
50 }
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn stub_is_zeroed() {
60 let p = PlayerInfo::stub();
61 assert_eq!(p.uuid, Uuid::default());
62 assert_eq!(p.entity_id, -1);
63 assert_eq!(p.username, "<system>");
64 assert_eq!(p.position.x, 0.0);
65 assert_eq!(p.rotation.yaw, 0.0);
66 }
67}