From 3a64bac8e25475b4e8bf606176bf97cd76d932d3 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Mon, 26 May 2025 17:37:40 +0700 Subject: [PATCH] systems can be queries themselves --- README.md | 27 +++++ develop/all.lua | 5 +- develop/testing/system_as_query_tests.lua | 128 ++++++++++++++++++++++ evolved.lua | 15 ++- 4 files changed, 166 insertions(+), 9 deletions(-) create mode 100644 develop/testing/system_as_query_tests.lua diff --git a/README.md b/README.md index 4b61406..a8b404a 100644 --- a/README.md +++ b/README.md @@ -671,6 +671,29 @@ 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. + +```lua +local evolved = require 'evolved' + +local health = evolved.id() + +local system = evolved.builder() + :include(health) + :execute(function(chunk, entity_list, entity_count) + local health_components = chunk:components(health) + + for i = 1, entity_count do + print(i) + health_components[i] = math.max( + health_components[i] - 1, + 0) + end + end):spawn() + +evolved.process(system) +``` + To group systems together, you can use the [`evolved.GROUP`](#evolvedgroup) fragment. Systems with a specified group will be processed when you call the [`evolved.process`](#evolvedprocess) function with this group. For example, you can group all physics systems together and process them in one [`evolved.process`](#evolvedprocess) call. ```lua @@ -1125,6 +1148,10 @@ builder_mt:destruction_policy :: id -> builder # Changelog +## vX.X.X-dev + +- Systems can be queries themselves + ## v1.0.0 - Initial release diff --git a/develop/all.lua b/develop/all.lua index 1a518e5..f6a56bc 100644 --- a/develop/all.lua +++ b/develop/all.lua @@ -1,6 +1,9 @@ require 'develop.example' -require 'develop.unbench' require 'develop.untests' + +require 'develop.testing.system_as_query_tests' + +require 'develop.unbench' require 'develop.usbench' local basics = require 'develop.basics' diff --git a/develop/testing/system_as_query_tests.lua b/develop/testing/system_as_query_tests.lua new file mode 100644 index 0000000..42effca --- /dev/null +++ b/develop/testing/system_as_query_tests.lua @@ -0,0 +1,128 @@ +local evo = require 'evolved' + +do + local f1, f2, f3 = evo.id(3) + + local q1e3 = evo.builder():include(f1):exclude(f3):spawn() + local q2e3 = evo.builder():include(f2):exclude(f3):spawn() + + local e1 = evo.builder():set(f1, 1):spawn() + local e12 = evo.builder():set(f1, 11):set(f2, 12):spawn() + local e2 = evo.builder():set(f2, 2):spawn() + local e23 = evo.builder():set(f2, 23):set(f3, 3):spawn() + + local c1 = evo.chunk(f1) + local c12 = evo.chunk(f1, f2) + local c2 = evo.chunk(f2) + + do + local _, entity_list, entity_count = evo.chunk(f2, f3) + assert(entity_count == 1 and entity_list[1] == e23) + end + + do + local entity_sum = 0 + + local s = evo.builder() + :query(q1e3) + :execute(function(chunk, entity_list, entity_count) + for i = 1, entity_count do + entity_sum = entity_sum + entity_list[i] + end + + if chunk == c1 then + assert(entity_count == 1) + assert(entity_list[1] == e1) + elseif chunk == c12 then + assert(entity_count == 1) + assert(entity_list[1] == e12) + else + assert(false, "Unexpected chunk: " .. tostring(chunk)) + end + end):spawn() + + evo.process(s) + + assert(entity_sum == e1 + e12) + end + + do + local entity_sum = 0 + + local s = evo.builder() + :query(q2e3) + :execute(function(chunk, entity_list, entity_count) + for i = 1, entity_count do + entity_sum = entity_sum + entity_list[i] + end + + if chunk == c12 then + assert(entity_count == 1) + assert(entity_list[1] == e12) + elseif chunk == c2 then + assert(entity_count == 1) + assert(entity_list[1] == e2) + else + assert(false, "Unexpected chunk: " .. tostring(chunk)) + end + end):spawn() + + evo.process(s) + + assert(entity_sum == e12 + e2) + end + + do + local entity_sum = 0 + + local s = evo.builder() + :include(f1) + :exclude(f3) + :execute(function(chunk, entity_list, entity_count) + for i = 1, entity_count do + entity_sum = entity_sum + entity_list[i] + end + + if chunk == c1 then + assert(entity_count == 1) + assert(entity_list[1] == e1) + elseif chunk == c12 then + assert(entity_count == 1) + assert(entity_list[1] == e12) + else + assert(false, "Unexpected chunk: " .. tostring(chunk)) + end + end):spawn() + + evo.process(s) + + assert(entity_sum == e1 + e12) + end + + do + local entity_sum = 0 + + local s = evo.builder() + :include(f2) + :exclude(f3) + :execute(function(chunk, entity_list, entity_count) + for i = 1, entity_count do + entity_sum = entity_sum + entity_list[i] + end + + if chunk == c12 then + assert(entity_count == 1) + assert(entity_list[1] == e12) + elseif chunk == c2 then + assert(entity_count == 1) + assert(entity_list[1] == e2) + else + assert(false, "Unexpected chunk: " .. tostring(chunk)) + end + end):spawn() + + evo.process(s) + + assert(entity_sum == e12 + e2) + end +end diff --git a/evolved.lua b/evolved.lua index 74e3460..74a70a6 100644 --- a/evolved.lua +++ b/evolved.lua @@ -2727,6 +2727,7 @@ end ---@param system evolved.system local function __system_process(system) + ---@type evolved.query?, evolved.execute?, evolved.prologue?, evolved.epilogue? local query, execute, prologue, epilogue = __evolved_get(system, __QUERY, __EXECUTE, __PROLOGUE, __EPILOGUE) @@ -2738,16 +2739,14 @@ local function __system_process(system) end end - if query and execute then + if execute then __evolved_defer() - do - for chunk, entity_list, entity_count in __evolved_execute(query) do - local success, result = __lua_pcall(execute, chunk, entity_list, entity_count) + for chunk, entity_list, entity_count in __evolved_execute(query or system) do + local success, result = __lua_pcall(execute, chunk, entity_list, entity_count) - if not success then - __evolved_commit() - __error_fmt('system execution failed: %s', result) - end + if not success then + __evolved_commit() + __error_fmt('system execution failed: %s', result) end end __evolved_commit()