--[[ ========================================= Miner's Electronic Tools by Micu (c) 2018 License: LGPLv2.1+ ========================================= ]]-- minertools = {} --[[ --------- Variables --------- ]]-- -- parameters if minetest.settings:get_bool("minertools_flashlight_on") then light_level = minetest.LIGHT_MAX else light_level = 0 end -- recognized ores local find_ore_list = { "default:stone_with_coal", "default:stone_with_iron", "default:stone_with_copper", "default:stone_with_tin", "default:stone_with_gold", "default:stone_with_mese", "default:stone_with_diamond" } if minetest.get_modpath("moreores") then find_ore_list[#find_ore_list + 1] = "moreores:mineral_silver" find_ore_list[#find_ore_list + 1] = "moreores:mineral_mithril" end local scan_ore_list = table.copy(find_ore_list) scan_ore_list[#scan_ore_list + 1] = "default:obsidian" -- colors local msg_white = minetest.get_color_escape_sequence("#FFFFFF") local msg_yellow = minetest.get_color_escape_sequence("#FFFF00") local msg_warn = minetest.get_color_escape_sequence("#FF8080") local msg_zero = minetest.get_color_escape_sequence("#00FFFF") local msg_plus = minetest.get_color_escape_sequence("#FF00FF") local msg_hot = minetest.get_color_escape_sequence("#FFC0C0") local msg_cold = minetest.get_color_escape_sequence("#C0C0FF") local msg_high = minetest.get_color_escape_sequence("#52D017") local msg_medium = minetest.get_color_escape_sequence("#EAC117") local msg_low = minetest.get_color_escape_sequence("#E56717") -- mineral labels (for display) local ore_label = {} ore_label["default:stone_with_coal"] = "coal" ore_label["default:stone_with_iron"] = "iron" ore_label["default:stone_with_copper"] = "copper" ore_label["default:stone_with_tin"] = "tin" ore_label["default:stone_with_gold"] = "gold" ore_label["default:stone_with_mese"] = "mese" ore_label["default:stone_with_diamond"] = "diamond" ore_label["default:obsidian"] = "obsidian" if minetest.get_modpath("moreores") then ore_label["moreores:mineral_silver"] = "silver" ore_label["moreores:mineral_mithril"] = "mithril" end -- multidevice MODE_GEOTHERM = 1 MODE_ORESCAN = 2 MODE_OREFIND = 3 local mode_name = { [MODE_GEOTHERM] = "Geothermometer", [MODE_ORESCAN] = "Mineral Scanner", [MODE_OREFIND] = "Mineral Finder" } -- fast lookup tables local rev_ore_label = {} for n, l in pairs(ore_label) do rev_ore_label[l] = n end local rev_mode_name = {} for i, m in pairs(mode_name) do rev_mode_name[m] = i end --[[ --------------- Sound functions --------------- ]]-- local function play_beep_ok(player_name) minetest.sound_play("minertools_beep_ok", { to_player = player_name, gain = 0.8, }) end local function play_beep_err(player_name) minetest.sound_play("minertools_beep_err", { to_player = player_name, gain = 0.5, }) end local function play_scan(player_name) minetest.sound_play("minertools_scan", { to_player = player_name, gain = 0.8, }) end local function play_click(player_name) minetest.sound_play("minertools_click", { to_player = player_name, gain = 0.6, }) end local function play_pulse(player_name) minetest.sound_play("minertools_pulse", { to_player = player_name, gain = 0.8, }) end local function play_toggle(player_name) minetest.sound_play("minertools_toggle", { to_player = player_name, gain = 0.6, }) end --[[ ------------------ Matching functions ------------------ ]]-- -- check if node is of type that device can scan -- (only nodes of natural origin can be analyzed properly) local function is_mineral(name) if name == nil then return false end if minetest.get_item_group(name, "sand") > 0 then return true end if minetest.get_item_group(name, "soil") > 0 then return true end if minetest.get_item_group(name, "stone") > 0 then return true end if string.match(name, "^default:stone_with_") then return true end if name == "default:gravel" or name == "default:clay" then return true end if minetest.get_modpath("moreores") then if string.match(name, "^moreores:mineral_") then return true end end return false end -- check if node is made of obsidian local function has_obsidian(name) if name == nil then return false end if string.match(name, "^default:obsidian") then return true end if minetest.get_modpath("stairs") then -- part of minetest game now if string.match(name, "^stairs:stair_obsidian") or string.match(name, "^stairs:slab_obsidian") then return true end end return false end -- check if node is in array local function is_member_of(name, array) for _, n in ipairs(array) do if n == name then return true end end return false end --[[ ------------- Settings Menu ------------- ]]-- -- show formspec local function show_menu(item, player, pointed_thing) local player_name = player:get_player_name() local tool_def = item:get_definition() tool_def._init_metadata(player, item) minetest.show_formspec(player_name, tool_def.name, tool_def._formspec(item)) end -- formspec callback minetest.register_on_player_receive_fields(function(player, formname, fields) if not string.match(formname, "^minertools:") then return false end local player_name = player:get_player_name() local tool = player:get_wielded_item() local tool_meta = tool:get_meta() local tool_upd = false local play_snd = true if fields and fields.ok then play_snd = false end if formname == "minertools:mineral_scanner" then if fields and fields.range then tool_meta:set_int("scan_range", tonumber(fields.range)) if play_snd then play_click(player_name) end tool_upd = true end elseif formname == "minertools:mineral_finder" then if fields and fields.ore then tool_meta:set_string("ore_type", rev_ore_label[fields.ore]) if play_snd then play_click(player_name) end tool_upd = true end elseif formname == "minertools:portable_mining_computer" or formname == "minertools:advanced_mining_assistant" or formname == "minertools:ultimate_mining_gizmo" then if fields then if fields.mode then tool_meta:set_int("mode", rev_mode_name[fields.mode]) if play_snd then play_toggle(player_name) end tool_upd = true end if fields.range then tool_meta:set_int("scan_range", tonumber(fields.range)) if play_snd then play_click(player_name) end tool_upd = true end if fields.ore then tool_meta:set_string("ore_type", rev_ore_label[fields.ore]) if play_snd then play_click(player_name) end tool_upd = true end end end if tool_upd then player:set_wielded_item(tool) end if fields and fields.ok then play_click(player_name) minetest.close_formspec(player_name, formname) end return true end) --[[ ---------------- Device formspecs ---------------- ]]-- local function mineralscanner_formspec(tool) -- function requires all metadata to be accessible -- (or initialized elsewhere) local tool_def = tool:get_definition() local range_min = tool_def._scan_range_min local range_max = tool_def._scan_range_max local tool_meta = tool:get_meta() local range = tool_meta:get_int("scan_range") local range_opts = "" for i = range_min, range_max, 1 do range_opts = range_opts .. tostring(i) if i < range_max then range_opts = range_opts .. "," end end return "size[3,2,true]".. "position[0.5,0.25]" .. "no_prepend[]" .. "label[0.5,0;" .. minetest.colorize("#FFFF00", "Mineral Scanner") .. "]" .. "label[0,0.75;Scan range]" .. "dropdown[1.75,0.625;1;range;" .. range_opts .. ";" .. (range - range_min + 1) .. "]" .. "button[0.75,1.75;1.5,0.5;ok;OK]" end local function mineralfinder_formspec(tool) -- function requires all metadata to be accessible -- (or initialized elsewhere) local tool_def = tool:get_definition() local ore_list = tool_def._find_ore_list local tool_meta = tool:get_meta() local ore_type = tool_meta:get_string("ore_type") local ore_opts = "" local ore_idx = 0 for i, n in ipairs(ore_list) do ore_opts = ore_opts .. ore_label[n] if i < #ore_list then ore_opts = ore_opts .. "," end if n == ore_type then ore_idx = i end end return "size[3,2,true]".. "position[0.5,0.25]" .. "no_prepend[]" .. "label[0.5,0;" .. minetest.colorize("#FFFF00", "Mineral Finder") .. "]" .. "label[0.25,0.75;Ore]" .. "dropdown[1.25,0.625;1.5;ore;" .. ore_opts .. ";" .. ore_idx .. "]" .. "button[0.75,1.75;1.5,0.5;ok;OK]" end local function multidevice_formspec(tool) -- function requires all metadata to be accessible -- (or initialized elsewhere) local tool_def = tool:get_definition() local label = tool_def.description local tool_meta = tool:get_meta() local mode = tool_meta:get_int("mode") local mode_opts = "" for i, n in ipairs(mode_name) do mode_opts = mode_opts .. n if i < #mode_name then mode_opts = mode_opts .. "," end end local range_min = tool_def._scan_range_min local range_max = tool_def._scan_range_max local range = tool_meta:get_int("scan_range") local range_opts = "" for i = range_min, range_max, 1 do range_opts = range_opts .. tostring(i) if i < range_max then range_opts = range_opts .. "," end end local ore_list = tool_def._find_ore_list local ore_type = tool_meta:get_string("ore_type") local ore_opts = "" local ore_idx = 0 for i, n in ipairs(ore_list) do ore_opts = ore_opts .. ore_label[n] if i < #ore_list then ore_opts = ore_opts .. "," end if n == ore_type then ore_idx = i end end return "size[4.25,4,true]".. "position[0.5,0.25]" .. "no_prepend[]" .. "label[0.5,0;" .. minetest.colorize("#FFFF00", label) .. "]" .. "label[0,0.75;" .. minetest.colorize("#00FFFF", "Mode") .. "]" .. "dropdown[1.75,0.625;2.5;mode;" .. mode_opts .. ";" .. mode .. "]" .. "label[0.5,1.75;Scan range]" .. "dropdown[2.5,1.625;1;range;" .. range_opts .. ";" .. (range - range_min + 1) .. "]" .. "label[0.5,2.75;Ore]" .. "dropdown[2,2.625;1.5;ore;" .. ore_opts .. ";" .. ore_idx .. "]" .. "button[1.25,3.75;1.5,0.5;ok;OK]" end --[[ --------------- Device metadata --------------- ]]-- local function mineralscanner_init_metadata(player, tool) -- write correct metadata only if not present or invalid local tool_def = tool:get_definition() local range_min = tool_def._scan_range_min local range_max = tool_def._scan_range_max local tool_meta = tool:get_meta() local range = tool_meta:get_int("scan_range") if range < range_min or range > range_max then tool_meta:set_int("scan_range", range_max) player:set_wielded_item(tool) -- update item return true end return false end local function mineralfinder_init_metadata(player, tool) -- write correct metadata only if not present or invalid local tool_def = tool:get_definition() local ore_list = tool_def._find_ore_list local tool_meta = tool:get_meta() local ore_type = tool_meta:get_string("ore_type") if not is_member_of(ore_type, ore_list) then tool_meta:set_string("ore_type", "default:stone_with_coal") player:set_wielded_item(tool) -- update item return true end return false end local function multidevice_init_metadata(player, tool) -- write correct metadata only if not present or invalid local tool_def = tool:get_definition() local tool_meta = tool:get_meta() local tool_upd = false -- mode select local mode = tool_meta:get_int("mode") if mode < 1 or mode > #mode_name then tool_meta:set_int("mode", MODE_GEOTHERM) tool_upd = true end -- mineral scanner module local range_min = tool_def._scan_range_min local range_max = tool_def._scan_range_max local range = tool_meta:get_int("scan_range") if range < range_min or range > range_max then tool_meta:set_int("scan_range", range_max) tool_upd = true end -- mineral finder module local ore_list = tool_def._find_ore_list local ore_type = tool_meta:get_string("ore_type") if not is_member_of(ore_type, ore_list) then tool_meta:set_string("ore_type", "default:stone_with_coal") tool_upd = true end -- all done if tool_upd then player:set_wielded_item(tool) end return tool_upd end --[[ ---------------- Device functions ---------------- ]]-- -- geothermometer (GT) -- parameters: item - item object (itemstack) -- player - player object (player) -- pointed_thing - node object (node) local function geothermometer_use(item, player, pointed_thing) if pointed_thing.type ~= "node" then return nil end local player_name = player:get_player_name() local node_pos = vector.new(pointed_thing.under) if not is_mineral(minetest.get_node(node_pos).name) then play_beep_err(player_name) return nil end local tool_def = item:get_definition() local label = tool_def._temp_label local radius = tool_def._temp_radius local scale = tool_def._temp_scale local strfmt = tool_def._temp_fmt local scan_vec = vector.new({x = radius, y = radius, z = radius}) local scan_pos1 = vector.subtract(node_pos, scan_vec) local scan_pos2 = vector.add(node_pos, scan_vec) local water = minetest.find_nodes_in_area(scan_pos1, scan_pos2, { "group:water" }) local lava = minetest.find_nodes_in_area(scan_pos1, scan_pos2, { "group:lava" }) local temp_var = 0.0 for _, v in ipairs(water) do local vd = vector.distance(node_pos, v) if vd <= radius then temp_var = temp_var - 1 / ( vd * vd ) end end for _, v in ipairs(lava) do local vd = vector.distance(node_pos, v) if vd <= radius then temp_var = temp_var + 1 / ( vd * vd ) end end local msg_val_clr = msg_white if temp_var < 0 then msg_val_clr = msg_cold elseif temp_var > 0 then msg_val_clr = msg_hot end play_beep_ok(player_name) minetest.chat_send_player(player_name, msg_yellow .. "[" .. label .. "]" .. msg_white .. " Temperature gradient for this block is " .. msg_val_clr .. string.format(strfmt, scale * temp_var) .. msg_white) return nil end -- mineral scanner (MS) -- parameters: item - item object (itemstack) -- player - player object (player) -- pointed_thing - node object (node) local function mineralscanner_use(item, player, pointed_thing) local player_name = player:get_player_name() local player_pos = vector.round(player:getpos()) local tool_def = item:get_definition() tool_def._init_metadata(player, item) local label = tool_def._scan_label local range_min = tool_def._scan_range_min local range_max = tool_def._scan_range_max local ore_list = tool_def._scan_ore_list local item_meta = item:get_meta() local range = item_meta:get_int("scan_range") local scan_vec = vector.new({x = range, y = range, z = range}) local scan_pos1 = vector.subtract(player_pos, scan_vec) local scan_pos2 = vector.add(player_pos, scan_vec) local _, minerals = minetest.find_nodes_in_area(scan_pos1, scan_pos2, ore_list) local oremsg = "" -- we do like our ore order for i, n in ipairs(ore_list) do local orecount = minerals[n] if orecount == 0 then oremsg = oremsg .. msg_zero else oremsg = oremsg .. msg_plus end oremsg = oremsg .. ore_label[n] .. " = " .. orecount if i < #ore_list then oremsg = oremsg .. msg_white .. ", " end end play_scan(player_name) minetest.chat_send_player(player_name, msg_yellow .. "[" .. label .. "]" .. msg_white .. " Scan results for cubic range " .. range .. " : " .. oremsg .. msg_white) return item end -- mineral finder (MF) -- parameters: item - item object (itemstack) -- player - player object (player) -- pointed_thing - node object (node) local function mineralfinder_use(item, player, pointed_thing) local player_name = player:get_player_name() local player_pos = vector.round(player:getpos()) local look_dir = player:get_look_dir() -- norm vec local tool_def = item:get_definition() tool_def._init_metadata(player, item) local label = tool_def._find_label local depth = tool_def._find_depth local det_lvl = tool_def._find_detail local item_meta = item:get_meta() local ore_name = item_meta:get_string("ore_type") local head_pos = vector.add(player_pos, { x = 0, y = 1, z = 0 }) local node = {} local pos_vec = {} local last_vec = nil local orecount = 0 local obsblock = false local oredepth = 0 for i = 1, depth, 1 do pos_vec = vector.round(vector.add(head_pos, vector.multiply(look_dir, i))) if not last_vec or not vector.equals(pos_vec, last_vec) then node = minetest.get_node_or_nil(pos_vec) if node then if node.name == ore_name then orecount = orecount + 1 if oredepth == 0 then oredepth = i end elseif has_obsidian(node.name) then obsblock = true break end end last_vec = pos_vec -- protects against double count end end local oremsg = "" if orecount > 0 then oremsg = msg_plus else oremsg = msg_zero end oremsg = oremsg .. orecount if oredepth > 0 then if det_lvl == 1 then oremsg = oremsg .. msg_white .. " (signal strength: " if oredepth <= depth / 3 then oremsg = oremsg .. msg_high .. "HIGH" elseif oredepth > depth * 2 / 3 then oremsg = oremsg .. msg_low .. "LOW" else oremsg = oremsg .. msg_medium .. "MEDIUM" end oremsg = oremsg .. msg_white .. ")" elseif det_lvl == 2 then oremsg = oremsg .. msg_white .. " (signal strength: " local sigpct = 100.0 * (depth - oredepth + 1) / depth if sigpct >= 75 then oremsg = oremsg .. msg_high elseif sigpct < 25 then oremsg = oremsg .. msg_low else oremsg = oremsg .. msg_medium end oremsg = oremsg .. string.format("%d%%", sigpct) .. msg_white .. ")" end end if obsblock then oremsg = oremsg .. msg_warn .. " (warning - scan incomplete, blocked by obsidian)" end play_pulse(player_name) minetest.chat_send_player(player_name, msg_yellow .. "[" .. label .. "]" .. msg_white .. " Scan result for " .. msg_zero .. ore_label[ore_name] .. msg_white .. " : " .. oremsg .. msg_white) return item end -- multidevices (PMC, AMA, UMG) -- parameters: item - item object (itemstack) -- player - player object (player) -- pointed_thing - node object (node) local function multidevice_use(item, player, pointed_thing) local player_name = player:get_player_name() local tool_def = item:get_definition() tool_def._init_metadata(player, item) local tool_meta = item:get_meta() local mode = tool_meta:get_int("mode") if mode == MODE_GEOTHERM then geothermometer_use(item, player, pointed_thing) elseif mode == MODE_ORESCAN then mineralscanner_use(item, player, pointed_thing) elseif mode == MODE_OREFIND then mineralfinder_use(item, player, pointed_thing) end return item end --[[ ----------------- Tool registration ----------------- ]]-- --[[ Mining Chip v1.0 Mandatory component for all electronic devices in this mod ]]-- minetest.register_craftitem("minertools:mining_chip", { description = "Mining Chip", inventory_image = "minertools_miningchip_inv.png", }) --[[ Geothermometer device v3.0 Principle of calculations: heat energy dissipates with square distance from source (twice the distance four times less heat) Works only on "natural" blocks like dirt, stone, sand and ores Calculations explained: * initial block temperature variation = 0.0 * find all water blocks in range, count them and find distance from block, then change temperature adding -sum(1/d^2) * find all lava blocks in range, count them and find distance from block, then change temperature adding +sum(1/d^2) * resulting value shows how nearby water or lava affects block temperature * scale it by chosen factor to amplify differences ]]-- minetest.register_tool("minertools:geothermometer", { description = "Geothermometer", wield_image = "minertools_geothermometer_hand.png", wield_scale = { x = 1, y = 1, z = 1 }, inventory_image = "minertools_geothermometer_inv.png", stack_max = 1, range = 8, _is_multidevice = false, _temp_label = "Geothermometer", _temp_radius = 10, -- radius for heat calculation _temp_scale = 50, -- scaling factor for output value _temp_fmt = "%+.4f", -- display format on_use = geothermometer_use }) --[[ Portable Mineral Scanner v3.0 Scans cube around player with specified range and provides feedback with ore quantity. Notice: area scanned is cube (2 * range + 1) not sphere Left click - scan and show results Right click - device menu ]]-- minetest.register_tool("minertools:mineral_scanner", { description = "Portable Mineral Scanner", wield_image = "minertools_mineralscanner_hand.png", wield_scale = { x = 1, y = 1, z = 1 }, inventory_image = "minertools_mineralscanner_inv.png", stack_max = 1, range = 0, _init_metadata = mineralscanner_init_metadata, _formspec = mineralscanner_formspec, _is_multidevice = false, _scan_label = "MineralScanner", _scan_range_min = 1, _scan_range_max = 8, _scan_ore_list = scan_ore_list, on_use = mineralscanner_use, on_place = show_menu, on_secondary_use = show_menu, }) --[[ Portable Mineral Finder v3.0 Short range directional radar that detects presence of selected ore in front of device. Notice: obsidian blocks signal so area behind it remains unexplored. Node position calculation by multiplying directional normalized vector is susceptible to rounding errors, so device has limited range to preserve acceptable accuracy. More accurate methods involve numerical complexity (Bresenham for example) so IMHO its better to follow KISS principle. Left click - scan Right click - device menu ]]-- minetest.register_tool("minertools:mineral_finder", { description = "Portable Mineral Finder", wield_image = "minertools_mineralfinder_hand.png", wield_scale = { x = 1, y = 1, z = 1 }, inventory_image = "minertools_mineralfinder_inv.png", stack_max = 1, range = 4, _init_metadata = mineralfinder_init_metadata, _formspec = mineralfinder_formspec, _is_multidevice = false, _find_label = "MineralFinder", _find_depth = 5, _find_detail = 0, _find_ore_list = find_ore_list, on_use = mineralfinder_use, on_place = show_menu, on_secondary_use = show_menu, }) --[[ Portable Mineral Computer aka PMC v3.0 This is all-in-one device that provides functionality of geothermometer, mineral scanner and mineral finder. These basic components are all connected and managed by dedicated Mining Chip. Thanks to this, although in one box, there is no signal loss or decreased range. Technical info: 3 devices combined into one with no modifications Left click - scan and show results Right click - device menu ]]-- minetest.register_tool("minertools:portable_mining_computer", { description = "Portable Mining Computer", wield_image = "minertools_pmc_hand.png", wield_scale = { x = 1, y = 1, z = 1 }, inventory_image = "minertools_pmc_inv.png", stack_max = 1, range = 8, _init_metadata = multidevice_init_metadata, _formspec = multidevice_formspec, _is_multidevice = true, _temp_label = "PMC:Geothermometer", _temp_radius = 10, _temp_scale = 50, _temp_fmt = "%+.4f", _scan_label = "PMC:MineralScanner", _scan_range_min = 1, _scan_range_max = 8, _scan_ore_list = scan_ore_list, _find_label = "PMC:MineralFinder", _find_depth = 5, _find_detail = 0, _find_ore_list = find_ore_list, on_use = multidevice_use, on_place = show_menu, on_secondary_use = show_menu, }) --[[ Advanced Mining Assistant aka AMA v3.0 This one is an upgraded version of PMC. Adding one more Mining Chip, gold circuitry and obsidian dampers allows PMC ranges and overall sensivity to be safely increased. Operational actions remain identical to PMC. Technical differences to PMC: * increased tool range * increased MineralFinder range * increased MineralScanner range * increased Geothermometer sensivity range * finder signal strength (low/medium/high) indicates distance to ore Left click - scan and show results Right click - device menu ]]-- minetest.register_tool("minertools:advanced_mining_assistant", { description = "Advanced Mining Assistant", wield_image = "minertools_ama_hand.png", wield_scale = { x = 1, y = 1, z = 1 }, inventory_image = "minertools_ama_inv.png", stack_max = 1, range = 10, -- PMC + 2 _init_metadata = multidevice_init_metadata, _formspec = multidevice_formspec, _is_multidevice = true, _temp_label = "AMA:Geothermometer", _temp_radius = 12, -- PMC + 2 _temp_scale = 50, _temp_fmt = "%+.4f", _scan_label = "AMA:MineralScanner", _scan_range_min = 1, _scan_range_max = 12, -- PMC + 2 _scan_ore_list = scan_ore_list, _find_label = "AMA:MineralFinder", _find_depth = 8, -- PMC + 3 _find_detail = 1, -- PMC ++ _find_ore_list = find_ore_list, on_use = multidevice_use, on_place = show_menu, on_secondary_use = show_menu, }) --[[ Ultimate Mining Gizmo aka UMG v3.0 This amazing device is an enhanced version of AMA. Ranges and sensivity are increased again, now thanks to optoelectronics based on diamonds and obsidian glass, all managed by (you guess it) dedicated Mining Chip. Operational actions remain identical to PMC and AMA. Technical differences to AMA: * increased tool range * increased MineralFinder range * increased MineralScanner range * increased Geothermometer sensivity range * increased Geothermometer display precision * finder signal strength (in percent) indicates distance to ore Left click - scan and show results Right click - device menu ]]-- minetest.register_tool("minertools:ultimate_mining_gizmo", { description = "Ultimate Mining Gizmo", wield_image = "minertools_umg_hand.png", wield_scale = { x = 1, y = 1, z = 1 }, inventory_image = "minertools_umg_inv.png", light_source = light_level, stack_max = 1, range = 12, -- AMA + 2 _init_metadata = multidevice_init_metadata, _formspec = multidevice_formspec, _is_multidevice = true, _temp_label = "UMG:Geothermometer", _temp_radius = 16, -- AMA + 4 _temp_scale = 50, _temp_fmt = "%+.6f", -- AMA ++ _scan_label = "UMG:MineralScanner", _scan_range_min = 1, _scan_range_max = 16, -- AMA + 4 _scan_ore_list = scan_ore_list, _find_label = "UMG:MineralFinder", _find_depth = 12, -- AMA + 4 _find_detail = 2, -- AMA ++ _find_ore_list = find_ore_list, on_use = multidevice_use, on_place = show_menu, on_secondary_use = show_menu, }) --[[ -------- Crafting -------- ]]-- minetest.register_craft({ output = "minertools:mining_chip", type = "shaped", recipe = { { "default:copper_ingot", "default:gold_ingot", "default:copper_ingot" }, { "default:copper_ingot", "default:mese_crystal", "default:copper_ingot" }, { "default:copper_ingot", "group:sand", "default:copper_ingot" }, }, }) minetest.register_craft({ output = "minertools:geothermometer", type = "shaped", recipe = { { "default:steel_ingot", "default:diamond", "default:steel_ingot" }, { "default:steel_ingot", "default:mese_crystal", "default:steel_ingot" }, { "default:steel_ingot", "minertools:mining_chip", "default:steel_ingot" }, }, }) minetest.register_craft({ output = "minertools:mineral_scanner", type = "shaped", recipe = { { "default:steel_ingot", "default:steel_ingot", "default:steel_ingot" }, { "default:mese_crystal", "default:gold_ingot", "default:mese_crystal" }, { "default:copper_ingot", "minertools:mining_chip", "default:copper_ingot" }, }, }) minetest.register_craft({ output = "minertools:mineral_finder", type = "shaped", recipe = { { "default:steel_ingot", "default:gold_ingot", "default:steel_ingot" }, { "default:gold_ingot", "default:mese_crystal", "default:gold_ingot" }, { "default:copper_ingot", "minertools:mining_chip", "default:copper_ingot" }, }, }) minetest.register_craft({ output = "minertools:portable_mining_computer", type = "shaped", recipe = { { "default:steel_ingot", "minertools:geothermometer", "default:steel_ingot" }, { "minertools:mineral_finder", "minertools:mining_chip", "minertools:mineral_scanner" }, { "default:steel_ingot", "default:mese_crystal", "default:steel_ingot" }, }, }) minetest.register_craft({ output = "minertools:advanced_mining_assistant", type = "shaped", recipe = { { "default:obsidian", "default:mese_crystal", "default:obsidian" }, { "default:gold_ingot", "minertools:portable_mining_computer", "default:gold_ingot" }, { "default:obsidian", "minertools:mining_chip", "default:obsidian" }, }, }) minetest.register_craft({ output = "minertools:ultimate_mining_gizmo", type = "shaped", recipe = { { "default:obsidian_glass", "default:mese_crystal", "default:obsidian_glass" }, { "default:diamond", "minertools:advanced_mining_assistant", "default:diamond" }, { "default:obsidian_glass", "minertools:mining_chip", "default:obsidian_glass" }, }, })