diff options
Diffstat (limited to 'world.lua')
-rw-r--r-- | world.lua | 119 |
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 |