mirror of
https://github.com/BlackMATov/evolved.lua.git
synced 2026-03-22 04:44:06 +07:00
Compare commits
55 Commits
v1.6.0
...
e364aaab37
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e364aaab37 | ||
|
|
b941baf6bb | ||
|
|
8b77b45421 | ||
|
|
f9943c9fca | ||
|
|
eb853c8392 | ||
|
|
b38594fdfc | ||
|
|
655c0aef07 | ||
|
|
2c4cb179bc | ||
|
|
e49a339f5e | ||
|
|
340feacf55 | ||
|
|
caa8cc5625 | ||
|
|
cd1a583682 | ||
|
|
5efd9ab2ae | ||
|
|
b7419eec5d | ||
|
|
287f03ef87 | ||
|
|
260f841a3b | ||
|
|
d1105c15ad | ||
|
|
a1440f26df | ||
|
|
7ce5ee924c | ||
|
|
539a62c8a8 | ||
|
|
63a7ab5c79 | ||
|
|
9a9fb1ddb9 | ||
|
|
7b44740803 | ||
|
|
b0d035c0d4 | ||
|
|
8d88d55267 | ||
|
|
b774abf63c | ||
|
|
4a018f4c40 | ||
|
|
39c20f13dd | ||
|
|
ce864b7433 | ||
|
|
04c9e4aaeb | ||
|
|
e9824a4776 | ||
|
|
c3760c40bf | ||
|
|
a2a4fc56e3 | ||
|
|
21d5091d14 | ||
|
|
18ee0d9a12 | ||
|
|
12c86ca679 | ||
|
|
a0f252f47c | ||
|
|
b17118544d | ||
|
|
b9cdbe961b | ||
|
|
4f78c8245c | ||
|
|
a7e5652ad4 | ||
|
|
c52f708184 | ||
|
|
e75ddef396 | ||
|
|
c9bfb26748 | ||
|
|
3a3abbd2fd | ||
|
|
d9c9b4cf85 | ||
|
|
20c94a0b72 | ||
|
|
e396c320ee | ||
|
|
52c898f912 | ||
|
|
a5319351c1 | ||
|
|
c9f4a74518 | ||
|
|
c29092c3e1 | ||
|
|
a0a4a20c35 | ||
|
|
2f8b0b0ef3 | ||
|
|
5e0170b4e8 |
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (C) 2024-2025, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
Copyright (C) 2024-2026, 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
614
README.md
@@ -35,6 +35,7 @@
|
||||
- [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)
|
||||
@@ -43,6 +44,7 @@
|
||||
- [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)
|
||||
@@ -51,7 +53,10 @@
|
||||
- [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)
|
||||
@@ -60,6 +65,10 @@
|
||||
- [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)
|
||||
@@ -416,17 +425,19 @@ You should try to avoid structural changes, especially in performance-critical c
|
||||
#### Spawning Entities
|
||||
|
||||
```lua
|
||||
---@param components? table<evolved.fragment, evolved.component>
|
||||
---@param component_table? table<evolved.fragment, evolved.component>
|
||||
---@param component_mapper? fun(chunk: evolved.chunk, place: integer)
|
||||
---@return evolved.entity
|
||||
function evolved.spawn(components) end
|
||||
function evolved.spawn(component_table, component_mapper) end
|
||||
|
||||
---@param prefab evolved.entity
|
||||
---@param components? table<evolved.fragment, evolved.component>
|
||||
---@param component_table? table<evolved.fragment, evolved.component>
|
||||
---@param component_mapper? fun(chunk: evolved.chunk, place: integer)
|
||||
---@return evolved.entity
|
||||
function evolved.clone(prefab, components) end
|
||||
function evolved.clone(prefab, component_table, component_mapper) 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 `components` 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 `component_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.
|
||||
|
||||
@@ -470,6 +481,54 @@ 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:
|
||||
@@ -586,16 +645,22 @@ 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) and [`evolved.EXCLUDES`](#evolvedexcludes). These fragments expect a list of fragments as their components.
|
||||
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.
|
||||
|
||||
```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:
|
||||
@@ -604,10 +669,11 @@ 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 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.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
@@ -786,7 +852,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` 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.
|
||||
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.
|
||||
|
||||
```lua
|
||||
local evolved = require 'evolved'
|
||||
@@ -880,6 +946,43 @@ 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
|
||||
@@ -1060,6 +1163,41 @@ 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.
|
||||
@@ -1107,6 +1245,163 @@ 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
|
||||
@@ -1122,12 +1417,18 @@ system :: id
|
||||
component :: any
|
||||
storage :: component[]
|
||||
|
||||
component_table :: <fragment, component>
|
||||
component_mapper :: {chunk, integer, integer}
|
||||
|
||||
default :: component
|
||||
duplicate :: {component -> component}
|
||||
|
||||
execute :: {chunk, entity[], integer}
|
||||
prologue :: {}
|
||||
epilogue :: {}
|
||||
realloc :: {storage?, integer, integer -> storage?}
|
||||
compmove :: {storage, integer, integer, integer, storage}
|
||||
|
||||
execute :: {chunk, entity[], integer, any...}
|
||||
prologue :: {any...}
|
||||
epilogue :: {any...}
|
||||
|
||||
set_hook :: {entity, fragment, component, component}
|
||||
assign_hook :: {entity, fragment, component, component}
|
||||
@@ -1154,11 +1455,15 @@ 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
|
||||
@@ -1193,11 +1498,15 @@ depth :: integer
|
||||
commit :: boolean
|
||||
cancel :: boolean
|
||||
|
||||
spawn :: <fragment, component>? -> entity
|
||||
multi_spawn :: integer, <fragment, component>? -> entity[], integer
|
||||
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? -> ()
|
||||
|
||||
clone :: entity, <fragment, component>? -> entity
|
||||
multi_clone :: integer, entity, <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? -> ()
|
||||
|
||||
alive :: entity -> boolean
|
||||
alive_all :: entity... -> boolean
|
||||
@@ -1211,7 +1520,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... -> ()
|
||||
@@ -1228,10 +1537,15 @@ 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 :: ()
|
||||
collect_garbage :: boolean? -> ()
|
||||
```
|
||||
|
||||
### Classes
|
||||
@@ -1258,14 +1572,20 @@ chunk_mt:components :: fragment... -> storage...
|
||||
```
|
||||
builder :: builder
|
||||
|
||||
builder_mt:build :: entity? -> entity
|
||||
builder_mt:multi_build :: integer, entity? -> entity[], integer
|
||||
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:spawn :: entity
|
||||
builder_mt:multi_spawn :: integer -> 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:clone :: entity -> entity
|
||||
builder_mt:multi_clone :: integer, entity -> 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:has :: fragment -> boolean
|
||||
builder_mt:has_all :: fragment... -> boolean
|
||||
@@ -1287,11 +1607,15 @@ 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
|
||||
@@ -1302,16 +1626,36 @@ builder_mt:on_remove :: {entity, fragment} -> builder
|
||||
builder_mt:group :: system -> builder
|
||||
|
||||
builder_mt:query :: query -> builder
|
||||
builder_mt:execute :: {chunk, entity[], integer} -> builder
|
||||
builder_mt:execute :: {chunk, entity[], integer, any...} -> builder
|
||||
|
||||
builder_mt:prologue :: {} -> builder
|
||||
builder_mt:epilogue :: {} -> builder
|
||||
builder_mt:prologue :: {any...} -> builder
|
||||
builder_mt:epilogue :: {any...} -> 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
|
||||
@@ -1376,6 +1720,10 @@ builder_mt:destruction_policy :: id -> builder
|
||||
|
||||
### `evolved.DUPLICATE`
|
||||
|
||||
### `evolved.REALLOC`
|
||||
|
||||
### `evolved.COMPMOVE`
|
||||
|
||||
### `evolved.PREFAB`
|
||||
|
||||
### `evolved.DISABLED`
|
||||
@@ -1384,6 +1732,8 @@ builder_mt:destruction_policy :: id -> builder
|
||||
|
||||
### `evolved.EXCLUDES`
|
||||
|
||||
### `evolved.VARIANTS`
|
||||
|
||||
### `evolved.REQUIRES`
|
||||
|
||||
### `evolved.ON_SET`
|
||||
@@ -1482,28 +1832,53 @@ function evolved.cancel() end
|
||||
### `evolved.spawn`
|
||||
|
||||
```lua
|
||||
---@param components? table<evolved.fragment, evolved.component>
|
||||
---@param component_table? evolved.component_table
|
||||
---@param component_mapper? evolved.component_mapper
|
||||
---@return evolved.entity entity
|
||||
function evolved.spawn(components) end
|
||||
function evolved.spawn(component_table, component_mapper) end
|
||||
```
|
||||
|
||||
### `evolved.multi_spawn`
|
||||
|
||||
```lua
|
||||
---@param entity_count integer
|
||||
---@param components? table<evolved.fragment, evolved.component>
|
||||
---@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, components) end
|
||||
---@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
|
||||
```
|
||||
|
||||
### `evolved.clone`
|
||||
|
||||
```lua
|
||||
---@param prefab evolved.entity
|
||||
---@param components? table<evolved.fragment, evolved.component>
|
||||
---@param component_table? evolved.component_table
|
||||
---@param component_mapper? evolved.component_mapper
|
||||
---@return evolved.entity entity
|
||||
function evolved.clone(prefab, components) end
|
||||
function evolved.clone(prefab, component_table, component_mapper) end
|
||||
```
|
||||
|
||||
### `evolved.multi_clone`
|
||||
@@ -1511,10 +1886,35 @@ function evolved.clone(prefab, components) end
|
||||
```lua
|
||||
---@param entity_count integer
|
||||
---@param prefab evolved.entity
|
||||
---@param components? table<evolved.fragment, evolved.component>
|
||||
---@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, components) end
|
||||
---@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
|
||||
```
|
||||
|
||||
### `evolved.alive`
|
||||
@@ -1703,6 +2103,35 @@ 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
|
||||
@@ -1710,6 +2139,14 @@ function evolved.locate(entity) 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
|
||||
@@ -1720,7 +2157,8 @@ function evolved.debug_mode(yesno) end
|
||||
### `evolved.collect_garbage`
|
||||
|
||||
```lua
|
||||
function evolved.collect_garbage() end
|
||||
---@param no_shrink? boolean
|
||||
function evolved.collect_garbage(no_shrink) end
|
||||
```
|
||||
|
||||
## Classes
|
||||
@@ -1823,8 +2261,9 @@ 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) end
|
||||
function evolved.builder_mt:build(prefab, component_mapper) end
|
||||
```
|
||||
|
||||
### `evolved.builder_mt:multi_build`
|
||||
@@ -1832,33 +2271,79 @@ function evolved.builder_mt:build(prefab) 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
|
||||
function evolved.builder_mt:multi_build(entity_count, prefab) end
|
||||
---@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
|
||||
```
|
||||
|
||||
#### `evolved.builder_mt:spawn`
|
||||
|
||||
```lua
|
||||
---@param component_mapper? evolved.component_mapper
|
||||
---@return evolved.entity entity
|
||||
function evolved.builder_mt:spawn() end
|
||||
function evolved.builder_mt:spawn(component_mapper) 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
|
||||
function evolved.builder_mt:multi_spawn(entity_count) end
|
||||
---@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
|
||||
```
|
||||
|
||||
#### `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) end
|
||||
function evolved.builder_mt:clone(prefab, component_mapper) end
|
||||
```
|
||||
|
||||
#### `evolved.builder_mt:multi_clone`
|
||||
@@ -1866,9 +2351,32 @@ function evolved.builder_mt:clone(prefab) 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
|
||||
function evolved.builder_mt:multi_clone(entity_count, prefab) end
|
||||
---@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
|
||||
```
|
||||
|
||||
#### `evolved.builder_mt:has`
|
||||
@@ -1983,6 +2491,22 @@ 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
|
||||
@@ -2013,6 +2537,14 @@ 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
|
||||
|
||||
@@ -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 are cannot be handled properly right now
|
||||
- Errors in hooks or rellocs/compmoves/mappers are cannot be handled properly right now
|
||||
|
||||
@@ -4,15 +4,20 @@ 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'
|
||||
@@ -34,3 +39,5 @@ print '----------------------------------------'
|
||||
basics.describe_fuzz 'develop.fuzzing.requires_fuzz'
|
||||
print '----------------------------------------'
|
||||
basics.describe_fuzz 'develop.fuzzing.unique_fuzz'
|
||||
|
||||
print 'All tests passed.'
|
||||
|
||||
@@ -307,11 +307,11 @@ print '----------------------------------------'
|
||||
basics.describe_bench(
|
||||
string.format('Clone Benchmarks: Multi Clone | %d entities with 1 component', N),
|
||||
function()
|
||||
local multi_clone = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [F1] = true }
|
||||
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [F1] = true }
|
||||
|
||||
evo.defer()
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [D1] = true }
|
||||
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
|
||||
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
|
||||
|
||||
evo.defer()
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true }
|
||||
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
|
||||
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
|
||||
|
||||
evo.defer()
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
|
||||
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [RF1] = true }
|
||||
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [RF1] = true }
|
||||
|
||||
evo.defer()
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [RD1] = true }
|
||||
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [RF123] = true }
|
||||
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [RF123] = true }
|
||||
|
||||
evo.defer()
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [RD123] = true }
|
||||
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [RF12345] = true }
|
||||
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [RF12345] = true }
|
||||
|
||||
evo.defer()
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(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 = evo.multi_clone
|
||||
local multi_clone_nr = evo.multi_clone_nr
|
||||
|
||||
local prefab = evo.spawn { [RD12345] = true }
|
||||
|
||||
multi_clone(N, prefab)
|
||||
multi_clone_nr(N, prefab)
|
||||
|
||||
evo.batch_destroy(QD1)
|
||||
end)
|
||||
|
||||
@@ -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(N, prefab_a)
|
||||
evo.multi_clone_nr(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(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.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.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(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0, [d] = 0, [e] = 0 })
|
||||
evo.multi_spawn_nr(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(N, { [world] = true, [chars[i]] = i, [data] = i })
|
||||
evo.multi_spawn_nr(N, { [world] = true, [chars[i]] = i, [data] = i })
|
||||
end
|
||||
|
||||
evo.builder()
|
||||
|
||||
56
develop/benchmarks/destroy_bmarks.lua
Normal file
56
develop/benchmarks/destroy_bmarks.lua
Normal file
@@ -0,0 +1,56 @@
|
||||
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)
|
||||
@@ -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(N, {
|
||||
evo.multi_spawn_nr(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(N, {
|
||||
evo.multi_spawn_nr(N, {
|
||||
[wf] = true,
|
||||
[pxf] = 0,
|
||||
[pyf] = 0,
|
||||
|
||||
@@ -536,11 +536,11 @@ print '----------------------------------------'
|
||||
basics.describe_bench(
|
||||
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 component', N),
|
||||
function()
|
||||
local multi_spawn = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [F1] = true }
|
||||
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [F1] = true }
|
||||
|
||||
evo.defer()
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [D1] = true }
|
||||
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [F1] = true, [F2] = true, [F3] = true }
|
||||
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [F1] = true, [F2] = true, [F3] = true }
|
||||
|
||||
evo.defer()
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [D1] = true, [D2] = true, [D3] = true }
|
||||
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
|
||||
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
|
||||
|
||||
evo.defer()
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
|
||||
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [F1] = true }
|
||||
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [F1] = true }
|
||||
|
||||
evo.defer()
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [D1] = true }
|
||||
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [RF123] = true }
|
||||
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [RF123] = true }
|
||||
|
||||
evo.defer()
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [RD123] = true }
|
||||
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [RF12345] = true }
|
||||
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [RF12345] = true }
|
||||
|
||||
evo.defer()
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(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 = evo.multi_spawn
|
||||
local multi_spawn_nr = evo.multi_spawn_nr
|
||||
|
||||
local components = { [RD12345] = true }
|
||||
|
||||
multi_spawn(N, components)
|
||||
multi_spawn_nr(N, components)
|
||||
|
||||
evo.batch_destroy(QD1)
|
||||
end)
|
||||
|
||||
@@ -118,11 +118,11 @@ end
|
||||
---
|
||||
|
||||
if math.random(1, 2) == 1 then
|
||||
evo.collect_garbage()
|
||||
evo.collect_garbage(math.random(1, 2) == 1)
|
||||
end
|
||||
|
||||
evo.destroy(__table_unpack(all_entity_list))
|
||||
|
||||
if math.random(1, 2) == 1 then
|
||||
evo.collect_garbage()
|
||||
evo.collect_garbage(math.random(1, 2) == 1)
|
||||
end
|
||||
|
||||
@@ -124,11 +124,11 @@ end
|
||||
---
|
||||
|
||||
if math.random(1, 2) == 1 then
|
||||
evo.collect_garbage()
|
||||
evo.collect_garbage(math.random(1, 2) == 1)
|
||||
end
|
||||
|
||||
evo.destroy(__table_unpack(all_entity_list))
|
||||
|
||||
if math.random(1, 2) == 1 then
|
||||
evo.collect_garbage()
|
||||
evo.collect_garbage(math.random(1, 2) == 1)
|
||||
end
|
||||
|
||||
@@ -56,6 +56,20 @@ 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
|
||||
@@ -63,6 +77,10 @@ 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
|
||||
@@ -173,12 +191,22 @@ 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
|
||||
@@ -189,19 +217,29 @@ local function execute_query(query)
|
||||
query_entity_set[entity] = true
|
||||
end
|
||||
|
||||
assert(chunk:has_all(__table_unpack(query_include_list)))
|
||||
assert(not chunk:has_any(__table_unpack(query_exclude_list)))
|
||||
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
|
||||
end
|
||||
|
||||
for i = 1, all_entity_count do
|
||||
local entity = all_entity_list[i]
|
||||
|
||||
local is_entity_matched =
|
||||
evo.has_all(entity, __table_unpack(query_include_list))
|
||||
and not evo.has_any(entity, __table_unpack(query_exclude_list))
|
||||
(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)))
|
||||
|
||||
for fragment in evo.each(entity) do
|
||||
if evo.has(fragment, evo.EXPLICIT) and not query_include_set[fragment] then
|
||||
if evo.has(fragment, evo.EXPLICIT) and not query_variant_set[fragment] and not query_include_set[fragment] then
|
||||
is_entity_matched = false
|
||||
end
|
||||
end
|
||||
@@ -236,10 +274,13 @@ for _ = 1, math.random(1, 5) do
|
||||
if math.random(1, 2) == 1 then
|
||||
generate_query(query)
|
||||
else
|
||||
if math.random(1, 2) == 1 then
|
||||
local r = math.random(1, 3)
|
||||
if r == 1 then
|
||||
evo.remove(query, evo.INCLUDES)
|
||||
else
|
||||
elseif r == 2 then
|
||||
evo.remove(query, evo.EXCLUDES)
|
||||
else
|
||||
evo.remove(query, evo.VARIANTS)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -255,7 +296,7 @@ end
|
||||
---
|
||||
|
||||
if math.random(1, 2) == 1 then
|
||||
evo.collect_garbage()
|
||||
evo.collect_garbage(math.random(1, 2) == 1)
|
||||
end
|
||||
|
||||
evo.destroy(__table_unpack(all_query_list))
|
||||
@@ -263,5 +304,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()
|
||||
evo.collect_garbage(math.random(1, 2) == 1)
|
||||
end
|
||||
|
||||
@@ -78,11 +78,11 @@ end
|
||||
---
|
||||
|
||||
if math.random(1, 2) == 1 then
|
||||
evo.collect_garbage()
|
||||
evo.collect_garbage(math.random(1, 2) == 1)
|
||||
end
|
||||
|
||||
evo.destroy(__table_unpack(all_entity_list))
|
||||
|
||||
if math.random(1, 2) == 1 then
|
||||
evo.collect_garbage()
|
||||
evo.collect_garbage(math.random(1, 2) == 1)
|
||||
end
|
||||
|
||||
@@ -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()
|
||||
evo.collect_garbage(math.random(1, 2) == 1)
|
||||
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()
|
||||
evo.collect_garbage(math.random(1, 2) == 1)
|
||||
end
|
||||
evo.destroy(__table_unpack(all_entity_list))
|
||||
end
|
||||
|
||||
if math.random(1, 2) == 1 then
|
||||
evo.collect_garbage()
|
||||
evo.collect_garbage(math.random(1, 2) == 1)
|
||||
end
|
||||
|
||||
@@ -64,11 +64,11 @@ end
|
||||
---
|
||||
|
||||
if math.random(1, 2) == 1 then
|
||||
evo.collect_garbage()
|
||||
evo.collect_garbage(math.random(1, 2) == 1)
|
||||
end
|
||||
|
||||
evo.destroy(__table_unpack(all_entity_list))
|
||||
|
||||
if math.random(1, 2) == 1 then
|
||||
evo.collect_garbage()
|
||||
evo.collect_garbage(math.random(1, 2) == 1)
|
||||
end
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
local evo = require 'evolved'
|
||||
|
||||
evo.debug_mode(true)
|
||||
|
||||
do
|
||||
local f1, f2 = evo.id(2)
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
local evo = require 'evolved'
|
||||
|
||||
evo.debug_mode(true)
|
||||
|
||||
do
|
||||
assert(evo.defer())
|
||||
assert(evo.cancel())
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
local evo = require 'evolved'
|
||||
|
||||
evo.debug_mode(true)
|
||||
|
||||
do
|
||||
do
|
||||
local p = evo.spawn()
|
||||
@@ -395,3 +397,165 @@ 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
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
local evo = require 'evolved'
|
||||
|
||||
evo.debug_mode(true)
|
||||
|
||||
do
|
||||
assert(evo.depth() == 0)
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
local evo = require 'evolved'
|
||||
|
||||
evo.debug_mode(true)
|
||||
|
||||
do
|
||||
local e = evo.id()
|
||||
assert(evo.alive(e))
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
local evo = require 'evolved'
|
||||
|
||||
evo.debug_mode(true)
|
||||
|
||||
do
|
||||
local e1, e2, f1, f2 = evo.id(4)
|
||||
|
||||
|
||||
195
develop/testing/lookup_tests.lua
Normal file
195
develop/testing/lookup_tests.lua
Normal file
@@ -0,0 +1,195 @@
|
||||
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
|
||||
@@ -2302,27 +2302,66 @@ do
|
||||
evo.set(e2, f2, 44)
|
||||
|
||||
do
|
||||
local iter, state = evo.execute(q)
|
||||
local chunk = iter(state)
|
||||
assert(chunk and chunk ~= evo.chunk(f1))
|
||||
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)
|
||||
end
|
||||
|
||||
evo.set(q, evo.EXCLUDES, { f2 })
|
||||
|
||||
do
|
||||
local iter, state = evo.execute(q)
|
||||
local chunk = iter(state)
|
||||
assert(chunk and chunk ~= evo.chunk(f1))
|
||||
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)
|
||||
end
|
||||
|
||||
evo.set(q, evo.INCLUDES, { f1 })
|
||||
|
||||
do
|
||||
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)
|
||||
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)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
244
develop/testing/mappers_tests.lua
Normal file
244
develop/testing/mappers_tests.lua
Normal file
@@ -0,0 +1,244 @@
|
||||
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
|
||||
@@ -1,5 +1,7 @@
|
||||
local evo = require 'evolved'
|
||||
|
||||
evo.debug_mode(true)
|
||||
|
||||
do
|
||||
local entity_list
|
||||
|
||||
@@ -605,3 +607,164 @@ 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
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
local evo = require 'evolved'
|
||||
|
||||
evo.debug_mode(true)
|
||||
|
||||
do
|
||||
local id = evo.id()
|
||||
|
||||
|
||||
109
develop/testing/process_with_tests.lua
Normal file
109
develop/testing/process_with_tests.lua
Normal file
@@ -0,0 +1,109 @@
|
||||
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
|
||||
596
develop/testing/realloc_tests.lua
Normal file
596
develop/testing/realloc_tests.lua
Normal file
@@ -0,0 +1,596 @@
|
||||
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
|
||||
@@ -1,5 +1,7 @@
|
||||
local evo = require 'evolved'
|
||||
|
||||
evo.debug_mode(true)
|
||||
|
||||
do
|
||||
local f1, f2 = evo.id(2)
|
||||
evo.set(f1, evo.REQUIRES)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
local evo = require 'evolved'
|
||||
|
||||
evo.debug_mode(true)
|
||||
|
||||
do
|
||||
do
|
||||
local e = evo.spawn()
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
local evo = require 'evolved'
|
||||
|
||||
evo.debug_mode(true)
|
||||
|
||||
do
|
||||
local f1, f2, f3 = evo.id(3)
|
||||
|
||||
|
||||
131
evolved.d.tl
131
evolved.d.tl
@@ -31,14 +31,64 @@
|
||||
end
|
||||
|
||||
interface Builder
|
||||
build: function(self: Builder, prefab?: Entity): Entity
|
||||
multi_build: function(self: Builder, entity_count: integer, prefab?: Entity): { Entity }, integer
|
||||
build: function(self: Builder,
|
||||
prefab?: Entity,
|
||||
component_mapper?: function(Chunk, integer)): Entity
|
||||
|
||||
spawn: function(self: Builder): Entity
|
||||
multi_spawn: function(self: Builder, entity_count: integer): { Entity }, integer
|
||||
multi_build: function(self: Builder,
|
||||
entity_count: integer,
|
||||
prefab?: Entity,
|
||||
component_mapper?: function(Chunk, integer, integer)): { Entity }, integer
|
||||
|
||||
clone: function(self: Builder, prefab: Entity): Entity
|
||||
multi_clone: function(self: Builder, entity_count: integer, prefab: Entity): { 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))
|
||||
|
||||
has: function(self: Builder, fragment: Fragment): boolean
|
||||
has_all: function(self: Builder, ...: Fragment): boolean
|
||||
@@ -64,11 +114,15 @@
|
||||
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
|
||||
@@ -79,10 +133,10 @@
|
||||
group: function(self: Builder, group: System): Builder
|
||||
|
||||
query: function(self: Builder, query: Query): Builder
|
||||
execute: function(self: Builder, execute: function(Chunk, {Entity}, integer)): Builder
|
||||
execute: function(self: Builder, execute: function(Chunk, {Entity}, integer, ...: any)): Builder
|
||||
|
||||
prologue: function(self: Builder, prologue: function()): Builder
|
||||
epilogue: function(self: Builder, epilogue: function()): Builder
|
||||
prologue: function(self: Builder, prologue: function(...: any)): Builder
|
||||
epilogue: function(self: Builder, epilogue: function(...: any)): Builder
|
||||
|
||||
destruction_policy: function(self: Builder, destruction_policy: Id): Builder
|
||||
end
|
||||
@@ -97,11 +151,15 @@
|
||||
DEFAULT: Fragment
|
||||
DUPLICATE: Fragment
|
||||
|
||||
REALLOC: Fragment
|
||||
COMPMOVE: Fragment
|
||||
|
||||
PREFAB: Fragment
|
||||
DISABLED: Fragment
|
||||
|
||||
INCLUDES: Fragment
|
||||
EXCLUDES: Fragment
|
||||
VARIANTS: Fragment
|
||||
REQUIRES: Fragment
|
||||
|
||||
ON_SET: Fragment
|
||||
@@ -131,11 +189,51 @@
|
||||
commit: function(): boolean
|
||||
cancel: function(): boolean
|
||||
|
||||
spawn: function(components?: { Fragment: any }): Entity
|
||||
multi_spawn: function(entity_count: integer, components?: { Fragment: any }): { Entity }, integer
|
||||
spawn: function(
|
||||
component_table?: { Fragment: any },
|
||||
component_mapper?: function(Chunk, integer)): Entity
|
||||
|
||||
clone: function(prefab: Entity, components?: { Fragment: any }): Entity
|
||||
multi_clone: function(entity_count: integer, prefab: Entity, 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))
|
||||
|
||||
alive: function(entity: Entity): boolean
|
||||
alive_all: function(...: Entity): boolean
|
||||
@@ -170,10 +268,15 @@
|
||||
|
||||
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()
|
||||
collect_garbage: function(no_shrink?: boolean)
|
||||
|
||||
chunk: function(fragment: Fragment, ...: Fragment): Chunk, { Entity }, integer
|
||||
builder: function(): Builder
|
||||
|
||||
3292
evolved.lua
3292
evolved.lua
File diff suppressed because it is too large
Load Diff
@@ -12,10 +12,6 @@ local STAGES = {
|
||||
:build(),
|
||||
}
|
||||
|
||||
local UNIFORMS = {
|
||||
DELTA_TIME = 1.0 / 60.0,
|
||||
}
|
||||
|
||||
local FRAGMENTS = {
|
||||
POSITION_X = evolved.builder()
|
||||
:name('FRAGMENTS.POSITION_X')
|
||||
@@ -56,25 +52,28 @@ evolved.builder()
|
||||
:name('SYSTEMS.STARTUP')
|
||||
:group(STAGES.ON_SETUP)
|
||||
:prologue(function()
|
||||
local screen_width, screen_height = love.graphics.getDimensions()
|
||||
evolved.multi_clone_nr(500, PREFABS.CIRCLE, nil, function(chunk, b_place, e_place)
|
||||
local screen_width, screen_height = love.graphics.getDimensions()
|
||||
|
||||
local circle_list, circle_count = evolved.multi_clone(100, PREFABS.CIRCLE)
|
||||
---@type number[], number[]
|
||||
local position_xs, position_ys = chunk:components(
|
||||
FRAGMENTS.POSITION_X, FRAGMENTS.POSITION_Y)
|
||||
|
||||
for i = 1, circle_count do
|
||||
local circle = circle_list[i]
|
||||
---@type number[], number[]
|
||||
local velocity_xs, velocity_ys = chunk:components(
|
||||
FRAGMENTS.VELOCITY_X, FRAGMENTS.VELOCITY_Y)
|
||||
|
||||
local px = math.random() * screen_width
|
||||
local py = math.random() * screen_height
|
||||
for i = b_place, e_place do
|
||||
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)
|
||||
|
||||
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
|
||||
position_xs[i], position_ys[i] = px, py
|
||||
velocity_xs[i], velocity_ys[i] = vx, vy
|
||||
end
|
||||
end)
|
||||
end):build()
|
||||
|
||||
evolved.builder()
|
||||
@@ -82,8 +81,7 @@ 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)
|
||||
local delta_time = UNIFORMS.DELTA_TIME
|
||||
:execute(function(chunk, _, entity_count, delta_time)
|
||||
local screen_width, screen_height = love.graphics.getDimensions()
|
||||
|
||||
---@type number[], number[]
|
||||
@@ -129,7 +127,7 @@ evolved.builder()
|
||||
|
||||
for i = 1, entity_count do
|
||||
local x, y = position_xs[i], position_ys[i]
|
||||
love.graphics.circle('fill', x, y, 10)
|
||||
love.graphics.circle('fill', x, y, 5)
|
||||
end
|
||||
end):build()
|
||||
|
||||
@@ -156,8 +154,7 @@ end
|
||||
|
||||
---@type love.update
|
||||
function love.update(dt)
|
||||
UNIFORMS.DELTA_TIME = dt
|
||||
evolved.process(STAGES.ON_UPDATE)
|
||||
evolved.process_with(STAGES.ON_UPDATE, dt)
|
||||
end
|
||||
|
||||
---@type love.draw
|
||||
|
||||
34
rockspecs/evolved.lua-1.7.0-0.rockspec
Normal file
34
rockspecs/evolved.lua-1.7.0-0.rockspec
Normal file
@@ -0,0 +1,34 @@
|
||||
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",
|
||||
}
|
||||
}
|
||||
34
rockspecs/evolved.lua-1.8.0-0.rockspec
Normal file
34
rockspecs/evolved.lua-1.8.0-0.rockspec
Normal file
@@ -0,0 +1,34 @@
|
||||
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",
|
||||
}
|
||||
}
|
||||
34
rockspecs/evolved.lua-1.9.0-0.rockspec
Normal file
34
rockspecs/evolved.lua-1.9.0-0.rockspec
Normal file
@@ -0,0 +1,34 @@
|
||||
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",
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user