Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --Version 1.1.2
- --Code by O'Reezy
- local helpString = [[Arguments: (in any order)
- -t terminal mode (incompatible with monitor mode)
- -d debug mode
- -nd non-daemon mode
- -m<side or name> specifies which monitor to use (no space) (incompatible with terminal mode)
- -s<.5-5> sets scale of radio (no space) (not available for terminal)
- -v<1-15> sets initial volume (no space)
- Example: radio -mmonitor_1 -s2
- ]]
- local radio, chest, display, displayName, radioDir, chestDir
- local mX, mY
- local disks = {}
- local diskLoc = {}
- local volumeSide
- local tArgs = {...}
- --Wraps necessary peripherals to variables
- local function findPeripherals()
- local peripherals = peripheral.getNames()
- for k,v in pairs(peripherals) do
- if string.match(peripheral.getType(v), "radio") then
- radio = peripheral.wrap(v)
- elseif string.match(peripheral.getType(v), "chest") then
- chest = peripheral.wrap(v)
- elseif string.match(peripheral.getType(v), "monitor") then
- display = peripheral.wrap(v)
- displayName = v
- end
- end
- --Errors if all necessary peripherals are not found
- if not radio then
- error("Radio peripheral not found", 0)
- elseif not chest then
- error("Chest peripheral not found", 0)
- end
- end
- --Table of possible arguments
- local options = {
- daemon = true;
- terminal = false;
- scale = false;
- debug = false;
- monitor = false;
- volume = 4;
- }
- local function saveOptions()
- local config = fs.open(".radioConfig", "w")
- config.write(textutils.serialize(options))
- config.close()
- end
- local function loadOptions()
- if fs.exists(".radioConfig") then
- local config = fs.open(".radioConfig", "r")
- options = textutils.unserialize(config.readAll())
- config.close()
- end
- end
- --Determines which arguments are used
- local function getArgs()
- local sides = {}
- for k,v in pairs({rs.getSides}) do
- sides[v] = true
- end
- for i= 1, #tArgs do
- if tArgs[i] == "-nd" then
- options.daemon = false
- elseif tArgs[i] == "-t" then
- options.terminal = true
- options.daemon = false
- elseif tArgs[i] == "-d" then
- options.debug = true
- options.daemon = false
- elseif string.match(tArgs[i], "-s") then
- options.scale = tonumber(string.match(tArgs[i], ".*", 3))
- if options.scale < .5 or options.scale > 5 then
- error("Scale must be (0.5-5.0)")
- end
- elseif string.match(tArgs[i], "-v") then
- options.volume = tonumber(string.match(tArgs[i], "%d"))
- if options.volume > 15 then
- options.volume = 15
- elseif options.volume < 1 then
- options.volume = 1
- end
- elseif string.match(tArgs[i], "-m") then
- local monFind = string.match(tArgs[i], ".*", 3)
- if sides[monFind] or peripheral.getType(monFind) == "monitor" then
- displayName = monFind
- display = peripheral.wrap(monFind)
- options.monitor = true
- end
- elseif tArgs[i] == "help" then
- error(helpString, 0)
- end
- end
- if #tArgs > 0 then
- saveOptions()
- end
- end
- --Finds which directions the chest/radio are from each other
- local function findDirection()
- local dirs = {"north", "east", "up", "south", "west", "down"}
- for i = 1,#dirs do
- local t = {radio.pullItemIntoSlot(dirs[i], 1, 1, 1)}
- if t[1] == 1 then
- if i <= 3 then
- radio.pushItemIntoSlot(dirs[i], 1, 1, 1)
- return dirs[i], dirs[i+3]
- elseif i >= 4 then
- radio.pushItemIntoSlot(dirs[i], 1, 1, 1)
- return dirs[i], dirs[i-3]
- end
- end
- end
- --Errors if the radio and chest are not next to each other
- error("Radio and Chest must be touching", 0)
- end
- --Creates a table and reverse table of disks available
- local function indexDisks()
- local t = chest.getAllStacks()
- --Creates indexed tables of disks in chests
- for k,v in pairs(t) do
- disks[#disks+1] = t[k].name
- end
- for k,v in pairs(disks) do
- diskLoc[v] = k
- end
- end
- --Checks if correct disks are used
- local function diskTypeCheck()
- local t = chest.getStackInSlot(1)
- if string.match(t.rawName, "tuned_crystal") then
- return true
- end
- return false
- end
- --Empties the radio if there is a disk already in it (necessary or findDirection will error)
- local function initialEmpty()
- local dirs = {"north", "east", "up", "south", "west", "down"}
- if radio.getStackInSlot(1) then
- if #chest.getAllStacks() < chest.getInventorySize() then
- for k,v in ipairs(dirs) do
- radio.pushItemIntoSlot(v, 1, 1, #chest.getAllStacks() + 1)
- end
- else
- error("No room in chest for crystal.")
- end
- end
- end
- local function debugPrint(string)
- if options.debug then
- print(string)
- end
- end
- --Prints the volume
- local function printVolume(target)
- target.setCursorPos(mX-5,1)
- target.write("^")
- target.setCursorPos(mX-6, math.ceil(mY/2))
- if options.volume < 10 then
- target.write(" ")
- end
- target.write(tostring(options.volume))
- target.setCursorPos(mX-5,mY)
- target.write("v")
- end
- --Draws all options found
- local select = 1
- local function drawOptions(target)
- local length = #disks
- if mY < length then
- length = mY
- end
- target.clear()
- target.setCursorPos(1,1)
- local x = 1
- for i = select, length-1+select do
- target.setCursorPos(1, x)
- if disks[i] ~= current then
- target.write(disks[i])
- else
- target.setTextColor(colors.green)
- target.write(disks[i])
- target.setTextColor(colors.lightBlue)
- end
- x = x+1
- end
- if mY < #disks then
- target.setCursorPos(mX-1,1)
- target.write("^")
- target.setCursorPos(mX-1,mY)
- target.write("v")
- end
- target.setCursorPos(mX-2, math.ceil(mY/2))
- if radio.getStackInSlot(1) then
- target.setTextColor(colors.green)
- target.write(" ON")
- target.setTextColor(colors.lightBlue)
- else
- target.setTextColor(colors.red)
- target.write("OFF")
- target.setTextColor(colors.lightBlue)
- end
- if volumeSide then
- printVolume(display)
- end
- end
- --Finds if the radio is on the side of the computer and returns the correct side
- local function findRadioSide()
- local sides = {"left", "right", "bottom", "top", "front", "back"}
- for k,v in ipairs(sides) do
- if peripheral.getType(v) then
- if string.match(peripheral.getType(v), "radio") then
- return v
- end
- end
- end
- return false
- end
- --Runs set up functions and prints info about the set up
- local function setUp()
- findPeripherals()
- debugPrint("All necessary peripherals found.")
- loadOptions()
- getArgs()
- if options.debug then
- term.clear()
- term.setCursorPos(1,1)
- term.setTextColor(colors.green)
- end
- --If terminal mode is active or no monitor is found
- if options.terminal or not display then
- display = term
- debugPrint("Terminal mode activated. Daemon mode and monitors inactive.")
- else
- options.monitor = true
- end
- --Last check if monitors/terminals are correct
- if options.terminal and options.monitor then
- error("Cannot run terminal and monitor modes simultaneously", 0)
- end
- initialEmpty()
- if not diskTypeCheck() then
- error("Must use openblocks tuned_crystal", 0)
- end
- radioDir, chestDir = findDirection()
- debugPrint("Radio and Chest connection found.")
- indexDisks()
- debugPrint("Disks indexed. Found "..#disks.." disks.")
- volumeSide = findRadioSide()
- if volumeSide then
- debugPrint("Volume control enabled")
- else
- term.setTextColor(colors.red)
- debugPrint("Volume control disabled. Place radio next to computer to enable.")
- term.setTextColor(colors.green)
- end
- mX, mY = display.getSize()
- if not options.terminal then
- if type(options.scale) == "number" then
- debugPrint("Custom scale found.")
- display.setTextScale(options.scale)
- mX, mY = display.getSize()
- elseif mX <= 18 then
- debugPrint("Small monitor found, scale reduced. Enter custom scale to change.\nUsage: radio (scale)")
- display.setTextScale(.5)
- mX, mY = display.getSize()
- end
- end
- if options.debug and options.terminal then
- print("Radio starting in 5 seconds")
- sleep(5)
- end
- display.clear()
- display.setTextColor(colors.lightBlue)
- drawOptions(display)
- if volumeSide then
- rs.setAnalogOutput(volumeSide, options.volume)
- end
- end
- --Runs the radio
- local function radioMonitor()
- while true do
- local input = {os.pullEvent()}
- if (options.monitor and input[1] == "monitor_touch" and input[2] == displayName) or (options.terminal and input[1] == "mouse_click") then
- --Checks disk selection
- if input[3] < mX-7 then
- if input[4] <= #disks then
- if current then
- radio.pushItemIntoSlot(radioDir, 1, 1, diskLoc[current])
- end
- radio.pullItem(radioDir, input[4]-1+select)
- current = disks[input[4]-1+select]
- if volumeSide then
- rs.setAnalogOutput(volumeSide, options.volume)
- end
- drawOptions(display)
- end
- --Checks volume selection
- elseif input[3] < mX-2 then
- if volumeSide then
- if input[4] <= 2 then
- if options.volume < 15 then
- options.volume = options.volume + 1
- rs.setAnalogOutput(volumeSide, options.volume)
- printVolume(display)
- end
- elseif input[4] >= mY - 1 then
- if options.volume > 1 then
- options.volume = options.volume - 1
- rs.setAnalogOutput(volumeSide, options.volume)
- printVolume(display)
- end
- end
- end
- --Checks OFF selection
- elseif input[4] <= math.ceil(mY/2)+1 and input[4] >= math.floor(mY/2) then
- radio.pushItemIntoSlot(radioDir, 1, 1, diskLoc[current])
- rs.setOutput("right", false)
- current = nil
- drawOptions(display)
- --Checks for scrolling selection
- elseif #disks > mY then
- if input[4] >= mY-1 then
- if select < mY-1 then
- select = select+1
- drawOptions(display)
- end
- elseif input[4] <= 2 then
- if select > 1 then
- select = select-1
- drawOptions(display)
- end
- end
- end
- end
- end
- end
- --Runs the radio in the background
- local function runDaemon()
- term.clear()
- term.setCursorPos(1, 1)
- shell.run("shell")
- end
- --Main Code
- setUp()
- if options.daemon then
- parallel.waitForAny(runDaemon, radioMonitor)
- else
- radioMonitor()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement