mirror of
				https://github.com/Ukendio/jecs.git
				synced 2025-11-04 10:59:18 +00:00 
			
		
		
		
	Cleanup functions and add missing types
This commit is contained in:
		
							parent
							
								
									ca8e1376ca
								
							
						
					
					
						commit
						447c7f12e7
					
				
					 1 changed files with 88 additions and 150 deletions
				
			
		
							
								
								
									
										238
									
								
								lib/init.lua
									
									
									
									
									
								
							
							
						
						
									
										238
									
								
								lib/init.lua
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -11,14 +11,14 @@ type ArchetypeId = number
 | 
			
		|||
 | 
			
		||||
type Column = { any }
 | 
			
		||||
 | 
			
		||||
type ArchetypeEdge = {
 | 
			
		||||
	add: Archetype,
 | 
			
		||||
	remove: Archetype,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Archetype = {
 | 
			
		||||
	id: number,
 | 
			
		||||
	edges: {
 | 
			
		||||
		[i53]: {
 | 
			
		||||
			add: Archetype,
 | 
			
		||||
			remove: Archetype,
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	edges: { [i53]: ArchetypeEdge },
 | 
			
		||||
	types: Ty,
 | 
			
		||||
	type: string | number,
 | 
			
		||||
	entities: { number },
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +75,7 @@ local ECS_ID_FLAGS_MASK = 0x10
 | 
			
		|||
local ECS_ENTITY_MASK = bit32.lshift(1, 24)
 | 
			
		||||
local ECS_GENERATION_MASK = bit32.lshift(1, 16)
 | 
			
		||||
 | 
			
		||||
local function addFlags(isPair: boolean)
 | 
			
		||||
local function addFlags(isPair: boolean): number
 | 
			
		||||
	local typeFlags = 0x0
 | 
			
		||||
 | 
			
		||||
	if isPair then
 | 
			
		||||
| 
						 | 
				
			
			@ -94,48 +94,17 @@ local function addFlags(isPair: boolean)
 | 
			
		|||
	return typeFlags
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
local function newId(source: number, target: number): number
 | 
			
		||||
    return ((source * 2^28) + target) * ECS_ID_FLAGS_MASK
 | 
			
		||||
local function ECS_COMBINE(source: number, target: number): i53
 | 
			
		||||
	return ((source * 268435456) + target) * ECS_ID_FLAGS_MASK
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function ECS_IS_PAIR(e: number): boolean
 | 
			
		||||
    return ( (e % 2^4) // FLAGS_PAIR ) ~= 0
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function separate(entity: number): (number, number, number)
 | 
			
		||||
	local type_flags = entity % 0x10
 | 
			
		||||
	local entity = entity // ECS_ID_FLAGS_MASK
 | 
			
		||||
	return new_entity // ECS_ENTITY_MASK, new_entity % ECS_GENERATION_MASK, type_flags
 | 
			
		||||
=======
 | 
			
		||||
local function ECS_COMBINE(source: number, target: number): i53
 | 
			
		||||
	local e = source * 268435456 + target * ECS_ID_FLAGS_MASK
 | 
			
		||||
	return e
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function ECS_IS_PAIR(e: number)
 | 
			
		||||
	if e > ECS_ENTITY_MASK then
 | 
			
		||||
		return (e % 2 ^ 4) // FLAGS_PAIR ~= 0
 | 
			
		||||
	end
 | 
			
		||||
	return false
 | 
			
		||||
>>>>>>> eae51988a9e3ca45e39ebcfdbea0f9f8706bd3cd
 | 
			
		||||
	return if e > ECS_ENTITY_MASK then (((e % 2) ^ 4) // FLAGS_PAIR) ~= 0 else false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- HIGH 24 bits LOW 24 bits
 | 
			
		||||
local function ECS_GENERATION(e: i53)
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
    return (e // 0x10) % ECS_GENERATION_MASK
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function ECS_ID(e: i53) 
 | 
			
		||||
    return (e // 0x10) // ECS_ENTITY_MASK
 | 
			
		||||
=======
 | 
			
		||||
	if e > ECS_ENTITY_MASK then
 | 
			
		||||
		e = e // 0x10
 | 
			
		||||
		return e % ECS_GENERATION_MASK
 | 
			
		||||
	end
 | 
			
		||||
	return 0
 | 
			
		||||
>>>>>>> eae51988a9e3ca45e39ebcfdbea0f9f8706bd3cd
 | 
			
		||||
local function ECS_GENERATION(e: i53): i24
 | 
			
		||||
	return if e > ECS_ENTITY_MASK then (e // 0x10) % ECS_GENERATION_MASK else 0
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function ECS_GENERATION_INC(e: i53)
 | 
			
		||||
| 
						 | 
				
			
			@ -144,74 +113,28 @@ local function ECS_GENERATION_INC(e: i53)
 | 
			
		|||
		local id = flags // ECS_ENTITY_MASK
 | 
			
		||||
		local generation = flags % ECS_GENERATION_MASK
 | 
			
		||||
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
    return newId(id, generation + 1) + flags
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- gets the high ID
 | 
			
		||||
local function ECS_PAIR_FIRST(entity: i53): i24
 | 
			
		||||
    return (entity // 0x10) % ECS_ENTITY_MASK
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- gets the low ID
 | 
			
		||||
local ECS_PAIR_SECOND = ECS_ID
 | 
			
		||||
 | 
			
		||||
local function ECS_PAIR(first: number, second: number):
 | 
			
		||||
	local target = WILDCARD
 | 
			
		||||
	local relation 
 | 
			
		||||
 | 
			
		||||
	if first == WILDCARD then 
 | 
			
		||||
		relation = second
 | 
			
		||||
	elseif second == WILDCARD then
 | 
			
		||||
		relation = first
 | 
			
		||||
	else
 | 
			
		||||
		relation = second 
 | 
			
		||||
		target = ECS_PAIR_SECOND(first)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	return newId(
 | 
			
		||||
		ECS_PAIR_SECOND(relation), target) + addFlags(--[[isPair]] true)
 | 
			
		||||
	)
 | 
			
		||||
end 
 | 
			
		||||
 | 
			
		||||
local function getAlive(entityIndex: EntityIndex, id: i53) 
 | 
			
		||||
    return entityIndex.dense[id]
 | 
			
		||||
=======
 | 
			
		||||
		return ECS_COMBINE(id, generation + 1) + flags
 | 
			
		||||
	else
 | 
			
		||||
		return ECS_COMBINE(e, 1)
 | 
			
		||||
	end
 | 
			
		||||
	return ECS_COMBINE(e, 1)
 | 
			
		||||
>>>>>>> eae51988a9e3ca45e39ebcfdbea0f9f8706bd3cd
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- FIRST gets the high ID
 | 
			
		||||
local function ECS_ENTITY_T_HI(e: i53): i24
 | 
			
		||||
	if e > ECS_ENTITY_MASK then
 | 
			
		||||
		e = e // 0x10
 | 
			
		||||
		return e % ECS_ENTITY_MASK
 | 
			
		||||
	end
 | 
			
		||||
	return e
 | 
			
		||||
	return if e > ECS_ENTITY_MASK then (e // 0x10) % ECS_ENTITY_MASK else e
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
local function nextEntityId(entityIndex, index: i24): i53
 | 
			
		||||
	local id = newId(index, 0)
 | 
			
		||||
=======
 | 
			
		||||
-- SECOND
 | 
			
		||||
local function ECS_ENTITY_T_LO(e: i53): i24
 | 
			
		||||
	if e > ECS_ENTITY_MASK then
 | 
			
		||||
		e = e // 0x10
 | 
			
		||||
		return e // ECS_ENTITY_MASK
 | 
			
		||||
	end
 | 
			
		||||
	return e
 | 
			
		||||
	return if e > ECS_ENTITY_MASK then (e // 0x10) // ECS_ENTITY_MASK else e
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function ECS_PAIR(pred: i53, obj: i53): i53
 | 
			
		||||
	return ECS_COMBINE(ECS_ENTITY_T_LO(obj), ECS_ENTITY_T_LO(pred)) + addFlags(--[[isPair]] true) :: i53
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function getAlive(entityIndex: EntityIndex, id: i24)
 | 
			
		||||
	local entityId = entityIndex.dense[id]
 | 
			
		||||
	return entityId
 | 
			
		||||
local function getAlive(entityIndex: EntityIndex, id: i24): i53
 | 
			
		||||
	return entityIndex.dense[id]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- ECS_PAIR_FIRST, gets the relationship target / obj / HIGH bits
 | 
			
		||||
| 
						 | 
				
			
			@ -227,7 +150,6 @@ end
 | 
			
		|||
local function nextEntityId(entityIndex: EntityIndex, index: i24): i53
 | 
			
		||||
	--local id = ECS_COMBINE(index, 0)
 | 
			
		||||
	local id = index
 | 
			
		||||
>>>>>>> eae51988a9e3ca45e39ebcfdbea0f9f8706bd3cd
 | 
			
		||||
	entityIndex.sparse[id] = {
 | 
			
		||||
		dense = index,
 | 
			
		||||
	} :: Record
 | 
			
		||||
| 
						 | 
				
			
			@ -298,7 +220,7 @@ local function archetypeAppend(entity: number, archetype: Archetype): number
 | 
			
		|||
	return length
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function newEntity(entityId: i53, record: Record, archetype: Archetype)
 | 
			
		||||
local function newEntity(entityId: i53, record: Record, archetype: Archetype): Record
 | 
			
		||||
	local row = archetypeAppend(entityId, archetype)
 | 
			
		||||
	record.archetype = archetype
 | 
			
		||||
	record.row = row
 | 
			
		||||
| 
						 | 
				
			
			@ -314,7 +236,7 @@ local function moveEntity(entityIndex: EntityIndex, entityId: i53, record: Recor
 | 
			
		|||
	record.row = destinationRow
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function hash(arr): string
 | 
			
		||||
local function hash(arr: { number }): string
 | 
			
		||||
	return table.concat(arr, "_")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -324,10 +246,10 @@ local function ensureComponentRecord(
 | 
			
		|||
	componentId: number,
 | 
			
		||||
	i: number
 | 
			
		||||
): ArchetypeMap
 | 
			
		||||
	local archetypesMap = componentIndex[componentId] 
 | 
			
		||||
	local archetypesMap = componentIndex[componentId]
 | 
			
		||||
 | 
			
		||||
	if not archetypesMap then
 | 
			
		||||
		archetypesMap = ({ size = 0, cache = {} }  :: any) :: ArchetypeMap
 | 
			
		||||
		archetypesMap = ({ size = 0, cache = {} } :: any) :: ArchetypeMap
 | 
			
		||||
		componentIndex[componentId] = archetypesMap
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -337,7 +259,7 @@ local function ensureComponentRecord(
 | 
			
		|||
	return archetypesMap
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function ECS_ID_IS_WILDCARD(e)
 | 
			
		||||
local function ECS_ID_IS_WILDCARD(e: i53): boolean
 | 
			
		||||
	assert(ECS_IS_PAIR(e))
 | 
			
		||||
	local first = ECS_ENTITY_T_HI(e)
 | 
			
		||||
	local second = ECS_ENTITY_T_LO(e)
 | 
			
		||||
| 
						 | 
				
			
			@ -391,7 +313,8 @@ end
 | 
			
		|||
 | 
			
		||||
local World = {}
 | 
			
		||||
World.__index = World
 | 
			
		||||
function World.new()
 | 
			
		||||
 | 
			
		||||
function World.new(): World
 | 
			
		||||
	local self = setmetatable({
 | 
			
		||||
		archetypeIndex = {} :: { [string]: Archetype },
 | 
			
		||||
		archetypes = {} :: Archetypes,
 | 
			
		||||
| 
						 | 
				
			
			@ -409,12 +332,13 @@ function World.new()
 | 
			
		|||
		ROOT_ARCHETYPE = (nil :: any) :: Archetype,
 | 
			
		||||
	}, World)
 | 
			
		||||
	self.ROOT_ARCHETYPE = archetypeOf(self, {})
 | 
			
		||||
	return self
 | 
			
		||||
 | 
			
		||||
	return table.freeze(self)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
export type World = typeof(World.new())
 | 
			
		||||
 | 
			
		||||
function World.component(world: World)
 | 
			
		||||
function World.component(world: World): i53
 | 
			
		||||
	local componentId = world.nextComponentId + 1
 | 
			
		||||
	if componentId > HI_COMPONENT_ID then
 | 
			
		||||
		-- IDs are partitioned into ranges because component IDs are not nominal,
 | 
			
		||||
| 
						 | 
				
			
			@ -425,7 +349,7 @@ function World.component(world: World)
 | 
			
		|||
	return nextEntityId(world.entityIndex, componentId)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function World.entity(world: World)
 | 
			
		||||
function World.entity(world: World): i53
 | 
			
		||||
	local entityId = world.nextEntityId + 1
 | 
			
		||||
	world.nextEntityId = entityId
 | 
			
		||||
	return nextEntityId(world.entityIndex, entityId + REST)
 | 
			
		||||
| 
						 | 
				
			
			@ -473,6 +397,7 @@ local function archetypeDelete(world: World, id: i53)
 | 
			
		|||
	local componentIndex = world.componentIndex
 | 
			
		||||
	local archetypesMap = componentIndex[id]
 | 
			
		||||
	local archetypes = world.archetypes
 | 
			
		||||
 | 
			
		||||
	if archetypesMap then
 | 
			
		||||
		for archetypeId in archetypesMap.cache do
 | 
			
		||||
			for _, entity in archetypes[archetypeId].entities do
 | 
			
		||||
| 
						 | 
				
			
			@ -534,7 +459,7 @@ local function ensureArchetype(world: World, types, prev): Archetype
 | 
			
		|||
	return archetypeOf(world, types, prev)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function findInsert(types: { i53 }, toAdd: i53)
 | 
			
		||||
local function findInsert(types: { i53 }, toAdd: i53): number
 | 
			
		||||
	for i, id in types do
 | 
			
		||||
		if id == toAdd then
 | 
			
		||||
			return -1
 | 
			
		||||
| 
						 | 
				
			
			@ -546,7 +471,7 @@ local function findInsert(types: { i53 }, toAdd: i53)
 | 
			
		|||
	return #types + 1
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function findArchetypeWith(world: World, node: Archetype, componentId: i53)
 | 
			
		||||
local function findArchetypeWith(world: World, node: Archetype, componentId: i53): Archetype
 | 
			
		||||
	local types = node.types
 | 
			
		||||
	-- Component IDs are added incrementally, so inserting and sorting
 | 
			
		||||
	-- them each time would be expensive. Instead this insertion sort can find the insertion
 | 
			
		||||
| 
						 | 
				
			
			@ -564,7 +489,7 @@ local function findArchetypeWith(world: World, node: Archetype, componentId: i53
 | 
			
		|||
	return ensureArchetype(world, destinationType, node)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function ensureEdge(archetype: Archetype, componentId: i53)
 | 
			
		||||
local function ensureEdge(archetype: Archetype, componentId: i53): ArchetypeEdge
 | 
			
		||||
	local edges = archetype.edges
 | 
			
		||||
	local edge = edges[componentId]
 | 
			
		||||
	if not edge then
 | 
			
		||||
| 
						 | 
				
			
			@ -662,7 +587,7 @@ function World.remove(world: World, entityId: i53, componentId: i53)
 | 
			
		|||
end
 | 
			
		||||
 | 
			
		||||
-- Keeping the function as small as possible to enable inlining
 | 
			
		||||
local function get(record: Record, componentId: i24)
 | 
			
		||||
local function get(record: Record, componentId: i24): any
 | 
			
		||||
	local archetype = record.archetype
 | 
			
		||||
	if not archetype then
 | 
			
		||||
		return nil
 | 
			
		||||
| 
						 | 
				
			
			@ -677,7 +602,7 @@ local function get(record: Record, componentId: i24)
 | 
			
		|||
	return archetype.columns[archetypeRecord][record.row]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function World.get(world: World, entityId: i53, a: i53, b: i53?, c: i53?, d: i53?, e: i53?): any
 | 
			
		||||
function World.get(world: World, entityId: i53, a: i53, b: i53?, c: i53?, d: i53?, e: i53?): ...any
 | 
			
		||||
	local id = entityId
 | 
			
		||||
	local record = world.entityIndex.sparse[id]
 | 
			
		||||
	if not record then
 | 
			
		||||
| 
						 | 
				
			
			@ -716,13 +641,13 @@ export type Query = typeof(EmptyQuery)
 | 
			
		|||
 | 
			
		||||
type CompatibleArchetype = { archetype: Archetype, indices: { number } }
 | 
			
		||||
 | 
			
		||||
function World.query(world: World, ...): Query
 | 
			
		||||
function World.query(world: World, ...: i53): Query
 | 
			
		||||
	-- breaking?
 | 
			
		||||
	if (...) == nil then
 | 
			
		||||
		error("Missing components")
 | 
			
		||||
		error("  Missing components")
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local compatibleArchetypes: { CompatibleArchetype } = {} 
 | 
			
		||||
	local compatibleArchetypes: { CompatibleArchetype } = {}
 | 
			
		||||
	local length = 0
 | 
			
		||||
 | 
			
		||||
	local components = { ... }
 | 
			
		||||
| 
						 | 
				
			
			@ -772,7 +697,7 @@ function World.query(world: World, ...): Query
 | 
			
		|||
	end
 | 
			
		||||
 | 
			
		||||
	local lastArchetype = 1
 | 
			
		||||
 	local compatibleArchetype: CompatibleArchetype = compatibleArchetypes[lastArchetype]
 | 
			
		||||
	local compatibleArchetype: CompatibleArchetype = compatibleArchetypes[lastArchetype]
 | 
			
		||||
 | 
			
		||||
	if not compatibleArchetype then
 | 
			
		||||
		return EmptyQuery
 | 
			
		||||
| 
						 | 
				
			
			@ -780,18 +705,18 @@ function World.query(world: World, ...): Query
 | 
			
		|||
 | 
			
		||||
	local preparedQuery = {}
 | 
			
		||||
	preparedQuery.__index = preparedQuery
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	local queryOutput = {}
 | 
			
		||||
 | 
			
		||||
	local i = 1
 | 
			
		||||
 | 
			
		||||
	local function queryNext() 
 | 
			
		||||
	local function queryNext(): ...any
 | 
			
		||||
		local archetype = compatibleArchetype.archetype
 | 
			
		||||
		local entityId = archetype.entities[i]
 | 
			
		||||
 | 
			
		||||
		while entityId == nil do 
 | 
			
		||||
		while entityId == nil do
 | 
			
		||||
			lastArchetype += 1
 | 
			
		||||
			if lastArchetype > #compatibleArchetypes then 
 | 
			
		||||
			if lastArchetype > #compatibleArchetypes then
 | 
			
		||||
				return
 | 
			
		||||
			end
 | 
			
		||||
			compatibleArchetype = compatibleArchetypes[lastArchetype]
 | 
			
		||||
| 
						 | 
				
			
			@ -801,7 +726,7 @@ function World.query(world: World, ...): Query
 | 
			
		|||
		end
 | 
			
		||||
 | 
			
		||||
		local row = i
 | 
			
		||||
		i+=1
 | 
			
		||||
		i += 1
 | 
			
		||||
 | 
			
		||||
		local columns = archetype.columns
 | 
			
		||||
		local tr = compatibleArchetype.indices
 | 
			
		||||
| 
						 | 
				
			
			@ -856,16 +781,16 @@ function World.query(world: World, ...): Query
 | 
			
		|||
 | 
			
		||||
		return entityId, unpack(queryOutput :: any, 1, queryLength)
 | 
			
		||||
	end
 | 
			
		||||
	
 | 
			
		||||
	function preparedQuery:__iter()
 | 
			
		||||
 | 
			
		||||
	function preparedQuery:__iter(): () -> ...any
 | 
			
		||||
		return queryNext
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	function preparedQuery:next() 
 | 
			
		||||
		return queryNext()	
 | 
			
		||||
	function preparedQuery:next(): ...any
 | 
			
		||||
		return queryNext()
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	function preparedQuery:without(...)
 | 
			
		||||
	function preparedQuery:without(...: i53): Query
 | 
			
		||||
		local withoutComponents = { ... }
 | 
			
		||||
		for i = #compatibleArchetypes, 1, -1 do
 | 
			
		||||
			local archetype = compatibleArchetypes[i].archetype
 | 
			
		||||
| 
						 | 
				
			
			@ -895,40 +820,53 @@ function World.query(world: World, ...): Query
 | 
			
		|||
	return setmetatable({}, preparedQuery) :: any
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function World.__iter(world: World): () -> any 
 | 
			
		||||
type WorldIterator = (() -> (i53, { [unknown]: unknown? })) & (() -> ()) & (() -> i53)
 | 
			
		||||
 | 
			
		||||
function World.__iter(world: World): WorldIterator
 | 
			
		||||
	local dense = world.entityIndex.dense
 | 
			
		||||
	local sparse = world.entityIndex.sparse
 | 
			
		||||
	local last
 | 
			
		||||
 | 
			
		||||
	return function()
 | 
			
		||||
		local lastEntity: number?, entityId: number = next(dense, last)
 | 
			
		||||
		if not lastEntity then 
 | 
			
		||||
			return 
 | 
			
		||||
	-- new solver doesnt like the world iterator type even tho its correct
 | 
			
		||||
	-- so any cast here i come
 | 
			
		||||
	local iterator: WorldIterator = (
 | 
			
		||||
		function()
 | 
			
		||||
			local lastEntity: number?, entityId: number = next(dense, last)
 | 
			
		||||
			if not lastEntity then
 | 
			
		||||
				-- ignore type error
 | 
			
		||||
				return
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			last = lastEntity
 | 
			
		||||
 | 
			
		||||
			local record = sparse[entityId]
 | 
			
		||||
			local archetype = record.archetype
 | 
			
		||||
			if not archetype then
 | 
			
		||||
				-- Returns only the entity id as an entity without data should not return
 | 
			
		||||
				-- data and allow the user to get an error if they don't handle the case.
 | 
			
		||||
				return entityId
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			local row = record.row
 | 
			
		||||
			local types = archetype.types
 | 
			
		||||
			local columns = archetype.columns
 | 
			
		||||
			local entityData = {}
 | 
			
		||||
			for i, column in columns do
 | 
			
		||||
				-- We use types because the key should be the component ID not the column index
 | 
			
		||||
				entityData[types[i]] = column[row]
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			return entityId, entityData
 | 
			
		||||
		end
 | 
			
		||||
	) :: any
 | 
			
		||||
 | 
			
		||||
		last = lastEntity
 | 
			
		||||
 | 
			
		||||
		local record = sparse[entityId]
 | 
			
		||||
		local archetype = record.archetype
 | 
			
		||||
		if not archetype then
 | 
			
		||||
			-- Returns only the entity id as an entity without data should not return
 | 
			
		||||
			-- data and allow the user to get an error if they don't handle the case.
 | 
			
		||||
			return entityId
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		local row = record.row
 | 
			
		||||
		local types = archetype.types
 | 
			
		||||
		local columns = archetype.columns
 | 
			
		||||
		local entityData = {}
 | 
			
		||||
		for i, column in columns do
 | 
			
		||||
			-- We use types because the key should be the component ID not the column index
 | 
			
		||||
			entityData[types[i]] = column[row]
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		return entityId, entityData
 | 
			
		||||
	end
 | 
			
		||||
	return iterator
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- freezing it incase somebody trys 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
 | 
			
		||||
-- or produces a union
 | 
			
		||||
export type Entity<T = any> = number & { __nominal_type_dont_use: T }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue