diff --git a/README.md b/README.md index ac8fc16..a642528 100644 --- a/README.md +++ b/README.md @@ -23,13 +23,13 @@ local Health = world:entity() local Damage = world:entity() local Position = world:entity() -world:add(player, Health, 100) -world:add(player, Damage, 8) -world:add(player, Position, Vector3.new(0, 5, 0)) +world:set(player, Health, 100) +world:set(player, Damage, 8) +world:set(player, Position, Vector3.new(0, 5, 0)) -world:add(opponent, Health, 100) -world:add(opponent, Damage, 21) -world:add(opponent, Position, Vector3.new(0, 5, 3)) +world:set(opponent, Health, 100) +world:set(opponent, Damage, 21) +world:set(opponent, Position, Vector3.new(0, 5, 3)) for playerId, playerPosition, health in world:query(Position, Health) do local totalDamage = 0 @@ -39,7 +39,7 @@ for playerId, playerPosition, health in world:query(Position, Health) do end end - world:add(playerId, Health, health - totalDamage) + world:set(playerId, Health, health - totalDamage) end assert(world:get(playerId, Health) == 79) @@ -47,4 +47,4 @@ assert(world:get(opponentId, Health) == 92) ``` -![Comparison](benches/image.png) \ No newline at end of file +![Comparison](image.png) \ No newline at end of file diff --git a/benches/insertion.bench.lua b/benches/insertion.bench.lua index abba6c7..3f7415a 100644 --- a/benches/insertion.bench.lua +++ b/benches/insertion.bench.lua @@ -80,14 +80,14 @@ return { for i = 1, 50 do - ecs:add(e, C1, {value = false}) - ecs:add(e, C2, {value = false}) - ecs:add(e, C3, {value = false}) - ecs:add(e, C4, {value = false}) - ecs:add(e, C5, {value = false}) - ecs:add(e, C6, {value = false}) - ecs:add(e, C7, {value = false}) - ecs:add(e, C8, {value = false}) + ecs:set(e, C1, {value = false}) + ecs:set(e, C2, {value = false}) + ecs:set(e, C3, {value = false}) + ecs:set(e, C4, {value = false}) + ecs:set(e, C5, {value = false}) + ecs:set(e, C6, {value = false}) + ecs:set(e, C7, {value = false}) + ecs:set(e, C8, {value = false}) end end diff --git a/benches/query.bench.lua b/benches/query.bench.lua index 42eeaf0..9d550e2 100644 --- a/benches/query.bench.lua +++ b/benches/query.bench.lua @@ -4,9 +4,13 @@ local ReplicatedStorage = game:GetService("ReplicatedStorage") local rgb = require(ReplicatedStorage.rgb) local Matter = require(ReplicatedStorage.DevPackages.Matter) -local jecs = require(ReplicatedStorage.Lib) +local Rewrite = require(ReplicatedStorage.rewrite) local ecr = require(ReplicatedStorage.DevPackages.ecr) local newWorld = Matter.World.new() +local world = Rewrite.World.new() +local component = Rewrite.component + +local jecs = require(ReplicatedStorage.Lib) local ecs = jecs.World.new() local A1 = Matter.component() @@ -27,14 +31,24 @@ local B6 = ecr.component() local B7 = ecr.component() local B8 = ecr.component() -local C1 = ecs:entity() -local C2 = ecs:entity() -local C3 = ecs:entity() -local C4 = ecs:entity() -local C5 = ecs:entity() -local C6 = ecs:entity() -local C7 = ecs:entity() -local C8 = ecs:entity() +local C1 = component() +local C2 = component() +local C3 = component() +local C4 = component() +local C5 = component() +local C6 = component() +local C7 = component() +local C8 = component() + +local D1 = ecs:entity() +local D2 = ecs:entity() +local D3 = ecs:entity() +local D4 = ecs:entity() +local D5 = ecs:entity() +local D6 = ecs:entity() +local D7 = ecs:entity() +local D8 = ecs:entity() + local registry2 = ecr.registry() @@ -49,57 +63,67 @@ for i = 1, N do local id = registry2.create() local combination = "" local n = newWorld:spawn() - local entity = ecs:entity() + local e = world:spawn() if flip() then combination ..= "B" registry2:set(id, B2, {value = true}) - ecs:add(entity, C2, { value = true}) - newWorld:insert(n, A2({value = true})) + world:insert(e, C2({ value = true})) + ecs:set(entity, D2, { value = true}) + newWorld:insert(n, A2({value = true})) end if flip() then combination ..= "C" registry2:set(id, B3, {value = true}) - ecs:add(entity, C3, { value = true}) + world:insert(e, C3({ value = true})) + ecs:set(entity, D3, { value = true}) newWorld:insert(n, A3({value = true})) end if flip() then combination ..= "D" registry2:set(id, B4, {value = true}) - ecs:add(entity, C4, { value = true}) + world:insert(e, C4({ value = true})) + ecs:set(entity, D4, { value = true}) newWorld:insert(n, A4({value = true})) end if flip() then combination ..= "E" registry2:set(id, B5, {value = true}) - ecs:add(entity, C5, { value = true}) + world:insert(e, C5({value = true})) + ecs:set(entity, D5, { value = true}) newWorld:insert(n, A5({value = true})) end if flip() then combination ..= "F" registry2:set(id, B6, {value = true}) - ecs:add(entity, C6, { value = true}) + world:insert(e, C6({value = true})) + ecs:set(entity, D6, { value = true}) newWorld:insert(n, A6({value = true})) end if flip() then combination ..= "G" registry2:set(id, B7, {value = true}) - ecs:add(entity, C7, { value = true}) + world:insert(e, C7{ value = true}) + ecs:set(entity, D7, { value = true}) + newWorld:insert(n, A7({value = true})) end if flip() then combination ..= "H" registry2:set(id, B8, {value = true}) - ecs:add(entity, C8, { value = true}) - newWorld:insert(n, A8({value = true})) + world:insert(e, C8{ value = true}) + newWorld:insert(n, A8({value = true})) + ecs:set(entity, D8, { value = true}) + end if #combination == 7 then combination = "A" .. combination common += 1 registry2:set(id, B1, {value = true}) - ecs:add(entity, C1, { value = true}) + world:insert(e, C1{ value = true}) + ecs:set(entity, D1, { value = true}) newWorld:insert(n, A1({value = true})) end @@ -135,25 +159,23 @@ return { end, Functions = { - Matter = function() - local matched = 0 - for entityId, firstComponent in newWorld:query(A1, A2, A3, A4) do - matched += 1 - end - end, - - ECR = function() local matched = 0 - for entityId, firstComponent in registry2:view(B1, B2, B3, B4) do + for entityId, firstComponent in registry2:view(B5, B6, B3, B4, B8, B7) do matched += 1 end end, + Rewrite = function() + local matched = 0 + for entityId, firstComponent in world:query(C5, C6, C3, C4, C8, C7) do + matched += 1 + end + end, Jecs = function() local matched = 0 - for entityId, firstComponent in ecs:query(C1, C2, C3, C4) do + for entityId, firstComponent in ecs:query(D5, D6, D3, D4, D8, D7) do matched += 1 end end diff --git a/lib/init.lua b/lib/init.lua index d12e83b..cfbbf0b 100644 --- a/lib/init.lua +++ b/lib/init.lua @@ -231,7 +231,7 @@ function World.ensureRecord(world: World, entityId: i53) return entityIndex[id] end -function World.add(world: World, entityId: i53, componentId: i53, data: unknown) +function World.set(world: World, entityId: i53, componentId: i53, data: unknown) local record = world:ensureRecord(entityId) local sourceArchetype = record.archetype local destinationArchetype = archetypeTraverseAdd(world, componentId, sourceArchetype) @@ -244,7 +244,6 @@ function World.add(world: World, entityId: i53, componentId: i53, data: unknown) newEntity(entityId, record, destinationArchetype) end end - local archetypeRecord = destinationArchetype.records[componentId] destinationArchetype.columns[archetypeRecord][record.row] = data end @@ -322,6 +321,11 @@ function World.archetypesWith(world: World, componentId: i53) return compatibleArchetypes end +local function noop(): any + return function() + end +end + function World.query(world: World, ...: i53): () -> (number, ...any) local compatibleArchetypes = {} local components = { ... } @@ -329,6 +333,9 @@ function World.query(world: World, ...: i53): () -> (number, ...any) local queryLength = #components local a, b, c, d, e = ... local firstArchetypeMap = world.componentIndex[components[1]] + if not firstArchetypeMap then + return noop() + end if queryLength == 1 then local function single() diff --git a/lib/init.spec.lua b/lib/init.spec.lua index 6096865..af54cf0 100644 --- a/lib/init.spec.lua +++ b/lib/init.spec.lua @@ -13,16 +13,16 @@ print("H", H) for i = 1, 256 do local entity = ecs:entity() - ecs:add(entity, A, true) - ecs:add(entity, B, true) - ecs:add(entity, C, true) - ecs:add(entity, D, true) + ecs:set(entity, A, true) + ecs:set(entity, B, true) + ecs:set(entity, C, true) + ecs:set(entity, D, true) --[[ - ecs:add(entity, E, true) - ecs:add(entity, F, true) - ecs:add(entity, G, true) - ecs:add(entity, H, true) + ecs:set(entity, E, true) + ecs:set(entity, F, true) + ecs:set(entity, G, true) + ecs:set(entity, H, true) print("end") ]] end @@ -31,19 +31,19 @@ return function() describe("World", function() it("should add component", function() local id = ecs:entity() - ecs:add(id, A, true) - ecs:add(id, B, 1) + ecs:set(id, A, true) + ecs:set(id, B, 1) local id1 = ecs:entity() - ecs:add(id1, A, "hello") + ecs:set(id1, A, "hello") expect(ecs:get(id, A)).to.equal(true) expect(ecs:get(id, B)).to.equal(1) expect(ecs:get(id1, A)).to.equal("hello") end) it("should remove component", function() local id = ecs:entity() - ecs:add(id, A, true) - ecs:add(id, B, 1000) + ecs:set(id, A, true) + ecs:set(id, B, 1000) ecs:remove(id, A, false) expect(ecs:get(id, A)).to.equal(nil) @@ -51,10 +51,10 @@ return function() it("should override component data", function() local id = ecs:entity() - ecs:add(id, A, true) + ecs:set(id, A, true) expect(ecs:get(id, A)).to.equal(true) - ecs:add(id, A, false) + ecs:set(id, A, false) expect(ecs:get(id, A)).to.equal(false) end)