Merge branch 'main' of https://github.com/Ukendio/jecs into add-clear

This commit is contained in:
Ukendio 2024-07-02 14:21:32 +02:00
commit c426436104

View file

@ -640,34 +640,31 @@ export type Query = typeof(EmptyQuery)
type CompatibleArchetype = { archetype: Archetype, indices: { number } } type CompatibleArchetype = { archetype: Archetype, indices: { number } }
local function PreparedQuery(compatibleArchetypes: { CompatibleArchetype } , components: { i53 }) local function preparedQuery(compatibleArchetypes: { Archetype },
components: { i53? }, indices: { { number } })
local queryLength = #components local queryLength = #components
local lastArchetype = 1 local lastArchetype = 1
local compatibleArchetype: CompatibleArchetype = compatibleArchetypes[lastArchetype] local archetype: Archetype = compatibleArchetypes[lastArchetype]
if not compatibleArchetype then if not archetype then
return EmptyQuery return EmptyQuery
end end
local preparedQuery = {}
preparedQuery.__index = preparedQuery
local queryOutput = {} local queryOutput = {}
local i = 1 local i = 1
local function queryNext(): ...any local function queryNext(): ...any
local archetype = compatibleArchetype.archetype
local entityId = archetype.entities[i] local entityId = archetype.entities[i]
while entityId == nil do while entityId == nil do
lastArchetype += 1 lastArchetype += 1
if lastArchetype > #compatibleArchetypes then archetype = compatibleArchetypes[lastArchetype]
if not archetype then
return return
end end
compatibleArchetype = compatibleArchetypes[lastArchetype]
archetype = compatibleArchetype.archetype
i = 1 i = 1
entityId = archetype.entities[i] entityId = archetype.entities[i]
end end
@ -676,7 +673,7 @@ local function PreparedQuery(compatibleArchetypes: { CompatibleArchetype } , com
i+=1 i+=1
local columns = archetype.columns local columns = archetype.columns
local tr = compatibleArchetype.indices local tr = indices[lastArchetype]
if queryLength == 1 then if queryLength == 1 then
return entityId, columns[tr[1]][row] return entityId, columns[tr[1]][row]
@ -728,19 +725,11 @@ local function PreparedQuery(compatibleArchetypes: { CompatibleArchetype } , com
return entityId, unpack(queryOutput, 1, queryLength) return entityId, unpack(queryOutput, 1, queryLength)
end end
function preparedQuery:__iter(): () -> ...any
return queryNext
end
function preparedQuery:next(): ...any local function without(self, ...): Query
return queryNext()
end
function preparedQuery:without(...: any): Query
local withoutComponents = { ... } local withoutComponents = { ... }
for i = #compatibleArchetypes, 1, -1 do for i = #compatibleArchetypes, 1, -1 do
local archetype = compatibleArchetypes[i].archetype local archetype = compatibleArchetypes[i]
local records = archetype.records local records = archetype.records
local shouldRemove = false local shouldRemove = false
@ -756,39 +745,47 @@ local function PreparedQuery(compatibleArchetypes: { CompatibleArchetype } , com
end end
end end
lastArchetype, compatibleArchetype = next(compatibleArchetypes)
if not lastArchetype then
return EmptyQuery
end
return self return self
end end
local query = {
__iter = function()
i = 1
lastArchetype = 1
archetype = compatibleArchetypes[1]
return setmetatable({}, preparedQuery) :: any return queryNext
end,
next = queryNext,
without = without
}
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 compatibleArchetypes: { CompatibleArchetype } = {} local indices: { { number } } = {}
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
@ -797,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 indices = {} local records: { number } = {}
local skip = false local skip = false
for i, componentId in components do for i, componentId in components do
@ -807,7 +804,7 @@ function World.query(world: World, ...: any): Query
break break
end end
-- index should be index.offset -- index should be index.offset
indices[i] = index records[i] = index
end end
if skip then if skip then
@ -815,28 +812,28 @@ function World.query(world: World, ...: any): Query
end end
length += 1 length += 1
compatibleArchetypes[length] = { compatibleArchetypes[length] = archetype
archetype = archetype, indices[length] = records
indices = indices,
}
end end
return PreparedQuery(compatibleArchetypes, components) 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
@ -865,10 +862,6 @@ function World.__iter(world: World): WorldIterator
return iterator :: any return iterator :: any
end end
-- freezing it incase somebody tries doing something stupid and modifying it
-- (unlikely but its easy to add extra safety so)
table.freeze(World)
-- __nominal_type_dont_use could not be any or T as it causes a type error -- __nominal_type_dont_use could not be any or T as it causes a type error
-- or produces a union -- or produces a union
export type Entity<T = any> = number & { __nominal_type_dont_use: T } export type Entity<T = any> = number & { __nominal_type_dont_use: T }
@ -999,7 +992,7 @@ export type WorldShim = typeof(setmetatable(
)) ))
return table.freeze({ return table.freeze({
World = (World :: any) :: { new: () -> WorldShim }, World = (table.freeze(World) :: any) :: { new: () -> WorldShim },
OnAdd = (ON_ADD :: any) :: Entity, OnAdd = (ON_ADD :: any) :: Entity,
OnRemove = (ON_REMOVE :: any) :: Entity, OnRemove = (ON_REMOVE :: any) :: Entity,