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}