summaryrefslogtreecommitdiff
path: root/honey/ecs.lua
diff options
context:
space:
mode:
authorsanine-a <sanine.not@pm.me>2023-05-09 11:31:17 -0500
committersanine-a <sanine.not@pm.me>2023-05-09 11:31:17 -0500
commita2ae7aae8357c8c2684d85fd58b0c5a0563ebab9 (patch)
tree5050161547408c80b521c9f4708bb9f7a9d0fa71 /honey/ecs.lua
parent2a14abecaee073aef1f1966bb397d6086b2e4785 (diff)
refactor: split ecs systems into multiple files
Diffstat (limited to 'honey/ecs.lua')
-rw-r--r--honey/ecs.lua277
1 files changed, 6 insertions, 271 deletions
diff --git a/honey/ecs.lua b/honey/ecs.lua
index b0409e4..82fd877 100644
--- a/honey/ecs.lua
+++ b/honey/ecs.lua
@@ -1,274 +1,9 @@
-math.randomseed(os.time())
-
-local glm = require 'honey.glm'
-
-local module = {}
-setmetatable(module, {__index=_G})
-setfenv(1, module)
-
-
---===== EntityDb =====--
-
-
--- EntityDb is a database of entities and their associated components
--- it should be quite efficient to query for all entities with a given component, and reasonably
--- efficient to query for all components of a given entity
-
-
-EntityDb = {}
-EntityDb.__index = EntityDb
-
-
-function EntityDb.new(_)
- local self = {
- entities = {},
- components = {},
- }
- setmetatable(self, EntityDb)
- return self
-end
-setmetatable(EntityDb, {__call=EntityDb.new})
-
-
-local function serialize(tbl)
- local tostr = function(x, value)
- if type(x) == "table" then
- if x.__tostring then
- return tostring(x)
- else
- return serialize(x)
- end
- elseif type(x) == "string" then
- if value then
- return string.format("\"%s\"", x)
- else
- return x
- end
- else
- return tostring(x)
- end
- end
- local str = "{"
- for key, value in pairs(tbl) do
- if type(key) == "string" and string.match(key, "^_") then
- -- ignore keys starting with an underscore
- else
- str = str .. string.format("%s=%s,", tostr(key), tostr(value, true))
- end
- end
- str = string.sub(str, 1, -2) .. "}"
- return str
-end
-
-
--- save current database to file
-function EntityDb.save(self, filename)
- local file, err = io.open(filename, "w")
- if not file then error(err) end
-
- for entity in pairs(self.entities) do
- local components = self:queryEntity(entity)
- file:write(string.format("Entity(\"%s\", %s)\n", entity, serialize(components)))
- end
-
- file:close()
-end
-
-
--- load database from file
-function EntityDb.load(self, filename)
- print(collectgarbage("count"))
- self.entities = {}
- self.components = {}
- collectgarbage()
- print(collectgarbage("count"))
- local env = {
- Entity = function(id, components)
- self:createEntity(id)
- self:addComponents(id, components)
- end,
- Vec3 = glm.Vec3,
- Mat4 = glm.Mat4,
- }
- local f, err = loadfile(filename)
- if not f then error(err) end
- setfenv(f, env)
- f()
-end
-
-
--- check if a given entity id is legitimate
-function EntityDb.checkIsValid(self, id)
- if not self.entities[id] then
- error(string.format("invalid entity id: %s", tostring(id)))
- end
-end
-
-
-local random = math.random
-local function uuid()
- local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
- return string.gsub(template, '[xy]', function (c)
- local v = (c == 'x') and random(0, 0xf) or random(8, 0xb)
- return string.format('%x', v)
- end)
-end
-
-
--- create a new entity
-function EntityDb.createEntity(self, id)
- local id = id or uuid() -- allow inserting entities at preset ids for loading
- self.entities[id] = true
- return id
-end
-
-
--- add a component to an entity
-function EntityDb.addComponent(self, id, name, value)
- self:checkIsValid(id)
-
- -- create the relevant component table if it doesn't exist
- if not self.components[name] then
- self.components[name] = { count=0, data={} }
- end
-
- local component = self.components[name]
- component.data[id] = value
- component.count = component.count + 1
-end
-
-
--- add multiple components at once, for convenience
-function EntityDb.addComponents(self, id, components)
- for name, value in pairs(components) do
- self:addComponent(id, name, value)
- end
-end
-
-
--- create an entity with components
-function EntityDb.createEntityWithComponents(self, components)
- local id = self:createEntity()
- self:addComponents(id, components)
- return id
-end
-
-
--- get all entities with a given component
-function EntityDb.queryComponent(self, name)
- local component = self.components[name]
- if component then
- return component.data
- else
- return {}
- end
-end
-
-
--- get all components associated with an entity
-function EntityDb.queryEntity(self, id)
- self:checkIsValid(id)
- local query = {}
- for name, component in pairs(self.components) do
- query[name] = component.data[id]
- end
- return query
-end
-
-
--- get a specific component from an entity
-function EntityDb.getComponent(self, id, name)
- self:checkIsValid(id)
- return self.components[name].data[id]
-end
-
-
--- remove a component from an entity
-function EntityDb.removeComponent(self, id, name)
- self:checkIsValid(id)
- local component = self.components[name]
- if component.data[id] ~= nil then
- component.data[id] = nil
- component.count = component.count - 1
- if component.count == 0 then
- self.components[name] = nil
- end
- end
-end
-
-
--- remove an entity from the db
-function EntityDb.deleteEntity(self, id)
- self:checkIsValid(id)
- for name in pairs(self.components) do
- self:removeComponent(id, name)
- end
- self.entities[id] = nil
-end
-
-
---===== SystemDb =====--
-
-SystemDb = {}
-SystemDb.__index = SystemDb
-
-
-function SystemDb.new(_, entityDb)
- local self = {
- systems = {},
- sorted = {},
- entityDb = entityDb,
- }
- setmetatable(self, SystemDb)
- return self
-end
-setmetatable(SystemDb, {__call=SystemDb.new})
-
-
-local function systemId()
- local template = "xx:xx:xx"
- return string.gsub(template, "x", function(c)
- return string.format("%x", random(0, 0xf))
- end)
-end
-
-
-function SystemDb.addSystem(self, systemFunc, params)
- local system
- if type(systemFunc) == "table" then
- system = systemFunc
- else
- local params = params or {}
- params.db = self.entityDb
- system = systemFunc(params)
- end
-
- local id = systemId()
- self.systems[id] = system
- table.insert(self.sorted, id)
- self:sort()
- return id
-end
-
-
-function SystemDb.sort(self)
- table.sort(self.sorted, function(a, b) return (self.systems[a].priority or 100) < (self.systems[b].priority or 100) end)
-end
-
-
-function SystemDb.update(self, dt)
- for _, system in ipairs(self.sorted) do
- self.systems[system]:update(dt)
- end
-end
-
-
-function SystemDb.removeSystem(self, id)
- self.systems[id] = nil
- for i=#self.sorted,1,-1 do
- if self.sorted[i] == id then table.remove(self.sorted, i) end
- end
-end
+local module = require 'honey.ecs.ecs'
+module.collision = require 'honey.ecs.collision'
+module.node = require 'honey.ecs.node'
+module.physics = require 'honey.ecs.physics'
+module.render = require 'honey.ecs.render'
+module.script = require 'honey.ecs.script'
return module