minertools: common code moved to functions.lua.

functions.lua file contains functions planned for reuse
with coming all-in-one devices.

Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
This commit is contained in:
Michal Cieslakiewicz 2018-10-05 20:57:21 +02:00
parent cc503d5663
commit b6933064a9
5 changed files with 170 additions and 141 deletions

157
minertools/functions.lua Normal file
View File

@ -0,0 +1,157 @@
--[[
Common functions for devices in this mod.
]]--
minertools = {}
-- ******************
-- Play sound effects
-- ******************
function minertools.play_beep_ok(player_name)
minetest.sound_play("minertools_beep_ok", {
to_player = player_name,
gain = 0.8,
})
end
function minertools.play_beep_err(player_name)
minetest.sound_play("minertools_beep_err", {
to_player = player_name,
gain = 0.5,
})
end
function minertools.play_scan(player_name)
minetest.sound_play("minertools_scan", {
to_player = player_name,
gain = 0.8,
})
end
function minertools.play_click(player_name)
minetest.sound_play("minertools_click", {
to_player = player_name,
gain = 0.6,
})
end
function minertools.play_pulse(player_name)
minetest.sound_play("minertools_pulse", {
to_player = player_name,
gain = 0.8,
})
end
-- *******************
-- Node classification
-- *******************
-- check if node is of type that device can scan
-- (only nodes of natural origin can be analyzed properly)
function minertools.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
function minertools.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
-- ************
-- Calculations
-- ************
-- calculate relative temperature (aka gradient based on thermal sources nearby)
-- return: temperature gradient
function minertools.calculate_rel_temp(pos, radius)
local scan_vec = vector.new({x = radius, y = radius, z = radius})
local scan_pos1 = vector.subtract(pos, scan_vec)
local scan_pos2 = vector.add(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(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(pos, v)
if vd <= radius then
temp_var = temp_var + 1 / ( vd * vd )
end
end
return temp_var
end
-- directional scan for specified mineral
-- parameters: pos - device position (vector)
-- range - scan depth (float)
-- look_dir - direction of looking (normalized vector)
-- name - ore to search for (string)
-- return: mineral count, blocked by obsidian true/false
function minertools.dir_mineral_scan(pos, range, look_dir, name)
local node = {}
local pos_vec = {}
local last_vec = nil
local orecount = 0
local obsblock = false
for i = 1, range, 1 do
pos_vec = vector.add(pos, vector.round(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 == name then
orecount = orecount + 1
elseif minertools.has_obsidian(node.name) then
obsblock = true
break
end
end
last_vec = pos_vec -- protects against double count
end
end
return orecount, obsblock
end
-- scan for ores in cubic area
-- parameters: pos - device position (vector)
-- range - scan max range (float)
-- nodes - node names to search for (array)
-- return: mineral table (keys - node names, values - node count)
function minertools.area_mineral_scan(pos, range, nodes)
local scan_vec = vector.new({x = range, y = range, z = range})
local scan_pos1 = vector.subtract(pos, scan_vec)
local scan_pos2 = vector.add(pos, scan_vec)
local _, minerals = minetest.find_nodes_in_area(scan_pos1, scan_pos2, nodes)
return minerals
end

View File

@ -32,74 +32,17 @@ local msg_hot = minetest.get_color_escape_sequence("#FFC0C0")
local msg_cold = minetest.get_color_escape_sequence("#C0C0FF")
local msg_yellow = minetest.get_color_escape_sequence("#FFFF00")
-- ****************
-- Helper 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
-- produce sounds
local function beep_ok(player_name)
minetest.sound_play("minertools_beep_ok", {
to_player = player_name,
gain = 0.8,
})
end
local function beep_err(player_name)
minetest.sound_play("minertools_beep_err", {
to_player = player_name,
gain = 0.5,
})
end
-- calculate and show relative temperature
function geothermometer.show_rel_temp(itemstack, user, pointed_thing)
if pointed_thing.type ~= "node" then return nil end
local player_name = user:get_player_name()
local node_pos = vector.new(pointed_thing.under)
if not is_mineral(minetest.get_node(node_pos).name) then
beep_err(player_name)
if not minertools.is_mineral(minetest.get_node(node_pos).name) then
minertools.play_beep_err(player_name)
return nil
end
local scan_vec = vector.new({x = scan_range, y = scan_range,
z = scan_range})
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 <= scan_range 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 <= scan_range then
temp_var = temp_var + 1 / ( vd * vd )
end
end
beep_ok(player_name)
local temp_var = minertools.calculate_rel_temp(node_pos, scan_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

View File

@ -1,6 +1,7 @@
-- This mod adds Miner's Electronic Tools
-- (c) Micu 2018
dofile(minetest.get_modpath("minertools").."/functions.lua")
dofile(minetest.get_modpath("minertools").."/mining_chip.lua")
dofile(minetest.get_modpath("minertools").."/geothermometer.lua")
dofile(minetest.get_modpath("minertools").."/mineralscanner.lua")

View File

@ -53,63 +53,14 @@ for i, _ in pairs(ore_list) do
end
local head_vec = vector.new({x = 0, y = 1, z = 0})
-- ****************
-- Helper functions
-- ****************
-- produce sound
local function sound_pulse(player_name)
minetest.sound_play("minertools_pulse", {
to_player = player_name,
gain = 0.8,
})
end
local function sound_click(player_name)
minetest.sound_play("minertools_click", {
to_player = player_name,
gain = 0.6,
})
end
-- check if node includes 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
-- scan for selected ore in front of device
function mineralfinder.scan_for_mineral(itemstack, user, pointed_thing)
local player_name = user:get_player_name()
local head_pos = vector.add(vector.round(user:getpos()), head_vec)
local look_dir = user:get_look_dir() -- normalized vec (x,y,z = -1..1)
local node = {}
local pos_vec = {}
local last_vec = nil
local orecount = 0
local obsblock = false
for i = 1, scan_range, 1 do
pos_vec = vector.add(head_pos, vector.round(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_stones[cur_stone_idx] then
orecount = orecount + 1
elseif has_obsidian(node.name) then
obsblock = true
break
end
end
last_vec = pos_vec -- protects against double count
end
end
local orecount, obsblock = minertools.dir_mineral_scan(head_pos,
scan_range, look_dir,
ore_stones[cur_stone_idx])
local oremsg = ""
if orecount > 0 then oremsg = msg_plus
else oremsg = msg_zero end
@ -118,7 +69,7 @@ function mineralfinder.scan_for_mineral(itemstack, user, pointed_thing)
oremsg = oremsg .. msg_warn ..
" (warning - scan incomplete, blocked by obsidian)"
end
sound_pulse(player_name)
minertools.play_pulse(player_name)
minetest.chat_send_player(player_name,
msg_yellow .. "[MineralFinder]" .. msg_white ..
" Scan result for " .. msg_zero ..
@ -130,7 +81,7 @@ end
function mineralfinder.change_mineral_type(itemstack, user_placer, pointed_thing)
local player_name = user_placer:get_player_name()
sound_click(player_name)
minertools.play_click(player_name)
cur_stone_idx = cur_stone_idx + 1
if cur_stone_idx > #ore_stones then
cur_stone_idx = 1

View File

@ -43,34 +43,11 @@ for i, _ in pairs(ore_list) do
ore_stones[#ore_stones + 1] = i
end
-- ****************
-- Helper functions
-- ****************
-- produce sound
local function sound_scan(player_name)
minetest.sound_play("minertools_scan", {
to_player = player_name,
gain = 0.8,
})
end
local function sound_range(player_name)
minetest.sound_play("minertools_click", {
to_player = player_name,
gain = 0.6,
})
end
-- scan for ores with center at current player position
function mineralscanner.scan_for_minerals(itemstack, user, pointed_thing)
local player_name = user:get_player_name()
local player_pos = vector.round(user:getpos())
local scan_vec = vector.new({x = scan_range, y = scan_range,
z = scan_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_stones)
minerals = minertools.area_mineral_scan(player_pos, scan_range, ore_stones)
local oremsg = ""
for orenode, orecount in pairs(minerals) do
local oms = ore_list[orenode] .. " = " .. orecount
@ -82,7 +59,7 @@ function mineralscanner.scan_for_minerals(itemstack, user, pointed_thing)
oremsg = oms
end
end
sound_scan(player_name)
minertools.play_scan(player_name)
minetest.chat_send_player(player_name,
msg_yellow .. "[MineralScanner]" .. msg_white ..
" Scan results for cubic range " .. scan_range ..
@ -92,7 +69,7 @@ end
function mineralscanner.change_scan_range(itemstack, user_placer, pointed_thing)
local player_name = user_placer:get_player_name()
sound_range(player_name)
minertools.play_click(player_name)
scan_range = scan_range - 1
if scan_range == 0 then
scan_range = scan_range_max