4 Commits

Author SHA1 Message Date
BlackMATov
e9824a4776 v1.8.0 2026-01-18 20:24:53 +07:00
BlackMATov
c3760c40bf update README 2026-01-18 20:20:13 +07:00
BlackMATov
a2a4fc56e3 Merge branch 'feature/mappers' into dev 2026-01-18 19:30:08 +07:00
BlackMATov
21d5091d14 first mappers impl 2026-01-18 19:28:12 +07:00
8 changed files with 728 additions and 266 deletions

159
README.md
View File

@@ -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)
@@ -62,7 +63,7 @@
- [Chunk](#chunk)
- [Builder](#builder)
- [Changelog](#changelog)
- [vX.Y.Z](#vxyz)
- [v1.8.0](#v180)
- [v1.7.0](#v170)
- [v1.6.0](#v160)
- [v1.5.0](#v150)
@@ -420,17 +421,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.
@@ -474,6 +477,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:
@@ -1268,22 +1319,22 @@ local MOVEMENT_SYSTEM = evolved.builder()
--
--
do
local entity_list, entity_count = evolved.builder()
:set(POSITION_X)
:set(POSITION_Y)
:set(VELOCITY_X)
:set(VELOCITY_Y)
:multi_build(10000)
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 i = 1, entity_count do
local entity = entity_list[i]
evolved.set(entity, POSITION_X, math.random(0, 640))
evolved.set(entity, POSITION_Y, math.random(0, 480))
evolved.set(entity, VELOCITY_X, math.random(-100, 100))
evolved.set(entity, VELOCITY_Y, math.random(-100, 100))
end
end
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)
--
--
@@ -1309,6 +1360,9 @@ system :: id
component :: any
storage :: component[]
component_table :: <fragment, component>
component_mapper :: {chunk, integer, integer}
default :: component
duplicate :: {component -> component}
@@ -1387,11 +1441,11 @@ 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
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
alive :: entity -> boolean
alive_all :: entity... -> boolean
@@ -1405,7 +1459,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... -> ()
@@ -1453,14 +1507,14 @@ 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: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: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:has :: fragment -> boolean
builder_mt:has_all :: fragment... -> boolean
@@ -1511,9 +1565,10 @@ builder_mt:destruction_policy :: id -> builder
## Changelog
### vX.Y.Z
### 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
@@ -1696,28 +1751,31 @@ 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
function evolved.multi_spawn(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`
@@ -1725,10 +1783,11 @@ 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
function evolved.multi_clone(entity_count, prefab, component_table, component_mapper) end
```
### `evolved.alive`
@@ -2045,8 +2104,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`
@@ -2054,33 +2114,37 @@ 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
function evolved.builder_mt:multi_build(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
function evolved.builder_mt:multi_spawn(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`
@@ -2088,9 +2152,10 @@ 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
function evolved.builder_mt:multi_clone(entity_count, prefab, component_mapper) end
```
#### `evolved.builder_mt:has`

View File

@@ -15,7 +15,8 @@
- Having a light version of the gargabe collector can be useful for some use-cases
- We can shrink the table pool tables on garbage collection if they are too large
- Should we sort chunk children by fragment id?
- Basic default component value as true looks awful, should we use something else?
## Known Issues
- Errors in hooks or rellocs/compmoves are cannot be handled properly right now
- Errors in hooks or rellocs/compmoves/mappers are cannot be handled properly right now

View File

@@ -5,6 +5,7 @@ require 'develop.testing.depth_tests'
require 'develop.testing.destroy_tests'
require 'develop.testing.locate_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'

View File

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

View File

@@ -31,14 +31,30 @@
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
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
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
has: function(self: Builder, fragment: Fragment): boolean
has_all: function(self: Builder, ...: Fragment): boolean
@@ -139,11 +155,25 @@
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
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
alive: function(entity: Entity): boolean
alive_all: function(...: Entity): boolean

View File

@@ -1,7 +1,7 @@
local evolved = {
__HOMEPAGE = 'https://github.com/BlackMATov/evolved.lua',
__DESCRIPTION = 'Evolved ECS (Entity-Component-System) for Lua',
__VERSION = '1.7.0',
__VERSION = '1.8.0',
__LICENSE = [[
MIT License
@@ -37,6 +37,9 @@ local evolved = {
---@alias evolved.component any
---@alias evolved.storage evolved.component[]
---@alias evolved.component_table table<evolved.fragment, evolved.component>
---@alias evolved.component_mapper fun(chunk: evolved.chunk, b_place: integer, e_place: integer)
---@alias evolved.default evolved.component
---@alias evolved.duplicate fun(component: evolved.component): evolved.component
@@ -198,7 +201,7 @@ __chunk_mt.__index = __chunk_mt
---@class evolved.builder
---@field package __chunk? evolved.chunk
---@field package __components table<evolved.fragment, evolved.component>
---@field package __component_table evolved.component_table
local __builder_mt = {}
__builder_mt.__index = __builder_mt
@@ -682,13 +685,11 @@ local __table_pool_tag = {
system_list = 3,
each_state = 4,
execute_state = 5,
entity_set = 6,
entity_list = 7,
fragment_set = 8,
fragment_list = 9,
component_map = 10,
component_list = 11,
__count = 11,
entity_list = 6,
fragment_set = 7,
fragment_list = 8,
component_table = 9,
__count = 9,
}
---@class (exact) evolved.table_pool
@@ -1017,21 +1018,6 @@ local __safe_tbls = {
__newindex = function() __error_fmt 'attempt to modify empty fragment set' end
}) --[[@as table<evolved.fragment, integer>]],
__EMPTY_FRAGMENT_LIST = __lua_setmetatable({}, {
__tostring = function() return 'empty fragment list' end,
__newindex = function() __error_fmt 'attempt to modify empty fragment list' end
}) --[=[@as evolved.fragment[]]=],
__EMPTY_COMPONENT_MAP = __lua_setmetatable({}, {
__tostring = function() return 'empty component map' end,
__newindex = function() __error_fmt 'attempt to modify empty component map' end
}) --[[@as table<evolved.fragment, evolved.component>]],
__EMPTY_COMPONENT_LIST = __lua_setmetatable({}, {
__tostring = function() return 'empty component list' end,
__newindex = function() __error_fmt 'attempt to modify empty component list' end
}) --[=[@as evolved.component[]]=],
__EMPTY_COMPONENT_STORAGE = __lua_setmetatable({}, {
__tostring = function() return 'empty component storage' end,
__newindex = function() __error_fmt 'attempt to modify empty component storage' end
@@ -1906,7 +1892,7 @@ function __chunk_with_fragment(chunk, fragment)
end
---@param chunk? evolved.chunk
---@param components table<evolved.fragment, evolved.component>
---@param components evolved.component_table
---@return evolved.chunk?
---@nodiscard
function __chunk_with_components(chunk, components)
@@ -2063,7 +2049,7 @@ function __chunk_fragments(head_fragment, ...)
return chunk
end
---@param components table<evolved.fragment, evolved.component>
---@param components evolved.component_table
---@return evolved.chunk?
---@nodiscard
function __chunk_components(components)
@@ -2313,14 +2299,15 @@ end
---@param chunk? evolved.chunk
---@param entity evolved.entity
---@param components table<evolved.fragment, evolved.component>
function __spawn_entity(chunk, entity, components)
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
function __spawn_entity(chunk, entity, component_table, component_mapper)
if __defer_depth <= 0 then
__error_fmt('spawn entity operations should be deferred')
end
if not chunk or chunk.__unreachable_or_collected then
chunk = __chunk_components(components)
chunk = component_table and __chunk_components(component_table)
end
while chunk and chunk.__has_required_fragments do
@@ -2369,7 +2356,7 @@ function __spawn_entity(chunk, entity, components)
local component_fragment = chunk_component_fragments[component_index]
local component_duplicate = chunk_component_duplicates[component_index]
local ini_component = components[component_fragment]
local ini_component = component_table and component_table[component_fragment]
if ini_component == nil then
ini_component = chunk_component_defaults[component_index]
@@ -2392,6 +2379,10 @@ function __spawn_entity(chunk, entity, components)
end
end
if component_mapper then
component_mapper(chunk, place, place)
end
if chunk.__has_insert_hooks then
local chunk_fragment_list = chunk.__fragment_list
local chunk_fragment_count = chunk.__fragment_count
@@ -2435,14 +2426,15 @@ end
---@param chunk? evolved.chunk
---@param entity_list evolved.entity[]
---@param entity_count integer
---@param components table<evolved.fragment, evolved.component>
function __multi_spawn_entity(chunk, entity_list, entity_count, components)
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
function __multi_spawn_entity(chunk, entity_list, entity_count, component_table, component_mapper)
if __defer_depth <= 0 then
__error_fmt('spawn entity operations should be deferred')
end
if not chunk or chunk.__unreachable_or_collected then
chunk = __chunk_components(components)
chunk = component_table and __chunk_components(component_table)
end
while chunk and chunk.__has_required_fragments do
@@ -2498,7 +2490,7 @@ function __multi_spawn_entity(chunk, entity_list, entity_count, components)
local component_fragment = chunk_component_fragments[component_index]
local component_duplicate = chunk_component_duplicates[component_index]
local ini_component = components[component_fragment]
local ini_component = component_table and component_table[component_fragment]
if ini_component == nil then
ini_component = chunk_component_defaults[component_index]
@@ -2525,6 +2517,10 @@ function __multi_spawn_entity(chunk, entity_list, entity_count, components)
end
end
if component_mapper then
component_mapper(chunk, b_place, e_place)
end
if chunk.__has_insert_hooks then
local chunk_fragment_list = chunk.__fragment_list
local chunk_fragment_count = chunk.__fragment_count
@@ -2575,8 +2571,9 @@ end
---@param prefab evolved.entity
---@param entity evolved.entity
---@param components table<evolved.fragment, evolved.component>
function __clone_entity(prefab, entity, components)
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
function __clone_entity(prefab, entity, component_table, component_mapper)
if __defer_depth <= 0 then
__error_fmt('clone entity operations should be deferred')
end
@@ -2592,12 +2589,12 @@ function __clone_entity(prefab, entity, components)
end
if not prefab_chunk or not prefab_chunk.__without_unique_fragments then
return __spawn_entity(nil, entity, components)
return __spawn_entity(nil, entity, component_table, component_mapper)
end
local chunk = __chunk_with_components(
prefab_chunk.__without_unique_fragments,
components)
local chunk = component_table
and __chunk_with_components(prefab_chunk.__without_unique_fragments, component_table)
or prefab_chunk.__without_unique_fragments
while chunk and chunk.__has_required_fragments do
local required_chunk = chunk.__with_required_fragments
@@ -2648,7 +2645,7 @@ function __clone_entity(prefab, entity, components)
local component_fragment = chunk_component_fragments[component_index]
local component_duplicate = chunk_component_duplicates[component_index]
local ini_component = components[component_fragment]
local ini_component = component_table and component_table[component_fragment]
if ini_component == nil then
if chunk == prefab_chunk then
@@ -2681,6 +2678,10 @@ function __clone_entity(prefab, entity, components)
end
end
if component_mapper then
component_mapper(chunk, place, place)
end
if chunk.__has_insert_hooks then
local chunk_fragment_list = chunk.__fragment_list
local chunk_fragment_count = chunk.__fragment_count
@@ -2724,8 +2725,9 @@ end
---@param prefab evolved.entity
---@param entity_list evolved.entity[]
---@param entity_count integer
---@param components table<evolved.fragment, evolved.component>
function __multi_clone_entity(prefab, entity_list, entity_count, components)
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
function __multi_clone_entity(prefab, entity_list, entity_count, component_table, component_mapper)
if __defer_depth <= 0 then
__error_fmt('clone entity operations should be deferred')
end
@@ -2741,12 +2743,12 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
end
if not prefab_chunk or not prefab_chunk.__without_unique_fragments then
return __multi_spawn_entity(nil, entity_list, entity_count, components)
return __multi_spawn_entity(nil, entity_list, entity_count, component_table, component_mapper)
end
local chunk = __chunk_with_components(
prefab_chunk.__without_unique_fragments,
components)
local chunk = component_table
and __chunk_with_components(prefab_chunk.__without_unique_fragments, component_table)
or prefab_chunk.__without_unique_fragments
while chunk and chunk.__has_required_fragments do
local required_chunk = chunk.__with_required_fragments
@@ -2804,7 +2806,7 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
local component_fragment = chunk_component_fragments[component_index]
local component_duplicate = chunk_component_duplicates[component_index]
local ini_component = components[component_fragment]
local ini_component = component_table and component_table[component_fragment]
if ini_component == nil then
if chunk == prefab_chunk then
@@ -2841,6 +2843,10 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
end
end
if component_mapper then
component_mapper(chunk, b_place, e_place)
end
if chunk.__has_insert_hooks then
local chunk_fragment_list = chunk.__fragment_list
local chunk_fragment_count = chunk.__fragment_count
@@ -3995,13 +4001,18 @@ end
---@param chunk? evolved.chunk
---@param entity evolved.entity
---@param component_map table<evolved.fragment, evolved.component>
function __defer_spawn_entity(chunk, entity, component_map)
---@type table<evolved.fragment, evolved.component>
local component_map_dup = __acquire_table(__table_pool_tag.component_map)
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
function __defer_spawn_entity(chunk, entity, component_table, component_mapper)
---@type evolved.component_table?
local component_table2
for fragment, component in __lua_next, component_map do
component_map_dup[fragment] = component
if component_table then
component_table2 = __acquire_table(__table_pool_tag.component_table)
for fragment, component in __lua_next, component_table do
component_table2[fragment] = component
end
end
local length = __defer_length
@@ -4010,43 +4021,53 @@ function __defer_spawn_entity(chunk, entity, component_map)
bytecode[length + 1] = __defer_op.spawn_entity
bytecode[length + 2] = chunk
bytecode[length + 3] = entity
bytecode[length + 4] = component_map_dup
bytecode[length + 4] = component_table2
bytecode[length + 5] = component_mapper
__defer_length = length + 4
__defer_length = length + 5
end
__defer_ops[__defer_op.spawn_entity] = function(bytes, index)
local chunk = bytes[index + 0]
local entity = bytes[index + 1]
local component_map_dup = bytes[index + 2]
local component_table2 = bytes[index + 2]
local component_mapper = bytes[index + 3]
__evolved_defer()
do
__spawn_entity(chunk, entity, component_map_dup)
__release_table(__table_pool_tag.component_map, component_map_dup)
__spawn_entity(chunk, entity, component_table2, component_mapper)
if component_table2 then
__release_table(__table_pool_tag.component_table, component_table2)
end
end
__evolved_commit()
return 3
return 4
end
---@param chunk? evolved.chunk
---@param entity_list evolved.entity[]
---@param entity_count integer
---@param component_map table<evolved.fragment, evolved.component>
function __defer_multi_spawn_entity(chunk, entity_list, entity_count, component_map)
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
function __defer_multi_spawn_entity(chunk, entity_list, entity_count, component_table, component_mapper)
---@type evolved.entity[]
local entity_list_dup = __acquire_table(__table_pool_tag.entity_list)
local entity_list2 = __acquire_table(__table_pool_tag.entity_list)
__lua_table_move(
entity_list, 1, entity_count,
1, entity_list_dup)
1, entity_list2)
---@type table<evolved.fragment, evolved.component>
local component_map_dup = __acquire_table(__table_pool_tag.component_map)
---@type evolved.component_table?
local component_table2
for fragment, component in __lua_next, component_map do
component_map_dup[fragment] = component
if component_table then
component_table2 = __acquire_table(__table_pool_tag.component_table)
for fragment, component in __lua_next, component_table do
component_table2[fragment] = component
end
end
local length = __defer_length
@@ -4055,38 +4076,51 @@ function __defer_multi_spawn_entity(chunk, entity_list, entity_count, component_
bytecode[length + 1] = __defer_op.multi_spawn_entity
bytecode[length + 2] = chunk
bytecode[length + 3] = entity_count
bytecode[length + 4] = entity_list_dup
bytecode[length + 5] = component_map_dup
bytecode[length + 4] = entity_list2
bytecode[length + 5] = component_table2
bytecode[length + 6] = component_mapper
__defer_length = length + 5
__defer_length = length + 6
end
__defer_ops[__defer_op.multi_spawn_entity] = function(bytes, index)
local chunk = bytes[index + 0]
local entity_count = bytes[index + 1]
local entity_list_dup = bytes[index + 2]
local component_map_dup = bytes[index + 3]
local entity_list2 = bytes[index + 2]
local component_table2 = bytes[index + 3]
local component_mapper = bytes[index + 4]
__evolved_defer()
do
__multi_spawn_entity(chunk, entity_list_dup, entity_count, component_map_dup)
__release_table(__table_pool_tag.entity_list, entity_list_dup)
__release_table(__table_pool_tag.component_map, component_map_dup)
__multi_spawn_entity(chunk, entity_list2, entity_count, component_table2, component_mapper)
if entity_list2 then
__release_table(__table_pool_tag.entity_list, entity_list2)
end
if component_table2 then
__release_table(__table_pool_tag.component_table, component_table2)
end
end
__evolved_commit()
return 4
return 5
end
---@param prefab evolved.entity
---@param entity evolved.entity
---@param component_map table<evolved.fragment, evolved.component>
function __defer_clone_entity(prefab, entity, component_map)
---@type table<evolved.fragment, evolved.component>
local component_map_dup = __acquire_table(__table_pool_tag.component_map)
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
function __defer_clone_entity(prefab, entity, component_table, component_mapper)
---@type evolved.component_table?
local component_table2
for fragment, component in __lua_next, component_map do
component_map_dup[fragment] = component
if component_table then
component_table2 = __acquire_table(__table_pool_tag.component_table)
for fragment, component in __lua_next, component_table do
component_table2[fragment] = component
end
end
local length = __defer_length
@@ -4095,43 +4129,53 @@ function __defer_clone_entity(prefab, entity, component_map)
bytecode[length + 1] = __defer_op.clone_entity
bytecode[length + 2] = prefab
bytecode[length + 3] = entity
bytecode[length + 4] = component_map_dup
bytecode[length + 4] = component_table2
bytecode[length + 5] = component_mapper
__defer_length = length + 4
__defer_length = length + 5
end
__defer_ops[__defer_op.clone_entity] = function(bytes, index)
local prefab = bytes[index + 0]
local entity = bytes[index + 1]
local component_map_dup = bytes[index + 2]
local component_table2 = bytes[index + 2]
local component_mapper = bytes[index + 3]
__evolved_defer()
do
__clone_entity(prefab, entity, component_map_dup)
__release_table(__table_pool_tag.component_map, component_map_dup)
__clone_entity(prefab, entity, component_table2, component_mapper)
if component_table2 then
__release_table(__table_pool_tag.component_table, component_table2)
end
end
__evolved_commit()
return 3
return 4
end
---@param prefab evolved.entity
---@param entity_list evolved.entity[]
---@param entity_count integer
---@param component_map table<evolved.fragment, evolved.component>
function __defer_multi_clone_entity(prefab, entity_list, entity_count, component_map)
---@param component_table? evolved.component_table
---@param component_mapper? evolved.component_mapper
function __defer_multi_clone_entity(prefab, entity_list, entity_count, component_table, component_mapper)
---@type evolved.entity[]
local entity_list_dup = __acquire_table(__table_pool_tag.entity_list)
local entity_list2 = __acquire_table(__table_pool_tag.entity_list)
__lua_table_move(
entity_list, 1, entity_count,
1, entity_list_dup)
1, entity_list2)
---@type table<evolved.fragment, evolved.component>
local component_map_dup = __acquire_table(__table_pool_tag.component_map)
---@type evolved.component_table?
local component_table2
for fragment, component in __lua_next, component_map do
component_map_dup[fragment] = component
if component_table then
component_table2 = __acquire_table(__table_pool_tag.component_table)
for fragment, component in __lua_next, component_table do
component_table2[fragment] = component
end
end
local length = __defer_length
@@ -4140,27 +4184,35 @@ function __defer_multi_clone_entity(prefab, entity_list, entity_count, component
bytecode[length + 1] = __defer_op.multi_clone_entity
bytecode[length + 2] = prefab
bytecode[length + 3] = entity_count
bytecode[length + 4] = entity_list_dup
bytecode[length + 5] = component_map_dup
bytecode[length + 4] = entity_list2
bytecode[length + 5] = component_table2
bytecode[length + 6] = component_mapper
__defer_length = length + 5
__defer_length = length + 6
end
__defer_ops[__defer_op.multi_clone_entity] = function(bytes, index)
local prefab = bytes[index + 0]
local entity_count = bytes[index + 1]
local entity_list_dup = bytes[index + 2]
local component_map_dup = bytes[index + 3]
local entity_list2 = bytes[index + 2]
local component_table2 = bytes[index + 3]
local component_mapper = bytes[index + 4]
__evolved_defer()
do
__multi_clone_entity(prefab, entity_list_dup, entity_count, component_map_dup)
__release_table(__table_pool_tag.entity_list, entity_list_dup)
__release_table(__table_pool_tag.component_map, component_map_dup)
__multi_clone_entity(prefab, entity_list2, entity_count, component_table2, component_mapper)
if entity_list2 then
__release_table(__table_pool_tag.entity_list, entity_list2)
end
if component_table2 then
__release_table(__table_pool_tag.component_table, component_table2)
end
end
__evolved_commit()
return 4
return 5
end
---
@@ -4479,28 +4531,33 @@ function __evolved_cancel()
return __evolved_commit()
end
---@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)
components = components or __safe_tbls.__EMPTY_COMPONENT_MAP
function __evolved_spawn(component_table, component_mapper)
if __debug_mode then
for fragment in __lua_next, components do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
if component_table then
for fragment in __lua_next, component_table do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
end
end
end
end
local entity = __acquire_id()
if not component_table or not __lua_next(component_table) then
return entity
end
if __defer_depth > 0 then
__defer_spawn_entity(nil, entity, components)
__defer_spawn_entity(nil, entity, component_table, component_mapper)
else
__evolved_defer()
do
__spawn_entity(nil, entity, components)
__spawn_entity(nil, entity, component_table, component_mapper)
end
__evolved_commit()
end
@@ -4509,21 +4566,22 @@ function __evolved_spawn(components)
end
---@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)
function __evolved_multi_spawn(entity_count, component_table, component_mapper)
if entity_count <= 0 then
return {}, 0
end
components = components or __safe_tbls.__EMPTY_COMPONENT_MAP
if __debug_mode then
for fragment in __lua_next, components do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
if component_table then
for fragment in __lua_next, component_table do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
end
end
end
end
@@ -4534,12 +4592,16 @@ function __evolved_multi_spawn(entity_count, components)
entity_list[entity_index] = __acquire_id()
end
if not component_table or not __lua_next(component_table) then
return entity_list, entity_count
end
if __defer_depth > 0 then
__defer_multi_spawn_entity(nil, entity_list, entity_count, components)
__defer_multi_spawn_entity(nil, entity_list, entity_count, component_table, component_mapper)
else
__evolved_defer()
do
__multi_spawn_entity(nil, entity_list, entity_count, components)
__multi_spawn_entity(nil, entity_list, entity_count, component_table, component_mapper)
end
__evolved_commit()
end
@@ -4548,21 +4610,22 @@ function __evolved_multi_spawn(entity_count, components)
end
---@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)
components = components or __safe_tbls.__EMPTY_COMPONENT_MAP
function __evolved_clone(prefab, component_table, component_mapper)
if __debug_mode then
if not __evolved_alive(prefab) then
__error_fmt('the prefab (%s) is not alive and cannot be used',
__id_name(prefab))
end
for fragment in __lua_next, components do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
if component_table then
for fragment in __lua_next, component_table do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
end
end
end
end
@@ -4570,11 +4633,11 @@ function __evolved_clone(prefab, components)
local entity = __acquire_id()
if __defer_depth > 0 then
__defer_clone_entity(prefab, entity, components)
__defer_clone_entity(prefab, entity, component_table, component_mapper)
else
__evolved_defer()
do
__clone_entity(prefab, entity, components)
__clone_entity(prefab, entity, component_table, component_mapper)
end
__evolved_commit()
end
@@ -4584,26 +4647,27 @@ end
---@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)
function __evolved_multi_clone(entity_count, prefab, component_table, component_mapper)
if entity_count <= 0 then
return {}, 0
end
components = components or __safe_tbls.__EMPTY_COMPONENT_MAP
if __debug_mode then
if not __evolved_alive(prefab) then
__error_fmt('the prefab (%s) is not alive and cannot be used',
__id_name(prefab))
end
for fragment in __lua_next, components do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
if component_table then
for fragment in __lua_next, component_table do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
end
end
end
end
@@ -4615,11 +4679,11 @@ function __evolved_multi_clone(entity_count, prefab, components)
end
if __defer_depth > 0 then
__defer_multi_clone_entity(prefab, entity_list, entity_count, components)
__defer_multi_clone_entity(prefab, entity_list, entity_count, component_table, component_mapper)
else
__evolved_defer()
do
__multi_clone_entity(prefab, entity_list, entity_count, components)
__multi_clone_entity(prefab, entity_list, entity_count, component_table, component_mapper)
end
__evolved_commit()
end
@@ -5976,7 +6040,7 @@ end
---@nodiscard
function __evolved_builder()
return __lua_setmetatable({
__components = {},
__component_table = {},
}, __builder_mt)
end
@@ -5984,7 +6048,7 @@ function __builder_mt:__tostring()
local fragment_list = {} ---@type evolved.fragment[]
local fragment_count = 0 ---@type integer
for fragment in __lua_next, self.__components do
for fragment in __lua_next, self.__component_table do
fragment_count = fragment_count + 1
fragment_list[fragment_count] = fragment
end
@@ -6001,49 +6065,58 @@ function __builder_mt:__tostring()
end
---@param prefab? evolved.entity
---@param component_mapper? evolved.component_mapper
---@return evolved.entity entity
function __builder_mt:build(prefab)
function __builder_mt:build(prefab, component_mapper)
if prefab then
return self:clone(prefab)
return self:clone(prefab, component_mapper)
else
return self:spawn()
return self:spawn(component_mapper)
end
end
---@param entity_count integer
---@param prefab? evolved.entity
---@param component_mapper? evolved.component_mapper
---@return evolved.entity[] entity_list
---@return integer entity_count
function __builder_mt:multi_build(entity_count, prefab)
function __builder_mt:multi_build(entity_count, prefab, component_mapper)
if prefab then
return self:multi_clone(entity_count, prefab)
return self:multi_clone(entity_count, prefab, component_mapper)
else
return self:multi_spawn(entity_count)
return self:multi_spawn(entity_count, component_mapper)
end
end
---@param component_mapper? evolved.component_mapper
---@return evolved.entity entity
function __builder_mt:spawn()
function __builder_mt:spawn(component_mapper)
local chunk = self.__chunk
local components = self.__components
local component_table = self.__component_table
if __debug_mode then
for fragment in __lua_next, components do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
if component_table then
for fragment in __lua_next, component_table do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
end
end
end
end
local entity = __acquire_id()
if not component_table or not __lua_next(component_table) then
return entity
end
if __defer_depth > 0 then
__defer_spawn_entity(chunk, entity, components)
__defer_spawn_entity(chunk, entity, component_table, component_mapper)
else
__evolved_defer()
do
__spawn_entity(chunk, entity, components)
__spawn_entity(chunk, entity, component_table, component_mapper)
end
__evolved_commit()
end
@@ -6052,21 +6125,24 @@ function __builder_mt:spawn()
end
---@param entity_count integer
---@param component_mapper? evolved.component_mapper
---@return evolved.entity[] entity_list
---@return integer entity_count
function __builder_mt:multi_spawn(entity_count)
function __builder_mt:multi_spawn(entity_count, component_mapper)
if entity_count <= 0 then
return {}, 0
end
local chunk = self.__chunk
local components = self.__components
local component_table = self.__component_table
if __debug_mode then
for fragment in __lua_next, components do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
if component_table then
for fragment in __lua_next, component_table do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
end
end
end
end
@@ -6077,12 +6153,16 @@ function __builder_mt:multi_spawn(entity_count)
entity_list[entity_index] = __acquire_id()
end
if not component_table or not __lua_next(component_table) then
return entity_list, entity_count
end
if __defer_depth > 0 then
__defer_multi_spawn_entity(chunk, entity_list, entity_count, components)
__defer_multi_spawn_entity(chunk, entity_list, entity_count, component_table, component_mapper)
else
__evolved_defer()
do
__multi_spawn_entity(chunk, entity_list, entity_count, components)
__multi_spawn_entity(chunk, entity_list, entity_count, component_table, component_mapper)
end
__evolved_commit()
end
@@ -6091,9 +6171,10 @@ function __builder_mt:multi_spawn(entity_count)
end
---@param prefab evolved.entity
---@param component_mapper? evolved.component_mapper
---@return evolved.entity entity
function __builder_mt:clone(prefab)
local components = self.__components
function __builder_mt:clone(prefab, component_mapper)
local component_table = self.__component_table
if __debug_mode then
if not __evolved_alive(prefab) then
@@ -6101,10 +6182,12 @@ function __builder_mt:clone(prefab)
__id_name(prefab))
end
for fragment in __lua_next, components do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
if component_table then
for fragment in __lua_next, component_table do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
end
end
end
end
@@ -6112,11 +6195,11 @@ function __builder_mt:clone(prefab)
local entity = __acquire_id()
if __defer_depth > 0 then
__defer_clone_entity(prefab, entity, components)
__defer_clone_entity(prefab, entity, component_table, component_mapper)
else
__evolved_defer()
do
__clone_entity(prefab, entity, components)
__clone_entity(prefab, entity, component_table, component_mapper)
end
__evolved_commit()
end
@@ -6126,14 +6209,15 @@ end
---@param entity_count integer
---@param prefab evolved.entity
---@param component_mapper? evolved.component_mapper
---@return evolved.entity[] entity_list
---@return integer entity_count
function __builder_mt:multi_clone(entity_count, prefab)
function __builder_mt:multi_clone(entity_count, prefab, component_mapper)
if entity_count <= 0 then
return {}, 0
end
local components = self.__components
local component_table = self.__component_table
if __debug_mode then
if not __evolved_alive(prefab) then
@@ -6141,10 +6225,12 @@ function __builder_mt:multi_clone(entity_count, prefab)
__id_name(prefab))
end
for fragment in __lua_next, components do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
if component_table then
for fragment in __lua_next, component_table do
if not __evolved_alive(fragment) then
__error_fmt('the fragment (%s) is not alive and cannot be used',
__id_name(fragment))
end
end
end
end
@@ -6156,11 +6242,11 @@ function __builder_mt:multi_clone(entity_count, prefab)
end
if __defer_depth > 0 then
__defer_multi_clone_entity(prefab, entity_list, entity_count, components)
__defer_multi_clone_entity(prefab, entity_list, entity_count, component_table, component_mapper)
else
__evolved_defer()
do
__multi_clone_entity(prefab, entity_list, entity_count, components)
__multi_clone_entity(prefab, entity_list, entity_count, component_table, component_mapper)
end
__evolved_commit()
end
@@ -6217,7 +6303,7 @@ function __builder_mt:get(...)
return
end
local cs = self.__components
local cs = self.__component_table
if fragment_count == 1 then
local f1 = ...
@@ -6260,7 +6346,7 @@ function __builder_mt:set(fragment, component)
end
local new_chunk = __chunk_with_fragment(self.__chunk, fragment)
local components = self.__components
local component_table = self.__component_table
if new_chunk.__has_setup_hooks then
---@type evolved.default?, evolved.duplicate?
@@ -6272,12 +6358,12 @@ function __builder_mt:set(fragment, component)
if new_component ~= nil and fragment_duplicate then new_component = fragment_duplicate(new_component) end
if new_component == nil then new_component = true end
components[fragment] = new_component
component_table[fragment] = new_component
else
local new_component = component
if new_component == nil then new_component = true end
components[fragment] = new_component
component_table[fragment] = new_component
end
self.__chunk = new_chunk
@@ -6294,12 +6380,12 @@ function __builder_mt:remove(...)
end
local new_chunk = self.__chunk
local components = self.__components
local component_table = self.__component_table
for fragment_index = 1, fragment_count do
---@type evolved.fragment
local fragment = __lua_select(fragment_index, ...)
new_chunk, components[fragment] = __chunk_without_fragment(new_chunk, fragment), nil
new_chunk, component_table[fragment] = __chunk_without_fragment(new_chunk, fragment), nil
end
self.__chunk = new_chunk
@@ -6309,7 +6395,7 @@ end
---@return evolved.builder builder
function __builder_mt:clear()
self.__chunk = nil
__lua_table_clear(self.__components)
__lua_table_clear(self.__component_table)
return self
end

View File

@@ -52,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(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()
@@ -124,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()

View 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",
}
}