mirror of
				https://github.com/Ukendio/jecs.git
				synced 2025-11-04 02:49:18 +00:00 
			
		
		
		
	Add OnDeleteTarget (#102)
This commit is contained in:
		
							parent
							
								
									461c3f6862
								
							
						
					
					
						commit
						6d45af93f0
					
				
					 4 changed files with 143 additions and 105 deletions
				
			
		| 
						 | 
					@ -1,6 +1,5 @@
 | 
				
			||||||
local jecs = require(game:GetService("ReplicatedStorage").ecs)
 | 
					local jecs = require(game:GetService("ReplicatedStorage").ecs)
 | 
				
			||||||
local world = require(script.world)
 | 
					local world = require(script.world)
 | 
				
			||||||
export type World = world.World
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
local std = {
 | 
					local std = {
 | 
				
			||||||
    ChangeTracker = require(script.changetracker),
 | 
					    ChangeTracker = require(script.changetracker),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
local jecs = require(game:GetService("ReplicatedStorage").ecs)
 | 
					local jecs = require(game:GetService("ReplicatedStorage").ecs)
 | 
				
			||||||
export type World = jecs.WorldShim
 | 
					export type World = jecs.t_world
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- I like the idea of only having the world be a singleton.
 | 
					-- I like the idea of only having the world be a singleton.
 | 
				
			||||||
return jecs.World.new()
 | 
					return jecs.World.new()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										243
									
								
								src/init.luau
									
									
									
									
									
								
							
							
						
						
									
										243
									
								
								src/init.luau
									
									
									
									
									
								
							| 
						 | 
					@ -16,7 +16,7 @@ type ArchetypeEdge = {
 | 
				
			||||||
	remove: Archetype,
 | 
						remove: Archetype,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Archetype = {
 | 
					export type Archetype = {
 | 
				
			||||||
	id: number,
 | 
						id: number,
 | 
				
			||||||
	edges: { [i53]: ArchetypeEdge },
 | 
						edges: { [i53]: ArchetypeEdge },
 | 
				
			||||||
	types: Ty,
 | 
						types: Ty,
 | 
				
			||||||
| 
						 | 
					@ -65,8 +65,9 @@ local EcsOnSet 				= HI_COMPONENT_ID + 3
 | 
				
			||||||
local EcsWildcard 			= HI_COMPONENT_ID + 4
 | 
					local EcsWildcard 			= HI_COMPONENT_ID + 4
 | 
				
			||||||
local EcsChildOf 			= HI_COMPONENT_ID + 5
 | 
					local EcsChildOf 			= HI_COMPONENT_ID + 5
 | 
				
			||||||
local EcsComponent  		= HI_COMPONENT_ID + 6
 | 
					local EcsComponent  		= HI_COMPONENT_ID + 6
 | 
				
			||||||
local EcsDelete             = HI_COMPONENT_ID + 7
 | 
					local EcsOnDeleteTarget     = HI_COMPONENT_ID + 7
 | 
				
			||||||
local EcsRest 				= HI_COMPONENT_ID + 8
 | 
					local EcsDelete             = HI_COMPONENT_ID + 8
 | 
				
			||||||
 | 
					local EcsRest 				= HI_COMPONENT_ID + 9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local ECS_PAIR_FLAG 		= 0x8
 | 
					local ECS_PAIR_FLAG 		= 0x8
 | 
				
			||||||
local ECS_ID_FLAGS_MASK 	= 0x10
 | 
					local ECS_ID_FLAGS_MASK 	= 0x10
 | 
				
			||||||
| 
						 | 
					@ -328,20 +329,6 @@ local function world_get_one_inline(world: World, entity: i53, id: i53)
 | 
				
			||||||
   	return archetype.columns[tr.column][record.row]
 | 
					   	return archetype.columns[tr.column][record.row]
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function world_has_one_inline(world: World, entity: i53, id: i53): boolean
 | 
					 | 
				
			||||||
   	local record = world.entityIndex.sparse[entity]
 | 
					 | 
				
			||||||
   	if not record then
 | 
					 | 
				
			||||||
  		return false
 | 
					 | 
				
			||||||
   	end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   	local archetype = record.archetype
 | 
					 | 
				
			||||||
   	if not archetype then
 | 
					 | 
				
			||||||
	   return false
 | 
					 | 
				
			||||||
   	end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return archetype.records[id] ~= nil
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
local function world_has(world: World, entity: number, ...: i53): boolean
 | 
					local function world_has(world: World, entity: number, ...: i53): boolean
 | 
				
			||||||
   	local record = world.entityIndex.sparse[entity]
 | 
					   	local record = world.entityIndex.sparse[entity]
 | 
				
			||||||
   	if not record then
 | 
					   	if not record then
 | 
				
			||||||
| 
						 | 
					@ -386,9 +373,31 @@ local function world_has_any(world: World, entity: number, ...: i53): boolean
 | 
				
			||||||
    return false
 | 
					    return false
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- TODO:
 | 
				
			||||||
 | 
					-- should have an additional `nth` parameter which selects the nth target
 | 
				
			||||||
 | 
					-- this is important when an entity can have multiple relationships with the same target
 | 
				
			||||||
 | 
					local function world_target(world: World, entity: i53, relation: i24--[[, nth: number]]): i24?
 | 
				
			||||||
 | 
						local record = world.entityIndex.sparse[entity]
 | 
				
			||||||
 | 
						local archetype = record.archetype
 | 
				
			||||||
 | 
						if not archetype then
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local idr = world.componentIndex[ECS_PAIR(relation, EcsWildcard)]
 | 
				
			||||||
 | 
						if not idr then
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local tr = idr.cache[archetype.id]
 | 
				
			||||||
 | 
						if not tr then
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ecs_pair_second(world, archetype.types[tr.column])
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function id_record_ensure(
 | 
					local function id_record_ensure(
 | 
				
			||||||
    world,
 | 
					    world: World,
 | 
				
			||||||
	id: number
 | 
						id: number
 | 
				
			||||||
): ArchetypeMap
 | 
					): ArchetypeMap
 | 
				
			||||||
    local componentIndex = world.componentIndex
 | 
					    local componentIndex = world.componentIndex
 | 
				
			||||||
| 
						 | 
					@ -397,8 +406,9 @@ local function id_record_ensure(
 | 
				
			||||||
	if not idr then
 | 
						if not idr then
 | 
				
			||||||
	    local flags = 0b0000
 | 
						    local flags = 0b0000
 | 
				
			||||||
		local relation = ECS_ENTITY_T_HI(id)
 | 
							local relation = ECS_ENTITY_T_HI(id)
 | 
				
			||||||
		if world_has_one_inline(world, relation, EcsDelete) then
 | 
							local cleanup_policy = world_target(world, relation, EcsOnDeleteTarget)
 | 
				
			||||||
		    flags = bit32.bor(flags, ECS_ID_HAS_DELETE)
 | 
							if cleanup_policy == EcsDelete then
 | 
				
			||||||
 | 
					            flags = bit32.bor(flags, ECS_ID_HAS_DELETE)
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if world_has_any(world, relation,
 | 
							if world_has_any(world, relation,
 | 
				
			||||||
| 
						 | 
					@ -429,7 +439,7 @@ local function ECS_ID_IS_WILDCARD(e: i53): boolean
 | 
				
			||||||
	return first == EcsWildcard or second == EcsWildcard
 | 
						return first == EcsWildcard or second == EcsWildcard
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function archetype_create(world: any, types: { i24 }, prev: Archetype?): Archetype
 | 
					local function archetype_create(world: World, types: { i24 }, prev: Archetype?): Archetype
 | 
				
			||||||
	local ty = hash(types)
 | 
						local ty = hash(types)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local id = world.nextArchetypeId + 1
 | 
						local id = world.nextArchetypeId + 1
 | 
				
			||||||
| 
						 | 
					@ -489,29 +499,6 @@ local function world_entity(world: World): i53
 | 
				
			||||||
	return entity_index_new_id(world.entityIndex, entityId + EcsRest)
 | 
						return entity_index_new_id(world.entityIndex, entityId + EcsRest)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- TODO:
 | 
					 | 
				
			||||||
-- should have an additional `nth` parameter which selects the nth target
 | 
					 | 
				
			||||||
-- this is important when an entity can have multiple relationships with the same target
 | 
					 | 
				
			||||||
local function world_target(world: World, entity: i53, relation: i24--[[, nth: number]]): i24?
 | 
					 | 
				
			||||||
	local record = world.entityIndex.sparse[entity]
 | 
					 | 
				
			||||||
	local archetype = record.archetype
 | 
					 | 
				
			||||||
	if not archetype then
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	local idr = world.componentIndex[ECS_PAIR(relation, EcsWildcard)]
 | 
					 | 
				
			||||||
	if not idr then
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	local tr = idr.cache[archetype.id]
 | 
					 | 
				
			||||||
	if not tr then
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ecs_pair_second(world, archetype.types[tr.column])
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
local function world_parent(world: World, entity: i53)
 | 
					local function world_parent(world: World, entity: i53)
 | 
				
			||||||
	return world_target(world, entity, EcsChildOf)
 | 
						return world_target(world, entity, EcsChildOf)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -717,25 +704,27 @@ local function world_clear(world: World, entity: i53)
 | 
				
			||||||
	entity_move(world.entityIndex, entity, record, ROOT_ARCHETYPE)
 | 
						entity_move(world.entityIndex, entity, record, ROOT_ARCHETYPE)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function archetype_fast_delete_last(world, columns,
 | 
					local function archetype_fast_delete_last(columns, column_count,
 | 
				
			||||||
    column_count, types, entity)
 | 
					    types, entity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for i, column in columns do
 | 
					    for i, column in columns do
 | 
				
			||||||
        column[column_count] = nil
 | 
					        column[column_count] = nil
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function archetype_fast_delete(world, columns,
 | 
					local function archetype_fast_delete(columns, column_count,
 | 
				
			||||||
    column_count, row, types, entity)
 | 
					    row, types, entity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for i, column in columns do
 | 
					    for i, column in columns do
 | 
				
			||||||
        column[row] = column[column_count]
 | 
					        column[row] = column[column_count]
 | 
				
			||||||
        column[column_count] = nil
 | 
					        column[column_count] = nil
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local ERROR_DELETE_PANIC = "Tried to delete entity that has (OnDelete, Panic)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function archetype_delete(world: World, archetype,
 | 
					local function archetype_delete(world: World,
 | 
				
			||||||
    row, track)
 | 
					    archetype: Archetype, row: number)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    local entityIndex = world.entityIndex
 | 
					    local entityIndex = world.entityIndex
 | 
				
			||||||
    local columns = archetype.columns
 | 
					    local columns = archetype.columns
 | 
				
			||||||
| 
						 | 
					@ -763,10 +752,10 @@ local function archetype_delete(world: World, archetype,
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if row == last then
 | 
					    if row == last then
 | 
				
			||||||
        archetype_fast_delete_last(world, columns,
 | 
					        archetype_fast_delete_last(columns,
 | 
				
			||||||
            column_count, types, delete)
 | 
					            column_count, types, delete)
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        archetype_fast_delete(world, columns, column_count,
 | 
					        archetype_fast_delete(columns, column_count,
 | 
				
			||||||
            row, types, delete)
 | 
					            row, types, delete)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -852,12 +841,12 @@ local function archetype_delete(world: World, archetype,
 | 
				
			||||||
                            -- Cascade deletions of it has Delete as component trait
 | 
					                            -- Cascade deletions of it has Delete as component trait
 | 
				
			||||||
                            world_delete(world, child)
 | 
					                            world_delete(world, child)
 | 
				
			||||||
                        end
 | 
					                        end
 | 
				
			||||||
                    end
 | 
					                    else
 | 
				
			||||||
                else
 | 
					                        local object = ECS_ENTITY_T_LO(id)
 | 
				
			||||||
                    local object = ECS_ENTITY_T_LO(id)
 | 
					                        if object == delete then
 | 
				
			||||||
                    if object == delete then
 | 
					                            for _, child in children do
 | 
				
			||||||
                        for _, child in children do
 | 
					                                world_remove(world, child, id)
 | 
				
			||||||
                            world_remove(world, child, id)
 | 
					                            end
 | 
				
			||||||
                        end
 | 
					                        end
 | 
				
			||||||
                    end
 | 
					                    end
 | 
				
			||||||
                end
 | 
					                end
 | 
				
			||||||
| 
						 | 
					@ -867,7 +856,7 @@ local function archetype_delete(world: World, archetype,
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function world_delete(world: World, entity: i53, track)
 | 
					function world_delete(world: World, entity: i53)
 | 
				
			||||||
	local entityIndex = world.entityIndex
 | 
						local entityIndex = world.entityIndex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local record = entityIndex.sparse[entity]
 | 
						local record = entityIndex.sparse[entity]
 | 
				
			||||||
| 
						 | 
					@ -881,14 +870,14 @@ function world_delete(world: World, entity: i53, track)
 | 
				
			||||||
	if archetype then
 | 
						if archetype then
 | 
				
			||||||
	    -- In the future should have a destruct mode for
 | 
						    -- In the future should have a destruct mode for
 | 
				
			||||||
	    -- deleting archetypes themselves. Maybe requires recycling
 | 
						    -- deleting archetypes themselves. Maybe requires recycling
 | 
				
			||||||
	    archetype_delete(world, archetype, row, track)
 | 
						    archetype_delete(world, archetype, row)
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    record.archetype = nil :: any
 | 
					    record.archetype = nil :: any
 | 
				
			||||||
	entityIndex.sparse[entity] = nil
 | 
						entityIndex.sparse[entity] = nil
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function world_contains(world, entity)
 | 
					local function world_contains(world: World, entity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return world.entityIndex.sparse[entity]
 | 
					    return world.entityIndex.sparse[entity]
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -930,7 +919,7 @@ do
 | 
				
			||||||
       	end
 | 
					       	end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function world_query(world, ...)
 | 
					    function world_query(world: World, ...)
 | 
				
			||||||
            -- breaking
 | 
					            -- breaking
 | 
				
			||||||
       	if (...) == nil then
 | 
					       	if (...) == nil then
 | 
				
			||||||
      		error("Missing components")
 | 
					      		error("Missing components")
 | 
				
			||||||
| 
						 | 
					@ -1418,7 +1407,7 @@ World.target = world_target
 | 
				
			||||||
World.parent = world_parent
 | 
					World.parent = world_parent
 | 
				
			||||||
World.contains = world_contains
 | 
					World.contains = world_contains
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function World.new()
 | 
					function World.new(): t_world
 | 
				
			||||||
    local self = setmetatable({
 | 
					    local self = setmetatable({
 | 
				
			||||||
        archetypeIndex = {} :: { [string]: Archetype },
 | 
					        archetypeIndex = {} :: { [string]: Archetype },
 | 
				
			||||||
        archetypes = {} :: Archetypes,
 | 
					        archetypes = {} :: Archetypes,
 | 
				
			||||||
| 
						 | 
					@ -1427,11 +1416,11 @@ function World.new()
 | 
				
			||||||
 			dense = {} :: { [i24]: i53 },
 | 
					 			dense = {} :: { [i24]: i53 },
 | 
				
			||||||
 			sparse = {} :: { [i53]: Record },
 | 
					 			sparse = {} :: { [i53]: Record },
 | 
				
			||||||
  		} :: EntityIndex,
 | 
					  		} :: EntityIndex,
 | 
				
			||||||
  		nextArchetypeId = 0,
 | 
					  		nextArchetypeId = 0 :: number,
 | 
				
			||||||
  		nextComponentId = 0,
 | 
					  		nextComponentId = 0 :: number,
 | 
				
			||||||
  		nextEntityId = 0,
 | 
					  		nextEntityId = 0 :: number,
 | 
				
			||||||
  		ROOT_ARCHETYPE = (nil :: any) :: Archetype,
 | 
					  		ROOT_ARCHETYPE = (nil :: any) :: Archetype,
 | 
				
			||||||
    }, World)
 | 
					    }, World) :: any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	self.ROOT_ARCHETYPE = archetype_create(self, {})
 | 
						self.ROOT_ARCHETYPE = archetype_create(self, {})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1440,7 +1429,8 @@ function World.new()
 | 
				
			||||||
		entity_index_new_id(self.entityIndex, i)
 | 
							entity_index_new_id(self.entityIndex, i)
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	world_add(self :: any, EcsChildOf, EcsDelete)
 | 
						world_add(self, EcsChildOf,
 | 
				
			||||||
 | 
						   ECS_PAIR(EcsOnDeleteTarget, EcsDelete))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return self
 | 
						return self
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -1464,49 +1454,97 @@ type Query<T...> = typeof(setmetatable({}, {
 | 
				
			||||||
    archetypes: () -> { Archetype },
 | 
					    archetypes: () -> { Archetype },
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type World = {
 | 
					type World = {
 | 
				
			||||||
    archetypeIndex: { [string]: Archetype },
 | 
					    archetypeIndex: { [string]: Archetype },
 | 
				
			||||||
    archetypes: Archetypes,
 | 
					    archetypes: Archetypes,
 | 
				
			||||||
    componentIndex: ComponentIndex,
 | 
					    componentIndex: ComponentIndex,
 | 
				
			||||||
    entityIndex: EntityIndex,
 | 
					    entityIndex: EntityIndex,
 | 
				
			||||||
    nextArchetypeId: number,
 | 
					    ROOT_ARCHETYPE: Archetype,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nextComponentId: number,
 | 
					    nextComponentId: number,
 | 
				
			||||||
    nextEntityId: number,
 | 
					    nextEntityId: number,
 | 
				
			||||||
    ROOT_ARCHETYPE: Archetype,
 | 
					    nextArchetypeId: number,
 | 
				
			||||||
} & {
 | 
					 | 
				
			||||||
    target: (World, entity: Entity, relation: Entity) -> Entity,
 | 
					 | 
				
			||||||
    parent: (World, entity: Entity) -> Entity,
 | 
					 | 
				
			||||||
    entity: (World) -> Entity,
 | 
					 | 
				
			||||||
    clear: (World, entity: Entity) -> (),
 | 
					 | 
				
			||||||
    delete: (World, entity: Entity) -> (),
 | 
					 | 
				
			||||||
    component: <T>(World) -> Entity<T>,
 | 
					 | 
				
			||||||
    get: (<T>(World, entity: Entity, id: Entity<T>) -> T)
 | 
					 | 
				
			||||||
        & (<A, B>(World, id: Entity, Entity<A>, Entity<B>) -> (A, B))
 | 
					 | 
				
			||||||
		& (<A, B, C>(World, id: Entity, Entity<A>, Entity<B>, Entity<C>) -> (A, B, C))
 | 
					 | 
				
			||||||
		&  <A, B, C, D>(World, id: Entity, Entity<A>, Entity<B>, Entity<C>, Entity<D>) -> (A, B, C, D),
 | 
					 | 
				
			||||||
    has: (World, entity: Entity, ...Entity) -> boolean,
 | 
					 | 
				
			||||||
    add: (World, entity: Entity, id: Entity) -> (),
 | 
					 | 
				
			||||||
    set: <T>(World, entity: Entity,
 | 
					 | 
				
			||||||
        id: Entity<T>, data: T) -> (),
 | 
					 | 
				
			||||||
    remove: (World, entity: Entity, id: Entity) -> (),
 | 
					 | 
				
			||||||
    query:
 | 
					 | 
				
			||||||
    (<A>(World, Entity<A>) -> Query<A>)
 | 
					 | 
				
			||||||
    & (<A, B>(World, Entity<A>, Entity<B>) -> Query<A, B>)
 | 
					 | 
				
			||||||
    & (<A, B, C>(World, Entity<A>, Entity<B>, Entity<C>) -> Query<A, B, C>)
 | 
					 | 
				
			||||||
    & (<A, B, C, D>(World, Entity<A>, Entity<B>, Entity<C>,
 | 
					 | 
				
			||||||
        Entity<D>) -> Query<A, B, C, D>)
 | 
					 | 
				
			||||||
    & (<A, B, C, D, E>(World, Entity<A>, Entity<B>, Entity<C>,
 | 
					 | 
				
			||||||
        Entity<D>, Entity<E>) -> Query<A, B, C, D, E>)
 | 
					 | 
				
			||||||
    & (<A, B, C, D, E, F>(World, Entity<A>, Entity<B>, Entity<C>,
 | 
					 | 
				
			||||||
        Entity<D>, Entity<E>, Entity<F>) -> Query<A, B, C, D, E, F>)
 | 
					 | 
				
			||||||
    & (<A, B, C, D, E, F, G>(World, Entity<A>, Entity<B>, Entity<C>,
 | 
					 | 
				
			||||||
        Entity<D>, Entity<E>, Entity<F>, Entity<G>) -> Query<A, B, C, D, E, F, G>)
 | 
					 | 
				
			||||||
    & (<A, B, C, D, E, F, G, H>(World, Entity<A>, Entity<B>, Entity<C>,
 | 
					 | 
				
			||||||
        Entity<D>, Entity<E>, Entity<F>, Entity<G>, Entity<H>) -> Query<A, B, C, D, E, F, G, H>)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type t_world = typeof(setmetatable(
 | 
				
			||||||
 | 
						{} :: {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							--- Creates a new entity
 | 
				
			||||||
 | 
							entity: (t_world) -> Entity,
 | 
				
			||||||
 | 
							--- Creates a new entity located in the first 256 ids.
 | 
				
			||||||
 | 
							--- These should be used for static components for fast access.
 | 
				
			||||||
 | 
							component: <T>(t_world) -> Entity<T>,
 | 
				
			||||||
 | 
							--- Gets the target of an relationship. For example, when a user calls
 | 
				
			||||||
 | 
							--- `world:target(id, ChildOf(parent))`, you will obtain the parent entity.
 | 
				
			||||||
 | 
							target: (t_world, id: Entity, relation: Entity) -> Entity?,
 | 
				
			||||||
 | 
							--- Deletes an entity and all it's related components and relationships.
 | 
				
			||||||
 | 
							delete: (t_world, id: Entity) -> (),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							--- Adds a component to the entity with no value
 | 
				
			||||||
 | 
							add: <T>(world: t_world, id: Entity, component: Entity<T>) -> (),
 | 
				
			||||||
 | 
							--- Assigns a value to a component on the given entity
 | 
				
			||||||
 | 
							set: <T>(world: World, id: Entity, component: Entity<T>, data: T) -> (),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							-- Clears an entity from the world
 | 
				
			||||||
 | 
							clear: (t_world, id: Entity) -> (),
 | 
				
			||||||
 | 
							--- Removes a component from the given entity
 | 
				
			||||||
 | 
							remove: (t_world, id: Entity, component: Entity) -> (),
 | 
				
			||||||
 | 
							--- Retrieves the value of up to 4 components. These values may be nil.
 | 
				
			||||||
 | 
							get: (<A>(t_world, id: any, Entity<A>) -> A)
 | 
				
			||||||
 | 
								& (<A, B>(t_world, id: Entity, Entity<A>, Entity<B>) -> (A, B))
 | 
				
			||||||
 | 
								& (<A, B, C>(t_world, id: Entity, Entity<A>, Entity<B>, Entity<C>) -> (A, B, C))
 | 
				
			||||||
 | 
								& <A, B, C, D>(t_world, id: Entity, Entity<A>, Entity<B>, Entity<C>, Entity<D>) -> (A, B, C, D),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							--- Searches the world for entities that match a given query
 | 
				
			||||||
 | 
							query: (<A>(t_world, Entity<A>) -> Query<A>)
 | 
				
			||||||
 | 
								& (<A, B>(t_world, Entity<A>, Entity<B>) -> Query<A, B>)
 | 
				
			||||||
 | 
								& (<A, B, C>(t_world, Entity<A>, Entity<B>, Entity<C>) -> Query<A, B, C>)
 | 
				
			||||||
 | 
								& (<A, B, C, D>(t_world, Entity<A>, Entity<B>, Entity<C>, Entity<D>) -> Query<A, B, C, D>)
 | 
				
			||||||
 | 
								& (<A, B, C, D, E>(
 | 
				
			||||||
 | 
									t_world,
 | 
				
			||||||
 | 
									Entity<A>,
 | 
				
			||||||
 | 
									Entity<B>,
 | 
				
			||||||
 | 
									Entity<C>,
 | 
				
			||||||
 | 
									Entity<D>,
 | 
				
			||||||
 | 
									Entity<E>
 | 
				
			||||||
 | 
								) -> Query<A, B, C, D, E>)
 | 
				
			||||||
 | 
								& (<A, B, C, D, E, F>(
 | 
				
			||||||
 | 
									t_world,
 | 
				
			||||||
 | 
									Entity<A>,
 | 
				
			||||||
 | 
									Entity<B>,
 | 
				
			||||||
 | 
									Entity<C>,
 | 
				
			||||||
 | 
									Entity<D>,
 | 
				
			||||||
 | 
									Entity<E>,
 | 
				
			||||||
 | 
									Entity<F>
 | 
				
			||||||
 | 
								) -> Query<A, B, C, D, E, F>)
 | 
				
			||||||
 | 
								& (<A, B, C, D, E, F, G>(
 | 
				
			||||||
 | 
									t_world,
 | 
				
			||||||
 | 
									Entity<A>,
 | 
				
			||||||
 | 
									Entity<B>,
 | 
				
			||||||
 | 
									Entity<C>,
 | 
				
			||||||
 | 
									Entity<D>,
 | 
				
			||||||
 | 
									Entity<E>,
 | 
				
			||||||
 | 
									Entity<F>,
 | 
				
			||||||
 | 
									Entity<G>
 | 
				
			||||||
 | 
								) -> Query<A, B, C, D, E, F, G>)
 | 
				
			||||||
 | 
								& (<A, B, C, D, E, F, G, H>(
 | 
				
			||||||
 | 
									t_world,
 | 
				
			||||||
 | 
									Entity<A>,
 | 
				
			||||||
 | 
									Entity<B>,
 | 
				
			||||||
 | 
									Entity<C>,
 | 
				
			||||||
 | 
									Entity<D>,
 | 
				
			||||||
 | 
									Entity<E>,
 | 
				
			||||||
 | 
									Entity<F>,
 | 
				
			||||||
 | 
									Entity<G>,
 | 
				
			||||||
 | 
									Entity<H>,
 | 
				
			||||||
 | 
									...Entity<any>
 | 
				
			||||||
 | 
								) -> Query<A, B, C, D, E, F, G, H>),
 | 
				
			||||||
 | 
						}, {}
 | 
				
			||||||
 | 
					))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return {
 | 
					return {
 | 
				
			||||||
	World = World :: { new: () -> World },
 | 
						World = World :: { new: () -> t_world },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	OnAdd = EcsOnAdd :: Entity,
 | 
						OnAdd = EcsOnAdd :: Entity,
 | 
				
			||||||
	OnRemove = EcsOnRemove :: Entity,
 | 
						OnRemove = EcsOnRemove :: Entity,
 | 
				
			||||||
| 
						 | 
					@ -1515,6 +1553,7 @@ return {
 | 
				
			||||||
	Component = EcsComponent :: Entity,
 | 
						Component = EcsComponent :: Entity,
 | 
				
			||||||
	Wildcard = EcsWildcard :: Entity,
 | 
						Wildcard = EcsWildcard :: Entity,
 | 
				
			||||||
	w = EcsWildcard :: Entity,
 | 
						w = EcsWildcard :: Entity,
 | 
				
			||||||
 | 
						OnDeleteTarget = EcsOnDeleteTarget :: Entity,
 | 
				
			||||||
	Delete = EcsDelete :: Entity,
 | 
						Delete = EcsDelete :: Entity,
 | 
				
			||||||
	Rest = EcsRest :: Entity,
 | 
						Rest = EcsRest :: Entity,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -851,7 +851,7 @@ TEST("world:delete", function()
 | 
				
			||||||
	do CASE "cycle"
 | 
						do CASE "cycle"
 | 
				
			||||||
        local world = jecs.World.new()
 | 
					        local world = jecs.World.new()
 | 
				
			||||||
        local Likes = world:component()
 | 
					        local Likes = world:component()
 | 
				
			||||||
        world:add(Likes, jecs.Delete)
 | 
					        world:add(Likes, pair(jecs.OnDeleteTarget, jecs.Delete))
 | 
				
			||||||
        local bob = world:entity()
 | 
					        local bob = world:entity()
 | 
				
			||||||
        local alice = world:entity()
 | 
					        local alice = world:entity()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue