6 Commits

5 changed files with 91 additions and 386 deletions

View File

@@ -65,7 +65,6 @@
- [Chunk](#chunk)
- [Builder](#builder)
- [Changelog](#changelog)
- [vX.Y.Z](#vxyz)
- [v1.10.0](#v1100)
- [v1.9.0](#v190)
- [v1.8.0](#v180)
@@ -1669,11 +1668,6 @@ builder_mt:destruction_policy :: id -> builder
## Changelog
### vX.Y.Z
- Slightly improved performance of modifying operations for fragments with [`ON_INSERT`](#evolvedon_insert) and [`ON_REMOVE`](#evolvedon_remove) hooks
- Slightly improved performance of queries with [`EXPLICIT`](#evolvedexplicit) fragments
### v1.10.0
- Added the new [`evolved.lookup`](#evolvedlookup) and [`evolved.multi_lookup`](#evolvedmulti_lookup) functions that allow finding ids by their names

View File

@@ -1,5 +1,4 @@
require 'develop.testing.build_tests'
require 'develop.testing.cached_hooks_tests'
require 'develop.testing.cancel_tests'
require 'develop.testing.clone_tests'
require 'develop.testing.depth_tests'

View File

@@ -1,203 +0,0 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local f1, f2 = evo.id(2)
local insert_hook_calls = 0
if f1 < f2 then
evo.set(f1, evo.ON_INSERT, function()
insert_hook_calls = insert_hook_calls + 1
end)
else
evo.set(f2, evo.ON_INSERT, function()
insert_hook_calls = insert_hook_calls + 1
end)
end
do
insert_hook_calls = 0
local e = evo.spawn { [f1] = 42, [f2] = 'hello' }
assert(insert_hook_calls == 1)
evo.destroy(e)
end
evo.remove(f1, evo.ON_INSERT)
evo.remove(f2, evo.ON_INSERT)
do
insert_hook_calls = 0
local e = evo.spawn { [f1] = 42, [f2] = 'hello' }
assert(insert_hook_calls == 0)
evo.destroy(e)
end
if f1 < f2 then
evo.set(f1, evo.ON_INSERT, function()
insert_hook_calls = insert_hook_calls + 2
end)
else
evo.set(f2, evo.ON_INSERT, function()
insert_hook_calls = insert_hook_calls + 2
end)
end
do
insert_hook_calls = 0
local e = evo.spawn { [f1] = 42, [f2] = 'hello' }
assert(insert_hook_calls == 2)
evo.destroy(e)
end
end
do
local f1, f2 = evo.id(2)
local insert_hook_calls = 0
if f1 > f2 then
evo.set(f1, evo.ON_INSERT, function()
insert_hook_calls = insert_hook_calls + 1
end)
else
evo.set(f2, evo.ON_INSERT, function()
insert_hook_calls = insert_hook_calls + 1
end)
end
do
insert_hook_calls = 0
local e = evo.spawn { [f1] = 42, [f2] = 'hello' }
assert(insert_hook_calls == 1)
evo.destroy(e)
end
evo.remove(f1, evo.ON_INSERT)
evo.remove(f2, evo.ON_INSERT)
do
insert_hook_calls = 0
local e = evo.spawn { [f1] = 42, [f2] = 'hello' }
assert(insert_hook_calls == 0)
evo.destroy(e)
end
if f1 > f2 then
evo.set(f1, evo.ON_INSERT, function()
insert_hook_calls = insert_hook_calls + 2
end)
else
evo.set(f2, evo.ON_INSERT, function()
insert_hook_calls = insert_hook_calls + 2
end)
end
do
insert_hook_calls = 0
local e = evo.spawn { [f1] = 42, [f2] = 'hello' }
assert(insert_hook_calls == 2)
evo.destroy(e)
end
end
do
local f1, f2 = evo.id(2)
local remove_hook_calls = 0
if f1 < f2 then
evo.set(f1, evo.ON_REMOVE, function()
remove_hook_calls = remove_hook_calls + 1
end)
else
evo.set(f2, evo.ON_REMOVE, function()
remove_hook_calls = remove_hook_calls + 1
end)
end
do
remove_hook_calls = 0
local e = evo.spawn { [f1] = 42, [f2] = 'hello' }
evo.destroy(e)
assert(remove_hook_calls == 1)
end
evo.remove(f1, evo.ON_REMOVE)
evo.remove(f2, evo.ON_REMOVE)
do
remove_hook_calls = 0
local e = evo.spawn { [f1] = 42, [f2] = 'hello' }
evo.destroy(e)
assert(remove_hook_calls == 0)
end
if f1 < f2 then
evo.set(f1, evo.ON_REMOVE, function()
remove_hook_calls = remove_hook_calls + 2
end)
else
evo.set(f2, evo.ON_REMOVE, function()
remove_hook_calls = remove_hook_calls + 2
end)
end
do
remove_hook_calls = 0
local e = evo.spawn { [f1] = 42, [f2] = 'hello' }
evo.destroy(e)
assert(remove_hook_calls == 2)
end
end
do
local f1, f2 = evo.id(2)
local remove_hook_calls = 0
if f1 > f2 then
evo.set(f1, evo.ON_REMOVE, function()
remove_hook_calls = remove_hook_calls + 1
end)
else
evo.set(f2, evo.ON_REMOVE, function()
remove_hook_calls = remove_hook_calls + 1
end)
end
do
remove_hook_calls = 0
local e = evo.spawn { [f1] = 42, [f2] = 'hello' }
evo.destroy(e)
assert(remove_hook_calls == 1)
end
evo.remove(f1, evo.ON_REMOVE)
evo.remove(f2, evo.ON_REMOVE)
do
remove_hook_calls = 0
local e = evo.spawn { [f1] = 42, [f2] = 'hello' }
evo.destroy(e)
assert(remove_hook_calls == 0)
end
if f1 > f2 then
evo.set(f1, evo.ON_REMOVE, function()
remove_hook_calls = remove_hook_calls + 2
end)
else
evo.set(f2, evo.ON_REMOVE, function()
remove_hook_calls = remove_hook_calls + 2
end)
end
do
remove_hook_calls = 0
local e = evo.spawn { [f1] = 42, [f2] = 'hello' }
evo.destroy(e)
assert(remove_hook_calls == 2)
end
end

View File

@@ -2928,8 +2928,8 @@ do
last_insert_entity, last_insert_component = 0, 0
local e = evo.spawn({ [f2] = 21, [f1] = true })
assert(set_count == 2 and insert_count == 2)
assert(last_set_entity == e and (last_set_component == 21 or last_set_component == true))
assert(last_insert_entity == e and (last_insert_component == 21 or last_insert_component == true))
assert(last_set_entity == e and last_set_component == 21)
assert(last_insert_entity == e and last_insert_component == 21)
end
do
@@ -2948,8 +2948,8 @@ do
last_insert_entity, last_insert_component = 0, 0
local e = evo.spawn({ [f3] = 33, [f2] = 22 })
assert(set_count == 2 and insert_count == 2)
assert(last_set_entity == e and (last_set_component == nil or last_set_component == 22))
assert(last_insert_entity == e and (last_insert_component == nil or last_insert_component == 22))
assert(last_set_entity == e and last_set_component == nil)
assert(last_insert_entity == e and last_insert_component == nil)
end
end

View File

@@ -202,12 +202,6 @@ local __structural_changes = 0 ---@type integer
---@field package __has_internal_minors boolean
---@field package __has_internal_fragments boolean
---@field package __has_required_fragments boolean
---@field package __insert_fragment_list? evolved.fragment[]
---@field package __insert_fragment_count integer
---@field package __remove_fragment_list? evolved.fragment[]
---@field package __remove_fragment_count integer
---@field package __explicit_fragment_list? evolved.fragment[]
---@field package __explicit_fragment_count integer
local __chunk_mt = {}
__chunk_mt.__index = __chunk_mt
@@ -825,13 +819,12 @@ end
---@param list V[]
---@param size? integer
---@return V[]
---@return integer dup_list_size
---@nodiscard
function __list_fns.dup(list, size)
local list_size = size or #list
if list_size == 0 then
return {}, 0
return {}
end
local dup_list = __list_fns.new(list_size)
@@ -840,7 +833,7 @@ function __list_fns.dup(list, size)
list, 1, list_size,
1, dup_list)
return dup_list, list_size
return dup_list
end
---@generic V
@@ -1415,12 +1408,6 @@ function __new_chunk(chunk_parent, chunk_fragment)
__has_internal_minors = false,
__has_internal_fragments = false,
__has_required_fragments = false,
__insert_fragment_list = nil,
__insert_fragment_count = 0,
__remove_fragment_list = nil,
__remove_fragment_count = 0,
__explicit_fragment_list = nil,
__explicit_fragment_count = 0,
}, __chunk_mt)
if not chunk_parent then
@@ -1603,22 +1590,17 @@ function __update_chunk_caches(chunk)
local chunk_fragment_list = chunk.__fragment_list
local chunk_fragment_count = chunk.__fragment_count
local has_setup_major = __evolved_has_any(chunk_fragment, __DEFAULT, __DUPLICATE)
local has_setup_minors = chunk_parent ~= nil and chunk_parent.__has_setup_hooks
local has_setup_hooks = chunk_parent ~= nil and chunk_parent.__has_setup_hooks
or __evolved_has_any(chunk_fragment, __DEFAULT, __DUPLICATE)
local has_assign_major = __evolved_has_any(chunk_fragment, __ON_SET, __ON_ASSIGN)
local has_assign_minors = chunk_parent ~= nil and chunk_parent.__has_assign_hooks
local has_assign_hooks = chunk_parent ~= nil and chunk_parent.__has_assign_hooks
or __evolved_has_any(chunk_fragment, __ON_SET, __ON_ASSIGN)
local has_insert_major = __evolved_has_any(chunk_fragment, __ON_SET, __ON_INSERT)
local has_insert_minors = chunk_parent ~= nil and chunk_parent.__has_insert_hooks
local has_insert_hooks = chunk_parent ~= nil and chunk_parent.__has_insert_hooks
or __evolved_has_any(chunk_fragment, __ON_SET, __ON_INSERT)
local has_remove_major = __evolved_has(chunk_fragment, __ON_REMOVE)
local has_remove_minors = chunk_parent ~= nil and chunk_parent.__has_remove_hooks
local has_setup_hooks = has_setup_major or has_setup_minors
local has_assign_hooks = has_assign_major or has_assign_minors
local has_insert_hooks = has_insert_major or has_insert_minors
local has_remove_hooks = has_remove_major or has_remove_minors
local has_remove_hooks = chunk_parent ~= nil and chunk_parent.__has_remove_hooks
or __evolved_has(chunk_fragment, __ON_REMOVE)
local has_unique_major = __evolved_has(chunk_fragment, __UNIQUE)
local has_unique_minors = chunk_parent ~= nil and chunk_parent.__has_unique_fragments
@@ -1685,75 +1667,6 @@ function __update_chunk_caches(chunk)
else
chunk.__without_unique_fragments = chunk
end
if has_insert_hooks then
local parent_insert_fragment_list = chunk_parent and chunk_parent.__insert_fragment_list
local parent_insert_fragment_count = chunk_parent and chunk_parent.__insert_fragment_count or 0
if has_insert_major then
local insert_fragment_list, insert_fragment_count = parent_insert_fragment_list
and __list_fns.dup(parent_insert_fragment_list, parent_insert_fragment_count)
or __list_fns.new(1), 0
insert_fragment_count = parent_insert_fragment_count + 1
insert_fragment_list[insert_fragment_count] = chunk_fragment
chunk.__insert_fragment_list = insert_fragment_list
chunk.__insert_fragment_count = insert_fragment_count
else
chunk.__insert_fragment_list = parent_insert_fragment_list
chunk.__insert_fragment_count = parent_insert_fragment_count
end
else
chunk.__insert_fragment_list = nil
chunk.__insert_fragment_count = 0
end
if has_remove_hooks then
local parent_remove_fragment_list = chunk_parent and chunk_parent.__remove_fragment_list
local parent_remove_fragment_count = chunk_parent and chunk_parent.__remove_fragment_count or 0
if has_remove_major then
local remove_fragment_list, remove_fragment_count = parent_remove_fragment_list
and __list_fns.dup(parent_remove_fragment_list, parent_remove_fragment_count)
or __list_fns.new(1), 0
remove_fragment_count = parent_remove_fragment_count + 1
remove_fragment_list[remove_fragment_count] = chunk_fragment
chunk.__remove_fragment_list = remove_fragment_list
chunk.__remove_fragment_count = remove_fragment_count
else
chunk.__remove_fragment_list = parent_remove_fragment_list
chunk.__remove_fragment_count = parent_remove_fragment_count
end
else
chunk.__remove_fragment_list = nil
chunk.__remove_fragment_count = 0
end
if has_explicit_fragments then
local parent_explicit_fragment_list = chunk_parent and chunk_parent.__explicit_fragment_list
local parent_explicit_fragment_count = chunk_parent and chunk_parent.__explicit_fragment_count or 0
if has_explicit_major then
local explicit_fragment_list, explicit_fragment_count = parent_explicit_fragment_list
and __list_fns.dup(parent_explicit_fragment_list, parent_explicit_fragment_count)
or __list_fns.new(1), 0
explicit_fragment_count = parent_explicit_fragment_count + 1
explicit_fragment_list[explicit_fragment_count] = chunk_fragment
chunk.__explicit_fragment_list = explicit_fragment_list
chunk.__explicit_fragment_count = explicit_fragment_count
else
chunk.__explicit_fragment_list = parent_explicit_fragment_list
chunk.__explicit_fragment_count = parent_explicit_fragment_count
end
else
chunk.__explicit_fragment_list = nil
chunk.__explicit_fragment_count = 0
end
end
---@param chunk evolved.chunk
@@ -2150,15 +2063,17 @@ function __query_minor_matches(chunk, query)
end
end
local chunk_explicit_fragment_list = chunk.__explicit_fragment_list
if chunk.__has_explicit_fragments then
local chunk_fragment_list = chunk.__fragment_list
local chunk_fragment_count = chunk.__fragment_count
if chunk_explicit_fragment_list then
for chunk_explicit_fragment_index = 1, chunk.__explicit_fragment_count do
local fragment = chunk_explicit_fragment_list[chunk_explicit_fragment_index]
for chunk_fragment_index = 1, chunk_fragment_count do
local chunk_fragment = chunk_fragment_list[chunk_fragment_index]
local is_chunk_fragment_matched =
(query_variant_count > 0 and query_variant_set[fragment]) or
(query_include_count > 0 and query_include_set[fragment])
(not __evolved_has(chunk_fragment, __EXPLICIT)) or
(query_variant_count > 0 and query_variant_set[chunk_fragment]) or
(query_include_count > 0 and query_include_set[chunk_fragment])
if not is_chunk_fragment_matched then
return false
@@ -2724,11 +2639,12 @@ function __spawn_entity(chunk, entity, component_table, component_mapper)
component_mapper(chunk, place, place)
end
local chunk_insert_fragment_list = chunk.__insert_fragment_list
if chunk.__has_insert_hooks then
local chunk_fragment_list = chunk.__fragment_list
local chunk_fragment_count = chunk.__fragment_count
if chunk_insert_fragment_list then
for chunk_insert_fragment_index = 1, chunk.__insert_fragment_count do
local fragment = chunk_insert_fragment_list[chunk_insert_fragment_index]
for chunk_fragment_index = 1, chunk_fragment_count do
local fragment = chunk_fragment_list[chunk_fragment_index]
---@type evolved.set_hook?, evolved.insert_hook?
local fragment_on_set, fragment_on_insert =
@@ -2862,11 +2778,12 @@ function __multi_spawn_entity(chunk, entity_list, entity_first, entity_count, co
component_mapper(chunk, b_place, e_place)
end
local chunk_insert_fragment_list = chunk.__insert_fragment_list
if chunk.__has_insert_hooks then
local chunk_fragment_list = chunk.__fragment_list
local chunk_fragment_count = chunk.__fragment_count
if chunk_insert_fragment_list then
for chunk_insert_fragment_index = 1, chunk.__insert_fragment_count do
local fragment = chunk_insert_fragment_list[chunk_insert_fragment_index]
for chunk_fragment_index = 1, chunk_fragment_count do
local fragment = chunk_fragment_list[chunk_fragment_index]
---@type evolved.set_hook?, evolved.insert_hook?
local fragment_on_set, fragment_on_insert =
@@ -3022,11 +2939,12 @@ function __clone_entity(prefab, entity, component_table, component_mapper)
component_mapper(chunk, place, place)
end
local chunk_insert_fragment_list = chunk.__insert_fragment_list
if chunk.__has_insert_hooks then
local chunk_fragment_list = chunk.__fragment_list
local chunk_fragment_count = chunk.__fragment_count
if chunk_insert_fragment_list then
for chunk_insert_fragment_index = 1, chunk.__insert_fragment_count do
local fragment = chunk_insert_fragment_list[chunk_insert_fragment_index]
for chunk_fragment_index = 1, chunk_fragment_count do
local fragment = chunk_fragment_list[chunk_fragment_index]
---@type evolved.set_hook?, evolved.insert_hook?
local fragment_on_set, fragment_on_insert =
@@ -3189,11 +3107,12 @@ function __multi_clone_entity(prefab, entity_list, entity_first, entity_count, c
component_mapper(chunk, b_place, e_place)
end
local chunk_insert_fragment_list = chunk.__insert_fragment_list
if chunk.__has_insert_hooks then
local chunk_fragment_list = chunk.__fragment_list
local chunk_fragment_count = chunk.__fragment_count
if chunk_insert_fragment_list then
for chunk_insert_fragment_index = 1, chunk.__insert_fragment_count do
local fragment = chunk_insert_fragment_list[chunk_insert_fragment_index]
for chunk_fragment_index = 1, chunk_fragment_count do
local fragment = chunk_fragment_list[chunk_fragment_index]
---@type evolved.set_hook?, evolved.insert_hook?
local fragment_on_set, fragment_on_insert =
@@ -3458,29 +3377,27 @@ function __clear_entity_one(entity)
local chunk = entity_chunks[entity_primary]
local place = entity_places[entity_primary]
if chunk then
local chunk_remove_fragment_list = chunk.__remove_fragment_list
if chunk and chunk.__has_remove_hooks then
local chunk_fragment_list = chunk.__fragment_list
local chunk_fragment_count = chunk.__fragment_count
local chunk_component_indices = chunk.__component_indices
local chunk_component_storages = chunk.__component_storages
if chunk_remove_fragment_list then
local chunk_component_indices = chunk.__component_indices
local chunk_component_storages = chunk.__component_storages
for chunk_fragment_index = 1, chunk_fragment_count do
local fragment = chunk_fragment_list[chunk_fragment_index]
for chunk_remove_fragment_index = 1, chunk.__remove_fragment_count do
local fragment = chunk_remove_fragment_list[chunk_remove_fragment_index]
---@type evolved.remove_hook?
local fragment_on_remove = __evolved_get(fragment, __ON_REMOVE)
---@type evolved.remove_hook?
local fragment_on_remove = __evolved_get(fragment, __ON_REMOVE)
if fragment_on_remove then
local component_index = chunk_component_indices[fragment]
if fragment_on_remove then
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
local old_component = component_storage[place]
fragment_on_remove(entity, fragment, old_component)
else
fragment_on_remove(entity, fragment)
end
if component_index then
local component_storage = chunk_component_storages[component_index]
local old_component = component_storage[place]
fragment_on_remove(entity, fragment, old_component)
else
fragment_on_remove(entity, fragment)
end
end
end
@@ -3527,29 +3444,27 @@ function __destroy_entity_one(entity)
local chunk = entity_chunks[entity_primary]
local place = entity_places[entity_primary]
if chunk then
local chunk_remove_fragment_list = chunk.__remove_fragment_list
if chunk and chunk.__has_remove_hooks then
local chunk_fragment_list = chunk.__fragment_list
local chunk_fragment_count = chunk.__fragment_count
local chunk_component_indices = chunk.__component_indices
local chunk_component_storages = chunk.__component_storages
if chunk_remove_fragment_list then
local chunk_component_indices = chunk.__component_indices
local chunk_component_storages = chunk.__component_storages
for chunk_fragment_index = 1, chunk_fragment_count do
local fragment = chunk_fragment_list[chunk_fragment_index]
for chunk_remove_fragment_index = 1, chunk.__remove_fragment_count do
local fragment = chunk_remove_fragment_list[chunk_remove_fragment_index]
---@type evolved.remove_hook?
local fragment_on_remove = __evolved_get(fragment, __ON_REMOVE)
---@type evolved.remove_hook?
local fragment_on_remove = __evolved_get(fragment, __ON_REMOVE)
if fragment_on_remove then
local component_index = chunk_component_indices[fragment]
if fragment_on_remove then
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
local old_component = component_storage[place]
fragment_on_remove(entity, fragment, old_component)
else
fragment_on_remove(entity, fragment)
end
if component_index then
local component_storage = chunk_component_storages[component_index]
local old_component = component_storage[place]
fragment_on_remove(entity, fragment, old_component)
else
fragment_on_remove(entity, fragment)
end
end
end
@@ -4145,6 +4060,8 @@ function __chunk_remove(old_chunk, ...)
local old_entity_list = old_chunk.__entity_list
local old_entity_count = old_chunk.__entity_count
local old_fragment_list = old_chunk.__fragment_list
local old_fragment_count = old_chunk.__fragment_count
local old_component_indices = old_chunk.__component_indices
local old_component_storages = old_chunk.__component_storages
@@ -4158,14 +4075,12 @@ function __chunk_remove(old_chunk, ...)
return
end
local old_remove_fragment_list = old_chunk.__remove_fragment_list
if old_remove_fragment_list then
if old_chunk.__has_remove_hooks then
local new_fragment_set = new_chunk and new_chunk.__fragment_set
or __safe_tbls.__EMPTY_FRAGMENT_SET
for old_remove_fragment_index = 1, old_chunk.__remove_fragment_count do
local fragment = old_remove_fragment_list[old_remove_fragment_index]
for old_fragment_index = 1, old_fragment_count do
local fragment = old_fragment_list[old_fragment_index]
if not new_fragment_set[fragment] then
---@type evolved.remove_hook?
@@ -4294,14 +4209,14 @@ function __chunk_clear(chunk)
return
end
local chunk_remove_fragment_list = chunk.__remove_fragment_list
if chunk_remove_fragment_list then
if chunk.__has_remove_hooks then
local chunk_fragment_list = chunk.__fragment_list
local chunk_fragment_count = chunk.__fragment_count
local chunk_component_indices = chunk.__component_indices
local chunk_component_storages = chunk.__component_storages
for chunk_remove_fragment_index = 1, chunk.__remove_fragment_count do
local fragment = chunk_remove_fragment_list[chunk_remove_fragment_index]
for chunk_fragment_index = 1, chunk_fragment_count do
local fragment = chunk_fragment_list[chunk_fragment_index]
---@type evolved.remove_hook?
local fragment_on_remove = __evolved_get(fragment, __ON_REMOVE)
@@ -5695,17 +5610,17 @@ function __evolved_remove(entity, ...)
__evolved_defer()
if old_chunk and old_chunk ~= new_chunk then
local old_fragment_list = old_chunk.__fragment_list
local old_fragment_count = old_chunk.__fragment_count
local old_component_indices = old_chunk.__component_indices
local old_component_storages = old_chunk.__component_storages
local old_remove_fragment_list = old_chunk.__remove_fragment_list
if old_remove_fragment_list then
if old_chunk.__has_remove_hooks then
local new_fragment_set = new_chunk and new_chunk.__fragment_set
or __safe_tbls.__EMPTY_FRAGMENT_SET
for old_remove_fragment_index = 1, old_chunk.__remove_fragment_count do
local fragment = old_remove_fragment_list[old_remove_fragment_index]
for old_fragment_index = 1, old_fragment_count do
local fragment = old_fragment_list[old_fragment_index]
if not new_fragment_set[fragment] then
---@type evolved.remove_hook?