Remove focus
Some checks are pending
analysis / Run Luau Analyze (push) Waiting to run
deploy-docs / build (push) Waiting to run
deploy-docs / Deploy (push) Blocked by required conditions
publish-npm / publish (push) Waiting to run
unit-testing / Run Luau Tests (push) Waiting to run

This commit is contained in:
Ukendio 2025-08-31 03:38:06 +02:00
parent 1eecaac96f
commit 3dacb2af80
5 changed files with 110 additions and 87 deletions

View file

@ -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)
if flip() then
ecs:set(entity, D8, true)
mcs:set(m, E8, true)
end
hm += 1
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,
},

View file

@ -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

View file

@ -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": {

View file

@ -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()

View file

@ -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"