1
0
cc-fake-peripheral/init.lua
2023-05-11 21:50:02 +03:00

222 lines
5.4 KiB
Lua

local PeripheralAPIFake = {}
PeripheralAPIFake.__index = PeripheralAPIFake
local expect = require("cc.expect").expect
local function isPeripheral(peripheral)
if type(peripheral) ~= "table" then return false end
local meta = getmetatable(peripheral)
if type(meta) ~= "table" then return false end
if meta.__name ~= "peripheral" then return false end
if type(meta.name) ~= "string" then return false end
if type(meta.type) ~= "string" then return false end
if type(meta.types) ~= "table" then return false end
for _, ty in ipairs(meta.types) do
if not meta.types[ty] then return false end
end
return true
end
-- TODO: Add descriptive error messages to asserts
local function expectPeripheral(index, peripheral)
if not isPeripheral(peripheral) then
error(("bad argument #%d (table is not a peripheral)"):format(index), 3)
end
end
--- Performs a deep clone of a table.
local function cloneTable(t)
local mt = getmetatable(t)
setmetatable(t, nil)
local cloned = {}
for k, v in pairs(t) do
if type(v) == "table" then
cloned[k] = cloneTable(v)
else
cloned[k] = v
end
end
setmetatable(t, mt)
return cloned
end
local function doesTableContain(t, value)
for _, v in pairs(t) do
if v == value then
return true
end
end
return false
end
local function getPeripheralName(peripheral)
return getmetatable(peripheral).name
end
local function getPeripheralTypes(peripheral)
return getmetatable(peripheral).types
end
function PeripheralAPIFake.new(peripherals)
expect(1, peripherals, "table", "nil")
local self = setmetatable({}, PeripheralAPIFake)
self.peripherals = {}
if peripherals then
for _, peripheral in ipairs(peripherals) do
self:addPeripehral(peripheral)
end
end
return self
end
function PeripheralAPIFake:newExternalAPI()
local api = {}
function api.call(name, method, ...)
expect(1, name, "string")
expect(2, method, "string")
local peripheral = self.peripherals[name]
if not peripheral then return end
local func = peripheral[method]
if type(func) ~= "function" then
error(("No such method %s"):format(method), 2)
end
return func(...)
end
function api.find(ty, filter)
expect(1, ty, "string")
expect(2, filter, "function", "nil")
local peripherals = {}
for name, peripheral in pairs(self.peripherals) do
local types = getPeripheralTypes(peripheral)
if doesTableContain(types, ty) then
local wrapped = api.wrap(name)
if not filter or filter(name, wrapped) then
table.insert(peripherals, wrapped)
end
end
end
return peripherals
end
function api.getMethods(name)
expect(1, name, "string")
local peripheral = self:getPeripheral(name)
if not peripheral then return end
local methods = {}
for methodName, method in pairs(peripheral) do
if type(method) == "function" then
table.insert(methods, methodName)
end
end
return methods
end
function api.getName(peripheral)
expect(1, peripheral, "table", "string")
expectPeripheral(1, peripheral)
return getPeripheralName(peripheral)
end
function api.getNames()
return self:listPeripherals()
end
function api.getType(peripheral)
expect(1, peripheral, "table", "string")
if type(peripheral) == "table" then
expectPeripheral(1, peripheral)
end
local p = self:getPeripheral(peripheral)
return table.unpack(getPeripheralTypes(p))
end
function api.hasType(peripheral, peripheral_type)
expect(1, peripheral, "table", "string")
if type(peripheral) == "table" then
expectPeripheral(1, peripheral)
end
expect(2, peripheral_type, "string")
local p = self:getPeripheral(peripheral)
if not p then return end
local types = getPeripheralTypes(peripheral)
return doesTableContain(types, peripheral_type)
end
function api.isPresent(name)
expect(1, name, "string")
return self:hasPeripheral(name)
end
function api.wrap(name)
expect(1, name, "string")
local peripheral = self.peripherals[name]
if not peripheral then return end
return cloneTable(peripheral)
end
return api
end
function PeripheralAPIFake:addPeripehral(peripheral)
expect(1, peripheral, "table")
expectPeripheral(1, peripheral)
local name = getPeripheralName(peripheral)
assert(not self.peripherals[name], "Expected peripheral name to be unique, it's not unique")
assert(not self:hasPeripheral(peripheral), "Peripheral already added to system")
self.peripherals[name] = peripheral
end
function PeripheralAPIFake:removePeripheral(peripheral)
expect(1, peripheral, "table", "string")
if type(peripheral) == "string" then
self.peripherals[peripheral] = nil
else
expectPeripheral(1, peripheral)
local name = getPeripheralName(peripheral)
self.peripherals[name] = nil
end
end
function PeripheralAPIFake:hasPeripheral(peripheral)
expect(1, peripheral, "table", "string")
return self:getPeripheral(peripheral) ~= nil
end
function PeripheralAPIFake:getPeripheral(peripheral)
expect(1, peripheral, "table", "string")
if type(peripheral) == "string" then
return self.peripherals[peripheral]
else
expectPeripheral(1, peripheral)
local name = getPeripheralName(peripheral)
return self.peripherals[name]
end
end
function PeripheralAPIFake:getPeripheralName(peripheral)
return getPeripheralName(self:getPeripheral(peripheral))
end
function PeripheralAPIFake:listPeripherals()
local names = {}
for _, peripheral in pairs(self.peripherals) do
table.insert(names, getPeripheralName(peripheral))
end
return names
end
return PeripheralAPIFake