2020-04-03 03:29:17 +00:00
|
|
|
--[[
|
|
|
|
Virtipheral -- virtual peripheral tool
|
|
|
|
|
|
|
|
Docs:
|
|
|
|
|
|
|
|
virtipheral.activate() - Turns on Virtipheral, and overwrites _G.peripheral.
|
|
|
|
virtipheral.deactivate() - Turns off Virtipheral, and reverts _G.peripheral back.
|
|
|
|
|
|
|
|
Upon activation, some new functions are added into _G.peripheral.
|
|
|
|
|
|
|
|
peripheral.attach(string Side, string PeripheralType) - Adds a new virtual peripheral on the specified Side. If that side is occupied by a real peripheral, the virtual one will take precedent.
|
|
|
|
peripheral.detach(string Side) - Detaches a virtual peripheral from the specified Side.
|
|
|
|
peripheral.saveAttach(optional string Path) - Saves the current setup of attached virtual peripherals to a file (by default, "/.virtipheral/p.lson").
|
|
|
|
peripheral.loadAttach(optional string Path, optional boolean Additive) - Loads a saved setup of virtual peripherals from a file. If additive is true, it will add any new peripherals into the current setup instead of overwriting the setup.
|
|
|
|
|
|
|
|
Create new virtual peripherals by making a Lua script that returns a table of methods.
|
|
|
|
Place these files at "/.virtipheral/peripherals/ and load them with peripheral.attach()."
|
|
|
|
--]]
|
|
|
|
|
2020-04-03 03:14:41 +00:00
|
|
|
local virtipheral = {
|
|
|
|
-- path where virtual peripherals are stored
|
|
|
|
peripheralPath = ".virtipheral/peripherals",
|
|
|
|
|
|
|
|
-- default path to store the list of currently loaded peripherals
|
|
|
|
configPath = ".virtipheral/p.lson",
|
|
|
|
}
|
|
|
|
|
|
|
|
-- list of currently loaded virtual peripherals
|
|
|
|
-- K = side, V = methods
|
|
|
|
local virtualPeripherals = {}
|
|
|
|
|
|
|
|
local function tableCopy(tbl)
|
|
|
|
local output = {}
|
|
|
|
for k,v in pairs(tbl) do
|
|
|
|
if type(v) == "table" then
|
|
|
|
output[k] = tableCopy(v)
|
|
|
|
else
|
|
|
|
output[k] = v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return output
|
|
|
|
end
|
|
|
|
|
|
|
|
local loadPeripheral = function(name)
|
|
|
|
local path = fs.combine(virtipheral.peripheralPath, name)
|
|
|
|
local output
|
|
|
|
if not fs.exists(path) then -- counteract edit.lua's fixation with ending every goddamn file with ".lua"
|
|
|
|
path = path .. ".lua"
|
|
|
|
end
|
|
|
|
if fs.exists(path) then
|
|
|
|
output = dofile(path)
|
|
|
|
return output
|
|
|
|
else
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local makeNewPeripheralAPI = function(old)
|
|
|
|
local p = {}
|
|
|
|
|
|
|
|
p.attach = function(side, name)
|
|
|
|
assert(type(side) == "string", "bad argument #1 to 'attach' (expected string, got " .. type(side) .. ")")
|
|
|
|
assert(type(name) == "string", "bad argument #2 to 'attach' (expected string, got " .. type(name) .. ")")
|
|
|
|
local methods = loadPeripheral(name)
|
|
|
|
if methods then
|
|
|
|
virtualPeripherals[side] = {
|
|
|
|
name = name,
|
|
|
|
side = side,
|
|
|
|
methods = methods,
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
else
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
p.detach = function(side)
|
|
|
|
assert(type(side) == "string", "bad argument #1 to 'detach' (expected string, got " .. type(side) .. ")")
|
|
|
|
virtualPeripherals[side] = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
p.saveAttach = function(configPath)
|
|
|
|
configPath = configPath or virtipheral.configPath
|
|
|
|
|
|
|
|
local save = {}
|
|
|
|
for k,v in pairs(virtualPeripherals) do
|
|
|
|
save[k] = {
|
|
|
|
name = v.name,
|
|
|
|
side = v.side,
|
|
|
|
}
|
|
|
|
end
|
|
|
|
local file = fs.open(configPath, "w")
|
|
|
|
file.write(textutils.serialize(save))
|
|
|
|
file.close()
|
|
|
|
end
|
|
|
|
|
|
|
|
p.loadAttach = function(configPath, additive)
|
|
|
|
configPath = configPath or virtipheral.configPath
|
|
|
|
local file = fs.open(configPath, "r")
|
|
|
|
local contents = textutils.unserialize(file.readAll() or "")
|
|
|
|
file.close()
|
|
|
|
if not additive then
|
|
|
|
virtualPeripherals = {}
|
|
|
|
end
|
|
|
|
if contents then
|
|
|
|
for k,v in pairs(contents) do
|
|
|
|
p.attach(v.side or k, v.name)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
p.wrap = function(side)
|
|
|
|
assert(type(side) == "string", "bad argument #1 to 'wrap' (expected string, got " .. type(side) .. ")")
|
|
|
|
if virtualPeripherals[side] then
|
|
|
|
return virtualPeripherals[side].methods
|
|
|
|
else
|
|
|
|
return old.wrap(side)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
p.call = function(side, method, ...)
|
|
|
|
assert(type(side) == "string", "bad argument #1 to 'call' (expected string, got " .. type(side) .. ")")
|
|
|
|
assert(type(method) == "string", "bad argument #2 to 'call' (expected string, got " .. type(method) .. ")")
|
|
|
|
if virtualPeripherals[side] then
|
|
|
|
if virtualPeripherals[side].methods[method] then
|
|
|
|
virtualPeripherals[side].methods[method](...)
|
|
|
|
else
|
|
|
|
error("no such method", 0)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
return old.call(side, method, ...)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
p.find = function(pType)
|
|
|
|
assert(type(pType) == "string", "bad argument #1 to 'find' (expected string, got " .. type(pType) .. ")")
|
|
|
|
for k,v in pairs(virtualPeripherals) do
|
|
|
|
if v.name == pType then
|
|
|
|
return v.methods
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return old.find(pType)
|
|
|
|
end
|
|
|
|
|
|
|
|
p.getNames = function()
|
|
|
|
local output = {}
|
|
|
|
for k, v in pairs(virtualPeripherals) do
|
|
|
|
output[#output + 1] = k
|
|
|
|
end
|
|
|
|
for k, v in pairs(old.getNames()) do
|
|
|
|
output[#output + 1] = v
|
|
|
|
end
|
|
|
|
return output
|
|
|
|
end
|
|
|
|
|
|
|
|
p.getMethods = function(side)
|
|
|
|
local output = {}
|
|
|
|
local list = (virtualPeripherals[side] or {}).methods or old.wrap(side)
|
|
|
|
if list then
|
|
|
|
for k,v in pairs(list) do
|
|
|
|
output[#output + 1] = k
|
|
|
|
end
|
|
|
|
else
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
return output
|
|
|
|
end
|
|
|
|
|
|
|
|
p.getType = function(side)
|
|
|
|
if virtualPeripherals[side] then
|
|
|
|
return virtualPeripherals[side].name
|
|
|
|
else
|
|
|
|
return old.getType(side)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
p.isPresent = function(side)
|
|
|
|
if virtualPeripherals[side] then
|
|
|
|
return true
|
|
|
|
else
|
2020-04-03 03:29:17 +00:00
|
|
|
return old.isPresent(side)
|
2020-04-03 03:14:41 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return p
|
|
|
|
end
|
|
|
|
|
|
|
|
virtipheral.activate = function()
|
|
|
|
if _G.virtipheralActive then
|
|
|
|
error("Virtipheral is already running", 0)
|
|
|
|
else
|
|
|
|
fs.makeDir(virtipheral.peripheralPath)
|
|
|
|
local old = tableCopy(_G.peripheral)
|
|
|
|
for k,v in pairs(old) do
|
|
|
|
local env = getfenv(old[k])
|
|
|
|
env.peripheral = old
|
|
|
|
end
|
|
|
|
_G.__old_peripheral = old
|
|
|
|
_G.peripheral = makeNewPeripheralAPI(old)
|
|
|
|
_G.virtipheralActive = true
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
virtipheral.deactivate = function()
|
|
|
|
if not _G.virtipheralActive then
|
|
|
|
error("Virtipheral is not running", 0)
|
|
|
|
else
|
|
|
|
_G.peripheral = tableCopy(_G.__old_peripheral)
|
|
|
|
for k,v in pairs(_G.peripheral) do
|
|
|
|
local env = getfenv(_G.peripheral[k])
|
|
|
|
env.peripheral = _G.peripheral
|
|
|
|
end
|
|
|
|
_G.__old_peripheral = nil
|
|
|
|
_G.virtipheralActive = false
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return virtipheral
|