local PROTOCOL = "automine" local TARGET = "devplayer0" local DIM_MAP = { overworld = "Overworld", the_nether = "Nether", the_end = "End", } local ICON_BASE = "https://p.nul.ie/cc/icon/" local ORE_ICONS = { ["minecraft:coal_ore"] = "coal", ["minecraft:deepslate_coal_ore"] = "ds-coal", ["minecraft:iron_ore"] = "iron", ["minecraft:deepslate_iron_ore"] = "ds-iron", ["minecraft:copper_ore"] = "copper", ["minecraft:deepslate_copper_ore"] = "ds-copper", ["minecraft:gold_ore"] = "gold", ["minecraft:deepslate_gold_ore"] = "ds-gold", ["minecraft:redstone_ore"] = "redstone", ["minecraft:deepslate_redstone_ore"] = "ds-redstone", ["minecraft:emerald_ore"] = "emerald", ["minecraft:deepslate_emerald_ore"] = "ds-emerald", ["minecraft:lapis_ore"] = "lapis", ["minecraft:deepslate_lapis_ore"] = "ds-lapis", ["minecraft:diamond_ore"] = "diamond", ["minecraft:deepslate_diamond_ore"] = "ds-diamond", ["minecraft:glowstone"] = "glowstone", ["minecraft:nether_quartz_ore"] = "nether-quartz", ["minecraft:ancient_debris"] = "ancient-debris", -- ["create:ochrum"] =, ["create:zinc_ore"] = "zinc", ["create:deepslate_zinc_ore"] = "ds-zinc", ["create_new_age:thorium_ore"] = "thorium", ["powah:deepslate_uraninite_ore_poor"] = "ds-uraninite-poor", ["powah:deepslate_uraninite_ore"] = "ds-uraninite", ["powah:deepslate_uraninite_ore_dense"] = "ds-uraninite-dense", ["powah:uraninite_ore_poor"] = "uraninite-poor", ["powah:uraninite_ore"] = "uraninite", ["powah:uraninite_ore_dense"] = "uraninite-dense", } function oreIcon(t) local i = "generic" if ORE_ICONS[t] then i = ORE_ICONS[t] end return ICON_BASE .. "ore-" .. i .. ".png" end function vecToStr(v) return v.x .. "," .. v.y .. "," .. v.z end function markerSet(msg) return "autominer_" .. msg.name end Chat = {} function Chat.new(prefix) local self = setmetatable({}, { __index = Chat }) self.chat = peripheral.find("chatBox") self.detector = peripheral.find("playerDetector") self.prefix = prefix self.lastSend = 0 return self end function Chat:send(msg, target) local delta = os.clock() - self.lastSend if delta < 1 then local amount = 1 - delta + 0.1 sleep(amount) end local msgJSON = textutils.serializeJSON(msg) -- print(msgJSON) if target and self.detector.getPlayerPos(target).dimension then assert(self.chat.sendFormattedMessageToPlayer(msgJSON, target, self.prefix)) else assert(self.chat.sendFormattedMessage(msgJSON, self.prefix)) end self.lastSend = os.clock() end MineMonitor = {} function MineMonitor.new(chat, target) local self = setmetatable({}, { __index = MineMonitor }) self.chat = chat self.target = target self.cart = peripheral.find("cartographer") self.cart.refreshIntegrations() peripheral.find("modem", rednet.open) return self end function MineMonitor:prepareMap(msg) local map = DIM_MAP[msg.dimension] assert(map) assert(self.cart.setCurrentMap(map)) local id = markerSet(msg) local sets = self.cart.getMarkerSets() assert(sets) local found = false for _, s in ipairs(sets) do if s == id then found = true break end end if not found then assert(self.cart.addMarkerSet(id, "AutoMiner " .. msg.name)) end return id end function MineMonitor:setPosMarker(msg) local id = markerSet(msg) local mId = id .. "_pos" self.cart.removeMarker(id, mId) self.cart.addPOIMarker( id, mId, msg.name, msg.name .. "'s position", msg.pos.x, msg.pos.y, msg.pos.z, ICON_BASE .. "turtle.png") end function MineMonitor:handleStart(msg) self.chat:send({ {text = msg.name, color = "green"}, {text = " @ ", color = "white"}, {text = vecToStr(msg.pos), color = "aqua"}, {text = " in ", color = "white"}, {text = msg.dimension, color = "aqua"}, {text = " found ", color = "white"}, {text = tostring(msg.oreCount), color = "red"}, {text = " ores (", color = "white"}, {text = tostring(#msg.veins), color = "red"}, {text = " veins) on iteration ", color = "white"}, {text = tostring(msg.i), color = "green"}, {text = "!", color = "white"}, }) local id = self:prepareMap(msg) self.cart.clearMarkerSet(id) self:setPosMarker(msg) local veinPoints = {} for i, v in ipairs(msg.veins) do table.insert(veinPoints, v.pos) self.cart.addPOIMarker( id, id .. "_vein_" .. i, v.count .. " " .. v.type, "Vein of " .. v.count .. " " .. v.type, v.pos.x, v.pos.y, v.pos.z, oreIcon(v.type)) end if #veinPoints >= 2 then self.cart.addLineMarker( id, id .. "_vein_path", "Mining path #" .. msg.i, "Current mining path", "#FF00FF", 0.7, 3, veinPoints) end end function MineMonitor:handleVein(msg) self.chat:send({ {text = msg.name, color = "green"}, {text = " @ ", color = "white"}, {text = vecToStr(msg.pos), color = "aqua"}, {text = " in ", color = "white"}, {text = msg.dimension, color = "aqua"}, {text = " is mining ", color = "white"}, {text = tostring(msg.oreCount), color = "red"}, {text = " ", color = "white"}, {text = msg.oreType, color = "dark_purple"}, {text = " (vein ", color = "white"}, {text = tostring(msg.i), color = "red"}, {text = " / ", color = "white"}, {text = tostring(msg.total), color = "red"}, {text = ")!", color = "white"}, }, self.target) local id = self:prepareMap(msg) self:setPosMarker(msg) if msg.i ~= 1 then self.cart.removeMarker(id, id .. "_vein_" .. (msg.i - 1)) end end function MineMonitor:handleRecall(msg) self.chat:send({ {text = msg.name, color = "green"}, {text = " @ ", color = "white"}, {text = vecToStr(msg.pos), color = "aqua"}, {text = " in ", color = "white"}, {text = msg.dimension, color = "aqua"}, {text = " is recalling to ", color = "white"}, {text = vecToStr(msg.to), color = "green"}, {text = "!", color = "white"}, }) local id = self:prepareMap(msg) self.cart.clearMarkerSet(id) self:setPosMarker({ name = msg.name, pos = msg.to, }) end function MineMonitor:handleRecallProgress(msg) self.chat:send({ {text = msg.name, color = "green"}, {text = " @ ", color = "white"}, {text = vecToStr(msg.pos), color = "aqua"}, {text = " in ", color = "white"}, {text = msg.dimension, color = "aqua"}, {text = " is ", color = "white"}, {text = "still", color = "green"}, {text = " recalling to ", color = "white"}, {text = vecToStr(msg.to), color = "green"}, {text = "!", color = "white"}, }, self.target) self:prepareMap(msg) self:setPosMarker(msg) end function MineMonitor:loop() while true do local _, sender, msg = os.pullEvent("mine_monitor_message") local handler = nil if msg.type == "iterationStart" then handler = self.handleStart elseif msg.type == "veinStart" then handler = self.handleVein elseif msg.type == "ackRecall" then handler = self.handleRecall elseif msg.type == "recallProgress" then handler = self.handleRecallProgress end if handler then handler(self, msg) end end end function MineMonitor:netLoop() while true do local sender, msg = rednet.receive(PROTOCOL) os.queueEvent("mine_monitor_message", sender, msg) end end function MineMonitor:run() parallel.waitForAll( function() self:loop() end, function() self:netLoop() end ) end local chat = Chat.new("AutoMine") local mineMon = MineMonitor.new(chat, TARGET) mineMon:run()