Merge pull request #1 from Beanzilla/dev

Merging in Dev, Xray and privs and chat commands
This commit is contained in:
Beanzilla 2021-10-08 17:55:42 -04:00 committed by GitHub
commit bf83340558
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 961 additions and 247 deletions

@ -15,5 +15,8 @@ read_globals = {
-- MTG
"default", "sfinv", "creative",
-- MCL
"mcl_sounds"
}

@ -1,54 +1,27 @@
# Ore Tracker
# Oretracker
A useful mod for tracking what ores are around the player.
Combines various tech to allow advanced mining operations.
## About this mod
## What's in the box
This mod provides a graphical HUD interface which displays a series of ores.
* Orehud: The original Oretracker mod with a single command to toggle the mod on or off per individual player.
* Xray: Based on Orehud except trackes non-ores and makes them appear invisible.
## The ores
## Orehud
| Ore name | Text Shown | Color code (HEX) |
|----------|------------|------------------|
| Coal | Coa | 0xc8c8c8 |
| Iron | Iro | 0xaf644b |
| Gold | Gol | 0xc8c84b |
| Mese\* | Mes | 0xffff4b |
| Diamond | Dia | 0x4bfafa |
| Quartz\*\*| Qua | 0xc8c8c8 |
| Copper\*\*\*| Cop | 0xc86400 |
| Tin\* | Tin | 0xc8c8c8 |
| Ancient Debris\*\*| Deb | 0xaa644b |
| Lapis | Lap | 0x4b4bc8 |
| Redstone\*\* | Red | 0xc81919 |
| Glowstone\*\* | Glo | 0xffff4b |
Displays ore positions via the player's HUD.
\* Only found in MTG.
> `/orehud` toggles the rendering of the ore positions on or off.
\*\* Found in MCL5 or MCL2 with the proper mods.
## Xray
\*\*\* Found in MTG and MCL5 or MCL2 with the proper mods.
Hides unwanted stone (and other varients) from view, only showing a empty node in it's wake.
## Settings
> `/xray` toggles the unwanted stone from visible to invisible (on or off).
### Detect Range
Yes, because xray interacts server side, all clients can make use of a single players client with xray. (This means you can see other players and ores they can see too by their xray)
The number of blocks away from the player the mod will scan/display for ores.
> Recommended 8 blocks with no more than 16 (Bigger numbers equals much higher loads on server and possibly client)
### Scan Frequency
The time in seconds till the mod updates ores it is indicating and if any new ores enter the scaning area (Dictated by Detect Range)
> Recommended no faster than 1 (for 1 second) (Lower numbers equals faster scans but can/will increase loads on server and possibly client)
> Use 0 or negative number to indicate instantanious (no delay) scans. (Not recommended)
# Future Plans
* Make a hand held item that dictates if the mod runs (displays ores) for that player.
* Possibly make a priviledge to limit what player can see ores.
* Make a GUI for changing colors, what gets shown for what ore, what ore gets displayed. (Per player settings)
* Make a longer range or faster scan priviledge for players (like admins or "ranked" players)
## Common Issues
* It was found that if the server crashes while a player is using xray, xray's nodes are kept. Created a special mode (fix_mode) to attempt to repair nodes which should return back to their original uppon detection. (If fix_mode is left on in production other players xrays can be overriden)
* It is possible to get xray nodes to say simply by logging off, xray attempts to cleanup nodes by players who are attempting to log out. (Please make an issue report with any logs and screenshots/video showing this still occurs)

38
api.lua

@ -1,38 +0,0 @@
oretracker.add_ore = function(orename)
if minetest.registered_nodes[orename] then
table.insert(oretracker.ores, orename)
else
minetest.log("action", "[oretracker] Failed to add '"..orename.."' as it is a unregistered node.")
end
end
oretracker.add_pos = function(pname, pos, title, color)
if not title then
title = minetest.pos_to_string(pos)
end
local player = minetest.get_player_by_name(pname)
local wps = minetest.deserialize(oretracker.store:get_string(pname)) or {}
if not color then
color = 0xffffff
end
table.insert(wps,
player:hud_add({
hud_elem_type = "waypoint",
name = title,
text = "m",
number = color,
world_pos = pos
})
)
oretracker.store:set_string(pname, minetest.serialize(wps))
end
oretracker.clear_pos = function(pname)
local player = minetest.get_player_by_name(pname)
local wps = minetest.deserialize(oretracker.store:get_string(pname)) or {}
for i, v in ipairs(wps) do
player:hud_remove(v)
end
oretracker.store:set_string(pname, minetest.serialize({}))
end

163
init.lua

