OreTracker/xray/init.lua
david 4d73085af4 V1.4: HUD Graphics
We now display XRAY or OREHUD when either feature is enabled.

  We also fix an issue where in singleplayer mode xray nodes don't get
cleaned up. (Like they do on a server)  < The ABM is still needed on the
server in cases where the server crashed.
2021-10-10 20:13:40 -04:00

219 lines
7.8 KiB
Lua

-- https://rubenwardy.com/minetest_modding_book/en/map/environment.html#finding-nodes
-- A public API
xray = {}
xray.S = minetest.get_translator("xray")
xray.modpath = minetest.get_modpath("xray")
xray.store = {}
xray.p_stats = {}
-- Settings
-- Do not set detect_range to a very high number it may cause extreme loads when there are multiple players with this range
-- Recommended range is 6 blocks
xray.detect_range = 6 -- Range in blocks
-- 0 or negative is instantanious updates (Which greatly impacts the server/client)
-- Recommended frequency is 1 second.
xray.scan_frequency = 1 -- Frequency in seconds
-- Light level that xray nodes emit (Max is 14 min is 0)
-- Recommended light_level is 4. (Provides enough light to use the mod, might need to use torches if you want it lighter, or adjust here)
xray.light_level = 4 -- From 0-14
-- Only turn this on if you have strange blobs of invisible blocks (due to a server crash, etc.)
--local fix_mode = false
-- This attempts to detect the gamemode
if not minetest.registered_nodes["default:stone"] then
if not minetest.registered_nodes["mcl_core:stone"] then
xray.gamemode = "N/A"
else
-- Attempt to determine if it's MCL5 or MCL2
if not minetest.registered_nodes["mcl_deepslate:deepslate"] then
xray.gamemode = "MCL2"
else
xray.gamemode = "MCL5"
end
end
else
xray.gamemode = "MTG"
end
minetest.log("action", "[oretracker-xray] Detected game "..xray.gamemode..".")
-- Form a container to track what ores we want to follow
xray.nodes = {}
-- Make our counterparts
dofile(xray.modpath .. "/register.lua")
dofile(xray.modpath .. "/abm.lua") -- The ABM passively will fix any nodes (and add a strange effect)
-- Make our api
dofile(xray.modpath .. "/api.lua")
-- Use api to assign ores we know/should be caring about
if xray.gamemode == "MCL2" or xray.gamemode == "MCL5" then
xray.add_node("mcl_core:stone") -- xray:mcl_stone
xray.add_node("mcl_core:granite") -- xray:mcl_granite
xray.add_node("mcl_core:andesite") -- xray:mcl_andesite
xray.add_node("mcl_core:diorite") -- xray:mcl_diorite
xray.add_node("mcl_core:sandstone") -- xray:mcl_sstone
xray.add_node("mcl_core:redsandstone") -- xray:mcl_rsstone
end
if xray.gamemode == "MCL5" then
xray.add_node("mcl_blackstone:blackstone") -- xray:mcl_bstone
xray.add_node("mcl_blackstone:basalt") -- xray:mcl_basalt
xray.add_node("mcl_nether:netherrack") -- xray:mcl_netherrack
-- Deepslate now included
xray.add_node("mcl_deepslate:deepslate") -- xray:mcl_deepslate
end
if xray.gamemode == "MTG" then
xray.add_node("default:stone") -- xray:mtg_stone
xray.add_node("default:desert_stone") -- xray:mtg_dstone
xray.add_node("default:sandstone") -- xray:mtg_sstone
xray.add_node("default:desert_sandstone") -- xray:mtg_dsstone
xray.add_node("default:silver_sandstone") -- xray:mtg_ssstone
end
-- Include our nodes so we can cleanup after ourselves
-- Yeah there will be warnings in your logs about unknown nodes but who really checks that anyway.
xray.add_node("xray:mtg_stone")
xray.add_node("xray:mtg_dstone")
xray.add_node("xray:mtg_sstone")
xray.add_node("xray:mtg_dsstone")
xray.add_node("xray:mtg_ssstone")
xray.add_node("xray:mcl_stone")
xray.add_node("xray:mcl_granite")
xray.add_node("xray:mcl_andesite")
xray.add_node("xray:mcl_diorite")
xray.add_node("xray:mcl_sstone")
xray.add_node("xray:mcl_rsstone")
xray.add_node("xray:mcl_bstone")
xray.add_node("xray:mcl_basalt")
xray.add_node("xray:mcl_netherrack")
xray.add_node("xray:mcl_deepslate")
local size = 0
local result = "Nodes: "
for i, v in ipairs(xray.nodes) do
result = result..v.." "
size = size + 1
end
minetest.log("action", "[oretracker-xray] Found "..size.." nodes configured.")
minetest.log("action", "[oretracker-xray] "..result)
-- Itterates an area of nodes, then swaps nodes if stone or stone varient
xray.check_player = function(p)
local pos = p:get_pos()
local pname = p:get_player_name()
local p1 = vector.subtract(pos, {x = xray.detect_range, y = xray.detect_range, z = xray.detect_range})
local p2 = vector.add(pos, {x = xray.detect_range, y = xray.detect_range, z = xray.detect_range})
local area = minetest.find_nodes_in_area(p1, p2, xray.nodes)
for i=1, #area do
local node = minetest.get_node_or_nil(area[i])
if node == nil then
minetest.log("action", "[oretracker-xray] Failed to obtain node at "..minetest.pos_to_string(area[1], 1)..".")
else
local delta = vector.subtract(area[i], pos)
local distance = (delta.x*delta.x) + (delta.y*delta.y) + (delta.z*delta.z)
if distance <= xray.detect_range*xray.detect_range then
--distance = string.format("%.0f", math.sqrt(distance))
-- Place the counterpart
--minetest.log("action", "xray "..pname.." "..minetest.pos_to_string(area[1], 1))
if xray.p_stats[pname] then
-- Adds the counter since we are enabled
xray.add_pos(pname, area[i])
end
end
end
end
end
-- Now register with minetest to actually do something
local interval = 0
minetest.register_globalstep(function(dtime)
interval = interval - dtime
if interval <= 0 then
for _, player in ipairs(minetest.get_connected_players()) do
local p = player
if not minetest.is_player(p) then
p = minetest.get_player_by_name(p)
end
if p ~= nil then
-- I need to clean up the player's nodes added by the latter code
xray.clear_pos(p:get_player_name())
-- Now make new nodes
xray.check_player(p)
end
end
interval = xray.scan_frequency
end
end)
minetest.register_on_joinplayer(function(player, laston)
xray.p_stats[player:get_player_name()] = nil
end)
minetest.register_on_leaveplayer(function(player, timeout)
local indx = 0
local found = false
for pname, val in ipairs(xray.p_stats) do
if pname == player:get_player_name() then
found = true
break
end
indx = indx + 1
end
if found then
-- Attempt to cleanup that player's invisible nodes before they log off
player:hud_remove(xray.p_stats[player:get_player_name()])
xray.clear_pos(player:get_player_name())
xray.p_stats[player:get_player_name()] = nil
table.remove(xray.p_stats, indx)
end
end)
-- Attempt to cleanup xrays in a singleplayer world
minetest.register_on_shutdown(function ()
for _, player in ipairs(minetest.get_connected_players()) do
xray.clear_pos(player:get_player_name())
end
end)
-- A priv for players so they can't abuse this power
minetest.register_privilege("xray", {
description = "Oretracker Xray Priv",
give_to_singleplayer = true -- Also given to those with server priv
})
minetest.register_chatcommand("xray", {
privs = {
shout = true,
xray = true -- Require our xray
},
func = function(name, param)
if xray.p_stats[name] then
local p = minetest.get_player_by_name(name)
if p ~= nil then
p:hud_remove(xray.p_stats[name])
xray.p_stats[name] = nil
end
else
local p = minetest.get_player_by_name(name)
if p ~= nil then
xray.p_stats[name] = p:hud_add({
hud_elem_type = "text",
position = {x = 0.9, y = 0.9},
offset = {x = 0.0, y = 0.0},
text = " XRAY ",
number = 0x00e100, -- 0, 225, 0 (RGB)
alignment = {x = 0.0, y = 0.0},
scale = {x = 100.0, y = 100.0}
})
end
end
end,
})