From bd08540ce0091ecfd0682c146c5dcf34e2624f95 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 18 Mar 2025 19:37:59 +0700 Subject: [PATCH 1/7] update roadmap --- ROADMAP.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ROADMAP.md b/ROADMAP.md index 5877029..b8967b5 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -3,6 +3,9 @@ ## Backlog - should set/assign/insert return a constructed component? +- enable/disable systems and phases +- add optional immediate mode for systems +- cached queries ## After first release From 66e13faf71115e7f19c69593e654d98a91bd6ce9 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 18 Mar 2025 16:13:07 +0700 Subject: [PATCH 2/7] style fix, update roadmap # Conflicts: # ROADMAP.md --- ROADMAP.md | 1 + evolved.lua | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index b8967b5..09e1f19 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -3,6 +3,7 @@ ## Backlog - should set/assign/insert return a constructed component? +- remove __evolved_defer/commit to __defer/commit indirect calls - enable/disable systems and phases - add optional immediate mode for systems - cached queries diff --git a/evolved.lua b/evolved.lua index 206d453..35ecd38 100644 --- a/evolved.lua +++ b/evolved.lua @@ -4940,7 +4940,7 @@ __evolved_is_alive = function(chunk_or_entity) local entity = chunk_or_entity --[[@as evolved.entity]] local entity_index = entity % 0x100000 - return __freelist_ids[entity_index] == chunk_or_entity + return __freelist_ids[entity_index] == entity end end From 0a5a36d6ea7cb4c1c1f8da4834fbd29f47b5c4c5 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 18 Mar 2025 20:53:31 +0700 Subject: [PATCH 3/7] remove defer/commit indirect calls --- ROADMAP.md | 7 +- develop/all.lua | 4 +- evolved.lua | 184 +++++++++++++++++++++++------------------------- 3 files changed, 93 insertions(+), 102 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 09e1f19..5f3d944 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -3,14 +3,13 @@ ## Backlog - should set/assign/insert return a constructed component? -- remove __evolved_defer/commit to __defer/commit indirect calls - enable/disable systems and phases -- add optional immediate mode for systems -- cached queries +- add system groups +- sort system groups instead of systems ## After first release -- add system groups +- cached queries - observers and events - add INDEX fragment trait - add REQUIRES fragment trait diff --git a/develop/all.lua b/develop/all.lua index 7d7536f..49a0913 100644 --- a/develop/all.lua +++ b/develop/all.lua @@ -1,4 +1,4 @@ require 'develop.example' --- require 'develop.unbench' +require 'develop.unbench' require 'develop.untests' --- require 'develop.usbench' +require 'develop.usbench' diff --git a/evolved.lua b/evolved.lua index 35ecd38..8170aa6 100644 --- a/evolved.lua +++ b/evolved.lua @@ -1479,9 +1479,6 @@ end --- --- -local __defer -local __commit - local __defer_set local __defer_assign local __defer_insert @@ -3324,18 +3321,18 @@ local function __system_process(system) end if query and execute then - __defer() + __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) if not success then - __commit() + __evolved_commit() __error_fmt('system execution failed: %s', result) end end end - __commit() + __evolved_commit() end if epilogue then @@ -3489,44 +3486,6 @@ local __defer_op = { ---@type table local __defer_ops = __lua_table_new(__defer_op.__count, 0) ----@return boolean started -__defer = function() - __defer_depth = __defer_depth + 1 - return __defer_depth == 1 -end - ----@return boolean committed -__commit = function() - if __defer_depth <= 0 then - __error_fmt('unbalanced defer/commit') - end - - __defer_depth = __defer_depth - 1 - - if __defer_depth > 0 then - return false - end - - if __defer_length == 0 then - return true - end - - local length = __defer_length - local bytecode = __defer_bytecode - - __defer_length = 0 - __defer_bytecode = __acquire_table(__table_pool_tag.bytecode) - - local bytecode_index = 1 - while bytecode_index <= length do - local op = __defer_ops[bytecode[bytecode_index]] - bytecode_index = bytecode_index + op(bytecode, bytecode_index + 1) + 1 - end - - __release_table(__table_pool_tag.bytecode, bytecode, true) - return true -end - ---@param entity evolved.entity ---@param fragment evolved.fragment ---@param ... any component arguments @@ -4716,13 +4675,13 @@ __defer_ops[__defer_op.spawn_entity_at] = function(bytes, index) __validate_fragment_list(fragment_list, fragment_count) end - __defer() + __evolved_defer() do __spawn_entity_at(entity, chunk, fragment_list, fragment_count, component_list) __release_table(__table_pool_tag.fragment_list, fragment_list) __release_table(__table_pool_tag.component_list, component_list) end - __commit() + __evolved_commit() return 5 end @@ -4767,13 +4726,13 @@ __defer_ops[__defer_op.spawn_entity_with] = function(bytes, index) __validate_fragment_list(fragment_list, fragment_count) end - __defer() + __evolved_defer() do __spawn_entity_with(entity, chunk, fragment_list, fragment_count, component_list) __release_table(__table_pool_tag.fragment_list, fragment_list) __release_table(__table_pool_tag.component_list, component_list) end - __commit() + __evolved_commit() return 5 end @@ -4918,12 +4877,40 @@ end ---@return boolean started __evolved_defer = function() - return __defer() + __defer_depth = __defer_depth + 1 + return __defer_depth == 1 end ---@return boolean committed __evolved_commit = function() - return __commit() + if __defer_depth <= 0 then + __error_fmt('unbalanced defer/commit') + end + + __defer_depth = __defer_depth - 1 + + if __defer_depth > 0 then + return false + end + + if __defer_length == 0 then + return true + end + + local length = __defer_length + local bytecode = __defer_bytecode + + __defer_length = 0 + __defer_bytecode = __acquire_table(__table_pool_tag.bytecode) + + local bytecode_index = 1 + while bytecode_index <= length do + local op = __defer_ops[bytecode[bytecode_index]] + bytecode_index = bytecode_index + op(bytecode, bytecode_index + 1) + 1 + end + + __release_table(__table_pool_tag.bytecode, bytecode, true) + return true end ---@param chunk_or_entity evolved.chunk | evolved.entity @@ -5258,7 +5245,7 @@ __evolved_set = function(entity, fragment, ...) __ON_SET, __ON_ASSIGN, __ON_INSERT) end - __defer() + __evolved_defer() if old_chunk == new_chunk then local old_component_indices = old_chunk.__component_indices @@ -5401,7 +5388,7 @@ __evolved_set = function(entity, fragment, ...) end end - __commit() + __evolved_commit() return true, false end @@ -5444,7 +5431,7 @@ __evolved_assign = function(entity, fragment, ...) __ON_SET, __ON_ASSIGN) end - __defer() + __evolved_defer() do local component_indices = chunk.__component_indices @@ -5507,7 +5494,7 @@ __evolved_assign = function(entity, fragment, ...) end end - __commit() + __evolved_commit() return true, false end @@ -5552,7 +5539,7 @@ __evolved_insert = function(entity, fragment, ...) __ON_SET, __ON_INSERT) end - __defer() + __evolved_defer() do local new_entity_list = new_chunk.__entity_list @@ -5636,7 +5623,7 @@ __evolved_insert = function(entity, fragment, ...) end end - __commit() + __evolved_commit() return true, false end @@ -5678,7 +5665,7 @@ __evolved_remove = function(entity, ...) return true, false end - __defer() + __evolved_defer() do local old_fragment_set = old_chunk.__fragment_set @@ -5748,7 +5735,7 @@ __evolved_remove = function(entity, ...) end end - __commit() + __evolved_commit() return true, false end @@ -5770,7 +5757,7 @@ __evolved_clear = function(...) local entity_chunks = __entity_chunks local entity_places = __entity_places - __defer() + __evolved_defer() for argument_index = 1, argument_count do ---@type evolved.entity @@ -5820,7 +5807,7 @@ __evolved_clear = function(...) end end - __commit() + __evolved_commit() return true, false end @@ -5842,7 +5829,7 @@ __evolved_destroy = function(...) local entity_chunks = __entity_chunks local entity_places = __entity_places - __defer() + __evolved_defer() for argument_index = 1, argument_count do ---@type evolved.entity @@ -5907,7 +5894,7 @@ __evolved_destroy = function(...) end end - __commit() + __evolved_commit() return true, false end @@ -5954,7 +5941,7 @@ __evolved_multi_set = function(entity, fragments, components) return false, false end - __defer() + __evolved_defer() if old_chunk == new_chunk then local old_component_indices = old_chunk.__component_indices @@ -6156,7 +6143,7 @@ __evolved_multi_set = function(entity, fragments, components) __release_table(__table_pool_tag.fragment_set, inserted_set) end - __commit() + __evolved_commit() return true, false end @@ -6201,7 +6188,7 @@ __evolved_multi_assign = function(entity, fragments, components) return false, false end - __defer() + __evolved_defer() do local chunk_fragment_set = chunk.__fragment_set @@ -6265,7 +6252,7 @@ __evolved_multi_assign = function(entity, fragments, components) end end - __commit() + __evolved_commit() return true, false end @@ -6312,7 +6299,7 @@ __evolved_multi_insert = function(entity, fragments, components) return false, false end - __defer() + __evolved_defer() do local new_entity_list = new_chunk.__entity_list @@ -6409,7 +6396,7 @@ __evolved_multi_insert = function(entity, fragments, components) __release_table(__table_pool_tag.fragment_set, inserted_set) end - __commit() + __evolved_commit() return true, false end @@ -6451,7 +6438,7 @@ __evolved_multi_remove = function(entity, fragments) return true, false end - __defer() + __evolved_defer() do local old_fragment_set = old_chunk.__fragment_set @@ -6520,7 +6507,7 @@ __evolved_multi_remove = function(entity, fragments) end end - __commit() + __evolved_commit() return true, false end @@ -6541,7 +6528,7 @@ __evolved_batch_set = function(chunk_or_query, fragment, ...) local set_count = 0 - __defer() + __evolved_defer() do if __lua_type(chunk_or_query) ~= 'number' then ---@cast chunk_or_query -evolved.query @@ -6569,7 +6556,7 @@ __evolved_batch_set = function(chunk_or_query, fragment, ...) __release_table(__table_pool_tag.chunk_stack, chunk_list) end end - __commit() + __evolved_commit() return set_count, false end @@ -6591,7 +6578,7 @@ __evolved_batch_assign = function(chunk_or_query, fragment, ...) local assigned_count = 0 - __defer() + __evolved_defer() do if __lua_type(chunk_or_query) ~= 'number' then ---@cast chunk_or_query -evolved.query @@ -6619,7 +6606,7 @@ __evolved_batch_assign = function(chunk_or_query, fragment, ...) __release_table(__table_pool_tag.chunk_stack, chunk_list) end end - __commit() + __evolved_commit() return assigned_count, false end @@ -6641,7 +6628,7 @@ __evolved_batch_insert = function(chunk_or_query, fragment, ...) local inserted_count = 0 - __defer() + __evolved_defer() do if __lua_type(chunk_or_query) ~= 'number' then ---@cast chunk_or_query -evolved.query @@ -6669,7 +6656,7 @@ __evolved_batch_insert = function(chunk_or_query, fragment, ...) __release_table(__table_pool_tag.chunk_stack, chunk_list) end end - __commit() + __evolved_commit() return inserted_count, false end @@ -6696,7 +6683,7 @@ __evolved_batch_remove = function(chunk_or_query, ...) local removed_count = 0 - __defer() + __evolved_defer() do if __lua_type(chunk_or_query) ~= 'number' then ---@cast chunk_or_query -evolved.query @@ -6724,7 +6711,7 @@ __evolved_batch_remove = function(chunk_or_query, ...) __release_table(__table_pool_tag.chunk_stack, chunk_list) end end - __commit() + __evolved_commit() return removed_count, false end @@ -6746,7 +6733,7 @@ __evolved_batch_clear = function(...) local cleared_count = 0 - __defer() + __evolved_defer() do ---@type evolved.chunk[] local chunk_list = __acquire_table(__table_pool_tag.chunk_stack) @@ -6780,7 +6767,7 @@ __evolved_batch_clear = function(...) __release_table(__table_pool_tag.chunk_stack, chunk_list) end - __commit() + __evolved_commit() return cleared_count, false end @@ -6802,7 +6789,7 @@ __evolved_batch_destroy = function(...) local destroyed_count = 0 - __defer() + __evolved_defer() do ---@type evolved.chunk[] local chunk_list = __acquire_table(__table_pool_tag.chunk_stack) @@ -6836,7 +6823,7 @@ __evolved_batch_destroy = function(...) __release_table(__table_pool_tag.chunk_stack, chunk_list) end - __commit() + __evolved_commit() return destroyed_count, false end @@ -6868,7 +6855,7 @@ __evolved_batch_multi_set = function(chunk_or_query, fragments, components) local set_count = 0 - __defer() + __evolved_defer() do if __lua_type(chunk_or_query) ~= 'number' then ---@cast chunk_or_query -evolved.query @@ -6896,7 +6883,7 @@ __evolved_batch_multi_set = function(chunk_or_query, fragments, components) __release_table(__table_pool_tag.chunk_stack, chunk_list) end end - __commit() + __evolved_commit() return set_count, false end @@ -6928,7 +6915,7 @@ __evolved_batch_multi_assign = function(chunk_or_query, fragments, components) local assigned_count = 0 - __defer() + __evolved_defer() do if __lua_type(chunk_or_query) ~= 'number' then ---@cast chunk_or_query -evolved.query @@ -6956,7 +6943,7 @@ __evolved_batch_multi_assign = function(chunk_or_query, fragments, components) __release_table(__table_pool_tag.chunk_stack, chunk_list) end end - __commit() + __evolved_commit() return assigned_count, false end @@ -6988,7 +6975,7 @@ __evolved_batch_multi_insert = function(chunk_or_query, fragments, components) local inserted_count = 0 - __defer() + __evolved_defer() do if __lua_type(chunk_or_query) ~= 'number' then ---@cast chunk_or_query -evolved.query @@ -7016,7 +7003,7 @@ __evolved_batch_multi_insert = function(chunk_or_query, fragments, components) __release_table(__table_pool_tag.chunk_stack, chunk_list) end end - __commit() + __evolved_commit() return inserted_count, false end @@ -7043,7 +7030,7 @@ __evolved_batch_multi_remove = function(chunk_or_query, fragments) local removed_count = 0 - __defer() + __evolved_defer() do if __lua_type(chunk_or_query) ~= 'number' then ---@cast chunk_or_query -evolved.query @@ -7071,7 +7058,7 @@ __evolved_batch_multi_remove = function(chunk_or_query, fragments) __release_table(__table_pool_tag.chunk_stack, chunk_list) end end - __commit() + __evolved_commit() return removed_count, false end @@ -7348,11 +7335,11 @@ __evolved_spawn_at = function(chunk, fragments, components) return entity, true end - __defer() + __evolved_defer() do __spawn_entity_at(entity, chunk, fragments, fragment_count, components) end - __commit() + __evolved_commit() return entity, false end @@ -7390,11 +7377,11 @@ __evolved_spawn_with = function(fragments, components) return entity, true end - __defer() + __evolved_defer() do __spawn_entity_with(entity, chunk, fragments, fragment_count, components) end - __commit() + __evolved_commit() return entity, false end @@ -7418,7 +7405,7 @@ __evolved_collect_garbage = function() return false, true end - __defer() + __evolved_defer() do ---@type evolved.chunk[] @@ -7471,7 +7458,7 @@ __evolved_collect_garbage = function() __release_table(__table_pool_tag.chunk_stack, postorder_chunk_stack) end - __commit() + __evolved_commit() return true, false end @@ -8041,6 +8028,7 @@ function evolved_system_builder:single(single) end ---@param phase evolved.phase +---@return evolved.system_builder builder function evolved_system_builder:phase(phase) self.__phase = phase return self @@ -8073,24 +8061,28 @@ function evolved_system_builder:after(...) end ---@param query evolved.query +---@return evolved.system_builder builder function evolved_system_builder:query(query) self.__query = query return self end ---@param execute evolved.execute +---@return evolved.system_builder builder function evolved_system_builder:execute(execute) self.__execute = execute return self end ---@param prologue evolved.prologue +---@return evolved.system_builder builder function evolved_system_builder:prologue(prologue) self.__prologue = prologue return self end ---@param epilogue evolved.epilogue +---@return evolved.system_builder builder function evolved_system_builder:epilogue(epilogue) self.__epilogue = epilogue return self From 252584a3ac52fb1202996decdbb661061255c0c2 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 19 Mar 2025 05:07:11 +0700 Subject: [PATCH 4/7] hide validation functions to internal __debug table --- evolved.lua | 212 +++++++++++++++++++++++++--------------------------- 1 file changed, 103 insertions(+), 109 deletions(-) diff --git a/evolved.lua b/evolved.lua index 8170aa6..3b11253 100644 --- a/evolved.lua +++ b/evolved.lua @@ -813,7 +813,7 @@ end --- --- -local __debug_mts = { +local __debug_fns = { chunk_mt = {}, ---@type metatable chunk_fragment_set_mt = {}, ---@type metatable @@ -825,7 +825,7 @@ local __debug_mts = { } ---@param self evolved.chunk -function __debug_mts.chunk_mt.__tostring(self) +function __debug_fns.chunk_mt.__tostring(self) local items = {} ---@type string[] for fragment_index, fragment in ipairs(self.__fragment_list) do @@ -836,7 +836,7 @@ function __debug_mts.chunk_mt.__tostring(self) end ---@param self table -function __debug_mts.chunk_fragment_set_mt.__tostring(self) +function __debug_fns.chunk_fragment_set_mt.__tostring(self) local items = {} ---@type string[] for fragment, fragment_index in pairs(self) do @@ -848,7 +848,7 @@ function __debug_mts.chunk_fragment_set_mt.__tostring(self) end ---@param self evolved.fragment[] -function __debug_mts.chunk_fragment_list_mt.__tostring(self) +function __debug_fns.chunk_fragment_list_mt.__tostring(self) local items = {} ---@type string[] for fragment_index, fragment in ipairs(self) do @@ -860,7 +860,7 @@ function __debug_mts.chunk_fragment_list_mt.__tostring(self) end ---@param self table -function __debug_mts.chunk_component_indices_mt.__tostring(self) +function __debug_fns.chunk_component_indices_mt.__tostring(self) local items = {} ---@type string[] for component_fragment, component_index in pairs(self) do @@ -872,7 +872,7 @@ function __debug_mts.chunk_component_indices_mt.__tostring(self) end ---@param self evolved.storage[] -function __debug_mts.chunk_component_storages_mt.__tostring(self) +function __debug_fns.chunk_component_storages_mt.__tostring(self) local items = {} ---@type string[] for component_index, component_storage in ipairs(self) do @@ -884,7 +884,7 @@ function __debug_mts.chunk_component_storages_mt.__tostring(self) end ---@param self evolved.fragment[] -function __debug_mts.chunk_component_fragments_mt.__tostring(self) +function __debug_fns.chunk_component_fragments_mt.__tostring(self) local items = {} ---@type string[] for component_index, component_fragment in ipairs(self) do @@ -895,6 +895,66 @@ function __debug_mts.chunk_component_fragments_mt.__tostring(self) return string.format('[%s]', table.concat(items, ', ')) end +---@param chunk evolved.chunk +function __debug_fns.validate_chunk(chunk) + if chunk.__unreachable_or_collected then + __error_fmt('the chunk (%s) is unreachable or collected and cannot be used', + chunk) + end +end + +---@param fragment evolved.fragment +function __debug_fns.validate_fragment(fragment) + local fragment_index = fragment % 0x100000 + + if __freelist_ids[fragment_index] ~= fragment then + __error_fmt('the fragment (%s) is not alive and cannot be used', + __id_name(fragment)) + end +end + +---@param ... evolved.fragment fragments +function __debug_fns.validate_fragments(...) + for i = 1, __lua_select('#', ...) do + __debug_fns.validate_fragment(__lua_select(i, ...)) + end +end + +---@param fragment_list evolved.fragment[] +---@param fragment_count integer +function __debug_fns.validate_fragment_list(fragment_list, fragment_count) + for i = 1, fragment_count do + __debug_fns.validate_fragment(fragment_list[i]) + end +end + +---@param query evolved.query +function __debug_fns.validate_query(query) + local query_index = query % 0x100000 + + if __freelist_ids[query_index] ~= query then + __error_fmt('the query (%s) is not alive and cannot be used', + __id_name(query)) + end +end + +---@param phase evolved.phase +function __debug_fns.validate_phase(phase) + local phase_index = phase % 0x100000 + + if __freelist_ids[phase_index] ~= phase then + __error_fmt('the phase (%s) is not alive and cannot be used', + __id_name(phase)) + end +end + +---@param ... evolved.phase phases +function __debug_fns.validate_phases(...) + for i = 1, __lua_select('#', ...) do + __debug_fns.validate_phase(__lua_select(i, ...)) + end +end + --- --- --- @@ -907,10 +967,10 @@ end ---@nodiscard local function __new_chunk(chunk_parent, chunk_fragment) ---@type table - local chunk_fragment_set = setmetatable({}, __debug_mts.chunk_fragment_set_mt) + local chunk_fragment_set = setmetatable({}, __debug_fns.chunk_fragment_set_mt) ---@type evolved.fragment[] - local chunk_fragment_list = setmetatable({}, __debug_mts.chunk_fragment_list_mt) + local chunk_fragment_list = setmetatable({}, __debug_fns.chunk_fragment_list_mt) ---@type integer local chunk_fragment_count = 0 @@ -919,13 +979,13 @@ local function __new_chunk(chunk_parent, chunk_fragment) local chunk_component_count = 0 ---@type table - local chunk_component_indices = setmetatable({}, __debug_mts.chunk_component_indices_mt) + local chunk_component_indices = setmetatable({}, __debug_fns.chunk_component_indices_mt) ---@type evolved.storage[] - local chunk_component_storages = setmetatable({}, __debug_mts.chunk_component_storages_mt) + local chunk_component_storages = setmetatable({}, __debug_fns.chunk_component_storages_mt) ---@type evolved.fragment[] - local chunk_component_fragments = setmetatable({}, __debug_mts.chunk_component_fragments_mt) + local chunk_component_fragments = setmetatable({}, __debug_fns.chunk_component_fragments_mt) local has_defaults_or_constructs = (chunk_parent and chunk_parent.__has_defaults_or_constructs) or __evolved_has_any(chunk_fragment, __DEFAULT, __CONSTRUCT) @@ -962,7 +1022,7 @@ local function __new_chunk(chunk_parent, chunk_fragment) __has_set_or_assign_hooks = has_set_or_assign_hooks, __has_set_or_insert_hooks = has_set_or_insert_hooks, __has_remove_hooks = has_remove_hooks, - }, __debug_mts.chunk_mt) + }, __debug_fns.chunk_mt) if chunk_parent then local parent_fragment_list = chunk_parent.__fragment_list @@ -1413,72 +1473,6 @@ end --- --- ----@param chunk evolved.chunk -local function __validate_chunk(chunk) - if chunk.__unreachable_or_collected then - __error_fmt('the chunk (%s) is unreachable or collected and cannot be used', - chunk) - end -end - ----@param fragment evolved.fragment -local function __validate_fragment(fragment) - local fragment_index = fragment % 0x100000 - - if __freelist_ids[fragment_index] ~= fragment then - __error_fmt('the fragment (%s) is not alive and cannot be used', - __id_name(fragment)) - end -end - ----@param ... evolved.fragment fragments -local function __validate_fragments(...) - for i = 1, __lua_select('#', ...) do - __validate_fragment(__lua_select(i, ...)) - end -end - ----@param fragment_list evolved.fragment[] ----@param fragment_count integer -local function __validate_fragment_list(fragment_list, fragment_count) - for i = 1, fragment_count do - __validate_fragment(fragment_list[i]) - end -end - ----@param query evolved.query -local function __validate_query(query) - local query_index = query % 0x100000 - - if __freelist_ids[query_index] ~= query then - __error_fmt('the query (%s) is not alive and cannot be used', - __id_name(query)) - end -end - ----@param phase evolved.phase -local function __validate_phase(phase) - local phase_index = phase % 0x100000 - - if __freelist_ids[phase_index] ~= phase then - __error_fmt('the phase (%s) is not alive and cannot be used', - __id_name(phase)) - end -end - ----@param ... evolved.phase phases -local function __validate_phases(...) - for i = 1, __lua_select('#', ...) do - __validate_phase(__lua_select(i, ...)) - end -end - ---- ---- ---- ---- ---- - local __defer_set local __defer_assign local __defer_insert @@ -4671,8 +4665,8 @@ __defer_ops[__defer_op.spawn_entity_at] = function(bytes, index) local component_list = bytes[index + 4] if __debug_mode then - __validate_chunk(chunk) - __validate_fragment_list(fragment_list, fragment_count) + __debug_fns.validate_chunk(chunk) + __debug_fns.validate_fragment_list(fragment_list, fragment_count) end __evolved_defer() @@ -4722,8 +4716,8 @@ __defer_ops[__defer_op.spawn_entity_with] = function(bytes, index) local component_list = bytes[index + 4] if __debug_mode then - __validate_chunk(chunk) - __validate_fragment_list(fragment_list, fragment_count) + __debug_fns.validate_chunk(chunk) + __debug_fns.validate_fragment_list(fragment_list, fragment_count) end __evolved_defer() @@ -5220,7 +5214,7 @@ __evolved_set = function(entity, fragment, ...) end if __debug_mode then - __validate_fragment(fragment) + __debug_fns.validate_fragment(fragment) end local entity_index = entity % 0x100000 @@ -5404,7 +5398,7 @@ __evolved_assign = function(entity, fragment, ...) end if __debug_mode then - __validate_fragment(fragment) + __debug_fns.validate_fragment(fragment) end local entity_index = entity % 0x100000 @@ -5510,7 +5504,7 @@ __evolved_insert = function(entity, fragment, ...) end if __debug_mode then - __validate_fragment(fragment) + __debug_fns.validate_fragment(fragment) end local entity_index = entity % 0x100000 @@ -5644,7 +5638,7 @@ __evolved_remove = function(entity, ...) end if __debug_mode then - __validate_fragments(...) + __debug_fns.validate_fragments(...) end local entity_index = entity % 0x100000 @@ -5920,7 +5914,7 @@ __evolved_multi_set = function(entity, fragments, components) end if __debug_mode then - __validate_fragment_list(fragments, fragment_count) + __debug_fns.validate_fragment_list(fragments, fragment_count) end local entity_index = entity % 0x100000 @@ -6169,7 +6163,7 @@ __evolved_multi_assign = function(entity, fragments, components) end if __debug_mode then - __validate_fragment_list(fragments, fragment_count) + __debug_fns.validate_fragment_list(fragments, fragment_count) end local entity_index = entity % 0x100000 @@ -6278,7 +6272,7 @@ __evolved_multi_insert = function(entity, fragments, components) end if __debug_mode then - __validate_fragment_list(fragments, fragment_count) + __debug_fns.validate_fragment_list(fragments, fragment_count) end local entity_index = entity % 0x100000 @@ -6417,7 +6411,7 @@ __evolved_multi_remove = function(entity, fragments) end if __debug_mode then - __validate_fragment_list(fragments, fragment_count) + __debug_fns.validate_fragment_list(fragments, fragment_count) end local entity_index = entity % 0x100000 @@ -6523,7 +6517,7 @@ __evolved_batch_set = function(chunk_or_query, fragment, ...) end if __debug_mode then - __validate_fragment(fragment) + __debug_fns.validate_fragment(fragment) end local set_count = 0 @@ -6573,7 +6567,7 @@ __evolved_batch_assign = function(chunk_or_query, fragment, ...) end if __debug_mode then - __validate_fragment(fragment) + __debug_fns.validate_fragment(fragment) end local assigned_count = 0 @@ -6623,7 +6617,7 @@ __evolved_batch_insert = function(chunk_or_query, fragment, ...) end if __debug_mode then - __validate_fragment(fragment) + __debug_fns.validate_fragment(fragment) end local inserted_count = 0 @@ -6678,7 +6672,7 @@ __evolved_batch_remove = function(chunk_or_query, ...) end if __debug_mode then - __validate_fragments(...) + __debug_fns.validate_fragments(...) end local removed_count = 0 @@ -6850,7 +6844,7 @@ __evolved_batch_multi_set = function(chunk_or_query, fragments, components) end if __debug_mode then - __validate_fragment_list(fragments, fragment_count) + __debug_fns.validate_fragment_list(fragments, fragment_count) end local set_count = 0 @@ -6910,7 +6904,7 @@ __evolved_batch_multi_assign = function(chunk_or_query, fragments, components) end if __debug_mode then - __validate_fragment_list(fragments, fragment_count) + __debug_fns.validate_fragment_list(fragments, fragment_count) end local assigned_count = 0 @@ -6970,7 +6964,7 @@ __evolved_batch_multi_insert = function(chunk_or_query, fragments, components) end if __debug_mode then - __validate_fragment_list(fragments, fragment_count) + __debug_fns.validate_fragment_list(fragments, fragment_count) end local inserted_count = 0 @@ -7025,7 +7019,7 @@ __evolved_batch_multi_remove = function(chunk_or_query, fragments) end if __debug_mode then - __validate_fragment_list(fragments, fragment_count) + __debug_fns.validate_fragment_list(fragments, fragment_count) end local removed_count = 0 @@ -7077,7 +7071,7 @@ end ---@nodiscard __evolved_chunk = function(head_fragment, ...) if __debug_mode then - __validate_fragments(head_fragment, ...) + __debug_fns.validate_fragments(head_fragment, ...) end local chunk = __chunk_fragments(head_fragment, ...) @@ -7090,7 +7084,7 @@ end ---@nodiscard __evolved_entities = function(chunk) if __debug_mode then - __validate_chunk(chunk) + __debug_fns.validate_chunk(chunk) end return chunk.__entity_list, chunk.__entity_count @@ -7102,7 +7096,7 @@ end ---@nodiscard __evolved_fragments = function(chunk) if __debug_mode then - __validate_chunk(chunk) + __debug_fns.validate_chunk(chunk) end return chunk.__fragment_list, chunk.__fragment_count @@ -7120,8 +7114,8 @@ __evolved_components = function(chunk, ...) end if __debug_mode then - __validate_chunk(chunk) - __validate_fragments(...) + __debug_fns.validate_chunk(chunk) + __debug_fns.validate_fragments(...) end local indices = chunk.__component_indices @@ -7213,7 +7207,7 @@ end ---@nodiscard __evolved_execute = function(query) if __debug_mode then - __validate_query(query) + __debug_fns.validate_query(query) end ---@type evolved.chunk[] @@ -7284,7 +7278,7 @@ __evolved_process = function(...) end if __debug_mode then - __validate_phases(...) + __debug_fns.validate_phases(...) end for i = 1, phase_count do @@ -7318,8 +7312,8 @@ __evolved_spawn_at = function(chunk, fragments, components) local component_count = #components if __debug_mode then - if chunk then __validate_chunk(chunk) end - __validate_fragment_list(fragments, fragment_count) + if chunk then __debug_fns.validate_chunk(chunk) end + __debug_fns.validate_fragment_list(fragments, fragment_count) end local entity = __acquire_id() @@ -7361,7 +7355,7 @@ __evolved_spawn_with = function(fragments, components) local component_count = #components if __debug_mode then - __validate_fragment_list(fragments, fragment_count) + __debug_fns.validate_fragment_list(fragments, fragment_count) end local entity, chunk = __acquire_id(), __chunk_fragment_list(fragments, fragment_count) From b8fdfcb939b0f85e428142448a8c3dfd6f39e0af Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 19 Mar 2025 05:32:21 +0700 Subject: [PATCH 5/7] simple group builder --- README.md | 7 ++++ develop/untests.lua | 14 ++++++++ evolved.lua | 78 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) diff --git a/README.md b/README.md index d1bc529..c21fe39 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,13 @@ query_builder:exclude :: fragment... -> query_builder query_builder:build :: query, boolean ``` +``` +group :: group_builder +group_builder:name :: string -> group_builder +group_builder:single :: component -> group_builder +group_builder:build :: group, boolean +``` + ``` phase :: phase_builder phase_builder:name :: string -> phase_builder diff --git a/develop/untests.lua b/develop/untests.lua index 5fbff34..5b993c0 100644 --- a/develop/untests.lua +++ b/develop/untests.lua @@ -8202,3 +8202,17 @@ do assert(not evo.is_alive_any(e1a, e1b, e12a, e12b)) assert(evo.is_empty_all(e1a, e1b, e12a, e12b)) end + +do + local gb = evo.group() + + local g1 = gb:build() + local g2 = gb:name('g2'):build() + local g3 = gb:single(42):build() + local g4 = gb:name('g4'):single(43):build() + + assert(not evo.has(g1, evo.NAME) and not evo.has(g1, g1)) + assert(evo.get(g2, evo.NAME) == 'g2' and not evo.has(g2, g2)) + assert(not evo.has(g3, evo.NAME) and evo.get(g3, g3) == 42) + assert(evo.get(g4, evo.NAME) == 'g4' and evo.get(g4, g4) == 43) +end diff --git a/evolved.lua b/evolved.lua index 3b11253..92c59a2 100644 --- a/evolved.lua +++ b/evolved.lua @@ -32,6 +32,7 @@ local evolved = { ---@alias evolved.entity evolved.id ---@alias evolved.fragment evolved.id ---@alias evolved.query evolved.id +---@alias evolved.group evolved.id ---@alias evolved.phase evolved.id ---@alias evolved.system evolved.id @@ -693,6 +694,7 @@ local __evolved_collect_garbage local __evolved_entity local __evolved_fragment local __evolved_query +local __evolved_group local __evolved_phase local __evolved_system @@ -7900,6 +7902,81 @@ end --- --- +---@class (exact) evolved.__group_builder +---@field package __name? string +---@field package __single? evolved.component + +---@class evolved.group_builder : evolved.__group_builder +local evolved_group_builder = {} +evolved_group_builder.__index = evolved_group_builder + +---@return evolved.group_builder builder +---@nodiscard +__evolved_group = function() + ---@type evolved.__group_builder + local builder = { + __name = nil, + __single = nil, + } + ---@cast builder evolved.group_builder + return setmetatable(builder, evolved_group_builder) +end + +---@param name string +---@return evolved.group_builder builder +function evolved_group_builder:name(name) + self.__name = name + return self +end + +---@param single evolved.component +---@return evolved.group_builder builder +function evolved_group_builder:single(single) + self.__single = single + return self +end + +---@return evolved.group group +---@return boolean is_deferred +function evolved_group_builder:build() + local name = self.__name + local single = self.__single + + self.__name = nil + self.__single = nil + + local group = __evolved_id() + + local fragment_list = __acquire_table(__table_pool_tag.fragment_list) + local component_list = __acquire_table(__table_pool_tag.component_list) + local component_count = 0 + + if name then + component_count = component_count + 1 + fragment_list[component_count] = __NAME + component_list[component_count] = name + end + + if single ~= nil then + component_count = component_count + 1 + fragment_list[component_count] = group + component_list[component_count] = single + end + + local _, is_deferred = __evolved_multi_set(group, fragment_list, component_list) + + __release_table(__table_pool_tag.fragment_list, fragment_list) + __release_table(__table_pool_tag.component_list, component_list) + + return group, is_deferred +end + +--- +--- +--- +--- +--- + ---@class (exact) evolved.__phase_builder ---@field package __name? string ---@field package __single? evolved.component @@ -8580,6 +8657,7 @@ evolved.collect_garbage = __evolved_collect_garbage evolved.entity = __evolved_entity evolved.fragment = __evolved_fragment evolved.query = __evolved_query +evolved.group = __evolved_group evolved.phase = __evolved_phase evolved.system = __evolved_system From fcfc74790d53e0bd26dbcb52523ccc2f8d0b592c Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 19 Mar 2025 05:42:37 +0700 Subject: [PATCH 6/7] GROUP builtin fragment, system_builder method for it --- README.md | 1 + develop/untests.lua | 6 ++++ evolved.lua | 71 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/README.md b/README.md index c21fe39..80aaefe 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ ON_ASSIGN :: fragment ON_INSERT :: fragment ON_REMOVE :: fragment +GROUP :: fragment PHASE :: fragment AFTER :: fragment diff --git a/develop/untests.lua b/develop/untests.lua index 5b993c0..d776d04 100644 --- a/develop/untests.lua +++ b/develop/untests.lua @@ -8216,3 +8216,9 @@ do assert(not evo.has(g3, evo.NAME) and evo.get(g3, g3) == 42) assert(evo.get(g4, evo.NAME) == 'g4' and evo.get(g4, g4) == 43) end + +do + local g = evo.group():build() + local s = evo.system():group(g):build() + assert(evo.get(s, evo.GROUP) == g) +end diff --git a/evolved.lua b/evolved.lua index 92c59a2..75776b7 100644 --- a/evolved.lua +++ b/evolved.lua @@ -114,6 +114,7 @@ local __entity_places = {} ---@type table local __structural_changes = 0 ---@type integer +local __group_systems = {} ---@type table local __phase_systems = {} ---@type table local __system_dependencies = {} ---@type table @@ -581,6 +582,7 @@ local __ON_ASSIGN = __acquire_id() local __ON_INSERT = __acquire_id() local __ON_REMOVE = __acquire_id() +local __GROUP = __acquire_id() local __PHASE = __acquire_id() local __AFTER = __acquire_id() @@ -8055,6 +8057,7 @@ end ---@class (exact) evolved.__system_builder ---@field package __name? string ---@field package __single? evolved.component +---@field package __group? evolved.group ---@field package __phase? evolved.phase ---@field package __after? evolved.system[] ---@field package __query? evolved.query @@ -8073,6 +8076,7 @@ __evolved_system = function() local builder = { __name = nil, __single = nil, + __group = nil, __phase = nil, __after = nil, __query = nil, @@ -8098,6 +8102,13 @@ function evolved_system_builder:single(single) return self end +---@param group evolved.group +---@return evolved.system_builder builder +function evolved_system_builder:group(group) + self.__group = group + return self +end + ---@param phase evolved.phase ---@return evolved.system_builder builder function evolved_system_builder:phase(phase) @@ -8164,6 +8175,7 @@ end function evolved_system_builder:build() local name = self.__name local single = self.__single + local group = self.__group local phase = self.__phase local after = self.__after local query = self.__query @@ -8173,6 +8185,7 @@ function evolved_system_builder:build() self.__name = nil self.__single = nil + self.__group = nil self.__phase = nil self.__after = nil self.__query = nil @@ -8198,6 +8211,12 @@ function evolved_system_builder:build() component_list[component_count] = single end + if group then + component_count = component_count + 1 + fragment_list[component_count] = __GROUP + component_list[component_count] = group + end + if phase then component_count = component_count + 1 fragment_list[component_count] = __PHASE @@ -8390,6 +8409,7 @@ assert(__evolved_insert(__ON_ASSIGN, __NAME, 'ON_ASSIGN')) assert(__evolved_insert(__ON_INSERT, __NAME, 'ON_INSERT')) assert(__evolved_insert(__ON_REMOVE, __NAME, 'ON_REMOVE')) +assert(__evolved_insert(__GROUP, __NAME, 'GROUP')) assert(__evolved_insert(__PHASE, __NAME, 'PHASE')) assert(__evolved_insert(__AFTER, __NAME, 'AFTER')) @@ -8484,6 +8504,56 @@ end)) --- --- +---@param system evolved.system +---@param new_group evolved.group +---@param old_group? evolved.group +assert(__evolved_insert(__GROUP, __ON_SET, function(system, _, new_group, old_group) + if new_group == old_group then + return + end + + if old_group then + local old_group_systems = __group_systems[old_group] + + if old_group_systems then + __assoc_list_remove(old_group_systems, system) + + if old_group_systems.__item_count == 0 then + __group_systems[old_group] = nil + end + end + end + + local new_group_systems = __group_systems[new_group] + + if not new_group_systems then + new_group_systems = __assoc_list_new(4) + __group_systems[new_group] = new_group_systems + end + + __assoc_list_insert(new_group_systems, system) +end)) + +---@param system evolved.system +---@param old_group evolved.group +assert(__evolved_insert(__GROUP, __ON_REMOVE, function(system, _, old_group) + local old_group_systems = __group_systems[old_group] + + if old_group_systems then + __assoc_list_remove(old_group_systems, system) + + if old_group_systems.__item_count == 0 then + __group_systems[old_group] = nil + end + end +end)) + +--- +--- +--- +--- +--- + ---@param system evolved.system ---@param new_phase evolved.phase ---@param old_phase? evolved.phase @@ -8579,6 +8649,7 @@ evolved.ON_ASSIGN = __ON_ASSIGN evolved.ON_INSERT = __ON_INSERT evolved.ON_REMOVE = __ON_REMOVE +evolved.GROUP = __GROUP evolved.PHASE = __PHASE evolved.AFTER = __AFTER From b2145093a2443dc669b2901c69ad0746bcf5f2fb Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 19 Mar 2025 06:51:07 +0700 Subject: [PATCH 7/7] groups have a phase and after dependencies, but systems don't --- README.md | 7 +- ROADMAP.md | 6 +- develop/example.lua | 18 ++- develop/untests.lua | 40 ++--- evolved.lua | 358 ++++++++++++++++++++++---------------------- 5 files changed, 219 insertions(+), 210 deletions(-) diff --git a/README.md b/README.md index 80aaefe..c987259 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,8 @@ ON_ASSIGN :: fragment ON_INSERT :: fragment ON_REMOVE :: fragment -GROUP :: fragment PHASE :: fragment +GROUP :: fragment AFTER :: fragment QUERY :: fragment @@ -153,6 +153,8 @@ query_builder:build :: query, boolean group :: group_builder group_builder:name :: string -> group_builder group_builder:single :: component -> group_builder +group_builder:phase :: phase -> group_builder +group_builder:after :: group... -> group_builder group_builder:build :: group, boolean ``` @@ -167,8 +169,7 @@ phase_builder:build :: phase, boolean system :: system_builder system_builder:name :: string -> system_builder system_builder:single :: component -> system_builder -system_builder:phase :: phase -> system_builder -system_builder:after :: system... -> system_builder +system_builder:group :: group -> system_builder system_builder:query :: query -> system_builder system_builder:execute :: {chunk, entity[], integer} -> system_builder system_builder:prologue :: {} -> system_builder diff --git a/ROADMAP.md b/ROADMAP.md index 5f3d944..bff49a5 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -3,9 +3,9 @@ ## Backlog - should set/assign/insert return a constructed component? -- enable/disable systems and phases -- add system groups -- sort system groups instead of systems +- enable/disable systems and groups +- should systems support multiple groups? +- should groups support multiple phases? ## After first release diff --git a/develop/example.lua b/develop/example.lua index eb1ae77..ecfdbc5 100644 --- a/develop/example.lua +++ b/develop/example.lua @@ -22,6 +22,13 @@ local phases = { shutdown = evo.phase():build(), } +local groups = { + awake = evo.group():phase(phases.awake):build(), + physics = evo.group():phase(phases.physics):build(), + graphics = evo.group():phase(phases.graphics):build(), + shutdown = evo.group():phase(phases.shutdown):build(), +} + local singles = { delta_time = evo.fragment():single(0.016):build(), physics_gravity = evo.fragment():single(vector2(0, 9.81)):build(), @@ -40,7 +47,7 @@ local queries = { } local awake_system = evo.system() - :phase(phases.awake) + :group(groups.awake) :prologue(function() print '-= | Awake | =-' evo.entity() @@ -51,7 +58,7 @@ local awake_system = evo.system() end):build() local integrate_forces_system = evo.system() - :phase(phases.physics) + :group(groups.physics) :query(queries.physics_bodies) :execute(function(chunk, entities, entity_count) ---@type number, evolved.vector2 @@ -72,8 +79,7 @@ local integrate_forces_system = evo.system() end):build() local integrate_velocities_system = evo.system() - :phase(phases.physics) - :after(integrate_forces_system) + :group(groups.physics) :query(queries.physics_bodies) :execute(function(chunk, entities, entity_count) ---@type number @@ -96,7 +102,7 @@ local integrate_velocities_system = evo.system() end):build() local graphics_system = evo.system() - :phase(phases.graphics) + :group(groups.graphics) :query(queries.physics_bodies) :execute(function(chunk, entities, entity_count) ---@type evolved.vector2[] @@ -113,7 +119,7 @@ local graphics_system = evo.system() end):build() local shutdown_system = evo.system() - :phase(phases.shutdown) + :group(groups.shutdown) :epilogue(function() print '-= | Shutdown | =-' evo.batch_destroy(queries.physics_bodies) diff --git a/develop/untests.lua b/develop/untests.lua index d776d04..0d57966 100644 --- a/develop/untests.lua +++ b/develop/untests.lua @@ -6569,26 +6569,6 @@ do end end -do - local s1 = evo.system():build() - do - local after = evo.get(s1, evo.AFTER) - assert(after == nil) - end - - local s2 = evo.system():after(s1):build() - do - local after = evo.get(s2, evo.AFTER) - assert(#after == 1 and after[1] == s1) - end - - local s3 = evo.system():after(s1, s2):build() - do - local after = evo.get(s3, evo.AFTER) - assert(#after == 2 and after[1] == s1 and after[2] == s2) - end -end - do local f1, f2 = evo.id(2) @@ -8222,3 +8202,23 @@ do local s = evo.system():group(g):build() assert(evo.get(s, evo.GROUP) == g) end + +do + local s1 = evo.group():build() + do + local after = evo.get(s1, evo.AFTER) + assert(after == nil) + end + + local g2 = evo.group():after(s1):build() + do + local after = evo.get(g2, evo.AFTER) + assert(#after == 1 and after[1] == s1) + end + + local g3 = evo.group():after(s1, g2):build() + do + local after = evo.get(g3, evo.AFTER) + assert(#after == 2 and after[1] == s1 and after[2] == g2) + end +end diff --git a/evolved.lua b/evolved.lua index 75776b7..9d8311d 100644 --- a/evolved.lua +++ b/evolved.lua @@ -114,9 +114,9 @@ local __entity_places = {} ---@type table local __structural_changes = 0 ---@type integer +local __phase_groups = {} ---@type table local __group_systems = {} ---@type table -local __phase_systems = {} ---@type table -local __system_dependencies = {} ---@type table +local __group_dependencies = {} ---@type table local __query_sorted_includes = {} ---@type table local __query_sorted_excludes = {} ---@type table @@ -287,7 +287,7 @@ local __table_pool_tag = { fragment_set = 5, fragment_list = 6, component_list = 7, - system_list = 8, + group_list = 8, sorting_stack = 9, sorting_marks = 10, __count = 10, @@ -582,8 +582,8 @@ local __ON_ASSIGN = __acquire_id() local __ON_INSERT = __acquire_id() local __ON_REMOVE = __acquire_id() -local __GROUP = __acquire_id() local __PHASE = __acquire_id() +local __GROUP = __acquire_id() local __AFTER = __acquire_id() local __QUERY = __acquire_id() @@ -778,8 +778,8 @@ local function __trace_fragment_chunks(fragment, trace, ...) do local major_chunks = __major_chunks[fragment] - local major_chunk_list = major_chunks and major_chunks.__item_list - local major_chunk_count = major_chunks and major_chunks.__item_count or 0 + local major_chunk_list = major_chunks and major_chunks.__item_list --[=[@as evolved.chunk[]]=] + local major_chunk_count = major_chunks and major_chunks.__item_count or 0 --[[@as integer]] if major_chunk_count > 0 then __lua_table_move( @@ -1898,8 +1898,8 @@ local function __purge_fragment(fragment, policy) end local minor_chunks = __minor_chunks[fragment] - local minor_chunk_list = minor_chunks and minor_chunks.__item_list - local minor_chunk_count = minor_chunks and minor_chunks.__item_count or 0 + local minor_chunk_list = minor_chunks and minor_chunks.__item_list --[=[@as evolved.chunk[]]=] + local minor_chunk_count = minor_chunks and minor_chunks.__item_count or 0 --[[@as integer]] if policy == __DESTROY_POLICY_DESTROY_ENTITY then for minor_chunk_index = minor_chunk_count, 1, -1 do @@ -3342,50 +3342,61 @@ local function __system_process(system) end end +---@param group evolved.group +local function __group_process(group) + local group_systems = __group_systems[group] + local group_system_list = group_systems and group_systems.__item_list --[=[@as evolved.system[]]=] + local group_system_count = group_systems and group_systems.__item_count or 0 --[[@as integer]] + + for group_system_index = 1, group_system_count do + __system_process(group_system_list[group_system_index]) + end +end + ---@param phase evolved.phase local function __phase_process(phase) - local phase_systems = __phase_systems[phase] - local phase_system_set = phase_systems and phase_systems.__item_set - local phase_system_list = phase_systems and phase_systems.__item_list - local phase_system_count = phase_systems and phase_systems.__item_count or 0 + local phase_groups = __phase_groups[phase] + local phase_group_set = phase_groups and phase_groups.__item_set --[[@as table]] + local phase_group_list = phase_groups and phase_groups.__item_list --[=[@as evolved.group[]]=] + local phase_group_count = phase_groups and phase_groups.__item_count or 0 --[[@as integer]] - ---@type evolved.system[] - local sorted_system_list = __acquire_table(__table_pool_tag.system_list) - local sorted_system_count = 0 + ---@type evolved.group[] + local sorted_group_list = __acquire_table(__table_pool_tag.group_list) + local sorted_group_count = 0 ---@type integer[] local sorting_marks = __acquire_table(__table_pool_tag.sorting_marks) - ---@type evolved.system[] + ---@type evolved.group[] local sorting_stack = __acquire_table(__table_pool_tag.sorting_stack) - local sorting_stack_size = phase_system_count + local sorting_stack_size = phase_group_count - for phase_system_index = 1, phase_system_count do - sorting_marks[phase_system_index] = 0 - local phase_system_rev_index = phase_system_count - phase_system_index + 1 - sorting_stack[phase_system_index] = phase_system_list[phase_system_rev_index] + for phase_group_index = 1, phase_group_count do + sorting_marks[phase_group_index] = 0 + local phase_group_rev_index = phase_group_count - phase_group_index + 1 + sorting_stack[phase_group_index] = phase_group_list[phase_group_rev_index] end while sorting_stack_size > 0 do - local system = sorting_stack[sorting_stack_size] + local group = sorting_stack[sorting_stack_size] - local system_mark_index = phase_system_set[system] - local system_mark = sorting_marks[system_mark_index] + local group_mark_index = phase_group_set[group] + local group_mark = sorting_marks[group_mark_index] - if not system_mark then - -- the system has already been added to the sorted list + if not group_mark then + -- the group has already been added to the sorted list sorting_stack[sorting_stack_size] = nil sorting_stack_size = sorting_stack_size - 1 - elseif system_mark == 0 then - sorting_marks[system_mark_index] = 1 + elseif group_mark == 0 then + sorting_marks[group_mark_index] = 1 - local dependencies = __system_dependencies[system] - local dependency_list = dependencies and dependencies.__item_list - local dependency_count = dependencies and dependencies.__item_count or 0 + local dependencies = __group_dependencies[group] + local dependency_list = dependencies and dependencies.__item_list --[=[@as evolved.group[]]=] + local dependency_count = dependencies and dependencies.__item_count or 0 --[[@as integer]] for dependency_index = dependency_count, 1, -1 do local dependency = dependency_list[dependency_index] - local dependency_mark_index = phase_system_set[dependency] + local dependency_mark_index = phase_group_set[dependency] if not dependency_mark_index then -- the dependency is not from this phase @@ -3398,19 +3409,19 @@ local function __phase_process(phase) sorting_stack_size = sorting_stack_size + 1 sorting_stack[sorting_stack_size] = dependency elseif dependency_mark == 1 then - local sorting_cycle_path = '' .. dependency + local sorting_cycle_path = '' .. __id_name(dependency) - for cycled_system_index = sorting_stack_size, 1, -1 do - local cycled_system = sorting_stack[cycled_system_index] + for cycled_group_index = sorting_stack_size, 1, -1 do + local cycled_group = sorting_stack[cycled_group_index] - local cycled_system_mark_index = phase_system_set[cycled_system] - local cycled_system_mark = sorting_marks[cycled_system_mark_index] + local cycled_group_mark_index = phase_group_set[cycled_group] + local cycled_group_mark = sorting_marks[cycled_group_mark_index] - if cycled_system_mark == 1 then + if cycled_group_mark == 1 then sorting_cycle_path = string.format('%s -> %s', - sorting_cycle_path, cycled_system) + sorting_cycle_path, __id_name(cycled_group)) - if cycled_system == dependency then + if cycled_group == dependency then break end end @@ -3420,23 +3431,22 @@ local function __phase_process(phase) end end end - elseif system_mark == 1 then - sorting_marks[system_mark_index] = nil + elseif group_mark == 1 then + sorting_marks[group_mark_index] = nil - sorted_system_count = sorted_system_count + 1 - sorted_system_list[sorted_system_count] = system + sorted_group_count = sorted_group_count + 1 + sorted_group_list[sorted_group_count] = group sorting_stack[sorting_stack_size] = nil sorting_stack_size = sorting_stack_size - 1 end end - for sorted_system_index = 1, sorted_system_count do - local system = sorted_system_list[sorted_system_index] - __system_process(system) + for sorted_group_index = 1, sorted_group_count do + __group_process(sorted_group_list[sorted_group_index]) end - __release_table(__table_pool_tag.system_list, sorted_system_list) + __release_table(__table_pool_tag.group_list, sorted_group_list) __release_table(__table_pool_tag.sorting_marks, sorting_marks, true) __release_table(__table_pool_tag.sorting_stack, sorting_stack, true) end @@ -7219,20 +7229,20 @@ __evolved_execute = function(query) local chunk_stack_size = 0 local query_includes = __query_sorted_includes[query] - local query_include_list = query_includes and query_includes.__item_list - local query_include_count = query_includes and query_includes.__item_count or 0 + local query_include_list = query_includes and query_includes.__item_list --[=[@as evolved.fragment[]]=] + local query_include_count = query_includes and query_includes.__item_count or 0 --[[@as integer]] local query_excludes = __query_sorted_excludes[query] - local query_exclude_set = query_excludes and query_excludes.__item_set - local query_exclude_list = query_excludes and query_excludes.__item_list - local query_exclude_count = query_excludes and query_excludes.__item_count or 0 + local query_exclude_set = query_excludes and query_excludes.__item_set --[[@as table]] + local query_exclude_list = query_excludes and query_excludes.__item_list --[=[@as evolved.fragment[]]=] + local query_exclude_count = query_excludes and query_excludes.__item_count or 0 --[[@as integer]] if query_include_count > 0 then local major_fragment = query_include_list[query_include_count] local major_chunks = __major_chunks[major_fragment] - local major_chunk_list = major_chunks and major_chunks.__item_list - local major_chunk_count = major_chunks and major_chunks.__item_count or 0 + local major_chunk_list = major_chunks and major_chunks.__item_list --[=[@as evolved.chunk[]]=] + local major_chunk_count = major_chunks and major_chunks.__item_count or 0 --[[@as integer]] for major_chunk_index = 1, major_chunk_count do local major_chunk = major_chunk_list[major_chunk_index] @@ -7275,20 +7285,12 @@ end ---@param ... evolved.phase phases __evolved_process = function(...) - local phase_count = __lua_select('#', ...) - - if phase_count == 0 then - return - end - if __debug_mode then __debug_fns.validate_phases(...) end - for i = 1, phase_count do - ---@type evolved.phase - local phase = __lua_select(i, ...) - __phase_process(phase) + for i = 1, __lua_select('#', ...) do + __phase_process(__lua_select(i, ...)) end end @@ -7906,6 +7908,8 @@ end ---@class (exact) evolved.__group_builder ---@field package __name? string +---@field package __phase? evolved.phase +---@field package __after? evolved.group[] ---@field package __single? evolved.component ---@class evolved.group_builder : evolved.__group_builder @@ -7919,6 +7923,8 @@ __evolved_group = function() local builder = { __name = nil, __single = nil, + __phase = nil, + __after = nil, } ---@cast builder evolved.group_builder return setmetatable(builder, evolved_group_builder) @@ -7938,14 +7944,51 @@ function evolved_group_builder:single(single) return self end +---@param phase evolved.phase +---@return evolved.group_builder builder +function evolved_group_builder:phase(phase) + self.__phase = phase + return self +end + +---@param ... evolved.group groups +---@return evolved.group_builder builder +function evolved_group_builder:after(...) + local group_count = __lua_select('#', ...) + + if group_count == 0 then + return self + end + + local after = self.__after + + if not after then + after = __lua_table_new(math.max(4, group_count), 0) + self.__after = after + end + + local after_count = #after + + for i = 1, group_count do + after_count = after_count + 1 + after[after_count] = __lua_select(i, ...) + end + + return self +end + ---@return evolved.group group ---@return boolean is_deferred function evolved_group_builder:build() local name = self.__name local single = self.__single + local phase = self.__phase + local after = self.__after self.__name = nil self.__single = nil + self.__phase = nil + self.__after = nil local group = __evolved_id() @@ -7965,6 +8008,18 @@ function evolved_group_builder:build() component_list[component_count] = single end + if phase then + component_count = component_count + 1 + fragment_list[component_count] = __PHASE + component_list[component_count] = phase + end + + if after then + component_count = component_count + 1 + fragment_list[component_count] = __AFTER + component_list[component_count] = after + end + local _, is_deferred = __evolved_multi_set(group, fragment_list, component_list) __release_table(__table_pool_tag.fragment_list, fragment_list) @@ -8058,8 +8113,6 @@ end ---@field package __name? string ---@field package __single? evolved.component ---@field package __group? evolved.group ----@field package __phase? evolved.phase ----@field package __after? evolved.system[] ---@field package __query? evolved.query ---@field package __execute? evolved.execute ---@field package __prologue? evolved.prologue @@ -8077,8 +8130,6 @@ __evolved_system = function() __name = nil, __single = nil, __group = nil, - __phase = nil, - __after = nil, __query = nil, __execute = nil, __prologue = nil, @@ -8109,39 +8160,6 @@ function evolved_system_builder:group(group) return self end ----@param phase evolved.phase ----@return evolved.system_builder builder -function evolved_system_builder:phase(phase) - self.__phase = phase - return self -end - ----@param ... evolved.system systems ----@return evolved.system_builder builder -function evolved_system_builder:after(...) - local system_count = __lua_select('#', ...) - - if system_count == 0 then - return self - end - - local after = self.__after - - if not after then - after = __lua_table_new(math.max(4, system_count), 0) - self.__after = after - end - - local after_count = #after - - for i = 1, system_count do - after_count = after_count + 1 - after[after_count] = __lua_select(i, ...) - end - - return self -end - ---@param query evolved.query ---@return evolved.system_builder builder function evolved_system_builder:query(query) @@ -8176,8 +8194,6 @@ function evolved_system_builder:build() local name = self.__name local single = self.__single local group = self.__group - local phase = self.__phase - local after = self.__after local query = self.__query local execute = self.__execute local prologue = self.__prologue @@ -8186,8 +8202,6 @@ function evolved_system_builder:build() self.__name = nil self.__single = nil self.__group = nil - self.__phase = nil - self.__after = nil self.__query = nil self.__execute = nil self.__prologue = nil @@ -8217,18 +8231,6 @@ function evolved_system_builder:build() component_list[component_count] = group end - if phase then - component_count = component_count + 1 - fragment_list[component_count] = __PHASE - component_list[component_count] = phase - end - - if after then - component_count = component_count + 1 - fragment_list[component_count] = __AFTER - component_list[component_count] = after - end - if query then component_count = component_count + 1 fragment_list[component_count] = __QUERY @@ -8409,8 +8411,8 @@ assert(__evolved_insert(__ON_ASSIGN, __NAME, 'ON_ASSIGN')) assert(__evolved_insert(__ON_INSERT, __NAME, 'ON_INSERT')) assert(__evolved_insert(__ON_REMOVE, __NAME, 'ON_REMOVE')) -assert(__evolved_insert(__GROUP, __NAME, 'GROUP')) assert(__evolved_insert(__PHASE, __NAME, 'PHASE')) +assert(__evolved_insert(__GROUP, __NAME, 'GROUP')) assert(__evolved_insert(__AFTER, __NAME, 'AFTER')) assert(__evolved_insert(__QUERY, __NAME, 'QUERY')) @@ -8504,6 +8506,56 @@ end)) --- --- +---@param group evolved.group +---@param new_phase evolved.phase +---@param old_phase? evolved.phase +assert(__evolved_insert(__PHASE, __ON_SET, function(group, _, new_phase, old_phase) + if new_phase == old_phase then + return + end + + if old_phase then + local old_phase_groups = __phase_groups[old_phase] + + if old_phase_groups then + __assoc_list_remove(old_phase_groups, group) + + if old_phase_groups.__item_count == 0 then + __phase_groups[old_phase] = nil + end + end + end + + local new_phase_groups = __phase_groups[new_phase] + + if not new_phase_groups then + new_phase_groups = __assoc_list_new(4) + __phase_groups[new_phase] = new_phase_groups + end + + __assoc_list_insert(new_phase_groups, group) +end)) + +---@param group evolved.group +---@param old_phase evolved.phase +assert(__evolved_insert(__PHASE, __ON_REMOVE, function(group, _, old_phase) + local old_phase_groups = __phase_groups[old_phase] + + if old_phase_groups then + __assoc_list_remove(old_phase_groups, group) + + if old_phase_groups.__item_count == 0 then + __phase_groups[old_phase] = nil + end + end +end)) + +--- +--- +--- +--- +--- + ---@param system evolved.system ---@param new_group evolved.group ---@param old_group? evolved.group @@ -8554,63 +8606,13 @@ end)) --- --- ----@param system evolved.system ----@param new_phase evolved.phase ----@param old_phase? evolved.phase -assert(__evolved_insert(__PHASE, __ON_SET, function(system, _, new_phase, old_phase) - if new_phase == old_phase then - return - end - - if old_phase then - local old_phase_systems = __phase_systems[old_phase] - - if old_phase_systems then - __assoc_list_remove(old_phase_systems, system) - - if old_phase_systems.__item_count == 0 then - __phase_systems[old_phase] = nil - end - end - end - - local new_phase_systems = __phase_systems[new_phase] - - if not new_phase_systems then - new_phase_systems = __assoc_list_new(4) - __phase_systems[new_phase] = new_phase_systems - end - - __assoc_list_insert(new_phase_systems, system) -end)) - ----@param system evolved.system ----@param old_phase evolved.phase -assert(__evolved_insert(__PHASE, __ON_REMOVE, function(system, _, old_phase) - local old_phase_systems = __phase_systems[old_phase] - - if old_phase_systems then - __assoc_list_remove(old_phase_systems, system) - - if old_phase_systems.__item_count == 0 then - __phase_systems[old_phase] = nil - end - end -end)) - ---- ---- ---- ---- ---- - ----@param system evolved.system ----@param new_after_list evolved.system[] -assert(__evolved_insert(__AFTER, __ON_SET, function(system, _, new_after_list) +---@param group evolved.group +---@param new_after_list evolved.group[] +assert(__evolved_insert(__AFTER, __ON_SET, function(group, _, new_after_list) local new_after_count = #new_after_list if new_after_count == 0 then - __system_dependencies[system] = nil + __group_dependencies[group] = nil return end @@ -8621,12 +8623,12 @@ assert(__evolved_insert(__AFTER, __ON_SET, function(system, _, new_after_list) __assoc_list_insert(new_dependencies, new_after) end - __system_dependencies[system] = new_dependencies + __group_dependencies[group] = new_dependencies end)) ----@param system evolved.system -assert(__evolved_insert(__AFTER, __ON_REMOVE, function(system) - __system_dependencies[system] = nil +---@param group evolved.group +assert(__evolved_insert(__AFTER, __ON_REMOVE, function(group) + __group_dependencies[group] = nil end)) --- @@ -8649,8 +8651,8 @@ evolved.ON_ASSIGN = __ON_ASSIGN evolved.ON_INSERT = __ON_INSERT evolved.ON_REMOVE = __ON_REMOVE -evolved.GROUP = __GROUP evolved.PHASE = __PHASE +evolved.GROUP = __GROUP evolved.AFTER = __AFTER evolved.QUERY = __QUERY