273 lines
7.4 KiB
Plaintext
273 lines
7.4 KiB
Plaintext
--:Minify:--
|
|
local apis = ({...})[1]
|
|
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH
|
|
local fs = apis.fs
|
|
local native = apis.peripheral
|
|
local peripheral = {}
|
|
local sides = {"top", "bottom", "left", "right", "front", "back"}
|
|
|
|
function peripheral.getNames()
|
|
local results = {}
|
|
for n = 1, #sides do
|
|
local side = sides[n]
|
|
if native.isPresent(side) then
|
|
table.insert(results, side)
|
|
if native.hasType(side, "peripheral_hub") then
|
|
local remote = native.call(side, "getNamesRemote")
|
|
for _, name in ipairs(remote) do
|
|
table.insert(results, name)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return results
|
|
end
|
|
|
|
function peripheral.isPresent(name)
|
|
if native.isPresent(name) then
|
|
return true
|
|
end
|
|
|
|
for n = 1, #sides do
|
|
local side = sides[n]
|
|
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
function peripheral.getType(peripheral)
|
|
if type(peripheral) == "string" then
|
|
if native.isPresent(peripheral) then
|
|
return native.getType(peripheral)
|
|
end
|
|
for n = 1, #sides do
|
|
local side = sides[n]
|
|
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
|
|
return native.call(side, "getTypeRemote", peripheral)
|
|
end
|
|
end
|
|
return nil
|
|
else
|
|
local mt = getmetatable(peripheral)
|
|
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
|
|
error("bad argument #1 (table is not a peripheral)", 2)
|
|
end
|
|
return table.unpack(mt.types)
|
|
end
|
|
end
|
|
|
|
function peripheral.hasType(peripheral, peripheral_type)
|
|
if type(peripheral) == "string" then
|
|
if native.isPresent(peripheral) then
|
|
return native.hasType(peripheral, peripheral_type)
|
|
end
|
|
for n = 1, #sides do
|
|
local side = sides[n]
|
|
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
|
|
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
|
|
end
|
|
end
|
|
return nil
|
|
else
|
|
local mt = getmetatable(peripheral)
|
|
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
|
|
error("bad argument #1 (table is not a peripheral)", 2)
|
|
end
|
|
return mt.types[peripheral_type] ~= nil
|
|
end
|
|
end
|
|
|
|
function peripheral.getMethods(name)
|
|
if native.isPresent(name) then
|
|
return native.getMethods(name)
|
|
end
|
|
for n = 1, #sides do
|
|
local side = sides[n]
|
|
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
|
|
return native.call(side, "getMethodsRemote", name)
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function peripheral.getName(peripheral)
|
|
local mt = getmetatable(peripheral)
|
|
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
|
|
error("bad argument #1 (table is not a peripheral)", 2)
|
|
end
|
|
return mt.name
|
|
end
|
|
|
|
function peripheral.call(name, method, ...)
|
|
if native.isPresent(name) then
|
|
return native.call(name, method, ...)
|
|
end
|
|
|
|
for n = 1, #sides do
|
|
local side = sides[n]
|
|
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
|
|
return native.call(side, "callRemote", name, method, ...)
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function peripheral.wrap(name)
|
|
local methods = peripheral.getMethods(name)
|
|
if not methods then
|
|
return nil
|
|
end
|
|
|
|
local types = { peripheral.getType(name) }
|
|
for i = 1, #types do types[types[i]] = true end
|
|
local result = setmetatable({}, {
|
|
__name = "peripheral",
|
|
name = name,
|
|
type = types[1],
|
|
types = types,
|
|
})
|
|
for _, method in ipairs(methods) do
|
|
result[method] = function(...)
|
|
return peripheral.call(name, method, ...)
|
|
end
|
|
end
|
|
return result
|
|
end
|
|
|
|
function peripheral.find(ty, filter)
|
|
local results = {}
|
|
for _, name in ipairs(peripheral.getNames()) do
|
|
if peripheral.hasType(name, ty) then
|
|
local wrapped = peripheral.wrap(name)
|
|
if filter == nil or filter(name, wrapped) then
|
|
table.insert(results, wrapped)
|
|
end
|
|
end
|
|
end
|
|
return table.unpack(results)
|
|
end
|
|
|
|
local disks = {}
|
|
local internal = {}
|
|
|
|
local function norm(path)
|
|
if not path or path == "" then return "/" end
|
|
return fs.combine("/", path)
|
|
end
|
|
|
|
local function createDisk(id, basePath, readonly, periph)
|
|
basePath = norm(basePath)
|
|
|
|
local disk = {address = id, isReadOnly = function() return readonly end}
|
|
|
|
function disk:spaceUsed()
|
|
return fs.getCapacity(basePath) - fs.getFreeSpace(basePath)
|
|
end
|
|
|
|
function disk:spaceTotal() return fs.getCapacity(basePath) end
|
|
|
|
function disk:list(path)
|
|
local p = fs.combine(basePath, path)
|
|
if not fs.exists(p) or not fs.isDir(p) then
|
|
return nil, "not directory"
|
|
end
|
|
return fs.list(p)
|
|
end
|
|
|
|
function disk:fileExists(path)
|
|
local p = fs.combine(basePath, path)
|
|
return fs.exists(p) and not fs.isDir(p)
|
|
end
|
|
|
|
function disk:directoryExists(path)
|
|
local p = fs.combine(basePath, path)
|
|
return fs.exists(p) and fs.isDir(p)
|
|
end
|
|
|
|
function disk:type(path)
|
|
local p = fs.combine(basePath, path)
|
|
if not fs.exists(p) then
|
|
return nil
|
|
elseif fs.isDir(p) then
|
|
return "directory"
|
|
else
|
|
return "file"
|
|
end
|
|
end
|
|
|
|
function disk:makeDirectory(path)
|
|
local p = fs.combine(basePath, path)
|
|
fs.makeDir(p)
|
|
return true
|
|
end
|
|
|
|
function disk:remove(path)
|
|
local p = fs.combine(basePath, path)
|
|
if fs.exists(p) then fs.delete(p) end
|
|
return true
|
|
end
|
|
|
|
function disk:setLabel(label) periph.setLabel(label) end
|
|
|
|
function disk:getLabel(label) return periph.getLabel() end
|
|
|
|
function disk:attributes(path)
|
|
local p = fs.combine(basePath, path)
|
|
return fs.attributes(p)
|
|
end
|
|
|
|
function disk:open(path, mode)
|
|
local p = fs.combine(basePath, path)
|
|
return fs.open(p, mode)
|
|
end
|
|
|
|
return disk
|
|
end
|
|
|
|
internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, {
|
|
setLabel = function(label)
|
|
local h = fs.open("/.label", "w")
|
|
h.write(label)
|
|
h.close()
|
|
end,
|
|
getLabel = function()
|
|
local h = fs.open("/.label", "r")
|
|
if not h then return "$" end
|
|
local label = h.readAll()
|
|
h.close()
|
|
return label
|
|
end
|
|
})
|
|
|
|
internal["rom"] = createDisk("rom", "/rom", true, {
|
|
setLabel = function(label)
|
|
error("Device is read-only")
|
|
end,
|
|
getLabel = function()
|
|
return "cctrom"
|
|
end
|
|
})
|
|
|
|
local function refresh()
|
|
disks={}
|
|
for _, disk in ipairs({peripheral.find("drive")}) do
|
|
if disk.isDiskPresent() then
|
|
disks[tostring(disk.getDiskID())]=createDisk("cctdisk"..tostring(disk.getDiskID()), disk.getMountPath(), false, fs)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function iter()
|
|
refresh()
|
|
local combined = {}
|
|
|
|
for id, obj in pairs(internal) do combined[id] = obj end
|
|
for id, obj in pairs(disks) do combined[id] = obj end
|
|
|
|
return pairs(combined)
|
|
end
|
|
|
|
return {refresh = refresh, list = iter}
|