cc-programs/mineMonitor.lua

278 lines
7.4 KiB
Lua

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()