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}