little more safety

This commit is contained in:
BlackMATov
2024-12-31 22:24:01 +07:00
parent 6f7c2618a8
commit 280460d609
2 changed files with 49 additions and 16 deletions

View File

@@ -9,3 +9,4 @@
- should we clear chunk's components by on_insert tag callback? - should we clear chunk's components by on_insert tag callback?
- use table.new/clear for cached tables - use table.new/clear for cached tables
- replace chunk_list/fragment_list pools to one generic table pool - replace chunk_list/fragment_list pools to one generic table pool
- replace id type aliases with separated types to hide implementation details

View File

@@ -52,7 +52,7 @@ local evolved = {
---@class (exact) evolved.execute_state ---@class (exact) evolved.execute_state
---@field [1] integer structural_changes ---@field [1] integer structural_changes
---@field [2] evolved.chunk[] chunk_stack ---@field [2] evolved.chunk[] chunk_stack
---@field [3] table<evolved.fragment, boolean>? exclude_set ---@field [3] table<evolved.fragment, boolean> exclude_set
---@alias evolved.each_iterator fun(state: evolved.each_state?): evolved.fragment?, evolved.component? ---@alias evolved.each_iterator fun(state: evolved.each_state?): evolved.fragment?, evolved.component?
---@alias evolved.execute_iterator fun(state: evolved.execute_state?): evolved.chunk?, evolved.entity[]? ---@alias evolved.execute_iterator fun(state: evolved.execute_state?): evolved.chunk?, evolved.entity[]?
@@ -312,7 +312,7 @@ end
--- ---
--- ---
---@param exclude_set? table<evolved.fragment, boolean> ---@param exclude_set table<evolved.fragment, boolean>
---@return evolved.execute_state ---@return evolved.execute_state
---@nodiscard ---@nodiscard
local function __acquire_execute_state(exclude_set) local function __acquire_execute_state(exclude_set)
@@ -355,7 +355,7 @@ local function __execute_iterator(state)
chunk_stack[#chunk_stack] = nil chunk_stack[#chunk_stack] = nil
for _, chunk_child in ipairs(chunk.__children) do for _, chunk_child in ipairs(chunk.__children) do
if not exclude_set or not exclude_set[chunk_child.__fragment] then if not exclude_set[chunk_child.__fragment] then
chunk_stack[#chunk_stack + 1] = chunk_child chunk_stack[#chunk_stack + 1] = chunk_child
end end
end end
@@ -2302,6 +2302,27 @@ end))
--- ---
--- ---
---@type table<evolved.fragment, boolean>
local __EMPTY_FRAGMENT_SET = setmetatable({}, {
__newindex = function() error('attempt to modify empty fragment set') end
})
---@type evolved.fragment[]
local __EMPTY_FRAGMENT_LIST = setmetatable({}, {
__newindex = function() error('attempt to modify empty fragment list') end
})
---@type evolved.component[]
local __EMPTY_COMPONENT_STORAGE = setmetatable({}, {
__newindex = function() error('attempt to modify empty component storage') end
})
---
---
---
---
---
---@param ... evolved.fragment fragments ---@param ... evolved.fragment fragments
---@return evolved.chunk?, evolved.entity[]? ---@return evolved.chunk?, evolved.entity[]?
function evolved.chunk(...) function evolved.chunk(...)
@@ -2346,7 +2367,7 @@ end
---@param chunk evolved.chunk ---@param chunk evolved.chunk
---@param ... evolved.fragment fragments ---@param ... evolved.fragment fragments
---@return evolved.component[]? ... components ---@return evolved.component[] ... components
---@nodiscard ---@nodiscard
function evolved.select(chunk, ...) function evolved.select(chunk, ...)
local fragment_count = select('#', ...) local fragment_count = select('#', ...)
@@ -2355,26 +2376,35 @@ function evolved.select(chunk, ...)
return return
end end
local components = chunk.__components local chunk_components = chunk.__components
if fragment_count == 1 then if fragment_count == 1 then
local f1 = ... local f1 = ...
return components[f1] return
chunk_components[f1] or __EMPTY_COMPONENT_STORAGE
end end
if fragment_count == 2 then if fragment_count == 2 then
local f1, f2 = ... local f1, f2 = ...
return components[f1], components[f2] return
chunk_components[f1] or __EMPTY_COMPONENT_STORAGE,
chunk_components[f2] or __EMPTY_COMPONENT_STORAGE
end end
if fragment_count == 3 then if fragment_count == 3 then
local f1, f2, f3 = ... local f1, f2, f3 = ...
return components[f1], components[f2], components[f3] return
chunk_components[f1] or __EMPTY_COMPONENT_STORAGE,
chunk_components[f2] or __EMPTY_COMPONENT_STORAGE,
chunk_components[f3] or __EMPTY_COMPONENT_STORAGE
end end
do do
local f1, f2, f3 = ... local f1, f2, f3 = ...
return components[f1], components[f2], components[f3], return
chunk_components[f1] or __EMPTY_COMPONENT_STORAGE,
chunk_components[f2] or __EMPTY_COMPONENT_STORAGE,
chunk_components[f3] or __EMPTY_COMPONENT_STORAGE,
evolved.select(chunk, select(4, ...)) evolved.select(chunk, select(4, ...))
end end
end end
@@ -2409,11 +2439,15 @@ function evolved.execute(query)
return __execute_iterator return __execute_iterator
end end
---@type evolved.fragment[]?, evolved.fragment[]? ---@type table<evolved.fragment, boolean>?, evolved.fragment[]?, evolved.fragment[]?
local include_list, exclude_list = evolved.get(query, local exclude_set, include_list, exclude_list = evolved.get(query,
__SORTED_INCLUDE_LIST, __SORTED_EXCLUDE_LIST) __EXCLUDE_SET, __SORTED_INCLUDE_LIST, __SORTED_EXCLUDE_LIST)
if not include_list or #include_list == 0 then if not exclude_set then exclude_set = __EMPTY_FRAGMENT_SET end
if not include_list then include_list = __EMPTY_FRAGMENT_LIST end
if not exclude_list then exclude_list = __EMPTY_FRAGMENT_LIST end
if #include_list == 0 then
return __execute_iterator return __execute_iterator
end end
@@ -2424,13 +2458,11 @@ function evolved.execute(query)
return __execute_iterator return __execute_iterator
end end
---@type table<evolved.fragment, boolean>?
local exclude_set = evolved.get(query, __EXCLUDE_SET)
local execute_state = __acquire_execute_state(exclude_set) local execute_state = __acquire_execute_state(exclude_set)
for _, major_fragment_chunk in ipairs(major_fragment_chunks) do for _, major_fragment_chunk in ipairs(major_fragment_chunks) do
if __chunk_has_all_fragment_list(major_fragment_chunk, include_list) then if __chunk_has_all_fragment_list(major_fragment_chunk, include_list) then
if not exclude_list or not __chunk_has_any_fragment_list(major_fragment_chunk, exclude_list) then if not __chunk_has_any_fragment_list(major_fragment_chunk, exclude_list) then
local chunk_stack = execute_state[2] local chunk_stack = execute_state[2]
chunk_stack[#chunk_stack + 1] = major_fragment_chunk chunk_stack[#chunk_stack + 1] = major_fragment_chunk
end end