mirror of
https://github.com/BlackMATov/evolved.lua.git
synced 2025-12-13 03:29:08 +07:00
118
README.md
118
README.md
@@ -59,6 +59,7 @@
|
||||
- [Chunk](#chunk)
|
||||
- [Builder](#builder)
|
||||
- [Changelog](#changelog)
|
||||
- [v1.4.0](#v140)
|
||||
- [v1.3.0](#v130)
|
||||
- [v1.2.0](#v120)
|
||||
- [v1.1.0](#v110)
|
||||
@@ -153,11 +154,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 +462,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 +503,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 +601,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 +658,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 +686,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 +734,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 +756,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 +769,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 +796,7 @@ local system = evolved.builder()
|
||||
health_components[i] - 1,
|
||||
0)
|
||||
end
|
||||
end):spawn()
|
||||
end):build()
|
||||
|
||||
evolved.process(system)
|
||||
```
|
||||
@@ -814,7 +815,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 +830,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 +846,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 +863,7 @@ local system = evolved.builder()
|
||||
:epilogue(function()
|
||||
print('Epilogue')
|
||||
end)
|
||||
:spawn()
|
||||
:build()
|
||||
|
||||
evolved.process(system)
|
||||
```
|
||||
@@ -904,7 +905,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 +930,7 @@ local enemy_prefab = evolved.builder()
|
||||
:prefab()
|
||||
:set(health, 100)
|
||||
:set(stamina, 50)
|
||||
:spawn()
|
||||
:build()
|
||||
|
||||
local enemy_clone = evolved.clone(enemy_prefab)
|
||||
|
||||
@@ -951,16 +952,16 @@ 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()
|
||||
```
|
||||
|
||||
#### Shared Components
|
||||
@@ -976,11 +977,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 +1006,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 +1030,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 +1058,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 +1083,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 +1182,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 +1246,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 +1300,12 @@ builder_mt:destruction_policy :: id -> builder
|
||||
|
||||
## Changelog
|
||||
|
||||
### 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 +1410,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 +1462,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 +1482,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 +1788,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 +1818,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 +1836,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
|
||||
```
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -1,7 +1,9 @@
|
||||
require 'develop.samples.systems'
|
||||
|
||||
require 'develop.testing.build_tests'
|
||||
require 'develop.testing.cancel_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'
|
||||
@@ -14,13 +16,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'
|
||||
|
||||
267
develop/fuzzing/execute_fuzz.lua
Normal file
267
develop/fuzzing/execute_fuzz.lua
Normal 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
|
||||
41
develop/testing/build_tests.lua
Normal file
41
develop/testing/build_tests.lua
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
1131
evolved.lua
1131
evolved.lua
File diff suppressed because it is too large
Load Diff
34
rockspecs/evolved.lua-1.4.0-0.rockspec
Normal file
34
rockspecs/evolved.lua-1.4.0-0.rockspec
Normal 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",
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user