summaryrefslogtreecommitdiff
path: root/honey.bak/ecs.lua
diff options
context:
space:
mode:
Diffstat (limited to 'honey.bak/ecs.lua')
-rw-r--r--honey.bak/ecs.lua234
1 files changed, 234 insertions, 0 deletions
diff --git a/honey.bak/ecs.lua b/honey.bak/ecs.lua
new file mode 100644
index 0000000..0672efe
--- /dev/null
+++ b/honey.bak/ecs.lua
@@ -0,0 +1,234 @@
+local module = {}
+setmetatable(module, {__index=_G})
+setfenv(1, module)
+
+
+--===== filters =====--
+
+
+Filter = {}
+
+-- base filter creation
+function Filter.new(_, operation, tbl)
+ local self = {}
+ self.keys = {}
+ self.filters = {}
+ self.op = operation
+
+ for _, v in ipairs(tbl) do
+ if type(v) == "function" then
+ table.insert(self.filters, v)
+ elseif type(v) == "string" then
+ table.insert(self.keys, v)
+ end
+ end
+
+ return function(entity, _self)
+ local entity = _self or entity -- able to call as . or :
+ return Filter.check(self, entity)
+ end
+end
+setmetatable(Filter, {__call=Filter.new})
+
+
+-- base filter checking
+function Filter.check(self, entity)
+ local funcname = "check" .. self.op
+ return Filter[funcname](self, entity)
+end
+
+
+-- AND filter (all keys and subfilters must match)
+function Filter.AND(tbl)
+ return Filter("AND", tbl)
+end
+function Filter.checkAND(self, entity)
+ for _, subfilter in ipairs(self.filters) do
+ if not subfilter(entity) then return false end
+ end
+ for _, key in ipairs(self.keys) do
+ if entity[key] == nil then return false end
+ end
+ return true
+end
+
+
+-- OR filter (at least one key or subfilter must match)
+function Filter.OR(tbl)
+ return Filter("OR", tbl)
+end
+function Filter.checkOR(self, entity)
+ for _, subfilter in ipairs(self.filters) do
+ if subfilter(entity) then return true end
+ end
+ for _, key in ipairs(self.keys) do
+ if entity[key] ~= nil then return true end
+ end
+ return false
+end
+
+
+-- NAND filter (at least one key or subfilter must NOT match)
+function Filter.NAND(tbl)
+ return Filter("NAND", tbl)
+end
+function Filter.checkNAND(self, entity)
+ for _, subfilter in ipairs(self.filters) do
+ if not subfilter(entity) then return true end
+ end
+ for _, key in ipairs(self.keys) do
+ if entity[key] == nil then return true end
+ end
+ return false
+end
+
+
+-- NOR filter (no keys or subfilters may match)
+function Filter.NOR(tbl)
+ return Filter("NOR", tbl)
+end
+function Filter.checkNOR(self, entity)
+ for _, subfilter in ipairs(self.filters) do
+ if subfilter(entity) then return false end
+ end
+ for _, key in ipairs(self.keys) do
+ if entity[key] ~= nil then return false end
+ end
+ return true
+end
+
+
+--===== levels =====--
+
+Level = {}
+Level.__index = Level
+
+function Level.new(_)
+ local self = {}
+ self.systems = {}
+ self.entities = {}
+ self.nextId = 1
+ setmetatable(self, Level)
+ return self
+end
+setmetatable(Level, {__call=Level.new})
+
+
+function Level.getEntity(self, id)
+ return self.entities[id]
+end
+
+
+local function systemLt(a, b)
+ return (a.priority or 50) < (b.priority or 50)
+end
+function Level.addSystem(self, system)
+ assert(system.update, "systems must have an 'update' key")
+ assert(system.filter, "systems must have a 'filter' key")
+ system.entities = {}
+ system.level = self
+ table.insert(self.systems, system)
+ table.sort(self.systems, systemLt)
+ if system.setup then
+ system.setup(system)
+ end
+end
+
+
+local function addEntityToSystem(system, id, entity)
+ -- check if entity is already present
+ if system.entities[id] then return end
+
+ if system.onAddEntity then
+ system:onAddEntity(id, entity)
+ end
+ system.entities[id] = true
+end
+
+
+local function removeEntityFromSystem(system, id, entity)
+ -- check if entity is already absent
+ if not system.entities[id] then return end
+
+ if system.onRemoveEntity then
+ system:onRemoveEntity(id, entity)
+ end
+ system.entities[id] = nil
+end
+
+
+function Level.addEntity(self, entity)
+ local id = self.nextId
+ self.entities[id] = entity
+ self.nextId = id + 1
+
+ for _, system in ipairs(self.systems) do
+ if system.filter(entity) then
+ addEntityToSystem(system, id, entity)
+ end
+ end
+
+ return id
+end
+
+
+function Level.reconfigureEntity(self, id)
+ local entity = self.entities[id]
+
+ for _, system in ipairs(self.systems) do
+ if system.filter(entity) then
+ addEntityToSystem(system, id, entity)
+ else
+ removeEntityFromSystem(system, id, entity)
+ end
+ end
+end
+
+
+function Level.removeEntity(self, id)
+ local entity = self.entities[id]
+ if not entity then error("bad id: "..tostring(id)) end
+ for _, system in ipairs(self.systems) do
+ removeEntityFromSystem(system, id, entity)
+ end
+ self.entities[id] = nil
+end
+
+
+function Level.reconfigureAllEntities(self)
+ for id in ipairs(self.entities) do
+ self:reconfigureEntity(id)
+ end
+end
+
+
+function Level.update(self, dt, paused)
+ local paused = paused or false
+ for _, system in ipairs(self.systems) do
+ if (not paused) or (paused and system.nopause) then
+ if system.preUpdate then
+ system:preUpdate()
+ end
+ if system.prepareEntity then
+ for id in pairs(system.entities) do
+ local entity = self.entities[id]
+ if entity then
+ system:prepareEntity(entity)
+ end
+ end
+ end
+ for id in pairs(system.entities) do
+ local entity = self.entities[id]
+ if entity then
+ system:update(entity, dt)
+ end
+ end
+ if system.postUpdate then
+ system:postUpdate()
+ end
+ end
+ end
+end
+
+
+return module