mirror of
https://github.com/Ukendio/jecs.git
synced 2025-07-19 20:49:17 +00:00
Fix on_remove hook not called on cached edge
This commit is contained in:
parent
d99088ea1e
commit
117a5e0ca7
2 changed files with 90 additions and 41 deletions
109
jecs.luau
109
jecs.luau
|
@ -2320,13 +2320,44 @@ local function world_new()
|
|||
local to: Archetype
|
||||
local idr: ComponentRecord
|
||||
if ECS_IS_PAIR(id::number) then
|
||||
local first = ECS_PAIR_FIRST(id::number)
|
||||
local wc = ECS_PAIR(first, EcsWildcard)
|
||||
idr = component_index[wc]
|
||||
|
||||
local edge = archetype_edges[src.id]
|
||||
to = edge[id]
|
||||
if not to then
|
||||
local first = ECS_PAIR_FIRST(id::number)
|
||||
local wc = ECS_PAIR(first, EcsWildcard)
|
||||
idr = component_index[wc]
|
||||
if idr and bit32.btest(idr.flags, ECS_ID_IS_EXCLUSIVE) then
|
||||
if to == nil then
|
||||
if idr and (bit32.btest(idr.flags) == true) then
|
||||
local cr = idr.records[src.id]
|
||||
if cr then
|
||||
local on_remove = idr.on_remove
|
||||
local id_types = src.types
|
||||
if on_remove then
|
||||
on_remove(entity, id_types[cr])
|
||||
|
||||
src = record.archetype
|
||||
id_types = src.types
|
||||
cr = idr.records[src.id]
|
||||
end
|
||||
|
||||
local dst = table.clone(id_types)
|
||||
dst[cr] = id
|
||||
to = archetype_ensure(world, dst)
|
||||
end
|
||||
end
|
||||
|
||||
if not to then
|
||||
to = find_archetype_with(world, id, src)
|
||||
end
|
||||
|
||||
if not idr then
|
||||
idr = component_index[wc]
|
||||
end
|
||||
|
||||
edge[id] = to
|
||||
archetype_edges[(to :: Archetype).id][id] = src
|
||||
else
|
||||
if bit32.btest(idr.flags, ECS_ID_IS_EXCLUSIVE) then
|
||||
local cr = idr.records[src.id]
|
||||
if cr then
|
||||
local on_remove = idr.on_remove
|
||||
|
@ -2340,18 +2371,11 @@ local function world_new()
|
|||
local dst = table.clone(id_types)
|
||||
dst[cr] = id
|
||||
to = archetype_ensure(world, dst)
|
||||
else
|
||||
to = find_archetype_with(world, id, src)
|
||||
idr = component_index[id]
|
||||
end
|
||||
else
|
||||
to = find_archetype_with(world, id, src)
|
||||
idr = component_index[id]
|
||||
end
|
||||
edge[id] = to
|
||||
archetype_edges[to.id][id] = src
|
||||
else
|
||||
idr = component_index[id]
|
||||
if not to then
|
||||
to = find_archetype_with(world, id, src)
|
||||
end
|
||||
end
|
||||
else
|
||||
local edges = archetype_edges
|
||||
|
@ -2401,14 +2425,46 @@ local function world_new()
|
|||
end
|
||||
local to: Archetype
|
||||
local idr: ComponentRecord
|
||||
|
||||
if ECS_IS_PAIR(id::number) then
|
||||
local first = ECS_PAIR_FIRST(id::number)
|
||||
local wc = ECS_PAIR(first, EcsWildcard)
|
||||
idr = component_index[wc]
|
||||
|
||||
local edge = archetype_edges[src.id]
|
||||
to = edge[id]
|
||||
if not to then
|
||||
local first = ECS_PAIR_FIRST(id::number)
|
||||
local wc = ECS_PAIR(first, EcsWildcard)
|
||||
idr = component_index[wc]
|
||||
if idr and bit32.btest(idr.flags, ECS_ID_IS_EXCLUSIVE) then
|
||||
if to == nil then
|
||||
if idr and (bit32.btest(idr.flags) == true) then
|
||||
local cr = idr.records[src.id]
|
||||
if cr then
|
||||
local on_remove = idr.on_remove
|
||||
local id_types = src.types
|
||||
if on_remove then
|
||||
on_remove(entity, id_types[cr])
|
||||
|
||||
src = record.archetype
|
||||
id_types = src.types
|
||||
cr = idr.records[src.id]
|
||||
end
|
||||
|
||||
local dst = table.clone(id_types)
|
||||
dst[cr] = id
|
||||
to = archetype_ensure(world, dst)
|
||||
end
|
||||
end
|
||||
|
||||
if not to then
|
||||
to = find_archetype_with(world, id, src)
|
||||
end
|
||||
|
||||
if not idr then
|
||||
idr = component_index[wc]
|
||||
end
|
||||
|
||||
edge[id] = to
|
||||
archetype_edges[(to :: Archetype).id][id] = src
|
||||
else
|
||||
if bit32.btest(idr.flags, ECS_ID_IS_EXCLUSIVE) then
|
||||
local cr = idr.records[src.id]
|
||||
if cr then
|
||||
local on_remove = idr.on_remove
|
||||
|
@ -2422,18 +2478,11 @@ local function world_new()
|
|||
local dst = table.clone(id_types)
|
||||
dst[cr] = id
|
||||
to = archetype_ensure(world, dst)
|
||||
else
|
||||
to = find_archetype_with(world, id, src)
|
||||
idr = component_index[id]
|
||||
end
|
||||
else
|
||||
to = find_archetype_with(world, id, src)
|
||||
idr = component_index[id]
|
||||
end
|
||||
edge[id] = to
|
||||
archetype_edges[to.id][id] = src
|
||||
else
|
||||
idr = component_index[id]
|
||||
if not to then
|
||||
to = find_archetype_with(world, id, src)
|
||||
end
|
||||
end
|
||||
else
|
||||
local edges = archetype_edges
|
||||
|
|
|
@ -346,23 +346,12 @@ TEST("world:add()", function()
|
|||
world:add(A, jecs.Exclusive)
|
||||
local on_remove_call = false
|
||||
world:set(A, jecs.OnRemove, function(e, id)
|
||||
CHECK(e == e_ptr)
|
||||
CHECK(id == jecs.pair(A, B))
|
||||
on_remove_call = true
|
||||
end)
|
||||
|
||||
local on_add_call_count = 0
|
||||
world:set(A, jecs.OnAdd, function(e, id)
|
||||
on_add_call_count += 1
|
||||
if on_add_call_count == 1 then
|
||||
CHECK(e == e_ptr)
|
||||
CHECK(id == jecs.pair(A, B))
|
||||
elseif on_add_call_count == 2 then
|
||||
CHECK(e == e_ptr)
|
||||
CHECK(id == jecs.pair(A, C))
|
||||
else
|
||||
CHECK(false)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
@ -377,6 +366,17 @@ TEST("world:add()", function()
|
|||
CHECK(world:has(e, pair(A, B)) == false)
|
||||
CHECK(world:has(e, pair(A, C)) == true)
|
||||
|
||||
-- We have to ensure that it actually invokes hooks everytime it
|
||||
-- traverses the archetype
|
||||
e = world:entity()
|
||||
world:add(e, pair(A, B))
|
||||
CHECK(on_add_call_count == 3)
|
||||
world:add(e, pair(A, C))
|
||||
CHECK(on_add_call_count == 4)
|
||||
CHECK(on_remove_call)
|
||||
|
||||
CHECK(world:has(e, pair(A, B)) == false)
|
||||
CHECK(world:has(e, pair(A, C)) == true)
|
||||
end
|
||||
|
||||
do CASE "idempotent"
|
||||
|
|
Loading…
Reference in a new issue