mirror of
https://github.com/Ukendio/jecs.git
synced 2026-02-04 15:15:21 +00:00
Add DEBUG mode with special assertions
This commit is contained in:
parent
e4d0fb447d
commit
ef4d880b0a
6 changed files with 853 additions and 654 deletions
|
|
@ -1,4 +1,4 @@
|
|||
[tools]
|
||||
wally = "upliftgames/wally@0.3.2"
|
||||
rojo = "rojo-rbx/rojo@7.4.4"
|
||||
luau = "luau-lang/luau@0.701"
|
||||
rojo = "rojo-rbx/rojo@7.7.0-rc.1"
|
||||
luau = "luau-lang/luau@0.703.0"
|
||||
|
|
|
|||
1174
src/jecs.luau
1174
src/jecs.luau
File diff suppressed because it is too large
Load diff
|
|
@ -12,16 +12,16 @@
|
|||
"ReplicatedStorage": {
|
||||
"$className": "ReplicatedStorage",
|
||||
"Lib": {
|
||||
"$path": "../src/jecs.luau"
|
||||
"$path": "../../src/jecs.luau"
|
||||
},
|
||||
"benches": {
|
||||
"$path": "benches"
|
||||
"$path": "visual"
|
||||
},
|
||||
"mirror": {
|
||||
"$path": "mirror.luau"
|
||||
"$path": "../../src/mirror.luau"
|
||||
},
|
||||
"DevPackages": {
|
||||
"$path": "benches/visual/DevPackages"
|
||||
"$path": "visual/DevPackages"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,48 +27,11 @@ do
|
|||
G: jecs.Id,
|
||||
H: jecs.Id
|
||||
)
|
||||
BENCH("1 component", function()
|
||||
for _ in world:query(A) do
|
||||
end
|
||||
end)
|
||||
|
||||
BENCH("2 component", function()
|
||||
for _ in world:query(B, A) do
|
||||
end
|
||||
end)
|
||||
|
||||
BENCH("4 component", function()
|
||||
for _ in world:query(D, C, B, A) do
|
||||
end
|
||||
end)
|
||||
|
||||
BENCH("8 component", function()
|
||||
for _ in world:query(H, G, F, E, D, C, B, A) do
|
||||
end
|
||||
end)
|
||||
|
||||
local e = world:entity()
|
||||
world:set(e, A, true)
|
||||
world:set(e, B, true)
|
||||
world:set(e, C, true)
|
||||
world:set(e, D, true)
|
||||
world:set(e, E, true)
|
||||
world:set(e, F, true)
|
||||
world:set(e, G, true)
|
||||
world:set(e, H, true)
|
||||
|
||||
BENCH("Update Data", function()
|
||||
for _ = 1, 100 do
|
||||
world:set(e, A, false)
|
||||
world:set(e, B, false)
|
||||
world:set(e, C, false)
|
||||
world:set(e, D, false)
|
||||
world:set(e, E, false)
|
||||
world:set(e, F, false)
|
||||
world:set(e, G, false)
|
||||
world:set(e, H, false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local D1 = ecs:component()
|
||||
|
|
@ -86,8 +49,9 @@ do
|
|||
|
||||
local added = 0
|
||||
local archetypes = {}
|
||||
for i = 1, 2 ^ 16 - 2 do
|
||||
for i = 1, 2 ^ 12 - 2 do
|
||||
local entity = ecs:entity()
|
||||
ecs:add(entity, entity)
|
||||
|
||||
local combination = ""
|
||||
|
||||
|
|
@ -153,48 +117,10 @@ do
|
|||
G: jecs.Id,
|
||||
H: jecs.Id
|
||||
)
|
||||
BENCH("1 component", function()
|
||||
for _ in world:query(A) do
|
||||
end
|
||||
end)
|
||||
|
||||
BENCH("2 component", function()
|
||||
for _ in world:query(B, A) do
|
||||
end
|
||||
end)
|
||||
|
||||
BENCH("4 component", function()
|
||||
for _ in world:query(D, C, B, A) do
|
||||
end
|
||||
end)
|
||||
|
||||
BENCH("8 component", function()
|
||||
for _ in world:query(H, G, F, E, D, C, B, A) do
|
||||
end
|
||||
end)
|
||||
|
||||
local e = world:entity()
|
||||
world:set(e, A, true)
|
||||
world:set(e, B, true)
|
||||
world:set(e, C, true)
|
||||
world:set(e, D, true)
|
||||
world:set(e, E, true)
|
||||
world:set(e, F, true)
|
||||
world:set(e, G, true)
|
||||
world:set(e, H, true)
|
||||
|
||||
BENCH("Update Data", function()
|
||||
for _ = 1, 100 do
|
||||
world:set(e, A, false)
|
||||
world:set(e, B, false)
|
||||
world:set(e, C, false)
|
||||
world:set(e, D, false)
|
||||
world:set(e, E, false)
|
||||
world:set(e, F, false)
|
||||
world:set(e, G, false)
|
||||
world:set(e, H, false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local D1 = ecs:component()
|
||||
|
|
@ -207,13 +133,14 @@ do
|
|||
local D8 = ecs:component()
|
||||
|
||||
local function flip()
|
||||
return math.random() >= 0.15
|
||||
return math.random() >= 0.5
|
||||
end
|
||||
|
||||
local added = 0
|
||||
local archetypes = {}
|
||||
for i = 1, 2 ^ 16 - 2 do
|
||||
for i = 1, 2 ^ 12 - 2 do
|
||||
local entity = ecs:entity()
|
||||
ecs:add(entity, entity)
|
||||
|
||||
local combination = ""
|
||||
|
||||
|
|
@ -246,11 +173,9 @@ do
|
|||
ecs:set(entity, D8, { value = true })
|
||||
end
|
||||
|
||||
if #combination == 7 then
|
||||
added += 1
|
||||
if flip() then
|
||||
ecs:set(entity, D1, { value = true })
|
||||
end
|
||||
archetypes[combination] = true
|
||||
end
|
||||
|
||||
local a = 0
|
||||
|
|
|
|||
|
|
@ -50,85 +50,54 @@ local E8 = mcs:component()
|
|||
local registry2 = ecr.registry()
|
||||
|
||||
local function flip()
|
||||
return math.random() >= 0.25
|
||||
return math.random() >= 0.5
|
||||
end
|
||||
|
||||
local N = 2 ^ 16 - 2
|
||||
local N = 2 ^ 12- 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
|
||||
ecs:add(entity, entity)
|
||||
mcs:add(m, m)
|
||||
end
|
||||
|
||||
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:set(entity, D1, {value = true})
|
||||
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 }))
|
||||
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 }))
|
||||
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 }))
|
||||
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 }))
|
||||
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 }))
|
||||
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 }))
|
||||
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 })
|
||||
end
|
||||
|
||||
if combination:find("BCDF") then
|
||||
if not archetypes[combination] then
|
||||
print(combination)
|
||||
end
|
||||
hm += 1
|
||||
end
|
||||
archetypes[combination] = true
|
||||
end
|
||||
print("TEST", hm)
|
||||
|
||||
|
|
@ -140,30 +109,38 @@ end
|
|||
|
||||
print(count)
|
||||
|
||||
local mq = mcs:query(E1, E2, E3, E4)
|
||||
local jq = ecs:query(D1, D2, D3, D4)
|
||||
|
||||
return {
|
||||
ParameterGenerator = function()
|
||||
return
|
||||
end,
|
||||
|
||||
Functions = {
|
||||
Matter = function()
|
||||
for entityId, firstComponent in newWorld:query(A2, A4, A6, A8) do
|
||||
end
|
||||
end,
|
||||
|
||||
ECR = function()
|
||||
for entityId, firstComponent in registry2:view(B2, B4, B6, B8) do
|
||||
end
|
||||
end,
|
||||
|
||||
-- Mirror = function()
|
||||
-- for entityId, firstComponent in mcs:query(E2, E4, E6, E8) do
|
||||
-- Matter = function()
|
||||
-- for entityId, firstComponent in newWorld:query(A2, A4, A6, A8) do
|
||||
-- end
|
||||
-- end,
|
||||
|
||||
Jecs = function()
|
||||
for entityId, firstComponent in ecs:query(D2, D4, D6, D8) do
|
||||
-- ECR = function()
|
||||
-- for entityId, firstComponent in registry2:view(B2, B4, B6, B8) do
|
||||
-- end
|
||||
-- end,
|
||||
|
||||
Mirror = function()
|
||||
for i = 1, 10 do
|
||||
for entityId, firstComponent in mq:iter() do
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
Jecs = function()
|
||||
for i = 1, 10 do
|
||||
for entityId, firstComponent in jq:iter() do
|
||||
end
|
||||
end
|
||||
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
101
test/tests.luau
101
test/tests.luau
|
|
@ -24,81 +24,7 @@ type Id<T=unknown> = jecs.Id<T>
|
|||
local entity_visualiser = require("@modules/entity_visualiser")
|
||||
local dwi = entity_visualiser.stringify
|
||||
|
||||
TEST("optimize idr_r removal", function()
|
||||
|
||||
local pair = jecs.pair
|
||||
local world = jecs.world()
|
||||
local rel = world:component()
|
||||
local A = world:component()
|
||||
local B = world:component()
|
||||
|
||||
local t1 = world:entity()
|
||||
local t2 = world:entity()
|
||||
|
||||
local entities = {} :: { jecs.Entity }
|
||||
|
||||
for i = 1, 10 do
|
||||
|
||||
local e1 = world:entity()
|
||||
local e2 = world:entity()
|
||||
|
||||
world:set(e1, A, true)
|
||||
world:set(e2, A, true)
|
||||
world:add(e1, pair(B, t1))
|
||||
world:add(e1, pair(B, t2))
|
||||
world:add(e2, pair(B, t1))
|
||||
world:add(e2, pair(B, t2))
|
||||
|
||||
table.insert(entities, e1)
|
||||
table.insert(entities, e2)
|
||||
end
|
||||
|
||||
local e1 = world:entity()
|
||||
local e2 = world:entity()
|
||||
|
||||
table.insert(entities, e1)
|
||||
table.insert(entities, e2)
|
||||
|
||||
world:set(e1, A, true)
|
||||
world:set(e2, A, true)
|
||||
world:add(e1, pair(B, t1))
|
||||
world:add(e1, pair(B, t2))
|
||||
world:add(e2, pair(B, t1))
|
||||
world:add(e2, pair(B, t2))
|
||||
|
||||
BENCH("delete B", function()
|
||||
world:delete(B)
|
||||
end)
|
||||
|
||||
for _, e in entities do
|
||||
CHECK(world:has(e, A))
|
||||
CHECK(not world:target(e, B))
|
||||
CHECK(not world:target(e, B))
|
||||
end
|
||||
|
||||
end)
|
||||
TEST("deleting t1's archetype before invoking its onremove hooks", function()
|
||||
local pair = jecs.pair
|
||||
local world = jecs.world()
|
||||
local rel = world:component()
|
||||
|
||||
local t1 = world:entity()
|
||||
local t2 = world:entity()
|
||||
|
||||
--[[
|
||||
weirdly enough if i do this (only when adding childof relation after adding (rel, t2) to t1) it does not error. Probably a red herring
|
||||
|
||||
world:add(t2, pair(rel, t1))
|
||||
world:add(t1, pair(rel, t2))
|
||||
world:add(t2, pair(jecs.ChildOf, t1))
|
||||
--]]
|
||||
|
||||
-- this causes world:delete to error
|
||||
world:add(t2, pair(jecs.ChildOf, t1))
|
||||
world:add(t1, pair(rel, t2))
|
||||
|
||||
world:delete(t1)
|
||||
end)
|
||||
FOCUS()
|
||||
TEST("reproduce idr_t nil archetype bug", function()
|
||||
local world = jecs.world()
|
||||
|
||||
|
|
@ -124,31 +50,46 @@ TEST("reproduce idr_t nil archetype bug", function()
|
|||
local dst = src and jecs.archetype_traverse_remove(world, id, src)
|
||||
end)
|
||||
|
||||
local batches = 10
|
||||
local batchSize = 20
|
||||
local batchSize = 200
|
||||
|
||||
local trackedEntities: { [number]: { parentId: number? } } = {}
|
||||
|
||||
for batch = 1, batches do
|
||||
for i = 1, batchSize do
|
||||
|
||||
local root = world:entity()
|
||||
world:add(root, jecs.pair(jecs.ChildOf, char))
|
||||
-- world:add(root, jecs.pair(jecs.ChildOf, char))
|
||||
|
||||
-- Removing animator from trackEntity1 causes it to stop happening
|
||||
local trackEntity1 = world:entity()
|
||||
world:set(trackEntity1, cts.Animator, 0)
|
||||
world:add(trackEntity1, jecs.pair(jecs.ChildOf, root))
|
||||
world:set(trackEntity1, jecs.Name, "trackEntity1v"..i)
|
||||
trackedEntities[trackEntity1] = { parentId = root }
|
||||
|
||||
-- Removing animator from trackEntity2 causes it to happen less frequently
|
||||
local trackEntity2 = world:entity()
|
||||
world:set(trackEntity2, cts.Animator, 0)
|
||||
world:add(trackEntity2, jecs.pair(jecs.ChildOf, root))
|
||||
world:set(trackEntity2, jecs.Name, "trackEntity2v"..i)
|
||||
trackedEntities[trackEntity2] = { parentId = root }
|
||||
|
||||
-- Removing this, but keeping Animator on the other 2 causes it to stop happening
|
||||
world:set(trackEntity1, cts.VelocitizeAnimationWeight, 0)
|
||||
|
||||
local q = world:query(jecs.pair(jecs.ChildOf, jecs.w)):cached()
|
||||
|
||||
|
||||
print("---- delete start root")
|
||||
print("--- root", world:contains(root), root, jecs.ECS_ID(root), jecs.ECS_GENERATION(root))
|
||||
world:delete(root)
|
||||
print("---- delete end root")
|
||||
|
||||
for entity in q do
|
||||
local parent = world:parent(entity) :: jecs.Entity
|
||||
print("--- root", world:contains(root), jecs.ECS_ID(root), jecs.ECS_GENERATION(root))
|
||||
print(world:get(entity, jecs.Name), jecs.ECS_ID(parent), jecs.ECS_GENERATION(parent), "root ->", root)
|
||||
CHECK(world:parent(entity) == nil)
|
||||
end
|
||||
for entityId, info in trackedEntities do
|
||||
if world:contains(entityId) and not world:parent(entityId :: any) then
|
||||
print(`bugged entity found: {entityId}`)
|
||||
|
|
@ -156,8 +97,6 @@ TEST("reproduce idr_t nil archetype bug", function()
|
|||
print(`batch = {batch}, i = {i}`)
|
||||
print("==========================================")
|
||||
trackedEntities[entityId] = nil
|
||||
world:delete(entityId)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue