Skip to content

Instantly share code, notes, and snippets.

@505e06b2
Created September 15, 2025 18:03
Show Gist options
  • Select an option

  • Save 505e06b2/8305a0b09f4a7946ae2b863b356babee to your computer and use it in GitHub Desktop.

Select an option

Save 505e06b2/8305a0b09f4a7946ae2b863b356babee to your computer and use it in GitHub Desktop.
Minecraft Plethora Peripherals - Jarvis (Ore Radar)
local timeInit = require("time_module")
local oreInit = require("orescanner_module")
local modules = peripheral.find("neuralInterface")
if not modules then error("Must have a neural interface", 0) end
if not modules.hasModule("plethora:glasses") then error("The overlay glasses are missing", 0) end
if not modules.hasModule("plethora:scanner") then error("The block scanner is missing", 0) end
local canvas = modules.canvas()
canvas.clear()
local timeModule = timeInit(canvas)
local oreModule = oreInit(canvas)
local shouldScanForOres = false
print("Scanning for Ores:", shouldScanForOres, "\nSpace to toggle")
function process()
while true do
timeModule.process(modules)
oreModule.process(modules)
sleep(1 / 5)
end
end
function render()
while true do
timeModule.render(modules)
oreModule.render(modules, shouldScanForOres)
sleep(1 / 10)
end
end
function input()
while true do
local event, key, is_held = os.pullEvent("key")
if key == keys.space then
shouldScanForOres = not shouldScanForOres
print("Toggled Ore Scan:", shouldScanForOres)
end
end
end
parallel.waitForAny(
render,
process,
input
)
local scannerRange = 8
local scannerWidth = scannerRange * 2 + 1
local offsetX = 100
local offsetY = 100
--- These values aren't very exciting, they just control what the minimap looks like
local size = 0.5
local cellSize = 16
local data = {
--Overworld
["Diamond"] = {
["name"] = "D",
["priority"] = 100,
["colour"] = 0x9cfffdFF,
["blocks"] = { "minecraft:diamond_ore", "minecraft:deepslate_diamond_ore", "resource_nether_ores:nether_diamond_ore" }
},
["Emerald"] = {
["name"] = "E",
["priority"] = 10,
["colour"] = 0xa8f7acFF,
["blocks"] = { "minecraft:emerald_ore", "minecraft:deepslate_emerald_ore", "resource_nether_ores:nether_emerald_ore" }
},
["Gold"] = {
["name"] = "G",
["priority"] = 10,
["colour"] = 0xf7df9eFF,
["blocks"] = { "minecraft:gold_ore", "minecraft:deepslate_gold_ore", "minecraft:nether_gold_ore" }
},
["Iron"] = {
["name"] = "I",
["priority"] = 5,
["colour"] = 0xffed9cFF,
["blocks"] = { "minecraft:iron_ore", "minecraft:deepslate_iron_ore", "resource_nether_ores:nether_iron_ore" }
},
["Redstone"] = {
["name"] = "RS",
["priority"] = 5,
["colour"] = 0xFF0000FF,
["blocks"] = { "minecraft:redstone_ore", "minecraft:deepslate_redstone_ore", "resource_nether_ores:nether_redstone_ore" }
},
["Lapis Lazuli"] = {
["name"] = "L",
["priority"] = 5,
["colour"] = 0xacbdfcFF,
["blocks"] = { "minecraft:lapis_ore", "minecraft:deepslate_lapis_ore", "resource_nether_ores:nether_lapis_ore" }
},
["Copper"] = {
["name"] = "CO",
["priority"] = 1,
["colour"] = 0xfff8d9FF,
["blocks"] = { "minecraft:copper_ore", "minecraft:deepslate_copper_ore", "resource_nether_ores:nether_copper_ore" }
},
["Coal"] = {
["name"] = "C",
["priority"] = 1,
["colour"] = 0xFFFFFFFF,
["blocks"] = { "minecraft:coal_ore", "minecraft:deepslate_coal_ore", "resource_nether_ores:nether_coal_ore" }
},
--Nether
["Nether Quartz"] = {
["name"] = "Q",
["priority"] = 10,
["colour"] = 0xedffb3FF,
["blocks"] = { "minecraft:nether_quartz_ore" }
},
["Glowstone"] = {
["name"] = "GL",
["priority"] = 10,
["colour"] = 0xedffb3FF,
["blocks"] = { "minecraft:glowstone" }
},
--Create
["Zinc"] = {
["name"] = "Z",
["priority"] = 10,
["colour"] = 0x9ec9f7FF,
["blocks"] = { "create:zinc_ore", "create:deepslate_zinc_ore" }
},
--Indrev
["Tungsten"] = {
["name"] = "TU",
["priority"] = 50,
["colour"] = 0xfffdf2FF,
["blocks"] = { "indrev:tungsten_ore", "indrev:deepslate_tungsten_ore" }
},
["Lead"] = {
["name"] = "LE",
["priority"] = 50,
["colour"] = 0xfffdf2FF,
["blocks"] = { "indrev:lead_ore", "indrev:deepslate_lead_ore" }
},
["Silver"] = {
["name"] = "S",
["priority"] = 40,
["colour"] = 0xfffdf2FF,
["blocks"] = { "indrev:silver_ore", "indrev:deepslate_silver_ore" }
},
["Tin"] = {
["name"] = "T",
["priority"] = 10,
["colour"] = 0xfff7d6FF,
["blocks"] = { "indrev:tin_ore", "indrev:deepslate_tin_ore" }
},
["Nikolite"] = {
["name"] = "N",
["priority"] = 10,
["colour"] = 0xaafab3FF,
["blocks"] = { "indrev:nikolite_ore", "indrev:deepslate_nikolite_ore" }
},
}
local process_data = {}
for key, value in pairs(data) do
for _, block_name in ipairs(value.blocks) do
process_data[block_name] = value
end
end
local block_text = {}
local blocks = {}
--- We also create a marker showing the current player's location.
--canvas.addText({ offsetX, offsetY }, "^", 0xFFFFFFFF, size * 2)
local function process(modules)
local scanned_blocks = modules.scan()
--- For each nearby position, we search the y axis for interesting ores. We look for the one which has
--- the highest priority and update the block information
for x = -scannerRange, scannerRange do
for z = -scannerRange, scannerRange do
local best_score, best_block, best_y = -1
for y = -scannerRange, scannerRange do
--- The block scanner returns blocks in a flat array, so we index into it with this rather scary formulae.
local scanned = scanned_blocks[scannerWidth ^ 2 * (x + scannerRange) + scannerWidth * (y + scannerRange) + (z + scannerRange) + 1]
--- If there is a block here, and it's more interesting than our previous ores, then let's use that!
if scanned then
local current_block = process_data[scanned.name]
if current_block then
local new_score = current_block.priority
if new_score and new_score > best_score then
best_block = current_block
best_score = new_score
best_y = y
end
end
end
end
-- Update our block table with this information.
blocks[x][z].data = best_block
blocks[x][z].y = best_y
end
end
end
local function render(modules, draw_ores)
--- If possible, we rotate the map using the current player's look direction. If it's not available, we'll just
--- use north as up.
local meta = modules.getMetaOwner and modules.getMetaOwner()
local angle = meta and math.rad(-meta.yaw % 360) or math.rad(180)
--- Like before, loop over every nearby block and update something. Though this time we're updating objects on
--- the overlay canvas.
for x = -scannerRange, scannerRange do
for z = -scannerRange, scannerRange do
local text = block_text[x][z]
local block = blocks[x][z]
if draw_ores and block.data then
--- If we've got a block here, we update the position of our text element to account for rotation,
local px = math.cos(angle) * -x - math.sin(angle) * -z
local py = math.sin(angle) * -x + math.cos(angle) * -z
local sx = math.floor(px * size * cellSize)
local sy = math.floor(py * (size * 1.5) * cellSize)
text.setPosition(offsetX + sx, offsetY + sy -3)
--- Then change the text and colour to match the location of the ore
text.setText(string.format("%s\n%d", block.data.name, block.y))
text.setColor(block.data.colour)
else
--- Otherwise we just make sure the text is empty. We don't need to faff about with clearing the
--- colour or position, as we'll change it next iteration anyway.
text.setText(" ")
end
end
end
end
local function init(canvas)
local size_w, size_h = canvas.getSize()
offsetX = math.floor(size_w / 2) - 3
offsetY = math.floor(size_h / 2) - 2
for x = -scannerRange, scannerRange, 1 do
block_text[x] = {}
blocks[x] = {}
for z = -scannerRange, scannerRange, 1 do
block_text[x][z] = canvas.addText({ 0, 0 }, " ", 0xFFFFFFFF, size)
blocks[x][z] = { y = nil, data = nil }
end
end
--canvas.addText({ offsetX, offsetY }, "^", 0xFFFFFFFF, size * 2)
return {
["process"] = process,
["render"] = render
}
end
return init
local width = 45
local group = nil
local background = nil
local text = nil
local function process(modules) end
local function render(modules)
local time = os.time()
local timeFormatString = textutils.formatTime(os.time(), true)
if time < 10 then
timeFormatString = "0" .. timeFormatString
end
text.setText(timeFormatString)
end
local function init(canvas)
local size_w, size_y = canvas.getSize()
group = canvas.addGroup({ size_w - width, 80 })
background = group.addRectangle(0, 0, width, 10, 0x00000077)
text = group.addText({ x = 10, y = 1 }, "")
return {
["process"] = process,
["render"] = render
}
end
return init
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment