Skip to main content

bevy_ecs/component/
register.rs

1use alloc::vec::Vec;
2use bevy_platform::sync::PoisonError;
3use bevy_utils::TypeIdHashMap;
4use core::any::Any;
5use core::{any::TypeId, fmt::Debug, ops::Deref};
6
7use crate::component::{enforce_no_required_components_recursion, RequiredComponentsRegistrator};
8use crate::lifecycle::ComponentHooks;
9use crate::{
10    component::{
11        Component, ComponentDescriptor, ComponentId, Components, RequiredComponents, StorageType,
12    },
13    query::DebugCheckedUnwrap as _,
14};
15
16/// Generates [`ComponentId`]s.
17#[derive(Debug, Default)]
18pub struct ComponentIds {
19    next: bevy_platform::sync::atomic::AtomicUsize,
20}
21
22impl ComponentIds {
23    /// Peeks the next [`ComponentId`] to be generated without generating it.
24    pub fn peek(&self) -> ComponentId {
25        ComponentId::new(
26            self.next
27                .load(bevy_platform::sync::atomic::Ordering::Relaxed),
28        )
29    }
30
31    /// Generates and returns the next [`ComponentId`].
32    pub fn next(&self) -> ComponentId {
33        ComponentId::new(
34            self.next
35                .fetch_add(1, bevy_platform::sync::atomic::Ordering::Relaxed),
36        )
37    }
38
39    /// Peeks the next [`ComponentId`] to be generated without generating it.
40    pub fn peek_mut(&mut self) -> ComponentId {
41        ComponentId::new(*self.next.get_mut())
42    }
43
44    /// Generates and returns the next [`ComponentId`].
45    pub fn next_mut(&mut self) -> ComponentId {
46        let id = self.next.get_mut();
47        let result = ComponentId::new(*id);
48        *id += 1;
49        result
50    }
51
52    /// Returns the number of [`ComponentId`]s generated.
53    pub fn len(&self) -> usize {
54        self.peek().index()
55    }
56
57    /// Returns true if and only if no ids have been generated.
58    pub fn is_empty(&self) -> bool {
59        self.len() == 0
60    }
61}
62
63/// A [`Components`] wrapper that enables additional features, like registration.
64pub struct ComponentsRegistrator<'w> {
65    pub(super) components: &'w mut Components,
66    pub(super) ids: &'w mut ComponentIds,
67    pub(super) recursion_check_stack: Vec<ComponentId>,
68}
69
70impl Deref for ComponentsRegistrator<'_> {
71    type Target = Components;
72
73    fn deref(&self) -> &Self::Target {
74        self.components
75    }
76}
77
78impl<'w> ComponentsRegistrator<'w> {
79    /// Constructs a new [`ComponentsRegistrator`].
80    ///
81    /// # Safety
82    ///
83    /// The [`Components`] and [`ComponentIds`] must match.
84    /// For example, they must be from the same world.
85    pub unsafe fn new(components: &'w mut Components, ids: &'w mut ComponentIds) -> Self {
86        Self {
87            components,
88            ids,
89            recursion_check_stack: Vec::new(),
90        }
91    }
92
93    /// Converts this [`ComponentsRegistrator`] into a [`ComponentsQueuedRegistrator`].
94    /// This is intended for use to pass this value to a function that requires [`ComponentsQueuedRegistrator`].
95    /// It is generally not a good idea to queue a registration when you can instead register directly on this type.
96    pub fn as_queued(&self) -> ComponentsQueuedRegistrator<'_> {
97        // SAFETY: ensured by the caller that created self.
98        unsafe { ComponentsQueuedRegistrator::new(self.components, self.ids) }
99    }
100
101    /// Applies every queued registration.
102    /// This ensures that every valid [`ComponentId`] is registered,
103    /// enabling retrieving [`ComponentInfo`](super::ComponentInfo), etc.
104    pub fn apply_queued_registrations(&mut self) {
105        if !self.any_queued_mut() {
106            return;
107        }
108
109        // Note:
110        //
111        // This is not just draining the queue. We need to empty the queue without removing the information from `Components`.
112        // If we drained directly, we could break invariance.
113        //
114        // For example, say `ComponentA` and `ComponentB` are queued, and `ComponentA` requires `ComponentB`.
115        // If we drain directly, and `ComponentA` was the first to be registered, then, when `ComponentA`
116        // registers `ComponentB` in `Component::register_required_components`,
117        // `Components` will not know that `ComponentB` was queued
118        // (since it will have been drained from the queue.)
119        // If that happened, `Components` would assign a new `ComponentId` to `ComponentB`
120        // which would be *different* than the id it was assigned in the queue.
121        // Then, when the drain iterator gets to `ComponentB`,
122        // it would be unsafely registering `ComponentB`, which is already registered.
123        //
124        // As a result, we need to pop from each queue one by one instead of draining.
125
126        // components
127        while let Some(registrator) = {
128            let queued = self
129                .components
130                .queued
131                .get_mut()
132                .unwrap_or_else(PoisonError::into_inner);
133            queued.components.keys().next().copied().map(|type_id| {
134                // SAFETY: the id just came from a valid iterator.
135                unsafe { queued.components.remove(&type_id).debug_checked_unwrap() }
136            })
137        } {
138            registrator.register(self);
139        }
140
141        // dynamic
142        let queued = &mut self
143            .components
144            .queued
145            .get_mut()
146            .unwrap_or_else(PoisonError::into_inner);
147        if !queued.dynamic_registrations.is_empty() {
148            for registrator in core::mem::take(&mut queued.dynamic_registrations) {
149                registrator.register(self);
150            }
151        }
152    }
153
154    /// Registers a [`Component`] of type `T` with this instance.
155    /// If a component of this type has already been registered, this will return
156    /// the ID of the pre-existing component.
157    ///
158    /// # See also
159    ///
160    /// * [`Components::component_id()`]
161    /// * [`ComponentsRegistrator::register_component_with_descriptor()`]
162    #[inline]
163    pub fn register_component<T: Component>(&mut self) -> ComponentId {
164        self.register_component_checked(
165            TypeId::of::<T>(),
166            ComponentDescriptor::new::<T>,
167            T::register_required_components,
168            ComponentHooks::update_from_component::<T>,
169        )
170    }
171
172    // This exists to cut down on monomorphized code in register_component, which reduces compile times and binary sizes.
173    fn register_component_checked(
174        &mut self,
175        type_id: TypeId,
176        descriptor: fn() -> ComponentDescriptor,
177        register_required_components: fn(ComponentId, &mut RequiredComponentsRegistrator),
178        update_from_component: fn(&mut ComponentHooks) -> &mut ComponentHooks,
179    ) -> ComponentId {
180        if let Some(&id) = self.indices.get(&type_id) {
181            enforce_no_required_components_recursion(self, &self.recursion_check_stack, id);
182            return id;
183        }
184
185        if let Some(registrator) = self
186            .components
187            .queued
188            .get_mut()
189            .unwrap_or_else(PoisonError::into_inner)
190            .components
191            .remove(&type_id)
192        {
193            // If we are trying to register something that has already been queued, we respect the queue.
194            // Just like if we are trying to register something that already is, we respect the first registration.
195            return registrator.register(self);
196        }
197
198        let id = self.ids.next_mut();
199        // SAFETY: The component is not currently registered, and the id is fresh.
200        unsafe {
201            self.register_component_unchecked(
202                type_id,
203                id,
204                descriptor(),
205                register_required_components,
206                update_from_component,
207            );
208        }
209        id
210    }
211
212    /// # Safety
213    ///
214    /// Neither this component, nor its id may be registered or queued. This must be a new registration.
215    // This was written in a type-erased way to cut down on monomorphized code in register_component, which reduces compile times and binary sizes.
216    unsafe fn register_component_unchecked(
217        &mut self,
218        type_id: TypeId,
219        id: ComponentId,
220        descriptor: ComponentDescriptor,
221        register_required_components: fn(ComponentId, &mut RequiredComponentsRegistrator),
222        update_from_component: fn(&mut ComponentHooks) -> &mut ComponentHooks,
223    ) {
224        // SAFETY: ensured by caller.
225        unsafe {
226            self.components.register_component_inner(id, descriptor);
227        }
228        let prev = self.components.indices.insert(type_id, id);
229        debug_assert!(prev.is_none());
230
231        self.recursion_check_stack.push(id);
232        let mut required_components = RequiredComponents::default();
233        // SAFETY: `required_components` is empty
234        let mut required_components_registrator =
235            unsafe { RequiredComponentsRegistrator::new(self, &mut required_components) };
236        register_required_components(id, &mut required_components_registrator);
237        // SAFETY:
238        // - `id` was just registered in `self`
239        // - RequiredComponentsRegistrator guarantees that only components from `self` are included in `required_components`;
240        // - we just initialized the component with id `id` so no component requiring it can exist yet.
241        unsafe {
242            self.components
243                .register_required_by(id, &required_components);
244        }
245        self.recursion_check_stack.pop();
246
247        // SAFETY: we just inserted it in `register_component_inner`
248        let info = unsafe {
249            &mut self
250                .components
251                .components
252                .get_mut(id.index())
253                .debug_checked_unwrap()
254                .as_mut()
255                .debug_checked_unwrap()
256        };
257
258        update_from_component(&mut info.hooks);
259
260        info.required_components = required_components;
261    }
262
263    /// Registers a component described by `descriptor`.
264    ///
265    /// # Note
266    ///
267    /// If this method is called multiple times with identical descriptors, a distinct [`ComponentId`]
268    /// will be created for each one.
269    ///
270    /// This can also be used to register resources and non-send data.
271    ///
272    /// # Warning
273    ///
274    /// When registering a custom resource be sure to add [`crate::resource::IsResource`] as a required component,
275    ///
276    /// # See also
277    ///
278    /// * [`Components::component_id()`]
279    /// * [`ComponentsRegistrator::register_component()`]
280    #[inline]
281    pub fn register_component_with_descriptor(
282        &mut self,
283        descriptor: ComponentDescriptor,
284    ) -> ComponentId {
285        let id = self.ids.next_mut();
286        // SAFETY: The id is fresh.
287        unsafe {
288            self.components.register_component_inner(id, descriptor);
289        }
290        id
291    }
292
293    /// Registers a [non-send resource](crate::system::NonSend) of type `T` with this instance.
294    /// If a resource of this type has already been registered, this will return
295    /// the ID of the pre-existing resource.
296    #[inline]
297    pub fn register_non_send<T: Any>(&mut self) -> ComponentId {
298        // SAFETY: The [`ComponentDescriptor`] matches the [`TypeId`]
299        unsafe {
300            self.register_non_send_with(TypeId::of::<T>(), || {
301                ComponentDescriptor::new_non_send::<T>(StorageType::default())
302            })
303        }
304    }
305
306    /// Same as [`Components::register_non_send_unchecked`] but handles safety.
307    ///
308    /// # Safety
309    ///
310    /// The [`ComponentDescriptor`] must match the [`TypeId`].
311    #[inline]
312    unsafe fn register_non_send_with(
313        &mut self,
314        type_id: TypeId,
315        descriptor: fn() -> ComponentDescriptor,
316    ) -> ComponentId {
317        if let Some(id) = self.indices.get(&type_id) {
318            return *id;
319        }
320
321        if let Some(registrator) = self
322            .components
323            .queued
324            .get_mut()
325            .unwrap_or_else(PoisonError::into_inner)
326            .components
327            .remove(&type_id)
328        {
329            // If we are trying to register something that has already been queued, we respect the queue.
330            // Just like if we are trying to register something that already is, we respect the first registration.
331            return registrator.register(self);
332        }
333
334        let id = self.ids.next_mut();
335        // SAFETY: The resource is not currently registered, the id is fresh, and the [`ComponentDescriptor`] matches the [`TypeId`]
336        unsafe {
337            self.components
338                .register_non_send_unchecked(type_id, id, descriptor());
339        }
340        id
341    }
342
343    /// Equivalent of `Components::any_queued_mut`
344    pub fn any_queued_mut(&mut self) -> bool {
345        self.components.any_queued_mut()
346    }
347
348    /// Equivalent of `Components::any_queued_mut`
349    pub fn num_queued_mut(&mut self) -> usize {
350        self.components.num_queued_mut()
351    }
352}
353
354/// A queued component registration.
355pub(super) struct QueuedRegistration {
356    pub(super) registrator: fn(&mut ComponentsRegistrator, ComponentId, ComponentDescriptor),
357    pub(super) id: ComponentId,
358    pub(super) descriptor: ComponentDescriptor,
359}
360
361impl QueuedRegistration {
362    /// Creates the [`QueuedRegistration`].
363    ///
364    /// # Safety
365    ///
366    /// [`ComponentId`] must be unique.
367    unsafe fn new(
368        id: ComponentId,
369        descriptor: ComponentDescriptor,
370        func: fn(&mut ComponentsRegistrator, ComponentId, ComponentDescriptor),
371    ) -> Self {
372        Self {
373            registrator: func,
374            id,
375            descriptor,
376        }
377    }
378
379    /// Performs the registration, returning the now valid [`ComponentId`].
380    pub(super) fn register(self, registrator: &mut ComponentsRegistrator) -> ComponentId {
381        (self.registrator)(registrator, self.id, self.descriptor);
382        self.id
383    }
384}
385
386/// Allows queuing components to be registered.
387#[derive(Default)]
388pub struct QueuedComponents {
389    pub(super) components: TypeIdHashMap<QueuedRegistration>,
390    pub(super) dynamic_registrations: Vec<QueuedRegistration>,
391}
392
393impl Debug for QueuedComponents {
394    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
395        let components = self
396            .components
397            .iter()
398            .map(|(type_id, queued)| (type_id, queued.id))
399            .collect::<Vec<_>>();
400        let dynamic_registrations = self
401            .dynamic_registrations
402            .iter()
403            .map(|queued| queued.id)
404            .collect::<Vec<_>>();
405        write!(
406            f,
407            "components: {components:?}, dynamic_registrations: {dynamic_registrations:?}"
408        )
409    }
410}
411
412/// A type that enables queuing registration in [`Components`].
413///
414/// # Note
415///
416/// These queued registrations return [`ComponentId`]s.
417/// These ids are not yet valid, but they will become valid
418/// when either [`ComponentsRegistrator::apply_queued_registrations`] is called or the same registration is made directly.
419/// In either case, the returned [`ComponentId`]s will be correct, but they are not correct yet.
420///
421/// Generally, that means these [`ComponentId`]s can be safely used for read-only purposes.
422/// Modifying the contents of the world through these [`ComponentId`]s directly without waiting for them to be fully registered
423/// and without then confirming that they have been fully registered is not supported.
424/// Hence, extra care is needed with these [`ComponentId`]s to ensure all safety rules are followed.
425///
426/// As a rule of thumb, if you have mutable access to [`ComponentsRegistrator`], prefer to use that instead.
427/// Use this only if you need to know the id of a component but do not need to modify the contents of the world based on that id.
428#[derive(Clone, Copy)]
429pub struct ComponentsQueuedRegistrator<'w> {
430    components: &'w Components,
431    ids: &'w ComponentIds,
432}
433
434impl Deref for ComponentsQueuedRegistrator<'_> {
435    type Target = Components;
436
437    fn deref(&self) -> &Self::Target {
438        self.components
439    }
440}
441
442impl<'w> ComponentsQueuedRegistrator<'w> {
443    /// Constructs a new [`ComponentsQueuedRegistrator`].
444    ///
445    /// # Safety
446    ///
447    /// The [`Components`] and [`ComponentIds`] must match.
448    /// For example, they must be from the same world.
449    pub unsafe fn new(components: &'w Components, ids: &'w ComponentIds) -> Self {
450        Self { components, ids }
451    }
452
453    /// Queues this function to run as a component registrator if the given
454    /// type is not already queued as a component.
455    ///
456    /// # Safety
457    ///
458    /// The [`TypeId`] must not already be registered as a component.
459    unsafe fn register_arbitrary_component(
460        &self,
461        type_id: TypeId,
462        descriptor: ComponentDescriptor,
463        func: fn(&mut ComponentsRegistrator, ComponentId, ComponentDescriptor),
464    ) -> ComponentId {
465        self.components
466            .queued
467            .write()
468            .unwrap_or_else(PoisonError::into_inner)
469            .components
470            .entry(type_id)
471            .or_insert_with(|| {
472                // SAFETY: The id was just generated.
473                unsafe { QueuedRegistration::new(self.ids.next(), descriptor, func) }
474            })
475            .id
476    }
477
478    /// Queues this function to run as a dynamic registrator.
479    fn register_arbitrary_dynamic(
480        &self,
481        descriptor: ComponentDescriptor,
482        func: fn(&mut ComponentsRegistrator, ComponentId, ComponentDescriptor),
483    ) -> ComponentId {
484        let id = self.ids.next();
485        self.components
486            .queued
487            .write()
488            .unwrap_or_else(PoisonError::into_inner)
489            .dynamic_registrations
490            .push(
491                // SAFETY: The id was just generated.
492                unsafe { QueuedRegistration::new(id, descriptor, func) },
493            );
494        id
495    }
496
497    /// This is a queued version of [`ComponentsRegistrator::register_component`].
498    /// This will reserve an id and queue the registration.
499    /// These registrations will be carried out at the next opportunity.
500    ///
501    /// If this has already been registered or queued, this returns the previous [`ComponentId`].
502    ///
503    /// # Note
504    ///
505    /// Technically speaking, the returned [`ComponentId`] is not valid, but it will become valid later.
506    /// See type level docs for details.
507    #[inline]
508    pub fn queue_register_component<T: Component>(&self) -> ComponentId {
509        self.component_id::<T>().unwrap_or_else(|| {
510            // SAFETY: We just checked that this type was not already registered.
511            unsafe {
512                self.register_arbitrary_component(
513                    TypeId::of::<T>(),
514                    ComponentDescriptor::new::<T>(),
515                    |registrator, id, descriptor| {
516                        // SAFETY: We just checked that this is not currently registered or queued, and if it was registered since, this would have been dropped from the queue.
517                        #[expect(unused_unsafe, reason = "More precise to specify.")]
518                        unsafe {
519                            registrator.register_component_unchecked(
520                                TypeId::of::<T>(),
521                                id,
522                                descriptor,
523                                T::register_required_components,
524                                ComponentHooks::update_from_component::<T>,
525                            );
526                        }
527                    },
528                )
529            }
530        })
531    }
532
533    /// This is a queued version of [`ComponentsRegistrator::register_component_with_descriptor`].
534    /// This will reserve an id and queue the registration.
535    /// These registrations will be carried out at the next opportunity.
536    ///
537    /// This can also be used to register resources and non-send data.
538    ///
539    /// # Note
540    ///
541    /// Technically speaking, the returned [`ComponentId`] is not valid, but it will become valid later.
542    /// See type level docs for details.
543    ///
544    /// # Warning
545    ///
546    /// When registering a custom resource be sure to add [`crate::resource::IsResource`] as a required component,
547    /// Otherwise it will not function as a resource.
548    #[inline]
549    pub fn queue_register_component_with_descriptor(
550        &self,
551        descriptor: ComponentDescriptor,
552    ) -> ComponentId {
553        self.register_arbitrary_dynamic(descriptor, |registrator, id, descriptor| {
554            // SAFETY: Id uniqueness handled by caller.
555            unsafe {
556                registrator
557                    .components
558                    .register_component_inner(id, descriptor);
559            }
560        })
561    }
562
563    /// This is a queued version of [`ComponentsRegistrator::register_non_send`].
564    /// This will reserve an id and queue the registration.
565    /// These registrations will be carried out at the next opportunity.
566    ///
567    /// If this has already been registered or queued, this returns the previous [`ComponentId`].
568    ///
569    /// # Note
570    ///
571    /// Technically speaking, the returned [`ComponentId`] is not valid, but it will become valid later.
572    /// See type level docs for details.
573    #[inline]
574    pub fn queue_register_non_send<T: Any>(&self) -> ComponentId {
575        let type_id = TypeId::of::<T>();
576        self.get_id(type_id).unwrap_or_else(|| {
577            // SAFETY: We just checked that this type was not already registered.
578            unsafe {
579                self.register_arbitrary_component(
580                    type_id,
581                    ComponentDescriptor::new_non_send::<T>(StorageType::default()),
582                    |registrator, id, descriptor| {
583                        // SAFETY: We just checked that this is not currently registered or queued, and if it was registered since, this would have been dropped from the queue.
584                        // SAFETY: Id uniqueness handled by caller, and the type_id matches descriptor.
585                        #[expect(unused_unsafe, reason = "More precise to specify.")]
586                        unsafe {
587                            registrator.components.register_non_send_unchecked(
588                                descriptor.type_id().unwrap(),
589                                id,
590                                descriptor,
591                            );
592                        }
593                    },
594                )
595            }
596        })
597    }
598}