Advertisement
melzneni

Turti new smart GPS

Aug 17th, 2023 (edited)
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.19 KB | None | 0 0
  1. local pStorage
  2. local pSave
  3. local currentDirectionPrivate
  4.  
  5. local api = {}
  6.  
  7. local NAN = 0 / 0
  8.  
  9. turtle_unhooked_turnLeft = installPreExecutionHook(turtle, "turnLeft", "smartGPS", function()
  10. if currentDirectionPrivate then
  11. setCurrentDirection(getCurrentDirection() - 1)
  12. end
  13. end)
  14.  
  15. turtle_unhooked_turnRight = installPreExecutionHook(turtle, "turnRight", "smartGPS", function()
  16. if currentDirectionPrivate then
  17. setCurrentDirection(getCurrentDirection() + 1)
  18. end
  19. end)
  20.  
  21. function api.moveTo(pos, direction)
  22. local path = findPath(gpsAdapter.locate(), pos)
  23. if not path then
  24. error("no path found")
  25. end
  26. local cleared = false
  27. while not followPath(path) do
  28. path = findPath(gpsAdapter.locate(), pos)
  29. while not path do
  30. if not cleared then
  31. resetCuboids()
  32. path = findPath(gpsAdapter.locate(), pos)
  33. cleared = true
  34. else
  35. error("no path found")
  36. end
  37. end
  38. end
  39. turnTowardsDirection(direction)
  40. pSave()
  41. end
  42.  
  43. function api.locate()
  44. return toTurtiArray(gpsAdapter.locate())
  45. end
  46.  
  47. function api.getDirection()
  48. return getCurrentDirection()
  49. end
  50.  
  51. function api.setDirection(direction)
  52. turnTowardsDirection(direction)
  53. end
  54.  
  55. function faceTowardAny(positions)
  56. local possiblePositions = {}
  57. for i, pos in ipairs(positions) do
  58. table.insert(possiblePositions, { pos[1] - 1, pos[2], pos[3] }) -- direction 0
  59. table.insert(possiblePositions, { pos[1], pos[2], pos[3] - 1 }) -- direction 1
  60. table.insert(possiblePositions, { pos[1] + 1, pos[2], pos[3] }) -- direction 2
  61. table.insert(possiblePositions, { pos[1], pos[2], pos[3] + 1 }) -- direction 3
  62. end
  63.  
  64. local cleared = false
  65.  
  66. while true do
  67. local path, index = findPathToAny(gpsAdapter.locate(), possiblePositions)
  68.  
  69. if path then
  70. if followPath(path) then
  71. turnTowardsDirection((index - 1) % 4)
  72. return math.floor((index - 1) / 4)
  73. end
  74. else
  75. if not cleared then
  76. resetCuboids()
  77. cleared = true
  78. else
  79. error("no path found")
  80. end
  81. end
  82. end
  83. end
  84.  
  85. function api.faceToward(pos)
  86. local possiblePositions = {
  87. { pos[1] - 1, pos[2], pos[3] }, -- direction 0
  88. { pos[1], pos[2], pos[3] - 1 }, -- direction 1
  89. { pos[1] + 1, pos[2], pos[3] }, -- direction 2
  90. { pos[1], pos[2], pos[3] + 1 } -- direction 3
  91. }
  92.  
  93. while true do
  94. local path, index = findPathToAny(gpsAdapter.locate(), possiblePositions)
  95.  
  96. if path then
  97. if followPath(path) then
  98. turnTowardsDirection(index - 1)
  99. return
  100. end
  101. else
  102. if not cleared then
  103. resetCuboids()
  104. cleared = true
  105. else
  106. error("no path found")
  107. end
  108. end
  109. end
  110. end
  111.  
  112. function api.faceTowardAny(...)
  113. return faceTowardAny({ ... })
  114. end
  115.  
  116. function api.getPosInDirection(pos, direction)
  117. return toTurtiArray(getPosInDirection(pos, direction))
  118. end
  119.  
  120. --[[function followPathOld(path)
  121. for i = 2, #path do
  122. local direction = getDirectionFromPoints(path[i - 1], path[i])
  123. if not moveInDirection(direction) then
  124. markAsObstructed(path[i])
  125. return false
  126. end
  127. end
  128.  
  129. return true
  130. end]]
  131.  
  132. function getPosInDirection(pos, direction, count)
  133. if not count then
  134. count = 1
  135. end
  136. if direction == 0 then
  137. return { pos[1] + count, pos[2], pos[3] }
  138. elseif direction == 1 then
  139. return { pos[1], pos[2], pos[3] + count }
  140. elseif direction == 2 then
  141. return { pos[1] - count, pos[2], pos[3] }
  142. elseif direction == 3 then
  143. return { pos[1], pos[2], pos[3] - count }
  144. elseif direction == 4 then
  145. return { pos[1], pos[2] + count, pos[3] }
  146. elseif direction == 5 then
  147. return { pos[1], pos[2] - count, pos[3] }
  148. end
  149. end
  150.  
  151. function moveInDirection(direction, count)
  152. if count == 0 then
  153. return 0
  154. end
  155. if direction == 4 then
  156. for i = 1, count do
  157. if not turtle.up() then
  158. return i - 1
  159. end
  160. end
  161. elseif direction == 5 then
  162. for i = 1, count do
  163. if not turtle.down() then
  164. return i - 1
  165. end
  166. end
  167. else
  168. turnTowardsDirection(direction)
  169. for i = 1, count do
  170. if not turtle.forward() then
  171. return i - 1
  172. end
  173. end
  174. end
  175. return count
  176. end
  177.  
  178. function getCurrentDirection()
  179. if currentDirectionPrivate then
  180. return currentDirectionPrivate
  181. end
  182. local directionShift = 0
  183. local currentPos = gpsAdapter.locate()
  184. local testY = 3
  185. local currentY = 0
  186. for y = 1, testY do
  187. for i = 0, 5 do
  188. if turtle.forward() then
  189. currentDirectionPrivate = getDirectionFromPoints(currentPos, gpsAdapter.locate())
  190. turtle.back()
  191. break
  192. end
  193. turtle_unhooked_turnLeft()
  194. directionShift = directionShift + 1
  195. end
  196. if currentDirectionPrivate then
  197. break
  198. end
  199. if turtle.up() then
  200. currentY = currentY + 1
  201. else
  202. break
  203. end
  204. end
  205. while currentY > 0 do
  206. turtle.down()
  207. currentY = currentY - 1
  208. end
  209. if currentDirectionPrivate then
  210. for _ = 1, directionShift do
  211. turtle.turnRight()
  212. end
  213. return currentDirectionPrivate
  214. end
  215. for y = 1, testY do
  216. for i = 0, 5 do
  217. if turtle.forward() then
  218. currentDirectionPrivate = getDirectionFromPoints(currentPos, gpsAdapter.locate())
  219. turtle.back()
  220. break
  221. end
  222. turtle_unhooked_turnLeft()
  223. directionShift = directionShift + 1
  224. end
  225. if currentDirectionPrivate then
  226. break
  227. end
  228. if turtle.down() then
  229. currentY = currentY - 1
  230. else
  231. break
  232. end
  233. end
  234. while currentY < 0 do
  235. turtle.up()
  236. currentY = currentY + 1
  237. end
  238.  
  239. if not currentDirectionPrivate then
  240. error("turtle is trapped!")
  241. end
  242. for _ = 1, directionShift do
  243. turtle.turnRight()
  244. end
  245. return currentDirectionPrivate
  246. end
  247.  
  248. function setCurrentDirection(cD)
  249. while cD > 3 do
  250. cD = cD - 4
  251. end
  252. while cD < 0 do
  253. cD = cD + 4
  254. end
  255. currentDirectionPrivate = cD
  256. end
  257.  
  258. function turnTowardsDirection(direction)
  259. while direction > 3 do
  260. direction = direction - 4
  261. end
  262. while direction < 0 do
  263. direction = direction + 4
  264. end
  265. if direction == 4 or direction == 5 then
  266. return
  267. end
  268. local turnLeftDirection = getCurrentDirection() + 3
  269. if turnLeftDirection > 3 then
  270. turnLeftDirection = turnLeftDirection - 4
  271. end
  272. if turnLeftDirection == direction then
  273. turtle.turnLeft()
  274. end
  275.  
  276. while getCurrentDirection() ~= direction do
  277. turtle.turnRight()
  278. end
  279. end
  280.  
  281. function getDirectionFromPoints(pos1, pos2)
  282. if pos2[1] == pos1[1] + 1 then
  283. return 0
  284. elseif pos2[3] == pos1[3] + 1 then
  285. return 1
  286. elseif pos2[1] == pos1[1] - 1 then
  287. return 2
  288. elseif pos2[3] == pos1[3] - 1 then
  289. return 3
  290. elseif pos2[2] == pos1[2] + 1 then
  291. return 4
  292. elseif pos2[2] == pos1[2] - 1 then
  293. return 5
  294. else
  295. printTable(pos1)
  296. printTable(pos2)
  297. error("cannot determine direction from points")
  298. end
  299. end
  300.  
  301. function yield()
  302. if not test then
  303. os.queueEvent("randomEvent")
  304. os.pullEvent()
  305. end
  306. end
  307.  
  308. function followPath(path)
  309. local directions = { 0, 4, 1, 2, 5, 3 }
  310. for i = 2, #path do
  311. local pos1 = path[i - 1][1]
  312. local pos2 = path[i][1]
  313. local axes = {}
  314. for iA = 1, 3 do
  315. if iA ~= path[i - 1][2] then
  316. table.insert(axes, iA)
  317. end
  318. end
  319. table.insert(axes, path[i - 1][2])
  320.  
  321. printTable(path[i - 1])
  322. printTable(path[i])
  323.  
  324. local pos = pos1
  325. for _, axis in ipairs(axes) do
  326. local dirP = directions[axis]
  327. local dirN = directions[axis + 3]
  328. local count = math.abs(pos2[axis] - pos1[axis])
  329. if pos2[axis] > pos1[axis] then
  330. local moved = moveInDirection(dirP, count)
  331. if moved ~= count then
  332. markAsObstructed(getPosInDirection(pos, dirP, moved + 1))
  333. return false
  334. end
  335. pos = getPosInDirection(pos1, dirP, moved)
  336. elseif pos2[axis] < pos1[axis] then
  337. local moved = moveInDirection(dirN, count)
  338. if moved ~= count then
  339. markAsObstructed(getPosInDirection(pos, dirN, moved + 1))
  340. return false
  341. end
  342. pos = getPosInDirection(pos1, dirN, moved)
  343. end
  344. end
  345. end
  346. return true
  347. end
  348.  
  349. function findPath(start, destination)
  350. local startNode = { start, findCuboidContainingPos(start) }
  351. local destinationNode = { destination, findCuboidContainingPos(destination) }
  352.  
  353. if startNode[2] == destinationNode[2] then
  354. return { { startNode[1], 3 }, { destinationNode[1], 3 } }
  355. end
  356. local openNodesQueue = {}
  357. local openNodes = {}
  358. local closedNodes = {}
  359.  
  360. table.insert(openNodesQueue, { node = startNode, identifier = nodeToIdentifier(startNode), f = 0, g = 0, pre = nil })
  361. openNodes[openNodesQueue[1].identifier] = openNodesQueue[1]
  362.  
  363. while (true) do
  364. table.sort(openNodesQueue, function(a, b)
  365. return a.f < b.f
  366. end)
  367. if #openNodesQueue > 10000 then
  368. return nil
  369. end
  370. local currentNode = table.remove(openNodesQueue, 1)
  371. if not currentNode then
  372. return nil
  373. end
  374. if posEquals(currentNode.node[1], destination) then
  375. return getPathFromNode(currentNode)
  376. end
  377.  
  378. closedNodes[currentNode.identifier] = true
  379.  
  380. aStarExpandNode(currentNode, openNodesQueue, openNodes, closedNodes, destinationNode)
  381. end
  382. end
  383.  
  384. function aStarExpandNode(currentEntry, openNodesQueue, openNodes, closedNodes, destinationNode)
  385. for _, successorNode in ipairs(getSuccessorNodes(currentEntry.node, destinationNode)) do
  386. local identifier = nodeToIdentifier(successorNode)
  387. if not closedNodes[identifier] then
  388. local g = currentEntry.g + getPointDistance(currentEntry.node[1], successorNode[1])
  389.  
  390. if openNodes[identifier] and g > openNodes[identifier].g then
  391.  
  392. else
  393. local f = g + getPointDistance(successorNode[1], destinationNode[1])
  394. if openNodes[identifier] then
  395. local entry = openNodes[identifier]
  396. entry.g = g
  397. entry.f = f
  398. entry.pre = currentEntry
  399. else
  400. local entry = { node = successorNode, identifier = identifier, f = f, g = g, pre = currentEntry }
  401. table.insert(openNodesQueue, entry)
  402. openNodes[identifier] = entry
  403. end
  404. end
  405. end
  406. end
  407. end
  408.  
  409. function getSuccessorNodes(currentNode, destinationNode)
  410. local pos = currentNode[1]
  411. local cuboid = currentNode[2]
  412. local successors = {}
  413. for _, connectedCuboid in ipairs(cuboid[7]) do
  414. local successorPos = getClosestPositionInCuboid(pos, connectedCuboid)
  415. table.insert(successors, { successorPos, connectedCuboid })
  416. if connectedCuboid == destinationNode[2] then
  417. table.insert(successors, destinationNode)
  418. end
  419. end
  420. return successors
  421. end
  422.  
  423. function getClosestPositionInCuboid(pos, cuboid)
  424. return { putNumInRange(pos[1], cuboid[1], cuboid[4]), putNumInRange(pos[2], cuboid[2], cuboid[5]), putNumInRange(pos[3], cuboid[3], cuboid[6]) }
  425. end
  426.  
  427. function putNumInRange(num, min, max)
  428. if min == min and num < min then
  429. return min
  430. elseif max == max and max <= num then
  431. return max - 1
  432. else
  433. return num
  434. end
  435. end
  436.  
  437. --[[
  438. function aStarExpandNode(currentNode, openNodesQueue, openNodes, closedNodes, destination)
  439. for i, successor in ipairs(getSuccessors(currentNode)) do
  440. local identifier = posToIdentifier(successor)
  441. if not closedNodes[identifier] then
  442. local g = currentNode.g + 1
  443.  
  444. if openNodes[identifier] and g > openNodes[identifier].g then
  445.  
  446. else
  447. local f = g + aStarH(successor, destination)
  448. if openNodes[identifier] then
  449. local entry = openNodes[identifier]
  450. entry.g = g
  451. entry.f = f
  452. entry.pre = currentNode
  453. else
  454. local entry = { pos = successor, identifier = identifier, f = f, g = g, pre = currentNode }
  455. table.insert(openNodesQueue, entry)
  456. openNodes[identifier] = entry
  457. end
  458. end
  459. end
  460. end
  461. end
  462. ]]
  463.  
  464. function getPathFromNode(node)
  465. local path = {}
  466. local nextNode
  467. local currentNode = node
  468. while currentNode do
  469. if nextNode then
  470. local overlappingDirection = getOverlappingCuboidDirection(nextNode.node[2], currentNode.node[2])
  471. table.insert(path, 1, {getPosInDirection(nextNode.node[1], overlappingDirection), 1})
  472. table.insert(path, 1, { currentNode.node[1], getOverlappingCuboidAxis(currentNode.node[2], nextNode.node[2]) })
  473. else
  474. table.insert(path, 1, { currentNode.node[1] })
  475. end
  476. nextNode = currentNode
  477. currentNode = currentNode.pre
  478. end
  479. return path
  480. end
  481.  
  482. function nodeToIdentifier(node)
  483. local pos = node[1]
  484. return pos[1] .. "_" .. pos[2] .. "_" .. pos[3] .. "_" .. node[2][8]
  485. end
  486.  
  487. function getPointDistance(p1, p2)
  488. return math.abs(p2[1] - p1[1]) + math.abs(p2[2] - p1[2]) + math.abs(p2[3] - p1[3])
  489. end
  490.  
  491.  
  492. --[[function findPath(start, destination)
  493. local openNodesQueue = {}
  494. local openNodes = {}
  495. local closedNodes = {}
  496. table.insert(openNodesQueue, { pos = start, identifier = posToIdentifier(start), f = 0, g = 0, pre = nil })
  497. openNodes[openNodesQueue[1].identifier] = openNodesQueue[1]
  498.  
  499. while (true) do
  500. table.sort(openNodesQueue, function(a, b)
  501. return a.f < b.f
  502. end)
  503. if #openNodesQueue > 1000 then
  504. return nil
  505. end
  506. yield()
  507. local currentNode = table.remove(openNodesQueue, 1)
  508.  
  509. if not currentNode then
  510. return nil
  511. end
  512.  
  513. if posEquals(currentNode.pos, destination) then
  514. return getPathFromNode(currentNode)
  515. end
  516.  
  517. closedNodes[currentNode.identifier] = true
  518.  
  519. aStarExpandNode(currentNode, openNodesQueue, openNodes, closedNodes, destination)
  520. end
  521. end
  522.  
  523. function getPathFromNode(endNode)
  524. local path = {}
  525. local currentNode = endNode
  526. while currentNode do
  527. table.insert(path, 1, currentNode.pos)
  528. currentNode = currentNode.pre
  529. end
  530. return path
  531. end
  532.  
  533. function aStarExpandNode(currentNode, openNodesQueue, openNodes, closedNodes, destination)
  534. for i, successor in ipairs(getSuccessors(currentNode)) do
  535. local identifier = posToIdentifier(successor)
  536. if not closedNodes[identifier] then
  537. local g = currentNode.g + 1
  538.  
  539. if openNodes[identifier] and g > openNodes[identifier].g then
  540.  
  541. else
  542. local f = g + aStarH(successor, destination)
  543. if openNodes[identifier] then
  544. local entry = openNodes[identifier]
  545. entry.g = g
  546. entry.f = f
  547. entry.pre = currentNode
  548. else
  549. local entry = { pos = successor, identifier = identifier, f = f, g = g, pre = currentNode }
  550. table.insert(openNodesQueue, entry)
  551. openNodes[identifier] = entry
  552. end
  553. end
  554. end
  555. end
  556. end
  557.  
  558. function aStarH(start, destination)
  559. return math.abs(destination[1] - start[1]) + math.abs(destination[2] - start[2]) + math.abs(destination[3] - start[3])
  560. end
  561.  
  562. function getSuccessors(node)
  563. local pos = node.pos
  564. local x = pos[1]
  565. local y = pos[2]
  566. local z = pos[3]
  567. local potentialSuccessors = {
  568. { x + 1, y, z },
  569. { x - 1, y, z },
  570. { x, y + 1, z },
  571. { x, y - 1, z },
  572. { x, y, z + 1 },
  573. { x, y, z - 1 }
  574. }
  575. local successors = {}
  576. for i, v in ipairs(potentialSuccessors) do
  577. if not isObstructed(v) then
  578. table.insert(successors, v)
  579. end
  580. end
  581. return successors
  582. end
  583.  
  584. function posToIdentifier(pos)
  585. return pos[1] .. ":" .. pos[2] .. ":" .. pos[3]
  586. end]]
  587.  
  588. --[[function findPathToAny(start, destinations)
  589. local allOpenNodesQueues = {}
  590. local allOpenNodes = {}
  591. local allClosedNodes = {}
  592. local activeRoutes = {}
  593.  
  594. for i, destination in pairs(destinations) do
  595. local openNodesQueue = {}
  596. local openNodes = {}
  597. table.insert(openNodesQueue, { pos = start, identifier = posToIdentifier(start), f = 0, g = 0, pre = nil })
  598. openNodes[openNodesQueue[1].identifier] = openNodesQueue[1]
  599.  
  600. table.insert(allOpenNodesQueues, openNodesQueue)
  601. table.insert(allOpenNodes, openNodes)
  602. table.insert(allClosedNodes, {})
  603. table.insert(activeRoutes, true)
  604. end
  605.  
  606. while (true) do
  607. local anyActive = false
  608. for i = 1, #activeRoutes do
  609. if activeRoutes[i] then
  610. anyActive = true
  611. local openNodesQueue = allOpenNodesQueues[i]
  612. local openNodes = allOpenNodes[i]
  613. local closedNodes = allClosedNodes[i]
  614. table.sort(openNodesQueue, function(a, b)
  615. return a.f < b.f
  616. end)
  617. yield()
  618. if #openNodesQueue > 1000 then
  619. activeRoutes[i] = false
  620. else
  621. local currentNode = table.remove(openNodesQueue, 1)
  622.  
  623. if not currentNode then
  624. activeRoutes[i] = false
  625. else
  626. if posEquals(currentNode.pos, destinations[i]) then
  627. return getPathFromNode(currentNode), i
  628. end
  629.  
  630. closedNodes[currentNode.identifier] = true
  631.  
  632. aStarExpandNode(currentNode, openNodesQueue, openNodes, closedNodes, destinations[i])
  633. end
  634. end
  635. end
  636. end
  637. if not anyActive then
  638. return false
  639. end
  640. end
  641.  
  642. end]]
  643.  
  644. function posEquals(pos1, pos2)
  645. return pos1[1] == pos2[1] and pos1[2] == pos2[2] and pos1[3] == pos2[3]
  646. end
  647.  
  648. --[[function isObstructed(pos)
  649. local blocks = pStorage.blocks
  650. if not blocks then
  651. return false
  652. end
  653. blocks = blocks[pos[1]]--[[
  654. if not blocks then
  655. return false
  656. end
  657. blocks = blocks[pos[2]]--[[
  658. if not blocks then
  659. return false
  660. end
  661. blocks = blocks[pos[3]]--[[
  662. if not blocks then
  663. return false
  664. end
  665. return true
  666. end]]
  667.  
  668. function resetCuboids()
  669. print("reset cuboids")
  670. pStorage.cuboids = { { NAN, NAN, NAN, NAN, NAN, NAN, {}, 1 } }
  671. end
  672.  
  673. function markAsObstructed(pos)
  674. local cuboid = findCuboidContainingPos(pos)
  675.  
  676. local newCuboids = splitCuboidAtPos(cuboid, pos)
  677. local numNewCuboids = #newCuboids
  678. -- delete
  679. for _, connectedCuboid in pairs(cuboid[7]) do
  680. removeValue(connectedCuboid[7], cuboid)
  681. for _, c in pairs(newCuboids) do
  682. if areCuboidsAdjacent(c, connectedCuboid) then
  683. connectCuboids(connectedCuboid, c)
  684. end
  685. end
  686. end
  687.  
  688. if numNewCuboids == 0 then
  689. table.remove(pStorage.cuboids, cuboid[8])
  690. reindexCuboids()
  691. return
  692. end
  693.  
  694. pStorage.cuboids[cuboid[8]] = newCuboids[1]
  695. newCuboids[1][8] = cuboid[8]
  696. local numCuboids = #pStorage.cuboids
  697. for i = 2, numNewCuboids do
  698. newCuboids[i][8] = numCuboids + i - 1
  699. table.insert(pStorage.cuboids, newCuboids[i])
  700. end
  701.  
  702. logCuboids()
  703. end
  704.  
  705. function logCuboids()
  706.  
  707. local txt = getTableSaveText(pStorage)
  708. local f = fs.open("out", "w")
  709. f.write(txt)
  710. f.close()
  711. end
  712.  
  713. function connectCuboids(c1, c2)
  714. table.insert(c1[7], c2)
  715. table.insert(c2[7], c1)
  716. end
  717.  
  718. function getOverlappingCuboidAxis(c1, c2)
  719. if c1[1] == c2[4] or c1[4] == c2[1] then
  720. return 1
  721. elseif c1[2] == c2[5] or c1[5] == c2[2] then
  722. return 2
  723. elseif c1[3] == c2[6] or c1[6] == c2[3] then
  724. return 3
  725. end
  726. printCuboidCoordinates(c1)
  727. printCuboidCoordinates(c2)
  728. error("invalid cuboids")
  729. end
  730.  
  731. function getOverlappingCuboidDirection(c1, c2)
  732. if c1[4] == c2[1] then
  733. return 0
  734. elseif c1[6] == c2[3] then
  735. return 1
  736. elseif c1[5] == c2[2] then
  737. return 4
  738. elseif c1[1] == c2[4] then
  739. return 2
  740. elseif c1[3] == c2[6] then
  741. return 3
  742. elseif c1[2] == c2[5] then
  743. return 5
  744. end
  745. printCuboidCoordinates(c1)
  746. printCuboidCoordinates(c2)
  747. error("invalid cuboids")
  748. end
  749.  
  750. function printCuboidCoordinates(c)
  751. print(c[1], c[2], c[3], c[4], c[5], c[6], "|", c[8])
  752. end
  753.  
  754. function areCuboidsAdjacent(c1, c2)
  755. local sum1 = 0
  756. local sum2 = 0
  757. if rangesOverlap(c1[1], c1[4], c2[1], c2[4]) then
  758. sum1 = sum1 + 1
  759. elseif c1[1] == c2[4] or c1[4] == c2[1] then
  760. sum2 = sum2 + 1
  761. end
  762. if rangesOverlap(c1[2], c1[5], c2[2], c2[5]) then
  763. sum1 = sum1 + 1
  764. elseif c1[2] == c2[5] or c1[5] == c2[2] then
  765. sum2 = sum2 + 1
  766. end
  767. if rangesOverlap(c1[3], c1[6], c2[3], c2[6]) then
  768. sum1 = sum1 + 1
  769. elseif c1[3] == c2[6] or c1[6] == c2[3] then
  770. sum2 = sum2 + 1
  771. end
  772. if sum1 > 2 then
  773. printCuboidCoordinates(c1)
  774. printCuboidCoordinates(c2)
  775. error("impossible case " .. sum1 .. ", " .. sum2)
  776. end
  777. return sum1 == 2 and sum2 == 1
  778. end
  779.  
  780. function isNan(v)
  781. return v ~= v
  782. end
  783.  
  784. function rangesOverlap(p1x1, p1x2, p2x1, p2x2)
  785. if isNan(p1x1) and isNan(p1x2) then
  786. return true
  787. elseif isNan(p2x1) and isNan(p2x2) then
  788. return true
  789. elseif isNan(p1x1) and isNan(p2x1) then
  790. return true
  791. elseif isNan(p1x2) and isNan(p2x2) then
  792. return true
  793. end
  794.  
  795. if isNan(p1x1) then
  796. p1x1 = p2x1
  797. elseif isNan(p2x1) then
  798. p2x1 = p1x1
  799. end
  800. if isNan(p1x2) then
  801. p1x2 = p2x2
  802. elseif isNan(p2x2) then
  803. p2x2 = p1x2
  804. end
  805.  
  806. return math.max(p1x2, p2x2) - math.min(p1x1, p2x1) < p2x2 - p2x1 + p1x2 - p1x1
  807. end
  808.  
  809. function reindexCuboids()
  810. for i = 1, #pStorage.cuboids do
  811. pStorage.cuboids[i][8] = i
  812. end
  813. end
  814.  
  815. function splitCuboidAtPos(cuboid, pos)
  816. local x1 = cuboid[1]
  817. local y1 = cuboid[2]
  818. local z1 = cuboid[3]
  819. local x2 = cuboid[4]
  820. local y2 = cuboid[5]
  821. local z2 = cuboid[6]
  822. local pX = pos[1]
  823. local pY = pos[2]
  824. local pZ = pos[3]
  825.  
  826. local cuboidYM = { x1, y1, z1, x2, pY, z2, {}, 1 }
  827. local cuboidYP = { x1, pY + 1, z1, x2, y2, z2, {}, 2 }
  828.  
  829. local cuboidXM = { x1, pY, z1, pX, pY + 1, z2, {}, 3 }
  830. local cuboidXP = { pX + 1, pY, z1, x2, pY + 1, z2, {}, 4 }
  831.  
  832. local cuboidZM = { pX, pY, z1, pX + 1, pY + 1, pZ, {}, 5 }
  833. local cuboidZP = { pX, pY, pZ + 1, pX + 1, pY + 1, z2, {}, 6 }
  834. local allCuboids = { cuboidXM, cuboidXP, cuboidYM, cuboidYP, cuboidZM, cuboidZP }
  835. local partners = { cuboidYP, cuboidYM, cuboidXP, cuboidXM, cuboidZP, cuboidZM }
  836.  
  837. local cuboids = {}
  838. for _, c in pairs(allCuboids) do
  839. if not isEmptyCuboid(c) then
  840. table.insert(cuboids, c)
  841. for _, cP in pairs(allCuboids) do
  842. if c ~= cP and partners[c[8]] ~= cP then
  843. table.insert(cP[7], c)
  844. end
  845. end
  846. end
  847. end
  848. return cuboids
  849. end
  850.  
  851. function findCuboidContainingPos(pos)
  852. -- TODO pass cuboid that might contain pos (from turtle position)
  853. for _, cuboid in ipairs(pStorage.cuboids) do
  854. printCuboidCoordinates(cuboid)
  855. if isPointInCuboid(pos, cuboid) then
  856. return cuboid
  857. end
  858. end
  859. printTable(pos)
  860. error("c")
  861. error("cuboid containing position not found!")
  862. end
  863.  
  864. function isPointInCuboid(pos, cuboid)
  865. if (pos[1] < cuboid[1]) and (cuboid[1] == cuboid[1]) then
  866. return false
  867. elseif (cuboid[4] <= pos[1]) and (cuboid[4] == cuboid[4]) then
  868. return false
  869. elseif (pos[2] < cuboid[2]) and (cuboid[2] == cuboid[2]) then
  870. return false
  871. elseif (cuboid[5] <= pos[2]) and (cuboid[5] == cuboid[5]) then
  872. return false
  873. elseif (pos[3] < cuboid[3]) and (cuboid[3] == cuboid[3]) then
  874. return false
  875. elseif (cuboid[6] <= pos[3]) and (cuboid[6] == cuboid[6]) then
  876. return false
  877. end
  878. return true
  879. end
  880.  
  881. function isEmptyCuboid(cuboid)
  882. return cuboid[1] == cuboid[4] or cuboid[2] == cuboid[5] or cuboid[3] == cuboid[6]
  883. end
  884.  
  885. function getAtKeyOrCreateTable(tbl, key)
  886. local v = tbl[key]
  887. if not v then
  888. v = {}
  889. tbl[key] = v
  890. end
  891. return v
  892. end
  893.  
  894. function removeValue(tbl, value)
  895. for i, v in pairs(tbl) do
  896. if v == value then
  897. table.remove(tbl, i)
  898. return
  899. end
  900. end
  901. end
  902.  
  903. return {
  904. name = 'smartGPS',
  905. api = api,
  906. onInitPersistentStorage = function(_pStorage, _pSave)
  907. pStorage = _pStorage
  908. if not pStorage.cuboids then
  909. resetCuboids()
  910. end
  911. pSave = _pSave
  912. end
  913. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement