1pub use bevy_ecs_macros::Bundle;
6
7use crate::{
8 archetype::{
9 Archetype, ArchetypeAfterBundleInsert, ArchetypeId, Archetypes, BundleComponentStatus,
10 ComponentStatus, SpawnBundleStatus,
11 },
12 change_detection::MaybeLocation,
13 component::{
14 Component, ComponentId, Components, ComponentsRegistrator, RequiredComponentConstructor,
15 RequiredComponents, StorageType, Tick,
16 },
17 entity::{Entities, Entity, EntityLocation},
18 observer::Observers,
19 prelude::World,
20 query::DebugCheckedUnwrap,
21 relationship::RelationshipHookMode,
22 storage::{SparseSetIndex, SparseSets, Storages, Table, TableRow},
23 world::{unsafe_world_cell::UnsafeWorldCell, EntityWorldMut, ON_ADD, ON_INSERT, ON_REPLACE},
24};
25use alloc::{boxed::Box, vec, vec::Vec};
26use bevy_platform::collections::{HashMap, HashSet};
27use bevy_ptr::{ConstNonNull, OwningPtr};
28use bevy_utils::TypeIdMap;
29use core::{any::TypeId, ptr::NonNull};
30use variadics_please::all_tuples;
31
32#[diagnostic::on_unimplemented(
147 message = "`{Self}` is not a `Bundle`",
148 label = "invalid `Bundle`",
149 note = "consider annotating `{Self}` with `#[derive(Component)]` or `#[derive(Bundle)]`"
150)]
151pub unsafe trait Bundle: DynamicBundle + Send + Sync + 'static {
152 #[doc(hidden)]
154 fn component_ids(components: &mut ComponentsRegistrator, ids: &mut impl FnMut(ComponentId));
155
156 fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option<ComponentId>));
158
159 fn register_required_components(
161 _components: &mut ComponentsRegistrator,
162 _required_components: &mut RequiredComponents,
163 );
164}
165
166pub unsafe trait BundleFromComponents {
181 #[doc(hidden)]
188 unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
189 where
190 F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>,
192 Self: Sized;
193}
194
195pub trait DynamicBundle {
197 type Effect: BundleEffect;
199 #[doc(hidden)]
206 fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) -> Self::Effect;
207}
208
209pub trait BundleEffect {
218 fn apply(self, entity: &mut EntityWorldMut);
220}
221
222unsafe impl<C: Component> Bundle for C {
226 fn component_ids(components: &mut ComponentsRegistrator, ids: &mut impl FnMut(ComponentId)) {
227 ids(components.register_component::<C>());
228 }
229
230 fn register_required_components(
231 components: &mut ComponentsRegistrator,
232 required_components: &mut RequiredComponents,
233 ) {
234 let component_id = components.register_component::<C>();
235 <C as Component>::register_required_components(
236 component_id,
237 components,
238 required_components,
239 0,
240 &mut Vec::new(),
241 );
242 }
243
244 fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option<ComponentId>)) {
245 ids(components.get_id(TypeId::of::<C>()));
246 }
247}
248
249unsafe impl<C: Component> BundleFromComponents for C {
252 unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
253 where
254 F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>,
256 Self: Sized,
257 {
258 let ptr = func(ctx);
259 unsafe { ptr.read() }
261 }
262}
263
264impl<C: Component> DynamicBundle for C {
265 type Effect = ();
266 #[inline]
267 fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) -> Self::Effect {
268 OwningPtr::make(self, |ptr| func(C::STORAGE_TYPE, ptr));
269 }
270}
271
272macro_rules! tuple_impl {
273 ($(#[$meta:meta])* $($name: ident),*) => {
274 #[expect(
275 clippy::allow_attributes,
276 reason = "This is a tuple-related macro; as such, the lints below may not always apply."
277 )]
278 #[allow(
279 unused_mut,
280 unused_variables,
281 reason = "Zero-length tuples won't use any of the parameters."
282 )]
283 $(#[$meta])*
284 unsafe impl<$($name: Bundle),*> Bundle for ($($name,)*) {
291 fn component_ids(components: &mut ComponentsRegistrator, ids: &mut impl FnMut(ComponentId)){
292 $(<$name as Bundle>::component_ids(components, ids);)*
293 }
294
295 fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option<ComponentId>)){
296 $(<$name as Bundle>::get_component_ids(components, ids);)*
297 }
298
299 fn register_required_components(
300 components: &mut ComponentsRegistrator,
301 required_components: &mut RequiredComponents,
302 ) {
303 $(<$name as Bundle>::register_required_components(components, required_components);)*
304 }
305 }
306
307 #[expect(
308 clippy::allow_attributes,
309 reason = "This is a tuple-related macro; as such, the lints below may not always apply."
310 )]
311 #[allow(
312 unused_mut,
313 unused_variables,
314 reason = "Zero-length tuples won't use any of the parameters."
315 )]
316 $(#[$meta])*
317 unsafe impl<$($name: BundleFromComponents),*> BundleFromComponents for ($($name,)*) {
324 #[allow(
325 clippy::unused_unit,
326 reason = "Zero-length tuples will generate a function body equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case."
327 )]
328 unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
329 where
330 F: FnMut(&mut T) -> OwningPtr<'_>
331 {
332 #[allow(
333 unused_unsafe,
334 reason = "Zero-length tuples will not run anything in the unsafe block. Additionally, rewriting this to move the () outside of the unsafe would require putting the safety comment inside the tuple, hurting readability of the code."
335 )]
336 unsafe { ($(<$name as BundleFromComponents>::from_components(ctx, func),)*) }
339 }
340 }
341
342 #[expect(
343 clippy::allow_attributes,
344 reason = "This is a tuple-related macro; as such, the lints below may not always apply."
345 )]
346 #[allow(
347 unused_mut,
348 unused_variables,
349 reason = "Zero-length tuples won't use any of the parameters."
350 )]
351 $(#[$meta])*
352 impl<$($name: Bundle),*> DynamicBundle for ($($name,)*) {
353 type Effect = ($($name::Effect,)*);
354 #[allow(
355 clippy::unused_unit,
356 reason = "Zero-length tuples will generate a function body equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case."
357 )]
358 #[inline(always)]
359 fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) -> Self::Effect {
360 #[allow(
361 non_snake_case,
362 reason = "The names of these variables are provided by the caller, not by us."
363 )]
364 let ($(mut $name,)*) = self;
365 ($(
366 $name.get_components(&mut *func),
367 )*)
368 }
369 }
370 }
371}
372
373all_tuples!(
374 #[doc(fake_variadic)]
375 tuple_impl,
376 0,
377 15,
378 B
379);
380
381pub trait NoBundleEffect {}
384
385macro_rules! after_effect_impl {
386 ($($after_effect: ident),*) => {
387 #[expect(
388 clippy::allow_attributes,
389 reason = "This is a tuple-related macro; as such, the lints below may not always apply."
390 )]
391 impl<$($after_effect: BundleEffect),*> BundleEffect for ($($after_effect,)*) {
392 #[allow(
393 clippy::unused_unit,
394 reason = "Zero-length tuples will generate a function body equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case.")
395 ]
396 fn apply(self, _entity: &mut EntityWorldMut) {
397 #[allow(
398 non_snake_case,
399 reason = "The names of these variables are provided by the caller, not by us."
400 )]
401 let ($($after_effect,)*) = self;
402 $($after_effect.apply(_entity);)*
403 }
404 }
405
406 impl<$($after_effect: NoBundleEffect),*> NoBundleEffect for ($($after_effect,)*) { }
407 }
408}
409
410all_tuples!(after_effect_impl, 0, 15, P);
411
412#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
416pub struct BundleId(usize);
417
418impl BundleId {
419 #[inline]
423 pub fn index(self) -> usize {
424 self.0
425 }
426}
427
428impl SparseSetIndex for BundleId {
429 #[inline]
430 fn sparse_set_index(&self) -> usize {
431 self.index()
432 }
433
434 #[inline]
435 fn get_sparse_set_index(value: usize) -> Self {
436 Self(value)
437 }
438}
439
440#[derive(Clone, Copy, Eq, PartialEq)]
442pub enum InsertMode {
443 Replace,
445 Keep,
447}
448
449pub struct BundleInfo {
453 id: BundleId,
454 component_ids: Vec<ComponentId>,
463 required_components: Vec<RequiredComponentConstructor>,
464 explicit_components_len: usize,
465}
466
467impl BundleInfo {
468 unsafe fn new(
475 bundle_type_name: &'static str,
476 storages: &mut Storages,
477 components: &Components,
478 mut component_ids: Vec<ComponentId>,
479 id: BundleId,
480 ) -> BundleInfo {
481 let mut deduped = component_ids.clone();
483 deduped.sort_unstable();
484 deduped.dedup();
485 if deduped.len() != component_ids.len() {
486 let mut seen = <HashSet<_>>::default();
488 let mut dups = Vec::new();
489 for id in component_ids {
490 if !seen.insert(id) {
491 dups.push(id);
492 }
493 }
494
495 let names = dups
496 .into_iter()
497 .map(|id| {
498 unsafe { components.get_info_unchecked(id).name() }
500 })
501 .collect::<Vec<_>>()
502 .join(", ");
503
504 panic!("Bundle {bundle_type_name} has duplicate components: {names}");
505 }
506
507 let explicit_components_len = component_ids.len();
509 let mut required_components = RequiredComponents::default();
510 for component_id in component_ids.iter().copied() {
511 let info = unsafe { components.get_info_unchecked(component_id) };
513 required_components.merge(info.required_components());
514 storages.prepare_component(info);
515 }
516 required_components.remove_explicit_components(&component_ids);
517
518 let required_components = required_components
520 .0
521 .into_iter()
522 .map(|(component_id, v)| {
523 let info = unsafe { components.get_info_unchecked(component_id) };
525 storages.prepare_component(info);
526 component_ids.push(component_id);
529 v.constructor
530 })
531 .collect();
532
533 BundleInfo {
538 id,
539 component_ids,
540 required_components,
541 explicit_components_len,
542 }
543 }
544
545 #[inline]
547 pub const fn id(&self) -> BundleId {
548 self.id
549 }
550
551 #[inline]
555 pub fn explicit_components(&self) -> &[ComponentId] {
556 &self.component_ids[0..self.explicit_components_len]
557 }
558
559 #[inline]
562 pub fn required_components(&self) -> &[ComponentId] {
563 &self.component_ids[self.explicit_components_len..]
564 }
565
566 #[inline]
570 pub fn contributed_components(&self) -> &[ComponentId] {
571 &self.component_ids
572 }
573
574 #[inline]
577 pub fn iter_explicit_components(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
578 self.explicit_components().iter().copied()
579 }
580
581 #[inline]
585 pub fn iter_contributed_components(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
586 self.component_ids.iter().copied()
587 }
588
589 pub fn iter_required_components(&self) -> impl Iterator<Item = ComponentId> + '_ {
592 self.required_components().iter().copied()
593 }
594
595 #[inline]
615 unsafe fn write_components<'a, T: DynamicBundle, S: BundleComponentStatus>(
616 &self,
617 table: &mut Table,
618 sparse_sets: &mut SparseSets,
619 bundle_component_status: &S,
620 required_components: impl Iterator<Item = &'a RequiredComponentConstructor>,
621 entity: Entity,
622 table_row: TableRow,
623 change_tick: Tick,
624 bundle: T,
625 insert_mode: InsertMode,
626 caller: MaybeLocation,
627 ) -> T::Effect {
628 let mut bundle_component = 0;
631 let after_effect = bundle.get_components(&mut |storage_type, component_ptr| {
632 let component_id = *self.component_ids.get_unchecked(bundle_component);
633 let status = unsafe { bundle_component_status.get_status(bundle_component) };
635 match storage_type {
636 StorageType::Table => {
637 let column =
638 unsafe { table.get_column_mut(component_id).debug_checked_unwrap() };
641 match (status, insert_mode) {
642 (ComponentStatus::Added, _) => {
643 column.initialize(table_row, component_ptr, change_tick, caller);
644 }
645 (ComponentStatus::Existing, InsertMode::Replace) => {
646 column.replace(table_row, component_ptr, change_tick, caller);
647 }
648 (ComponentStatus::Existing, InsertMode::Keep) => {
649 if let Some(drop_fn) = table.get_drop_for(component_id) {
650 drop_fn(component_ptr);
651 }
652 }
653 }
654 }
655 StorageType::SparseSet => {
656 let sparse_set =
657 unsafe { sparse_sets.get_mut(component_id).debug_checked_unwrap() };
660 match (status, insert_mode) {
661 (ComponentStatus::Added, _) | (_, InsertMode::Replace) => {
662 sparse_set.insert(entity, component_ptr, change_tick, caller);
663 }
664 (ComponentStatus::Existing, InsertMode::Keep) => {
665 if let Some(drop_fn) = sparse_set.get_drop() {
666 drop_fn(component_ptr);
667 }
668 }
669 }
670 }
671 }
672 bundle_component += 1;
673 });
674
675 for required_component in required_components {
676 required_component.initialize(
677 table,
678 sparse_sets,
679 change_tick,
680 table_row,
681 entity,
682 caller,
683 );
684 }
685
686 after_effect
687 }
688
689 pub(crate) unsafe fn initialize_required_component(
702 table: &mut Table,
703 sparse_sets: &mut SparseSets,
704 change_tick: Tick,
705 table_row: TableRow,
706 entity: Entity,
707 component_id: ComponentId,
708 storage_type: StorageType,
709 component_ptr: OwningPtr,
710 caller: MaybeLocation,
711 ) {
712 {
713 match storage_type {
714 StorageType::Table => {
715 let column =
716 unsafe { table.get_column_mut(component_id).debug_checked_unwrap() };
719 column.initialize(table_row, component_ptr, change_tick, caller);
720 }
721 StorageType::SparseSet => {
722 let sparse_set =
723 unsafe { sparse_sets.get_mut(component_id).debug_checked_unwrap() };
726 sparse_set.insert(entity, component_ptr, change_tick, caller);
727 }
728 }
729 }
730 }
731
732 pub(crate) unsafe fn insert_bundle_into_archetype(
741 &self,
742 archetypes: &mut Archetypes,
743 storages: &mut Storages,
744 components: &Components,
745 observers: &Observers,
746 archetype_id: ArchetypeId,
747 ) -> ArchetypeId {
748 if let Some(archetype_after_insert_id) = archetypes[archetype_id]
749 .edges()
750 .get_archetype_after_bundle_insert(self.id)
751 {
752 return archetype_after_insert_id;
753 }
754 let mut new_table_components = Vec::new();
755 let mut new_sparse_set_components = Vec::new();
756 let mut bundle_status = Vec::with_capacity(self.explicit_components_len);
757 let mut added_required_components = Vec::new();
758 let mut added = Vec::new();
759 let mut existing = Vec::new();
760
761 let current_archetype = &mut archetypes[archetype_id];
762 for component_id in self.iter_explicit_components() {
763 if current_archetype.contains(component_id) {
764 bundle_status.push(ComponentStatus::Existing);
765 existing.push(component_id);
766 } else {
767 bundle_status.push(ComponentStatus::Added);
768 added.push(component_id);
769 let component_info = unsafe { components.get_info_unchecked(component_id) };
771 match component_info.storage_type() {
772 StorageType::Table => new_table_components.push(component_id),
773 StorageType::SparseSet => new_sparse_set_components.push(component_id),
774 }
775 }
776 }
777
778 for (index, component_id) in self.iter_required_components().enumerate() {
779 if !current_archetype.contains(component_id) {
780 added_required_components.push(self.required_components[index].clone());
781 added.push(component_id);
782 let component_info = unsafe { components.get_info_unchecked(component_id) };
784 match component_info.storage_type() {
785 StorageType::Table => {
786 new_table_components.push(component_id);
787 }
788 StorageType::SparseSet => {
789 new_sparse_set_components.push(component_id);
790 }
791 }
792 }
793 }
794
795 if new_table_components.is_empty() && new_sparse_set_components.is_empty() {
796 let edges = current_archetype.edges_mut();
797 edges.cache_archetype_after_bundle_insert(
799 self.id,
800 archetype_id,
801 bundle_status,
802 added_required_components,
803 added,
804 existing,
805 );
806 archetype_id
807 } else {
808 let table_id;
809 let table_components;
810 let sparse_set_components;
811 {
813 let current_archetype = &archetypes[archetype_id];
814 table_components = if new_table_components.is_empty() {
815 table_id = current_archetype.table_id();
817 current_archetype.table_components().collect()
818 } else {
819 new_table_components.extend(current_archetype.table_components());
820 new_table_components.sort_unstable();
822 table_id = unsafe {
824 storages
825 .tables
826 .get_id_or_insert(&new_table_components, components)
827 };
828
829 new_table_components
830 };
831
832 sparse_set_components = if new_sparse_set_components.is_empty() {
833 current_archetype.sparse_set_components().collect()
834 } else {
835 new_sparse_set_components.extend(current_archetype.sparse_set_components());
836 new_sparse_set_components.sort_unstable();
838 new_sparse_set_components
839 };
840 };
841 let new_archetype_id = archetypes.get_id_or_insert(
843 components,
844 observers,
845 table_id,
846 table_components,
847 sparse_set_components,
848 );
849 archetypes[archetype_id]
851 .edges_mut()
852 .cache_archetype_after_bundle_insert(
853 self.id,
854 new_archetype_id,
855 bundle_status,
856 added_required_components,
857 added,
858 existing,
859 );
860 new_archetype_id
861 }
862 }
863
864 pub(crate) unsafe fn remove_bundle_from_archetype(
880 &self,
881 archetypes: &mut Archetypes,
882 storages: &mut Storages,
883 components: &Components,
884 observers: &Observers,
885 archetype_id: ArchetypeId,
886 intersection: bool,
887 ) -> Option<ArchetypeId> {
888 let archetype_after_remove_result = {
891 let edges = archetypes[archetype_id].edges();
892 if intersection {
893 edges.get_archetype_after_bundle_remove(self.id())
894 } else {
895 edges.get_archetype_after_bundle_take(self.id())
896 }
897 };
898 let result = if let Some(result) = archetype_after_remove_result {
899 result
901 } else {
902 let mut next_table_components;
903 let mut next_sparse_set_components;
904 let next_table_id;
905 {
906 let current_archetype = &mut archetypes[archetype_id];
907 let mut removed_table_components = Vec::new();
908 let mut removed_sparse_set_components = Vec::new();
909 for component_id in self.iter_explicit_components() {
910 if current_archetype.contains(component_id) {
911 let component_info = unsafe { components.get_info_unchecked(component_id) };
913 match component_info.storage_type() {
914 StorageType::Table => removed_table_components.push(component_id),
915 StorageType::SparseSet => {
916 removed_sparse_set_components.push(component_id);
917 }
918 }
919 } else if !intersection {
920 current_archetype
923 .edges_mut()
924 .cache_archetype_after_bundle_take(self.id(), None);
925 return None;
926 }
927 }
928
929 removed_table_components.sort_unstable();
932 removed_sparse_set_components.sort_unstable();
933 next_table_components = current_archetype.table_components().collect();
934 next_sparse_set_components = current_archetype.sparse_set_components().collect();
935 sorted_remove(&mut next_table_components, &removed_table_components);
936 sorted_remove(
937 &mut next_sparse_set_components,
938 &removed_sparse_set_components,
939 );
940
941 next_table_id = if removed_table_components.is_empty() {
942 current_archetype.table_id()
943 } else {
944 unsafe {
946 storages
947 .tables
948 .get_id_or_insert(&next_table_components, components)
949 }
950 };
951 }
952
953 let new_archetype_id = archetypes.get_id_or_insert(
954 components,
955 observers,
956 next_table_id,
957 next_table_components,
958 next_sparse_set_components,
959 );
960 Some(new_archetype_id)
961 };
962 let current_archetype = &mut archetypes[archetype_id];
963 if intersection {
965 current_archetype
966 .edges_mut()
967 .cache_archetype_after_bundle_remove(self.id(), result);
968 } else {
969 current_archetype
970 .edges_mut()
971 .cache_archetype_after_bundle_take(self.id(), result);
972 }
973 result
974 }
975}
976
977pub(crate) struct BundleInserter<'w> {
979 world: UnsafeWorldCell<'w>,
980 bundle_info: ConstNonNull<BundleInfo>,
981 archetype_after_insert: ConstNonNull<ArchetypeAfterBundleInsert>,
982 table: NonNull<Table>,
983 archetype: NonNull<Archetype>,
984 archetype_move_type: ArchetypeMoveType,
985 change_tick: Tick,
986}
987
988pub(crate) enum ArchetypeMoveType {
991 SameArchetype,
994 NewArchetypeSameTable { new_archetype: NonNull<Archetype> },
997 NewArchetypeNewTable {
1000 new_archetype: NonNull<Archetype>,
1001 new_table: NonNull<Table>,
1002 },
1003}
1004
1005impl<'w> BundleInserter<'w> {
1006 #[inline]
1007 pub(crate) fn new<T: Bundle>(
1008 world: &'w mut World,
1009 archetype_id: ArchetypeId,
1010 change_tick: Tick,
1011 ) -> Self {
1012 let mut registrator =
1014 unsafe { ComponentsRegistrator::new(&mut world.components, &mut world.component_ids) };
1015 let bundle_id = world
1016 .bundles
1017 .register_info::<T>(&mut registrator, &mut world.storages);
1018 unsafe { Self::new_with_id(world, archetype_id, bundle_id, change_tick) }
1020 }
1021
1022 #[inline]
1027 pub(crate) unsafe fn new_with_id(
1028 world: &'w mut World,
1029 archetype_id: ArchetypeId,
1030 bundle_id: BundleId,
1031 change_tick: Tick,
1032 ) -> Self {
1033 let bundle_info = world.bundles.get_unchecked(bundle_id);
1035 let bundle_id = bundle_info.id();
1036 let new_archetype_id = bundle_info.insert_bundle_into_archetype(
1037 &mut world.archetypes,
1038 &mut world.storages,
1039 &world.components,
1040 &world.observers,
1041 archetype_id,
1042 );
1043 if new_archetype_id == archetype_id {
1044 let archetype = &mut world.archetypes[archetype_id];
1045 let archetype_after_insert = unsafe {
1047 archetype
1048 .edges()
1049 .get_archetype_after_bundle_insert_internal(bundle_id)
1050 .debug_checked_unwrap()
1051 };
1052 let table_id = archetype.table_id();
1053 let table = &mut world.storages.tables[table_id];
1054 Self {
1055 archetype_after_insert: archetype_after_insert.into(),
1056 archetype: archetype.into(),
1057 bundle_info: bundle_info.into(),
1058 table: table.into(),
1059 archetype_move_type: ArchetypeMoveType::SameArchetype,
1060 change_tick,
1061 world: world.as_unsafe_world_cell(),
1062 }
1063 } else {
1064 let (archetype, new_archetype) =
1065 world.archetypes.get_2_mut(archetype_id, new_archetype_id);
1066 let archetype_after_insert = unsafe {
1068 archetype
1069 .edges()
1070 .get_archetype_after_bundle_insert_internal(bundle_id)
1071 .debug_checked_unwrap()
1072 };
1073 let table_id = archetype.table_id();
1074 let new_table_id = new_archetype.table_id();
1075 if table_id == new_table_id {
1076 let table = &mut world.storages.tables[table_id];
1077 Self {
1078 archetype_after_insert: archetype_after_insert.into(),
1079 archetype: archetype.into(),
1080 bundle_info: bundle_info.into(),
1081 table: table.into(),
1082 archetype_move_type: ArchetypeMoveType::NewArchetypeSameTable {
1083 new_archetype: new_archetype.into(),
1084 },
1085 change_tick,
1086 world: world.as_unsafe_world_cell(),
1087 }
1088 } else {
1089 let (table, new_table) = world.storages.tables.get_2_mut(table_id, new_table_id);
1090 Self {
1091 archetype_after_insert: archetype_after_insert.into(),
1092 archetype: archetype.into(),
1093 bundle_info: bundle_info.into(),
1094 table: table.into(),
1095 archetype_move_type: ArchetypeMoveType::NewArchetypeNewTable {
1096 new_archetype: new_archetype.into(),
1097 new_table: new_table.into(),
1098 },
1099 change_tick,
1100 world: world.as_unsafe_world_cell(),
1101 }
1102 }
1103 }
1104 }
1105
1106 #[inline]
1110 pub(crate) unsafe fn insert<T: DynamicBundle>(
1111 &mut self,
1112 entity: Entity,
1113 location: EntityLocation,
1114 bundle: T,
1115 insert_mode: InsertMode,
1116 caller: MaybeLocation,
1117 relationship_hook_mode: RelationshipHookMode,
1118 ) -> (EntityLocation, T::Effect) {
1119 let bundle_info = self.bundle_info.as_ref();
1120 let archetype_after_insert = self.archetype_after_insert.as_ref();
1121 let archetype = self.archetype.as_ref();
1122
1123 unsafe {
1126 let mut deferred_world = self.world.into_deferred();
1128
1129 if insert_mode == InsertMode::Replace {
1130 if archetype.has_replace_observer() {
1131 deferred_world.trigger_observers(
1132 ON_REPLACE,
1133 entity,
1134 archetype_after_insert.iter_existing(),
1135 caller,
1136 );
1137 }
1138 deferred_world.trigger_on_replace(
1139 archetype,
1140 entity,
1141 archetype_after_insert.iter_existing(),
1142 caller,
1143 relationship_hook_mode,
1144 );
1145 }
1146 }
1147
1148 let table = self.table.as_mut();
1149
1150 let archetype = self.archetype.as_mut();
1153
1154 let (new_archetype, new_location, after_effect) = match &mut self.archetype_move_type {
1155 ArchetypeMoveType::SameArchetype => {
1156 let sparse_sets = {
1158 let world = self.world.world_mut();
1159 &mut world.storages.sparse_sets
1160 };
1161
1162 let after_effect = bundle_info.write_components(
1163 table,
1164 sparse_sets,
1165 archetype_after_insert,
1166 archetype_after_insert.required_components.iter(),
1167 entity,
1168 location.table_row,
1169 self.change_tick,
1170 bundle,
1171 insert_mode,
1172 caller,
1173 );
1174
1175 (archetype, location, after_effect)
1176 }
1177 ArchetypeMoveType::NewArchetypeSameTable { new_archetype } => {
1178 let new_archetype = new_archetype.as_mut();
1179
1180 let (sparse_sets, entities) = {
1182 let world = self.world.world_mut();
1183 (&mut world.storages.sparse_sets, &mut world.entities)
1184 };
1185
1186 let result = archetype.swap_remove(location.archetype_row);
1187 if let Some(swapped_entity) = result.swapped_entity {
1188 let swapped_location =
1189 unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
1191 entities.set(
1192 swapped_entity.index(),
1193 EntityLocation {
1194 archetype_id: swapped_location.archetype_id,
1195 archetype_row: location.archetype_row,
1196 table_id: swapped_location.table_id,
1197 table_row: swapped_location.table_row,
1198 },
1199 );
1200 }
1201 let new_location = new_archetype.allocate(entity, result.table_row);
1202 entities.set(entity.index(), new_location);
1203 let after_effect = bundle_info.write_components(
1204 table,
1205 sparse_sets,
1206 archetype_after_insert,
1207 archetype_after_insert.required_components.iter(),
1208 entity,
1209 result.table_row,
1210 self.change_tick,
1211 bundle,
1212 insert_mode,
1213 caller,
1214 );
1215
1216 (new_archetype, new_location, after_effect)
1217 }
1218 ArchetypeMoveType::NewArchetypeNewTable {
1219 new_archetype,
1220 new_table,
1221 } => {
1222 let new_table = new_table.as_mut();
1223 let new_archetype = new_archetype.as_mut();
1224
1225 let (archetypes_ptr, sparse_sets, entities) = {
1227 let world = self.world.world_mut();
1228 let archetype_ptr: *mut Archetype = world.archetypes.archetypes.as_mut_ptr();
1229 (
1230 archetype_ptr,
1231 &mut world.storages.sparse_sets,
1232 &mut world.entities,
1233 )
1234 };
1235 let result = archetype.swap_remove(location.archetype_row);
1236 if let Some(swapped_entity) = result.swapped_entity {
1237 let swapped_location =
1238 unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
1240 entities.set(
1241 swapped_entity.index(),
1242 EntityLocation {
1243 archetype_id: swapped_location.archetype_id,
1244 archetype_row: location.archetype_row,
1245 table_id: swapped_location.table_id,
1246 table_row: swapped_location.table_row,
1247 },
1248 );
1249 }
1250 let move_result = table.move_to_superset_unchecked(result.table_row, new_table);
1253 let new_location = new_archetype.allocate(entity, move_result.new_row);
1254 entities.set(entity.index(), new_location);
1255
1256 if let Some(swapped_entity) = move_result.swapped_entity {
1258 let swapped_location =
1259 unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
1261
1262 entities.set(
1263 swapped_entity.index(),
1264 EntityLocation {
1265 archetype_id: swapped_location.archetype_id,
1266 archetype_row: swapped_location.archetype_row,
1267 table_id: swapped_location.table_id,
1268 table_row: result.table_row,
1269 },
1270 );
1271
1272 if archetype.id() == swapped_location.archetype_id {
1273 archetype
1274 .set_entity_table_row(swapped_location.archetype_row, result.table_row);
1275 } else if new_archetype.id() == swapped_location.archetype_id {
1276 new_archetype
1277 .set_entity_table_row(swapped_location.archetype_row, result.table_row);
1278 } else {
1279 (*archetypes_ptr.add(swapped_location.archetype_id.index()))
1281 .set_entity_table_row(swapped_location.archetype_row, result.table_row);
1282 }
1283 }
1284
1285 let after_effect = bundle_info.write_components(
1286 new_table,
1287 sparse_sets,
1288 archetype_after_insert,
1289 archetype_after_insert.required_components.iter(),
1290 entity,
1291 move_result.new_row,
1292 self.change_tick,
1293 bundle,
1294 insert_mode,
1295 caller,
1296 );
1297
1298 (new_archetype, new_location, after_effect)
1299 }
1300 };
1301
1302 let new_archetype = &*new_archetype;
1303 let mut deferred_world = unsafe { self.world.into_deferred() };
1305
1306 unsafe {
1309 deferred_world.trigger_on_add(
1310 new_archetype,
1311 entity,
1312 archetype_after_insert.iter_added(),
1313 caller,
1314 );
1315 if new_archetype.has_add_observer() {
1316 deferred_world.trigger_observers(
1317 ON_ADD,
1318 entity,
1319 archetype_after_insert.iter_added(),
1320 caller,
1321 );
1322 }
1323 match insert_mode {
1324 InsertMode::Replace => {
1325 deferred_world.trigger_on_insert(
1327 new_archetype,
1328 entity,
1329 archetype_after_insert.iter_inserted(),
1330 caller,
1331 relationship_hook_mode,
1332 );
1333 if new_archetype.has_insert_observer() {
1334 deferred_world.trigger_observers(
1335 ON_INSERT,
1336 entity,
1337 archetype_after_insert.iter_inserted(),
1338 caller,
1339 );
1340 }
1341 }
1342 InsertMode::Keep => {
1343 deferred_world.trigger_on_insert(
1346 new_archetype,
1347 entity,
1348 archetype_after_insert.iter_added(),
1349 caller,
1350 relationship_hook_mode,
1351 );
1352 if new_archetype.has_insert_observer() {
1353 deferred_world.trigger_observers(
1354 ON_INSERT,
1355 entity,
1356 archetype_after_insert.iter_added(),
1357 caller,
1358 );
1359 }
1360 }
1361 }
1362 }
1363
1364 (new_location, after_effect)
1365 }
1366
1367 #[inline]
1368 pub(crate) fn entities(&mut self) -> &mut Entities {
1369 unsafe { &mut self.world.world_mut().entities }
1371 }
1372}
1373
1374pub(crate) struct BundleSpawner<'w> {
1376 world: UnsafeWorldCell<'w>,
1377 bundle_info: ConstNonNull<BundleInfo>,
1378 table: NonNull<Table>,
1379 archetype: NonNull<Archetype>,
1380 change_tick: Tick,
1381}
1382
1383impl<'w> BundleSpawner<'w> {
1384 #[inline]
1385 pub fn new<T: Bundle>(world: &'w mut World, change_tick: Tick) -> Self {
1386 let mut registrator =
1388 unsafe { ComponentsRegistrator::new(&mut world.components, &mut world.component_ids) };
1389 let bundle_id = world
1390 .bundles
1391 .register_info::<T>(&mut registrator, &mut world.storages);
1392 unsafe { Self::new_with_id(world, bundle_id, change_tick) }
1394 }
1395
1396 #[inline]
1401 pub(crate) unsafe fn new_with_id(
1402 world: &'w mut World,
1403 bundle_id: BundleId,
1404 change_tick: Tick,
1405 ) -> Self {
1406 let bundle_info = world.bundles.get_unchecked(bundle_id);
1407 let new_archetype_id = bundle_info.insert_bundle_into_archetype(
1408 &mut world.archetypes,
1409 &mut world.storages,
1410 &world.components,
1411 &world.observers,
1412 ArchetypeId::EMPTY,
1413 );
1414 let archetype = &mut world.archetypes[new_archetype_id];
1415 let table = &mut world.storages.tables[archetype.table_id()];
1416 Self {
1417 bundle_info: bundle_info.into(),
1418 table: table.into(),
1419 archetype: archetype.into(),
1420 change_tick,
1421 world: world.as_unsafe_world_cell(),
1422 }
1423 }
1424
1425 #[inline]
1426 pub fn reserve_storage(&mut self, additional: usize) {
1427 let (archetype, table) = unsafe { (self.archetype.as_mut(), self.table.as_mut()) };
1429 archetype.reserve(additional);
1430 table.reserve(additional);
1431 }
1432
1433 #[inline]
1436 #[track_caller]
1437 pub unsafe fn spawn_non_existent<T: DynamicBundle>(
1438 &mut self,
1439 entity: Entity,
1440 bundle: T,
1441 caller: MaybeLocation,
1442 ) -> (EntityLocation, T::Effect) {
1443 let bundle_info = self.bundle_info.as_ref();
1445 let (location, after_effect) = {
1446 let table = self.table.as_mut();
1447 let archetype = self.archetype.as_mut();
1448
1449 let (sparse_sets, entities) = {
1451 let world = self.world.world_mut();
1452 (&mut world.storages.sparse_sets, &mut world.entities)
1453 };
1454 let table_row = table.allocate(entity);
1455 let location = archetype.allocate(entity, table_row);
1456 let after_effect = bundle_info.write_components(
1457 table,
1458 sparse_sets,
1459 &SpawnBundleStatus,
1460 bundle_info.required_components.iter(),
1461 entity,
1462 table_row,
1463 self.change_tick,
1464 bundle,
1465 InsertMode::Replace,
1466 caller,
1467 );
1468 entities.set(entity.index(), location);
1469 (location, after_effect)
1470 };
1471
1472 let mut deferred_world = unsafe { self.world.into_deferred() };
1474 let archetype = self.archetype.as_ref();
1476 unsafe {
1479 deferred_world.trigger_on_add(
1480 archetype,
1481 entity,
1482 bundle_info.iter_contributed_components(),
1483 caller,
1484 );
1485 if archetype.has_add_observer() {
1486 deferred_world.trigger_observers(
1487 ON_ADD,
1488 entity,
1489 bundle_info.iter_contributed_components(),
1490 caller,
1491 );
1492 }
1493 deferred_world.trigger_on_insert(
1494 archetype,
1495 entity,
1496 bundle_info.iter_contributed_components(),
1497 caller,
1498 RelationshipHookMode::Run,
1499 );
1500 if archetype.has_insert_observer() {
1501 deferred_world.trigger_observers(
1502 ON_INSERT,
1503 entity,
1504 bundle_info.iter_contributed_components(),
1505 caller,
1506 );
1507 }
1508 };
1509
1510 (location, after_effect)
1511 }
1512
1513 #[inline]
1516 pub unsafe fn spawn<T: Bundle>(
1517 &mut self,
1518 bundle: T,
1519 caller: MaybeLocation,
1520 ) -> (Entity, T::Effect) {
1521 let entity = self.entities().alloc();
1522 let (_, after_effect) = unsafe { self.spawn_non_existent(entity, bundle, caller) };
1524 (entity, after_effect)
1525 }
1526
1527 #[inline]
1528 pub(crate) fn entities(&mut self) -> &mut Entities {
1529 unsafe { &mut self.world.world_mut().entities }
1531 }
1532
1533 #[inline]
1536 pub(crate) unsafe fn flush_commands(&mut self) {
1537 self.world.world_mut().flush();
1539 }
1540}
1541
1542#[derive(Default)]
1544pub struct Bundles {
1545 bundle_infos: Vec<BundleInfo>,
1546 bundle_ids: TypeIdMap<BundleId>,
1548 contributed_bundle_ids: TypeIdMap<BundleId>,
1550 dynamic_bundle_ids: HashMap<Box<[ComponentId]>, BundleId>,
1552 dynamic_bundle_storages: HashMap<BundleId, Vec<StorageType>>,
1553 dynamic_component_bundle_ids: HashMap<ComponentId, BundleId>,
1555 dynamic_component_storages: HashMap<BundleId, StorageType>,
1556}
1557
1558impl Bundles {
1559 pub fn len(&self) -> usize {
1561 self.bundle_infos.len()
1562 }
1563
1564 pub fn is_empty(&self) -> bool {
1566 self.len() == 0
1567 }
1568
1569 pub fn iter(&self) -> impl Iterator<Item = &BundleInfo> {
1571 self.bundle_infos.iter()
1572 }
1573
1574 #[inline]
1577 pub fn get(&self, bundle_id: BundleId) -> Option<&BundleInfo> {
1578 self.bundle_infos.get(bundle_id.index())
1579 }
1580
1581 #[inline]
1585 pub fn get_id(&self, type_id: TypeId) -> Option<BundleId> {
1586 self.bundle_ids.get(&type_id).cloned()
1587 }
1588
1589 pub(crate) fn register_info<T: Bundle>(
1593 &mut self,
1594 components: &mut ComponentsRegistrator,
1595 storages: &mut Storages,
1596 ) -> BundleId {
1597 let bundle_infos = &mut self.bundle_infos;
1598 *self.bundle_ids.entry(TypeId::of::<T>()).or_insert_with(|| {
1599 let mut component_ids= Vec::new();
1600 T::component_ids(components, &mut |id| component_ids.push(id));
1601 let id = BundleId(bundle_infos.len());
1602 let bundle_info =
1603 unsafe { BundleInfo::new(core::any::type_name::<T>(), storages, components, component_ids, id) };
1608 bundle_infos.push(bundle_info);
1609 id
1610 })
1611 }
1612
1613 pub(crate) fn register_contributed_bundle_info<T: Bundle>(
1617 &mut self,
1618 components: &mut ComponentsRegistrator,
1619 storages: &mut Storages,
1620 ) -> BundleId {
1621 if let Some(id) = self.contributed_bundle_ids.get(&TypeId::of::<T>()).cloned() {
1622 id
1623 } else {
1624 let explicit_bundle_id = self.register_info::<T>(components, storages);
1625 let id = unsafe {
1627 let (ptr, len) = {
1628 let contributed = self
1630 .get_unchecked(explicit_bundle_id)
1631 .contributed_components();
1632 (contributed.as_ptr(), contributed.len())
1633 };
1634 self.init_dynamic_info(storages, components, core::slice::from_raw_parts(ptr, len))
1637 };
1638 self.contributed_bundle_ids.insert(TypeId::of::<T>(), id);
1639 id
1640 }
1641 }
1642
1643 pub(crate) unsafe fn get_unchecked(&self, id: BundleId) -> &BundleInfo {
1646 self.bundle_infos.get_unchecked(id.0)
1647 }
1648
1649 pub(crate) unsafe fn get_storage_unchecked(&self, id: BundleId) -> StorageType {
1652 *self
1653 .dynamic_component_storages
1654 .get(&id)
1655 .debug_checked_unwrap()
1656 }
1657
1658 pub(crate) unsafe fn get_storages_unchecked(&mut self, id: BundleId) -> &mut Vec<StorageType> {
1661 self.dynamic_bundle_storages
1662 .get_mut(&id)
1663 .debug_checked_unwrap()
1664 }
1665
1666 pub(crate) fn init_dynamic_info(
1673 &mut self,
1674 storages: &mut Storages,
1675 components: &Components,
1676 component_ids: &[ComponentId],
1677 ) -> BundleId {
1678 let bundle_infos = &mut self.bundle_infos;
1679
1680 let (_, bundle_id) = self
1682 .dynamic_bundle_ids
1683 .raw_entry_mut()
1684 .from_key(component_ids)
1685 .or_insert_with(|| {
1686 let (id, storages) = initialize_dynamic_bundle(
1687 bundle_infos,
1688 storages,
1689 components,
1690 Vec::from(component_ids),
1691 );
1692 unsafe {
1694 self.dynamic_bundle_storages
1695 .insert_unique_unchecked(id, storages);
1696 }
1697 (component_ids.into(), id)
1698 });
1699 *bundle_id
1700 }
1701
1702 pub(crate) fn init_component_info(
1708 &mut self,
1709 storages: &mut Storages,
1710 components: &Components,
1711 component_id: ComponentId,
1712 ) -> BundleId {
1713 let bundle_infos = &mut self.bundle_infos;
1714 let bundle_id = self
1715 .dynamic_component_bundle_ids
1716 .entry(component_id)
1717 .or_insert_with(|| {
1718 let (id, storage_type) = initialize_dynamic_bundle(
1719 bundle_infos,
1720 storages,
1721 components,
1722 vec![component_id],
1723 );
1724 self.dynamic_component_storages.insert(id, storage_type[0]);
1725 id
1726 });
1727 *bundle_id
1728 }
1729}
1730
1731fn initialize_dynamic_bundle(
1734 bundle_infos: &mut Vec<BundleInfo>,
1735 storages: &mut Storages,
1736 components: &Components,
1737 component_ids: Vec<ComponentId>,
1738) -> (BundleId, Vec<StorageType>) {
1739 let storage_types = component_ids.iter().map(|&id| {
1741 components.get_info(id).unwrap_or_else(|| {
1742 panic!(
1743 "init_dynamic_info called with component id {id:?} which doesn't exist in this world"
1744 )
1745 }).storage_type()
1746 }).collect();
1747
1748 let id = BundleId(bundle_infos.len());
1749 let bundle_info =
1750 unsafe { BundleInfo::new("<dynamic bundle>", storages, components, component_ids, id) };
1752 bundle_infos.push(bundle_info);
1753
1754 (id, storage_types)
1755}
1756
1757fn sorted_remove<T: Eq + Ord + Copy>(source: &mut Vec<T>, remove: &[T]) {
1758 let mut remove_index = 0;
1759 source.retain(|value| {
1760 while remove_index < remove.len() && *value > remove[remove_index] {
1761 remove_index += 1;
1762 }
1763
1764 if remove_index < remove.len() {
1765 *value != remove[remove_index]
1766 } else {
1767 true
1768 }
1769 });
1770}
1771
1772#[cfg(test)]
1773mod tests {
1774 use crate::{component::HookContext, prelude::*, world::DeferredWorld};
1775 use alloc::vec;
1776
1777 #[derive(Component)]
1778 struct A;
1779
1780 #[derive(Component)]
1781 #[component(on_add = a_on_add, on_insert = a_on_insert, on_replace = a_on_replace, on_remove = a_on_remove)]
1782 struct AMacroHooks;
1783
1784 fn a_on_add(mut world: DeferredWorld, _: HookContext) {
1785 world.resource_mut::<R>().assert_order(0);
1786 }
1787
1788 fn a_on_insert(mut world: DeferredWorld, _: HookContext) {
1789 world.resource_mut::<R>().assert_order(1);
1790 }
1791
1792 fn a_on_replace(mut world: DeferredWorld, _: HookContext) {
1793 world.resource_mut::<R>().assert_order(2);
1794 }
1795
1796 fn a_on_remove(mut world: DeferredWorld, _: HookContext) {
1797 world.resource_mut::<R>().assert_order(3);
1798 }
1799
1800 #[derive(Component)]
1801 struct B;
1802
1803 #[derive(Component)]
1804 struct C;
1805
1806 #[derive(Component)]
1807 struct D;
1808
1809 #[derive(Component, Eq, PartialEq, Debug)]
1810 struct V(&'static str); #[derive(Resource, Default)]
1813 struct R(usize);
1814
1815 impl R {
1816 #[track_caller]
1817 fn assert_order(&mut self, count: usize) {
1818 assert_eq!(count, self.0);
1819 self.0 += 1;
1820 }
1821 }
1822
1823 #[test]
1824 fn component_hook_order_spawn_despawn() {
1825 let mut world = World::new();
1826 world.init_resource::<R>();
1827 world
1828 .register_component_hooks::<A>()
1829 .on_add(|mut world, _| world.resource_mut::<R>().assert_order(0))
1830 .on_insert(|mut world, _| world.resource_mut::<R>().assert_order(1))
1831 .on_replace(|mut world, _| world.resource_mut::<R>().assert_order(2))
1832 .on_remove(|mut world, _| world.resource_mut::<R>().assert_order(3));
1833
1834 let entity = world.spawn(A).id();
1835 world.despawn(entity);
1836 assert_eq!(4, world.resource::<R>().0);
1837 }
1838
1839 #[test]
1840 fn component_hook_order_spawn_despawn_with_macro_hooks() {
1841 let mut world = World::new();
1842 world.init_resource::<R>();
1843
1844 let entity = world.spawn(AMacroHooks).id();
1845 world.despawn(entity);
1846
1847 assert_eq!(4, world.resource::<R>().0);
1848 }
1849
1850 #[test]
1851 fn component_hook_order_insert_remove() {
1852 let mut world = World::new();
1853 world.init_resource::<R>();
1854 world
1855 .register_component_hooks::<A>()
1856 .on_add(|mut world, _| world.resource_mut::<R>().assert_order(0))
1857 .on_insert(|mut world, _| world.resource_mut::<R>().assert_order(1))
1858 .on_replace(|mut world, _| world.resource_mut::<R>().assert_order(2))
1859 .on_remove(|mut world, _| world.resource_mut::<R>().assert_order(3));
1860
1861 let mut entity = world.spawn_empty();
1862 entity.insert(A);
1863 entity.remove::<A>();
1864 entity.flush();
1865 assert_eq!(4, world.resource::<R>().0);
1866 }
1867
1868 #[test]
1869 fn component_hook_order_replace() {
1870 let mut world = World::new();
1871 world
1872 .register_component_hooks::<A>()
1873 .on_replace(|mut world, _| world.resource_mut::<R>().assert_order(0))
1874 .on_insert(|mut world, _| {
1875 if let Some(mut r) = world.get_resource_mut::<R>() {
1876 r.assert_order(1);
1877 }
1878 });
1879
1880 let entity = world.spawn(A).id();
1881 world.init_resource::<R>();
1882 let mut entity = world.entity_mut(entity);
1883 entity.insert(A);
1884 entity.insert_if_new(A); entity.flush();
1886 assert_eq!(2, world.resource::<R>().0);
1887 }
1888
1889 #[test]
1890 fn component_hook_order_recursive() {
1891 let mut world = World::new();
1892 world.init_resource::<R>();
1893 world
1894 .register_component_hooks::<A>()
1895 .on_add(|mut world, context| {
1896 world.resource_mut::<R>().assert_order(0);
1897 world.commands().entity(context.entity).insert(B);
1898 })
1899 .on_remove(|mut world, context| {
1900 world.resource_mut::<R>().assert_order(2);
1901 world.commands().entity(context.entity).remove::<B>();
1902 });
1903
1904 world
1905 .register_component_hooks::<B>()
1906 .on_add(|mut world, context| {
1907 world.resource_mut::<R>().assert_order(1);
1908 world.commands().entity(context.entity).remove::<A>();
1909 })
1910 .on_remove(|mut world, _| {
1911 world.resource_mut::<R>().assert_order(3);
1912 });
1913
1914 let entity = world.spawn(A).flush();
1915 let entity = world.get_entity(entity).unwrap();
1916 assert!(!entity.contains::<A>());
1917 assert!(!entity.contains::<B>());
1918 assert_eq!(4, world.resource::<R>().0);
1919 }
1920
1921 #[test]
1922 fn component_hook_order_recursive_multiple() {
1923 let mut world = World::new();
1924 world.init_resource::<R>();
1925 world
1926 .register_component_hooks::<A>()
1927 .on_add(|mut world, context| {
1928 world.resource_mut::<R>().assert_order(0);
1929 world.commands().entity(context.entity).insert(B).insert(C);
1930 });
1931
1932 world
1933 .register_component_hooks::<B>()
1934 .on_add(|mut world, context| {
1935 world.resource_mut::<R>().assert_order(1);
1936 world.commands().entity(context.entity).insert(D);
1937 });
1938
1939 world
1940 .register_component_hooks::<C>()
1941 .on_add(|mut world, _| {
1942 world.resource_mut::<R>().assert_order(3);
1943 });
1944
1945 world
1946 .register_component_hooks::<D>()
1947 .on_add(|mut world, _| {
1948 world.resource_mut::<R>().assert_order(2);
1949 });
1950
1951 world.spawn(A).flush();
1952 assert_eq!(4, world.resource::<R>().0);
1953 }
1954
1955 #[test]
1956 fn insert_if_new() {
1957 let mut world = World::new();
1958 let id = world.spawn(V("one")).id();
1959 let mut entity = world.entity_mut(id);
1960 entity.insert_if_new(V("two"));
1961 entity.insert_if_new((A, V("three")));
1962 entity.flush();
1963 let entity = world.entity(id);
1965 assert!(entity.contains::<A>());
1966 assert_eq!(entity.get(), Some(&V("one")));
1967 }
1968
1969 #[test]
1970 fn sorted_remove() {
1971 let mut a = vec![1, 2, 3, 4, 5, 6, 7];
1972 let b = vec![1, 2, 3, 5, 7];
1973 super::sorted_remove(&mut a, &b);
1974
1975 assert_eq!(a, vec![4, 6]);
1976
1977 let mut a = vec![1];
1978 let b = vec![1];
1979 super::sorted_remove(&mut a, &b);
1980
1981 assert_eq!(a, vec![]);
1982
1983 let mut a = vec![1];
1984 let b = vec![2];
1985 super::sorted_remove(&mut a, &b);
1986
1987 assert_eq!(a, vec![1]);
1988 }
1989}