Drainless iterators

This commit is contained in:
Ukendio 2024-07-02 12:53:33 +02:00
parent 0ff2348a6e
commit 0256c765a0

View file

@ -640,8 +640,8 @@ export type Query = typeof(EmptyQuery)
type CompatibleArchetype = { archetype: Archetype, indices: { number } } type CompatibleArchetype = { archetype: Archetype, indices: { number } }
local function PreparedQuery( local function preparedQuery(compatibleArchetypes: { Archetype },
compatibleArchetypes: { Archetype } , components: { i53 }, indices: { [number]: number }) components: { i53? }, indices: { { number } })
local queryLength = #components local queryLength = #components
@ -652,7 +652,6 @@ local function PreparedQuery(
return EmptyQuery return EmptyQuery
end end
local queryOutput = {} local queryOutput = {}
local i = 1 local i = 1
@ -746,48 +745,47 @@ local function PreparedQuery(
end end
end end
lastArchetype, archetype = next(compatibleArchetypes)
if not lastArchetype then
return EmptyQuery
end
return self return self
end end
local preparedQuery = { local query = {
__iter = function() __iter = function()
i = 1
lastArchetype = 1
archetype = compatibleArchetypes[1]
return queryNext return queryNext
end, end,
next = queryNext, next = queryNext,
without = without without = without
} }
return (setmetatable(preparedQuery, preparedQuery) :: any):: Query return setmetatable(query, query) :: any
end end
function World.query(world: World, ...: any): Query function World.query(world: World, ...: number?): Query
-- breaking? -- breaking?
if (...) == nil then if (...) == nil then
error("Missing components") error("Missing components")
end end
local columns = {} local indices: { { number } } = {}
local compatibleArchetypes: { CompatibleArchetype } = {} local compatibleArchetypes: { Archetype } = {}
local length = 0 local length = 0
local components = { ... } :: any local components: { number? } = { ... }
local archetypes = world.archetypes local archetypes: { Archetype } = world.archetypes :: any
local firstArchetypeMap: ArchetypeMap local firstArchetypeMap: ArchetypeMap
local componentIndex = world.componentIndex local componentIndex = world.componentIndex
for _, componentId in components do for _, componentId in components do
local map = componentIndex[componentId] local map: ArchetypeMap = componentIndex[componentId] :: any
if not map then if not map then
return EmptyQuery return EmptyQuery
end end
if firstArchetypeMap == nil or map.size < firstArchetypeMap.size then if (firstArchetypeMap :: any) == nil or firstArchetypeMap.size < map.size then
firstArchetypeMap = map firstArchetypeMap = map
end end
end end
@ -796,7 +794,7 @@ function World.query(world: World, ...: any): Query
local archetype = archetypes[id] local archetype = archetypes[id]
local archetypeRecords = archetype.records local archetypeRecords = archetype.records
local records = {} local records: { number } = {}
local skip = false local skip = false
for i, componentId in components do for i, componentId in components do
@ -815,25 +813,27 @@ function World.query(world: World, ...: any): Query
length += 1 length += 1
compatibleArchetypes[length] = archetype compatibleArchetypes[length] = archetype
columns[length] = records indices[length] = records
end end
return PreparedQuery(compatibleArchetypes, components, columns) return preparedQuery(compatibleArchetypes, components, indices)
end end
type WorldIterator = (() -> (i53, { [unknown]: unknown? })) & (() -> ()) & (() -> i53) type WorldIterator = (() -> (i53, { [unknown]: unknown? })) & (() -> ()) & (() -> i53)
function World.__iter(world: World): WorldIterator function World.__iter(world: World): WorldIterator
local dense = world.entityIndex.dense local entityIndex = world.entityIndex
local sparse = world.entityIndex.sparse local dense = entityIndex.dense
local sparse = entityIndex.sparse
local last local last
-- new solver doesnt like the world iterator type even tho its correct -- new solver doesnt like the world iterator type even tho its correct
-- so any cast here i come -- so any cast here i come
local i = 0
local function iterator() local function iterator()
local lastEntity: number?, entityId: number = next(dense, last) i+=1
if not lastEntity then local entityId = dense[i]
-- ignore type error if not entityId then
return return
end end