mirror of
				https://github.com/Ukendio/jecs.git
				synced 2025-11-03 18:39:19 +00:00 
			
		
		
		
	Remove eagerly
This commit is contained in:
		
							parent
							
								
									037035a9a1
								
							
						
					
					
						commit
						917c951d55
					
				
					 2 changed files with 153 additions and 73 deletions
				
			
		
							
								
								
									
										127
									
								
								jecs.luau
									
									
									
									
									
								
							
							
						
						
									
										127
									
								
								jecs.luau
									
									
									
									
									
								
							| 
						 | 
					@ -54,6 +54,8 @@ export type Query<T...> = typeof(setmetatable(
 | 
				
			||||||
		archetypes: (self: Query<T...>) -> { Archetype },
 | 
							archetypes: (self: Query<T...>) -> { Archetype },
 | 
				
			||||||
		cached: (self: Query<T...>) -> Query<T...>,
 | 
							cached: (self: Query<T...>) -> Query<T...>,
 | 
				
			||||||
		ids: { Id<any> },
 | 
							ids: { Id<any> },
 | 
				
			||||||
 | 
							filter_with: { Id<any> }?,
 | 
				
			||||||
 | 
							filter_without: { Id<any> }?
 | 
				
			||||||
		-- world: World
 | 
							-- world: World
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	{} :: {
 | 
						{} :: {
 | 
				
			||||||
| 
						 | 
					@ -92,13 +94,14 @@ type archetype = {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type componentrecord = {
 | 
					type componentrecord = {
 | 
				
			||||||
 | 
						component: i53,
 | 
				
			||||||
	records: { [number]: number },
 | 
						records: { [number]: number },
 | 
				
			||||||
	counts: { [i53]: number },
 | 
						counts: { [i53]: number },
 | 
				
			||||||
	flags: number,
 | 
						flags: number,
 | 
				
			||||||
	size: number,
 | 
						size: number,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	on_add: ((entity: i53, id: i53, value: any?) -> ())?,
 | 
						on_add: ((entity: i53, id: i53, value: any, oldarchetype: archetype) -> ())?,
 | 
				
			||||||
	on_change: ((entity: i53, id: i53, value: any) -> ())?,
 | 
						on_change: ((entity: i53, id: i53, value: any, oldarchetype: archetype) -> ())?,
 | 
				
			||||||
	on_remove: ((entity: i53, id: i53) -> ())?,
 | 
						on_remove: ((entity: i53, id: i53) -> ())?,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wildcard_pairs: { [number]: componentrecord },
 | 
						wildcard_pairs: { [number]: componentrecord },
 | 
				
			||||||
| 
						 | 
					@ -166,9 +169,9 @@ export type World = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	observable: Map<Id, Map<Id, { Observer }>>,
 | 
						observable: Map<Id, Map<Id, { Observer }>>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	added: <T>(World, Entity<T>, <e>(e: Entity<e>, id: Id<T>, value: T) -> ()) -> () -> (),
 | 
						added: <T>(World, Entity<T>, <e>(e: Entity<e>, id: Id<T>, value: T, oldarchetype: Archetype) -> ()) -> () -> (),
 | 
				
			||||||
	removed: <T>(World, Entity<T>, (e: Entity, id: Id<T>) -> ()) -> () -> (),
 | 
						removed: <T>(World, Entity<T>, (e: Entity, id: Id<T>) -> ()) -> () -> (),
 | 
				
			||||||
	changed:  <T>(World, Entity<T>, <e>(e: Entity<e>, id: Id<T>, value: T) -> ()) -> () -> (),
 | 
						changed:  <T>(World, Entity<T>, <e>(e: Entity<e>, id: Id<T>, value: T, oldarchetype: Archetype) -> ()) -> () -> (),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	--- Enforce a check on entities to be created within desired range
 | 
						--- Enforce a check on entities to be created within desired range
 | 
				
			||||||
	range: (self: World, range_begin: number, range_end: number?) -> (),
 | 
						range: (self: World, range_begin: number, range_end: number?) -> (),
 | 
				
			||||||
| 
						 | 
					@ -262,8 +265,8 @@ export type ComponentRecord = {
 | 
				
			||||||
	flags: number,
 | 
						flags: number,
 | 
				
			||||||
	size: number,
 | 
						size: number,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	on_add: (<T>(entity: Entity, id: Entity<T>, value: T?) -> ())?,
 | 
						on_add: (<T>(entity: Entity, id: Entity<T>, value: T, oldarchetype: Archetype) -> ())?,
 | 
				
			||||||
	on_change: (<T>(entity: Entity, id: Entity<T>, value: T) -> ())?,
 | 
						on_change: (<T>(entity: Entity, id: Entity<T>, value: T, oldArchetype: Archetype) -> ())?,
 | 
				
			||||||
	on_remove: ((entity: Entity, id: Entity) -> ())?,
 | 
						on_remove: ((entity: Entity, id: Entity) -> ())?,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
export type ComponentIndex = Map<Id, ComponentRecord>
 | 
					export type ComponentIndex = Map<Id, ComponentRecord>
 | 
				
			||||||
| 
						 | 
					@ -924,14 +927,6 @@ local function archetype_create(world: world, id_types: { i53 }, ty, prev: i53?)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			idr_t.size += 1
 | 
								idr_t.size += 1
 | 
				
			||||||
			archetype_append_to_records(idr_t, archetype_id, columns_map, t, i, column)
 | 
								archetype_append_to_records(idr_t, archetype_id, columns_map, t, i, column)
 | 
				
			||||||
 | 
					 | 
				
			||||||
			-- Hypothetically this should only capture leaf component records
 | 
					 | 
				
			||||||
			local idr_t_wc_pairs = idr_t.wildcard_pairs
 | 
					 | 
				
			||||||
			if not idr_t_wc_pairs then
 | 
					 | 
				
			||||||
				idr_t_wc_pairs = {} :: {[i53]: componentrecord }
 | 
					 | 
				
			||||||
				idr_t.wildcard_pairs = idr_t_wc_pairs
 | 
					 | 
				
			||||||
			end
 | 
					 | 
				
			||||||
			idr_t_wc_pairs[component_id] = idr
 | 
					 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2058,6 +2053,7 @@ local function ecs_bulk_insert(world: world, entity: i53, ids: { i53 }, values:
 | 
				
			||||||
		local dst_types = ids
 | 
							local dst_types = ids
 | 
				
			||||||
		local to = archetype_ensure(world, dst_types)
 | 
							local to = archetype_ensure(world, dst_types)
 | 
				
			||||||
		new_entity(entity, r, to)
 | 
							new_entity(entity, r, to)
 | 
				
			||||||
 | 
							local ROOT_ARCHETYPE = world.ROOT_ARCHETYPE
 | 
				
			||||||
		for i, id in ids do
 | 
							for i, id in ids do
 | 
				
			||||||
			local value = values[i]
 | 
								local value = values[i]
 | 
				
			||||||
			local cdr = component_index[id]
 | 
								local cdr = component_index[id]
 | 
				
			||||||
| 
						 | 
					@ -2066,11 +2062,11 @@ local function ecs_bulk_insert(world: world, entity: i53, ids: { i53 }, values:
 | 
				
			||||||
			if value then
 | 
								if value then
 | 
				
			||||||
				r.archetype.columns_map[id][r.row] = value
 | 
									r.archetype.columns_map[id][r.row] = value
 | 
				
			||||||
				if on_add then
 | 
									if on_add then
 | 
				
			||||||
					on_add(entity, id, value :: any)
 | 
										on_add(entity, id, value, ROOT_ARCHETYPE)
 | 
				
			||||||
				end
 | 
									end
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				if on_add then
 | 
									if on_add then
 | 
				
			||||||
					on_add(entity, id)
 | 
										on_add(entity, id, nil, ROOT_ARCHETYPE)
 | 
				
			||||||
				end
 | 
									end
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
| 
						 | 
					@ -2112,10 +2108,10 @@ local function ecs_bulk_insert(world: world, entity: i53, ids: { i53 }, values:
 | 
				
			||||||
			local on_change = idr.on_change
 | 
								local on_change = idr.on_change
 | 
				
			||||||
			local hook = if set then on_change else on_add
 | 
								local hook = if set then on_change else on_add
 | 
				
			||||||
			if hook then
 | 
								if hook then
 | 
				
			||||||
				hook(entity, id, value :: any)
 | 
									hook(entity, id, value :: any, from)
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
		elseif on_add then
 | 
							elseif on_add then
 | 
				
			||||||
			on_add(entity, id)
 | 
								on_add(entity, id, nil, from)
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -2306,7 +2302,6 @@ local function world_new()
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local function inner_entity_move(
 | 
						local function inner_entity_move(
 | 
				
			||||||
		entity_index: entityindex,
 | 
					 | 
				
			||||||
		entity: i53,
 | 
							entity: i53,
 | 
				
			||||||
		record: record,
 | 
							record: record,
 | 
				
			||||||
		to: archetype
 | 
							to: archetype
 | 
				
			||||||
| 
						 | 
					@ -2380,7 +2375,7 @@ local function world_new()
 | 
				
			||||||
			-- and just set the data directly.
 | 
								-- and just set the data directly.
 | 
				
			||||||
			local on_change = idr.on_change
 | 
								local on_change = idr.on_change
 | 
				
			||||||
			if on_change then
 | 
								if on_change then
 | 
				
			||||||
				on_change(entity, id, data)
 | 
									on_change(entity, id, data, src)
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			local to: archetype
 | 
								local to: archetype
 | 
				
			||||||
| 
						 | 
					@ -2450,7 +2445,7 @@ local function world_new()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if from then
 | 
								if from then
 | 
				
			||||||
				-- If there was a previous archetype, then the entity needs to move the archetype
 | 
									-- If there was a previous archetype, then the entity needs to move the archetype
 | 
				
			||||||
				inner_entity_move(entity_index, entity, record, to)
 | 
									inner_entity_move(entity, record, to)
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				new_entity(entity, record, to)
 | 
									new_entity(entity, record, to)
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
| 
						 | 
					@ -2460,7 +2455,7 @@ local function world_new()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			local on_add = idr.on_add
 | 
								local on_add = idr.on_add
 | 
				
			||||||
			if on_add then
 | 
								if on_add then
 | 
				
			||||||
				on_add(entity, id, data)
 | 
									on_add(entity, id, data, src)
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
| 
						 | 
					@ -2470,7 +2465,6 @@ local function world_new()
 | 
				
			||||||
		entity: i53,
 | 
							entity: i53,
 | 
				
			||||||
		id: i53
 | 
							id: i53
 | 
				
			||||||
	): ()
 | 
						): ()
 | 
				
			||||||
		local entity_index = world.entity_index
 | 
					 | 
				
			||||||
		local record = entity_index_try_get_unsafe(entity :: number)
 | 
							local record = entity_index_try_get_unsafe(entity :: number)
 | 
				
			||||||
		if not record then
 | 
							if not record then
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
| 
						 | 
					@ -2549,7 +2543,7 @@ local function world_new()
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if from then
 | 
							if from then
 | 
				
			||||||
			inner_entity_move(entity_index, entity, record, to)
 | 
								inner_entity_move(entity, record, to)
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			if #to.types > 0 then
 | 
								if #to.types > 0 then
 | 
				
			||||||
				new_entity(entity, record, to)
 | 
									new_entity(entity, record, to)
 | 
				
			||||||
| 
						 | 
					@ -2559,7 +2553,7 @@ local function world_new()
 | 
				
			||||||
		local on_add = idr.on_add
 | 
							local on_add = idr.on_add
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if on_add then
 | 
							if on_add then
 | 
				
			||||||
			on_add(entity, id)
 | 
								on_add(entity, id, nil, src)
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2593,7 +2587,7 @@ local function world_new()
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	type Listener<T> = (e: i53, id: i53, value: T?) -> ()
 | 
						type Listener<T> = (e: i53, id: i53, value: T, oldarchetype: archetype) -> ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	world.added = function<T>(_: world, component: i53, fn: Listener<T>)
 | 
						world.added = function<T>(_: world, component: i53, fn: Listener<T>)
 | 
				
			||||||
		local listeners = signals.added[component]
 | 
							local listeners = signals.added[component]
 | 
				
			||||||
| 
						 | 
					@ -2601,9 +2595,9 @@ local function world_new()
 | 
				
			||||||
			listeners = {}
 | 
								listeners = {}
 | 
				
			||||||
			signals.added[component] = listeners
 | 
								signals.added[component] = listeners
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			local function on_add(entity, id, value)
 | 
								local function on_add(entity, id, value, oldarchetype)
 | 
				
			||||||
				for _, listener in listeners :: { Listener<T> } do
 | 
									for _, listener in listeners :: { Listener<T> } do
 | 
				
			||||||
					listener(entity, id, value)
 | 
										listener(entity, id, value, oldarchetype)
 | 
				
			||||||
				end
 | 
									end
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
			local existing_hook = world_get(world, component, EcsOnAdd) :: Listener<T>
 | 
								local existing_hook = world_get(world, component, EcsOnAdd) :: Listener<T>
 | 
				
			||||||
| 
						 | 
					@ -2644,9 +2638,9 @@ local function world_new()
 | 
				
			||||||
		if not listeners then
 | 
							if not listeners then
 | 
				
			||||||
			listeners = {}
 | 
								listeners = {}
 | 
				
			||||||
			signals.changed[component] = listeners
 | 
								signals.changed[component] = listeners
 | 
				
			||||||
			local function on_change(entity, id, value: any)
 | 
								local function on_change(entity, id, value, oldarchetype)
 | 
				
			||||||
				for _, listener in listeners :: { Listener<T> }  do
 | 
									for _, listener in listeners :: { Listener<T> }  do
 | 
				
			||||||
					listener(entity, id, value)
 | 
										listener(entity, id, value, oldarchetype)
 | 
				
			||||||
				end
 | 
									end
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
			local existing_hook = world_get(world, component, EcsOnChange) :: Listener<T>
 | 
								local existing_hook = world_get(world, component, EcsOnChange) :: Listener<T>
 | 
				
			||||||
| 
						 | 
					@ -2686,7 +2680,7 @@ local function world_new()
 | 
				
			||||||
			listeners = {}
 | 
								listeners = {}
 | 
				
			||||||
			signals.removed[component] = listeners
 | 
								signals.removed[component] = listeners
 | 
				
			||||||
			local function on_remove(entity, id)
 | 
								local function on_remove(entity, id)
 | 
				
			||||||
				for _, listener in listeners :: { Listener<T> } do
 | 
									for _, listener in listeners :: { (...any) -> () } do
 | 
				
			||||||
					listener(entity, id)
 | 
										listener(entity, id)
 | 
				
			||||||
				end
 | 
									end
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
| 
						 | 
					@ -2881,7 +2875,7 @@ local function world_new()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			local to = archetype_traverse_remove(world, id, record.archetype)
 | 
								local to = archetype_traverse_remove(world, id, record.archetype)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			inner_entity_move(entity_index, entity, record, to)
 | 
								inner_entity_move(entity, record, to)
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2945,7 +2939,7 @@ local function world_new()
 | 
				
			||||||
								-- this is hypothetically not that expensive of an operation anyways
 | 
													-- this is hypothetically not that expensive of an operation anyways
 | 
				
			||||||
								to = archetype_traverse_remove(world, entity, from)
 | 
													to = archetype_traverse_remove(world, entity, from)
 | 
				
			||||||
							end
 | 
												end
 | 
				
			||||||
							inner_entity_move(entity_index, e, r, to)
 | 
												inner_entity_move(e, r, to)
 | 
				
			||||||
						end
 | 
											end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						archetype_destroy(world, idr_archetype)
 | 
											archetype_destroy(world, idr_archetype)
 | 
				
			||||||
| 
						 | 
					@ -2967,53 +2961,41 @@ local function world_new()
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
		if idr_t then
 | 
							if idr_t then
 | 
				
			||||||
			for id, cr in idr_t.wildcard_pairs do
 | 
								local archetype_ids = idr_t.records
 | 
				
			||||||
				local flags = cr.flags
 | 
								for archetype_id in archetype_ids do
 | 
				
			||||||
				local flags_delete_mask = bit32.btest(flags, ECS_ID_DELETE)
 | 
									local idr_t_archetype = archetypes[archetype_id]
 | 
				
			||||||
				local on_remove = cr.on_remove
 | 
									local idr_t_types = idr_t_archetype.types
 | 
				
			||||||
				if flags_delete_mask then
 | 
									local entities = idr_t_archetype.entities
 | 
				
			||||||
					for archetype_id in cr.records do
 | 
					
 | 
				
			||||||
						local idr_t_archetype = archetypes[archetype_id]
 | 
									for _, id in idr_t_types do
 | 
				
			||||||
						local entities = idr_t_archetype.entities
 | 
										if not ECS_IS_PAIR(id) then
 | 
				
			||||||
 | 
											continue
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
										local object = entity_index_get_alive(
 | 
				
			||||||
 | 
										    entity_index, ECS_PAIR_SECOND(id))
 | 
				
			||||||
 | 
										if object ~= entity then
 | 
				
			||||||
 | 
											continue
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
										local id_record = component_index[id]
 | 
				
			||||||
 | 
										local flags = id_record.flags
 | 
				
			||||||
 | 
										local flags_delete_mask = bit32.btest(flags, ECS_ID_DELETE)
 | 
				
			||||||
 | 
										if flags_delete_mask then
 | 
				
			||||||
						for i = #entities, 1, -1 do
 | 
											for i = #entities, 1, -1 do
 | 
				
			||||||
							local child = entities[i]
 | 
												local child = entities[i]
 | 
				
			||||||
							world_delete(world, child)
 | 
												world_delete(world, child)
 | 
				
			||||||
						end
 | 
											end
 | 
				
			||||||
					end
 | 
											break
 | 
				
			||||||
				else
 | 
										else
 | 
				
			||||||
					for archetype_id in cr.records do
 | 
					 | 
				
			||||||
						local idr_t_archetype = archetypes[archetype_id]
 | 
					 | 
				
			||||||
						local entities = idr_t_archetype.entities
 | 
					 | 
				
			||||||
						-- archetype_traverse_remove is not idempotent meaning
 | 
					 | 
				
			||||||
						-- this access is actually unsafe because it can
 | 
					 | 
				
			||||||
						-- incorrectly cache an edge despite a node of the
 | 
					 | 
				
			||||||
						-- component id on the archetype does not exist. This
 | 
					 | 
				
			||||||
						-- requires careful testing to ensure correct values are
 | 
					 | 
				
			||||||
						-- being passed to the arguments.
 | 
					 | 
				
			||||||
						local to = archetype_traverse_remove(world, id, idr_t_archetype)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						for i = #entities, 1, -1 do
 | 
											for i = #entities, 1, -1 do
 | 
				
			||||||
							local e = entities[i]
 | 
												local child = entities[i]
 | 
				
			||||||
							local r = eindex_sparse_array[ECS_ID(e :: number)]
 | 
												world_remove(world, child, id)
 | 
				
			||||||
							if on_remove then
 | 
					 | 
				
			||||||
								on_remove(e, id)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
								local from = r.archetype
 | 
					 | 
				
			||||||
								if from ~= idr_t_archetype then
 | 
					 | 
				
			||||||
									-- unfortunately the on_remove hook allows a window where `e` can have changed archetype
 | 
					 | 
				
			||||||
									-- this is hypothetically not that expensive of an operation anyways
 | 
					 | 
				
			||||||
									to = archetype_traverse_remove(world, id, from)
 | 
					 | 
				
			||||||
								end
 | 
					 | 
				
			||||||
							end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							inner_entity_move(entity_index, e, r, to)
 | 
					 | 
				
			||||||
						end
 | 
											end
 | 
				
			||||||
					end
 | 
										end
 | 
				
			||||||
				end
 | 
									end
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				for archetype_id in cr.records do
 | 
								for archetype_id in archetype_ids do
 | 
				
			||||||
					archetype_destroy(world, archetypes[archetype_id])
 | 
									archetype_destroy(world, archetypes[archetype_id])
 | 
				
			||||||
				end
 | 
					 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3055,7 +3037,7 @@ local function world_new()
 | 
				
			||||||
					for i = #entities, 1, -1 do
 | 
										for i = #entities, 1, -1 do
 | 
				
			||||||
						local e = entities[i]
 | 
											local e = entities[i]
 | 
				
			||||||
						local r = entity_index_try_get_unsafe(e) :: record
 | 
											local r = entity_index_try_get_unsafe(e) :: record
 | 
				
			||||||
						inner_entity_move(entity_index, e, r, node)
 | 
											inner_entity_move(e, r, node)
 | 
				
			||||||
					end
 | 
										end
 | 
				
			||||||
				end
 | 
									end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3065,6 +3047,7 @@ local function world_new()
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		local dense = record.dense
 | 
							local dense = record.dense
 | 
				
			||||||
		local i_swap = entity_index.alive_count
 | 
							local i_swap = entity_index.alive_count
 | 
				
			||||||
		entity_index.alive_count = i_swap - 1
 | 
							entity_index.alive_count = i_swap - 1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,104 @@ type Id<T=unknown> = jecs.Id<T>
 | 
				
			||||||
local entity_visualiser = require("@tools/entity_visualiser")
 | 
					local entity_visualiser = require("@tools/entity_visualiser")
 | 
				
			||||||
local dwi = entity_visualiser.stringify
 | 
					local dwi = entity_visualiser.stringify
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SKIP()
 | 
				
			||||||
 | 
					TEST("jecs delete", function()
 | 
				
			||||||
 | 
						do CASE "delete children"
 | 
				
			||||||
 | 
							local world = jecs.world()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							local Health = world:component()
 | 
				
			||||||
 | 
							local Poison = world:component()
 | 
				
			||||||
 | 
							local FriendsWith = world:component()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							local e = world:entity()
 | 
				
			||||||
 | 
							world:set(e, Poison, 5)
 | 
				
			||||||
 | 
							world:set(e, Health, 50)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							local children = {}
 | 
				
			||||||
 | 
							for i = 1, 10 do
 | 
				
			||||||
 | 
								local child = world:entity()
 | 
				
			||||||
 | 
								world:set(child, Poison, 9999)
 | 
				
			||||||
 | 
								world:set(child, Health, 100)
 | 
				
			||||||
 | 
								world:add(child, pair(jecs.ChildOf, e))
 | 
				
			||||||
 | 
								table.insert(children, child)
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							BENCH("delete children of entity", function()
 | 
				
			||||||
 | 
								world:delete(e)
 | 
				
			||||||
 | 
							end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for i, child in children do
 | 
				
			||||||
 | 
								CHECK(not world:contains(child))
 | 
				
			||||||
 | 
								CHECK(not world:has(child, pair(jecs.ChildOf, e)))
 | 
				
			||||||
 | 
								CHECK(not world:has(child, Health))
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							e = world:entity()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							local friends = {}
 | 
				
			||||||
 | 
							for i = 1, 10 do
 | 
				
			||||||
 | 
								local friend = world:entity()
 | 
				
			||||||
 | 
								world:set(friend, Poison, 9999)
 | 
				
			||||||
 | 
								world:set(friend, Health, 100)
 | 
				
			||||||
 | 
								world:add(friend, pair(FriendsWith, e))
 | 
				
			||||||
 | 
								for j = 1, 10 do
 | 
				
			||||||
 | 
									world:add(friend, world:component())
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
								table.insert(friends, friend)
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							BENCH("remove friends of entity", function()
 | 
				
			||||||
 | 
								world:delete(e)
 | 
				
			||||||
 | 
							end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for i, friend in friends do
 | 
				
			||||||
 | 
								CHECK(not world:has(friend, pair(FriendsWith, e)))
 | 
				
			||||||
 | 
								CHECK(world:has(friend, Health))
 | 
				
			||||||
 | 
								CHECK(world:contains(friend))
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST("pepe", function()
 | 
				
			||||||
 | 
						local world = jecs.world()
 | 
				
			||||||
 | 
						local t = world:entity()
 | 
				
			||||||
 | 
						local c = world:component()
 | 
				
			||||||
 | 
						world:add(c, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local component = world:component()
 | 
				
			||||||
 | 
						local lifetime = world:component()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local tag = world:entity()
 | 
				
			||||||
 | 
						local rel1 = world:entity()
 | 
				
			||||||
 | 
						local rel2 = world:entity()
 | 
				
			||||||
 | 
						local rel3 = world:entity()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local destroyed = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						world:removed(lifetime, function(e)
 | 
				
			||||||
 | 
						    destroyed = true
 | 
				
			||||||
 | 
						end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local parent = world:entity()
 | 
				
			||||||
 | 
						world:set(parent, component, "foo")
 | 
				
			||||||
 | 
						world:add(parent, jecs.pair(rel1, component))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local other1 = world:entity()
 | 
				
			||||||
 | 
						world:add(other1, tag)
 | 
				
			||||||
 | 
						world:add(other1, jecs.pair(jecs.ChildOf, parent))
 | 
				
			||||||
 | 
						world:add(other1, jecs.pair(rel1, component))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local child = world:entity()
 | 
				
			||||||
 | 
						world:set(child, lifetime, "")
 | 
				
			||||||
 | 
						world:add(child, jecs.pair(jecs.ChildOf, parent))
 | 
				
			||||||
 | 
						world:add(child, jecs.pair(rel3, parent))
 | 
				
			||||||
 | 
						world:add(child, jecs.pair(rel2, other1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						world:delete(parent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CHECK(destroyed)
 | 
				
			||||||
 | 
						CHECK(not world:contains(child))
 | 
				
			||||||
 | 
					end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST("ardi", function()
 | 
					TEST("ardi", function()
 | 
				
			||||||
	local world = jecs.world()
 | 
						local world = jecs.world()
 | 
				
			||||||
| 
						 | 
					@ -856,7 +954,6 @@ TEST("world:delete()", function()
 | 
				
			||||||
		local world = jecs.world()
 | 
							local world = jecs.world()
 | 
				
			||||||
		local A = world:component()
 | 
							local A = world:component()
 | 
				
			||||||
		local B = world:component()
 | 
							local B = world:component()
 | 
				
			||||||
		local C = world:component()
 | 
					 | 
				
			||||||
		world:set(A, jecs.OnRemove, function(entity, id)
 | 
							world:set(A, jecs.OnRemove, function(entity, id)
 | 
				
			||||||
			world:set(entity, B, true)
 | 
								world:set(entity, B, true)
 | 
				
			||||||
		end)
 | 
							end)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue