﻿ # Turtle_Base

Nov 23rd, 2020 (edited)
702
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. home = {x = nil, y = nil, z = nil, direction = nil, globalRotation = nil}
2.
3. location = {x = nil, y = nil, z = nil, direction = nil}
4.
5. work = {x = nil, y = nil, z = nil, direction = nil}
6.
7. listeners = {}
8.
9. validTools = {crafting = "Crafting", pickaxe = "Pickaxe", axe = "Axe", shovel = "Shovel", hoe = "Hoe", modem = "Modem", none = "None"}
10. tools = {left = validTools.none, right = validTools.none}
11.
12. fuel = { "minecraft:coal", "minecraft:charcoal" }
13.
14. function init(requiresTools, equippedTools)
16.   initRednet()
17.   -- find out where we are by knowing where we aren't
18.   local x, y, z, dir, startDir = getInitialPosition()
19.   initHome(x, y, z, dir)
20.   location.x = x
21.   location.y = y
22.   location.z = z
23.   location.direction = dir
24.   rotateTo(startDir)
25.   if requiresTools and not equippedTools then
26.     getTools()
27.   elseif requiresTools and equippedTools then
28.     tools = equippedTools
29.   end
30.   sendStatus("Init Complete")
31. end
32.
33. function canDig()
35. end
36.
37. -- global rotations
38. -- 0 = north
39. -- 1 = east
40. -- 2 = south
41. -- 3 = west
42.
43. function convertToLocal(newX, newZ)
44.   if not newX or not newZ then
45.     newX = location.x
46.     newZ = location.z
47.   end
48.   if home.globalRotation == 0 then
49.     return {x = newX, z = newZ}
50.   elseif home.globalRotation == 1 then
51.     return {x = -newZ, z = newX}
52.   elseif home.globalRotation == 2 then
53.     return {x = -newX, z = -newZ}
54.   else
55.     return {x = newZ, z = -newX}
56.   end
57. end
58.
59. -- (literal global direction)
60. -- global rotations:
61. -- north = 0
62. -- east = 1
63. -- south = 2
64. -- west = 3
65.
66. -- (relative to the rotation of the start position)
67. -- local rotations
68. -- forwards = 0
69. -- right = 1
70. -- backwards = 2
71. -- left = 3
72.
73. -- home.globalRotation = 0 local rotation
74. -- location.direction = relative rotation
75. -- this function needs to convert local (relative to home) rotation to world rotation
76. function getGlobalRotation()
77.   return (location.direction + home.globalRotation) % 4
78. end
79.
80. function getInitialPosition()
81.   -- find current global rotation
82.   local x1, y1, z1 = gps.locate()
83.   local globalRotation = nil
84.   foundRotation = false
85.   attempts = 0
86.   -- find global rotation by moving and comparing gps position
88.     move = turtle.forward()
89.     local x2, y2, z2 = gps.locate()
90.     if move then
91.       if (x1 < x2) then globalRotation = 3
92.       elseif(z1 > z2) then globalRotation = 2
93.       elseif(x1 > x2) then globalRotation = 1
94.       elseif(z1 < z2) then globalRotation = 0 end
95.       foundRotation = true
96.       turtle.turnLeft()
97.       turtle.turnLeft()
98.       turtle.forward()
99.     else
100.       turtle.turnLeft()
101.       attempts = attempts + 1
102.     end
103.   end
104.
105.   -- error out if rotation could not be found
107.     sendStatus("Could not find rotation")
108.     error()
109.   end
110.
111.   local startGlobalRotation = (globalRotation - attempts - 2) % 4
112.   -- get offset from global Rotation
113.   home.globalRotation = settings.get("HomeGlobalRotation", startGlobalRotation)
114.   local direction = globalToLocalRotation(globalRotation)
115.   -- find initial direction
116.   local startDirection = globalToLocalRotation(startGlobalRotation)
117.   return x1, y1, z1, direction, startDirection
118. end
119.
120. -- get rotation relative to global home rotation
121. function globalToLocalRotation(globalRotation)
122.   local direction
123.   if globalRotation == home.globalRotation then direction = 0
124.   elseif (globalRotation + 1) % 4 == home.globalRotation then direction = 1
125.   elseif (globalRotation - 1) % 4 == home.globalRotation then direction = 3
126.   else direction = 2 end
127.   return direction
128. end
129.
130. function initHome(x, y, z, dir)
132.   home.x = settings.get("HomeXPos", x)
133.   home.y = settings.get("HomeYPos", y)
134.   home.z = settings.get("HomeZPos", z)
135.   home.direction = settings.get("HomeRotation", dir)
136.   saveHome()
137. end
138.
139. function saveHome()
141.   settings.set("HomeXPos", home.x)
142.   settings.set("HomeYPos", home.y)
143.   settings.set("HomeZPos", home.z)
144.   settings.set("HomeRotation", home.direction)
145.   settings.set("HomeGlobalRotation", home.globalRotation)
146.   settings.save("settings")
147. end
148.
149. function updateWorklocation()
150.   work.x = location.x
151.   work.y = location.y
152.   work.z = location.z
153.   work.direction = location.direction
154. end
155.
156. function moveToPosition(newX, newY, newZ, newDir, name)
157.   if not newDir then newDir = 0 end
158.   if not name then name = "Somewhere" end
159.
160.   local blockages = 0
161.   local newLocation = {x = newX, y = newY, z = newZ, direction = newDir}
162.   local moved = false
163.
164.   while not compareLocations(location, newLocation, false) and blockages < 10 do
165.     sendStatus("Moving to "..name.. ":\n["..newX..", "..newY..", "..newZ..", "..newDir.."]")
166.     -- move to new Y location
167.     while location.y ~= newY do
168.       if location.y > newY then
169.         moved = moveDown()
170.       elseif location.y < newY then
171.         moved = moveUp()
172.       end
173.       if not moved then
174.         blockages = blockages +1
175.         break
176.       end
177.     end
178.     -- move to new X location
179.     while location.x ~= newX do
180.       if location.x > newX then
181.         if getGlobalRotation() ~= 3 then rotateToGlobal(3) end
182.         moved = moveForward()
183.       elseif location.x < newX then
184.         if getGlobalRotation() ~= 1 then rotateToGlobal(1) end
185.         moved = moveForward()
186.       end
187.       if not moved then
188.         blockages = blockages + 1
189.         break
190.       end
191.     end
192.     -- move to new Z location
193.     while location.z ~= newZ do
194.       if location.z > newZ then
195.         if getGlobalRotation() ~= 2 then rotateToGlobal(2) end
196.         moved = moveForward()
197.       elseif location.z < newZ then
198.         if getGlobalRotation() ~= 0 then rotateToGlobal(0) end
199.         moved = moveForward()
200.       end
201.       if not moved then
202.         blockages = blockages + 1
203.         break
204.       end
205.     end
206.   end
207.   rotateTo(newDir)
208.   return compareLocations(location, newLocation)
209. end
210.
211. function compareLocations(tab1, tab2, includeRotation)
212.   if includeRotation then
213.     return tab1.x == tab2.x and tab1.y == tab2.y and tab1.z == tab2.z and tab1.direction == tab2.direction
214.   else
215.     return tab1.x == tab2.x and tab1.y == tab2.y and tab1.z == tab2.z
216.   end
217. end
218.
219. function locationNil(tab)
220.   return not tab.x or not tab.y or not tab.z or not tab.direction
221. end
222.
223. function rotateLeft()
224.   location.direction = location.direction-1
225.   if (location.direction == -1) then
226.     location.direction = 3
227.   end
228.   turtle.turnLeft()
229. end
230.
231. function rotateRight()
232.   location.direction = location.direction+1
233.   if (location.direction == 4) then
234.     location.direction = 0
235.   end
236.   turtle.turnRight()
237. end
238.
239. function rotateTo(newDir)
240.   if location.direction == newDir then
241.     return
242.   elseif (location.direction + 1) % 4 == newDir then
243.     rotateRight()
244.   elseif (location.direction - 1) % 4 == newDir then
245.     rotateLeft()
246.   else
247.     while location.direction ~= newDir do
248.       rotateLeft()
249.     end
250.   end
251. end
252.
253. function rotateToGlobal(newDir)
254.   local globalRotation = getGlobalRotation()
255.   print("Rotating to ".. newDir)
256.   if globalRotation == newDir then
257.     return
258.   elseif (globalRotation + 1) % 4 == newDir then
259.     rotateRight()
260.   elseif (globalRotation - 1) % 4 == newDir then
261.     rotateLeft()
262.   else
263.     while getGlobalRotation() ~= newDir do
264.       rotateLeft()
265.     end
266.   end
267. end
268.
269. function moveForward()
270.   -- if able to dig clear out blocks in front
271.   if canDig() then
272.     while turtle.detect() do
273.       turtle.dig()
274.     end
275.   end
276.   moved = turtle.forward()
277.   if moved then
278.     rotation = getGlobalRotation()
279.     if rotation == 0 then
280.       location.z = location.z+1
281.     elseif rotation == 1 then
282.       location.x = location.x+1
283.     elseif rotation == 2 then
284.       location.z = location.z-1
285.     elseif rotation == 3 then
286.       location.x = location.x-1
287.     end
288.     return true
289.   else
290.     return false
291.   end
292. end
293.
294. -- returns true on valid movement
295. function moveUp()
296.   if canDig() then
297.     while turtle.detectUp() do
298.       turtle.digUp()
299.     end
300.   end
301.   local moved = turtle.up()
302.   if not moved then return false end
303.   location.y = location.y + 1
304.   return true
305. end
306.
307. function moveDown()
308.   if canDig() then
309.     while turtle.detectDown() do
310.       turtle.digDown()
311.     end
312.   end
313.   local moved = turtle.down()
314.   if not moved then return false end
315.   location.y = location.y - 1
316.   return true
317. end
318.
319. function currentPosition()
320.   local direction = location.direction or -1
321.   local x, y, z
322.   if not x or not y or not z then
323.     x, y, z = gps.locate()
324.   else
325.     x = location.x
326.     y = location.y
327.     z = location.z
328.   end
329.   return "[".. x..", ".. y..", ".. z..", ".. direction .."]"
330. end
331.
332. function returnHome()
333.   local returnedHome = moveToPosition(home.x, home.y, home.z, home.direction, "Home")
334.   if not returnedHome then
335.     sendStatus("I'm stuck ;-;")
336.     error()
337.   end
338. end
339.
340. function returnToWork()
341.   if locationNil(work) then
342.     sendStatus("attempted to return to work when I have no work location")
343.     error()
344.   end
345.   local returnedToWork = moveToPosition(work.x, work.x, work.z, work.direction, "Work")
346.   if not returnedToWork then
347.     sendStatus("I'm stuck ;-;")
348.     error()
349.   end
350. end
351.
352. function getValidToolText()
353.   local text = ""
354.   for k, v in pairs(validTools) do
355.     if text ~= "" then text = text.. ", " end
356.     text = text .. v
357.   end
358.   return text
359. end
360.
361. function getTools()
362.   local complete = false
363.   local toolText = "Valid Tools: ".. getValidToolText()
364.   local sides = peripheral.getNames()
365.   if tableContains("left", sides) then
366.     complete = true
367.     tools.left = validTools.modem
368.   end
369.   while not complete do
370.     term.clear()
371.     term.setCursorPos(1,1)
372.     print(toolText)
373.     io.write("Enter Left Tool: ")
375.     local valid, leftTool = validTool(leftTool)
376.     if valid then
377.       complete = true
378.       tools.left = leftTool
379.     end
380.   end
381.   complete = false
382.   if tableContains("right", sides) then
383.     complete = true
384.     tools.right = validTools.modem
385.   end
386.   while not complete do
387.     term.clear()
388.     term.setCursorPos(1,1)
389.     print(toolText)
390.     io.write("Enter Right Tool: ")
392.     local valid, rightTool = validTool(rightTool)
393.     if valid then
394.       complete = true
395.       tools.right = rightTool
396.     end
397.   end
398. end
399.
400. function validTool(tool)
401.   for k,v in pairs(validTools) do
402.     if string.lower(v) == string.lower(tool) then
403.       return true, v
404.     end
405.   end
406.   return false, validTools.none
407. end
408.
409. function tableContains(str, table)
410.   for k, v in pairs(table) do
411.     if v == str then return true end
412.   end
413.   return false
414. end
415.
416. function resetSettings()
418.   settings.clear()
419.   settings.save("settings")
420. end
421.
422. function findItem(id)
423.   local itemTable = {}
424.   for i = 1, 16, 1 do
425.     local slotData = turtle.getItemDetail(i)
426.     if (slotData and slotData.name == id) then
427.       table.insert(itemTable, i)
428.     end
429.   end
430.   if table.getn(itemTable) > 0 then
431.     return itemTable
432.   end
433.   return nil
434. end
435.
436. -- returns true if empty slot was found ant item was moved
437. function moveItemToEmpty(slot)
438.   turtle.select(slot)
439.   for i = 1, 16, 1 do
440.     if i ~= slot then
441.       if turtle.transferTo(i) then
442.         return true
443.       end
444.     end
445.   end
446.   return false
447. end
448.
449. -- returns true if space remains
450. function checkSpace()
451.   for i = 1, 16, 1 do
452.     if not turtle.getItemDetail(i) then
453.       return true
454.     end
455.   end
456.   return false
457. end
458.
459. function minifyStacks()
460.   for i = 16, 1, -1 do
461.     local slotData = turtle.getItemDetail(i)
462.     if slotData then
463.       slotsTable = findItem(slotData.name)
464.       if slotsTable and table.getn(slotsTable) > 1 then
465.         for k,v in pairs(slotsTable or {}) do
466.           turtle.select(v)
467.           turtle.transferTo(i, turtle.getItemSpace(i))
468.         end
469.       end
470.     end
471.   end
472. end
473.
474. -- returns home and requests more fuel
475. function giveMeFuel()
476.   while not hasFuel() do
477.     sleep(2)
478.   end
479.   returnToWork()
480. end
481.
482. -- attempts to fill fuel slot, returns true if enough fuel is located in the fuel slot.
483. function hasFuel()
484.   local fuelSlots = {}
485.
486.   local slotData = turtle.getItemDetail(1)
487.   -- search the first slot for a valid fuel item
488.   for k,v in pairs(fuel or {}) do
489.     -- find if any other slots contain any fuel
490.     local slotTable = findItem(v)
491.     table.insert(fuelSlots, slotTable)
492.
493.     -- look in slot one, if contains fuel return
494.     if (slotData and slotData.name == v) then
495.       return turtle.getItemCount(1) > 1, slotTable
496.     end
497.   end
498.
499.   -- move item out of fuel slot
500.   if slotData then
501.     moveItemToEmpty(1)
502.   end
503.
504.   -- move valid fuel into slot
505.   for k,v in pairs(fuelSlots or {}) do
506.     if v then
507.       if table.getn(v) > 0 then
508.         turtle.select(v)
509.         turtle.transferTo(1)
510.       end
511.       return turtle.getItemCount(1) > 1, v
512.     end
513.   end
514.   return false, nil
515. end
516.
517. function isFuel(slotData)
518.   for k,v in pairs(fuel or {}) do
519.     if slotData.name == v then return true end
520.   end
521.   return false
522. end
523.
524. function getMinFuelLevel()
525.   if locationNil(work) or locationNil(home) then return 800 end
526.   return math.abs(work.x) + math.abs(work.z) + math.abs(home.y - work.y) + 50
527. end
528.
529. -- checks fuel levels and attempts to refuel the turtle
530. function refuel()
531.   local hasFuelLeft, fuelSlots = hasFuel()
532.   if turtle.getFuelLevel() < getMinFuelLevel() then
533.     if not hasFuelLeft then
534.       giveMeFuel()
535.     end
536.   end
537.
538.   if turtle.getFuelLevel() < 5120 then
539.     turtle.select(1)
540.     coalCount = turtle.getItemCount(1)
541.     if coalCount > 0 then turtle.refuel(coalCount-1) end
542.   end
543. end
544.
545. function offsetFromHome()
546.   return {x = home.x - location.x, y = home.y - location.y, z = home.z - location.z}
547. end
548.
549. function getListeners()
550.   listeners = {rednet.lookup("turtle_status")}
551.   if listeners then
552.     for k, v in pairs(listeners) do
553.       rednet.send(v, "request_connect")
554.     end
555.   end
556. end
557.
558. function sendStatus(status)
559.   for k, v in pairs(listeners) do
560.     rednet.send(v, status.. "\n" .. currentPosition())
561.   end
562. end
563.
564. function dumpExtraStacks(itemId)
565.   items = findItem(itemId)
566.   if items and #items > 1 then
567.     for i = 2, #items, 1 do
568.       turtle.select(items[i])
569.       turtle.drop()
570.     end
571.   end
572. end
573.
574. function openRednet()
575.   side = getModemSide()
576.   if not side then error("could not find modem") end
577.   rednet.open(side, 255)
578. end
579.
580. function getModemSide()
581.   sides = peripheral.getNames()
582.   for k, v in pairs(sides) do
583.     if peripheral.getType(v) == "modem" then return v end
584.   end
585.   return nil
586. end
587.
588. function initRednet()
589.   term.clear()
590.   term.setCursorPos(1,1)
591.   print("Initialising Rednet System")
592.   openRednet()
593.   getListeners()
594. end
595.
596. return {home = home, fuel = fuel, location = location, work = work, validTools = validTools, tools = tools, canDig = canDig, getInitialPosition = getInitialPosition, initHome = initHome, saveHome = saveHome, updateWorklocation = updateWorklocation, moveToPosition = moveToPosition, compareLocations = compareLocations, locationNil = locationNil, rotateLeft = rotateLeft, rotateRight = rotateRight, rotateTo = rotateTo, moveForward = moveForward, moveUp = moveUp, moveDown = moveDown, returnHome = returnHome, returnToWork = returnToWork, init = init, getValidToolText = getValidToolText, getTools = getTools, validTool = validTool, tableContains = tableContains, resetSettings = resetSettings, findItem = findItem, moveItemToEmpty = moveItemToEmpty, checkSpace = checkSpace, minifyStacks = minifyStacks, giveMeFuel = giveMeFuel, hasFuel = hasFuel, getMinFuelLevel = getMinFuelLevel, refuel = refuel, sendStatus = sendStatus, currentPosition = currentPosition, convertToLocal = convertToLocal, getGlobalRotation = getGlobalRotation, dumpExtraStacks = dumpExtraStacks, offsetFromHome = offsetFromHome, rotateToGlobal = rotateToGlobal}
597.
RAW Paste Data