NoxiaZ

Dome and sphere builder for minecraft

Jul 12th, 2014
634
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.69 KB | None | 0 0
  1. -- Dome and sphere builder for minecraft.
  2. -- Copyright (C) 2012 Timothy Goddard
  3. --
  4. -- Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. -- this software and associated documentation files (the "Software"), to deal in
  6. -- the Software without restriction, including without limitation the rights to
  7. -- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  8. -- the Software, and to permit persons to whom the Software is furnished to do so,
  9. -- subject to the following conditions:
  10. --
  11. -- The above copyright notice and this permission notice shall be included in all
  12. -- copies or substantial portions of the Software.
  13. --
  14. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  16. -- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  17. -- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  18. -- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. --
  21. -- usage: sdbuild <type> <radius> [-c]
  22. -- type should be either dome or sphere
  23. -- radius is distance from centre - total width is actually 2 * radius + 1
  24. -- the structure will be built with its lowest point on the level the turtle is at
  25. -- the block the turtle starts on will be the horizontal centre
  26. -- if -c is passed, will only calculate number of blocks required and not build
  27.  
  28. local arg = { ... }
  29.  
  30. type = arg[1]
  31. radius = tonumber(arg[2])
  32.  
  33. cost_only = false
  34. blocks = 0
  35. if arg[3] == "-c" then
  36.   cost_only = true
  37. end
  38.  
  39. -- Navigation features
  40. -- allow the turtle to move while tracking its position
  41. -- this allows us to just give a destination point and have it go there
  42.  
  43. positionx = radius
  44. positiony = radius
  45. facing = 0
  46.  
  47. function turnRightTrack()
  48.   turtle.turnRight()
  49.   facing = facing + 1
  50.   if facing >= 4 then
  51.     facing = 0
  52.   end
  53. end
  54.  
  55. function turnLeftTrack()
  56.   turtle.turnLeft()
  57.   facing = facing - 1
  58.   if facing < 0 then
  59.     facing = 3
  60.   end
  61. end
  62.  
  63. function safeForward()
  64.   success = false
  65.   trydig = true;
  66.   while not success do
  67.     refuel()
  68.     success = turtle.forward()
  69.     if not success then
  70.       if trydig then
  71.         turtle.dig()
  72.         trydig = false
  73.       else
  74.         print("Blocked attempting to move forward.")
  75.         print("Please clear and press enter to continue.")
  76.         io.read()
  77.       end
  78.     end
  79.   end
  80. end
  81.  
  82. function safeBack()
  83.   success = false
  84.   trydig = true;
  85.   while not success do
  86.     refuel()
  87.     success = turtle.back()
  88.     if not success then
  89.       if trydig then
  90.         turtle.turnLeft()
  91.         turtle.turnLeft()
  92.         turtle.dig()
  93.         turtle.turnLeft()
  94.         turtle.turnLeft()
  95.         trydig = false
  96.       else
  97.         print("Blocked attempting to move back.")
  98.         print("Please clear and press enter to continue.")
  99.         io.read()
  100.       end
  101.     end
  102.   end
  103. end
  104.  
  105. function safeUp()
  106.   success = false
  107.   trydig = true;
  108.   while not success do
  109.     refuel()
  110.     success = turtle.up()
  111.     if not success then
  112.       if trydig then
  113.          turtle.digUp()
  114.          trydig = false
  115.       else
  116.         print("Blocked attempting to move up.")
  117.         print("Please clear and press enter to continue.")
  118.         io.read()
  119.       end
  120.     end
  121.   end
  122. end
  123.  
  124. function refuel()
  125.   if turtle.getFuelLevel() == 0 then    
  126.     turtle.select(1)
  127.     turtle.refuel()
  128.     turtle.select(2)
  129.   end
  130. end
  131.  
  132. function moveY(targety)
  133.   if targety == positiony then
  134.     return
  135.   end
  136.  
  137.   if (facing ~= 0 and facing ~= 2) then -- check axis
  138.     turnRightTrack()
  139.   end
  140.  
  141.   while targety > positiony do
  142.     if facing == 0 then
  143.       safeForward()
  144.     else
  145.       safeBack()
  146.     end
  147.     positiony = positiony + 1
  148.   end
  149.  
  150.   while targety < positiony do
  151.     if facing == 2 then
  152.       safeForward()
  153.     else
  154.       safeBack()
  155.     end
  156.     positiony = positiony - 1
  157.   end
  158. end
  159.  
  160. function moveX(targetx)
  161.   if targetx == positionx then
  162.     return
  163.   end
  164.  
  165.   if (facing ~= 1 and facing ~= 3) then -- check axis
  166.     turnRightTrack()
  167.   end
  168.  
  169.   while targetx > positionx do
  170.     if facing == 1 then
  171.       safeForward()
  172.     else
  173.       safeBack()
  174.     end
  175.     positionx = positionx + 1
  176.   end
  177.  
  178.   while targetx < positionx do
  179.     if facing == 3 then
  180.       safeForward()
  181.     else
  182.       safeBack()
  183.     end
  184.     positionx = positionx - 1
  185.   end
  186. end
  187.  
  188. function navigateTo(targetx, targety)
  189.   -- Cost calculation mode - don't move
  190.   if cost_only then
  191.     return
  192.   end
  193.  
  194.   if facing == 0 or facing == 2 then -- Y axis
  195.     moveY(targety)
  196.     moveX(targetx)
  197.   else
  198.     moveX(targetx)
  199.     moveY(targety)
  200.   end
  201. end
  202.  
  203. cslot = 2
  204. function placeBlock()
  205.   -- Cost calculation mode - don't move
  206.   blocks = blocks + 1
  207.   if cost_only then
  208.     return
  209.   end
  210.  
  211.   turtle.select(cslot)
  212.   print("Current slot: ", cslot )
  213.   print("Items in; ", turtle.getItemCount(cslot))
  214.  
  215.   if turtle.getItemCount(cslot) == 0 then
  216.     foundSlot = false
  217.     while not foundSlot do
  218.       for i = 2,16 do
  219.         if turtle.getItemCount(i) > 0 then
  220.           foundSlot = i
  221.           break
  222.         end
  223.       end
  224.       if not foundSlot then
  225.         -- No resources
  226.         print("Out of building materials. Please refill and press enter to continue.")
  227.         io.read()
  228.       end
  229.     end
  230.     cslot = foundSlot
  231.     print("Using slot: ", foundSlot)
  232.     print("Items in; ", turtle.getItemCount(foundSlot))
  233.     turtle.select(foundSlot)
  234.   end
  235.  
  236.   turtle.placeDown()
  237. end
  238.  
  239. -- Main dome and sphere building routine
  240.  
  241. width = radius * 2 + 1
  242. sqrt3 = 3 ^ 0.5
  243. boundary_radius = radius + 1.0
  244. boundary2 = boundary_radius ^ 2
  245.  
  246. if type == "dome" then
  247.   zstart = radius
  248. elseif type == "sphere" then
  249.   zstart = 0
  250. else
  251.   print("Usage: sdbuild <shape> <radius> [-c]")
  252.   os.exit(1)
  253. end
  254. zend = width - 1
  255. turtle.select(1)
  256. turtle.refuel()
  257.  
  258. -- This loop is for each vertical layer through the sphere or dome.
  259. for z = zstart,zend do
  260.   if not cost_only then
  261.     safeUp()
  262.   end
  263.   print("Layer " .. z)
  264.   cz2 = (radius - z) ^ 2
  265.  
  266.   limit_offset_y = (boundary2 - cz2) ^ 0.5
  267.   max_offset_y = math.ceil(limit_offset_y)
  268.  
  269.   -- We do first the +x side, then the -x side to make movement efficient
  270.   for side = 0,1 do
  271.     -- On the right we go from small y to large y, on the left reversed
  272.     -- This makes us travel clockwise around each layer
  273.     if (side == 0) then
  274.       ystart = radius - max_offset_y
  275.       yend = radius + max_offset_y
  276.       ystep = 1
  277.     else
  278.       ystart = radius + max_offset_y
  279.       yend = radius - max_offset_y
  280.       ystep = -1
  281.     end
  282.    
  283.     for y = ystart,yend,ystep do
  284.       cy2 = (radius - y) ^ 2
  285.      
  286.       remainder2 = (boundary2 - cz2 - cy2)
  287.      
  288.      
  289.       if remainder2 >= 0 then
  290.         -- This is the maximum difference in x from the centre we can be without definitely being outside the radius
  291.         max_offset_x = math.ceil((boundary2 - cz2 - cy2) ^ 0.5)
  292.        
  293.         -- Only do either the +x or -x side
  294.         if (side == 0) then
  295.           -- +x side
  296.           xstart = radius
  297.           xend = radius + max_offset_x
  298.         else
  299.           -- -x side
  300.           xstart = radius - max_offset_x
  301.           xend = radius - 1
  302.         end
  303.        
  304.         -- Reverse direction we traverse xs when in -y side
  305.         if y > radius then
  306.           temp = xstart
  307.           xstart = xend
  308.           xend = temp
  309.           xstep = -1
  310.         else
  311.           xstep = 1
  312.         end
  313.        
  314.         for x = xstart,xend,xstep do
  315.           cx2 = (radius - x) ^ 2
  316.           distance_to_centre = (cx2 + cy2 + cz2) ^ 0.5
  317.           -- Only blocks within the radius but still within 1 3d-diagonal block of the edge are eligible
  318.           if distance_to_centre < boundary_radius and distance_to_centre + sqrt3 >= boundary_radius then
  319.             offsets = {{0, 1, 0}, {0, -1, 0}, {1, 0, 0}, {-1, 0, 0}, {0, 0, 1}, {0, 0, -1}}
  320.             for i=1,6 do
  321.               offset = offsets[i]
  322.               dx = offset[1]
  323.               dy = offset[2]
  324.               dz = offset[3]
  325.               if ((radius - (x + dx)) ^ 2 + (radius - (y + dy)) ^ 2 + (radius - (z + dz)) ^ 2) ^ 0.5 >= boundary_radius then
  326.                 -- This is a point to use
  327.                 navigateTo(x, y)
  328.                 placeBlock()
  329.                 break
  330.               end
  331.             end
  332.           end
  333.         end
  334.       end
  335.     end
  336.   end
  337. end
  338.  
  339. -- Return to where we started in x,y place and turn to face original direction
  340. -- Don't change vertical place though - should be solid under us!
  341. navigateTo(radius, radius)
  342. while (facing > 0) do
  343.   turnLeftTrack()
  344. end
  345.  
  346. print("Blocks used: " .. blocks)
Advertisement
Add Comment
Please, Sign In to add comment