OReezy

Touch Screen openblocks Radio Controller

Mar 6th, 2014
1,357
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --Version 1.1.2
  2. --Code by O'Reezy
  3.  
  4. local helpString = [[Arguments: (in any order)
  5. -t terminal mode (incompatible with monitor mode)
  6. -d debug mode
  7. -nd non-daemon mode
  8. -m<side or name> specifies which monitor to use (no space) (incompatible with terminal mode)
  9. -s<.5-5> sets scale of radio (no space) (not available for terminal)
  10. -v<1-15> sets initial volume (no space)
  11.  
  12. Example: radio -mmonitor_1 -s2
  13. ]]
  14.  
  15. local radio, chest, display, displayName, radioDir, chestDir
  16. local mX, mY
  17. local disks = {}
  18. local diskLoc = {}
  19. local volumeSide
  20. local tArgs = {...}
  21.  
  22. --Wraps necessary peripherals to variables
  23. local function findPeripherals()
  24.     local peripherals = peripheral.getNames()
  25.     for k,v in pairs(peripherals) do
  26.         if string.match(peripheral.getType(v), "radio") then
  27.             radio = peripheral.wrap(v)
  28.         elseif string.match(peripheral.getType(v), "chest") then
  29.             chest = peripheral.wrap(v)
  30.         elseif string.match(peripheral.getType(v), "monitor") then
  31.             display = peripheral.wrap(v)
  32.             displayName = v
  33.         end
  34.     end
  35.     --Errors if all necessary peripherals are not found
  36.     if not radio then
  37.         error("Radio peripheral not found", 0)
  38.     elseif not chest then
  39.         error("Chest peripheral not found", 0)
  40.     end
  41. end
  42.  
  43. --Table of possible arguments
  44. local options = {
  45.     daemon = true;
  46.     terminal = false;
  47.     scale = false;
  48.     debug = false;
  49.     monitor = false;
  50.     volume = 4;
  51. }
  52.  
  53. local function saveOptions()
  54.     local config = fs.open(".radioConfig", "w")
  55.     config.write(textutils.serialize(options))
  56.     config.close()
  57. end
  58.  
  59. local function loadOptions()
  60.     if fs.exists(".radioConfig") then
  61.         local config = fs.open(".radioConfig", "r")
  62.         options = textutils.unserialize(config.readAll())
  63.         config.close()
  64.     end
  65. end
  66.  
  67. --Determines which arguments are used
  68. local function getArgs()
  69.     local sides = {}
  70.     for k,v in pairs({rs.getSides}) do
  71.         sides[v] = true
  72.     end
  73.     for i= 1, #tArgs do
  74.         if tArgs[i] == "-nd" then
  75.             options.daemon = false
  76.         elseif tArgs[i] == "-t" then
  77.             options.terminal = true
  78.             options.daemon = false
  79.         elseif tArgs[i] == "-d" then
  80.             options.debug = true
  81.             options.daemon = false
  82.         elseif string.match(tArgs[i], "-s") then
  83.             options.scale = tonumber(string.match(tArgs[i], ".*", 3))
  84.             if options.scale < .5 or options.scale > 5 then
  85.                 error("Scale must be (0.5-5.0)")
  86.             end
  87.         elseif string.match(tArgs[i], "-v") then
  88.             options.volume = tonumber(string.match(tArgs[i], "%d"))
  89.             if options.volume > 15 then
  90.                 options.volume = 15
  91.             elseif options.volume < 1 then
  92.                 options.volume = 1
  93.             end
  94.         elseif string.match(tArgs[i], "-m") then
  95.             local monFind = string.match(tArgs[i], ".*", 3)
  96.             if sides[monFind] or peripheral.getType(monFind) == "monitor" then
  97.                 displayName = monFind
  98.                 display = peripheral.wrap(monFind)
  99.                 options.monitor = true
  100.             end
  101.         elseif tArgs[i] == "help" then
  102.             error(helpString, 0)
  103.         end
  104.     end
  105.     if #tArgs > 0 then
  106.         saveOptions()
  107.     end
  108. end
  109.  
  110. --Finds which directions the chest/radio are from each other
  111. local function findDirection()
  112.     local dirs = {"north", "east", "up", "south", "west", "down"}
  113.     for i = 1,#dirs do
  114.         local t = {radio.pullItemIntoSlot(dirs[i], 1, 1, 1)}
  115.         if t[1] == 1 then
  116.             if i <= 3 then
  117.                 radio.pushItemIntoSlot(dirs[i], 1, 1, 1)
  118.                 return dirs[i], dirs[i+3]
  119.             elseif i >= 4 then
  120.                 radio.pushItemIntoSlot(dirs[i], 1, 1, 1)
  121.                 return dirs[i], dirs[i-3]
  122.             end
  123.         end
  124.     end
  125.     --Errors if the radio and chest are not next to each other
  126.     error("Radio and Chest must be touching", 0)
  127. end
  128.  
  129. --Creates a table and reverse table of disks available
  130. local function indexDisks()
  131.     local t = chest.getAllStacks()
  132.     --Creates indexed tables of disks in chests
  133.     for k,v in pairs(t) do
  134.         disks[#disks+1] = t[k].name
  135.     end
  136.  
  137.     for k,v in pairs(disks) do
  138.         diskLoc[v] = k
  139.     end
  140. end
  141.  
  142. --Checks if correct disks are used
  143. local function diskTypeCheck()
  144.     local t = chest.getStackInSlot(1)
  145.     if string.match(t.rawName, "tuned_crystal") then
  146.         return true
  147.     end
  148.     return false
  149. end
  150.  
  151. --Empties the radio if there is a disk already in it (necessary or findDirection will error)
  152. local function initialEmpty()
  153.     local dirs = {"north", "east", "up", "south", "west", "down"}  
  154.     if radio.getStackInSlot(1) then
  155.         if #chest.getAllStacks() < chest.getInventorySize() then
  156.             for k,v in ipairs(dirs) do
  157.                 radio.pushItemIntoSlot(v, 1, 1, #chest.getAllStacks() + 1)
  158.             end
  159.         else
  160.             error("No room in chest for crystal.")
  161.         end
  162.     end
  163. end
  164.  
  165. local function debugPrint(string)
  166.     if options.debug then
  167.         print(string)
  168.     end
  169. end
  170.  
  171. --Prints the volume
  172. local function printVolume(target)
  173.     target.setCursorPos(mX-5,1)
  174.     target.write("^")
  175.     target.setCursorPos(mX-6, math.ceil(mY/2))
  176.     if options.volume < 10 then
  177.         target.write(" ")
  178.     end
  179.     target.write(tostring(options.volume))
  180.     target.setCursorPos(mX-5,mY)
  181.     target.write("v")
  182. end
  183.  
  184. --Draws all options found
  185. local select = 1
  186. local function drawOptions(target)
  187.     local length = #disks
  188.     if mY < length then
  189.         length = mY
  190.     end
  191.     target.clear()
  192.     target.setCursorPos(1,1)
  193.     local x = 1
  194.     for i = select, length-1+select do
  195.         target.setCursorPos(1, x)
  196.         if disks[i] ~= current then
  197.             target.write(disks[i])
  198.         else
  199.             target.setTextColor(colors.green)          
  200.             target.write(disks[i])
  201.             target.setTextColor(colors.lightBlue)
  202.         end
  203.         x = x+1
  204.     end
  205.     if mY < #disks then
  206.         target.setCursorPos(mX-1,1)
  207.         target.write("^")
  208.         target.setCursorPos(mX-1,mY)
  209.         target.write("v")
  210.     end
  211.     target.setCursorPos(mX-2, math.ceil(mY/2))
  212.     if radio.getStackInSlot(1) then
  213.         target.setTextColor(colors.green)
  214.         target.write(" ON")
  215.         target.setTextColor(colors.lightBlue)
  216.     else
  217.         target.setTextColor(colors.red)
  218.         target.write("OFF")
  219.         target.setTextColor(colors.lightBlue)
  220.     end
  221.     if volumeSide then
  222.         printVolume(display)
  223.     end
  224. end
  225.  
  226. --Finds if the radio is on the side of the computer and returns the correct side
  227. local function findRadioSide()
  228.     local sides = {"left", "right", "bottom", "top", "front", "back"}
  229.     for k,v in ipairs(sides) do
  230.         if peripheral.getType(v) then
  231.             if string.match(peripheral.getType(v), "radio") then
  232.                 return v
  233.             end
  234.         end
  235.     end
  236.     return false
  237. end
  238.  
  239. --Runs set up functions and prints info about the set up
  240. local function setUp()
  241.     findPeripherals()
  242.     debugPrint("All necessary peripherals found.")
  243.     loadOptions()
  244.     getArgs()
  245.     if options.debug then
  246.         term.clear()
  247.         term.setCursorPos(1,1)
  248.         term.setTextColor(colors.green)
  249.     end
  250.     --If terminal mode is active or no monitor is found
  251.     if options.terminal or not display then
  252.         display = term
  253.         debugPrint("Terminal mode activated. Daemon mode and monitors inactive.")
  254.     else
  255.         options.monitor = true
  256.     end
  257.     --Last check if monitors/terminals are correct
  258.     if options.terminal and options.monitor then
  259.         error("Cannot run terminal and monitor modes simultaneously", 0)
  260.     end
  261.     initialEmpty()
  262.     if not diskTypeCheck() then
  263.         error("Must use openblocks tuned_crystal", 0)
  264.     end
  265.     radioDir, chestDir = findDirection()
  266.     debugPrint("Radio and Chest connection found.")
  267.     indexDisks()
  268.     debugPrint("Disks indexed. Found "..#disks.." disks.")
  269.     volumeSide = findRadioSide()
  270.     if volumeSide then
  271.         debugPrint("Volume control enabled")
  272.     else
  273.         term.setTextColor(colors.red)
  274.         debugPrint("Volume control disabled. Place radio next to computer to enable.")
  275.         term.setTextColor(colors.green)
  276.     end
  277.     mX, mY = display.getSize()
  278.     if not options.terminal then
  279.         if type(options.scale) == "number" then
  280.             debugPrint("Custom scale found.")
  281.             display.setTextScale(options.scale)
  282.             mX, mY = display.getSize()
  283.         elseif mX <= 18 then
  284.             debugPrint("Small monitor found, scale reduced. Enter custom scale to change.\nUsage: radio (scale)")
  285.             display.setTextScale(.5)
  286.             mX, mY = display.getSize()
  287.         end
  288.     end
  289.     if options.debug and options.terminal then
  290.         print("Radio starting in 5 seconds")
  291.         sleep(5)
  292.     end
  293.     display.clear()
  294.     display.setTextColor(colors.lightBlue)
  295.     drawOptions(display)
  296.     if volumeSide then
  297.         rs.setAnalogOutput(volumeSide, options.volume)
  298.     end
  299. end
  300.  
  301. --Runs the radio
  302. local function radioMonitor()
  303.     while true do
  304.         local input = {os.pullEvent()}
  305.         if (options.monitor and input[1] ==  "monitor_touch" and input[2] == displayName) or (options.terminal and input[1] == "mouse_click") then
  306.             --Checks disk selection
  307.             if input[3] < mX-7 then
  308.                 if input[4] <= #disks then
  309.                     if current then
  310.                         radio.pushItemIntoSlot(radioDir, 1, 1, diskLoc[current])
  311.                     end
  312.                     radio.pullItem(radioDir, input[4]-1+select)
  313.                     current = disks[input[4]-1+select]
  314.                     if volumeSide then
  315.                         rs.setAnalogOutput(volumeSide, options.volume)
  316.                     end
  317.                     drawOptions(display)
  318.                 end
  319.             --Checks volume selection
  320.             elseif input[3] < mX-2 then
  321.                 if volumeSide then
  322.                     if input[4] <= 2 then
  323.                         if options.volume < 15 then
  324.                             options.volume = options.volume + 1
  325.                             rs.setAnalogOutput(volumeSide, options.volume)
  326.                             printVolume(display)
  327.                         end
  328.                     elseif input[4] >= mY - 1 then
  329.                         if options.volume > 1 then
  330.                             options.volume = options.volume - 1
  331.                             rs.setAnalogOutput(volumeSide, options.volume)
  332.                             printVolume(display)
  333.                         end
  334.                     end
  335.                 end
  336.             --Checks OFF selection
  337.             elseif input[4] <= math.ceil(mY/2)+1 and input[4] >= math.floor(mY/2) then
  338.                 radio.pushItemIntoSlot(radioDir, 1, 1, diskLoc[current])
  339.                 rs.setOutput("right", false)
  340.                 current = nil
  341.                 drawOptions(display)
  342.             --Checks for scrolling selection
  343.             elseif #disks > mY then
  344.                 if input[4] >= mY-1 then
  345.                     if select < mY-1 then
  346.                         select = select+1
  347.                         drawOptions(display)
  348.                     end
  349.                 elseif input[4] <= 2 then
  350.                     if select > 1 then
  351.                         select = select-1
  352.                         drawOptions(display)
  353.                     end
  354.                 end
  355.             end
  356.         end
  357.     end
  358. end
  359.  
  360. --Runs the radio in the background
  361. local function runDaemon()
  362.     term.clear()
  363.     term.setCursorPos(1, 1)
  364.     shell.run("shell")
  365. end
  366.  
  367. --Main Code
  368. setUp()
  369. if options.daemon then
  370.     parallel.waitForAny(runDaemon, radioMonitor)
  371. else
  372.     radioMonitor()
  373. end
RAW Paste Data