Advertisement
SirSheepe

STQ Turtle

May 15th, 2023 (edited)
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.38 KB | None | 0 0
  1. local argument = ({ ... })[1]
  2.  
  3. local WHITELIST = {
  4. "minecraft:iron_ore",
  5. "minecraft:deepslate_iron_ore",
  6. "minecraft:copper_ore",
  7. "minecraft:deepslate_copper_ore",
  8. "minecraft:gold_ore",
  9. "minecraft:deepslate_gold_ore",
  10. "minecraft:redstone_ore",
  11. "minecraft:deepslate_redstone_ore",
  12. "minecraft:emerald_ore",
  13. "minecraft:deepslate_emerald_ore",
  14. "minecraft:lapis_ore",
  15. "minecraft:deepslate_lapis_ore",
  16. "minecraft:diamond_ore",
  17. "minecraft:deepslate_diamond_ore",
  18. "minecraft:nether_gold_ore",
  19. "minecraft:nether_quartz_ore",
  20. "minecraft:ancient_debris",
  21. "minecraft:obsidian",
  22. "create:zinc_ore",
  23. "create:deepslate_zinc_ore",
  24. "tconstruct:cobalt_ore",
  25. "mekanism:tin_ore",
  26. "mekanism:deepslate_tin_ore",
  27. "mekanism:lead_ore",
  28. "mekanism:deepslate_lead_ore",
  29. "mekanism:osmium_ore",
  30. "mekanism:deepslate_osmium_ore",
  31. "mekanism:uranium_ore",
  32. "mekanism:deepslate_uranium_ore",
  33. -- "mekanism:fluorite_ore",
  34. -- "mekanism:deepslate_fluorite_ore"
  35. "alltheores:aluminum_ore",
  36. "alltheores:aluminum_end_ore",
  37. "alltheores:aluminum_nether_ore",
  38. "alltheores:aluminum_other_ore",
  39. "alltheores:aluminum_slate_ore",
  40. "alltheores:copper_other_ore",
  41. "alltheores:diamond_other_ore",
  42. "alltheores:emerald_other_ore",
  43. "alltheores:gold_other_ore",
  44. "alltheores:iridium_ore",
  45. "alltheores:iridium_end_ore",
  46. "alltheores:iridium_nether_ore",
  47. "alltheores:iridium_other_ore",
  48. "alltheores:iridium_slate_ore",
  49. "alltheores:iron_other_ore",
  50. "alltheores:lapis_other_ore",
  51. "alltheores:lead_end_ore",
  52. "alltheores:lead_ore",
  53. "alltheores:lead_nether_ore",
  54. "alltheores:lead_other_ore",
  55. "alltheores:lead_slate_ore",
  56. "alltheores:nickel_end_ore",
  57. "alltheores:nickel_ore",
  58. "alltheores:nickel_nether_ore",
  59. "alltheores:nickel_other_ore",
  60. "alltheores:nickel_slate_ore",
  61. "alltheores:osmium_end_ore",
  62. "alltheores:osmium_ore",
  63. "alltheores:osmium_nether_ore",
  64. "alltheores:osmium_other_ore",
  65. "alltheores:osmium_slate_ore",
  66. "alltheores:platinum_end_ore",
  67. "alltheores:platinum_ore",
  68. "alltheores:platinum_nether_ore",
  69. "alltheores:platinum_other_ore",
  70. "alltheores:platinum_slate_ore",
  71. "alltheores:quartz_other_ore",
  72. "alltheores:redstone_other_ore",
  73. "alltheores:silver_end_ore",
  74. "alltheores:silver_nether_ore",
  75. "alltheores:silver_ore",
  76. "alltheores:silver_other_ore",
  77. "alltheores:silver_slate_ore",
  78. "alltheores:tin_end_ore",
  79. "alltheores:tin_nether_ore",
  80. "alltheores:tin_ore",
  81. "alltheores:tin_other_ore",
  82. "alltheores:tin_slate_ore",
  83. "alltheores:uranium_end_ore",
  84. "alltheores:uranium_nether_ore",
  85. "alltheores:uranium_ore",
  86. "alltheores:uranium_other_ore",
  87. "alltheores:uranium_slate_ore",
  88. "alltheores:zinc_end_ore",
  89. "alltheores:zinc_nether_ore",
  90. "alltheores:zinc_ore",
  91. "alltheores:zinc_other_ore",
  92. "alltheores:zinc_slate_ore",
  93. "minecraft:coal_ore",
  94. "minecraft:deepslate_coal_ore",
  95. "alltheores:coal_end_ore",
  96. "alltheores:coal_nether_ore",
  97. "alltheores:coal_other_ore",
  98. }
  99.  
  100. table.includes = function(tbl, item)
  101. for i = 1, #tbl do
  102. if tbl[i] == item then
  103. return true
  104. end
  105. end
  106. return false
  107. end
  108.  
  109. local Network = {}
  110. Network.__index = Network
  111.  
  112. function Network.new(modem)
  113. local self = setmetatable({}, Network)
  114.  
  115. if modem == nil then
  116. error("Unable to create network, no modem provided", 2)
  117. end
  118.  
  119. self.registry = registry
  120. self.DEFAULT_CHANNEL = 42424
  121. self.expectedPackets = {}
  122. self.outgoingPackets = {}
  123. self.responseTime = 3
  124. self.modems = { modem }
  125.  
  126. return self
  127. end
  128.  
  129. function Network:Listen()
  130. while true do
  131. local event, id, channel, reply, message = os.pullEvent()
  132.  
  133. if argument == "debug" then
  134. print("l", event, id, channel, message)
  135. end
  136.  
  137. if event == "network_disconnect" then
  138. self.expectedPackets = {}
  139. self.outgoingPackets = {}
  140. break
  141. end
  142.  
  143. if event == "timer" or event == "modem_message" then
  144. local closed = {}
  145.  
  146. for i = 1, #self.expectedPackets do
  147. local packet = self.expectedPackets[i]
  148.  
  149. if event == "timer" and id == packet.timeout then
  150. table.remove(self.expectedPackets, i)
  151. i = i - 1
  152. end
  153.  
  154. if event == "modem_message" and channel == packet.channel and message == packet.message then
  155. table.remove(self.expectedPackets, i)
  156. table.insert(closed, channel)
  157. os.queueEvent(packet.uuid)
  158. os.cancelTimer(packet.timeout)
  159. i = i - 1
  160. end
  161. end
  162.  
  163. local connection = self.connection
  164.  
  165. if connection then
  166. if event == "timer" and connection.timeoutID == id then
  167. os.queueEvent("connection_end")
  168. self.connection = nil
  169. self:CancelRepeatedPacket(connection.signalUUID)
  170. connection.status = 0
  171. if connection.timeoutListener then
  172. connection.timeoutListener(connection)
  173. end
  174. table.insert(closed, channel)
  175. elseif event == "modem_message" and channel == connection.channel then
  176. os.cancelTimer(connection.timeoutID)
  177. connection.timeoutID = os.startTimer(self.responseTime)
  178. if connection.status == 0 and message == connection.message then
  179. connection.status = 1
  180. connection.timeout = self.responseTime
  181. os.queueEvent("network_connect", connection.UUID)
  182. if connection.connectedListener then
  183. connection.connectedListener(connection)
  184. end
  185. elseif connection.status == 1 and message ~= connection.message then
  186. os.queueEvent("connection_update", message)
  187. end
  188. end
  189. end
  190.  
  191. for i = 1, #closed do
  192. local required = false
  193.  
  194. for _, packet in pairs(self.expectedPackets) do
  195. local channel = closed[i]
  196.  
  197. if packet.channel == channel then
  198. required = true
  199. break
  200. end
  201. end
  202.  
  203. if not required then
  204. self:CloseChannel(channel)
  205. end
  206. end
  207.  
  208. if event == "timer" then
  209. for i, packet in pairs(self.outgoingPackets) do
  210. if packet.timerID == id then
  211. if self:Transmit(packet.channel, packet.message, packet.wireless) then
  212. local timer = os.startTimer(packet.period)
  213. packet.timerID = timer
  214.  
  215. if argument == "debug" then
  216. print("u", "send", packet.channel, packet.message, packet.wireless)
  217. end
  218. else
  219. table.remove(self.outgoingPackets, i)
  220. end
  221. break
  222. end
  223. end
  224. end
  225. end
  226. end
  227. end
  228.  
  229. -- https://gist.github.com/jrus/3197011
  230.  
  231. function Network:GenerateEventUUID()
  232. local template = "STNPxxxx-xxxx-xxxx"
  233. return string.gsub(template, "[x]", function(c)
  234. return string.format("%x", math.random(0, 0xf))
  235. end)
  236. end
  237.  
  238. function Network:Stop()
  239. os.queueEvent("network_disconnect")
  240. end
  241.  
  242. function Network:WaitForAll(timeout)
  243. local timerID = os.startTimer(timeout or 60)
  244.  
  245. while #self.expectedPackets > 0 do
  246. local event, id = os.pullEvent()
  247.  
  248. if event == "timer" and id == timerID then
  249. break
  250. end
  251. end
  252.  
  253. return #self.expectedPackets == 0
  254. end
  255.  
  256. function Network:WaitForBatch(batch, timeout)
  257. local events = {}
  258. local result = {}
  259.  
  260. for i, packet in pairs(batch) do
  261. table.insert(
  262. events,
  263. Network:Expect(packet.channel, packet.message, timeout, function(success)
  264. result[i] = success
  265. return packet.callback(success)
  266. end)
  267. )
  268. end
  269.  
  270. parallel.waitForAll(unpack(events))
  271.  
  272. return result
  273. end
  274.  
  275. function Network:Wait(channel, message, timeout, callback)
  276. return self:Expect(channel, message, timeout, callback)()
  277. end
  278.  
  279. function Network:Expect(channel, message, timeout, callback)
  280. local packetUUID = self:GenerateEventUUID()
  281. local timerID = timeout == false and -1 or os.startTimer(timeout or 30)
  282.  
  283. self:OpenChannel(channel)
  284.  
  285. table.insert(self.expectedPackets, {
  286. channel = channel,
  287. message = message,
  288. timeout = timerID,
  289. uuid = packetUUID,
  290. })
  291.  
  292. return function()
  293. while true do
  294. local event, id = os.pullEvent()
  295.  
  296. if event == "timer" and id == timerID then
  297. if callback then
  298. return callback(false)
  299. end
  300. return false
  301. end
  302.  
  303. if event == packetUUID then
  304. if callback then
  305. return callback(false)
  306. end
  307. return true
  308. end
  309. end
  310. end
  311. end
  312.  
  313. function Network:HasModem(otherModem)
  314. for i, modem in pairs(self.modems) do
  315. for channel = 1, 65535 do
  316. if not (modem.isOpen(channel) or otherModem.isOpen(channel)) then
  317. modem.open(channel)
  318.  
  319. local newOpen = otherModem.isOpen(channel)
  320. modem.close(channel)
  321.  
  322. return newOpen
  323. end
  324. end
  325. end
  326. return false
  327. end
  328.  
  329. function Network:AddModem(newModem)
  330. if self:HasModem(newModem) then
  331. return false
  332. end
  333.  
  334. table.insert(self.modems, newModem)
  335.  
  336. return true
  337. end
  338.  
  339. function Network:OpenChannel(channel, wireless)
  340. if wireless == nil then
  341. wireless = true
  342. end
  343.  
  344. for _, modem in pairs(self.modems) do
  345. if
  346. ((modem.isWireless() and wireless) or (not modem.isWireless() and not wireless)) and modem.isOpen(channel)
  347. then
  348. return true
  349. end
  350. end
  351.  
  352. for _, modem in pairs(self.modems) do
  353. if
  354. ((modem.isWireless() and wireless) or (not modem.isWireless() and not wireless))
  355. and pcall(modem.open, channel)
  356. then
  357. return true
  358. end
  359. end
  360.  
  361. error("Too many channels open, no modems available", 2)
  362. end
  363.  
  364. function Network:CloseChannel(channel)
  365. for _, modem in pairs(self.modems) do
  366. if modem.isOpen(channel) then
  367. modem.close(channel)
  368. end
  369. end
  370. end
  371.  
  372. function Network:Transmit(channel, message, wireless)
  373. if #self.modems == 0 then
  374. error("No modem available to transmit message", 2)
  375. end
  376.  
  377. if wireless == nil then
  378. wireless = true
  379. end
  380.  
  381. for _, modem in pairs(self.modems) do
  382. local isWireless = select(2, pcall(modem.isWireless))
  383. if (isWireless and wireless) or not (isWireless or wireless) then
  384. modem.transmit(channel, channel, message)
  385. return true
  386. end
  387. end
  388.  
  389. return false
  390. end
  391.  
  392. function Network:SendRepeatedPacket(channel, message, period, wireless)
  393. local uuid = self:GenerateEventUUID()
  394. local timerID = os.startTimer(period)
  395.  
  396. if self:Transmit(channel, message, wireless) then
  397. table.insert(self.outgoingPackets, {
  398. uuid = uuid,
  399. timerID = timerID,
  400. channel = channel,
  401. message = message,
  402. period = period,
  403. wireless = wireless,
  404. })
  405. else
  406. os.cancelTimer(timerID)
  407. return
  408. end
  409.  
  410. return uuid
  411. end
  412.  
  413. function Network:CancelRepeatedPacket(uuid)
  414. for i, packet in pairs(self.outgoingPackets) do
  415. if packet.uuid == uuid then
  416. os.cancelTimer(packet.timerID)
  417. table.remove(self.outgoingPackets, i)
  418. return true
  419. end
  420. end
  421. return false
  422. end
  423.  
  424. function Network:GetListenerHandle()
  425. return function()
  426. self:Listen()
  427. end
  428. end
  429.  
  430. function Network:Obfuscate(str, id, reverse)
  431. local lid = os.getComputerID()
  432. math.randomseed(id >= lid and (id * id + id + lid) or (id + lid * lid))
  433.  
  434. if #str % 2 == 1 then
  435. str = str .. ";"
  436. end
  437.  
  438. local keys = {}
  439. local mul = reverse and 2 or 1
  440. local len = #str / (2 * mul)
  441.  
  442. for i = 1, 16 do
  443. local key = {}
  444. for i = 1, len do
  445. table.insert(key, math.random(0, 255))
  446. end
  447. keys[i] = key
  448. end
  449.  
  450. local function xor8(x, y)
  451. return (math.floor(x / 0x80) == math.floor(y / 0x80) and 0 or 0x80)
  452. + (math.floor(x / 0x40) % 2 == math.floor(y / 0x40) % 2 and 0x00 or 0x40)
  453. + (math.floor(x / 0x20) % 2 == math.floor(y / 0x20) % 2 and 0x00 or 0x20)
  454. + (math.floor(x / 0x10) % 2 == math.floor(y / 0x10) % 2 and 0x00 or 0x10)
  455. + (math.floor(x / 0x08) % 2 == math.floor(y / 0x08) % 2 and 0x00 or 0x08)
  456. + (math.floor(x / 0x04) % 2 == math.floor(y / 0x04) % 2 and 0x00 or 0x04)
  457. + (math.floor(x / 0x02) % 2 == math.floor(y / 0x02) % 2 and 0x00 or 0x02)
  458. + (x % 2 == y % 2 and 0x00 or 0x01)
  459. end
  460.  
  461. local function xor(x, y)
  462. local o = {}
  463. for i = 1, #x do
  464. table.insert(o, xor8(x[i], y[i]))
  465. end
  466. return o
  467. end
  468.  
  469. local L, R = {}, {}
  470.  
  471. for i = 1, #str, mul do
  472. local chunk = reverse and tonumber(str:sub(i, i + 1), 16) or str:byte(i)
  473. if i <= #str / 2 then
  474. table.insert(L, chunk)
  475. else
  476. table.insert(R, chunk)
  477. end
  478. end
  479.  
  480. if not reverse then
  481. for i = 1, #keys do
  482. L, R = R, xor(L, xor(keys[i], R))
  483. end
  484. else
  485. for i = #keys, 1, -1 do
  486. L, R = R, xor(L, xor(keys[i], R))
  487. end
  488. end
  489.  
  490. local out = ""
  491.  
  492. for i = 1, len do
  493. if reverse then
  494. out = out .. string.char(R[i])
  495. else
  496. out = out .. ("%02x"):format(R[i])
  497. end
  498. end
  499.  
  500. for i = 1, len do
  501. if reverse then
  502. if not (L[i] == 59 and i == len) then
  503. out = out .. string.char(L[i])
  504. end
  505. else
  506. out = out .. ("%02x"):format(L[i])
  507. end
  508. end
  509.  
  510. return out
  511. end
  512.  
  513. function Network:IsConnected()
  514. return self.connection ~= nil
  515. end
  516.  
  517. function Network:ConnectToServer(timeout, timeoutListener, connectedListener)
  518. if self:IsConnected(t) then
  519. return self.connection.UUID
  520. end
  521.  
  522. local message = self:Obfuscate(settings.get("uuid") .. "-CONNECT", settings.get("cid"))
  523. local timerID = os.startTimer(timeout or 300)
  524. local UUID = self:GenerateEventUUID()
  525.  
  526. self:OpenChannel(settings.get("channel"), true)
  527.  
  528. self.connection = {
  529. status = 0,
  530. timeoutID = timerID,
  531. timeout = timeout or 60,
  532. channel = settings.get("channel"),
  533. message = message,
  534. signalUUID = self:SendRepeatedPacket(settings.get("channel"), message, 1, true),
  535. timeoutListener = timeoutListener,
  536. connectedListener = connectedListener,
  537. UUID = UUID,
  538. }
  539.  
  540. return function()
  541. while true do
  542. local event, id = os.pullEvent()
  543.  
  544. if event == "timer" and id == timerID then
  545. return nil
  546. end
  547.  
  548. if event == "network_connect" and id == UUID then
  549. return UUID
  550. end
  551. end
  552. end
  553. end
  554.  
  555. function Network:ReadCommand(s)
  556. --[[
  557. data format
  558. entries split by :
  559.  
  560. status=1:key=value:ins=1,3,2#scan|
  561. until the ins key, where we
  562. split by #
  563. ]]
  564. local directionMap = {
  565. N = { 0, 0, -1 },
  566. S = { 0, 0, 1 },
  567. W = { -1, 0, 0 },
  568. E = { 1, 0, 0 },
  569. }
  570. local info = {}
  571.  
  572. for chunk in s:gmatch("[^:]+") do
  573. local bits = {}
  574. for bit in chunk:gmatch("[^=]+") do
  575. table.insert(bits, bit)
  576. end
  577.  
  578. if #bits ~= 2 or not bits[1]:match("%a") then
  579. return
  580. end
  581.  
  582. local key = bits[1]
  583.  
  584. if key == "ins" then
  585. local ins = {}
  586.  
  587. for i in bits[2]:gmatch("[^/]+") do
  588. local dat = {}
  589. for k in i:gmatch("[^#]+") do
  590. table.insert(dat, k)
  591. end
  592.  
  593. if #dat ~= 2 or not dat[2]:match("%a") then
  594. return
  595. end
  596.  
  597. local coords = {}
  598. for dir in dat[1]:gmatch("[^,]+") do
  599. local n = tonumber(dir)
  600. if n == nil and #coords < 3 then
  601. return
  602. end
  603. table.insert(coords, n or dir)
  604. end
  605.  
  606. if #coords ~= 4 then
  607. return
  608. end
  609.  
  610. if not coords[4]:match("[NESW~]") then
  611. return
  612. end
  613.  
  614. table.insert(ins, {
  615. direction = directionMap[table.remove(coords, 4)],
  616. position = coords,
  617. action = dat[2],
  618. })
  619. end
  620.  
  621. info.ins = ins
  622. else
  623. local anum = tonumber(bits[2])
  624. info[key] = anum ~= nil and anum or bits[2]
  625. end
  626. end
  627.  
  628. return info
  629. end
  630.  
  631. function Network:WaitForCommand()
  632. if not self:IsConnected() then
  633. return false
  634. end
  635.  
  636. while true do
  637. local event, message = os.pullEvent()
  638.  
  639. if event == "connection_end" then
  640. return false
  641. elseif event == "connection_update" then
  642. local data = self:Obfuscate(message, settings.get("cid"), true)
  643. print("new cmd", data)
  644. local read = self:ReadCommand(data)
  645.  
  646. if read ~= nil then
  647. return true, read
  648. end
  649. end
  650. end
  651. end
  652.  
  653. function Network:ConnectionSend(data)
  654. if not self:IsConnected() then
  655. return false
  656. end
  657.  
  658. local chunks = {}
  659.  
  660. for i, v in pairs(data) do
  661. table.insert(chunks, i .. "=" .. v)
  662. end
  663.  
  664. local message = self:Obfuscate(table.concat(chunks, ":"), settings.get("cid"))
  665.  
  666. self:Transmit(settings.get("channel"), message, true)
  667. end
  668.  
  669. local ActionManager = {}
  670. ActionManager.__index = ActionManager
  671.  
  672. function ActionManager.new(network)
  673. local self = setmetatable({}, ActionManager)
  674.  
  675. self.network = network
  676.  
  677. self.queue = {}
  678. self.position = nil
  679. self.endPosition = nil
  680. self.direction = nil
  681. self.fuel = turtle.getFuelLevel()
  682. self.fuelStorage = 1
  683. self.outStorage = 2
  684. self.toolStorage = 3
  685. self.canDig = true
  686.  
  687. local geoScanner = peripheral.find("geoScanner")
  688. local item = turtle.getItemDetail(self.toolStorage)
  689.  
  690. if item == nil or (item.name ~= "advancedperipherals:geo_scanner" and item.name ~= "minecraft:diamond_pickaxe") then
  691. if geoScanner == nil then
  692. error("Geo scanner missing from slot " .. self.toolStorage, 2)
  693. else
  694. error("Diamond pickaxe missing from slot " .. self.toolStorage, 2)
  695. end
  696. elseif geoScanner ~= nil then
  697. self.scanner = geoScanner
  698. turtle.select(self.toolStorage)
  699. turtle.equipRight()
  700. elseif geoScanner == nil then
  701. turtle.select(self.toolStorage)
  702. turtle.equipRight()
  703. self.scanner = peripheral.find("geoScanner")
  704. turtle.equipRight()
  705. end
  706.  
  707. return self
  708. end
  709.  
  710. function ActionManager:ClearQueue()
  711. self.queue = {}
  712. if self.trigger ~= nil then
  713. os.cancelTimer(self.trigger)
  714. end
  715. end
  716.  
  717. function ActionManager:Refuel()
  718. if not self.canDig then
  719. turtle.select(self.toolStorage)
  720. turtle.equipRight()
  721. self.canDig = true
  722. end
  723.  
  724. turtle.digUp()
  725. turtle.select(self.fuelStorage)
  726. turtle.placeUp()
  727. while not turtle.getItemDetail(self.fuelStorage) do
  728. turtle.suckUp(64)
  729. turtle.refuel(64)
  730. end
  731. turtle.dropUp(64)
  732. turtle.digUp()
  733. end
  734.  
  735. function ActionManager:Update()
  736. while true do
  737. local event, id, success, msg = os.pullEvent()
  738.  
  739. if event == "action_stop" then
  740. break
  741. end
  742.  
  743. if event == "action_process" and #self.queue > 0 and self.processing then
  744. local item = self.queue[1]
  745. local action = item.action
  746.  
  747. print("a!", #self.queue, action)
  748.  
  749. if action == "scan" then
  750. if self.canDig then
  751. turtle.equipRight()
  752. turtle.select(self.toolStorage)
  753. self.canDig = false
  754. end
  755.  
  756. local data = self.scanner.scan(8)
  757.  
  758. if data ~= nil then
  759. item.callback(data)
  760. table.remove(self.queue, 1)
  761. end
  762. else
  763. if (action == "dig" or action == "digDown" or action == "digUp") and not self.canDig then
  764. turtle.select(self.toolStorage)
  765. turtle.equipRight()
  766. self.canDig = true
  767. end
  768.  
  769. local success = turtle[action](unpack(item.arguments or {}))
  770.  
  771. if success then
  772. table.remove(self.queue, 1)
  773.  
  774. local returnLocation = true
  775. self.fuel = self.fuel - 1
  776.  
  777. if action == "forward" then
  778. self.position.x = self.position.x + self.direction.x
  779. self.position.z = self.position.z + self.direction.z
  780. elseif action == "back" then
  781. self.position.x = self.position.x - self.direction.x
  782. self.position.z = self.position.z - self.direction.z
  783. elseif action == "up" then
  784. self.position.y = self.position.y + 1
  785. elseif action == "down" then
  786. self.position.y = self.position.y - 1
  787. else
  788. self.fuel = self.fuel + 1
  789. returnLocation = false
  790.  
  791. if action == "turnLeft" then
  792. self.direction = {
  793. x = -self.direction.z,
  794. y = 0,
  795. z = self.direction.x,
  796. }
  797. elseif action == "turnRight" then
  798. self.direction = {
  799. x = self.direction.z,
  800. y = 0,
  801. z = -self.direction.x,
  802. }
  803. elseif action == "refuel" then
  804. self.fuel = turtle.getFuelLevel()
  805. end
  806. end
  807.  
  808. if returnLocation then
  809. self.network:ConnectionSend({
  810. type = "locate",
  811. x = self.position.x,
  812. y = self.position.y,
  813. z = self.position.z,
  814. dx = self.direction.x,
  815. dy = self.direction.y,
  816. dz = self.direction.z,
  817. })
  818. end
  819. else
  820. if action == "forward" or action == "back" or action == "up" or action == "down" then
  821. if self.fuel <= 0 then
  822. self:Refuel()
  823. elseif action == "forward" and turtle.inspect() ~= nil then
  824. table.insert(self.queue, 1, { action = "dig" })
  825. elseif action == "up" and turtle.inspectUp() ~= nil then
  826. table.insert(self.queue, 1, { action = "digUp" })
  827. elseif action == "down" and turtle.inspectDown() ~= nil then
  828. table.insert(self.queue, 1, { action = "digDown" })
  829. end
  830. else
  831. if
  832. action == "digUp"
  833. or action == "dig"
  834. or action == "digDown"
  835. or action == "placeUp"
  836. or action == "place"
  837. or action == "placeDown"
  838. then
  839. if action == "digUp" or action == "dig" or action == "digDown" then
  840. if self.canDig then
  841. table.remove(self.queue, 1)
  842. else
  843. turtle.select(self.toolStorage)
  844. turtle.equipRight()
  845. self.canDig = true
  846. end
  847. end
  848. end
  849. end
  850. end
  851. end
  852.  
  853. os.queueEvent("action_process")
  854. end
  855. end
  856. end
  857.  
  858. function ActionManager:GetUpdateHandle()
  859. return function()
  860. return self:Update()
  861. end
  862. end
  863.  
  864. function ActionManager:Start()
  865. if #self.queue > self.fuel then
  866. self:Refuel()
  867. end
  868. self.processing = true
  869. print("queuing", #self.queue)
  870. os.queueEvent("action_process")
  871. end
  872.  
  873. function ActionManager:Pause()
  874. self.processing = false
  875. end
  876.  
  877. function ActionManager:Stop()
  878. os.queueEvent("action_stop")
  879. self.processing = false
  880. self:ClearQueue()
  881. end
  882.  
  883. function ActionManager:GenerateMinimumActionsTo(pos, dir)
  884. local cpos = self.endPosition
  885. local cdir = { x = self.endDirection.x, y = self.endDirection.y, z = self.endDirection.z }
  886.  
  887. local actions = {}
  888. local diff = { x = pos.x - cpos.x, y = pos.y - cpos.y, z = pos.z - cpos.z }
  889.  
  890. if diff.x ~= 0 then
  891. if cdir.x == 0 and ((diff.z > 0 and cdir.z > 0) or (diff.z < 0 and cdir.z < 0)) then
  892. if diff.z ~= 0 then
  893. for i = 1, math.abs(diff.z) do
  894. table.insert(actions, { action = "dig" })
  895. table.insert(actions, { action = "forward" })
  896. end
  897. end
  898. if (diff.x > 0 and cdir.z > 0) or (diff.x < 0 and cdir.z < 0) then
  899. table.insert(actions, { action = "turnLeft" })
  900. else
  901. table.insert(actions, { action = "turnRight" })
  902. end
  903. for i = 1, math.abs(diff.x) do
  904. table.insert(actions, { action = "dig" })
  905. table.insert(actions, { action = "forward" })
  906. end
  907. else
  908. if cdir.x == 0 then
  909. if (diff.x > 0 and cdir.z > 0) or (diff.x < 0 and cdir.z < 0) then
  910. table.insert(actions, { action = "turnLeft" })
  911. else
  912. table.insert(actions, { action = "turnRight" })
  913. end
  914. end
  915. if (diff.x > 0 and cdir.x < 0) or (diff.x < 0 and cdir.x > 0) then
  916. table.insert(actions, { action = "turnRight" })
  917. table.insert(actions, { action = "turnRight" })
  918. end
  919. for i = 1, math.abs(diff.x) do
  920. table.insert(actions, { action = "dig" })
  921. table.insert(actions, { action = "forward" })
  922. end
  923. if diff.z ~= 0 then
  924. if (diff.z > 0 and diff.x > 0) or (diff.z < 0 and diff.x < 0) then
  925. table.insert(actions, { action = "turnRight" })
  926. else
  927. table.insert(actions, { action = "turnLeft" })
  928. end
  929. for i = 1, math.abs(diff.z) do
  930. table.insert(actions, { action = "dig" })
  931. table.insert(actions, { action = "forward" })
  932. end
  933. end
  934. end
  935. elseif diff.z ~= 0 then
  936. if cdir.z == 0 then
  937. if (diff.z > 0 and cdir.x > 0) or (diff.z < 0 and cdir.x < 0) then
  938. table.insert(actions, { action = "turnRight" })
  939. else
  940. table.insert(actions, { action = "turnLeft" })
  941. end
  942. elseif (cdir.z > 0 and diff.z < 0) or (cdir.z < 0 and diff.z > 0) then
  943. table.insert(actions, { action = "turnRight" })
  944. table.insert(actions, { action = "turnRight" })
  945. end
  946. for i = 1, math.abs(diff.z) do
  947. table.insert(actions, { action = "dig" })
  948. table.insert(actions, { action = "forward" })
  949. end
  950. end
  951.  
  952. if diff.y > 0 then
  953. for i = 1, math.abs(diff.y) do
  954. table.insert(actions, { action = "digUp" })
  955. table.insert(actions, { action = "up" })
  956. end
  957. elseif diff.y < 0 then
  958. for i = 1, math.abs(diff.y) do
  959. table.insert(actions, { action = "digDown" })
  960. table.insert(actions, { action = "down" })
  961. end
  962. end
  963.  
  964. for i, v in pairs(actions) do
  965. if action == "turnLeft" then
  966. cdir = {
  967. x = -cdir.z,
  968. y = 0,
  969. z = cdir.x,
  970. }
  971. elseif action == "turnRight" then
  972. cdir = {
  973. x = cdir.z,
  974. y = 0,
  975. z = -cdir.x,
  976. }
  977. end
  978. end
  979.  
  980. if dir ~= nil then
  981. if dir.x == 0 then
  982. if cdir.x == 0 and cdir.z ~= dir.z then
  983. table.insert(actions, { action = "turnLeft" })
  984. table.insert(actions, { action = "turnLeft" })
  985. elseif (cdir.x > 0 and dir.z < 0) or (cdir.x < 0 and dir.z > 0) then
  986. table.insert(actions, { action = "turnLeft" })
  987. elseif cdir.z ~= dir.z then
  988. table.insert(actions, { action = "turnRight" })
  989. end
  990. else
  991. if cdir.z == 0 and cdir.x ~= dir.x then
  992. table.insert(actions, { action = "turnRight" })
  993. table.insert(actions, { action = "turnRight" })
  994. elseif (cdir.z > 0 and dir.x < 0) or (cdir.z < 0 and dir.x > 0) then
  995. table.insert(actions, { action = "turnRight" })
  996. elseif cdir.x ~= dir.x then
  997. table.insert(actions, { action = "turnLeft" })
  998. end
  999. end
  1000. end
  1001.  
  1002. return actions, { x = pos.x, y = pos.y, z = pos.z }, cdir
  1003. end
  1004.  
  1005. function ActionManager:GetTimeTo(pos, dir)
  1006. return #self:GenerateMinimumActions(pos, dir)
  1007. end
  1008.  
  1009. function ActionManager:CompileInstruction(ins)
  1010. if self.position == nil then
  1011. return
  1012. end
  1013.  
  1014. if ins.action == "scan" then
  1015. table.insert(self.queue, {
  1016. action = "scan",
  1017. callback = function(data)
  1018. local list = {}
  1019.  
  1020. for i, block in pairs(list) do
  1021. if table.includes(WHITELIST, block.name) then
  1022. table.insert(list, block.x)
  1023. table.insert(list, block.y)
  1024. table.insert(list, block.z)
  1025. end
  1026. end
  1027.  
  1028. list.type = "scan"
  1029.  
  1030. self.network:ConnectionSend(list)
  1031. end,
  1032. })
  1033. elseif ins.action == "move" then
  1034. local aim = ins.position
  1035. local aimDir = ins.direction
  1036.  
  1037. local actions, endPos, endDir = self:GenerateMinimumActionsTo({
  1038. x = aim[1],
  1039. y = aim[2],
  1040. z = aim[3],
  1041. }, aimDir and {
  1042. x = aimDir[1],
  1043. y = aimDir[2],
  1044. z = aimDir[3],
  1045. } or nil)
  1046.  
  1047. for i, action in pairs(actions) do
  1048. table.insert(self.queue, action)
  1049. end
  1050.  
  1051. self.endPosition = endPos
  1052. self.endDirection = endDir
  1053. end
  1054. end
  1055.  
  1056. function ActionManager:LocateTurtle(px, py, pz)
  1057. if self.canDig then
  1058. turtle.select(self.toolStorage)
  1059. turtle.equipRight()
  1060. self.canDig = false
  1061. end
  1062.  
  1063. local x, y, z
  1064. local scan = self.scanner.scan(8)
  1065.  
  1066. for i, v in pairs(scan) do
  1067. if v.name == "computercraft:computer_advanced" then
  1068. x = -v.x + px
  1069. y = -v.y + py
  1070. z = -v.z + pz
  1071. break
  1072. end
  1073. end
  1074.  
  1075. if x == nil or y == nil or z == nil then
  1076. error("Unable to locate turtle", 2)
  1077. end
  1078.  
  1079. self.position = { x = x, y = y, z = z }
  1080. self.endPosition = { x = x, y = y, z = z }
  1081.  
  1082. if self.fuel < 2 then
  1083. self:Refuel()
  1084. os.pullEvent("refuel_complete")
  1085. end
  1086.  
  1087. if turtle.inspect() and not self.canDig then
  1088. turtle.select(self.toolStorage)
  1089. turtle.equipRight()
  1090. self.canDig = true
  1091. turtle.dig()
  1092. end
  1093.  
  1094. if not turtle.forward() then
  1095. error("Please clear space in front of the turtle for location purposes", 2)
  1096. end
  1097.  
  1098. if self.canDig then
  1099. turtle.select(self.toolStorage)
  1100. turtle.equipRight()
  1101. self.canDig = false
  1102. end
  1103.  
  1104. os.sleep(2.05)
  1105.  
  1106. local x, y, z
  1107. local scan = self.scanner.scan(8)
  1108.  
  1109. for i, v in pairs(scan) do
  1110. if v.name == "computercraft:computer_advanced" then
  1111. x = -v.x + px
  1112. y = -v.y + py
  1113. z = -v.z + pz
  1114. break
  1115. end
  1116. end
  1117.  
  1118. if x == nil or y == nil or z == nil then
  1119. error("Unable to locate turtle", 2)
  1120. end
  1121.  
  1122. self.direction = { x = x - self.position.x, y = 0, z = z - self.position.z }
  1123. self.endDirection = { x = x - self.position.x, y = 0, z = z - self.position.z }
  1124.  
  1125. turtle.back()
  1126.  
  1127. return self.position
  1128. end
  1129.  
  1130. local modem = peripheral.find("modem", function(_, o)
  1131. return o.isWireless()
  1132. end)
  1133. local network = Network.new(modem)
  1134.  
  1135. local actionManager = ActionManager.new(network)
  1136.  
  1137. local function registrationSetup()
  1138. local lan = peripheral.find("modem", function(_, o)
  1139. return not o.isWireless()
  1140. end)
  1141.  
  1142. if not lan then
  1143. error("Please connect the computer to the registration network", 2)
  1144. end
  1145.  
  1146. network:AddModem(lan)
  1147.  
  1148. local drive = peripheral.find("drive")
  1149.  
  1150. if not drive then
  1151. error("Please connect the computer to the registration network", 2)
  1152. end
  1153.  
  1154. if not drive.isDiskPresent() then
  1155. error("Please place a floppy disk into the drive", 2)
  1156. end
  1157. end
  1158.  
  1159. local function registration()
  1160. registrationSetup()
  1161.  
  1162. network:OpenChannel(network.DEFAULT_CHANNEL, false)
  1163.  
  1164. while true do
  1165. print("Searching for a registration server...")
  1166. local register = network:Wait(network.DEFAULT_CHANNEL, "ST-REG", false)
  1167.  
  1168. if register then
  1169. print("Registration server found, attempting connection...")
  1170.  
  1171. network:OpenChannel(network.DEFAULT_CHANNEL, false)
  1172.  
  1173. local signalUUID = network:SendRepeatedPacket(network.DEFAULT_CHANNEL, "ST-REG-CONFIRM", 1, false)
  1174. local success = network:Wait(network.DEFAULT_CHANNEL, "ST-REG-FINISH", 30)
  1175. network:CancelRepeatedPacket(signalUUID)
  1176.  
  1177. if success then
  1178. settings.load("disk/reg")
  1179. settings.save()
  1180.  
  1181. fs.delete("disk/reg")
  1182.  
  1183. local uuid = settings.get("uuid")
  1184.  
  1185. if uuid then
  1186. print(("Successfully registered to the server as %s"):format(uuid))
  1187. network:Transmit(settings.get("channel"), "ST-REG-SUCCESS", false)
  1188. break
  1189. else
  1190. print("Failed to parse settings data, registration failed")
  1191. end
  1192. else
  1193. print("Registration failed, try again later")
  1194. end
  1195. end
  1196. end
  1197.  
  1198. network:Stop()
  1199. end
  1200.  
  1201. local function deregistration()
  1202. registrationSetup()
  1203.  
  1204. if not settings.get("uuid") then
  1205. error("This turtle is not registered to any server")
  1206. return
  1207. end
  1208.  
  1209. local tchannel = settings.get("channel")
  1210.  
  1211. network:OpenChannel(tchannel, false)
  1212.  
  1213. while true do
  1214. print("Searching for a registration server...")
  1215. local register = network:Wait(tchannel, "ST-DEREG", false)
  1216.  
  1217. if register then
  1218. print("Registration server found, attempting connection...")
  1219.  
  1220. network:OpenChannel(tchannel, false)
  1221.  
  1222. local conUUID = network:Transmit(tchannel, "ST-DEREG-CONFIRM", false)
  1223. local success = network:Wait(tchannel, "ST-DEREG-SUCCESS", 60)
  1224. network:CancelRepeatedPacket(conUUID)
  1225.  
  1226. if success then
  1227. print("Deregistration successful")
  1228. settings.clear()
  1229. settings.save()
  1230. break
  1231. else
  1232. print("Failed to connect to the server, please try again")
  1233. end
  1234. else
  1235. print("This turtle is not registered to any system")
  1236. end
  1237. end
  1238.  
  1239. network:Stop()
  1240. end
  1241.  
  1242. local function processCommand(actionManager, cmd)
  1243. for i, v in pairs(cmd) do
  1244. print(i, v)
  1245. end
  1246.  
  1247. if cmd.fuel then
  1248. network:ConnectionSend({ type = "fuel", current = turtle.getFuelLevel(), max = turtle.getFuelLimit() })
  1249. end
  1250.  
  1251. if cmd.locate then
  1252. if actionManager.position == nil then
  1253. actionManager:LocateTurtle(cmd.cx, cmd.cy, cmd.cz)
  1254. end
  1255. local pos, dir = actionManager.position, actionManager.direction
  1256. network:ConnectionSend({
  1257. type = "locate",
  1258. x = pos.x,
  1259. y = pos.y,
  1260. z = pos.z,
  1261. dx = dir.x,
  1262. dy = dir.y,
  1263. dz = dir.z,
  1264. })
  1265. end
  1266.  
  1267. if cmd.ins then
  1268. for i, v in pairs(cmd.ins) do
  1269. actionManager:CompileInstruction(v)
  1270. end
  1271. end
  1272.  
  1273. if cmd.status then
  1274. local status = cmd.status
  1275.  
  1276. if status == "stop" then
  1277. actionManager:Stop()
  1278. elseif status == "pause" then
  1279. actionManager:Pause()
  1280. elseif status == "start" then
  1281. actionManager:Start()
  1282. end
  1283. end
  1284. end
  1285.  
  1286. parallel.waitForAll(network:GetListenerHandle(), actionManager:GetUpdateHandle(), function()
  1287. if argument == "join" then
  1288. registration()
  1289. elseif argument == "leave" then
  1290. deregistration()
  1291. end
  1292.  
  1293. print("Connecting to the server...")
  1294.  
  1295. local connectionUUID = network:ConnectToServer(60, function()
  1296. error("Timed out attempting to connect to the server, try again")
  1297. end, nil)()
  1298.  
  1299. if connectionUUID then
  1300. print("Connected")
  1301. network.responseTime = 10
  1302. while true do
  1303. local continue, data = network:WaitForCommand()
  1304.  
  1305. if continue then
  1306. processCommand(actionManager, data)
  1307. else
  1308. break
  1309. end
  1310. end
  1311. end
  1312.  
  1313. print("Timed out")
  1314. end)
  1315.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement