39 Commits

Author SHA1 Message Date
BlackMATov
760b477564 update changelog 2025-11-21 06:31:42 +07:00
BlackMATov
fc910881bd cache defaults/duplicates per chunk, use it for spawn/clone ops 2025-11-21 05:37:14 +07:00
BlackMATov
71a7c84a67 add spawn/clone with defaults bmarks 2025-11-20 16:19:13 +07:00
BlackMATov
582a09a6db additional spawn/clone tests 2025-11-20 05:00:52 +07:00
BlackMATov
de73881f63 improve performance of the clone operations 2025-11-19 08:51:26 +07:00
BlackMATov
55e444ca63 improve performance of the spawn operations 2025-11-19 02:23:48 +07:00
BlackMATov
e499c701ef add defer clone bmarks 2025-11-12 23:44:34 +07:00
BlackMATov
789f167bf4 add defer spawn bmarks 2025-11-12 16:47:38 +07:00
BlackMATov
00367ce07e Merge branch 'feature/teal' into dev 2025-11-08 01:34:29 +07:00
BlackMATov
07902eb184 teal definitions cleanup 2025-11-07 23:26:45 +07:00
ecdbfe660f Merge pull request #30 from p0sel0k/main 2025-11-07 16:03:22 +07:00
p0sel0k
cfd68767cf fix: set and batch_set component argument should be optional 2025-11-04 21:57:00 +03:00
p0sel0k
f1ba9ab909 fix: replace number type with integer; EachState\ExecuteState records 2025-11-04 18:56:02 +03:00
BlackMATov
77ff3e77db readme: internal fragments
https://github.com/BlackMATov/evolved.lua/issues/28
2025-11-04 21:00:22 +07:00
p0sel0k
825eba5328 fix: remove teal types for internal usage 2025-11-04 10:06:01 +03:00
p0sel0k
67002503ed fix: removed IComponent and added generics for functions and hooks that take Component as a single argument 2025-11-03 11:57:18 +03:00
p0sel0k
1bb0089e9f fix: functions arguments naming 2025-11-02 21:21:25 +03:00
p0sel0k
dc642f5294 fix: fixes after review 2025-11-02 21:12:26 +03:00
p0sel0k
a81a8646e9 fix: wrong file name 2025-10-29 19:29:56 +03:00
p0sel0k
aa6d2c1c48 feat: add Teal language definitions 2025-10-29 19:24:07 +03:00
BlackMATov
5fe48de890 little speed up of exclude-only queries 2025-10-29 22:57:58 +07:00
0d7adcb5fd Merge pull request #27 from BlackMATov/dev
Dev
2025-10-20 16:16:39 +07:00
BlackMATov
f48f1bb290 v1.4.0 2025-10-20 16:11:03 +07:00
BlackMATov
6f1a85165f more tests 2025-10-16 06:22:30 +07:00
BlackMATov
bd87e593e9 root directory cleanup 2025-10-14 17:50:51 +07:00
BlackMATov
0eac310fd5 style fixes 2025-10-12 23:35:28 +07:00
BlackMATov
22cedd26bb remove some of the specialized defer functions in favor of the universal defer_call_hook 2025-10-12 07:04:44 +07:00
BlackMATov
d298be4188 ON_REMOVE hooks are now invoked before the fragment is actually removed from the entity
issue: https://github.com/BlackMATov/evolved.lua/issues/26
2025-10-12 06:46:43 +07:00
BlackMATov
24933e6a04 little internal hooks refactoring 2025-10-08 16:18:49 +07:00
BlackMATov
6841bb42fe style fixes 2025-10-07 22:56:29 +07:00
BlackMATov
dc912eb6da the universal builder:build/multi_build methods 2025-10-06 19:05:16 +07:00
BlackMATov
8d3c4633fb little coverage upping 2025-10-06 16:53:53 +07:00
BlackMATov
8704fb0c39 update changelog 2025-10-06 04:46:14 +07:00
BlackMATov
86c9ef7cf2 caching exclude-only queries was a mistake 2025-10-06 04:38:06 +07:00
BlackMATov
bd5f9bb61f cache exclude-only queries too 2025-10-06 02:53:38 +07:00
BlackMATov
cfa5dc7a9f lazy query chunks updating 2025-10-06 01:46:54 +07:00
BlackMATov
243adc1a93 fix query cache reset 2025-10-05 09:13:59 +07:00
BlackMATov
cf19fba9e4 cache query major chunks: first impl 2025-10-05 08:59:07 +07:00
BlackMATov
784b9c6a15 delele some unnecessary checks 2025-09-29 15:20:37 +07:00
16 changed files with 3854 additions and 1367 deletions

View File

