· 5 years ago · Apr 18, 2020, 01:58 AM
1-- Quarry Client
2-- PREREQUISITES
3-- *Needs GPS constellation active
4-- *Needs QuarryServer active to be assigned tasks
5-- *Must be wireless mining turtle
6
7-- SETUP
8-- Load file in the shell with : pastebin get <pastecode> QuarryClient.lua
9-- Edit Startup.lua to include the following
10--[[
11 os.loadAPI("QuarryClient.lua")
12 QuarryClient.start()
13--]]
14-- use initialize() from home position
15-- About the home position
16-- ->horizontally adjacent spaces should be air
17-- ->Y coordinate of home position should not be shared with any other home position
18-- ->inventory above should be provided with fuel (coal, coal blocks, blaze rods) A dropper makes sense.
19-- ->inventory below should be empty and automatically emptied. Mined items will be placed here. Any inventory with >=12 will work.
20-- SETUP COMPLETE
21
22-- LOGGER SETUP
23-- To set up a logger for the client, place a computer anywhere with an ender modem and complete the setup outlined in QuarryClientLogger.lua
24-- Then call QuarryClinet.setLoggerID(id) with the logger computer's ID.
25-- LOGGER SETUP COMPLETE
26
27--globals
28quarryProtocol = "quarry"
29logProtocol = "log"
30facing = "undefined"
31loggerID = -1
32
33--functions
34function xTranslate(amount)
35 local i
36 face("E")
37 if amount > 0 then
38 for i = 1, amount, 1 do
39 turtle.forward()
40 end
41 elseif amount < 0 then
42 amount = -amount
43 for i = 1, amount, 1 do
44 turtle.back()
45 end
46 end
47end
48
49function yTranslate(amount)
50 local i
51 if amount > 0 then
52 for i = 1, amount, 1 do
53 turtle.up()
54 end
55 elseif amount < 0 then
56 amount = -amount
57 for i = 1, amount, 1 do
58 if turtle.detectDown() then
59 turtle.digDown()
60 end
61 turtle.down()
62 end
63 end
64end
65
66function zTranslate(amount)
67 local i
68 face("S")
69 if amount > 0 then
70 for i = 1, amount, 1 do
71 turtle.forward()
72 end
73 elseif amount < 0 then
74 amount = -amount
75 for i = 1, amount, 1 do
76 turtle.back()
77 end
78 end
79end
80
81function goToQuarry(xGoal, yGoal, zGoal)
82 local x0,y0,z0,dx,dy,dz
83 print(string.format("Goal: %i %i %i", xGoal, yGoal, zGoal))
84 rednet.send(loggerID, string.format("Goal: %i %i %i", xGoal, yGoal, zGoal), logProtocol)
85 x0, y0, z0 = gps.locate()
86 print(string.format("Location: %i %i %i", x0, y0, z0))
87 rednet.send(loggerID, string.format("Location: %i %i %i", x0, y0, z0), logProtocol)
88 dx = xGoal-x0
89 dy = yGoal-y0
90 dz = zGoal-z0
91 print(string.format("Direction:%i %i %i", dx, dy, dz))
92 rednet.send(loggerID, "Moving to Quarry...", logProtocol)
93-- Go to correct z
94 print("Translating along Z...")
95 zTranslate(dz)
96-- Go to correct x
97 print("Translating along X...")
98 xTranslate(dx)
99-- Go to correct y
100 print("Translating along Y...")
101 yTranslate(dy)
102--Face correctly
103 face("N")
104 print("Arrived At Quarry")
105 rednet.send(loggerID, "Arrived at Quarry", logProtocol)
106end
107
108function getHome()
109 --check if home.txt exists
110 if not fs.exists("home.txt") then
111 print("Home has not been set! Use initialize() from the home position")
112 error()
113 end
114 --open file
115 local file = fs.open("home.txt", "r")
116 --get string table
117 local fileData = {}
118 local line = file.readLine()
119 repeat
120 table.insert(fileData,line)
121 line = file.readline()
122 until line == nil
123 file.close()
124 --convert to numbers
125 local x,y,z
126 x = tonumber(fileData[1])
127 y = tonumber(fileData[2])
128 z = tonumber(fileData[3])
129 return x, y, z
130end
131
132function setHome(x, y, z)
133 --create home.txt
134 local file = fs.open("home.txt", "w")
135 --log formatted string
136 file.write(string.format("%d\n%d\n%d\n",x,y,z))--write x y and z to separate lines
137 file.close()
138end
139
140function goToHome()
141 local x0,y0,z0,dx,dy,dz, xGoal, yGoal, zGoal
142 xGoal, yGoal, zGoal = getHome()
143 print(string.format("Goal: %i %i %i", xGoal, yGoal, zGoal))
144 rednet.send(loggerID, "Moving to Home...", logProtocol)
145 x0, y0, z0 = gps.locate()
146 print(string.format("Location: %i %i %i", x0, y0, z0))
147 dx = xGoal-x0
148 dy = yGoal-y0
149 dz = zGoal-z0
150 print(string.format("Direction:%i %i %i", dx, dy, dz))
151-- Go to correct y
152 print("Translating along Y...")
153 yTranslate(dy)
154-- Go to correct x
155 print("Translating along X...")
156 xTranslate(dx)
157-- Go to correct z
158 print("Translating along Z...")
159 zTranslate(dz)
160-- Flip around
161 face("N")
162 print("Arrived at Home")
163 rednet.send(loggerID, "Arrived at Home", logProtocol)
164end
165
166function determineFacing()
167 local x0,y0,z0,x1,y1,z1
168 facing = ""
169 x0, y0, z0 = gps.locate()
170 if turtle.detect() then
171 turtle.dig()
172 end
173 turtle.forward()
174 x1, y1, z1 = gps.locate()
175 turtle.back()
176 if x0 == x1 then
177 if z1>z0 then facing = "S"
178 elseif z1<z0 then facing = "N"
179 end
180 elseif z0 == z1 then
181 if x1>x0 then facing = "E"
182 elseif x1<x0 then facing = "W"
183 end
184 end
185end
186
187function face(faceGoal)
188 while not (facing == faceGoal) do
189 facingTurnRight()
190 end
191end
192
193function facingTurnRight()
194 turtle.turnRight()
195 if facing == "N" then facing = "E"
196 elseif facing == "E" then facing = "S"
197 elseif facing == "S" then facing = "W"
198 elseif facing == "W" then facing = "N"
199 end
200end
201
202function facingTurnLeft()
203 turtle.turnRight()
204 if facing == "N" then facing = "W"
205 elseif facing == "W" then facing = "S"
206 elseif facing == "S" then facing = "E"
207 elseif facing == "E" then facing = "N"
208 end
209end
210
211function getFacing()
212 return facing
213end
214
215function goToChunkOrigin()
216 local x0,y0,z0,dx,dy,dz
217 x0, y0, z0 = gps.locate()
218 dx = -math.mod(x0,16)
219 dz = -math.mod(z0,16)
220 rednet.send(loggerID, "Moving to Chunk Origin...", logProtocol)
221-- Go to correct x
222 print("Translating along X...")
223 xTranslate(dx, facing)
224-- Go to correct z
225 print("Translating along Z...")
226 zTranslate(dz, "E")
227 print("Arrived at Chunk Origin.")
228 rednet.send(loggerID, "Arrived at Chunk Origin", logProtocol)
229end
230
231function mineLayer(depth)
232 local x,y,z,i,j,k,count
233 goToChunkOrigin()
234 x,y,z = gps.locate()
235
236 for k = y,depth-1,-1 do
237 if turtle.detectDown() then
238 turtle.digDown()
239 count = count + 1
240 end
241 turtle.down()
242 end
243
244 for i = 0,15,1 do
245 for j = 0,15,1 do
246 if turtle.detectUp() then
247 turtle.digUp()
248 count = count + 1
249 end
250 if turtle.detectDown() then
251 turtle.digDown()
252 count = count + 1
253 end
254 if turtle.detect() and j~=15 then
255 turtle.dig()
256 count = count + 1
257 end
258 if j~=15 then
259 turtle.forward()
260 elseif i~=15 then
261 --position for next strip
262 face("E")
263 if turtle.detect() then
264 turtle.dig()
265 count = count + 1
266 end
267 turtle.forward()
268 if math.mod(j,2)==0 then
269 turtle.turnRight()
270 facing = "S"
271 else
272 turtle.turnLeft()
273 facing = "N"
274 end
275 end
276 end
277 end
278 return count
279end
280
281function hasEnoughFuelToMine()
282 --sum dx, dy, dz
283 local x0,y0,z0,dx,dy,dz, xGoal, yGoal, zGoal, sum
284 x0,y0,z0 = gps.locate()
285 xGoal,yGoal,zGoal = getHome()
286 dx = math.abs(xGoal-x0)
287 dy = math.abs(yGoal-y0)
288 dz = math.abs(zGoal-z0)
289 sum = dx+dy+dz+256
290
291 return turtle.getFuelLevel()>sum
292end
293
294function hasEnoughSpaceToMine()
295 local filledSlotCount = 0
296 local i
297 for i=1,16,1 do
298 if turtle.getItemCount(i) > 0 then
299 filledSlotCount = filledSlotCount + 1
300 end
301 end
302 return filledSlotCount<=9
303end
304
305
306function dropItemsDown()
307 local i
308 for i = i, 16, 1 do
309 turtle.select(i)
310 turtle.dropDown(64)
311 end
312end
313
314function refuelUp()
315 turtle.suckUp(64)
316 turtle.refuel()
317 turtle.dropDown(64)
318end
319
320function getLoggerID()
321 --check if home.txt exists
322 if not fs.exists("loggerID.txt") then
323 print("loggerID has not been set. Use setLoggerID(id) if you wish.")
324 return os.getComputerID()
325 end
326 --open file
327 local file = fs.open("loggerID.txt", "r")
328 --get string
329 local fileData = {}
330 local line = file.readLine()
331 repeat
332 table.insert(fileData,line)
333 line = file.readline()
334 until line == nil
335 file.close()
336 local idStr = fileData[1]
337 --convert to number
338 local id = tonumber(idStr)
339 return id
340end
341
342function setLoggerID(id)
343 --create loggerID.txt
344 local file = fs.open("loggerID.txt", "w")
345 --log formatted string
346 file.writeLine(string.format("%d",id))
347 file.close()
348end
349
350function split(s, delimiter)
351 result = {};
352 for match in (s..delimiter):gmatch("(.-)"..delimiter) do
353 table.insert(result, match);
354 end
355 return result;
356end
357
358function initialize() --easy setup
359 rednet.open("left")
360 loggerID = getLoggerID()
361 rednet.send(loggerID, "Logger Initialized", logProtocol)
362 local x,y,z
363 x,y,z = gps.locate()
364 setHome(x,y,z)
365 print("Home set to current location")
366 rednet.send(loggerID, "Home set to current location", logProtocol)
367 determineFacing()
368 face("N")
369 main()
370end
371
372function main()
373 while true do
374 repeat
375 print("Requesting chunk assignment...")
376 rednet.send(loggerID, "Requesting chunk assignment...", logProtocol)
377 --send rednet request over quarry protocol with ID
378 rednet.broadcast("REQUEST", quarryProtocol)
379 --listen for response
380 id = nil
381 message = nil
382 local id, message = rednet.receive(quarryProtocol, 10)--wait 10 seconds. if disabled by server, no response will be set and program will hang here
383 rednet.broadcast("ACCEPTED", quarryProtocol)
384 until message ~= nil
385 --parse message format is "cx cz depth"
386 local messageStrs = split(message, " ")
387 local cx, cz, x, y, z, assignedDepth
388 cx = tonumber(messageStrs[1])
389 cz = tonumber(messageStrs[2])
390 assignedDepth = tonumber(messageStrs[3])
391 rednet.send(loggerID, string.format("Assignment recieved: %d %d at depth %d", cx, cy, assignedDepth))
392 --calculate target position
393 x = 16*cx
394 z = 16*cz
395 y = assignedDepth
396 print("Moving to assigned chunk...")
397 rednet.send(loggerID, "Moving to assigned chunk...", logProtocol)
398 goToQuarry(x,y,z)
399 local keepMining = true
400 while keepMining do
401 print(string.format("Mining at depth %d...", assignedDepth))
402 rednet.send(loggerID, string.format("Mining at depth %d...", assignedDepth), logProtocol)
403 --mine the next three layers!
404 local blocksMined = mineLayer(assignedDepth)
405 --update mining depth
406 if assignedDepth == 8 then assignedDepth = 6
407 elseif assignedDepth == 7 then assignedDepth = 6
408 else assignedDepth = assignedDepth-3
409 end
410 --send update over rednet (chunk coords)(assignedDepth)(blocks mined) !don't proceed until response received!
411 local id, message
412 repeat
413 rednet.broadcast("PROGRESS", quarryProtocol)
414 id = nil
415 message = nil
416 id, message = rednet.recieve(quarryProtocol, 1)
417 until message == "READY"
418 repeat
419 rednet.broadcast(string.format("%d %d %d %d", cx, cz, assignedDepth, blocksMined), quarryProtocol)
420 id = nil
421 message = nil
422 id, message = rednet.recieve(quarryProtocol, 1)
423 until message == "ACCEPTED"
424 --check if should keepMining
425 if assignedDepth < 6 then
426 print("Reached Bedrock")
427 rednet.send(loggerID, "Reached Bedrock", logProtocol)
428 keepMining = false
429 end
430 if not hasEnoughFuelToMine() then
431 print("Need more fuel to continue mining")
432 rednet.send(loggerID, "Need more fuel to continue mining", logProtocol)
433 keepMining = false
434 end
435 if not hasEnoughSpaceToMine() then
436 print("Need more inventory space to continue mining")
437 rednet.send(loggerID, "Need more inventory space to continue mining", logProtocol)
438 keepMining = false
439 end
440 end
441 --inform server that work has stopped
442 local id, message
443 repeat
444 rednet.broadcast("STOPPING", quarryProtocol)
445 id = nil
446 message = nil
447 id, message = rednet.recieve(quarryProtocol, 1)
448 until message == "READY"
449 repeat
450 rednet.broadcast(string.format("%d %d", cx, cz), quarryProtocol)
451 id = nil
452 message = nil
453 id, message = rednet.recieve(quarryProtocol, 1)
454 until message == "ACCEPTED"
455 --go to Home
456 print("Moving to Home...")
457 rednet.send(loggerID, "Moving to Home...", logProtocol)
458 goToHome()
459 print("Unloading Items...")
460 rednet.send(loggerID, "Unloading Items...", logProtocol)
461 dropItemsDown()
462 print("Refueling...")
463 rednet.send(loggerID, "Refueling...", logProtocol)
464 refuelUp()
465 end
466end
467
468function start()
469 rednet.open("left")
470 os.sleep(1) --to allow logger to start
471 loggerID = getLoggerID()
472 print("Quarry Client has started!")
473 rednet.send(loggerID, "Quarry Client has started!", logProtocol)
474 print(string.format("ID: %d", os.getComputerID()))
475 print("Determining Facing...")
476 rednet.send(loggerID, "Determining Facing...", logProtocol)
477 determineFacing()
478 face("N")
479 local x,y,z = gps.locate()
480 local xHome, yHome, zHome = getHome()
481 if not (x == xHome and y == yHome and z == zHome) then
482 print("Moving to Chunk Origin...")
483 rednet.send(loggerID, "Moving to Chunk Origin...", logProtocol)
484 goToChunkOrigin()
485 print("Moving to Home...")
486 rednet.send(loggerID, "Moving to Home...", logProtocol)
487 goToHome()
488 else
489 print("Current position is Home")
490 end
491 print("Unloading Items...")
492 rednet.send(loggerID, "Unloading Items...", logProtocol)
493 dropItemsDown()
494 print("Refueling...")
495 rednet.send(loggerID, "Refueling...", logProtocol)
496 refuelUp()
497 main()
498end