Fishthedj

Untitled

Nov 3rd, 2014
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --Version 1.0.2 DJF
  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.  
  24.  
  25. --Function Declarations--
  26. local function debug(...) if doDebug then return print(...) end end --Debug print
  27.  
  28. local function newID()
  29.   return math.random(1,2000000000) --1 through 2 billion; close enough
  30. end
  31. local function addID(id)
  32.     sentMessages[id] = true
  33.     tempCounter = tempCounter + 1
  34.     counter = counter + 1
  35.     recentID = id
  36. end
  37. local function save()
  38.   debug("Saving File")
  39.   local file = fs.open(saveFile, "w")
  40.   file.writeLine(textutils.serialize(channels):gsub("[\n\r]",""))
  41.   file.writeLine(counter)
  42.   return file.close()
  43. end
  44. local function openChannels()
  45.   for a,b in pairs(channels) do
  46.     debug("Checking channel ",b)
  47.     if not modem.isOpen(b) then
  48.       debug("Opening channel ",b)
  49.       modem.open(b)
  50.     end
  51.   end
  52. end
  53. local function testPeripheral(periph, periphFunc)
  54.   if type(periph) ~= "table" then return false end
  55.   if type(periph[periphFunc]) ~= "function" then return false end
  56.   if periph[periphFunc]() == nil then --Expects string because the function could access nil
  57.     return false
  58.   end
  59.   return true
  60. end
  61. local function initModem() --Sets up modem, returns true if modem exists
  62.   if not testPeripheral(modem, "isWireless") then
  63.     if peripheral.getType(modemSide or "") == "modem" then
  64.       modem = peripheral.wrap(modemSide)    
  65.       if not modem.isWireless() then --Apparently this is a thing
  66.         modem = nil
  67.         return false
  68.       end
  69.       return true
  70.     end
  71.     if peripheral.find then
  72.       modem = peripheral.find("modem", function(side, obj) return obj.isWireless() end)
  73.     end
  74.     return modem and true or false
  75.   end
  76.   return true
  77. end
  78. local function addChannel(num, manually) --Tries to add channel number. Checks if channel not already added. Speaks if manually set to true.
  79.   local chExists = false
  80.   for a, b in pairs(channels) do
  81.     if b == num then
  82.       chExists = true
  83.       break
  84.     end
  85.   end
  86.   if not chExists then
  87.     if num >= 1 and num <= 65535 then
  88.       table.insert(channels, tonumber(num))
  89.       if manually then
  90.         print("Channel "..num.." added.")
  91.       end
  92.     end
  93.   else
  94.     if manually then
  95.       print("Channel "..num.." already added.")
  96.     end
  97.   end
  98. end
  99.  
  100. --Actual Program Part Starts Here--
  101. if fs.exists(saveFile) then
  102.   local file = fs.open(saveFile,"r")
  103.   channels = textutils.unserialize(file.readLine()) or (print("Channels could not be read") and {})
  104.   counter = tonumber(file.readLine()) or (print("Counter could not be read") and 0)
  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. for i=1, #channels do
  119.   debug("Opening ",channels[i])
  120.   modem.open(channels[i])
  121. end
  122.  
  123. local continue = true
  124. while continue do
  125.   print("\nHit 'q' to quit, 'r' to remove channels, 'p' to ping or any other key to add channels")
  126.   local event, key, receivedFreq, replyFreq, received, dist = os.pullEvent()
  127.   term.clear()
  128.   term.setCursorPos(1,1)
  129.   if event == "modem_message" then
  130.     print("Modem Message Received")
  131.     debug("Received on channel "..receivedFreq.."\nReply channel is "..replyFreq.."\nDistance is "..dist)
  132.     if acceptLegacy and type(received) ~= "table" then
  133.       debug("Unformatted message, formatting for quarry")
  134.       received = { message = received, id = newID(), distance = 0, fingerprint = "quarry"}
  135.     end
  136.    
  137.     debug("Message Properties")
  138.     for a, b in pairs(received) do
  139.       debug(a,"   ",b)
  140.     end
  141.    
  142.     if expectedFingerprints[received.fingerprint] and not sentMessages[received.id] then --A regular expected message
  143.       if received.distance then
  144.         received.distance = received.distance + dist --Add on to repeater how far message had to go
  145.       else
  146.         received.distance = dist
  147.       end
  148.       debug("Adding return channel "..replyFreq.." to channels")
  149.       addChannel(replyFreq,false)
  150.       sleep(0.5)
  151.       debug("Sending Return Message")
  152.       modem.transmit(receivedFreq, replyFreq, received) --Send back exactly what we got
  153.       addID(received.id)
  154.     elseif doAcceptPing and received.fingerprint == pingFingerprint then --We got a ping!
  155.       debug("We got a ping!")
  156.       redstone.setOutput(pingSide, true) --Just a toggle should be fine
  157.       sleep(1)
  158.       redstone.setOutput(pingSide, false)
  159.     end
  160.  
  161.     if tempCounter > arbitraryNumber then --Purge messages to save memory
  162.       debug("Purging messages")
  163.       sleep(0.05) --Wait a tick for no good reason
  164.       sentMessages = {} --Completely reset table
  165.       sentMessages[recentID] = true --Reset last message (not sure if really needed. Oh well.
  166.       tempCounter = 0
  167.     end
  168.    
  169.     print("Messages Received: "..counter)
  170.    
  171.   elseif event == "char" then
  172.     if key == "q" then --Quitting
  173.       print("Quitting")
  174.       continue = false
  175.     elseif key == "p" then --Ping other channels
  176.       for a,b in pairs(channels) do --Ping all open channels
  177.         debug("Pinging channel ",b)
  178.         modem.transmit(b,b,{message = "I am ping! Wrar!", fingerprint = "ping"})
  179.         sleep(1)
  180.       end
  181.     elseif key == "r" then --Removing Channels
  182.       print("Enter a comma seperated list of channels to remove")
  183.       local str = "" --Concantenate all the channels into one, maybe restructure this for sorting?
  184.       for i=1,#channels do
  185.         str = str..tostring(channels[i])..", "
  186.       end
  187.       print("Channels: ",str:sub(1,-2)) --Sub for removing comma and space
  188.       local input = io.read()
  189.       local toRemove = {} --We have to use this table because user list will not be in reverse numerical order. Because modifying while iterating is bad...
  190.       for num in input:gmatch("%d+") do
  191.         for a, b in pairs(channels) do
  192.           if b == tonumber(num) then
  193.             debug("Removing ",b)
  194.             table.insert(toRemove, a, 1) --This way it will go from the back of the table
  195.             modem.close(b)
  196.             break --No use checking the rest of the table for this number
  197.           end
  198.         end
  199.       end
  200.       for i=1, #toRemove do --So that we arent
  201.         table.remove(channels, toRemove[i])
  202.       end
  203.     else  --Adding Channels
  204.       print("What channels would you like to open. Enter a comma-separated list.\nAdd only sending channels. Receiving ones will be added automatically.\n")
  205.       local input = io.read()
  206.       for num in input:gmatch("%d+") do
  207.         num = tonumber(num)
  208.         addChannel(num,true)
  209.       end
  210.     end
  211.     save()
  212.     openChannels()
  213.    
  214.   end
  215. end
  216.  
  217. for i=1, #channels do
  218.   modem.close(channels[i])
  219. end
Advertisement
Add Comment
Please, Sign In to add comment