mirror of
https://github.com/BlackMATov/evolved.lua.git
synced 2026-04-19 02:14:26 +07:00
chunk batch functions
This commit is contained in:
27
README.md
27
README.md
@@ -59,25 +59,32 @@ registry.has -> entity -> entity -> (boolean)
|
||||
registry.has_all -> entity -> entity... -> (boolean)
|
||||
registry.has_any -> entity -> entity... -> (boolean)
|
||||
registry.set -> entity -> entity -> any -> (entity)
|
||||
registry.chunk_set -> chunk -> entity -> any -> (integer, integer)
|
||||
registry.query_set -> query -> entity -> any -> (integer, integer)
|
||||
registry.apply -> entity -> {any -> any} -> entity -> (boolean)
|
||||
registry.chunk_apply -> chunk -> {any -> any} -> entity -> (integer)
|
||||
registry.query_apply -> query -> {any -> any} -> entity -> (integer)
|
||||
registry.assign -> entity -> entity -> any -> (boolean)
|
||||
registry.chunk_assign -> chunk -> entity -> any -> (integer)
|
||||
registry.query_assign -> query -> entity -> any -> (integer)
|
||||
registry.insert -> entity -> entity -> any -> (boolean)
|
||||
registry.chunk_insert -> chunk -> entity -> any -> (integer)
|
||||
registry.query_insert -> query -> entity -> any -> (integer)
|
||||
registry.remove -> entity -> entity... -> (boolean)
|
||||
registry.chunk_remove -> chunk -> entity... -> (integer)
|
||||
registry.query_remove -> query -> entity... -> (integer)
|
||||
registry.detach -> entity -> (boolean)
|
||||
registry.detach -> entity -> (entity)
|
||||
registry.chunk_detach -> chunk -> (integer)
|
||||
registry.query_detach -> query -> (integer)
|
||||
registry.destroy -> entity -> (boolean)
|
||||
registry.destroy -> entity -> (entity)
|
||||
registry.chunk_destroy -> chunk -> (integer)
|
||||
registry.query_destroy -> query -> (integer)
|
||||
registry.query -> entity... -> (query)
|
||||
registry.include -> query -> entity... -> query
|
||||
registry.exclude -> query -> entity... -> query
|
||||
registry.execute -> query -> ({execution_state? -> chunk?}, execution_state?)
|
||||
registry.chunk -> entity -> entity... -> (chunk)
|
||||
registry.entities -> chunk -> entity -> (entity[])
|
||||
registry.entities -> chunk -> (entity[])
|
||||
registry.components -> chunk -> entity... -> (any[]...)
|
||||
```
|
||||
|
||||
@@ -96,8 +103,8 @@ entity:apply -> {any -> any} -> entity -> (boolean)
|
||||
entity:assign -> entity -> any -> (boolean)
|
||||
entity:insert -> entity -> any -> (boolean)
|
||||
entity:remove -> entity... -> (boolean)
|
||||
entity:detach -> (boolean)
|
||||
entity:destroy -> (boolean)
|
||||
entity:detach -> (entity)
|
||||
entity:destroy -> (entity)
|
||||
```
|
||||
|
||||
### Instance `query`
|
||||
@@ -119,8 +126,16 @@ query:destroy -> (integer)
|
||||
### Instance `chunk`
|
||||
|
||||
```
|
||||
chunk:entities -> entity -> (entity[])
|
||||
chunk:entities -> (entity[])
|
||||
chunk:components -> entity... -> (any[]...)
|
||||
|
||||
chunk:set -> entity -> any -> (integer, integer)
|
||||
chunk:apply -> {any -> any} -> entity -> (integer)
|
||||
chunk:assign -> entity -> any -> (integer)
|
||||
chunk:insert -> entity -> any -> (integer)
|
||||
chunk:remove -> entity... -> (integer)
|
||||
chunk:detach -> (integer)
|
||||
chunk:destroy -> (integer)
|
||||
```
|
||||
|
||||
## Module `singles`
|
||||
|
||||
@@ -19,4 +19,6 @@
|
||||
- [ ] add inplace vector operations
|
||||
- [x] cache chunk lists in batch operations
|
||||
- [ ] impl compat.move for 5.1 vanilla lua
|
||||
- [x] add registry.batch_set
|
||||
- [x] add registry.batch_set
|
||||
- [ ] rename include/exclude/execute to query_include/exclude/execute
|
||||
- [ ] rename entities/components to chunk_entities/components
|
||||
@@ -108,11 +108,11 @@ do
|
||||
assert(e:alive())
|
||||
assert(e.__chunk == evo.registry.chunk(f1, f2))
|
||||
|
||||
assert(e:destroy())
|
||||
assert(e == e:destroy())
|
||||
assert(not e:alive())
|
||||
assert(e.__chunk == nil)
|
||||
|
||||
assert(not e:destroy())
|
||||
assert(e == e:destroy())
|
||||
assert(not e:alive())
|
||||
assert(e.__chunk == nil)
|
||||
end
|
||||
@@ -257,11 +257,11 @@ do
|
||||
assert(e:alive())
|
||||
assert(e.__chunk == evo.registry.chunk(f1, f2))
|
||||
|
||||
assert(e:detach())
|
||||
assert(e == e:detach())
|
||||
assert(e:alive())
|
||||
assert(e.__chunk == nil)
|
||||
|
||||
assert(not e:detach())
|
||||
assert(e == e:detach())
|
||||
assert(e:alive())
|
||||
assert(e.__chunk == nil)
|
||||
end
|
||||
@@ -321,7 +321,7 @@ do
|
||||
assert(e:alive())
|
||||
assert(e.__chunk == evo.registry.chunk(f1))
|
||||
|
||||
assert(e:destroy())
|
||||
assert(e == e:destroy())
|
||||
assert(not e:alive())
|
||||
assert(e.__chunk == nil)
|
||||
|
||||
@@ -340,7 +340,7 @@ do
|
||||
assert(not e:alive())
|
||||
assert(e.__chunk == nil)
|
||||
|
||||
assert(not e:detach())
|
||||
assert(e == e:detach())
|
||||
assert(not e:alive())
|
||||
assert(e.__chunk == nil)
|
||||
end
|
||||
@@ -545,6 +545,153 @@ do
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local f1, f2 =
|
||||
evo.registry.entity(),
|
||||
evo.registry.entity()
|
||||
|
||||
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 c_f1 = evo.registry.chunk(f1)
|
||||
local c_f1_f2 = evo.registry.chunk(f1, f2)
|
||||
|
||||
do
|
||||
local q = evo.registry.query(f1)
|
||||
|
||||
assert(2 == q:insert(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)
|
||||
|
||||
assert(#c_f1:entities() == 0)
|
||||
assert(#c_f1:components(f1) == 0)
|
||||
assert(c_f1:components(f2) == nil)
|
||||
|
||||
assert(#c_f1_f2:entities() == 4)
|
||||
assert(#c_f1_f2:components(f1) == 4)
|
||||
assert(#c_f1_f2:components(f2) == 4)
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local f1, f2 =
|
||||
evo.registry.entity(),
|
||||
evo.registry.entity()
|
||||
|
||||
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 c_f1 = evo.registry.chunk(f1)
|
||||
local c_f1_f2 = evo.registry.chunk(f1, f2)
|
||||
|
||||
do
|
||||
local q = evo.registry.query(f2)
|
||||
|
||||
assert(2 == q:remove(f2))
|
||||
|
||||
assert(e1:get(f1) == 10 and e2:get(f1) == 15 and e3:get(f1) == 20 and e4:get(f1) == 25)
|
||||
assert(e1:get(f2) == nil and e2:get(f2) == nil and e3:get(f2) == nil and e4:get(f2) == nil)
|
||||
|
||||
assert(#c_f1:entities() == 4)
|
||||
assert(#c_f1:components(f1) == 4)
|
||||
assert(c_f1:components(f2) == nil)
|
||||
|
||||
assert(#c_f1_f2:entities() == 0)
|
||||
assert(#c_f1_f2:components(f1) == 0)
|
||||
assert(#c_f1_f2:components(f2) == 0)
|
||||
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 c_f1 = evo.registry.chunk(f1)
|
||||
local c_f2 = evo.registry.chunk(f2)
|
||||
local c_f1_f2 = evo.registry.chunk(f1, f2)
|
||||
|
||||
do
|
||||
local q = evo.registry.query(f1)
|
||||
|
||||
assert(2 == q:insert(f2, 42))
|
||||
|
||||
assert(e1:get(f1) == 10 and e2:get(f1) == 15)
|
||||
assert(e1:get(f2) == 42 and e2:get(f2) == 42)
|
||||
|
||||
assert(#c_f1:entities() == 0)
|
||||
assert(#c_f1:components(f1) == 0)
|
||||
assert(c_f1:components(f2) == nil)
|
||||
|
||||
assert(#c_f2:entities() == 0)
|
||||
assert(c_f2:components(f1) == nil)
|
||||
assert(#c_f2:components(f2) == 0)
|
||||
|
||||
assert(#c_f1_f2:entities() == 2)
|
||||
assert(#c_f1_f2:components(f1) == 2)
|
||||
assert(#c_f1_f2:components(f2) == 2)
|
||||
end
|
||||
|
||||
do
|
||||
local q = evo.registry.query(f1)
|
||||
|
||||
assert(2 == q:remove(f1, f3))
|
||||
|
||||
assert(e1:get(f1) == nil and e2:get(f1) == nil)
|
||||
assert(e1:get(f2) == 42 and e2:get(f2) == 42)
|
||||
|
||||
assert(#c_f1:entities() == 0)
|
||||
assert(#c_f1:components(f1) == 0)
|
||||
assert(c_f1:components(f2) == nil)
|
||||
assert(c_f1:components(f3) == nil)
|
||||
|
||||
assert(#c_f2:entities() == 2)
|
||||
assert(c_f2:components(f1) == nil)
|
||||
assert(#c_f2:components(f2) == 2)
|
||||
assert(c_f2:components(f3) == nil)
|
||||
|
||||
assert(#c_f1_f2:entities() == 0)
|
||||
assert(#c_f1_f2:components(f1) == 0)
|
||||
assert(#c_f1_f2:components(f2) == 0)
|
||||
assert(c_f1_f2:components(f3) == nil)
|
||||
end
|
||||
|
||||
do
|
||||
local q = evo.registry.query(f2)
|
||||
|
||||
assert(2 == q:remove(f2, f3))
|
||||
|
||||
assert(e1:get(f1) == nil and e2:get(f1) == nil)
|
||||
assert(e1:get(f2) == nil and e2:get(f2) == nil)
|
||||
|
||||
assert(#c_f1:entities() == 0)
|
||||
assert(#c_f1:components(f1) == 0)
|
||||
assert(c_f1:components(f2) == nil)
|
||||
assert(c_f1:components(f3) == nil)
|
||||
|
||||
assert(#c_f2:entities() == 0)
|
||||
assert(c_f2:components(f1) == nil)
|
||||
assert(#c_f2:components(f2) == 0)
|
||||
assert(c_f2:components(f3) == nil)
|
||||
|
||||
assert(#c_f1_f2:entities() == 0)
|
||||
assert(#c_f1_f2:components(f1) == 0)
|
||||
assert(#c_f1_f2:components(f2) == 0)
|
||||
assert(c_f1_f2:components(f3) == nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local f1, f2, f3, f4 =
|
||||
evo.registry.entity(),
|
||||
|
||||
@@ -63,7 +63,8 @@ evolved_chunk_mt.__index = evolved_chunk_mt
|
||||
|
||||
---@param entity evolved.entity
|
||||
local function __detach_entity(entity)
|
||||
local chunk = assert(entity.__chunk)
|
||||
local chunk = entity.__chunk
|
||||
if chunk == nil then return end
|
||||
|
||||
local chunk_size = #chunk.__entities
|
||||
local chunk_entities = chunk.__entities
|
||||
@@ -88,7 +89,9 @@ local function __detach_entity(entity)
|
||||
end
|
||||
end
|
||||
|
||||
entity.__chunk, entity.__index_in_chunk = nil, 0
|
||||
entity.__chunk = nil
|
||||
entity.__index_in_chunk = 0
|
||||
|
||||
__structural_changes = __structural_changes + 1
|
||||
end
|
||||
|
||||
@@ -324,174 +327,6 @@ local function __chunk_without_fragments(chunk, ...)
|
||||
return chunk
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@param apply fun(any): any
|
||||
---@param fragment evolved.entity
|
||||
local function __chunk_apply(chunk, apply, fragment)
|
||||
local chunk_size = #chunk.__entities
|
||||
local chunk_components = chunk.__components
|
||||
local chunk_fragment_components = chunk_components[fragment]
|
||||
|
||||
for i = 1, chunk_size do
|
||||
local component = apply(chunk_fragment_components[i])
|
||||
chunk_fragment_components[i] = component == nil and true or component
|
||||
end
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@param fragment evolved.entity
|
||||
---@param component any
|
||||
local function __chunk_assign(chunk, fragment, component)
|
||||
local chunk_size = #chunk.__entities
|
||||
local chunk_components = chunk.__components
|
||||
local chunk_fragment_components = chunk_components[fragment]
|
||||
|
||||
for i = 1, chunk_size do
|
||||
chunk_fragment_components[i] = component == nil and true or component
|
||||
end
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@param fragment evolved.entity
|
||||
---@param component any
|
||||
local function __chunk_insert(chunk, fragment, component)
|
||||
local new_chunk = __chunk_with_fragment(chunk, fragment)
|
||||
assert(chunk ~= new_chunk)
|
||||
|
||||
local chunk_size = #chunk.__entities
|
||||
local chunk_entities = chunk.__entities
|
||||
local chunk_components = chunk.__components
|
||||
|
||||
if new_chunk then
|
||||
local new_chunk_size = #new_chunk.__entities
|
||||
local new_chunk_entities = new_chunk.__entities
|
||||
local new_chunk_components = new_chunk.__components
|
||||
local new_chunk_fragment_components = new_chunk_components[fragment]
|
||||
|
||||
compat.move(chunk_entities, 1, chunk_size, new_chunk_size + 1, new_chunk_entities)
|
||||
|
||||
for f, cs in pairs(chunk_components) do
|
||||
local new_cs = new_chunk_components[f]
|
||||
compat.move(cs, 1, chunk_size, new_chunk_size + 1, new_cs)
|
||||
end
|
||||
|
||||
for index_in_chunk = 1, chunk_size do
|
||||
local new_index_in_chunk = index_in_chunk + new_chunk_size
|
||||
|
||||
local entity = new_chunk_entities[new_index_in_chunk]
|
||||
entity.__chunk, entity.__index_in_chunk = new_chunk, new_index_in_chunk
|
||||
|
||||
new_chunk_fragment_components[new_index_in_chunk] = component == nil and true or component
|
||||
end
|
||||
else
|
||||
for index_in_chunk = 1, chunk_size do
|
||||
local entity = chunk_entities[index_in_chunk]
|
||||
entity.__chunk, entity.__index_in_chunk = nil, 0
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
chunk.__entities = {}
|
||||
|
||||
for f, _ in pairs(chunk_components) do
|
||||
chunk_components[f] = {}
|
||||
end
|
||||
end
|
||||
|
||||
__structural_changes = __structural_changes + chunk_size
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@param ... evolved.entity fragments
|
||||
local function __chunk_remove(chunk, ...)
|
||||
local new_chunk = __chunk_without_fragments(chunk, ...)
|
||||
assert(chunk ~= new_chunk)
|
||||
|
||||
local chunk_size = #chunk.__entities
|
||||
local chunk_entities = chunk.__entities
|
||||
local chunk_components = chunk.__components
|
||||
|
||||
if new_chunk then
|
||||
local new_chunk_size = #new_chunk.__entities
|
||||
local new_chunk_entities = new_chunk.__entities
|
||||
local new_chunk_components = new_chunk.__components
|
||||
|
||||
compat.move(chunk_entities, 1, chunk_size, new_chunk_size + 1, new_chunk_entities)
|
||||
|
||||
for new_f, new_cs in pairs(new_chunk_components) do
|
||||
local cs = chunk_components[new_f]
|
||||
compat.move(cs, 1, chunk_size, new_chunk_size + 1, new_cs)
|
||||
end
|
||||
|
||||
for index_in_chunk = 1, chunk_size do
|
||||
local new_index_in_chunk = index_in_chunk + new_chunk_size
|
||||
|
||||
local entity = new_chunk_entities[new_index_in_chunk]
|
||||
entity.__chunk, entity.__index_in_chunk = new_chunk, new_index_in_chunk
|
||||
end
|
||||
else
|
||||
for index_in_chunk = 1, chunk_size do
|
||||
local entity = chunk_entities[index_in_chunk]
|
||||
entity.__chunk, entity.__index_in_chunk = nil, 0
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
chunk.__entities = {}
|
||||
|
||||
for f, _ in pairs(chunk_components) do
|
||||
chunk_components[f] = {}
|
||||
end
|
||||
end
|
||||
|
||||
__structural_changes = __structural_changes + chunk_size
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
local function __chunk_detach(chunk)
|
||||
local chunk_size = #chunk.__entities
|
||||
local chunk_entities = chunk.__entities
|
||||
local chunk_components = chunk.__components
|
||||
|
||||
for index_in_chunk = 1, chunk_size do
|
||||
local entity = chunk_entities[index_in_chunk]
|
||||
entity.__chunk, entity.__index_in_chunk = nil, 0
|
||||
end
|
||||
|
||||
do
|
||||
chunk.__entities = {}
|
||||
|
||||
for f, _ in pairs(chunk_components) do
|
||||
chunk_components[f] = {}
|
||||
end
|
||||
end
|
||||
|
||||
__structural_changes = __structural_changes + chunk_size
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
local function __chunk_destroy(chunk)
|
||||
local chunk_size = #chunk.__entities
|
||||
local chunk_entities = chunk.__entities
|
||||
local chunk_components = chunk.__components
|
||||
|
||||
for index_in_chunk = 1, chunk_size do
|
||||
local entity = chunk_entities[index_in_chunk]
|
||||
entity.__chunk, entity.__index_in_chunk = nil, 0
|
||||
idpools.release(__guids, entity.__guid)
|
||||
end
|
||||
|
||||
do
|
||||
chunk.__entities = {}
|
||||
|
||||
for f, _ in pairs(chunk_components) do
|
||||
chunk_components[f] = {}
|
||||
end
|
||||
end
|
||||
|
||||
__structural_changes = __structural_changes + chunk_size
|
||||
end
|
||||
|
||||
---@return evolved.execution_stack
|
||||
---@nodiscard
|
||||
local function __execution_stack_acquire()
|
||||
@@ -715,7 +550,9 @@ function registry.set(entity, fragment, component)
|
||||
__detach_entity(entity)
|
||||
end
|
||||
|
||||
entity.__chunk, entity.__index_in_chunk = new_chunk, new_index_in_chunk
|
||||
entity.__chunk = new_chunk
|
||||
entity.__index_in_chunk = new_index_in_chunk
|
||||
|
||||
__structural_changes = __structural_changes + 1
|
||||
else
|
||||
__detach_entity(entity)
|
||||
@@ -724,40 +561,55 @@ function registry.set(entity, fragment, component)
|
||||
return entity
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@param fragment evolved.entity
|
||||
---@param component any
|
||||
---@return integer assigned_count
|
||||
---@return integer inserted_count
|
||||
function registry.chunk_set(chunk, fragment, component)
|
||||
if __chunk_has_fragment(chunk, fragment) then
|
||||
local assigned = registry.chunk_assign(chunk, fragment, component)
|
||||
return assigned, 0
|
||||
else
|
||||
local inserted = registry.chunk_insert(chunk, fragment, component)
|
||||
return 0, inserted
|
||||
end
|
||||
end
|
||||
|
||||
---@param query evolved.query
|
||||
---@param fragment evolved.entity
|
||||
---@param component any
|
||||
---@return integer assigned_count
|
||||
---@return integer inserted_count
|
||||
function registry.query_set(query, fragment, component)
|
||||
local to_assign_chunks = __execution_stack_acquire()
|
||||
local to_insert_chunks = __execution_stack_acquire()
|
||||
local assign_chunks = __execution_stack_acquire()
|
||||
local insert_chunks = __execution_stack_acquire()
|
||||
|
||||
for chunk in registry.execute(query) do
|
||||
if chunk.__components[fragment] ~= nil then
|
||||
to_assign_chunks[#to_assign_chunks + 1] = chunk
|
||||
if __chunk_has_fragment(chunk, fragment) then
|
||||
assign_chunks[#assign_chunks + 1] = chunk
|
||||
else
|
||||
to_insert_chunks[#to_insert_chunks + 1] = chunk
|
||||
insert_chunks[#insert_chunks + 1] = chunk
|
||||
end
|
||||
end
|
||||
|
||||
local assigned_count = 0
|
||||
local inserted_count = 0
|
||||
|
||||
for i = 1, #to_assign_chunks do
|
||||
local chunk = to_assign_chunks[i]
|
||||
assigned_count = assigned_count + #chunk.__entities
|
||||
__chunk_assign(chunk, fragment, component)
|
||||
for i = 1, #assign_chunks do
|
||||
local assigned, inserted = registry.chunk_set(assign_chunks[i], fragment, component)
|
||||
assigned_count = assigned_count + assigned
|
||||
inserted_count = inserted_count + inserted
|
||||
end
|
||||
|
||||
for i = 1, #to_insert_chunks do
|
||||
local chunk = to_insert_chunks[i]
|
||||
inserted_count = inserted_count + #chunk.__entities
|
||||
__chunk_insert(chunk, fragment, component)
|
||||
for i = 1, #insert_chunks do
|
||||
local assigned, inserted = registry.chunk_set(insert_chunks[i], fragment, component)
|
||||
assigned_count = assigned_count + assigned
|
||||
inserted_count = inserted_count + inserted
|
||||
end
|
||||
|
||||
__execution_stack_release(to_assign_chunks)
|
||||
__execution_stack_release(to_insert_chunks)
|
||||
__execution_stack_release(assign_chunks)
|
||||
__execution_stack_release(insert_chunks)
|
||||
return assigned_count, inserted_count
|
||||
end
|
||||
|
||||
@@ -776,15 +628,43 @@ function registry.apply(entity, apply, fragment)
|
||||
local components = chunk.__components[fragment]
|
||||
if components == nil then return false end
|
||||
|
||||
local component = components[entity.__index_in_chunk]
|
||||
do
|
||||
local component = components[entity.__index_in_chunk]
|
||||
|
||||
component = apply(component)
|
||||
component = component == nil and true or component
|
||||
component = apply(component)
|
||||
component = component == nil and true or component
|
||||
|
||||
components[entity.__index_in_chunk] = component
|
||||
end
|
||||
|
||||
components[entity.__index_in_chunk] = component
|
||||
return true
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@param apply fun(any): any
|
||||
---@param fragment evolved.entity
|
||||
---@return integer applied_count
|
||||
function registry.chunk_apply(chunk, apply, fragment)
|
||||
local chunk_size = #chunk.__entities
|
||||
local chunk_components = chunk.__components
|
||||
local chunk_fragment_components = chunk_components[fragment]
|
||||
|
||||
if chunk_size == 0 or chunk_fragment_components == nil then
|
||||
return 0
|
||||
end
|
||||
|
||||
for i = 1, chunk_size do
|
||||
local component = chunk_fragment_components[i]
|
||||
|
||||
component = apply(component)
|
||||
component = component == nil and true or component
|
||||
|
||||
chunk_fragment_components[i] = component
|
||||
end
|
||||
|
||||
return chunk_size
|
||||
end
|
||||
|
||||
---@param query evolved.query
|
||||
---@param apply fun(any): any
|
||||
---@param fragment evolved.entity
|
||||
@@ -793,17 +673,14 @@ function registry.query_apply(query, apply, fragment)
|
||||
local chunks = __execution_stack_acquire()
|
||||
|
||||
for chunk in registry.execute(query) do
|
||||
if chunk.__components[fragment] ~= nil then
|
||||
chunks[#chunks + 1] = chunk
|
||||
end
|
||||
chunks[#chunks + 1] = chunk
|
||||
end
|
||||
|
||||
local applied_count = 0
|
||||
|
||||
for i = 1, #chunks do
|
||||
local chunk = chunks[i]
|
||||
applied_count = applied_count + #chunk.__entities
|
||||
__chunk_apply(chunk, apply, fragment)
|
||||
local applied = registry.chunk_apply(chunks[i], apply, fragment)
|
||||
applied_count = applied_count + applied
|
||||
end
|
||||
|
||||
__execution_stack_release(chunks)
|
||||
@@ -827,31 +704,51 @@ function registry.assign(entity, fragment, component)
|
||||
local components = chunk.__components[fragment]
|
||||
if components == nil then return false end
|
||||
|
||||
components[entity.__index_in_chunk] = component
|
||||
do
|
||||
components[entity.__index_in_chunk] = component
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@param fragment evolved.entity
|
||||
---@param component any
|
||||
---@return integer assigned_count
|
||||
function registry.chunk_assign(chunk, fragment, component)
|
||||
component = component == nil and true or component
|
||||
|
||||
local chunk_size = #chunk.__entities
|
||||
local chunk_components = chunk.__components
|
||||
local chunk_fragment_components = chunk_components[fragment]
|
||||
|
||||
if chunk_size == 0 or chunk_fragment_components == nil then
|
||||
return 0
|
||||
end
|
||||
|
||||
for i = 1, chunk_size do
|
||||
chunk_fragment_components[i] = component
|
||||
end
|
||||
|
||||
return chunk_size
|
||||
end
|
||||
|
||||
---@param query evolved.query
|
||||
---@param fragment evolved.entity
|
||||
---@param component any
|
||||
---@return integer assigned_count
|
||||
function registry.query_assign(query, fragment, component)
|
||||
component = component == nil and true or component
|
||||
|
||||
local chunks = __execution_stack_acquire()
|
||||
|
||||
for chunk in registry.execute(query) do
|
||||
if chunk.__components[fragment] ~= nil then
|
||||
chunks[#chunks + 1] = chunk
|
||||
end
|
||||
chunks[#chunks + 1] = chunk
|
||||
end
|
||||
|
||||
local assigned_count = 0
|
||||
|
||||
for i = 1, #chunks do
|
||||
local chunk = chunks[i]
|
||||
assigned_count = assigned_count + #chunk.__entities
|
||||
__chunk_assign(chunk, fragment, component)
|
||||
local assigned = registry.chunk_assign(chunks[i], fragment, component)
|
||||
assigned_count = assigned_count + assigned
|
||||
end
|
||||
|
||||
__execution_stack_release(chunks)
|
||||
@@ -895,7 +792,9 @@ function registry.insert(entity, fragment, component)
|
||||
__detach_entity(entity)
|
||||
end
|
||||
|
||||
entity.__chunk, entity.__index_in_chunk = new_chunk, new_index_in_chunk
|
||||
entity.__chunk = new_chunk
|
||||
entity.__index_in_chunk = new_index_in_chunk
|
||||
|
||||
__structural_changes = __structural_changes + 1
|
||||
else
|
||||
__detach_entity(entity)
|
||||
@@ -904,27 +803,100 @@ function registry.insert(entity, fragment, component)
|
||||
return true
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@param fragment evolved.entity
|
||||
---@param component any
|
||||
---@return integer inserted_count
|
||||
function registry.chunk_insert(chunk, fragment, component)
|
||||
component = component == nil and true or component
|
||||
|
||||
local old_chunk = chunk
|
||||
local new_chunk = __chunk_with_fragment(old_chunk, fragment)
|
||||
|
||||
if old_chunk == new_chunk then
|
||||
return 0
|
||||
end
|
||||
|
||||
local old_chunk_size = #old_chunk.__entities
|
||||
local old_chunk_entities = old_chunk.__entities
|
||||
local old_chunk_components = old_chunk.__components
|
||||
|
||||
if new_chunk ~= nil then
|
||||
local new_chunk_size = #new_chunk.__entities
|
||||
local new_chunk_entities = new_chunk.__entities
|
||||
local new_chunk_components = new_chunk.__components
|
||||
|
||||
if new_chunk_size == 0 then
|
||||
new_chunk.__entities, old_chunk.__entities = old_chunk_entities, new_chunk_entities
|
||||
new_chunk_entities, old_chunk_entities = old_chunk_entities, new_chunk_entities
|
||||
|
||||
new_chunk.__components, old_chunk.__components = old_chunk_components, new_chunk_components
|
||||
new_chunk_components, old_chunk_components = old_chunk_components, new_chunk_components
|
||||
|
||||
if old_chunk_components[fragment] ~= nil then
|
||||
new_chunk_components[fragment] = {}
|
||||
old_chunk_components[fragment] = nil
|
||||
end
|
||||
else
|
||||
compat.move(
|
||||
old_chunk_entities, 1, old_chunk_size,
|
||||
new_chunk_size + 1, new_chunk_entities)
|
||||
|
||||
for old_f, old_cs in pairs(old_chunk_components) do
|
||||
local new_cs = new_chunk_components[old_f]
|
||||
compat.move(old_cs, 1, old_chunk_size, new_chunk_size + 1, new_cs)
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local new_chunk_fragment_components = new_chunk_components[fragment]
|
||||
|
||||
for new_index_in_chunk = new_chunk_size + 1, new_chunk_size + old_chunk_size do
|
||||
new_chunk_fragment_components[new_index_in_chunk] = component
|
||||
end
|
||||
end
|
||||
|
||||
for new_index_in_chunk = new_chunk_size + 1, new_chunk_size + old_chunk_size do
|
||||
local entity = new_chunk_entities[new_index_in_chunk]
|
||||
entity.__chunk, entity.__index_in_chunk = new_chunk, new_index_in_chunk
|
||||
end
|
||||
else
|
||||
for old_index_in_chunk = 1, old_chunk_size do
|
||||
local entity = old_chunk_entities[old_index_in_chunk]
|
||||
entity.__chunk, entity.__index_in_chunk = nil, 0
|
||||
end
|
||||
end
|
||||
|
||||
if #old_chunk_entities ~= 0 then
|
||||
old_chunk.__entities = {}
|
||||
end
|
||||
|
||||
for old_f, old_cs in pairs(old_chunk_components) do
|
||||
if #old_cs ~= 0 then
|
||||
old_chunk_components[old_f] = {}
|
||||
end
|
||||
end
|
||||
|
||||
__structural_changes = __structural_changes + old_chunk_size
|
||||
return old_chunk_size
|
||||
end
|
||||
|
||||
---@param query evolved.query
|
||||
---@param fragment evolved.entity
|
||||
---@param component any
|
||||
---@return integer inserted_count
|
||||
function registry.query_insert(query, fragment, component)
|
||||
component = component == nil and true or component
|
||||
|
||||
local chunks = __execution_stack_acquire()
|
||||
|
||||
for chunk in registry.execute(query) do
|
||||
if chunk.__components[fragment] == nil then
|
||||
chunks[#chunks + 1] = chunk
|
||||
end
|
||||
chunks[#chunks + 1] = chunk
|
||||
end
|
||||
|
||||
local inserted_count = 0
|
||||
|
||||
for i = 1, #chunks do
|
||||
local chunk = chunks[i]
|
||||
inserted_count = inserted_count + #chunk.__entities
|
||||
__chunk_insert(chunks[i], fragment, component)
|
||||
local inserted = registry.chunk_insert(chunks[i], fragment, component)
|
||||
inserted_count = inserted_count + inserted
|
||||
end
|
||||
|
||||
__execution_stack_release(chunks)
|
||||
@@ -964,7 +936,9 @@ function registry.remove(entity, ...)
|
||||
__detach_entity(entity)
|
||||
end
|
||||
|
||||
entity.__chunk, entity.__index_in_chunk = new_chunk, new_index_in_chunk
|
||||
entity.__chunk = new_chunk
|
||||
entity.__index_in_chunk = new_index_in_chunk
|
||||
|
||||
__structural_changes = __structural_changes + 1
|
||||
else
|
||||
__detach_entity(entity)
|
||||
@@ -973,6 +947,76 @@ function registry.remove(entity, ...)
|
||||
return true
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@param ... evolved.entity fragments
|
||||
---@return integer removed_count
|
||||
function registry.chunk_remove(chunk, ...)
|
||||
local old_chunk = chunk
|
||||
local new_chunk = __chunk_without_fragments(old_chunk, ...)
|
||||
|
||||
if old_chunk == new_chunk then
|
||||
return 0
|
||||
end
|
||||
|
||||
local old_chunk_size = #old_chunk.__entities
|
||||
local old_chunk_entities = old_chunk.__entities
|
||||
local old_chunk_components = old_chunk.__components
|
||||
|
||||
if new_chunk ~= nil then
|
||||
local new_chunk_size = #new_chunk.__entities
|
||||
local new_chunk_entities = new_chunk.__entities
|
||||
local new_chunk_components = new_chunk.__components
|
||||
|
||||
if new_chunk_size == 0 then
|
||||
new_chunk.__entities, old_chunk.__entities = old_chunk_entities, new_chunk_entities
|
||||
new_chunk_entities, old_chunk_entities = old_chunk_entities, new_chunk_entities
|
||||
|
||||
new_chunk.__components, old_chunk.__components = old_chunk_components, new_chunk_components
|
||||
new_chunk_components, old_chunk_components = old_chunk_components, new_chunk_components
|
||||
|
||||
for i = 1, select('#', ...) do
|
||||
local fragment = select(i, ...)
|
||||
if new_chunk_components[fragment] ~= nil then
|
||||
old_chunk_components[fragment] = {}
|
||||
new_chunk_components[fragment] = nil
|
||||
end
|
||||
end
|
||||
else
|
||||
compat.move(
|
||||
old_chunk_entities, 1, old_chunk_size,
|
||||
new_chunk_size + 1, new_chunk_entities)
|
||||
|
||||
for new_f, new_cs in pairs(new_chunk_components) do
|
||||
local old_cs = old_chunk_components[new_f]
|
||||
compat.move(old_cs, 1, old_chunk_size, new_chunk_size + 1, new_cs)
|
||||
end
|
||||
end
|
||||
|
||||
for new_index_in_chunk = new_chunk_size + 1, new_chunk_size + old_chunk_size do
|
||||
local entity = new_chunk_entities[new_index_in_chunk]
|
||||
entity.__chunk, entity.__index_in_chunk = new_chunk, new_index_in_chunk
|
||||
end
|
||||
else
|
||||
for old_index_in_chunk = 1, old_chunk_size do
|
||||
local entity = old_chunk_entities[old_index_in_chunk]
|
||||
entity.__chunk, entity.__index_in_chunk = nil, 0
|
||||
end
|
||||
end
|
||||
|
||||
if #old_chunk_entities ~= 0 then
|
||||
old_chunk.__entities = {}
|
||||
end
|
||||
|
||||
for old_f, old_cs in pairs(old_chunk_components) do
|
||||
if #old_cs ~= 0 then
|
||||
old_chunk_components[old_f] = {}
|
||||
end
|
||||
end
|
||||
|
||||
__structural_changes = __structural_changes + old_chunk_size
|
||||
return old_chunk_size
|
||||
end
|
||||
|
||||
---@param query evolved.query
|
||||
---@param ... evolved.entity fragments
|
||||
---@return integer removed_count
|
||||
@@ -980,17 +1024,14 @@ function registry.query_remove(query, ...)
|
||||
local chunks = __execution_stack_acquire()
|
||||
|
||||
for chunk in registry.execute(query) do
|
||||
if __chunk_has_any_fragments(chunk, ...) then
|
||||
chunks[#chunks + 1] = chunk
|
||||
end
|
||||
chunks[#chunks + 1] = chunk
|
||||
end
|
||||
|
||||
local removed_count = 0
|
||||
|
||||
for i = 1, #chunks do
|
||||
local chunk = chunks[i]
|
||||
removed_count = removed_count + #chunk.__entities
|
||||
__chunk_remove(chunk, ...)
|
||||
local removed = registry.chunk_remove(chunks[i], ...)
|
||||
removed_count = removed_count + removed
|
||||
end
|
||||
|
||||
__execution_stack_release(chunks)
|
||||
@@ -998,18 +1039,46 @@ function registry.query_remove(query, ...)
|
||||
end
|
||||
|
||||
---@param entity evolved.entity
|
||||
---@return boolean is_detached
|
||||
---@return evolved.entity
|
||||
function registry.detach(entity)
|
||||
if not idpools.alive(__guids, entity.__guid) then
|
||||
return false
|
||||
return entity
|
||||
end
|
||||
|
||||
if entity.__chunk == nil then
|
||||
return false
|
||||
if entity.__chunk ~= nil then
|
||||
__detach_entity(entity)
|
||||
end
|
||||
|
||||
__detach_entity(entity)
|
||||
return true
|
||||
return entity
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@return integer detached_count
|
||||
function registry.chunk_detach(chunk)
|
||||
local chunk_size = #chunk.__entities
|
||||
local chunk_entities = chunk.__entities
|
||||
local chunk_components = chunk.__components
|
||||
|
||||
if chunk_size == 0 then
|
||||
return 0
|
||||
end
|
||||
|
||||
for index_in_chunk = 1, chunk_size do
|
||||
local entity = chunk_entities[index_in_chunk]
|
||||
entity.__chunk = nil
|
||||
entity.__index_in_chunk = 0
|
||||
end
|
||||
|
||||
do
|
||||
chunk.__entities = {}
|
||||
|
||||
for f, _ in pairs(chunk_components) do
|
||||
chunk_components[f] = {}
|
||||
end
|
||||
end
|
||||
|
||||
__structural_changes = __structural_changes + chunk_size
|
||||
return chunk_size
|
||||
end
|
||||
|
||||
---@param query evolved.query
|
||||
@@ -1024,9 +1093,8 @@ function registry.query_detach(query)
|
||||
local detached_count = 0
|
||||
|
||||
for i = 1, #chunks do
|
||||
local chunk = chunks[i]
|
||||
detached_count = detached_count + #chunk.__entities
|
||||
__chunk_detach(chunk)
|
||||
local detached = registry.chunk_detach(chunks[i])
|
||||
detached_count = detached_count + detached
|
||||
end
|
||||
|
||||
__execution_stack_release(chunks)
|
||||
@@ -1034,10 +1102,10 @@ function registry.query_detach(query)
|
||||
end
|
||||
|
||||
---@param entity evolved.entity
|
||||
---@return boolean is_destroyed
|
||||
---@return evolved.entity
|
||||
function registry.destroy(entity)
|
||||
if not idpools.alive(__guids, entity.__guid) then
|
||||
return false
|
||||
return entity
|
||||
end
|
||||
|
||||
if entity.__chunk ~= nil then
|
||||
@@ -1045,7 +1113,38 @@ function registry.destroy(entity)
|
||||
end
|
||||
|
||||
idpools.release(__guids, entity.__guid)
|
||||
return true
|
||||
|
||||
return entity
|
||||
end
|
||||
|
||||
---@param chunk evolved.chunk
|
||||
---@return integer destroyed_count
|
||||
function registry.chunk_destroy(chunk)
|
||||
local chunk_size = #chunk.__entities
|
||||
local chunk_entities = chunk.__entities
|
||||
local chunk_components = chunk.__components
|
||||
|
||||
if chunk_size == 0 then
|
||||
return 0
|
||||
end
|
||||
|
||||
for index_in_chunk = 1, chunk_size do
|
||||
local entity = chunk_entities[index_in_chunk]
|
||||
entity.__chunk = nil
|
||||
entity.__index_in_chunk = 0
|
||||
idpools.release(__guids, entity.__guid)
|
||||
end
|
||||
|
||||
do
|
||||
chunk.__entities = {}
|
||||
|
||||
for f, _ in pairs(chunk_components) do
|
||||
chunk_components[f] = {}
|
||||
end
|
||||
end
|
||||
|
||||
__structural_changes = __structural_changes + chunk_size
|
||||
return chunk_size
|
||||
end
|
||||
|
||||
---@param query evolved.query
|
||||
@@ -1060,9 +1159,8 @@ function registry.query_destroy(query)
|
||||
local destroyed_count = 0
|
||||
|
||||
for i = 1, #chunks do
|
||||
local chunk = chunks[i]
|
||||
destroyed_count = destroyed_count + #chunk.__entities
|
||||
__chunk_destroy(chunks[i])
|
||||
local destroyed = registry.chunk_destroy(chunks[i])
|
||||
destroyed_count = destroyed_count + destroyed
|
||||
end
|
||||
|
||||
__execution_stack_release(chunks)
|
||||
@@ -1212,16 +1310,25 @@ end
|
||||
---@return evolved.chunk
|
||||
---@nodiscard
|
||||
function registry.chunk(fragment, ...)
|
||||
local fragments = { fragment, ... }
|
||||
local fragment_list = { fragment }
|
||||
local fragment_set = { [fragment] = true }
|
||||
|
||||
table.sort(fragments, function(a, b)
|
||||
for i = 1, select('#', ...) do
|
||||
local f = select(i, ...)
|
||||
if not fragment_set[f] then
|
||||
fragment_set[f] = true
|
||||
fragment_list[#fragment_list + 1] = f
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(fragment_list, function(a, b)
|
||||
return a.__guid < b.__guid
|
||||
end)
|
||||
|
||||
local chunk = __root_chunk(fragments[1])
|
||||
local chunk = __root_chunk(fragment_list[1])
|
||||
|
||||
for i = 2, #fragments do
|
||||
chunk = __chunk_with_fragment(chunk, fragments[i])
|
||||
for i = 2, #fragment_list do
|
||||
chunk = __chunk_with_fragment(chunk, fragment_list[i])
|
||||
end
|
||||
|
||||
return chunk
|
||||
@@ -1345,6 +1452,14 @@ end
|
||||
evolved_chunk_mt.entities = registry.entities
|
||||
evolved_chunk_mt.components = registry.components
|
||||
|
||||
evolved_chunk_mt.set = registry.chunk_set
|
||||
evolved_chunk_mt.apply = registry.chunk_apply
|
||||
evolved_chunk_mt.assign = registry.chunk_assign
|
||||
evolved_chunk_mt.insert = registry.chunk_insert
|
||||
evolved_chunk_mt.remove = registry.chunk_remove
|
||||
evolved_chunk_mt.detach = registry.chunk_detach
|
||||
evolved_chunk_mt.destroy = registry.chunk_destroy
|
||||
|
||||
---
|
||||
---
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user