summaryrefslogtreecommitdiff
path: root/world.lua
diff options
context:
space:
mode:
Diffstat (limited to 'world.lua')
-rw-r--r--world.lua119
1 files changed, 119 insertions, 0 deletions
diff --git a/world.lua b/world.lua
new file mode 100644
index 0000000..a219589
--- /dev/null
+++ b/world.lua
@@ -0,0 +1,119 @@
+local obj_proto = {}
+local obj_mt = {__newindex = function()assert(false)end}
+
+function obj_proto:get(ct)
+ assert(ct, "component type")
+ return self.components[ct]
+end
+
+function obj_proto:all_components()
+ local k, v
+ return function()
+ k, v = next(self.components, k)
+ return v
+ end
+end
+
+function obj_proto:call(method, ...)
+ for c in self:all_components() do
+ if c[method] then
+ c[method](c, ...)
+ end
+ end
+end
+
+function obj_proto:enable()
+ self.world:registered(self, nil, true)
+ for c in self:all_components() do
+ self.world:registered(self, c.component_type, true)
+ if c.enable then c:enable() end
+ end
+end
+
+function obj_proto:disable()
+ self.world:registered(self, nil, false)
+ for c in self:all_components() do
+ self.world:registered(self, c.component_type, false)
+ if c.disable then c:disable() end
+ end
+end
+
+function obj_mt:__index(k)
+ return obj_proto[k] or self:get(k)
+end
+
+local function init_cmp(obj, c)
+ assert(not c.inited)
+ c.obj = obj
+ for _, dep in ipairs(c.deps) do
+ local ct, inst = unpack(dep)
+ assert(ct, "component type")
+ obj:require(ct, inst)
+ end
+ c:init(c.i)
+ if c.enable then c:enable() end
+ c.inited = true
+end
+
+function obj_proto:add(c)
+ assert(not self.components[c.component_type])
+ self.components[c.component_type] = c
+ init_cmp(self, c)
+ return c
+end
+
+function obj_proto:remove(ct)
+ local c = assert(self:get(ct))
+ self.world:unreg_component(c)
+ if c.disable then c:disable() end
+end
+
+function obj_proto:require(ct, instance)
+ if self:get(ct) then return end
+ return self:add(ct(instance))
+end
+
+local world_proto = {}
+local world_mt =
+ {__index = world_proto, __newindex = function()assert(false)end}
+
+local function world()
+ local w = setmetatable({objects = {}, components = {}}, world_mt)
+ return w
+end
+
+-- create an object in the world with the components specified in the arguments
+function world_proto:object(...)
+ local components = {...}
+ local o = setmetatable({world = self, components = {}}, obj_mt)
+ for _, c in ipairs(components) do
+ assert(type(c) == 'table')
+ o.components[c.component_type] = c
+ end
+ for _, c in pairs(o.components) do
+ if not c.inited then
+ init_cmp(o, c)
+ end
+ end
+ o:enable()
+ return o
+end
+
+function world_proto:registered(object, ct, is_reg)
+ if ct then
+ self.components[ct] = self.components[ct] or {}
+ self.components[ct][object] = is_reg and true or nil
+ else
+ self.objects[object] = is_reg and true or nil
+ end
+end
+
+function world_proto:iterate(ct)
+ if ct then
+ return pairs(self.components[ct] or {})
+ else
+ return pairs(self.objects)
+ end
+end
+
+return world