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
				
			
		
							
								
								
									
										224
									
								
								lib/init.lua
									
									
									
									
									
								
							
							
						
						
									
										224
									
								
								lib/init.lua
									
									
									
									
									
								
							| 
						 | 
					@ -11,14 +11,14 @@ type ArchetypeId = number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Column = { any }
 | 
					type Column = { any }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ArchetypeEdge = {
 | 
				
			||||||
 | 
						add: Archetype,
 | 
				
			||||||
 | 
						remove: Archetype,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Archetype = {
 | 
					type Archetype = {
 | 
				
			||||||
	id: number,
 | 
						id: number,
 | 
				
			||||||
	edges: {
 | 
						edges: { [i53]: ArchetypeEdge },
 | 
				
			||||||
		[i53]: {
 | 
					 | 
				
			||||||
			add: Archetype,
 | 
					 | 
				
			||||||
			remove: Archetype,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	types: Ty,
 | 
						types: Ty,
 | 
				
			||||||
	type: string | number,
 | 
						type: string | number,
 | 
				
			||||||
	entities: { number },
 | 
						entities: { number },
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,7 @@ local ECS_ID_FLAGS_MASK = 0x10
 | 
				
			||||||
local ECS_ENTITY_MASK = bit32.lshift(1, 24)
 | 
					local ECS_ENTITY_MASK = bit32.lshift(1, 24)
 | 
				
			||||||
local ECS_GENERATION_MASK = bit32.lshift(1, 16)
 | 
					local ECS_GENERATION_MASK = bit32.lshift(1, 16)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function addFlags(isPair: boolean)
 | 
					local function addFlags(isPair: boolean): number
 | 
				
			||||||
	local typeFlags = 0x0
 | 
						local typeFlags = 0x0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if isPair then
 | 
						if isPair then
 | 
				
			||||||
| 
						 | 
					@ -94,48 +94,17 @@ local function addFlags(isPair: boolean)
 | 
				
			||||||
	return typeFlags
 | 
						return typeFlags
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<<<<<<< HEAD
 | 
					local function ECS_COMBINE(source: number, target: number): i53
 | 
				
			||||||
local function newId(source: number, target: number): number
 | 
						return ((source * 268435456) + target) * ECS_ID_FLAGS_MASK
 | 
				
			||||||
    return ((source * 2^28) + target) * ECS_ID_FLAGS_MASK
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function ECS_IS_PAIR(e: number): boolean
 | 
					local function ECS_IS_PAIR(e: number): boolean
 | 
				
			||||||
    return ( (e % 2^4) // FLAGS_PAIR ) ~= 0
 | 
						return if e > ECS_ENTITY_MASK then (((e % 2) ^ 4) // FLAGS_PAIR) ~= 0 else false
 | 
				
			||||||
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
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- HIGH 24 bits LOW 24 bits
 | 
					-- HIGH 24 bits LOW 24 bits
 | 
				
			||||||
local function ECS_GENERATION(e: i53)
 | 
					local function ECS_GENERATION(e: i53): i24
 | 
				
			||||||
<<<<<<< HEAD
 | 
						return if e > ECS_ENTITY_MASK then (e // 0x10) % ECS_GENERATION_MASK else 0
 | 
				
			||||||
    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
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function ECS_GENERATION_INC(e: i53)
 | 
					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 id = flags // ECS_ENTITY_MASK
 | 
				
			||||||
		local generation = flags % ECS_GENERATION_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
 | 
							return ECS_COMBINE(id, generation + 1) + flags
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return ECS_COMBINE(e, 1)
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
	return ECS_COMBINE(e, 1)
 | 
					 | 
				
			||||||
>>>>>>> eae51988a9e3ca45e39ebcfdbea0f9f8706bd3cd
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- FIRST gets the high ID
 | 
					-- FIRST gets the high ID
 | 
				
			||||||
local function ECS_ENTITY_T_HI(e: i53): i24
 | 
					local function ECS_ENTITY_T_HI(e: i53): i24
 | 
				
			||||||
	if e > ECS_ENTITY_MASK then
 | 
						return if e > ECS_ENTITY_MASK then (e // 0x10) % ECS_ENTITY_MASK else e
 | 
				
			||||||
		e = e // 0x10
 | 
					 | 
				
			||||||
		return e % ECS_ENTITY_MASK
 | 
					 | 
				
			||||||
	end
 | 
					 | 
				
			||||||
	return e
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<<<<<<< HEAD
 | 
					 | 
				
			||||||
local function nextEntityId(entityIndex, index: i24): i53
 | 
					 | 
				
			||||||
	local id = newId(index, 0)
 | 
					 | 
				
			||||||
=======
 | 
					 | 
				
			||||||
-- SECOND
 | 
					-- SECOND
 | 
				
			||||||
local function ECS_ENTITY_T_LO(e: i53): i24
 | 
					local function ECS_ENTITY_T_LO(e: i53): i24
 | 
				
			||||||
	if e > ECS_ENTITY_MASK then
 | 
						return if e > ECS_ENTITY_MASK then (e // 0x10) // ECS_ENTITY_MASK else e
 | 
				
			||||||
		e = e // 0x10
 | 
					 | 
				
			||||||
		return e // ECS_ENTITY_MASK
 | 
					 | 
				
			||||||
	end
 | 
					 | 
				
			||||||
	return e
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function ECS_PAIR(pred: i53, obj: i53): i53
 | 
					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
 | 
						return ECS_COMBINE(ECS_ENTITY_T_LO(obj), ECS_ENTITY_T_LO(pred)) + addFlags(--[[isPair]] true) :: i53
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function getAlive(entityIndex: EntityIndex, id: i24)
 | 
					local function getAlive(entityIndex: EntityIndex, id: i24): i53
 | 
				
			||||||
	local entityId = entityIndex.dense[id]
 | 
						return entityIndex.dense[id]
 | 
				
			||||||
	return entityId
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- ECS_PAIR_FIRST, gets the relationship target / obj / HIGH bits
 | 
					-- ECS_PAIR_FIRST, gets the relationship target / obj / HIGH bits
 | 
				
			||||||
| 
						 | 
					@ -227,7 +150,6 @@ end
 | 
				
			||||||
local function nextEntityId(entityIndex: EntityIndex, index: i24): i53
 | 
					local function nextEntityId(entityIndex: EntityIndex, index: i24): i53
 | 
				
			||||||
	--local id = ECS_COMBINE(index, 0)
 | 
						--local id = ECS_COMBINE(index, 0)
 | 
				
			||||||
	local id = index
 | 
						local id = index
 | 
				
			||||||
>>>>>>> eae51988a9e3ca45e39ebcfdbea0f9f8706bd3cd
 | 
					 | 
				
			||||||
	entityIndex.sparse[id] = {
 | 
						entityIndex.sparse[id] = {
 | 
				
			||||||
		dense = index,
 | 
							dense = index,
 | 
				
			||||||
	} :: Record
 | 
						} :: Record
 | 
				
			||||||
| 
						 | 
					@ -298,7 +220,7 @@ local function archetypeAppend(entity: number, archetype: Archetype): number
 | 
				
			||||||
	return length
 | 
						return length
 | 
				
			||||||
end
 | 
					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)
 | 
						local row = archetypeAppend(entityId, archetype)
 | 
				
			||||||
	record.archetype = archetype
 | 
						record.archetype = archetype
 | 
				
			||||||
	record.row = row
 | 
						record.row = row
 | 
				
			||||||
| 
						 | 
					@ -314,7 +236,7 @@ local function moveEntity(entityIndex: EntityIndex, entityId: i53, record: Recor
 | 
				
			||||||
	record.row = destinationRow
 | 
						record.row = destinationRow
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function hash(arr): string
 | 
					local function hash(arr: { number }): string
 | 
				
			||||||
	return table.concat(arr, "_")
 | 
						return table.concat(arr, "_")
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -327,7 +249,7 @@ local function ensureComponentRecord(
 | 
				
			||||||
	local archetypesMap = componentIndex[componentId]
 | 
						local archetypesMap = componentIndex[componentId]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if not archetypesMap then
 | 
						if not archetypesMap then
 | 
				
			||||||
		archetypesMap = ({ size = 0, cache = {} }  :: any) :: ArchetypeMap
 | 
							archetypesMap = ({ size = 0, cache = {} } :: any) :: ArchetypeMap
 | 
				
			||||||
		componentIndex[componentId] = archetypesMap
 | 
							componentIndex[componentId] = archetypesMap
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -337,7 +259,7 @@ local function ensureComponentRecord(
 | 
				
			||||||
	return archetypesMap
 | 
						return archetypesMap
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function ECS_ID_IS_WILDCARD(e)
 | 
					local function ECS_ID_IS_WILDCARD(e: i53): boolean
 | 
				
			||||||
	assert(ECS_IS_PAIR(e))
 | 
						assert(ECS_IS_PAIR(e))
 | 
				
			||||||
	local first = ECS_ENTITY_T_HI(e)
 | 
						local first = ECS_ENTITY_T_HI(e)
 | 
				
			||||||
	local second = ECS_ENTITY_T_LO(e)
 | 
						local second = ECS_ENTITY_T_LO(e)
 | 
				
			||||||
| 
						 | 
					@ -391,7 +313,8 @@ end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local World = {}
 | 
					local World = {}
 | 
				
			||||||
World.__index = World
 | 
					World.__index = World
 | 
				
			||||||
function World.new()
 | 
					
 | 
				
			||||||
 | 
					function World.new(): World
 | 
				
			||||||
	local self = setmetatable({
 | 
						local self = setmetatable({
 | 
				
			||||||
		archetypeIndex = {} :: { [string]: Archetype },
 | 
							archetypeIndex = {} :: { [string]: Archetype },
 | 
				
			||||||
		archetypes = {} :: Archetypes,
 | 
							archetypes = {} :: Archetypes,
 | 
				
			||||||
| 
						 | 
					@ -409,12 +332,13 @@ function World.new()
 | 
				
			||||||
		ROOT_ARCHETYPE = (nil :: any) :: Archetype,
 | 
							ROOT_ARCHETYPE = (nil :: any) :: Archetype,
 | 
				
			||||||
	}, World)
 | 
						}, World)
 | 
				
			||||||
	self.ROOT_ARCHETYPE = archetypeOf(self, {})
 | 
						self.ROOT_ARCHETYPE = archetypeOf(self, {})
 | 
				
			||||||
	return self
 | 
					
 | 
				
			||||||
 | 
						return table.freeze(self)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type World = typeof(World.new())
 | 
					export type World = typeof(World.new())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function World.component(world: World)
 | 
					function World.component(world: World): i53
 | 
				
			||||||
	local componentId = world.nextComponentId + 1
 | 
						local componentId = world.nextComponentId + 1
 | 
				
			||||||
	if componentId > HI_COMPONENT_ID then
 | 
						if componentId > HI_COMPONENT_ID then
 | 
				
			||||||
		-- IDs are partitioned into ranges because component IDs are not nominal,
 | 
							-- 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)
 | 
						return nextEntityId(world.entityIndex, componentId)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function World.entity(world: World)
 | 
					function World.entity(world: World): i53
 | 
				
			||||||
	local entityId = world.nextEntityId + 1
 | 
						local entityId = world.nextEntityId + 1
 | 
				
			||||||
	world.nextEntityId = entityId
 | 
						world.nextEntityId = entityId
 | 
				
			||||||
	return nextEntityId(world.entityIndex, entityId + REST)
 | 
						return nextEntityId(world.entityIndex, entityId + REST)
 | 
				
			||||||
| 
						 | 
					@ -473,6 +397,7 @@ local function archetypeDelete(world: World, id: i53)
 | 
				
			||||||
	local componentIndex = world.componentIndex
 | 
						local componentIndex = world.componentIndex
 | 
				
			||||||
	local archetypesMap = componentIndex[id]
 | 
						local archetypesMap = componentIndex[id]
 | 
				
			||||||
	local archetypes = world.archetypes
 | 
						local archetypes = world.archetypes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if archetypesMap then
 | 
						if archetypesMap then
 | 
				
			||||||
		for archetypeId in archetypesMap.cache do
 | 
							for archetypeId in archetypesMap.cache do
 | 
				
			||||||
			for _, entity in archetypes[archetypeId].entities 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)
 | 
						return archetypeOf(world, types, prev)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function findInsert(types: { i53 }, toAdd: i53)
 | 
					local function findInsert(types: { i53 }, toAdd: i53): number
 | 
				
			||||||
	for i, id in types do
 | 
						for i, id in types do
 | 
				
			||||||
		if id == toAdd then
 | 
							if id == toAdd then
 | 
				
			||||||
			return -1
 | 
								return -1
 | 
				
			||||||
| 
						 | 
					@ -546,7 +471,7 @@ local function findInsert(types: { i53 }, toAdd: i53)
 | 
				
			||||||
	return #types + 1
 | 
						return #types + 1
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function findArchetypeWith(world: World, node: Archetype, componentId: i53)
 | 
					local function findArchetypeWith(world: World, node: Archetype, componentId: i53): Archetype
 | 
				
			||||||
	local types = node.types
 | 
						local types = node.types
 | 
				
			||||||
	-- Component IDs are added incrementally, so inserting and sorting
 | 
						-- Component IDs are added incrementally, so inserting and sorting
 | 
				
			||||||
	-- them each time would be expensive. Instead this insertion sort can find the insertion
 | 
						-- 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)
 | 
						return ensureArchetype(world, destinationType, node)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function ensureEdge(archetype: Archetype, componentId: i53)
 | 
					local function ensureEdge(archetype: Archetype, componentId: i53): ArchetypeEdge
 | 
				
			||||||
	local edges = archetype.edges
 | 
						local edges = archetype.edges
 | 
				
			||||||
	local edge = edges[componentId]
 | 
						local edge = edges[componentId]
 | 
				
			||||||
	if not edge then
 | 
						if not edge then
 | 
				
			||||||
| 
						 | 
					@ -662,7 +587,7 @@ function World.remove(world: World, entityId: i53, componentId: i53)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- Keeping the function as small as possible to enable inlining
 | 
					-- 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
 | 
						local archetype = record.archetype
 | 
				
			||||||
	if not archetype then
 | 
						if not archetype then
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
| 
						 | 
					@ -677,7 +602,7 @@ local function get(record: Record, componentId: i24)
 | 
				
			||||||
	return archetype.columns[archetypeRecord][record.row]
 | 
						return archetype.columns[archetypeRecord][record.row]
 | 
				
			||||||
end
 | 
					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 id = entityId
 | 
				
			||||||
	local record = world.entityIndex.sparse[id]
 | 
						local record = world.entityIndex.sparse[id]
 | 
				
			||||||
	if not record then
 | 
						if not record then
 | 
				
			||||||
| 
						 | 
					@ -716,10 +641,10 @@ export type Query = typeof(EmptyQuery)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type CompatibleArchetype = { archetype: Archetype, indices: { number } }
 | 
					type CompatibleArchetype = { archetype: Archetype, indices: { number } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function World.query(world: World, ...): Query
 | 
					function World.query(world: World, ...: i53): Query
 | 
				
			||||||
	-- breaking?
 | 
						-- breaking?
 | 
				
			||||||
	if (...) == nil then
 | 
						if (...) == nil then
 | 
				
			||||||
		error("Missing components")
 | 
							error("  Missing components")
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local compatibleArchetypes: { CompatibleArchetype } = {}
 | 
						local compatibleArchetypes: { CompatibleArchetype } = {}
 | 
				
			||||||
| 
						 | 
					@ -772,7 +697,7 @@ function World.query(world: World, ...): Query
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local lastArchetype = 1
 | 
						local lastArchetype = 1
 | 
				
			||||||
 	local compatibleArchetype: CompatibleArchetype = compatibleArchetypes[lastArchetype]
 | 
						local compatibleArchetype: CompatibleArchetype = compatibleArchetypes[lastArchetype]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if not compatibleArchetype then
 | 
						if not compatibleArchetype then
 | 
				
			||||||
		return EmptyQuery
 | 
							return EmptyQuery
 | 
				
			||||||
| 
						 | 
					@ -785,7 +710,7 @@ function World.query(world: World, ...): Query
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local i = 1
 | 
						local i = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local function queryNext() 
 | 
						local function queryNext(): ...any
 | 
				
			||||||
		local archetype = compatibleArchetype.archetype
 | 
							local archetype = compatibleArchetype.archetype
 | 
				
			||||||
		local entityId = archetype.entities[i]
 | 
							local entityId = archetype.entities[i]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -801,7 +726,7 @@ function World.query(world: World, ...): Query
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		local row = i
 | 
							local row = i
 | 
				
			||||||
		i+=1
 | 
							i += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		local columns = archetype.columns
 | 
							local columns = archetype.columns
 | 
				
			||||||
		local tr = compatibleArchetype.indices
 | 
							local tr = compatibleArchetype.indices
 | 
				
			||||||
| 
						 | 
					@ -857,15 +782,15 @@ function World.query(world: World, ...): Query
 | 
				
			||||||
		return entityId, unpack(queryOutput :: any, 1, queryLength)
 | 
							return entityId, unpack(queryOutput :: any, 1, queryLength)
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function preparedQuery:__iter()
 | 
						function preparedQuery:__iter(): () -> ...any
 | 
				
			||||||
		return queryNext
 | 
							return queryNext
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function preparedQuery:next() 
 | 
						function preparedQuery:next(): ...any
 | 
				
			||||||
		return queryNext()
 | 
							return queryNext()
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function preparedQuery:without(...)
 | 
						function preparedQuery:without(...: i53): 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].archetype
 | 
				
			||||||
| 
						 | 
					@ -895,40 +820,53 @@ function World.query(world: World, ...): Query
 | 
				
			||||||
	return setmetatable({}, preparedQuery) :: any
 | 
						return setmetatable({}, preparedQuery) :: any
 | 
				
			||||||
end
 | 
					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 dense = world.entityIndex.dense
 | 
				
			||||||
	local sparse = world.entityIndex.sparse
 | 
						local sparse = world.entityIndex.sparse
 | 
				
			||||||
	local last
 | 
						local last
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return function()
 | 
						-- new solver doesnt like the world iterator type even tho its correct
 | 
				
			||||||
		local lastEntity: number?, entityId: number = next(dense, last)
 | 
						-- so any cast here i come
 | 
				
			||||||
		if not lastEntity then 
 | 
						local iterator: WorldIterator = (
 | 
				
			||||||
			return 
 | 
							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
 | 
							end
 | 
				
			||||||
 | 
						) :: any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		last = lastEntity
 | 
						return iterator
 | 
				
			||||||
 | 
					 | 
				
			||||||
		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
 | 
					 | 
				
			||||||
end
 | 
					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
 | 
					-- __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 }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue