Merge branch 'feature/multi_spawn' into dev

This commit is contained in:
BlackMATov
2025-09-12 05:13:55 +07:00
6 changed files with 1252 additions and 67 deletions

View File

@@ -1103,7 +1103,10 @@ defer :: boolean
commit :: boolean
spawn :: <fragment, component>? -> entity
clone :: entity -> <fragment, component>? -> entity
multi_spawn :: integer, <fragment, component>? -> entity[]
clone :: entity, <fragment, component>? -> entity
multi_clone :: integer, entity, <fragment, component>? -> entity[]
alive :: entity -> boolean
alive_all :: entity... -> boolean
@@ -1163,7 +1166,10 @@ chunk_mt:components :: fragment... -> storage...
builder :: builder
builder_mt:spawn :: entity
builder_mt:multi_spawn :: integer -> entity[]
builder_mt:clone :: entity -> entity
builder_mt:multi_clone :: integer, entity -> entity[]
builder_mt:has :: fragment -> boolean
builder_mt:has_all :: fragment... -> boolean
@@ -1217,6 +1223,7 @@ builder_mt:destruction_policy :: id -> builder
## vX.X.X
- Added the new [`evolved.name`](#evolvedname-1) function
- Added the new [`evolved.multi_spawn`](#evolvedmulti_spawn) and [`evolved.multi_clone`](#evolvedmulti_clone) functions
- Added the new [`evolved.INTERNAL`](#evolvedinternal) fragment trait
## v1.1.0
@@ -1342,15 +1349,34 @@ function evolved.commit() end
function evolved.spawn(components) end
```
### `evolved.multi_spawn`
```lua
---@param entity_count integer
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity[] entity_list
function evolved.multi_spawn(entity_count, components) end
```
### `evolved.clone`
```lua
---@param prefab evolved.entity
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity
---@return evolved.entity entity
function evolved.clone(prefab, components) end
```
### `evolved.multi_clone`
```lua
---@param entity_count integer
---@param prefab evolved.entity
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity[] entity_list
function evolved.multi_clone(entity_count, prefab, components) end
```
### `evolved.alive`
```lua
@@ -1646,18 +1672,35 @@ function evolved.builder() end
#### `evolved.builder_mt:spawn`
```lua
---@return evolved.entity
---@return evolved.entity entity
function evolved.builder_mt:spawn() end
```
#### `evolved.builder_mt:multi_spawn`
```lua
---@param entity_count integer
---@return evolved.entity[] entity_list
function evolved.builder_mt:multi_spawn(entity_count) end
```
#### `evolved.builder_mt:clone`
```lua
---@param prefab evolved.entity
---@return evolved.entity
---@return evolved.entity entity
function evolved.builder_mt:clone(prefab) end
```
#### `evolved.builder_mt:multi_clone`
```lua
---@param entity_count integer
---@param prefab evolved.entity
---@return evolved.entity[] entity_list
function evolved.builder_mt:multi_clone(entity_count, prefab) end
```
#### `evolved.builder_mt:has`
```lua

View File

@@ -1,9 +1,13 @@
require 'develop.samples.systems'
require 'develop.testing.multi_spawn_tests'
require 'develop.testing.name_tests'
require 'develop.testing.requires_fragment_tests'
require 'develop.testing.system_as_query_tests'
require 'develop.benchmarks.multi_clone_bmarks'
require 'develop.benchmarks.multi_spawn_bmarks'
require 'develop.untests'
require 'develop.unbench'

View File

@@ -0,0 +1,59 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('Multi Clone Benchmarks: Simple Clone | %d entities with 1 component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Clone Benchmarks: Simple Clone | %d entities with 5 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Clone Benchmarks: Multi Clone | %d entities with 1 component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Clone Benchmarks: Multi Clone | %d entities with 5 components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
end)

View File

@@ -0,0 +1,59 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('Multi Spawn Benchmarks: Simple Spawn | %d entities with 1 component', N),
function()
local spawn = evo.spawn
local components = { [F1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Spawn Benchmarks: Simple Spawn | %d entities with 5 components', N),
function()
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Spawn Benchmarks: Multi Spawn | %d entities with 1 component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Spawn Benchmarks: Multi Spawn | %d entities with 5 components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
end)

View File

@@ -0,0 +1,308 @@
local evo = require 'evolved'
do
local entity_list
do
entity_list = evo.multi_spawn(0)
assert(entity_list and #entity_list == 0)
entity_list = evo.multi_spawn(0, {})
assert(entity_list and #entity_list == 0)
end
do
entity_list = evo.multi_spawn(-1)
assert(entity_list and #entity_list == 0)
entity_list = evo.multi_spawn(-1, {})
assert(entity_list and #entity_list == 0)
end
do
entity_list = evo.builder():multi_spawn(0)
assert(entity_list and #entity_list == 0)
end
do
entity_list = evo.builder():multi_spawn(-1)
assert(entity_list and #entity_list == 0)
end
end
do
local entity_list
do
entity_list = evo.multi_spawn(1)
assert(entity_list and #entity_list == 1)
assert(entity_list[1] and evo.empty(entity_list[1]))
assert(not entity_list[2])
entity_list = evo.multi_spawn(1, {})
assert(entity_list and #entity_list == 1)
assert(entity_list[1] and evo.empty(entity_list[1]))
assert(not entity_list[2])
end
do
entity_list = evo.multi_spawn(2)
assert(entity_list and #entity_list == 2)
assert(entity_list[1] and evo.empty(entity_list[1]))
assert(entity_list[2] and evo.empty(entity_list[2]))
assert(not entity_list[3])
entity_list = evo.multi_spawn(2, {})
assert(entity_list and #entity_list == 2)
assert(entity_list[1] and evo.empty(entity_list[1]))
assert(entity_list[2] and evo.empty(entity_list[2]))
assert(not entity_list[3])
end
do
entity_list = evo.builder():multi_spawn(1)
assert(entity_list and #entity_list == 1)
assert(entity_list[1] and evo.empty(entity_list[1]))
assert(not entity_list[2])
end
do
entity_list = evo.builder():multi_spawn(2)
assert(entity_list and #entity_list == 2)
assert(entity_list[1] and evo.empty(entity_list[1]))
assert(entity_list[2] and evo.empty(entity_list[2]))
assert(not entity_list[3])
end
end
do
local entity_list
local prefab = evo.id()
do
entity_list = evo.multi_clone(0, prefab)
assert(entity_list and #entity_list == 0)
entity_list = evo.multi_clone(0, prefab, {})
assert(entity_list and #entity_list == 0)
end
do
entity_list = evo.multi_clone(-1, prefab)
assert(entity_list and #entity_list == 0)
entity_list = evo.multi_clone(-1, prefab, {})
assert(entity_list and #entity_list == 0)
end
do
entity_list = evo.builder():multi_clone(0, prefab)
assert(entity_list and #entity_list == 0)
end
do
entity_list = evo.builder():multi_clone(-1, prefab)
assert(entity_list and #entity_list == 0)
end
end
do
local entity_list
local prefab = evo.id()
do
entity_list = evo.multi_clone(1, prefab)
assert(entity_list and #entity_list == 1)
assert(entity_list[1] and evo.empty(entity_list[1]))
assert(not entity_list[2])
entity_list = evo.multi_clone(1, prefab, {})
assert(entity_list and #entity_list == 1)
assert(entity_list[1] and evo.empty(entity_list[1]))
assert(not entity_list[2])
end
do
entity_list = evo.multi_clone(2, prefab)
assert(entity_list and #entity_list == 2)
assert(entity_list[1] and evo.empty(entity_list[1]))
assert(entity_list[2] and evo.empty(entity_list[2]))
assert(not entity_list[3])
entity_list = evo.multi_clone(2, prefab, {})
assert(entity_list and #entity_list == 2)
assert(entity_list[1] and evo.empty(entity_list[1]))
assert(entity_list[2] and evo.empty(entity_list[2]))
assert(not entity_list[3])
end
do
entity_list = evo.builder():multi_clone(1, prefab)
assert(entity_list and #entity_list == 1)
assert(entity_list[1] and evo.empty(entity_list[1]))
assert(not entity_list[2])
end
do
entity_list = evo.builder():multi_clone(2, prefab)
assert(entity_list and #entity_list == 2)
assert(entity_list[1] and evo.empty(entity_list[1]))
assert(entity_list[2] and evo.empty(entity_list[2]))
assert(not entity_list[3])
end
end
do
local f1, f2 = evo.id(2)
do
local entity_list
entity_list = evo.multi_spawn(2, { [f1] = true, [f2] = 123 })
assert(entity_list and #entity_list == 2)
assert(entity_list[1] and evo.get(entity_list[1], f1) == true and evo.get(entity_list[1], f2) == 123)
assert(entity_list[2] and evo.get(entity_list[2], f1) == true and evo.get(entity_list[2], f2) == 123)
entity_list = evo.multi_spawn(2, { [f1] = false, [f2] = 456 })
assert(entity_list and #entity_list == 2)
assert(entity_list[1] and evo.get(entity_list[1], f1) == false and evo.get(entity_list[1], f2) == 456)
assert(entity_list[2] and evo.get(entity_list[2], f1) == false and evo.get(entity_list[2], f2) == 456)
end
do
local prefab = evo.builder():set(f1, true):set(f2, 123):spawn()
local entity_list
entity_list = evo.multi_clone(2, prefab)
assert(entity_list and #entity_list == 2)
assert(entity_list[1] and evo.get(entity_list[1], f1) == true and evo.get(entity_list[1], f2) == 123)
assert(entity_list[2] and evo.get(entity_list[2], f1) == true and evo.get(entity_list[2], f2) == 123)
entity_list = evo.multi_clone(2, prefab, {})
assert(entity_list and #entity_list == 2)
assert(entity_list[1] and evo.get(entity_list[1], f1) == true and evo.get(entity_list[1], f2) == 123)
assert(entity_list[2] and evo.get(entity_list[2], f1) == true and evo.get(entity_list[2], f2) == 123)
entity_list = evo.multi_clone(2, prefab, { [f1] = false, [f2] = 456 })
assert(entity_list and #entity_list == 2)
assert(entity_list[1] and evo.get(entity_list[1], f1) == false and evo.get(entity_list[1], f2) == 456)
assert(entity_list[2] and evo.get(entity_list[2], f1) == false and evo.get(entity_list[2], f2) == 456)
end
end
do
local f1, f2, f3 = evo.id(3)
do
local entity_list1, entity_list2
evo.defer()
do
entity_list1 = evo.multi_spawn(2, { [f1] = 42, [f2] = "hello", [f3] = false })
assert(entity_list1 and #entity_list1 == 2)
assert(entity_list1[1] and evo.empty(entity_list1[1]))
assert(entity_list1[2] and evo.empty(entity_list1[2]))
assert(not entity_list1[3])
entity_list2 = evo.multi_spawn(3, { [f2] = "world", [f3] = true })
assert(entity_list2 and #entity_list2 == 3)
assert(entity_list2[1] and evo.empty(entity_list2[1]))
assert(entity_list2[2] and evo.empty(entity_list2[2]))
assert(entity_list2[3] and evo.empty(entity_list2[3]))
end
evo.commit()
do
assert(entity_list1 and #entity_list1 == 2)
assert(entity_list1[1] and not evo.empty(entity_list1[1]))
assert(entity_list1[2] and not evo.empty(entity_list1[2]))
assert(not entity_list1[3])
assert(
evo.get(entity_list1[1], f1) == 42 and
evo.get(entity_list1[1], f2) == "hello" and
evo.get(entity_list1[1], f3) == false)
assert(
evo.get(entity_list1[2], f1) == 42 and
evo.get(entity_list1[2], f2) == "hello" and
evo.get(entity_list1[2], f3) == false)
assert(entity_list2 and #entity_list2 == 3)
assert(entity_list2[1] and not evo.empty(entity_list2[1]))
assert(entity_list2[2] and not evo.empty(entity_list2[2]))
assert(entity_list2[3] and not evo.empty(entity_list2[3]))
assert(not entity_list2[4])
assert(
evo.get(entity_list2[1], f1) == nil and
evo.get(entity_list2[1], f2) == "world" and
evo.get(entity_list2[1], f3) == true)
assert(
evo.get(entity_list2[2], f1) == nil and
evo.get(entity_list2[2], f2) == "world" and
evo.get(entity_list2[2], f3) == true)
assert(
evo.get(entity_list2[3], f1) == nil and
evo.get(entity_list2[3], f2) == "world" and
evo.get(entity_list2[3], f3) == true)
end
end
end
do
local f1, f2, f3 = evo.id(3)
do
local prefab = evo.builder():set(f1, false):set(f2, 123):spawn()
local entity_list1, entity_list2
evo.defer()
do
entity_list1 = evo.multi_clone(2, prefab)
assert(entity_list1 and #entity_list1 == 2)
assert(entity_list1[1] and evo.empty(entity_list1[1]))
assert(entity_list1[2] and evo.empty(entity_list1[2]))
assert(not entity_list1[3])
entity_list2 = evo.multi_clone(3, prefab, { [f2] = 456, [f3] = "world" })
assert(entity_list2 and #entity_list2 == 3)
assert(entity_list2[1] and evo.empty(entity_list2[1]))
assert(entity_list2[2] and evo.empty(entity_list2[2]))
assert(entity_list2[3] and evo.empty(entity_list2[3]))
end
evo.commit()
do
assert(entity_list1 and #entity_list1 == 2)
assert(entity_list1[1] and not evo.empty(entity_list1[1]))
assert(entity_list1[2] and not evo.empty(entity_list1[2]))
assert(not entity_list1[3])
assert(
evo.get(entity_list1[1], f1) == false and
evo.get(entity_list1[1], f2) == 123 and
evo.get(entity_list1[1], f3) == nil)
assert(
evo.get(entity_list1[2], f1) == false and
evo.get(entity_list1[2], f2) == 123 and
evo.get(entity_list1[2], f3) == nil)
assert(entity_list2 and #entity_list2 == 3)
assert(entity_list2[1] and not evo.empty(entity_list2[1]))
assert(entity_list2[2] and not evo.empty(entity_list2[2]))
assert(entity_list2[3] and not evo.empty(entity_list2[3]))
assert(not entity_list2[4])
assert(
evo.get(entity_list2[1], f1) == false and
evo.get(entity_list2[1], f2) == 456 and
evo.get(entity_list2[1], f3) == "world")
assert(
evo.get(entity_list2[2], f1) == false and
evo.get(entity_list2[2], f2) == 456 and
evo.get(entity_list2[2], f3) == "world")
assert(
evo.get(entity_list2[3], f1) == false and
evo.get(entity_list2[3], f2) == 456 and
evo.get(entity_list2[3], f3) == "world")
end
end
end

File diff suppressed because it is too large Load Diff