classicube_helpers\entities/
mod.rs

1mod entity;
2use std::{
3    cell::RefCell,
4    collections::HashMap,
5    rc::{Rc, Weak},
6};
7
8use classicube_sys::{Entities, ENTITIES_MAX_COUNT};
9use tracing::warn;
10
11pub use self::entity::{Entity, ENTITY_SELF_ID};
12use crate::{
13    callback_handler::CallbackHandler,
14    events::entity::{AddedEvent, AddedEventHandler, RemovedEvent, RemovedEventHandler},
15};
16
17/// safe access to entities list and entity events
18pub struct Entities {
19    entities: Rc<RefCell<HashMap<u8, Rc<Entity>>>>,
20
21    #[allow(clippy::type_complexity)]
22    added_callbacks: Rc<RefCell<CallbackHandler<(u8, Weak<Entity>)>>>,
23    #[allow(dead_code)]
24    added_handler: AddedEventHandler,
25
26    removed_callbacks: Rc<RefCell<CallbackHandler<u8>>>,
27    #[allow(dead_code)]
28    removed_handler: RemovedEventHandler,
29}
30
31impl Entities {
32    /// register event listeners, listeners will unregister on drop
33    #[must_use]
34    pub fn new() -> Self {
35        let mut entities = HashMap::with_capacity(256);
36
37        // add self entity which always exists
38        unsafe {
39            entities.insert(
40                ENTITY_SELF_ID,
41                Rc::new(Entity::from_id(ENTITY_SELF_ID).expect("Entity::from_id(ENTITY_SELF_ID)")),
42            );
43        }
44
45        let entities = Rc::new(RefCell::new(entities));
46
47        let added_callbacks = Rc::new(RefCell::new(CallbackHandler::new()));
48        let mut added_handler = AddedEventHandler::new();
49        {
50            let entities = entities.clone();
51            let added_callbacks = added_callbacks.clone();
52            added_handler.on(move |AddedEvent { id }| {
53                let id = *id;
54                let entity = Rc::new(match unsafe { Entity::from_id(id) } {
55                    None => {
56                        warn!(?id, "AddedEvent Entity::from_id returned None");
57                        return;
58                    }
59                    Some(entity) => entity,
60                });
61                let weak = Rc::downgrade(&entity);
62
63                {
64                    let mut entities = entities.borrow_mut();
65                    entities.insert(id, entity);
66                }
67
68                let mut added_callbacks = added_callbacks.borrow_mut();
69                added_callbacks.handle_event(&(id, weak));
70            });
71        }
72
73        let removed_callbacks = Rc::new(RefCell::new(CallbackHandler::new()));
74        let mut removed_handler = RemovedEventHandler::new();
75        {
76            let entities = entities.clone();
77            let removed_callbacks = removed_callbacks.clone();
78            removed_handler.on(move |RemovedEvent { id }| {
79                {
80                    let mut entities = entities.borrow_mut();
81                    entities.remove(id);
82                }
83
84                let mut removed_callbacks = removed_callbacks.borrow_mut();
85                removed_callbacks.handle_event(id);
86            });
87        }
88
89        let mut s = Self {
90            entities,
91            added_callbacks,
92            added_handler,
93            removed_callbacks,
94            removed_handler,
95        };
96
97        s.update_to_real_entities();
98
99        s
100    }
101
102    fn update_to_real_entities(&mut self) {
103        let mut entities = self.entities.borrow_mut();
104        entities.clear();
105
106        for id in 0..ENTITIES_MAX_COUNT {
107            unsafe {
108                if !Entities.List[id as usize].is_null() {
109                    if let Some(entity) = Entity::from_id(u8::try_from(id).unwrap()) {
110                        entities.insert(u8::try_from(id).unwrap(), Rc::new(entity));
111                    }
112                }
113            }
114        }
115    }
116
117    pub fn on_added<F>(&mut self, callback: F)
118    where
119        F: FnMut(&(u8, Weak<Entity>)),
120        F: 'static,
121    {
122        let mut added_callbacks = self.added_callbacks.borrow_mut();
123        added_callbacks.on(callback);
124    }
125
126    pub fn on_removed<F>(&mut self, callback: F)
127    where
128        F: FnMut(&u8),
129        F: 'static,
130    {
131        let mut removed_callbacks = self.removed_callbacks.borrow_mut();
132        removed_callbacks.on(callback);
133    }
134
135    #[must_use]
136    pub fn get(&self, id: u8) -> Option<Weak<Entity>> {
137        let entities = self.entities.borrow();
138        let entity = entities.get(&id)?;
139        Some(Rc::downgrade(entity))
140    }
141
142    #[must_use]
143    pub fn get_all(&self) -> Vec<(u8, Weak<Entity>)> {
144        let entities = self.entities.borrow();
145        entities
146            .values()
147            .map(|entity| (entity.get_id(), Rc::downgrade(entity)))
148            .collect::<Vec<_>>()
149    }
150}
151
152impl Default for Entities {
153    fn default() -> Self {
154        Self::new()
155    }
156}