mirror of
				https://github.com/Ukendio/jecs.git
				synced 2025-10-31 01:09:16 +00:00 
			
		
		
		
	Merge branch 'empty-query-replacement' of https://github.com/outofbearspace/jecs into empty-query-replacement
This commit is contained in:
		
						commit
						5a550c2786
					
				
					 5 changed files with 3572 additions and 11 deletions
				
			
		|  | @ -9,13 +9,16 @@ local function TITLE(title: string) | |||
| end | ||||
| 
 | ||||
| local jecs = require("../mirror/init") | ||||
| local ecs = jecs.World.new() | ||||
| 
 | ||||
| local oldMatter = require("../oldMatter") | ||||
| 
 | ||||
| local newMatter = require("../newMatter") | ||||
| type i53 = number | ||||
| 
 | ||||
| do TITLE (testkit.color.white_underline("query")) | ||||
| do TITLE (testkit.color.white_underline("Jecs query")) | ||||
|     local ecs = jecs.World.new() | ||||
|     do TITLE "one component in common" | ||||
| 
 | ||||
|         local function view_bench( | ||||
|             world: jecs.World, | ||||
|             A: i53, B: i53, C: i53, D: i53, E: i53, F: i53, G: i53, H: i53 | ||||
|  | @ -61,37 +64,37 @@ do TITLE (testkit.color.white_underline("query")) | |||
| 
 | ||||
|             if flip() then  | ||||
|                 combination ..= "B" | ||||
|                 ecs:set(entity, D2, true) | ||||
|                 ecs:set(entity, D2, {value = true}) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "C" | ||||
|                 ecs:set(entity, D3, true) | ||||
|                 ecs:set(entity, D3, { value = true }) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "D" | ||||
|                 ecs:set(entity, D4, true) | ||||
|                 ecs:set(entity, D4, { value = true}) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "E" | ||||
|                 ecs:set(entity, D5, true) | ||||
|                 ecs:set(entity, D5, { value = true}) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "F" | ||||
|                 ecs:set(entity, D6, true) | ||||
|                 ecs:set(entity, D6, {value = true}) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "G" | ||||
|                 ecs:set(entity, D7, true) | ||||
|                 ecs:set(entity, D7, { value = true}) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "H" | ||||
|                 ecs:set(entity, D8, true) | ||||
|                 ecs:set(entity, D8, {value = true}) | ||||
| 
 | ||||
|             end | ||||
| 
 | ||||
|             if #combination == 7 then  | ||||
|                 added += 1 | ||||
|                 ecs:set(entity, D1, true) | ||||
|                 ecs:set(entity, D1, { value = true}) | ||||
|             end | ||||
| 			archetypes[combination] = true | ||||
|         end | ||||
|  | @ -101,4 +104,196 @@ do TITLE (testkit.color.white_underline("query")) | |||
| 
 | ||||
|         view_bench(ecs, D1, D2, D3, D4, D5, D6, D7, D8) | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| do TITLE(testkit.color.white_underline("OldMatter query"))  | ||||
| 
 | ||||
|     local ecs = oldMatter.World.new() | ||||
|     local component = oldMatter.component | ||||
| 
 | ||||
|     do TITLE "one component in common" | ||||
|         local function view_bench( | ||||
|             world: jecs.World, | ||||
|             A: i53, B: i53, C: i53, D: i53, E: i53, F: i53, G: i53, H: i53 | ||||
|         ) | ||||
| 
 | ||||
|             BENCH("1 component", function() | ||||
|                 for _ in world:query(A) do end | ||||
|             end) | ||||
| 
 | ||||
|             BENCH("2 component", function() | ||||
|                 for _ in world:query(A, B) do end | ||||
|             end) | ||||
| 
 | ||||
|             BENCH("4 component", function() | ||||
|                 for _ in world:query(A, B, C, D) do  | ||||
|                 end | ||||
|             end) | ||||
| 
 | ||||
|             BENCH("8 component", function() | ||||
|                 for _ in world:query(A, B, C, D, E, F, G, H) do end | ||||
|             end) | ||||
|         end | ||||
| 
 | ||||
|         local D1 = component() | ||||
|         local D2 = component() | ||||
|         local D3 = component() | ||||
|         local D4 = component() | ||||
|         local D5 = component() | ||||
|         local D6 = component() | ||||
|         local D7 = component() | ||||
|         local D8 = component() | ||||
| 
 | ||||
|         local function flip()  | ||||
|             return math.random() >= 0.15 | ||||
|         end | ||||
| 
 | ||||
|         local added = 0 | ||||
| 		local archetypes = {} | ||||
|         for i = 1, 2^16-2 do  | ||||
|             local entity = ecs:spawn() | ||||
| 
 | ||||
|             local combination = "" | ||||
| 
 | ||||
|             if flip() then  | ||||
|                 combination ..= "B" | ||||
|                 ecs:insert(entity, D2({value =  true})) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "C" | ||||
|                 ecs:insert(entity, D3({value =  true})) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "D" | ||||
|                 ecs:insert(entity, D4({value =  true})) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "E" | ||||
|                 ecs:insert(entity, D5({value =  true})) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "F" | ||||
|                 ecs:insert(entity, D6({value =  true})) | ||||
| 
 | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "G" | ||||
|                 ecs:insert(entity, D7({value =  true})) | ||||
| 
 | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "H" | ||||
|                 ecs:insert(entity, D8({value =  true})) | ||||
|             end | ||||
| 
 | ||||
|             if #combination == 7 then  | ||||
|                 added += 1 | ||||
|                 ecs:insert(entity, D1({value =  true})) | ||||
| 
 | ||||
|             end | ||||
| 			archetypes[combination] = true | ||||
|         end | ||||
| 
 | ||||
| 		local a = 0 | ||||
| 		for _ in archetypes do a+= 1 end | ||||
| 
 | ||||
|         view_bench(ecs, D1, D2, D3, D4, D5, D6, D7, D8) | ||||
|     end | ||||
| 
 | ||||
| end | ||||
| 
 | ||||
| do TITLE(testkit.color.white_underline("NewMatter query"))  | ||||
| 
 | ||||
|     local ecs = newMatter.World.new() | ||||
|     local component = newMatter.component | ||||
| 
 | ||||
|     do TITLE "one component in common" | ||||
|         local function view_bench( | ||||
|             world: jecs.World, | ||||
|             A: i53, B: i53, C: i53, D: i53, E: i53, F: i53, G: i53, H: i53 | ||||
|         ) | ||||
| 
 | ||||
|             BENCH("1 component", function() | ||||
|                 for _ in world:query(A) do end | ||||
|             end) | ||||
| 
 | ||||
|             BENCH("2 component", function() | ||||
|                 for _ in world:query(A, B) do end | ||||
|             end) | ||||
| 
 | ||||
|             BENCH("4 component", function() | ||||
|                 for _ in world:query(A, B, C, D) do  | ||||
|                 end | ||||
|             end) | ||||
| 
 | ||||
|             BENCH("8 component", function() | ||||
|                 for _ in world:query(A, B, C, D, E, F, G, H) do end | ||||
|             end) | ||||
|         end | ||||
| 
 | ||||
|         local D1 = component() | ||||
|         local D2 = component() | ||||
|         local D3 = component() | ||||
|         local D4 = component() | ||||
|         local D5 = component() | ||||
|         local D6 = component() | ||||
|         local D7 = component() | ||||
|         local D8 = component() | ||||
| 
 | ||||
|         local function flip()  | ||||
|             return math.random() >= 0.15 | ||||
|         end | ||||
| 
 | ||||
|         local added = 0 | ||||
| 		local archetypes = {} | ||||
|         for i = 1, 2^16-2 do  | ||||
|             local entity = ecs:spawn() | ||||
| 
 | ||||
|             local combination = "" | ||||
| 
 | ||||
|             if flip() then  | ||||
|                 combination ..= "B" | ||||
|                 ecs:insert(entity, D2({value =  true})) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "C" | ||||
|                 ecs:insert(entity, D3({value =  true})) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "D" | ||||
|                 ecs:insert(entity, D4({value =  true})) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "E" | ||||
|                 ecs:insert(entity, D5({value =  true})) | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "F" | ||||
|                 ecs:insert(entity, D6({value =  true})) | ||||
| 
 | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "G" | ||||
|                 ecs:insert(entity, D7({value =  true})) | ||||
| 
 | ||||
|             end | ||||
|             if flip() then  | ||||
|                 combination ..= "H" | ||||
|                 ecs:insert(entity, D8({value =  true})) | ||||
|             end | ||||
| 
 | ||||
|             if #combination == 7 then  | ||||
|                 added += 1 | ||||
|                 ecs:insert(entity, D1({value =  true})) | ||||
| 
 | ||||
|             end | ||||
| 			archetypes[combination] = true | ||||
|         end | ||||
| 
 | ||||
| 		local a = 0 | ||||
| 		for _ in archetypes do a+= 1 end | ||||
| 
 | ||||
|         view_bench(ecs, D1, D2, D3, D4, D5, D6, D7, D8) | ||||
|     end | ||||
| 
 | ||||
| end | ||||
|  | @ -191,5 +191,113 @@ return function() | |||
| 			end | ||||
| 			expect(count).to.equal(1) | ||||
| 		end) | ||||
| 
 | ||||
| 		it("should query all matching entities", function() | ||||
| 
 | ||||
| 			local world = jecs.World.new() | ||||
| 			local A = world:component() | ||||
| 			local B = world:component() | ||||
| 
 | ||||
| 			local entities = {} | ||||
| 			for i = 1, N do | ||||
| 				local id = world:entity() | ||||
| 
 | ||||
| 
 | ||||
| 				world:set(id, A, true) | ||||
| 				if i > 5 then world:set(id, B, true) end | ||||
| 				entities[i] = id | ||||
| 			end | ||||
| 
 | ||||
| 			for id in world:query(A) do | ||||
| 				local i = table.find(entities, id) | ||||
| 				expect(i).to.be.ok() | ||||
| 				table.remove(entities, i) | ||||
| 			end | ||||
| 
 | ||||
| 			expect(#entities).to.equal(0) | ||||
| 		end) | ||||
| 
 | ||||
| 		it("should query all matching entities when irrelevant component is removed", function() | ||||
| 
 | ||||
| 			 | ||||
| 			local world = jecs.World.new() | ||||
| 			local A = world:component() | ||||
| 			local B = world:component() | ||||
| 	 | ||||
| 			local entities = {} | ||||
| 			for i = 1, N do | ||||
| 				local id = world:entity() | ||||
| 	 | ||||
| 				world:set(id, A, true) | ||||
| 				world:set(id, B, true) | ||||
| 				if i > 5 then world:remove(id, B, true) end | ||||
| 				entities[i] = id | ||||
| 			end | ||||
| 	 | ||||
| 			local added = 0 | ||||
| 			for id in world:query(A) do | ||||
| 				added += 1 | ||||
| 				local i = table.find(entities, id) | ||||
| 				expect(i).to.be.ok() | ||||
| 				table.remove(entities, i) | ||||
| 			end | ||||
| 	 | ||||
| 			expect(added).to.equal(N) | ||||
| 		end) | ||||
| 
 | ||||
| 		it("should query all entities without B", function()  | ||||
| 			local world = jecs.World.new() | ||||
| 			local A = world:component() | ||||
| 			local B = world:component() | ||||
| 	 | ||||
| 			local entities = {} | ||||
| 			for i = 1, N do | ||||
| 				local id = world:entity() | ||||
| 	 | ||||
| 				world:set(id, A, true) | ||||
| 				if i < 5 then | ||||
| 					entities[i] = id | ||||
| 				else | ||||
| 					world:set(id, B, true) | ||||
| 				end | ||||
| 				 | ||||
| 			end | ||||
| 	 | ||||
| 			for id in world:query(A):without(B) do | ||||
| 				local i = table.find(entities, id) | ||||
| 				expect(i).to.be.ok() | ||||
| 				table.remove(entities, i) | ||||
| 			end | ||||
| 	 | ||||
| 			expect(#entities).to.equal(0) | ||||
| 		end) | ||||
| 
 | ||||
| 		it("should allow setting components in arbitrary order", function()  | ||||
| 			local world = jecs.World.new() | ||||
| 
 | ||||
| 			local Health = world:entity() | ||||
| 			local Poison = world:component() | ||||
| 
 | ||||
| 			local id = world:entity() | ||||
| 			world:set(id, Poison, 5) | ||||
| 			world:set(id, Health, 50) | ||||
| 
 | ||||
| 			expect(world:get(id, Poison)).to.equal(5) | ||||
| 		end) | ||||
| 
 | ||||
| 		it("Should allow deleting components", function()  | ||||
| 			local world = jecs.World.new() | ||||
| 
 | ||||
| 			local Health = world:entity() | ||||
| 			local Poison = world:component() | ||||
| 
 | ||||
| 			local id = world:entity() | ||||
| 			world:set(id, Poison, 5) | ||||
| 			world:set(id, Health, 50) | ||||
| 			world:delete(id) | ||||
| 
 | ||||
| 			expect(world:get(id, Poison)).to.never.be.ok() | ||||
| 			expect(world:get(id, Health)).to.never.be.ok() | ||||
| 		end) | ||||
| 	end) | ||||
| end | ||||
							
								
								
									
										1664
									
								
								newMatter.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1664
									
								
								newMatter.lua
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										1567
									
								
								oldMatter.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1567
									
								
								oldMatter.lua
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -6,7 +6,6 @@ local TEST, CASE, CHECK, FINISH, SKIP = testkit.test() | |||
| local N = 10 | ||||
| 
 | ||||
| TEST("world:query", function()  | ||||
| 
 | ||||
|     do CASE "should query all matching entities" | ||||
| 
 | ||||
|         local world = jecs.World.new() | ||||
|  | @ -83,6 +82,34 @@ TEST("world:query", function() | |||
| 
 | ||||
|     end | ||||
| 
 | ||||
|     do CASE "should allow setting components in arbitrary order"  | ||||
|         local world = jecs.World.new() | ||||
| 
 | ||||
|         local Health = world:entity() | ||||
|         local Poison = world:component() | ||||
| 
 | ||||
|         local id = world:entity() | ||||
|         world:set(id, Poison, 5) | ||||
|         world:set(id, Health, 50) | ||||
| 
 | ||||
|         CHECK(world:get(id, Poison) == 5) | ||||
|     end | ||||
| 
 | ||||
|     do CASE "Should allow deleting components"  | ||||
|         local world = jecs.World.new() | ||||
| 
 | ||||
|         local Health = world:entity() | ||||
|         local Poison = world:component() | ||||
| 
 | ||||
|         local id = world:entity() | ||||
|         world:set(id, Poison, 5) | ||||
|         world:set(id, Health, 50) | ||||
|         world:delete(id) | ||||
| 
 | ||||
|         CHECK(world:get(id, Poison) == nil) | ||||
|         CHECK(world:get(id, Health) == nil) | ||||
|     end | ||||
| 
 | ||||
| end) | ||||
| 
 | ||||
| FINISH() | ||||
		Loading…
	
		Reference in a new issue