mirror of
https://github.com/Ukendio/jecs.git
synced 2025-08-04 19:29:18 +00:00
Compare commits
1 commit
17034d97d3
...
30d2e2604c
Author | SHA1 | Date | |
---|---|---|---|
|
30d2e2604c |
6 changed files with 252 additions and 336 deletions
|
@ -1,62 +1,42 @@
|
||||||
--!strict
|
|
||||||
local jecs = require("@jecs")
|
local jecs = require("@jecs")
|
||||||
|
|
||||||
export type PatchedWorld = jecs.World & {
|
export type PatchedWorld = jecs.World & {
|
||||||
added: <T>(PatchedWorld, jecs.Id<T>, <e>(e: jecs.Entity<e>, id: jecs.Id<T>, value: T?) -> ()) -> () -> (),
|
added: <T>(PatchedWorld, jecs.Id<T>, (e: jecs.Entity, id: jecs.Id, value: T) -> ()) -> () -> (),
|
||||||
removed: <T>(PatchedWorld, jecs.Id<T>, (e: jecs.Entity, id: jecs.Id) -> ()) -> () -> (),
|
removed: <T>(PatchedWorld, jecs.Id<T>, (e: jecs.Entity, id: jecs.Id) -> ()) -> () -> (),
|
||||||
changed: <T>(PatchedWorld, jecs.Id<T>, <e>(e: jecs.Entity<e>, id: jecs.Id<T>, value: T) -> ()) -> () -> (),
|
changed: <T>(PatchedWorld, jecs.Id<T>, (e: jecs.Entity, id: jecs.Id, value: T) -> ()) -> () -> (),
|
||||||
observer: <T...>(
|
observer: (
|
||||||
PatchedWorld,
|
PatchedWorld,
|
||||||
jecs.Query<T...>,
|
any,
|
||||||
(<a>(jecs.Entity, jecs.Id<a>, a) -> ())?
|
(jecs.Entity) -> ()
|
||||||
) -> () -> (jecs.Entity),
|
) -> (),
|
||||||
monitor: (
|
monitor: (
|
||||||
PatchedWorld,
|
PatchedWorld,
|
||||||
any,
|
any,
|
||||||
(<a>(jecs.Entity, jecs.Id<a>) -> ())?
|
(jecs.Entity, jecs.Id) -> ()
|
||||||
) -> ()
|
) -> ()
|
||||||
}
|
}
|
||||||
|
|
||||||
local function observers_new(
|
local function observers_new(world, query, callback)
|
||||||
world: PatchedWorld,
|
local terms = query.filter_with :: { jecs.Id }
|
||||||
query: any,
|
if not terms then
|
||||||
callback: (<T, a>(jecs.Entity<T>, jecs.Id<a>, value: a?) -> ())?
|
local ids = query.ids
|
||||||
)
|
query.filter_with = ids
|
||||||
query = query:cached()
|
terms = ids
|
||||||
|
|
||||||
local archetypes = {}
|
|
||||||
local terms = query.ids
|
|
||||||
local first = terms[1]
|
|
||||||
|
|
||||||
local observers_on_create = world.observable[jecs.ArchetypeCreate][first]
|
|
||||||
observers_on_create[#observers_on_create].callback = function(archetype)
|
|
||||||
archetypes[archetype.id] = true
|
|
||||||
end
|
|
||||||
local observers_on_delete = world.observable[jecs.ArchetypeDelete][first]
|
|
||||||
observers_on_delete[#observers_on_delete].callback = function(archetype)
|
|
||||||
archetypes[archetype.id] = nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local entity_index = world.entity_index :: any
|
local entity_index = world.entity_index :: any
|
||||||
local i = 0
|
local function emplaced(entity, id, value)
|
||||||
local entities = {}
|
|
||||||
|
|
||||||
local function emplaced<T, a>(
|
|
||||||
entity: jecs.Entity<T>,
|
|
||||||
id: jecs.Id<a>,
|
|
||||||
value: a?
|
|
||||||
)
|
|
||||||
local r = jecs.entity_index_try_get_fast(
|
local r = jecs.entity_index_try_get_fast(
|
||||||
entity_index, entity :: any) :: jecs.Record
|
entity_index, entity :: any)
|
||||||
|
|
||||||
|
if not r then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local archetype = r.archetype
|
local archetype = r.archetype
|
||||||
|
|
||||||
if archetypes[archetype.id] then
|
if jecs.query_match(query, archetype) then
|
||||||
i += 1
|
callback(entity)
|
||||||
entities[i] = entity
|
|
||||||
if callback ~= nil then
|
|
||||||
callback(entity, id, value)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -64,19 +44,6 @@ local function observers_new(
|
||||||
world:added(term, emplaced)
|
world:added(term, emplaced)
|
||||||
world:changed(term, emplaced)
|
world:changed(term, emplaced)
|
||||||
end
|
end
|
||||||
|
|
||||||
return function()
|
|
||||||
local row = i
|
|
||||||
return function()
|
|
||||||
if row == 0 then
|
|
||||||
i = 0
|
|
||||||
table.clear(entities)
|
|
||||||
end
|
|
||||||
local entity = entities[row]
|
|
||||||
row -= 1
|
|
||||||
return entity
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function join(world, component)
|
local function join(world, component)
|
||||||
|
@ -124,47 +91,41 @@ local function join(world, component)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function monitors_new(world, query, callback)
|
local function monitors_new(world, query, callback)
|
||||||
query = query:cached()
|
local terms = query.filter_with :: { jecs.Id }
|
||||||
|
if not terms then
|
||||||
local archetypes = {}
|
local ids = query.ids
|
||||||
local terms = query.ids
|
query.filter_with = ids
|
||||||
local first = terms[1]
|
terms = ids
|
||||||
|
|
||||||
local observers_on_create = world.observable[jecs.ArchetypeCreate][first]
|
|
||||||
observers_on_create[#observers_on_create].callback = function(archetype)
|
|
||||||
archetypes[archetype.id] = true
|
|
||||||
end
|
|
||||||
local observers_on_delete = world.observable[jecs.ArchetypeDelete][first]
|
|
||||||
observers_on_delete[#observers_on_delete].callback = function(archetype)
|
|
||||||
archetypes[archetype.id] = nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local entity_index = world.entity_index :: any
|
local entity_index = world.entity_index :: any
|
||||||
local i = 0
|
local function emplaced(entity: jecs.Entity)
|
||||||
local entities = {}
|
|
||||||
|
|
||||||
local function emplaced<T, a>(
|
|
||||||
entity: jecs.Entity<T>,
|
|
||||||
id: jecs.Id<a>,
|
|
||||||
value: a?
|
|
||||||
)
|
|
||||||
local r = jecs.entity_index_try_get_fast(
|
local r = jecs.entity_index_try_get_fast(
|
||||||
entity_index, entity :: any) :: jecs.Record
|
entity_index, entity :: any)
|
||||||
|
|
||||||
|
if not r then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local archetype = r.archetype
|
local archetype = r.archetype
|
||||||
|
|
||||||
if archetypes[archetype.id] then
|
if jecs.query_match(query, archetype) then
|
||||||
i += 1
|
callback(entity, jecs.OnAdd)
|
||||||
entities[i] = entity
|
|
||||||
if callback ~= nil then
|
|
||||||
callback(entity, id, value)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function removed(entity: jecs.Entity, component: jecs.Id)
|
local function removed(entity: jecs.Entity, component: jecs.Id)
|
||||||
local EcsOnRemove = jecs.OnRemove :: jecs.Id
|
local r = jecs.entity_index_try_get_fast(
|
||||||
if callback ~= nil then
|
entity_index, entity :: any)
|
||||||
|
|
||||||
|
if not r then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local archetype = r.archetype
|
||||||
|
|
||||||
|
if jecs.query_match(query, archetype) then
|
||||||
|
local EcsOnRemove = jecs.OnRemove :: jecs.Id
|
||||||
callback(entity, EcsOnRemove)
|
callback(entity, EcsOnRemove)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -173,19 +134,6 @@ local function monitors_new(world, query, callback)
|
||||||
world:added(term, emplaced)
|
world:added(term, emplaced)
|
||||||
world:removed(term, removed)
|
world:removed(term, removed)
|
||||||
end
|
end
|
||||||
|
|
||||||
return function()
|
|
||||||
local row = i
|
|
||||||
return function()
|
|
||||||
if row == 0 then
|
|
||||||
i = 0
|
|
||||||
table.clear(entities)
|
|
||||||
end
|
|
||||||
local entity = entities[row]
|
|
||||||
row -= 1
|
|
||||||
return entity
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function observers_add(world: jecs.World): PatchedWorld
|
local function observers_add(world: jecs.World): PatchedWorld
|
||||||
|
@ -221,7 +169,7 @@ local function observers_add(world: jecs.World): PatchedWorld
|
||||||
|
|
||||||
local idr = world.component_index[component]
|
local idr = world.component_index[component]
|
||||||
if idr then
|
if idr then
|
||||||
idr.on_add = on_add
|
idr.hooks.on_add = on_add
|
||||||
else
|
else
|
||||||
world:set(component, jecs.OnAdd, on_add)
|
world:set(component, jecs.OnAdd, on_add)
|
||||||
end
|
end
|
||||||
|
@ -255,7 +203,7 @@ local function observers_add(world: jecs.World): PatchedWorld
|
||||||
end
|
end
|
||||||
local idr = world.component_index[component]
|
local idr = world.component_index[component]
|
||||||
if idr then
|
if idr then
|
||||||
idr.on_change = on_change
|
idr.hooks.on_change = on_change
|
||||||
else
|
else
|
||||||
world:set(component, jecs.OnChange, on_change)
|
world:set(component, jecs.OnChange, on_change)
|
||||||
end
|
end
|
||||||
|
@ -290,7 +238,7 @@ local function observers_add(world: jecs.World): PatchedWorld
|
||||||
|
|
||||||
local idr = world.component_index[component]
|
local idr = world.component_index[component]
|
||||||
if idr then
|
if idr then
|
||||||
idr.on_remove = on_remove
|
idr.hooks.on_remove = on_remove
|
||||||
else
|
else
|
||||||
world:set(component, jecs.OnRemove, on_remove)
|
world:set(component, jecs.OnRemove, on_remove)
|
||||||
end
|
end
|
||||||
|
|
1
jecs.d.ts
vendored
1
jecs.d.ts
vendored
|
@ -310,7 +310,6 @@ export declare const OnDeleteTarget: Tag;
|
||||||
export declare const Delete: Tag;
|
export declare const Delete: Tag;
|
||||||
export declare const Remove: Tag;
|
export declare const Remove: Tag;
|
||||||
export declare const Name: Entity<string>;
|
export declare const Name: Entity<string>;
|
||||||
export declare const Exclusive: Tag;
|
|
||||||
export declare const Rest: Entity;
|
export declare const Rest: Entity;
|
||||||
|
|
||||||
export type ComponentRecord = {
|
export type ComponentRecord = {
|
||||||
|
|
411
jecs.luau
411
jecs.luau
|
@ -42,12 +42,14 @@ export type Iter<T...> = (query: Query<T...>) -> () -> (Entity, T...)
|
||||||
export type Query<T...> = typeof(setmetatable(
|
export type Query<T...> = typeof(setmetatable(
|
||||||
{} :: {
|
{} :: {
|
||||||
iter: Iter<T...>,
|
iter: Iter<T...>,
|
||||||
with: (<a>(Query<T...>, Id<a>) -> Query<T...>)
|
with:
|
||||||
|
(<a>(Query<T...>, Id<a>) -> Query<T...>)
|
||||||
& (<a, b>(Query<T...>, Id<a>, Id<b>) -> Query<T...>)
|
& (<a, b>(Query<T...>, Id<a>, Id<b>) -> Query<T...>)
|
||||||
& (<a, b, c>(Query<T...>, Id<a>, Id<b>, Id<c>) -> Query<T...>)
|
& (<a, b, c>(Query<T...>, Id<a>, Id<b>, Id<c>) -> Query<T...>)
|
||||||
& (<a, b, c>(Query<T...>, Id<a>, Id<b>, Id<c>) -> Query<T...>)
|
& (<a, b, c>(Query<T...>, Id<a>, Id<b>, Id<c>) -> Query<T...>)
|
||||||
& (<a, b, c, d>(Query<T...>, Id<a>, Id<b>, Id<c>, Id) -> Query<T...>),
|
& (<a, b, c, d>(Query<T...>, Id<a>, Id<b>, Id<c>, Id) -> Query<T...>),
|
||||||
without: (<a>(Query<T...>, Id<a>) -> Query<T...>)
|
without:
|
||||||
|
(<a>(Query<T...>, Id<a>) -> Query<T...>)
|
||||||
& (<a, b>(Query<T...>, Id<a>, Id<b>) -> Query<T...>)
|
& (<a, b>(Query<T...>, Id<a>, Id<b>) -> Query<T...>)
|
||||||
& (<a, b, c>(Query<T...>, Id<a>, Id<b>, Id<c>) -> Query<T...>)
|
& (<a, b, c>(Query<T...>, Id<a>, Id<b>, Id<c>) -> Query<T...>)
|
||||||
& (<a, b, c>(Query<T...>, Id<a>, Id<b>, Id<c>) -> Query<T...>)
|
& (<a, b, c>(Query<T...>, Id<a>, Id<b>, Id<c>) -> Query<T...>)
|
||||||
|
@ -170,10 +172,11 @@ export type ComponentRecord = {
|
||||||
counts: { [Id]: number },
|
counts: { [Id]: number },
|
||||||
flags: number,
|
flags: number,
|
||||||
size: number,
|
size: number,
|
||||||
|
hooks: {
|
||||||
on_add: (<T>(entity: Entity, id: Entity<T>, value: T?) -> ())?,
|
on_add: (<T>(entity: Entity, id: Entity<T>, value: T?) -> ())?,
|
||||||
on_change: (<T>(entity: Entity, id: Entity<T>, value: T) -> ())?,
|
on_change: (<T>(entity: Entity, id: Entity<T>, value: T) -> ())?,
|
||||||
on_remove: ((entity: Entity, id: Entity) -> ())?,
|
on_remove: ((entity: Entity, id: Entity) -> ())?,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
export type ComponentIndex = Map<Id, ComponentRecord>
|
export type ComponentIndex = Map<Id, ComponentRecord>
|
||||||
export type Archetypes = { [Id]: Archetype }
|
export type Archetypes = { [Id]: Archetype }
|
||||||
|
@ -193,10 +196,10 @@ local ECS_ENTITY_MASK = bit32.lshift(1, 24)
|
||||||
local ECS_GENERATION_MASK = bit32.lshift(1, 16)
|
local ECS_GENERATION_MASK = bit32.lshift(1, 16)
|
||||||
local ECS_PAIR_OFFSET = 2^48
|
local ECS_PAIR_OFFSET = 2^48
|
||||||
|
|
||||||
local ECS_ID_DELETE = 0b0001
|
local ECS_ID_DELETE = 0b0001
|
||||||
local ECS_ID_IS_TAG = 0b0010
|
local ECS_ID_IS_TAG = 0b0010
|
||||||
local ECS_ID_IS_EXCLUSIVE = 0b0100
|
local ECS_ID_IS_EXCLUSIVE = 0b0100
|
||||||
local ECS_ID_MASK = 0b0000
|
local ECS_ID_MASK = 0b0000
|
||||||
|
|
||||||
local HI_COMPONENT_ID = 256
|
local HI_COMPONENT_ID = 256
|
||||||
local EcsOnAdd = HI_COMPONENT_ID + 1
|
local EcsOnAdd = HI_COMPONENT_ID + 1
|
||||||
|
@ -745,10 +748,11 @@ local function id_record_ensure(world: World, id: Entity): ComponentRecord
|
||||||
records = {},
|
records = {},
|
||||||
counts = {},
|
counts = {},
|
||||||
flags = flags,
|
flags = flags,
|
||||||
|
hooks = {
|
||||||
on_add = on_add,
|
on_add = on_add,
|
||||||
on_change = on_change,
|
on_change = on_change,
|
||||||
on_remove = on_remove,
|
on_remove = on_remove,
|
||||||
|
},
|
||||||
} :: ComponentRecord
|
} :: ComponentRecord
|
||||||
|
|
||||||
component_index[id] = idr
|
component_index[id] = idr
|
||||||
|
@ -1027,7 +1031,7 @@ local function archetype_delete(world: World, archetype: Archetype, row: number)
|
||||||
|
|
||||||
for _, id in id_types do
|
for _, id in id_types do
|
||||||
local idr = component_index[id]
|
local idr = component_index[id]
|
||||||
local on_remove = idr.on_remove
|
local on_remove = idr.hooks.on_remove
|
||||||
if on_remove then
|
if on_remove then
|
||||||
on_remove(delete, id)
|
on_remove(delete, id)
|
||||||
end
|
end
|
||||||
|
@ -1061,13 +1065,6 @@ local function archetype_destroy(world: World, archetype: Archetype)
|
||||||
local columns_map = archetype.columns_map
|
local columns_map = archetype.columns_map
|
||||||
|
|
||||||
for id in columns_map do
|
for id in columns_map do
|
||||||
local idr = component_index[id]
|
|
||||||
idr.records[archetype_id] = nil :: any
|
|
||||||
idr.counts[archetype_id] = nil
|
|
||||||
idr.size -= 1
|
|
||||||
if idr.size == 0 then
|
|
||||||
component_index[id] = nil :: any
|
|
||||||
end
|
|
||||||
local observer_list = find_observers(world, EcsOnArchetypeDelete, id)
|
local observer_list = find_observers(world, EcsOnArchetypeDelete, id)
|
||||||
if not observer_list then
|
if not observer_list then
|
||||||
continue
|
continue
|
||||||
|
@ -1078,6 +1075,16 @@ local function archetype_destroy(world: World, archetype: Archetype)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
for id in columns_map do
|
||||||
|
local idr = component_index[id]
|
||||||
|
idr.records[archetype_id] = nil :: any
|
||||||
|
idr.counts[archetype_id] = nil
|
||||||
|
idr.size -= 1
|
||||||
|
if idr.size == 0 then
|
||||||
|
component_index[id] = nil :: any
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function NOOP() end
|
local function NOOP() end
|
||||||
|
@ -2023,7 +2030,7 @@ local function ecs_bulk_insert(world: World, entity: Entity, ids: { Entity }, va
|
||||||
local value = values[i]
|
local value = values[i]
|
||||||
local cdr = component_index[id]
|
local cdr = component_index[id]
|
||||||
|
|
||||||
local on_add = cdr.on_add
|
local on_add = cdr.hooks.on_add
|
||||||
if value then
|
if value then
|
||||||
columns_map[id][row] = value
|
columns_map[id][row] = value
|
||||||
if on_add then
|
if on_add then
|
||||||
|
@ -2068,11 +2075,11 @@ local function ecs_bulk_insert(world: World, entity: Entity, ids: { Entity }, va
|
||||||
|
|
||||||
local value = values[i] :: any
|
local value = values[i] :: any
|
||||||
|
|
||||||
local on_add = idr.on_add
|
local on_add = idr.hooks.on_add
|
||||||
|
|
||||||
if value ~= nil then
|
if value ~= nil then
|
||||||
columns_map[id][row] = value
|
columns_map[id][row] = value
|
||||||
local on_change = idr.on_change
|
local on_change = idr.hooks.on_change
|
||||||
local hook = if set then on_change else on_add
|
local hook = if set then on_change else on_add
|
||||||
if hook then
|
if hook then
|
||||||
hook(entity, id, value :: any)
|
hook(entity, id, value :: any)
|
||||||
|
@ -2107,7 +2114,7 @@ local function ecs_bulk_remove(world: World, entity: Entity, ids: { Entity })
|
||||||
remove[id] = true
|
remove[id] = true
|
||||||
local idr = component_index[id]
|
local idr = component_index[id]
|
||||||
|
|
||||||
local on_remove = idr.on_remove
|
local on_remove = idr.hooks.on_remove
|
||||||
if on_remove then
|
if on_remove then
|
||||||
on_remove(entity, id)
|
on_remove(entity, id)
|
||||||
end
|
end
|
||||||
|
@ -2174,83 +2181,13 @@ local function world_new()
|
||||||
local function inner_entity_index_try_get_any(entity: number): Record?
|
local function inner_entity_index_try_get_any(entity: number): Record?
|
||||||
local r = eindex_sparse_array[ECS_ENTITY_T_LO(entity)]
|
local r = eindex_sparse_array[ECS_ENTITY_T_LO(entity)]
|
||||||
|
|
||||||
if not r then
|
if not r or r.dense == 0 then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
return r
|
return r
|
||||||
end
|
end
|
||||||
|
|
||||||
local function inner_archetype_move(
|
|
||||||
entity: Entity,
|
|
||||||
to: Archetype,
|
|
||||||
dst_row: i24,
|
|
||||||
from: Archetype,
|
|
||||||
src_row: i24
|
|
||||||
)
|
|
||||||
local src_columns = from.columns
|
|
||||||
local dst_entities = to.entities
|
|
||||||
local src_entities = from.entities
|
|
||||||
|
|
||||||
local last = #src_entities
|
|
||||||
local id_types = from.types
|
|
||||||
local columns_map = to.columns_map
|
|
||||||
|
|
||||||
if src_row ~= last then
|
|
||||||
for i, column in src_columns do
|
|
||||||
if column == NULL_ARRAY then
|
|
||||||
continue
|
|
||||||
end
|
|
||||||
local dst_column = columns_map[id_types[i]]
|
|
||||||
|
|
||||||
if dst_column then
|
|
||||||
dst_column[dst_row] = column[src_row]
|
|
||||||
end
|
|
||||||
|
|
||||||
column[src_row] = column[last]
|
|
||||||
column[last] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local e2 = src_entities[last]
|
|
||||||
src_entities[src_row] = e2
|
|
||||||
|
|
||||||
local record2 = eindex_sparse_array[ECS_ENTITY_T_LO(e2 :: number)]
|
|
||||||
record2.row = src_row
|
|
||||||
else
|
|
||||||
for i, column in src_columns do
|
|
||||||
if column == NULL_ARRAY then
|
|
||||||
continue
|
|
||||||
end
|
|
||||||
-- Retrieves the new column index from the source archetype's record from each component
|
|
||||||
-- We have to do this because the columns are tightly packed and indexes may not correspond to each other.
|
|
||||||
local dst_column = columns_map[id_types[i]]
|
|
||||||
|
|
||||||
-- Sometimes target column may not exist, e.g. when you remove a component.
|
|
||||||
if dst_column then
|
|
||||||
dst_column[dst_row] = column[src_row]
|
|
||||||
end
|
|
||||||
|
|
||||||
column[last] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
src_entities[last] = nil :: any
|
|
||||||
dst_entities[dst_row] = entity
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inner_entity_move(
|
|
||||||
entity_index: EntityIndex,
|
|
||||||
entity: Entity,
|
|
||||||
record: Record,
|
|
||||||
to: Archetype
|
|
||||||
)
|
|
||||||
local sourceRow = record.row
|
|
||||||
local from = record.archetype
|
|
||||||
local dst_row = archetype_append(entity, to)
|
|
||||||
inner_archetype_move(entity, to, dst_row, from, sourceRow)
|
|
||||||
record.archetype = to
|
|
||||||
record.row = dst_row
|
|
||||||
end
|
|
||||||
|
|
||||||
-- local function inner_entity_index_try_get(entity: number): Record?
|
-- local function inner_entity_index_try_get(entity: number): Record?
|
||||||
-- local r = inner_entity_index_try_get_any(entity)
|
-- local r = inner_entity_index_try_get_any(entity)
|
||||||
-- if r then
|
-- if r then
|
||||||
|
@ -2303,7 +2240,7 @@ local function world_new()
|
||||||
if idr and bit32.btest(idr.flags, ECS_ID_IS_EXCLUSIVE) then
|
if idr and 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.hooks.on_remove
|
||||||
local id_types = src.types
|
local id_types = src.types
|
||||||
if on_remove then
|
if on_remove then
|
||||||
on_remove(entity, id_types[cr])
|
on_remove(entity, id_types[cr])
|
||||||
|
@ -2330,14 +2267,14 @@ local function world_new()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if from then
|
if from then
|
||||||
inner_entity_move(entity_index, entity, record, to)
|
entity_move(entity_index, entity, record, to)
|
||||||
else
|
else
|
||||||
if #to.types > 0 then
|
if #to.types > 0 then
|
||||||
new_entity(entity, record, to)
|
new_entity(entity, record, to)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local on_add = idr.on_add
|
local on_add = idr.hooks.on_add
|
||||||
|
|
||||||
if on_add then
|
if on_add then
|
||||||
on_add(entity, id)
|
on_add(entity, id)
|
||||||
|
@ -2349,7 +2286,7 @@ local function world_new()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if from then
|
if from then
|
||||||
inner_entity_move(entity_index, entity, record, to)
|
entity_move(entity_index, entity, record, to)
|
||||||
else
|
else
|
||||||
if #to.types > 0 then
|
if #to.types > 0 then
|
||||||
new_entity(entity, record, to)
|
new_entity(entity, record, to)
|
||||||
|
@ -2357,7 +2294,7 @@ local function world_new()
|
||||||
end
|
end
|
||||||
|
|
||||||
local idr = component_index[id]
|
local idr = component_index[id]
|
||||||
local on_add = idr.on_add
|
local on_add = idr.hooks.on_add
|
||||||
|
|
||||||
if on_add then
|
if on_add then
|
||||||
on_add(entity, id)
|
on_add(entity, id)
|
||||||
|
@ -2485,73 +2422,104 @@ local function world_new()
|
||||||
end
|
end
|
||||||
|
|
||||||
local from: Archetype = record.archetype
|
local from: Archetype = record.archetype
|
||||||
local src = from or ROOT_ARCHETYPE
|
if ECS_IS_PAIR(id::number) then
|
||||||
local column = src.columns_map[id]
|
local src = from or ROOT_ARCHETYPE
|
||||||
if column then
|
local edge = archetype_edges[src.id]
|
||||||
local idr = component_index[id]
|
local to = edge[id]
|
||||||
column[record.row] = data
|
|
||||||
|
|
||||||
-- If the archetypes are the same it can avoid moving the entity
|
|
||||||
-- and just set the data directly.
|
|
||||||
local on_change = idr.on_change
|
|
||||||
if on_change then
|
|
||||||
on_change(entity, id, data)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local to: Archetype
|
|
||||||
local idr: ComponentRecord
|
local idr: ComponentRecord
|
||||||
if ECS_IS_PAIR(id::number) then
|
if not to then
|
||||||
local edge = archetype_edges[src.id]
|
local first = ECS_PAIR_FIRST(id::number)
|
||||||
to = edge[id]
|
local wc = ECS_PAIR(first, EcsWildcard)
|
||||||
if not to then
|
idr = component_index[wc]
|
||||||
local first = ECS_PAIR_FIRST(id::number)
|
if idr and bit32.btest(idr.flags, ECS_ID_IS_EXCLUSIVE) 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.hooks.on_remove
|
||||||
local cr = idr.records[src.id]
|
local id_types = src.types
|
||||||
if cr then
|
if on_remove then
|
||||||
local on_remove = idr.on_remove
|
on_remove(entity, id_types[cr])
|
||||||
local id_types = src.types
|
src = record.archetype
|
||||||
if on_remove then
|
id_types = src.types
|
||||||
on_remove(entity, id_types[cr])
|
cr = idr.records[src.id]
|
||||||
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)
|
|
||||||
else
|
|
||||||
to = find_archetype_with(world, id, src)
|
|
||||||
idr = component_index[id]
|
|
||||||
end
|
end
|
||||||
|
local dst = table.clone(id_types)
|
||||||
|
dst[cr] = id
|
||||||
|
to = archetype_ensure(world, dst)
|
||||||
else
|
else
|
||||||
to = find_archetype_with(world, id, src)
|
to = find_archetype_with(world, id, src)
|
||||||
idr = component_index[id]
|
idr = component_index[id]
|
||||||
end
|
end
|
||||||
edge[id] = to
|
|
||||||
else
|
else
|
||||||
|
to = find_archetype_with(world, id, src)
|
||||||
idr = component_index[id]
|
idr = component_index[id]
|
||||||
end
|
end
|
||||||
|
edge[id] = to
|
||||||
else
|
else
|
||||||
to = inner_archetype_traverse_add(id, from)
|
|
||||||
idr = component_index[id]
|
idr = component_index[id]
|
||||||
end
|
end
|
||||||
|
local idr_hooks = idr.hooks
|
||||||
|
if from == to then
|
||||||
|
local column = to.columns_map[id]
|
||||||
|
column[record.row] = data
|
||||||
|
|
||||||
|
-- If the archetypes are the same it can avoid moving the entity
|
||||||
|
-- and just set the data directly.
|
||||||
|
local on_change = idr_hooks.on_change
|
||||||
|
if on_change then
|
||||||
|
on_change(entity, id, data)
|
||||||
|
end
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if from then
|
if from then
|
||||||
-- If there was a previous archetype, then the entity needs to move the archetype
|
entity_move(entity_index, entity, record, to)
|
||||||
inner_entity_move(entity_index, entity, record, to)
|
|
||||||
else
|
else
|
||||||
new_entity(entity, record, to)
|
if #to.types > 0 then
|
||||||
|
new_entity(entity, record, to)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
column = to.columns_map[id]
|
local column = to.columns_map[id]
|
||||||
column[record.row] = data
|
column[record.row] = data
|
||||||
|
|
||||||
local on_add = idr.on_add
|
local on_add = idr.hooks.on_add
|
||||||
|
|
||||||
if on_add then
|
if on_add then
|
||||||
on_add(entity, id, data)
|
on_add(entity, id)
|
||||||
end
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local to: Archetype = inner_archetype_traverse_add(id, from)
|
||||||
|
local idr = component_index[id]
|
||||||
|
local idr_hooks = idr.hooks
|
||||||
|
|
||||||
|
if from == to then
|
||||||
|
local column = to.columns_map[id]
|
||||||
|
column[record.row] = data
|
||||||
|
|
||||||
|
-- If the archetypes are the same it can avoid moving the entity
|
||||||
|
-- and just set the data directly.
|
||||||
|
local on_change = idr_hooks.on_change
|
||||||
|
if on_change then
|
||||||
|
on_change(entity, id, data)
|
||||||
|
end
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if from then
|
||||||
|
-- If there was a previous archetype, then the entity needs to move the archetype
|
||||||
|
entity_move(entity_index, entity, record, to)
|
||||||
|
else
|
||||||
|
new_entity(entity, record, to)
|
||||||
|
end
|
||||||
|
local column = to.columns_map[id]
|
||||||
|
column[record.row] = data
|
||||||
|
|
||||||
|
local on_add = idr_hooks.on_add
|
||||||
|
if on_add then
|
||||||
|
on_add(entity, id, data)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2589,7 +2557,7 @@ local function world_new()
|
||||||
return entity
|
return entity
|
||||||
else
|
else
|
||||||
for i = eindex_max_id + 1, index do
|
for i = eindex_max_id + 1, index do
|
||||||
eindex_sparse_array[i] = { dense = i } :: Record
|
eindex_sparse_array[i]= { dense = i } :: Record
|
||||||
eindex_dense_array[i] = i
|
eindex_dense_array[i] = i
|
||||||
end
|
end
|
||||||
entity_index.max_id = index
|
entity_index.max_id = index
|
||||||
|
@ -2629,14 +2597,14 @@ local function world_new()
|
||||||
|
|
||||||
if from.columns_map[id] then
|
if from.columns_map[id] then
|
||||||
local idr = world.component_index[id]
|
local idr = world.component_index[id]
|
||||||
local on_remove = idr.on_remove
|
local on_remove = idr.hooks.on_remove
|
||||||
if on_remove then
|
if on_remove then
|
||||||
on_remove(entity, id)
|
on_remove(entity, id)
|
||||||
end
|
end
|
||||||
|
|
||||||
local to = archetype_traverse_remove(world, id, record.archetype)
|
local to = archetype_traverse_remove(world, id, record.archetype)
|
||||||
|
|
||||||
inner_entity_move(entity_index, entity, record, to)
|
entity_move(entity_index, entity, record, to)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2663,13 +2631,16 @@ local function world_new()
|
||||||
end
|
end
|
||||||
|
|
||||||
if idr_t then
|
if idr_t then
|
||||||
|
local queue: { i53 }
|
||||||
|
local ids: Map<i53, boolean>
|
||||||
|
|
||||||
|
local count = 0
|
||||||
local archetype_ids = idr_t.records
|
local archetype_ids = idr_t.records
|
||||||
for archetype_id in archetype_ids do
|
for archetype_id in archetype_ids do
|
||||||
local idr_t_archetype = archetypes[archetype_id]
|
local idr_t_archetype = archetypes[archetype_id]
|
||||||
local idr_t_types = idr_t_archetype.types
|
local idr_t_types = idr_t_archetype.types
|
||||||
local entities = idr_t_archetype.entities
|
local entities = idr_t_archetype.entities
|
||||||
|
local removal_queued = false
|
||||||
local node = idr_t_archetype
|
|
||||||
|
|
||||||
for _, id in idr_t_types do
|
for _, id in idr_t_types do
|
||||||
if not ECS_IS_PAIR(id::number) then
|
if not ECS_IS_PAIR(id::number) then
|
||||||
|
@ -2680,54 +2651,64 @@ local function world_new()
|
||||||
if object ~= entity then
|
if object ~= entity then
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
node = archetype_traverse_remove(world, id, node)
|
if not ids then
|
||||||
local on_remove = component_index[id].on_remove
|
ids = {} :: { [i53]: boolean }
|
||||||
if on_remove then
|
|
||||||
for _, entity in entities do
|
|
||||||
on_remove(entity, id)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
ids[id] = true
|
||||||
|
removal_queued = true
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = #entities, 1, -1 do
|
if not removal_queued then
|
||||||
local e = entities[i]
|
continue
|
||||||
local r = inner_entity_index_try_get_unsafe(e::number) :: Record
|
end
|
||||||
inner_entity_move(entity_index, e, r, node)
|
|
||||||
|
if not queue then
|
||||||
|
queue = {} :: { i53 }
|
||||||
|
end
|
||||||
|
|
||||||
|
local n = #entities
|
||||||
|
table.move(entities, 1, n, count + 1, queue)
|
||||||
|
count += n
|
||||||
|
end
|
||||||
|
|
||||||
|
for id in ids do
|
||||||
|
for _, child in queue do
|
||||||
|
inner_world_remove(world, child, id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if idr_r then
|
if idr_r then
|
||||||
|
local count = 0
|
||||||
local archetype_ids = idr_r.records
|
local archetype_ids = idr_r.records
|
||||||
|
local ids = {}
|
||||||
|
local queue = {}
|
||||||
local records = idr_r.records
|
local records = idr_r.records
|
||||||
local counts = idr_r.counts
|
local counts = idr_r.counts
|
||||||
for archetype_id in archetype_ids do
|
for archetype_id in archetype_ids do
|
||||||
local idr_r_archetype = archetypes[archetype_id]
|
local idr_r_archetype = archetypes[archetype_id]
|
||||||
local node = idr_r_archetype
|
|
||||||
local entities = idr_r_archetype.entities
|
local entities = idr_r_archetype.entities
|
||||||
local tr = records[archetype_id]
|
local tr = records[archetype_id]
|
||||||
local tr_count = counts[archetype_id]
|
local tr_count = counts[archetype_id]
|
||||||
local types = idr_r_archetype.types
|
local types = idr_r_archetype.types
|
||||||
for i = tr, tr + tr_count - 1 do
|
for i = tr, tr + tr_count - 1 do
|
||||||
local id = types[i]
|
ids[types[i]] = true
|
||||||
node = archetype_traverse_remove(world, id, idr_r_archetype)
|
|
||||||
local on_remove = component_index[id].on_remove
|
|
||||||
if on_remove then
|
|
||||||
for _, entity in entities do
|
|
||||||
on_remove(entity, id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
for i = #entities, 1, -1 do
|
local n = #entities
|
||||||
local e = entities[i]
|
table.move(entities, 1, n, count + 1, queue)
|
||||||
local r = inner_entity_index_try_get_unsafe(e::number) :: Record
|
count += n
|
||||||
inner_entity_move(entity_index, e, r, node)
|
end
|
||||||
|
|
||||||
|
for _, e in queue do
|
||||||
|
for id in ids do
|
||||||
|
inner_world_remove(world, e, id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function inner_world_delete<T>(world: World, entity: Entity<T>)
|
local function inner_world_delete<T>(world: World, entity: Entity<T>)
|
||||||
|
local entity_index = world.entity_index
|
||||||
local record = inner_entity_index_try_get_unsafe(entity::number)
|
local record = inner_entity_index_try_get_unsafe(entity::number)
|
||||||
if not record then
|
if not record then
|
||||||
return
|
return
|
||||||
|
@ -2766,7 +2747,7 @@ local function world_new()
|
||||||
archetype_destroy(world, idr_archetype)
|
archetype_destroy(world, idr_archetype)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local on_remove = idr.on_remove
|
local on_remove = idr.hooks.on_remove
|
||||||
if on_remove then
|
if on_remove then
|
||||||
for archetype_id in idr.records do
|
for archetype_id in idr.records do
|
||||||
local idr_archetype = archetypes[archetype_id]
|
local idr_archetype = archetypes[archetype_id]
|
||||||
|
@ -2783,7 +2764,7 @@ local function world_new()
|
||||||
-- this is hypothetically not that expensive of an operation anyways
|
-- this is hypothetically not that expensive of an operation anyways
|
||||||
to = archetype_traverse_remove(world, entity, from)
|
to = archetype_traverse_remove(world, entity, from)
|
||||||
end
|
end
|
||||||
inner_entity_move(entity_index, e, r, to)
|
entity_move(entity_index, e, r, to)
|
||||||
end
|
end
|
||||||
|
|
||||||
archetype_destroy(world, idr_archetype)
|
archetype_destroy(world, idr_archetype)
|
||||||
|
@ -2804,15 +2785,19 @@ local function world_new()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if idr_t then
|
if idr_t then
|
||||||
|
local children: { i53 }
|
||||||
|
local ids: Map<i53, boolean>
|
||||||
|
|
||||||
|
local count = 0
|
||||||
local archetype_ids = idr_t.records
|
local archetype_ids = idr_t.records
|
||||||
for archetype_id in archetype_ids do
|
for archetype_id in archetype_ids do
|
||||||
local idr_t_archetype = archetypes[archetype_id]
|
local idr_t_archetype = archetypes[archetype_id]
|
||||||
local node = idr_t_archetype
|
|
||||||
local idr_t_types = idr_t_archetype.types
|
local idr_t_types = idr_t_archetype.types
|
||||||
local entities = idr_t_archetype.entities
|
local entities = idr_t_archetype.entities
|
||||||
|
local removal_queued = false
|
||||||
|
|
||||||
local deleted = false
|
|
||||||
for _, id in idr_t_types do
|
for _, id in idr_t_types do
|
||||||
if not ECS_IS_PAIR(id::number) then
|
if not ECS_IS_PAIR(id::number) then
|
||||||
continue
|
continue
|
||||||
|
@ -2830,24 +2815,31 @@ local function world_new()
|
||||||
local child = entities[i]
|
local child = entities[i]
|
||||||
inner_world_delete(world, child)
|
inner_world_delete(world, child)
|
||||||
end
|
end
|
||||||
deleted = true
|
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
node = archetype_traverse_remove(world, id, node)
|
if not ids then
|
||||||
local on_remove = component_index[id].on_remove
|
ids = {} :: { [i53]: boolean }
|
||||||
if on_remove then
|
|
||||||
for _, entity in entities do
|
|
||||||
on_remove(entity, id)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
ids[id] = true
|
||||||
|
removal_queued = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if not deleted then
|
if not removal_queued then
|
||||||
for i = #entities, 1, -1 do
|
continue
|
||||||
local e = entities[i]
|
end
|
||||||
local r = inner_entity_index_try_get_unsafe(e::number) :: Record
|
if not children then
|
||||||
inner_entity_move(entity_index, e, r, node)
|
children = {} :: { i53 }
|
||||||
|
end
|
||||||
|
local n = #entities
|
||||||
|
table.move(entities, 1, n, count + 1, children)
|
||||||
|
count += n
|
||||||
|
end
|
||||||
|
|
||||||
|
if ids then
|
||||||
|
for _, child in children do
|
||||||
|
for id in ids do
|
||||||
|
inner_world_remove(world, child, id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -2871,29 +2863,28 @@ local function world_new()
|
||||||
archetype_destroy(world, idr_r_archetype)
|
archetype_destroy(world, idr_r_archetype)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
local children = {}
|
||||||
|
local count = 0
|
||||||
|
local ids = {}
|
||||||
local counts = idr_r.counts
|
local counts = idr_r.counts
|
||||||
local records = idr_r.records
|
local records = idr_r.records
|
||||||
for archetype_id in archetype_ids do
|
for archetype_id in archetype_ids do
|
||||||
local idr_r_archetype = archetypes[archetype_id]
|
local idr_r_archetype = archetypes[archetype_id]
|
||||||
local node = idr_r_archetype
|
|
||||||
local entities = idr_r_archetype.entities
|
local entities = idr_r_archetype.entities
|
||||||
local tr = records[archetype_id]
|
local tr = records[archetype_id]
|
||||||
local tr_count = counts[archetype_id]
|
local tr_count = counts[archetype_id]
|
||||||
local types = idr_r_archetype.types
|
local types = idr_r_archetype.types
|
||||||
for i = tr, tr + tr_count - 1 do
|
for i = tr, tr + tr_count - 1 do
|
||||||
local id = types[i]
|
ids[types[i]] = true
|
||||||
node = archetype_traverse_remove(world, id, node)
|
|
||||||
local on_remove = component_index[id].on_remove
|
|
||||||
if on_remove then
|
|
||||||
for _, entity in entities do
|
|
||||||
on_remove(entity, id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
for i = #entities, 1, -1 do
|
|
||||||
local e = entities[i]
|
local n = #entities
|
||||||
local r = inner_entity_index_try_get_unsafe(e::number) :: Record
|
table.move(entities, 1, n, count + 1, children)
|
||||||
inner_entity_move(entity_index, e, r, node)
|
count += n
|
||||||
|
end
|
||||||
|
for _, child in children do
|
||||||
|
for id in ids do
|
||||||
|
inner_world_remove(world, child, id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2903,19 +2894,21 @@ local function world_new()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local dense_array = entity_index.dense_array
|
||||||
local dense = record.dense
|
local dense = record.dense
|
||||||
local i_swap = entity_index.alive_count
|
local i_swap = entity_index.alive_count
|
||||||
entity_index.alive_count = i_swap - 1
|
entity_index.alive_count = i_swap - 1
|
||||||
|
|
||||||
local e_swap = eindex_dense_array[i_swap]
|
local e_swap = dense_array[i_swap]
|
||||||
local r_swap = inner_entity_index_try_get_any(e_swap :: number) :: Record
|
local r_swap = inner_entity_index_try_get_any(e_swap :: number) :: Record
|
||||||
|
|
||||||
r_swap.dense = dense
|
r_swap.dense = dense
|
||||||
record.archetype = nil :: any
|
record.archetype = nil :: any
|
||||||
record.row = nil :: any
|
record.row = nil :: any
|
||||||
record.dense = i_swap
|
record.dense = i_swap
|
||||||
|
|
||||||
eindex_dense_array[dense] = e_swap
|
dense_array[dense] = e_swap
|
||||||
eindex_dense_array[i_swap] = ECS_GENERATION_INC(entity :: number)
|
dense_array[i_swap] = ECS_GENERATION_INC(entity :: number)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function inner_world_exists<T>(world: World, entity: Entity<T>): boolean
|
local function inner_world_exists<T>(world: World, entity: Entity<T>): boolean
|
||||||
|
@ -3063,8 +3056,6 @@ return {
|
||||||
Remove = (EcsRemove :: any) :: Entity,
|
Remove = (EcsRemove :: any) :: Entity,
|
||||||
Name = (EcsName :: any) :: Entity<string>,
|
Name = (EcsName :: any) :: Entity<string>,
|
||||||
Exclusive = EcsExclusive :: Entity,
|
Exclusive = EcsExclusive :: Entity,
|
||||||
ArchetypeCreate = EcsOnArchetypeCreate,
|
|
||||||
ArchetypeDelete = EcsOnArchetypeDelete,
|
|
||||||
Rest = (EcsRest :: any) :: Entity,
|
Rest = (EcsRest :: any) :: Entity,
|
||||||
|
|
||||||
pair = (ECS_PAIR :: any) :: <P, O>(first: Id<P>, second: Id<O>) -> Pair<P, O>,
|
pair = (ECS_PAIR :: any) :: <P, O>(first: Id<P>, second: Id<O>) -> Pair<P, O>,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@rbxts/jecs",
|
"name": "@rbxts/jecs",
|
||||||
"version": "0.8.2",
|
"version": "0.7.3",
|
||||||
"description": "Stupidly fast Entity Component System",
|
"description": "Stupidly fast Entity Component System",
|
||||||
"main": "jecs.luau",
|
"main": "jecs.luau",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
|
@ -659,6 +659,7 @@ TEST("world:delete()", function()
|
||||||
CHECK(not world:has(id1, Health))
|
CHECK(not world:has(id1, Health))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
do CASE "delete children"
|
do CASE "delete children"
|
||||||
local world = jecs.world()
|
local world = jecs.world()
|
||||||
|
|
||||||
|
@ -845,16 +846,6 @@ TEST("world:delete()", function()
|
||||||
CHECK(not world:contains(bob))
|
CHECK(not world:contains(bob))
|
||||||
CHECK(not world:contains(alice))
|
CHECK(not world:contains(alice))
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE "deleted entity should not be able to be operated on"
|
|
||||||
local world = jecs.world()
|
|
||||||
local e = world:entity()
|
|
||||||
local A = world:component()
|
|
||||||
world:set(e, A, true)
|
|
||||||
world:delete(e)
|
|
||||||
world:set(e, A, true)
|
|
||||||
CHECK(world:has(e, A) == false)
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
TEST("world:each()", function()
|
TEST("world:each()", function()
|
||||||
|
@ -886,19 +877,6 @@ TEST("world:each()", function()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
TEST("world:range()", function()
|
TEST("world:range()", function()
|
||||||
do CASE "delete outside partitioned range"
|
|
||||||
local server = jecs.world()
|
|
||||||
local client = jecs.world()
|
|
||||||
|
|
||||||
server:range(0, 1000)
|
|
||||||
client:range(1000, 5000)
|
|
||||||
|
|
||||||
local e1 = server:entity()
|
|
||||||
CHECK((e1::number)< 1000)
|
|
||||||
local e2 = client:entity(e1)
|
|
||||||
CHECK(e2 == e1)
|
|
||||||
client:delete(e1)
|
|
||||||
end
|
|
||||||
do CASE "under range start"
|
do CASE "under range start"
|
||||||
local world = jecs.world()
|
local world = jecs.world()
|
||||||
world:range(400, 1000)
|
world:range(400, 1000)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "ukendio/jecs"
|
name = "ukendio/jecs"
|
||||||
version = "0.8.2"
|
version = "0.7.3"
|
||||||
registry = "https://github.com/UpliftGames/wally-index"
|
registry = "https://github.com/UpliftGames/wally-index"
|
||||||
realm = "shared"
|
realm = "shared"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
Loading…
Reference in a new issue