2 Commits

Author SHA1 Message Date
a1423ea9ee Merge pull request #33 from BlackMATov/dev
Dev
2025-12-28 06:48:21 +07:00
12a720bd9e Merge pull request #31 from BlackMATov/dev
Dev
2025-11-24 13:49:59 +07:00
37 changed files with 1035 additions and 4961 deletions

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (C) 2024-2026, by Matvey Cherevko (blackmatov@gmail.com)
Copyright (C) 2024-2025, by Matvey Cherevko (blackmatov@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

614
README.md
View File

@@ -35,7 +35,6 @@
- [Structural Changes](#structural-changes)
- [Spawning Entities](#spawning-entities)
- [Entity Builders](#entity-builders)
- [Multi-Entity Spawning](#multi-entity-spawning)
- [Access Operations](#access-operations)
- [Iterating Over Fragments](#iterating-over-fragments)
- [Modifying Operations](#modifying-operations)
@@ -44,7 +43,6 @@
- [Deferred Operations](#deferred-operations)
- [Batch Operations](#batch-operations)
- [Systems](#systems)
- [Processing Payloads](#processing-payloads)
- [Predefined Traits](#predefined-traits)
- [Fragment Tags](#fragment-tags)
- [Fragment Hooks](#fragment-hooks)
@@ -53,10 +51,7 @@
- [Internal Fragments](#internal-fragments)
- [Shared Components](#shared-components)
- [Fragment Requirements](#fragment-requirements)
- [Id Names](#id-names)
- [Destruction Policies](#destruction-policies)
- [Custom Component Storages](#custom-component-storages)
- [Garbage Collection](#garbage-collection)
- [Cheat Sheet](#cheat-sheet)
- [Aliases](#aliases)
- [Predefs](#predefs)
@@ -65,10 +60,6 @@
- [Chunk](#chunk)
- [Builder](#builder)
- [Changelog](#changelog)
- [vX.Y.Z](#vxyz)
- [v1.9.0](#v190)
- [v1.8.0](#v180)
- [v1.7.0](#v170)
- [v1.6.0](#v160)
- [v1.5.0](#v150)
- [v1.4.0](#v140)
@@ -425,19 +416,17 @@ You should try to avoid structural changes, especially in performance-critical c
#### Spawning Entities
```lua
---@param component_table? table<evolved.fragment, evolved.component>
---@param component_mapper? fun(chunk: evolved.chunk, place: integer)
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity
function evolved.spawn(component_table, component_mapper) end
function evolved.spawn(components) end
---@param prefab evolved.entity
---@param component_table? table<evolved.fragment, evolved.component>
---@param component_mapper? fun(chunk: evolved.chunk, place: integer)
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity
function evolved.clone(prefab, component_table, component_mapper) end
function evolved.clone(prefab, components) end
```
The [`evolved.spawn`](#evolvedspawn) function allows you to spawn an entity with all the necessary fragments. It takes a table of components as an argument, where the keys are fragments and the values are components. By the way, you don't need to create this `component_table` every time; consider using a predefined table for maximum performance.
The [`evolved.spawn`](#evolvedspawn) function allows you to spawn an entity with all the necessary fragments. It takes a table of components as an argument, where the keys are fragments and the values are components. By the way, you don't need to create this `components` table every time; consider using a predefined table for maximum performance.
You can also use the [`evolved.clone`](#evolvedclone) function to clone an existing entity. This is useful for creating entities with the same fragments as an existing entity but with different components.
@@ -481,54 +470,6 @@ local enemy = evolved.builder()
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.
#### Multi-Entity Spawning
When you need to spawn multiple entities with identical fragments, use `multi_spawn` and `multi_clone` to optimize performance and reduce overhead.
```lua
---@param entity_count integer
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
---@return evolved.entity[] entity_list
---@return integer entity_count
function evolved.multi_spawn(entity_count, component_table, component_mapper) end
---@param entity_count integer
---@param prefab evolved.entity
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
---@return evolved.entity[] entity_list
---@return integer entity_count
function evolved.multi_clone(entity_count, prefab, component_table, component_mapper) end
```
These functions behave like their single-entity counterparts, but they allow you to spawn or clone multiple entities in one call. This approach minimizes the overhead of repeated function calls and structural changes, improving performance when handling large numbers of entities.
Typically, when spawning multiple entities, they share the same set of fragments, but their components can differ. You can achieve this by providing a `component_mapper` function, which receives the chunk and the range of places for the newly spawned entities. This avoids many `evolved.set` calls after spawning, which can be costly when creating many entities.
Here is a small example of using `evolved.multi_spawn` with a `component_mapper`:
```lua
local evolved = require 'evolved'
local position_x, position_y = evolved.id(2)
evolved.multi_spawn(1000, {
[position_x] = 0,
[position_y] = 0,
}, function(chunk, b_place, e_place)
local x_components = chunk:components(position_x)
local y_components = chunk:components(position_y)
for i = b_place, e_place do
x_components[i] = math.random(-100, 100)
y_components[i] = math.random(-100, 100)
end
end)
```
Of course, you can use `evolved.multi_clone` in the same way. Builders can also be used for multi-entity spawning and cloning by calling the corresponding methods on the builder object.
### Access Operations
The library provides all the necessary functions to access entities and their components. I'm not going to cover all the accessor functions here, because they are pretty straightforward and self-explanatory. You can check the [API Reference](#api-reference) for all of them. Here are some of the most important ones:
@@ -645,22 +586,16 @@ evolved.set(entity, fragment, 42)
One of the most important features of any ECS library is the ability to process entities by filters or queries. `evolved.lua` provides a simple and efficient way to do this.
First, you need to create a query that describes which entities you want to process. You can specify fragments you want to include, and fragments you want to exclude. Queries are just identifiers with a special predefined fragments: [`evolved.INCLUDES`](#evolvedincludes), [`evolved.EXCLUDES`](#evolvedexcludes), and [`evolved.VARIANTS`](#evolvedvariants). These fragments expect a list of fragments as their components.
- [`evolved.INCLUDES`](#evolvedincludes) is used to specify fragments that must be present in the entity;
- [`evolved.EXCLUDES`](#evolvedexcludes) is used to specify fragments that must not be present in the entity;
- [`evolved.VARIANTS`](#evolvedvariants) is used to specify fragments where at least one must be present in the entity.
First, you need to create a query that describes which entities you want to process. You can specify fragments you want to include, and fragments you want to exclude. Queries are just identifiers with a special predefined fragments: [`evolved.INCLUDES`](#evolvedincludes) and [`evolved.EXCLUDES`](#evolvedexcludes). These fragments expect a list of fragments as their components.
```lua
local evolved = require 'evolved'
local health, poisoned, resistant = evolved.id(3)
local alive, undead = evolved.id(2)
local query = evolved.id()
evolved.set(query, evolved.INCLUDES, { health, poisoned })
evolved.set(query, evolved.EXCLUDES, { resistant })
evolved.set(query, evolved.VARIANTS, { alive, undead })
```
The builder interface can be used to create queries too. It is more convenient to use, because the builder has special methods for including and excluding fragments. Here is a simple example of this:
@@ -669,11 +604,10 @@ The builder interface can be used to create queries too. It is more convenient t
local query = evolved.builder()
:include(health, poisoned)
:exclude(resistant)
:variant(alive, undead)
:build()
```
We don't have to set all of [`evolved.INCLUDES`](#evolvedincludes), [`evolved.EXCLUDES`](#evolvedexcludes), and [`evolved.VARIANTS`](#evolvedvariants) fragments, we can even do it without filters at all, then the query will match all chunks in the world.
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.
After the query is created, we are ready to process our filtered by this query entities. You can do this by using the [`evolved.execute`](#evolvedexecute) function. This function takes a query as an argument and returns an iterator that can be used to iterate over all matching with the query chunks.
@@ -852,7 +786,7 @@ The [`evolved.process`](#evolvedprocess) function is used to process systems. It
function evolved.process(...) end
```
If you don't specify a query for the system, the system itself will be treated as a query. This means the system can contain `evolved.INCLUDES`, `evolved.EXCLUDES`, and `evolved.VARIANTS` fragments, and it will be processed according to them. This is useful for creating systems with unique queries that don't need to be reused in other systems.
If you don't specify a query for the system, the system itself will be treated as a query. This means the system can contain `evolved.INCLUDES` and `evolved.EXCLUDES` fragments, and it will be processed according to them. This is useful for creating systems with unique queries that don't need to be reused in other systems.
```lua
local evolved = require 'evolved'
@@ -946,43 +880,6 @@ The prologue and epilogue fragments do not require an explicit query. They will
> [!NOTE]
> And one more thing about systems. Execution callbacks are called in the [deferred scope](#deferred-operations), which means that all modifying operations inside the callback will be queued and applied after the system has processed all chunks. But prologue and epilogue callbacks are not called in the deferred scope, so all modifying operations inside them will be applied immediately. This is done to avoid confusion and to make it clear that prologue and epilogue callbacks are not part of the chunk processing.
#### Processing Payloads
Additionally, systems can have a payload that will be passed to the execution, prologue, and epilogue callbacks. This is useful for passing additional data to the system without using global variables or closures.
```lua
---@param system evolved.system
---@param ... any processing payload
function evolved.process_with(system, ...) end
```
The [`evolved.process_with`](#evolvedprocess_with) function is similar to the [`evolved.process`](#evolvedprocess) function, but it takes a processing payload as additional arguments. These arguments will be passed to the system's callbacks.
```lua
local evolved = require 'evolved'
local position_x, position_y = evolved.id(2)
local velocity_x, velocity_y = evolved.id(2)
local physics_system = evolved.builder()
:include(position_x, position_y)
:include(velocity_x, velocity_y)
:execute(function(chunk, entity_list, entity_count, delta_time)
local px, py = chunk:components(position_x, position_y)
local vx, vy = chunk:components(velocity_x, velocity_y)
for i = 1, entity_count do
px[i] = px[i] + vx[i] * delta_time
py[i] = py[i] + vy[i] * delta_time
end
end):build()
local delta_time = 0.016
evolved.process_with(physics_system, delta_time)
```
`delta_time` in this example is passed as a processing payload to the system's execution callback. Payloads can be of any type and can be multiple values. Also, payloads are passed to prologue and epilogue callbacks if they are defined. Every subsystem in a group will receive the same payload when the group is processed with [`evolved.process_with`](#evolvedprocess_with).
### Predefined Traits
#### Fragment Tags
@@ -1163,41 +1060,6 @@ local enemy = evolved.builder()
assert(evolved.has_all(enemy, position, velocity))
```
#### Id Names
The library provides a way to assign names to any id using the [`evolved.NAME`](#evolvedname) fragment. This is useful for debugging and development purposes, as it allows you to identify entities or fragments by their names instead of their identifiers. The name of an entity can be retrieved using the [`evolved.name`](#evolvedname-1) function.
```lua
local evolved = require 'evolved'
local player = evolved.builder()
:name('Player')
:build()
assert(evolved.name(player) == 'Player')
```
Names are not unique, so multiple entities can have the same name. Also, the name of an entity can be changed at any time by setting a new name using the [`evolved.NAME`](#evolvedname) fragment as a usual component.
You can find entities by their names using the [`evolved.lookup`](#evolvedlookup) and [`evolved.multi_lookup`](#evolvedmulti_lookup) functions. The [`evolved.lookup`](#evolvedlookup) function returns the first entity with the specified name, while the [`evolved.multi_lookup`](#evolvedmulti_lookup) function returns a list of all entities with the specified name.
```lua
local evolved = require 'evolved'
local player1 = evolved.builder()
:name('Player')
:build()
local player2 = evolved.builder()
:name('Player')
:build()
assert(evolved.lookup('Player') == player1)
local player_list, player_count = evolved.multi_lookup('Player')
assert(player_count == 2 and player_list[1] == player1 and player_list[2] == player2)
```
#### Destruction Policies
Typically, fragments remain alive for the entire lifetime of the program. However, in some cases, you might want to destroy fragments when they are no longer needed. For example, you can use some runtime entities as fragments for other entities. In this case, you might want to destroy such fragments even while they are still attached to other entities. Since entities cannot have destroyed fragments, a destruction policy must be applied to resolve this. By default, the library will remove the destroyed fragment from all entities that have it.
@@ -1245,163 +1107,6 @@ evolved.destroy(world)
assert(not evolved.alive(entity))
```
#### Custom Component Storages
In some cases, you might want custom storages for fragment components. For example, you might want to store components in a specialized way for performance reasons. The library provides two fragment traits for this purpose: [`evolved.REALLOC`](#evolvedrealloc) and [`evolved.COMPMOVE`](#evolvedcompmove).
The [`evolved.REALLOC`](#evolvedrealloc) trait expects a function that is called when the fragment storage needs to be reallocated. The [`evolved.COMPMOVE`](#evolvedcompmove) trait expects a function that is called when components need to be moved from one storage to another.
A canonical example of using custom storages is implementing a fragment that stores components in an FFI-backed storage for better processing performance in LuaJIT. This is an advanced topic and requires a good understanding of LuaJIT FFI and memory management. So I won't cover it here in detail, but here is a simple example to give you an idea of how it works. More information can be found on the [LuaJIT](https://luajit.org/ext_ffi.html) website.
```lua
local ffi = require 'ffi'
local evolved = require 'evolved'
--
--
-- Define FFI double storage realloc and compmove functions
--
--
local FFI_DOUBLE_TYPEOF = ffi.typeof('double')
local FFI_DOUBLE_SIZEOF = ffi.sizeof(FFI_DOUBLE_TYPEOF)
local FFI_DOUBLE_STORAGE_TYPEOF = ffi.typeof('double[?]')
---@param src ffi.cdata*?
---@param src_size integer
---@param dst_size integer
---@return ffi.cdata*?
local function FFI_DOUBLE_STORAGE_REALLOC(src, src_size, dst_size)
if dst_size == 0 then
-- freeing the src storage, just let the GC handle it
return
end
-- to support 1-based indexing, allocate one extra element
local dst = ffi.new(FFI_DOUBLE_STORAGE_TYPEOF, dst_size + 1)
if src and src_size > 0 then
-- handle both expanding and shrinking
local min_size = math.min(src_size, dst_size)
ffi.copy(dst + 1, src + 1, min_size * FFI_DOUBLE_SIZEOF)
end
return dst
end
---@param src ffi.cdata*
---@param f integer
---@param e integer
---@param t integer
---@param dst ffi.cdata*
local function FFI_DOUBLE_STORAGE_COMPMOVE(src, f, e, t, dst)
ffi.copy(dst + t, src + f, (e - f + 1) * FFI_DOUBLE_SIZEOF)
end
--
--
-- Define fragments with our custom FFI storages
--
--
local POSITION_X = evolved.builder()
:default(0)
:realloc(FFI_DOUBLE_STORAGE_REALLOC)
:compmove(FFI_DOUBLE_STORAGE_COMPMOVE)
:build()
local POSITION_Y = evolved.builder()
:default(0)
:realloc(FFI_DOUBLE_STORAGE_REALLOC)
:compmove(FFI_DOUBLE_STORAGE_COMPMOVE)
:build()
local VELOCITY_X = evolved.builder()
:default(0)
:realloc(FFI_DOUBLE_STORAGE_REALLOC)
:compmove(FFI_DOUBLE_STORAGE_COMPMOVE)
:build()
local VELOCITY_Y = evolved.builder()
:default(0)
:realloc(FFI_DOUBLE_STORAGE_REALLOC)
:compmove(FFI_DOUBLE_STORAGE_COMPMOVE)
:build()
--
--
-- Define a movement system that uses these components
--
--
local MOVEMENT_SYSTEM = evolved.builder()
:include(POSITION_X, POSITION_Y)
:include(VELOCITY_X, VELOCITY_Y)
:execute(function(chunk, entity_list, entity_count, delta_time)
local position_xs, position_ys = chunk:components(POSITION_X, POSITION_Y)
local velocity_xs, velocity_ys = chunk:components(VELOCITY_X, VELOCITY_Y)
for i = 1, entity_count do
local px, py = position_xs[i], position_ys[i]
local vx, vy = velocity_xs[i], velocity_ys[i]
px = px + vx * delta_time
py = py + vy * delta_time
position_xs[i], position_ys[i] = px, py
end
end):build()
--
--
-- Spawn some entities with these components
--
--
evolved.builder()
:set(POSITION_X)
:set(POSITION_Y)
:set(VELOCITY_X)
:set(VELOCITY_Y)
:multi_spawn(10000, function(chunk, b_place, e_place)
local position_xs, position_ys = chunk:components(POSITION_X, POSITION_Y)
local velocity_xs, velocity_ys = chunk:components(VELOCITY_X, VELOCITY_Y)
for place = b_place, e_place do
position_xs[place] = math.random(0, 640)
position_ys[place] = math.random(0, 480)
velocity_xs[place] = math.random(-100, 100)
velocity_ys[place] = math.random(-100, 100)
end
end)
--
--
-- Process the movement system with a delta time payload
--
--
evolved.process_with(MOVEMENT_SYSTEM, 0.016)
```
### Garbage Collection
While using the library, some internal data structures can become obsolete and should be cleaned up to free memory. For example, empty chunks that no longer contain entities can be removed. Component storages can also have unused capacity that can be shrunk to save memory. The library provides a function to control this garbage collection process.
```lua
---@param no_shrink? boolean
function evolved.collect_garbage(no_shrink) end
```
By default, [`evolved.collect_garbage`](#evolvedcollect_garbage) cleans up obsolete data structures and shrinks component storages to fit their current size. If you pass `true`, it only cleans up obsolete data structures and skips shrinking. This avoids the overhead of resizing storages, which can be expensive.
Call this function periodically to keep memory usage under control. It is best to call it between levels or during loading screens when performance is not critical. Also, call Lua's built-in garbage collector afterward to ensure all unused memory is freed.
```lua
evolved.collect_garbage()
collectgarbage('collect')
```
## Cheat Sheet
### Aliases
@@ -1417,18 +1122,12 @@ system :: id
component :: any
storage :: component[]
component_table :: <fragment, component>
component_mapper :: {chunk, integer, integer}
default :: component
duplicate :: {component -> component}
realloc :: {storage?, integer, integer -> storage?}
compmove :: {storage, integer, integer, integer, storage}
execute :: {chunk, entity[], integer, any...}
prologue :: {any...}
epilogue :: {any...}
execute :: {chunk, entity[], integer}
prologue :: {}
epilogue :: {}
set_hook :: {entity, fragment, component, component}
assign_hook :: {entity, fragment, component, component}
@@ -1455,15 +1154,11 @@ INTERNAL :: fragment
DEFAULT :: fragment
DUPLICATE :: fragment
REALLOC :: fragment
COMPMOVE :: fragment
PREFAB :: fragment
DISABLED :: fragment
INCLUDES :: fragment
EXCLUDES :: fragment
VARIANTS :: fragment
REQUIRES :: fragment
ON_SET :: fragment
@@ -1498,15 +1193,11 @@ depth :: integer
commit :: boolean
cancel :: boolean
spawn :: component_table?, component_mapper? -> entity
multi_spawn :: integer, component_table?, component_mapper? -> entity[], integer
multi_spawn_nr :: integer, component_table?, component_mapper? -> ()
multi_spawn_to :: entity[], integer, integer, component_table?, component_mapper? -> ()
spawn :: <fragment, component>? -> entity
multi_spawn :: integer, <fragment, component>? -> entity[], integer
clone :: entity, component_table?, component_mapper? -> entity
multi_clone :: integer, entity, component_table?, component_mapper? -> entity[], integer
multi_clone_nr :: integer, entity, component_table?, component_mapper? -> ()
multi_clone_to :: entity[], integer, integer, entity, component_table?, component_mapper? -> ()
clone :: entity, <fragment, component>? -> entity
multi_clone :: integer, entity, <fragment, component>? -> entity[], integer
alive :: entity -> boolean
alive_all :: entity... -> boolean
@@ -1520,7 +1211,7 @@ has :: entity, fragment -> boolean
has_all :: entity, fragment... -> boolean
has_any :: entity, fragment... -> boolean
get :: entity, fragment... -> component...
get :: entity, fragment... -> component...
set :: entity, fragment, component -> ()
remove :: entity, fragment... -> ()
@@ -1537,15 +1228,10 @@ execute :: query -> {execute_state? -> chunk?, entity[]?, integer?}, execute_sta
locate :: entity -> chunk?, integer
lookup :: string -> entity?
multi_lookup :: string -> entity[], integer
multi_lookup_to :: entity[], integer, string -> integer
process :: system... -> ()
process_with :: system, ... -> ()
debug_mode :: boolean -> ()
collect_garbage :: boolean? -> ()
collect_garbage :: ()
```
### Classes
@@ -1572,20 +1258,14 @@ chunk_mt:components :: fragment... -> storage...
```
builder :: builder
builder_mt:build :: entity?, component_mapper? -> entity
builder_mt:multi_build :: integer, entity?, component_mapper? -> entity[], integer
builder_mt:multi_build_nr :: integer, entity?, component_mapper? -> ()
builder_mt:multi_build_to :: entity[], integer, integer, entity?, component_mapper? -> ()
builder_mt:build :: entity? -> entity
builder_mt:multi_build :: integer, entity? -> entity[], integer
builder_mt:spawn :: component_mapper? -> entity
builder_mt:multi_spawn :: integer, component_mapper? -> entity[], integer
builder_mt:multi_spawn_nr :: integer, component_mapper? -> ()
builder_mt:multi_spawn_to :: entity[], integer, integer, component_mapper? -> ()
builder_mt:spawn :: entity
builder_mt:multi_spawn :: integer -> entity[], integer
builder_mt:clone :: entity, component_mapper? -> entity
builder_mt:multi_clone :: integer, entity, component_mapper? -> entity[], integer
builder_mt:multi_clone_nr :: integer, entity, component_mapper? -> ()
builder_mt:multi_clone_to :: entity[], integer, integer, entity, component_mapper? -> ()
builder_mt:clone :: entity -> entity
builder_mt:multi_clone :: integer, entity -> entity[], integer
builder_mt:has :: fragment -> boolean
builder_mt:has_all :: fragment... -> boolean
@@ -1607,15 +1287,11 @@ builder_mt:internal :: builder
builder_mt:default :: component -> builder
builder_mt:duplicate :: {component -> component} -> builder
builder_mt:realloc :: {storage?, integer, integer -> storage?} -> builder
builder_mt:compmove :: {storage, integer, integer, integer, storage} -> builder
builder_mt:prefab :: builder
builder_mt:disabled :: builder
builder_mt:include :: fragment... -> builder
builder_mt:exclude :: fragment... -> builder
builder_mt:variant :: fragment... -> builder
builder_mt:require :: fragment... -> builder
builder_mt:on_set :: {entity, fragment, component, component} -> builder
@@ -1626,36 +1302,16 @@ builder_mt:on_remove :: {entity, fragment} -> builder
builder_mt:group :: system -> builder
builder_mt:query :: query -> builder
builder_mt:execute :: {chunk, entity[], integer, any...} -> builder
builder_mt:execute :: {chunk, entity[], integer} -> builder
builder_mt:prologue :: {any...} -> builder
builder_mt:epilogue :: {any...} -> builder
builder_mt:prologue :: {} -> builder
builder_mt:epilogue :: {} -> builder
builder_mt:destruction_policy :: id -> builder
```
## Changelog
### vX.Y.Z
- Added the new [`evolved.lookup`](#evolvedlookup) and [`evolved.multi_lookup`](#evolvedmulti_lookup) functions that allow finding ids by their names
- Added a non-shrinking version of the [`evolved.collect_garbage`](#evolvedcollect_garbage) function that only collects garbage without shrinking storages
### v1.9.0
- Performance improvements of the [`evolved.destroy`](#evolveddestroy) and [`evolved.batch_destroy`](#evolvedbatch_destroy) functions
- Ensured deterministic chunk ordering to improve processing consistency across runs
### v1.8.0
- Added the new [`evolved.REALLOC`](#evolvedrealloc) and [`evolved.COMPMOVE`](#evolvedcompmove) fragment traits that allow customizing component storages
- Added `component_mapper` argument to the spawning and cloning functions that allows filling components in chunks during the operation
### v1.7.0
- Added the new [`evolved.VARIANTS`](#evolvedvariants) query fragment that allows specifying any of multiple fragments in queries
- Added the new [`evolved.process_with`](#evolvedprocess_with) function that allows passing payloads to processing systems
### v1.6.0
- Significant performance improvements of the [`evolved.REQUIRES`](#evolvedrequires) fragment trait
@@ -1720,10 +1376,6 @@ builder_mt:destruction_policy :: id -> builder
### `evolved.DUPLICATE`
### `evolved.REALLOC`
### `evolved.COMPMOVE`
### `evolved.PREFAB`
### `evolved.DISABLED`
@@ -1732,8 +1384,6 @@ builder_mt:destruction_policy :: id -> builder
### `evolved.EXCLUDES`
### `evolved.VARIANTS`
### `evolved.REQUIRES`
### `evolved.ON_SET`
@@ -1832,53 +1482,28 @@ function evolved.cancel() end
### `evolved.spawn`
```lua
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity entity
function evolved.spawn(component_table, component_mapper) end
function evolved.spawn(components) end
```
### `evolved.multi_spawn`
```lua
---@param entity_count integer
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity[] entity_list
---@return integer entity_count
---@nodiscard
function evolved.multi_spawn(entity_count, component_table, component_mapper) end
```
### `evolved.multi_spawn_nr`
```lua
---@param entity_count integer
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
function evolved.multi_spawn_nr(entity_count, component_table, component_mapper) end
```
### `evolved.multi_spawn_to`
```lua
---@param out_entity_list evolved.entity[]
---@param out_entity_first integer
---@param entity_count integer
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
function evolved.multi_spawn_to(out_entity_list, out_entity_first,
entity_count, component_table, component_mapper) end
function evolved.multi_spawn(entity_count, components) end
```
### `evolved.clone`
```lua
---@param prefab evolved.entity
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity entity
function evolved.clone(prefab, component_table, component_mapper) end
function evolved.clone(prefab, components) end
```
### `evolved.multi_clone`
@@ -1886,35 +1511,10 @@ function evolved.clone(prefab, component_table, component_mapper) end
```lua
---@param entity_count integer
---@param prefab evolved.entity
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity[] entity_list
---@return integer entity_count
---@nodiscard
function evolved.multi_clone(entity_count, prefab, component_table, component_mapper) end
```
### `evolved.multi_clone_nr`
```lua
---@param entity_count integer
---@param prefab evolved.entity
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
function evolved.multi_clone_nr(entity_count, prefab, component_table, component_mapper) end
```
### `evolved.multi_clone_to`
```lua
---@param out_entity_list evolved.entity[]
---@param out_entity_first integer
---@param entity_count integer
---@param prefab evolved.entity
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
function evolved.multi_clone_to(out_entity_list, out_entity_first,
entity_count, prefab, component_table, component_mapper) end
function evolved.multi_clone(entity_count, prefab, components) end
```
### `evolved.alive`
@@ -2103,35 +1703,6 @@ function evolved.execute(query) end
function evolved.locate(entity) end
```
### `evolved.lookup`
```lua
---@param name string
---@return evolved.entity? entity
---@nodiscard
function evolved.lookup(name) end
```
### `evolved.multi_lookup`
```lua
---@param name string
---@return evolved.entity[] entity_list
---@return integer entity_count
---@nodiscard
function evolved.multi_lookup(name) end
```
### `evolved.multi_lookup_to`
```lua
---@param out_entity_list evolved.entity[]
---@param out_entity_first integer
---@param name string
---@return integer entity_count
function evolved.multi_lookup_to(out_entity_list, out_entity_first, name) end
```
### `evolved.process`
```lua
@@ -2139,14 +1710,6 @@ function evolved.multi_lookup_to(out_entity_list, out_entity_first, name) end
function evolved.process(...) end
```
### `evolved.process_with`
```lua
---@param system evolved.system
---@param ... any processing payload
function evolved.process_with(system, ...) end
```
### `evolved.debug_mode`
```lua
@@ -2157,8 +1720,7 @@ function evolved.debug_mode(yesno) end
### `evolved.collect_garbage`
```lua
---@param no_shrink? boolean
function evolved.collect_garbage(no_shrink) end
function evolved.collect_garbage() end
```
## Classes
@@ -2261,9 +1823,8 @@ function evolved.builder() end
```lua
---@param prefab? evolved.entity
---@param component_mapper? evolved.component_mapper
---@return evolved.entity entity
function evolved.builder_mt:build(prefab, component_mapper) end
function evolved.builder_mt:build(prefab) end
```
### `evolved.builder_mt:multi_build`
@@ -2271,79 +1832,33 @@ function evolved.builder_mt:build(prefab, component_mapper) end
```lua
---@param entity_count integer
---@param prefab? evolved.entity
---@param component_mapper? evolved.component_mapper
---@return evolved.entity[] entity_list
---@return integer entity_count
---@nodiscard
function evolved.builder_mt:multi_build(entity_count, prefab, component_mapper) end
```
### `evolved.builder_mt:multi_build_nr`
```lua
---@param entity_count integer
---@param prefab? evolved.entity
---@param component_mapper? evolved.component_mapper
function evolved.builder_mt:multi_build_nr(entity_count, prefab, component_mapper) end
```
### `evolved.builder_mt:multi_build_to`
```lua
---@param out_entity_list evolved.entity[]
---@param out_entity_first integer
---@param entity_count integer
---@param prefab? evolved.entity
---@param component_mapper? evolved.component_mapper
function evolved.builder_mt:multi_build_to(out_entity_list, out_entity_first,
entity_count, prefab, component_mapper) end
function evolved.builder_mt:multi_build(entity_count, prefab) end
```
#### `evolved.builder_mt:spawn`
```lua
---@param component_mapper? evolved.component_mapper
---@return evolved.entity entity
function evolved.builder_mt:spawn(component_mapper) end
function evolved.builder_mt:spawn() end
```
#### `evolved.builder_mt:multi_spawn`
```lua
---@param entity_count integer
---@param component_mapper? evolved.component_mapper
---@return evolved.entity[] entity_list
---@return integer entity_count
---@nodiscard
function evolved.builder_mt:multi_spawn(entity_count, component_mapper) end
```
#### `evolved.builder_mt:multi_spawn_nr`
```lua
---@param entity_count integer
---@param component_mapper? evolved.component_mapper
function evolved.builder_mt:multi_spawn_nr(entity_count, component_mapper) end
```
#### `evolved.builder_mt:multi_spawn_to`
```lua
---@param out_entity_list evolved.entity[]
---@param out_entity_first integer
---@param entity_count integer
---@param component_mapper? evolved.component_mapper
function evolved.builder_mt:multi_spawn_to(out_entity_list, out_entity_first,
entity_count, component_mapper) end
function evolved.builder_mt:multi_spawn(entity_count) end
```
#### `evolved.builder_mt:clone`
```lua
---@param prefab evolved.entity
---@param component_mapper? evolved.component_mapper
---@return evolved.entity entity
function evolved.builder_mt:clone(prefab, component_mapper) end
function evolved.builder_mt:clone(prefab) end
```
#### `evolved.builder_mt:multi_clone`
@@ -2351,32 +1866,9 @@ function evolved.builder_mt:clone(prefab, component_mapper) end
```lua
---@param entity_count integer
---@param prefab evolved.entity
---@param component_mapper? evolved.component_mapper
---@return evolved.entity[] entity_list
---@return integer entity_count
---@nodiscard
function evolved.builder_mt:multi_clone(entity_count, prefab, component_mapper) end
```
#### `evolved.builder_mt:multi_clone_nr`
```lua
---@param entity_count integer
---@param prefab evolved.entity
---@param component_mapper? evolved.component_mapper
function evolved.builder_mt:multi_clone_nr(entity_count, prefab, component_mapper) end
```
#### `evolved.builder_mt:multi_clone_to`
```lua
---@param out_entity_list evolved.entity[]
---@param out_entity_first integer
---@param entity_count integer
---@param prefab evolved.entity
---@param component_mapper? evolved.component_mapper
function evolved.builder_mt:multi_clone_to(out_entity_list, out_entity_first,
entity_count, prefab, component_mapper) end
function evolved.builder_mt:multi_clone(entity_count, prefab) end
```
#### `evolved.builder_mt:has`
@@ -2491,22 +1983,6 @@ function evolved.builder_mt:default(default) end
function evolved.builder_mt:duplicate(duplicate) end
```
#### `evolved.builder_mt:realloc`
```lua
---@param realloc evolved.realloc
---@return evolved.builder builder
function evolved.builder_mt:realloc(realloc) end
```
#### `evolved.builder_mt:compmove`
```lua
---@param compmove evolved.compmove
---@return evolved.builder builder
function evolved.builder_mt:compmove(compmove) end
```
#### `evolved.builder_mt:prefab`
```lua
@@ -2537,14 +2013,6 @@ function evolved.builder_mt:include(...) end
function evolved.builder_mt:exclude(...) end
```
#### `evolved.builder_mt:variant`
```lua
---@param ... evolved.fragment fragments
---@return evolved.builder builder
function evolved.builder_mt:variant(...) end
```
### `evolved.builder_mt:require`
```lua

View File

@@ -5,12 +5,12 @@
- observers and events
- add INDEX fragment trait
- use compact prefix-tree for chunks
- optional ffi component storages
## Thoughts
- We should have a way to not copy components on deferred spawn/clone
- Basic default component value as true looks awful, should we use something else?
## Known Issues
- Errors in hooks or rellocs/compmoves/mappers are cannot be handled properly right now
- Errors in hooks are cannot be handled properly right now

View File

@@ -4,20 +4,15 @@ require 'develop.testing.clone_tests'
require 'develop.testing.depth_tests'
require 'develop.testing.destroy_tests'
require 'develop.testing.locate_tests'
require 'develop.testing.lookup_tests'
require 'develop.testing.main_tests'
require 'develop.testing.mappers_tests'
require 'develop.testing.multi_spawn_tests'
require 'develop.testing.name_tests'
require 'develop.testing.process_with_tests'
require 'develop.testing.realloc_tests'
require 'develop.testing.requires_fragment_tests'
require 'develop.testing.spawn_tests'
require 'develop.testing.system_as_query_tests'
require 'develop.benchmarks.clone_bmarks'
require 'develop.benchmarks.common_bmarks'
require 'develop.benchmarks.destroy_bmarks'
require 'develop.benchmarks.migration_bmarks'
require 'develop.benchmarks.process_bmarks'
require 'develop.benchmarks.spawn_bmarks'
@@ -39,5 +34,3 @@ print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.requires_fuzz'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.unique_fuzz'
print 'All tests passed.'

View File

@@ -307,11 +307,11 @@ print '----------------------------------------'
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 1 component', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true }
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.batch_destroy(QF1)
end)
@@ -319,12 +319,12 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 1 component', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true }
evo.defer()
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
@@ -333,11 +333,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 1 component', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [D1] = true }
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)
@@ -345,11 +345,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 3 components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.batch_destroy(QF1)
end)
@@ -357,12 +357,12 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 3 components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
@@ -371,11 +371,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 3 components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true }
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)
@@ -383,11 +383,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 5 components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.batch_destroy(QF1)
end)
@@ -395,12 +395,12 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 5 components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
evo.defer()
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
@@ -409,11 +409,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 5 components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)
@@ -423,11 +423,11 @@ print '----------------------------------------'
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 1 required component', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF1] = true }
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.batch_destroy(QF1)
end)
@@ -435,12 +435,12 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 1 required component', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF1] = true }
evo.defer()
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
@@ -449,11 +449,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 1 required component', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RD1] = true }
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)
@@ -461,11 +461,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 3 required components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF123] = true }
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.batch_destroy(QF1)
end)
@@ -473,12 +473,12 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 3 required components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF123] = true }
evo.defer()
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
@@ -487,11 +487,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 3 required components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RD123] = true }
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)
@@ -499,11 +499,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 5 required components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF12345] = true }
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.batch_destroy(QF1)
end)
@@ -511,12 +511,12 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 5 required components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF12345] = true }
evo.defer()
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
@@ -525,11 +525,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 5 required components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RD12345] = true }
multi_clone_nr(N, prefab)
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)

View File

@@ -54,7 +54,7 @@ basics.describe_bench(string.format('Common Benchmarks: Evolved Entity Cycle | %
local prefab_a = evo.builder():prefab():set(world):set(a, 0):spawn()
local prefab_b = evo.builder():prefab():set(world):set(b, 0):spawn()
evo.multi_clone_nr(N, prefab_a)
evo.multi_clone(N, prefab_a)
evo.builder()
:set(world):group(world):query(query_a)
@@ -129,10 +129,10 @@ basics.describe_bench(string.format('Common Benchmarks: Evolved Simple Iteration
local query_cd = evo.builder():set(world):include(c, d):spawn()
local query_ce = evo.builder():set(world):include(c, e):spawn()
evo.multi_spawn_nr(N, { [world] = true, [a] = 0, [b] = 0 })
evo.multi_spawn_nr(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0 })
evo.multi_spawn_nr(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0, [d] = 0 })
evo.multi_spawn_nr(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0, [e] = 0 })
evo.multi_spawn(N, { [world] = true, [a] = 0, [b] = 0 })
evo.multi_spawn(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0 })
evo.multi_spawn(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0, [d] = 0 })
evo.multi_spawn(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0, [e] = 0 })
evo.builder()
:set(world):group(world):query(query_ab)
@@ -223,7 +223,7 @@ basics.describe_bench(string.format('Common Benchmarks: Evolved Packed Iteration
local query_d = evo.builder():set(world):include(d):spawn()
local query_e = evo.builder():set(world):include(e):spawn()
evo.multi_spawn_nr(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0, [d] = 0, [e] = 0 })
evo.multi_spawn(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0, [d] = 0, [e] = 0 })
evo.builder()
:set(world):group(world):query(query_a)
@@ -317,7 +317,7 @@ basics.describe_bench(string.format('Common Benchmarks: Evolved Fragmented Itera
local query_z = evo.builder():set(world):include(chars[#chars]):spawn()
for i = 1, #chars do
evo.multi_spawn_nr(N, { [world] = true, [chars[i]] = i, [data] = i })
evo.multi_spawn(N, { [world] = true, [chars[i]] = i, [data] = i })
end
evo.builder()

View File

@@ -1,56 +0,0 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
print '----------------------------------------'
basics.describe_bench(string.format('Destroy Benchmarks: Acquire and Release %d ids', N),
function(tables)
local id = evo.id
local destroy = evo.destroy
for i = 1, N do
tables[i] = id()
end
for i = 1, N do
destroy(tables[i])
end
end, function()
return {}
end)
basics.describe_bench(string.format('Destroy Benchmarks: Acquire and Release %d double ids', N),
function(tables)
local id = evo.id
local destroy = evo.destroy
for i = 1, N, 2 do
tables[i], tables[i + 1] = id(2)
end
for i = 1, N, 2 do
destroy(tables[i], tables[i + 1])
end
end, function()
return {}
end)
basics.describe_bench(string.format('Destroy Benchmarks: Acquire and Release %d triple ids', N),
function(tables)
local id = evo.id
local destroy = evo.destroy
for i = 1, N, 3 do
tables[i], tables[i + 1], tables[i + 2] = id(3)
end
for i = 1, N, 3 do
destroy(tables[i], tables[i + 1], tables[i + 2])
end
end, function()
return {}
end)

View File

@@ -20,7 +20,7 @@ basics.describe_bench(string.format('Process Benchmarks: Evolved AoS Processing
local pf = evo.builder():set(wf):spawn()
local vf = evo.builder():set(wf):spawn()
evo.multi_spawn_nr(N, {
evo.multi_spawn(N, {
[wf] = true,
[pf] = { x = 0, y = 0, z = 0, w = 0 },
[vf] = { x = 0, y = 0, z = 0, w = 0 },
@@ -67,7 +67,7 @@ basics.describe_bench(string.format('Process Benchmarks: Evolved SoA Processing
local vzf = evo.builder():set(wf):spawn()
local vwf = evo.builder():set(wf):spawn()
evo.multi_spawn_nr(N, {
evo.multi_spawn(N, {
[wf] = true,
[pxf] = 0,
[pyf] = 0,

View File

@@ -536,11 +536,11 @@ print '----------------------------------------'
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 component', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [F1] = true }
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.batch_destroy(QF1)
end)
@@ -548,12 +548,12 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 1 component', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [F1] = true }
evo.defer()
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
@@ -562,11 +562,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 1 component', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [D1] = true }
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)
@@ -574,11 +574,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true }
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.batch_destroy(QF1)
end)
@@ -586,12 +586,12 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 3 components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
@@ -600,11 +600,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 3 components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [D1] = true, [D2] = true, [D3] = true }
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)
@@ -612,11 +612,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.batch_destroy(QF1)
end)
@@ -624,12 +624,12 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 5 components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
evo.defer()
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
@@ -638,11 +638,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 5 components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)
@@ -652,11 +652,11 @@ print '----------------------------------------'
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 required component', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [F1] = true }
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.batch_destroy(QF1)
end)
@@ -664,12 +664,12 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 1 required component', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [F1] = true }
evo.defer()
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
@@ -678,11 +678,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 1 required component', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [D1] = true }
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)
@@ -690,11 +690,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 required components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [RF123] = true }
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.batch_destroy(QF1)
end)
@@ -702,12 +702,12 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 3 required components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [RF123] = true }
evo.defer()
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
@@ -716,11 +716,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 3 required components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [RD123] = true }
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)
@@ -728,11 +728,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 required components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [RF12345] = true }
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.batch_destroy(QF1)
end)
@@ -740,12 +740,12 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 5 required components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [RF12345] = true }
evo.defer()
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
@@ -754,11 +754,11 @@ basics.describe_bench(
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 5 required components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local multi_spawn = evo.multi_spawn
local components = { [RD12345] = true }
multi_spawn_nr(N, components)
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)

View File

@@ -118,11 +118,11 @@ end
---
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
evo.collect_garbage()
end
evo.destroy(__table_unpack(all_entity_list))
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
evo.collect_garbage()
end

View File

@@ -124,11 +124,11 @@ end
---
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
evo.collect_garbage()
end
evo.destroy(__table_unpack(all_entity_list))
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
evo.collect_garbage()
end

View File

@@ -56,20 +56,6 @@ local function generate_query(query)
end
end
local variant_set = {}
local variant_list = {}
local variant_count = 0
for _ = 1, math.random(0, #all_fragment_list) do
local variant = all_fragment_list[math.random(1, #all_fragment_list)]
if not variant_set[variant] then
variant_count = variant_count + 1
variant_set[variant] = variant_count
variant_list[variant_count] = variant
end
end
if include_count > 0 then
evo.set(query, evo.INCLUDES, include_list)
end
@@ -77,10 +63,6 @@ local function generate_query(query)
if exclude_count > 0 then
evo.set(query, evo.EXCLUDES, exclude_list)
end
if variant_count > 0 then
evo.set(query, evo.VARIANTS, variant_list)
end
end
---@param query_count integer
@@ -191,22 +173,12 @@ local function execute_query(query)
local query_include_list = evo.get(query, evo.INCLUDES) or {}
local query_exclude_list = evo.get(query, evo.EXCLUDES) or {}
local query_variant_list = evo.get(query, evo.VARIANTS) or {}
local query_include_count = #query_include_list
local query_exclude_count = #query_exclude_list
local query_variant_count = #query_variant_list
local query_include_set = {}
for _, include in ipairs(query_include_list) do
query_include_set[include] = true
end
local query_variant_set = {}
for _, variant in ipairs(query_variant_list) do
query_variant_set[variant] = true
end
for chunk, entity_list, entity_count in evo.execute(query) do
assert(not query_chunk_set[chunk])
query_chunk_set[chunk] = true
@@ -217,29 +189,19 @@ local function execute_query(query)
query_entity_set[entity] = true
end
if query_include_count > 0 then
assert(chunk:has_all(__table_unpack(query_include_list)))
end
if query_exclude_count > 0 then
assert(not chunk:has_any(__table_unpack(query_exclude_list)))
end
if query_variant_count > 0 then
assert(chunk:has_any(__table_unpack(query_variant_list)))
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 =
(query_variant_count == 0 or evo.has_any(entity, __table_unpack(query_variant_list))) and
(query_include_count == 0 or evo.has_all(entity, __table_unpack(query_include_list))) and
(query_exclude_count == 0 or not evo.has_any(entity, __table_unpack(query_exclude_list)))
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_variant_set[fragment] and not query_include_set[fragment] then
if evo.has(fragment, evo.EXPLICIT) and not query_include_set[fragment] then
is_entity_matched = false
end
end
@@ -274,13 +236,10 @@ for _ = 1, math.random(1, 5) do
if math.random(1, 2) == 1 then
generate_query(query)
else
local r = math.random(1, 3)
if r == 1 then
if math.random(1, 2) == 1 then
evo.remove(query, evo.INCLUDES)
elseif r == 2 then
evo.remove(query, evo.EXCLUDES)
else
evo.remove(query, evo.VARIANTS)
evo.remove(query, evo.EXCLUDES)
end
end
end
@@ -296,7 +255,7 @@ end
---
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
evo.collect_garbage()
end
evo.destroy(__table_unpack(all_query_list))
@@ -304,5 +263,5 @@ evo.destroy(__table_unpack(all_entity_list))
evo.destroy(__table_unpack(all_fragment_list))
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
evo.collect_garbage()
end

View File

@@ -78,11 +78,11 @@ end
---
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
evo.collect_garbage()
end
evo.destroy(__table_unpack(all_entity_list))
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
evo.collect_garbage()
end

View File

@@ -115,17 +115,17 @@ end
if math.random(1, 2) == 1 then
evo.destroy(__table_unpack(all_entity_list))
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
evo.collect_garbage()
end
evo.destroy(__table_unpack(all_fragment_list))
else
evo.destroy(__table_unpack(all_fragment_list))
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
evo.collect_garbage()
end
evo.destroy(__table_unpack(all_entity_list))
end
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
evo.collect_garbage()
end

View File

@@ -64,11 +64,11 @@ end
---
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
evo.collect_garbage()
end
evo.destroy(__table_unpack(all_entity_list))
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
evo.collect_garbage()
end

View File

@@ -1,7 +1,5 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local f1, f2 = evo.id(2)

View File

@@ -1,7 +1,5 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
assert(evo.defer())
assert(evo.cancel())

View File

@@ -1,7 +1,5 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
do
local p = evo.spawn()
@@ -397,165 +395,3 @@ do
end
end
end
do
local f1, f2 = evo.id(2)
local p = evo.spawn { [f1] = 42, [f2] = 'hello' }
do
local entity_list, entity_count = {}, 2
evo.multi_clone_to(entity_list, 1, entity_count, p)
assert(evo.has_all(entity_list[1], f1, f2))
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.get(entity_list[1], f1) == 42 and evo.get(entity_list[1], f2) == 'hello')
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == 'hello')
end
do
local entity_list, entity_count = {}, 2
evo.multi_clone_to(entity_list, 2, entity_count, p)
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.has_all(entity_list[3], f1, f2))
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == 'hello')
assert(evo.get(entity_list[3], f1) == 42 and evo.get(entity_list[3], f2) == 'hello')
end
do
local entity_list, entity_count = {}, 2
evo.defer()
evo.multi_clone_to(entity_list, 1, entity_count, p)
assert(entity_list[1] and entity_list[2])
assert(evo.empty_all(entity_list[1], entity_list[2]))
evo.commit()
assert(evo.has_all(entity_list[1], f1, f2))
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.get(entity_list[1], f1) == 42 and evo.get(entity_list[1], f2) == 'hello')
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == 'hello')
end
do
local entity_list, entity_count = {}, 2
evo.defer()
evo.multi_clone_to(entity_list, 2, entity_count, p)
assert(entity_list[2] and entity_list[3])
assert(evo.empty_all(entity_list[2], entity_list[3]))
evo.commit()
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.has_all(entity_list[3], f1, f2))
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == 'hello')
assert(evo.get(entity_list[3], f1) == 42 and evo.get(entity_list[3], f2) == 'hello')
end
end
do
local f1, f2 = evo.id(2)
local q12 = evo.builder():include(f1, f2):build()
local p = evo.spawn { [f1] = 42, [f2] = 'hello' }
do
assert(select('#', evo.multi_clone_nr(2, p)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 3)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, 'hello')
assert(select('#', b:multi_clone_nr(2, p)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 5)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, 'hello')
assert(select('#', b:multi_build_nr(2, p)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 7)
end
end
end
do
local f1, f2 = evo.id(2)
local q12 = evo.builder():include(f1, f2):build()
local p = evo.spawn { [f1] = 42, [f2] = 'hello' }
do
local entity_list = {}
assert(select('#', evo.multi_clone_to(entity_list, 1, 2, p)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 3)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, 'hello')
local entity_list = {}
assert(select('#', b:multi_clone_to(entity_list, 1, 2, p)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 5)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, 'hello')
local entity_list = {}
assert(select('#', b:multi_build_to(entity_list, 1, 2, p)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 7)
end
end
end

View File

@@ -1,7 +1,5 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
assert(evo.depth() == 0)

View File

@@ -1,7 +1,5 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local e = evo.id()
assert(evo.alive(e))

View File

@@ -1,7 +1,5 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local e1, e2, f1, f2 = evo.id(4)

View File

@@ -1,195 +0,0 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local e1, e2, e3 = evo.id(3)
do
assert(evo.lookup('lookup_hello') == nil)
assert(evo.lookup('lookup_world') == nil)
do
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
do
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
end
evo.set(e1, evo.NAME, 'lookup_hello')
do
assert(evo.lookup('lookup_hello') == e1)
assert(evo.lookup('lookup_world') == nil)
do
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e1)
end
do
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
end
evo.set(e2, evo.NAME, 'lookup_hello')
evo.set(e3, evo.NAME, 'lookup_hello')
do
assert(evo.lookup('lookup_hello') == e1)
assert(evo.lookup('lookup_world') == nil)
do
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 3 and entity_count == 3)
assert(entity_list[1] == e1 and entity_list[2] == e2 and entity_list[3] == e3)
end
end
evo.set(e2, evo.NAME, 'lookup_world')
do
assert(evo.lookup('lookup_hello') == e1)
assert(evo.lookup('lookup_world') == e2)
do
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e1 and entity_list[2] == e3)
end
do
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e2)
end
end
evo.set(e3, evo.NAME, 'lookup_world')
do
assert(evo.lookup('lookup_hello') == e1)
assert(evo.lookup('lookup_world') == e2)
do
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e1)
end
do
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e2 or entity_list[1] == e3)
end
end
evo.remove(e1, evo.NAME)
do
assert(evo.lookup('lookup_hello') == nil)
assert(evo.lookup('lookup_world') == e2)
do
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
do
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e2 or entity_list[1] == e3)
end
end
end
do
local e1, e2, e3 = evo.id(3)
evo.set(e1, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e1)
end
evo.set(e2, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e1 and entity_list[2] == e2)
end
evo.set(e3, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 3 and entity_count == 3)
assert(entity_list[1] == e1 and entity_list[2] == e2 and entity_list[3] == e3)
end
evo.clear(e1, e2, e3)
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
evo.set(e3, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e3)
end
evo.set(e2, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e3 and entity_list[2] == e2)
end
evo.set(e1, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 3 and entity_count == 3)
assert(entity_list[1] == e3 and entity_list[2] == e2 and entity_list[3] == e1)
end
evo.destroy(e3, e2, e1)
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
end
do
local e1, e2 = evo.id(2)
evo.set(e1, evo.NAME, 'lookup_e')
evo.set(e2, evo.NAME, 'lookup_e')
do
local entity_list = {}
local entity_count = evo.multi_lookup_to(entity_list, 1, 'lookup_e')
assert(entity_count == 2 and entity_list[1] == e1 and entity_list[2] == e2)
end
do
local entity_list = {}
local entity_count = evo.multi_lookup_to(entity_list, 2, 'lookup_e')
assert(entity_count == 2 and entity_list[2] == e1 and entity_list[3] == e2)
end
end

View File

@@ -2302,66 +2302,27 @@ do
evo.set(e2, f2, 44)
do
local e1_count = 0
local e2_count = 0
for _, 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
elseif entity_list[i] == e2 then
e2_count = e2_count + 1
end
end
end
assert(e1_count == 1)
assert(e2_count == 1)
local iter, state = evo.execute(q)
local chunk = iter(state)
assert(chunk and chunk ~= evo.chunk(f1))
end
evo.set(q, evo.EXCLUDES, { f2 })
do
local e1_count = 0
local e2_count = 0
for chunk, entity_list, entity_count in evo.execute(q) do
assert(not chunk:has(f2))
for i = 1, entity_count do
if entity_list[i] == e1 then
e1_count = e1_count + 1
elseif entity_list[i] == e2 then
e2_count = e2_count + 1
end
end
end
assert(e1_count == 1)
assert(e2_count == 0)
local iter, state = evo.execute(q)
local chunk = iter(state)
assert(chunk and chunk ~= evo.chunk(f1))
end
evo.set(q, evo.INCLUDES, { f1 })
do
local e1_count = 0
local e2_count = 0
for chunk, entity_list, entity_count in evo.execute(q) do
assert(chunk:has(f1))
assert(not chunk:has(f2))
for i = 1, entity_count do
if entity_list[i] == e1 then
e1_count = e1_count + 1
elseif entity_list[i] == e2 then
e2_count = e2_count + 1
end
end
end
assert(e1_count == 1)
assert(e2_count == 0)
local iter, state = evo.execute(q)
local chunk, entity_list, entity_count = iter(state)
assert(chunk == evo.chunk(f1))
assert(entity_list and entity_list[1] == e1)
assert(entity_count == 1)
end
end

View File

@@ -1,244 +0,0 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local f1, f2 = evo.id(2)
local e1 = evo.spawn({ [f1] = 1, [f2] = 2 }, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] * 2
f2s[p] = f2s[p] * 3
end)
local e2 = evo.spawn({ [f1] = 1, [f2] = 2 }, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end)
assert(evo.has(e1, f1) and evo.get(e1, f1) == 2)
assert(evo.has(e1, f2) and evo.get(e1, f2) == 6)
assert(evo.has(e2, f1) and evo.get(e2, f1) == 11)
assert(evo.has(e2, f2) and evo.get(e2, f2) == 22)
local e11 = evo.clone(e1, nil, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] * 3
f2s[p] = f2s[p] * 4
end)
local e22 = evo.clone(e2, nil, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] + 30
f2s[p] = f2s[p] + 40
end)
assert(evo.has(e11, f1) and evo.get(e11, f1) == 6)
assert(evo.has(e11, f2) and evo.get(e11, f2) == 24)
assert(evo.has(e22, f1) and evo.get(e22, f1) == 41)
assert(evo.has(e22, f2) and evo.get(e22, f2) == 62)
end
do
local f1, f2 = evo.id(2)
evo.defer()
local e1 = evo.spawn({ [f1] = 1, [f2] = 2 }, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] * 2
f2s[p] = f2s[p] * 3
end)
local e2 = evo.spawn({ [f1] = 1, [f2] = 2 }, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end)
assert(not evo.has(e1, f1) and evo.get(e1, f1) == nil)
assert(not evo.has(e1, f2) and evo.get(e1, f2) == nil)
assert(not evo.has(e2, f1) and evo.get(e2, f1) == nil)
assert(not evo.has(e2, f2) and evo.get(e2, f2) == nil)
evo.commit()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 2)
assert(evo.has(e1, f2) and evo.get(e1, f2) == 6)
assert(evo.has(e2, f1) and evo.get(e2, f1) == 11)
assert(evo.has(e2, f2) and evo.get(e2, f2) == 22)
evo.defer()
local e11 = evo.clone(e1, nil, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] * 3
f2s[p] = f2s[p] * 4
end)
local e22 = evo.clone(e2, nil, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] + 30
f2s[p] = f2s[p] + 40
end)
assert(not evo.has(e11, f1) and evo.get(e11, f1) == nil)
assert(not evo.has(e11, f2) and evo.get(e11, f2) == nil)
assert(not evo.has(e22, f1) and evo.get(e22, f1) == nil)
assert(not evo.has(e22, f2) and evo.get(e22, f2) == nil)
evo.commit()
assert(evo.has(e11, f1) and evo.get(e11, f1) == 6)
assert(evo.has(e11, f2) and evo.get(e11, f2) == 24)
assert(evo.has(e22, f1) and evo.get(e22, f1) == 41)
assert(evo.has(e22, f2) and evo.get(e22, f2) == 62)
end
do
local f1, f2 = evo.id(2)
local es, ec = evo.multi_spawn(10, { [f1] = 1, [f2] = 2 }, function(c, b, e)
local f1s, f2s = c:components(f1, f2)
for p = b, e do
f1s[p] = f1s[p] * 2
f2s[p] = f2s[p] * 3
end
end)
for i = 1, ec do
local e = es[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 2)
assert(evo.has(e, f2) and evo.get(e, f2) == 6)
end
local es2, ec2 = evo.multi_clone(10, es[1], nil, function(c, b, e)
local f1s, f2s = c:components(f1, f2)
for p = b, e do
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end
end)
for i = 1, ec2 do
local e = es2[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 12)
assert(evo.has(e, f2) and evo.get(e, f2) == 26)
end
end
do
local f1, f2 = evo.id(2)
evo.defer()
local es, ec = evo.multi_spawn(10, { [f1] = 1, [f2] = 2 }, function(c, b, e)
local f1s, f2s = c:components(f1, f2)
for p = b, e do
f1s[p] = f1s[p] * 2
f2s[p] = f2s[p] * 3
end
end)
for i = 1, ec do
local e = es[i]
assert(not evo.has(e, f1) and evo.get(e, f1) == nil)
assert(not evo.has(e, f2) and evo.get(e, f2) == nil)
end
evo.commit()
for i = 1, ec do
local e = es[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 2)
assert(evo.has(e, f2) and evo.get(e, f2) == 6)
end
evo.defer()
local es2, ec2 = evo.multi_clone(10, es[1], nil, function(c, b, e)
local f1s, f2s = c:components(f1, f2)
for p = b, e do
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end
end)
for i = 1, ec2 do
local e = es2[i]
assert(not evo.has(e, f1) and evo.get(e, f1) == nil)
assert(not evo.has(e, f2) and evo.get(e, f2) == nil)
end
evo.commit()
for i = 1, ec2 do
local e = es2[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 12)
assert(evo.has(e, f2) and evo.get(e, f2) == 26)
end
end
do
local f1, f2 = evo.id(2)
local e1 = evo.builder():set(f1, 1):set(f2, 2):build(nil, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] * 2
f2s[p] = f2s[p] * 3
end)
assert(evo.has(e1, f1) and evo.get(e1, f1) == 2)
assert(evo.has(e1, f2) and evo.get(e1, f2) == 6)
local e2 = evo.builder():build(e1, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end)
assert(evo.has(e2, f1) and evo.get(e2, f1) == 12)
assert(evo.has(e2, f2) and evo.get(e2, f2) == 26)
local e3 = evo.builder():set(f2, 3):build(e1, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end)
assert(evo.has(e3, f1) and evo.get(e3, f1) == 12)
assert(evo.has(e3, f2) and evo.get(e3, f2) == 23)
end
do
local f1, f2 = evo.id(2)
local es, ec = evo.builder():set(f1, 1):set(f2, 2):multi_build(10, nil, function(c, b, e)
local f1s, f2s = c:components(f1, f2)
for p = b, e do
f1s[p] = f1s[p] * 2
f2s[p] = f2s[p] * 3
end
end)
for i = 1, ec do
local e = es[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 2)
assert(evo.has(e, f2) and evo.get(e, f2) == 6)
end
local es2, ec2 = evo.builder():multi_build(10, es[1], function(c, b, e)
local f1s, f2s = c:components(f1, f2)
for p = b, e do
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end
end)
for i = 1, ec2 do
local e = es2[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 12)
assert(evo.has(e, f2) and evo.get(e, f2) == 26)
end
end

View File

@@ -1,7 +1,5 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local entity_list
@@ -607,164 +605,3 @@ do
end
end
end
do
local f1, f2 = evo.id(2)
do
local entity_list, entity_count = {}, 2
evo.multi_spawn_to(entity_list, 1, entity_count, { [f1] = 42, [f2] = "hello" })
assert(evo.has_all(entity_list[1], f1, f2))
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.get(entity_list[1], f1) == 42 and evo.get(entity_list[1], f2) == "hello")
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == "hello")
end
do
local entity_list, entity_count = {}, 2
evo.multi_spawn_to(entity_list, 2, entity_count, { [f1] = 42, [f2] = "hello" })
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.has_all(entity_list[3], f1, f2))
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == "hello")
assert(evo.get(entity_list[3], f1) == 42 and evo.get(entity_list[3], f2) == "hello")
end
do
local entity_list, entity_count = {}, 2
evo.defer()
evo.multi_spawn_to(entity_list, 1, entity_count, { [f1] = 42, [f2] = "hello" })
assert(entity_list[1] and entity_list[2])
assert(evo.empty_all(entity_list[1], entity_list[2]))
evo.commit()
assert(evo.has_all(entity_list[1], f1, f2))
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.get(entity_list[1], f1) == 42 and evo.get(entity_list[1], f2) == "hello")
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == "hello")
end
do
local entity_list, entity_count = {}, 2
evo.defer()
evo.multi_spawn_to(entity_list, 2, entity_count, { [f1] = 42, [f2] = "hello" })
assert(entity_list[2] and entity_list[3])
assert(evo.empty_all(entity_list[2], entity_list[3]))
evo.commit()
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.has_all(entity_list[3], f1, f2))
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == "hello")
assert(evo.get(entity_list[3], f1) == 42 and evo.get(entity_list[3], f2) == "hello")
end
end
do
local f1, f2 = evo.id(2)
local q12 = evo.builder():include(f1, f2):spawn()
do
assert(select('#', evo.multi_spawn_nr(2, { [f1] = 42, [f2] = "hello" })) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 2)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, "hello")
assert(select('#', b:multi_spawn_nr(2)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 4)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, "hello")
assert(select('#', b:multi_build_nr(2)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 6)
end
end
end
do
local f1, f2 = evo.id(2)
local q12 = evo.builder():include(f1, f2):spawn()
do
local entity_list = {}
assert(select('#', evo.multi_spawn_to(entity_list, 1, 2, { [f1] = 42, [f2] = "hello" })) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 2)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, "hello")
local entity_list = {}
assert(select('#', b:multi_spawn_to(entity_list, 1, 2)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 4)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, "hello")
local entity_list = {}
assert(select('#', b:multi_build_to(entity_list, 1, 2)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 6)
end
end
end

View File

@@ -1,7 +1,5 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local id = evo.id()

View File

@@ -1,109 +0,0 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local f = evo.id()
local e = evo.builder():set(f, 42):spawn()
local s = evo.builder()
:include(f)
:prologue(function(payload1, payload2, payload3)
assert(payload1 == 11 and payload2 == 22 and payload3 == 33)
end)
:execute(function(chunk, entity_list, entity_count, payload1, payload2, payload3)
assert(payload1 == 11 and payload2 == 22 and payload3 == 33)
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
end)
:epilogue(function(payload1, payload2, payload3)
assert(payload1 == 11 and payload2 == 22 and payload3 == 33)
end)
:spawn()
evo.process_with(s, 11, 22, 33)
end
do
local f = evo.id()
local e = evo.builder():set(f, 42):spawn()
local s = evo.builder()
:include(f)
:prologue(function(payload1, payload2, payload3)
assert(payload1 == nil and payload2 == 42 and payload3 == nil)
end)
:execute(function(chunk, entity_list, entity_count, payload1, payload2, payload3)
assert(payload1 == nil and payload2 == 42 and payload3 == nil)
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
end)
:epilogue(function(payload1, payload2, payload3)
assert(payload1 == nil and payload2 == 42 and payload3 == nil)
end)
:spawn()
evo.process_with(s, nil, 42)
end
do
local f = evo.id()
local e = evo.builder():set(f, 42):spawn()
local s = evo.builder()
:include(f)
:prologue(function(payload1, payload2, payload3)
assert(payload1 == nil and payload2 == nil and payload3 == nil)
end)
:execute(function(chunk, entity_list, entity_count, payload1, payload2, payload3)
assert(payload1 == nil and payload2 == nil and payload3 == nil)
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
end)
:epilogue(function(payload1, payload2, payload3)
assert(payload1 == nil and payload2 == nil and payload3 == nil)
end)
:spawn()
evo.process_with(s)
end
do
local f = evo.id()
local e = evo.builder():set(f, 42):spawn()
local prologue_sum, execute_sum, epilogue_sum = 0, 0, 0
local function sum(...)
local s = 0
for i = 1, select('#', ...) do
s = s + select(i, ...)
end
return s
end
local function iota(n)
if n == 0 then return end
return n, iota(n - 1)
end
local s = evo.builder()
:include(f)
:prologue(function(...)
prologue_sum = prologue_sum + sum(...)
end)
:execute(function(chunk, entity_list, entity_count, ...)
execute_sum = execute_sum + sum(...)
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
end)
:epilogue(function(...)
epilogue_sum = epilogue_sum + sum(...)
end)
:spawn()
for n = 0, 50 do
prologue_sum, execute_sum, epilogue_sum = 0, 0, 0
evo.process_with(s, iota(n))
local expect_sum = (n * (n + 1)) / 2
assert(prologue_sum == expect_sum)
assert(execute_sum == expect_sum)
assert(epilogue_sum == expect_sum)
end
end

View File

@@ -1,596 +0,0 @@
local evo = require 'evolved'
evo.debug_mode(true)
---@type ffilib?
local ffi = (function()
if package and package.loaded then
local loaded_ffi = package.loaded.ffi
if loaded_ffi then return loaded_ffi end
end
if package and package.preload then
local ffi_loader = package.preload.ffi
if ffi_loader then return ffi_loader() end
end
end)()
if not ffi then
return
end
local FLOAT_TYPEOF = ffi.typeof('float')
local FLOAT_SIZEOF = ffi.sizeof(FLOAT_TYPEOF)
local FLOAT_STORAGE_TYPEOF = ffi.typeof('$[?]', FLOAT_TYPEOF)
local DOUBLE_TYPEOF = ffi.typeof('double')
local DOUBLE_SIZEOF = ffi.sizeof(DOUBLE_TYPEOF)
local DOUBLE_STORAGE_TYPEOF = ffi.typeof('$[?]', DOUBLE_TYPEOF)
local STORAGE_SIZES = {}
---@type evolved.realloc
local function float_realloc(src, src_size, dst_size)
if dst_size == 0 then
assert(src and src_size > 0)
local expected_src_size = STORAGE_SIZES[src]
assert(expected_src_size == src_size)
STORAGE_SIZES[src] = nil
return
else
if src then
assert(src_size > 0)
local expected_src_size = STORAGE_SIZES[src]
assert(expected_src_size == src_size)
else
assert(src_size == 0)
end
local dst = ffi.new(FLOAT_STORAGE_TYPEOF, dst_size + 1)
STORAGE_SIZES[dst] = dst_size
if src then
ffi.copy(dst + 1, src + 1, math.min(src_size, dst_size) * FLOAT_SIZEOF)
end
return dst
end
end
---@type evolved.realloc
local function double_realloc(src, src_size, dst_size)
if dst_size == 0 then
assert(src and src_size > 0)
local expected_src_size = STORAGE_SIZES[src]
assert(expected_src_size == src_size)
STORAGE_SIZES[src] = nil
return
else
if src then
assert(src_size > 0)
local expected_src_size = STORAGE_SIZES[src]
assert(expected_src_size == src_size)
else
assert(src_size == 0)
end
local dst = ffi.new(DOUBLE_STORAGE_TYPEOF, dst_size + 1)
STORAGE_SIZES[dst] = dst_size
if src then
ffi.copy(dst + 1, src + 1, math.min(src_size, dst_size) * DOUBLE_SIZEOF)
end
return dst
end
end
---@type evolved.compmove
local function double_compmove(src, f, e, t, dst)
ffi.copy(dst + t, src + f, (e - f + 1) * DOUBLE_SIZEOF)
end
do
local f1 = evo.builder():realloc(double_realloc):build()
local e1 = evo.builder():set(f1, 21):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 21)
local e2 = evo.builder():set(f1, 42):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 21)
assert(evo.has(e2, f1) and evo.get(e2, f1) == 42)
local e3 = evo.builder():set(f1, 84):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 21)
assert(evo.has(e2, f1) and evo.get(e2, f1) == 42)
assert(evo.has(e3, f1) and evo.get(e3, f1) == 84)
evo.destroy(e1)
assert(not evo.has(e1, f1))
assert(evo.has(e2, f1) and evo.get(e2, f1) == 42)
assert(evo.has(e3, f1) and evo.get(e3, f1) == 84)
evo.destroy(e3)
assert(not evo.has(e1, f1))
assert(evo.has(e2, f1) and evo.get(e2, f1) == 42)
assert(not evo.has(e3, f1))
evo.destroy(e2)
assert(not evo.has(e1, f1))
assert(not evo.has(e2, f1))
assert(not evo.has(e3, f1))
end
do
local f1 = evo.builder():realloc(double_realloc):build()
local q1 = evo.builder():include(f1):build()
do
local es, ec = {}, 10
for i = 1, ec do es[i] = evo.spawn({ [f1] = i }) end
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == i) end
end
do
local p = evo.builder():set(f1, 42):build()
local es, ec = {}, 10
for i = 1, ec do es[i] = evo.clone(p) end
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42) end
end
do
local es1, ec1 = evo.multi_spawn(10, { [f1] = 42 })
for i = 1, ec1 do assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 42) end
local es2, ec2 = evo.multi_spawn(20, { [f1] = 84 })
for i = 1, ec1 do assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 42) end
for i = 1, ec2 do assert(evo.has(es2[i], f1) and evo.get(es2[i], f1) == 84) end
end
do
local p = evo.builder():set(f1, 21):build()
local es1, ec1 = evo.multi_clone(10, p)
for i = 1, ec1 do assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 21) end
local es2, ec2 = evo.multi_clone(20, p)
for i = 1, ec1 do assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 21) end
for i = 1, ec2 do assert(evo.has(es2[i], f1) and evo.get(es2[i], f1) == 21) end
end
evo.batch_destroy(q1)
end
do
local f1 = evo.builder():realloc(double_realloc):build()
local f2 = evo.builder():realloc(double_realloc):build()
local q1 = evo.builder():include(f1):build()
local q2 = evo.builder():include(f2):build()
do
local e = evo.builder():set(f1, 21):set(f2, 42):build()
assert(evo.has(e, f1) and evo.get(e, f1) == 21)
assert(evo.has(e, f2) and evo.get(e, f2) == 42)
evo.remove(e, f1)
assert(not evo.has(e, f1))
assert(evo.has(e, f2) and evo.get(e, f2) == 42)
end
do
local e = evo.builder():set(f1, 21):set(f2, 42):build()
assert(evo.has(e, f1) and evo.get(e, f1) == 21)
assert(evo.has(e, f2) and evo.get(e, f2) == 42)
evo.clear(e)
assert(not evo.has(e, f1))
assert(not evo.has(e, f2))
end
do
local es, ec = evo.multi_spawn(10, { [f1] = 21, [f2] = 42 })
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 21)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 42)
end
evo.batch_remove(q1, f1)
local e12 = evo.builder():set(f1, 1):set(f2, 2):build()
assert(evo.has(e12, f1) and evo.get(e12, f1) == 1)
assert(evo.has(e12, f2) and evo.get(e12, f2) == 2)
for i = 1, ec do
assert(not evo.has(es[i], f1))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 42)
end
evo.batch_set(q2, f1, 84)
assert(evo.has(e12, f1) and evo.get(e12, f1) == 84)
assert(evo.has(e12, f2) and evo.get(e12, f2) == 2)
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 84)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 42)
end
evo.batch_set(q2, f1, 21)
assert(evo.has(e12, f1) and evo.get(e12, f1) == 21)
assert(evo.has(e12, f2) and evo.get(e12, f2) == 2)
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 21)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 42)
end
end
end
do
local f1 = evo.builder():realloc(double_realloc):compmove(double_compmove):build()
local f2 = evo.builder():realloc(double_realloc):compmove(double_compmove):build()
local q1 = evo.builder():include(f1):build()
local q2 = evo.builder():include(f2):build()
do
local es1, ec1 = evo.multi_spawn(10, { [f1] = 1, [f2] = 2 })
for i = 1, ec1 do
assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 1)
assert(evo.has(es1[i], f2) and evo.get(es1[i], f2) == 2)
end
local es2, ec2 = evo.multi_spawn(20, { [f1] = 3, [f2] = 4 })
for i = 1, ec1 do
assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 1)
assert(evo.has(es1[i], f2) and evo.get(es1[i], f2) == 2)
end
for i = 1, ec2 do
assert(evo.has(es2[i], f1) and evo.get(es2[i], f1) == 3)
assert(evo.has(es2[i], f2) and evo.get(es2[i], f2) == 4)
end
local e2 = evo.builder():set(f2, 42):build()
assert(evo.has(e2, f2) and evo.get(e2, f2) == 42)
evo.batch_remove(q1, f1)
assert(evo.has(e2, f2) and evo.get(e2, f2) == 42)
for i = 1, ec1 do
assert(not evo.has(es1[i], f1))
assert(evo.has(es1[i], f2) and evo.get(es1[i], f2) == 2)
end
for i = 1, ec2 do
assert(not evo.has(es2[i], f1))
assert(evo.has(es2[i], f2) and evo.get(es2[i], f2) == 4)
end
local e12 = evo.builder():set(f1, 21):set(f2, 42):build()
assert(evo.has(e2, f2) and evo.get(e2, f2) == 42)
assert(evo.has(e12, f1) and evo.get(e12, f1) == 21)
assert(evo.has(e12, f2) and evo.get(e12, f2) == 42)
evo.batch_set(q2, f1, 84)
assert(evo.has(e2, f2) and evo.get(e2, f2) == 42)
assert(evo.has(e12, f1) and evo.get(e12, f1) == 84)
assert(evo.has(e12, f2) and evo.get(e12, f2) == 42)
for i = 1, ec1 do
assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 84)
assert(evo.has(es1[i], f2) and evo.get(es1[i], f2) == 2)
end
for i = 1, ec2 do
assert(evo.has(es2[i], f1) and evo.get(es2[i], f1) == 84)
assert(evo.has(es2[i], f2) and evo.get(es2[i], f2) == 4)
end
end
end
do
local f1 = evo.builder():default(42):build()
local es, ec = evo.multi_spawn(10, { [f1] = 21 })
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 21) end
evo.set(f1, evo.TAG)
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil) end
evo.remove(f1, evo.TAG)
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42) end
end
do
local f1 = evo.builder():realloc(float_realloc):build()
local e1 = evo.builder():set(f1, 3):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 3)
evo.set(f1, evo.REALLOC, double_realloc)
assert(evo.has(e1, f1) and evo.get(e1, f1) == 3)
evo.remove(f1, evo.REALLOC)
assert(evo.has(e1, f1) and evo.get(e1, f1) == 3)
evo.set(f1, evo.REALLOC, double_realloc)
assert(evo.has(e1, f1) and evo.get(e1, f1) == 3)
end
do
local f1 = evo.builder():realloc(double_realloc):build()
local es, ec = evo.multi_spawn(20, { [f1] = 42 })
for i = 1, ec / 2 do
evo.destroy(es[ec - i + 1])
end
evo.collect_garbage()
for i = 1, ec / 2 do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
end
end
do
evo.collect_garbage()
local f1 = evo.builder():name('f1'):realloc(double_realloc):compmove(double_compmove):build()
local f2 = evo.builder():name('f2'):realloc(double_realloc):compmove(double_compmove):build()
local q1 = evo.builder():include(f1):build()
local q2 = evo.builder():include(f2):build()
do
local es, ec = evo.multi_spawn(40, { [f2] = 2 })
for i = 1, ec do
assert(not evo.has(es[i], f1))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_destroy(q2)
end
do
local es, ec = evo.multi_spawn(50, { [f1] = 1, [f2] = 2 })
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 1)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_remove(q1, f1)
for i = 1, ec do
assert(not evo.has(es[i], f1))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_destroy(q1, q2)
end
do
evo.spawn({ [f1] = 1 })
evo.spawn({ [f2] = 2 })
evo.spawn({ [f1] = 1, [f2] = 2 })
end
evo.collect_garbage()
end
do
evo.collect_garbage()
local f1 = evo.builder():name('f1'):realloc(double_realloc):compmove(double_compmove):build()
local f2 = evo.builder():name('f2'):realloc(double_realloc):compmove(double_compmove):build()
local q1 = evo.builder():include(f1):build()
local q2 = evo.builder():include(f2):build()
do
local es, ec = evo.multi_spawn(40, { [f1] = 1, [f2] = 2 })
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 1)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_destroy(q2)
end
do
local es, ec = evo.multi_spawn(50, { [f1] = 1 })
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 1)
assert(not evo.has(es[i], f2))
end
evo.batch_set(q1, f2, 2)
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 1)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_destroy(q1, q2)
end
do
evo.spawn({ [f1] = 1 })
evo.spawn({ [f2] = 2 })
evo.spawn({ [f1] = 1, [f2] = 2 })
end
evo.collect_garbage()
end
do
evo.collect_garbage()
local alloc_call_count = 0
local free_call_count = 0
local resize_call_count = 0
local function ctor_realloc()
---@type evolved.realloc
return function(src, src_size, dst_size)
if dst_size == 0 then
assert(src and src_size > 0)
free_call_count = free_call_count + 1
return
else
if src then
assert(src_size > 0)
resize_call_count = resize_call_count + 1
else
assert(src_size == 0)
alloc_call_count = alloc_call_count + 1
end
local dst = {}
if src then
for i = 1, math.min(src_size, dst_size) do
dst[i] = src[i]
end
end
return dst
end
end
end
do
local realloc1 = ctor_realloc()
local realloc2 = ctor_realloc()
local f1 = evo.builder():default(44):realloc(realloc1):build()
alloc_call_count, free_call_count, resize_call_count = 0, 0, 0
do
local e1 = evo.builder():set(f1, 21):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 21)
assert(alloc_call_count == 1 and free_call_count == 0)
local e2 = evo.builder():set(f1, 42):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 21)
assert(evo.has(e2, f1) and evo.get(e2, f1) == 42)
assert(alloc_call_count == 1 and free_call_count == 0)
evo.collect_garbage()
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.destroy(e1)
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.collect_garbage()
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.destroy(e2)
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.collect_garbage()
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
end
alloc_call_count, free_call_count, resize_call_count = 0, 0, 0
do
local es, ec = evo.multi_spawn(10, { [f1] = 84 })
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
for i = 1, ec / 2 do evo.destroy(es[i]) end
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.collect_garbage()
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 1)
evo.set(f1, evo.REALLOC, realloc2)
assert(alloc_call_count == 2 and free_call_count == 1 and resize_call_count == 1)
for i = 1, ec do evo.destroy(es[i]) end
evo.collect_garbage()
assert(alloc_call_count == 2 and free_call_count == 2 and resize_call_count == 1)
end
alloc_call_count, free_call_count, resize_call_count = 0, 0, 0
do
local e1 = evo.builder():set(f1, 24):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 24)
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.set(f1, evo.TAG)
assert(evo.has(e1, f1) and evo.get(e1, f1) == nil)
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
local es, ec = evo.multi_spawn(20, { [f1] = 48 })
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil) end
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
evo.remove(f1, evo.TAG)
assert(evo.has(e1, f1) and evo.get(e1, f1) == 44)
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 44) end
assert(alloc_call_count == 2 and free_call_count == 1 and resize_call_count == 0)
evo.destroy(e1)
for i = 1, ec do evo.destroy(es[i]) end
assert(alloc_call_count == 2 and free_call_count == 1 and resize_call_count == 0)
evo.collect_garbage()
assert(alloc_call_count == 2 and free_call_count == 2 and resize_call_count == 0)
end
alloc_call_count, free_call_count, resize_call_count = 0, 0, 0
do
local e1 = evo.builder():set(f1, 100):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 100)
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.set(f1, evo.TAG)
assert(evo.has(e1, f1) and evo.get(e1, f1) == nil)
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
local es, ec = evo.multi_spawn(20, { [f1] = 48 })
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil) end
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
evo.destroy(e1)
for i = 1, ec do evo.destroy(es[i]) end
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
evo.collect_garbage()
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
end
end
do
local realloc = ctor_realloc()
local f1 = evo.builder():realloc(realloc):build()
alloc_call_count, free_call_count, resize_call_count = 0, 0, 0
do
local e1 = evo.builder():set(f1, 42):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 42)
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.destroy(e1)
assert(not evo.has(e1, f1) and evo.get(e1, f1) == nil)
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.set(f1, evo.TAG)
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
end
end
end

