ComputerCraft Archive

virtipheral

computer utility LDDestroier github

Description

A collection of all my ComputerCraft programs and the APIs they use. This is mostly just to get them the fuck off of pastebin, and also to ensure that API owners don't change things to break my precious programs...!

Installation

Copy one of these commands into your ComputerCraft terminal:

wget:wget https://raw.githubusercontent.com/LDDestroier/CC/master/virtipheral.lua virtipheral
Archive:wget https://cc.shobie.xyz/cc/get/gh-LDDestroier-CC-virtipheral virtipheral
Quick Install: wget https://cc.shobie.xyz/cc/get/gh-LDDestroier-CC-virtipheral virtipheral

Usage

Run: virtipheral

Tags

none

Source

View Original Source

Code Preview

--[[
	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()."
--]]

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
			return old.isPresent(side)
		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