opus/sys/init/3.modules.lua

110 lines
2.5 KiB
Lua

local Util = require('opus.util')
local device = _G.device
local kernel = _G.kernel
local os = _G.os
local containers = {
manipulator = true,
neuralInterface = true,
}
local cache = { }
local function getModules(dev, side)
local list = { }
if dev and dev.listModules then
for _, module in pairs(dev.listModules()) do
list[module] = Util.shallowCopy(dev)
list[module].name = module
list[module].type = module
list[module].side = side
end
end
return list
end
-- if a device has been reattached, reuse the existing
-- table so any references to the table are retained
local function addDevice(dev, args, doQueue)
local name = args.name
if not cache[name] then
cache[name] = { }
end
device[name] = cache[name]
Util.merge(device[name], dev)
Util.merge(device[name], args)
if doQueue then
os.queueEvent('device_attach', name)
end
end
local function addContainer(v, doQueue)
-- add devices like plethora:scanner
for name, dev in pairs(getModules(v, v.side)) do
-- neural and attached modules have precedence over manipulator modules
if not device[name] or v.type ~= 'manipulator' then
addDevice(dev, { name = dev.name, type = dev.name, side = dev.side }, doQueue)
end
end
if v.getName then
pcall(function()
local name = v.getName()
if name then
if v.getInventory then
addDevice(v.getInventory(), {
name = name .. ':inventory',
type = 'inventory',
side = v.side
}, doQueue)
end
if v.getEquipment then
addDevice(v.getEquipment(), {
name = name .. ':equipment',
type = 'equipment',
side = v.side
}, doQueue)
end
if v.getEnder then
addDevice(v.getEnder(), {
name = name .. ':enderChest',
type = 'enderChest',
side = v.side
}, doQueue)
end
end
end)
end
end
for k,v in pairs(device) do
if containers[v.type] then
cache[k] = v
addContainer(v)
end
end
-- register modules as peripherals
kernel.hook('device_attach', function(_, eventData)
local name = eventData[1]
local dev = device[name]
if dev and containers[dev.type] then
-- so... basically, if you get a handle to device.neuralInterface
-- (or manipulator) - that handle will still be valid after
-- a module is removed
if cache[name] then
device[name] = cache[name]
-- TODO: cannot simply merge - need to remove
-- all functions then merge
Util.merge(device[name], dev)
else
cache[name] = dev
end
addContainer(dev, true)
end
end)