From 9e532cce95e4f02cf7e6cfc1fc1f005e54df0ae4 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 21 Jan 2025 08:50:24 +0700 Subject: [PATCH] batch-multi-api: batch_multi_set impl --- develop/untests.lua | 377 +++++++++++++++++++++++++++++++++++++++++++- evolved.lua | 304 ++++++++++++++++++++++++++++++++++- 2 files changed, 679 insertions(+), 2 deletions(-) diff --git a/develop/untests.lua b/develop/untests.lua index b557f5d..4de4ea9 100644 --- a/develop/untests.lua +++ b/develop/untests.lua @@ -4307,7 +4307,368 @@ do end do - local f1, f2, f3 = evo.id(3) + local f1, f2, f3, f4 = evo.id(4) + + evo.set(f2, evo.DEFAULT, 52) + evo.set(f4, evo.TAG) + + local e1a = evo.entity():set(f1, 11):build() + local e1b = evo.entity():set(f1, 11):build() + + local e2a = evo.entity():set(f1, 21):set(f2, 22):build() + local e2b = evo.entity():set(f1, 21):set(f2, 22):build() + + local e3a = evo.entity():set(f1, 31):set(f2, 32):set(f3, 33):build() + local e3b = evo.entity():set(f1, 31):set(f2, 32):set(f3, 33):build() + + local e4a = evo.entity():set(f1, 41):set(f2, 42):set(f3, 43):set(f4, 44):build() + local e4b = evo.entity():set(f1, 41):set(f2, 42):set(f3, 43):set(f4, 44):build() + + do + local q = evo.query():include(f1):build() + assert(evo.batch_multi_set(q, {}) == 0) + end + + do + local q = evo.query():include(f3):exclude(f4):build() + assert(evo.batch_multi_set(q, { f3 }) == 2) + assert(evo.get(e1a, f1) == 11 and evo.get(e1a, f2) == nil and evo.get(e1a, f3) == nil) + assert(evo.get(e1b, f1) == 11 and evo.get(e1b, f2) == nil and evo.get(e1b, f3) == nil) + assert(evo.get(e2a, f1) == 21 and evo.get(e2a, f2) == 22 and evo.get(e2a, f3) == nil) + assert(evo.get(e2b, f1) == 21 and evo.get(e2b, f2) == 22 and evo.get(e2b, f3) == nil) + assert(evo.get(e3a, f1) == 31 and evo.get(e3a, f2) == 32 and evo.get(e3a, f3) == true) + assert(evo.get(e3b, f1) == 31 and evo.get(e3b, f2) == 32 and evo.get(e3b, f3) == true) + assert(evo.get(e4a, f1) == 41 and evo.get(e4a, f2) == 42 and evo.get(e4a, f3) == 43 and evo.get(e4a, f4) == nil) + assert(evo.get(e4b, f1) == 41 and evo.get(e4b, f2) == 42 and evo.get(e4b, f3) == 43 and evo.get(e4b, f4) == nil) + end + + do + local q = evo.query():include(f3):exclude(f4):build() + assert(evo.batch_multi_set(q, { f3 }, { 43, 44 }) == 2) + assert(evo.get(e1a, f1) == 11 and evo.get(e1a, f2) == nil and evo.get(e1a, f3) == nil) + assert(evo.get(e1b, f1) == 11 and evo.get(e1b, f2) == nil and evo.get(e1b, f3) == nil) + assert(evo.get(e2a, f1) == 21 and evo.get(e2a, f2) == 22 and evo.get(e2a, f3) == nil) + assert(evo.get(e2b, f1) == 21 and evo.get(e2b, f2) == 22 and evo.get(e2b, f3) == nil) + assert(evo.get(e3a, f1) == 31 and evo.get(e3a, f2) == 32 and evo.get(e3a, f3) == 43) + assert(evo.get(e3b, f1) == 31 and evo.get(e3b, f2) == 32 and evo.get(e3b, f3) == 43) + assert(evo.get(e4a, f1) == 41 and evo.get(e4a, f2) == 42 and evo.get(e4a, f3) == 43 and evo.get(e4a, f4) == nil) + assert(evo.get(e4b, f1) == 41 and evo.get(e4b, f2) == 42 and evo.get(e4b, f3) == 43 and evo.get(e4b, f4) == nil) + end + + do + local q = evo.query():include(f2):exclude(f3, f4):build() + assert(evo.batch_multi_set(q, { f2 }, {}) == 2) + assert(evo.get(e1a, f1) == 11 and evo.get(e1a, f2) == nil and evo.get(e1a, f3) == nil) + assert(evo.get(e1b, f1) == 11 and evo.get(e1b, f2) == nil and evo.get(e1b, f3) == nil) + assert(evo.get(e2a, f1) == 21 and evo.get(e2a, f2) == 52 and evo.get(e2a, f3) == nil) + assert(evo.get(e2b, f1) == 21 and evo.get(e2b, f2) == 52 and evo.get(e2b, f3) == nil) + assert(evo.get(e3a, f1) == 31 and evo.get(e3a, f2) == 32 and evo.get(e3a, f3) == 43) + assert(evo.get(e3b, f1) == 31 and evo.get(e3b, f2) == 32 and evo.get(e3b, f3) == 43) + assert(evo.get(e4a, f1) == 41 and evo.get(e4a, f2) == 42 and evo.get(e4a, f3) == 43 and evo.get(e4a, f4) == nil) + assert(evo.get(e4b, f1) == 41 and evo.get(e4b, f2) == 42 and evo.get(e4b, f3) == 43 and evo.get(e4b, f4) == nil) + end + + do + local q = evo.query():include(f2):exclude(f3, f4):build() + assert(evo.batch_multi_set(q, { f2 }, { 62, 63 }) == 2) + assert(evo.get(e1a, f1) == 11 and evo.get(e1a, f2) == nil and evo.get(e1a, f3) == nil) + assert(evo.get(e1b, f1) == 11 and evo.get(e1b, f2) == nil and evo.get(e1b, f3) == nil) + assert(evo.get(e2a, f1) == 21 and evo.get(e2a, f2) == 62 and evo.get(e2a, f3) == nil) + assert(evo.get(e2b, f1) == 21 and evo.get(e2b, f2) == 62 and evo.get(e2b, f3) == nil) + assert(evo.get(e3a, f1) == 31 and evo.get(e3a, f2) == 32 and evo.get(e3a, f3) == 43) + assert(evo.get(e3b, f1) == 31 and evo.get(e3b, f2) == 32 and evo.get(e3b, f3) == 43) + assert(evo.get(e4a, f1) == 41 and evo.get(e4a, f2) == 42 and evo.get(e4a, f3) == 43 and evo.get(e4a, f4) == nil) + assert(evo.get(e4b, f1) == 41 and evo.get(e4b, f2) == 42 and evo.get(e4b, f3) == 43 and evo.get(e4b, f4) == nil) + end +end + +do + local fc = evo.id() + evo.set(fc, evo.TAG) + + local f1, f2, f3, f4 = evo.id(4) + + evo.set(f2, evo.DEFAULT, 52) + evo.set(f4, evo.TAG) + + evo.set(f1, fc) + evo.set(f2, fc) + evo.set(f3, fc) + evo.set(f4, fc) + + local sum_entity = 0 + local last_assign_entity = 0 + local last_assign_component = 0 + + do + local q = evo.query():include(fc):build() + evo.batch_set(q, evo.ON_ASSIGN, function(e, f, c) + assert(f == f1 or f == f2 or f == f3 or f == f4) + sum_entity = sum_entity + e + last_assign_entity = e + last_assign_component = c + end) + end + + local e2a = evo.entity():set(f1, 21):set(f2, 22):build() + local e2b = evo.entity():set(f1, 21):set(f2, 22):build() + + local e3a = evo.entity():set(f1, 31):set(f2, 32):set(f3, 33):build() + local e3b = evo.entity():set(f1, 31):set(f2, 32):set(f3, 33):build() + + local e4a = evo.entity():set(f1, 41):set(f2, 42):set(f3, 43):set(f4, 44):build() + local e4b = evo.entity():set(f1, 41):set(f2, 42):set(f3, 43):set(f4, 44):build() + + do + local q = evo.query():include(f1):build() + assert(evo.batch_multi_set(q, {}) == 0) + end + + do + local q = evo.query():include(f2):exclude(f3, f4):build() + + sum_entity = 0 + last_assign_entity = 0 + last_assign_component = 0 + + assert(evo.batch_multi_set(q, { f2 }) == 2) + assert(sum_entity == e2a + e2b) + assert(last_assign_entity == e2b) + assert(last_assign_component == 52) + assert(evo.get(e2a, f2) == 52 and evo.get(e2b, f2) == 52) + + sum_entity = 0 + last_assign_entity = 0 + last_assign_component = 0 + + assert(evo.batch_multi_set(q, { f2, f2 }) == 2) + assert(sum_entity == e2a + e2b + e2a + e2b) + assert(last_assign_entity == e2b) + assert(last_assign_component == 52) + assert(evo.get(e2a, f2) == 52 and evo.get(e2b, f2) == 52) + end + + do + local q = evo.query():include(f2):exclude(f3, f4):build() + + sum_entity = 0 + last_assign_entity = 0 + last_assign_component = 0 + + assert(evo.batch_multi_set(q, { f2 }, { 62, 63 }) == 2) + assert(sum_entity == e2a + e2b) + assert(last_assign_entity == e2b) + assert(last_assign_component == 62) + assert(evo.get(e2a, f2) == 62 and evo.get(e2b, f2) == 62) + + sum_entity = 0 + last_assign_entity = 0 + last_assign_component = 0 + + assert(evo.batch_multi_set(q, { f2, f2 }, { 62, 63 }) == 2) + assert(sum_entity == e2a + e2b + e2a + e2b) + assert(last_assign_entity == e2b) + assert(last_assign_component == 63) + assert(evo.get(e2a, f2) == 63 and evo.get(e2b, f2) == 63) + end + + do + local q = evo.query():include(f3):exclude(f4):build() + + sum_entity = 0 + last_assign_entity = 0 + last_assign_component = 0 + + assert(evo.batch_multi_set(q, { f3 }) == 2) + assert(sum_entity == e3a + e3b) + assert(last_assign_entity == e3b) + assert(last_assign_component == true) + assert(evo.get(e3a, f3) == true and evo.get(e3b, f3) == true) + end + + do + local q = evo.query():include(f4):build() + + sum_entity = 0 + last_assign_entity = 0 + last_assign_component = 0 + + assert(evo.batch_multi_set(q, { f4 }, { 62, 63 }) == 2) + assert(sum_entity == e4a + e4b) + assert(last_assign_entity == e4b) + assert(last_assign_component == nil) + assert(evo.has(e4a, f4) and evo.has(e4b, f4)) + assert(evo.get(e4a, f4) == nil and evo.get(e4b, f4) == nil) + + sum_entity = 0 + last_assign_entity = 0 + last_assign_component = 0 + + assert(evo.batch_multi_set(q, { f4, f4 }, { 62, 63 }) == 2) + assert(sum_entity == e4a + e4b + e4a + e4b) + assert(last_assign_entity == e4b) + assert(last_assign_component == nil) + assert(evo.get(e2a, f4) == nil and evo.get(e2b, f4) == nil) + end +end + +do + local f1, f2, f3, f4 = evo.id(4) + + evo.set(f2, evo.DEFAULT, 52) + evo.set(f4, evo.TAG) + + local e1a = evo.entity():set(f1, 11):build() + local e1b = evo.entity():set(f1, 11):build() + + local e2a = evo.entity():set(f1, 21):set(f2, 22):build() + local e2b = evo.entity():set(f1, 21):set(f2, 22):build() + + local e3a = evo.entity():set(f1, 31):set(f2, 32):set(f3, 33):build() + local e3b = evo.entity():set(f1, 31):set(f2, 32):set(f3, 33):build() + + do + local q = evo.query():include(f2):exclude(f3, f4):build() + assert(evo.batch_multi_set(q, { f3 }) == 2) + assert(evo.get(e2a, f1) == 21 and evo.get(e2a, f2) == 22 and evo.get(e2a, f3) == true) + assert(evo.get(e2b, f1) == 21 and evo.get(e2b, f2) == 22 and evo.get(e2b, f3) == true) + assert(evo.get(e3a, f1) == 31 and evo.get(e3a, f2) == 32 and evo.get(e3a, f3) == 33) + assert(evo.get(e3b, f1) == 31 and evo.get(e3b, f2) == 32 and evo.get(e3b, f3) == 33) + do + local c12, c12_es = evo.chunk(f1, f2) + assert(c12 and #c12_es == 0) + assert(#evo.select(c12, f1) == 0) + assert(#evo.select(c12, f2) == 0) + + local c123, c123_es = evo.chunk(f1, f2, f3) + assert(c123 and #c123_es == 4) + assert(#evo.select(c123, f1) == 4) + assert(#evo.select(c123, f2) == 4) + assert(#evo.select(c123, f3) == 4) + end + end + + do + local q = evo.query():include(f2, f3):exclude(f4):build() + assert(evo.batch_multi_set(q, { f2, f3, f4, f4 }, { 62, 63, 64, 65 }) == 4) + assert(evo.has_all(e2a, f2, f3, f4) and evo.has_all(e2b, f2, f3, f4)) + assert(evo.get(e2a, f1) == 21 and evo.get(e2a, f2) == 62 and evo.get(e2a, f3) == 63 and evo.get(e2a, f4) == nil) + assert(evo.get(e2b, f1) == 21 and evo.get(e2b, f2) == 62 and evo.get(e2b, f3) == 63 and evo.get(e2b, f4) == nil) + assert(evo.get(e3a, f1) == 31 and evo.get(e3a, f2) == 62 and evo.get(e3a, f3) == 63 and evo.get(e3a, f4) == nil) + assert(evo.get(e3b, f1) == 31 and evo.get(e3b, f2) == 62 and evo.get(e3b, f3) == 63 and evo.get(e3b, f4) == nil) + end + + do + local q = evo.query():include(f1):exclude(f2, f3, f4):build() + assert(evo.batch_multi_set(q, { f2, f1 }, { nil, 71 }) == 2) + assert(evo.get(e1a, f1) == 71 and evo.get(e1a, f2) == 52) + assert(evo.get(e1b, f1) == 71 and evo.get(e1b, f2) == 52) + do + local c1, c1_es = evo.chunk(f1) + assert(c1 and #c1_es == 0) + assert(#evo.select(c1, f1) == 0) + + local c12, c12_es = evo.chunk(f1, f2) + assert(c12 and #c12_es == 2) + assert(#evo.select(c12, f1) == 2) + assert(#evo.select(c12, f2) == 2) + end + end +end + +do + local fc = evo.id() + evo.set(fc, evo.TAG) + + local f0, f1, f2, f3, f4 = evo.id(5) + + evo.set(f2, evo.DEFAULT, 52) + evo.set(f1, evo.TAG) + + evo.set(f0, fc) + evo.set(f1, fc) + evo.set(f2, fc) + evo.set(f3, fc) + evo.set(f4, fc) + + local sum_entity = 0 + local last_assign_entity = 0 + local last_assign_component = 0 + local last_insert_entity = 0 + local last_insert_component = 0 + + do + local q = evo.query():include(fc):build() + evo.batch_set(q, evo.ON_ASSIGN, function(e, f, c) + assert(f == f0 or f == f1 or f == f2 or f == f3 or f == f4) + sum_entity = sum_entity + e + last_assign_entity = e + last_assign_component = c + end) + evo.batch_set(q, evo.ON_INSERT, function(e, f, c) + assert(f == f0 or f == f1 or f == f2 or f == f3 or f == f4) + sum_entity = sum_entity + e + last_insert_entity = e + last_insert_component = c + end) + end + + local e0a = evo.entity():set(f0, 0):build() + local e0b = evo.entity():set(f0, 0):build() + + local e3a = evo.entity():set(f1, 31):set(f2, 32):set(f3, 33):build() + local e3b = evo.entity():set(f1, 31):set(f2, 32):set(f3, 33):build() + + do + local q = evo.query():include(f0):build() + + sum_entity = 0 + last_assign_entity, last_assign_component = 0, 0 + last_insert_entity, last_insert_component = 0, 0 + + assert(evo.batch_multi_set(q, { f1, f2 }, { 51 }) == 2) + assert(sum_entity == e0a + e0b + e0a + e0b) + assert(last_assign_entity == 0) + assert(last_assign_component == 0) + assert(last_insert_entity == e0b) + assert(last_insert_component == 52) + assert(evo.get(e0a, f0) == 0 and evo.get(e0a, f1) == nil and evo.get(e0a, f2) == 52 and evo.get(e0a, f3) == nil) + assert(evo.get(e0b, f0) == 0 and evo.get(e0b, f1) == nil and evo.get(e0b, f2) == 52 and evo.get(e0b, f3) == nil) + + sum_entity = 0 + last_assign_entity, last_assign_component = 0, 0 + last_insert_entity, last_insert_component = 0, 0 + + assert(evo.batch_multi_set(q, { f1, f3, f2 }, { 61 }) == 2) + assert(sum_entity == e0a + e0b + e0a + e0b + e0a + e0b) + assert(last_assign_entity == e0b) + assert(last_assign_component == 52) + assert(last_insert_entity == e0b) + assert(last_insert_component == true) + assert(evo.get(e0a, f0) == 0 and evo.get(e0a, f1) == nil and evo.get(e0a, f2) == 52 and evo.get(e0a, f3) == true) + assert(evo.get(e0b, f0) == 0 and evo.get(e0b, f1) == nil and evo.get(e0b, f2) == 52 and evo.get(e0b, f3) == true) + end + + do + local q = evo.query():include(f3):exclude(f0, f4):build() + + sum_entity = 0 + last_assign_entity, last_assign_component = 0, 0 + last_insert_entity, last_insert_component = 0, 0 + + assert(evo.batch_multi_set(q, { f3, f4 }, { 53, 54 }) == 2) + assert(sum_entity == e3a + e3b + e3a + e3b) + assert(last_assign_entity == e3b) + assert(last_assign_component == 53) + assert(last_insert_entity == e3b) + assert(last_insert_component == 54) + assert(evo.get(e3a, f1) == nil and evo.get(e3a, f2) == 32 and evo.get(e3a, f3) == 53 and evo.get(e3a, f4) == 54) + assert(evo.get(e3b, f1) == nil and evo.get(e3b, f2) == 32 and evo.get(e3b, f3) == 53 and evo.get(e3b, f4) == 54) + end +end + +do + local f1, f2, f3, f4 = evo.id(4) local e1 = evo.entity():set(f1, 11):build() local e2 = evo.entity():set(f1, 21):set(f2, 22):build() @@ -4338,4 +4699,18 @@ do assert(evo.get(e2, f1) == nil and evo.get(e2, f2) == 22 and evo.get(e2, f3) == nil) assert(evo.get(e3, f1) == nil and evo.get(e3, f2) == 32 and evo.get(e3, f3) == 43) end + assert(evo.defer()) + do + local q = evo.query():include(f2):build() + do + local n, d = evo.batch_multi_set(q, { f3, f4 }, { 53, 54 }) + assert(n == 0 and d == true) + end + end + assert(evo.commit()) + do + assert(evo.get(e1, f1) == nil and evo.get(e1, f2) == 42 and evo.get(e1, f3) == 53 and evo.get(e1, f4) == 54) + assert(evo.get(e2, f1) == nil and evo.get(e2, f2) == 22 and evo.get(e2, f3) == 53 and evo.get(e2, f4) == 54) + assert(evo.get(e3, f1) == nil and evo.get(e3, f2) == 32 and evo.get(e3, f3) == 53 and evo.get(e3, f4) == 54) + end end diff --git a/evolved.lua b/evolved.lua index 6106a5e..6eb6a2a 100644 --- a/evolved.lua +++ b/evolved.lua @@ -1356,7 +1356,309 @@ end ---@param components evolved.component[] ---@return integer set_count local function __chunk_multi_set(chunk, fragments, components) - error('not implemented yet', 2) + if __defer_depth <= 0 then + error('batched chunk operations should be deferred', 2) + end + + local fragment_count = #fragments + + if fragment_count == 0 then + return 0 + end + + local old_chunk = chunk + local new_chunk = __chunk_with_fragment_list(chunk, fragments) + + if not new_chunk then + return 0 + end + + local old_entities = old_chunk.__entities + local old_size = #old_entities + + local old_fragment_set = old_chunk.__fragment_set + local old_component_indices = old_chunk.__component_indices + local old_component_storages = old_chunk.__component_storages + local old_component_fragments = old_chunk.__component_fragments + + if old_chunk == new_chunk then + for i = 1, fragment_count do + local fragment = fragments[i] + if chunk.__has_set_or_assign_hooks and __fragment_has_set_or_assign_hooks(fragment) then + local old_component_index = old_component_indices[fragment] + if old_component_index then + local old_component_storage = old_component_storages[old_component_index] + if chunk.__has_defaults_or_constructs and __fragment_has_default_or_construct(fragment) then + local new_component = components[i] + + if new_component == nil then + new_component = evolved.get(fragment, evolved.DEFAULT) + end + + if new_component == nil then + new_component = true + end + + for place = 1, old_size do + local entity = old_entities[place] + local old_component = old_component_storage[place] + old_component_storage[place] = new_component + __fragment_call_set_and_assign_hooks(entity, fragment, new_component, old_component) + end + else + local new_component = components[i] + + if new_component == nil then + new_component = true + end + + for place = 1, old_size do + local entity = old_entities[place] + local old_component = old_component_storage[place] + old_component_storage[place] = new_component + __fragment_call_set_and_assign_hooks(entity, fragment, new_component, old_component) + end + end + else + for place = 1, old_size do + local entity = old_entities[place] + __fragment_call_set_and_assign_hooks(entity, fragment) + end + end + else + local old_component_index = old_component_indices[fragment] + if old_component_index then + local old_component_storage = old_component_storages[old_component_index] + if chunk.__has_defaults_or_constructs and __fragment_has_default_or_construct(fragment) then + local new_component = components[i] + + if new_component == nil then + new_component = evolved.get(fragment, evolved.DEFAULT) + end + + if new_component == nil then + new_component = true + end + + for place = 1, old_size do + old_component_storage[place] = new_component + end + else + local new_component = components[i] + + if new_component == nil then + new_component = true + end + + for place = 1, old_size do + old_component_storage[place] = new_component + end + end + else + -- nothing + end + end + end + else + local new_entities = new_chunk.__entities + local new_size = #new_entities + + local new_component_indices = new_chunk.__component_indices + local new_component_storages = new_chunk.__component_storages + + do + __table_move( + old_entities, 1, old_size, + new_size + 1, new_entities) + + for i = 1, #old_component_fragments do + local old_f = old_component_fragments[i] + local old_cs = old_component_storages[i] + local new_ci = new_component_indices[old_f] + if new_ci then + local new_cs = new_component_storages[new_ci] + __table_move(old_cs, 1, old_size, new_size + 1, new_cs) + end + end + end + + local inserted_set = __acquire_table(__TABLE_POOL_TAG__FRAGMENT_SET, 0, fragment_count) + + for i = 1, fragment_count do + local fragment = fragments[i] + if inserted_set[fragment] or old_fragment_set[fragment] then + if new_chunk.__has_set_or_assign_hooks and __fragment_has_set_or_assign_hooks(fragment) then + local new_component_index = new_component_indices[fragment] + if new_component_index then + local new_component_storage = new_component_storages[new_component_index] + if new_chunk.__has_defaults_or_constructs and __fragment_has_default_or_construct(fragment) then + local new_component = components[i] + + if new_component == nil then + new_component = evolved.get(fragment, evolved.DEFAULT) + end + + if new_component == nil then + new_component = true + end + + for new_place = new_size + 1, new_size + old_size do + local entity = new_entities[new_place] + local old_component = new_component_storage[new_place] + new_component_storage[new_place] = new_component + __fragment_call_set_and_assign_hooks(entity, fragment, new_component, old_component) + end + else + local new_component = components[i] + + if new_component == nil then + new_component = true + end + + for new_place = new_size + 1, new_size + old_size do + local entity = new_entities[new_place] + local old_component = new_component_storage[new_place] + new_component_storage[new_place] = new_component + __fragment_call_set_and_assign_hooks(entity, fragment, new_component, old_component) + end + end + else + for new_place = new_size + 1, new_size + old_size do + local entity = new_entities[new_place] + __fragment_call_set_and_assign_hooks(entity, fragment) + end + end + else + local new_component_index = new_component_indices[fragment] + if new_component_index then + local new_component_storage = new_component_storages[new_component_index] + if new_chunk.__has_defaults_or_constructs and __fragment_has_default_or_construct(fragment) then + local new_component = components[i] + + if new_component == nil then + new_component = evolved.get(fragment, evolved.DEFAULT) + end + + if new_component == nil then + new_component = true + end + + for new_place = new_size + 1, new_size + old_size do + new_component_storage[new_place] = new_component + end + else + local new_component = components[i] + + if new_component == nil then + new_component = true + end + + for new_place = new_size + 1, new_size + old_size do + new_component_storage[new_place] = new_component + end + end + else + -- nothing + end + end + else + inserted_set[fragment] = true + if new_chunk.__has_set_or_insert_hooks and __fragment_has_set_or_insert_hooks(fragment) then + local new_component_index = new_component_indices[fragment] + if new_component_index then + local new_component_storage = new_component_storages[new_component_index] + if new_chunk.__has_defaults_or_constructs and __fragment_has_default_or_construct(fragment) then + local new_component = components[i] + + if new_component == nil then + new_component = evolved.get(fragment, evolved.DEFAULT) + end + + if new_component == nil then + new_component = true + end + + for new_place = new_size + 1, new_size + old_size do + local entity = new_entities[new_place] + new_component_storage[new_place] = new_component + __fragment_call_set_and_insert_hooks(entity, fragment, new_component) + end + else + local new_component = components[i] + + if new_component == nil then + new_component = true + end + + for new_place = new_size + 1, new_size + old_size do + local entity = new_entities[new_place] + new_component_storage[new_place] = new_component + __fragment_call_set_and_insert_hooks(entity, fragment, new_component) + end + end + else + for new_place = new_size + 1, new_size + old_size do + local entity = new_entities[new_place] + __fragment_call_set_and_insert_hooks(entity, fragment) + end + end + else + local new_component_index = new_component_indices[fragment] + if new_component_index then + local new_component_storage = new_component_storages[new_component_index] + if new_chunk.__has_defaults_or_constructs and __fragment_has_default_or_construct(fragment) then + local new_component = components[i] + + if new_component == nil then + new_component = evolved.get(fragment, evolved.DEFAULT) + end + + if new_component == nil then + new_component = true + end + + for new_place = new_size + 1, new_size + old_size do + new_component_storage[new_place] = new_component + end + else + local new_component = components[i] + + if new_component == nil then + new_component = true + end + + for new_place = new_size + 1, new_size + old_size do + new_component_storage[new_place] = new_component + end + end + else + -- nothing + end + end + end + end + + __release_table(__TABLE_POOL_TAG__FRAGMENT_SET, inserted_set) + + for new_place = new_size + 1, new_size + old_size do + local entity = new_entities[new_place] + local entity_index = entity % 0x100000 + __entity_chunks[entity_index] = new_chunk + __entity_places[entity_index] = new_place + end + + do + old_chunk.__entities = {} + + for i = 1, #old_component_storages do + old_component_storages[i] = {} + end + end + + __structural_changes = __structural_changes + old_size + end + + return old_size end ---@param chunk evolved.chunk