Advertisement
civilwargeeky

Quarry Repeater

Sep 17th, 2014
4,128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.80 KB | None | 0 0
  1. --Version 1.0.3
  2. --This program will act as a repeater between a turtle and a receiver computer
  3. --important options are doAcceptPing and arbitraryNumber
  4. --expected message format: {message, id, distance, fingerprint}
  5. --added modifications similar to receiver program
  6.  
  7. --Config
  8. local doDebug = false --...
  9. local arbitraryNumber = 100 --How many messages to keep between deletions
  10. local saveFile = "QuarryRepeaterSave"
  11. local expectedFingerprints = {quarry = true, quarryReceiver = true}
  12. local acceptLegacy = true --This will auto-format old messages that come along
  13. local doAcceptPing = true --Accept pings. Can be turned off for tight quarters
  14. local pingFingerprint = "ping"
  15. local pingSide = "top"
  16. --Init
  17. local sentMessages = {} --Table of received message ids
  18. local counter = 0
  19. local tempCounter = 0 --How many messages since last delete
  20. local recentID = 1 --Most recent message ID received, used for restore in delete
  21. local channels = {} --List of channels to open listen on
  22. local modem --The wireless modem
  23. local modemSide --Will not necessarily be set
  24.  
  25.  
  26. --Function Declarations--
  27. local function debug(...) if doDebug then return print(...) end end --Debug print
  28.  
  29. local function newID()
  30.   return math.random(1,2000000000) --1 through 2 billion; close enough
  31. end
  32. local function save()
  33.   debug("Saving File")
  34.   local file = fs.open(saveFile, "w")
  35.   file.writeLine(textutils.serialize(channels):gsub("[\n\r]","")) --All the channels
  36.   file.writeLine(counter) --Total number of messages received
  37.   file.writeLine(modemSide) --The side the modem is on, helps for old MC
  38.   return file.close()
  39. end
  40. local function addID(id)
  41.     sentMessages[id] = true
  42.     tempCounter = tempCounter + 1
  43.     counter = counter + 1
  44.     recentID = id
  45.     save()
  46. end
  47. local function openChannels()
  48.   for a,b in pairs(channels) do
  49.     debug("Checking channel ",b)
  50.     if not modem.isOpen(b) then
  51.       debug("Opening channel ",b)
  52.       modem.open(b)
  53.     end
  54.   end
  55. end
  56. local function testPeripheral(periph, periphFunc)
  57.   if type(periph) ~= "table" then return false end
  58.   if type(periph[periphFunc]) ~= "function" then return false end
  59.   if periph[periphFunc]() == nil then --Expects string because the function could access nil
  60.     return false
  61.   end
  62.   return true
  63. end
  64. local function initModem() --Sets up modem, returns true if modem exists
  65.   if not testPeripheral(modem, "isWireless") then
  66.     if peripheral.getType(modemSide or "") == "modem" then
  67.       modem = peripheral.wrap(modemSide)    
  68.       if not modem.isWireless() then --Apparently this is a thing
  69.         modem = nil
  70.         return false
  71.       end
  72.       return true
  73.     end
  74.     if peripheral.find then
  75.       modem = peripheral.find("modem", function(side, obj) return obj.isWireless() end)
  76.     end
  77.     return modem and true or false
  78.   end
  79.   return true
  80. end
  81. local function addChannel(num, doPrint) --Tries to add channel number. Checks if channel not already added. Speaks if doPrint set to true.
  82.   num = tonumber(num)
  83.   for a, b in pairs(channels) do
  84.     if b == num then
  85.       if doPrint then
  86.         print("Channel "..num.." already added.")
  87.       end
  88.       return false
  89.     end
  90.   end
  91.   if num >= 1 and num <= 65535 then
  92.     table.insert(channels, num)
  93.     if doPrint then
  94.       print("Channel "..num.." added.")
  95.     end
  96.   end
  97. end
  98.  
  99. --Actual Program Part Starts Here--
  100. if fs.exists(saveFile) then
  101.   local file = fs.open(saveFile,"r")
  102.   channels = textutils.unserialize(file.readLine()) or (print("Channels could not be read") and {})
  103.   counter = tonumber(file.readLine()) or (print("Counter could not be read") and 0)
  104.   modemSide = file.readLine() or (print("Modem Side not read") and "")
  105.   print("Done reading save file")
  106.   file.close()
  107. end
  108.  
  109. while not initModem() do
  110.   print("No modem is connected, please attach one")
  111.   if not peripheral.find then
  112.     print("What side was that on?")
  113.     modemSide = read()
  114.   else
  115.     os.pullEvent("peripheral")
  116.   end
  117. end
  118. openChannels()
  119.  
  120. sleep(2) --Give users a second to read this stuff.
  121.  
  122. local continue = true
  123. while continue do
  124.   print("\nHit 'q' to quit, 'r' to remove channels, 'p' to ping or any other key to add channels")
  125.   local event, key, receivedFreq, replyFreq, received, dist = os.pullEvent()
  126.   term.clear()
  127.   term.setCursorPos(1,1)
  128.   if event == "modem_message" then
  129.     print("Modem Message Received")
  130.     debug("Received on channel "..receivedFreq.."\nReply channel is "..replyFreq.."\nDistance is "..dist)
  131.     if acceptLegacy and type(received) ~= "table" then
  132.       debug("Unformatted message, formatting for quarry")
  133.       received = { message = received, id = newID(), distance = 0, fingerprint = "quarry"}
  134.     end
  135.    
  136.     debug("Message Properties")
  137.     for a, b in pairs(received) do
  138.       debug(a,"   ",b)
  139.     end
  140.    
  141.     if expectedFingerprints[received.fingerprint] and not sentMessages[received.id] then --A regular expected message
  142.       if received.distance then
  143.         received.distance = received.distance + dist --Add on to repeater how far message had to go
  144.       else
  145.         received.distance = dist
  146.       end
  147.       debug("Adding return channel "..replyFreq.." to channels")
  148.       addChannel(replyFreq,false)
  149.       debug("Sending Return Message")
  150.       modem.transmit(receivedFreq, replyFreq, received) --Send back exactly what we got
  151.       addID(received.id)
  152.     elseif doAcceptPing and received.fingerprint == pingFingerprint then --We got a ping!
  153.       debug("We got a ping!")
  154.       redstone.setOutput(pingSide, true) --Just a toggle should be fine
  155.       sleep(1)
  156.       redstone.setOutput(pingSide, false)
  157.     end
  158.  
  159.     if tempCounter > arbitraryNumber then --Purge messages to save memory
  160.       debug("Purging messages")
  161.       sleep(0.05) --Wait a tick for no good reason
  162.       sentMessages = {} --Completely reset table
  163.       sentMessages[recentID] = true --Reset last message (not sure if really needed. Oh well.)
  164.       tempCounter = 0
  165.     end
  166.    
  167.     print("Messages Received: "..counter)
  168.    
  169.   elseif event == "char" then
  170.     if key == "q" then --Quitting
  171.       print("Quitting")
  172.       continue = false
  173.     elseif key == "p" then --Ping other channels
  174.       for a,b in pairs(channels) do --Ping all open channels
  175.         debug("Pinging channel ",b)
  176.         modem.transmit(b,b,{message = "I am ping! Wrar!", fingerprint = "ping"})
  177.         sleep(1)
  178.       end
  179.     elseif key == "r" then --Removing Channels
  180.       print("Enter a comma separated list of channels to remove")
  181.       local str = "" --Concatenate all the channels into one, maybe restructure this for sorting?
  182.       for i=1,#channels do
  183.         str = str..tostring(channels[i])..", "
  184.       end
  185.       print("Channels: ",str:sub(1,-2)) --Sub for removing comma and space
  186.       local input = io.read()
  187.       local toRemove = {} --We have to use this table because user list will not be in reverse numerical order. Because modifying while iterating is bad...
  188.       for num in input:gmatch("%d+") do
  189.         for a, b in pairs(channels) do
  190.           if b == tonumber(num) then
  191.             debug("Removing ",b)
  192.             table.insert(toRemove, a, 1) --This way it will remove indexes from the back of the table
  193.             modem.close(b)
  194.             break --No use checking the rest of the table for this number
  195.           end
  196.         end
  197.       end
  198.       for i=1, #toRemove do
  199.         table.remove(channels, toRemove[i])
  200.       end
  201.     else  --Adding Channels
  202.       print("What channels would you like to open. Enter a comma-separated list.\nAdd only sending channels. Receiving ones will be added automatically.\n")
  203.       local input = io.read()
  204.       for num in input:gmatch("%d+") do
  205.         addChannel(num,true)
  206.       end
  207.       sleep(2)
  208.     end
  209.     save()
  210.     openChannels() --This will only open channels if they aren't open
  211.    
  212.   end
  213. end
  214.  
  215. for i=1, #channels do
  216.   modem.close(channels[i])
  217. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement