mirror of
https://github.com/BlackMATov/evolved.lua.git
synced 2025-12-15 04:15:28 +07:00
aos variant of spawn/clone functions WIP
This commit is contained in:
@@ -95,6 +95,9 @@ execute :: query -> {execute_state? -> chunk?, entity[]?, integer?}, execute_sta
|
||||
|
||||
process :: system... -> ()
|
||||
|
||||
spawn :: <fragment, component>? -> entity
|
||||
clone :: entity -> <fragment, component>? -> entity
|
||||
|
||||
spawn_at :: chunk?, fragment[]?, component[]? -> entity
|
||||
spawn_as :: entity?, fragment[]?, component[]? -> entity
|
||||
spawn_with :: fragment[]?, component[]? -> entity
|
||||
|
||||
@@ -528,6 +528,171 @@ basics.describe_bench(string.format('create and destroy %d entities with 5 compo
|
||||
|
||||
print '----------------------------------------'
|
||||
|
||||
basics.describe_bench(string.format('create and destroy %d entities with 1 components / spawn', N),
|
||||
---@param entities evolved.id[]
|
||||
function(entities)
|
||||
local spawn = evo.spawn
|
||||
|
||||
local components = { [F1] = true }
|
||||
|
||||
for i = 1, N do
|
||||
entities[i] = spawn(components)
|
||||
end
|
||||
|
||||
evo.batch_destroy(Q1)
|
||||
end, function()
|
||||
return {}
|
||||
end)
|
||||
|
||||
basics.describe_bench(string.format('create and destroy %d entities with 2 components / spawn', N),
|
||||
---@param entities evolved.id[]
|
||||
function(entities)
|
||||
local spawn = evo.spawn
|
||||
|
||||
local components = { [F1] = true, [F2] = true }
|
||||
|
||||
for i = 1, N do
|
||||
entities[i] = spawn(components)
|
||||
end
|
||||
|
||||
evo.batch_destroy(Q1)
|
||||
end, function()
|
||||
return {}
|
||||
end)
|
||||
|
||||
basics.describe_bench(string.format('create and destroy %d entities with 3 components / spawn', N),
|
||||
---@param entities evolved.id[]
|
||||
function(entities)
|
||||
local spawn = evo.spawn
|
||||
|
||||
local components = { [F1] = true, [F2] = true, [F3] = true }
|
||||
|
||||
for i = 1, N do
|
||||
entities[i] = spawn(components)
|
||||
end
|
||||
|
||||
evo.batch_destroy(Q1)
|
||||
end, function()
|
||||
return {}
|
||||
end)
|
||||
|
||||
basics.describe_bench(string.format('create and destroy %d entities with 4 components / spawn', N),
|
||||
---@param entities evolved.id[]
|
||||
function(entities)
|
||||
local spawn = evo.spawn
|
||||
|
||||
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true }
|
||||
|
||||
for i = 1, N do
|
||||
entities[i] = spawn(components)
|
||||
end
|
||||
|
||||
evo.batch_destroy(Q1)
|
||||
end, function()
|
||||
return {}
|
||||
end)
|
||||
|
||||
basics.describe_bench(string.format('create and destroy %d entities with 5 components / spawn', N),
|
||||
---@param entities evolved.id[]
|
||||
function(entities)
|
||||
local spawn = evo.spawn
|
||||
|
||||
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
|
||||
|
||||
for i = 1, N do
|
||||
entities[i] = spawn(components)
|
||||
end
|
||||
|
||||
evo.batch_destroy(Q1)
|
||||
end, function()
|
||||
return {}
|
||||
end)
|
||||
|
||||
print '----------------------------------------'
|
||||
|
||||
|
||||
basics.describe_bench(string.format('create and destroy %d entities with 1 components / clone', N),
|
||||
---@param entities evolved.id[]
|
||||
function(entities)
|
||||
local clone = evo.clone
|
||||
|
||||
local prefab = evo.spawn({ [F1] = true })
|
||||
|
||||
for i = 1, N do
|
||||
entities[i] = clone(prefab)
|
||||
end
|
||||
|
||||
evo.batch_destroy(Q1)
|
||||
end, function()
|
||||
return {}
|
||||
end)
|
||||
|
||||
basics.describe_bench(string.format('create and destroy %d entities with 2 components / clone', N),
|
||||
---@param entities evolved.id[]
|
||||
function(entities)
|
||||
local clone = evo.clone
|
||||
|
||||
local prefab = evo.spawn({ [F1] = true, [F2] = true })
|
||||
|
||||
for i = 1, N do
|
||||
entities[i] = clone(prefab)
|
||||
end
|
||||
|
||||
evo.batch_destroy(Q1)
|
||||
end, function()
|
||||
return {}
|
||||
end)
|
||||
|
||||
basics.describe_bench(string.format('create and destroy %d entities with 3 components / clone', N),
|
||||
---@param entities evolved.id[]
|
||||
function(entities)
|
||||
local clone = evo.clone
|
||||
|
||||
local prefab = evo.spawn({ [F1] = true, [F2] = true, [F3] = true })
|
||||
|
||||
for i = 1, N do
|
||||
entities[i] = clone(prefab)
|
||||
end
|
||||
|
||||
evo.batch_destroy(Q1)
|
||||
end, function()
|
||||
return {}
|
||||
end)
|
||||
|
||||
basics.describe_bench(string.format('create and destroy %d entities with 4 components / clone', N),
|
||||
---@param entities evolved.id[]
|
||||
function(entities)
|
||||
local clone = evo.clone
|
||||
|
||||
local prefab = evo.spawn({ [F1] = true, [F2] = true, [F3] = true, [F4] = true })
|
||||
|
||||
for i = 1, N do
|
||||
entities[i] = clone(prefab)
|
||||
end
|
||||
|
||||
evo.batch_destroy(Q1)
|
||||
end, function()
|
||||
return {}
|
||||
end)
|
||||
|
||||
basics.describe_bench(string.format('create and destroy %d entities with 5 components / clone', N),
|
||||
---@param entities evolved.id[]
|
||||
function(entities)
|
||||
local clone = evo.clone
|
||||
|
||||
local prefab = evo.spawn({ [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true })
|
||||
|
||||
for i = 1, N do
|
||||
entities[i] = clone(prefab)
|
||||
end
|
||||
|
||||
evo.batch_destroy(Q1)
|
||||
end, function()
|
||||
return {}
|
||||
end)
|
||||
|
||||
print '----------------------------------------'
|
||||
|
||||
basics.describe_bench(string.format('create and destroy %d entities with 1 components / spawn_at', N),
|
||||
---@param entities evolved.id[]
|
||||
function(entities)
|
||||
|
||||
@@ -6688,3 +6688,282 @@ do
|
||||
assert(not evo.has(e3, f1) and evo.get(e3, f1) == nil)
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local f1, f2 = evo.id(2)
|
||||
|
||||
do
|
||||
local e = evo.spawn()
|
||||
assert(evo.is_alive(e) and evo.is_empty(e))
|
||||
end
|
||||
|
||||
do
|
||||
local e = evo.spawn({})
|
||||
assert(evo.is_alive(e) and evo.is_empty(e))
|
||||
end
|
||||
|
||||
do
|
||||
local e = evo.spawn({ [f1] = 1 })
|
||||
assert(evo.is_alive(e) and not evo.is_empty(e))
|
||||
assert(evo.has(e, f1) and evo.get(e, f1) == 1)
|
||||
assert(not evo.has(e, f2) and evo.get(e, f2) == nil)
|
||||
end
|
||||
|
||||
do
|
||||
local e = evo.spawn({ [f1] = 1, [f2] = 2 })
|
||||
assert(evo.is_alive(e) and not evo.is_empty(e))
|
||||
assert(evo.has(e, f1) and evo.get(e, f1) == 1)
|
||||
assert(evo.has(e, f2) and evo.get(e, f2) == 2)
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local f1, f2, f3 = evo.id(3)
|
||||
|
||||
do
|
||||
local p = evo.spawn()
|
||||
|
||||
local e1 = evo.clone(p)
|
||||
assert(evo.is_alive(e1) and evo.is_empty(e1))
|
||||
|
||||
local e2 = evo.clone(p, {})
|
||||
assert(evo.is_alive(e2) and evo.is_empty(e2))
|
||||
|
||||
local e3 = evo.clone(p, { [f1] = 11 })
|
||||
assert(evo.is_alive(e3) and not evo.is_empty(e3))
|
||||
assert(evo.has(e3, f1) and evo.get(e3, f1) == 11)
|
||||
assert(not evo.has(e3, f2) and evo.get(e3, f2) == nil)
|
||||
|
||||
local e4 = evo.clone(p, { [f1] = 11, [f2] = 22 })
|
||||
assert(evo.is_alive(e4) and not evo.is_empty(e4))
|
||||
assert(evo.has(e4, f1) and evo.get(e4, f1) == 11)
|
||||
assert(evo.has(e4, f2) and evo.get(e4, f2) == 22)
|
||||
|
||||
local e5 = evo.clone(p, { [f3] = 33 })
|
||||
assert(evo.is_alive(e5) and not evo.is_empty(e5))
|
||||
assert(not evo.has(e5, f1) and evo.get(e5, f1) == nil)
|
||||
assert(not evo.has(e5, f2) and evo.get(e5, f2) == nil)
|
||||
assert(evo.has(e5, f3) and evo.get(e5, f3) == 33)
|
||||
|
||||
local e6 = evo.clone(p, { [f1] = 11, [f2] = 22, [f3] = 33 })
|
||||
assert(evo.is_alive(e6) and not evo.is_empty(e6))
|
||||
assert(evo.has(e6, f1) and evo.get(e6, f1) == 11)
|
||||
assert(evo.has(e6, f2) and evo.get(e6, f2) == 22)
|
||||
assert(evo.has(e6, f3) and evo.get(e6, f3) == 33)
|
||||
end
|
||||
|
||||
do
|
||||
local p = evo.spawn({ [f1] = 1 })
|
||||
|
||||
local e1 = evo.clone(p)
|
||||
assert(evo.is_alive(e1) and not evo.is_empty(e1))
|
||||
assert(evo.has(e1, f1) and evo.get(e1, f1) == 1)
|
||||
assert(not evo.has(e1, f2) and evo.get(e1, f2) == nil)
|
||||
|
||||
local e2 = evo.clone(p, {})
|
||||
assert(evo.is_alive(e2) and not evo.is_empty(e2))
|
||||
assert(evo.has(e2, f1) and evo.get(e2, f1) == 1)
|
||||
assert(not evo.has(e2, f2) and evo.get(e2, f2) == nil)
|
||||
|
||||
local e3 = evo.clone(p, { [f1] = 11 })
|
||||
assert(evo.is_alive(e3) and not evo.is_empty(e3))
|
||||
assert(evo.has(e3, f1) and evo.get(e3, f1) == 11)
|
||||
assert(not evo.has(e3, f2) and evo.get(e3, f2) == nil)
|
||||
|
||||
local e4 = evo.clone(p, { [f2] = 22 })
|
||||
assert(evo.is_alive(e4) and not evo.is_empty(e4))
|
||||
assert(evo.has(e4, f1) and evo.get(e4, f1) == 1)
|
||||
assert(evo.has(e4, f2) and evo.get(e4, f2) == 22)
|
||||
|
||||
local e5 = evo.clone(p, { [f1] = 11, [f2] = 22 })
|
||||
assert(evo.is_alive(e5) and not evo.is_empty(e5))
|
||||
assert(evo.has(e5, f1) and evo.get(e5, f1) == 11)
|
||||
assert(evo.has(e5, f2) and evo.get(e5, f2) == 22)
|
||||
|
||||
local e6 = evo.clone(p, { [f3] = 33 })
|
||||
assert(evo.is_alive(e6) and not evo.is_empty(e6))
|
||||
assert(evo.has(e6, f1) and evo.get(e6, f1) == 1)
|
||||
assert(not evo.has(e6, f2) and evo.get(e6, f2) == nil)
|
||||
assert(evo.has(e6, f3) and evo.get(e6, f3) == 33)
|
||||
|
||||
local e7 = evo.clone(p, { [f1] = 11, [f2] = 22, [f3] = 33 })
|
||||
assert(evo.is_alive(e7) and not evo.is_empty(e7))
|
||||
assert(evo.has(e7, f1) and evo.get(e7, f1) == 11)
|
||||
assert(evo.has(e7, f2) and evo.get(e7, f2) == 22)
|
||||
assert(evo.has(e7, f3) and evo.get(e7, f3) == 33)
|
||||
end
|
||||
|
||||
do
|
||||
local p = evo.spawn({ [f1] = 1, [f2] = 2 })
|
||||
|
||||
local e1 = evo.clone(p)
|
||||
assert(evo.is_alive(e1) and not evo.is_empty(e1))
|
||||
assert(evo.has(e1, f1) and evo.get(e1, f1) == 1)
|
||||
assert(evo.has(e1, f2) and evo.get(e1, f2) == 2)
|
||||
|
||||
local e2 = evo.clone(p, {})
|
||||
assert(evo.is_alive(e2) and not evo.is_empty(e2))
|
||||
assert(evo.has(e2, f1) and evo.get(e2, f1) == 1)
|
||||
assert(evo.has(e2, f2) and evo.get(e2, f2) == 2)
|
||||
|
||||
local e3 = evo.clone(p, { [f1] = 11 })
|
||||
assert(evo.is_alive(e3) and not evo.is_empty(e3))
|
||||
assert(evo.has(e3, f1) and evo.get(e3, f1) == 11)
|
||||
assert(evo.has(e3, f2) and evo.get(e3, f2) == 2)
|
||||
|
||||
local e4 = evo.clone(p, { [f2] = 22 })
|
||||
assert(evo.is_alive(e4) and not evo.is_empty(e4))
|
||||
assert(evo.has(e4, f1) and evo.get(e4, f1) == 1)
|
||||
assert(evo.has(e4, f2) and evo.get(e4, f2) == 22)
|
||||
|
||||
local e5 = evo.clone(p, { [f1] = 11, [f2] = 22 })
|
||||
assert(evo.is_alive(e5) and not evo.is_empty(e5))
|
||||
assert(evo.has(e5, f1) and evo.get(e5, f1) == 11)
|
||||
assert(evo.has(e5, f2) and evo.get(e5, f2) == 22)
|
||||
|
||||
local e6 = evo.clone(p, { [f3] = 33 })
|
||||
assert(evo.is_alive(e6) and not evo.is_empty(e6))
|
||||
assert(evo.has(e6, f1) and evo.get(e6, f1) == 1)
|
||||
assert(evo.has(e6, f2) and evo.get(e6, f2) == 2)
|
||||
assert(evo.has(e6, f3) and evo.get(e6, f3) == 33)
|
||||
|
||||
local e7 = evo.clone(p, { [f1] = 11, [f2] = 22, [f3] = 33 })
|
||||
assert(evo.is_alive(e7) and not evo.is_empty(e7))
|
||||
assert(evo.has(e7, f1) and evo.get(e7, f1) == 11)
|
||||
assert(evo.has(e7, f2) and evo.get(e7, f2) == 22)
|
||||
assert(evo.has(e7, f3) and evo.get(e7, f3) == 33)
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local f1, f2, f3 = evo.id(3)
|
||||
|
||||
do
|
||||
assert(evo.defer())
|
||||
|
||||
local e1 = evo.spawn()
|
||||
local e2 = evo.spawn({})
|
||||
local e3 = evo.spawn({ [f1] = 11 })
|
||||
local e4 = evo.spawn({ [f1] = 11, [f2] = 22 })
|
||||
|
||||
assert(evo.is_alive(e1) and evo.is_empty(e1))
|
||||
assert(evo.is_alive(e2) and evo.is_empty(e2))
|
||||
assert(evo.is_alive(e3) and evo.is_empty(e3))
|
||||
assert(evo.is_alive(e4) and evo.is_empty(e4))
|
||||
|
||||
assert(evo.commit())
|
||||
|
||||
assert(evo.is_alive(e1) and evo.is_empty(e1))
|
||||
assert(evo.is_alive(e2) and evo.is_empty(e2))
|
||||
assert(evo.is_alive(e3) and not evo.is_empty(e3))
|
||||
assert(evo.is_alive(e4) and not evo.is_empty(e4))
|
||||
|
||||
assert(evo.has(e3, f1) and evo.get(e3, f1) == 11)
|
||||
assert(not evo.has(e3, f2) and evo.get(e3, f2) == nil)
|
||||
|
||||
assert(evo.has(e4, f1) and evo.get(e4, f1) == 11)
|
||||
assert(evo.has(e4, f2) and evo.get(e4, f2) == 22)
|
||||
end
|
||||
|
||||
do
|
||||
local p1 = evo.spawn()
|
||||
local p2 = evo.spawn({ [f1] = 1 })
|
||||
local p3 = evo.spawn({ [f1] = 1, [f2] = 2 })
|
||||
|
||||
assert(evo.defer())
|
||||
|
||||
local e1a = evo.clone(p1)
|
||||
local e1b = evo.clone(p1, {})
|
||||
local e1c = evo.clone(p1, { [f1] = 11 })
|
||||
local e1d = evo.clone(p1, { [f2] = 22 })
|
||||
local e1e = evo.clone(p1, { [f1] = 11, [f2] = 22 })
|
||||
local e1f = evo.clone(p1, { [f3] = 33 })
|
||||
local e1g = evo.clone(p1, { [f1] = 11, [f2] = 22, [f3] = 33 })
|
||||
|
||||
local e2a = evo.clone(p2)
|
||||
local e2b = evo.clone(p2, {})
|
||||
local e2c = evo.clone(p2, { [f1] = 11 })
|
||||
local e2d = evo.clone(p2, { [f2] = 22 })
|
||||
local e2e = evo.clone(p2, { [f1] = 11, [f2] = 22 })
|
||||
local e2f = evo.clone(p2, { [f3] = 33 })
|
||||
local e2g = evo.clone(p2, { [f1] = 11, [f2] = 22, [f3] = 33 })
|
||||
|
||||
local e3a = evo.clone(p3)
|
||||
local e3b = evo.clone(p3, {})
|
||||
local e3c = evo.clone(p3, { [f1] = 11 })
|
||||
local e3d = evo.clone(p3, { [f2] = 22 })
|
||||
local e3e = evo.clone(p3, { [f1] = 11, [f2] = 22 })
|
||||
local e3f = evo.clone(p3, { [f3] = 33 })
|
||||
local e3g = evo.clone(p3, { [f1] = 11, [f2] = 22, [f3] = 33 })
|
||||
|
||||
assert(evo.is_alive_all(e1a, e1b, e1c, e1d, e1e, e1f, e1g))
|
||||
assert(evo.is_alive_all(e2a, e2b, e2c, e2d, e2e, e2f, e2g))
|
||||
assert(evo.is_alive_all(e3a, e3b, e3c, e3d, e3e, e3f, e3g))
|
||||
|
||||
assert(evo.is_empty_all(e1a, e1b, e1c, e1d, e1e, e1f, e1g))
|
||||
assert(evo.is_empty_all(e2a, e2b, e2c, e2d, e2e, e2f, e2g))
|
||||
assert(evo.is_empty_all(e3a, e3b, e3c, e3d, e3e, e3f, e3g))
|
||||
|
||||
assert(evo.commit())
|
||||
|
||||
assert(not evo.has(e1a, f1) and not evo.has(e1a, f2))
|
||||
assert(not evo.has(e1b, f1) and not evo.has(e1b, f2))
|
||||
|
||||
assert(evo.has(e1c, f1) and evo.get(e1c, f1) == 11 and not evo.has(e1c, f2))
|
||||
assert(not evo.has(e1d, f1) and evo.has(e1d, f2) and evo.get(e1d, f2) == 22)
|
||||
|
||||
assert(not evo.has(e1f, f1) and evo.get(e1f, f1) == nil)
|
||||
assert(not evo.has(e1f, f2) and evo.get(e1f, f2) == nil)
|
||||
assert(evo.has(e1f, f3) and evo.get(e1f, f3) == 33)
|
||||
|
||||
assert(evo.has(e1g, f1) and evo.get(e1g, f1) == 11)
|
||||
assert(evo.has(e1g, f2) and evo.get(e1g, f2) == 22)
|
||||
assert(evo.has(e1g, f3) and evo.get(e1g, f3) == 33)
|
||||
|
||||
assert(evo.has(e2a, f1) and evo.get(e2a, f1) == 1)
|
||||
assert(not evo.has(e2a, f2) and evo.get(e2a, f2) == nil)
|
||||
|
||||
assert(evo.has(e2b, f1) and evo.get(e2b, f1) == 1)
|
||||
assert(not evo.has(e2b, f2) and evo.get(e2b, f2) == nil)
|
||||
|
||||
assert(evo.has(e2c, f1) and evo.get(e2c, f1) == 11)
|
||||
assert(not evo.has(e2c, f2) and evo.get(e2c, f2) == nil)
|
||||
|
||||
assert(evo.has(e2d, f1) and evo.get(e2d, f1) == 1)
|
||||
assert(evo.has(e2d, f2) and evo.get(e2d, f2) == 22)
|
||||
|
||||
assert(evo.has(e2e, f1) and evo.get(e2e, f1) == 11)
|
||||
assert(evo.has(e2e, f2) and evo.get(e2e, f2) == 22)
|
||||
|
||||
assert(evo.has(e2f, f1) and evo.get(e2f, f1) == 1)
|
||||
assert(not evo.has(e2f, f2) and evo.get(e2f, f2) == nil)
|
||||
assert(evo.has(e2f, f3) and evo.get(e2f, f3) == 33)
|
||||
|
||||
assert(evo.has(e2g, f1) and evo.get(e2g, f1) == 11)
|
||||
assert(evo.has(e2g, f2) and evo.get(e2g, f2) == 22)
|
||||
assert(evo.has(e2g, f3) and evo.get(e2g, f3) == 33)
|
||||
|
||||
assert(evo.has(e3a, f1) and evo.get(e3a, f1) == 1)
|
||||
assert(evo.has(e3a, f2) and evo.get(e3a, f2) == 2)
|
||||
|
||||
assert(evo.has(e3b, f1) and evo.get(e3b, f1) == 1)
|
||||
assert(evo.has(e3b, f2) and evo.get(e3b, f2) == 2)
|
||||
|
||||
assert(evo.has(e3c, f1) and evo.get(e3c, f1) == 11)
|
||||
assert(evo.has(e3c, f2) and evo.get(e3c, f2) == 2)
|
||||
|
||||
assert(evo.has(e3d, f1) and evo.get(e3d, f1) == 1)
|
||||
assert(evo.has(e3d, f2) and evo.get(e3d, f2) == 22)
|
||||
|
||||
assert(evo.has(e3e, f1) and evo.get(e3e, f1) == 11)
|
||||
assert(evo.has(e3e, f2) and evo.get(e3e, f2) == 22)
|
||||
|
||||
assert(evo.has(e3f, f1) and evo.get(e3f, f1) == 1)
|
||||
assert(evo.has(e3f, f2) and evo.get(e3f, f2) == 2)
|
||||
assert(evo.has(e3f, f3) and evo.get(e3f, f3) == 33)
|
||||
|
||||
assert(evo.has(e3g, f1) and evo.get(e3g, f1) == 11)
|
||||
assert(evo.has(e3g, f2) and evo.get(e3g, f2) == 22)
|
||||
assert(evo.has(e3g, f3) and evo.get(e3g, f3) == 33)
|
||||
end
|
||||
end
|
||||
|
||||
480
evolved.lua
480
evolved.lua
@@ -339,8 +339,9 @@ local __table_pool_tag = {
|
||||
entity_list = 7,
|
||||
fragment_set = 8,
|
||||
fragment_list = 9,
|
||||
component_list = 10,
|
||||
__count = 10,
|
||||
component_map = 10,
|
||||
component_list = 11,
|
||||
__count = 11,
|
||||
}
|
||||
|
||||
---@class (exact) evolved.table_pool
|
||||
@@ -662,6 +663,11 @@ local __safe_tbls = {
|
||||
__newindex = function() __error_fmt('attempt to modify empty fragment list') end
|
||||
}),
|
||||
|
||||
---@type table<evolved.fragment, evolved.component>
|
||||
__EMPTY_COMPONENT_MAP = __lua_setmetatable({}, {
|
||||
__newindex = function() __error_fmt('attempt to modify empty component map') end
|
||||
}),
|
||||
|
||||
---@type evolved.component[]
|
||||
__EMPTY_COMPONENT_LIST = __lua_setmetatable({}, {
|
||||
__newindex = function() __error_fmt('attempt to modify empty component list') end
|
||||
@@ -716,6 +722,9 @@ local __evolved_execute
|
||||
|
||||
local __evolved_process
|
||||
|
||||
local __evolved_spawn
|
||||
local __evolved_clone
|
||||
|
||||
local __evolved_spawn_at
|
||||
local __evolved_spawn_as
|
||||
local __evolved_spawn_with
|
||||
@@ -1073,6 +1082,13 @@ function __debug_fns.validate_fragment_list(fragment_list, fragment_count)
|
||||
end
|
||||
end
|
||||
|
||||
---@param components table<evolved.fragment, evolved.component>
|
||||
function __debug_fns.validate_component_map(components)
|
||||
for fragment in __lua_next, components do
|
||||
__debug_fns.validate_fragment(fragment)
|
||||
end
|
||||
end
|
||||
|
||||
---@param query evolved.query
|
||||
function __debug_fns.validate_query(query)
|
||||
local query_index = query % 0x100000
|
||||
@@ -1301,6 +1317,18 @@ local function __chunk_with_fragment_list(chunk, fragment_list, fragment_count)
|
||||
return chunk
|
||||
end
|
||||
|
||||
---@param chunk? evolved.chunk
|
||||
---@param components table<evolved.fragment, evolved.component>
|
||||
---@return evolved.chunk?
|
||||
---@nodiscard
|
||||
local function __chunk_with_component_map(chunk, components)
|
||||
for fragment in __lua_next, components do
|
||||
chunk = __chunk_with_fragment(chunk, fragment)
|
||||
end
|
||||
|
||||
return chunk
|
||||
end
|
||||
|
||||
---@param chunk? evolved.chunk
|
||||
---@param fragment evolved.fragment
|
||||
---@return evolved.chunk?
|
||||
@@ -1433,6 +1461,27 @@ local function __chunk_fragment_list(fragment_list, fragment_count)
|
||||
return chunk
|
||||
end
|
||||
|
||||
---@param components table<evolved.fragment, evolved.component>
|
||||
---@return evolved.chunk?
|
||||
---@nodiscard
|
||||
local function __chunk_component_map(components)
|
||||
local root_fragment = __lua_next(components)
|
||||
|
||||
if not root_fragment then
|
||||
return
|
||||
end
|
||||
|
||||
local chunk = __root_chunks[root_fragment]
|
||||
or __chunk_with_fragment(nil, root_fragment)
|
||||
|
||||
for child_fragment in __lua_next, components, root_fragment do
|
||||
chunk = chunk.__with_fragment_edges[child_fragment]
|
||||
or __chunk_with_fragment(chunk, child_fragment)
|
||||
end
|
||||
|
||||
return chunk
|
||||
end
|
||||
|
||||
---
|
||||
---
|
||||
---
|
||||
@@ -1640,6 +1689,9 @@ local __defer_batch_remove
|
||||
local __defer_batch_clear
|
||||
local __defer_batch_destroy
|
||||
|
||||
local __defer_spawn_entity
|
||||
local __defer_clone_entity
|
||||
|
||||
local __defer_spawn_entity_at
|
||||
local __defer_spawn_entity_as
|
||||
local __defer_spawn_entity_with
|
||||
@@ -1703,6 +1755,281 @@ local function __detach_all_entities(chunk)
|
||||
chunk.__entity_count = 0
|
||||
end
|
||||
|
||||
---@param entity evolved.entity
|
||||
---@param components table<evolved.fragment, evolved.component>
|
||||
local function __spawn_entity(entity, components)
|
||||
if __defer_depth <= 0 then
|
||||
__error_fmt('spawn entity operations should be deferred')
|
||||
end
|
||||
|
||||
local chunk = __chunk_component_map(components)
|
||||
|
||||
if not chunk then
|
||||
return
|
||||
end
|
||||
|
||||
local chunk_entity_list = chunk.__entity_list
|
||||
local chunk_entity_count = chunk.__entity_count
|
||||
|
||||
local chunk_component_indices = chunk.__component_indices
|
||||
local chunk_component_storages = chunk.__component_storages
|
||||
|
||||
local place = chunk_entity_count + 1
|
||||
chunk.__entity_count = place
|
||||
|
||||
chunk_entity_list[place] = entity
|
||||
|
||||
do
|
||||
local entity_index = entity % 0x100000
|
||||
|
||||
__entity_chunks[entity_index] = chunk
|
||||
__entity_places[entity_index] = place
|
||||
|
||||
__structural_changes = __structural_changes + 1
|
||||
end
|
||||
|
||||
if chunk.__has_setup_hooks then
|
||||
for fragment, component in __lua_next, components do
|
||||
local component_index = chunk_component_indices[fragment]
|
||||
|
||||
if component_index then
|
||||
---@type evolved.duplicate?
|
||||
local fragment_duplicate =
|
||||
__evolved_get(fragment, __DUPLICATE)
|
||||
|
||||
local new_component = component
|
||||
|
||||
if new_component ~= nil and fragment_duplicate then
|
||||
new_component = fragment_duplicate(new_component)
|
||||
end
|
||||
|
||||
if new_component == nil then
|
||||
new_component = true
|
||||
end
|
||||
|
||||
local component_storage = chunk_component_storages[component_index]
|
||||
|
||||
component_storage[place] = new_component
|
||||
end
|
||||
end
|
||||
else
|
||||
for fragment, component in __lua_next, components do
|
||||
local component_index = chunk_component_indices[fragment]
|
||||
|
||||
if component_index then
|
||||
local new_component = component
|
||||
|
||||
local component_storage = chunk_component_storages[component_index]
|
||||
|
||||
component_storage[place] = new_component
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if chunk.__has_insert_hooks then
|
||||
local chunk_fragment_list = chunk.__fragment_list
|
||||
local chunk_fragment_count = chunk.__fragment_count
|
||||
|
||||
for chunk_fragment_index = 1, chunk_fragment_count do
|
||||
local fragment = chunk_fragment_list[chunk_fragment_index]
|
||||
|
||||
---@type evolved.set_hook?, evolved.insert_hook?
|
||||
local fragment_on_set, fragment_on_insert =
|
||||
__evolved_get(fragment, __ON_SET, __ON_INSERT)
|
||||
|
||||
local component_index = chunk_component_indices[fragment]
|
||||
|
||||
if component_index then
|
||||
local component_storage = chunk_component_storages[component_index]
|
||||
|
||||
local new_component = component_storage[place]
|
||||
|
||||
if fragment_on_set then
|
||||
__defer_call_hook(fragment_on_set, entity, fragment, new_component)
|
||||
end
|
||||
|
||||
if fragment_on_insert then
|
||||
__defer_call_hook(fragment_on_insert, entity, fragment, new_component)
|
||||
end
|
||||
else
|
||||
if fragment_on_set then
|
||||
__defer_call_hook(fragment_on_set, entity, fragment)
|
||||
end
|
||||
|
||||
if fragment_on_insert then
|
||||
__defer_call_hook(fragment_on_insert, entity, fragment)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param entity evolved.entity
|
||||
---@param prefab evolved.entity
|
||||
---@param components table<evolved.fragment, evolved.component>
|
||||
local function __clone_entity(entity, prefab, components)
|
||||
if __defer_depth <= 0 then
|
||||
__error_fmt('clone entity operations should be deferred')
|
||||
end
|
||||
|
||||
local prefab_index = prefab % 0x100000
|
||||
local prefab_chunk = __entity_chunks[prefab_index]
|
||||
local prefab_place = __entity_places[prefab_index]
|
||||
|
||||
local chunk = __chunk_with_component_map(prefab_chunk, components)
|
||||
|
||||
if not chunk then
|
||||
return
|
||||
end
|
||||
|
||||
local chunk_entity_list = chunk.__entity_list
|
||||
local chunk_entity_count = chunk.__entity_count
|
||||
|
||||
local chunk_component_indices = chunk.__component_indices
|
||||
local chunk_component_storages = chunk.__component_storages
|
||||
|
||||
local place = chunk_entity_count + 1
|
||||
chunk.__entity_count = place
|
||||
|
||||
chunk_entity_list[place] = entity
|
||||
|
||||
do
|
||||
local entity_index = entity % 0x100000
|
||||
|
||||
__entity_chunks[entity_index] = chunk
|
||||
__entity_places[entity_index] = place
|
||||
|
||||
__structural_changes = __structural_changes + 1
|
||||
end
|
||||
|
||||
if prefab_chunk then
|
||||
local prefab_component_count = prefab_chunk.__component_count
|
||||
local prefab_component_storages = prefab_chunk.__component_storages
|
||||
local prefab_component_fragments = prefab_chunk.__component_fragments
|
||||
|
||||
if prefab_chunk.__has_setup_hooks then
|
||||
for prefab_component_index = 1, prefab_component_count do
|
||||
local fragment = prefab_component_fragments[prefab_component_index]
|
||||
|
||||
---@type evolved.duplicate?
|
||||
local fragment_duplicate =
|
||||
__evolved_get(fragment, __DUPLICATE)
|
||||
|
||||
local prefab_component_storage = prefab_component_storages[prefab_component_index]
|
||||
local prefab_component = prefab_component_storage[prefab_place]
|
||||
|
||||
local new_component = prefab_component
|
||||
|
||||
if new_component ~= nil and fragment_duplicate then
|
||||
new_component = fragment_duplicate(new_component)
|
||||
end
|
||||
|
||||
if new_component == nil then
|
||||
new_component = true
|
||||
end
|
||||
|
||||
local component_index = chunk_component_indices[fragment]
|
||||
local component_storage = chunk_component_storages[component_index]
|
||||
|
||||
component_storage[place] = new_component
|
||||
end
|
||||
else
|
||||
for prefab_component_index = 1, prefab_component_count do
|
||||
local fragment = prefab_component_fragments[prefab_component_index]
|
||||
|
||||
local prefab_component_storage = prefab_component_storages[prefab_component_index]
|
||||
local prefab_component = prefab_component_storage[prefab_place]
|
||||
|
||||
local new_component = prefab_component
|
||||
|
||||
if new_component == nil then
|
||||
new_component = true
|
||||
end
|
||||
|
||||
local component_index = chunk_component_indices[fragment]
|
||||
local component_storage = chunk_component_storages[component_index]
|
||||
|
||||
component_storage[place] = new_component
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if chunk.__has_setup_hooks then
|
||||
for fragment, component in __lua_next, components do
|
||||
local component_index = chunk_component_indices[fragment]
|
||||
|
||||
if component_index then
|
||||
---@type evolved.duplicate?
|
||||
local fragment_duplicate =
|
||||
__evolved_get(fragment, __DUPLICATE)
|
||||
|
||||
local new_component = component
|
||||
|
||||
if new_component ~= nil and fragment_duplicate then
|
||||
new_component = fragment_duplicate(new_component)
|
||||
end
|
||||
|
||||
if new_component == nil then
|
||||
new_component = true
|
||||
end
|
||||
|
||||
local component_storage = chunk_component_storages[component_index]
|
||||
|
||||
component_storage[place] = new_component
|
||||
end
|
||||
end
|
||||
else
|
||||
for fragment, component in __lua_next, components do
|
||||
local component_index = chunk_component_indices[fragment]
|
||||
|
||||
if component_index then
|
||||
local new_component = component
|
||||
|
||||
local component_storage = chunk_component_storages[component_index]
|
||||
|
||||
component_storage[place] = new_component
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if chunk.__has_insert_hooks then
|
||||
local chunk_fragment_list = chunk.__fragment_list
|
||||
local chunk_fragment_count = chunk.__fragment_count
|
||||
|
||||
for chunk_fragment_index = 1, chunk_fragment_count do
|
||||
local fragment = chunk_fragment_list[chunk_fragment_index]
|
||||
|
||||
---@type evolved.set_hook?, evolved.insert_hook?
|
||||
local fragment_on_set, fragment_on_insert =
|
||||
__evolved_get(fragment, __ON_SET, __ON_INSERT)
|
||||
|
||||
local component_index = chunk_component_indices[fragment]
|
||||
|
||||
if component_index then
|
||||
local component_storage = chunk_component_storages[component_index]
|
||||
|
||||
local new_component = component_storage[place]
|
||||
|
||||
if fragment_on_set then
|
||||
__defer_call_hook(fragment_on_set, entity, fragment, new_component)
|
||||
end
|
||||
|
||||
if fragment_on_insert then
|
||||
__defer_call_hook(fragment_on_insert, entity, fragment, new_component)
|
||||
end
|
||||
else
|
||||
if fragment_on_set then
|
||||
__defer_call_hook(fragment_on_set, entity, fragment)
|
||||
end
|
||||
|
||||
if fragment_on_insert then
|
||||
__defer_call_hook(fragment_on_insert, entity, fragment)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param entity evolved.entity
|
||||
---@param chunk? evolved.chunk
|
||||
---@param fragment_list evolved.fragment[]
|
||||
@@ -2999,13 +3326,16 @@ local __defer_op = {
|
||||
batch_clear = 7,
|
||||
batch_destroy = 8,
|
||||
|
||||
spawn_entity_at = 9,
|
||||
spawn_entity_as = 10,
|
||||
spawn_entity_with = 11,
|
||||
spawn_entity = 9,
|
||||
clone_entity = 10,
|
||||
|
||||
call_hook = 12,
|
||||
spawn_entity_at = 11,
|
||||
spawn_entity_as = 12,
|
||||
spawn_entity_with = 13,
|
||||
|
||||
__count = 12,
|
||||
call_hook = 14,
|
||||
|
||||
__count = 14,
|
||||
}
|
||||
|
||||
---@type table<evolved.defer_op, fun(bytes: any[], index: integer): integer>
|
||||
@@ -3492,6 +3822,85 @@ __defer_ops[__defer_op.batch_destroy] = function(bytes, index)
|
||||
return 1 + argument_count
|
||||
end
|
||||
|
||||
---@param entity evolved.entity
|
||||
---@param components table<evolved.fragment, evolved.component>
|
||||
function __defer_spawn_entity(entity, components)
|
||||
---@type table<evolved.fragment, evolved.component>
|
||||
local component_map = __acquire_table(__table_pool_tag.component_map)
|
||||
|
||||
for fragment, component in __lua_next, components do
|
||||
component_map[fragment] = component
|
||||
end
|
||||
|
||||
local length = __defer_length
|
||||
local bytecode = __defer_bytecode
|
||||
|
||||
bytecode[length + 1] = __defer_op.spawn_entity
|
||||
bytecode[length + 2] = entity
|
||||
bytecode[length + 3] = component_map
|
||||
|
||||
__defer_length = length + 3
|
||||
end
|
||||
|
||||
__defer_ops[__defer_op.spawn_entity] = function(bytes, index)
|
||||
local entity = bytes[index + 0]
|
||||
local component_map = bytes[index + 1]
|
||||
|
||||
if __debug_mode then
|
||||
__debug_fns.validate_component_map(component_map)
|
||||
end
|
||||
|
||||
__evolved_defer()
|
||||
do
|
||||
__spawn_entity(entity, component_map)
|
||||
__release_table(__table_pool_tag.component_map, component_map)
|
||||
end
|
||||
__evolved_commit()
|
||||
|
||||
return 2
|
||||
end
|
||||
|
||||
---@param entity evolved.entity
|
||||
---@param prefab evolved.entity
|
||||
---@param components table<evolved.fragment, evolved.component>
|
||||
function __defer_clone_entity(entity, prefab, components)
|
||||
---@type table<evolved.fragment, evolved.component>
|
||||
local component_map = __acquire_table(__table_pool_tag.component_map)
|
||||
|
||||
for fragment, component in __lua_next, components do
|
||||
component_map[fragment] = component
|
||||
end
|
||||
|
||||
local length = __defer_length
|
||||
local bytecode = __defer_bytecode
|
||||
|
||||
bytecode[length + 1] = __defer_op.clone_entity
|
||||
bytecode[length + 2] = entity
|
||||
bytecode[length + 3] = prefab
|
||||
bytecode[length + 4] = component_map
|
||||
|
||||
__defer_length = length + 4
|
||||
end
|
||||
|
||||
__defer_ops[__defer_op.clone_entity] = function(bytes, index)
|
||||
local entity = bytes[index + 0]
|
||||
local prefab = bytes[index + 1]
|
||||
local component_map = bytes[index + 2]
|
||||
|
||||
if __debug_mode then
|
||||
__debug_fns.validate_component_map(component_map)
|
||||
end
|
||||
|
||||
__evolved_defer()
|
||||
do
|
||||
__clone_entity(entity, prefab, component_map)
|
||||
__release_table(__table_pool_tag.component_map, component_map)
|
||||
end
|
||||
__evolved_commit()
|
||||
|
||||
return 3
|
||||
end
|
||||
|
||||
---@param entity evolved.entity
|
||||
---@param chunk? evolved.chunk
|
||||
---@param fragments evolved.fragment[]
|
||||
@@ -4755,6 +5164,60 @@ end
|
||||
---
|
||||
---
|
||||
|
||||
---@param components? table<evolved.fragment, evolved.component>
|
||||
---@return evolved.entity
|
||||
function __evolved_spawn(components)
|
||||
if not components then
|
||||
components = __safe_tbls.__EMPTY_COMPONENT_MAP
|
||||
end
|
||||
|
||||
if __debug_mode then
|
||||
__debug_fns.validate_component_map(components)
|
||||
end
|
||||
|
||||
local entity = __acquire_id()
|
||||
|
||||
if __defer_depth > 0 then
|
||||
__defer_spawn_entity(entity, components)
|
||||
else
|
||||
__evolved_defer()
|
||||
do
|
||||
__spawn_entity(entity, components)
|
||||
end
|
||||
__evolved_commit()
|
||||
end
|
||||
|
||||
return entity
|
||||
end
|
||||
|
||||
---@param prefab evolved.entity
|
||||
---@param components? table<evolved.fragment, evolved.component>
|
||||
---@return evolved.entity
|
||||
function __evolved_clone(prefab, components)
|
||||
if not components then
|
||||
components = __safe_tbls.__EMPTY_COMPONENT_MAP
|
||||
end
|
||||
|
||||
if __debug_mode then
|
||||
__debug_fns.validate_prefab(prefab)
|
||||
__debug_fns.validate_component_map(components)
|
||||
end
|
||||
|
||||
local entity = __acquire_id()
|
||||
|
||||
if __defer_depth > 0 then
|
||||
__defer_clone_entity(entity, prefab, components)
|
||||
else
|
||||
__evolved_defer()
|
||||
do
|
||||
__clone_entity(entity, prefab, components)
|
||||
end
|
||||
__evolved_commit()
|
||||
end
|
||||
|
||||
return entity
|
||||
end
|
||||
|
||||
---@param chunk? evolved.chunk
|
||||
---@param fragments? evolved.fragment[]
|
||||
---@param components? evolved.component[]
|
||||
@@ -5862,6 +6325,9 @@ evolved.execute = __evolved_execute
|
||||
|
||||
evolved.process = __evolved_process
|
||||
|
||||
evolved.spawn = __evolved_spawn
|
||||
evolved.clone = __evolved_clone
|
||||
|
||||
evolved.spawn_at = __evolved_spawn_at
|
||||
evolved.spawn_as = __evolved_spawn_as
|
||||
evolved.spawn_with = __evolved_spawn_with
|
||||
|
||||
Reference in New Issue
Block a user