mirror of
https://github.com/Keyslam-Group/Concord.git
synced 2025-08-28 08:18:29 -04:00
216 lines
5.7 KiB
Lua
216 lines
5.7 KiB
Lua
local PATH = (...):gsub('%.[^%.]+$', '')
|
|
|
|
local Entity = require(PATH..".entity")
|
|
local System = require(PATH..".system")
|
|
local Type = require(PATH..".type")
|
|
local List = require(PATH..".list")
|
|
|
|
local Instance = {}
|
|
Instance.__index = Instance
|
|
|
|
--- Creates a new Instance.
|
|
-- @return The new instance
|
|
function Instance.new()
|
|
local instance = setmetatable({
|
|
entities = List(),
|
|
systems = List(),
|
|
events = {},
|
|
removed = {},
|
|
|
|
__isInstance = true,
|
|
}, Instance)
|
|
|
|
return instance
|
|
end
|
|
|
|
--- Adds an Entity to the Instance.
|
|
-- @param e The Entity to add
|
|
-- @return self
|
|
function Instance:addEntity(e)
|
|
if not Type.isEntity(e) then
|
|
error("bad argument #1 to 'Instance:addEntity' (Entity expected, got "..type(e)..")", 2)
|
|
end
|
|
|
|
e.instances:add(self)
|
|
self.entities:add(e)
|
|
self:checkEntity(e)
|
|
|
|
return self
|
|
end
|
|
|
|
--- Checks an Entity against all the systems in the Instance.
|
|
-- @param e The Entity to check
|
|
-- @return self
|
|
function Instance:checkEntity(e)
|
|
if not Type.isEntity(e) then
|
|
error("bad argument #1 to 'Instance:checkEntity' (Entity expected, got "..type(e)..")", 2)
|
|
end
|
|
|
|
for i = 1, self.systems.size do
|
|
self.systems:get(i):__check(e)
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Marks an Entity as removed from the Instance.
|
|
-- @param e The Entity to mark
|
|
-- @return self
|
|
function Instance:removeEntity(e)
|
|
if not Type.isEntity(e) then
|
|
error("bad argument #1 to 'Instance:removeEntity' (Entity expected, got "..type(e)..")", 2)
|
|
end
|
|
|
|
self.removed[#self.removed + 1] = e
|
|
|
|
return self
|
|
end
|
|
|
|
--- Completely removes all marked Entities in the Instance.
|
|
-- @return self
|
|
function Instance:flush()
|
|
if #self.removed > 0 then
|
|
for i = 1, #self.removed do
|
|
local e = self.removed[i]
|
|
|
|
e.instances:remove(self)
|
|
self.entities:remove(e)
|
|
|
|
for i = 1, self.systems.size do
|
|
self.systems:get(i):__remove(e)
|
|
end
|
|
end
|
|
|
|
self.removed = {}
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Adds a System to the Instance.
|
|
-- @param system The System to add
|
|
-- @param eventName The Event to register to
|
|
-- @param callback The function name to call. Defaults to eventName
|
|
-- @param enabled If the system is enabled. Defaults to true
|
|
-- @return self
|
|
function Instance:addSystem(system, eventName, callback, enabled)
|
|
if not Type.isSystem(system) then
|
|
error("bad argument #1 to 'Instance:addSystem' (System expected, got "..type(system)..")", 2)
|
|
end
|
|
|
|
if system.__instance and system.__instance ~= self then
|
|
error("System already in instance '" ..tostring(system.__instance).."'")
|
|
end
|
|
|
|
if not self.systems:has(system) then
|
|
self.systems:add(system)
|
|
system.__instance = self
|
|
end
|
|
|
|
if eventName then
|
|
self.events[eventName] = self.events[eventName] or {}
|
|
|
|
local i = #self.events[eventName] + 1
|
|
self.events[eventName][i] = {
|
|
system = system,
|
|
callback = callback or eventName,
|
|
enabled = enabled == nil and true or enabled,
|
|
}
|
|
end
|
|
|
|
local e
|
|
for i = 1, self.entities.size do
|
|
e = self.entities:get(i)
|
|
|
|
self:checkEntity(e)
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Enables a System in the Instance.
|
|
-- @param system The System to enable
|
|
-- @param eventName The Event it was registered to
|
|
-- @param callback The callback it was registered with. Defaults to eventName
|
|
-- @return self
|
|
function Instance:enableSystem(system, eventName, callback)
|
|
if not Type.isSystem(system) then
|
|
error("bad argument #1 to 'Instance:enableSystem' (System expected, got "..type(system)..")", 2)
|
|
end
|
|
|
|
return self:setSystem(system, eventName, callback, true)
|
|
end
|
|
|
|
--- Disables a System in the Instance.
|
|
-- @param system The System to disable
|
|
-- @param eventName The Event it was registered to
|
|
-- @param callback The callback it was registered with. Defaults to eventName
|
|
-- @return self
|
|
function Instance:disableSystem(system, eventName, callback)
|
|
if not Type.isSystem(system) then
|
|
error("bad argument #1 to 'Instance:disableSystem' (System expected, got "..type(system)..")", 2)
|
|
end
|
|
|
|
return self:setSystem(system, eventName, callback, false)
|
|
end
|
|
|
|
--- Sets a System 'enable' in the Instance.
|
|
-- @param system The System to set
|
|
-- @param eventName The Event it was registered to
|
|
-- @param callback The callback it was registered with. Defaults to eventName
|
|
-- @param enable The state to set it to
|
|
-- @return self
|
|
function Instance:setSystem(system, eventName, callback, enable)
|
|
if not Type.isSystem(system) then
|
|
error("bad argument #1 to 'Instance:setSystem' (System expected, got "..type(system)..")", 2)
|
|
end
|
|
|
|
callback = callback or eventName
|
|
|
|
if callback then
|
|
local listeners = self.events[eventName]
|
|
|
|
if listeners then
|
|
for i = 1, #listeners do
|
|
local listener = listeners[i]
|
|
|
|
if listener.system == system and listener.callback == callback then
|
|
listener.enabled = enable
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Emits an Event in the Instance.
|
|
-- @param eventName The Event that should be emitted
|
|
-- @param ... Parameters passed to listeners
|
|
-- @return self
|
|
function Instance:emit(eventName, ...)
|
|
if not eventName or type(eventName) ~= "string" then
|
|
error("bad argument #1 to 'Instance:emit' (String expected, got "..type(eventName)..")")
|
|
end
|
|
|
|
self:flush()
|
|
|
|
local listeners = self.events[eventName]
|
|
|
|
if listeners then
|
|
for i = 1, #listeners do
|
|
local listener = listeners[i]
|
|
|
|
if listener.enabled then
|
|
listener.system[listener.callback](listener.system, ...)
|
|
end
|
|
end
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
return setmetatable(Instance, {
|
|
__call = function(_, ...) return Instance.new(...) end,
|
|
})
|