Advertisement
BombBloke

Wool Image Printer (ComputerCraft)

Jun 18th, 2017
817
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.10 KB | None | 0 0
  1. -- +--------------------------------------------------------+
  2. -- |                                                        |
  3. -- |                   Wool Image Printer                   |
  4. -- |                                                        |
  5. -- +--------------------------------------------------------+
  6.  
  7. local version = "Version 1.0.0"
  8.  
  9. -- By Jeffrey Alexander, aka Bomb Bloke.
  10. -- Loads GIF or paintutils images and has a turtle construct them.
  11. -- http://www.computercraft.info/forums2/index.php?/topic/28727-cc164-wool-image-printer/
  12.  
  13. -- ----------------------------------------------------------
  14. -- Variable Declarations
  15. -- ----------------------------------------------------------
  16.  
  17. local fileName = ...
  18.  
  19. local wool, node, pos, slots, img, starty, startNode = {}, {}, {}, {}
  20.  
  21. local facing = {"north","east","south","west"}
  22. local amounts = {[0] = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
  23. local names = {[0] = "White", "Orange", "Magenta", "Light Blue", "Yellow", "Lime", "Pink", "Gray", "Light Gray", "Cyan", "Purple", "Blue", "Brown", "Green", "Red", "Black"}
  24. local blocks = {["minecraft:wool"] = true, ["minecraft:stained_hardened_clay"] = true, ["minecraft:stained_glass"] = true, ["minecraft:stained_glass_pane"] = true}
  25.  
  26. for i = 0, 15 do wool[2^i] = i end
  27.  
  28. -- ----------------------------------------------------------
  29. -- Function Declarations
  30. -- ----------------------------------------------------------
  31.  
  32. -- Accepts strings representing compass-facings to turn the turtle.
  33. local function faceDirection(targetdirection)
  34.     local tardir = 1
  35.     for i=1,4 do if targetdirection == facing[i] then tardir = i end end
  36.    
  37.     if tardir < pos.direction then
  38.         if tardir == 1 and pos.direction == 4 then
  39.             while not turtle.turnRight() do end
  40.         else
  41.             for i=1,pos.direction-tardir do while not turtle.turnLeft() do end end
  42.         end
  43.     elseif tardir > pos.direction then
  44.         if tardir == 4 and pos.direction == 1 then
  45.             while not turtle.turnLeft() do end
  46.         else
  47.             for i=1,tardir-pos.direction do while not turtle.turnRight() do end end
  48.         end
  49.     end
  50.    
  51.     pos.direction = tardir
  52. end
  53.  
  54. -- Move ahead a block, keeping track of the turtle's position.
  55. local function forward(amount)
  56.     if not amount then amount = 1 end
  57.    
  58.     while not turtle.forward() do
  59.         turtle.dig()
  60.         turtle.attack()
  61.     end
  62.    
  63.     if pos.direction == 1 then pos.z = pos.z - amount
  64.     elseif pos.direction == 2 then pos.x = pos.x + amount
  65.     elseif pos.direction == 3 then pos.z = pos.z + amount
  66.     else pos.x = pos.x - amount end
  67. end
  68.  
  69. -- Same again but non-destructive.
  70. local function safeForward(amount)
  71.     if not amount then amount = 1 end
  72.     for i = 1, amount do repeat until turtle.forward() end
  73.    
  74.     if pos.direction == 1 then pos.z = pos.z - amount
  75.     elseif pos.direction == 2 then pos.x = pos.x + amount
  76.     elseif pos.direction == 3 then pos.z = pos.z + amount
  77.     else pos.x = pos.x - amount end
  78. end
  79.  
  80. local function turn(tardir)
  81.     if tardir == "left" then
  82.         while not turtle.turnLeft() do end
  83.         pos.direction = pos.direction - 1
  84.         if pos.direction < 1 then pos.direction = 4 end
  85.     elseif tardir == "right" then
  86.         while not turtle.turnRight() do end
  87.         pos.direction = pos.direction + 1
  88.         if pos.direction > 4 then pos.direction = 1 end
  89.     end
  90. end
  91.  
  92. -- Travel to a co-ordinate.
  93. local function goToPos(target,digger)
  94.     while (pos.x ~= node[target][1]) or (pos.y ~= node[target][2]) or (pos.z ~= node[target][3]) do
  95.         if pos.y > node[target][2] then
  96.             if digger then
  97.                 while not turtle.down() do
  98.                     turtle.digDown()
  99.                     turtle.attackDown()
  100.                 end
  101.                 pos.y = pos.y - 1
  102.             elseif turtle.down() then pos.y = pos.y - 1 end
  103.         elseif pos.y < node[target][2] then
  104.             if digger then
  105.                 while not turtle.up() do
  106.                     turtle.digUp()
  107.                     turtle.attackUp()
  108.                 end
  109.                 pos.y = pos.y + 1
  110.             elseif turtle.up() then pos.y = pos.y + 1 end
  111.         end
  112.        
  113.         if pos.x > node[target][1] then
  114.             if pos.direction ~= 4 then faceDirection("west") end
  115.             if digger then forward() elseif turtle.forward() then pos.x = pos.x - 1 end
  116.         elseif pos.x < node[target][1] then
  117.             if pos.direction ~= 2 then faceDirection("east") end
  118.             if digger then forward() elseif turtle.forward() then pos.x = pos.x + 1 end
  119.         end
  120.        
  121.         if pos.z > node[target][3] then
  122.             if pos.direction ~= 1 then faceDirection("north") end
  123.             if digger then forward() elseif turtle.forward() then pos.z = pos.z - 1 end
  124.         elseif pos.z < node[target][3] then
  125.             if pos.direction ~= 3 then faceDirection("south") end
  126.             if digger then forward() elseif turtle.forward() then pos.z = pos.z + 1 end
  127.         end
  128.     end
  129.    
  130.     faceDirection(node[target][4])
  131. end
  132.  
  133. local function getSlotName(slotNum)
  134.     local data = turtle.getItemDetail(slotNum)
  135.     if not data then return nil else return data.name end
  136. end
  137.  
  138. local function mapSlots()
  139.     slots = {}
  140.     for i = 1, 16 do
  141.         local data = turtle.getItemDetail(i)
  142.         if data and blocks[data.name] then slots[data.damage] = i end
  143.     end
  144. end
  145.  
  146. -- ----------------------------------------------------------
  147. -- Initialisation
  148. -- ----------------------------------------------------------
  149.  
  150. term.clear()
  151. term.setCursorPos(1, 1)
  152.  
  153. if fs.exists("progress.txt") then
  154.     print("Build already in progress; resume? ")
  155.    
  156.     if read():lower():sub(1, 1) == "y" then
  157.         local file = fs.open("progress.txt", "r")
  158.         local data = textutils.unserialise(file.readAll())
  159.         file.close()
  160.         fileName, starty, startNode = data[1], data[2], data[3]
  161.     end
  162.    
  163.     print()
  164. end
  165.  
  166. if not fs.exists(fileName) then
  167.     if fs.exists(fileName .. ".nfp") then
  168.         fileName = fileName .. ".nfp"
  169.     elseif fs.exists(fileName .. ".gif") then
  170.         fileName = fileName .. ".gif"
  171.     else error("Can't find the specified image file.") end
  172. end
  173.  
  174. if fileName:lower():sub(-4) == ".gif" then
  175.     if not bbpack then
  176.         if not (fs.exists("bbpack") or fs.exists(shell.resolve("bbpack"))) then
  177.             shell.run("pastebin get cUYTGbpb bbpack")
  178.             os.loadAPI(shell.resolve("bbpack"))
  179.         else os.loadAPI(fs.exists("bbpack") and "bbpack" or shell.resolve("bbpack")) end
  180.     end
  181.  
  182.     if not GIF then
  183.         if not (fs.exists("GIF") or fs.exists(shell.resolve("GIF"))) then
  184.             shell.run("pastebin get 5uk9uRjC GIF")
  185.             os.loadAPI(shell.resolve("GIF"))
  186.         else os.loadAPI(fs.exists("GIF") and "GIF" or shell.resolve("GIF")) end
  187.     end
  188.    
  189.     img = GIF.toPaintutils(GIF.loadGIF(fileName))
  190. else
  191.     img = paintutils.loadImage(fileName)
  192. end
  193.  
  194. -- Strip any empty rows from the bottom of the image:
  195. for y = #img, 1, -1 do
  196.     local row, found = img[y], false
  197.  
  198.     for x = 1, #row do if row[x] > 0 then
  199.         found = true
  200.         break
  201.     end end
  202.  
  203.     if found then break else img[y] = nil end
  204. end
  205.  
  206. -- Strip any empty columns from the right of the image:
  207. for y = 1, #img do
  208.     local row = img[y]
  209.  
  210.     for x = #row, 1, -1 do if row[x] > 0 then
  211.         break
  212.     else
  213.         row[x] = nil
  214.     end end
  215. end
  216.  
  217. if not startNode then
  218.     for y = 1, #img do
  219.         local row = img[y]
  220.         for x = 1, #row do
  221.             local thisCol = wool[row[x]]
  222.             if thisCol then amounts[thisCol] = amounts[thisCol] + 1 end
  223.         end
  224.     end
  225.  
  226.     local flip = false
  227.  
  228.     print("Requirements:")
  229.     for i = 0, 15 do if amounts[i] > 0 then
  230.         write(names[i] .. ": " .. amounts[i])
  231.  
  232.         if flip then
  233.             print()
  234.         else
  235.             local x, y = term.getCursorPos()
  236.             term.setCursorPos(20, y)
  237.         end
  238.  
  239.         flip = not flip
  240.     end end
  241.  
  242.     print()
  243.     if not flip then print() end
  244.  
  245.     write("Proceed? ")
  246.  
  247.     if read():lower():sub(1, 1) ~= "y" then return end
  248.    
  249.     starty = 1
  250.     print()
  251. end
  252.  
  253. -- ----------------------------------------------------------
  254. -- Determine Position
  255. -- ----------------------------------------------------------
  256.  
  257. -- Ping the GPS servers until I get a valid reading:
  258. if peripheral.find("modem") then
  259.     local tempx, tempy, tempz
  260.     while tempx == nil or tempy == nil or tempz == nil do
  261.         tempx, tempy, tempz = gps.locate(5)
  262.         sleep(5)
  263.     end
  264.    
  265.     while not turtle.forward() do while not turtle.turnLeft() do end end
  266.     pos.x,pos.y,pos.z = gps.locate(5)
  267.  
  268.     if pos.x < tempx then pos.direction = 4
  269.     elseif pos.x > tempx then pos.direction = 2
  270.     elseif pos.z < tempz then pos.direction = 1
  271.     else pos.direction = 3 end
  272.    
  273.     repeat until turtle.back()
  274.     pos.x,pos.y,pos.z = gps.locate(5)
  275.     print("I'm at "..pos.x..","..pos.y..","..pos.z..", I have "..turtle.getFuelLevel().." fuel, and I'm facing "..facing[pos.direction]..".")
  276. else
  277.     pos.x,pos.y,pos.z,pos.direction = 0, 0, 0, 1
  278.     print("I have "..turtle.getFuelLevel().." fuel, but I don't know where I am. If I have to be restarted, manually place me back at my initial position first.")
  279. end
  280.  
  281. print()
  282.  
  283. mapSlots()
  284. node[1] = startNode or {pos.x, pos.y, pos.z, facing[pos.direction]}
  285.  
  286. if pos.y > node[1][2] then
  287.     node[2] = {node[1][1], pos.y, node[1][3], facing[pos.direction]}
  288.     goToPos(2)
  289.     goToPos(1)
  290. end
  291.  
  292. -- ----------------------------------------------------------
  293. -- Primary Work Loop
  294. -- ----------------------------------------------------------
  295.  
  296. for y = starty, #img do
  297.     local file = fs.open("progress.txt", "w")
  298.     file.write(textutils.serialise({fileName, y, node[1]}))
  299.     file.close()
  300.  
  301.     local thisRow = img[#img - y + 1]
  302.    
  303.     if y + #thisRow + 10 > turtle.getFuelLevel() then
  304.         print("Low of energy. Please provide fuel items.")
  305.  
  306.         goToPos(1)
  307.  
  308.         repeat
  309.             os.pullEvent("turtle_inventory")
  310.            
  311.             for i = 1, 16 do
  312.                 local slot = getSlotName(i)
  313.                 if slot and not blocks[slot] then
  314.                     turtle.select(i)
  315.                     turtle.refuel()
  316.                 end
  317.             end
  318.         until turtle.getFuelLevel() > y + #thisRow + 10
  319.     end
  320.  
  321.     node[2] = {node[1][1], node[1][2] + y, node[1][3], node[1][4]}
  322.     goToPos(2)
  323.  
  324.     for x = 1, #thisRow do
  325.         safeForward()
  326.  
  327.         local thisCol = wool[thisRow[x]]
  328.         if thisCol and not turtle.detectDown() then
  329.             if not slots[thisCol] or turtle.getItemCount(slots[thisCol]) == 0 then
  330.                 mapSlots()
  331.  
  332.                 if not slots[thisCol] or turtle.getItemCount(slots[thisCol]) == 0 then
  333.                     print("Out of " .. names[thisCol] .. "!")
  334.  
  335.                     node[3] = {pos.x, pos.y, pos.z, node[1][4]}
  336.  
  337.                     goToPos(2)
  338.                     goToPos(1)
  339.  
  340.                     repeat
  341.                         os.pullEvent("turtle_inventory")
  342.                         mapSlots()
  343.                     until slots[thisCol] and turtle.getItemCount(slots[thisCol]) > 0
  344.                    
  345.                     goToPos(2)
  346.                     goToPos(3)
  347.                 end
  348.             end
  349.  
  350.             turtle.select(slots[thisCol])
  351.             turtle.placeDown()
  352.         end
  353.     end
  354.  
  355.     goToPos(2)
  356. end
  357.  
  358. goToPos(1)
  359.  
  360. print("Done!")
  361. fs.delete("progress.txt")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement