View difference between Paste ID: DtWu49r7 and VXAyXqBv
SHOW: | | - or go back to the newest paste.
1
-- GPS Deploy 1.2 - update by Dog aka HydrantHunter
2
-- http://www.computercraft.info/forums2/index.php?/topic/18830-dogs-progs-for-stargates-biolocks-and-more/
3
-- pastebin: VXAyXqBv
4
--
5
-- This script is originally from BigSHinyToys from ComputerCraft.info
6
-- Original link can be found here:
7
-- http://www.computercraft.info/forums2/index.php?/topic/3088-how-to-guide-gps-global-position-system/page__p__28333#entry28333
8
--
9
-- Modifications included (line numbers no longer valid):
10
--
11
-- GPS Deploy by neonerZ v1.1
12
-- http://youtube.com/neonerz
13
-- http://www.computercraft.info/forums2/index.php?/topic/9528-gps-deploy-11-updated-04012014/
14
--
15
-- happydude11209: Line 209 - added logic to check if the server is set to no fuel mode
16
-- http://www.computercraft.info/forums2/index.php?/topic/9528-gps-deploy-10/page__view__findpost__p__123411
17
--
18
-- kittykiller: Line 110 - Bug in the locate code if you were using an existing GPS system to deploy a new one
19
-- http://www.computercraft.info/forums2/index.php?/topic/9528-gps-deploy-10/page__view__findpost__p__80323
20
--
21
-- Mad_Professor: Line 296 - Bug calling computers, monitors. Making people think they needed to load 4 monitors
22
-- http://www.computercraft.info/forums2/index.php?/topic/9528-gps-deploy-10/page__view__findpost__p__150291
23
--
24
-- Dog: Too many fixes and changes to list - based on v1.1:
25
--   Localized variables, reformatted table construction, eliminated duplicate
26
--   and unnecessary sanity checks, reduced use of tonumber() and turtle calls,
27
--   added automatic modem finding and an error for non-wireless turtles when
28
--   using 'locate', automatic GPS host computer labeling (respects currently
29
--   labeled computers), custom host support re-enabled, emergency
30
--   return-to-start when unable to complete the job, re-ordered the program to
31
--   make it more linear, converted many variables to camelCase, and more.
32
--   Reasonably well tested with 100% accuracy in all tests.
33
--
34
-- In order to use this script you need to setup
35
-- either a mining turtle, or a standard turtle
36
-- Mining Turtle:
37
--          Slot 1 - Fuel
38
--          Slot 2 - 1 floppy disk
39
--          Slot 3 - 1 disk drive
40
--          Slot 4 - 4 wireless modems
41
--          Slot 5 - 4 computers (labeled, unlabeled, or mixed) across
42
--                      slots 5, 6, 7, 8 (unlabeled computers may be stacked)
43
-- Non-Mining Turtle:
44
--          Slot 1 - Fuel
45
--          Slot 2 - 1 floppy disk
46
--          Slot 3 - 4 disk drives
47
--          Slot 4 - 4 wireless modems
48
--          Slot 5 - 4 computers (labeled, unlabeled, or mixed) across
49
--                      slots 5, 6, 7, 8 (unlabeled computers may be stacked)
50
--
51
-- (mining turtles will be able to reuse the same
52
--  disk drive, where-as a standard turtle will leave
53
--  them and deploy a separate disk drive for each
54
--  GPS host)
55
--
56
-- Default Usage: Place the turtle where you want it
57
--    deployed facing the SOUTH or 0 direction.
58
--    Fill the turtle with the required materials
59
--    above. Then use the command
60
--
61
--    gps-deploy x y z
62
--
63
--    Where x, y, z is the *absolute* position of the deployment
64
--    turtle. By default the turtle will deploy the
65
--    the GPS array at around y = 254. Add a fourth
66
--    value to specify the height offset.
67
--    IMPORTANT: It's crucial you use your absolute coordinates,
68
--     (the ones inside the parentheses next to your relative coordinates)
69
--     For Example: If F3 shows X = -6.43534 (-7) or Z = -15.542 (-16)
70
--     you'd use -7 and -16 respectively. If you use -6 and -15 all coordinates
71
--     that go past 0 in the opposite direction will be off by 1.)
72
--
73
--    Example: gps-deploy 1 1 1 20
74
--
75
--    Would assume the turtle's start position is
76
--    x = 1, y = 1, z = 1 and will deploy the satellite
77
--    array at y = 21
78
--
79
-- neonerZ added features
80
--  Smart Refilling: Fuel should go in slot 1.
81
--    If not enough fuel is available script
82
--    will prompt user for more fuel and wait 30.
83
--    Script will estimate how much fuel is needed
84
--    and try to take only that much (in coal)
85
--  Item Detection: Script will check slots 2-5
86
--    for the correct quantity of items. It does
87
--    *not* check if items are valid
88
--  GPS Host Coordinates: The script now requires
89
--    you to enter in the coordinates of the
90
--    turtle before launching. This will set
91
--    the GPS host computers to the correct
92
--    coordinates.
93
--  Satelite Array Location: The script allows
94
--    the user to set an offset for the placement
95
--    of the four satellites
96
97
-- check if the script is running on a turtle
98
-- (original code - modified by Dog)
99
if not turtle then error("Error: Not a turtle.\n", 0) end
100
101
-- How high up should the satellite be deployed?
102
-- This is not absolute height, but relative height.
103
-- This is the default value if you don't pass a
104
-- value to the script. There is a check down below
105
-- to make sure the absolute height isn't > 254
106
local height, currentHeight, MAXHEIGHT = 254, 0, 254
107
local tArgs, xCoord, yCoord, zCoord, modemSide = { ... }
108
109
term.setBackgroundColor(colors.black)
110
term.clear()
111
112
-- determine if the turtle has a wireless modem (for 'locate' and coord verification at the end)
113
for _, side in pairs({ "left", "right" }) do
114
  if peripheral.isPresent(side) and peripheral.getType(side) == "modem" and peripheral.call(side, "isWireless") then