View File

@@ -1,7 +1,5 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES)

View File

@@ -1,7 +1,5 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
do
local e = evo.spawn()

View File

@@ -1,7 +1,5 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local f1, f2, f3 = evo.id(3)

View File

@@ -31,64 +31,14 @@
end
interface Builder
build: function(self: Builder,
prefab?: Entity,
component_mapper?: function(Chunk, integer)): Entity
build: function(self: Builder, prefab?: Entity): Entity
multi_build: function(self: Builder, entity_count: integer, prefab?: Entity): { Entity }, integer
multi_build: function(self: Builder,
entity_count: integer,
prefab?: Entity,
component_mapper?: function(Chunk, integer, integer)): { Entity }, integer
spawn: function(self: Builder): Entity
multi_spawn: function(self: Builder, entity_count: integer): { Entity }, integer
multi_build_nr: function(self: Builder,
entity_count: integer,
prefab?: Entity,
component_mapper?: function(Chunk, integer, integer))
multi_build_to: function(self: Builder,
out_entity_list: { Entity },
out_entity_first: integer,
entity_count: integer,
prefab?: Entity,
component_mapper?: function(Chunk, integer, integer))
spawn: function(self: Builder,
component_mapper?: function(Chunk, integer)): Entity
multi_spawn: function(self: Builder,
entity_count: integer,
component_mapper?: function(Chunk, integer, integer)): { Entity }, integer
multi_spawn_nr: function(self: Builder,
entity_count: integer,
component_mapper?: function(Chunk, integer, integer))
multi_spawn_to: function(self: Builder,
out_entity_list: { Entity },
out_entity_first: integer,
entity_count: integer,
component_mapper?: function(Chunk, integer, integer))
clone: function(self: Builder,
prefab: Entity,
component_mapper?: function(Chunk, integer)): Entity
multi_clone: function(self: Builder,
entity_count: integer,
prefab: Entity,
component_mapper?: function(Chunk, integer, integer)): { Entity }, integer
multi_clone_nr: function(self: Builder,
entity_count: integer,
prefab: Entity,
component_mapper?: function(Chunk, integer, integer))
multi_clone_to: function(self: Builder,
out_entity_list: { Entity },
out_entity_first: integer,
entity_count: integer,
prefab: Entity,
component_mapper?: function(Chunk, integer, 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
@@ -114,15 +64,11 @@
default: function<Component>(self: Builder, default: Component): Builder
duplicate: function<Component>(self: Builder, duplicate: function(Component): Component): Builder
realloc: function<Component>(self: Builder, realloc: function({ Component } | nil, integer, integer): { Component } | nil): Builder
compmove: function<Component>(self: Builder, compmove: function({ Component }, integer, integer, integer, { Component })): Builder
prefab: function(self: Builder): Builder
disabled: function(self: Builder): Builder
include: function(self: Builder, ...: Fragment): Builder
exclude: function(self: Builder, ...: Fragment): Builder
variant: 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
@@ -133,10 +79,10 @@
group: function(self: Builder, group: System): Builder
query: function(self: Builder, query: Query): Builder
execute: function(self: Builder, execute: function(Chunk, {Entity}, integer, ...: any)): Builder
execute: function(self: Builder, execute: function(Chunk, {Entity}, integer)): Builder
prologue: function(self: Builder, prologue: function(...: any)): Builder
epilogue: function(self: Builder, epilogue: function(...: any)): 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
@@ -151,15 +97,11 @@
DEFAULT: Fragment
DUPLICATE: Fragment
REALLOC: Fragment
COMPMOVE: Fragment
PREFAB: Fragment
DISABLED: Fragment
INCLUDES: Fragment
EXCLUDES: Fragment
VARIANTS: Fragment
REQUIRES: Fragment
ON_SET: Fragment
@@ -189,51 +131,11 @@
commit: function(): boolean
cancel: function(): boolean
spawn: function(
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer)): Entity
spawn: function(components?: { Fragment: any }): Entity
multi_spawn: function(entity_count: integer, components?: { Fragment: any }): { Entity }, integer
multi_spawn: function(
entity_count: integer,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer, integer)): { Entity }, integer
multi_spawn_nr: function(
entity_count: integer,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer, integer))
multi_spawn_to: function(
out_entity_list: { Entity },
out_entity_first: integer,
entity_count: integer,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer, integer))
clone: function(
prefab: Entity,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer)): Entity
multi_clone: function(
entity_count: integer,
prefab: Entity,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer, integer)): { Entity }, integer
multi_clone_nr: function(
entity_count: integer,
prefab: Entity,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer, integer))
multi_clone_to: function(
out_entity_list: { Entity },
out_entity_first: integer,
entity_count: integer,
prefab: Entity,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer, 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
@@ -268,15 +170,10 @@
locate: function(entity: Entity): Chunk | nil, integer
lookup: function(name: string): Entity | nil
multi_lookup: function(name: string): { Entity }, integer
multi_lookup_to: function(out_entity_list: { Entity }, out_entity_first: integer, name: string): integer
process: function(...: System)
process_with: function(system: System, ...: any)
debug_mode: function(yesno: boolean)
collect_garbage: function(no_shrink?: boolean)
collect_garbage: function()
chunk: function(fragment: Fragment, ...: Fragment): Chunk, { Entity }, integer
builder: function(): Builder

File diff suppressed because it is too large Load Diff

View File

@@ -12,6 +12,10 @@ local STAGES = {
:build(),
}
local UNIFORMS = {
DELTA_TIME = 1.0 / 60.0,
}
local FRAGMENTS = {
POSITION_X = evolved.builder()
:name('FRAGMENTS.POSITION_X')
@@ -52,28 +56,25 @@ evolved.builder()
:name('SYSTEMS.STARTUP')
:group(STAGES.ON_SETUP)
:prologue(function()
evolved.multi_clone_nr(500, PREFABS.CIRCLE, nil, function(chunk, b_place, e_place)
local screen_width, screen_height = love.graphics.getDimensions()
local screen_width, screen_height = love.graphics.getDimensions()
---@type number[], number[]
local position_xs, position_ys = chunk:components(
FRAGMENTS.POSITION_X, FRAGMENTS.POSITION_Y)
local circle_list, circle_count = evolved.multi_clone(100, PREFABS.CIRCLE)
---@type number[], number[]
local velocity_xs, velocity_ys = chunk:components(
FRAGMENTS.VELOCITY_X, FRAGMENTS.VELOCITY_Y)
for i = 1, circle_count do
local circle = circle_list[i]
for i = b_place, e_place do
local px = math.random() * screen_width
local py = math.random() * screen_height
local px = math.random() * screen_width
local py = math.random() * screen_height
local vx = math.random(-100, 100)
local vy = math.random(-100, 100)
local vx = math.random(-100, 100)
local vy = math.random(-100, 100)
position_xs[i], position_ys[i] = px, py
velocity_xs[i], velocity_ys[i] = vx, vy
end
end)
evolved.set(circle, FRAGMENTS.POSITION_X, px)
evolved.set(circle, FRAGMENTS.POSITION_Y, py)
evolved.set(circle, FRAGMENTS.VELOCITY_X, vx)
evolved.set(circle, FRAGMENTS.VELOCITY_Y, vy)
end
end):build()
evolved.builder()
@@ -81,7 +82,8 @@ evolved.builder()
:group(STAGES.ON_UPDATE)
:include(FRAGMENTS.POSITION_X, FRAGMENTS.POSITION_Y)
:include(FRAGMENTS.VELOCITY_X, FRAGMENTS.VELOCITY_Y)
:execute(function(chunk, _, entity_count, delta_time)
:execute(function(chunk, _, entity_count)
local delta_time = UNIFORMS.DELTA_TIME
local screen_width, screen_height = love.graphics.getDimensions()
---@type number[], number[]
@@ -127,7 +129,7 @@ evolved.builder()
for i = 1, entity_count do
local x, y = position_xs[i], position_ys[i]
love.graphics.circle('fill', x, y, 5)
love.graphics.circle('fill', x, y, 10)
end
end):build()
@@ -154,7 +156,8 @@ end
---@type love.update
function love.update(dt)
evolved.process_with(STAGES.ON_UPDATE, dt)
UNIFORMS.DELTA_TIME = dt
evolved.process(STAGES.ON_UPDATE)
end
---@type love.draw

View File

@@ -1,34 +0,0 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.7.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.7.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",
}
}

View File

@@ -1,34 +0,0 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.8.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.8.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",
}
}

View File

@@ -1,34 +0,0 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.9.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.9.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",
}
}