multi fragments removing

This commit is contained in:
BlackMATov
2024-11-24 09:19:27 +07:00
parent 1f15a92831
commit 39e18294c1
4 changed files with 84 additions and 45 deletions

View File

@@ -34,8 +34,8 @@ 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.assign -> entity -> entity -> any -> () registry.assign -> entity -> entity -> any -> ()
registry.insert -> entity -> entity -> any -> () registry.insert -> entity -> entity -> any -> (boolean)
registry.remove -> entity -> entity -> () registry.remove -> entity -> entity... -> (boolean)
registry.query -> entity -> entity... -> (query) registry.query -> entity -> entity... -> (query)
registry.execute -> query -> (() -> (chunk?)) registry.execute -> query -> (() -> (chunk?))
registry.chunk -> entity -> entity... -> (chunk) registry.chunk -> entity -> entity... -> (chunk)
@@ -55,8 +55,8 @@ entity:has -> entity -> (boolean)
entity:has_all -> entity... -> (boolean) entity:has_all -> entity... -> (boolean)
entity:has_any -> entity... -> (boolean) entity:has_any -> entity... -> (boolean)
entity:assign -> entity -> any -> () entity:assign -> entity -> any -> ()
entity:insert -> entity -> any -> () entity:insert -> entity -> any -> (boolean)
entity:remove -> entity -> () entity:remove -> entity... -> (boolean)
``` ```
### Instance `query` ### Instance `query`

View File

@@ -7,7 +7,9 @@
- [ ] add blocklist of fragments for queries - [ ] add blocklist of fragments for queries
- [ ] add checks of prohibited changes while querying - [ ] add checks of prohibited changes while querying
- [ ] add check inserts and removes after destroying entity - [ ] add check inserts and removes after destroying entity
- [ ] add multi remove fragments function from entities - [x] add multi remove fragments function from entities
- [ ] add multi get fragments function from entities
- [ ] add multi entity creation function
- [ ] cache matched chunks in queries - [ ] cache matched chunks in queries
- [x] cache transitions between chunks - [x] cache transitions between chunks
- [x] chunk's children should be stored in an array instead of a table - [x] chunk's children should be stored in an array instead of a table

View File

@@ -2,26 +2,53 @@
local evo = require 'evolved.evolved' local evo = require 'evolved.evolved'
do do
local f1, f2 = evo.registry.entity(), evo.registry.entity() local f1, f2, f3 =
evo.registry.entity(),
evo.registry.entity(),
evo.registry.entity()
local e = evo.registry.entity() local e = evo.registry.entity()
assert(e.__chunk == nil) assert(e.__chunk == nil)
e:insert(f1) assert(e:insert(f1))
assert(e:has(f1)) assert(e:has(f1))
assert(not e:has(f2)) assert(not e:has(f2))
e:insert(f2) assert(e:insert(f2))
assert(e:has(f1)) assert(e:has(f1))
assert(e:has(f2)) assert(e:has(f2))
e:remove(f1) assert(e:remove(f1))
assert(not e:has(f1)) assert(not e:has(f1))
assert(e:has(f2)) assert(e:has(f2))
e:remove(f2) assert(e:remove(f2))
assert(not e:has(f1)) assert(not e:has(f1))
assert(not e:has(f2)) assert(not e:has(f2))
assert(e:insert(f3))
assert(not e:remove(f2))
assert(not e:remove())
end
do
local f1, f2, f3, f4, f5 =
evo.registry.entity(),
evo.registry.entity(),
evo.registry.entity(),
evo.registry.entity(),
evo.registry.entity()
local e = evo.registry.entity()
assert(e:insert(f1, f1:guid()))
assert(e:insert(f2, f2:guid()))
assert(e:insert(f3, f3:guid()))
assert(e:insert(f4, f4:guid()))
assert(e:remove(f1, f2, f5))
assert(e.__chunk == evo.registry.chunk(f3, f4))
end end
do do
@@ -36,15 +63,14 @@ do
assert(e:get_or(f) == nil) assert(e:get_or(f) == nil)
assert(e:get_or(f, 42) == 42) assert(e:get_or(f, 42) == 42)
e:insert(f, 84) assert(e:insert(f, 84))
assert(e:get(f) == 84) assert(e:get(f) == 84)
assert(e:get_or(f) == 84) assert(e:get_or(f) == 84)
assert(e:get_or(f, 42) == 84) assert(e:get_or(f, 42) == 84)
if not os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") then assert(not e:insert(f, 42))
assert(not pcall(e.insert, e, f, 42)) assert(e:get(f) == 42)
end
e:assign(f) e:assign(f)
assert(e:get(f) == true) assert(e:get(f) == true)
@@ -102,7 +128,7 @@ 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(1, 10) local insert_fragment_count = math.random(0, 10)
for _ = 1, insert_fragment_count do for _ = 1, insert_fragment_count do
local fragment = evo.registry.entity() local fragment = evo.registry.entity()
@@ -110,7 +136,7 @@ for _ = 1, 100 do
end end
local remove_fragments = {} ---@type evolved.entity[] local remove_fragments = {} ---@type evolved.entity[]
local remove_fragment_count = math.random(1, insert_fragment_count) local remove_fragment_count = math.random(0, insert_fragment_count)
for _ = 1, remove_fragment_count do for _ = 1, remove_fragment_count do
local fragment = insert_fragments[math.random(1, #insert_fragments)] local fragment = insert_fragments[math.random(1, #insert_fragments)]

View File

@@ -334,7 +334,8 @@ end
---@return boolean ---@return boolean
---@nodiscard ---@nodiscard
function registry.has(entity, fragment) function registry.has(entity, fragment)
return entity.__chunk ~= nil and __chunk_has_fragment(entity.__chunk, fragment) if entity.__chunk == nil then return false end
return __chunk_has_fragment(entity.__chunk, fragment)
end end
---@param entity evolved.entity ---@param entity evolved.entity
@@ -373,6 +374,7 @@ end
---@param entity evolved.entity ---@param entity evolved.entity
---@param fragment evolved.entity ---@param fragment evolved.entity
---@param component any ---@param component any
---@return boolean is_inserted
function registry.insert(entity, fragment, component) function registry.insert(entity, fragment, component)
component = component == nil and true or component component = component == nil and true or component
@@ -380,62 +382,71 @@ function registry.insert(entity, fragment, component)
local new_chunk = __chunk_with_fragment(old_chunk, fragment) local new_chunk = __chunk_with_fragment(old_chunk, fragment)
if old_chunk == new_chunk then if old_chunk == new_chunk then
error(string.format('entity %s already has fragment %s', entity, fragment), 2) local chunk_components = new_chunk.__components[fragment]
chunk_components[entity.__index_in_chunk] = component
return false
end end
local old_index_in_chunk = entity.__index_in_chunk local old_index_in_chunk = entity.__index_in_chunk
local new_index_in_chunk = new_chunk and #new_chunk.__entities + 1 or 0 local new_index_in_chunk = #new_chunk.__entities + 1
if new_chunk ~= nil then new_chunk.__entities[new_index_in_chunk] = entity
new_chunk.__entities[new_index_in_chunk] = entity new_chunk.__components[fragment][new_index_in_chunk] = component
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
end
end
if old_chunk ~= nil then 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) __detach_entity(entity)
end end
entity.__chunk = new_chunk entity.__chunk = new_chunk
entity.__index_in_chunk = new_index_in_chunk entity.__index_in_chunk = new_index_in_chunk
return true
end end
---@param entity evolved.entity ---@param entity evolved.entity
---@param fragment evolved.entity ---@param ... evolved.entity fragments
function registry.remove(entity, fragment) ---@return boolean is_removed
function registry.remove(entity, ...)
local old_chunk = entity.__chunk local old_chunk = entity.__chunk
local new_chunk = __chunk_without_fragment(old_chunk, fragment) local new_chunk = entity.__chunk
for i = 1, select('#', ...) do
local fragment = select(i, ...)
new_chunk = __chunk_without_fragment(new_chunk, fragment)
end
if old_chunk == new_chunk then if old_chunk == new_chunk then
error(string.format('entity %s does not have fragment %s', entity, fragment), 2) return false
end
if new_chunk == nil then
__detach_entity(entity)
return true
end end
local old_index_in_chunk = entity.__index_in_chunk local old_index_in_chunk = entity.__index_in_chunk
local new_index_in_chunk = new_chunk and #new_chunk.__entities + 1 or 0 local new_index_in_chunk = #new_chunk.__entities + 1
if new_chunk ~= nil then 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
local old_cs = old_chunk.__components[new_f]
new_cs[new_index_in_chunk] = old_cs[old_index_in_chunk]
end
end
end
if old_chunk ~= nil then if old_chunk ~= nil then
for new_f, new_cs in pairs(new_chunk.__components) do
local old_cs = old_chunk.__components[new_f]
new_cs[new_index_in_chunk] = old_cs[old_index_in_chunk]
end
__detach_entity(entity) __detach_entity(entity)
end end
entity.__chunk = new_chunk entity.__chunk = new_chunk
entity.__index_in_chunk = new_index_in_chunk entity.__index_in_chunk = new_index_in_chunk
return true
end end
---@param fragment evolved.entity ---@param fragment evolved.entity