115
    modemSide = side
116
    break
117
  end
118
end
119
120
-- Check to see if the necessary values were
121
-- passed to the script
122
-- confirm absolute height isn't set above 254
123
if tArgs[1] == "locate" then
124
  if not modemSide then error("Error: Wireless turtle required for auto-location.\n", 0) end
125
  print("Locating GPS signal...\n")
126
  rednet.open(modemSide)
127
  xCoord, yCoord, zCoord = gps.locate(3)
128
  rednet.close(modemSide)
129
  if not xCoord then error("No GPS signal detected, please re-run manually.\n", 0) end
130
  if tArgs[2] and tonumber(tArgs[2]) then
131
    height = math.min(MAXHEIGHT - yCoord, tonumber(tArgs[2]))
132
  else
133
    height = MAXHEIGHT - yCoord
134
  end
135
else
136
  if (#tArgs < 3 or #tArgs > 4) or (not tonumber(tArgs[1]) or not tonumber(tArgs[2]) or not tonumber(tArgs[3])) then
137
    local prog = shell.getRunningProgram()
138
    print("Usage:\n")
139
    print(prog .. " <x> <y> <z> [height]")
140
    print(" - or -")
141
    print(prog .. " locate [height]\n")
142
    print("Height is relative to your position.")
143
    print("Example: " .. prog .. " 1 1 1 20")
144
    print("would deploy the satellite to y = 21.\n")
145
    print("If you have working GPS use 'locate'")
146
    print("to automatically set the start coords.")
147
    return
148
  else
149
    xCoord = tonumber(tArgs[1])
150
    yCoord = tonumber(tArgs[2])
151
    zCoord = tonumber(tArgs[3])
152
    if tArgs[4] and tonumber(tArgs[4]) then
153
      height = math.min(MAXHEIGHT - yCoord, tonumber(tArgs[4]))
154
    else
155
      height = MAXHEIGHT - yCoord
156
    end
157
  end
158
end
159
160
-- Check if we have enough fuel
161
-- we estimate the fuel usage ((height * 2) + 70) needed to
162
-- complete the deployment and then see if we have enough
163
-- fuel loaded. If we don't, it checks the first slot for
164
-- available fuel and tries to fill up on it. If it doesn't
165
-- have enough fuel in there, it prompts the user for more
166
-- fuel. It allows 30 seconds for the user to add  fuel
167
-- (trying to refuel and verify fuel level every second)
168
-- and if it doesn't get it's fill within 30 seconds
169
-- it exits with a message to the user
170
-- neonerZ (updated by Dog)
171
local fuelHave = turtle.getFuelLevel()
172
if type(fuelHave) == "string" then
173
  print("\n-= No-fuel mode =-\n")
174
else
175
  local fuelRequired, fuel, coal, totalCoal = (height * 2) + 70
176
  if fuelHave < fuelRequired then
177
    turtle.select(1)
178
    repeat
179
      totalCoal = (fuelRequired - fuelHave) / 80
180
      coal = math.min(64, math.ceil(totalCoal))
181
      if not turtle.refuel(coal) then
182
        fuelHave = turtle.getFuelLevel()
183
        fuel = fuelRequired - fuelHave
184
        totalCoal = fuel / 80
185
        coal = math.min(64, math.ceil(totalCoal))
186
        term.clear()
187
        term.setCursorPos(1, 1)
188
        print("Insufficient fuel in slot 1.")
189
        for i = 30, 1, -1 do
190
          term.setCursorPos(1, 3)
191
          print("Please insert " .. tostring(fuel) .. " fuel or " .. tostring(totalCoal) .. " coal to continue.          ")
192
          term.setCursorPos(1, 5)
193
          print("Waiting " .. tostring(i) .. " seconds for fuel or exiting. ")
194
          sleep(1)
195
          turtle.refuel(coal)
196
          fuelHave = turtle.getFuelLevel()
197
          if fuelHave >= fuelRequired then break end
198
          totalCoal = (fuelRequired - fuelHave) / 80
199
          coal = math.min(64, math.ceil(totalCoal))
200
          fuel = fuelRequired - fuelHave
201
          if i == 1 then
202
            print("\nNot enough fuel provided.\n")
203
            print("Please provide " .. tostring(fuel) .. " fuel or " .. tostring(totalCoal) .. " coal and try again.\n")
204
            return
205
          end
206
        end
207
      else
208
        fuelHave = turtle.getFuelLevel()
209
      end
210
    until fuelHave >= fuelRequired
211
  end
212
  print("\n-= Turtle Fueled =-\n")
213
end
214
215
-- check if the required quantity of items
216
-- are in the appropriate spots. I'm sure
217
-- there's a more elegant way of doing this.
218
-- I don't believe there's a way to check if
219
-- the items are correct without using compare
220
-- inventory checking re-written and slotNum selection adjusted by Dog
221
local err = false
222
local itemTable = {
223
  [2] = { 1, "Please place 1 floppy disk in slot two." };
224
  [3] = { 1, "Please place 1 disk drive in slot three (mining turtle), or place 4 disk drives in slot three (standard turtle)." };
225
  [4] = { 4, "Please place 4 modems in slot four." };
226
  [5] = { 4, "Please place 4 computers across slots 5, 6, 7, 8. They may be labled, unlabled, or a mix of both.  Unlabeled computers may be stacked." };
227
}
228
229
for i = 2, 5 do
230
  if turtle.getItemCount(i) < itemTable[i][1] then
231
    if i == 5 then
232
      if (turtle.getItemCount(5) + turtle.getItemCount(6) + turtle.getItemCount(7) + turtle.getItemCount(8)) < 4 then
233
        print(itemTable[5][2] .. "\n")
234
        error("Please fix the above issue(s) and restart.\n", 0)
235
      end 
236
    else
237
      print(itemTable[i][2] .. "\n")
238
      error("Please fix the above issue(s) and restart.\n", 0)
239
    end
240
  end
241
end
242
243
--# Custom host program support - re-enabled by Dog
244
local base
245
if fs.exists("custom") then
246
  term.clear()
247
  term.setCursorPos(1, 1)
248
  print("Custom program detected!")
249
  print("Please enter base station number.\n")
250
  repeat
251
    write(" > ")
252
    base = tonumber(read())
253
    if not base then
254
      print("Error: Not a number.")
255
      print("Try again...\n")
256
    end
257
  until base
258
end
259
260
-- move functions
261
local facing, currentX, currentZ = 1, xCoord, zCoord
262
local cardinals, xOffset, zOffset = { "South", "West", "North", "East" }, { 0, -1, 0, 1 }, { 1, 0, -1, 0 }
263
264
local function emergencyStop()
265
  local failCount = 0
266
  print("ABORT! Unable to complete action.")
267
  print("Attempting to return to origin point.")
268
  if currentX > xCoord then     --# If east of the target then...
269
    if facing ~= 2 then         --# if not facing west then...
270
      repeat                    --# turn until facing west
271
        turtle.turnRight()
272
        facing = (facing % 4) + 1
273
      until facing == 2
274
    end
275
  elseif currentX < xCoord then --# If west of the target then...
276
    if facing ~= 4 then         --# if not facing east then...
277
      repeat                    --# turn until facing east
278
        turtle.turnRight()
279
        facing = (facing % 4) + 1
280
      until facing == 4
281
    end
282
  end
283
  if currentX ~= xCoord then
284
    repeat                      --# Move forward until currentX == xCoord
285
      while not turtle.forward() do
286
        turtle.dig()
287
        failCount = failCount + 1
288
        if failCount == 10 then error("Aborting return trip - too many obstacles.", 0) end
289
      end
290
      currentX = currentX + xOffset[facing]
291
    until currentX == xCoord
292
  end
293
  if currentZ > zCoord then     --# If south of the target then...
294
    if facing ~= 3 then         --# if not facing north then...
295
      repeat                    --# turn until facing north
296
        turtle.turnRight()
297
        facing = (facing % 4) + 1
298
      until facing == 3
299
    end
300
  elseif currentZ < zCoord then --# If north of the target then...
301
    if facing ~= 1 then         --# if not facing south then...
302
      repeat                    --# turn until facing south
303
        turtle.turnRight()
304
        facing = (facing % 4) + 1
305
      until facing == 1
306
    end
307
  end
308
  if currentZ ~= zCoord then
309
    failCount = 0
310
    repeat                      --# Move forward until currentZ == zCoord
311
      while not turtle.forward() do
312
        turtle.dig()
313
        failCount = failCount + 1
314
        if failCount == 10 then error("Aborting return trip - too many obstacles.", 0) end
315
      end
316
      currentZ = currentZ + zOffset[facing]
317
    until currentZ == zCoord
318
  end
319
  if facing ~= 1 then           --# If not facing south then...
320
    repeat                      --# turn until facing south
321
      turtle.turnRight()
322
      facing = (facing % 4) + 1
323
    until facing == 1
324
  end
325
  failCount = 0
326
  for i = 1, currentHeight do   --# Now above origin point, go down until reaching the origin point
327
    while not turtle.down() do
328
      turtle.digDown()
329
      failCount = failCount + 1
330
      if failCount == 10 then error("Aborting return trip - too many obstacles.", 0) end
331
    end
332
  end
333
  if modemSide then
334
    rednet.open(modemSide)
335
    local gpsX, gpsY, gpsZ = gps.locate(3)
336
    rednet.close(modemSide)
337
    if gpsX then
338
      print((gpsX == xCoord and gpsY == yCoord and gpsZ == zCoord) and "Coordinates verified." or "Coordinates don't match.")
339
    else
340
      print("GPS array unreachable.")
341
    end
342
  end
343
  error("Return trip complete.\n", 0)
344
end
345
346
-- (original code - reformatted and modified by Dog)
347
local failCount --# use a forward declaration so the variable doesn't have to be initialized every time a mov function is called
348
local mov = {
349
  forward = function()
350
    failCount = 0
351
    while not turtle.forward() do
352
      sleep(1)
353
      failCount = failCount + 1
354
      if failCount == 5 then emergencyStop() end
355
    end
356
    currentX = currentX + xOffset[facing]
357
    currentZ = currentZ + zOffset[facing]
358
  end;
359
  back = function()
360
    failCount = 0
361
    while not turtle.back() do
362
      sleep(1)
363
      failCount = failCount + 1
364
      if failCount == 5 then emergencyStop() end
365
    end
366
    currentX = currentX - xOffset[facing]
367
    currentZ = currentZ - zOffset[facing]
368
  end;
369
  up = function()
370
    failCount = 0
371
    while not turtle.up() do
372
      sleep(1)
373
      failCount = failCount + 1
374
      if failCount == 5 then emergencyStop() end
375
    end
376
    currentHeight = currentHeight + 1
377
  end;
378
  down = function()
379
    failCount = 0
380
    while not turtle.down() do
381
      sleep(1)
382
      failCount = failCount + 1
383
      if failCount == 5 then emergencyStop() end
384
    end
385
    currentHeight = currentHeight - 1
386
  end;
387
  left = function()
388
    turtle.turnLeft()
389
    facing = ((facing - 2) % 4) + 1
390
  end;
391
  right = function()
392
    turtle.turnRight()
393
    facing = (facing % 4) + 1
394
  end;
395
  place = function()
396
    failCount = 0
397
    while not turtle.place() do
398
      sleep(1)
399
      failCount = failCount + 1
400
      if failCount == 5 then emergencyStop() end
401
    end
402
  end;
403
}
404
405
print("\nX: " .. tostring(xCoord) .. " Y: " .. tostring(yCoord) .. " Z: " .. tostring(zCoord) .. " Height: " .. tostring(height + yCoord) .. " (+" .. tostring(height) ..")\n")
406
print("-= Launching =-\n")
407
-- start the climb up to the correct yCoord
408
for i = 1, height do
409
  mov.up()
410
end
411
412
-- once at the correct height, deploy GPS array
413
-- this is a mixture of my own code and the
414
-- original code
415
-- calculate the coordinates of the 4 satellite computers
416
local toYcordNS = math.min(MAXHEIGHT, yCoord + height)
417
local toYcordWE = toYcordNS - 3
418
local file, direction
419
local coords = {
420
  { x = xCoord, z = zCoord + 3, y = toYcordNS };
421
  { x = xCoord - 3, z = zCoord, y = toYcordWE };
422
  { x = xCoord, z = zCoord - 3, y = toYcordNS };
423
  { x = xCoord + 3, z = zCoord, y = toYcordWE };
424
}
425
426
for a = 1, 4 do
427
  direction = cardinals[a]
428
  mov.forward()
429
  mov.forward()
430
  if turtle.getItemCount(5) > 0 then --# Select & place computer
431
    turtle.select(5)
432
  elseif turtle.getItemCount(6) > 0 then
433
    turtle.select(6)
434
  elseif turtle.getItemCount(7) > 0 then
435
    turtle.select(7)
436
  else
437
    turtle.select(8)
438
  end
439
  print("Placing " .. direction .. ".")
440
  mov.place()
441
  mov.back()
442
  turtle.select(4) --# Select & place modem
443
  mov.place()
444
  mov.down()
445
  mov.forward()
446
  turtle.select(3) --# Select & place disk drive
447
  mov.place()
448
  turtle.select(2) --# Select & insert floppy disk
449
  turtle.drop()
450
  -- make a custom disk that starts up the gps host application
451
  -- with the correct coordinates and copy it over. also
452
  -- makes it a startup script so the program will
453
  -- start back up properly after chunk reloading
454
  print("Configuring " .. direction .. ".")
455
  if fs.exists("custom") then
456
    fs.copy("custom","disk/custom")
457
  end
458
  file = fs.open("disk/startup", "w")
459
  file.write([[
460
if not os.getComputerLabel() then os.setComputerLabel("GPS Host ]] .. direction .. [[ (" .. tostring(os.getComputerID()) .. ")") end
461
if fs.exists("startup") and fs.exists("startup-old") then fs.delete("startup-old") end
462
if fs.exists("startup") then fs.move("startup", "startup-old") end
463
fs.copy("disk/install", "startup")
464
fs.delete("disk/startup")
465
if fs.exists("disk/custom") then
466
  fs.copy("disk/custom", "custom")
467
  fs.delete("disk/custom")
468
end
469
print("Sleeping for 5 seconds.")
470
sleep(5)
471
os.reboot()
472
]])
473
  file.close()
474
  file = fs.open("disk/install","w")
475
  file.write([[
476
if fs.exists("custom") then
477
  shell.run("custom", "host", ]] .. coords[a]["x"] .. ", " .. coords[a]["y"] .. ", " .. coords[a]["z"] .. ", " .. (base or "nil") .. [[)
478
else
479
  shell.run("gps", "host", ]] .. coords[a]["x"] .. ", " .. coords[a]["y"] .. ", " .. coords[a]["z"] .. [[)
480
end
481
]])
482
  file.close()
483
  mov.left()
484
  mov.forward()
485
  mov.up()
486
  mov.right()
487
  mov.forward()
488
  mov.right()
489
  print("Activating " .. direction .. ".")
490
  peripheral.call("front", "turnOn")
491
  mov.down()
492
  print("Retrieving floppy & drive from " .. direction .. ".")
493
  turtle.select(2) --# Select slot & retreive floppy disk
494
  turtle.suck()
495
  turtle.select(3) --# Select slot & retreive floppy drive
496
  turtle.dig()
497
  mov.up()
498
  mov.right()
499
  mov.forward()
500
  mov.forward()
501
  mov.forward()
502
  mov.left()
503
  mov.forward()
504
  if a == 2 then
505
    mov.up()
506
    mov.up()
507
    mov.up()
508
  elseif a % 2 ~= 0 then
509
    mov.down()
510
    mov.down()
511
    mov.down()
512
  end
513
end
514
515
-- Return to starting point
516
print("Returning home.\n")
517
for i = 1, currentHeight do
518
  mov.down()
519
end
520
if modemSide then
521
  rednet.open(modemSide)
522
  local gpsX, gpsY, gpsZ = gps.locate(3)
523
  rednet.close(modemSide)
524
  if gpsX then
525
    print((gpsX == xCoord and gpsY == yCoord and gpsZ == zCoord) and "Success! Coordinates verified.\n" or "Failure. Coordinates don't match.\n")
526
  else
527
    print("GPS array unreachable.  Unable to verify installation.\n")
528
  end
529
else
530
  print("Finished.\n")
531
end