Advertisement
dadragon84

QuarryRepeater

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