mirror of
https://github.com/Ukendio/jecs.git
synced 2025-04-24 17:10:03 +00:00
Add iter method (#20)
This commit is contained in:
parent
7cb610b097
commit
d5414f1bc4
3 changed files with 98 additions and 1 deletions
33
lib/init.lua
33
lib/init.lua
|
@ -178,7 +178,7 @@ local World = {}
|
|||
World.__index = World
|
||||
function World.new()
|
||||
local self = setmetatable({
|
||||
archetypeIndex = {};
|
||||
archetypeIndex = {};
|
||||
archetypes = {};
|
||||
componentIndex = {};
|
||||
entityIndex = {};
|
||||
|
@ -651,6 +651,37 @@ function World.observer(world: World, ...)
|
|||
}
|
||||
end
|
||||
|
||||
function World.__iter(world: World): () -> (number?, unknown?)
|
||||
local entityIndex = world.entityIndex
|
||||
local last
|
||||
|
||||
return function()
|
||||
local entity, record = next(entityIndex, last)
|
||||
if not entity then
|
||||
return
|
||||
end
|
||||
last = entity
|
||||
|
||||
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 entity
|
||||
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 entity, entityData
|
||||
end
|
||||
end
|
||||
|
||||
return table.freeze({
|
||||
World = World;
|
||||
ON_ADD = ON_ADD;
|
||||
|
|
|
@ -299,5 +299,38 @@ return function()
|
|||
expect(world:get(id, Poison)).to.never.be.ok()
|
||||
expect(world:get(id, Health)).to.never.be.ok()
|
||||
end)
|
||||
|
||||
it("should allow iterating the whole world", function()
|
||||
local world = jecs.World.new()
|
||||
|
||||
local A, B = world:entity(), world:entity()
|
||||
|
||||
local eA = world:entity()
|
||||
world:set(eA, A, true)
|
||||
local eB = world:entity()
|
||||
world:set(eB, B, true)
|
||||
local eAB = world:entity()
|
||||
world:set(eAB, A, true)
|
||||
world:set(eAB, B, true)
|
||||
|
||||
local count = 0
|
||||
for id, data in world do
|
||||
count += 1
|
||||
if id == eA then
|
||||
expect(data[A]).to.be.ok()
|
||||
expect(data[B]).to.never.be.ok()
|
||||
elseif id == eB then
|
||||
expect(data[B]).to.be.ok()
|
||||
expect(data[A]).to.never.be.ok()
|
||||
elseif id == eAB then
|
||||
expect(data[A]).to.be.ok()
|
||||
expect(data[B]).to.be.ok()
|
||||
else
|
||||
error("unknown entity", id)
|
||||
end
|
||||
end
|
||||
|
||||
expect(count).to.equal(3)
|
||||
end)
|
||||
end)
|
||||
end
|
|
@ -110,6 +110,39 @@ TEST("world:query", function()
|
|||
CHECK(world:get(id, Health) == nil)
|
||||
end
|
||||
|
||||
do CASE "Should allow iterating the whole world"
|
||||
local world = jecs.World.new()
|
||||
|
||||
local A, B = world:entity(), world:entity()
|
||||
|
||||
local eA = world:entity()
|
||||
world:set(eA, A, true)
|
||||
local eB = world:entity()
|
||||
world:set(eB, B, true)
|
||||
local eAB = world:entity()
|
||||
world:set(eAB, A, true)
|
||||
world:set(eAB, B, true)
|
||||
|
||||
local count = 0
|
||||
for id, data in world do
|
||||
count += 1
|
||||
if id == eA then
|
||||
CHECK(data[A] == true)
|
||||
CHECK(data[B] == nil)
|
||||
elseif id == eB then
|
||||
CHECK(data[B] == true)
|
||||
CHECK(data[A] == nil)
|
||||
elseif id == eAB then
|
||||
CHECK(data[A] == true)
|
||||
CHECK(data[B] == true)
|
||||
else
|
||||
error("unknown entity", id)
|
||||
end
|
||||
end
|
||||
|
||||
CHECK(count == 3)
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
FINISH()
|
Loading…
Reference in a new issue