@ -1,163 +0,0 @@
-- https://rubenwardy.com/minetest_modding_book/en/map/environment.html#finding-nodes
-- A public API
oretracker = {}
oretracker.S = minetest.get_translator("oretracker")
oretracker.modpath = minetest.get_modpath("oretracker")
oretracker.store = minetest.get_mod_storage()
-- 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 8 blocks
oretracker.detect_range = 8 -- Range in blocks
-- The prefered fastest is 1 second, 0 or negative is instantanious updates (Which greatly impacts the server/client)
-- Recommended default is 3 seconds.
oretracker.scan_frequency = 3 -- Frequency in seconds
-- This attempts to detect the gamemode
if not minetest.registered_nodes["default:stone"] then
if not minetest.registered_nodes["mcl_core:stone"] then
oretracker.gamemode = "N/A"
else
oretracker.gamemode = "MCL"
-- Attempt to determine if it's MCL5 or MCL2
if not minetest.registered_nodes["mcl_nether:ancient_debris"] then
oretracker.gamemode = "MCL2"
else
oretracker.gamemode = "MCL5"
end
end
else
oretracker.gamemode = "MTG"
end
minetest.log("action", "[oretracker] Detected game "..oretracker.gamemode..".")
-- Form a container to track what ores we want to follow
oretracker.ores = {}
dofile(oretracker.modpath .. "/api.lua")
-- Use api to assign ores we know/should be caring about
if oretracker.gamemode == "MCL2" or oretracker.gamemode == "MCL5" then
oretracker.add_ore("mcl_core:stone_with_coal")
oretracker.add_ore("mcl_core:stone_with_iron")
oretracker.add_ore("mcl_core:stone_with_gold")
oretracker.add_ore("mcl_core:stone_with_redstone")
oretracker.add_ore("mcl_core:stone_with_redstone_lit")
oretracker.add_ore("mcl_core:stone_with_lapis")
oretracker.add_ore("mcl_core:stone_with_emerald")
oretracker.add_ore("mcl_core:stone_with_diamond")
oretracker.add_ore("mcl_nether:quartz_ore") -- This fails on MCL2 :S
-- oretracker.add_ore("mcl_nether:glowstone") -- Same here, though by default this is disabled as glowstone isn't a "ore"
end
if oretracker.gamemode == "MCL5" then
oretracker.add_ore("mcl_copper:stone_with_copper")
oretracker.add_ore("mcl_nether:ancient_debris")
oretracker.add_ore("mcl_nether_gold:nether_gold_ore")
end
if oretracker.gamemode == "MTG" then
oretracker.add_ore("default:stone_with_coal")
oretracker.add_ore("default:stone_with_iron")
oretracker.add_ore("default:stone_with_gold")
oretracker.add_ore("default:stone_with_copper")
oretracker.add_ore("default:stone_with_tin")
oretracker.add_ore("default:stone_with_mese")
oretracker.add_ore("default:stone_with_diamond")
end
local size = 0
local result = "Ores: "
for i, v in ipairs(oretracker.ores) do
result = result..v.." "
size = size + 1
end
minetest.log("action", "[oretracker] Found "..size.." ores configured.")
minetest.log("action", "[oretracker] "..result)
-- Now to add the tracker notification system
oretracker.check_player = function(player)
local p = player
if not minetest.is_player(p) then
p = minetest.get_player_by_name(p)
end
local pos = p:get_pos()
local pname = p:get_player_name()
-- I need to clean up the player's ore waypoints added by the latter code
oretracker.clear_pos(pname)
local p1 = vector.subtract(pos, {x = oretracker.detect_range, y = oretracker.detect_range, z = oretracker.detect_range})
local p2 = vector.add(pos, {x = oretracker.detect_range, y = oretracker.detect_range, z = oretracker.detect_range})
local area = minetest.find_nodes_in_area(p1, p2, oretracker.ores)
for i=1, #area do
local node = minetest.get_node_or_nil(area[i])
if node == nil then
minetest.log("action", "[oretracker] 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 <= oretracker.detect_range*oretracker.detect_range then
distance = string.format("%.0f", math.sqrt(distance))
local block = "?"
local color = 0xffffff
if string.find(node.name, "coal") then
block = "Coa"
color = 0xc8c8c8
elseif string.find(node.name, "iron") then
block = "Iro"
color = 0xaf644b
elseif string.find(node.name, "gold") then
block = "Gol"
color = 0xc8c84b
elseif string.find(node.name, "mese") then
block = "Mes"
color = 0xffff4b
elseif string.find(node.name, "diamond") then
block = "Dia"
color = 0x4bfafa
elseif string.find(node.name, "quartz") then
block = "Qua"
color = 0xc8c8c8
elseif string.find(node.name, "copper") then
block = "Cop"
color = 0xc86400
elseif string.find(node.name, "tin") then
block = "Tin"
color = 0xc8c8c8
elseif string.find(node.name, "debris") then
block = "Deb"
color = 0xaa644b
elseif string.find(node.name, "lapis") then
block = "Lap"
color = 0x4b4bc8
elseif string.find(node.name, "redstone") then
block = "Red"
color = 0xc81919
elseif string.find(node.name, "glowstone") then
block = "Glo"
color = 0xffff4b
end
if block == "?" then
minetest.log("action", "[oretracker] Found '"..node.name.."' at "..minetest.pos_to_string(area[i], 1).." which is "..distance.." away from '"..pname..".")
block = node.name
end
-- Make a waypoint with the nodes name
oretracker.add_pos(pname, area[i], block, color)
end
end
end
end
local interval = 0
minetest.register_globalstep(function(dtime)
interval = interval - dtime
if interval <= 0 then
for _, player in ipairs(minetest.get_connected_players()) do
oretracker.check_player(player)
end
interval = oretracker.scan_frequency
end
end)

@ -1,4 +0,0 @@
name = oretracker
description = "A useful mod for tracking what ores are around the player."
author = ApolloX
optional_depends = default, mcl_core

0
modpack.txt Normal file

21
orehud/LICENSE Normal file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Beanzilla
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

48
orehud/README.md Normal file

@ -0,0 +1,48 @@
# Ore Tracker > Ore hud
Displays ore position by using the HUD.
## About this mod
This mod provides a graphical HUD interface which displays a series of ores.
Simply use `/orehud` to enable or disable displaying the ores on your HUD.
## The ores
| Ore name | Text Shown | Color code (HEX) |
|----------|------------|------------------|
| Coal | Coa | 0xc8c8c8 |
| Iron | Iro | 0xaf644b |
| Gold | Gol | 0xc8c84b |
| Mese\* | Mes | 0xffff4b |
| Diamond | Dia | 0x4bfafa |
| Quartz\*\*| Qua | 0xc8c8c8 |
| Copper\*\*\*| Cop | 0xc86400 |
| Tin\* | Tin | 0xc8c8c8 |
| Ancient Debris\*\*| Deb | 0xaa644b |
| Lapis | Lap | 0x4b4bc8 |
| Redstone\*\* | Red | 0xc81919 |
| Glowstone\*\* | Glo | 0xffff4b |
\* Only found in MTG.
\*\* Found in MCL5 or MCL2 with the proper mods.
\*\*\* Found in MTG and MCL5 or MCL2 with the proper mods.
## Settings
### Detect Range
The number of blocks away from the player the mod will scan/display for ores.
> Recommended 8 blocks with no more than 16 (Bigger numbers equals much higher loads on server and possibly client)
### Scan Frequency
The time in seconds till the mod updates ores it is indicating and if any new ores enter the scaning area (Dictated by Detect Range)
> Recommended no faster than 1 (for 1 second) (Lower numbers equals faster scans but can/will increase loads on server and possibly client)
> Use 0 or negative number to indicate instantanious (no delay) scans. (Not recommended)

41
orehud/api.lua Normal file

@ -0,0 +1,41 @@
-- Adds an "ore" node to track, only if that node actually is a valid node
orehud.add_ore = function(orename)
if minetest.registered_nodes[orename] then
table.insert(orehud.ores, orename)
else
minetest.log("action", "[oretracker-orehud] Failed to add '"..orename.."' as it is a unregistered node.")
end
end
-- Adds a waypoint to the given player's HUD, given title and color
orehud.add_pos = function(pname, pos, title, color)
if not title then
title = minetest.pos_to_string(pos)
end
local player = minetest.get_player_by_name(pname)
local wps = orehud.store[pname] or {}
if not color then
color = 0xffffff
end
table.insert(wps,
player:hud_add({
hud_elem_type = "waypoint",
name = title,
text = "m",
number = color,
world_pos = pos
})
)
orehud.store[pname] = wps
end
-- Clears all waypoints from the given player's HUD
orehud.clear_pos = function(pname)
local player = minetest.get_player_by_name(pname)
local wps = orehud.store[pname] or {}
for i, v in ipairs(wps) do
player:hud_remove(v)
end
orehud.store[pname] = {}
end

214
orehud/init.lua Normal file

@ -0,0 +1,214 @@
-- https://rubenwardy.com/minetest_modding_book/en/map/environment.html#finding-nodes
-- A public API
orehud = {}
orehud.S = minetest.get_translator("orehud")
orehud.modpath = minetest.get_modpath("orehud")
orehud.store = {}
orehud.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 8 blocks
orehud.detect_range = 8 -- Range in blocks
-- The prefered fastest is 1 second, 0 or negative is instantanious updates (Which greatly impacts the server/client)
-- Recommended default is 3 seconds.
orehud.scan_frequency = 3 -- Frequency in seconds
-- This attempts to detect the gamemode
if not minetest.registered_nodes["default:stone"] then
if not minetest.registered_nodes["mcl_core:stone"] then
orehud.gamemode = "N/A"
else
orehud.gamemode = "MCL"
-- Attempt to determine if it's MCL5 or MCL2
if not minetest.registered_nodes["mcl_nether:ancient_debris"] then
orehud.gamemode = "MCL2"
else
orehud.gamemode = "MCL5"
end
end
else
orehud.gamemode = "MTG"
end
minetest.log("action", "[oretracker-orehud] Detected game "..orehud.gamemode..".")
-- Form a container to track what ores we want to follow
orehud.ores = {}
dofile(orehud.modpath .. "/api.lua")
-- Use api to assign ores we know/should be caring about
if orehud.gamemode == "MCL2" or orehud.gamemode == "MCL5" then
orehud.add_ore("mcl_core:stone_with_coal")
orehud.add_ore("mcl_core:stone_with_iron")
orehud.add_ore("mcl_core:stone_with_gold")
orehud.add_ore("mcl_core:stone_with_redstone")
orehud.add_ore("mcl_core:stone_with_redstone_lit")
orehud.add_ore("mcl_core:stone_with_lapis")
orehud.add_ore("mcl_core:stone_with_emerald")
orehud.add_ore("mcl_core:stone_with_diamond")
orehud.add_ore("mcl_nether:quartz_ore") -- This fails on MCL2 :S (LOL, I didn't realize my test suite was MCL2, I though it was MCL5)
-- orehud.add_ore("mcl_nether:glowstone") -- By default this is disabled as glowstone isn't a "ore", but just uncomment this line to get it too
end
if orehud.gamemode == "MCL5" then
orehud.add_ore("mcl_copper:stone_with_copper")
orehud.add_ore("mcl_nether:ancient_debris")
orehud.add_ore("mcl_nether_gold:nether_gold_ore")
end
if orehud.gamemode == "MTG" then
orehud.add_ore("default:stone_with_coal")
orehud.add_ore("default:stone_with_iron")
orehud.add_ore("default:stone_with_gold")
orehud.add_ore("default:stone_with_copper")
orehud.add_ore("default:stone_with_tin")
orehud.add_ore("default:stone_with_mese")
orehud.add_ore("default:stone_with_diamond")
end
local size = 0
local result = "Ores: "
for i, v in ipairs(orehud.ores) do
result = result..v.." "
size = size + 1
end
minetest.log("action", "[oretracker-orehud] Found "..size.." ores configured.")
minetest.log("action", "[oretracker-orehud] "..result)
-- Itterates an area of nodes for "ores", then adds a waypoint at that nodes position for that "ore".
orehud.check_player = function(player)
local p = player
if not minetest.is_player(p) then
p = minetest.get_player_by_name(p)
end
local pos = p:get_pos()
local pname = p:get_player_name()
local p1 = vector.subtract(pos, {x = orehud.detect_range, y = orehud.detect_range, z = orehud.detect_range})
local p2 = vector.add(pos, {x = orehud.detect_range, y = orehud.detect_range, z = orehud.detect_range})
local area = minetest.find_nodes_in_area(p1, p2, orehud.ores)
for i=1, #area do
local node = minetest.get_node_or_nil(area[i])
if node == nil then
minetest.log("action", "[oretracker-orehud] 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 <= orehud.detect_range*orehud.detect_range then
distance = string.format("%.0f", math.sqrt(distance))
local block = "?"
local color = 0xffffff
if string.find(node.name, "coal") then
block = "Coa"
color = 0xc8c8c8
elseif string.find(node.name, "iron") then
block = "Iro"
color = 0xaf644b
elseif string.find(node.name, "gold") then
block = "Gol"
color = 0xc8c84b
elseif string.find(node.name, "mese") then
block = "Mes"
color = 0xffff4b
elseif string.find(node.name, "diamond") then
block = "Dia"
color = 0x4bfafa
elseif string.find(node.name, "quartz") then
block = "Qua"
color = 0xc8c8c8
elseif string.find(node.name, "copper") then
block = "Cop"
color = 0xc86400
elseif string.find(node.name, "tin") then
block = "Tin"
color = 0xc8c8c8
elseif string.find(node.name, "debris") then
block = "Deb"
color = 0xaa644b
elseif string.find(node.name, "lapis") then
block = "Lap"
color = 0x4b4bc8
elseif string.find(node.name, "redstone") then
block = "Red"
color = 0xc81919
elseif string.find(node.name, "glowstone") then
block = "Glo"
color = 0xffff4b
end
if block == "?" then
minetest.log("action", "[oretracker-orehud] Found '"..node.name.."' at "..minetest.pos_to_string(area[i], 1).." which is "..distance.." away from '"..pname..".")
block = node.name
end
-- Make a waypoint with the nodes name
orehud.add_pos(pname, area[i], block, color)
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
-- I need to clean up the player's ore waypoints added by the latter code
orehud.clear_pos(p:get_player_name())
if orehud.p_stats[p:get_player_name()] or false then
-- Only run if that player wants to run
orehud.check_player(p)
end
end
interval = orehud.scan_frequency
end
end)
minetest.register_on_joinplayer(function(player, laston)
orehud.p_stats[player:get_player_name()] = false
end)
minetest.register_on_leaveplayer(function(player, timeout)
local indx = 0
local found = false
for pname, val in ipairs(orehud.p_stats) do
if pname == player:get_player_name() then
found = true
break
end
indx = indx + 1
end
if found then
table.remove(orehud.p_stats, indx)
end
end)
-- A priv for those to use this power
minetest.register_privilege("orehud", {
description = "Oretracker Orehud Priv",
give_to_singleplayer = true -- Also given to those with server priv
})
minetest.register_chatcommand("orehud", {
privs = {
shout = true,
orehud = true -- Require our own priv
},
func = function(name, param)
if orehud.p_stats[name] then
orehud.p_stats[name] = false
minetest.chat_send_player(name, "Orehud: OFF")
else
orehud.p_stats[name] = true
minetest.chat_send_player(name, "Orehud: ON")
end
end,
})

4
orehud/mod.conf Normal file

@ -0,0 +1,4 @@
name = orehud
description = Displays ore positions via the HUD.
author = ApolloX
optional_depends = default, mcl_core

BIN
orehud/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 405 KiB

After

Width:  |  Height:  |  Size: 379 KiB

21
xray/LICENSE Normal file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Beanzilla
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

38
xray/README.md Normal file

@ -0,0 +1,38 @@
# Ore Tracker > Xray
Hides stone and stone varients from view.
## About this mod
This mod provides graphical counterparts for stone and stone varients to appear invisible.
Simply use `/xray` to enable or disable displaying the stone or stone varients around you.
> If your server crashes while any of your players are using xray it may cause residual invisible nodes... simply enable the fix_mode and then wander around the area they were at. (make sure you disable fix_mode in production, as it can overwrite other player's xray zones)
## How it works
When you issue `/xray` and it becomes active, it checks a cube like area around you, if within this scan area it detects stone for example it then swaps it with it's own stone node (Which simply is a transparent node, but the counterpart was made so I could replace particular stone varients without causing the player to only get stone and nothing else). Reverse the process for reverting the invisible counterpart back to the visible node.
> Yes you can see other player's xray's since there isn't a way to hide nodes just for one client but show them for other clients.
## Settings
### Detect Range
The distance at which nodes will be swapped. (Higher numbers means more blocks swapped but might increase server/client loads)
> Recommended detect_range of 6. (No more than 16)
### Scan Frequency
The rate at which nodes will be checked and swapped. (Lower numbers means more "updates" making it smoother to move around and see the environment change, but might increase server/client loads)
> Recommended scan_frequency of 1. (Use 0 or negative numbers for instantanious "updates", This number is in seconds)
### Light Level
The level that xray nodes emit light. (0 is minimum and 14 is maximum, dictated by minetest)
> Recommended level 4. (This makes xray a dark dull but if you don't mind players never using torches you could make this higher)

136
xray/api.lua Normal file

@ -0,0 +1,136 @@
-- Adds a node to track, only if that node actually is a valid node
xray.add_node = function(nodename)
if minetest.registered_nodes[nodename] then
table.insert(xray.nodes, nodename)
else
minetest.log("action", "[oretracker-xray] Failed to add '"..nodename.."' as it is a unregistered node.")
end
end
-- Swaps with one of the registered nodes that has the invisiblity factor
xray.add_pos = function(pname, pos)
local current = minetest.get_node_or_nil(pos)
if current == nil then
minetest.log("action", "[oretracker-xray] Failed to obtain node at "..minetest.pos_to_string(pos).." for swap.")
end
current = current.name
--minetest.log("action", "[oretracker-xray] Swapping "..current)
local nps = xray.store[pname] or {}
table.insert(nps, pos)
-- Place a switch here to identify which kind of node would be best used here
if current == "default:stone" then
minetest.swap_node(pos, {name="xray:mtg_stone"})
elseif current == "default:desert_stone" then
minetest.swap_node(pos, {name="xray:mtg_dstone"})
elseif current == "default:sandstone" then
minetest.swap_node(pos, {name="xray:mtg_sstone"})
elseif current == "default:desert_sandstone" then
minetest.swap_node(pos, {name="xray:mtg_dsstone"})
elseif current == "default:silver_sandstone" then
minetest.swap_node(pos, {name="xray:mtg_ssstone"})
elseif current == "mcl_core:stone" then
minetest.swap_node(pos, {name="xray:mcl_stone"})
elseif current == "mcl_core:granite" then
minetest.swap_node(pos, {name="xray:mcl_granite"})
elseif current == "mcl_core:andesite" then
minetest.swap_node(pos, {name="xray:mcl_andesite"})
elseif current == "mcl_core:diorite" then
minetest.swap_node(pos, {name="xray:mcl_diorite"})
elseif current == "mcl_core:sandstone" then
minetest.swap_node(pos, {name="xray:mcl_sstone"})
elseif current == "mcl_core:redsandstone" then
minetest.swap_node(pos, {name="xray:mcl_rsstone"})
elseif current == "mcl_blackstone:blackstone" then
minetest.swap_node(pos, {name="xray:mcl_bstone"})
elseif current == "mcl_blackstone:basalt" then
minetest.swap_node(pos, {name="xray:mcl_basalt"})
elseif current == "mcl_nether:netherrack" then
minetest.swap_node(pos, {name="xray:mcl_netherrack"})
end
-- Stone, Diorite, Anasite, Granite, etc.
xray.store[pname] = nps
end
-- Clears all invisible nodes back to their originals (per player)
xray.clear_pos = function(pname)
--local player = minetest.get_player_by_name(pname)
local wps = xray.store[pname] or {}
for i, v in ipairs(wps) do
local node = minetest.get_node_or_nil(v)
if node == nil then
minetest.log("action", "[oretracker-xray] Failed to obtain node at "..minetest.pos_to_string(v).." for revert ("..i..")")
end
node = node.name
--minetest.log("action", "[oretracker-xray] Reverting "..current)
-- Place a switch here to identify what node should be put back here
if node == "xray:mtg_stone" then
minetest.swap_node(v, {name="default:stone"})
elseif node == "xray:mtg_dstone" then
minetest.swap_node(v, {name="default:desert_stone"})
elseif node == "xray:mtg_sstone" then
minetest.swap_node(v, {name="default:sandstone"})
elseif node == "xray:mtg_dsstone" then
minetest.swap_node(v, {name="default:desert_sandstone"})
elseif node == "xray:mtg_ssstone" then
minetest.swap_node(v, {name="default:silver_sandstone"})
elseif node == "xray:mcl_stone" then
minetest.swap_node(v, {name="mcl_core:stone"})
elseif node == "xray:mcl_granite" then
minetest.swap_node(v, {name="mcl_core:granite"})
elseif node == "xray:mcl_andesite" then
minetest.swap_node(v, {name="mcl_core:andesite"})
elseif node == "xray:mcl_diorite" then
minetest.swap_node(v, {name="mcl_core:diorite"})
elseif node == "xray:mcl_sstone" then
minetest.swap_node(v, {name="mcl_core:sandstone"})
elseif node == "xray:mcl_rsstone" then
minetest.swap_node(v, {name="mcl_core:redsandstone"})
elseif node == "xray:mcl_bstone" then
minetest.swap_node(v, {name="mcl_blackstone:blackstone"})
elseif node == "xray:mcl_basalt" then
minetest.swap_node(v, {name="mcl_blackstone:basalt"})
elseif node == "xray:mcl_netherrack" then
minetest.swap_node(v, {name="mcl_nether:netherrack"})
end
end
xray.store[pname] = {}
end
-- Attempt to repair the damage to this node (In the process of development I found my system made a ball of unrepairable goo, invisible blocks)
xray.fix_pos = function (pos)
local node = minetest.get_node_or_nil(pos)
if node == nil then
minetest.log("action", "[oretracker-xray] Failed to obtain node at "..minetest.pos_to_string(pos).." for revert (fix_pos)")
end
node = node.name
if node == "xray:mtg_stone" then
minetest.swap_node(pos, {name="default:stone"})
elseif node == "xray:mtg_dstone" then
minetest.swap_node(pos, {name="default:desert_stone"})
elseif node == "xray:mtg_sstone" then
minetest.swap_node(pos, {name="default:sandstone"})
elseif node == "xray:mtg_dsstone" then
minetest.swap_node(pos, {name="default:desert_sandstone"})
elseif node == "xray:mtg_ssstone" then
minetest.swap_node(pos, {name="default:silver_sandstone"})
elseif node == "xray:mcl_stone" then
minetest.swap_node(pos, {name="mcl_core:stone"})
elseif node == "xray:mcl_granite" then
minetest.swap_node(pos, {name="mcl_core:granite"})
elseif node == "xray:mcl_andesite" then
minetest.swap_node(pos, {name="mcl_core:andesite"})
elseif node == "xray:mcl_diorite" then
minetest.swap_node(pos, {name="mcl_core:diorite"})
elseif node == "xray:mcl_sstone" then
minetest.swap_node(pos, {name="mcl_core:sandstone"})
elseif node == "xray:mcl_rsstone" then
minetest.swap_node(pos, {name="mcl_core:redsandstone"})
elseif node == "xray:mcl_bstone" then
minetest.swap_node(pos, {name="mcl_blackstone:blackstone"})
elseif node == "xray:mcl_basalt" then
minetest.swap_node(pos, {name="mcl_blackstone:basalt"})
elseif node == "xray:mcl_netherrack" then
minetest.swap_node(pos, {name="mcl_nether:netherrack"})
end
end

198
xray/init.lua Normal file

@ -0,0 +1,198 @@
-- 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
xray.gamemode = "MCL"
-- Attempt to determine if it's MCL5 or MCL2
if not minetest.registered_nodes["mcl_nether:ancient_debris"] 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")
-- 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
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
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")
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])
elseif string.find(node.name, "xray") and fix_mode then
-- Attempt to cleanup that node if it's one of ours
-- Warning don't leave fix_mode on all the time, can cause someone elses xray to be blocked because of ordering
xray.fix_pos(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()] = false
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
xray.p_stats[player:get_player_name()] = false
minetest.log("action", "Cleaning up "..player:get_player_name().." as they wish to leave.")
xray.clear_pos(player:get_player_name())
table.remove(xray.p_stats, indx)
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
xray.p_stats[name] = false
minetest.chat_send_player(name, "Xray: OFF")
else
xray.p_stats[name] = true
minetest.chat_send_player(name, "Xray: ON")
end
end,
})

