Skip to main content

bevy_ecs/component/
register.rs

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