This commit is contained in:
Ukendio 2024-05-21 17:46:36 +02:00
parent 09ae7794ea
commit 4375150683
4 changed files with 136 additions and 147 deletions

View file

@ -31,7 +31,7 @@ local Name = world:component()
local function parent(entity)
return world:target(entity, ChildOf)
end
local function name(entity)
local function getName(entity)
return world:get(entity, Name)
end

0
docs/api/index.md Normal file
View file

View file

@ -1,6 +0,0 @@
# Installing Jecs
To use Jecs, you will need to add the library to your project's source folder.
## Installing with Wally
Navigate over to the Wally

View file

@ -26,12 +26,11 @@ type Archetype = {
records: {},
}
type Record = {
archetype: Archetype,
row: number,
dense: i24,
componentRecord: ArchetypeMap
componentRecord: ArchetypeMap,
}
type EntityIndex = { dense: { [i24]: i53 }, sparse: { [i53]: Record } }
@ -52,7 +51,7 @@ type ArchetypeMap = {
first: ArchetypeMap,
second: ArchetypeMap,
parent: ArchetypeMap,
size: number
size: number,
}
type ComponentIndex = { [i24]: ArchetypeMap }
@ -96,7 +95,7 @@ local function addFlags(isPair: boolean)
end
local function ECS_COMBINE(source: number, target: number): i53
local e = source * 2^28 + target * ECS_ID_FLAGS_MASK
local e = source * 268435456 + target * ECS_ID_FLAGS_MASK
return e
end
@ -104,24 +103,20 @@ local function ECS_IS_PAIR(e: number)
return (e % 2 ^ 4) // FLAGS_PAIR ~= 0
end
function separate(entity: number)
local _typeFlags = entity % 0x10
entity //= ECS_ID_FLAGS_MASK
return entity // ECS_ENTITY_MASK, entity % ECS_GENERATION_MASK, _typeFlags
function separate(e: number)
local _typeFlags = e % 0x10
-- Revert to //= after highligting gets fixed
--
e = e // ECS_ID_FLAGS_MASK
return e // ECS_ENTITY_MASK, e % ECS_GENERATION_MASK, _typeFlags
end
-- HIGH 24 bits LOW 24 bits
local function ECS_GENERATION(e: i53)
e //= 0x10
e = e // 0x10
return e % ECS_GENERATION_MASK
end
-- SECOND
local function ECS_ENTITY_T_LO(e: i53)
e //= 0x10
return e // ECS_ENTITY_MASK
end
local function ECS_GENERATION_INC(e: i53)
local id, generation, flags = separate(e)
@ -129,13 +124,18 @@ local function ECS_GENERATION_INC(e: i53)
end
-- FIRST gets the high ID
local function ECS_ENTITY_T_HI(entity: i53): i24
entity //= 0x10
local first = entity % ECS_ENTITY_MASK
return first
local function ECS_ENTITY_T_HI(e: i53): i24
e = e // 0x10
return e % ECS_ENTITY_MASK
end
local function ECS_PAIR(pred: number, obj: number)
-- SECOND
local function ECS_ENTITY_T_LO(e: i53)
e = e // 0x10
return e // ECS_ENTITY_MASK
end
local function ECS_PAIR(pred: i53, obj: i53): i53
local first
local second: number = WILDCARD
@ -148,35 +148,28 @@ local function ECS_PAIR(pred: number, obj: number)
second = ECS_ENTITY_T_LO(pred)
end
return ECS_COMBINE(
ECS_ENTITY_T_LO(first), second) + addFlags(--[[isPair]] true)
return ECS_COMBINE(ECS_ENTITY_T_LO(first), second) + addFlags(--[[isPair]] true)
end
local function getAlive(entityIndex: EntityIndex, id: i24)
local entityId = entityIndex.dense[id]
local record = entityIndex.sparse[entityIndex.dense[id]]
if not record then
error(id.." is not alive")
end
return entityId
end
-- ECS_PAIR_FIRST, gets the relationship target / obj / HIGH bits
local function ECS_PAIR_RELATION(entityIndex, e)
assert(ECS_IS_PAIR(e))
return getAlive(entityIndex, ECS_ENTITY_T_HI(e))
end
-- ECS_PAIR_SECOND gets the relationship / pred / LOW bits
local function ECS_PAIR_OBJECT(entityIndex, e)
assert(ECS_IS_PAIR(e))
return getAlive(entityIndex, ECS_ENTITY_T_LO(e))
end
local function nextEntityId(entityIndex, index: i24): i53
local id = ECS_COMBINE(index, 0)
entityIndex.sparse[id] = {
dense = index
dense = index,
} :: Record
entityIndex.dense[index] = id
@ -252,7 +245,7 @@ local function newEntity(entityId: i53, record: Record, archetype: Archetype)
return record
end
local function moveEntity(entityIndex, entityId: i53, record: Record, to: Archetype)
local function moveEntity(entityIndex: EntityIndex, entityId: i53, record: Record, to: Archetype)
local sourceRow = record.row
local from = record.archetype
local destinationRow = archetypeAppend(entityId, to)
@ -265,7 +258,12 @@ local function hash(arr): string | number
return table.concat(arr, "_")
end
local function ensureComponentRecord(componentIndex: ComponentIndex, archetypeId, componentId, i): ArchetypeMap
local function ensureComponentRecord(
componentIndex: ComponentIndex,
archetypeId: number,
componentId: number,
i: number
): ArchetypeMap
local archetypesMap = componentIndex[componentId]
if not archetypesMap then
@ -286,7 +284,6 @@ local function ECS_ID_IS_WILDCARD(e)
return first == WILDCARD or second == WILDCARD
end
local function archetypeOf(world: any, types: { i24 }, prev: Archetype?): Archetype
local ty = hash(types)
@ -306,26 +303,24 @@ local function archetypeOf(world: any, types: {i24}, prev: Archetype?): Archetyp
local object = ECS_PAIR_OBJECT(world.entityIndex, componentId)
local idr_r = ECS_PAIR(relation, WILDCARD)
ensureComponentRecord(
componentIndex, id, idr_r, i)
ensureComponentRecord(componentIndex, id, idr_r, i)
records[idr_r] = i
local idr_t = ECS_PAIR(WILDCARD, object)
ensureComponentRecord(
componentIndex, id, idr_t, i)
ensureComponentRecord(componentIndex, id, idr_t, i)
records[idr_t] = i
end
columns[i] = {}
end
local archetype = {
columns = columns;
edges = {};
entities = {};
id = id;
records = records;
type = ty;
types = types;
columns = columns,
edges = {},
entities = {},
id = id,
records = records,
type = ty,
types = types,
}
world.archetypeIndex[ty] = archetype
world.archetypes[id] = archetype
@ -337,20 +332,20 @@ local World = {}
World.__index = World
function World.new()
local self = setmetatable({
archetypeIndex = {};
archetypes = {} :: Archetypes;
componentIndex = {} :: ComponentIndex;
archetypeIndex = {},
archetypes = {} :: Archetypes,
componentIndex = {} :: ComponentIndex,
entityIndex = {
dense = {},
sparse = {}
} :: EntityIndex;
sparse = {},
} :: EntityIndex,
hooks = {
[ON_ADD] = {};
};
nextArchetypeId = 0;
nextComponentId = 0;
nextEntityId = 0;
ROOT_ARCHETYPE = (nil :: any) :: Archetype;
[ON_ADD] = {},
},
nextArchetypeId = 0,
nextComponentId = 0,
nextEntityId = 0,
ROOT_ARCHETYPE = (nil :: any) :: Archetype,
}, World)
self.ROOT_ARCHETYPE = archetypeOf(self, {})
return self
@ -644,20 +639,20 @@ end
-- the less creation the better
local function actualNoOperation() end
local function noop(_self: Query, ...: i53): () -> (number, ...any)
local function noop(_self: Query, ...): () -> ()
return actualNoOperation :: any
end
local EmptyQuery = {
__iter = noop;
without = noop;
__iter = noop,
without = noop,
}
EmptyQuery.__index = EmptyQuery
setmetatable(EmptyQuery, EmptyQuery)
export type Query = typeof(EmptyQuery)
function World.query(world: World, ...: i53): Query
function World.query(world: World, ...): Query
-- breaking?
if (...) == nil then
error("Missing components")
@ -708,7 +703,7 @@ function World.query(world: World, ...: i53): Query
length += 1
compatibleArchetypes[length] = {
archetype = archetype,
indices = indices
indices = indices,
}
end
@ -857,11 +852,11 @@ function World.__iter(world: World): () -> (number?, unknown?)
end
return table.freeze({
World = World;
World = World,
OnAdd = ON_ADD;
OnRemove = ON_REMOVE;
OnSet = ON_SET;
OnAdd = ON_ADD,
OnRemove = ON_REMOVE,
OnSet = ON_SET,
Wildcard = WILDCARD,
w = WILDCARD,
Rest = REST,