primary/secondary iterators for pair entities

This commit is contained in:
BlackMATov
2025-08-29 18:19:19 +07:00
parent d4a7c7b77c
commit 22302cee75
2 changed files with 369 additions and 122 deletions

View File

@@ -1683,6 +1683,201 @@ do
end
end
do
---@generic T1, T2
---@param first T1
---@param second T2
---@return T1
---@diagnostic disable-next-line: unused-local
local function fst(first, second)
return first
end
---@generic T1, T2
---@param first T1
---@param second T2
---@return T2
---@diagnostic disable-next-line: unused-local
local function snd(first, second)
return second
end
do
local p, s1, s2, f = evo.id(4)
local e = evo.builder()
:set(evo.pair(p, s1), 21)
:set(evo.pair(p, s2), 42)
:spawn()
assert(fst(evo.primary(e, s1)) == p)
assert(snd(evo.primary(e, s1)) == 21)
assert(fst(evo.primary(e, s2)) == p)
assert(snd(evo.primary(e, s2)) == 42)
assert(fst(evo.primary(e, s1, 1)) == p)
assert(snd(evo.primary(e, s1, 1)) == 21)
assert(fst(evo.primary(e, s2, 1)) == p)
assert(snd(evo.primary(e, s2, 1)) == 42)
assert(fst(evo.primary(e, s1, 2)) == nil)
assert(snd(evo.primary(e, s1, 2)) == nil)
assert(fst(evo.primary(e, s2, 2)) == nil)
assert(snd(evo.primary(e, s2, 2)) == nil)
assert(fst(evo.primary(evo.pair(e, f), s1)) == p)
assert(snd(evo.primary(evo.pair(e, f), s1)) == 21)
assert(fst(evo.primary(evo.pair(e, f), s2)) == p)
assert(snd(evo.primary(evo.pair(e, f), s2)) == 42)
assert(fst(evo.primary(evo.pair(e, f), s1, 1)) == p)
assert(snd(evo.primary(evo.pair(e, f), s1, 1)) == 21)
assert(fst(evo.primary(evo.pair(e, f), s2, 1)) == p)
assert(snd(evo.primary(evo.pair(e, f), s2, 1)) == 42)
assert(fst(evo.primary(evo.pair(e, f), s1, 2)) == nil)
assert(snd(evo.primary(evo.pair(e, f), s1, 2)) == nil)
assert(fst(evo.primary(evo.pair(e, f), s2, 2)) == nil)
assert(snd(evo.primary(evo.pair(e, f), s2, 2)) == nil)
assert(fst(evo.secondary(e, p)) == s1)
assert(snd(evo.secondary(e, p)) == 21)
assert(fst(evo.secondary(e, p, 1)) == s1)
assert(snd(evo.secondary(e, p, 1)) == 21)
assert(fst(evo.secondary(e, p, 2)) == s2)
assert(snd(evo.secondary(e, p, 2)) == 42)
assert(fst(evo.secondary(e, p, 3)) == nil)
assert(snd(evo.secondary(e, p, 3)) == nil)
assert(fst(evo.secondary(evo.pair(e, f), p)) == s1)
assert(snd(evo.secondary(evo.pair(e, f), p)) == 21)
assert(fst(evo.secondary(evo.pair(e, f), p, 1)) == s1)
assert(snd(evo.secondary(evo.pair(e, f), p, 1)) == 21)
assert(fst(evo.secondary(evo.pair(e, f), p, 2)) == s2)
assert(snd(evo.secondary(evo.pair(e, f), p, 2)) == 42)
assert(fst(evo.secondary(evo.pair(e, f), p, 3)) == nil)
assert(snd(evo.secondary(evo.pair(e, f), p, 3)) == nil)
assert(fst(evo.primary(evo.pair(f, e), s1)) == nil)
assert(snd(evo.primary(evo.pair(f, e), s1)) == nil)
assert(fst(evo.primary(evo.pair(f, e), s2)) == nil)
assert(snd(evo.primary(evo.pair(f, e), s2)) == nil)
assert(fst(evo.secondary(evo.pair(f, e), p)) == nil)
assert(snd(evo.secondary(evo.pair(f, e), p)) == nil)
end
do
local p, s1, s2, f = evo.id(4)
local e = evo.builder()
:set(evo.pair(p, s1), 21)
:set(evo.pair(p, s2), 42)
:spawn()
assert(evo.primary_count(e, p) == 0)
assert(evo.primary_count(e, s1) == 1)
assert(evo.primary_count(e, s2) == 1)
assert(evo.secondary_count(e, p) == 2)
assert(evo.secondary_count(e, s1) == 0)
assert(evo.secondary_count(e, s2) == 0)
assert(evo.primary_count(evo.pair(e, f), p) == 0)
assert(evo.primary_count(evo.pair(e, f), s1) == 1)
assert(evo.primary_count(evo.pair(e, f), s2) == 1)
assert(evo.secondary_count(evo.pair(e, f), p) == 2)
assert(evo.secondary_count(evo.pair(e, f), s1) == 0)
assert(evo.secondary_count(evo.pair(e, f), s2) == 0)
assert(evo.primary_count(evo.pair(f, e), p) == 0)
assert(evo.primary_count(evo.pair(f, e), s1) == 0)
assert(evo.primary_count(evo.pair(f, e), s2) == 0)
assert(evo.secondary_count(evo.pair(f, e), p) == 0)
assert(evo.secondary_count(evo.pair(f, e), s1) == 0)
assert(evo.secondary_count(evo.pair(f, e), s2) == 0)
end
do
local p, s1, s2, f = evo.id(4)
local e = evo.builder()
:set(evo.pair(p, s1), 21)
:set(evo.pair(p, s2), 42)
:spawn()
do
local iter, state = evo.primaries(e, p)
local fragment, component = iter(state)
assert(fragment == nil and component == nil)
iter, state = evo.primaries(evo.pair(e, f), p)
fragment, component = iter(state)
assert(fragment == nil and component == nil)
end
do
local iter, state = evo.primaries(e, s1)
local fragment, component = iter(state)
assert(fragment == p and component == 21)
fragment, component = iter(state)
assert(fragment == nil and component == nil)
iter, state = evo.primaries(evo.pair(e, f), s1)
fragment, component = iter(state)
assert(fragment == p and component == 21)
fragment, component = iter(state)
assert(fragment == nil and component == nil)
end
do
local iter, state = evo.primaries(e, s2)
local fragment, component = iter(state)
assert(fragment == p and component == 42)
fragment, component = iter(state)
assert(fragment == nil and component == nil)
iter, state = evo.primaries(evo.pair(e, f), s2)
fragment, component = iter(state)
assert(fragment == p and component == 42)
fragment, component = iter(state)
assert(fragment == nil and component == nil)
end
end
do
local p, s1, s2, f = evo.id(4)
local e = evo.builder()
:set(evo.pair(p, s1), 21)
:set(evo.pair(p, s2), 42)
:spawn()
do
local iter, state = evo.secondaries(e, s1)
local fragment, component = iter(state)
assert(fragment == nil and component == nil)
iter, state = evo.secondaries(evo.pair(e, f), s1)
fragment, component = iter(state)
assert(fragment == nil and component == nil)
end
do
local iter, state = evo.secondaries(e, p)
local fragment, component = iter(state)
assert(fragment == s1 and component == 21)
fragment, component = iter(state)
assert(fragment == s2 and component == 42)
fragment, component = iter(state)
assert(fragment == nil and component == nil)
iter, state = evo.secondaries(evo.pair(e, f), p)
fragment, component = iter(state)
assert(fragment == s1 and component == 21)
fragment, component = iter(state)
assert(fragment == s2 and component == 42)
fragment, component = iter(state)
assert(fragment == nil and component == nil)
end
end
end
-- TODO
-- builder:has/has_all/has_any should work with wildcards / remove too?
-- should we provide wildcard support for get operations?

