robathome

Basic mining turtle w/ remote

Oct 27th, 2025 (edited)
510
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.44 KB | None | 0 0
  1. -- turtle_mine_coords.lua (CC:Tweaked)
  2. -- Mine a rectangular volume defined by two GPS corners (x1,x2 then y1,y2 then z1,z2).
  3. -- Uses GPS only to pick and reach the nearest corner, then mines with relative moves.
  4. -- Slot 1 = fuel. Slots 2..16 = filler for water/lava. Rednet protocol tmine.v1.
  5.  
  6. local PROTO = "tmine.v1"
  7.  
  8. -- ---------- Modem / Rednet ----------
  9. local function openAnyModem()
  10. for _,side in ipairs(rs.getSides()) do
  11. if peripheral.getType(side) == "modem" then
  12. local m = peripheral.wrap(side)
  13. if m and m.isWireless and m.isWireless() then rednet.open(side); return true end
  14. end
  15. end
  16. return false
  17. end
  18. assert(openAnyModem(), "No wireless modem found/opened")
  19.  
  20. local function log(msg)
  21. print(msg)
  22. rednet.broadcast({id=os.getComputerID(), msg=msg, t=os.epoch("utc")}, PROTO)
  23. end
  24.  
  25. -- ---------- GPS ----------
  26. local function gpsPos() local x,y,z = gps.locate(2.0); return x,y,z end
  27. do local x,y,z=gpsPos(); assert(x and y and z,"GPS not available"); log(("GPS lock: (%.1f, %.1f, %.1f)"):format(x,y,z)) end
  28.  
  29. -- ---------- Fuel ----------
  30. local function refuel(minFuel)
  31. if turtle.getFuelLevel()=="unlimited" then return true end
  32. minFuel = minFuel or 400
  33. if turtle.getFuelLevel() >= minFuel then return true end
  34. local keep = turtle.getSelectedSlot()
  35. turtle.select(1)
  36. while turtle.getFuelLevel() < minFuel do
  37. if turtle.getItemCount(1)==0 then turtle.select(keep); log("Fuel low; slot1 empty"); return false end
  38. turtle.refuel(1)
  39. end
  40. turtle.select(keep); return true
  41. end
  42.  
  43. -- ---------- Liquids / Filler ----------
  44. local function selectFillSlot()
  45. for s=2,16 do if turtle.getItemCount(s)>0 then turtle.select(s); return true end end
  46. return false
  47. end
  48. local function isLiquid(info) return info and info.name and (info.name:find("water") or info.name:find("lava")) end
  49. local function damFront() local ok,d=turtle.inspect(); if ok and isLiquid(d) then if selectFillSlot() then if turtle.place() then log("Dam front") end end end end
  50. local function damUp() local ok,d=turtle.inspectUp(); if ok and isLiquid(d) then if selectFillSlot() then if turtle.placeUp() then log("Dam up") end end end end
  51. local function damDown() local ok,d=turtle.inspectDown(); if ok and isLiquid(d) then if selectFillSlot() then if turtle.placeDown() then log("Dam down") end end end end
  52.  
  53. -- ---------- Dig-safe moves ----------
  54. local function fwd()
  55. while true do
  56. damFront()
  57. local ok,d=turtle.inspect(); if ok and not isLiquid(d) then turtle.dig() end
  58. if turtle.forward() then assertInside("forward"); return true end
  59. sleep(0.1)
  60. end
  61. end
  62.  
  63. local function up()
  64. while true do
  65. damUp()
  66. local ok,d=turtle.inspectUp(); if ok and not isLiquid(d) then turtle.digUp() end
  67. if turtle.up() then assertInside("up"); return true end
  68. sleep(0.1)
  69. end
  70. end
  71.  
  72. local function down()
  73. while true do
  74. damDown()
  75. local ok,d=turtle.inspectDown(); if ok and not isLiquid(d) then turtle.digDown() end
  76. if turtle.down() then assertInside("down"); return true end
  77. sleep(0.1)
  78. end
  79. end
  80.  
  81. ---------- Heading control ----------
  82. local heading = 0 -- 0=+X,1=+Z,2=-X,3=-Z
  83. local function right() turtle.turnRight(); heading=(heading+1)%4 end
  84. local function left() turtle.turnLeft(); heading=(heading+3)%4 end
  85. local function face(dir)
  86. local d=(dir-heading)%4
  87. if d==1 then right()
  88. elseif d==2 then right(); right()
  89. elseif d==3 then left()
  90. end
  91. end
  92.  
  93. -- ---------- Move to absolute GPS corner (one-time) ----------
  94. local function moveAxis(axis, delta)
  95. if delta==0 then return end
  96. if axis=="x" then
  97. face(delta>0 and 0 or 2); for i=1,math.abs(delta) do refuel(200); fwd() end
  98. elseif axis=="z" then
  99. face(delta>0 and 1 or 3); for i=1,math.abs(delta) do refuel(200); fwd() end
  100. elseif axis=="y" then
  101. local step = delta>0 and up or down; for i=1,math.abs(delta) do refuel(200); step() end
  102. end
  103. end
  104. local function gotoXYZ(tx,ty,tz)
  105. local x,y,z = gpsPos(); assert(x,"GPS lost")
  106. moveAxis("x", math.floor(tx - x + 0.5))
  107. x,y,z = gpsPos()
  108. moveAxis("z", math.floor(tz - z + 0.5))
  109. x,y,z = gpsPos()
  110. moveAxis("y", math.floor(ty - y + 0.5))
  111. end
  112.  
  113. -- ---------- Vertical step actions ----------
  114. local function step_3layer()
  115. damUp(); local okU,du=turtle.inspectUp(); if okU and not isLiquid(du) then turtle.digUp() end
  116. damDown(); local okD,dd=turtle.inspectDown(); if okD and not isLiquid(dd) then turtle.digDown() end
  117. end
  118. local function step_2layer()
  119. damDown(); local okD,dd=turtle.inspectDown(); if okD and not isLiquid(dd) then turtle.digDown() end
  120. end
  121. local function step_1layer() end
  122.  
  123. -- ---------- Serpentine over XZ (relative, bounded) ----------
  124. -- Start at the chosen origin corner on the current Y layer.
  125. -- enterDirX: 0 for +X travel on first row, 2 for -X.
  126. -- Directions based on chosen corner
  127. local DIR_X_POS = (sx==1) and 0 or 2 -- face(+X in world)
  128. local DIR_X_NEG = (sx==1) and 2 or 0 -- face(-X in world)
  129. local DIR_Z_STEP= (sz==1) and 1 or 3 -- step toward interior along Z
  130. local DIR_Z_BACK= (sz==1) and 3 or 1 -- return toward origin along Z
  131.  
  132. -- enterDirX must be either DIR_X_POS or DIR_X_NEG
  133. local function serpentine_pass(nx, nz, enterDirX, stepAction)
  134.  
  135. -- First row
  136. face(enterDirX)
  137. stepAction()
  138. for i=2,nx do fwd(); stepAction() end
  139.  
  140. -- Remaining rows
  141. local curDir = enterDirX
  142. for row=1,(nz-1) do
  143. -- advance one row along Z (toward interior)
  144. face(DIR_Z_STEP); fwd()
  145.  
  146. -- flip X direction
  147. curDir = (curDir==DIR_X_POS) and DIR_X_NEG or DIR_X_POS
  148. face(curDir)
  149. stepAction()
  150. for i=2,nx do fwd(); stepAction() end
  151. end
  152.  
  153. -- Return to origin corner in-plane
  154. if (nz % 2)==1 then
  155. -- We ended on the far X edge; go back along X to origin edge
  156. face((curDir==DIR_X_POS) and DIR_X_NEG or DIR_X_POS)
  157. for i=2,nx do fwd() end
  158. end
  159. -- Go back along Z to origin
  160. face(DIR_Z_BACK)
  161. for i=2,nz do fwd() end
  162. end
  163.  
  164. -- ---------- Input ----------
  165. local function readNum(p) term.write(p); local s=read(); local n=tonumber(s); assert(n,"number"); return n end
  166. term.clear(); term.setCursorPos(1,1)
  167. print("Volume Miner by Coordinates (slot1=fuel; 2..16 filler)")
  168. print("Enter X limits first, then Y, then Z. Any order allowed within each pair.")
  169. local x1 = readNum("x1: "); local x2 = readNum("x2: ")
  170. local y1 = readNum("y1: "); local y2 = readNum("y2: ")
  171. local z1 = readNum("z1: "); local z2 = readNum("z2: ")
  172.  
  173. local minX,maxX = math.floor(math.min(x1,x2)), math.floor(math.max(x1,x2))
  174. local minY,maxY = math.floor(math.min(y1,y2)), math.floor(math.max(y1,y2))
  175. local minZ,maxZ = math.floor(math.min(z1,z2)), math.floor(math.max(z1,z2))
  176. local nx = maxX - minX + 1
  177. local ny = maxY - minY + 1
  178. local nz = maxZ - minZ + 1
  179. assert(nx>0 and ny>0 and nz>0, "empty volume")
  180.  
  181. local function assertInside(where)
  182. local x,y,z = gps.locate(2.0)
  183. if not x then error("GPS lost during "..where, 0) end
  184. if x < minX or x > maxX or y < minY or y > maxY or z < minZ or z > maxZ then
  185. error(("ABORT: left volume at %s (%.0f,%.0f,%.0f)"):format(where,x,y,z), 0)
  186. end
  187. end
  188.  
  189. -- Choose the nearest of the four bottom-layer corners (we’ll handle vertical later)
  190. local cx,cy,cz = gpsPos(); assert(cx,"GPS lost")
  191. local candidates = {
  192. {minX,minY,minZ}, {maxX,minY,minZ}, {minX,minY,maxZ}, {maxX,minY,maxZ},
  193. }
  194. local best,bd=nil,1e18
  195. for _,c in ipairs(candidates) do
  196. local d=math.abs(c[1]-cx)+math.abs(c[2]-cy)+math.abs(c[3]-cz)
  197. if d<bd then bd=d; best=c end
  198. end
  199. local ox,oy,oz = table.unpack(best)
  200. local sx = (ox==minX) and 1 or -1
  201. local sz = (oz==minZ) and 1 or -1
  202. local sy = 1 -- we will mine upward in chunks; oy is at minY
  203. log(("Box X[%d..%d] Y[%d..%d] Z[%d..%d] -> %dx%dx%d"):format(minX,maxX,minY,maxY,minZ,maxZ,nx,ny,nz))
  204. log(("Origin corner: (%d,%d,%d) dir sx=%d sz=%d"):format(ox,oy,oz,sx,sz))
  205.  
  206. -- Go to origin corner once
  207. gotoXYZ(ox,oy,oz)
  208.  
  209. -- Orient first-row X direction based on sx
  210. local enterDirX = (sx==1) and DIR_X_POS or DIR_X_NEG
  211.  
  212. -- Before each pass, ensure we are at the plane origin corner (we already are after our return)
  213. local currentY = oy
  214. local remaining = ny
  215.  
  216. -- Helper: raise/lower to specific absolute Y by relative move (no GPS during mining)
  217. local function goToYAbs(targetY)
  218. local x,y,z = gpsPos(); assert(x,"GPS lost")
  219. local dy = targetY - y
  220. if dy>0 then for i=1,dy do up() end
  221. elseif dy<0 then for i=1,-dy do down() end end
  222. end
  223.  
  224. assertInside("start")
  225.  
  226. -- Vertical policy loop
  227. while remaining > 0 do
  228.  
  229. refuel(nx*nz*math.min(remaining,3) + 300)
  230.  
  231. if remaining >= 3 then
  232. -- Middle of the 3-layer chunk
  233. local midY = currentY + 1
  234. goToYAbs(midY)
  235. -- Serpentine on this layer, clearing up and down each cell
  236. serpentine_pass(nx, nz, enterDirX, step_3layer); assertInside("after 3-layer")
  237. currentY = currentY + 3
  238. remaining = remaining - 3
  239.  
  240. elseif remaining == 2 then
  241. -- Upper of the 2-layer chunk
  242. local upperY = currentY + 1
  243. goToYAbs(upperY)
  244. serpentine_pass(nx, nz, enterDirX, step_2layer); assertInside("after 2-layer")
  245. currentY = currentY + 2
  246. remaining = remaining - 2
  247.  
  248. else -- remaining == 1
  249. goToYAbs(currentY)
  250. serpentine_pass(nx, nz, enterDirX, step_1layer); assertInside("after 1-layer")
  251. currentY = currentY + 1
  252. remaining = remaining - 1
  253. end
  254. -- After each pass, we are returned to the same XZ origin corner by serpentine_pass.
  255. end
  256.  
  257. local ex,ey,ez = gpsPos()
  258. log(("Complete. End GPS: (%.1f, %.1f, %.1f)"):format(ex or -1, ey or -1, ez or -1))
  259. print("Mining complete.")
  260.  
Add Comment
Please, Sign In to add comment