naia_shared/connection/
priority_state.rs1use std::{collections::HashMap, hash::Hash};
2
3use crate::connection::entity_priority::{EntityPriorityData, EntityPriorityMut, EntityPriorityRef};
4use crate::world::entity::global_entity::GlobalEntity;
5
6pub trait OutgoingPriorityHook {
15 fn advance(&mut self, entity: &GlobalEntity) -> f32;
20
21 fn reset_after_send(&mut self, entity: &GlobalEntity, current_tick: u32);
24}
25
26pub struct GlobalPriorityState<E: Copy + Eq + Hash> {
32 entries: HashMap<E, EntityPriorityData>,
33}
34
35impl<E: Copy + Eq + Hash> GlobalPriorityState<E> {
36 pub fn new() -> Self {
38 Self {
39 entries: HashMap::new(),
40 }
41 }
42
43 pub fn get_ref(&self, entity: E) -> EntityPriorityRef<'_, E> {
45 EntityPriorityRef {
46 state: self.entries.get(&entity),
47 entity,
48 }
49 }
50
51 pub fn get_mut(&mut self, entity: E) -> EntityPriorityMut<'_, E> {
53 EntityPriorityMut {
54 entries: &mut self.entries,
55 entity,
56 }
57 }
58
59 pub fn on_despawn(&mut self, entity: &E) {
61 self.entries.remove(entity);
62 }
63
64 pub fn gain_override(&self, entity: &E) -> Option<f32> {
67 self.entries.get(entity).and_then(|d| d.gain_override)
68 }
69}
70
71impl<E: Copy + Eq + Hash> Default for GlobalPriorityState<E> {
72 fn default() -> Self {
73 Self::new()
74 }
75}
76
77pub struct UserPriorityState<E: Copy + Eq + Hash> {
81 entries: HashMap<E, EntityPriorityData>,
82}
83
84impl<E: Copy + Eq + Hash> UserPriorityState<E> {
85 pub fn new() -> Self {
87 Self {
88 entries: HashMap::new(),
89 }
90 }
91
92 pub fn get_ref(&self, entity: E) -> EntityPriorityRef<'_, E> {
94 EntityPriorityRef {
95 state: self.entries.get(&entity),
96 entity,
97 }
98 }
99
100 pub fn get_mut(&mut self, entity: E) -> EntityPriorityMut<'_, E> {
102 EntityPriorityMut {
103 entries: &mut self.entries,
104 entity,
105 }
106 }
107
108 pub fn on_scope_exit(&mut self, entity: &E) {
110 self.entries.remove(entity);
111 }
112
113 pub fn gain_override(&self, entity: &E) -> Option<f32> {
115 self.entries.get(entity).and_then(|d| d.gain_override)
116 }
117
118 pub fn advance(&mut self, entity: E, gain: f32) -> f32 {
125 let entry = self.entries.entry(entity).or_default();
126 entry.accumulated += gain;
127 entry.accumulated
128 }
129
130 pub fn accumulated(&self, entity: &E) -> f32 {
132 self.entries.get(entity).map(|d| d.accumulated).unwrap_or(0.0)
133 }
134
135 pub fn reset_after_send(&mut self, entity: &E, current_tick: u32) {
139 if let Some(data) = self.entries.get_mut(entity) {
140 data.accumulated = 0.0;
141 data.last_sent_tick = Some(current_tick);
142 }
143 }
144}
145
146impl<E: Copy + Eq + Hash> Default for UserPriorityState<E> {
147 fn default() -> Self {
148 Self::new()
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155
156 #[test]
157 fn global_on_despawn_evicts_entry() {
158 let mut s = GlobalPriorityState::<u32>::new();
159 s.get_mut(7).set_gain(5.0);
160 assert_eq!(s.get_ref(7).gain(), Some(5.0));
161 s.on_despawn(&7);
162 assert_eq!(s.get_ref(7).gain(), None);
163 }
164
165 #[test]
166 fn user_on_scope_exit_evicts_entry() {
167 let mut s = UserPriorityState::<u32>::new();
168 s.get_mut(7).boost_once(3.0);
169 assert_eq!(s.get_ref(7).accumulated(), 3.0);
170 s.on_scope_exit(&7);
171 assert_eq!(s.get_ref(7).accumulated(), 0.0);
172 }
173
174 #[test]
175 fn global_eviction_preserves_other_entries() {
176 let mut s = GlobalPriorityState::<u32>::new();
177 s.get_mut(7).set_gain(5.0);
178 s.get_mut(9).set_gain(2.0);
179 s.on_despawn(&7);
180 assert_eq!(s.get_ref(7).gain(), None);
181 assert_eq!(s.get_ref(9).gain(), Some(2.0));
182 }
183}