Advertisement
renanmfd

sworm_master

Dec 2nd, 2022 (edited)
826
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.29 KB | None | 0 0
  1. -- @file sworm_master.lua
  2. --
  3. -------------------------------------------------------------------------------
  4.  
  5. -- ============================================================================
  6. -- Variables ------------------------------------------------------------------
  7.  
  8. local TURTLE_SLOT_FUEL    = 1
  9. local TURTLE_SLOT_UNLOAD  = 2
  10. local TURTLE_SLOT_BUCKET  = 3
  11. local MASTER_CHUNKLOADERS = 4
  12. local MASTER_TURTLES      = 5
  13.  
  14. -- state and position handlers
  15.  
  16. local origin = nil
  17. local state = "serving" -- "serving" "retriving" "placing" "setting"
  18. local chunkCount = 0    -- Number of chunks mined (chunk loader used).
  19. local spotCount  = 0    -- Number of spots mined.
  20. local channels = {}
  21.  
  22. -- file handler
  23.  
  24. local file = "state.cc"
  25.  
  26. -- Modem channels
  27. local modem = nil
  28. local initialChannel = 100
  29.  
  30. -- ============================================================================
  31. -- PRIVATE functions ----------------------------------------------------------
  32.  
  33. local function saveState()
  34.   f = fs.open(file , "w")
  35.   f.writeLine(state)
  36.   f.writeLine(origin.x)
  37.   f.writeLine(origin.y)
  38.   f.writeLine(origin.z)
  39.   f.writeLine(tostring(chunkCount))
  40.   f.writeLine(tostring(spotCount))
  41.   f.writeLine(textutils.serialiseJSON(channels))
  42.   f.close()
  43. end
  44.  
  45. -------------------------------------------------------------------------------
  46.  
  47. local function loadState()
  48.   local x, y, z
  49.   if not fs.exists(file) then
  50.     return false
  51.   end
  52.   f = fs.open(file, "r")
  53.   state = f.readLine()
  54.   x = tonumber(f.readLine())
  55.   y = tonumber(f.readLine())
  56.   z = tonumber(f.readLine())
  57.   origin = vector.new(x, y, z)
  58.   chunkCount = tonumber(f.readLine())
  59.   spotCount = tonumber(f.readLine())
  60.   channels = textutils.unserialiseJSON(f.readLine())
  61.   f.close()
  62.   return true
  63. end
  64.  
  65. -------------------------------------------------------------------------------
  66.  
  67. function spotMapping()
  68.   local spots = {}
  69.   -- =================================== --
  70.   spots[0]  = {front = 0, side = 15}
  71.   spots[1]  = {front = 0, side = 10}
  72.   spots[2]  = {front = 0, side = 5}
  73.   spots[3]  = {front = 0, side = 0}
  74.  
  75.   spots[4]  = {front = 1, side = 12}
  76.   spots[5]  = {front = 1, side = 7}
  77.   spots[6]  = {front = 1, side = 2}
  78.  
  79.   spots[7]  = {front = 2, side = 14}
  80.   spots[8]  = {front = 2, side = 9}
  81.   spots[9]  = {front = 2, side = 4}
  82.   spots[10] = {front = 2, side = -1}
  83.  
  84.   spots[11] = {front = 3, side = 16}
  85.   spots[12] = {front = 3, side = 11}
  86.   spots[13] = {front = 3, side = 6}
  87.   spots[14] = {front = 3, side = 1}
  88.  
  89.   spots[15] = {front = 4, side = 13}
  90.   spots[16] = {front = 4, side = 8}
  91.   spots[17] = {front = 4, side = 3}
  92.   -- =================================== --
  93.   spots[18] = {front = 5, side = 15}
  94.   spots[19] = {front = 5, side = 10}
  95.   spots[20] = {front = 5, side = 5}
  96.   spots[21] = {front = 5, side = 0}
  97.  
  98.   spots[22] = {front = 6, side = 12}
  99.   spots[23] = {front = 6, side = 7}
  100.   spots[24] = {front = 6, side = 2}
  101.  
  102.   spots[25] = {front = 7, side = 14}
  103.   spots[26] = {front = 7, side = 9}
  104.   spots[27] = {front = 7, side = 4}
  105.   spots[28] = {front = 7, side = -1}
  106.  
  107.   spots[29] = {front = 8, side = 16}
  108.   spots[30] = {front = 8, side = 11}
  109.   spots[31] = {front = 8, side = 6}
  110.   spots[32] = {front = 8, side = 1}
  111.  
  112.   spots[33] = {front = 9, side = 13}
  113.   spots[34] = {front = 9, side = 8}
  114.   spots[35] = {front = 9, side = 3}
  115.   -- =================================== --
  116.   spots[36] = {front = 10, side = 15}
  117.   spots[37] = {front = 10, side = 10}
  118.   spots[38] = {front = 10, side = 5}
  119.   spots[39] = {front = 10, side = 0}
  120.  
  121.   spots[40] = {front = 11, side = 12}
  122.   spots[41] = {front = 11, side = 7}
  123.   spots[42] = {front = 11, side = 2}
  124.  
  125.   spots[43] = {front = 12, side = 14}
  126.   spots[44] = {front = 12, side = 9}
  127.   spots[45] = {front = 12, side = 4}
  128.   spots[46] = {front = 12, side = -1}
  129.  
  130.   spots[47] = {front = 13, side = 16}
  131.   spots[48] = {front = 13, side = 11}
  132.   spots[49] = {front = 13, side = 6}
  133.   spots[50] = {front = 13, side = 1}
  134.  
  135.   spots[51] = {front = 14, side = 13}
  136.   spots[52] = {front = 14, side = 8}
  137.   spots[53] = {front = 14, side = 3}
  138.   -- =================================== --
  139.   --spots[54] = {front = 15, side = 15}
  140.   --spots[55] = {front = 15, side = 10}
  141.   --spots[56] = {front = 15, side = 5}
  142.   --spots[57] = {front = 15, side = 0}
  143.  
  144.   return spots
  145. end
  146.  
  147. -- ============================================================================
  148. -- PUBLIC functions -----------------------------------------------------------
  149.  
  150. -------------------------------------------------------------------------------
  151.  
  152. getSpot = function (index)
  153.   local spots = spotMapping()
  154.  
  155.   if index < 0 or index > #spots then
  156.     return false, false
  157.   end
  158.  
  159.   return spots[index].front, spots[index].side
  160. end
  161.  
  162. -------------------------------------------------------------------------------
  163.  
  164. getSpotMax = function ()
  165.   local spots = spotMapping()
  166.   return table.getn(spots) + 1
  167. end
  168.  
  169. -------------------------------------------------------------------------------
  170.  
  171. getNextSpot = function ()
  172.   local nextChunk = false
  173.   local spotFront, spotSide, x, z, y, pos, facing
  174.  
  175.   spotFront, spotSide = getSpot(spotCount)
  176.   -- print("getNextSpot from map (" .. spotCount .. ") " .. spotFront .. ", " .. spotSide)
  177.   spotCount = spotCount + 1
  178.  
  179.   -- If all spots on the "chunk" (15 blocks, not 16) got mined, move to the next.
  180.   if spotCount >= getSpotMax() then
  181.     spotCount = 0
  182.     nextChunk = true
  183.   end
  184.   saveState()
  185.  
  186.   -- Set mining spot based on facing direction and position.
  187.   pos = sworm_api.getPosition()
  188.   facing = sworm_api.getFacing()
  189.   y = pos.y - 2
  190.  
  191.   if facing == sworm_api.DIRECTION_NORTH then
  192.     x = pos.x + spotSide
  193.     z = pos.z - spotFront
  194.   elseif facing == sworm_api.DIRECTION_SOUTH then
  195.     x = pos.x - spotSide
  196.     z = pos.z + spotFront
  197.   elseif facing == sworm_api.DIRECTION_WEST then
  198.     x = pos.x - spotFront
  199.     z = pos.z - spotSide
  200.   elseif facing == sworm_api.DIRECTION_EAST then
  201.     x = pos.x + spotFront
  202.     z = pos.z + spotSide
  203.   end
  204.  
  205.   return {x = x, y = y, z = z}, nextChunk
  206. end
  207.  
  208. -------------------------------------------------------------------------------
  209.  
  210. placeChunkLoader = function ()
  211.   turtle.digUp()
  212.   turtle.select(MASTER_CHUNKLOADERS)
  213.   turtle.placeUp()
  214.   turtle.select(MASTER_TURTLES)
  215. end
  216.  
  217. -------------------------------------------------------------------------------
  218.  
  219. rescueChunkLoader = function ()
  220.   turtle.select(MASTER_CHUNKLOADERS)
  221.   turtle.digUp()
  222.   turtle.select(MASTER_TURTLES)
  223. end
  224.  
  225. -------------------------------------------------------------------------------
  226.  
  227. goToNextChunk = function ()
  228.   local newChunkDirection, newChunkPosition, facing
  229.  
  230.   -- Make sure we are at the origin.
  231.   sworm_api.moveTo(origin)
  232.   facing = sworm_api.getFacing()
  233.  
  234.   -- Get direction vector based on facing direction.
  235.   if facing == sworm_api.DIRECTION_NORTH then
  236.     newChunkDirection = vector.new(0, 0, -15)
  237.   elseif facing == sworm_api.DIRECTION_SOUTH then
  238.     newChunkDirection = vector.new(0, 0, 15)
  239.   elseif facing == sworm_api.DIRECTION_WEST then
  240.     newChunkDirection = vector.new(-15, 0, 0)
  241.   elseif facing == sworm_api.DIRECTION_EAST then
  242.     newChunkDirection = vector.new(15, 0, 0)
  243.   else
  244.     print("Facing direction invalid  " .. facing)
  245.     error()
  246.   end
  247.  
  248.   newChunkPosition = origin:add(newChunkDirection)
  249.   print("goToNextChunk " .. newChunkPosition:tostring())
  250.  
  251.   print("Placing chunk loader")
  252.   sworm_api.moveTo(newChunkPosition, false)
  253.   placeChunkLoader()
  254.  
  255.   attendRequests()
  256.   attendRequests()
  257.  
  258.   print("Rescuing chunk loader")
  259.   sworm_api.moveTo(origin, false)
  260.   rescueChunkLoader()
  261.  
  262.   print("Reposition to start serving")
  263.   sworm_api.moveTo(newChunkPosition, false)
  264.   origin = newChunkPosition
  265.  
  266.   print("Done chunk move")
  267. end
  268.  
  269. -------------------------------------------------------------------------------
  270.  
  271. setupSlaveInventory = function ()
  272.   -- Same order as inventory on slavescode.
  273.   turtle.select(TURTLE_SLOT_FUEL)
  274.   turtle.dropDown(1)
  275.   turtle.select(TURTLE_SLOT_UNLOAD)
  276.   turtle.dropDown(1)
  277.   turtle.select(TURTLE_SLOT_BUCKET)
  278.   turtle.dropDown(1)
  279. end
  280.  
  281. -------------------------------------------------------------------------------
  282.  
  283. checkSlotItem = function (slot, item)
  284.   local inspect = turtle.getItemDetail(slot)
  285.   if inspect == nil then
  286.     return false
  287.   end
  288.   return inspect.name == item
  289. end
  290.  
  291. -------------------------------------------------------------------------------
  292.  
  293. initChunkloader = function ()
  294.   -- Make sure we can place the chunk loader at the top and place it.
  295.   if turtle.detectUp() then
  296.     if not turtle.digUp() then
  297.       print("Error: Master's top not clear.")
  298.       error()
  299.     end
  300.   end
  301.   turtle.select(MASTER_CHUNKLOADERS)
  302.   turtle.placeUp()
  303.   turtle.select(MASTER_TURTLES)
  304. end
  305.  
  306. -------------------------------------------------------------------------------
  307.  
  308. setupSlaves = function ()
  309.   local timeout, spot, nextChunk
  310.  
  311.   -- Open connection to attached wireless modem and open chanel.
  312.   modem.open(initialChannel)
  313.   -- print("Receive channel " .. initialChannel .. " is open")
  314.  
  315.   -- Loop through all slave turtle inventories.
  316.   for i = MASTER_TURTLES , 16 do
  317.     turtle.select(i)
  318.  
  319.     -- Check if there is only on item (turtle) in the slot. If empty, skip.
  320.     if turtle.getItemCount(i) ~= 1 then
  321.       -- Silent fail. Happens very often.
  322.       -- print("Skipping inventory slot " .. i)
  323.       break
  324.     end
  325.  
  326.     -- Check if selected item is a turtle.
  327.     if not checkSlotItem(i, 'computercraft:turtle') and not checkSlotItem(i, 'computercraft:turtle_advanced') then
  328.       print("No turtle on the turtle slot " .. i)
  329.       break
  330.     end
  331.  
  332.     -- Check if we have all necessary items.
  333.     if not checkSlotItem(TURTLE_SLOT_FUEL, 'enderstorage:ender_chest') then
  334.       print("No fuel enderchest on slot " .. TURTLE_SLOT_FUEL)
  335.       break
  336.     end
  337.     if not checkSlotItem(TURTLE_SLOT_UNLOAD, 'enderstorage:ender_chest') then
  338.       print("No unload item enderchest on slot " .. TURTLE_SLOT_UNLOAD)
  339.       break
  340.     end
  341.     if not checkSlotItem(TURTLE_SLOT_BUCKET, 'minecraft:bucket') then
  342.       print("No lava for fuel bucket on slot " .. TURTLE_SLOT_BUCKET)
  343.       break
  344.     end
  345.  
  346.     state = "setting"
  347.     sworm_api.down()
  348.     saveState()
  349.  
  350.     -- Place the slave turtle at the bottom.
  351.     -- print("Placing Turtle " .. (i - MASTER_TURTLES + 1))
  352.     turtle.placeDown()
  353.     sleep(0.5)
  354.  
  355.     -- Check if the turtle is at the bottom.
  356.     if peripheral.isPresent("bottom") then
  357.       -- Turn on slave turtle.
  358.       -- print("---> Turtle")
  359.       peripheral.wrap("bottom").turnOn()
  360.  
  361.       -- Connect to slave and wait response.
  362.       -- print("Waiting for slave response")
  363.       timeout = 0
  364.       event, side, freq , reply , msg , dist = os.pullEvent("modem_message")
  365.       while msg ~= "ready" do
  366.         event, side, freq , reply , msg , dist = os.pullEvent("modem_message")
  367.         timeout = timeout + 1
  368.         if timeout > 10 then
  369.           turtle.digDown()
  370.           sworm_api.up()
  371.           return
  372.         end
  373.         print("No response. Retry in 1 sec (" .. timeout .. "/10).")
  374.         sleep(1)
  375.       end
  376.  
  377.       -- Setup slave.
  378.       -- print("Response received. Seting him up to mine.")
  379.       setupSlaveInventory()
  380.       channel = reply
  381.       channels[reply] = reply
  382.       sworm_api.up()
  383.  
  384.       -- Sending all set message.
  385.       -- print("Sending 'all set' message CH:" .. channel)
  386.       modem.transmit(channel, 0, channel)
  387.  
  388.       modem.open(channel)
  389.       timeout = 0
  390.       event, side, freq , reply , msg , dist = os.pullEvent("modem_message")
  391.       while reply ~= channel do
  392.         event, side, freq , reply , msg , dist = os.pullEvent("modem_message")
  393.         timeout = timeout + 1
  394.         if timeout > 10 then
  395.             turtle.digDown()
  396.           return
  397.         end
  398.         print("No response. Retry in 2 sec (" .. timeout .. "/10).")
  399.         sleep(2)
  400.       end
  401.  
  402.       -- Send the first mine spot to the slave.
  403.       -- print("Slave requesting spot")
  404.       spot, nextChunk = getNextSpot()
  405.       -- spot.y = spot.y + 1
  406.       modem.transmit(channel, 0, spot)
  407.       print("Slave " .. channel .. " started (" .. spotCount .. ") x=" .. spot.x .. " y=" .. spot.y .. " z=" .. spot.z)
  408.  
  409.       -- Make sure we don't close the channels.
  410.       -- modem.close(channel)
  411.  
  412.       saveState()
  413.       sleep(2)
  414.     else
  415.       print("Error: Turtle not present at the bottom.")
  416.     end
  417.     print("---------------------------------")
  418.   end
  419.  
  420.   modem.close(initialChannel)
  421. end
  422.  
  423. -------------------------------------------------------------------------------
  424.  
  425. attendRequests = function ()
  426.   local spot, nextChunk
  427.   local event, side, freq , reply , msg , dist
  428.  
  429.   state = "serving"
  430.   saveState()
  431.  
  432.   event, side, freq , reply , msg , dist = os.pullEvent("modem_message")
  433.  
  434.   if msg == "request" then
  435.     local spot, nextChunk = getNextSpot()
  436.     print("Slave " .. reply .. ", job on x=" .. spot.x .. " y=" .. spot.y .. " z=" .. spot.z)
  437.     modem.transmit(reply, 0, spot)
  438.  
  439.     if nextChunk then
  440.       state = "moving"
  441.       goToNextChunk()
  442.       chunkCount = chunkCount + 1
  443.     end
  444.   end
  445. end
  446.  
  447. -------------------------------------------------------------------------------
  448.  
  449. openChannels = function ()
  450.   print("Opening channels for comms.")
  451.   for channel, open in pairs(channels) do
  452.     modem.open(channel)
  453.   end
  454. end
  455.  
  456. -------------------------------------------------------------------------------
  457. -- Main -----------------------------------------------------------------------
  458.  
  459. main = function ()
  460.   modem = peripheral.find("modem")
  461.  
  462.   if not loadState() then
  463.     print("Master started. Ready to command!")
  464.  
  465.     -- Position to start service.
  466.     sworm_api.init()
  467.     sworm_api.up()
  468.     sworm_api.up()
  469.     sworm_api.gpsCheck()
  470.     origin = sworm_api.getPosition()
  471.     saveState()
  472.     initChunkloader()
  473.   else
  474.     print("State loaded. Resuming command! " .. state)
  475.     sworm_api.init()
  476.  
  477.     -- Break any turtle not completly set and restart setting.
  478.     if state == "setting" then
  479.       turtle.digDown()
  480.     -- Back to origin and restart next chunk move.
  481.     elseif state == "moving" then
  482.       sworm_api.moveTo(origin)
  483.       goToNextChunk()
  484.     end
  485.  
  486.     openChannels()
  487.     sleep(1)
  488.     print("Start working...")
  489.   end
  490.  
  491.   while true do
  492.     setupSlaves()
  493.     attendRequests()
  494.   end
  495.  
  496.   print("Program ENDED")
  497. end
  498.  
  499. os.loadAPI("sworm_api")
  500. sleep(5)
  501. main()
  502.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement