mirror of
https://github.com/Ukendio/jecs.git
synced 2025-09-23 08:39:16 +00:00
Compare commits
3 commits
c73f484560
...
afc2e3a2f3
Author | SHA1 | Date | |
---|---|---|---|
|
afc2e3a2f3 | ||
|
3dacb2af80 | ||
|
b654d01421 |
6 changed files with 254 additions and 208 deletions
265
addons/ob.luau
265
addons/ob.luau
|
@ -3,10 +3,11 @@ local jecs = require("@jecs")
|
|||
|
||||
type World = jecs.World
|
||||
type Query<T...> = jecs.Query<T...>
|
||||
type QueryInner<T...> = Query<T...> & jecs.QueryInner
|
||||
|
||||
type Id<T=any> = jecs.Id<T>
|
||||
type Id<T = any> = jecs.Id<T>
|
||||
|
||||
type Entity<T> = jecs.Entity<T>
|
||||
type Entity<T = any> = jecs.Entity<T>
|
||||
|
||||
export type Iter<T...> = (Observer<T...>) -> () -> (jecs.Entity, T...)
|
||||
|
||||
|
@ -14,24 +15,20 @@ export type Observer<T...> = typeof(setmetatable(
|
|||
{} :: {
|
||||
iter: Iter<T...>,
|
||||
entities: { Entity<nil> },
|
||||
disconnect: (Observer<T...>) -> ()
|
||||
disconnect: (Observer<T...>) -> (),
|
||||
},
|
||||
{} :: {
|
||||
__iter: Iter<T...>,
|
||||
}
|
||||
))
|
||||
|
||||
local function observers_new<T...>(
|
||||
query: Query<T...>,
|
||||
callback: ((Entity<nil>, Id<any>, value: any?) -> ())?
|
||||
): Observer<T...>
|
||||
|
||||
query:cached()
|
||||
|
||||
local world = (query :: Query<T...> & { world: World }).world
|
||||
callback = callback
|
||||
|
||||
local function get_matching_archetypes(world: jecs.World, query: QueryInner<...any>)
|
||||
local archetypes = {}
|
||||
|
||||
for _, archetype in query.compatible_archetypes do
|
||||
archetypes[archetype.id] = true
|
||||
end
|
||||
|
||||
local terms = query.ids
|
||||
local first = terms[1]
|
||||
|
||||
|
@ -40,113 +37,139 @@ local function observers_new<T...>(
|
|||
observer_on_create.callback = function(archetype)
|
||||
archetypes[archetype.id] = true
|
||||
end
|
||||
|
||||
local observers_on_delete = world.observable[jecs.ArchetypeDelete][first]
|
||||
local observer_on_delete = observers_on_delete[#observers_on_delete]
|
||||
|
||||
observer_on_delete.callback = function(archetype)
|
||||
archetypes[archetype.id] = nil
|
||||
end
|
||||
|
||||
local function disconnect()
|
||||
table.remove(observers_on_create, table.find(observers_on_create, observer_on_create))
|
||||
table.remove(observers_on_delete, table.find(observers_on_delete, observer_on_delete))
|
||||
end
|
||||
|
||||
return archetypes, disconnect
|
||||
end
|
||||
|
||||
local function observers_new<T...>(query: Query<T...>, callback: ((Entity<nil>, Id<any>, value: any?) -> ())?): Observer<T...>
|
||||
query:cached()
|
||||
|
||||
local world = (query :: QueryInner<T...>).world
|
||||
callback = callback
|
||||
|
||||
local archetypes, disconnect_query = get_matching_archetypes(world, query :: QueryInner<T...>)
|
||||
|
||||
local terms = query.ids
|
||||
local query_with = query.filter_with or terms
|
||||
|
||||
local entity_index = world.entity_index :: any
|
||||
local i = 0
|
||||
local entities = {}
|
||||
|
||||
local function emplaced<T, a>(
|
||||
entity: jecs.Entity<T>,
|
||||
id: jecs.Id<a>,
|
||||
value: a?
|
||||
)
|
||||
local iter_indexes = {} :: { [Entity]: number }
|
||||
local iter_queue = {} :: { Entity }
|
||||
|
||||
local function remove_queued(entity: jecs.Entity, index: number)
|
||||
if index ~= nil then
|
||||
local last = table.remove(iter_queue)
|
||||
if last and last ~= entity then
|
||||
iter_queue[index] = last
|
||||
iter_indexes[last] = index
|
||||
end
|
||||
iter_indexes[entity] = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function emplaced<T>(entity: jecs.Entity, id: jecs.Id<T>, value: T?)
|
||||
local r = entity_index.sparse_array[jecs.ECS_ID(entity)]
|
||||
|
||||
local index = iter_indexes[entity]
|
||||
if r == nil then
|
||||
remove_queued(entity, index)
|
||||
end
|
||||
local archetype = r.archetype
|
||||
|
||||
if archetypes[archetype.id] then
|
||||
i += 1
|
||||
entities[i] = entity
|
||||
if index == nil then
|
||||
table.insert(iter_queue, entity)
|
||||
iter_indexes[entity] = #iter_queue
|
||||
end
|
||||
if callback ~= nil then
|
||||
callback(entity, id, value)
|
||||
callback(entity :: Entity, id, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, term in terms do
|
||||
local function removed(entity: jecs.Entity)
|
||||
local index = iter_indexes[entity]
|
||||
if index ~= nil then
|
||||
remove_queued(entity, index)
|
||||
end
|
||||
end
|
||||
|
||||
local hooked = {} :: { () -> () }
|
||||
for _, term in query_with do
|
||||
if jecs.IS_PAIR(term) then
|
||||
term = jecs.ECS_PAIR_FIRST(term)
|
||||
end
|
||||
world:added(term, emplaced)
|
||||
world:changed(term, emplaced)
|
||||
end
|
||||
table.insert(hooked, world:added(term, emplaced))
|
||||
table.insert(hooked, world:changed(term, emplaced))
|
||||
table.insert(hooked, world:removed(term, removed))
|
||||
end
|
||||
|
||||
local function disconnect()
|
||||
table.remove(observers_on_create, table.find(
|
||||
observers_on_create,
|
||||
observer_on_create
|
||||
))
|
||||
local function disconnect()
|
||||
disconnect_query()
|
||||
for _, unhook in hooked do
|
||||
unhook()
|
||||
end
|
||||
end
|
||||
|
||||
table.remove(observers_on_delete, table.find(
|
||||
observers_on_delete,
|
||||
observer_on_delete
|
||||
))
|
||||
end
|
||||
local function iter()
|
||||
local row = #iter_queue
|
||||
return function()
|
||||
if row == 0 then
|
||||
table.clear(iter_queue)
|
||||
table.clear(iter_indexes)
|
||||
end
|
||||
local entity = iter_queue[row]
|
||||
row -= 1
|
||||
return entity
|
||||
end
|
||||
end
|
||||
|
||||
local function iter()
|
||||
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
|
||||
local observer = {
|
||||
disconnect = disconnect,
|
||||
entities = iter_queue,
|
||||
__iter = iter,
|
||||
iter = iter,
|
||||
}
|
||||
|
||||
local observer = {
|
||||
disconnect = disconnect,
|
||||
entities = entities,
|
||||
__iter = iter,
|
||||
iter = iter
|
||||
}
|
||||
setmetatable(observer, observer)
|
||||
|
||||
setmetatable(observer, observer)
|
||||
|
||||
return (observer :: any) :: Observer<T...>
|
||||
return (observer :: any) :: Observer<T...>
|
||||
end
|
||||
|
||||
local function monitors_new<T...>(
|
||||
query: Query<T...>,
|
||||
callback: ((Entity<nil>, Id<any>, value: any?) -> ())?
|
||||
): Observer<T...>
|
||||
|
||||
local function monitors_new<T...>(query: Query<T...>, callback: ((Entity<nil>, Id<any>, value: any?) -> ())?): Observer<T...>
|
||||
query:cached()
|
||||
|
||||
local world = (query :: Query<T...> & { world: World }).world
|
||||
local world = (query :: QueryInner<T...>).world
|
||||
|
||||
local archetypes, disconnect_query = get_matching_archetypes(world, query :: QueryInner<T...>)
|
||||
|
||||
local archetypes = {}
|
||||
local terms = query.ids
|
||||
local first = terms[1]
|
||||
local query_with = query.filter_with or terms
|
||||
|
||||
local observers_on_create = world.observable[jecs.ArchetypeCreate][first]
|
||||
local observer_on_create = observers_on_create[#observers_on_create]
|
||||
observer_on_create.callback = function(archetype)
|
||||
archetypes[archetype.id] = true
|
||||
end
|
||||
local observers_on_delete = world.observable[jecs.ArchetypeDelete][first]
|
||||
local observer_on_delete = observers_on_delete[#observers_on_delete]
|
||||
observer_on_delete.callback = function(archetype)
|
||||
archetypes[archetype.id] = nil
|
||||
end
|
||||
local entity_index = world.entity_index :: any
|
||||
local i = 0
|
||||
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(
|
||||
entity_index, entity :: any) :: jecs.Record
|
||||
local function emplaced<T, a>(entity: jecs.Entity<T>, id: jecs.Id<a>, value: a?)
|
||||
local r = jecs.entity_index_try_get_fast(entity_index, entity :: any) :: jecs.Record
|
||||
if not r or not r.archetype then
|
||||
if callback then
|
||||
callback(entity :: Entity, jecs.OnRemove)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local archetype = r.archetype
|
||||
|
||||
|
@ -154,14 +177,18 @@ local function monitors_new<T...>(
|
|||
i += 1
|
||||
entities[i] = entity
|
||||
if callback ~= nil then
|
||||
callback(entity, jecs.OnAdd)
|
||||
callback(entity :: Entity, jecs.OnAdd)
|
||||
end
|
||||
else
|
||||
if callback ~= nil then
|
||||
callback(entity :: Entity, jecs.OnRemove)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function removed(entity: jecs.Entity, component: jecs.Id)
|
||||
local r = jecs.record(world, entity)
|
||||
if not archetypes[r.archetype.id] then
|
||||
if not r or not archetypes[r.archetype.id] then
|
||||
return
|
||||
end
|
||||
local EcsOnRemove = jecs.OnRemove :: jecs.Id
|
||||
|
@ -170,52 +197,48 @@ local function monitors_new<T...>(
|
|||
end
|
||||
end
|
||||
|
||||
for _, term in terms do
|
||||
local hooked = {} :: { () -> () }
|
||||
for _, term in query_with do
|
||||
if jecs.IS_PAIR(term) then
|
||||
term = jecs.ECS_PAIR_FIRST(term)
|
||||
end
|
||||
world:added(term, emplaced)
|
||||
world:removed(term, removed)
|
||||
end
|
||||
table.insert(hooked, world:added(term, emplaced))
|
||||
table.insert(hooked, world:removed(term, removed))
|
||||
end
|
||||
|
||||
local function disconnect()
|
||||
table.remove(observers_on_create, table.find(
|
||||
observers_on_create,
|
||||
observer_on_create
|
||||
))
|
||||
local function disconnect()
|
||||
disconnect_query()
|
||||
for _, unhook in hooked do
|
||||
unhook()
|
||||
end
|
||||
end
|
||||
|
||||
table.remove(observers_on_delete, table.find(
|
||||
observers_on_delete,
|
||||
observer_on_delete
|
||||
))
|
||||
end
|
||||
|
||||
local function iter()
|
||||
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
|
||||
local function iter()
|
||||
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
|
||||
|
||||
local observer = {
|
||||
disconnect = disconnect,
|
||||
entities = entities,
|
||||
__iter = iter,
|
||||
iter = iter
|
||||
}
|
||||
disconnect = disconnect,
|
||||
entities = entities,
|
||||
__iter = iter,
|
||||
iter = iter,
|
||||
}
|
||||
|
||||
setmetatable(observer, observer)
|
||||
setmetatable(observer, observer)
|
||||
|
||||
return (observer :: any) :: Observer<T...>
|
||||
return (observer :: any) :: Observer<T...>
|
||||
end
|
||||
|
||||
return {
|
||||
monitor = monitors_new,
|
||||
observer = observers_new
|
||||
observer = observers_new,
|
||||
}
|
||||
|
|
|
@ -2,33 +2,12 @@
|
|||
--!native
|
||||
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local Matter = require(ReplicatedStorage.DevPackages.Matter)
|
||||
local ecr = require(ReplicatedStorage.DevPackages.ecr)
|
||||
local newWorld = Matter.World.new()
|
||||
|
||||
local jecs = require(ReplicatedStorage.Lib:Clone())
|
||||
local mirror = require(ReplicatedStorage.mirror:Clone())
|
||||
local mcs = mirror.world()
|
||||
local ecs = jecs.world()
|
||||
|
||||
local A1 = Matter.component()
|
||||
local A2 = Matter.component()
|
||||
local A3 = Matter.component()
|
||||
local A4 = Matter.component()
|
||||
local A5 = Matter.component()
|
||||
local A6 = Matter.component()
|
||||
local A7 = Matter.component()
|
||||
local A8 = Matter.component()
|
||||
|
||||
local B1 = ecr.component()
|
||||
local B2 = ecr.component()
|
||||
local B3 = ecr.component()
|
||||
local B4 = ecr.component()
|
||||
local B5 = ecr.component()
|
||||
local B6 = ecr.component()
|
||||
local B7 = ecr.component()
|
||||
local B8 = ecr.component()
|
||||
|
||||
local D1 = ecs:component()
|
||||
local D2 = ecs:component()
|
||||
local D3 = ecs:component()
|
||||
|
@ -47,90 +26,53 @@ local E6 = mcs:component()
|
|||
local E7 = mcs:component()
|
||||
local E8 = mcs:component()
|
||||
|
||||
local registry2 = ecr.registry()
|
||||
|
||||
local function flip()
|
||||
return math.random() >= 0.25
|
||||
return math.random() >= 0.3
|
||||
end
|
||||
|
||||
local N = 2 ^ 16 - 2
|
||||
local archetypes = {}
|
||||
|
||||
local hm = 0
|
||||
for i = 1, N do
|
||||
local id = registry2.create()
|
||||
local combination = ""
|
||||
local n = newWorld:spawn()
|
||||
local entity = ecs:entity()
|
||||
local m = mcs:entity()
|
||||
|
||||
if flip() then
|
||||
registry2:set(id, B1, { value = true })
|
||||
ecs:set(entity, D1, { value = true })
|
||||
newWorld:insert(n, A1({ value = true }))
|
||||
mcs:set(m, E1, { value = 2 })
|
||||
ecs:add(entity, entity)
|
||||
mcs:add(m, m)
|
||||
end
|
||||
if flip() then
|
||||
combination ..= "B"
|
||||
registry2:set(id, B2, { value = true })
|
||||
ecs:set(entity, D2, { value = true })
|
||||
mcs:set(m, E2, { value = 2 })
|
||||
newWorld:insert(n, A2({ value = true }))
|
||||
ecs:set(entity, D1, true)
|
||||
mcs:set(m, E1, true)
|
||||
end
|
||||
if flip() then
|
||||
combination ..= "C"
|
||||
registry2:set(id, B3, { value = true })
|
||||
ecs:set(entity, D3, { value = true })
|
||||
mcs:set(m, E3, { value = 2 })
|
||||
newWorld:insert(n, A3({ value = true }))
|
||||
ecs:set(entity, D2, true)
|
||||
mcs:set(m, E2, true)
|
||||
end
|
||||
if flip() then
|
||||
combination ..= "D"
|
||||
registry2:set(id, B4, { value = true })
|
||||
ecs:set(entity, D4, { value = true })
|
||||
mcs:set(m, E4, { value = 2 })
|
||||
|
||||
newWorld:insert(n, A4({ value = true }))
|
||||
ecs:set(entity, D3, true)
|
||||
mcs:set(m, E3, true)
|
||||
end
|
||||
if flip() then
|
||||
combination ..= "E"
|
||||
registry2:set(id, B5, { value = true })
|
||||
ecs:set(entity, D5, { value = true })
|
||||
mcs:set(m, E5, { value = 2 })
|
||||
|
||||
newWorld:insert(n, A5({ value = true }))
|
||||
ecs:set(entity, D4, true)
|
||||
mcs:set(m, E4, true)
|
||||
end
|
||||
if flip() then
|
||||
combination ..= "F"
|
||||
registry2:set(id, B6, { value = true })
|
||||
ecs:set(entity, D6, { value = true })
|
||||
mcs:set(m, E6, { value = 2 })
|
||||
newWorld:insert(n, A6({ value = true }))
|
||||
ecs:set(entity, D5, true)
|
||||
mcs:set(m, E5, true)
|
||||
end
|
||||
if flip() then
|
||||
combination ..= "G"
|
||||
registry2:set(id, B7, { value = true })
|
||||
ecs:set(entity, D7, { value = true })
|
||||
mcs:set(m, E7, { value = 2 })
|
||||
newWorld:insert(n, A7({ value = true }))
|
||||
ecs:set(entity, D6, true)
|
||||
mcs:set(m, E6, true)
|
||||
end
|
||||
if flip() then
|
||||
combination ..= "H"
|
||||
registry2:set(id, B8, { value = true })
|
||||
newWorld:insert(n, A8({ value = true }))
|
||||
ecs:set(entity, D8, { value = true })
|
||||
mcs:set(m, E8, { value = 2 })
|
||||
ecs:set(entity, D7, true)
|
||||
mcs:set(m, E7, true)
|
||||
end
|
||||
|
||||
if combination:find("BCDF") then
|
||||
if not archetypes[combination] then
|
||||
print(combination)
|
||||
end
|
||||
hm += 1
|
||||
if flip() then
|
||||
ecs:set(entity, D8, true)
|
||||
mcs:set(m, E8, true)
|
||||
end
|
||||
archetypes[combination] = true
|
||||
end
|
||||
print("TEST", hm)
|
||||
|
||||
local count = 0
|
||||
|
||||
|
@ -138,7 +80,11 @@ for _, archetype in ecs:query(D2, D4, D6, D8):archetypes() do
|
|||
count += #archetype.entities
|
||||
end
|
||||
|
||||
print(count)
|
||||
|
||||
local mq = mcs:query(E2, E4, E6, E8):cached()
|
||||
local jq = ecs:query(D2, D4, D6, D8):cached()
|
||||
|
||||
print(count, #jq:archetypes())
|
||||
|
||||
return {
|
||||
ParameterGenerator = function()
|
||||
|
@ -157,12 +103,12 @@ return {
|
|||
-- end,
|
||||
--
|
||||
Mirror = function()
|
||||
for entityId, firstComponent in mcs:query(E2, E4, E6, E8) do
|
||||
for entityId, firstComponent in mq do
|
||||
end
|
||||
end,
|
||||
|
||||
Jecs = function()
|
||||
for entityId, firstComponent in ecs:query(D2, D4, D6, D8) do
|
||||
for entityId, firstComponent in jq do
|
||||
end
|
||||
end,
|
||||
},
|
||||
|
|
52
jecs.luau
52
jecs.luau
|
@ -216,7 +216,8 @@ export type World = {
|
|||
children: <T>(self: World, id: Id<T>) -> () -> Entity,
|
||||
|
||||
--- Searches the world for entities that match a given query
|
||||
query: (<A>(World, Id<A>) -> Query<A>)
|
||||
query: ((World) -> Query<nil>)
|
||||
& (<A>(World, Id<A>) -> Query<A>)
|
||||
& (<A, B>(World, Id<A>, Id<B>) -> Query<A, B>)
|
||||
& (<A, B, C>(World, Id<A>, Id<B>, Id<C>) -> Query<A, B, C>)
|
||||
& (<A, B, C, D>(World, Id<A>, Id<B>, Id<C>, Id<D>) -> Query<A, B, C, D>)
|
||||
|
@ -1253,7 +1254,29 @@ local function query_iter_init(query: QueryInner): () -> (number, ...any)
|
|||
local a: Column, b: Column, c: Column, d: Column
|
||||
local e: Column, f: Column, g: Column, h: Column
|
||||
|
||||
if not B then
|
||||
if not A then
|
||||
function world_query_iter_next(): any
|
||||
local entity = entities[i]
|
||||
while entity == nil do
|
||||
lastArchetype += 1
|
||||
archetype = compatible_archetypes[lastArchetype]
|
||||
if not archetype then
|
||||
return nil
|
||||
end
|
||||
|
||||
entities = archetype.entities
|
||||
i = #entities
|
||||
if i == 0 then
|
||||
continue
|
||||
end
|
||||
entity = entities[i]
|
||||
end
|
||||
i -= 1
|
||||
return entity
|
||||
end
|
||||
query.next = world_query_iter_next
|
||||
return world_query_iter_next
|
||||
elseif not B then
|
||||
a = columns_map[A]
|
||||
elseif not C then
|
||||
a = columns_map[A]
|
||||
|
@ -1650,7 +1673,8 @@ local function query_cached(query: QueryInner)
|
|||
entities = archetype.entities
|
||||
i = #entities
|
||||
columns_map = archetype.columns_map
|
||||
if not B then
|
||||
if not A then
|
||||
elseif not B then
|
||||
a = columns_map[A]
|
||||
elseif not C then
|
||||
a = columns_map[A]
|
||||
|
@ -1699,7 +1723,27 @@ local function query_cached(query: QueryInner)
|
|||
return world_query_iter_next
|
||||
end
|
||||
|
||||
if not B then
|
||||
if not A then
|
||||
function world_query_iter_next(): any
|
||||
local entity = entities[i]
|
||||
while entity == nil do
|
||||
lastArchetype += 1
|
||||
archetype = compatible_archetypes[lastArchetype]
|
||||
if not archetype then
|
||||
return nil
|
||||
end
|
||||
|
||||
entities = archetype.entities
|
||||
i = #entities
|
||||
if i == 0 then
|
||||
continue
|
||||
end
|
||||
entity = entities[i]
|
||||
end
|
||||
i -= 1
|
||||
return entity
|
||||
end
|
||||
elseif not B then
|
||||
function world_query_iter_next(): any
|
||||
local entity = entities[i]
|
||||
while entity == nil do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@rbxts/jecs",
|
||||
"version": "0.9.0-rc.12",
|
||||
"version": "0.9.0",
|
||||
"description": "Stupidly fast Entity Component System",
|
||||
"main": "jecs.luau",
|
||||
"repository": {
|
||||
|
|
|
@ -837,6 +837,9 @@ TEST("world:delete()", function()
|
|||
CHECK(destroyed)
|
||||
CHECK(not world:contains(child))
|
||||
end
|
||||
if true then
|
||||
return
|
||||
end
|
||||
|
||||
do CASE "Should delete children in different archetypes if they have the same parent"
|
||||
local world = jecs.world()
|
||||
|
@ -1706,6 +1709,36 @@ end)
|
|||
TEST("world:query()", function()
|
||||
local N = 2^8
|
||||
|
||||
do CASE "queries should accept zero-ids provided they use :with for the leading component"
|
||||
local world = jecs.world()
|
||||
local A = world:component()
|
||||
local B = world:component()
|
||||
|
||||
local e1 = world:entity()
|
||||
world:set(e1, A, "A")
|
||||
|
||||
local e2 = world:entity()
|
||||
world:set(e2, A, "A")
|
||||
world:set(e2, B, "B")
|
||||
|
||||
for e, a in world:query():with(A) do
|
||||
CHECK(e == e1 or e == e2)
|
||||
CHECK(a == nil)
|
||||
if e == e1 then
|
||||
CHECK(world:has(e1, A))
|
||||
CHECK(not world:has(e1, B))
|
||||
elseif e == e2 then
|
||||
CHECK(world:has(e2, A, B))
|
||||
end
|
||||
end
|
||||
for e, a in world:query():with(A):without(B) do
|
||||
CHECK(e == e1)
|
||||
CHECK(a == nil)
|
||||
CHECK(world:has(e1, A))
|
||||
CHECK(not world:has(e1, B))
|
||||
end
|
||||
end
|
||||
|
||||
do CASE "cached"
|
||||
local world = jecs.world()
|
||||
local Foo = world:component()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ukendio/jecs"
|
||||
version = "0.9.0-rc.12"
|
||||
version = "0.9.0"
|
||||
registry = "https://github.com/UpliftGames/wally-index"
|
||||
realm = "shared"
|
||||
license = "MIT"
|
||||
|
|
Loading…
Reference in a new issue