Advertisement
hbar

fresco

Nov 24th, 2013
590
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.92 KB | None | 0 0
  1. --[[
  2. Fresco v 1.1.0
  3. Matti Vapa, 2013
  4. https://github.com/mattijv/fresco
  5. http://pastebin.com/KU8RWSQd
  6.  
  7. This program will take as an argument a URL to an image file and request a copy of
  8. it via a server that converts it to a proper format. It then reproduces the image
  9. using Glowstone Illuminators from Thermal Expansion. Required mods are
  10.  
  11.     * ComputerCraft (duh),
  12.     * Thermal Expansion,
  13.     * OpenPeripheral.
  14.  
  15. Instead of a direct URL you can also input a Minecraft username with the -u handle.
  16. The program will download the skin corresponding to the username and build the face
  17. part of the skin.
  18.  
  19. Possible future features:
  20.    
  21.     * Ability to specify a part of the image to be build, so multiple turtles can
  22.       be used for the same picture. This will probably be implemented.
  23.     * Add more comments so people can easily modify this code.
  24.  
  25. Changelog:
  26.  
  27.     0.1.0 - 0.8.0:
  28.                 * Added most features and tested until 6 AM.
  29.    
  30.     0.9.0:
  31.                 * Released for public testing.
  32.     1.0.0:
  33.                 * Added option to build the image horizontally.
  34.                 * Cleaning up the code.
  35.     1.1.0:
  36.                 * Updated to match the OpenPeripheral API changes.
  37.                   For older modpacks, use the previous version:
  38.                   http://pastebin.com/42KWALhR
  39.                 * Added the option to restart an uncomplete build.
  40.                 * Removed MiscPeripherals support as the mod is no
  41.                   longer updated. :/
  42.                 * Removed cosmetic calls of sleep() in the startup.
  43.                 * Fixed a crash caused by someone standing in front
  44.                   of the turtle while it was placing Illuminators.
  45.                 * Fixed punctuation in the change log.
  46.  
  47. Thanks to VerTiGo_Etrex and Mikrysoft for pointing out the changes in the
  48. OpenPeripheral API.
  49.  
  50. ]]--
  51.  
  52. if not http then
  53.     print("HTTP must be enabled.")
  54.     return
  55. end
  56.  
  57.  
  58. VERSION = "1.1.0"
  59.  
  60. print("Fresco v "..VERSION)
  61.  
  62. apiURL = "http://lakka.kapsi.fi:62096"
  63. playerURL = "http://s3.amazonaws.com/MinecraftSkins/"
  64.  
  65. local chest = nil
  66. local url
  67. local restart
  68. local skip
  69. local maxsize
  70. local height,width
  71. local row,column
  72. -- for finding the face in the skin file
  73. local offsetY,offsetX = 0,0
  74. local ascend = turtle.up
  75. local descend = turtle.down
  76.  
  77. local usage = function()
  78.     print("Usage:")
  79.     print("fresco [-h] [-u playername] [url] [size] [-r]")
  80.     print("Either a playername with -u option or url to image must be supplied.")
  81.     print("With -u option the size parameter is the dimensions of the face (default 8 pixels).")
  82.     print("The size option is the length of the longest size in the finished build.")
  83.     print("Use -r to restart a failed build. You will be prompted for a number of columns to skip.")
  84.     print("The number of columns should be equal to the number of completed columns.")
  85.  
  86.     --[[
  87.     print("Options:")
  88.     print("-u    Uses the face from the skin of the player with the name 'playername' as the image.")
  89.     print("      If you use -u you don't need to provide the url as an argument.")
  90.     print("url   The url to the desired picture in the form: http://www.images.com/coolpic.png.")
  91.     print("      Not needed if you use -u.")
  92.     print("size  The maximum lenght of the longer side. The image will be (down/up)scaled to fit this size.")
  93.     print("      With -u the size is the size of the players face, default 8 pixels.")
  94.     ]]--
  95. end
  96.  
  97. local move = function(f)
  98.     while turtle.getFuelLevel() < 1 do
  99.         print("Low on fuel. Please add fuel to my inventory and press return.")
  100.         local e,c = os.pullEvent("key")
  101.         while c ~= 28 do
  102.             e,c = os.pullEvent("key")
  103.         end
  104.         print("Checking for fuel...")
  105.         shell.run("refuel all")
  106.     end
  107.     while not f() do
  108.         sleep(0.3)
  109.     end
  110.     sleep(0.1)
  111. end
  112.  
  113.  
  114. local resupply = function()
  115.     local r = row
  116.     local c = column
  117.     while r < height do
  118.         move(descend)
  119.         r = r + 1
  120.     end
  121.     turtle.turnLeft()
  122.     while c > 1 do
  123.         move(turtle.forward)
  124.         c = c - 1
  125.     end
  126.     turtle.turnRight()
  127.     move(turtle.back)
  128.     local slot = 1
  129.     chest.condenseItems()
  130.     while not chest.getStackInSlot(1) do
  131.             print("Please add more Illuminators to the chest.")
  132.             sleep(5)
  133.             chest.condenseItems()
  134.     end
  135.     chest.pushItemIntoSlot("down",1,64,slot)
  136.     slot = 2
  137.     while slot < 16 do
  138.         chest.condenseItems()
  139.         if not chest.getStackInSlot(1) then
  140.             break
  141.         end
  142.         chest.pushItemIntoSlot("down",1,64,slot)
  143.         slot = slot + 1
  144.     end
  145.     move(turtle.forward)
  146.     turtle.turnRight()
  147.     while c < column do
  148.         move(turtle.forward)
  149.         c = c + 1
  150.     end
  151.     turtle.turnLeft()
  152.     while r > row do
  153.         move(ascend)
  154.         r = r - 1
  155.     end
  156. end
  157.  
  158. local placeFront = function(color)
  159.     if turtle.detect() then return end
  160.     if turtle.getItemCount(1) < 2 then
  161.         if turtle.getItemCount(1) == 0 then
  162.             local slot = 2
  163.             while slot <= 16 do
  164.                 turtle.select(slot)
  165.                 if turtle.transferTo(1) then
  166.                     break
  167.                 end
  168.                 slot = slot + 1
  169.             end
  170.             if slot > 16 then
  171.                 resupply()
  172.             end
  173.         end
  174.     end
  175.     turtle.select(1)
  176.     while not turtle.place() do
  177.         print("Outta my way!")
  178.         sleep(1)
  179.     end
  180.     local lamp = peripheral.wrap("front")
  181.     lamp.setColor(tonumber(color,16))
  182.     turtle.attack()
  183. end
  184.  
  185. local placeDown = function(color)
  186.     if turtle.detectDown() then return end
  187.     if turtle.getItemCount(1) < 2 then
  188.         if turtle.getItemCount(1) == 0 then
  189.             local slot = 2
  190.             while slot <= 16 do
  191.                 turtle.select(slot)
  192.                 if turtle.transferTo(1) then
  193.                     break
  194.                 end
  195.                 slot = slot + 1
  196.             end
  197.             if slot > 16 then
  198.                 resupply()
  199.             end
  200.         end
  201.     end
  202.     turtle.select(1)
  203.     while not turtle.placeDown() do
  204.         print("Outta my way!")
  205.         sleep(1)
  206.     end
  207.     local lamp = peripheral.wrap("bottom")
  208.     lamp.setColor(tonumber(color,16))
  209.     turtle.attackDown()
  210. end
  211.  
  212. local calcFuelNeed = function (h,w)
  213.     local fuel = (h-1)*w+w+1
  214.     if w%2 == 1 then
  215.         fuel = fuel + (h-1)
  216.     end
  217.     if chest then
  218.         local fuelruns = math.floor((w*h-1)/1024)
  219.         for i = 1,fuelruns do
  220.             local columns, frac = math.modf(i*1024/h)
  221.             -- horizontal movement
  222.             fuel = fuel + 2*(columns+1)+2
  223.             -- vertical movement
  224.             if columns % 2 == 1 then
  225.                 fuel = fuel + 2*(h-math.floor(frac*h+0.5)-1)
  226.             else
  227.                 fuel = fuel + 2*(math.floor(frac*h+0.5)-1)
  228.             end
  229.         end
  230.     end
  231.     return fuel
  232. end
  233.  
  234.  
  235. _args = {...}
  236. args = {}
  237.  
  238.  
  239. local place = placeFront
  240.  
  241. local i = 1
  242. while i <= #_args do
  243.     if _args[i] == "-h" then
  244.         place = placeDown
  245.         ascend = turtle.forward
  246.         descend = turtle.back
  247.     elseif _args[i] == "-r" then
  248.         restart = true
  249.     elseif _args[i]:sub(1,1) == "-" then
  250.         args[_args[i]] = _args[i+1]
  251.         i = i + 1
  252.     elseif tonumber(_args[i]) ~= nil then
  253.         args["maxsize"] = _args[i]
  254.     else
  255.         args["url"] = _args[i]
  256.     end
  257.     i = i + 1
  258. end
  259.  
  260.  
  261. if not args["url"] and not args["-u"] then
  262.     usage()
  263.     return
  264. else
  265.     if args["-u"] ~= nil then
  266.         url = playerURL..args["-u"]..".png"
  267.         if args["maxsize"] then
  268.                 maxsize = tostring(math.floor(tonumber(args["maxsize"])*(64/8)+0.5))
  269.         end
  270.     else
  271.         url = args["url"]
  272.         maxsize = args["maxsize"]
  273.     end
  274.    
  275. end
  276.  
  277. if not url then
  278.     usage()
  279.     return
  280. end
  281.  
  282. local vars = "url="..url
  283. if maxsize then
  284.     vars = vars.."&maxsize="..maxsize
  285. end
  286. print("Requesting image from")
  287. print(url)
  288. f = http.post(apiURL,vars)
  289. if not f then
  290.     print("No response from image server.")
  291.     return
  292. elseif f.getResponseCode() ~= 200 then
  293.     print("Error while connecting to server!")
  294.     print("Server response")
  295.     print("Code: "..f.getResponseCode())
  296.     print("Message:")
  297.     print(f.readAll())
  298.     return
  299. end
  300.  
  301. local oldSize = f.readLine()
  302. local newSize = f.readLine()
  303. if oldSize ~= newSize then
  304.     print("Original image size was (w,h): "..oldSize)
  305.     print("New size is (w,h): "..newSize)
  306. else
  307.     print("Image size is (w,h): "..newSize)
  308. end
  309.  
  310. local img = {}
  311.  
  312. line = f.readLine()
  313. while line ~= nil do
  314.     table.insert(img,line)
  315.     line = f.readLine()
  316. end
  317. f.close()
  318.  
  319.  
  320. -- X:8, Y:8 to X: 15, Y:15 (top left, bottom right of face)
  321. maxsize = tonumber(maxsize)
  322. if args["-u"] then
  323.     if maxsize then
  324.         -- multiply by 8/64 to get the face size and hack a rounding function
  325.         local size = math.floor(maxsize*0.125+0.5)
  326.         height,width = size,size
  327.         offsetY,offsetX = size,size
  328.     else
  329.         height,width = 8,8
  330.         offsetY,offsetX = 8,8
  331.     end
  332. else
  333.     height,width = #img, #img[1]/8
  334.     row,column = height,1
  335. end
  336.  
  337. row,column = height,1
  338. print("Press return to continue.")
  339. local e,c = os.pullEvent("key")
  340. while c ~= 28 do
  341.     e,c = os.pullEvent("key")
  342. end
  343.  
  344.  
  345. if peripheral.getType("top") == nil then
  346.     print("No valid inventory found on top.")
  347.     return
  348. end
  349. chest = peripheral.wrap("top")
  350. if chest.pushItemIntoSlot == nil then
  351.     print("Inventory does not support required operation: pushItemIntoSlot.")
  352.     return
  353. end
  354.  
  355. print("Resupply inventory located.")
  356. print("Calculating needed fuel...")
  357. local fuelNeed = calcFuelNeed(height,width)
  358. print("Fuel consumption will be (approximate): "..tostring(fuelNeed))
  359. print("Current fuel level is: "..tostring(turtle.getFuelLevel()))
  360. if turtle.getFuelLevel() < fuelNeed then
  361.     while turtle.getFuelLevel() < fuelNeed do
  362.         print(string.format("Need %d fuel units more.",fuelNeed-turtle.getFuelLevel()))
  363.         print("Please put more fuel into my inventory and press return.")
  364.         local e,c = os.pullEvent("key")
  365.         while c ~= 28 do
  366.             e,c = os.pullEvent("key")
  367.         end
  368.         print("Checking for fuel...")
  369.         shell.run("refuel all")
  370.     end
  371. end
  372. print("Fuel requirements met. Looking for building materials...")
  373. while turtle.getItemCount(1) < 1 do
  374.     print("Please put Glowstone Illuminators into the first slot of my inventory.")
  375.     print("Press return to continue.")
  376.     local e,c = os.pullEvent("key")
  377.     while c ~= 28 do
  378.         e,c = os.pullEvent("key")
  379.     end
  380. end
  381.  
  382. print("Good to go!")
  383. print(string.format("The process will take around %f minutes to finish.",(1.2*fuelNeed)/60))
  384. print("Press return to begin.")
  385. e,c = os.pullEvent("key")
  386. while c ~= 28 do
  387.     e,c = os.pullEvent("key")
  388. end
  389.  
  390. if restart then
  391.     print("You wanted to restart.")
  392.     print("Please input how many columns to skip (or press return to cancel).")
  393.     while true do
  394.         term.write("Columns: ")
  395.         skip = io.read()
  396.         if columns == "" then return end
  397.         if not tonumber(skip) or tonumber(skip) < 0 or tonumber(skip) >= width then
  398.             print("Bad input!")
  399.         else
  400.             print("Skipping "..skip.." columns.")
  401.             skip = tonumber(skip)
  402.             break
  403.         end
  404.     end
  405. end
  406.  
  407. print("Starting printing...")
  408.  
  409. move(turtle.forward)
  410. turtle.select(1)
  411.  
  412. if restart then
  413.     turtle.turnRight()
  414.     column = skip + 1
  415.     local c = 1
  416.     while c < column do
  417.         move(turtle.forward)
  418.         c = c + 1
  419.     end
  420.     turtle.turnLeft()
  421. end
  422.  
  423. while true do
  424.     if column > width then break end
  425.     place(img[row+offsetY]:sub(1+8*(column-1+offsetX),1+8*(column-1+offsetX)+7))
  426.     while row > 1 do
  427.         move(ascend)
  428.         row = row - 1
  429.         place(img[row+offsetY]:sub(1+8*(column-1+offsetX),1+8*(column-1+offsetX)+7))
  430.     end
  431.     turtle.turnRight()
  432.     move(turtle.forward)
  433.     turtle.turnLeft()
  434.     column = column + 1
  435.     if column > width then break end
  436.     place(img[row+offsetY]:sub(1+8*(column-1+offsetX),1+8*(column-1+offsetX)+7))
  437.     while row < height do
  438.         move(descend)
  439.         row = row + 1
  440.         place(img[row+offsetY]:sub(1+8*(column-1+offsetX),1+8*(column-1+offsetX)+7))
  441.     end
  442.     turtle.turnRight()
  443.     move(turtle.forward)
  444.     turtle.turnLeft()
  445.     column = column + 1
  446. end
  447.  
  448. if width % 2 == 1 then
  449.     for i = 1, height-1 do
  450.         move(descend)
  451.     end
  452. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement