registry.batch_insert/remove impl

This commit is contained in:
BlackMATov
2024-11-29 16:34:15 +07:00
parent fafd8d2566
commit 007ba7905b
3 changed files with 222 additions and 41 deletions

View File

@@ -37,7 +37,7 @@ registry.has -> entity -> entity -> (boolean)
registry.has_all -> entity -> entity... -> (boolean) registry.has_all -> entity -> entity... -> (boolean)
registry.has_any -> entity -> entity... -> (boolean) registry.has_any -> entity -> entity... -> (boolean)
registry.apply -> entity -> entity -> (any -> any) -> (boolean) registry.apply -> entity -> entity -> (any -> any) -> (boolean)
registry.batch_apply -> query -> entity -> (any -> any) -> (boolean) registry.batch_apply -> query -> entity -> (any -> any) -> (integer)
registry.assign -> entity -> entity -> any -> (boolean) registry.assign -> entity -> entity -> any -> (boolean)
registry.batch_assign -> query -> entity -> any -> (integer) registry.batch_assign -> query -> entity -> any -> (integer)
registry.insert -> entity -> entity -> any -> (boolean) registry.insert -> entity -> entity -> any -> (boolean)

View File

@@ -506,6 +506,64 @@ do
end end
end end
do
local f1, f2 = evo.registry.entity(), evo.registry.entity()
do
local e1 = evo.registry.entity():set(f1, 10)
local e2 = evo.registry.entity():set(f1, 15)
local e3 = evo.registry.entity():set(f1, 20):set(f2, 40)
local e4 = evo.registry.entity():set(f1, 25):set(f2, 45)
local q = evo.registry.query(f1)
assert(2 == evo.registry.batch_insert(q, f2, 42))
assert(e1:get(f1) == 10 and e2:get(f1) == 15 and e3:get(f1) == 20 and e4:get(f1) == 25)
assert(e1:get(f2) == 42 and e2:get(f2) == 42 and e3:get(f2) == 40 and e4:get(f2) == 45)
end
end
do
local f1, f2, f3 = evo.registry.entity(), evo.registry.entity(), evo.registry.entity()
do
local e1 = evo.registry.entity():set(f1, 10)
local e2 = evo.registry.entity():set(f1, 15)
local e3 = evo.registry.entity():set(f1, 20):set(f2, 40)
local e4 = evo.registry.entity():set(f1, 25):set(f2, 45):set(f3, 55)
local e5 = evo.registry.entity():set(f3, 65)
do
local q = evo.registry.query(f2)
assert(2 == evo.registry.batch_remove(q, f1))
assert(e1.__chunk == evo.registry.chunk(f1))
assert(e2.__chunk == evo.registry.chunk(f1))
assert(e3.__chunk == evo.registry.chunk(f2))
assert(e4.__chunk == evo.registry.chunk(f2, f3))
assert(e5.__chunk == evo.registry.chunk(f3))
assert(e1:get(f1) == 10 and e2:get(f1) == 15)
assert(e3:get(f2) == 40 and e4:get(f2) == 45 and e4:get(f3) == 55)
assert(2 == evo.registry.batch_remove(q, f2))
assert(e1.__chunk == evo.registry.chunk(f1))
assert(e2.__chunk == evo.registry.chunk(f1))
assert(e3.__chunk == nil)
assert(e4.__chunk == evo.registry.chunk(f3))
assert(e5.__chunk == evo.registry.chunk(f3))
assert(e1:get(f1) == 10 and e2:get(f1) == 15)
assert(e3:get(f2) == nil and e4:get(f2) == nil and e4:get(f3) == 55)
assert(e5:get(f3) == 65)
end
do
local q = evo.registry.query(f3)
assert(0 == evo.registry.batch_remove(q, f1))
assert(2 == evo.registry.batch_remove(q, f3))
end
end
end
for _ = 1, 100 do for _ = 1, 100 do
local insert_fragments = {} ---@type evolved.entity[] local insert_fragments = {} ---@type evolved.entity[]
local insert_fragment_count = math.random(0, 10) local insert_fragment_count = math.random(0, 10)

View File