@@ -1,5 +1,5 @@
{
"[json][jsonc][lua][markdown][yaml]": {
"[json][jsonc][lua][markdown][teal][yaml]": {
"editor.formatOnSave": true,
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,

131
README.md
View File

@@ -48,6 +48,7 @@
- [Fragment Hooks](#fragment-hooks)
- [Unique Fragments](#unique-fragments)
- [Explicit Fragments](#explicit-fragments)
- [Internal Fragments](#internal-fragments)
- [Shared Components](#shared-components)
- [Fragment Requirements](#fragment-requirements)
- [Destruction Policies](#destruction-policies)
@@ -59,6 +60,8 @@
- [Chunk](#chunk)
- [Builder](#builder)
- [Changelog](#changelog)
- [vX.X.X](#vxxx)
- [v1.4.0](#v140)
- [v1.3.0](#v130)
- [v1.2.0](#v120)
- [v1.1.0](#v110)
@@ -153,11 +156,11 @@ function evolved.alive_any(...) end
Sometimes (for debugging purposes, for example), it is necessary to extract the index and version from an identifier or to pack them back into an identifier. The [`evolved.pack`](#evolvedpack) and [`evolved.unpack`](#evolvedunpack) functions can be used for this purpose.
```lua
---@param index integer
---@param version integer
---@param primary integer
---@param secondary integer
---@return evolved.id id
---@nodiscard
function evolved.pack(index, version) end
function evolved.pack(primary, secondary) end
---@param id evolved.id
---@return integer primary
@@ -461,7 +464,7 @@ local health, stamina = evolved.id(2)
local enemy = evolved.builder()
:set(health, 100)
:set(stamina, 50)
:spawn()
:build()
```
Builders can be reused, so you can create a builder with a specific set of fragments and components and then use it to spawn multiple entities with the same fragments and components.
@@ -502,16 +505,16 @@ local evolved = require 'evolved'
local health = evolved.builder()
:name('health')
:spawn()
:build()
local stamina = evolved.builder()
:name('stamina')
:spawn()
:build()
local player = evolved.builder()
:set(health, 100)
:set(stamina, 50)
:spawn()
:build()
for fragment, component in evolved.each(player) do
print(string.format('Fragment (%s) has value %d',
@@ -600,7 +603,7 @@ The builder interface can be used to create queries too. It is more convenient t
local query = evolved.builder()
:include(health, poisoned)
:exclude(resistant)
:spawn()
:build()
```
We don't have to set both [`evolved.INCLUDES`](#evolvedincludes) and [`evolved.EXCLUDES`](#evolvedexcludes) fragments, we can even do it without filters at all, then the query will match all chunks in the world.
@@ -657,7 +660,7 @@ local health, poisoned = evolved.id(2)
local player = evolved.builder()
:set(health, 100)
:set(poisoned, true)
:spawn()
:build()
-- start a deferred scope
evolved.defer()
@@ -685,7 +688,7 @@ local health, poisoned = evolved.id(2)
local player = evolved.builder()
:set(health, 100)
:set(poisoned, true)
:spawn()
:build()
-- start a deferred scope
evolved.defer()
@@ -733,7 +736,7 @@ local destroying_mark = evolved.id()
local destroying_mark_query = evolved.builder()
:include(destroying_mark)
:spawn()
:build()
-- destroy all entities with the destroying_mark fragment
evolved.batch_destroy(destroying_mark_query)
@@ -755,7 +758,7 @@ local health, max_health = evolved.id(2)
local query = evolved.builder()
:include(health, max_health)
:spawn()
:build()
local system = evolved.builder()
:query(query)
@@ -768,7 +771,7 @@ local system = evolved.builder()
health_components[i] + 1,
max_health_components[i])
end
end):spawn()
end):build()
```
The [`evolved.process`](#evolvedprocess) function is used to process systems. It takes systems as arguments and executes them in the order they were passed.
@@ -795,7 +798,7 @@ local system = evolved.builder()
health_components[i] - 1,
0)
end
end):spawn()
end):build()
evolved.process(system)
```
@@ -814,7 +817,7 @@ local velocity_x, velocity_y = evolved.id(2)
local physical_body_query = evolved.builder()
:include(position_x, position_y)
:include(velocity_x, velocity_y)
:spawn()
:build()
local physics_group = evolved.id()
@@ -829,7 +832,7 @@ evolved.builder()
vx[i] = vx[i] + gravity_x
vy[i] = vy[i] + gravity_y
end
end):spawn()
end):build()
evolved.builder()
:group(physics_group)
@@ -845,7 +848,7 @@ evolved.builder()
px[i] = px[i] + vx[i]
py[i] = py[i] + vy[i]
end
end):spawn()
end):build()
evolved.process(physics_group)
```
@@ -862,7 +865,7 @@ local system = evolved.builder()
:epilogue(function()
print('Epilogue')
end)
:spawn()
:build()
evolved.process(system)
```
@@ -904,7 +907,7 @@ local evolved = require 'evolved'
local health = evolved.builder()
:on_set(function(entity, fragment, component)
print('health set to ' .. component)
end):spawn()
end):build()
local player = evolved.id()
evolved.set(player, health, 100) -- prints "health set to 100"
@@ -929,7 +932,7 @@ local enemy_prefab = evolved.builder()
:prefab()
:set(health, 100)
:set(stamina, 50)
:spawn()
:build()
local enemy_clone = evolved.clone(enemy_prefab)
@@ -951,18 +954,22 @@ local evolved = require 'evolved'
local enemy_tag = evolved.builder()
:tag()
:spawn()
:build()
local only_enabled_enemies = evolved.builder()
:include(enemy_tag)
:spawn()
:build()
local all_enemies_including_disabled = evolved.builder()
:include(enemy_tag)
:include(evolved.DISABLED)
:spawn()
:build()
```
#### Internal Fragments
All predefined fragments provided by the library are marked as internal with the [`evolved.INTERNAL`](#evolvedinternal) trait. Because [`evolved.INTERNAL`](#evolvedinternal) is itself marked as [`evolved.EXPLICIT`](#evolvedexplicit), these fragments are hidden from queries by default. This prevents accidental use of internal fragments in user code and helps distinguish them from user-defined fragments.
#### Shared Components
Often, we want to store components as tables, and by default, these tables will be shared between entities. This means that if you modify the table in one entity, it will be modified in all entities that share this table. Sometimes this is what we want. For example, when we want to share a configuration or some resource between entities. But in other cases, we want each entity to have its own copy of the table. For example, if we want to store the position of an entity as a table, we don't want to share this table with other entities. Yes, we can copy the table manually, but the library provides a little bit of syntactic sugar for this.
@@ -976,11 +983,11 @@ local position = evolved.id()
local enemy1 = evolved.builder()
:set(position, initial_position)
:spawn()
:build()
local enemy2 = evolved.builder()
:set(position, initial_position)
:spawn()
:build()
-- the enemy1 and enemy2 share the same table,
-- and that's definitely not what we want in this case
@@ -1005,15 +1012,15 @@ end
local position = evolved.builder()
:default(vector2(0, 0))
:duplicate(vector2_duplicate)
:spawn()
:build()
local enemy1 = evolved.builder()
:set(position)
:spawn()
:build()
local enemy2 = evolved.builder()
:set(position)
:spawn()
:build()
-- the enemy1 and enemy2 have different tables now
assert(evolved.get(enemy1, position) ~= evolved.get(enemy2, position))
@@ -1029,21 +1036,21 @@ local evolved = require 'evolved'
local position = evolved.builder()
:default(vector2(0, 0))
:duplicate(vector2_duplicate)
:spawn()
:build()
local velocity = evolved.builder()
:default(vector2(0, 0))
:duplicate(vector2_duplicate)
:spawn()
:build()
local physical = evolved.builder()
:tag()
:require(position, velocity)
:spawn()
:build()
local enemy = evolved.builder()
:set(physical)
:spawn()
:build()
assert(evolved.has_all(enemy, position, velocity))
```
@@ -1057,11 +1064,11 @@ local evolved = require 'evolved'
local world = evolved.builder()
:tag()
:spawn()
:build()
local entity = evolved.builder()
:set(world)
:spawn()
:build()
-- destroy the world fragment that is attached to the entity
evolved.destroy(world)
@@ -1082,11 +1089,11 @@ local evolved = require 'evolved'
local world = evolved.builder()
:tag()
:destruction_policy(evolved.DESTRUCTION_POLICY_DESTROY_ENTITY)
:spawn()
:build()
local entity = evolved.builder()
:set(world)
:spawn()
:build()
-- destroy the world fragment that is attached to the entity
evolved.destroy(world)
@@ -1181,10 +1188,10 @@ commit :: boolean
cancel :: boolean
spawn :: <fragment, component>? -> entity
multi_spawn :: integer, <fragment, component>? -> entity[]
multi_spawn :: integer, <fragment, component>? -> entity[], integer
clone :: entity, <fragment, component>? -> entity
multi_clone :: integer, entity, <fragment, component>? -> entity[]
multi_clone :: integer, entity, <fragment, component>? -> entity[], integer
alive :: entity -> boolean
alive_all :: entity... -> boolean
@@ -1245,11 +1252,14 @@ chunk_mt:components :: fragment... -> storage...
```
builder :: builder
builder_mt:build :: entity? -> entity
builder_mt:multi_build :: integer, entity? -> entity[], integer
builder_mt:spawn :: entity
builder_mt:multi_spawn :: integer -> entity[]
builder_mt:multi_spawn :: integer -> entity[], integer
builder_mt:clone :: entity -> entity
builder_mt:multi_clone :: integer, entity -> entity[]
builder_mt:multi_clone :: integer, entity -> entity[], integer
builder_mt:has :: fragment -> boolean
builder_mt:has_all :: fragment... -> boolean
@@ -1296,6 +1306,17 @@ builder_mt:destruction_policy :: id -> builder
## Changelog
### vX.X.X
- The spawn and clone operations with defaults have been significantly optimized
- Added basic [Teal](https://github.com/teal-language) type definitions, thanks to [@p0sel0k](https://github.com/p0sel0k)
### v1.4.0
- Improved query execution performance by caching some internal calculations
- Added the universal [`builder.build`](#evolvedbuilder_mtbuild) and [`builder.multi_build`](#evolvedbuilder_mtmulti_build) methods that can be used to spawn or clone entities depending on the method arguments
- [`evolved.ON_REMOVE`](#evolvedon_remove) hooks are now invoked before the fragment is actually removed from the entity
### v1.3.0
- Added the new [`evolved.cancel`](#evolvedcancel) function
@@ -1400,11 +1421,11 @@ function evolved.name(...) end
### `evolved.pack`
```lua
---@param index integer
---@param version integer
---@param primary integer
---@param secondary integer
---@return evolved.id id
---@nodiscard
function evolved.pack(index, version) end
function evolved.pack(primary, secondary) end
```
### `evolved.unpack`
@@ -1452,6 +1473,7 @@ function evolved.spawn(components) end
---@param entity_count integer
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity[] entity_list
---@return integer entity_count
function evolved.multi_spawn(entity_count, components) end
```
@@ -1471,6 +1493,7 @@ function evolved.clone(prefab, components) end
---@param prefab evolved.entity
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity[] entity_list
---@return integer entity_count
function evolved.multi_clone(entity_count, prefab, components) end
```
@@ -1776,6 +1799,24 @@ function evolved.chunk_mt:components(...) end
function evolved.builder() end
```
#### `evolved.builder_mt:build`
```lua
---@param prefab? evolved.entity
---@return evolved.entity entity
function evolved.builder_mt:build(prefab) end
```
### `evolved.builder_mt:multi_build`
```lua
---@param entity_count integer
---@param prefab? evolved.entity
---@return evolved.entity[] entity_list
---@return integer entity_count
function evolved.builder_mt:multi_build(entity_count, prefab) end
```
#### `evolved.builder_mt:spawn`
```lua
@@ -1788,6 +1829,7 @@ function evolved.builder_mt:spawn() end
```lua
---@param entity_count integer
---@return evolved.entity[] entity_list
---@return integer entity_count
function evolved.builder_mt:multi_spawn(entity_count) end
```
@@ -1805,6 +1847,7 @@ function evolved.builder_mt:clone(prefab) end
---@param entity_count integer
---@param prefab evolved.entity
---@return evolved.entity[] entity_list
---@return integer entity_count
function evolved.builder_mt:multi_clone(entity_count, prefab) end
```
@@ -1907,7 +1950,7 @@ function evolved.builder_mt:internal() end
#### `evolved.builder_mt:default`
```lua
---@param default evolved.component
---@param default evolved.default
---@return evolved.builder builder
function evolved.builder_mt:default(default) end
```

View File

@@ -2,7 +2,6 @@
## Backlog
- Queries can cache major chunks to avoid finding them every time.
- observers and events
- add INDEX fragment trait
- use compact prefix-tree for chunks
@@ -11,8 +10,9 @@
## Thoughts
- We can return deferred status from modifying operations and spawn/clone methods.
- Should we make one builder:build method instead of :spawn and :clone?
- We should have a way to not copy components on deferred spawn/clone.
## Known Issues
- Required fragments are slower than they should be
- Errors in hooks are cannot be handled properly right now

View File

@@ -1,10 +1,14 @@
require 'develop.samples.systems'
require 'develop.testing.build_tests'
require 'develop.testing.cancel_tests'
require 'develop.testing.clone_tests'
require 'develop.testing.locate_tests'
require 'develop.testing.main_tests'
require 'develop.testing.multi_spawn_tests'
require 'develop.testing.name_tests'
require 'develop.testing.requires_fragment_tests'
require 'develop.testing.spawn_tests'
require 'develop.testing.system_as_query_tests'
require 'develop.benchmarks.clone_bmarks'
@@ -14,13 +18,13 @@ require 'develop.benchmarks.process_bmarks'
require 'develop.benchmarks.spawn_bmarks'
require 'develop.benchmarks.table_bmarks'
require 'develop.untests'
local basics = require 'develop.basics'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.destroy_fuzz'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.execute_fuzz'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.batch_destroy_fuzz'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.explicit_fuzz'

View File

@@ -6,16 +6,35 @@ evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local D1, D2, D3, D4, D5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
evo.set(D1, evo.DEFAULT, true)
evo.set(D2, evo.DEFAULT, true)
evo.set(D3, evo.DEFAULT, true)
evo.set(D4, evo.DEFAULT, true)
evo.set(D5, evo.DEFAULT, true)
local R1 = evo.builder():require(F1):spawn()
local R3 = evo.builder():require(F1, F2, F3):spawn()
local R5 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
evo.set(D1, evo.DUPLICATE, function(v) return not v end)
evo.set(D2, evo.DUPLICATE, function(v) return not v end)
evo.set(D3, evo.DUPLICATE, function(v) return not v end)
evo.set(D4, evo.DUPLICATE, function(v) return not v end)
evo.set(D5, evo.DUPLICATE, function(v) return not v end)
local QF1 = evo.builder():include(F1):spawn()
local QD1 = evo.builder():include(D1):spawn()
local RF1 = evo.builder():require(F1):spawn()
local RF123 = evo.builder():require(F1, F2, F3):spawn()
local RF12345 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
local RD1 = evo.builder():require(D1):spawn()
local RD123 = evo.builder():require(D1, D2, D3):spawn()
local RD12345 = evo.builder():require(D1, D2, D3, D4, D5):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 1 component', N),
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 1 component', N),
function()
local clone = evo.clone
@@ -25,10 +44,41 @@ basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entitie
clone(prefab)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 3 components', N),
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 1 component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 1 component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [D1] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 3 components', N),
function()
local clone = evo.clone
@@ -38,10 +88,41 @@ basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entitie
clone(prefab)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 5 components', N),
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 3 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 3 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 5 components', N),
function()
local clone = evo.clone
@@ -51,53 +132,177 @@ basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entitie
clone(prefab)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer 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 }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 5 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 1 required component', N),
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 1 required component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [R1] = true }
local prefab = evo.spawn { [RF1] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 3 required components', N),
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 1 required component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [R3] = true }
local prefab = evo.spawn { [RF1] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 5 required components', N),
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 1 required component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [R5] = true }
local prefab = evo.spawn { [RD1] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 3 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF123] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 3 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF123] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 3 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RD123] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 5 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF12345] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 5 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF12345] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 5 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RD12345] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 1 component', N),
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 1 component', N),
function()
local multi_clone = evo.multi_clone
@@ -105,10 +310,37 @@ basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities
multi_clone(N, prefab)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 3 components', N),
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 1 component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true }
evo.defer()
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 1 component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [D1] = true }
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 3 components', N),
function()
local multi_clone = evo.multi_clone
@@ -116,10 +348,37 @@ basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities
multi_clone(N, prefab)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 5 components', N),
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 3 components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 3 components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true }
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 5 components', N),
function()
local multi_clone = evo.multi_clone
@@ -127,40 +386,147 @@ basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities
multi_clone(N, prefab)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer 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 }
evo.defer()
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 5 components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 1 required component', N),
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 1 required component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [R1] = true }
local prefab = evo.spawn { [RF1] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 3 required components', N),
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 1 required component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [R3] = true }
local prefab = evo.spawn { [RF1] = true }
evo.defer()
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 5 required components', N),
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 1 required component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [R5] = true }
local prefab = evo.spawn { [RD1] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 3 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF123] = true }
multi_clone(N, prefab)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 3 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF123] = true }
evo.defer()
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 3 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RD123] = true }
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 5 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF12345] = true }
multi_clone(N, prefab)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 5 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF12345] = true }
evo.defer()
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 5 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RD12345] = true }
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)

View File

@@ -6,16 +6,35 @@ evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local D1, D2, D3, D4, D5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
evo.set(D1, evo.DEFAULT, true)
evo.set(D2, evo.DEFAULT, true)
evo.set(D3, evo.DEFAULT, true)
evo.set(D4, evo.DEFAULT, true)
evo.set(D5, evo.DEFAULT, true)
local R1 = evo.builder():require(F1):spawn()
local R3 = evo.builder():require(F1, F2, F3):spawn()
local R5 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
evo.set(D1, evo.DUPLICATE, function(v) return not v end)
evo.set(D2, evo.DUPLICATE, function(v) return not v end)
evo.set(D3, evo.DUPLICATE, function(v) return not v end)
evo.set(D4, evo.DUPLICATE, function(v) return not v end)
evo.set(D5, evo.DUPLICATE, function(v) return not v end)
local QF1 = evo.builder():include(F1):spawn()
local QD1 = evo.builder():include(D1):spawn()
local RF1 = evo.builder():require(F1):spawn()
local RF123 = evo.builder():require(F1, F2, F3):spawn()
local RF12345 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
local RD1 = evo.builder():require(D1):spawn()
local RD123 = evo.builder():require(D1, D2, D3):spawn()
local RD12345 = evo.builder():require(D1, D2, D3, D4, D5):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 component', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 component', N),
function()
local spawn = evo.spawn
@@ -25,10 +44,41 @@ basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entitie
spawn(components)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 1 component', N),
function()
local spawn = evo.spawn
local components = { [F1] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 1 component', N),
function()
local spawn = evo.spawn
local components = { [D1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 components', N),
function()
local spawn = evo.spawn
@@ -38,10 +88,41 @@ basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entitie
spawn(components)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 3 components', N),
function()
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 3 components', N),
function()
local spawn = evo.spawn
local components = { [D1] = true, [D2] = true, [D3] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 components', N),
function()
local spawn = evo.spawn
@@ -51,53 +132,177 @@ basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entitie
spawn(components)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 5 components', N),
function()
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 5 components', N),
function()
local spawn = evo.spawn
local components = { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 required component', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 required component', N),
function()
local spawn = evo.spawn
local components = { [R1] = true }
local components = { [RF1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 required components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 1 required component', N),
function()
local spawn = evo.spawn
local components = { [R3] = true }
local components = { [RF1] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 required components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 1 required component', N),
function()
local spawn = evo.spawn
local components = { [R5] = true }
local components = { [RD1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 required components', N),
function()
local spawn = evo.spawn
local components = { [RF123] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 3 required components', N),
function()
local spawn = evo.spawn
local components = { [RF123] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 3 required components', N),
function()
local spawn = evo.spawn
local components = { [RD123] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 required components', N),
function()
local spawn = evo.spawn
local components = { [RF12345] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 5 required components', N),
function()
local spawn = evo.spawn
local components = { [RF12345] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 5 required components', N),
function()
local spawn = evo.spawn
local components = { [RD12345] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 component', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 component', N),
function()
local builder = evo.builder():set(F1)
@@ -105,10 +310,37 @@ basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entiti
builder:spawn()
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 1 component', N),
function()
local builder = evo.builder():set(F1)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 1 component', N),
function()
local builder = evo.builder():set(D1)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 components', N),
function()
local builder = evo.builder():set(F1):set(F2):set(F3)
@@ -116,10 +348,37 @@ basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entiti
builder:spawn()
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 3 components', N),
function()
local builder = evo.builder():set(F1):set(F2):set(F3)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 3 components', N),
function()
local builder = evo.builder():set(D1):set(D2):set(D3)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 components', N),
function()
local builder = evo.builder():set(F1):set(F2):set(F3):set(F4):set(F5)
@@ -127,47 +386,155 @@ basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entiti
builder:spawn()
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 5 components', N),
function()
local builder = evo.builder():set(F1):set(F2):set(F3):set(F4):set(F5)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 5 components', N),
function()
local builder = evo.builder():set(D1):set(D2):set(D3):set(D4):set(D5)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 required component', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 required component', N),
function()
local builder = evo.builder():set(R1)
local builder = evo.builder():set(RF1)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 required components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 1 required component', N),
function()
local builder = evo.builder():set(R3)
local builder = evo.builder():set(RF1)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 required components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 1 required component', N),
function()
local builder = evo.builder():set(R5)
local builder = evo.builder():set(RD1)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(Q1)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 required components', N),
function()
local builder = evo.builder():set(RF123)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 3 required components', N),
function()
local builder = evo.builder():set(RF123)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 3 required components', N),
function()
local builder = evo.builder():set(RD123)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 required components', N),
function()
local builder = evo.builder():set(RF12345)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 5 required components', N),
function()
local builder = evo.builder():set(RF12345)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 5 required components', N),
function()
local builder = evo.builder():set(RD12345)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 component', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 component', N),
function()
local multi_spawn = evo.multi_spawn
@@ -175,10 +542,37 @@ basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities
multi_spawn(N, components)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 1 component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true }
evo.defer()
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 1 component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [D1] = true }
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 components', N),
function()
local multi_spawn = evo.multi_spawn
@@ -186,10 +580,37 @@ basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities
multi_spawn(N, components)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 3 components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 3 components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [D1] = true, [D2] = true, [D3] = true }
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 components', N),
function()
local multi_spawn = evo.multi_spawn
@@ -197,12 +618,39 @@ basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities
multi_spawn(N, components)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer 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 }
evo.defer()
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 5 components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 required component', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 required component', N),
function()
local multi_spawn = evo.multi_spawn
@@ -210,27 +658,107 @@ basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities
multi_spawn(N, components)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 required components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 1 required component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [R3] = true }
local components = { [F1] = true }
evo.defer()
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 required components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 1 required component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [R5] = true }
local components = { [D1] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [RF123] = true }
multi_spawn(N, components)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 3 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [RF123] = true }
evo.defer()
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 3 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [RD123] = true }
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [RF12345] = true }
multi_spawn(N, components)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 5 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [RF12345] = true }
evo.defer()
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 5 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [RD12345] = true }
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)

View File

@@ -0,0 +1,267 @@
local evo = require 'evolved'
evo.debug_mode(true)
---
---
---
---
---
local __table_unpack = (function()
---@diagnostic disable-next-line: deprecated
return table.unpack or unpack
end)()
---
---
---
---
---
local all_fragment_list = {} ---@type evolved.fragment[]
for i = 1, math.random(1, 10) do
local fragment = evo.id()
all_fragment_list[i] = fragment
end
---@param query evolved.query
local function generate_query(query)
local include_set = {}
local include_list = {}
local include_count = 0
for _ = 1, math.random(0, #all_fragment_list) do
local include = all_fragment_list[math.random(1, #all_fragment_list)]
if not include_set[include] then
include_count = include_count + 1
include_set[include] = include_count
include_list[include_count] = include
end
end
local exclude_set = {}
local exclude_list = {}
local exclude_count = 0
for _ = 1, math.random(0, #all_fragment_list) do
local exclude = all_fragment_list[math.random(1, #all_fragment_list)]
if not exclude_set[exclude] then
exclude_count = exclude_count + 1
exclude_set[exclude] = exclude_count
exclude_list[exclude_count] = exclude
end
end
if include_count > 0 then
evo.set(query, evo.INCLUDES, include_list)
end
if exclude_count > 0 then
evo.set(query, evo.EXCLUDES, exclude_list)
end
end
---@param query_count integer
---@return evolved.query[] query_list
---@return integer query_count
---@nodiscard
local function generate_queries(query_count)
local query_list = {} ---@type evolved.query[]
for i = 1, query_count do
local query = evo.id()
query_list[i] = query
generate_query(query)
end
return query_list, query_count
end
---@param entity evolved.entity
local function generate_entity(entity)
for _ = 0, math.random(0, #all_fragment_list) do
local fragment = all_fragment_list[math.random(1, #all_fragment_list)]
evo.set(entity, fragment)
end
end
---@param entity_count integer
---@return evolved.entity[] entity_list
---@return integer entity_count
local function generate_entities(entity_count)
local entity_list = {} ---@type evolved.entity[]
for i = 1, entity_count do
local entity = evo.id()
entity_list[i] = entity
generate_entity(entity)
end
return entity_list, entity_count
end
local pre_query_list, pre_query_count = generate_queries(math.random(1, 10))
local pre_entity_list, pre_entity_count = generate_entities(math.random(1, 10))
for _ = 1, math.random(1, 5) do
local fragment = all_fragment_list[math.random(1, #all_fragment_list)]
evo.set(fragment, evo.EXPLICIT)
end
for _ = 1, math.random(1, 5) do
local query = pre_query_list[math.random(1, pre_query_count)]
if math.random(1, 2) == 1 then
generate_query(query)
else
if math.random(1, 2) == 1 then
evo.remove(query, evo.INCLUDES)
else
evo.remove(query, evo.EXCLUDES)
end
end
end
local post_query_list, post_query_count = generate_queries(math.random(1, 10))
local post_entity_list, post_entity_count = generate_entities(math.random(1, 10))
---
---
---
---
---
local all_query_list = {}
local all_query_count = 0
local all_entity_list = {}
local all_entity_count = 0
for i = 1, pre_query_count do
all_query_count = all_query_count + 1
all_query_list[all_query_count] = pre_query_list[i]
end
for i = 1, post_query_count do
all_query_count = all_query_count + 1
all_query_list[all_query_count] = post_query_list[i]
end
for i = 1, pre_entity_count do
all_entity_count = all_entity_count + 1
all_entity_list[all_entity_count] = pre_entity_list[i]
end
for i = 1, post_entity_count do
all_entity_count = all_entity_count + 1
all_entity_list[all_entity_count] = post_entity_list[i]
end
---
---
---
---
---
local function execute_query(query)
local query_chunk_set = {}
local query_entity_set = {}
local query_include_list = evo.get(query, evo.INCLUDES) or {}
local query_exclude_list = evo.get(query, evo.EXCLUDES) or {}
local query_include_set = {}
for _, include in ipairs(query_include_list) do
query_include_set[include] = true
end
for chunk, entity_list, entity_count in evo.execute(query) do
assert(not query_chunk_set[chunk])
query_chunk_set[chunk] = true
for i = 1, entity_count do
local entity = entity_list[i]
assert(not query_entity_set[entity])
query_entity_set[entity] = true
end
assert(chunk:has_all(__table_unpack(query_include_list)))
assert(not chunk:has_any(__table_unpack(query_exclude_list)))
end
for i = 1, all_entity_count do
local entity = all_entity_list[i]
local is_entity_matched =
evo.has_all(entity, __table_unpack(query_include_list))
and not evo.has_any(entity, __table_unpack(query_exclude_list))
for fragment in evo.each(entity) do
if evo.has(fragment, evo.EXPLICIT) and not query_include_set[fragment] then
is_entity_matched = false
end
end
if is_entity_matched then
assert(query_entity_set[entity])
else
assert(not query_entity_set[entity])
end
end
end
for i = 1, all_query_count do
execute_query(all_query_list[i])
end
---
---
---
---
---
for _ = 1, math.random(1, 5) do
local fragment = all_fragment_list[math.random(1, #all_fragment_list)]
evo.set(fragment, evo.EXPLICIT)
end
for _ = 1, math.random(1, 5) do
local query = pre_query_list[math.random(1, pre_query_count)]
if math.random(1, 2) == 1 then
generate_query(query)
else
if math.random(1, 2) == 1 then
evo.remove(query, evo.INCLUDES)
else
evo.remove(query, evo.EXCLUDES)
end
end
end
for i = 1, all_query_count do
execute_query(all_query_list[i])
end
---
---
---
---
---
if math.random(1, 2) == 1 then
evo.collect_garbage()
end
evo.destroy(__table_unpack(all_query_list))
evo.destroy(__table_unpack(all_entity_list))
evo.destroy(__table_unpack(all_fragment_list))
if math.random(1, 2) == 1 then
evo.collect_garbage()
end

View File

@@ -0,0 +1,41 @@
local evo = require 'evolved'
do
local f1, f2 = evo.id(2)
do
local e = evo.builder():set(f1, 42):set(f2, 'hello'):build()
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
end
do
local p = evo.builder():set(f1, 42):build()
local e = evo.builder():set(f2, 'hello'):build(p)
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
end
do
local entity_list, entity_count = evo.builder():set(f1, 42):set(f2, 'hello'):multi_build(5)
assert(entity_count == 5)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
end
end
do
local p = evo.builder():set(f1, 42):build()
local entity_list, entity_count = evo.builder():set(f2, 'hello'):multi_build(5, p)
assert(entity_count == 5)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
end
end
end

View File

@@ -0,0 +1,397 @@
local evo = require 'evolved'
do
do
local p = evo.spawn()
local e = evo.clone(p)
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn()
local e = evo.clone(p, {})
assert(evo.alive(e) and evo.empty(e))
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES, { f2 })
evo.set(f2, evo.DEFAULT, 42)
local p = evo.spawn()
local e = evo.clone(p, { [f1] = 'hello' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2))
assert(evo.has(e, f1) and evo.get(e, f1) == 'hello')
assert(evo.has(e, f2) and evo.get(e, f2) == 42)
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.TAG)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f4, evo.UNIQUE)
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p)
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p, {})
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p, { [f4] = 'another' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f4))
assert(evo.has(e, f4) and evo.get(e, f4) == 'another')
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f4] = 'another' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f2, f4))
assert(evo.has(e, f2) and evo.get(e, f2) == 100)
assert(evo.has(e, f4) and evo.get(e, f4) == 'another')
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f1] = 'hello', [f3] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == nil)
assert(evo.has(e, f2) and evo.get(e, f2) == 100)
assert(evo.has(e, f3) and evo.get(e, f3) == 10)
end
end
do
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f4, evo.TAG)
do
local p = evo.spawn { [f2] = 21, [f3] = 'hello', [f4] = true }
local e = evo.clone(p, { [f1] = 'world', [f2] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(e, f1) and evo.get(e, f1) == 'world')
assert(evo.has(e, f2) and evo.get(e, f2) == 10)
assert(evo.has(e, f3) and evo.get(e, f3) == 'hello')
assert(evo.has(e, f4) and evo.get(e, f4) == nil)
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f2, evo.DEFAULT, 42)
evo.set(f3, evo.DUPLICATE, function() return nil end)
evo.set(f4, evo.TAG)
do
local p = evo.spawn { [f2] = 21, [f3] = 'hello', [f4] = true }
local e = evo.clone(p, { [f1] = 'world', [f2] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(e, f1) and evo.get(e, f1) == 'world')
assert(evo.has(e, f2) and evo.get(e, f2) == 10)
assert(evo.has(e, f3) and evo.get(e, f3) == true)
assert(evo.has(e, f4) and evo.get(e, f4) == nil)
end
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.TAG)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f2, evo.DEFAULT, 42)
evo.set(f2, evo.DUPLICATE, function(v) return v * 2 end)
evo.set(f3, evo.DUPLICATE, function() return nil end)
evo.set(f4, evo.UNIQUE)
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p)
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p, {})
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p, { [f4] = 'another' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f4))
assert(evo.has(e, f4) and evo.get(e, f4) == 'another')
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f4] = 'another' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f2, f4))
assert(evo.has(e, f2) and evo.get(e, f2) == 200 * 2)
assert(evo.has(e, f4) and evo.get(e, f4) == 'another')
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f1] = 'hello', [f2] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == nil)
assert(evo.has(e, f2) and evo.get(e, f2) == 10 * 2)
assert(evo.has(e, f3) and evo.get(e, f3) == true)
end
local f1_set_count, f1_inserted_count = 0, 0
local f2_set_sum, f3_inserted_count = 0, 0
evo.set(f1, evo.ON_SET, function(e, f, c)
assert(evo.get(e, f) == c)
f1_set_count = f1_set_count + 1
end)
evo.set(f1, evo.ON_INSERT, function(e, f, c)
assert(evo.get(e, f) == c)
f1_inserted_count = f1_inserted_count + 1
end)
evo.set(f2, evo.ON_SET, function(e, f, c)
assert(evo.get(e, f) == c)
f2_set_sum = f2_set_sum + c
end)
evo.set(f3, evo.ON_INSERT, function(e, f, c)
assert(evo.get(e, f) == c)
f3_inserted_count = f3_inserted_count + 1
end)
do
f1_set_count, f1_inserted_count = 0, 0
f2_set_sum, f3_inserted_count = 0, 0
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f1] = 'hello', [f2] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == nil)
assert(evo.has(e, f2) and evo.get(e, f2) == 10 * 2)
assert(evo.has(e, f3) and evo.get(e, f3) == true)
assert(f1_set_count == 1)
assert(f1_inserted_count == 1)
assert(f2_set_sum == 100 * 2 + 10 * 2)
assert(f3_inserted_count == 1)
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.TAG)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f4, evo.UNIQUE)
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(1, p)
assert(#es == 1 and ec == 1)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(2, p, {})
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(3, p, { [f4] = 'another' })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f4))
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == 'another')
end
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(4, p, { [f4] = 'another' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f2, f4))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 100)
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == 'another')
end
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(5, p, { [f1] = 'hello', [f3] = 10 })
assert(#es == 5 and ec == 5)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 100)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == 10)
end
end
end
do
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f4, evo.TAG)
do
local p = evo.spawn { [f2] = 21, [f3] = 'hello', [f4] = true }
local es, ec = evo.multi_clone(2, p, { [f1] = 'world', [f2] = 10 })
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 'world')
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 10)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == 'hello')
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == nil)
end
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f2, evo.DEFAULT, 42)
evo.set(f3, evo.DUPLICATE, function() return nil end)
evo.set(f4, evo.TAG)
do
local p = evo.spawn { [f2] = 21, [f3] = 'hello', [f4] = true }
local es, ec = evo.multi_clone(2, p, { [f1] = 'world', [f2] = 10 })
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 'world')
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 10)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == nil)
end
end
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.TAG)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f2, evo.DEFAULT, 42)
evo.set(f2, evo.DUPLICATE, function(v) return v * 2 end)
evo.set(f3, evo.DUPLICATE, function() return nil end)
evo.set(f4, evo.UNIQUE)
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(3, p)
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(3, p, {})
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(2, p, { [f4] = 'another' })
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f4))
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == 'another')
end
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(4, p, { [f4] = 'another' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f2, f4))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 200 * 2)
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == 'another')
end
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(5, p, { [f1] = 'hello', [f2] = 10 })
assert(#es == 5 and ec == 5)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 10 * 2)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
end
end
local f1_set_count, f1_inserted_count = 0, 0
local f2_set_sum, f3_inserted_count = 0, 0
evo.set(f1, evo.ON_SET, function(e, f, c)
assert(evo.get(e, f) == c)
f1_set_count = f1_set_count + 1
end)
evo.set(f1, evo.ON_INSERT, function(e, f, c)
assert(evo.get(e, f) == c)
f1_inserted_count = f1_inserted_count + 1
end)
evo.set(f2, evo.ON_SET, function(e, f, c)
assert(evo.get(e, f) == c)
f2_set_sum = f2_set_sum + c
end)
evo.set(f3, evo.ON_INSERT, function(e, f, c)
assert(evo.get(e, f) == c)
f3_inserted_count = f3_inserted_count + 1
end)
do
f1_set_count, f1_inserted_count = 0, 0
f2_set_sum, f3_inserted_count = 0, 0
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(1, p, { [f1] = 'hello', [f2] = 10 })
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 10 * 2)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
assert(f1_set_count == 1)
assert(f1_inserted_count == 1)
assert(f2_set_sum == 100 * 2 + 10 * 2)
assert(f3_inserted_count == 1)
end
end
end

View File

@@ -2530,7 +2530,7 @@ do
end)
:on_remove(function(e, f, c)
f2_remove_count = f2_remove_count + 1
assert(evo.get(e, f) == nil)
assert(evo.get(e, f) == c)
assert(evo.alive(f))
assert(c == 82)
end)
@@ -3321,7 +3321,7 @@ do
remove_count = remove_count + 1
assert(f == f1)
assert(c == 51)
assert(evo.get(e, f1) == nil)
assert(evo.get(e, f1) == c)
do
evo.remove(e, f2)
@@ -3348,7 +3348,7 @@ do
remove_count = remove_count + 1
assert(f == f2)
assert(c == 51)
assert(evo.get(e, f2) == nil)
assert(evo.get(e, f2) == c)
end)
end
@@ -3518,8 +3518,7 @@ do
assert(e == e1 or e == e2)
assert(f == f1)
assert(c == 51)
assert(evo.get(e1, f1) == nil)
assert(evo.get(e2, f1) == nil)
assert(evo.get(e, f) == c)
end)
do
@@ -6449,3 +6448,650 @@ do
assert(b:has_all() and not b:has_any())
assert(b:has(ff) and b:has(ft) and b:has_all(ff, ft) and b:has_any(ff, ft))
end
do
do
local f = evo.id()
local q = evo.builder():include(f):spawn()
local e = evo.builder():set(f, 42):spawn()
local iter, state = evo.execute(q)
local chunk, entity_list, entity_count = iter(state)
assert(chunk and entity_list and entity_count)
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
end
do
local f = evo.id()
local e = evo.builder():set(f, 42):spawn()
local q = evo.builder():include(f):spawn()
local iter, state = evo.execute(q)
local chunk, entity_list, entity_count = iter(state)
assert(chunk and entity_list and entity_count)
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
end
do
local f1, f2 = evo.id(2)
local q = evo.builder():exclude(f2):spawn()
local e = evo.builder():set(f1, 42):spawn()
local e_count = 0
for chunk, entity_list, entity_count in evo.execute(q) do
for i = 1, entity_count do
if entity_list[i] == e then
e_count = e_count + 1
assert(chunk == evo.chunk(f1))
assert(chunk:components(f1)[1] == 42)
end
end
end
assert(e_count == 1)
end
do
local f1, f2, f3 = evo.id(3)
local q = evo.builder():exclude(f2):spawn()
local e1 = evo.builder():set(f1, 42):spawn()
local e2 = evo.builder():set(f1, 42):set(f3, 21):spawn()
local e1_count, e2_count = 0, 0
for chunk, entity_list, entity_count in evo.execute(q) do
for i = 1, entity_count do
if entity_list[i] == e1 then
e1_count = e1_count + 1
assert(chunk == evo.chunk(f1))
assert(chunk:components(f1)[1] == 42)
end
if entity_list[i] == e2 then
e2_count = e2_count + 1
assert(chunk == evo.chunk(f1, f3))
assert(chunk:components(f1)[1] == 42)
assert(chunk:components(f3)[1] == 21)
end
end
end
assert(e1_count == 1)
assert(e2_count == 1)
end
do
local f1, f2 = evo.id(2)
local e = evo.builder():set(f1, 42):spawn()
local q = evo.builder():exclude(f2):spawn()
local e_count = 0
for chunk, entity_list, entity_count in evo.execute(q) do
for i = 1, entity_count do
if entity_list[i] == e then
e_count = e_count + 1
assert(chunk == evo.chunk(f1))
assert(chunk:components(f1)[1] == 42)
end
end
end
assert(e_count == 1)
end
do
local f1, f2, f3 = evo.id(3)
local e1 = evo.builder():set(f1, 42):spawn()
local e2 = evo.builder():set(f1, 42):set(f3, 21):spawn()
local q = evo.builder():exclude(f2):spawn()
local e1_count, e2_count = 0, 0
for chunk, entity_list, entity_count in evo.execute(q) do
for i = 1, entity_count do
if entity_list[i] == e1 then
e1_count = e1_count + 1
assert(chunk == evo.chunk(f1))
assert(chunk:components(f1)[1] == 42)
end
if entity_list[i] == e2 then
e2_count = e2_count + 1
assert(chunk == evo.chunk(f1, f3))
assert(chunk:components(f1)[1] == 42)
assert(chunk:components(f3)[1] == 21)
end
end
end
assert(e1_count == 1)
assert(e2_count == 1)
end
end
do
local f1, f2 = evo.id(2)
local q1 = evo.builder():include(f1):spawn()
local q2 = evo.builder():include(f2):spawn()
local e12 = evo.builder():set(f1, 42):set(f2, 21):spawn()
do
local iter, state = evo.execute(q1)
local chunk, entity_list, entity_count = iter(state)
assert(chunk and entity_list and entity_count)
assert(chunk == evo.chunk(f1, f2) and entity_count == 1 and entity_list[1] == e12)
end
do
local iter, state = evo.execute(q2)
local chunk, entity_list, entity_count = iter(state)
assert(chunk and entity_list and entity_count)
assert(chunk == evo.chunk(f1, f2) and entity_count == 1 and entity_list[1] == e12)
end
evo.set(f1, evo.EXPLICIT)
do
local iter, state = evo.execute(q1)
local chunk, entity_list, entity_count = iter(state)
assert(chunk and entity_list and entity_count)
assert(chunk == evo.chunk(f1, f2) and entity_count == 1 and entity_list[1] == e12)
end
do
local iter, state = evo.execute(q2)
local chunk, entity_list, entity_count = iter(state)
assert(not chunk and not entity_list and not entity_count)
end
end
do
local function v2(x, y) return { x = x or 0, y = y or 0 } end
local function v2_clone(v) return { x = v.x, y = v.y } end
local f1, f2 = evo.id(2)
local f1_default = v2(1, 2)
local f2_default = v2(3, 4)
evo.set(f1, evo.DEFAULT, f1_default)
evo.set(f2, evo.DEFAULT, f2_default)
evo.set(f1, evo.DUPLICATE, v2_clone)
evo.set(f2, evo.DUPLICATE, v2_clone)
local e1 = evo.builder():set(f1, v2(10, 11)):spawn()
local e2 = evo.builder():set(f1, v2(12, 13)):set(f2, v2(14, 15)):spawn()
do
assert(evo.has(e1, f1) and evo.get(e1, f1).x == 10 and evo.get(e1, f1).y == 11)
assert(evo.get(e1, f1) ~= f1_default)
assert(evo.has(e2, f1) and evo.get(e2, f1).x == 12 and evo.get(e2, f1).y == 13)
assert(evo.get(e2, f1) ~= f1_default)
assert(evo.has(e2, f2) and evo.get(e2, f2).x == 14 and evo.get(e2, f2).y == 15)
assert(evo.get(e2, f2) ~= f2_default)
end
evo.set(f1, evo.TAG)
do
assert(evo.has(e1, f1) and evo.get(e1, f1) == nil)
assert(evo.has(e2, f1) and evo.get(e2, f1) == nil)
assert(evo.has(e2, f2) and evo.get(e2, f2).x == 14 and evo.get(e2, f2).y == 15)
assert(evo.get(e2, f2) ~= f2_default)
end
evo.remove(f1, evo.TAG)
do
assert(evo.has(e1, f1) and evo.get(e1, f1).x == 1 and evo.get(e1, f1).y == 2)
assert(evo.get(e1, f1) ~= f1_default)
assert(evo.has(e2, f1) and evo.get(e2, f1).x == 1 and evo.get(e2, f1).y == 2)
assert(evo.get(e2, f1) ~= f1_default)
assert(evo.has(e2, f2) and evo.get(e2, f2).x == 14 and evo.get(e2, f2).y == 15)
assert(evo.get(e2, f2) ~= f2_default)
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f2, evo.DEFAULT, false)
evo.set(f3, evo.TAG)
local v_set_sum = 0
local v_insert_sum = 0
local f3_set_times = 0
local f3_insert_times = 0
evo.set(f1, evo.ON_SET, function(e, f, v)
assert(f == f1)
v_set_sum = v_set_sum + v
assert(evo.get(e, f) == v)
end)
evo.set(f1, evo.ON_INSERT, function(e, f, v)
assert(f == f1)
v_insert_sum = v_insert_sum + v
assert(evo.get(e, f) == v)
end)
evo.set(f3, evo.ON_SET, function(e, f, v)
assert(f == f3)
f3_set_times = f3_set_times + 1
assert(v == nil)
assert(evo.has(e, f))
end)
evo.set(f3, evo.ON_INSERT, function(e, f, v)
assert(f == f3)
f3_insert_times = f3_insert_times + 1
assert(v == nil)
assert(evo.has(e, f))
end)
do
local e = evo.spawn({ [f1] = 42 })
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
local e = evo.clone(entity_prefab)
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
evo.remove(entity_prefab, f2, f3)
local e = evo.clone(entity_prefab, { [f1] = 21 })
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 21)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
end
assert(v_set_sum == 42 * 4 + 21 * 1)
assert(v_insert_sum == 42 * 4 + 21 * 1)
assert(f3_set_times == 5)
assert(f3_insert_times == 5)
end
do
local function v2(x, y) return { x = x or 0, y = y or 0 } end
local function v2_clone(v) return { x = v.x, y = v.y } end
local f1, f2, f3, f4, f5, f6, f7 = evo.id(7)
evo.set(f1, evo.REQUIRES, { f2, f3, f4 })
evo.set(f5, evo.REQUIRES, { f6, f7 })
local f1_default = v2(1, 2)
local f2_default = v2(3, 4)
local f3_default = v2(10, 11)
local f4_default = v2(12, 13)
local f6_default = v2(14, 15)
local f7_default = v2(16, 17)
evo.set(f1, evo.DEFAULT, f1_default)
evo.set(f2, evo.DEFAULT, f2_default)
evo.set(f3, evo.DEFAULT, f3_default)
evo.set(f4, evo.DEFAULT, f4_default)
evo.set(f6, evo.DEFAULT, f6_default)
evo.set(f7, evo.DEFAULT, f7_default)
evo.set(f1, evo.DUPLICATE, v2_clone)
evo.set(f2, evo.DUPLICATE, v2_clone)
evo.set(f3, evo.DUPLICATE, v2_clone)
evo.set(f5, evo.DUPLICATE, v2_clone)
evo.set(f6, evo.DUPLICATE, v2_clone)
do
local entity_list, entity_count = evo.multi_spawn(2, { [f1] = v2(5, 6), [f2] = v2(7, 8) })
assert(entity_list and #entity_list == 2)
assert(entity_count == 2)
local q_f1 = evo.builder():include(f1):spawn()
local f2_v = v2(20, 21)
evo.batch_set(q_f1, f2, f2_v)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2).x == 20 and evo.get(e, f2).y == 21)
assert(evo.has(e, f3) and evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4).x == 12 and evo.get(e, f4).y == 13)
assert(evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f2) ~= f2_v and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f4) == f4_default)
end
local f5_v = v2(30, 31)
evo.batch_set(q_f1, f5, f5_v)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2).x == 20 and evo.get(e, f2).y == 21)
assert(evo.has(e, f3) and evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4).x == 12 and evo.get(e, f4).y == 13)
assert(evo.has(e, f5) and evo.get(e, f5).x == 30 and evo.get(e, f5).y == 31)
assert(evo.has(e, f6) and evo.get(e, f6).x == 14 and evo.get(e, f6).y == 15)
assert(evo.has(e, f7) and evo.get(e, f7).x == 16 and evo.get(e, f7).y == 17)
assert(evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f2) ~= f2_v and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f4) == f4_default)
assert(evo.get(e, f5) ~= f5_v)
assert(evo.get(e, f6) ~= f6_default)
assert(evo.get(e, f7) == f7_default)
end
f5_v = v2(32, 33)
evo.batch_set(q_f1, f5, f5_v)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2).x == 20 and evo.get(e, f2).y == 21)
assert(evo.has(e, f3) and evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4).x == 12 and evo.get(e, f4).y == 13)
assert(evo.has(e, f5) and evo.get(e, f5).x == 32 and evo.get(e, f5).y == 33)
assert(evo.has(e, f6) and evo.get(e, f6).x == 14 and evo.get(e, f6).y == 15)
assert(evo.has(e, f7) and evo.get(e, f7).x == 16 and evo.get(e, f7).y == 17)
assert(evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f2) ~= f2_v and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f4) == f4_default)
assert(evo.get(e, f5) ~= f5_v)
assert(evo.get(e, f6) ~= f6_default)
assert(evo.get(e, f7) == f7_default)
end
end
end
do
local function v2(x, y) return { x = x or 0, y = y or 0 } end
local function v2_clone(v) return { x = v.x, y = v.y } end
local f1, f2, f3, f4, f5, f6, f7 = evo.id(7)
evo.set(f1, evo.REQUIRES, { f2, f3, f4 })
evo.set(f5, evo.REQUIRES, { f6, f7 })
local f1_default = v2(1, 2)
local f2_default = v2(3, 4)
local f3_default = v2(10, 11)
local f4_default = v2(12, 13)
local f6_default = v2(14, 15)
local f7_default = v2(16, 17)
evo.set(f1, evo.DEFAULT, f1_default)
evo.set(f2, evo.DEFAULT, f2_default)
evo.set(f3, evo.DEFAULT, f3_default)
evo.set(f4, evo.DEFAULT, f4_default)
evo.set(f6, evo.DEFAULT, f6_default)
evo.set(f7, evo.DEFAULT, f7_default)
evo.set(f1, evo.DUPLICATE, v2_clone)
evo.set(f2, evo.DUPLICATE, v2_clone)
evo.set(f3, evo.DUPLICATE, v2_clone)
evo.set(f5, evo.DUPLICATE, v2_clone)
evo.set(f6, evo.DUPLICATE, v2_clone)
local f5_set_sum = 0
local f5_insert_sum = 0
local f6_set_sum = 0
local f6_insert_sum = 0
local f7_set_sum = 0
local f7_insert_sum = 0
evo.set(f5, evo.ON_SET, function(e, f, v)
assert(evo.get(e, f) == v)
assert(f == f5)
f5_set_sum = f5_set_sum + v.x + v.y
end)
evo.set(f5, evo.ON_INSERT, function(e, f, v)
assert(evo.get(e, f) == v)
assert(f == f5)
f5_insert_sum = f5_insert_sum + v.x + v.y
end)
evo.set(f6, evo.ON_SET, function(e, f, v)
assert(evo.get(e, f) == v)
assert(f == f6)
f6_set_sum = f6_set_sum + v.x + v.y
end)
evo.set(f6, evo.ON_INSERT, function(e, f, v)
assert(evo.get(e, f) == v)
assert(f == f6)
f6_insert_sum = f6_insert_sum + v.x + v.y
end)
evo.set(f7, evo.ON_SET, function(e, f, v)
assert(evo.get(e, f) == v)
assert(f == f7)
f7_set_sum = f7_set_sum + v.x + v.y
end)
evo.set(f7, evo.ON_INSERT, function(e, f, v)
assert(evo.get(e, f) == v)
assert(f == f7)
f7_insert_sum = f7_insert_sum + v.x + v.y
end)
do
local entity_list, entity_count = evo.multi_spawn(2, { [f1] = v2(5, 6), [f2] = v2(7, 8) })
assert(entity_list and #entity_list == 2)
assert(entity_count == 2)
local q_f1 = evo.builder():include(f1):spawn()
local f2_v = v2(20, 21)
evo.batch_set(q_f1, f2, f2_v)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2).x == 20 and evo.get(e, f2).y == 21)
assert(evo.has(e, f3) and evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4).x == 12 and evo.get(e, f4).y == 13)
assert(evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f2) ~= f2_v and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f4) == f4_default)
end
assert(f5_set_sum == 0)
assert(f5_insert_sum == 0)
assert(f6_set_sum == 0)
assert(f6_insert_sum == 0)
assert(f7_set_sum == 0)
assert(f7_insert_sum == 0)
local f5_v = v2(30, 31)
evo.batch_set(q_f1, f5, f5_v)
assert(f5_set_sum == (30 + 31) * entity_count)
assert(f5_insert_sum == (30 + 31) * entity_count)
assert(f6_set_sum == (14 + 15) * entity_count)
assert(f6_insert_sum == (14 + 15) * entity_count)
assert(f7_set_sum == (16 + 17) * entity_count)
assert(f7_insert_sum == (16 + 17) * entity_count)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2).x == 20 and evo.get(e, f2).y == 21)
assert(evo.has(e, f3) and evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4).x == 12 and evo.get(e, f4).y == 13)
assert(evo.has(e, f5) and evo.get(e, f5).x == 30 and evo.get(e, f5).y == 31)
assert(evo.has(e, f6) and evo.get(e, f6).x == 14 and evo.get(e, f6).y == 15)
assert(evo.has(e, f7) and evo.get(e, f7).x == 16 and evo.get(e, f7).y == 17)
assert(evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f2) ~= f2_v and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f4) == f4_default)
assert(evo.get(e, f5) ~= f5_v)
assert(evo.get(e, f6) ~= f6_default)
assert(evo.get(e, f7) == f7_default)
end
f5_set_sum = 0
f5_insert_sum = 0
f6_set_sum = 0
f6_insert_sum = 0
f7_set_sum = 0
f7_insert_sum = 0
f5_v = v2(32, 33)
evo.batch_set(q_f1, f5, f5_v)
assert(f5_set_sum == (32 + 33) * entity_count)
assert(f5_insert_sum == 0)
assert(f6_set_sum == 0)
assert(f6_insert_sum == 0)
assert(f7_set_sum == 0)
assert(f7_insert_sum == 0)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2).x == 20 and evo.get(e, f2).y == 21)
assert(evo.has(e, f3) and evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4).x == 12 and evo.get(e, f4).y == 13)
assert(evo.has(e, f5) and evo.get(e, f5).x == 32 and evo.get(e, f5).y == 33)
assert(evo.has(e, f6) and evo.get(e, f6).x == 14 and evo.get(e, f6).y == 15)
assert(evo.has(e, f7) and evo.get(e, f7).x == 16 and evo.get(e, f7).y == 17)
assert(evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f2) ~= f2_v and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f4) == f4_default)
assert(evo.get(e, f5) ~= f5_v)
assert(evo.get(e, f6) ~= f6_default)
assert(evo.get(e, f7) == f7_default)
end
end
end
do
local s1, s2 = evo.id(2)
local process_order = ''
evo.set(s1, evo.PROLOGUE, function()
process_order = process_order .. '1'
end)
evo.set(s2, evo.PROLOGUE, function()
process_order = process_order .. '2'
end)
do
process_order = ''
evo.set(s2, evo.GROUP, s1)
evo.process(s1)
assert(process_order == '12')
end
do
process_order = ''
evo.remove(s2, evo.GROUP)
evo.process(s1)
assert(process_order == '1')
end
end
do
local s1, s2, s3 = evo.id(3)
local process_order = ''
evo.set(s1, evo.PROLOGUE, function()
process_order = process_order .. '1'
end)
evo.set(s2, evo.PROLOGUE, function()
process_order = process_order .. '2'
end)
evo.set(s3, evo.PROLOGUE, function()
process_order = process_order .. '3'
end)
do
process_order = ''
evo.set(s2, evo.GROUP, s1)
evo.process(s1)
assert(process_order == '12')
end
do
process_order = ''
evo.set(s2, evo.GROUP, s3)
evo.process(s1)
assert(process_order == '1')
evo.process(s3)
assert(process_order == '132')
end
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.NAME, 'f1')
evo.set(f2, evo.NAME, 'f2')
do
local c1 = evo.chunk(f1)
assert(tostring(c1) == '<f1>')
local c2 = evo.chunk(f2)
assert(tostring(c2) == '<f2>')
local c12 = evo.chunk(f1, f2)
assert(tostring(c12) == '<f1, f2>')
local c21 = evo.chunk(f2, f1)
assert(tostring(c21) == '<f1, f2>')
end
do
local b = evo.builder():set(f1)
assert(tostring(b) == '<f1>')
b:set(f1, 1):set(f2, 2)
assert(tostring(b) == '<f1, f2>')
end
end

View File

@@ -306,3 +306,302 @@ do
end
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f3, evo.TAG)
do
local entity_list, entity_count = evo.multi_spawn(2, { [f1] = 42 })
assert(entity_list and #entity_list == 2)
assert(entity_count == 2)
for i = 1, entity_count do
local e = entity_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == true)
assert(evo.has(e, f3) and evo.get(e, f3) == nil)
end
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
local clone_list, clone_count = evo.multi_clone(2, entity_prefab)
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == true)
assert(evo.has(e, f3) and evo.get(e, f3) == nil)
end
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
evo.remove(entity_prefab, f2, f3)
local clone_list, clone_count = evo.multi_clone(2, entity_prefab, { [f1] = 21 })
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 21)
assert(evo.has(e, f2) and evo.get(e, f2) == true)
assert(evo.has(e, f3) and evo.get(e, f3) == nil)
end
end
evo.set(f2, evo.DEFAULT, false)
do
local entity_list, entity_count = evo.multi_spawn(2, { [f1] = 42 })
assert(entity_list and #entity_list == 2)
assert(entity_count == 2)
for i = 1, entity_count do
local e = entity_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
assert(evo.has(e, f3) and evo.get(e, f3) == nil)
end
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
local clone_list, clone_count = evo.multi_clone(2, entity_prefab)
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
assert(evo.has(e, f3) and evo.get(e, f3) == nil)
end
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
evo.remove(entity_prefab, f2, f3)
local clone_list, clone_count = evo.multi_clone(2, entity_prefab, { [f1] = 21 })
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 21)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
assert(evo.has(e, f3) and evo.get(e, f3) == nil)
end
end
local v_set_sum = 0
local v_insert_sum = 0
local f3_set_times = 0
local f3_insert_times = 0
evo.set(f1, evo.ON_SET, function(e, f, v)
assert(f == f1)
v_set_sum = v_set_sum + v
assert(evo.get(e, f) == v)
end)
evo.set(f1, evo.ON_INSERT, function(e, f, v)
assert(f == f1)
v_insert_sum = v_insert_sum + v
assert(evo.get(e, f) == v)
end)
evo.set(f3, evo.ON_SET, function(e, f, v)
assert(f == f3)
f3_set_times = f3_set_times + 1
assert(v == nil)
assert(evo.has(e, f))
end)
evo.set(f3, evo.ON_INSERT, function(e, f, v)
assert(f == f3)
f3_insert_times = f3_insert_times + 1
assert(v == nil)
assert(evo.has(e, f))
end)
do
local entity_list, entity_count = evo.multi_spawn(2, { [f1] = 42 })
assert(entity_list and #entity_list == 2)
assert(entity_count == 2)
for i = 1, entity_count do
local e = entity_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
end
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
local clone_list, clone_count = evo.multi_clone(2, entity_prefab)
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
end
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
evo.remove(entity_prefab, f2, f3)
local clone_list, clone_count = evo.multi_clone(2, entity_prefab, { [f1] = 21 })
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 21)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
end
end
assert(v_set_sum == 42 * 6 + 21 * 2)
assert(v_insert_sum == 42 * 6 + 21 * 2)
assert(f3_set_times == 8)
assert(f3_insert_times == 8)
end
do
local function v2(x, y) return { x = x or 0, y = y or 0 } end
local function v2_clone(v) return { x = v.x, y = v.y } end
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.REQUIRES, { f2, f3, f4 })
local f1_default = v2(1, 2)
local f2_default = v2(3, 4)
local f3_default = v2(10, 11)
local f4_default = v2(12, 13)
evo.set(f1, evo.DEFAULT, f1_default)
evo.set(f2, evo.DEFAULT, f2_default)
evo.set(f3, evo.DEFAULT, f3_default)
evo.set(f4, evo.DEFAULT, f4_default)
evo.set(f1, evo.DUPLICATE, v2_clone)
evo.set(f2, evo.DUPLICATE, v2_clone)
evo.set(f3, evo.DUPLICATE, v2_clone)
do
local entity_list, entity_count = evo.multi_spawn(2, { [f1] = v2(5, 6), [f2] = v2(7, 8) })
assert(entity_list and #entity_list == 2)
assert(entity_count == 2)
for i = 1, entity_count do
local e = entity_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f2).x == 7 and evo.get(e, f2).y == 8)
assert(evo.has(e, f3) and evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4) == f4_default)
end
end
do
local entity_prefab = evo.builder():set(f1, v2(5, 6)):set(f2, v2(7, 8)):spawn()
local clone_list, clone_count = evo.multi_clone(2, entity_prefab, { [f2] = f2_default })
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) ~= f1_default and evo.get(e, f1) ~= evo.get(entity_prefab, f1))
assert(evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2) ~= f2_default and evo.get(e, f2) ~= evo.get(entity_prefab, f2))
assert(evo.get(e, f2).x == 3 and evo.get(e, f2).y == 4)
assert(evo.has(e, f3) and evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4) == f4_default)
end
end
do
local entity_prefab = evo.builder():set(f1, v2(5, 6)):set(f2, v2(7, 8)):spawn()
evo.remove(entity_prefab, f2, f3, f4)
local clone_list, clone_count = evo.multi_clone(2, entity_prefab, { [f2] = f2_default })
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) ~= f1_default and evo.get(e, f1) ~= evo.get(entity_prefab, f1))
assert(evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2) ~= f2_default and evo.get(e, f2) ~= evo.get(entity_prefab, f2))
assert(evo.get(e, f2).x == 3 and evo.get(e, f2).y == 4)
assert(evo.has(e, f3) and evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4) == f4_default)
end
end
end

View File

@@ -0,0 +1,329 @@
local evo = require 'evolved'
do
do
local e = evo.spawn()
assert(evo.alive(e) and evo.empty(e))
end
do
local e = evo.spawn({})
assert(evo.alive(e) and evo.empty(e))
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f2, evo.REQUIRES, { f1, f3 })
do
local e = evo.spawn({ [f1] = 42 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
end
do
local e = evo.spawn({ [f1] = 42, [f2] = 'hello' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
assert(evo.has(e, f3) and evo.get(e, f3) == true)
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f2, evo.REQUIRES, { f1, f3 })
evo.set(f3, evo.DEFAULT, 21)
evo.set(f3, evo.REQUIRES, { f2 })
do
local e = evo.spawn({ [f1] = 42 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
end
do
local e = evo.spawn({ [f1] = 42, [f2] = 'hello' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
assert(evo.has(e, f3) and evo.get(e, f3) == 21)
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f2, evo.DUPLICATE, function() return nil end)
evo.set(f2, evo.REQUIRES, { f1, f3, f4 })
evo.set(f3, evo.DEFAULT, 21)
evo.set(f3, evo.DUPLICATE, function(v) return v * 3 end)
evo.set(f3, evo.REQUIRES, { f2 })
do
local e = evo.spawn({ [f1] = 42 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
end
do
local e = evo.spawn({ [f1] = 42, [f2] = true })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == true)
assert(evo.has(e, f3) and evo.get(e, f3) == 21 * 3)
assert(evo.has(e, f4) and evo.get(e, f4) == true)
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f2, evo.REQUIRES, { f3 })
evo.set(f3, evo.TAG)
local f2_set_sum, f2_inserted_sum = 0, 0
local f3_set_count, f3_inserted_count = 0, 0
evo.set(f2, evo.ON_SET, function(e, f, c)
assert(c == 42)
assert(evo.get(e, f) == c)
assert(f == f2)
f2_set_sum = f2_set_sum + c
end)
evo.set(f2, evo.ON_INSERT, function(e, f, c)
assert(c == 42)
assert(evo.get(e, f) == c)
assert(f == f2)
f2_inserted_sum = f2_inserted_sum + c
end)
evo.set(f3, evo.ON_SET, function(e, f, c)
assert(c == nil)
assert(evo.get(e, f) == c)
assert(f == f3)
f3_set_count = f3_set_count + 1
end)
evo.set(f3, evo.ON_INSERT, function(e, f, c)
assert(c == nil)
assert(evo.get(e, f) == c)
assert(f == f3)
f3_inserted_count = f3_inserted_count + 1
end)
do
f3_set_count, f3_inserted_count = 0, 0
local e = evo.spawn({ [f1] = 'hello', [f2] = 42 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(f2_set_sum == 42 and f2_inserted_sum == 42)
assert(f3_set_count == 1 and f3_inserted_count == 1)
end
end
do
do
local es, ec = evo.multi_spawn(2)
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local es, ec = evo.multi_spawn(2, {})
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
end
do
local f1, f2 = evo.id(2)
do
local es, ec = evo.multi_spawn(3, { [f1] = 42 })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
end
end
do
local es, ec = evo.multi_spawn(3, { [f1] = 42, [f2] = 'hello' })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'hello')
end
end
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES, { f2 })
do
local es, ec = evo.multi_spawn(3, { [f1] = 42 })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == true)
end
end
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES, { f2 })
do
local es, ec = evo.multi_spawn(1, { [f1] = 42 })
assert(#es == 1 and ec == 1)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == true)
end
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f2, evo.DEFAULT, 'hello')
do
local es, ec = evo.multi_spawn(4, { [f1] = 42 })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'hello')
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
end
end
do
local es, ec = evo.multi_spawn(4, { [f1] = 42, [f2] = 'world' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'world')
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
end
end
do
local es, ec = evo.multi_spawn(4, { [f1] = 42, [f2] = 'world', [f3] = false })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'world')
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == false)
end
end
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES, { f2 })
evo.set(f1, evo.DUPLICATE, function() return nil end)
evo.set(f2, evo.DEFAULT, 'hello')
evo.set(f2, evo.DUPLICATE, function(v) return v .. '!' end)
do
local es, ec = evo.multi_spawn(4, { [f1] = 42 })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == true)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'hello!')
end
end
do
local es, ec = evo.multi_spawn(4, { [f1] = 42, [f2] = 'world' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == true)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'world!')
end
end
do
local es, ec = evo.multi_spawn(4, { [f2] = 'hello world' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f2))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'hello world!')
end
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f2, evo.REQUIRES, { f3 })
evo.set(f3, evo.TAG)
local f2_set_sum, f2_inserted_sum = 0, 0
local f3_set_count, f3_inserted_count = 0, 0
evo.set(f2, evo.ON_SET, function(e, f, c)
assert(c == 42)
assert(evo.get(e, f) == c)
assert(f == f2)
f2_set_sum = f2_set_sum + c
end)
evo.set(f2, evo.ON_INSERT, function(e, f, c)
assert(c == 42)
assert(evo.get(e, f) == c)
assert(f == f2)
f2_inserted_sum = f2_inserted_sum + c
end)
evo.set(f3, evo.ON_SET, function(e, f, c)
assert(c == nil)
assert(evo.get(e, f) == c)
assert(f == f3)
f3_set_count = f3_set_count + 1
end)
evo.set(f3, evo.ON_INSERT, function(e, f, c)
assert(c == nil)
assert(evo.get(e, f) == c)
assert(f == f3)
f3_inserted_count = f3_inserted_count + 1
end)
do
local es, ec = evo.multi_spawn(3, { [f1] = 'hello', [f2] = 42 })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(f2_set_sum == 42 * 3 and f2_inserted_sum == 42 * 3)
assert(f3_set_count == 3 and f3_inserted_count == 3)
end
end
end

181
evolved.d.tl Normal file
View File

@@ -0,0 +1,181 @@
local record Evolved
interface Id end
type Entity = Id
type Fragment = Id
type Query = Id
type System = Id
interface EachState end
interface ExecuteState end
type EachIterator = function(state?: EachState): Fragment, any
type ExecuteIterator = function(state?: ExecuteState): Chunk, { Entity }, integer
interface Chunk
alive: function(self: Chunk): boolean
empty: function(self: Chunk): boolean
has: function(self: Chunk, fragment: Fragment): boolean
has_all: function(self: Chunk, ...: Fragment): boolean
has_any: function(self: Chunk, ...: Fragment): boolean
entities: function(self: Chunk): { Entity }, integer
fragments: function(self: Chunk): { Fragment }, integer
components: function(self: Chunk)
components: function<C1>(self: Chunk, f1: Fragment): { C1 }
components: function<C1, C2>(self: Chunk, f1: Fragment, f2: Fragment): { C1 }, { C2 }
components: function<C1, C2, C3>(self: Chunk, f1: Fragment, f2: Fragment, f3: Fragment): { C1 }, { C2 }, { C3 }
components: function<C1, C2, C3, C4>(self: Chunk, f1: Fragment, f2: Fragment, f3: Fragment, f4: Fragment): { C1 }, { C2 }, { C3 }, { C4 }
end
interface Builder
build: function(self: Builder, prefab?: Entity): Entity
multi_build: function(self: Builder, entity_count: integer, prefab?: Entity): { Entity }, integer
spawn: function(self: Builder): Entity
multi_spawn: function(self: Builder, entity_count: integer): { Entity }, integer
clone: function(self: Builder, prefab: Entity): Entity
multi_clone: function(self: Builder, entity_count: integer, prefab: Entity): { Entity }, integer
has: function(self: Builder, fragment: Fragment): boolean
has_all: function(self: Builder, ...: Fragment): boolean
has_any: function(self: Builder, ...: Fragment): boolean
get: function(self: Builder)
get: function<C1>(self: Builder, f1: Fragment): C1 | nil
get: function<C1, C2>(self: Builder, f1: Fragment, f2: Fragment): C1 | nil, C2 | nil
get: function<C1, C2, C3>(self: Builder, f1: Fragment, f2: Fragment, f3: Fragment): C1 | nil, C2 | nil, C3 | nil
get: function<C1, C2, C3, C4>(self: Builder, f1: Fragment, f2: Fragment, f3: Fragment, f4: Fragment): C1 | nil, C2 | nil, C3 | nil, C4 | nil
set: function<Component>(self: Builder, fragment: Fragment, component?: Component): Builder
remove: function(self: Builder, ...: Fragment): Builder
clear: function(self: Builder): Builder
tag: function(self: Builder): Builder
name: function(self: Builder, name: string): Builder
unique: function(self: Builder): Builder
explicit: function(self: Builder): Builder
internal: function(self: Builder): Builder
default: function<Component>(self: Builder, default: Component): Builder
duplicate: function<Component>(self: Builder, duplicate: function(Component): Component): Builder
prefab: function(self: Builder): Builder
disabled: function(self: Builder): Builder
include: function(self: Builder, ...: Fragment): Builder
exclude: function(self: Builder, ...: Fragment): Builder
require: function(self: Builder, ...: Fragment): Builder
on_set: function<Component>(self: Builder, on_set: function(Entity, Fragment, ? Component, ? Component)): Builder
on_assign: function<Component>(self: Builder, on_assign: function(Entity, Fragment, ? Component, ? Component)): Builder
on_insert: function<Component>(self: Builder, on_insert: function(Entity, Fragment, ? Component)): Builder
on_remove: function<Component>(self: Builder, on_remove: function(Entity, Fragment, ? Component)): Builder
group: function(self: Builder, group: System): Builder
query: function(self: Builder, query: Query): Builder
execute: function(self: Builder, execute: function(Chunk, {Entity}, integer)): Builder
prologue: function(self: Builder, prologue: function()): Builder
epilogue: function(self: Builder, epilogue: function()): Builder
destruction_policy: function(self: Builder, destruction_policy: Id): Builder
end
TAG: Fragment
NAME: Fragment
UNIQUE: Fragment
EXPLICIT: Fragment
INTERNAL: Fragment
DEFAULT: Fragment
DUPLICATE: Fragment
PREFAB: Fragment
DISABLED: Fragment
INCLUDES: Fragment
EXCLUDES: Fragment
REQUIRES: Fragment
ON_SET: Fragment
ON_ASSIGN: Fragment
ON_INSERT: Fragment
ON_REMOVE: Fragment
GROUP: Fragment
QUERY: Fragment
EXECUTE: Fragment
PROLOGUE: Fragment
EPILOGUE: Fragment
DESTRUCTION_POLICY: Fragment
DESTRUCTION_POLICY_DESTROY_ENTITY: Id
DESTRUCTION_POLICY_REMOVE_FRAGMENT: Id
id: function(count?: integer): Id...
name: function(...: Id): string...
pack: function(primary: integer, secondary: integer): Id
unpack: function(id: Id): integer, integer
defer: function(): boolean
commit: function(): boolean
cancel: function(): boolean
spawn: function(components?: { Fragment: any }): Entity
multi_spawn: function(entity_count: integer, components?: { Fragment: any }): { Entity }, integer
clone: function(prefab: Entity, components?: { Fragment: any }): Entity
multi_clone: function(entity_count: integer, prefab: Entity, components?: { Fragment: any }): { Entity }, integer
alive: function(entity: Entity): boolean
alive_all: function(...: Entity): boolean
alive_any: function(...: Entity): boolean
empty: function(entity: Entity): boolean
empty_all: function(...: Entity): boolean
empty_any: function(...: Entity): boolean
has: function(entity: Entity, fragment: Fragment): boolean
has_all: function(entity: Entity, ...: Fragment): boolean
has_any: function(entity: Entity, ...: Fragment): boolean
get: function(entity: Entity)
get: function<C1>(entity: Entity, f1: Fragment): C1 | nil
get: function<C1, C2>(entity: Entity, f1: Fragment, f2: Fragment): C1 | nil, C2 | nil
get: function<C1, C2, C3>(entity: Entity, f1: Fragment, f2: Fragment, f3: Fragment): C1 | nil, C2 | nil, C3 | nil
get: function<C1, C2, C3, C4>(entity: Entity, f1: Fragment, f2: Fragment, f3: Fragment, f4: Fragment): C1 | nil, C2 | nil, C3 | nil, C4 | nil
set: function<Component>(entity: Entity, fragment: Fragment, component?: Component)
remove: function(entity: Entity, ...: Fragment)
clear: function(...: Entity)
destroy: function(...: Entity)
batch_set: function<Component>(query: Query, fragment: Fragment, component?: Component)
batch_remove: function(query: Query, ...: Fragment)
batch_clear: function(...: Query)
batch_destroy: function(...: Query)
each: function(entity: Entity): EachIterator, EachState | nil
execute: function(query: Query): ExecuteIterator, ExecuteState | nil
locate: function(entity: Entity): Chunk | nil, integer
process: function(...: System)
debug_mode: function(yesno: boolean)
collect_garbage: function()
chunk: function(fragment: Fragment, ...: Fragment): Chunk, { Entity }, integer
builder: function(): Builder
end
return Evolved

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.4.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.4.0",
}
description = {
homepage = "https://github.com/BlackMATov/evolved.lua",
summary = "Evolved ECS (Entity-Component-System) for Lua",
detailed = [[
`evolved.lua` is a fast and flexible ECS (Entity-Component-System) library for Lua.
It is designed to be simple and easy to use, while providing all the features needed to create complex systems with blazing performance.
]],
license = "MIT",
labels = {
"ecs",
"entity",
"entities",
"component",
"components",
"entity-component",
"entity-component-system",
},
}
dependencies = {
"lua >= 5.1",
}
build = {
type = "builtin",
modules = {
evolved = "evolved.lua",
}
}