Skip to content

Commit 5e0170b

Browse files
committed
new evolved.process_with function impl
1 parent d42c0cf commit 5e0170b

6 files changed

Lines changed: 406 additions & 43 deletions

File tree

README.md

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
- [Deferred Operations](#deferred-operations)
4444
- [Batch Operations](#batch-operations)
4545
- [Systems](#systems)
46+
- [Processing Payloads](#processing-payloads)
4647
- [Predefined Traits](#predefined-traits)
4748
- [Fragment Tags](#fragment-tags)
4849
- [Fragment Hooks](#fragment-hooks)
@@ -60,6 +61,7 @@
6061
- [Chunk](#chunk)
6162
- [Builder](#builder)
6263
- [Changelog](#changelog)
64+
- [vX.Y.Z](#vxyz)
6365
- [v1.6.0](#v160)
6466
- [v1.5.0](#v150)
6567
- [v1.4.0](#v140)
@@ -880,6 +882,43 @@ The prologue and epilogue fragments do not require an explicit query. They will
880882
> [!NOTE]
881883
> 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.
882884
885+
#### Processing Payloads
886+
887+
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.
888+
889+
```lua
890+
---@param system evolved.system
891+
---@param ... any processing payload
892+
function evolved.process_with(system, ...) end
893+
```
894+
895+
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.
896+
897+
```lua
898+
local evolved = require 'evolved'
899+
900+
local position_x, position_y = evolved.id(2)
901+
local velocity_x, velocity_y = evolved.id(2)
902+
903+
local physics_system = evolved.builder()
904+
:include(position_x, position_y)
905+
:include(velocity_x, velocity_y)
906+
:execute(function(chunk, entity_list, entity_count, delta_time)
907+
local px, py = chunk:components(position_x, position_y)
908+
local vx, vy = chunk:components(velocity_x, velocity_y)
909+
910+
for i = 1, entity_count do
911+
px[i] = px[i] + vx[i] * delta_time
912+
py[i] = py[i] + vy[i] * delta_time
913+
end
914+
end):build()
915+
916+
local delta_time = 0.016
917+
evolved.process_with(physics_system, delta_time)
918+
```
919+
920+
`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).
921+
883922
### Predefined Traits
884923

885924
#### Fragment Tags
@@ -1125,9 +1164,9 @@ storage :: component[]
11251164
default :: component
11261165
duplicate :: {component -> component}
11271166
1128-
execute :: {chunk, entity[], integer}
1129-
prologue :: {}
1130-
epilogue :: {}
1167+
execute :: {chunk, entity[], integer, any...}
1168+
prologue :: {any...}
1169+
epilogue :: {any...}
11311170
11321171
set_hook :: {entity, fragment, component, component}
11331172
assign_hook :: {entity, fragment, component, component}
@@ -1229,6 +1268,7 @@ execute :: query -> {execute_state? -> chunk?, entity[]?, integer?}, execute_sta
12291268
locate :: entity -> chunk?, integer
12301269
12311270
process :: system... -> ()
1271+
process_with :: system, ... -> ()
12321272
12331273
debug_mode :: boolean -> ()
12341274
collect_garbage :: ()
@@ -1302,16 +1342,20 @@ builder_mt:on_remove :: {entity, fragment} -> builder
13021342
builder_mt:group :: system -> builder
13031343
13041344
builder_mt:query :: query -> builder
1305-
builder_mt:execute :: {chunk, entity[], integer} -> builder
1345+
builder_mt:execute :: {chunk, entity[], integer, any...} -> builder
13061346
1307-
builder_mt:prologue :: {} -> builder
1308-
builder_mt:epilogue :: {} -> builder
1347+
builder_mt:prologue :: {any...} -> builder
1348+
builder_mt:epilogue :: {any...} -> builder
13091349
13101350
builder_mt:destruction_policy :: id -> builder
13111351
```
13121352

13131353
## Changelog
13141354

1355+
### vX.Y.Z
1356+
1357+
- Added the new [`evolved.process_with`](#evolvedprocess_with) function that allows passing payloads to processing systems
1358+
13151359
### v1.6.0
13161360

13171361
- Significant performance improvements of the [`evolved.REQUIRES`](#evolvedrequires) fragment trait
@@ -1710,6 +1754,14 @@ function evolved.locate(entity) end
17101754
function evolved.process(...) end
17111755
```
17121756

1757+
### `evolved.process_with`
1758+
1759+
```lua
1760+
---@param system evolved.system
1761+
---@param ... any processing payload
1762+
function evolved.process_with(system, ...) end
1763+
```
1764+
17131765
### `evolved.debug_mode`
17141766

17151767
```lua

develop/all.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require 'develop.testing.locate_tests'
77
require 'develop.testing.main_tests'
88
require 'develop.testing.multi_spawn_tests'
99
require 'develop.testing.name_tests'
10+
require 'develop.testing.process_with_tests'
1011
require 'develop.testing.requires_fragment_tests'
1112
require 'develop.testing.spawn_tests'
1213
require 'develop.testing.system_as_query_tests'
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
local evo = require 'evolved'
2+
3+
do
4+
local f = evo.id()
5+
local e = evo.builder():set(f, 42):spawn()
6+
7+
local s = evo.builder()
8+
:include(f)
9+
:prologue(function(payload1, payload2, payload3)
10+
assert(payload1 == 11 and payload2 == 22 and payload3 == 33)
11+
end)
12+
:execute(function(chunk, entity_list, entity_count, payload1, payload2, payload3)
13+
assert(payload1 == 11 and payload2 == 22 and payload3 == 33)
14+
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
15+
end)
16+
:epilogue(function(payload1, payload2, payload3)
17+
assert(payload1 == 11 and payload2 == 22 and payload3 == 33)
18+
end)
19+
:spawn()
20+
21+
evo.process_with(s, 11, 22, 33)
22+
end
23+
24+
do
25+
local f = evo.id()
26+
local e = evo.builder():set(f, 42):spawn()
27+
28+
local s = evo.builder()
29+
:include(f)
30+
:prologue(function(payload1, payload2, payload3)
31+
assert(payload1 == nil and payload2 == 42 and payload3 == nil)
32+
end)
33+
:execute(function(chunk, entity_list, entity_count, payload1, payload2, payload3)
34+
assert(payload1 == nil and payload2 == 42 and payload3 == nil)
35+
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
36+
end)
37+
:epilogue(function(payload1, payload2, payload3)
38+
assert(payload1 == nil and payload2 == 42 and payload3 == nil)
39+
end)
40+
:spawn()
41+
42+
evo.process_with(s, nil, 42)
43+
end
44+
45+
do
46+
local f = evo.id()
47+
local e = evo.builder():set(f, 42):spawn()
48+
49+
local s = evo.builder()
50+
:include(f)
51+
:prologue(function(payload1, payload2, payload3)
52+
assert(payload1 == nil and payload2 == nil and payload3 == nil)
53+
end)
54+
:execute(function(chunk, entity_list, entity_count, payload1, payload2, payload3)
55+
assert(payload1 == nil and payload2 == nil and payload3 == nil)
56+
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
57+
end)
58+
:epilogue(function(payload1, payload2, payload3)
59+
assert(payload1 == nil and payload2 == nil and payload3 == nil)
60+
end)
61+
:spawn()
62+
63+
evo.process_with(s)
64+
end
65+
66+
do
67+
local f = evo.id()
68+
local e = evo.builder():set(f, 42):spawn()
69+
70+
local prologue_sum, execute_sum, epilogue_sum = 0, 0, 0
71+
72+
local function sum(...)
73+
local s = 0
74+
for i = 1, select('#', ...) do
75+
s = s + select(i, ...)
76+
end
77+
return s
78+
end
79+
80+
local function iota(n)
81+
if n == 0 then return end
82+
return n, iota(n - 1)
83+
end
84+
85+
local s = evo.builder()
86+
:include(f)
87+
:prologue(function(...)
88+
prologue_sum = prologue_sum + sum(...)
89+
end)
90+
:execute(function(chunk, entity_list, entity_count, ...)
91+
execute_sum = execute_sum + sum(...)
92+
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
93+
end)
94+
:epilogue(function(...)
95+
epilogue_sum = epilogue_sum + sum(...)
96+
end)
97+
:spawn()
98+
99+
for n = 0, 50 do
100+
prologue_sum, execute_sum, epilogue_sum = 0, 0, 0
101+
evo.process_with(s, iota(n))
102+
local expect_sum = (n * (n + 1)) / 2
103+
assert(prologue_sum == expect_sum)
104+
assert(execute_sum == expect_sum)
105+
assert(epilogue_sum == expect_sum)
106+
end
107+
end

evolved.d.tl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@
7979
group: function(self: Builder, group: System): Builder
8080

8181
query: function(self: Builder, query: Query): Builder
82-
execute: function(self: Builder, execute: function(Chunk, {Entity}, integer)): Builder
82+
execute: function(self: Builder, execute: function(Chunk, {Entity}, integer, ...: any)): Builder
8383

84-
prologue: function(self: Builder, prologue: function()): Builder
85-
epilogue: function(self: Builder, epilogue: function()): Builder
84+
prologue: function(self: Builder, prologue: function(...: any)): Builder
85+
epilogue: function(self: Builder, epilogue: function(...: any)): Builder
8686

8787
destruction_policy: function(self: Builder, destruction_policy: Id): Builder
8888
end
@@ -171,6 +171,7 @@
171171
locate: function(entity: Entity): Chunk | nil, integer
172172

173173
process: function(...: System)
174+
process_with: function(system: System, ...: any)
174175

175176
debug_mode: function(yesno: boolean)
176177
collect_garbage: function()

0 commit comments

Comments
 (0)