Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 64 additions & 16 deletions src/jecs.luau
Original file line number Diff line number Diff line change
Expand Up @@ -3497,10 +3497,14 @@ local function world_new(DEBUG: boolean?)
end
if idr_t then
local archetype_ids = idr_t.records
local to_remove = {}:: { [i53]: componentrecord}

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 deleted_any = false
local remove_count = 0

for _, id in idr_t_types do
if not ECS_IS_PAIR(id) then
Expand All @@ -3515,27 +3519,71 @@ 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
for i = #entities, 1, -1 do
local child = entities[i]
world_delete(world, child)
end
deleted_any = true
break
else
local on_remove = id_record.on_remove

local to = archetype_traverse_remove(world, id, idr_t_archetype)
for i = #entities, 1, -1 do
local child = entities[i]
if on_remove then
on_remove(child, id)
end

local r = entity_index_try_get_unsafe(child) :: record
inner_entity_move(child, r, to)
end
to_remove[id] = id_record
remove_count += 1
end
end

if deleted_any then
continue
end

if remove_count == 1 then
local id, id_record = next(to_remove)
local to_u = archetype_traverse_remove(world, id :: i53, idr_t_archetype)
local on_remove = id_record.on_remove
for i = #entities, 1, -1 do
local child = entities[i]
local r = entity_index_try_get_unsafe(child) :: record
local to = to_u
if on_remove then
on_remove(child, id :: i53)
local src = r.archetype
if src ~= idr_t_archetype then
to = archetype_traverse_remove(world, id::i53, src)
end
end

inner_entity_move(child, r, to)
end
elseif remove_count > 1 then
local dst_types = table.clone(idr_t_types)
for id, component_record in to_remove do
table.remove(dst_types, table.find(dst_types, id))
end

local to_u = archetype_ensure(world, dst_types)
for i = #entities, 1, -1 do
local child = entities[i]
local r = entity_index_try_get_unsafe(child) :: record

local to = to_u
for id, component_record in to_remove do
local on_remove = component_record.on_remove
if on_remove then
-- NOTE(marcus): We could be smarter with this and
-- assume hooks are deterministic and that they will
-- move to the same archetype. However users often are not reasonable people.
on_remove(child, id)
local src = r.archetype
if src ~= idr_t_archetype then
to = archetype_traverse_remove(world, id, src)
end
end
end

inner_entity_move(child, r, to)
end
end

table.clear(to_remove)
archetype_destroy(world, idr_t_archetype)
end
end
Expand Down