mirror of
https://github.com/Ukendio/jecs.git
synced 2025-04-24 17:10:03 +00:00
Archetype deletion (#126)
* initial commit * cleanup edges * rename ptr to edge
This commit is contained in:
parent
ca00d4c0c1
commit
2ed869ba93
3 changed files with 300 additions and 105 deletions
389
src/init.luau
389
src/init.luau
|
@ -11,16 +11,30 @@ type ArchetypeId = number
|
||||||
|
|
||||||
type Column = { any }
|
type Column = { any }
|
||||||
|
|
||||||
type ArchetypeEdge = {
|
type Map<K, V> = {[K]: V}
|
||||||
add: Archetype,
|
|
||||||
remove: Archetype,
|
type GraphEdge = {
|
||||||
|
from: Archetype,
|
||||||
|
to: Archetype?,
|
||||||
|
prev: GraphEdge?,
|
||||||
|
next: GraphEdge?,
|
||||||
|
id: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type GraphEdges = Map<i53, GraphEdge>
|
||||||
|
|
||||||
|
type GraphNode = {
|
||||||
|
add: GraphEdges,
|
||||||
|
remove: GraphEdges,
|
||||||
|
add_ref: GraphEdge?,
|
||||||
|
remove_ref: GraphEdge?
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Archetype = {
|
export type Archetype = {
|
||||||
id: number,
|
id: number,
|
||||||
edges: { [i53]: ArchetypeEdge },
|
node: GraphNode,
|
||||||
types: Ty,
|
types: Ty,
|
||||||
type: string | number,
|
type: string,
|
||||||
entities: { number },
|
entities: { number },
|
||||||
columns: { Column },
|
columns: { Column },
|
||||||
records: { ArchetypeRecord },
|
records: { ArchetypeRecord },
|
||||||
|
@ -28,27 +42,26 @@ export type Archetype = {
|
||||||
type Record = {
|
type Record = {
|
||||||
archetype: Archetype,
|
archetype: Archetype,
|
||||||
row: number,
|
row: number,
|
||||||
dense: i24,
|
dense: i24
|
||||||
componentRecord: ArchetypeMap,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type EntityIndex = { dense: { [i24]: i53 }, sparse: { [i53]: Record } }
|
type EntityIndex = {
|
||||||
|
dense: Map<i24, i53>,
|
||||||
|
sparse: Map<i53, Record>
|
||||||
|
}
|
||||||
|
|
||||||
type ArchetypeRecord = {
|
type ArchetypeRecord = {
|
||||||
count: number,
|
count: number,
|
||||||
column: number,
|
column: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
type ArchetypeMap = {
|
type IdRecord = {
|
||||||
cache: { ArchetypeRecord },
|
cache: { ArchetypeRecord },
|
||||||
flags: number,
|
flags: number,
|
||||||
first: ArchetypeMap,
|
|
||||||
second: ArchetypeMap,
|
|
||||||
parent: ArchetypeMap,
|
|
||||||
size: number,
|
size: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
type ComponentIndex = { [i24]: ArchetypeMap }
|
type ComponentIndex = Map<i53, IdRecord>
|
||||||
|
|
||||||
type Archetypes = { [ArchetypeId]: Archetype }
|
type Archetypes = { [ArchetypeId]: Archetype }
|
||||||
|
|
||||||
|
@ -420,7 +433,7 @@ local function ECS_ID_IS_WILDCARD(e: i53): boolean
|
||||||
return first == EcsWildcard or second == EcsWildcard
|
return first == EcsWildcard or second == EcsWildcard
|
||||||
end
|
end
|
||||||
|
|
||||||
local function id_record_ensure(world: World, id: number): ArchetypeMap
|
local function id_record_ensure(world: World, id: number): IdRecord
|
||||||
local componentIndex = world.componentIndex
|
local componentIndex = world.componentIndex
|
||||||
local idr = componentIndex[id]
|
local idr = componentIndex[id]
|
||||||
|
|
||||||
|
@ -453,14 +466,20 @@ local function id_record_ensure(world: World, id: number): ArchetypeMap
|
||||||
size = 0,
|
size = 0,
|
||||||
cache = {},
|
cache = {},
|
||||||
flags = flags,
|
flags = flags,
|
||||||
} :: ArchetypeMap
|
} :: IdRecord
|
||||||
componentIndex[id] = idr
|
componentIndex[id] = idr
|
||||||
end
|
end
|
||||||
|
|
||||||
return idr
|
return idr
|
||||||
end
|
end
|
||||||
|
|
||||||
local function archetype_append_to_records(idr: ArchetypeMap, archetype_id, records, id, index)
|
local function archetype_append_to_records(
|
||||||
|
idr: IdRecord,
|
||||||
|
archetype_id: number,
|
||||||
|
records: Map<i53, ArchetypeRecord>,
|
||||||
|
id: number,
|
||||||
|
index: number
|
||||||
|
)
|
||||||
local tr = idr.cache[archetype_id]
|
local tr = idr.cache[archetype_id]
|
||||||
if not tr then
|
if not tr then
|
||||||
tr = { column = index, count = 1}
|
tr = { column = index, count = 1}
|
||||||
|
@ -472,7 +491,7 @@ local function archetype_append_to_records(idr: ArchetypeMap, archetype_id, reco
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function archetype_create(world: World, types: { i24 }, prev: Archetype?): Archetype
|
local function archetype_create(world: World, types: { i24 }, prev: i53?): Archetype
|
||||||
local ty = hash(types)
|
local ty = hash(types)
|
||||||
|
|
||||||
local archetype_id = (world.nextArchetypeId :: number) + 1
|
local archetype_id = (world.nextArchetypeId :: number) + 1
|
||||||
|
@ -507,7 +526,7 @@ local function archetype_create(world: World, types: { i24 }, prev: Archetype?):
|
||||||
|
|
||||||
local archetype: Archetype = {
|
local archetype: Archetype = {
|
||||||
columns = columns,
|
columns = columns,
|
||||||
edges = {},
|
node = { add = {}, remove = {} },
|
||||||
entities = {},
|
entities = {},
|
||||||
id = archetype_id,
|
id = archetype_id,
|
||||||
records = records,
|
records = records,
|
||||||
|
@ -531,7 +550,7 @@ local function world_parent(world: World, entity: i53)
|
||||||
return world_target(world, entity, EcsChildOf, 0)
|
return world_target(world, entity, EcsChildOf, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function archetype_ensure(world: World, types, prev): Archetype
|
local function archetype_ensure(world: World, types): Archetype
|
||||||
if #types < 1 then
|
if #types < 1 then
|
||||||
return world.ROOT_ARCHETYPE
|
return world.ROOT_ARCHETYPE
|
||||||
end
|
end
|
||||||
|
@ -542,7 +561,7 @@ local function archetype_ensure(world: World, types, prev): Archetype
|
||||||
return archetype
|
return archetype
|
||||||
end
|
end
|
||||||
|
|
||||||
return archetype_create(world, types, prev)
|
return archetype_create(world, types)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function find_insert(types: { i53 }, toAdd: i53): number
|
local function find_insert(types: { i53 }, toAdd: i53): number
|
||||||
|
@ -572,32 +591,125 @@ local function find_archetype_with(world: World, node: Archetype, id: i53): Arch
|
||||||
end
|
end
|
||||||
table.insert(dst, at, id)
|
table.insert(dst, at, id)
|
||||||
|
|
||||||
return archetype_ensure(world, dst, node)
|
return archetype_ensure(world, dst)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function edge_ensure(archetype: Archetype, id: i53): ArchetypeEdge
|
local function find_archetype_without(world: World, node: Archetype, id: i53): Archetype
|
||||||
local edges = archetype.edges
|
local types = node.types
|
||||||
local edge = edges[id]
|
local at = table.find(types, id)
|
||||||
if not edge then
|
if at == nil then
|
||||||
edge = {} :: any
|
return node
|
||||||
edges[id] = edge
|
|
||||||
end
|
end
|
||||||
return edge
|
|
||||||
|
local dst = table.clone(types)
|
||||||
|
table.remove(dst, at)
|
||||||
|
|
||||||
|
return archetype_ensure(world, dst)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function archetype_traverse_add(world: World, id: i53, from: Archetype): Archetype
|
local function archetype_init_edge(archetype: Archetype,
|
||||||
from = from or world.ROOT_ARCHETYPE
|
edge: GraphEdge, id: i53, to: Archetype)
|
||||||
|
edge.from = archetype
|
||||||
|
edge.to = to
|
||||||
|
edge.id = id
|
||||||
|
end
|
||||||
|
|
||||||
local edge = edge_ensure(from, id)
|
local function archetype_ensure_edge(world, edges, id): GraphEdge
|
||||||
local add = edge.add
|
local edge = edges[id]
|
||||||
if not add then
|
if not edge then
|
||||||
-- Save an edge using the component ID to the archetype to allow
|
edge = {
|
||||||
-- faster traversals to adjacent archetypes.
|
from = nil :: any,
|
||||||
add = find_archetype_with(world, from, id)
|
to = nil :: any,
|
||||||
edge.add = add :: never
|
id = id,
|
||||||
end
|
prev = nil,
|
||||||
|
next = nil,
|
||||||
|
} :: GraphEdge
|
||||||
|
edges[id] = edge
|
||||||
|
end
|
||||||
|
|
||||||
return add
|
return edge
|
||||||
|
end
|
||||||
|
|
||||||
|
local function init_edge_for_add(world, archetype, edge, id, to)
|
||||||
|
archetype_init_edge(archetype, edge, id, to)
|
||||||
|
archetype_ensure_edge(world, archetype.node.add, id)
|
||||||
|
if archetype ~= to then
|
||||||
|
local to_add_ref = to.node.add_ref
|
||||||
|
edge.next = to_add_ref
|
||||||
|
edge.prev = nil
|
||||||
|
if to_add_ref then
|
||||||
|
to_add_ref.prev = edge
|
||||||
|
end
|
||||||
|
to.node.add_ref = edge
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function init_edge_for_remove(world, archetype, edge, id, to)
|
||||||
|
archetype_init_edge(archetype, edge, id, to)
|
||||||
|
archetype_ensure_edge(world, archetype.node.remove, id)
|
||||||
|
if archetype ~= to then
|
||||||
|
local to_remove_ref = to.node.remove_ref
|
||||||
|
local prev
|
||||||
|
if to_remove_ref then
|
||||||
|
prev = to_remove_ref.prev
|
||||||
|
to_remove_ref.prev = edge
|
||||||
|
edge.next = to_remove_ref
|
||||||
|
else
|
||||||
|
to.node.remove_ref = edge
|
||||||
|
edge.next = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
edge.prev = prev
|
||||||
|
if prev then
|
||||||
|
prev.next = edge
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function create_edge_for_add(world: World, node: Archetype,
|
||||||
|
edge: GraphEdge, id: i53): Archetype
|
||||||
|
|
||||||
|
local to = find_archetype_with(world, node, id)
|
||||||
|
init_edge_for_add(world, node, edge, id, to)
|
||||||
|
return to
|
||||||
|
end
|
||||||
|
|
||||||
|
local function create_edge_for_remove(world: World, node: Archetype,
|
||||||
|
edge: GraphEdge, id: i53): Archetype
|
||||||
|
|
||||||
|
local to = find_archetype_without(world, node, id)
|
||||||
|
init_edge_for_remove(world, node, edge, id, to)
|
||||||
|
return to
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function archetype_traverse_add(world: World, id: i53,
|
||||||
|
from: Archetype): Archetype
|
||||||
|
|
||||||
|
from = from or world.ROOT_ARCHETYPE
|
||||||
|
local edge = archetype_ensure_edge(
|
||||||
|
world, from.node.add, id)
|
||||||
|
|
||||||
|
local to = edge.to
|
||||||
|
if not to then
|
||||||
|
to = create_edge_for_add(world, from, edge, id)
|
||||||
|
end
|
||||||
|
|
||||||
|
return to :: Archetype
|
||||||
|
end
|
||||||
|
|
||||||
|
local function archetype_traverse_remove(world: World, id: i53, from: Archetype): Archetype
|
||||||
|
from = from or world.ROOT_ARCHETYPE
|
||||||
|
|
||||||
|
local edge = archetype_ensure_edge(
|
||||||
|
world, from.node.add, id)
|
||||||
|
|
||||||
|
local to = edge.to
|
||||||
|
if not to then
|
||||||
|
to = create_edge_for_remove(world, from, edge, id)
|
||||||
|
end
|
||||||
|
|
||||||
|
return to :: Archetype
|
||||||
end
|
end
|
||||||
|
|
||||||
local function invoke_hook(world: World, hook_id: number, id: i53, entity: i53, data: any?)
|
local function invoke_hook(world: World, hook_id: number, id: i53, entity: i53, data: any?)
|
||||||
|
@ -700,24 +812,6 @@ local function world_component(world: World): i53
|
||||||
return id
|
return id
|
||||||
end
|
end
|
||||||
|
|
||||||
local function archetype_traverse_remove(world: World, id: i53, from: Archetype): Archetype
|
|
||||||
local edge = edge_ensure(from, id)
|
|
||||||
|
|
||||||
local remove = edge.remove
|
|
||||||
if not remove then
|
|
||||||
local to = table.clone(from.types) :: { i53 }
|
|
||||||
local at = table.find(to, id)
|
|
||||||
if not at then
|
|
||||||
return from
|
|
||||||
end
|
|
||||||
table.remove(to, at)
|
|
||||||
remove = archetype_ensure(world, to, from)
|
|
||||||
edge.remove = remove :: any
|
|
||||||
end
|
|
||||||
|
|
||||||
return remove
|
|
||||||
end
|
|
||||||
|
|
||||||
local function world_remove(world: World, entity: i53, id: i53)
|
local function world_remove(world: World, entity: i53, id: i53)
|
||||||
local entity_index = world.entityIndex
|
local entity_index = world.entityIndex
|
||||||
local record = entity_index.sparse[entity]
|
local record = entity_index.sparse[entity]
|
||||||
|
@ -755,30 +849,118 @@ local function world_clear(world: World, entity: i53)
|
||||||
entity_move(world.entityIndex, entity, record, ROOT_ARCHETYPE)
|
entity_move(world.entityIndex, entity, record, ROOT_ARCHETYPE)
|
||||||
end
|
end
|
||||||
|
|
||||||
local world_delete: (world: World, entity: i53) -> ()
|
local function archetype_fast_delete_last(columns: { Column },
|
||||||
|
column_count: number, types: { i53 }, entity: i53)
|
||||||
|
|
||||||
|
for i, column in columns do
|
||||||
|
if column ~= NULL_ARRAY then
|
||||||
|
column[column_count] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function archetype_fast_delete(columns: { Column },
|
||||||
|
column_count: number, row, types, entity)
|
||||||
|
|
||||||
|
for i, column in columns do
|
||||||
|
if column ~= NULL_ARRAY then
|
||||||
|
column[row] = column[column_count]
|
||||||
|
column[column_count] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function archetype_disconnect_edge(edge: GraphEdge)
|
||||||
|
local edge_next = edge.next
|
||||||
|
local edge_prev = edge.prev
|
||||||
|
if edge_next then
|
||||||
|
edge_next.prev = edge_prev
|
||||||
|
end
|
||||||
|
if edge_prev then
|
||||||
|
edge_prev.next = edge_next
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function archetype_remove_edge(edges: Map<i53, GraphEdge>,
|
||||||
|
id: i53, edge: GraphEdge)
|
||||||
|
|
||||||
|
archetype_disconnect_edge(edge)
|
||||||
|
edges[id] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function archetype_clear_edges(archetype: Archetype)
|
||||||
|
local node = archetype.node
|
||||||
|
local add = node.add
|
||||||
|
local remove = node.remove
|
||||||
|
for _, edge in add do
|
||||||
|
archetype_disconnect_edge(edge)
|
||||||
|
end
|
||||||
|
for _, edge in remove do
|
||||||
|
archetype_disconnect_edge(edge)
|
||||||
|
end
|
||||||
|
local node_add_ref = node.add_ref
|
||||||
|
if node_add_ref then
|
||||||
|
local current = node_add_ref.next
|
||||||
|
while current do
|
||||||
|
local edge = current
|
||||||
|
current = current.next
|
||||||
|
local node_add = edge.from.node.add
|
||||||
|
if node_add then
|
||||||
|
archetype_remove_edge(node_add, edge.id, edge)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local node_remove_ref = node.remove_ref
|
||||||
|
if node_remove_ref then
|
||||||
|
local current = node_remove_ref.prev
|
||||||
|
while current do
|
||||||
|
local edge = current
|
||||||
|
current = current.prev
|
||||||
|
local node_remove = edge.from.node.remove
|
||||||
|
if node_remove then
|
||||||
|
archetype_remove_edge(node_remove, edge.id, edge)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
node.add = nil :: any
|
||||||
|
node.remove = nil :: any
|
||||||
|
node.add_ref = nil :: any
|
||||||
|
node.remove_ref = nil :: any
|
||||||
|
end
|
||||||
|
|
||||||
|
local function archetype_destroy(world: World, archetype: Archetype)
|
||||||
|
local component_index = world.componentIndex
|
||||||
|
archetype_clear_edges(archetype)
|
||||||
|
local archetype_id = archetype.id
|
||||||
|
world.archetypes[archetype_id] = nil
|
||||||
|
world.archetypeIndex[archetype.type] = nil
|
||||||
|
local records = archetype.records
|
||||||
|
|
||||||
|
for id in records do
|
||||||
|
local idr = component_index[id]
|
||||||
|
idr.cache[archetype_id] = nil
|
||||||
|
idr.size -= 1
|
||||||
|
records[id] = nil
|
||||||
|
if idr.size == 0 then
|
||||||
|
component_index[id] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function world_cleanup(world)
|
||||||
|
for _, archetype in world.archetypes do
|
||||||
|
if #archetype.entities == 0 then
|
||||||
|
archetype_destroy(world, archetype)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local world_delete: (world: World, entity: i53, destruct: boolean?) -> ()
|
||||||
do
|
do
|
||||||
local function archetype_fast_delete_last(columns: { Column },
|
|
||||||
column_count: number, types: { i53 }, entity: i53)
|
|
||||||
|
|
||||||
for i, column in columns do
|
|
||||||
if column ~= NULL_ARRAY then
|
|
||||||
column[column_count] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function archetype_fast_delete(columns: { Column },
|
|
||||||
column_count: number, row, types, entity)
|
|
||||||
|
|
||||||
for i, column in columns do
|
|
||||||
if column ~= NULL_ARRAY then
|
|
||||||
column[row] = column[column_count]
|
|
||||||
column[column_count] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local function archetype_delete(world: World,
|
local function archetype_delete(world: World,
|
||||||
archetype: Archetype, row: number)
|
archetype: Archetype, row: number, destruct: boolean?)
|
||||||
|
|
||||||
local entityIndex = world.entityIndex
|
local entityIndex = world.entityIndex
|
||||||
local columns = archetype.columns
|
local columns = archetype.columns
|
||||||
|
@ -812,33 +994,31 @@ do
|
||||||
end
|
end
|
||||||
|
|
||||||
local component_index = world.componentIndex
|
local component_index = world.componentIndex
|
||||||
|
|
||||||
local archetypes = world.archetypes
|
local archetypes = world.archetypes
|
||||||
|
|
||||||
local idr = component_index[delete]
|
local idr = component_index[delete]
|
||||||
if idr then
|
if idr then
|
||||||
local children = {}
|
local children = {}
|
||||||
for archetype_id in idr.cache do
|
for archetype_id in idr.cache do
|
||||||
local idr_archetype = archetypes[archetype_id]
|
local idr_archetype = archetypes[archetype_id]
|
||||||
|
|
||||||
for i, child in idr_archetype.entities do
|
for i, child in idr_archetype.entities do
|
||||||
table.insert(children, child)
|
table.insert(children, child)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local flags = idr.flags
|
local flags = idr.flags
|
||||||
if bit32.band(flags, ECS_ID_DELETE) ~= 0 then
|
if bit32.band(flags, ECS_ID_DELETE) ~= 0 then
|
||||||
for _, child in children do
|
for _, child in children do
|
||||||
-- Cascade deletion to children
|
-- Cascade deletion to children
|
||||||
world_delete(world, child)
|
world_delete(world, child)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
for _, child in children do
|
for _, child in children do
|
||||||
world_remove(world, child, delete)
|
world_remove(world, child, delete)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
component_index[delete] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- TODO: iterate each linked record.
|
-- TODO: iterate each linked record.
|
||||||
-- local r = ECS_PAIR(delete, EcsWildcard)
|
-- local r = ECS_PAIR(delete, EcsWildcard)
|
||||||
-- local idr_r = component_index[r]
|
-- local idr_r = component_index[r]
|
||||||
|
@ -890,7 +1070,7 @@ do
|
||||||
if bit32.band(flags, ECS_ID_DELETE) ~= 0 then
|
if bit32.band(flags, ECS_ID_DELETE) ~= 0 then
|
||||||
for _, child in children do
|
for _, child in children do
|
||||||
-- Cascade deletions of it has Delete as component trait
|
-- Cascade deletions of it has Delete as component trait
|
||||||
world_delete(world, child)
|
world_delete(world, child, destruct)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local object = ECS_ENTITY_T_LO(id)
|
local object = ECS_ENTITY_T_LO(id)
|
||||||
|
@ -903,11 +1083,10 @@ do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
component_index[o] = nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function world_delete(world: World, entity: i53)
|
function world_delete(world: World, entity: i53, destruct: boolean?)
|
||||||
local entityIndex = world.entityIndex
|
local entityIndex = world.entityIndex
|
||||||
|
|
||||||
local record = entityIndex.sparse[entity]
|
local record = entityIndex.sparse[entity]
|
||||||
|
@ -921,11 +1100,12 @@ do
|
||||||
if archetype then
|
if archetype then
|
||||||
-- In the future should have a destruct mode for
|
-- In the future should have a destruct mode for
|
||||||
-- deleting archetypes themselves. Maybe requires recycling
|
-- deleting archetypes themselves. Maybe requires recycling
|
||||||
archetype_delete(world, archetype, row)
|
archetype_delete(world, archetype, row, destruct)
|
||||||
end
|
end
|
||||||
|
|
||||||
record.archetype = nil :: any
|
record.archetype = nil :: any
|
||||||
entityIndex.sparse[entity] = nil
|
entityIndex.sparse[entity] = nil
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1368,7 +1548,7 @@ local function world_query(world: World, ...)
|
||||||
|
|
||||||
local archetypes = world.archetypes
|
local archetypes = world.archetypes
|
||||||
|
|
||||||
local idr: ArchetypeMap
|
local idr: IdRecord
|
||||||
local componentIndex = world.componentIndex
|
local componentIndex = world.componentIndex
|
||||||
|
|
||||||
for _, id in ids do
|
for _, id in ids do
|
||||||
|
@ -1435,6 +1615,7 @@ World.has = world_has
|
||||||
World.target = world_target
|
World.target = world_target
|
||||||
World.parent = world_parent
|
World.parent = world_parent
|
||||||
World.contains = world_contains
|
World.contains = world_contains
|
||||||
|
World.cleanup = world_cleanup
|
||||||
|
|
||||||
if _G.__JECS_DEBUG then
|
if _G.__JECS_DEBUG then
|
||||||
-- taken from https://github.com/centau/ecr/blob/main/src/ecr.luau
|
-- taken from https://github.com/centau/ecr/blob/main/src/ecr.luau
|
||||||
|
|
14
test/memory.luau
Normal file
14
test/memory.luau
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
local testkit = require("@testkit")
|
||||||
|
local jecs = require("@jecs")
|
||||||
|
|
||||||
|
local world = jecs.World.new()
|
||||||
|
|
||||||
|
local A = world:component()
|
||||||
|
local B = world:component()
|
||||||
|
|
||||||
|
local e = world:entity()
|
||||||
|
world:add(e, A)
|
||||||
|
world:add(e, B)
|
||||||
|
local archetype_id = world.archetypeIndex["1_2"].id
|
||||||
|
world:delete(e)
|
||||||
|
testkit.print(world)
|
|
@ -842,7 +842,7 @@ TEST("world:delete", function()
|
||||||
CHECK(world:get(id1, Health) == 50)
|
CHECK(world:get(id1, Health) == 50)
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE "delete entities using another Entity as component"
|
do CASE "delete entities using another Entity as component with Delete cleanup action"
|
||||||
local world = jecs.World.new()
|
local world = jecs.World.new()
|
||||||
|
|
||||||
local Health = world:entity()
|
local Health = world:entity()
|
||||||
|
|
Loading…
Reference in a new issue