@@ -620,26 +620,31 @@ function registry.insert(entity, fragment, component)
return false return false
end end
local old_index_in_chunk = entity.__index_in_chunk do
local new_index_in_chunk = #new_chunk.__entities + 1 __changes = __changes + 1
__changes = __changes + 1
new_chunk.__changes = new_chunk.__changes + 1
new_chunk.__entities[new_index_in_chunk] = entity
new_chunk.__components[fragment][new_index_in_chunk] = component
if old_chunk ~= nil then
for old_f, old_cs in pairs(old_chunk.__components) do
local new_cs = new_chunk.__components[old_f]
new_cs[new_index_in_chunk] = old_cs[old_index_in_chunk]
end
__detach_entity(entity)
end end
entity.__chunk = new_chunk if new_chunk ~= nil then
entity.__index_in_chunk = new_index_in_chunk local old_index_in_chunk = entity.__index_in_chunk
local new_index_in_chunk = #new_chunk.__entities + 1
new_chunk.__changes = new_chunk.__changes + 1
new_chunk.__entities[new_index_in_chunk] = entity
new_chunk.__components[fragment][new_index_in_chunk] = component
if old_chunk ~= nil then
for old_f, old_cs in pairs(old_chunk.__components) do
local new_cs = new_chunk.__components[old_f]
new_cs[new_index_in_chunk] = old_cs[old_index_in_chunk]
end
__detach_entity(entity)
end
entity.__chunk = new_chunk
entity.__index_in_chunk = new_index_in_chunk
else
__detach_entity(entity)
end
return true return true
end end
@@ -649,9 +654,68 @@ end
---@param component any ---@param component any
---@return integer inserted_count ---@return integer inserted_count
function registry.batch_insert(query, fragment, component) function registry.batch_insert(query, fragment, component)
error('not impl yet', 2) component = component == nil and true or component
end
---@type evolved.chunk[]
local chunks = {}
for chunk in registry.execute(query) do
if not __chunk_has_fragment(chunk, fragment) then
chunks[#chunks + 1] = chunk
end
end
local inserted_count = 0
for _, old_chunk in ipairs(chunks) do
local new_chunk = __chunk_with_fragment(old_chunk, fragment)
do
local changes = #old_chunk.__entities
__changes = __changes + changes
inserted_count = inserted_count + changes
old_chunk.__changes = old_chunk.__changes + changes
if new_chunk ~= nil then
new_chunk.__changes = new_chunk.__changes + changes
end
end
if new_chunk ~= nil then
for _, entity in ipairs(old_chunk.__entities) do
local new_index_in_chunk = #new_chunk.__entities + 1
new_chunk.__entities[new_index_in_chunk] = entity
new_chunk.__components[fragment][new_index_in_chunk] = component
entity.__chunk = new_chunk
entity.__index_in_chunk = new_index_in_chunk
end
for old_f, old_cs in pairs(old_chunk.__components) do
local new_cs = new_chunk.__components[old_f]
for i = 1, #old_cs do new_cs[#new_cs + 1] = old_cs[i] end
end
else
for _, entity in ipairs(old_chunk.__entities) do
entity.__chunk = nil
entity.__index_in_chunk = 0
end
end
do
old_chunk.__entities = {}
for old_f, _ in pairs(old_chunk.__components) do
old_chunk.__components[old_f] = {}
end
end
end
return inserted_count
end
---@param entity evolved.entity ---@param entity evolved.entity
---@param ... evolved.entity fragments ---@param ... evolved.entity fragments
@@ -668,39 +732,96 @@ function registry.remove(entity, ...)
return false return false
end end
if new_chunk == nil then do
__detach_entity(entity) __changes = __changes + 1
return true
end end
local old_index_in_chunk = entity.__index_in_chunk if new_chunk ~= nil then
local new_index_in_chunk = #new_chunk.__entities + 1 local old_index_in_chunk = entity.__index_in_chunk
local new_index_in_chunk = #new_chunk.__entities + 1
__changes = __changes + 1 new_chunk.__changes = new_chunk.__changes + 1
new_chunk.__changes = new_chunk.__changes + 1 new_chunk.__entities[new_index_in_chunk] = entity
new_chunk.__entities[new_index_in_chunk] = entity if old_chunk ~= nil then
for new_f, new_cs in pairs(new_chunk.__components) do
if old_chunk ~= nil then local old_cs = old_chunk.__components[new_f]
for new_f, new_cs in pairs(new_chunk.__components) do new_cs[new_index_in_chunk] = old_cs[old_index_in_chunk]
local old_cs = old_chunk.__components[new_f] end
new_cs[new_index_in_chunk] = old_cs[old_index_in_chunk] __detach_entity(entity)
end end
entity.__chunk = new_chunk
entity.__index_in_chunk = new_index_in_chunk
else
__detach_entity(entity) __detach_entity(entity)
end end
entity.__chunk = new_chunk
entity.__index_in_chunk = new_index_in_chunk
return true return true
end end
---@param query evolved.query ---@param query evolved.query
---@param ... evolved.entity fragments ---@param ... evolved.entity fragments
---@return boolean removed_count ---@return integer removed_count
function registry.batch_remove(query, ...) function registry.batch_remove(query, ...)
error('not impl yet', 2) ---@type evolved.chunk[]
local chunks = {}
for chunk in registry.execute(query) do
if __chunk_has_any_fragments(chunk, ...) then
chunks[#chunks + 1] = chunk
end
end
local removed_count = 0
for _, old_chunk in ipairs(chunks) do
local new_chunk = __chunk_without_fragments(old_chunk, ...)
do
local changes = #old_chunk.__entities
__changes = __changes + changes
removed_count = removed_count + changes
old_chunk.__changes = old_chunk.__changes + changes
if new_chunk ~= nil then
new_chunk.__changes = new_chunk.__changes + changes
end
end
if new_chunk ~= nil then
for _, entity in ipairs(old_chunk.__entities) do
local new_index_in_chunk = #new_chunk.__entities + 1
new_chunk.__entities[new_index_in_chunk] = entity
entity.__chunk = new_chunk
entity.__index_in_chunk = new_index_in_chunk
end
for new_f, new_cs in pairs(new_chunk.__components) do
local old_cs = old_chunk.__components[new_f]
for i = 1, #old_cs do new_cs[#new_cs + 1] = old_cs[i] end
end
else
for _, entity in ipairs(old_chunk.__entities) do
entity.__chunk = nil
entity.__index_in_chunk = 0
end
end
do
old_chunk.__entities = {}
for old_f, _ in pairs(old_chunk.__components) do
old_chunk.__components[old_f] = {}
end
end
end
return removed_count
end end
---@param entity evolved.entity ---@param entity evolved.entity
@@ -719,7 +840,7 @@ function registry.detach(entity)
end end
---@param query evolved.query ---@param query evolved.query
---@return boolean detached_count ---@return integer detached_count
function registry.batch_detach(query) function registry.batch_detach(query)
error('not impl yet', 2) error('not impl yet', 2)
end end
@@ -854,7 +975,9 @@ function registry.execute(query)
end end
end end
return matched_chunk if #matched_chunk.__entities > 0 then
return matched_chunk
end
end end
end end
end end