BIN
xray/mcl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

4
xray/mod.conf Normal file

@ -0,0 +1,4 @@
name = xray
description = Hides stone and stone varients from view.
author = ApolloX
optional_depends = default, mcl_core, mcl_sounds

BIN
xray/mtg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

218
xray/register.lua Normal file

@ -0,0 +1,218 @@
-- MTG
if xray.gamemode == "MTG" then
minetest.register_node("xray:mtg_stone", {
description = xray.S("Xray Stone"),
tiles = {"xray_stone.png"},
groups = {cracky = 3, stone = 1},
drop = "default:cobble",
drawtype = "glasslike",
sunlight_propagates = true,
legacy_mineral = true,
light_source = xray.light_level,
sounds = default.node_sound_stone_defaults(),
})
minetest.register_node("xray:mtg_dstone", {
description = xray.S("Xray Stone"),
tiles = {"xray_stone.png"},
groups = {cracky = 3, stone = 1},
drop = "default:desert_cobble",
drawtype = "glasslike",
sunlight_propagates = true,
legacy_mineral = true,
light_source = xray.light_level,
sounds = default.node_sound_stone_defaults(),
})
minetest.register_node("xray:mtg_sstone", {
description = xray.S("Xray Stone"),
tiles = {"xray_stone.png"},
groups = {cracky = 3, stone = 1},
drop = "default:sandstone",
drawtype = "glasslike",
sunlight_propagates = true,
legacy_mineral = true,
light_source = xray.light_level,
sounds = default.node_sound_stone_defaults(),
})
minetest.register_node("xray:mtg_dsstone", {
description = xray.S("Xray Stone"),
tiles = {"xray_stone.png"},
groups = {cracky = 3, stone = 1},
drop = "default:desert_sandstone",
drawtype = "glasslike",
sunlight_propagates = true,
legacy_mineral = true,
light_source = xray.light_level,
sounds = default.node_sound_stone_defaults(),
})
minetest.register_node("xray:mtg_ssstone", {
description = xray.S("Xray Stone"),
tiles = {"xray_stone.png"},
groups = {cracky = 3, stone = 1},
drop = "default:silver_sandstone",
drawtype = "glasslike",
sunlight_propagates = true,
legacy_mineral = true,
light_source = xray.light_level,
sounds = default.node_sound_stone_defaults(),
})
end
-- MCL (2 and 5)
if xray.gamemode == "MCL2" or xray.gamemode == "MCL5" then
minetest.register_node("xray:mcl_stone", {
description = xray.S("Xray Stone"),
_doc_items_longdesc = xray.S("An Invisible block"),
_doc_items_hidden = true,
tiles = {"xray_stone.png"},
is_ground_content = false,
stack_max = 1,
groups = {pickaxey=1, stone=1, building_block=1, material_stone=1},
drawtype = "glasslike",
sunlight_propagates = true,
light_source = xray.light_level,
drop = 'mcl_core:cobble',
sounds = mcl_sounds.node_sound_stone_defaults(),
_mcl_blast_resistance = 6,
_mcl_hardness = 1.5,
_mcl_silk_touch_drop = false,
})
minetest.register_node("xray:mcl_granite", {
description = xray.S("Xray Stone"),
_doc_items_longdesc = xray.S("An Invisible block"),
_doc_items_hidden = true,
tiles = {"xray_stone.png"},
is_ground_content = false,
stack_max = 1,
groups = {pickaxey=1, stone=1, building_block=1, material_stone=1},
drawtype = "glasslike",
sunlight_propagates = true,
light_source = xray.light_level,
drop = 'mcl_core:granite',
sounds = mcl_sounds.node_sound_stone_defaults(),
_mcl_blast_resistance = 6,
_mcl_hardness = 1.5,
_mcl_silk_touch_drop = false,
})
minetest.register_node("xray:mcl_andesite", {
description = xray.S("Xray Stone"),
_doc_items_longdesc = xray.S("An Invisible block"),
_doc_items_hidden = true,
tiles = {"xray_stone.png"},
is_ground_content = false,
stack_max = 1,
groups = {pickaxey=1, stone=1, building_block=1, material_stone=1},
drawtype = "glasslike",
sunlight_propagates = true,
light_source = xray.light_level,
drop = 'mcl_core:andesite',
sounds = mcl_sounds.node_sound_stone_defaults(),
_mcl_blast_resistance = 6,
_mcl_hardness = 1.5,
_mcl_silk_touch_drop = false,
})
minetest.register_node("xray:mcl_diorite", {
description = xray.S("Xray Stone"),
_doc_items_longdesc = xray.S("An Invisible block"),
_doc_items_hidden = true,
tiles = {"xray_stone.png"},
is_ground_content = false,
light_source = xray.light_level,
stack_max = 1,
groups = {pickaxey=1, stone=1, building_block=1, material_stone=1},
drawtype = "glasslike",
sunlight_propagates = true,
drop = 'mcl_core:diorite',
sounds = mcl_sounds.node_sound_stone_defaults(),
_mcl_blast_resistance = 6,
_mcl_hardness = 1.5,
_mcl_silk_touch_drop = false,
})
minetest.register_node("xray:mcl_sstone", {
description = xray.S("Xray Stone"),
_doc_items_hidden = true,
_doc_items_longdesc = xray.S("An Invisible block"),
tiles = {"xray_stone.png"},
is_ground_content = false,
light_source = xray.light_level,
stack_max = 1,
groups = {pickaxey=1, sandstone=1, normal_sandstone=1, building_block=1, material_stone=1},
drawtype = "glasslike",
sunlight_propagates = true,
drop = 'mcl_core:sandstone',
sounds = mcl_sounds.node_sound_stone_defaults(),
_mcl_blast_resistance = 0.8,
_mcl_hardness = 0.8,
_mcl_silk_touch_drop = false,
})
minetest.register_node("xray:mcl_rsstone", {
description = xray.S("Xray Stone"),
_doc_items_hidden = true,
_doc_items_longdesc = xray.S("An Invisible block"),
tiles = {"xray_stone.png"},
is_ground_content = false,
light_source = xray.light_level,
stack_max = 1,
groups = {pickaxey=1, sandstone=1, normal_sandstone=1, building_block=1, material_stone=1},
drawtype = "glasslike",
sunlight_propagates = true,
drop = 'mcl_core:redsandstone',
sounds = mcl_sounds.node_sound_stone_defaults(),
_mcl_blast_resistance = 0.8,
_mcl_hardness = 0.8,
_mcl_silk_touch_drop = false,
})
end
-- MCL (5 only)
if xray.gamemode == "MCL5" then
minetest.register_node("xray:mcl_bstone", {
description = xray.S("Xray Stone"),
_doc_items_hidden = true,
tiles = {"xray_dark.png"},
light_source = xray.light_level,
sounds = mcl_sounds.node_sound_stone_defaults(),
is_ground_content = false,
stack_max = 1,
groups = {cracky = 3, pickaxey=2, material_stone=1},
drawtype = "glasslike",
sunlight_propagates = true,
drop = 'mcl_blackstone:blackstone',
_mcl_blast_resistance = 2,
_mcl_hardness = 2,
_mcl_silk_touch_drop = false,
})
minetest.register_node("xray:mcl_basalt", {
description = xray.S("Xray Stone"),
_doc_items_hidden = true,
tiles = {"xray_dark.png"},
light_source = xray.light_level,
sounds = mcl_sounds.node_sound_stone_defaults(),
drawtype = "glasslike",
sunlight_propagates = true,
is_ground_content = false,
stack_max = 1,
groups = {cracky = 3, pickaxey=2, material_stone=1},
drop = 'mcl_blackstone:basalt',
_mcl_blast_resistance = 2,
_mcl_hardness = 2,
_mcl_silk_touch_drop = false,
})
minetest.register_node("xray:mcl_netherrack", {
description = xray.S("Xray Stone"),
_doc_items_hidden = true,
light_source = xray.light_level,
_doc_items_longdesc = xray.S("An Invisible block"),
stack_max = 1,
tiles = {"xray_nether.png"},
is_ground_content = false,
groups = {pickaxey=1, building_block=1, material_stone=1},
drawtype = "glasslike",
sunlight_propagates = true,
drop = 'mcl_nether:netherrack',
sounds = mcl_sounds.node_sound_stone_defaults(),
_mcl_blast_resistance = 0.4,
_mcl_hardness = 0.4,
_mcl_silk_touch_drop = false,
})
end

BIN
xray/textures/xray_dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B