valence_scoreboard/
components.rs
1use std::collections::HashMap;
2
3use bevy_ecs::prelude::*;
4use derive_more::{Deref, DerefMut};
5use valence_server::entity::EntityLayerId;
6use valence_server::protocol::packets::play::scoreboard_display_s2c::ScoreboardPosition;
7use valence_server::protocol::packets::play::scoreboard_objective_update_s2c::ObjectiveRenderType;
8use valence_server::text::IntoText;
9use valence_server::Text;
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash, Component, Deref)]
17pub struct Objective(pub(crate) String);
18
19impl Objective {
20 pub fn new<N: Into<String>>(name: N) -> Self {
21 let name = name.into();
22 debug_assert!(
23 name.len() <= 16,
24 "Objective name {} is too long ({} > 16)",
25 name,
26 name.len()
27 );
28 Self(name)
29 }
30
31 pub fn name(&self) -> &str {
32 &self.0
33 }
34}
35
36#[derive(Debug, Clone, PartialEq, Component, Deref, DerefMut)]
39pub struct ObjectiveDisplay(pub Text);
40
41#[derive(Debug, Clone, Component, Default)]
43pub struct ObjectiveScores(pub(crate) HashMap<String, i32>);
44
45impl ObjectiveScores {
46 pub fn new() -> Self {
47 Default::default()
48 }
49
50 pub fn with_map<M: Into<HashMap<String, i32>>>(map: M) -> Self {
51 Self(map.into())
52 }
53
54 pub fn get(&self, key: &str) -> Option<&i32> {
55 self.0.get(key)
56 }
57
58 pub fn get_mut(&mut self, key: &str) -> Option<&mut i32> {
59 self.0.get_mut(key)
60 }
61
62 pub fn insert<K: Into<String>>(&mut self, key: K, value: i32) -> Option<i32> {
63 self.0.insert(key.into(), value)
64 }
65}
66
67#[derive(Debug, Clone, Default, PartialEq, Component)]
68pub struct OldObjectiveScores(pub(crate) HashMap<String, i32>);
69
70impl OldObjectiveScores {
71 pub fn diff<'a>(&'a self, scores: &'a ObjectiveScores) -> Vec<&'a str> {
72 let mut diff = Vec::new();
73
74 for (key, value) in &self.0 {
75 if scores.0.get(key) != Some(value) {
76 diff.push(key.as_str());
77 }
78 }
79
80 let new_keys = scores
81 .0
82 .keys()
83 .filter(|key| !self.0.contains_key(key.as_str()))
84 .map(|key| key.as_str());
85
86 let removed_keys = self
87 .0
88 .keys()
89 .filter(|key| !scores.0.contains_key(key.as_str()))
90 .map(|key| key.as_str());
91
92 diff.extend(new_keys);
93 diff.extend(removed_keys);
94 diff
95 }
96}
97
98#[derive(Bundle)]
99pub struct ObjectiveBundle {
100 pub name: Objective,
101 pub display: ObjectiveDisplay,
102 pub render_type: ObjectiveRenderType,
103 pub scores: ObjectiveScores,
104 pub old_scores: OldObjectiveScores,
105 pub position: ScoreboardPosition,
106 pub layer: EntityLayerId,
107}
108
109impl Default for ObjectiveBundle {
110 fn default() -> Self {
111 Self {
112 name: Objective::new(""),
113 display: ObjectiveDisplay("".into_text()),
114 render_type: Default::default(),
115 scores: Default::default(),
116 old_scores: Default::default(),
117 position: Default::default(),
118 layer: Default::default(),
119 }
120 }
121}