diff --git a/src/jecs.luau b/src/jecs.luau index 3cae329..fa2a076 100755 --- a/src/jecs.luau +++ b/src/jecs.luau @@ -3497,10 +3497,14 @@ local function world_new(DEBUG: boolean?) end if idr_t then local archetype_ids = idr_t.records + local to_remove = {} + for archetype_id in archetype_ids do local idr_t_archetype = archetypes[archetype_id] local idr_t_types = idr_t_archetype.types local entities = idr_t_archetype.entities + local should_delete = false + local remove_count = 0 for _, id in idr_t_types do if not ECS_IS_PAIR(id) then @@ -3515,27 +3519,56 @@ local function world_new(DEBUG: boolean?) local flags = id_record.flags local flags_delete_mask = bit32.btest(flags, ECS_ID_DELETE) if flags_delete_mask then - for i = #entities, 1, -1 do - local child = entities[i] - world_delete(world, child) - end + should_delete = true break else - local on_remove = id_record.on_remove + to_remove[id] = id_record + remove_count += 1 + end + end - local to = archetype_traverse_remove(world, id, idr_t_archetype) - for i = #entities, 1, -1 do + if should_delete then + for i = #entities, 1, -1 do + local child = entities[i] + world_delete(world, child) + end + else + if remove_count == 1 then + local id, id_record = next(to_remove) + local to = archetype_traverse_remove(world, id :: i53, idr_t_archetype) + local on_remove = (id_record :: componentrecord).on_remove + for i = #entities, 1, -1 do local child = entities[i] if on_remove then - on_remove(child, id) + on_remove(child, id :: i53) end local r = entity_index_try_get_unsafe(child) :: record inner_entity_move(child, r, to) end - end - end + elseif remove_count > 1 then + local dst_types = table.clone(idr_t_types) + for id, record in to_remove do + table.remove(dst_types, table.find(dst_types, id)) + local on_remove = record.on_remove + if on_remove then + for _, child in entities do + on_remove(child, id :: i53) + end + end + end + + local to = archetype_ensure(world, dst_types) + for i = #entities, 1, -1 do + local child = entities[i] + local r = entity_index_try_get_unsafe(child) :: record + inner_entity_move(child, r, to) + end + end + end + + table.clear(to_remove) archetype_destroy(world, idr_t_archetype) end end