Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local argument = ({ ... })[1]
- local WHITELIST = {
- "minecraft:iron_ore",
- "minecraft:deepslate_iron_ore",
- "minecraft:copper_ore",
- "minecraft:deepslate_copper_ore",
- "minecraft:gold_ore",
- "minecraft:deepslate_gold_ore",
- "minecraft:redstone_ore",
- "minecraft:deepslate_redstone_ore",
- "minecraft:emerald_ore",
- "minecraft:deepslate_emerald_ore",
- "minecraft:lapis_ore",
- "minecraft:deepslate_lapis_ore",
- "minecraft:diamond_ore",
- "minecraft:deepslate_diamond_ore",
- "minecraft:nether_gold_ore",
- "minecraft:nether_quartz_ore",
- "minecraft:ancient_debris",
- "minecraft:obsidian",
- "create:zinc_ore",
- "create:deepslate_zinc_ore",
- "tconstruct:cobalt_ore",
- "mekanism:tin_ore",
- "mekanism:deepslate_tin_ore",
- "mekanism:lead_ore",
- "mekanism:deepslate_lead_ore",
- "mekanism:osmium_ore",
- "mekanism:deepslate_osmium_ore",
- "mekanism:uranium_ore",
- "mekanism:deepslate_uranium_ore",
- -- "mekanism:fluorite_ore",
- -- "mekanism:deepslate_fluorite_ore"
- "alltheores:aluminum_ore",
- "alltheores:aluminum_end_ore",
- "alltheores:aluminum_nether_ore",
- "alltheores:aluminum_other_ore",
- "alltheores:aluminum_slate_ore",
- "alltheores:copper_other_ore",
- "alltheores:diamond_other_ore",
- "alltheores:emerald_other_ore",
- "alltheores:gold_other_ore",
- "alltheores:iridium_ore",
- "alltheores:iridium_end_ore",
- "alltheores:iridium_nether_ore",
- "alltheores:iridium_other_ore",
- "alltheores:iridium_slate_ore",
- "alltheores:iron_other_ore",
- "alltheores:lapis_other_ore",
- "alltheores:lead_end_ore",
- "alltheores:lead_ore",
- "alltheores:lead_nether_ore",
- "alltheores:lead_other_ore",
- "alltheores:lead_slate_ore",
- "alltheores:nickel_end_ore",
- "alltheores:nickel_ore",
- "alltheores:nickel_nether_ore",
- "alltheores:nickel_other_ore",
- "alltheores:nickel_slate_ore",
- "alltheores:osmium_end_ore",
- "alltheores:osmium_ore",
- "alltheores:osmium_nether_ore",
- "alltheores:osmium_other_ore",
- "alltheores:osmium_slate_ore",
- "alltheores:platinum_end_ore",
- "alltheores:platinum_ore",
- "alltheores:platinum_nether_ore",
- "alltheores:platinum_other_ore",
- "alltheores:platinum_slate_ore",
- "alltheores:quartz_other_ore",
- "alltheores:redstone_other_ore",
- "alltheores:silver_end_ore",
- "alltheores:silver_nether_ore",
- "alltheores:silver_ore",
- "alltheores:silver_other_ore",
- "alltheores:silver_slate_ore",
- "alltheores:tin_end_ore",
- "alltheores:tin_nether_ore",
- "alltheores:tin_ore",
- "alltheores:tin_other_ore",
- "alltheores:tin_slate_ore",
- "alltheores:uranium_end_ore",
- "alltheores:uranium_nether_ore",
- "alltheores:uranium_ore",
- "alltheores:uranium_other_ore",
- "alltheores:uranium_slate_ore",
- "alltheores:zinc_end_ore",
- "alltheores:zinc_nether_ore",
- "alltheores:zinc_ore",
- "alltheores:zinc_other_ore",
- "alltheores:zinc_slate_ore",
- "minecraft:coal_ore",
- "minecraft:deepslate_coal_ore",
- "alltheores:coal_end_ore",
- "alltheores:coal_nether_ore",
- "alltheores:coal_other_ore",
- }
- table.includes = function(tbl, item)
- for i = 1, #tbl do
- if tbl[i] == item then
- return true
- end
- end
- return false
- end
- local Network = {}
- Network.__index = Network
- function Network.new(modem)
- local self = setmetatable({}, Network)
- if modem == nil then
- error("Unable to create network, no modem provided", 2)
- end
- self.registry = registry
- self.DEFAULT_CHANNEL = 42424
- self.expectedPackets = {}
- self.outgoingPackets = {}
- self.responseTime = 3
- self.modems = { modem }
- return self
- end
- function Network:Listen()
- while true do
- local event, id, channel, reply, message = os.pullEvent()
- if argument == "debug" then
- print("l", event, id, channel, message)
- end
- if event == "network_disconnect" then
- self.expectedPackets = {}
- self.outgoingPackets = {}
- break
- end
- if event == "timer" or event == "modem_message" then
- local closed = {}
- for i = 1, #self.expectedPackets do
- local packet = self.expectedPackets[i]
- if event == "timer" and id == packet.timeout then
- table.remove(self.expectedPackets, i)
- i = i - 1
- end
- if event == "modem_message" and channel == packet.channel and message == packet.message then
- table.remove(self.expectedPackets, i)
- table.insert(closed, channel)
- os.queueEvent(packet.uuid)
- os.cancelTimer(packet.timeout)
- i = i - 1
- end
- end
- local connection = self.connection
- if connection then
- if event == "timer" and connection.timeoutID == id then
- os.queueEvent("connection_end")
- self.connection = nil
- self:CancelRepeatedPacket(connection.signalUUID)
- connection.status = 0
- if connection.timeoutListener then
- connection.timeoutListener(connection)
- end
- table.insert(closed, channel)
- elseif event == "modem_message" and channel == connection.channel then
- os.cancelTimer(connection.timeoutID)
- connection.timeoutID = os.startTimer(self.responseTime)
- if connection.status == 0 and message == connection.message then
- connection.status = 1
- connection.timeout = self.responseTime
- os.queueEvent("network_connect", connection.UUID)
- if connection.connectedListener then
- connection.connectedListener(connection)
- end
- elseif connection.status == 1 and message ~= connection.message then
- os.queueEvent("connection_update", message)
- end
- end
- end
- for i = 1, #closed do
- local required = false
- for _, packet in pairs(self.expectedPackets) do
- local channel = closed[i]
- if packet.channel == channel then
- required = true
- break
- end
- end
- if not required then
- self:CloseChannel(channel)
- end
- end
- if event == "timer" then
- for i, packet in pairs(self.outgoingPackets) do
- if packet.timerID == id then
- if self:Transmit(packet.channel, packet.message, packet.wireless) then
- local timer = os.startTimer(packet.period)
- packet.timerID = timer
- if argument == "debug" then
- print("u", "send", packet.channel, packet.message, packet.wireless)
- end
- else
- table.remove(self.outgoingPackets, i)
- end
- break
- end
- end
- end
- end
- end
- end
- -- https://gist.github.com/jrus/3197011
- function Network:GenerateEventUUID()
- local template = "STNPxxxx-xxxx-xxxx"
- return string.gsub(template, "[x]", function(c)
- return string.format("%x", math.random(0, 0xf))
- end)
- end
- function Network:Stop()
- os.queueEvent("network_disconnect")
- end
- function Network:WaitForAll(timeout)
- local timerID = os.startTimer(timeout or 60)
- while #self.expectedPackets > 0 do
- local event, id = os.pullEvent()
- if event == "timer" and id == timerID then
- break
- end
- end
- return #self.expectedPackets == 0
- end
- function Network:WaitForBatch(batch, timeout)
- local events = {}
- local result = {}
- for i, packet in pairs(batch) do
- table.insert(
- events,
- Network:Expect(packet.channel, packet.message, timeout, function(success)
- result[i] = success
- return packet.callback(success)
- end)
- )
- end
- parallel.waitForAll(unpack(events))
- return result
- end
- function Network:Wait(channel, message, timeout, callback)
- return self:Expect(channel, message, timeout, callback)()
- end
- function Network:Expect(channel, message, timeout, callback)
- local packetUUID = self:GenerateEventUUID()
- local timerID = timeout == false and -1 or os.startTimer(timeout or 30)
- self:OpenChannel(channel)
- table.insert(self.expectedPackets, {
- channel = channel,
- message = message,
- timeout = timerID,
- uuid = packetUUID,
- })
- return function()
- while true do
- local event, id = os.pullEvent()
- if event == "timer" and id == timerID then
- if callback then
- return callback(false)
- end
- return false
- end
- if event == packetUUID then
- if callback then
- return callback(false)
- end
- return true
- end
- end
- end
- end
- function Network:HasModem(otherModem)
- for i, modem in pairs(self.modems) do
- for channel = 1, 65535 do
- if not (modem.isOpen(channel) or otherModem.isOpen(channel)) then
- modem.open(channel)
- local newOpen = otherModem.isOpen(channel)
- modem.close(channel)
- return newOpen
- end
- end
- end
- return false
- end
- function Network:AddModem(newModem)
- if self:HasModem(newModem) then
- return false
- end
- table.insert(self.modems, newModem)
- return true
- end
- function Network:OpenChannel(channel, wireless)
- if wireless == nil then
- wireless = true
- end
- for _, modem in pairs(self.modems) do
- if
- ((modem.isWireless() and wireless) or (not modem.isWireless() and not wireless)) and modem.isOpen(channel)
- then
- return true
- end
- end
- for _, modem in pairs(self.modems) do
- if
- ((modem.isWireless() and wireless) or (not modem.isWireless() and not wireless))
- and pcall(modem.open, channel)
- then
- return true
- end
- end
- error("Too many channels open, no modems available", 2)
- end
- function Network:CloseChannel(channel)
- for _, modem in pairs(self.modems) do
- if modem.isOpen(channel) then
- modem.close(channel)
- end
- end
- end
- function Network:Transmit(channel, message, wireless)
- if #self.modems == 0 then
- error("No modem available to transmit message", 2)
- end
- if wireless == nil then
- wireless = true
- end
- for _, modem in pairs(self.modems) do
- local isWireless = select(2, pcall(modem.isWireless))
- if (isWireless and wireless) or not (isWireless or wireless) then
- modem.transmit(channel, channel, message)
- return true
- end
- end
- return false
- end
- function Network:SendRepeatedPacket(channel, message, period, wireless)
- local uuid = self:GenerateEventUUID()
- local timerID = os.startTimer(period)
- if self:Transmit(channel, message, wireless) then
- table.insert(self.outgoingPackets, {
- uuid = uuid,
- timerID = timerID,
- channel = channel,
- message = message,
- period = period,
- wireless = wireless,
- })
- else
- os.cancelTimer(timerID)
- return
- end
- return uuid
- end
- function Network:CancelRepeatedPacket(uuid)
- for i, packet in pairs(self.outgoingPackets) do
- if packet.uuid == uuid then
- os.cancelTimer(packet.timerID)
- table.remove(self.outgoingPackets, i)
- return true
- end
- end
- return false
- end
- function Network:GetListenerHandle()
- return function()
- self:Listen()
- end
- end
- function Network:Obfuscate(str, id, reverse)
- local lid = os.getComputerID()
- math.randomseed(id >= lid and (id * id + id + lid) or (id + lid * lid))
- if #str % 2 == 1 then
- str = str .. ";"
- end
- local keys = {}
- local mul = reverse and 2 or 1
- local len = #str / (2 * mul)
- for i = 1, 16 do
- local key = {}
- for i = 1, len do
- table.insert(key, math.random(0, 255))
- end
- keys[i] = key
- end
- local function xor8(x, y)
- return (math.floor(x / 0x80) == math.floor(y / 0x80) and 0 or 0x80)
- + (math.floor(x / 0x40) % 2 == math.floor(y / 0x40) % 2 and 0x00 or 0x40)
- + (math.floor(x / 0x20) % 2 == math.floor(y / 0x20) % 2 and 0x00 or 0x20)
- + (math.floor(x / 0x10) % 2 == math.floor(y / 0x10) % 2 and 0x00 or 0x10)
- + (math.floor(x / 0x08) % 2 == math.floor(y / 0x08) % 2 and 0x00 or 0x08)
- + (math.floor(x / 0x04) % 2 == math.floor(y / 0x04) % 2 and 0x00 or 0x04)
- + (math.floor(x / 0x02) % 2 == math.floor(y / 0x02) % 2 and 0x00 or 0x02)
- + (x % 2 == y % 2 and 0x00 or 0x01)
- end
- local function xor(x, y)
- local o = {}
- for i = 1, #x do
- table.insert(o, xor8(x[i], y[i]))
- end
- return o
- end
- local L, R = {}, {}
- for i = 1, #str, mul do
- local chunk = reverse and tonumber(str:sub(i, i + 1), 16) or str:byte(i)
- if i <= #str / 2 then
- table.insert(L, chunk)
- else
- table.insert(R, chunk)
- end
- end
- if not reverse then
- for i = 1, #keys do
- L, R = R, xor(L, xor(keys[i], R))
- end
- else
- for i = #keys, 1, -1 do
- L, R = R, xor(L, xor(keys[i], R))
- end
- end
- local out = ""
- for i = 1, len do
- if reverse then
- out = out .. string.char(R[i])
- else
- out = out .. ("%02x"):format(R[i])
- end
- end
- for i = 1, len do
- if reverse then
- if not (L[i] == 59 and i == len) then
- out = out .. string.char(L[i])
- end
- else
- out = out .. ("%02x"):format(L[i])
- end
- end
- return out
- end
- function Network:IsConnected()
- return self.connection ~= nil
- end
- function Network:ConnectToServer(timeout, timeoutListener, connectedListener)
- if self:IsConnected(t) then
- return self.connection.UUID
- end
- local message = self:Obfuscate(settings.get("uuid") .. "-CONNECT", settings.get("cid"))
- local timerID = os.startTimer(timeout or 300)
- local UUID = self:GenerateEventUUID()
- self:OpenChannel(settings.get("channel"), true)
- self.connection = {
- status = 0,
- timeoutID = timerID,
- timeout = timeout or 60,
- channel = settings.get("channel"),
- message = message,
- signalUUID = self:SendRepeatedPacket(settings.get("channel"), message, 1, true),
- timeoutListener = timeoutListener,
- connectedListener = connectedListener,
- UUID = UUID,
- }
- return function()
- while true do
- local event, id = os.pullEvent()
- if event == "timer" and id == timerID then
- return nil
- end
- if event == "network_connect" and id == UUID then
- return UUID
- end
- end
- end
- end
- function Network:ReadCommand(s)
- --[[
- data format
- entries split by :
- status=1:key=value:ins=1,3,2#scan|
- until the ins key, where we
- split by #
- ]]
- local directionMap = {
- N = { 0, 0, -1 },
- S = { 0, 0, 1 },
- W = { -1, 0, 0 },
- E = { 1, 0, 0 },
- }
- local info = {}
- for chunk in s:gmatch("[^:]+") do
- local bits = {}
- for bit in chunk:gmatch("[^=]+") do
- table.insert(bits, bit)
- end
- if #bits ~= 2 or not bits[1]:match("%a") then
- return
- end
- local key = bits[1]
- if key == "ins" then
- local ins = {}
- for i in bits[2]:gmatch("[^/]+") do
- local dat = {}
- for k in i:gmatch("[^#]+") do
- table.insert(dat, k)
- end
- if #dat ~= 2 or not dat[2]:match("%a") then
- return
- end
- local coords = {}
- for dir in dat[1]:gmatch("[^,]+") do
- local n = tonumber(dir)
- if n == nil and #coords < 3 then
- return
- end
- table.insert(coords, n or dir)
- end
- if #coords ~= 4 then
- return
- end
- if not coords[4]:match("[NESW~]") then
- return
- end
- table.insert(ins, {
- direction = directionMap[table.remove(coords, 4)],
- position = coords,
- action = dat[2],
- })
- end
- info.ins = ins
- else
- local anum = tonumber(bits[2])
- info[key] = anum ~= nil and anum or bits[2]
- end
- end
- return info
- end
- function Network:WaitForCommand()
- if not self:IsConnected() then
- return false
- end
- while true do
- local event, message = os.pullEvent()
- if event == "connection_end" then
- return false
- elseif event == "connection_update" then
- local data = self:Obfuscate(message, settings.get("cid"), true)
- print("new cmd", data)
- local read = self:ReadCommand(data)
- if read ~= nil then
- return true, read
- end
- end
- end
- end
- function Network:ConnectionSend(data)
- if not self:IsConnected() then
- return false
- end
- local chunks = {}
- for i, v in pairs(data) do
- table.insert(chunks, i .. "=" .. v)
- end
- local message = self:Obfuscate(table.concat(chunks, ":"), settings.get("cid"))
- self:Transmit(settings.get("channel"), message, true)
- end
- local ActionManager = {}
- ActionManager.__index = ActionManager
- function ActionManager.new(network)
- local self = setmetatable({}, ActionManager)
- self.network = network
- self.queue = {}
- self.position = nil
- self.endPosition = nil
- self.direction = nil
- self.fuel = turtle.getFuelLevel()
- self.fuelStorage = 1
- self.outStorage = 2
- self.toolStorage = 3
- self.canDig = true
- local geoScanner = peripheral.find("geoScanner")
- local item = turtle.getItemDetail(self.toolStorage)
- if item == nil or (item.name ~= "advancedperipherals:geo_scanner" and item.name ~= "minecraft:diamond_pickaxe") then
- if geoScanner == nil then
- error("Geo scanner missing from slot " .. self.toolStorage, 2)
- else
- error("Diamond pickaxe missing from slot " .. self.toolStorage, 2)
- end
- elseif geoScanner ~= nil then
- self.scanner = geoScanner
- turtle.select(self.toolStorage)
- turtle.equipRight()
- elseif geoScanner == nil then
- turtle.select(self.toolStorage)
- turtle.equipRight()
- self.scanner = peripheral.find("geoScanner")
- turtle.equipRight()
- end
- return self
- end
- function ActionManager:ClearQueue()
- self.queue = {}
- if self.trigger ~= nil then
- os.cancelTimer(self.trigger)
- end
- end
- function ActionManager:Refuel()
- if not self.canDig then
- turtle.select(self.toolStorage)
- turtle.equipRight()
- self.canDig = true
- end
- turtle.digUp()
- turtle.select(self.fuelStorage)
- turtle.placeUp()
- while not turtle.getItemDetail(self.fuelStorage) do
- turtle.suckUp(64)
- turtle.refuel(64)
- end
- turtle.dropUp(64)
- turtle.digUp()
- end
- function ActionManager:Update()
- while true do
- local event, id, success, msg = os.pullEvent()
- if event == "action_stop" then
- break
- end
- if event == "action_process" and #self.queue > 0 and self.processing then
- local item = self.queue[1]
- local action = item.action
- print("a!", #self.queue, action)
- if action == "scan" then
- if self.canDig then
- turtle.equipRight()
- turtle.select(self.toolStorage)
- self.canDig = false
- end
- local data = self.scanner.scan(8)
- if data ~= nil then
- item.callback(data)
- table.remove(self.queue, 1)
- end
- else
- if (action == "dig" or action == "digDown" or action == "digUp") and not self.canDig then
- turtle.select(self.toolStorage)
- turtle.equipRight()
- self.canDig = true
- end
- local success = turtle[action](unpack(item.arguments or {}))
- if success then
- table.remove(self.queue, 1)
- local returnLocation = true
- self.fuel = self.fuel - 1
- if action == "forward" then
- self.position.x = self.position.x + self.direction.x
- self.position.z = self.position.z + self.direction.z
- elseif action == "back" then
- self.position.x = self.position.x - self.direction.x
- self.position.z = self.position.z - self.direction.z
- elseif action == "up" then
- self.position.y = self.position.y + 1
- elseif action == "down" then
- self.position.y = self.position.y - 1
- else
- self.fuel = self.fuel + 1
- returnLocation = false
- if action == "turnLeft" then
- self.direction = {
- x = -self.direction.z,
- y = 0,
- z = self.direction.x,
- }
- elseif action == "turnRight" then
- self.direction = {
- x = self.direction.z,
- y = 0,
- z = -self.direction.x,
- }
- elseif action == "refuel" then
- self.fuel = turtle.getFuelLevel()
- end
- end
- if returnLocation then
- self.network:ConnectionSend({
- type = "locate",
- x = self.position.x,
- y = self.position.y,
- z = self.position.z,
- dx = self.direction.x,
- dy = self.direction.y,
- dz = self.direction.z,
- })
- end
- else
- if action == "forward" or action == "back" or action == "up" or action == "down" then
- if self.fuel <= 0 then
- self:Refuel()
- elseif action == "forward" and turtle.inspect() ~= nil then
- table.insert(self.queue, 1, { action = "dig" })
- elseif action == "up" and turtle.inspectUp() ~= nil then
- table.insert(self.queue, 1, { action = "digUp" })
- elseif action == "down" and turtle.inspectDown() ~= nil then
- table.insert(self.queue, 1, { action = "digDown" })
- end
- else
- if
- action == "digUp"
- or action == "dig"
- or action == "digDown"
- or action == "placeUp"
- or action == "place"
- or action == "placeDown"
- then
- if action == "digUp" or action == "dig" or action == "digDown" then
- if self.canDig then
- table.remove(self.queue, 1)
- else
- turtle.select(self.toolStorage)
- turtle.equipRight()
- self.canDig = true
- end
- end
- end
- end
- end
- end
- os.queueEvent("action_process")
- end
- end
- end
- function ActionManager:GetUpdateHandle()
- return function()
- return self:Update()
- end
- end
- function ActionManager:Start()
- if #self.queue > self.fuel then
- self:Refuel()
- end
- self.processing = true
- print("queuing", #self.queue)
- os.queueEvent("action_process")
- end
- function ActionManager:Pause()
- self.processing = false
- end
- function ActionManager:Stop()
- os.queueEvent("action_stop")
- self.processing = false
- self:ClearQueue()
- end
- function ActionManager:GenerateMinimumActionsTo(pos, dir)
- local cpos = self.endPosition
- local cdir = { x = self.endDirection.x, y = self.endDirection.y, z = self.endDirection.z }
- local actions = {}
- local diff = { x = pos.x - cpos.x, y = pos.y - cpos.y, z = pos.z - cpos.z }
- if diff.x ~= 0 then
- if cdir.x == 0 and ((diff.z > 0 and cdir.z > 0) or (diff.z < 0 and cdir.z < 0)) then
- if diff.z ~= 0 then
- for i = 1, math.abs(diff.z) do
- table.insert(actions, { action = "dig" })
- table.insert(actions, { action = "forward" })
- end
- end
- if (diff.x > 0 and cdir.z > 0) or (diff.x < 0 and cdir.z < 0) then
- table.insert(actions, { action = "turnLeft" })
- else
- table.insert(actions, { action = "turnRight" })
- end
- for i = 1, math.abs(diff.x) do
- table.insert(actions, { action = "dig" })
- table.insert(actions, { action = "forward" })
- end
- else
- if cdir.x == 0 then
- if (diff.x > 0 and cdir.z > 0) or (diff.x < 0 and cdir.z < 0) then
- table.insert(actions, { action = "turnLeft" })
- else
- table.insert(actions, { action = "turnRight" })
- end
- end
- if (diff.x > 0 and cdir.x < 0) or (diff.x < 0 and cdir.x > 0) then
- table.insert(actions, { action = "turnRight" })
- table.insert(actions, { action = "turnRight" })
- end
- for i = 1, math.abs(diff.x) do
- table.insert(actions, { action = "dig" })
- table.insert(actions, { action = "forward" })
- end
- if diff.z ~= 0 then
- if (diff.z > 0 and diff.x > 0) or (diff.z < 0 and diff.x < 0) then
- table.insert(actions, { action = "turnRight" })
- else
- table.insert(actions, { action = "turnLeft" })
- end
- for i = 1, math.abs(diff.z) do
- table.insert(actions, { action = "dig" })
- table.insert(actions, { action = "forward" })
- end
- end
- end
- elseif diff.z ~= 0 then
- if cdir.z == 0 then
- if (diff.z > 0 and cdir.x > 0) or (diff.z < 0 and cdir.x < 0) then
- table.insert(actions, { action = "turnRight" })
- else
- table.insert(actions, { action = "turnLeft" })
- end
- elseif (cdir.z > 0 and diff.z < 0) or (cdir.z < 0 and diff.z > 0) then
- table.insert(actions, { action = "turnRight" })
- table.insert(actions, { action = "turnRight" })
- end
- for i = 1, math.abs(diff.z) do
- table.insert(actions, { action = "dig" })
- table.insert(actions, { action = "forward" })
- end
- end
- if diff.y > 0 then
- for i = 1, math.abs(diff.y) do
- table.insert(actions, { action = "digUp" })
- table.insert(actions, { action = "up" })
- end
- elseif diff.y < 0 then
- for i = 1, math.abs(diff.y) do
- table.insert(actions, { action = "digDown" })
- table.insert(actions, { action = "down" })
- end
- end
- for i, v in pairs(actions) do
- if action == "turnLeft" then
- cdir = {
- x = -cdir.z,
- y = 0,
- z = cdir.x,
- }
- elseif action == "turnRight" then
- cdir = {
- x = cdir.z,
- y = 0,
- z = -cdir.x,
- }
- end
- end
- if dir ~= nil then
- if dir.x == 0 then
- if cdir.x == 0 and cdir.z ~= dir.z then
- table.insert(actions, { action = "turnLeft" })
- table.insert(actions, { action = "turnLeft" })
- elseif (cdir.x > 0 and dir.z < 0) or (cdir.x < 0 and dir.z > 0) then
- table.insert(actions, { action = "turnLeft" })
- elseif cdir.z ~= dir.z then
- table.insert(actions, { action = "turnRight" })
- end
- else
- if cdir.z == 0 and cdir.x ~= dir.x then
- table.insert(actions, { action = "turnRight" })
- table.insert(actions, { action = "turnRight" })
- elseif (cdir.z > 0 and dir.x < 0) or (cdir.z < 0 and dir.x > 0) then
- table.insert(actions, { action = "turnRight" })
- elseif cdir.x ~= dir.x then
- table.insert(actions, { action = "turnLeft" })
- end
- end
- end
- return actions, { x = pos.x, y = pos.y, z = pos.z }, cdir
- end
- function ActionManager:GetTimeTo(pos, dir)
- return #self:GenerateMinimumActions(pos, dir)
- end
- function ActionManager:CompileInstruction(ins)
- if self.position == nil then
- return
- end
- if ins.action == "scan" then
- table.insert(self.queue, {
- action = "scan",
- callback = function(data)
- local list = {}
- for i, block in pairs(list) do
- if table.includes(WHITELIST, block.name) then
- table.insert(list, block.x)
- table.insert(list, block.y)
- table.insert(list, block.z)
- end
- end
- list.type = "scan"
- self.network:ConnectionSend(list)
- end,
- })
- elseif ins.action == "move" then
- local aim = ins.position
- local aimDir = ins.direction
- local actions, endPos, endDir = self:GenerateMinimumActionsTo({
- x = aim[1],
- y = aim[2],
- z = aim[3],
- }, aimDir and {
- x = aimDir[1],
- y = aimDir[2],
- z = aimDir[3],
- } or nil)
- for i, action in pairs(actions) do
- table.insert(self.queue, action)
- end
- self.endPosition = endPos
- self.endDirection = endDir
- end
- end
- function ActionManager:LocateTurtle(px, py, pz)
- if self.canDig then
- turtle.select(self.toolStorage)
- turtle.equipRight()
- self.canDig = false
- end
- local x, y, z
- local scan = self.scanner.scan(8)
- for i, v in pairs(scan) do
- if v.name == "computercraft:computer_advanced" then
- x = -v.x + px
- y = -v.y + py
- z = -v.z + pz
- break
- end
- end
- if x == nil or y == nil or z == nil then
- error("Unable to locate turtle", 2)
- end
- self.position = { x = x, y = y, z = z }
- self.endPosition = { x = x, y = y, z = z }
- if self.fuel < 2 then
- self:Refuel()
- os.pullEvent("refuel_complete")
- end
- if turtle.inspect() and not self.canDig then
- turtle.select(self.toolStorage)
- turtle.equipRight()
- self.canDig = true
- turtle.dig()
- end
- if not turtle.forward() then
- error("Please clear space in front of the turtle for location purposes", 2)
- end
- if self.canDig then
- turtle.select(self.toolStorage)
- turtle.equipRight()
- self.canDig = false
- end
- os.sleep(2.05)
- local x, y, z
- local scan = self.scanner.scan(8)
- for i, v in pairs(scan) do
- if v.name == "computercraft:computer_advanced" then
- x = -v.x + px
- y = -v.y + py
- z = -v.z + pz
- break
- end
- end
- if x == nil or y == nil or z == nil then
- error("Unable to locate turtle", 2)
- end
- self.direction = { x = x - self.position.x, y = 0, z = z - self.position.z }
- self.endDirection = { x = x - self.position.x, y = 0, z = z - self.position.z }
- turtle.back()
- return self.position
- end
- local modem = peripheral.find("modem", function(_, o)
- return o.isWireless()
- end)
- local network = Network.new(modem)
- local actionManager = ActionManager.new(network)
- local function registrationSetup()
- local lan = peripheral.find("modem", function(_, o)
- return not o.isWireless()
- end)
- if not lan then
- error("Please connect the computer to the registration network", 2)
- end
- network:AddModem(lan)
- local drive = peripheral.find("drive")
- if not drive then
- error("Please connect the computer to the registration network", 2)
- end
- if not drive.isDiskPresent() then
- error("Please place a floppy disk into the drive", 2)
- end
- end
- local function registration()
- registrationSetup()
- network:OpenChannel(network.DEFAULT_CHANNEL, false)
- while true do
- print("Searching for a registration server...")
- local register = network:Wait(network.DEFAULT_CHANNEL, "ST-REG", false)
- if register then
- print("Registration server found, attempting connection...")
- network:OpenChannel(network.DEFAULT_CHANNEL, false)
- local signalUUID = network:SendRepeatedPacket(network.DEFAULT_CHANNEL, "ST-REG-CONFIRM", 1, false)
- local success = network:Wait(network.DEFAULT_CHANNEL, "ST-REG-FINISH", 30)
- network:CancelRepeatedPacket(signalUUID)
- if success then
- settings.load("disk/reg")
- settings.save()
- fs.delete("disk/reg")
- local uuid = settings.get("uuid")
- if uuid then
- print(("Successfully registered to the server as %s"):format(uuid))
- network:Transmit(settings.get("channel"), "ST-REG-SUCCESS", false)
- break
- else
- print("Failed to parse settings data, registration failed")
- end
- else
- print("Registration failed, try again later")
- end
- end
- end
- network:Stop()
- end
- local function deregistration()
- registrationSetup()
- if not settings.get("uuid") then
- error("This turtle is not registered to any server")
- return
- end
- local tchannel = settings.get("channel")
- network:OpenChannel(tchannel, false)
- while true do
- print("Searching for a registration server...")
- local register = network:Wait(tchannel, "ST-DEREG", false)
- if register then
- print("Registration server found, attempting connection...")
- network:OpenChannel(tchannel, false)
- local conUUID = network:Transmit(tchannel, "ST-DEREG-CONFIRM", false)
- local success = network:Wait(tchannel, "ST-DEREG-SUCCESS", 60)
- network:CancelRepeatedPacket(conUUID)
- if success then
- print("Deregistration successful")
- settings.clear()
- settings.save()
- break
- else
- print("Failed to connect to the server, please try again")
- end
- else
- print("This turtle is not registered to any system")
- end
- end
- network:Stop()
- end
- local function processCommand(actionManager, cmd)
- for i, v in pairs(cmd) do
- print(i, v)
- end
- if cmd.fuel then
- network:ConnectionSend({ type = "fuel", current = turtle.getFuelLevel(), max = turtle.getFuelLimit() })
- end
- if cmd.locate then
- if actionManager.position == nil then
- actionManager:LocateTurtle(cmd.cx, cmd.cy, cmd.cz)
- end
- local pos, dir = actionManager.position, actionManager.direction
- network:ConnectionSend({
- type = "locate",
- x = pos.x,
- y = pos.y,
- z = pos.z,
- dx = dir.x,
- dy = dir.y,
- dz = dir.z,
- })
- end
- if cmd.ins then
- for i, v in pairs(cmd.ins) do
- actionManager:CompileInstruction(v)
- end
- end
- if cmd.status then
- local status = cmd.status
- if status == "stop" then
- actionManager:Stop()
- elseif status == "pause" then
- actionManager:Pause()
- elseif status == "start" then
- actionManager:Start()
- end
- end
- end
- parallel.waitForAll(network:GetListenerHandle(), actionManager:GetUpdateHandle(), function()
- if argument == "join" then
- registration()
- elseif argument == "leave" then
- deregistration()
- end
- print("Connecting to the server...")
- local connectionUUID = network:ConnectToServer(60, function()
- error("Timed out attempting to connect to the server, try again")
- end, nil)()
- if connectionUUID then
- print("Connected")
- network.responseTime = 10
- while true do
- local continue, data = network:WaitForCommand()
- if continue then
- processCommand(actionManager, data)
- else
- break
- end
- end
- end
- print("Timed out")
- end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement