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

View File

@@ -7,7 +7,9 @@
- [ ] add blocklist of fragments for queries
- [ ] add checks of prohibited changes while querying
- [ ] 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
- [x] cache transitions between chunks
- [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'
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()
assert(e.__chunk == nil)
e:insert(f1)
assert(e:insert(f1))
assert(e:has(f1))
assert(not e:has(f2))
e:insert(f2)
assert(e:insert(f2))
assert(e:has(f1))
assert(e:has(f2))
e:remove(f1)
assert(e:remove(f1))
assert(not e:has(f1))
assert(e:has(f2))
e:remove(f2)
assert(e:remove(f2))
assert(not e:has(f1))
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
do
@@ -36,15 +63,14 @@ do
assert(e:get_or(f) == nil)
assert(e:get_or(f, 42) == 42)
e:insert(f, 84)
assert(e:insert(f, 84))
assert(e:get(f) == 84)
assert(e:get_or(f) == 84)
assert(e:get_or(f, 42) == 84)
if not os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") then
assert(not pcall(e.insert, e, f, 42))
end
assert(not e:insert(f, 42))
assert(e:get(f) == 42)
e:assign(f)
assert(e:get(f) == true)
@@ -102,7 +128,7 @@ end
for _ = 1, 100 do
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
local fragment = evo.registry.entity()
@@ -110,7 +136,7 @@ for _ = 1, 100 do
end
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
local fragment = insert_fragments[math.random(1, #insert_fragments)]

View File

@@ -334,7 +334,8 @@ end
---@return boolean
---@nodiscard
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
---@param entity evolved.entity
@@ -373,6 +374,7 @@ end
---@param entity evolved.entity
---@param fragment evolved.entity
---@param component any
---@return boolean is_inserted
function registry.insert(entity, fragment, component)
component = component == nil and true or component
@@ -380,13 +382,14 @@ function registry.insert(entity, fragment, component)
local new_chunk = __chunk_with_fragment(old_chunk, fragment)
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
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.__components[fragment][new_index_in_chunk] = component
@@ -395,31 +398,40 @@ function registry.insert(entity, fragment, component)
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
__detach_entity(entity)
end
entity.__chunk = new_chunk
entity.__index_in_chunk = new_index_in_chunk
return true
end
---@param entity evolved.entity
---@param fragment evolved.entity
function registry.remove(entity, fragment)
---@param ... evolved.entity fragments
---@return boolean is_removed
function registry.remove(entity, ...)
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
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
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
if old_chunk ~= nil then
@@ -427,15 +439,14 @@ function registry.remove(entity, fragment)
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
__detach_entity(entity)
end
entity.__chunk = new_chunk
entity.__index_in_chunk = new_index_in_chunk
return true
end
---@param fragment evolved.entity