232 lines
7.6 KiB
Lua
Raw Normal View History

--[[
Portable Mineral Computer aka PMC v1.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.
Left click - scan and show results
Right click - change scan range/searched ore
Double right click - change device mode
]]--
-- ************************
-- Namespaces and variables
-- ************************
local pmc = {}
local MODE_GEOTHERM = 1
local MODE_OREFIND = 2
local MODE_ORESCAN = 3
local mode = MODE_GEOTHERM
local mode_name = { [MODE_GEOTHERM] = "Geothermometer",
[MODE_OREFIND] = "Mineral Finder",
[MODE_ORESCAN] = "Mineral Scanner", }
local tool_range = { [MODE_GEOTHERM] = 8, [MODE_OREFIND] = 5, [MODE_ORESCAN] = 0 }
local scan_range_min = 1
local scan_range_max = 8
local scan_range = scan_range_max
local find_range = 5
local temp_range = 10
local temp_scale = 50.0
local head_vec = vector.new({x = 0, y = 1, z = 0})
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 find_ore_list = {}
find_ore_list["default:stone_with_coal"] = "coal"
find_ore_list["default:stone_with_iron"] = "iron"
find_ore_list["default:stone_with_copper"] = "copper"
find_ore_list["default:stone_with_tin"] = "tin"
find_ore_list["default:stone_with_gold"] = "gold"
find_ore_list["default:stone_with_mese"] = "mese"
find_ore_list["default:stone_with_diamond"] = "diamond"
if minetest.get_modpath("moreores") then
find_ore_list["moreores:mineral_silver"] = "silver"
find_ore_list["moreores:mineral_mithril"] = "mithril"
end
local def_stone_idx = 1
local find_ore_stones = {}
for i, _ in pairs(find_ore_list) do
find_ore_stones[#find_ore_stones + 1] = i
if i == "default:stone_with_coal" then
def_stone_idx = #find_ore_stones
end
end
local cur_stone_idx = def_stone_idx
local scan_ore_list = {}
for i, n in pairs(find_ore_list) do
scan_ore_list[i] = n
end
scan_ore_list["default:obsidian"] = "obsidian"
local scan_ore_stones = {}
for i, _ in pairs(scan_ore_list) do
scan_ore_stones[#scan_ore_stones + 1] = i
end
local dbl_click_ms = 400
local last_rclick_ts = minetest.get_us_time()
-- activate device function
function pmc.use(itemstack, user, pointed_thing)
local player_name = user:get_player_name()
local player_pos = vector.round(user:getpos())
local node_pos = vector.new(pointed_thing.under)
if mode == MODE_GEOTHERM then
if pointed_thing.type ~= "node" then return nil end
if not minertools.is_mineral(minetest.get_node(node_pos).name) then
minertools.play_beep_err(player_name)
return nil
end
local temp_var = minertools.calculate_rel_temp(node_pos, temp_range)
minertools.play_beep_ok(player_name)
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
minetest.chat_send_player(player_name,
msg_yellow .. "[PMC:Geothermometer]" ..
msg_white ..
" Temperature gradient for this block is " ..
msg_val_clr ..
string.format("%+.4f", temp_scale * temp_var) ..
msg_white)
elseif mode == MODE_OREFIND then
local head_pos = vector.add(vector.round(user:getpos()), head_vec)
local look_dir = user:get_look_dir()
local orecount, obsblock = minertools.dir_mineral_scan(head_pos,
find_range, look_dir,
find_ore_stones[cur_stone_idx])
local oremsg = ""
if orecount > 0 then oremsg = msg_plus
else oremsg = msg_zero end
oremsg = oremsg .. orecount
if obsblock then
oremsg = oremsg .. msg_warn ..
" (warning - scan incomplete, blocked by obsidian)"
end
minertools.play_pulse(player_name)
minetest.chat_send_player(player_name,
msg_yellow .. "[PMC:MineralFinder]" .. msg_white ..
" Scan result for " .. msg_zero ..
find_ore_list[find_ore_stones[cur_stone_idx]] ..
msg_white .. " : " ..
oremsg .. msg_white)
elseif mode == MODE_ORESCAN then
local minerals = minertools.area_mineral_scan(player_pos,
scan_range, scan_ore_stones)
local oremsg = ""
for orenode, orecount in pairs(minerals) do
local oms = scan_ore_list[orenode] .. " = " .. orecount
if orecount == 0 then oms = msg_zero .. oms
else oms = msg_plus .. oms end
if oremsg ~= "" then
oremsg = oremsg .. msg_white .. ", " .. oms
else
oremsg = oms
end
end
minertools.play_scan(player_name)
minetest.chat_send_player(player_name,
msg_yellow .. "[PMC:MineralScanner]" .. msg_white ..
" Scan results for cubic range " .. scan_range ..
" : " .. oremsg .. msg_white)
end
return nil
end
function pmc.change_mode(itemstack, user_placer, pointed_thing)
local player_name = user_placer:get_player_name()
local rclick_ts = minetest.get_us_time()
-- detect right double-click
if rclick_ts - last_rclick_ts < dbl_click_ms * 1000 then
-- mode change
minertools.play_click(player_name)
mode = ((mode + 1) % 3) + 1
minetest.override_item("minertools:portable_mining_computer",
{range = tool_range[mode]})
minetest.chat_send_player(player_name,
msg_yellow .. "[PMC]" .. msg_white ..
" Switching mode to " .. msg_yellow ..
mode_name[mode] .. msg_white)
if mode == MODE_OREFIND then
cur_stone_idx = def_stone_idx
minetest.chat_send_player(player_name,
msg_yellow .. "[PMC:MineralFinder]" .. msg_white ..
" Mineral type set to " .. msg_zero ..
find_ore_list[find_ore_stones[cur_stone_idx]] ..
msg_white)
elseif mode == MODE_ORESCAN then
scan_range = scan_range_max
minetest.chat_send_player(player_name,
msg_yellow .. "[PMC:MineralScanner]" ..
msg_white .. " Scan range set to "
.. msg_zero .. scan_range .. msg_white)
end
else
-- option change
if mode == MODE_OREFIND then
cur_stone_idx = cur_stone_idx + 1
if cur_stone_idx > #find_ore_stones then
cur_stone_idx = 1
end
minertools.play_click(player_name)
minetest.chat_send_player(player_name,
msg_yellow .. "[PMC:MineralFinder]" .. msg_white ..
" Mineral type set to " .. msg_zero ..
find_ore_list[find_ore_stones[cur_stone_idx]] ..
msg_white)
elseif mode == MODE_ORESCAN then
scan_range = scan_range - 1
if scan_range == 0 then
scan_range = scan_range_max
end
minertools.play_click(player_name)
minetest.chat_send_player(player_name,
msg_yellow .. "[PMC:MineralScanner]" .. msg_white ..
" Scan range set to " .. msg_zero .. scan_range ..
msg_white)
end
end
last_rclick_ts = rclick_ts
return nil
end
-- *************
-- Register Tool
-- *************
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 = tool_range[mode],
on_use = pmc.use,
on_place = pmc.change_mode,
on_secondary_use = pmc.change_mode,
})
-- ************
-- Craft Recipe
-- ************
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" },
},
})