Call entity_move before invoke_hook (#124)

This commit is contained in:
Marcus 2024-09-17 16:39:28 +02:00 committed by GitHub
parent 2b1122e073
commit bd187e69ad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 79 additions and 21 deletions

View file

@ -152,10 +152,10 @@ do TITLE "target"
world:set(ent, pair(A, B)) world:set(ent, pair(A, B))
world:set(ent, pair(A, C)) world:set(ent, pair(A, C))
world:set(ent, pair(A, D)) world:set(ent, pair(A, D))
end end
for i = 1, START(N) do for i = 1, START(N) do
world:target(entities[i], A) world:target(entities[i], A, 0)
end end
end) end)
@ -170,7 +170,10 @@ do TITLE(`query {N} entities`)
local function view_bench(n: number) local function view_bench(n: number)
BENCH(`{n} entities per archetype`, function() BENCH(`{n} entities per archetype`, function()
local world = jecs.World.new() local world = jecs.World.new()
local A, B, C, D = world:entity(), world:entity(), world:entity(), world:entity() local A = world:component()
local B = world:component()
local C = world:component()
local D = world:component()
for i = 1, N, n do for i = 1, N, n do
local ct = world:entity() local ct = world:entity()
@ -184,15 +187,48 @@ do TITLE(`query {N} entities`)
end end
end end
START() START()
for id in world:query(A, B, C, D) do for id in world:query(A, B, C, D) do
end end
end)
BENCH(`inlined query`, function()
local world = jecs.World.new()
local A = world:component()
local B = world:component()
local C = world:component()
local D = world:component()
for i = 1, N, n do
local ct = world:entity()
for j = 1, n do
local id = world:entity()
world:set(id, A, true)
world:set(id, B, true)
world:set(id, C, true)
world:set(id, D, true)
world:set(id, ct, true)
end
end
START()
for _, archetype in world:query(A, B, C, D):archetypes() do
local columns, records = archetype.columns, archetype.records
local a = columns[records[A].column]
local b = columns[records[B].column]
local c = columns[records[C].column]
local d = columns[records[D].column]
for row in archetype.entities do
local _1, _2, _3, _4 = a[row], b[row], c[row], d[row]
end
end
end) end)
end end
for i = 13, 0, -1 do for i = 13, 0, -1 do
view_bench(2^i) view_bench(2^i)
end end
end end

View file

@ -728,8 +728,13 @@ local function world_remove(world: World, entity: i53, id: i53)
local to = archetype_traverse_remove(world, id, from) local to = archetype_traverse_remove(world, id, from)
if from and not (from == to) then if from and not (from == to) then
invoke_hook(world, EcsOnRemove, id, entity)
entity_move(entity_index, entity, record, to) entity_move(entity_index, entity, record, to)
local idr = world.componentIndex[id]
local flags = idr.flags
local has_on_remove = bit32.band(flags, ECS_ID_HAS_ON_REMOVE) ~= 0
if has_on_remove then
invoke_hook(world, EcsOnRemove, id, entity)
end
end end
end end
@ -955,7 +960,7 @@ local EMPTY_QUERY = {
setmetatable(EMPTY_QUERY, EMPTY_QUERY) setmetatable(EMPTY_QUERY, EMPTY_QUERY)
local function query_init(query) local function query_iter(query)
local world_query_iter_next local world_query_iter_next
if query.should_drain then if query.should_drain then
@ -1215,12 +1220,8 @@ local function query_init(query)
return world_query_iter_next return world_query_iter_next
end end
local function query_iter(query)
return query_init(query)
end
local function query_drain(query) local function query_drain(query)
local query_iter_next = query_init(query) local query_iter_next = query_iter(query)
query.next = query_iter_next query.next = query_iter_next
query.should_drain = true query.should_drain = true
return query return query

View file

@ -1284,16 +1284,37 @@ TEST("Hooks", function()
end end
do CASE "OnRemove" do CASE "OnRemove"
local world = jecs.World.new() do
local A = world:component() -- basic
local e1 = world:entity() local world = jecs.World.new()
world:add(e1, A) local A = world:component()
world:set(A, jecs.OnRemove, function(entity) local e1 = world:entity()
CHECK(e1 == entity) world:add(e1, A)
CHECK(world:has(e1, A)) world:set(A, jecs.OnRemove, function(entity)
end) CHECK(e1 == entity)
world:remove(e1, A) CHECK(not world:has(e1, A))
CHECK(not world:has(e1, A)) end)
world:remove(e1, A)
CHECK(not world:has(e1, A))
end
do
-- [BUG] https://github.com/Ukendio/jecs/issues/118
local world = world_new()
local A = world:component()
local B = world:component()
local e = world:entity()
world:set(A, jecs.OnRemove, function(entity)
world:set(entity, B, true)
CHECK(not world:get(entity, A))
CHECK(world:get(entity, B))
end)
world:set(e, A, true)
world:remove(e, A)
CHECK(not world:get(e, A))
CHECK(world:get(e, B))
end
end end
do CASE "the filip incident" do CASE "the filip incident"