Some ECS cleanup with ews() rework.
This commit is contained in:
parent
109d67bea9
commit
ff2b1d0180
210
src/ecs.lua
210
src/ecs.lua
|
@ -1,10 +1,29 @@
|
||||||
local ENTITY_STORAGE = {}
|
|
||||||
local PLACEHOLDER = {}
|
|
||||||
|
|
||||||
ecs = { }
|
ecs = { }
|
||||||
|
|
||||||
|
local ALL_ENTITIES = {}
|
||||||
|
|
||||||
|
---@alias System { callback: fun(delta: number, a: any, b: any, c: any, d: any, e: any, any), shapes: {}, keys: string[], entityCache: table<any, boolean> }
|
||||||
|
|
||||||
|
---@type System[]
|
||||||
|
local SYSTEMS = {}
|
||||||
|
|
||||||
|
local PLACEHOLDER = {}
|
||||||
|
|
||||||
|
-- TODO: Add entity to any existing systems
|
||||||
function ecs.addEntity(entity)
|
function ecs.addEntity(entity)
|
||||||
ENTITY_STORAGE[entity] = true
|
ALL_ENTITIES[entity] = true
|
||||||
|
for _, system in pairs(SYSTEMS) do
|
||||||
|
if entityMatchesShapes(entity, system.shapes) then
|
||||||
|
system.entityCache[entity] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ecs.removeEntity(entity)
|
||||||
|
ALL_ENTITIES[entity] = nil
|
||||||
|
for _, system in pairs(SYSTEMS) do
|
||||||
|
system.entityCache[entity] = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return any
|
---@return any
|
||||||
|
@ -21,49 +40,15 @@ function allKeysIncluded(entity, filter)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function allFiltersMatch(entity, filters)
|
function entityMatchesShapes(entity, shapes)
|
||||||
for _, filter in pairs(filters) do
|
for _, shape in pairs(shapes) do
|
||||||
if not allKeysIncluded(entity, filter) then
|
if not allKeysIncluded(entity, shape) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
---@generic T
|
|
||||||
---@param shape T
|
|
||||||
---@return fun(): T[]
|
|
||||||
function ecs.buildEntityFilter(shape)
|
|
||||||
local filters = {shape}
|
|
||||||
return function()
|
|
||||||
-- TODO? Cache all this?
|
|
||||||
local ret = {}
|
|
||||||
for entity,_ in pairs(ENTITY_STORAGE) do
|
|
||||||
if allFiltersMatch(entity, filters) then
|
|
||||||
ret[#ret + 1] = entity;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@generic T
|
|
||||||
---@return fun(): T[]
|
|
||||||
function ecs.buildRequiredFields(...)
|
|
||||||
local filters = arg
|
|
||||||
return function()
|
|
||||||
-- TODO? Cache all this?
|
|
||||||
local ret = {}
|
|
||||||
for entity,_ in pairs(ENTITY_STORAGE) do
|
|
||||||
if allKeysIncluded(entity, filters) then
|
|
||||||
ret[#ret + 1] = entity;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- --@overload fun(tShape: `T`): fun(callback: fun(componentT: `T`))
|
|
||||||
|
|
||||||
---@generic T
|
---@generic T
|
||||||
---@generic U
|
---@generic U
|
||||||
---@generic V
|
---@generic V
|
||||||
|
@ -73,11 +58,55 @@ end
|
||||||
---@param vShape V?
|
---@param vShape V?
|
||||||
---@param wShape W?
|
---@param wShape W?
|
||||||
---@return fun(callback: fun(componentT: T, componentU: U, componentV: V, componentW: W))
|
---@return fun(callback: fun(componentT: T, componentU: U, componentV: V, componentW: W))
|
||||||
function ecs.entitiesWithShapes(tShape, uShape, vShape, wShape)
|
function ecs.entitiesHavingShapes(tShape, uShape, vShape, wShape)
|
||||||
return function()
|
return function()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Print contents of `tbl`, with indentation.
|
||||||
|
-- `indent` sets the initial level of indentation.
|
||||||
|
function tprint (tbl, indent)
|
||||||
|
if not indent then indent = 0 end
|
||||||
|
for k, v in pairs(tbl) do
|
||||||
|
formatting = string.rep(" ", indent) .. k .. ": "
|
||||||
|
if type(v) == "table" then
|
||||||
|
print(formatting)
|
||||||
|
tprint(v, indent+1)
|
||||||
|
elseif type(v) == 'boolean' then
|
||||||
|
print(formatting .. tostring(v))
|
||||||
|
else
|
||||||
|
print(formatting .. v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function addSystem(callback, keys, shapes)
|
||||||
|
SYSTEMS[#SYSTEMS + 1] = {
|
||||||
|
callback = callback,
|
||||||
|
keys = keys,
|
||||||
|
shapes = shapes,
|
||||||
|
entityCache = nil
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param deltaSeconds number
|
||||||
|
function ecs.update(deltaSeconds)
|
||||||
|
for _,system in pairs(SYSTEMS) do
|
||||||
|
if not system.entityCache then
|
||||||
|
system.entityCache = {}
|
||||||
|
for entity,_ in pairs(ALL_ENTITIES) do
|
||||||
|
if entityMatchesShapes(entity, system.shapes) then
|
||||||
|
system.entityCache[entity] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for entity,_ in pairs(system.entityCache) do
|
||||||
|
local keys = system.keys
|
||||||
|
system.callback(deltaSeconds, entity[keys[1]], entity[keys[2]], entity[keys[3]], entity[keys[4]], entity)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Returns a function that accepts a callback. This callback will receive one argument for each Shape provided.
|
--- Returns a function that accepts a callback. This callback will receive one argument for each Shape provided.
|
||||||
---
|
---
|
||||||
---@generic T
|
---@generic T
|
||||||
|
@ -89,82 +118,51 @@ end
|
||||||
---@generic W
|
---@generic W
|
||||||
---@generic WKey
|
---@generic WKey
|
||||||
---@param tShape { [TKey]: T }
|
---@param tShape { [TKey]: T }
|
||||||
---@param uShape { [UKey]: U }?
|
---@param uShape { [UKey]: U } | fun(componentT: T, any) | nil
|
||||||
---@param vShape { [VKey]: V }?
|
---@param vShape { [VKey]: V } | fun(componentT: T, componentU: U, any) | nil
|
||||||
---@param wShape { [WKey]: W }?
|
---@param wShape { [WKey]: W } | fun(componentT: T, componentU: U, componentV: V, any) | nil
|
||||||
---@return fun(callback: fun(componentT: T, componentU: U, componentV: V, componentW: W))
|
---@param finalFunc fun(componentT: T, componentU: U, componentV: V, componentW: W, any) | nil
|
||||||
function ecs.entitiesWithShapes2(tShape, uShape, vShape, wShape)
|
function ecs.entitiesWithShapes(tShape, uShape, vShape, wShape, finalFunc)
|
||||||
local filters = {tShape, uShape, vShape, wShape}
|
local maybeShapes = {tShape, uShape, vShape, wShape, finalFunc}
|
||||||
return function(callback)
|
local shapes = {}
|
||||||
-- TODO? Cache all this?
|
local callback
|
||||||
local ret = {}
|
|
||||||
for entity,_ in pairs(ENTITY_STORAGE) do
|
for _,maybeShape in pairs(maybeShapes) do
|
||||||
if allFiltersMatch(entity, filters) then
|
if type(maybeShape) == "table" then
|
||||||
callback(entity, entity, entity, entity)
|
shapes[#shapes + 1] = maybeShape
|
||||||
|
elseif type(maybeShape) == "function" then
|
||||||
|
callback = maybeShape
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return ret
|
|
||||||
|
local keys = {}
|
||||||
|
for _,shape in pairs(shapes) do
|
||||||
|
for key,_ in pairs(shape) do
|
||||||
|
keys[#keys + 1] = key
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
addSystem(callback, keys, shapes)
|
||||||
end
|
end
|
||||||
|
|
||||||
local f = ecs.field()
|
local f = ecs.field()
|
||||||
|
|
||||||
---@alias XYPair { x:number, y: number }
|
---@type { x: number, y: number }
|
||||||
|
|
||||||
---@type XYPair
|
|
||||||
local XYPair = { x = f, y = f }
|
local XYPair = { x = f, y = f }
|
||||||
|
|
||||||
local HasPosition = { position = XYPair }
|
local Position = { position = XYPair }
|
||||||
local HasVelocity = { velocity = XYPair }
|
local Velocity = { velocity = XYPair }
|
||||||
|
|
||||||
local entIt = ecs.entitiesWithShapes(HasPosition, HasVelocity)
|
local someMovable = {
|
||||||
entIt(function(hasPos, hasVel)
|
|
||||||
hasPos.position.x = hasPos.position.x + hasVel.velocity.y
|
|
||||||
end)
|
|
||||||
|
|
||||||
local entIt2 = ecs.entitiesWithShapes2(HasPosition)
|
|
||||||
entIt2(function(position, velocity)
|
|
||||||
---@type number
|
|
||||||
local num = 0
|
|
||||||
num = position.x
|
|
||||||
num = velocity.z
|
|
||||||
print(num)
|
|
||||||
end)
|
|
||||||
|
|
||||||
---@return fun(callback: fun(T))
|
|
||||||
function ecs.entitiesWithFields(...)
|
|
||||||
local filters = {...}
|
|
||||||
return function(callback)
|
|
||||||
-- TODO? Cache all this?
|
|
||||||
for entity,_ in pairs(ENTITY_STORAGE) do
|
|
||||||
if allKeysIncluded(entity, filters) then
|
|
||||||
callback(entity)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@type unknown
|
|
||||||
function ecs.shape(...)
|
|
||||||
local shape = {}
|
|
||||||
for _,incomingShape in ipairs(arg) do
|
|
||||||
for k,v in pairs(incomingShape) do
|
|
||||||
shape[k] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return shape
|
|
||||||
end
|
|
||||||
|
|
||||||
local exampleEntity = {
|
|
||||||
position = { x = 0, y = 0 },
|
position = { x = 0, y = 0 },
|
||||||
velocity = { x = 1, y = 1 }
|
velocity = { x = 2, y = 1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
ecs.addEntity(exampleEntity)
|
ecs.addEntity(someMovable)
|
||||||
|
|
||||||
---@type fun(system: fun(entity: { position: XYPair, velocity: XYPair }))
|
ecs.entitiesWithShapes(Position, Velocity, function (delta, pos, vel)
|
||||||
local forEachPosVel = ecs.entitiesWithFields('position', 'velocity')
|
print("position:")
|
||||||
|
tprint(pos, 1)
|
||||||
forEachPosVel(function(hasVelPos)
|
pos.x = pos.x + (vel.x * delta)
|
||||||
print(hasVelPos.velocity.x)
|
pos.y = pos.y + (vel.y * delta)
|
||||||
end)
|
end)
|
Loading…
Reference in New Issue