From 1b49f4fcd09a4c4efb1b9a5fb68d5306e4d661b6 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 20 Aug 2025 23:04:11 +0700 Subject: [PATCH] temp remove pairs to merge other changes to dev --- README.md | 136 +-- develop/all.lua | 4 - develop/fuzzing/wildcard_fuzz.lua | 254 ----- develop/samples/relations.lua | 79 -- develop/testing/pairs_tests.lua | 1607 --------------------------- evolved.lua | 1675 ++++------------------------- 6 files changed, 185 insertions(+), 3570 deletions(-) delete mode 100644 develop/fuzzing/wildcard_fuzz.lua delete mode 100644 develop/samples/relations.lua delete mode 100644 develop/testing/pairs_tests.lua diff --git a/README.md b/README.md index e67b685..37d5738 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,6 @@ - [Aliases](#aliases) - [Predefs](#predefs) - [Functions](#functions) - - [Relations](#relations) - [Classes](#classes) - [Chunk](#chunk) - [Builder](#builder) @@ -1049,20 +1048,14 @@ remove_hook :: {entity, fragment, component} each_state :: implementation-specific execute_state :: implementation-specific -primaries_state :: implementation-specific -secondaries_state :: implementation-specific each_iterator :: {each_state? -> fragment?, component?} execute_iterator :: {execute_state? -> chunk?, entity[]?, integer?} -primaries_iterator :: {primaries_state? -> fragment?, component?} -secondaries_iterator :: {secondaries_state? -> fragment?, component?} ``` ### Predefs ``` -ANY :: fragment - TAG :: fragment NAME :: fragment @@ -1146,25 +1139,6 @@ debug_mode :: boolean -> () collect_garbage :: () ``` -### Relations - -``` -pair :: id, id -> id -unpair :: id -> id, id - -is_pair :: id -> boolean -is_wildcard :: id -> boolean - -primary :: entity, fragment, integer? -> fragment?, component? -secondary :: entity, fragment, integer? -> fragment?, component? - -primaries :: entity, fragment -> {primaries_state? -> fragment?, component?}, primaries_state? -secondaries :: entity, fragment -> {secondaries_state? -> fragment?, component?}, secondaries_state? - -primary_count :: entity, fragment -> integer -secondary_count :: entity, fragment -> integer -``` - ### Classes #### Chunk @@ -1254,8 +1228,6 @@ builder_mt:destruction_policy :: id -> builder ## Predefs -### `evolved.ANY` - ### `evolved.TAG` ### `evolved.NAME` @@ -1304,7 +1276,7 @@ builder_mt:destruction_policy :: id -> builder ### `evolved.DESTRUCTION_POLICY_REMOVE_FRAGMENT` -## Core Functions +## Functions ### `evolved.id` @@ -1572,112 +1544,6 @@ function evolved.debug_mode(yesno) end function evolved.collect_garbage() end ``` -## Relation Functions - -### `evolved.pair` - -```lua ----@param primary evolved.id ----@param secondary evolved.id ----@return evolved.id pair ----@nodiscard -function evolved.pair(primary, secondary) end -``` - -### `evolved.unpair` - -```lua ----@param pair evolved.id ----@return evolved.id primary ----@return evolved.id secondary ----@nodiscard -function evolved.unpair(pair) end -``` - -### `evolved.is_pair` - -```lua ----@param id evolved.id ----@return boolean ----@nodiscard -function evolved.is_pair(id) end -``` - -### `evolved.is_wildcard` - -```lua ----@param id evolved.id ----@return boolean ----@nodiscard -function evolved.is_wildcard(id) end -``` - -### `evolved.primary` - -```lua ----@param entity evolved.entity ----@param secondary evolved.fragment ----@param index? integer ----@return evolved.fragment? primary ----@return evolved.component? component ----@nodiscard -function evolved.primary(entity, secondary, index) end -``` - -### `evolved.secondary` - -```lua ----@param entity evolved.entity ----@param primary evolved.fragment ----@param index? integer ----@return evolved.fragment? secondary ----@return evolved.component? component ----@nodiscard -function evolved.secondary(entity, primary, index) end -``` - -### `evolved.primaries` - -```lua ----@param entity evolved.entity ----@param secondary evolved.fragment ----@return evolved.primaries_iterator iterator ----@return evolved.primaries_state? iterator_state ----@nodiscard -function evolved.primaries(entity, secondary) end -``` - -### `evolved.secondaries` - -```lua ----@param entity evolved.entity ----@param primary evolved.fragment ----@return evolved.secondaries_iterator iterator ----@return evolved.secondaries_state? iterator_state ----@nodiscard -function evolved.secondaries(entity, primary) end -``` - -### `evolved.primary_count` - -```lua ----@param entity evolved.entity ----@param secondary evolved.fragment ----@return integer ----@nodiscard -function evolved.primary_count(entity, secondary) end -``` - -### `evolved.secondary_count` - -```lua ----@param entity evolved.entity ----@param primary evolved.fragment ----@return integer ----@nodiscard -function evolved.secondary_count(entity, primary) end -``` - ## Classes ### Chunk diff --git a/develop/all.lua b/develop/all.lua index b5d6025..bd34bf9 100644 --- a/develop/all.lua +++ b/develop/all.lua @@ -1,8 +1,6 @@ -require 'develop.samples.relations' require 'develop.samples.systems' require 'develop.testing.name_tests' -require 'develop.testing.pairs_tests' require 'develop.testing.requires_fragment_tests' require 'develop.testing.system_as_query_tests' @@ -25,5 +23,3 @@ print '----------------------------------------' basics.describe_fuzz 'develop.fuzzing.requires_fuzz' print '----------------------------------------' basics.describe_fuzz 'develop.fuzzing.unique_fuzz' -print '----------------------------------------' -basics.describe_fuzz 'develop.fuzzing.wildcard_fuzz' diff --git a/develop/fuzzing/wildcard_fuzz.lua b/develop/fuzzing/wildcard_fuzz.lua deleted file mode 100644 index 916afc2..0000000 --- a/develop/fuzzing/wildcard_fuzz.lua +++ /dev/null @@ -1,254 +0,0 @@ -local evo = require 'evolved' - -evo.debug_mode(true) - ---- ---- ---- ---- ---- - -local __table_unpack = (function() - ---@diagnostic disable-next-line: deprecated - return table.unpack or unpack -end)() - ---- ---- ---- ---- ---- - -local all_entity_list = {} ---@type evolved.entity[] -local all_fragment_list = {} ---@type evolved.fragment[] - -for i = 1, math.random(1, 5) do - local fragment_builder = evo.builder() - - if math.random(1, 3) == 1 then - fragment_builder:explicit() - end - - if math.random(1, 3) == 1 then - if math.random(1, 2) == 1 then - fragment_builder:destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - else - fragment_builder:destruction_policy(evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT) - end - end - - all_fragment_list[i] = fragment_builder:spawn() -end - -for i = 1, math.random(50, 100) do - local entity_builder = evo.builder() - - for _ = 0, math.random(0, #all_fragment_list) do - if math.random(1, 2) == 1 then - local fragment = all_fragment_list[math.random(1, #all_fragment_list)] - entity_builder:set(fragment) - else - local primary = all_fragment_list[math.random(1, #all_fragment_list)] - local secondary = all_fragment_list[math.random(1, #all_fragment_list)] - entity_builder:set(evo.pair(primary, secondary)) - end - end - - all_entity_list[i] = entity_builder:spawn() -end - ---- ---- ---- ---- ---- - -for _ = 1, math.random(1, 100) do - local query_builder = evo.builder() - - local query_include_set = {} ---@type table - local query_include_list = {} ---@type evolved.entity[] - local query_include_count = 0 ---@type integer - - local query_exclude_set = {} ---@type table - local query_exclude_list = {} ---@type evolved.entity[] - local query_exclude_count = 0 ---@type integer - - for _ = 1, math.random(0, 2) do - if math.random(1, 2) == 1 then - local fragment = all_fragment_list[math.random(1, #all_fragment_list)] - - query_builder:include(fragment) - - if not query_include_set[fragment] then - query_include_count = query_include_count + 1 - query_include_set[fragment] = query_include_count - query_include_list[query_include_count] = fragment - end - else - local primary = all_fragment_list[math.random(1, #all_fragment_list)] - local secondary = all_fragment_list[math.random(1, #all_fragment_list)] - - if math.random(1, 3) == 1 then - primary = evo.ANY - end - - if math.random(1, 3) == 1 then - secondary = evo.ANY - end - - local pair = evo.pair(primary, secondary) - - query_builder:include(pair) - - if not query_include_set[pair] then - query_include_count = query_include_count + 1 - query_include_set[pair] = query_include_count - query_include_list[query_include_count] = pair - end - end - end - - for _ = 1, math.random(0, 2) do - if math.random(1, 2) == 1 then - local fragment = all_fragment_list[math.random(1, #all_fragment_list)] - - query_builder:exclude(fragment) - - if not query_exclude_set[fragment] then - query_exclude_count = query_exclude_count + 1 - query_exclude_set[fragment] = query_exclude_count - query_exclude_list[query_exclude_count] = fragment - end - else - local primary = all_fragment_list[math.random(1, #all_fragment_list)] - local secondary = all_fragment_list[math.random(1, #all_fragment_list)] - - if math.random(1, 3) == 1 then - primary = evo.ANY - end - - if math.random(1, 3) == 1 then - secondary = evo.ANY - end - - local pair = evo.pair(primary, secondary) - - query_builder:exclude(pair) - - if not query_exclude_set[pair] then - query_exclude_count = query_exclude_count + 1 - query_exclude_set[pair] = query_exclude_count - query_exclude_list[query_exclude_count] = pair - end - end - end - - local query_entity_set = {} ---@type table - local query_entity_count = 0 ---@type integer - - do - local query = query_builder:spawn() - - for chunk, entity_list, entity_count in evo.execute(query) do - if not chunk:has(evo.INTERNAL) then - for i = 1, entity_count do - local entity = entity_list[i] - assert(not query_entity_set[entity]) - query_entity_count = query_entity_count + 1 - query_entity_set[entity] = query_entity_count - end - end - end - - if query_entity_set[query] then - query_entity_set[query] = nil - query_entity_count = query_entity_count - 1 - end - - evo.destroy(query) - end - - do - local expected_entity_count = 0 - - for _, entity in ipairs(all_entity_list) do - local is_entity_expected = - not evo.empty(entity) and - evo.has_all(entity, __table_unpack(query_include_list)) and - not evo.has_any(entity, __table_unpack(query_exclude_list)) - - for fragment in evo.each(entity) do - if evo.has(fragment, evo.EXPLICIT) then - local is_fragment_included = - query_include_set[fragment] ~= nil or - query_include_set[evo.pair(fragment, evo.ANY)] ~= nil - - if not is_fragment_included then - is_entity_expected = false - break - end - end - end - - if is_entity_expected then - assert(query_entity_set[entity]) - expected_entity_count = expected_entity_count + 1 - else - assert(not query_entity_set[entity]) - end - end - - for _, entity in ipairs(all_fragment_list) do - local is_entity_expected = - not evo.empty(entity) and - evo.has_all(entity, __table_unpack(query_include_list)) and - not evo.has_any(entity, __table_unpack(query_exclude_list)) - - for fragment in evo.each(entity) do - if evo.has(fragment, evo.EXPLICIT) then - is_entity_expected = is_entity_expected and - (query_include_set[fragment] ~= nil) or - (evo.is_pair(fragment) and query_include_set[evo.pair(fragment, evo.ANY)] ~= nil) - end - end - - if is_entity_expected then - assert(query_entity_set[entity]) - expected_entity_count = expected_entity_count + 1 - else - assert(not query_entity_set[entity]) - end - end - - assert(query_entity_count == expected_entity_count) - end -end - ---- ---- ---- ---- ---- - -if math.random(1, 2) == 1 then - evo.collect_garbage() -end - -if math.random(1, 2) == 1 then - evo.destroy(__table_unpack(all_entity_list)) - if math.random(1, 2) == 1 then - evo.collect_garbage() - end - evo.destroy(__table_unpack(all_fragment_list)) -else - evo.destroy(__table_unpack(all_fragment_list)) - if math.random(1, 2) == 1 then - evo.collect_garbage() - end - evo.destroy(__table_unpack(all_entity_list)) -end - -if math.random(1, 2) == 1 then - evo.collect_garbage() -end diff --git a/develop/samples/relations.lua b/develop/samples/relations.lua deleted file mode 100644 index 6311fbe..0000000 --- a/develop/samples/relations.lua +++ /dev/null @@ -1,79 +0,0 @@ ----@diagnostic disable: unused-local - -local evo = require 'evolved' - -evo.debug_mode(true) - -local fragments = { - planet = evo.builder() - :name('planet') - :tag() - :spawn(), - spaceship = evo.builder() - :name('spaceship') - :tag() - :spawn(), -} - -local relations = { - docked_to = evo.builder() - :name('docked_to') - :tag() - :spawn(), -} - -local planets = { - mars = evo.builder() - :name('Mars') - :set(fragments.planet) - :spawn(), - venus = evo.builder() - :name('Venus') - :set(fragments.planet) - :spawn(), -} - -local spaceships = { - falcon = evo.builder() - :name('Millennium Falcon') - :set(fragments.spaceship) - :set(evo.pair(relations.docked_to, planets.mars)) - :spawn(), - enterprise = evo.builder() - :name('USS Enterprise') - :set(fragments.spaceship) - :set(evo.pair(relations.docked_to, planets.venus)) - :spawn(), -} - -local queries = { - all_docked_spaceships = evo.builder() - :include(fragments.spaceship) - :include(evo.pair(relations.docked_to, evo.ANY)) - :spawn(), - docked_spaceships_to_mars = evo.builder() - :include(fragments.spaceship) - :include(evo.pair(relations.docked_to, planets.mars)) - :spawn(), - -} - -print '-= | All Docked Spaceships | =-' - -for chunk, entity_list, entity_count in evo.execute(queries.all_docked_spaceships) do - for i = 1, entity_count do - local entity = entity_list[i] - local planet = evo.secondary(entity, relations.docked_to) - print(string.format('%s is docked to %s', evo.name(entity), evo.name(planet))) - end -end - -print '-= | Docked Spaceships to Mars | =-' - -for chunk, entity_list, entity_count in evo.execute(queries.docked_spaceships_to_mars) do - for i = 1, entity_count do - local entity = entity_list[i] - local planet = evo.secondary(entity, relations.docked_to) - print(string.format('%s is docked to %s', evo.name(entity), evo.name(planet))) - end -end diff --git a/develop/testing/pairs_tests.lua b/develop/testing/pairs_tests.lua deleted file mode 100644 index e5982bd..0000000 --- a/develop/testing/pairs_tests.lua +++ /dev/null @@ -1,1607 +0,0 @@ -local evo = require 'evolved' - -do - local p1, s1 = evo.id(2) - local pair1 = evo.pair(p1, s1) - local p2, s2 = evo.unpair(pair1) - assert(p1 == p2 and s1 == s2) -end - -do - local p, s1, s2 = evo.id(3) - - local e1 = evo.id() - evo.set(e1, evo.pair(p, s1), 11) - - local e12 = evo.id() - evo.set(e12, evo.pair(p, s1), 21) - evo.set(e12, evo.pair(p, s2), 42) - - assert(evo.has(e1, evo.pair(p, s1))) - assert(evo.get(e1, evo.pair(p, s1)) == 11) - assert(evo.has(e12, evo.pair(p, s1))) - assert(evo.get(e12, evo.pair(p, s1)) == 21) - - assert(not evo.has(e1, evo.pair(p, s2))) - assert(evo.get(e1, evo.pair(p, s2)) == nil) - assert(evo.has(e12, evo.pair(p, s2))) - assert(evo.get(e12, evo.pair(p, s2)) == 42) - - assert(evo.has(e1, evo.pair(p, evo.ANY))) - assert(evo.has(e1, evo.pair(evo.ANY, s1))) - assert(not evo.has(e1, evo.pair(evo.ANY, s2))) - assert(evo.has(e12, evo.pair(p, evo.ANY))) - assert(evo.has(e12, evo.pair(evo.ANY, s1))) - assert(evo.has(e12, evo.pair(evo.ANY, s2))) - - assert(not evo.has_all(e1, evo.pair(evo.ANY, s1), evo.pair(evo.ANY, s2))) - assert(evo.has_any(e1, evo.pair(evo.ANY, s1), evo.pair(evo.ANY, s2))) - assert(evo.has_all(e12, evo.pair(evo.ANY, s1), evo.pair(evo.ANY, s2))) - assert(evo.has_any(e12, evo.pair(evo.ANY, s1), evo.pair(evo.ANY, s2))) -end - -do - local p1, p2, s = evo.id(3) - - local e1 = evo.id() - evo.set(e1, evo.pair(p1, s), 11) - - local e12 = evo.id() - evo.set(e12, evo.pair(p1, s), 21) - evo.set(e12, evo.pair(p2, s), 42) - - assert(evo.has(e1, evo.pair(p1, s))) - assert(evo.get(e1, evo.pair(p1, s)) == 11) - assert(evo.has(e12, evo.pair(p1, s))) - assert(evo.get(e12, evo.pair(p1, s)) == 21) - - assert(not evo.has(e1, evo.pair(p2, s))) - assert(evo.get(e1, evo.pair(p2, s)) == nil) - assert(evo.has(e12, evo.pair(p2, s))) - assert(evo.get(e12, evo.pair(p2, s)) == 42) - - assert(evo.has(e1, evo.pair(p1, evo.ANY))) - assert(not evo.has(e1, evo.pair(p2, evo.ANY))) - assert(evo.has(e1, evo.pair(evo.ANY, s))) - assert(evo.has(e12, evo.pair(p1, evo.ANY))) - assert(evo.has(e12, evo.pair(p2, evo.ANY))) - assert(evo.has(e12, evo.pair(evo.ANY, s))) - - assert(not evo.has_all(e1, evo.pair(p1, evo.ANY), evo.pair(p2, evo.ANY))) - assert(evo.has_any(e1, evo.pair(p1, evo.ANY), evo.pair(p2, evo.ANY))) - assert(evo.has_all(e12, evo.pair(p1, evo.ANY), evo.pair(p2, evo.ANY))) - assert(evo.has_any(e12, evo.pair(p1, evo.ANY), evo.pair(p2, evo.ANY))) -end - -do - local p1, s1, p2, s2 = evo.id(4) - evo.set(p1, s1) - evo.set(s1, p1) - evo.set(p2, s2) - assert(not evo.empty(evo.pair(p1, s1))) - assert(not evo.empty(evo.pair(p2, s2))) - assert(not evo.empty_all(evo.pair(p1, s1), evo.pair(p2, s2))) - assert(not evo.empty_any(evo.pair(p1, s1), evo.pair(p2, s2))) - assert(not evo.empty_all(evo.pair(p1, s1), evo.pair(p2, s2), p1)) - assert(not evo.empty_any(evo.pair(p1, s1), evo.pair(p2, s2), p1)) - assert(not evo.empty_all(evo.pair(p1, s1), evo.pair(p2, s2), s2)) - assert(evo.empty_any(evo.pair(p1, s1), evo.pair(p2, s2), s2)) -end - -do - local p1, s1 = evo.id(2) - evo.set(p1, s1) - evo.set(s1, p1) - assert(not evo.has(evo.pair(p1, s1), p1)) - assert(evo.has(evo.pair(p1, s1), s1)) - assert(not evo.has_all(evo.pair(p1, s1), p1, s1)) - assert(evo.has_any(evo.pair(p1, s1), p1, s1)) - assert(evo.get(evo.pair(p1, s1), p1) == nil) - assert(evo.get(evo.pair(p1, s1), s1) == true) -end - -do - local p, s1, s2 = evo.id(3) - - do - local e = evo.builder() - :set(evo.pair(p, s1), 21) - :set(evo.pair(p, s2), 42) - :spawn() - - evo.remove(e, evo.pair(p, s1)) - - assert(not evo.has(e, evo.pair(p, s1))) - assert(evo.get(e, evo.pair(p, s1)) == nil) - - assert(evo.has(e, evo.pair(p, s2))) - assert(evo.get(e, evo.pair(p, s2)) == 42) - - evo.remove(e, evo.pair(p, s2)) - - assert(not evo.has(e, evo.pair(p, s2))) - assert(evo.get(e, evo.pair(p, s2)) == nil) - - assert(not evo.has(e, evo.pair(p, s2))) - assert(evo.get(e, evo.pair(p, s2)) == nil) - end - - do - local e = evo.builder() - :set(evo.pair(p, s1), 21) - :set(evo.pair(p, s2), 42) - :spawn() - - evo.remove(e, evo.pair(p, s2)) - - assert(evo.has(e, evo.pair(p, s1))) - assert(evo.get(e, evo.pair(p, s1)) == 21) - - assert(not evo.has(e, evo.pair(p, s2))) - assert(evo.get(e, evo.pair(p, s2)) == nil) - - evo.remove(e, evo.pair(p, s1)) - - assert(not evo.has(e, evo.pair(p, s1))) - assert(evo.get(e, evo.pair(p, s1)) == nil) - - assert(not evo.has(e, evo.pair(p, s2))) - assert(evo.get(e, evo.pair(p, s2)) == nil) - end -end - -do - local p1, p2, s1, s2 = evo.id(4) - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 11) - :set(evo.pair(p1, s2), 12) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 22) - :spawn() - - evo.remove(e, evo.pair(p1, evo.ANY)) - - assert(not evo.has(e, evo.pair(p1, s1))) - assert(not evo.has(e, evo.pair(p1, s2))) - assert(not evo.has(e, evo.pair(p1, evo.ANY))) - - assert(evo.has(e, evo.pair(p2, s1))) - assert(evo.get(e, evo.pair(p2, s1)) == 21) - assert(evo.has(e, evo.pair(p2, s2))) - assert(evo.get(e, evo.pair(p2, s2)) == 22) - assert(evo.has(e, evo.pair(p2, evo.ANY))) - end - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 11) - :set(evo.pair(p1, s2), 12) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 22) - :spawn() - - evo.remove(e, evo.pair(p2, evo.ANY)) - - assert(not evo.has(e, evo.pair(p2, s1))) - assert(not evo.has(e, evo.pair(p2, s2))) - assert(not evo.has(e, evo.pair(p2, evo.ANY))) - - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == 11) - assert(evo.has(e, evo.pair(p1, s2))) - assert(evo.get(e, evo.pair(p1, s2)) == 12) - assert(evo.has(e, evo.pair(p1, evo.ANY))) - end - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 11) - :set(evo.pair(p1, s2), 12) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 22) - :spawn() - - evo.remove(e, evo.pair(evo.ANY, s1)) - - assert(not evo.has(e, evo.pair(p1, s1))) - assert(not evo.has(e, evo.pair(p2, s1))) - assert(not evo.has(e, evo.pair(evo.ANY, s1))) - - assert(evo.has(e, evo.pair(p1, s2))) - assert(evo.get(e, evo.pair(p1, s2)) == 12) - assert(evo.has(e, evo.pair(p2, s2))) - assert(evo.get(e, evo.pair(p2, s2)) == 22) - end - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 11) - :set(evo.pair(p1, s2), 12) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 22) - :spawn() - - evo.remove(e, evo.pair(evo.ANY, s2)) - - assert(not evo.has(e, evo.pair(p1, s2))) - assert(not evo.has(e, evo.pair(p2, s2))) - assert(not evo.has(e, evo.pair(evo.ANY, s2))) - - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == 11) - assert(evo.has(e, evo.pair(p2, s1))) - assert(evo.get(e, evo.pair(p2, s1)) == 21) - end - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 11) - :set(evo.pair(p1, s2), 12) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 22) - :set(p1, s1) - :set(p2, s2) - :spawn() - - evo.remove(e, evo.pair(evo.ANY, evo.ANY)) - - assert(not evo.has(e, evo.pair(p1, s1))) - assert(not evo.has(e, evo.pair(p1, s2))) - assert(not evo.has(e, evo.pair(p2, s1))) - assert(not evo.has(e, evo.pair(p2, s2))) - - assert(evo.has(e, p1) and evo.get(e, p1) == s1) - assert(evo.has(e, p2) and evo.get(e, p2) == s2) - end -end - -do - local p1, s1, p2, s2 = evo.id(4) - - local e = evo.builder() - :set(evo.pair(p1, s1), 42) - :spawn() - - evo.remove(e, evo.pair(p2, evo.ANY)) - evo.remove(e, evo.pair(evo.ANY, s2)) - - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == 42) - - evo.remove(e, evo.pair(p1, s1)) - - assert(not evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == nil) -end - -do - local f1, f2, f3, p1, s1, p2, s2 = evo.id(7) - evo.set(f1, evo.REQUIRES, { f2 }) - evo.set(f2, evo.DEFAULT, 84) - evo.set(f2, evo.REQUIRES, { evo.pair(p2, s2) }) - evo.set(p1, evo.REQUIRES, { f3 }) - evo.set(s1, evo.REQUIRES, { f3 }) - evo.set(p2, evo.REQUIRES, { f3 }) - evo.set(s2, evo.REQUIRES, { f3 }) - - local e = evo.builder() - :set(f1, 21) - :set(evo.pair(p1, s1), 42) - :spawn() - - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == 42) - - assert(evo.has(e, evo.pair(p2, s2))) - assert(evo.get(e, evo.pair(p2, s2)) == true) - - assert(evo.has(e, f1)) - assert(evo.get(e, f1) == 21) - - assert(evo.has(e, f2)) - assert(evo.get(e, f2) == 84) - - assert(evo.has(e, f3)) - assert(evo.get(e, f3) == true) -end - -do - local p1, p2, s1, s2 = evo.id(4) - - do - local e1 = evo.builder() - :set(evo.pair(p1, s1)) - :set(evo.pair(p1, s2)) - :spawn() - - local e2 = evo.clone(e1) - - evo.remove(e1, evo.pair(p1, evo.ANY)) - evo.remove(e2, evo.pair(p1, evo.ANY)) - assert(evo.empty_all(e1, e2)) - end - - do - local e1 = evo.builder() - :set(evo.pair(p1, s1)) - :set(evo.pair(p2, s1)) - :spawn() - - local e2 = evo.clone(e1) - - evo.remove(e1, evo.pair(evo.ANY, s1)) - evo.remove(e2, evo.pair(evo.ANY, s1)) - assert(evo.empty_all(e1, e2)) - end - - do - local e1 = evo.builder() - :set(evo.pair(p1, s1)) - :set(evo.pair(p1, s2)) - :set(evo.pair(p2, s1)) - :set(evo.pair(p2, s2)) - :spawn() - - local e2 = evo.clone(e1) - - evo.remove(e1, evo.pair(evo.ANY, evo.ANY)) - evo.remove(e2, evo.pair(evo.ANY, evo.ANY)) - assert(evo.empty_all(e1, e2)) - end -end - -do - local f, p1, p2, s1, s2 = evo.id(5) - - do - local e1 = evo.builder() - :set(f, 42) - :set(evo.pair(p1, s1)) - :set(evo.pair(p1, s2)) - :spawn() - - local e2 = evo.clone(e1) - - evo.remove(e1, evo.pair(p1, evo.ANY)) - evo.remove(e2, evo.pair(p1, evo.ANY)) - - assert(evo.has(e1, f) and evo.has(e2, f)) - assert(not evo.has(e1, evo.pair(evo.ANY, evo.ANY))) - end - - do - local e1 = evo.builder() - :set(f, 42) - :set(evo.pair(p1, s1)) - :set(evo.pair(p2, s1)) - :spawn() - - local e2 = evo.clone(e1) - - evo.remove(e1, evo.pair(evo.ANY, s1)) - evo.remove(e2, evo.pair(evo.ANY, s1)) - - assert(evo.has(e1, f) and evo.has(e2, f)) - assert(not evo.has(e1, evo.pair(evo.ANY, evo.ANY))) - end - - do - local e1 = evo.builder() - :set(f, 42) - :set(evo.pair(p1, s1)) - :set(evo.pair(p1, s2)) - :set(evo.pair(p2, s1)) - :set(evo.pair(p2, s2)) - :spawn() - - local e2 = evo.clone(e1) - - evo.remove(e1, evo.pair(evo.ANY, evo.ANY)) - evo.remove(e2, evo.pair(evo.ANY, evo.ANY)) - - assert(evo.has(e1, f) and evo.has(e2, f)) - assert(not evo.has(e1, evo.pair(evo.ANY, evo.ANY))) - end -end - -do - do - local p, s = evo.id(2) - evo.set(p, evo.NAME, 'p') - evo.set(s, evo.NAME, 's') - local ps_chunk = evo.chunk(evo.pair(p, s)) - assert(tostring(ps_chunk) == '<${p,s}>') - end - do - local p, s = evo.id(2) - local ps_chunk = evo.chunk(evo.pair(p, s)) - evo.set(p, evo.NAME, 'p') - evo.set(s, evo.NAME, 's') - evo.destroy(p) - assert(tostring(ps_chunk) ~= '<${p,s}>') - end - do - local p, s = evo.id(2) - local ps_chunk = evo.chunk(evo.pair(p, s)) - evo.set(p, evo.NAME, 'p') - evo.set(s, evo.NAME, 's') - evo.destroy(s) - assert(tostring(ps_chunk) ~= '<${p,s}>') - end - do - local p, s = evo.id(2) - local ps_chunk = evo.chunk(evo.pair(p, s)) - evo.set(p, evo.NAME, 'p') - evo.set(s, evo.NAME, 's') - evo.destroy(p, s) - assert(tostring(ps_chunk) ~= '<${p,s}>') - end -end - -do - do - local p, s = evo.id(2) - local ps = evo.pair(evo.ANY, s) - local e = evo.id() - evo.set(e, p, 42) - evo.destroy(s) - evo.remove(e, ps) - end - - do - local p, s = evo.id(2) - local ps = evo.pair(p, evo.ANY) - local e = evo.id() - evo.set(e, s, 42) - evo.destroy(p) - evo.remove(e, ps) - end -end - -do - local p, s = evo.id(2) - - local e = evo.id() - assert(not evo.has(e, evo.pair(p, s))) - assert(not evo.has(e, evo.pair(p, evo.ANY))) - assert(not evo.has(e, evo.pair(evo.ANY, s))) - assert(not evo.has(e, evo.pair(evo.ANY, evo.ANY))) - - evo.set(e, p) - assert(not evo.has(e, evo.pair(p, s))) - assert(not evo.has(e, evo.pair(p, evo.ANY))) - assert(not evo.has(e, evo.pair(evo.ANY, s))) - assert(not evo.has(e, evo.pair(evo.ANY, evo.ANY))) - - evo.set(e, s) - assert(not evo.has(e, evo.pair(p, s))) - assert(not evo.has(e, evo.pair(p, evo.ANY))) - assert(not evo.has(e, evo.pair(evo.ANY, s))) - assert(not evo.has(e, evo.pair(evo.ANY, evo.ANY))) - - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, evo.pair(p, s))) - assert(evo.has(e, evo.pair(p, evo.ANY))) - assert(evo.has(e, evo.pair(evo.ANY, s))) - assert(evo.has(e, evo.pair(evo.ANY, evo.ANY))) -end - -do - local p1, s1, p2, s2 = evo.id(4) - - local e = evo.builder():set(evo.pair(p1, s1)):spawn() - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.has(e, evo.pair(p1, evo.ANY))) - assert(evo.has(e, evo.pair(evo.ANY, s1))) - assert(evo.has(e, evo.pair(evo.ANY, evo.ANY))) - assert(not evo.has(e, evo.pair(p1, s2))) - assert(not evo.has(e, evo.pair(p2, s1))) - assert(not evo.has(e, evo.pair(p2, s2))) - assert(not evo.has(e, evo.pair(p2, evo.ANY))) - assert(not evo.has(e, evo.pair(evo.ANY, s2))) - - evo.set(e, evo.pair(p2, s2)) - - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.has(e, evo.pair(p1, evo.ANY))) - assert(evo.has(e, evo.pair(evo.ANY, s1))) - assert(evo.has(e, evo.pair(evo.ANY, evo.ANY))) - assert(not evo.has(e, evo.pair(p1, s2))) - assert(not evo.has(e, evo.pair(p2, s1))) - assert(evo.has(e, evo.pair(p2, s2))) - assert(evo.has(e, evo.pair(p2, evo.ANY))) - assert(evo.has(e, evo.pair(evo.ANY, s2))) -end - -do - local p1, s1, s2 = evo.id(3) - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 42) - :spawn() - - evo.set(e, evo.pair(p1, s1), 84) - assert(evo.get(e, evo.pair(p1, s1)) == 84) - assert(evo.get(e, evo.pair(p1, s2)) == nil) - - evo.set(e, evo.pair(p1, s2), 42) - assert(evo.get(e, evo.pair(p1, s1)) == 84) - assert(evo.get(e, evo.pair(p1, s2)) == 42) - end -end - -do - local p1, s1, p2, s2 = evo.id(4) - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 42) - :set(evo.pair(p1, s2), 84) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 63) - :spawn() - - evo.remove(e, evo.pair(p1, evo.ANY)) - assert(not evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == nil) - assert(not evo.has(e, evo.pair(p1, s2))) - assert(evo.get(e, evo.pair(p1, s2)) == nil) - assert(evo.has(e, evo.pair(p2, s1))) - assert(evo.get(e, evo.pair(p2, s1)) == 21) - assert(evo.has(e, evo.pair(p2, s2))) - assert(evo.get(e, evo.pair(p2, s2)) == 63) - end - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 42) - :set(evo.pair(p1, s2), 84) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 63) - :spawn() - - evo.remove(e, evo.pair(evo.ANY, s2)) - assert(evo.has(e, evo.pair(p1, s1))) - assert(evo.get(e, evo.pair(p1, s1)) == 42) - assert(not evo.has(e, evo.pair(p1, s2))) - assert(evo.get(e, evo.pair(p1, s2)) == nil) - assert(evo.has(e, evo.pair(p2, s1))) - assert(evo.get(e, evo.pair(p2, s1)) == 21) - assert(not evo.has(e, evo.pair(p2, s2))) - assert(evo.get(e, evo.pair(p2, s2)) == nil) - end -end - -do - local p1, p2, s1, s2 = evo.id(4) - - ---@param o evolved.entity - ---@param s evolved.fragment - ---@return evolved.fragment[], evolved.component[], number - local function collect_primaries(o, s) - local fragments, components, count = {}, {}, 0 - - for f, c in evo.primaries(o, s) do - count = count + 1 - - fragments[count] = f - components[count] = c - - do - local ff, cc = evo.primary(o, s, count) - assert(ff == f and cc == c) - end - end - - assert(evo.primary_count(o, s) == count) - return fragments, components, count - end - - ---@param o evolved.entity - ---@param p evolved.fragment - ---@return evolved.fragment[], evolved.component[], number - local function collect_secondaries(o, p) - local fragments, components, count = {}, {}, 0 - - for f, c in evo.secondaries(o, p) do - count = count + 1 - fragments[count] = f - components[count] = c - end - - return fragments, components, count - end - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 42) - :spawn() - - assert(evo.primary(e, s1) == p1) - assert(evo.primary(e, s2) == nil) - - assert(evo.secondary(e, p1) == s1) - assert(evo.secondary(e, p2) == nil) - - assert(evo.primary_count(e, s1) == 1) - assert(evo.primary_count(e, s2) == 0) - assert(evo.secondary_count(e, p1) == 1) - assert(evo.secondary_count(e, p2) == 0) - - do - local p_list, c_list, count = collect_primaries(e, s1) - assert(#p_list == 1 and #c_list == 1 and count == 1) - assert(p_list[1] == p1 and c_list[1] == 42) - end - - do - local p_list, c_list, count = collect_primaries(e, s2) - assert(#p_list == 0 and #c_list == 0 and count == 0) - end - - do - local s_list, c_list, count = collect_secondaries(e, p1) - assert(#s_list == 1 and #c_list == 1 and count == 1) - assert(s_list[1] == s1 and c_list[1] == 42) - end - - do - local s_list, c_list, count = collect_secondaries(e, p2) - assert(#s_list == 0 and #c_list == 0 and count == 0) - end - end - - do - local e = evo.builder() - :set(evo.pair(p1, s1), 42) - :set(evo.pair(p1, s2), 84) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 63) - :spawn() - - do - assert(evo.primary_count(e, s1) == 2) - assert(evo.primary_count(e, s2) == 2) - assert(evo.secondary_count(e, p1) == 2) - assert(evo.secondary_count(e, p2) == 2) - end - - do - local pp, cc = evo.primary(e, s1) - assert(pp == p1 and cc == 42) - - pp, cc = evo.primary(e, s1, 1) - assert(pp == p1 and cc == 42) - - pp, cc = evo.primary(e, s1, 2) - assert(pp == p2 and cc == 21) - - pp, cc = evo.primary(e, s1, 3) - assert(pp == nil and cc == nil) - end - - do - local pp, cc = evo.primary(e, s2) - assert(pp == p1 and cc == 84) - - pp, cc = evo.primary(e, s2, 1) - assert(pp == p1 and cc == 84) - - pp, cc = evo.primary(e, s2, 2) - assert(pp == p2 and cc == 63) - - pp, cc = evo.primary(e, s2, 3) - assert(pp == nil and cc == nil) - end - - do - local pp, cc = evo.secondary(e, p1) - assert(pp == s1 and cc == 42) - - pp, cc = evo.secondary(e, p1, 1) - assert(pp == s1 and cc == 42) - - pp, cc = evo.secondary(e, p1, 2) - assert(pp == s2 and cc == 84) - - pp, cc = evo.secondary(e, p1, 3) - assert(pp == nil and cc == nil) - end - - do - local pp, cc = evo.secondary(e, p2) - assert(pp == s1 and cc == 21) - - pp, cc = evo.secondary(e, p2, 1) - assert(pp == s1 and cc == 21) - - pp, cc = evo.secondary(e, p2, 2) - assert(pp == s2 and cc == 63) - - pp, cc = evo.secondary(e, p2, 3) - assert(pp == nil and cc == nil) - end - - do - local p_list, c_list, count = collect_primaries(e, s1) - assert(#p_list == 2 and #c_list == 2 and count == 2) - assert(p_list[1] == p1 and c_list[1] == 42) - assert(p_list[2] == p2 and c_list[2] == 21) - end - - do - local p_list, c_list, count = collect_primaries(e, s2) - assert(#p_list == 2 and #c_list == 2 and count == 2) - assert(p_list[1] == p1 and c_list[1] == 84) - assert(p_list[2] == p2 and c_list[2] == 63) - end - - do - local s_list, c_list, count = collect_secondaries(e, p1) - assert(#s_list == 2 and #c_list == 2 and count == 2) - assert(s_list[1] == s1 and c_list[1] == 42) - assert(s_list[2] == s2 and c_list[2] == 84) - end - - do - local s_list, c_list, count = collect_secondaries(e, p2) - assert(#s_list == 2 and #c_list == 2 and count == 2) - assert(s_list[1] == s1 and c_list[1] == 21) - assert(s_list[2] == s2 and c_list[2] == 63) - end - end -end - -do - local p, s = evo.id(2) - - local e = evo.id() - - assert(not evo.primary(e, s)) - assert(not evo.primary(e, s, 1)) - assert(not evo.primary(e, s, 2)) - assert(not evo.primary(e, s, 0)) - assert(not evo.primary(e, s, -1)) - assert(not evo.primary(e, s, -2)) - - assert(not evo.secondary(e, p)) - assert(not evo.secondary(e, p, 1)) - assert(not evo.secondary(e, p, 2)) - assert(not evo.secondary(e, p, 0)) - assert(not evo.secondary(e, p, -1)) - assert(not evo.secondary(e, p, -2)) - - assert(evo.primary_count(e, s) == 0) - assert(evo.secondary_count(e, p) == 0) - - assert(evo.primaries(e, s)() == nil) - assert(evo.secondaries(e, p)() == nil) -end - -do - local p1, p2, s1, s2 = evo.id(4) - - local e = evo.builder() - :set(evo.pair(p1, s1), 42) - :set(evo.pair(p1, s2), 84) - :set(evo.pair(p2, s1), 21) - :set(evo.pair(p2, s2), 63) - :spawn() - - assert(evo.primary(e, evo.ANY) == nil) - assert(evo.primary(e, evo.ANY, 1) == nil) - assert(evo.primary(e, evo.ANY, 2) == nil) - - assert(evo.secondary(e, evo.ANY) == nil) - assert(evo.secondary(e, evo.ANY, 1) == nil) - assert(evo.secondary(e, evo.ANY, 2) == nil) - - assert(evo.primaries(e, evo.ANY)() == nil) - assert(evo.secondaries(e, evo.ANY)() == nil) - - assert(evo.primary_count(e, evo.ANY) == 0) - assert(evo.secondary_count(e, evo.ANY) == 0) -end - -do - do - local p, s = evo.id(2) - - local e = evo.builder() - :set(s) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(p) - assert(evo.alive(e)) - assert(evo.has(e, s)) - assert(not evo.has(e, evo.pair(p, s))) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local p, s = evo.id(2) - - local e = evo.builder() - :set(p) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(s) - assert(evo.alive(e)) - assert(evo.has(e, p)) - assert(not evo.has(e, evo.pair(p, s))) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local p, s = evo.id(2) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder() - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(p) - assert(not evo.alive(e)) - end - - do - local p, s = evo.id(2) - evo.set(s, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder() - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(s) - assert(not evo.alive(e)) - end -end - -do - local p1, s1 = evo.id(2) - - local e0 = evo.builder() - :destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - :spawn() - - local e1 = evo.builder() - :set(evo.pair(p1, e0), 11) - :destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - :spawn() - - local e2 = evo.builder() - :set(evo.pair(e1, s1), 22) - :destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - :spawn() - - local e3 = evo.builder() - :set(evo.pair(e2, e2), 33) - :spawn() - - evo.destroy(e0) - assert(not evo.alive(e1)) - assert(not evo.alive(e2)) - assert(not evo.alive(e3)) -end - -do - do - local f, p, s = evo.id(3) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(f) - assert(evo.get(e, f) == nil) - assert(evo.get(e, evo.pair(p, s)) == 42) - end - - do - local f, p, s = evo.id(3) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(p) - assert(evo.get(e, f) == 21) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(s) - assert(evo.get(e, f) == 21) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(p, s) - assert(evo.get(e, f) == 21) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(f, p, s) - assert(evo.alive(e) and evo.empty(e)) - end -end - -do - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(p) - assert(not evo.alive(e)) - end - - do - local f, p, s = evo.id(3) - evo.set(s, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(p) - assert(evo.get(e, f) == 21) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(s) - assert(evo.get(e, f) == 21) - assert(evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(s, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(s) - assert(not evo.alive(e)) - end -end - -do - local f, p, s = evo.id(3) - - local e = evo.builder():set(f, 21):set(evo.pair(p, s), 42):spawn() - - evo.destroy(evo.pair(p, s)) - evo.destroy(evo.pair(evo.ANY, s)) - evo.destroy(evo.pair(p, evo.ANY)) - evo.destroy(evo.pair(evo.ANY, evo.ANY)) - - assert(evo.get(e, f) == 21) - assert(evo.get(e, evo.pair(p, s)) == 42) -end - -do - evo.collect_garbage() - - local f, p1, s1, p2, s2 = evo.id(5) - - local e1 = evo.builder() - :set(f, 21) - :set(evo.pair(p1, s1), 42) - :set(evo.pair(p2, s2), 84) - :spawn() - - local e2 = evo.builder() - :set(f, 21) - :set(evo.pair(p1, s1), 42) - :set(evo.pair(p2, s2), 84) - :spawn() - - local f_chunk = evo.chunk(f) - local f_p2s2_chunk = evo.chunk(f, evo.pair(p2, s2)) - local f_p1s1_p2s2_chunk = evo.chunk(f, evo.pair(p1, s1), evo.pair(p2, s2)) - - assert(f_p1s1_p2s2_chunk:entities()[1] == e1) - assert(f_p1s1_p2s2_chunk:entities()[2] == e2) - - evo.remove(e1, evo.pair(p1, evo.ANY)) - - assert(f_p2s2_chunk:entities()[1] == e1) - assert(f_p1s1_p2s2_chunk:entities()[1] == e2) - - evo.remove(e1, evo.pair(p2, evo.ANY)) - - assert(f_chunk:entities()[1] == e1) - assert(f_p1s1_p2s2_chunk:entities()[1] == e2) - - evo.collect_garbage() - - assert(f_chunk:alive()) - assert(not f_p2s2_chunk:alive()) - assert(f_p1s1_p2s2_chunk:alive()) - - evo.remove(e2, evo.pair(p1, evo.ANY)) - - local new_f_p2s2_chunk = evo.chunk(f, evo.pair(p2, s2)) - assert(new_f_p2s2_chunk:entities()[1] == e2) -end - -do - evo.collect_garbage() - - local f, p1, p2, s1, s2 = evo.id(5) - - local e1 = evo.builder() - :set(f, 21) - :set(evo.pair(p1, s1), 42) - :set(evo.pair(p2, s2), 84) - :spawn() - - local f_p1s1_p2s2_chunk = evo.chunk(f, evo.pair(p1, s1), evo.pair(p2, s2)) - assert(f_p1s1_p2s2_chunk:entities()[1] == e1) - - evo.destroy(p2, s2) - - evo.collect_garbage() - - local f_p1s1_chunk = evo.chunk(f, evo.pair(p1, s1)) - assert(f_p1s1_chunk:entities()[1] == e1) -end - -do - local f, p, s = evo.id(3) - evo.set(p, evo.DEFAULT, 42) - - do - local e = evo.id() - evo.set(e, f) - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end - - do - local e = evo.builder():set(f):set(evo.pair(p, s)):spawn() - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end - - do - local e = evo.builder():set(f, 84):set(evo.pair(p, s), 21):spawn() - evo.set(e, f) - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end -end - -do - do - local f, p, s = evo.id(3) - assert(evo.empty(evo.pair(p, s))) - - evo.set(p, f) - assert(not evo.empty(evo.pair(p, s))) - - evo.destroy(p) - assert(evo.empty(evo.pair(p, s))) - end - - do - local f, p, s = evo.id(3) - assert(evo.empty(evo.pair(p, s))) - - evo.set(p, f) - assert(not evo.empty(evo.pair(p, s))) - - evo.destroy(s) - assert(not evo.empty(evo.pair(p, s))) - - evo.destroy(p) - assert(evo.empty(evo.pair(p, s))) - end - - do - local f, p, s = evo.id(3) - assert(not evo.has(p, f)) - assert(not evo.has(evo.pair(p, s), f)) - - evo.set(p, f, 42) - assert(evo.has(p, f)) - assert(evo.has(evo.pair(p, s), f)) - assert(not evo.has(evo.pair(s, p), f)) - assert(evo.get(p, f) == 42) - assert(evo.get(evo.pair(p, s), f) == 42) - assert(evo.get(evo.pair(s, p), f) == nil) - end -end - -do - local p, s = evo.id(3) - - local set_count = 0 - local insert_count = 0 - local remove_count = 0 - - evo.set(p, evo.ON_SET, function(e, f, nc, oc) - set_count = set_count + 1 - assert(f == p or f == evo.pair(p, s)) - assert(nc == 21 or nc == 42) - assert(oc == nil or oc == 21) - assert(evo.has(e, f)) - assert(evo.get(e, f) == nc) - end) - - evo.set(p, evo.ON_INSERT, function(e, f, nc) - insert_count = insert_count + 1 - assert(f == p or f == evo.pair(p, s)) - assert(nc == 21 or nc == 42) - assert(evo.has(e, f)) - assert(evo.get(e, f) == nc) - end) - - evo.set(p, evo.ON_REMOVE, function(e, f, oc) - remove_count = remove_count + 1 - assert(f == p or f == evo.pair(p, s)) - assert(oc == 21 or oc == 42) - assert(not evo.has(e, f)) - end) - - do - set_count, insert_count, remove_count = 0, 0, 0 - local e = evo.id() - evo.set(e, p, 21) - evo.set(e, evo.pair(p, s), 42) - assert(set_count == 2) - assert(insert_count == 2) - assert(remove_count == 0) - evo.remove(e, p) - assert(set_count == 2) - assert(insert_count == 2) - assert(remove_count == 1) - evo.remove(e, evo.pair(p, s)) - assert(set_count == 2) - assert(insert_count == 2) - assert(remove_count == 2) - end - - do - set_count, insert_count, remove_count = 0, 0, 0 - local e = evo.id() - evo.set(e, p, 21) - evo.set(e, evo.pair(p, s), 42) - assert(set_count == 2) - assert(insert_count == 2) - assert(remove_count == 0) - evo.destroy(e) - assert(set_count == 2) - assert(insert_count == 2) - assert(remove_count == 2) - end -end - -do - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder() - :set(f, 21) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(p) - - assert(not evo.alive(e) and evo.empty(e)) - assert(not evo.has(e, f) and evo.get(e, f) == nil) - assert(not evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder() - :set(f, 21) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(s) - - assert(evo.alive(e) and not evo.empty(e)) - assert(evo.has(e, f) and evo.get(e, f) == 21) - assert(not evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT) - - local e = evo.builder() - :set(f, 21) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(p) - - assert(evo.alive(e) and not evo.empty(e)) - assert(evo.has(e, f) and evo.get(e, f) == 21) - assert(not evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT) - - local e = evo.builder() - :set(f, 21) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(s) - - assert(evo.alive(e) and not evo.empty(e)) - assert(evo.has(e, f) and evo.get(e, f) == 21) - assert(not evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT) - evo.set(s, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder() - :set(f, 21) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(p) - - assert(evo.alive(e) and not evo.empty(e)) - assert(evo.has(e, f) and evo.get(e, f) == 21) - assert(not evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT) - evo.set(s, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - - local e = evo.builder() - :set(f, 21) - :set(evo.pair(p, s), 42) - :spawn() - - evo.destroy(s) - - assert(not evo.alive(e) and evo.empty(e)) - assert(not evo.has(e, f) and evo.get(e, f) == nil) - assert(not evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end -end - -do - do - local p, s = evo.id(2) - evo.set(p, evo.DEFAULT, 42) - - do - local e = evo.id() - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end - - do - local e = evo.builder():set(evo.pair(p, s)):spawn() - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end - end - - do - local p, s = evo.id(2) - evo.set(s, evo.DEFAULT, 21) - - do - local e = evo.id() - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - end - - do - local e = evo.builder():set(evo.pair(p, s)):spawn() - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - end - end - - do - local p, s = evo.id(2) - evo.set(p, evo.DEFAULT, 42) - evo.set(s, evo.DEFAULT, 21) - - do - local e = evo.id() - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end - - do - local e = evo.builder():set(evo.pair(p, s)):spawn() - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - end - end -end - -do - do - local f, p, s = evo.id(3) - evo.set(p, evo.REQUIRES, { f }) - - do - local e = evo.id() - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - end - - do - local e = evo.builder():set(evo.pair(p, s)):spawn() - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - end - end - - do - local f, p, s = evo.id(3) - evo.set(s, evo.REQUIRES, { f }) - - do - local e = evo.id() - evo.set(e, evo.pair(p, s)) - assert(not evo.has(e, f) and evo.get(e, f) == nil) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - end - - do - local e = evo.builder():set(evo.pair(p, s)):spawn() - assert(not evo.has(e, f) and evo.get(e, f) == nil) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - end - end - - do - local f, p, s = evo.id(3) - evo.set(p, evo.REQUIRES, { f }) - evo.set(f, evo.REQUIRES, { evo.pair(s, p) }) - evo.set(s, evo.REQUIRES, { p }) - - do - local e = evo.id() - evo.set(e, evo.pair(p, s)) - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - assert(evo.has(e, evo.pair(s, p)) and evo.get(e, evo.pair(s, p)) == true) - assert(evo.has(e, p) and evo.get(e, p) == true) - end - - do - local e = evo.builder():set(evo.pair(p, s)):spawn() - assert(evo.has(e, f) and evo.get(e, f) == true) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == true) - assert(evo.has(e, evo.pair(s, p)) and evo.get(e, evo.pair(s, p)) == true) - assert(evo.has(e, p) and evo.get(e, p) == true) - end - end -end - -do - do - local p, s = evo.id(2) - - local e = evo.builder():set(p, 21):set(evo.pair(p, s), 42):spawn() - assert(evo.has(e, p) and evo.get(e, p) == 21) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - - evo.set(s, evo.TAG) - assert(evo.has(e, p) and evo.get(e, p) == 21) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - - evo.set(p, evo.TAG) - assert(evo.has(e, p) and evo.get(e, p) == nil) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end - - do - local p, s = evo.id(2) - - local e = evo.builder():set(evo.pair(p, s), 42):spawn() - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - - evo.set(s, evo.TAG) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == 42) - - evo.set(p, evo.TAG) - assert(evo.has(e, evo.pair(p, s)) and evo.get(e, evo.pair(p, s)) == nil) - end -end - -do - local p1, p2, s1, s2 = evo.id(4) - - do - local b = evo.builder() - - b:set(evo.pair(p1, s1), 11) - b:set(evo.pair(p1, s2), 12) - b:set(evo.pair(p2, s1), 21) - b:set(evo.pair(p2, s2), 22) - - b:remove(evo.pair(evo.ANY, evo.ANY)) - - assert(not b:has(evo.pair(p1, s1))) - assert(not b:has(evo.pair(p1, s2))) - assert(not b:has(evo.pair(p2, s1))) - assert(not b:has(evo.pair(p2, s2))) - - assert(not b:has(evo.pair(p1, evo.ANY))) - assert(not b:has(evo.pair(p2, evo.ANY))) - assert(not b:has(evo.pair(evo.ANY, s1))) - assert(not b:has(evo.pair(evo.ANY, s2))) - - assert(not b:has(evo.pair(evo.ANY, evo.ANY))) - end - - do - local b = evo.builder() - - b:set(evo.pair(p1, s1), 11) - b:set(evo.pair(p1, s2), 12) - b:set(evo.pair(p2, s1), 21) - b:set(evo.pair(p2, s2), 22) - - b:remove(evo.pair(p2, evo.ANY)) - - assert(b:has(evo.pair(p1, s1))) - assert(b:has(evo.pair(p1, s2))) - assert(not b:has(evo.pair(p2, s1))) - assert(not b:has(evo.pair(p2, s2))) - - assert(b:has(evo.pair(p1, evo.ANY))) - assert(not b:has(evo.pair(p2, evo.ANY))) - assert(b:has(evo.pair(evo.ANY, s1))) - assert(b:has(evo.pair(evo.ANY, s2))) - - assert(b:has(evo.pair(evo.ANY, evo.ANY))) - end - - do - local b = evo.builder() - - b:set(evo.pair(p1, s1), 11) - b:set(evo.pair(p1, s2), 12) - b:set(evo.pair(p2, s1), 21) - b:set(evo.pair(p2, s2), 22) - - b:remove(evo.pair(p2, evo.ANY)) - - assert(b:has_all(evo.pair(p1, s1))) - assert(b:has_all(evo.pair(p1, s1), evo.pair(p1, s2))) - assert(not b:has_all(evo.pair(p1, s1), evo.pair(p2, s1))) - assert(not b:has_all(evo.pair(p2, s1), evo.pair(p1, s2))) - assert(not b:has_all(evo.pair(p2, s1), evo.pair(p2, s2))) - - assert(b:has_all(evo.pair(p1, evo.ANY))) - assert(b:has_all(evo.pair(p1, evo.ANY), evo.pair(evo.ANY, s1))) - assert(not b:has_all(evo.pair(p2, evo.ANY), evo.pair(evo.ANY, s1))) - assert(not b:has_all(evo.pair(p2, evo.ANY), evo.pair(evo.ANY, p1))) - - assert(b:has_all(evo.pair(evo.ANY, evo.ANY))) - - assert(b:has_all( - evo.pair(p1, s1), - evo.pair(p1, s2), - evo.pair(evo.ANY, s1), - evo.pair(p1, evo.ANY), - evo.pair(evo.ANY, evo.ANY))) - - assert(not b:has_all( - evo.pair(p1, s1), - evo.pair(p1, s2), - evo.pair(evo.ANY, s1), - evo.pair(p1, evo.ANY), - evo.pair(evo.ANY, evo.ANY), - evo.pair(p2, evo.ANY))) - end - - do - local b = evo.builder() - - b:set(evo.pair(p1, s1), 11) - b:set(evo.pair(p1, s2), 12) - b:set(evo.pair(p2, s1), 21) - b:set(evo.pair(p2, s2), 22) - - b:remove(evo.pair(p2, evo.ANY)) - - assert(b:has_any(evo.pair(p1, s1))) - assert(b:has_any(evo.pair(p1, s1), evo.pair(p1, s2))) - assert(b:has_any(evo.pair(p1, s1), evo.pair(p2, s1))) - assert(b:has_any(evo.pair(p2, s1), evo.pair(p1, s2))) - assert(not b:has_any(evo.pair(p2, s1), evo.pair(p2, s2))) - - assert(b:has_any(evo.pair(p1, evo.ANY))) - assert(b:has_any(evo.pair(p1, evo.ANY), evo.pair(evo.ANY, s1))) - assert(b:has_any(evo.pair(p2, evo.ANY), evo.pair(evo.ANY, s1))) - assert(not b:has_any(evo.pair(p2, evo.ANY), evo.pair(evo.ANY, p1))) - - assert(b:has_any(evo.pair(evo.ANY, evo.ANY))) - - assert(b:has_any( - evo.pair(p1, s1), - evo.pair(p1, s2), - evo.pair(evo.ANY, s1), - evo.pair(p1, evo.ANY), - evo.pair(evo.ANY, evo.ANY))) - - assert(not b:has_any( - evo.pair(p2, s1), - evo.pair(p2, s2), - evo.pair(p2, evo.ANY), - evo.pair(evo.ANY, p1), - evo.pair(evo.ANY, p2))) - - assert(b:has_any( - evo.pair(p2, s1), - evo.pair(p2, s2), - evo.pair(p2, evo.ANY), - evo.pair(evo.ANY, p1), - evo.pair(evo.ANY, p2), - evo.pair(p1, evo.ANY))) - end - - do - local b = evo.builder() - - b:set(evo.pair(p1, s1), 11) - b:set(evo.pair(p1, s2), 12) - b:set(evo.pair(p2, s1), 21) - b:set(evo.pair(p2, s2), 22) - - b:remove(evo.pair(p1, evo.ANY)) - b:remove(evo.pair(p1, evo.ANY)) - - b:remove(evo.pair(p2, evo.ANY)) - b:remove(evo.pair(p2, evo.ANY)) - - b:remove(evo.pair(evo.ANY, s1)) - b:remove(evo.pair(evo.ANY, s1)) - - b:remove(evo.pair(evo.ANY, s2)) - b:remove(evo.pair(evo.ANY, s2)) - - assert(not b:has(evo.pair(evo.ANY, evo.ANY))) - end -end - --- TODO --- builder:has/has_all/has_any should work with wildcards / remove too? --- should we provide wildcard support for get operations? --- prevent setting pairs with dead secondary fragments --- process evo.ANY as single wildcard diff --git a/evolved.lua b/evolved.lua index a1fb6fe..416f0ea 100644 --- a/evolved.lua +++ b/evolved.lua @@ -82,20 +82,6 @@ local evolved = { ---@field package [3] integer chunk_stack_size ---@field package [4] table? exclude_set ----@class (exact) evolved.primaries_state ----@field package [1] integer structural_changes ----@field package [2] evolved.chunk entity_chunk ----@field package [3] integer entity_place ----@field package [4] integer secondary_index ----@field package [5] integer secondary_fragment_index - ----@class (exact) evolved.secondaries_state ----@field package [1] integer structural_changes ----@field package [2] evolved.chunk entity_chunk ----@field package [3] integer entity_place ----@field package [4] integer primary_index ----@field package [5] integer primary_fragment_index - ---@alias evolved.each_iterator fun( --- state: evolved.each_state?): --- evolved.fragment?, evolved.component? @@ -104,14 +90,6 @@ local evolved = { --- state: evolved.execute_state?): --- evolved.chunk?, evolved.entity[]?, integer? ----@alias evolved.primaries_iterator fun( ---- state: evolved.primaries_state?): ---- evolved.fragment?, evolved.component? - ----@alias evolved.secondaries_iterator fun( ---- state: evolved.secondaries_state?): ---- evolved.fragment?, evolved.component? - --- --- --- @@ -120,15 +98,11 @@ local evolved = { --[=[------------------------------------------------------------------\ | |-------- OPTIONS --------|- SECONDARY -|-- PRIMARY --| - | IDENTIFIER'S | 12 bits | | | - | ANATOMY |--------|--------|-------| 20 bits | 20 bits | - | | 9 bits | 2 bits | 1 bit | | | - |--------------|--------|--------|-------|-------------|-------------| - | ID | RSVD | 00 | 0 | version | index | - | PAIR | RSVD | 00 | 1 | SEC index | PRI index | - | PRI WILDCARD | RSVD | 01 | 1 | SEC index | ANY index | - | SEC WILDCARD | RSVD | 10 | 1 | ANY index | PRI index | - | ANY WILDCARD | RSVD | 11 | 1 | ANY index | ANY index | + | IDENTIFIER'S | | | | + | ANATOMY | 12 bits | 20 bits | 20 bits | + | | | | | + |--------------|-------------------------|-------------|-------------| + | ID | RESERVED | version | index | \------------------------------------------------------------------]=] --- @@ -185,10 +159,6 @@ local __group_subsystems = {} ---@type table ---@field package __component_indices table ---@field package __component_storages evolved.storage[] ---@field package __component_fragments evolved.fragment[] ----@field package __pair_list evolved.id[] ----@field package __pair_count integer ----@field package __primary_pairs table ----@field package __secondary_pairs table ---@field package __with_fragment_edges table ---@field package __without_fragment_edges table ---@field package __unreachable_or_collected boolean @@ -196,9 +166,6 @@ local __group_subsystems = {} ---@type table ---@field package __has_assign_hooks boolean ---@field package __has_insert_hooks boolean ---@field package __has_remove_hooks boolean ----@field package __has_pair_major boolean ----@field package __has_pair_minors boolean ----@field package __has_pair_fragments boolean ---@field package __has_unique_major boolean ---@field package __has_unique_minors boolean ---@field package __has_unique_fragments boolean @@ -214,8 +181,6 @@ __chunk_mt.__index = __chunk_mt ---@class evolved.builder ---@field package __components table ----@field package __primary_pairs? table ----@field package __secondary_pairs? table local __builder_mt = {} __builder_mt.__index = __builder_mt @@ -463,15 +428,13 @@ local __table_pool_tag = { system_list = 3, each_state = 4, execute_state = 5, - primaries_state = 6, - secondaries_state = 7, - entity_set = 8, - entity_list = 9, - fragment_set = 10, - fragment_list = 11, - component_map = 12, - component_list = 13, - __count = 13, + entity_set = 6, + entity_list = 7, + fragment_set = 8, + fragment_list = 9, + component_map = 10, + component_list = 11, + __count = 11, } ---@class (exact) evolved.table_pool @@ -579,7 +542,6 @@ end ---@field package __item_count integer local __assoc_list_new -local __assoc_list_dup local __assoc_list_move local __assoc_list_move_ex local __assoc_list_sort @@ -601,31 +563,6 @@ function __assoc_list_new(reserve) } end ----@generic K ----@param al evolved.assoc_list ----@return evolved.assoc_list ----@nodiscard -function __assoc_list_dup(al) - local al_item_list = al.__item_list - local al_item_count = al.__item_count - - local dup_item_set = __lua_table_new(0, al_item_count) - local dup_item_list = __lua_table_new(al_item_count, 0) - - for al_item_index = 1, al_item_count do - local al_item = al_item_list[al_item_index] - dup_item_set[al_item] = al_item_index - dup_item_list[al_item_index] = al_item - end - - ---@type evolved.assoc_list - return { - __item_set = dup_item_set, - __item_list = dup_item_list, - __item_count = al_item_count, - } -end - ---@generic K ---@param src_item_list K[] ---@param src_item_first integer @@ -775,8 +712,6 @@ end --- --- -local __ANY = __acquire_id() - local __TAG = __acquire_id() local __NAME = __acquire_id() @@ -817,23 +752,6 @@ local __DESTRUCTION_POLICY_REMOVE_FRAGMENT = __acquire_id() --- --- -local __PAIR_OPTS = 1 -- 0b001 -local __WILDCARD_OPTS = 7 -- 0b111 -local __PRIMARY_WILDCARD_OPTS = 3 -- 0b011 -local __SECONDARY_WILDCARD_OPTS = 5 -- 0b101 - -local __ANY_INDEX = __ANY % 2 ^ 20 --[[@as integer]] - -local __WILDCARD_PAIR = __ANY_INDEX - + __ANY_INDEX * 2 ^ 20 - + __WILDCARD_OPTS * 2 ^ 40 --[[@as evolved.id]] - ---- ---- ---- ---- ---- - local __safe_tbls = { ---@type table __EMPTY_FRAGMENT_SET = __lua_setmetatable({}, { @@ -916,21 +834,6 @@ local __evolved_process local __evolved_debug_mode local __evolved_collect_garbage -local __evolved_pair -local __evolved_unpair - -local __evolved_is_pair -local __evolved_is_wildcard - -local __evolved_primary -local __evolved_secondary - -local __evolved_primaries -local __evolved_secondaries - -local __evolved_primary_count -local __evolved_secondary_count - local __evolved_chunk local __evolved_builder @@ -942,79 +845,23 @@ local __evolved_builder local __id_name -local __primary_wildcard -local __secondary_wildcard - local __component_storage ---@param id evolved.id ---@return string ---@nodiscard function __id_name(id) - if not __evolved_is_pair(id) then - ---@type string? - local id_name = __evolved_get(id, __NAME) + ---@type string? + local id_name = __evolved_get(id, __NAME) - if id_name then - return id_name - end - else - local id_primary_index, id_secondary_index = __evolved_unpack(id) - - local id_primary = __freelist_ids[id_primary_index] --[[@as evolved.id?]] - local id_secondary = __freelist_ids[id_secondary_index] --[[@as evolved.id?]] - - local id_primary_name, id_secondary_name - - if id_primary and id_primary % 2 ^ 20 == id_primary_index then - id_primary_name = __id_name(id_primary) - end - - if id_secondary and id_secondary % 2 ^ 20 == id_secondary_index then - id_secondary_name = __id_name(id_secondary) - end - - if id_primary_name and id_secondary_name then - return __lua_string_format('${%s,%s}', id_primary_name, id_secondary_name) - end + if id_name then + return id_name end local id_primary, id_secondary, id_options = __evolved_unpack(id) return __lua_string_format('$%d#%d:%d:%d', id, id_primary, id_secondary, id_options) end ----@param secondary evolved.id | integer id or index ----@return evolved.id pair (*, secondary) ----@nodiscard -function __primary_wildcard(secondary) - local primary_index = __ANY_INDEX - local secondary_index = secondary % 2 ^ 20 - - if secondary_index == __ANY_INDEX then - return __WILDCARD_PAIR - end - - return primary_index - + secondary_index * 2 ^ 20 - + __PRIMARY_WILDCARD_OPTS * 2 ^ 40 --[[@as evolved.id]] -end - ----@param primary evolved.id | integer id or index ----@return evolved.id pair (primary, *) ----@nodiscard -function __secondary_wildcard(primary) - local primary_index = primary % 2 ^ 20 - local secondary_index = __ANY_INDEX - - if primary_index == __ANY_INDEX then - return __WILDCARD_PAIR - end - - return primary_index - + secondary_index * 2 ^ 20 - + __SECONDARY_WILDCARD_OPTS * 2 ^ 40 --[[@as evolved.id]] -end - ---@param fragment evolved.fragment ---@return evolved.storage ---@nodiscard @@ -1090,16 +937,6 @@ function __iterator_fns.__execute_major_iterator(execute_state) (not chunk_child.__has_explicit_major) and (not exclude_set or not exclude_set[chunk_child_fragment]) - if is_chunk_child_matched and exclude_set and chunk_child.__has_pair_major then - local chunk_child_primary_index, chunk_child_secondary_index = - __evolved_unpack(chunk_child_fragment) - - is_chunk_child_matched = - not exclude_set[__WILDCARD_PAIR] and - not exclude_set[__primary_wildcard(chunk_child_secondary_index)] and - not exclude_set[__secondary_wildcard(chunk_child_primary_index)] - end - if is_chunk_child_matched then chunk_stack_size = chunk_stack_size + 1 chunk_stack[chunk_stack_size] = chunk_child @@ -1150,72 +987,6 @@ function __iterator_fns.__execute_minor_iterator(execute_state) __release_table(__table_pool_tag.execute_state, execute_state, true) end ----@type evolved.primaries_iterator -function __iterator_fns.__primaries_iterator(primaries_state) - if not primaries_state then return end - - local structural_changes = primaries_state[1] - local entity_chunk = primaries_state[2] - local entity_place = primaries_state[3] - local secondary_index = primaries_state[4] - local secondary_fragment_index = primaries_state[5] - - if structural_changes ~= __structural_changes then - __error_fmt('structural changes are prohibited during iteration') - end - - local secondary_fragments = entity_chunk.__secondary_pairs[secondary_index] - local secondary_fragment_list = secondary_fragments and secondary_fragments.__item_list - local secondary_fragment_count = secondary_fragments and secondary_fragments.__item_count or 0 - - if secondary_fragment_index >= 1 and secondary_fragment_index <= secondary_fragment_count then - primaries_state[5] = secondary_fragment_index + 1 - - local secondary_fragment = secondary_fragment_list[secondary_fragment_index] - local primary, _ = __evolved_unpair(secondary_fragment) - - local component_index = entity_chunk.__component_indices[secondary_fragment] - local component_storage = entity_chunk.__component_storages[component_index] - - return primary, component_storage and component_storage[entity_place] - end - - __release_table(__table_pool_tag.primaries_state, primaries_state, true) -end - ----@type evolved.secondaries_iterator -function __iterator_fns.__secondaries_iterator(secondaries_state) - if not secondaries_state then return end - - local structural_changes = secondaries_state[1] - local entity_chunk = secondaries_state[2] - local entity_place = secondaries_state[3] - local primary_index = secondaries_state[4] - local primary_fragment_index = secondaries_state[5] - - if structural_changes ~= __structural_changes then - __error_fmt('structural changes are prohibited during iteration') - end - - local primary_fragments = entity_chunk.__primary_pairs[primary_index] - local primary_fragment_list = primary_fragments and primary_fragments.__item_list - local primary_fragment_count = primary_fragments and primary_fragments.__item_count or 0 - - if primary_fragment_index >= 1 and primary_fragment_index <= primary_fragment_count then - secondaries_state[5] = primary_fragment_index + 1 - - local primary_fragment = primary_fragment_list[primary_fragment_index] - local _, secondary = __evolved_unpair(primary_fragment) - - local component_index = entity_chunk.__component_indices[primary_fragment] - local component_storage = entity_chunk.__component_storages[component_index] - - return secondary, component_storage and component_storage[entity_place] - end - - __release_table(__table_pool_tag.secondaries_state, secondaries_state, true) -end - --- --- --- @@ -1235,48 +1006,17 @@ local __update_major_chunks_trace ---@return evolved.chunk ---@nodiscard function __new_chunk(chunk_parent, chunk_fragment) - if __evolved_is_wildcard(chunk_fragment) then - __error_fmt('chunk cannot contain wildcard fragments') - end - local chunk_fragment_set = {} ---@type table local chunk_fragment_list = {} ---@type evolved.fragment[] local chunk_fragment_count = 0 ---@type integer - local chunk_pair_list = {} ---@type evolved.id[] - local chunk_pair_count = 0 ---@type integer - - local chunk_primary_pairs = {} ---@type table - local chunk_secondary_pairs = {} ---@type table - if chunk_parent then - do - local chunk_parent_fragment_list = chunk_parent.__fragment_list - local chunk_parent_fragment_count = chunk_parent.__fragment_count + local chunk_parent_fragment_list = chunk_parent.__fragment_list + local chunk_parent_fragment_count = chunk_parent.__fragment_count - chunk_fragment_count = __assoc_list_move_ex( - chunk_parent_fragment_list, 1, chunk_parent_fragment_count, - chunk_fragment_set, chunk_fragment_list, chunk_fragment_count) - end - - do - local chunk_parent_pair_list = chunk_parent.__pair_list - local chunk_parent_pair_count = chunk_parent.__pair_count - - __lua_table_move( - chunk_parent_pair_list, 1, chunk_parent_pair_count, - chunk_pair_count + 1, chunk_pair_list) - - chunk_pair_count = chunk_pair_count + chunk_parent_pair_count - end - - for parent_primary_index, parent_primary_fragments in __lua_next, chunk_parent.__primary_pairs do - chunk_primary_pairs[parent_primary_index] = __assoc_list_dup(parent_primary_fragments) - end - - for parent_secondary_index, parent_secondary_fragments in __lua_next, chunk_parent.__secondary_pairs do - chunk_secondary_pairs[parent_secondary_index] = __assoc_list_dup(parent_secondary_fragments) - end + chunk_fragment_count = __assoc_list_move_ex( + chunk_parent_fragment_list, 1, chunk_parent_fragment_count, + chunk_fragment_set, chunk_fragment_list, chunk_fragment_count) end do @@ -1285,30 +1025,6 @@ function __new_chunk(chunk_parent, chunk_fragment) chunk_fragment_list[chunk_fragment_count] = chunk_fragment end - if __evolved_is_pair(chunk_fragment) then - chunk_pair_count = chunk_pair_count + 1 - chunk_pair_list[chunk_pair_count] = chunk_fragment - - local chunk_primary_index, chunk_secondary_index = - __evolved_unpack(chunk_fragment) - - local chunk_primary_fragments = chunk_primary_pairs[chunk_primary_index] - local chunk_secondary_fragments = chunk_secondary_pairs[chunk_secondary_index] - - if not chunk_primary_fragments then - chunk_primary_fragments = __assoc_list_new(1) - chunk_primary_pairs[chunk_primary_index] = chunk_primary_fragments - end - - if not chunk_secondary_fragments then - chunk_secondary_fragments = __assoc_list_new(1) - chunk_secondary_pairs[chunk_secondary_index] = chunk_secondary_fragments - end - - __assoc_list_insert(chunk_primary_fragments, chunk_fragment) - __assoc_list_insert(chunk_secondary_fragments, chunk_fragment) - end - ---@type evolved.chunk local chunk = __lua_setmetatable({ __parent = nil, @@ -1325,10 +1041,6 @@ function __new_chunk(chunk_parent, chunk_fragment) __component_indices = {}, __component_storages = {}, __component_fragments = {}, - __pair_list = chunk_pair_list, - __pair_count = chunk_pair_count, - __primary_pairs = chunk_primary_pairs, - __secondary_pairs = chunk_secondary_pairs, __with_fragment_edges = {}, __without_fragment_edges = {}, __unreachable_or_collected = false, @@ -1336,9 +1048,6 @@ function __new_chunk(chunk_parent, chunk_fragment) __has_assign_hooks = false, __has_insert_hooks = false, __has_remove_hooks = false, - __has_pair_major = false, - __has_pair_minors = false, - __has_pair_fragments = false, __has_unique_major = false, __has_unique_minors = false, __has_unique_fragments = false, @@ -1394,90 +1103,6 @@ function __new_chunk(chunk_parent, chunk_fragment) __assoc_list_insert(minor_chunks, chunk) end - if __evolved_is_pair(chunk_fragment) then - local major = chunk_fragment - local major_primary_index, major_secondary_index = - __evolved_unpack(major) - - do - local major_wildcard = __WILDCARD_PAIR - local major_wildcard_chunks = __major_chunks[major_wildcard] - - if not major_wildcard_chunks then - major_wildcard_chunks = __assoc_list_new(4) - __major_chunks[major_wildcard] = major_wildcard_chunks - end - - __assoc_list_insert(major_wildcard_chunks, chunk) - end - - do - local major_wildcard = __secondary_wildcard(major_primary_index) - local major_wildcard_chunks = __major_chunks[major_wildcard] - - if not major_wildcard_chunks then - major_wildcard_chunks = __assoc_list_new(4) - __major_chunks[major_wildcard] = major_wildcard_chunks - end - - __assoc_list_insert(major_wildcard_chunks, chunk) - end - - do - local major_wildcard = __primary_wildcard(major_secondary_index) - local major_wildcard_chunks = __major_chunks[major_wildcard] - - if not major_wildcard_chunks then - major_wildcard_chunks = __assoc_list_new(4) - __major_chunks[major_wildcard] = major_wildcard_chunks - end - - __assoc_list_insert(major_wildcard_chunks, chunk) - end - end - - if chunk_pair_count > 0 then - local minor_wildcard = __WILDCARD_PAIR - local minor_wildcard_chunks = __minor_chunks[minor_wildcard] - - if not minor_wildcard_chunks then - minor_wildcard_chunks = __assoc_list_new(4) - __minor_chunks[minor_wildcard] = minor_wildcard_chunks - end - - __assoc_list_insert(minor_wildcard_chunks, chunk) - end - - for i = 1, chunk_pair_count do - local minor = chunk_pair_list[i] - local minor_primary_index, minor_secondary_index = - __evolved_unpack(minor) - - do - local minor_wildcard = __secondary_wildcard(minor_primary_index) - local minor_wildcard_chunks = __minor_chunks[minor_wildcard] - - if not minor_wildcard_chunks then - minor_wildcard_chunks = __assoc_list_new(4) - __minor_chunks[minor_wildcard] = minor_wildcard_chunks - end - - __assoc_list_insert(minor_wildcard_chunks, chunk) - end - - do - local minor_wildcard = __primary_wildcard(minor_secondary_index) - local minor_wildcard_chunks = __minor_chunks[minor_wildcard] - - if not minor_wildcard_chunks then - minor_wildcard_chunks = __assoc_list_new(4) - __minor_chunks[minor_wildcard] = minor_wildcard_chunks - end - - __assoc_list_insert(minor_wildcard_chunks, chunk) - end - end - __update_chunk_tags(chunk) __update_chunk_flags(chunk) @@ -1565,10 +1190,6 @@ function __update_chunk_flags(chunk) local has_remove_hooks = (chunk_parent ~= nil and chunk_parent.__has_remove_hooks) or __evolved_has(chunk_fragment, __ON_REMOVE) - local has_pair_major = __evolved_is_pair(chunk_fragment) - local has_pair_minors = chunk_parent ~= nil and chunk_parent.__has_pair_fragments - local has_pair_fragments = has_pair_major or has_pair_minors - local has_unique_major = __evolved_has(chunk_fragment, __UNIQUE) local has_unique_minors = chunk_parent ~= nil and chunk_parent.__has_unique_fragments local has_unique_fragments = has_unique_major or has_unique_minors @@ -1589,10 +1210,6 @@ function __update_chunk_flags(chunk) chunk.__has_insert_hooks = has_insert_hooks chunk.__has_remove_hooks = has_remove_hooks - chunk.__has_pair_major = has_pair_major - chunk.__has_pair_minors = has_pair_minors - chunk.__has_pair_fragments = has_pair_fragments - chunk.__has_unique_major = has_unique_major chunk.__has_unique_minors = has_unique_minors chunk.__has_unique_fragments = has_unique_fragments @@ -1612,10 +1229,6 @@ end ---@param trace fun(chunk: evolved.chunk, ...: any) ---@param ... any additional trace arguments function __trace_major_chunks(major, trace, ...) - if __evolved_is_pair(major) then - __error_fmt('trace operations on pair fragments are not supported') - end - ---@type evolved.chunk[] local chunk_stack = __acquire_table(__table_pool_tag.chunk_list) local chunk_stack_size = 0 @@ -1634,34 +1247,6 @@ function __trace_major_chunks(major, trace, ...) end end - do - local major_chunks = __major_chunks[__primary_wildcard(major)] - 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( - major_chunk_list, 1, major_chunk_count, - chunk_stack_size + 1, chunk_stack) - - chunk_stack_size = chunk_stack_size + major_chunk_count - end - end - - do - local major_chunks = __major_chunks[__secondary_wildcard(major)] - 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( - major_chunk_list, 1, major_chunk_count, - chunk_stack_size + 1, chunk_stack) - - chunk_stack_size = chunk_stack_size + major_chunk_count - end - end - while chunk_stack_size > 0 do local chunk = chunk_stack[chunk_stack_size] @@ -1689,10 +1274,6 @@ end ---@param trace fun(chunk: evolved.chunk, ...: any) ---@param ... any additional trace arguments function __trace_minor_chunks(minor, trace, ...) - if __evolved_is_pair(minor) then - __error_fmt('trace operations on pair fragments are not supported') - end - ---@type evolved.chunk[] local chunk_stack = __acquire_table(__table_pool_tag.chunk_list) local chunk_stack_size = 0 @@ -1711,34 +1292,6 @@ function __trace_minor_chunks(minor, trace, ...) end end - do - local minor_chunks = __minor_chunks[__primary_wildcard(minor)] - 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 minor_chunk_count > 0 then - __lua_table_move( - minor_chunk_list, 1, minor_chunk_count, - chunk_stack_size + 1, chunk_stack) - - chunk_stack_size = chunk_stack_size + minor_chunk_count - end - end - - do - local minor_chunks = __minor_chunks[__secondary_wildcard(minor)] - 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 minor_chunk_count > 0 then - __lua_table_move( - minor_chunk_list, 1, minor_chunk_count, - chunk_stack_size + 1, chunk_stack) - - chunk_stack_size = chunk_stack_size + minor_chunk_count - end - end - while chunk_stack_size > 0 do local chunk = chunk_stack[chunk_stack_size] @@ -1845,96 +1398,6 @@ local function __chunk_without_fragment(chunk, fragment) if without_fragment_edge then return without_fragment_edge end end - if chunk.__has_pair_fragments and __evolved_is_wildcard(fragment) then - local primary_index, secondary_index, fragment_opts = - __evolved_unpack(fragment) - - if fragment_opts == __WILDCARD_OPTS then - while chunk and chunk.__has_pair_major do - chunk = chunk.__parent - end - - if not chunk or not chunk.__has_pair_fragments then - return chunk - end - - local sib_chunk = chunk.__parent - - while sib_chunk and sib_chunk.__has_pair_fragments do - sib_chunk = sib_chunk.__parent - end - - if sib_chunk then - chunk.__without_fragment_edges[fragment] = sib_chunk - sib_chunk.__with_fragment_edges[fragment] = chunk - end - - return sib_chunk - elseif fragment_opts == __PRIMARY_WILDCARD_OPTS then - if not chunk.__secondary_pairs[secondary_index] then - -- the chunk does not have such pairs - return chunk - end - - local sib_chunk = chunk.__parent - - while sib_chunk and sib_chunk.__has_pair_fragments and sib_chunk.__secondary_pairs[secondary_index] do - sib_chunk = sib_chunk.__parent - end - - local ini_pair_list = chunk.__pair_list - local ini_pair_count = chunk.__pair_count - - local lst_pair_index = sib_chunk and sib_chunk.__pair_count + 2 or 2 - - for ini_pair_index = lst_pair_index, ini_pair_count do - local ini_pair = ini_pair_list[ini_pair_index] - local _, ini_secondary_index = __evolved_unpack(ini_pair) - if ini_secondary_index ~= secondary_index then - sib_chunk = __chunk_with_fragment(sib_chunk, ini_pair) - end - end - - if sib_chunk then - chunk.__without_fragment_edges[fragment] = sib_chunk - sib_chunk.__with_fragment_edges[fragment] = chunk - end - - return sib_chunk - elseif fragment_opts == __SECONDARY_WILDCARD_OPTS then - if not chunk.__primary_pairs[primary_index] then - -- the chunk does not have such pairs - return chunk - end - - local sib_chunk = chunk.__parent - - while sib_chunk and sib_chunk.__has_pair_fragments and sib_chunk.__primary_pairs[primary_index] do - sib_chunk = sib_chunk.__parent - end - - local ini_pair_list = chunk.__pair_list - local ini_pair_count = chunk.__pair_count - - local lst_pair_index = sib_chunk and sib_chunk.__pair_count + 2 or 2 - - for ini_pair_index = lst_pair_index, ini_pair_count do - local ini_pair = ini_pair_list[ini_pair_index] - local ini_primary_index, _ = __evolved_unpack(ini_pair) - if ini_primary_index ~= primary_index then - sib_chunk = __chunk_with_fragment(sib_chunk, ini_pair) - end - end - - if sib_chunk then - chunk.__without_fragment_edges[fragment] = sib_chunk - sib_chunk.__with_fragment_edges[fragment] = chunk - end - - return sib_chunk - end - end - if fragment > chunk.__fragment or not chunk.__fragment_set[fragment] then return chunk end @@ -2082,21 +1545,6 @@ local function __chunk_has_fragment(chunk, fragment) return true end - if chunk.__has_pair_fragments and __evolved_is_wildcard(fragment) then - local primary_index, secondary_index, fragment_opts = - __evolved_unpack(fragment) - - if fragment_opts == __WILDCARD_OPTS then - return true - elseif fragment_opts == __PRIMARY_WILDCARD_OPTS then - local secondary_fragments = chunk.__secondary_pairs[secondary_index] - return secondary_fragments and secondary_fragments.__item_count > 0 - elseif fragment_opts == __SECONDARY_WILDCARD_OPTS then - local primary_fragments = chunk.__primary_pairs[primary_index] - return primary_fragments and primary_fragments.__item_count > 0 - end - end - return false end @@ -2113,41 +1561,30 @@ local function __chunk_has_all_fragments(chunk, ...) local fs = chunk.__fragment_set - local has_f = __chunk_has_fragment - local has_fs = __chunk_has_all_fragments - - local has_p = chunk.__has_pair_fragments - if fragment_count == 1 then local f1 = ... - return (has_p and has_f(chunk, f1)) - or (not has_p and fs[f1] ~= nil) + return fs[f1] ~= nil end if fragment_count == 2 then local f1, f2 = ... - return (has_p and has_f(chunk, f1) and has_f(chunk, f2)) - or (not has_p and fs[f1] ~= nil and fs[f2] ~= nil) + return fs[f1] ~= nil and fs[f2] ~= nil end if fragment_count == 3 then local f1, f2, f3 = ... - return (has_p and has_f(chunk, f1) and has_f(chunk, f2) and has_f(chunk, f3)) - or (not has_p and fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil) + return fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil end if fragment_count == 4 then local f1, f2, f3, f4 = ... - return (has_p and has_f(chunk, f1) and has_f(chunk, f2) and has_f(chunk, f3) and has_f(chunk, f4)) - or (not has_p and fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil and fs[f4] ~= nil) + return fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil and fs[f4] ~= nil end do local f1, f2, f3, f4 = ... - return (has_p and has_f(chunk, f1) and has_f(chunk, f2) and has_f(chunk, f3) and has_f(chunk, f4) - and has_fs(chunk, __lua_select(5, ...))) - or (not has_p and fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil and fs[f4] ~= nil - and has_fs(chunk, __lua_select(5, ...))) + return fs[f1] ~= nil and fs[f2] ~= nil and fs[f3] ~= nil and fs[f4] ~= nil + and __chunk_has_all_fragments(chunk, __lua_select(5, ...)) end end @@ -2163,22 +1600,10 @@ local function __chunk_has_all_fragment_list(chunk, fragment_list, fragment_coun local fs = chunk.__fragment_set - local has_f = __chunk_has_fragment - local has_p = chunk.__has_pair_fragments - - if has_p then - for i = 1, fragment_count do - local f = fragment_list[i] - if not has_f(chunk, f) then - return false - end - end - else - for i = 1, fragment_count do - local f = fragment_list[i] - if fs[f] == nil then - return false - end + for i = 1, fragment_count do + local f = fragment_list[i] + if fs[f] == nil then + return false end end @@ -2198,41 +1623,30 @@ local function __chunk_has_any_fragments(chunk, ...) local fs = chunk.__fragment_set - local has_f = __chunk_has_fragment - local has_fs = __chunk_has_any_fragments - - local has_p = chunk.__has_pair_fragments - if fragment_count == 1 then local f1 = ... - return (has_p and has_f(chunk, f1)) - or (not has_p and fs[f1] ~= nil) + return fs[f1] ~= nil end if fragment_count == 2 then local f1, f2 = ... - return (has_p and (has_f(chunk, f1) or has_f(chunk, f2))) - or (not has_p and (fs[f1] ~= nil or fs[f2] ~= nil)) + return fs[f1] ~= nil or fs[f2] ~= nil end if fragment_count == 3 then local f1, f2, f3 = ... - return (has_p and (has_f(chunk, f1) or has_f(chunk, f2) or has_f(chunk, f3))) - or (not has_p and (fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil)) + return fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil end if fragment_count == 4 then local f1, f2, f3, f4 = ... - return (has_p and (has_f(chunk, f1) or has_f(chunk, f2) or has_f(chunk, f3) or has_f(chunk, f4))) - or (not has_p and (fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil or fs[f4] ~= nil)) + return fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil or fs[f4] ~= nil end do local f1, f2, f3, f4 = ... - return (has_p and (has_f(chunk, f1) or has_f(chunk, f2) or has_f(chunk, f3) or has_f(chunk, f4) - or has_fs(chunk, __lua_select(5, ...)))) - or (not has_p and (fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil or fs[f4] ~= nil - or has_fs(chunk, __lua_select(5, ...)))) + return fs[f1] ~= nil or fs[f2] ~= nil or fs[f3] ~= nil or fs[f4] ~= nil + or __chunk_has_any_fragments(chunk, __lua_select(5, ...)) end end @@ -2248,22 +1662,10 @@ local function __chunk_has_any_fragment_list(chunk, fragment_list, fragment_coun local fs = chunk.__fragment_set - local has_f = __chunk_has_fragment - local has_p = chunk.__has_pair_fragments - - if has_p then - for i = 1, fragment_count do - local f = fragment_list[i] - if has_f(chunk, f) then - return true - end - end - else - for i = 1, fragment_count do - local f = fragment_list[i] - if fs[f] ~= nil then - return true - end + for i = 1, fragment_count do + local f = fragment_list[i] + if fs[f] ~= nil then + return true end end @@ -2365,10 +1767,6 @@ local function __chunk_required_fragments(chunk, req_fragment_set, req_fragment_ fragment_stack[fragment_stack_size] = nil fragment_stack_size = fragment_stack_size - 1 - if __evolved_is_pair(stack_fragment) then - stack_fragment = __evolved_unpair(stack_fragment) - end - local fragment_requires = __sorted_requires[stack_fragment] local fragment_require_list = fragment_requires and fragment_requires.__item_list --[=[@as evolved.fragment[]]=] local fragment_require_count = fragment_requires and fragment_requires.__item_count or 0 --[[@as integer]] @@ -2415,10 +1813,6 @@ local function __fragment_required_fragments(fragment, req_fragment_set, req_fra fragment_stack[fragment_stack_size] = nil fragment_stack_size = fragment_stack_size - 1 - if __evolved_is_pair(stack_fragment) then - stack_fragment = __evolved_unpair(stack_fragment) - end - local fragment_requires = __sorted_requires[stack_fragment] local fragment_require_list = fragment_requires and fragment_requires.__item_list --[=[@as evolved.fragment[]]=] local fragment_require_count = fragment_requires and fragment_requires.__item_count or 0 --[[@as integer]] @@ -3021,51 +2415,6 @@ local function __purge_chunk(chunk) end end - if chunk.__has_pair_fragments then - local wildcard = __WILDCARD_PAIR - - local major_wildcard_chunks = __major_chunks[wildcard] - local minor_wildcard_chunks = __minor_chunks[wildcard] - - if major_wildcard_chunks and __assoc_list_remove(major_wildcard_chunks, chunk) == 0 then - __major_chunks[wildcard] = nil - end - - if minor_wildcard_chunks and __assoc_list_remove(minor_wildcard_chunks, chunk) == 0 then - __minor_chunks[wildcard] = nil - end - end - - for primary_index in __lua_next, chunk.__primary_pairs do - local secondary_wildcard = __secondary_wildcard(primary_index) - - local major_wildcard_chunks = __major_chunks[secondary_wildcard] - local minor_wildcard_chunks = __minor_chunks[secondary_wildcard] - - if major_wildcard_chunks and __assoc_list_remove(major_wildcard_chunks, chunk) == 0 then - __major_chunks[secondary_wildcard] = nil - end - - if minor_wildcard_chunks and __assoc_list_remove(minor_wildcard_chunks, chunk) == 0 then - __minor_chunks[secondary_wildcard] = nil - end - end - - for secondary_index in __lua_next, chunk.__secondary_pairs do - local primary_wildcard = __primary_wildcard(secondary_index) - - local major_wildcard_chunks = __major_chunks[primary_wildcard] - local minor_wildcard_chunks = __minor_chunks[primary_wildcard] - - if major_wildcard_chunks and __assoc_list_remove(major_wildcard_chunks, chunk) == 0 then - __major_chunks[primary_wildcard] = nil - end - - if minor_wildcard_chunks and __assoc_list_remove(minor_wildcard_chunks, chunk) == 0 then - __minor_chunks[primary_wildcard] = nil - end - end - if chunk_parent then chunk.__parent, chunk_parent.__child_count = nil, __assoc_list_remove_ex( chunk_parent.__child_set, chunk_parent.__child_list, chunk_parent.__child_count, @@ -3255,10 +2604,7 @@ local function __destroy_fragment_list(fragment_list, fragment_count) for i = 1, remove_fragment_policy_fragment_count do local fragment = remove_fragment_policy_fragment_list[i] - __trace_minor_chunks(fragment, __chunk_remove, - fragment, - __primary_wildcard(fragment), - __secondary_wildcard(fragment)) + __trace_minor_chunks(fragment, __chunk_remove, fragment) end __release_table(__table_pool_tag.fragment_list, remove_fragment_policy_fragment_list) @@ -4799,24 +4145,13 @@ end ---@return boolean ---@nodiscard function __evolved_alive(entity) - if not __evolved_is_pair(entity) then - local entity_index = entity % 2 ^ 20 + local entity_index = entity % 2 ^ 20 - if __freelist_ids[entity_index] ~= entity then - return false - end - - return true - else - local primary_index = entity % 2 ^ 20 - - local primary = __freelist_ids[primary_index] --[[@as evolved.id?]] - if not primary or primary % 2 ^ 20 ~= primary_index then - return false - end - - return true + if __freelist_ids[entity_index] ~= entity then + return false end + + return true end ---@param ... evolved.entity entities @@ -4865,24 +4200,13 @@ end ---@return boolean ---@nodiscard function __evolved_empty(entity) - if not __evolved_is_pair(entity) then - local entity_index = entity % 2 ^ 20 + local entity_index = entity % 2 ^ 20 - if __freelist_ids[entity_index] ~= entity then - return true - end - - return not __entity_chunks[entity_index] - else - local primary_index = entity % 2 ^ 20 - - local primary = __freelist_ids[primary_index] --[[@as evolved.id?]] - if not primary or primary % 2 ^ 20 ~= primary_index then - return true - end - - return not __entity_chunks[primary_index] + if __freelist_ids[entity_index] ~= entity then + return true end + + return not __entity_chunks[entity_index] end ---@param ... evolved.entity entities @@ -4932,36 +4256,19 @@ end ---@return boolean ---@nodiscard function __evolved_has(entity, fragment) - if not __evolved_is_pair(entity) then - local entity_index = entity % 2 ^ 20 + local entity_index = entity % 2 ^ 20 - if __freelist_ids[entity_index] ~= entity then - return false - end - - local entity_chunk = __entity_chunks[entity_index] - - if not entity_chunk then - return false - end - - return __chunk_has_fragment(entity_chunk, fragment) - else - local primary_index = entity % 2 ^ 20 - - local primary = __freelist_ids[primary_index] --[[@as evolved.id?]] - if not primary or primary % 2 ^ 20 ~= primary_index then - return false - end - - local primary_chunk = __entity_chunks[primary_index] - - if not primary_chunk then - return false - end - - return __chunk_has_fragment(primary_chunk, fragment) + if __freelist_ids[entity_index] ~= entity then + return false end + + local entity_chunk = __entity_chunks[entity_index] + + if not entity_chunk then + return false + end + + return __chunk_has_fragment(entity_chunk, fragment) end ---@param entity evolved.entity @@ -4969,36 +4276,19 @@ end ---@return boolean ---@nodiscard function __evolved_has_all(entity, ...) - if not __evolved_is_pair(entity) then - local entity_index = entity % 2 ^ 20 + local entity_index = entity % 2 ^ 20 - if __freelist_ids[entity_index] ~= entity then - return __lua_select('#', ...) == 0 - end - - local entity_chunk = __entity_chunks[entity_index] - - if not entity_chunk then - return __lua_select('#', ...) == 0 - end - - return __chunk_has_all_fragments(entity_chunk, ...) - else - local primary_index = entity % 2 ^ 20 - - local primary = __freelist_ids[primary_index] --[[@as evolved.id?]] - if not primary or primary % 2 ^ 20 ~= primary_index then - return __lua_select('#', ...) == 0 - end - - local primary_chunk = __entity_chunks[primary_index] - - if not primary_chunk then - return __lua_select('#', ...) == 0 - end - - return __chunk_has_all_fragments(primary_chunk, ...) + if __freelist_ids[entity_index] ~= entity then + return __lua_select('#', ...) == 0 end + + local entity_chunk = __entity_chunks[entity_index] + + if not entity_chunk then + return __lua_select('#', ...) == 0 + end + + return __chunk_has_all_fragments(entity_chunk, ...) end ---@param entity evolved.entity @@ -5006,36 +4296,19 @@ end ---@return boolean ---@nodiscard function __evolved_has_any(entity, ...) - if not __evolved_is_pair(entity) then - local entity_index = entity % 2 ^ 20 + local entity_index = entity % 2 ^ 20 - if __freelist_ids[entity_index] ~= entity then - return false - end - - local entity_chunk = __entity_chunks[entity_index] - - if not entity_chunk then - return false - end - - return __chunk_has_any_fragments(entity_chunk, ...) - else - local primary_index = entity % 2 ^ 20 - - local primary = __freelist_ids[primary_index] --[[@as evolved.id?]] - if not primary or primary % 2 ^ 20 ~= primary_index then - return false - end - - local primary_chunk = __entity_chunks[primary_index] - - if not primary_chunk then - return false - end - - return __chunk_has_any_fragments(primary_chunk, ...) + if __freelist_ids[entity_index] ~= entity then + return false end + + local entity_chunk = __entity_chunks[entity_index] + + if not entity_chunk then + return false + end + + return __chunk_has_any_fragments(entity_chunk, ...) end ---@param entity evolved.entity @@ -5043,38 +4316,20 @@ end ---@return evolved.component ... components ---@nodiscard function __evolved_get(entity, ...) - if not __evolved_is_pair(entity) then - local entity_index = entity % 2 ^ 20 + local entity_index = entity % 2 ^ 20 - if __freelist_ids[entity_index] ~= entity then - return - end - - local entity_chunk = __entity_chunks[entity_index] - - if not entity_chunk then - return - end - - local entity_place = __entity_places[entity_index] - return __chunk_get_components(entity_chunk, entity_place, ...) - else - local primary_index = entity % 2 ^ 20 - - local primary = __freelist_ids[primary_index] --[[@as evolved.id?]] - if not primary or primary % 2 ^ 20 ~= primary_index then - return - end - - local primary_chunk = __entity_chunks[primary_index] - - if not primary_chunk then - return - end - - local primary_place = __entity_places[primary_index] - return __chunk_get_components(primary_chunk, primary_place, ...) + if __freelist_ids[entity_index] ~= entity then + return end + + local entity_chunk = __entity_chunks[entity_index] + + if not entity_chunk then + return + end + + local entity_place = __entity_places[entity_index] + return __chunk_get_components(entity_chunk, entity_place, ...) end ---@param entity evolved.entity @@ -5082,14 +4337,6 @@ end ---@param component evolved.component function __evolved_set(entity, fragment, component) if __debug_mode then - if __evolved_is_pair(entity) then - __error_fmt('the pair (%s) cannot be used as an entity', __id_name(entity)) - end - - if __evolved_is_wildcard(fragment) then - __error_fmt('the wildcard fragment (%s) cannot be used as a fragment', __id_name(fragment)) - end - if not __evolved_alive(entity) then __error_fmt('the entity (%s) is not alive and cannot be used', __id_name(entity)) end @@ -5335,11 +4582,6 @@ function __evolved_remove(entity, ...) return end - if __evolved_is_pair(entity) then - -- pairs cannot have fragments, nothing to remove - return - end - local entity_index = entity % 2 ^ 20 if __freelist_ids[entity_index] ~= entity then @@ -5458,9 +4700,7 @@ function __evolved_clear(...) local entity = __lua_select(argument_index, ...) local entity_index = entity % 2 ^ 20 - if __evolved_is_pair(entity) then - -- pairs cannot have fragments, nothing to clear - elseif __freelist_ids[entity_index] ~= entity then + if __freelist_ids[entity_index] ~= entity then -- this entity is not alive, nothing to clear else local chunk = entity_chunks[entity_index] @@ -5536,15 +4776,10 @@ function __evolved_destroy(...) local entity = __lua_select(argument_index, ...) local entity_index = entity % 2 ^ 20 - if __evolved_is_pair(entity) then - -- pairs cannot be destroyed, nothing to do - elseif __freelist_ids[entity_index] ~= entity then + if __freelist_ids[entity_index] ~= entity then -- this entity is not alive, nothing to destroy else - local is_fragment = - minor_chunks[entity] or - minor_chunks[__primary_wildcard(entity)] or - minor_chunks[__secondary_wildcard(entity)] + local is_fragment = minor_chunks[entity] if not is_fragment then purging_entity_count = purging_entity_count + 1 @@ -5579,14 +4814,6 @@ end ---@param component evolved.component function __evolved_batch_set(query, fragment, component) if __debug_mode then - if __evolved_is_pair(query) then - __error_fmt('the pair (%s) cannot be used as a query', __id_name(query)) - end - - if __evolved_is_wildcard(fragment) then - __error_fmt('the wildcard fragment (%s) cannot be used as a fragment', __id_name(fragment)) - end - if not __evolved_alive(query) then __error_fmt('the query (%s) is not alive and cannot be used', __id_name(query)) end @@ -5740,10 +4967,7 @@ function __evolved_batch_destroy(...) for i = 1, entity_count do local entity = entity_list[i] - local is_fragment = - minor_chunks[entity] or - minor_chunks[__primary_wildcard(entity)] or - minor_chunks[__secondary_wildcard(entity)] + local is_fragment = minor_chunks[entity] if not is_fragment then purging_entity_count = purging_entity_count + 1 @@ -5786,11 +5010,6 @@ end ---@return evolved.each_state? iterator_state ---@nodiscard function __evolved_each(entity) - if __evolved_is_pair(entity) then - -- pairs cannot be used as entities, nothing to iterate - return __iterator_fns.__each_iterator - end - local entity_index = entity % 2 ^ 20 if __freelist_ids[entity_index] ~= entity then @@ -5824,11 +5043,6 @@ end ---@return evolved.execute_state? iterator_state ---@nodiscard function __evolved_execute(query) - if __evolved_is_pair(query) then - -- pairs cannot be used as queries, nothing to execute - return __iterator_fns.__execute_major_iterator - end - local query_index = query % 2 ^ 20 if __freelist_ids[query_index] ~= query then @@ -5853,134 +5067,57 @@ function __evolved_execute(query) if query_include_count > 0 then local query_major = query_include_list[query_include_count] - if __evolved_is_wildcard(query_major) then - local minor_chunks = __minor_chunks[query_major] - 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]] + local major_chunks = __major_chunks[query_major] + 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 query_include_index = 1, query_include_count - 1 do - local query_minor = query_include_list[query_include_index] + for major_chunk_index = 1, major_chunk_count do + local major_chunk = major_chunk_list[major_chunk_index] - local query_chunks = __minor_chunks[query_minor] - local query_chunk_list = query_chunks and query_chunks.__item_list --[=[@as evolved.chunk[]]=] - local query_chunk_count = query_chunks and query_chunks.__item_count or 0 --[[@as integer]] + local is_major_chunk_matched = true - if query_chunk_count < minor_chunk_count then - minor_chunks, minor_chunk_list, minor_chunk_count = - query_chunks, query_chunk_list, query_chunk_count + if is_major_chunk_matched and query_include_count > 1 then + is_major_chunk_matched = __chunk_has_all_fragment_list( + major_chunk, query_include_list, query_include_count - 1) + end - if query_chunk_count == 0 then + if is_major_chunk_matched and query_exclude_count > 0 then + is_major_chunk_matched = not __chunk_has_any_fragment_list( + major_chunk, query_exclude_list, query_exclude_count) + end + + if is_major_chunk_matched and major_chunk.__has_explicit_minors then + local major_chunk_minor_list = major_chunk.__fragment_list + local major_chunk_minor_count = major_chunk.__fragment_count - 1 + + for major_chunk_fragment_index = 1, major_chunk_minor_count do + local major_chunk_minor = major_chunk_minor_list[major_chunk_fragment_index] + + local is_major_chunk_minor_included = + query_include_set[major_chunk_minor] + + if not is_major_chunk_minor_included and __evolved_has(major_chunk_minor, __EXPLICIT) then + is_major_chunk_matched = false break end end end - for minor_chunk_index = 1, minor_chunk_count do - local minor_chunk = minor_chunk_list[minor_chunk_index] - - local is_minor_chunk_matched = true - - if is_minor_chunk_matched and minor_chunk.__entity_count == 0 then - is_minor_chunk_matched = false - end - - if is_minor_chunk_matched then - is_minor_chunk_matched = __chunk_has_all_fragment_list( - minor_chunk, query_include_list, query_include_count) - end - - if is_minor_chunk_matched and query_exclude_count > 0 then - is_minor_chunk_matched = not __chunk_has_any_fragment_list( - minor_chunk, query_exclude_list, query_exclude_count) - end - - if is_minor_chunk_matched and minor_chunk.__has_explicit_fragments then - local minor_chunk_fragment_list = minor_chunk.__fragment_list - local minor_chunk_fragment_count = minor_chunk.__fragment_count - - for minor_chunk_fragment_index = 1, minor_chunk_fragment_count do - local minor_chunk_fragment = minor_chunk_fragment_list[minor_chunk_fragment_index] - - local is_minor_chunk_fragment_included = - query_include_set[minor_chunk_fragment] or - query_include_set[__secondary_wildcard(__evolved_unpack(minor_chunk_fragment))] - - if not is_minor_chunk_fragment_included and __evolved_has(minor_chunk_fragment, __EXPLICIT) then - is_minor_chunk_matched = false - break - end - end - end - - if is_minor_chunk_matched then - chunk_stack_size = chunk_stack_size + 1 - chunk_stack[chunk_stack_size] = minor_chunk - end + if is_major_chunk_matched then + chunk_stack_size = chunk_stack_size + 1 + chunk_stack[chunk_stack_size] = major_chunk end - - ---@type evolved.execute_state - local execute_state = __acquire_table(__table_pool_tag.execute_state) - - execute_state[1] = __structural_changes - execute_state[2] = chunk_stack - execute_state[3] = chunk_stack_size - execute_state[4] = query_exclude_set - - return __iterator_fns.__execute_minor_iterator, execute_state - else - local major_chunks = __major_chunks[query_major] - 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] - - local is_major_chunk_matched = true - - if is_major_chunk_matched and query_include_count > 1 then - is_major_chunk_matched = __chunk_has_all_fragment_list( - major_chunk, query_include_list, query_include_count - 1) - end - - if is_major_chunk_matched and query_exclude_count > 0 then - is_major_chunk_matched = not __chunk_has_any_fragment_list( - major_chunk, query_exclude_list, query_exclude_count) - end - - if is_major_chunk_matched and major_chunk.__has_explicit_minors then - local major_chunk_minor_list = major_chunk.__fragment_list - local major_chunk_minor_count = major_chunk.__fragment_count - 1 - - for major_chunk_fragment_index = 1, major_chunk_minor_count do - local major_chunk_minor = major_chunk_minor_list[major_chunk_fragment_index] - - local is_major_chunk_minor_included = - query_include_set[major_chunk_minor] or - query_include_set[__secondary_wildcard(__evolved_unpack(major_chunk_minor))] - - if not is_major_chunk_minor_included and __evolved_has(major_chunk_minor, __EXPLICIT) then - is_major_chunk_matched = false - break - end - end - end - - if is_major_chunk_matched then - chunk_stack_size = chunk_stack_size + 1 - chunk_stack[chunk_stack_size] = major_chunk - end - end - - ---@type evolved.execute_state - local execute_state = __acquire_table(__table_pool_tag.execute_state) - - execute_state[1] = __structural_changes - execute_state[2] = chunk_stack - execute_state[3] = chunk_stack_size - execute_state[4] = query_exclude_set - - return __iterator_fns.__execute_major_iterator, execute_state end + + ---@type evolved.execute_state + local execute_state = __acquire_table(__table_pool_tag.execute_state) + + execute_state[1] = __structural_changes + execute_state[2] = chunk_stack + execute_state[3] = chunk_stack_size + execute_state[4] = query_exclude_set + + return __iterator_fns.__execute_major_iterator, execute_state else for _, root_chunk in __lua_next, __root_chunks do local is_root_chunk_matched = true @@ -6024,9 +5161,7 @@ function __evolved_process(...) ---@type evolved.system local system = __lua_select(argument_index, ...) - if __evolved_is_pair(system) then - -- pairs cannot be used as systems, nothing to process - elseif not __evolved_alive(system) then + if not __evolved_alive(system) then -- this system is not alive, nothing to process elseif __evolved_has(system, __DISABLED) then -- this system is disabled, nothing to process @@ -6107,277 +5242,6 @@ function __evolved_collect_garbage() __evolved_commit() end ----@param primary evolved.id ----@param secondary evolved.id ----@return evolved.id pair ----@nodiscard -function __evolved_pair(primary, secondary) - local options = __PAIR_OPTS - - if primary == __ANY and secondary == __ANY then - options = __WILDCARD_OPTS - elseif primary == __ANY then - options = __PRIMARY_WILDCARD_OPTS - elseif secondary == __ANY then - options = __SECONDARY_WILDCARD_OPTS - end - - return primary % 2 ^ 20 - + secondary % 2 ^ 20 * 2 ^ 20 - + options * 2 ^ 40 --[[@as evolved.id]] -end - ----@param pair evolved.id ----@return evolved.id primary ----@return evolved.id secondary ----@nodiscard -function __evolved_unpair(pair) - local primary_index = pair % 2 ^ 20 - local secondary_index = (pair - primary_index) / 2 ^ 20 % 2 ^ 20 - - local primary = __freelist_ids[primary_index] --[[@as evolved.id]] - if not primary or primary % 2 ^ 20 ~= primary_index then - __error_fmt('the primary fragment of the pair (%s) is not alive and cannot be unpaired', - __id_name(pair)) - end - - local secondary = __freelist_ids[secondary_index] --[[@as evolved.id]] - if not secondary or secondary % 2 ^ 20 ~= secondary_index then - __error_fmt('the secondary fragment of the pair (%s) is not alive and cannot be unpaired', - __id_name(pair)) - end - - return primary, secondary -end - ----@param id evolved.id ----@return boolean ----@nodiscard -function __evolved_is_pair(id) - return id % 2 ^ 41 >= 2 ^ 40 -end - ----@param id evolved.id ----@return boolean ----@nodiscard -function __evolved_is_wildcard(id) - return id % 2 ^ 43 >= 2 ^ 41 -end - ----@param entity evolved.entity ----@param secondary evolved.fragment ----@param index? integer ----@return evolved.fragment? primary ----@return evolved.component? component ----@nodiscard -function __evolved_primary(entity, secondary, index) - index = index or 1 - - if __evolved_is_pair(entity) then - -- pairs are always empty - return - end - - local entity_index = entity % 2 ^ 20 - - if __freelist_ids[entity_index] ~= entity then - -- non-alive entities do not have any fragments - return - end - - local chunk = __entity_chunks[entity_index] - local place = __entity_places[entity_index] - - local secondary_fragments = chunk and chunk.__secondary_pairs[secondary % 2 ^ 20] - local secondary_fragment_list = secondary_fragments and secondary_fragments.__item_list - local secondary_fragment_count = secondary_fragments and secondary_fragments.__item_count or 0 - - if index < 1 or index > secondary_fragment_count then - return - end - - local secondary_fragment = secondary_fragment_list[index] - local primary, _ = __evolved_unpair(secondary_fragment) - - local component_index = chunk.__component_indices[secondary_fragment] - local component_storage = chunk.__component_storages[component_index] - - return primary, component_storage and component_storage[place] -end - ----@param entity evolved.entity ----@param primary evolved.fragment ----@param index? integer ----@return evolved.fragment? secondary ----@return evolved.component? component ----@nodiscard -function __evolved_secondary(entity, primary, index) - index = index or 1 - - if __evolved_is_pair(entity) then - -- pairs are always empty - return - end - - local entity_index = entity % 2 ^ 20 - - if __freelist_ids[entity_index] ~= entity then - -- non-alive entities do not have any fragments - return - end - - local chunk = __entity_chunks[entity_index] - local place = __entity_places[entity_index] - - local primary_fragments = chunk and chunk.__primary_pairs[primary % 2 ^ 20] - local primary_fragment_list = primary_fragments and primary_fragments.__item_list - local primary_fragment_count = primary_fragments and primary_fragments.__item_count or 0 - - if index < 1 or index > primary_fragment_count then - return - end - - local primary_fragment = primary_fragment_list[index] - local _, secondary = __evolved_unpair(primary_fragment) - - local component_index = chunk.__component_indices[primary_fragment] - local component_storage = chunk.__component_storages[component_index] - - return secondary, component_storage and component_storage[place] -end - ----@param entity evolved.entity ----@param secondary evolved.fragment ----@return evolved.primaries_iterator iterator ----@return evolved.primaries_state? iterator_state ----@nodiscard -function __evolved_primaries(entity, secondary) - if __evolved_is_pair(entity) then - -- pairs are always empty - return __iterator_fns.__primaries_iterator - end - - local entity_index = entity % 2 ^ 20 - - if __freelist_ids[entity_index] ~= entity then - -- non-alive entities do not have any fragments - return __iterator_fns.__primaries_iterator - end - - local chunk = __entity_chunks[entity_index] - local place = __entity_places[entity_index] - - local secondary_index = secondary % 2 ^ 20 - local secondary_fragments = chunk and chunk.__secondary_pairs[secondary_index] - - if not secondary_fragments or secondary_fragments.__item_count == 0 then - -- no primaries for this secondary - return __iterator_fns.__primaries_iterator - end - - ---@type evolved.primaries_state - local primaries_state = __acquire_table(__table_pool_tag.primaries_state) - - primaries_state[1] = __structural_changes - primaries_state[2] = chunk - primaries_state[3] = place - primaries_state[4] = secondary_index - primaries_state[5] = 1 - - return __iterator_fns.__primaries_iterator, primaries_state -end - ----@param entity evolved.entity ----@param primary evolved.fragment ----@return evolved.secondaries_iterator iterator ----@return evolved.secondaries_state? iterator_state ----@nodiscard -function __evolved_secondaries(entity, primary) - if __evolved_is_pair(entity) then - -- pairs are always empty - return __iterator_fns.__secondaries_iterator - end - - local entity_index = entity % 2 ^ 20 - - if __freelist_ids[entity_index] ~= entity then - -- non-alive entities do not have any fragments - return __iterator_fns.__secondaries_iterator - end - - local chunk = __entity_chunks[entity_index] - local place = __entity_places[entity_index] - - local primary_index = primary % 2 ^ 20 - local primary_fragments = chunk and chunk.__primary_pairs[primary_index] - - if not primary_fragments or primary_fragments.__item_count == 0 then - -- no secondaries for this primary - return __iterator_fns.__secondaries_iterator - end - - ---@type evolved.secondaries_state - local secondaries_state = __acquire_table(__table_pool_tag.secondaries_state) - - secondaries_state[1] = __structural_changes - secondaries_state[2] = chunk - secondaries_state[3] = place - secondaries_state[4] = primary_index - secondaries_state[5] = 1 - - return __iterator_fns.__secondaries_iterator, secondaries_state -end - ----@param entity evolved.entity ----@param secondary evolved.fragment ----@return integer ----@nodiscard -function __evolved_primary_count(entity, secondary) - if __evolved_is_pair(entity) then - -- pairs are always empty - return 0 - end - - local entity_index = entity % 2 ^ 20 - - if __freelist_ids[entity_index] ~= entity then - -- non-alive entities do not have any fragments - return 0 - end - - local chunk = __entity_chunks[entity_index] - - local secondary_index = secondary % 2 ^ 20 - local secondary_fragments = chunk and chunk.__secondary_pairs[secondary_index] - - return secondary_fragments and secondary_fragments.__item_count or 0 -end - ----@param entity evolved.entity ----@param primary evolved.fragment ----@return integer ----@nodiscard -function __evolved_secondary_count(entity, primary) - if __evolved_is_pair(entity) then - -- pairs are always empty - return 0 - end - - local entity_index = entity % 2 ^ 20 - - if __freelist_ids[entity_index] ~= entity then - -- non-alive entities do not have any fragments - return 0 - end - - local chunk = __entity_chunks[entity_index] - - local primary_index = primary % 2 ^ 20 - local primary_fragments = chunk and chunk.__primary_pairs[primary_index] - - return primary_fragments and primary_fragments.__item_count or 0 -end - --- --- --- @@ -6566,30 +5430,6 @@ function __builder_mt:has(fragment) return true end - local primary_pairs = self.__primary_pairs - local secondary_pairs = self.__secondary_pairs - - local maybe_has_pairs = primary_pairs and secondary_pairs - - if maybe_has_pairs and __evolved_is_wildcard(fragment) then - ---@cast primary_pairs -? - ---@cast secondary_pairs -? - - local fragment_primary_index, fragment_secondary_index, fragment_opts = - __evolved_unpack(fragment) - - if fragment_opts == __WILDCARD_OPTS then - return __lua_next(primary_pairs) ~= nil - and __lua_next(secondary_pairs) ~= nil - elseif fragment_opts == __PRIMARY_WILDCARD_OPTS then - local secondary_fragments = secondary_pairs[fragment_secondary_index] - return secondary_fragments ~= nil and secondary_fragments.__item_count > 0 - elseif fragment_opts == __SECONDARY_WILDCARD_OPTS then - local primary_fragments = primary_pairs[fragment_primary_index] - return primary_fragments ~= nil and primary_fragments.__item_count > 0 - end - end - return false end @@ -6605,41 +5445,30 @@ function __builder_mt:has_all(...) local cs = self.__components - local has_f = self.has - local has_fs = self.has_all - - local m_has_p = self.__primary_pairs and self.__secondary_pairs - if fragment_count == 1 then local f1 = ... - return (m_has_p and has_f(self, f1)) - or (not m_has_p and cs[f1] ~= nil) + return cs[f1] ~= nil end if fragment_count == 2 then local f1, f2 = ... - return (m_has_p and has_f(self, f1) and has_f(self, f2)) - or (not m_has_p and cs[f1] ~= nil and cs[f2] ~= nil) + return cs[f1] ~= nil and cs[f2] ~= nil end if fragment_count == 3 then local f1, f2, f3 = ... - return (m_has_p and has_f(self, f1) and has_f(self, f2) and has_f(self, f3)) - or (not m_has_p and cs[f1] ~= nil and cs[f2] ~= nil and cs[f3] ~= nil) + return cs[f1] ~= nil and cs[f2] ~= nil and cs[f3] ~= nil end if fragment_count == 4 then local f1, f2, f3, f4 = ... - return (m_has_p and has_f(self, f1) and has_f(self, f2) and has_f(self, f3) and has_f(self, f4)) - or (not m_has_p and cs[f1] ~= nil and cs[f2] ~= nil and cs[f3] ~= nil and cs[f4] ~= nil) + return cs[f1] ~= nil and cs[f2] ~= nil and cs[f3] ~= nil and cs[f4] ~= nil end do local f1, f2, f3, f4 = ... - return (m_has_p and has_f(self, f1) and has_f(self, f2) and has_f(self, f3) and has_f(self, f4) - and has_fs(self, __lua_select(5, ...))) - or (not m_has_p and cs[f1] ~= nil and cs[f2] ~= nil and cs[f3] ~= nil and cs[f4] ~= nil - and has_fs(self, __lua_select(5, ...))) + return cs[f1] ~= nil and cs[f2] ~= nil and cs[f3] ~= nil and cs[f4] ~= nil + and self:has_all(__lua_select(5, ...)) end end @@ -6655,41 +5484,30 @@ function __builder_mt:has_any(...) local cs = self.__components - local has_f = self.has - local has_fs = self.has_any - - local m_has_p = self.__primary_pairs and self.__secondary_pairs - if fragment_count == 1 then local f1 = ... - return (m_has_p and has_f(self, f1)) - or (not m_has_p and cs[f1] ~= nil) + return cs[f1] ~= nil end if fragment_count == 2 then local f1, f2 = ... - return (m_has_p and (has_f(self, f1) or has_f(self, f2))) - or (not m_has_p and (cs[f1] ~= nil or cs[f2] ~= nil)) + return cs[f1] ~= nil or cs[f2] ~= nil end if fragment_count == 3 then local f1, f2, f3 = ... - return (m_has_p and (has_f(self, f1) or has_f(self, f2) or has_f(self, f3))) - or (not m_has_p and (cs[f1] ~= nil or cs[f2] ~= nil or cs[f3] ~= nil)) + return cs[f1] ~= nil or cs[f2] ~= nil or cs[f3] ~= nil end if fragment_count == 4 then local f1, f2, f3, f4 = ... - return (m_has_p and (has_f(self, f1) or has_f(self, f2) or has_f(self, f3) or has_f(self, f4))) - or (not m_has_p and (cs[f1] ~= nil or cs[f2] ~= nil or cs[f3] ~= nil or cs[f4] ~= nil)) + return cs[f1] ~= nil or cs[f2] ~= nil or cs[f3] ~= nil or cs[f4] ~= nil end do local f1, f2, f3, f4 = ... - return (m_has_p and (has_f(self, f1) or has_f(self, f2) or has_f(self, f3) or has_f(self, f4) - or has_fs(self, __lua_select(5, ...)))) - or (not m_has_p and (cs[f1] ~= nil or cs[f2] ~= nil or cs[f3] ~= nil or cs[f4] ~= nil - or has_fs(self, __lua_select(5, ...)))) + return cs[f1] ~= nil or cs[f2] ~= nil or cs[f3] ~= nil or cs[f4] ~= nil + or self:has_any(__lua_select(5, ...)) end end @@ -6740,10 +5558,6 @@ function __builder_mt:set(fragment, component) if not __evolved_alive(fragment) then __error_fmt('the fragment (%s) is not alive and cannot be used', __id_name(fragment)) end - - if __evolved_is_wildcard(fragment) then - __error_fmt('the wildcard fragment (%s) cannot be used as a fragment', __id_name(fragment)) - end end do @@ -6759,40 +5573,6 @@ function __builder_mt:set(fragment, component) self.__components[fragment] = new_component end - if __evolved_is_pair(fragment) then - local fragment_primary_index, fragment_secondary_index = - __evolved_unpack(fragment) - - local primary_pairs = self.__primary_pairs - local secondary_pairs = self.__secondary_pairs - - if not primary_pairs then - primary_pairs = {} - self.__primary_pairs = primary_pairs - end - - if not secondary_pairs then - secondary_pairs = {} - self.__secondary_pairs = secondary_pairs - end - - local primary_fragments = primary_pairs[fragment_primary_index] - local secondary_fragments = secondary_pairs[fragment_secondary_index] - - if not primary_fragments then - primary_fragments = __assoc_list_new(4) - primary_pairs[fragment_primary_index] = primary_fragments - end - - if not secondary_fragments then - secondary_fragments = __assoc_list_new(4) - secondary_pairs[fragment_secondary_index] = secondary_fragments - end - - __assoc_list_insert(primary_fragments, fragment) - __assoc_list_insert(secondary_fragments, fragment) - end - return self end @@ -6805,100 +5585,42 @@ function __builder_mt:remove(...) return self end - local fragment = ... + local cs = self.__components - local components = self.__components - - components[fragment] = nil - - local primary_pairs = self.__primary_pairs - local secondary_pairs = self.__secondary_pairs - - local maybe_has_pairs = primary_pairs and secondary_pairs - - if maybe_has_pairs and __evolved_is_wildcard(fragment) then - ---@cast primary_pairs -? - ---@cast secondary_pairs -? - - local fragment_primary_index, fragment_secondary_index, fragment_opts = - __evolved_unpack(fragment) - - if fragment_opts == __WILDCARD_OPTS then - for primary_index, primary_fragments in __lua_next, primary_pairs do - local primary_fragment_list = primary_fragments.__item_list - local primary_fragment_count = primary_fragments.__item_count - - for primary_fragment_index = 1, primary_fragment_count do - local primary_fragment = primary_fragment_list[primary_fragment_index] - components[primary_fragment] = nil - end - - primary_pairs[primary_index] = nil - end - - for secondary_index, secondary_fragments in __lua_next, secondary_pairs do - local secondary_fragment_list = secondary_fragments.__item_list - local secondary_fragment_count = secondary_fragments.__item_count - - for secondary_fragment_index = 1, secondary_fragment_count do - local secondary_fragment = secondary_fragment_list[secondary_fragment_index] - components[secondary_fragment] = nil - end - - secondary_pairs[secondary_index] = nil - end - elseif fragment_opts == __PRIMARY_WILDCARD_OPTS then - local secondary_fragments = secondary_pairs[fragment_secondary_index] - local secondary_fragment_list = secondary_fragments and secondary_fragments.__item_list - local secondary_fragment_count = secondary_fragments and secondary_fragments.__item_count or 0 - - for secondary_fragment_index = 1, secondary_fragment_count do - local secondary_fragment = secondary_fragment_list[secondary_fragment_index] - components[secondary_fragment] = nil - - local secondary_fragment_primary_index, _ = __evolved_unpack(secondary_fragment) - if __assoc_list_remove(primary_pairs[secondary_fragment_primary_index], secondary_fragment) == 0 then - primary_pairs[secondary_fragment_primary_index] = nil - end - end - - secondary_pairs[fragment_secondary_index] = nil - elseif fragment_opts == __SECONDARY_WILDCARD_OPTS then - local primary_fragments = primary_pairs[fragment_primary_index] - local primary_fragment_list = primary_fragments and primary_fragments.__item_list - local primary_fragment_count = primary_fragments and primary_fragments.__item_count or 0 - - for primary_fragment_index = 1, primary_fragment_count do - local primary_fragment = primary_fragment_list[primary_fragment_index] - components[primary_fragment] = nil - - local _, primary_fragment_secondary_index = __evolved_unpack(primary_fragment) - if __assoc_list_remove(secondary_pairs[primary_fragment_secondary_index], primary_fragment) == 0 then - secondary_pairs[primary_fragment_secondary_index] = nil - end - end - - primary_pairs[fragment_primary_index] = nil - end + if fragment_count == 1 then + local f1 = ... + cs[f1] = nil + return self end - return fragment_count > 1 and self:remove(__lua_select(2, ...)) or self + if fragment_count == 2 then + local f1, f2 = ... + cs[f1] = nil; cs[f2] = nil + return self + end + + if fragment_count == 3 then + local f1, f2, f3 = ... + cs[f1] = nil; cs[f2] = nil; cs[f3] = nil + return self + end + + if fragment_count == 4 then + local f1, f2, f3, f4 = ... + cs[f1] = nil; cs[f2] = nil; cs[f3] = nil; cs[f4] = nil + return self + end + + do + local f1, f2, f3, f4 = ... + cs[f1] = nil; cs[f2] = nil; cs[f3] = nil; cs[f4] = nil + return self:remove(__lua_select(5, ...)) + end end ---@return evolved.builder builder function __builder_mt:clear() - if self.__components then - __lua_table_clear(self.__components) - end - - if self.__primary_pairs then - __lua_table_clear(self.__primary_pairs) - end - - if self.__secondary_pairs then - __lua_table_clear(self.__secondary_pairs) - end - + __lua_table_clear(self.__components) return self end @@ -7134,8 +5856,6 @@ __evolved_set(__REQUIRES, __ON_REMOVE, __update_major_chunks_hook) --- --- -__evolved_set(__ANY, __NAME, 'ANY') - __evolved_set(__TAG, __NAME, 'TAG') __evolved_set(__NAME, __NAME, 'NAME') @@ -7176,8 +5896,6 @@ __evolved_set(__DESTRUCTION_POLICY_REMOVE_FRAGMENT, __NAME, 'DESTRUCTION_POLICY_ --- --- -__evolved_set(__ANY, __INTERNAL) - __evolved_set(__TAG, __INTERNAL) __evolved_set(__NAME, __INTERNAL) @@ -7218,8 +5936,6 @@ __evolved_set(__DESTRUCTION_POLICY_REMOVE_FRAGMENT, __INTERNAL) --- --- -__evolved_set(__ANY, __TAG) - __evolved_set(__TAG, __TAG) __evolved_set(__UNIQUE, __TAG) @@ -7384,8 +6100,6 @@ end) --- --- -evolved.ANY = __ANY - evolved.TAG = __TAG evolved.NAME = __NAME @@ -7422,7 +6136,7 @@ evolved.DESTRUCTION_POLICY_REMOVE_FRAGMENT = __DESTRUCTION_POLICY_REMOVE_FRAGMEN --- --- ---- Core Functions +--- Functions --- --- @@ -7473,27 +6187,6 @@ evolved.collect_garbage = __evolved_collect_garbage evolved.chunk = __evolved_chunk evolved.builder = __evolved_builder ---- ---- ---- Relation Functions ---- ---- - -evolved.pair = __evolved_pair -evolved.unpair = __evolved_unpair - -evolved.is_pair = __evolved_is_pair -evolved.is_wildcard = __evolved_is_wildcard - -evolved.primary = __evolved_primary -evolved.secondary = __evolved_secondary - -evolved.primaries = __evolved_primaries -evolved.secondaries = __evolved_secondaries - -evolved.primary_count = __evolved_primary_count -evolved.secondary_count = __evolved_secondary_count - --- --- ---