From 35c65924188d6241e7e0254bfb0ed8772bcd8ebc Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 1 Aug 2025 06:46:43 +0700 Subject: [PATCH] required fragments work with pairs by primary fragment --- develop/testing/pairs_tests.lua | 223 +++++++++++++++++++++++++++++++- evolved.lua | 78 +++++------ 2 files changed, 250 insertions(+), 51 deletions(-) diff --git a/develop/testing/pairs_tests.lua b/develop/testing/pairs_tests.lua index 64892f3..9d6c4ed 100644 --- a/develop/testing/pairs_tests.lua +++ b/develop/testing/pairs_tests.lua @@ -303,8 +303,8 @@ do assert(evo.has(e, f2)) assert(evo.get(e, f2) == 84) - assert(not evo.has(e, f3)) - assert(evo.get(e, f3) == nil) + assert(evo.has(e, f3)) + assert(evo.get(e, f3) == true) end do @@ -1195,9 +1195,218 @@ do 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 + -- TODO: --- How should required fragments work with pairs? --- How can we set defaults for paired fragments? --- Prevent setting wildcard pairs to entities! --- Should we have destruction policies analog for pairs? --- Should we call hooks for pairs? +-- Add errors on modifying pairs diff --git a/evolved.lua b/evolved.lua index f29fb41..619c2ef 100644 --- a/evolved.lua +++ b/evolved.lua @@ -1194,8 +1194,8 @@ function __iterator_fns.__secondaries_iterator(secondaries_state) end local pairs = entity_chunk.__primary_pairs[primary_fragment] - local pair_list = pairs and pairs.__item_list - local pair_count = pairs and pairs.__item_count or 0 + local pair_list = pairs and pairs.__item_list --[=[@as evolved.id[]]=] + local pair_count = pairs and pairs.__item_count or 0 --[[@as integer]] if primary_pair_index >= 1 and primary_pair_index <= pair_count then secondaries_state[5] = primary_pair_index + 1 @@ -2282,30 +2282,25 @@ local function __chunk_required_fragments(chunk, req_fragment_set, req_fragment_ fragment_stack_size = fragment_stack_size - 1 if __is_pair(stack_fragment) then - -- this is a pair fragment, just skip it - else - local fragment_requires = __sorted_requires[stack_fragment] - local fragment_require_list = fragment_requires and fragment_requires.__item_list - local fragment_require_count = fragment_requires and fragment_requires.__item_count or 0 + stack_fragment = __evolved_unpair(stack_fragment) + end - for fragment_require_index = 1, fragment_require_count do - ---@cast fragment_require_list -? - local required_fragment = fragment_require_list[fragment_require_index] + local fragment_requires = __sorted_requires[stack_fragment] + local fragment_require_list = fragment_requires and fragment_requires.__item_list + local fragment_require_count = fragment_requires and fragment_requires.__item_count or 0 - if req_fragment_set[required_fragment] then - -- this fragment has already been gathered - else - req_fragment_count = req_fragment_count + 1 - req_fragment_set[required_fragment] = req_fragment_count - req_fragment_list[req_fragment_count] = required_fragment + for fragment_require_index = 1, fragment_require_count do + local required_fragment = fragment_require_list[fragment_require_index] - if __is_pair(required_fragment) then - -- this is a pair fragment, just skip it - else - fragment_stack_size = fragment_stack_size + 1 - fragment_stack[fragment_stack_size] = required_fragment - end - end + if req_fragment_set[required_fragment] then + -- this fragment has already been gathered + else + req_fragment_count = req_fragment_count + 1 + req_fragment_set[required_fragment] = req_fragment_count + req_fragment_list[req_fragment_count] = required_fragment + + fragment_stack_size = fragment_stack_size + 1 + fragment_stack[fragment_stack_size] = required_fragment end end end @@ -2337,30 +2332,25 @@ local function __fragment_required_fragments(fragment, req_fragment_set, req_fra fragment_stack_size = fragment_stack_size - 1 if __is_pair(stack_fragment) then - -- this is a pair fragment, just skip it - else - local fragment_requires = __sorted_requires[stack_fragment] - local fragment_require_list = fragment_requires and fragment_requires.__item_list - local fragment_require_count = fragment_requires and fragment_requires.__item_count or 0 + stack_fragment = __evolved_unpair(stack_fragment) + end - for fragment_require_index = 1, fragment_require_count do - ---@cast fragment_require_list -? - local required_fragment = fragment_require_list[fragment_require_index] + local fragment_requires = __sorted_requires[stack_fragment] + local fragment_require_list = fragment_requires and fragment_requires.__item_list + local fragment_require_count = fragment_requires and fragment_requires.__item_count or 0 - if req_fragment_set[required_fragment] then - -- this fragment has already been gathered - else - req_fragment_count = req_fragment_count + 1 - req_fragment_set[required_fragment] = req_fragment_count - req_fragment_list[req_fragment_count] = required_fragment + for fragment_require_index = 1, fragment_require_count do + local required_fragment = fragment_require_list[fragment_require_index] - if __is_pair(required_fragment) then - -- this is a pair fragment, just skip it - else - fragment_stack_size = fragment_stack_size + 1 - fragment_stack[fragment_stack_size] = required_fragment - end - end + if req_fragment_set[required_fragment] then + -- this fragment has already been gathered + else + req_fragment_count = req_fragment_count + 1 + req_fragment_set[required_fragment] = req_fragment_count + req_fragment_list[req_fragment_count] = required_fragment + + fragment_stack_size = fragment_stack_size + 1 + fragment_stack[fragment_stack_size] = required_fragment end end end