View File

@@ -4681,15 +4681,14 @@ end
---@nodiscard
function __evolved_pack(index, version)
if index < 1 or index > 2 ^ 20 - 1 then
__error_fmt('id index (%d) is out of range [1, 2 ^ 20 - 1]', index)
__error_fmt('the index (%d) is out of range [1, 2 ^ 20 - 1]', index)
end
if version < 1 or version > 2 ^ 20 - 1 then
__error_fmt('id version (%d) is out of range [1, 2 ^ 20 - 1]', version)
__error_fmt('the version (%d) is out of range [1, 2 ^ 20 - 1]', version)
end
return index
+ version * 2 ^ 20 --[[@as evolved.id]]
return index + version * 2 ^ 20 --[[@as evolved.id]]
end
---@param id evolved.id
@@ -4817,8 +4816,8 @@ function __evolved_alive(entity)
return false
end
else
local primary = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not primary or primary % 2 ^ 20 ~= entity_index then
local entity_primary_id = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not entity_primary_id or entity_primary_id % 2 ^ 20 ~= entity_index then
return false
end
end
@@ -4879,8 +4878,8 @@ function __evolved_empty(entity)
return true
end
else
local primary = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not primary or primary % 2 ^ 20 ~= entity_index then
local entity_primary_id = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not entity_primary_id or entity_primary_id % 2 ^ 20 ~= entity_index then
return true
end
end
@@ -4942,8 +4941,8 @@ function __evolved_has(entity, fragment)
return false
end
else
local primary = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not primary or primary % 2 ^ 20 ~= entity_index then
local entity_primary_id = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not entity_primary_id or entity_primary_id % 2 ^ 20 ~= entity_index then
return false
end
end
@@ -4971,8 +4970,8 @@ function __evolved_has_all(entity, ...)
return false
end
else
local primary = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not primary or primary % 2 ^ 20 ~= entity_index then
local entity_primary_id = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not entity_primary_id or entity_primary_id % 2 ^ 20 ~= entity_index then
return false
end
end
@@ -5000,8 +4999,8 @@ function __evolved_has_any(entity, ...)
return false
end
else
local primary = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not primary or primary % 2 ^ 20 ~= entity_index then
local entity_primary_id = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not entity_primary_id or entity_primary_id % 2 ^ 20 ~= entity_index then
return false
end
end
@@ -5023,8 +5022,8 @@ function __evolved_get(entity, ...)
return
end
else
local primary = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not primary or primary % 2 ^ 20 ~= entity_index then
local entity_primary_id = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not entity_primary_id or entity_primary_id % 2 ^ 20 ~= entity_index then
return
end
end
@@ -5068,13 +5067,13 @@ function __evolved_set(entity, fragment, component)
__error_fmt('the pair (%s) is a wildcard and cannot be set', __id_name(fragment))
end
local primary = __freelist_ids[primary_index] --[[@as evolved.id?]]
if not primary or primary % 2 ^ 20 ~= primary_index then
local fragment_primary_id = __freelist_ids[primary_index] --[[@as evolved.id?]]
if not fragment_primary_id or fragment_primary_id % 2 ^ 20 ~= primary_index then
__error_fmt('the pair (%s) has no alive primary id and cannot be set', __id_name(fragment))
end
local secondary = __freelist_ids[secondary_index] --[[@as evolved.id?]]
if not secondary or secondary % 2 ^ 20 ~= secondary_index then
local fragment_secondary_id = __freelist_ids[secondary_index] --[[@as evolved.id?]]
if not fragment_secondary_id or fragment_secondary_id % 2 ^ 20 ~= secondary_index then
__error_fmt('the pair (%s) has no alive secondary id and cannot be set', __id_name(fragment))
end
end
@@ -5577,13 +5576,13 @@ function __evolved_batch_set(query, fragment, component)
__error_fmt('the pair (%s) is a wildcard and cannot be set', __id_name(fragment))
end
local primary = __freelist_ids[primary_index] --[[@as evolved.id?]]
if not primary or primary % 2 ^ 20 ~= primary_index then
local fragment_primary_id = __freelist_ids[primary_index] --[[@as evolved.id?]]
if not fragment_primary_id or fragment_primary_id % 2 ^ 20 ~= primary_index then
__error_fmt('the pair (%s) has no alive primary id and cannot be set', __id_name(fragment))
end
local secondary = __freelist_ids[secondary_index] --[[@as evolved.id?]]
if not secondary or secondary % 2 ^ 20 ~= secondary_index then
local fragment_secondary_id = __freelist_ids[secondary_index] --[[@as evolved.id?]]
if not fragment_secondary_id or fragment_secondary_id % 2 ^ 20 ~= secondary_index then
__error_fmt('the pair (%s) has no alive secondary id and cannot be set', __id_name(fragment))
end
end
@@ -6121,29 +6120,27 @@ end
function __evolved_pair(primary, secondary)
local primary_index, _, primary_options = __evolved_unpack(primary)
if primary_options >= __PAIR_OPTS then
__error_fmt('the primary id (%s) is a pair and cannot be used as a primary id of a pair',
__error_fmt('the primary id (%s) is a pair and cannot be used as a primary id of a new pair',
__id_name(primary))
end
local secondary_index, _, secondary_options = __evolved_unpack(secondary)
if secondary_options >= __PAIR_OPTS then
__error_fmt('the secondary id (%s) is a pair and cannot be used as a secondary id of a pair',
__error_fmt('the secondary id (%s) is a pair and cannot be used as a secondary id of a new pair',
__id_name(secondary))
end
local pair_options = __PAIR_OPTS
if primary == __ANY and secondary == __ANY then
if primary_index == __ANY_INDEX and secondary_index == __ANY_INDEX then
pair_options = __ANY_WILDCARD_OPTS
elseif primary == __ANY then
elseif primary_index == __ANY_INDEX then
pair_options = __PRI_WILDCARD_OPTS
elseif secondary == __ANY then
elseif secondary_index == __ANY_INDEX then
pair_options = __SEC_WILDCARD_OPTS
end
return primary_index
+ secondary_index * 2 ^ 20
+ pair_options * 2 ^ 40 --[[@as evolved.pair]]
return primary_index + secondary_index * 2 ^ 20 + pair_options * 2 ^ 40 --[[@as evolved.pair]]
end
---@param pair evolved.pair
@@ -6151,44 +6148,41 @@ end
---@return evolved.id secondary
---@nodiscard
function __evolved_unpair(pair)
local pair_primary, pair_secondary, pair_options = __evolved_unpack(pair)
local primary_index, secondary_index, pair_options = __evolved_unpack(pair)
if pair_options < __PAIR_OPTS then
__error_fmt('the id (%s) is not a pair and cannot be unpaired',
__id_name(pair))
__error_fmt('the id (%s) is not a pair and cannot be unpaired', __id_name(pair))
end
local primary = __freelist_ids[pair_primary] --[[@as evolved.id?]]
if not primary or primary % 2 ^ 20 ~= pair_primary then
__error_fmt('the primary id of the pair (%s) is not alive and cannot be unpaired',
__id_name(pair))
local pair_primary_id = __freelist_ids[primary_index] --[[@as evolved.id?]]
if not pair_primary_id or pair_primary_id % 2 ^ 20 ~= primary_index then
__error_fmt('the pair (%s) has not alive primary id and cannot be unpaired', __id_name(pair))
else
---@cast primary -?
---@cast pair_primary_id -?
end
local secondary = __freelist_ids[pair_secondary] --[[@as evolved.id?]]
if not secondary or secondary % 2 ^ 20 ~= pair_secondary then
__error_fmt('the secondary id of the pair (%s) is not alive and cannot be unpaired',
__id_name(pair))
local pair_secondary_id = __freelist_ids[secondary_index] --[[@as evolved.id?]]
if not pair_secondary_id or pair_secondary_id % 2 ^ 20 ~= secondary_index then
__error_fmt('the pair (%s) has not alive secondary id and cannot be unpaired', __id_name(pair))
else
---@cast secondary -?
---@cast pair_secondary_id -?
end
return primary, secondary
return pair_primary_id, pair_secondary_id
end
---@param id evolved.id
---@return boolean
---@nodiscard
function __evolved_is_pair(id)
return id % 2 ^ 41 >= 2 ^ 40
return id >= __PAIR_OPTS * 2 ^ 40
end
---@param id evolved.id
---@return boolean
---@nodiscard
function __evolved_is_wildcard(id)
return id % 2 ^ 43 >= 2 ^ 41
return id >= __PRI_WILDCARD_OPTS * 2 ^ 40
end
---@param entity evolved.entity
@@ -6200,22 +6194,32 @@ end
function __evolved_primary(entity, secondary, index)
index = index or 1
if __evolved_is_pair(entity) then
-- pairs are always empty
local entity_index, _, entity_options = __evolved_unpack(entity)
if entity_options < __PAIR_OPTS then
if __freelist_ids[entity_index] ~= entity then
return
end
else
local entity_primary_id = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not entity_primary_id or entity_primary_id % 2 ^ 20 ~= entity_index then
return
end
end
local entity_chunk = __entity_chunks[entity_index]
if not entity_chunk then
return
end
local entity_index = entity % 2 ^ 20
local secondary_index, _, secondary_options = __evolved_unpack(secondary)
if __freelist_ids[entity_index] ~= entity then
-- non-alive entities do not have any fragments
return
if secondary_options >= __PAIR_OPTS then
__error_fmt('the pair (%s) cannot be used as a secondary fragment', __id_name(secondary))
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_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
@@ -6226,10 +6230,11 @@ function __evolved_primary(entity, secondary, index)
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]
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[place]
local entity_place = __entity_places[entity_index]
return primary, component_storage and component_storage[entity_place]
end
---@param entity evolved.entity
@@ -6241,22 +6246,32 @@ end
function __evolved_secondary(entity, primary, index)
index = index or 1
if __evolved_is_pair(entity) then
-- pairs are always empty
local entity_index, _, entity_options = __evolved_unpack(entity)
if entity_options < __PAIR_OPTS then
if __freelist_ids[entity_index] ~= entity then
return
end
else
local entity_primary_id = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not entity_primary_id or entity_primary_id % 2 ^ 20 ~= entity_index then
return
end
end
local entity_chunk = __entity_chunks[entity_index]
if not entity_chunk then
return
end
local entity_index = entity % 2 ^ 20
local primary_index, _, primary_options = __evolved_unpack(primary)
if __freelist_ids[entity_index] ~= entity then
-- non-alive entities do not have any fragments
return
if primary_options >= __PAIR_OPTS then
__error_fmt('the pair (%s) cannot be used as a primary fragment', __id_name(primary))
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_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
@@ -6267,10 +6282,11 @@ function __evolved_secondary(entity, primary, index)
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]
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[place]
local entity_place = __entity_places[entity_index]
return secondary, component_storage and component_storage[entity_place]
end
---@param entity evolved.entity
@@ -6279,26 +6295,34 @@ end
---@return evolved.primaries_state? iterator_state
---@nodiscard
function __evolved_primaries(entity, secondary)
if __evolved_is_pair(entity) then
-- pairs are always empty
local entity_index, _, entity_options = __evolved_unpack(entity)
if entity_options < __PAIR_OPTS then
if __freelist_ids[entity_index] ~= entity then
return __iterator_fns.__primaries_iterator
end
else
local entity_primary_id = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not entity_primary_id or entity_primary_id % 2 ^ 20 ~= entity_index then
return __iterator_fns.__primaries_iterator
end
end
local entity_chunk = __entity_chunks[entity_index]
if not entity_chunk then
return __iterator_fns.__primaries_iterator
end
local entity_index = entity % 2 ^ 20
local secondary_index, _, secondary_options = __evolved_unpack(secondary)
if __freelist_ids[entity_index] ~= entity then
-- non-alive entities do not have any fragments
return __iterator_fns.__primaries_iterator
if secondary_options >= __PAIR_OPTS then
__error_fmt('the pair (%s) cannot be used as a secondary fragment', __id_name(secondary))
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]
local secondary_fragments = entity_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
@@ -6306,8 +6330,8 @@ function __evolved_primaries(entity, secondary)
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[2] = entity_chunk
primaries_state[3] = __entity_places[entity_index]
primaries_state[4] = secondary_index
primaries_state[5] = 1
@@ -6320,26 +6344,34 @@ end
---@return evolved.secondaries_state? iterator_state
---@nodiscard
function __evolved_secondaries(entity, primary)
if __evolved_is_pair(entity) then
-- pairs are always empty
local entity_index, _, entity_options = __evolved_unpack(entity)
if entity_options < __PAIR_OPTS then
if __freelist_ids[entity_index] ~= entity then
return __iterator_fns.__secondaries_iterator
end
else
local entity_primary_id = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not entity_primary_id or entity_primary_id % 2 ^ 20 ~= entity_index then
return __iterator_fns.__secondaries_iterator
end
end
local entity_chunk = __entity_chunks[entity_index]
if not entity_chunk then
return __iterator_fns.__secondaries_iterator
end
local entity_index = entity % 2 ^ 20
local primary_index, _, primary_options = __evolved_unpack(primary)
if __freelist_ids[entity_index] ~= entity then
-- non-alive entities do not have any fragments
return __iterator_fns.__secondaries_iterator
if primary_options >= __PAIR_OPTS then
__error_fmt('the pair (%s) cannot be used as a primary fragment', __id_name(primary))
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]
local primary_fragments = entity_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
@@ -6347,8 +6379,8 @@ function __evolved_secondaries(entity, primary)
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[2] = entity_chunk
secondaries_state[3] = __entity_places[entity_index]
secondaries_state[4] = primary_index
secondaries_state[5] = 1
@@ -6360,22 +6392,32 @@ end
---@return integer
---@nodiscard
function __evolved_primary_count(entity, secondary)
if __evolved_is_pair(entity) then
-- pairs are always empty
local entity_index, _, entity_options = __evolved_unpack(entity)
if entity_options < __PAIR_OPTS then
if __freelist_ids[entity_index] ~= entity then
return 0
end
else
local entity_primary_id = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not entity_primary_id or entity_primary_id % 2 ^ 20 ~= entity_index then
return 0
end
end
local entity_chunk = __entity_chunks[entity_index]
if not entity_chunk then
return 0
end
local entity_index = entity % 2 ^ 20
local secondary_index, _, secondary_options = __evolved_unpack(secondary)
if __freelist_ids[entity_index] ~= entity then
-- non-alive entities do not have any fragments
return 0
if secondary_options >= __PAIR_OPTS then
__error_fmt('the pair (%s) cannot be used as a secondary fragment', __id_name(secondary))
end
local chunk = __entity_chunks[entity_index]
local secondary_index = secondary % 2 ^ 20
local secondary_fragments = chunk and chunk.__secondary_pairs[secondary_index]
local secondary_fragments = entity_chunk.__secondary_pairs[secondary_index]
return secondary_fragments and secondary_fragments.__item_count or 0
end
@@ -6385,22 +6427,32 @@ end
---@return integer
---@nodiscard
function __evolved_secondary_count(entity, primary)
if __evolved_is_pair(entity) then
-- pairs are always empty
local entity_index, _, entity_options = __evolved_unpack(entity)
if entity_options < __PAIR_OPTS then
if __freelist_ids[entity_index] ~= entity then
return 0
end
else
local entity_primary_id = __freelist_ids[entity_index] --[[@as evolved.id?]]
if not entity_primary_id or entity_primary_id % 2 ^ 20 ~= entity_index then
return 0
end
end
local entity_chunk = __entity_chunks[entity_index]
if not entity_chunk then
return 0
end
local entity_index = entity % 2 ^ 20
local primary_index, _, primary_options = __evolved_unpack(primary)
if __freelist_ids[entity_index] ~= entity then
-- non-alive entities do not have any fragments
return 0
if primary_options >= __PAIR_OPTS then
__error_fmt('the pair (%s) cannot be used as a primary fragment', __id_name(primary))
end
local chunk = __entity_chunks[entity_index]
local primary_index = primary % 2 ^ 20
local primary_fragments = chunk and chunk.__primary_pairs[primary_index]
local primary_fragments = entity_chunk.__primary_pairs[primary_index]
return primary_fragments and primary_fragments.__item_count or 0
end