Hotfix archetype not being marked dead

This commit is contained in:
Ukendio 2025-07-10 12:50:59 +02:00
parent ad5ed3b5ea
commit aa178981dc
2 changed files with 72 additions and 5 deletions

View file

@ -781,6 +781,7 @@ local function archetype_register(world: World, archetype: Archetype)
local archetype_id = archetype.id local archetype_id = archetype.id
local columns_map = archetype.columns_map local columns_map = archetype.columns_map
local columns = archetype.columns local columns = archetype.columns
for i, component_id in archetype.types do for i, component_id in archetype.types do
local idr = id_record_ensure(world, component_id) local idr = id_record_ensure(world, component_id)
local is_tag = bit32.btest(idr.flags, ECS_ID_IS_TAG) local is_tag = bit32.btest(idr.flags, ECS_ID_IS_TAG)
@ -803,6 +804,10 @@ local function archetype_register(world: World, archetype: Archetype)
archetype_append_to_records(idr_t, archetype_id, columns_map, t, i, column) archetype_append_to_records(idr_t, archetype_id, columns_map, t, i, column)
end end
end end
world.archetype_index[archetype.type] = archetype
world.archetypes[archetype_id] = archetype
world.archetype_edges[archetype.id] = {} :: Map<Id, Archetype>
end end
local function archetype_create(world: World, id_types: { Id }, ty, prev: i53?): Archetype local function archetype_create(world: World, id_types: { Id }, ty, prev: i53?): Archetype
@ -824,7 +829,7 @@ local function archetype_create(world: World, id_types: { Id }, ty, prev: i53?):
dead = false, dead = false,
} }
archetype_register(world, archetype) archetype_register(world, archetype, false)
for id in columns_map do for id in columns_map do
local observer_list = find_observers(world, EcsOnArchetypeCreate, id) local observer_list = find_observers(world, EcsOnArchetypeCreate, id)
@ -838,9 +843,6 @@ local function archetype_create(world: World, id_types: { Id }, ty, prev: i53?):
end end
end end
world.archetype_index[ty] = archetype
world.archetypes[archetype_id] = archetype
world.archetype_edges[archetype.id] = {} :: Map<Id, Archetype>
return archetype return archetype
end end
@ -1078,6 +1080,8 @@ local function archetype_destroy(world: World, archetype: Archetype)
end end
end end
end end
archetype.dead = true
end end
local function NOOP() end local function NOOP() end
@ -2324,6 +2328,10 @@ local function world_new()
end end
edge[id] = to edge[id] = to
else else
if to.dead then
archetype_register(world, to)
to.dead = false
end
idr = component_index[id] idr = component_index[id]
end end
if from == to then if from == to then
@ -2342,6 +2350,7 @@ local function world_new()
if on_add then if on_add then
on_add(entity, id) on_add(entity, id)
end end
return return
end end
local to = archetype_traverse_add(world, id, from) local to = archetype_traverse_add(world, id, from)

View file

@ -24,6 +24,44 @@ type Id<T=unknown> = jecs.Id<T>
local entity_visualiser = require("@tools/entity_visualiser") local entity_visualiser = require("@tools/entity_visualiser")
local dwi = entity_visualiser.stringify local dwi = entity_visualiser.stringify
FOCUS()
TEST("", function()
local world = jecs.world()
local data = world:component()
local relation = world:component()
world:add(relation, jecs.pair(jecs.OnDeleteTarget, jecs.Delete))
local e1 = world:entity()
local e2 = world:entity()
world:set(e2, data, 456)
world:add(e2, jecs.pair(relation, e1))
world:delete(e1)
local e1v1 = world:entity()
CHECK(ECS_ID(e1v1) == e1)
local e2v1 = world:entity()
CHECK(ECS_ID(e2v1) == e2)
world:set(e2v1, data, 456)
CHECK(world:contains(e1v1))
CHECK(not world:contains(e2))
CHECK(world:contains(e2v1))
local count = 0
for i,val in world:query(data):iter() do
count += 1
end
CHECK(count == 1)
count = 0
world:add(e2v1, jecs.pair(relation, e1v1))
CHECK(world:has(e2v1, jecs.pair(relation, e1v1)))
for i,val in world:query(data):iter() do
count += 1
end
CHECK(count==1)
end)
TEST("bulk", function() TEST("bulk", function()
local world = jecs.world() local world = jecs.world()
local A = world:component() local A = world:component()
@ -885,7 +923,6 @@ TEST("world:each()", function()
end end
end) end)
FOCUS()
TEST("world:range()", function() TEST("world:range()", function()
do CASE "spawn entity under min range" do CASE "spawn entity under min range"
@ -1122,6 +1159,7 @@ end)
TEST("world:query()", function() TEST("world:query()", function()
local N = 2^8 local N = 2^8
do CASE "cached" do CASE "cached"
local world = jecs.world() local world = jecs.world()
local Foo = world:component() local Foo = world:component()
@ -1158,6 +1196,26 @@ TEST("world:query()", function()
world:delete(Foo) world:delete(Foo)
CHECK(#q:archetypes() == 0) CHECK(#q:archetypes() == 0)
end end
do CASE "3 components"
local world = jecs.world()
local A = world:component() :: jecs.Entity<boolean>
local B = world:component() :: jecs.Entity<boolean>
local C = world:component() :: jecs.Entity<boolean>
local e = world:entity()
world:set(e, A, true)
world:set(e, B, true)
world:set(e, C, true)
local q = world:query(A, B, C):cached()
local counter = 0
for x, a, b, c in q:iter() do
counter += 1
CHECK(a)
CHECK(b)
CHECK(c)
end
CHECK(counter == 1)
end
do CASE "multiple iter" do CASE "multiple iter"
local world = jecs.world() local world = jecs.world()
local A = world:component() :: jecs.Entity<string> local A = world:component() :: jecs.Entity<string>