Advertisement
Jyzarc

ModemRS 3.0.0 (Beta)

Jan 9th, 2014
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.51 KB | None | 0 0
  1. --Configs
  2. local MODEM_SIDES = {"all"}
  3. local INPUT_SIDES = {"all"}
  4. local OUTPUT_SIDES = {"all"}
  5. local FREQUENCIES = {"1"}
  6. local MODEM_RS_CHANNEL = 127
  7. local INVERT_INPUT = false
  8. local INVERT_OUTPUT = false
  9. local OUTPUT_ANALOG = false
  10. local OUTPUT_LOGIC = {"r",1,0}
  11. local INPUT_LOGIC = "or"
  12.  
  13. --[[
  14. MODEM_SIDES:
  15. Fill this table with a list of sides which this computer should try to wrap as modems.
  16. If the first element is "all" it will try to wrap a modem on every valid side.
  17. If There isn't a modem on a side the program will skip it.
  18. Default is "all".
  19. It is recommended that you leave this on "all" unless you don't want it to wrap a specific modem or modems.
  20.  
  21. INPUT_SIDES:
  22. Fill this table with list of sides which should be inputs.
  23. If the first element is "all" all sides will be input.
  24. If the first element is nil or "none" no sides will be inputs.
  25. Default is "all".
  26.  
  27. OUTPUT_SIDES:
  28. Fill this table with list of sides which this computer should output a received signal
  29. If the first element is "all" it will output to all sides
  30. If the first element is nil or "none" no sides will be outputs.
  31. Default is "all".
  32.  
  33. FREQUENCIES:
  34. Fill this table with a  list of sides which this computer should send a receive modem messages
  35. These are NOT modem channels.
  36. This program uses one modem channel but allows for an infinite amount of frequencies
  37. Frequencies can be either a number or string
  38. A computer can be connected to as many frequencies as you would like.
  39.  
  40. MODEM_RS_CHANNEL:
  41. This is the modem channel this program uses to send and receive messages.
  42. Default is 127; it is not recommended that you change this.
  43.  
  44. INVERT_INPUT:
  45. If true the signal on input computers will be inverted.
  46. This only affects bundled and digital inputs
  47. default is false.
  48.  
  49. INVERT_OUTPUT:
  50. If true the signal on output computers will be inverted.
  51. This only affects bundled and digital outputs.
  52. default is false.
  53.  
  54. OUTPUT_ANALOG:
  55. Outputs combined analog (1-15) signal strength.
  56. Doesn't Apply to bundled cable.
  57. If this is enabled it ignored output logic
  58. Default is false
  59.  
  60. OUTPUT_LOGIC:
  61. Logic can be used to specify how many computers have to be on for the ouput to turn on.
  62. This works for bundled too but treats every color as a different signal.
  63. The first element in this array can either be "r" or "l"
  64. "r" means range; "l" means list.
  65. If "r" then the amount of "on" computers has to be between the next to elements in the array
  66. If the 3rd element (or max range) is 0 then it will be infinite.
  67. So if the first element is 2nd element is 1 and the 2nd is 0 it will be an or gate.
  68. If "l" then any element after that will be an acceptable amount.
  69. Any other number will be ignored.
  70. So if the elements following "l" are 3,5,7 then if the amount of on computers equals anything else.
  71. Default is {"r",1,0}
  72.  
  73. INPUT_LOGIC:
  74. Can be either "or" or "and".
  75. If "and" then all input sides have to be on for that computer to send an "on" signal.
  76. If "or" then any of the inputs will turn on the output.
  77. "or" is default.
  78. ]]
  79.  
  80. --Variables (dont edit these)
  81. local version = "3.0.0"
  82. local ID = os.getComputerID()
  83. local analog = {lastNum=0,stack = 0}
  84. local bundled = {lastStates = {},stacks = {},states = {},updates = {}}
  85. local digital = {lastState=false,stack = 0}
  86. local modems = {}
  87. local freqs = {}
  88. local event,senderID,message,void,handle
  89.  
  90. --local function errorCheck()
  91.  
  92. local function writeToFile(sText,sFile)
  93.     handle = fs.open("Jyzarc/modemRS/"..sFile,"w")
  94.     handle.write(sText)
  95.     handle.close()
  96. end
  97.    
  98. --Modem Wrapping Loop
  99. local function wrapModems()
  100.     if MODEM_SIDES[1] == "all" then
  101.         for i = 1,6 do
  102.             --Check if peripheral on side exists
  103.             if peripheral.getType(rs.getSides()[i]) == "modem" then
  104.                 --Wraps peripheral
  105.                 modems[#modems+1] = peripheral.wrap(rs.getSides()[i])
  106.             end
  107.         end
  108.     else
  109.         for i = 1,#MODEM_SIDES do
  110.             --Check if peripheral on side exists
  111.             if peripheral.getType(MODEM_SIDES[i]) then
  112.                 --Wraps peripheral
  113.                 modems[#modems+1] = peripheral.wrap(MODEM_SIDES[i])
  114.             end
  115.         end
  116.     end
  117. end
  118.  
  119. --Opens Modem Channel on all connected modems
  120. local function openChannel()
  121.     for i = 1,#modems do
  122.         --Opens up modem channel
  123.         modems[i].open(MODEM_RS_CHANNEL)
  124.     end
  125. end
  126.  
  127. --Sets all of the frequencies in the "FREQUENCIES" table to true
  128. local function addFrequencies()
  129.     for i = 1,#FREQUENCIES do
  130.         freqs[FREQUENCIES[i]] = true
  131.     end
  132. end
  133.  
  134. --Just resets all of the bundled info.
  135. local function fillBundledInfo()
  136.     for i = 1,16 do
  137.         bundled.lastStates[i] = false
  138.         bundled.stacks[i] = 0
  139.     end
  140. end
  141.  
  142. --Redstone functions
  143.  
  144. function digital.get()
  145.     if INPUT_LOGIC == "or" then
  146.         digital.state = false
  147.         if INPUT_SIDES[1] == "all" then
  148.             for i = 1,6 do
  149.                 digital.state = digital.state or rs.getInput(rs.getSides()[i])
  150.             end
  151.         else
  152.             for i = 1,#INPUT_SIDES do
  153.                 digital.state = digital.state or rs.getInput(INPUT_SIDES[i])
  154.             end
  155.         end
  156.     elseif INPUT_LOGIC == "and" then
  157.         digital.state = true
  158.         if INPUT_SIDES[1] == "all" then
  159.             for i = 1,6 do
  160.                 digital.state = digital.state and rs.getInput(rs.getSides()[i])
  161.             end
  162.         else
  163.             for i = 1,#INPUT_SIDES do
  164.                 digital.state = digital.state and rs.getInput(INPUT_SIDES[i])
  165.             end
  166.         end
  167.     end
  168.     --Inverts signal if invert option is true
  169.     if INVERT_INPUT then
  170.         digital.state = not digital.state
  171.     end
  172.     --Checks if this signal was the same as the last
  173.     if digital.state == digital.lastState then
  174.         digital.update = 0
  175.     elseif digital.state then
  176.         digital.update = 1
  177.     else
  178.         digital.update = -1
  179.     end
  180.     digital.lastState = digital.state
  181.     return digital.update
  182. end
  183.  
  184. function digital.updateSignal(sBool)
  185.     if INVERT_OUTPUT then
  186.         sBool = not sBool
  187.     end
  188.     if OUTPUT_SIDES[1] == "all" then
  189.         for i = 1,6 do
  190.             rs.setOutput(rs.getSides()[i],sBool)
  191.         end
  192.     else
  193.         for i = 1,#OUTPUT_SIDES do
  194.             rs.setOutput(OUTPUT_SIDES[i],sBool)
  195.         end
  196.     end
  197. end
  198.  
  199. function digital.set(sUpdate)
  200.     digital.temp = false
  201.     digital.stack = digital.stack + sUpdate
  202.     if digital.stack < 0 then
  203.         digital.stack = 0
  204.     end
  205.     writeToFile(digital.stack,"digital")
  206.     if OUTPUT_LOGIC[1] == "r" then
  207.         if digital.stack >= OUTPUT_LOGIC[2]
  208.         and (digital.stack <= OUTPUT_LOGIC[3]
  209.         or OUTPUT_LOGIC[3] == 0) then
  210.             digital.updateSignal(true)
  211.         else
  212.             digital.updateSignal(false)
  213.         end
  214.     elseif OUTPUT_LOGIC[1] == "l" then
  215.         for i = 1,#OUTPUT_LOGIC-1 do
  216.             digital.temp = digital.temp or digital.stack == OUTPUT_LOGIC[i+1]
  217.         end
  218.         if digital.temp then
  219.             digital.updateSignal(true)
  220.         else
  221.             digital.updateSignal(false)
  222.         end
  223.     end
  224. end
  225.  
  226. function analog.get()
  227.     analog.num = 0
  228.     if INPUT_SIDES[1] == "all" then
  229.         for i = 1,6 do
  230.             analog.num = analog.num + rs.getAnalogInput(rs.getSides()[i])
  231.         end
  232.     else
  233.         for i = 1,#INPUT_SIDES do
  234.             analog.num = analog.num + rs.getAnalogInput(INPUT_SIDES[i])
  235.         end
  236.     end
  237.     analog.update = analog.num - analog.lastNum
  238.     analog.lastNum = analog.num
  239.     return analog.update
  240. end
  241.  
  242. function analog.set(sUpdate)
  243.     analog.stack = analog.stack + sUpdate
  244.     if analog.stack < 0 then
  245.         analog.stack = 0
  246.     end
  247.     if analog.stack > 15 then
  248.         analog.stack = 15
  249.     end
  250.     writeToFile(analog.stack,"analog")
  251.     if OUTPUT_SIDES[1] == "all" then
  252.         for i = 1,6 do
  253.             rs.setAnalogOutput(rs.getSides()[i],analog.stack)
  254.         end
  255.     else
  256.         for i = 1,#OUTPUT_SIDES do
  257.             rs.setAnalgOutput(OUTPUT_SIDES[i],analog.stack)
  258.         end
  259.     end
  260. end
  261.  
  262. function bundled.get() --I've made a huge mistake
  263.     for i = 1,16 do
  264.         if INPUT_LOGIC == "or" then
  265.             bundled.states[i] = false
  266.             if INPUT_SIDES[1] == "all" then
  267.                 for s = 1,6 do
  268.                     bundled.states[i] = bundled.states[i] or rs.testBundledInput(rs.getSides()[s],2^(i-1))
  269.                 end
  270.             else
  271.                 for s = 1,#INPUT_SIDES do
  272.                     bundled.states[i] = bundled.states[i] or rs.testBundledInput(INPUT_SIDES[s],2^(i-1))
  273.                 end
  274.             end
  275.         elseif INPUT_LOGIC == "and" then
  276.             bundled.states[i] = true
  277.             if INPUT_SIDES[1] == "all" then
  278.                 for s = 1,6 do
  279.                     bundled.states[i] = bundled.state[i] and rs.testBundledInput(rs.getSides()[s],2^(i-1))
  280.                 end
  281.             else
  282.                 for s = 1,#INPUT_SIDES do
  283.                     bundled.states[i] = bundled.states[i] and rs.testBundledInput(INPUT_SIDES[s],2^(i-1))
  284.                 end
  285.             end
  286.         end
  287.         if INVERT_INPUT then
  288.             bundled.states[i] = not bundled.states[i]
  289.         end
  290.         if bundled.states[i] == bundled.lastStates[i] then
  291.             bundled.updates[i] = 0
  292.         elseif bundled.states[i] then
  293.             bundled.updates[i] = 1
  294.         else
  295.             bundled.updates[i] = -1
  296.         end
  297.         bundled.lastStates[i] = bundled.states[i]
  298.     end
  299.     return bundled.updates
  300. end
  301.  
  302. function bundled.updateSignal(sBools) --The fun continues
  303.     bundled.number = 0
  304.     for i = 1,16 do
  305.         if INVERT_OUTPUT then
  306.             sBools = not sBools
  307.         end
  308.         if sBools[i] then
  309.             bundled.number = bundled.number + 2^(i-1)
  310.         end
  311.     end
  312.     if OUTPUT_SIDES[1] == "all" then
  313.         for y = 1,6 do
  314.             rs.setBundledOutput(rs.getSides()[y],bundled.number)
  315.         end
  316.     else
  317.         for y = 1,#OUTPUT_SIDES do
  318.             rs.setBundledOutput(OUTPUT_SIDES[y],bundled.number)
  319.         end
  320.     end
  321. end
  322.  
  323. function bundled.set(sUpdates) --Make it stop
  324.     for i = 1,16 do
  325.         bundled.temp = false
  326.         bundled.stacks[i] = bundled.stacks[i] + sUpdates[i]
  327.         if bundled.stacks[i] < 0 then
  328.             bundled.stacks[i] = 0
  329.         end
  330.         if OUTPUT_LOGIC[1] == "r" then
  331.             if bundled.stacks[i] >= OUTPUT_LOGIC[2]
  332.             and (bundled.stacks[i] <= OUTPUT_LOGIC[3]
  333.             or OUTPUT_LOGIC[3] == 0) then
  334.                 bundled.states[i] = true
  335.             else
  336.                 bundled.states[i] = false
  337.             end
  338.             writeToFile(textutils.serialize(bundled.stacks),"bundled")
  339.         elseif OUTPUT_LOGIC[1] == "l" then
  340.             for i = 1,#OUTPUT_LOGIC-1 do
  341.                 bundled.temp = bundled.temp or bundled.stacks[i] == OUTPUT_LOGIC[i+1]
  342.             end
  343.             if bundled.temp then
  344.                 bundled.updateSignal(true)
  345.             else
  346.                 bundled.updateSignal(false)
  347.             end
  348.         end
  349.     end
  350.     bundled.updateSignal(bundled.states)
  351. end
  352.  
  353. local function setStartupSignals()
  354.     if fs.exists("Jyzarc/modemRS/digital") then
  355.         handle = fs.open("Jyzarc/modemRS/digital","r")
  356.         digital.file = handle.readAll()
  357.         handle.close()
  358.         fs.delete("Jyzarc/modemRS/digital")
  359.         if not OUTPUT_ANALOG then
  360.             digital.set(tonumber(digital.file))
  361.         end
  362.     end
  363.     if fs.exists("Jyzarc/modemRS/analog") then
  364.         handle = fs.open("Jyzarc/modemRS/analog","r")
  365.         analog.file = handle.readAll()
  366.         handle.close()
  367.         fs.delete("Jyzarc/modemRS/analog")
  368.         if OUTPUT_ANALOG then
  369.             analog.set(tonumber(analog.file))
  370.         end
  371.     end
  372.     if fs.exists("Jyzarc/modemRS/bundled") then
  373.         handle = fs.open("Jyzarc/modemRS/bundled","r")
  374.         bundled.file = handle.readAll()
  375.         handle.close()
  376.         fs.delete("Jyzarc/modemRS/bundled")
  377.         bundled.set(textutils.unserialize(bundled.file))
  378.     end
  379. end
  380.  
  381. local function send()
  382.     for x = 1,#modems do
  383.         for y = 1,#FREQUENCIES do
  384.             modems[x].transmit(MODEM_RS_CHANNEL,ID,{FREQUENCIES[y],digital.get(),analog.get(),bundled.get()})
  385.         end
  386.     end
  387. end
  388.  
  389. --This runs on startup and sets everything up
  390. local function startup()
  391.     --Clear screen
  392.     term.clear()
  393.     --Set cursor to top left
  394.     term.setCursorPos(1,1)
  395.     print("ModemRS version "..version.." by Jyzarc27")
  396.     wrapModems()
  397.     openChannel()
  398.     addFrequencies()
  399.     fillBundledInfo()
  400.     if not fs.exists("Jyzarc/modemRS") then
  401.         fs.makeDir("Jyzarc")
  402.         fs.makeDir("Jyzarc/modemRS")
  403.     end
  404.     setStartupSignals()
  405. end
  406.  
  407. startup()
  408.  
  409. while true do
  410.     event,void,void,senderID,message = os.pullEvent()
  411.     if event == "redstone" then
  412.         if INPUT_SIDES[1] ~= nil
  413.         and INPUT_SIDES[1] ~= "none" then
  414.             send()
  415.         end
  416.     elseif event == "modem_message" then
  417.         if OUTPUT_SIDES[1] ~= nil
  418.         and OUTPUT_SIDES[1] ~= "none" then
  419.             if freqs[message[1]] then
  420.                 if OUTPUT_ANALOG then
  421.                     analog.set(message[3])
  422.                 else
  423.                     digital.set(message[2])
  424.                 end
  425.                 bundled.set(message[4])
  426.             end
  427.         end
  428.     end
  429. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement