mirror of
https://github.com/Ukendio/jecs.git
synced 2025-07-20 04:59:16 +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 to: Archetype
|
||||||
local idr: ComponentRecord
|
local idr: ComponentRecord
|
||||||
if ECS_IS_PAIR(id::number) then
|
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]
|
local edge = archetype_edges[src.id]
|
||||||
to = edge[id]
|
to = edge[id]
|
||||||
if not to then
|
if to == nil then
|
||||||
local first = ECS_PAIR_FIRST(id::number)
|
if idr and (bit32.btest(idr.flags) == true) then
|
||||||
local wc = ECS_PAIR(first, EcsWildcard)
|
local cr = idr.records[src.id]
|
||||||
idr = component_index[wc]
|
if cr then
|
||||||
if idr and bit32.btest(idr.flags, ECS_ID_IS_EXCLUSIVE) 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]
|
local cr = idr.records[src.id]
|
||||||
if cr then
|
if cr then
|
||||||
local on_remove = idr.on_remove
|
local on_remove = idr.on_remove
|
||||||
|
@ -2340,18 +2371,11 @@ local function world_new()
|
||||||
local dst = table.clone(id_types)
|
local dst = table.clone(id_types)
|
||||||
dst[cr] = id
|
dst[cr] = id
|
||||||
to = archetype_ensure(world, dst)
|
to = archetype_ensure(world, dst)
|
||||||
else
|
|
||||||
to = find_archetype_with(world, id, src)
|
|
||||||
idr = component_index[id]
|
|
||||||
end
|
end
|
||||||
else
|
|
||||||
to = find_archetype_with(world, id, src)
|
|
||||||
idr = component_index[id]
|
|
||||||
end
|
end
|
||||||
edge[id] = to
|
if not to then
|
||||||
archetype_edges[to.id][id] = src
|
to = find_archetype_with(world, id, src)
|
||||||
else
|
end
|
||||||
idr = component_index[id]
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local edges = archetype_edges
|
local edges = archetype_edges
|
||||||
|
@ -2401,14 +2425,46 @@ local function world_new()
|
||||||
end
|
end
|
||||||
local to: Archetype
|
local to: Archetype
|
||||||
local idr: ComponentRecord
|
local idr: ComponentRecord
|
||||||
|
|
||||||
if ECS_IS_PAIR(id::number) then
|
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]
|
local edge = archetype_edges[src.id]
|
||||||
to = edge[id]
|
to = edge[id]
|
||||||
if not to then
|
if to == nil then
|
||||||
local first = ECS_PAIR_FIRST(id::number)
|
if idr and (bit32.btest(idr.flags) == true) then
|
||||||
local wc = ECS_PAIR(first, EcsWildcard)
|
local cr = idr.records[src.id]
|
||||||
idr = component_index[wc]
|
if cr then
|
||||||
if idr and bit32.btest(idr.flags, ECS_ID_IS_EXCLUSIVE) 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]
|
local cr = idr.records[src.id]
|
||||||
if cr then
|
if cr then
|
||||||
local on_remove = idr.on_remove
|
local on_remove = idr.on_remove
|
||||||
|
@ -2422,18 +2478,11 @@ local function world_new()
|
||||||
local dst = table.clone(id_types)
|
local dst = table.clone(id_types)
|
||||||
dst[cr] = id
|
dst[cr] = id
|
||||||
to = archetype_ensure(world, dst)
|
to = archetype_ensure(world, dst)
|
||||||
else
|
|
||||||
to = find_archetype_with(world, id, src)
|
|
||||||
idr = component_index[id]
|
|
||||||
end
|
end
|
||||||
else
|
|
||||||
to = find_archetype_with(world, id, src)
|
|
||||||
idr = component_index[id]
|
|
||||||
end
|
end
|
||||||
edge[id] = to
|
if not to then
|
||||||
archetype_edges[to.id][id] = src
|
to = find_archetype_with(world, id, src)
|
||||||
else
|
end
|
||||||
idr = component_index[id]
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local edges = archetype_edges
|
local edges = archetype_edges
|
||||||
|
|
|
@ -346,23 +346,12 @@ TEST("world:add()", function()
|
||||||
world:add(A, jecs.Exclusive)
|
world:add(A, jecs.Exclusive)
|
||||||
local on_remove_call = false
|
local on_remove_call = false
|
||||||
world:set(A, jecs.OnRemove, function(e, id)
|
world:set(A, jecs.OnRemove, function(e, id)
|
||||||
CHECK(e == e_ptr)
|
|
||||||
CHECK(id == jecs.pair(A, B))
|
|
||||||
on_remove_call = true
|
on_remove_call = true
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local on_add_call_count = 0
|
local on_add_call_count = 0
|
||||||
world:set(A, jecs.OnAdd, function(e, id)
|
world:set(A, jecs.OnAdd, function(e, id)
|
||||||
on_add_call_count += 1
|
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)
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
@ -377,6 +366,17 @@ TEST("world:add()", function()
|
||||||
CHECK(world:has(e, pair(A, B)) == false)
|
CHECK(world:has(e, pair(A, B)) == false)
|
||||||
CHECK(world:has(e, pair(A, C)) == true)
|
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
|
end
|
||||||
|
|
||||||
do CASE "idempotent"
|
do CASE "idempotent"
|
||||||
|
|
Loading…
Reference in a new issue