Compare commits

...

5 Commits

Author SHA1 Message Date
David G 5632b309c3 Validate tunnel_lights setting, and use default:torch if invalid. 2022-08-15 19:17:30 -07:00
David G d85358b381 Pull request from rlars: Allow access to dig_tunnel for other mods. 2022-08-15 19:00:05 -07:00
David G 06081768e9 Perform protection checks on all nodes before digging. 2021-07-03 07:36:03 -07:00
David G 3a6bb95d23 Fix area protection checks. 2021-06-28 09:07:22 -07:00
David G 779b5d15bb Update documentation. 2019-03-22 21:07:19 -07:00
3 changed files with 120 additions and 59 deletions

View File

@ -13,7 +13,8 @@ For Minetest 0.4.x, use the git branch legacy, or the following zip file: [tunne
Quick Use Guide
---------------
- Works in creative or survival mode, but must have "tunneling" privileges to use. However, no crafting recipe so needs to be given to player.
- Requires "tunneling" privileges to use: *(/grant <player> tunneling)*.
- No crafting recipe: *(/give <player> tunnelmaker:tool1)*.
- Left-click mouse to dig just about any node with one click.
- To dig train tunnel:
- Point cursor at ground level.
@ -26,10 +27,11 @@ Features *(Does way more than just dig tunnels!)*
--------
- Create paths, bridges, and tunnels in all sixteen possible advtrains track directions with one click.
- Also digs up or down in the eight possible advtrains slope track directions.
- Digging mode and options can be set using new User Options menu.
- Supports Advanced trains mod with gravel embankment, arched and optionally lined tunnels, and two widths of bridges.
- Supports Bike mod with two widths of cobblestone pathways and bridges, along with unlined tunnels.
- Supports general excavation with unlined and lined tunnels.
- New User Options menu to set digging mode and other options.
- Mode 1: General purpose excavation with unlined and lined tunnels.
- Mode 2: Advanced trains mod with gravel embankment, arched and optionally lined tunnels, and two widths of bridges.
- Mode 3: Bike mod with two widths of cobblestone pathways and bridges, along with unlined tunnels.
- Supports
- Adds reference nodes to help digging and laying advtrains track—now easy to remove when done.
- Adds glass enclosure when in water to create water tunnels.
- Requires "tunneling" privilege, and checks protections before digging.
@ -39,18 +41,18 @@ Features *(Does way more than just dig tunnels!)*
![Bike path up mountain](images/bike_path.png "Bike path up mountain")
Controls *(Revert back to classic controls.)*
----------------------------------------------
- **Left-click:** Super dig one node. One click digs any node (non-repeating) and places it in player's inventory. However, it can't be used to pick up dropped items.
- **Shift-left-click:** Bring up User Options menu. Can also use Aux-right-click for Android.
Controls
--------
- **Left-click:** Super dig one node. One click digs nearly any node (non-repeating) and places it in player's inventory.
- **Shift-left-click:** Bring up User Options menu. (Can also use Aux-right-click for Android.)
- **Right-click:** - Dig tunnel in direction player pointed. Note that this won't place any of the dug nodes in player's inventory.
- **Shift-right-click:** Cycle through vertical digging modes, up, down, and horizontal.
How to enable
-------------
- Install tunnelmaker mod, requires default and stairs. For nicer bike path ramps, I recommend installing the angledstairs mod, which was used for the picture above, but it's not required.
- Grant player "tunneling" privilege (/grant <player> tunneling).
- To give player a tunnelmaker tool use (/give <player> tunnelmaker:tool1).
- Grant player "tunneling" privilege *(/grant <player> tunneling)*.
- To give player a tunnelmaker tool use *(/give <player> tunnelmaker:tool1)*.
How to dig
----------

154
init.lua
View File

@ -6,9 +6,14 @@
-- by David G (kestral246@gmail.com)
-- and by Mikola
-- Version 2.0.4 - 2019-03-14
-- Remove all references to morebl*ks mod.
-- This mod will rename all default stairs nodes, so don't use it if you care about stairs.
-- Version 2.2.0 - 2022-08-15
-- Pull request from rlars: Allow access to dig_tunnel for other mods.
-- Validate tunnel_lights setting, and if invalid use default:torch instead.
-- Version 2.1.0 - 2021-07-02
-- Perform protection checks on all nodes before digging tunnel.
-- Perform protection checks during clear tree cover.
-- Fix protection check while removing reference nodes.
-- Controls for operation
-------------------------
@ -24,12 +29,13 @@
-- distributed without any warranty.
-- You should have received a copy of the CC0 Public Domain Dedication along with this
-- software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
-- software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
-- User Options defaults (for minetest.conf)
-------------------------------------------
-- Initial digging mode for User Options (1, 2, or 3).
-- 1 = General purpose, 2 = Advanced trains, 3 = Bike paths.
local tunnel_mode_default = tonumber(minetest.settings:get("tunnel_digging_mode") or 2)
-- Train tunnels can be lined with a coating.
@ -80,7 +86,7 @@ local embankment = "default:gravel"
-- If this is changed, old reference marks won't be able to be removed by tunnelmaker tool.
local reference_marks = "default:stone_block"
-- Time that reference marks are removed when this command enabled by the user.
-- Time that reference marks are removed when this command enabled by the user.
local remove_refs_enable_time = 120
-- Material for bike paths.
@ -132,15 +138,18 @@ local user_config = {}
-- Adjust light spacing and deal with multi-orientation lights.
minetest.register_on_mods_loaded(function()
if minetest.registered_nodes[lighting] then
if minetest.registered_nodes[lighting].light_source > 13 then
lighting_search_radius = 2
end
if minetest.registered_nodes[lighting].drop then
multi_orient = true
base_lighting = minetest.registered_nodes[lighting].drop
-- minetest.debug("base = "..base_lighting) -- debug
end
if minetest.registered_nodes[lighting] == nil then
minetest.log("warning", "Tunnelmaker: Setting for tunnel_lights ("..lighting..") invalid. Using default:torch instead.")
lighting = "default:torch"
lighting_p2 = 0
end
if minetest.registered_nodes[lighting].light_source > 13 then
lighting_search_radius = 2
end
if minetest.registered_nodes[lighting].drop then
multi_orient = true
base_lighting = minetest.registered_nodes[lighting].drop
-- minetest.debug("base = "..base_lighting) -- debug
end
end)
@ -351,7 +360,7 @@ end
-- Combine all the checks to determine if digging should be allowed.
-- Currently supports area protection, unbreakable, and can_dig(). Others TBD.
local ok_to_tunnel = function(user, pos, name)
if minetest.is_protected(pos, user) then
if minetest.is_protected(pos, user:get_player_name()) then
--minetest.debug("Protection error")
return false
elseif not (minetest.get_item_group(name, "unbreakable") == 0) then -- Unbreakable
@ -374,7 +383,7 @@ local call_on_dignodes = function(pos, node, user)
end
end
-- Lookup table to map direction to appropriate rotation for angled_stair_left nodes.
-- Lookup table to map direction to appropriate rotation for angled_stair_left nodes.
local astairs_lu = {
[-1] ={[2]=1,[6]=0,[10]=3,[14]=2}, -- down
[1] = {[2]=3,[6]=2,[10]=1,[14]=0} -- up
@ -389,18 +398,18 @@ region = {
function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local node = minetest.get_node(pos)
if ok_to_tunnel(user, pos, node.name) then
--if ok_to_tunnel(user, pos, node.name) then
if not (node.name == "air" or is_light(node.name) or string.match(node.name, "dtrack")) then
minetest.set_node(pos, {name = "air"})
call_on_dignodes(pos, node, user)
end
end
--end
end,
[2] = -- Ceiling.
function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local node = minetest.get_node(pos)
if ok_to_tunnel(user, pos, node.name) then
--if ok_to_tunnel(user, pos, node.name) then
local pname = user:get_player_name()
if string.match(node.name, "water") then -- Always line water with glass.
minetest.set_node(pos, {name = glass_walls})
@ -429,21 +438,29 @@ region = {
for i = y, clear_trees_max do
local posi = vector.add(pointed_thing.under, {x=x, y=i, z=z})
local nodei = minetest.get_node(posi)
if nodei.name == "default:snow" or is_flammable(nodei.name) then
minetest.set_node(posi, {name = "air"})
call_on_dignodes(posi, nodei, user)
elseif namei ~= "air" then
-- Add check for protection above tunnel.
if ok_to_tunnel(user, posi, nodei.name) then
if nodei.name == "default:snow" or is_flammable(nodei.name) then
minetest.set_node(posi, {name = "air"})
call_on_dignodes(posi, nodei, user)
elseif nodei.name ~= "air" then
break
end
else
user_config[pname].clear_trees = 0 -- Disable clear_trees on protection error.
minetest.chat_send_player(pname, "Tunnelmaker can't clear trees—area above protected.")
minetest.log("action", pname.." tried to use tunnelmaker to clear trees at protected position "..minetest.pos_to_string(pointed_thing.under))
break
end
end
end
end
--end
end,
[3] = -- Side walls.
function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local node = minetest.get_node(pos)
if ok_to_tunnel(user, pos, node.name) then
--if ok_to_tunnel(user, pos, node.name) then
local pname = user:get_player_name()
if string.match(node.name, "water") then
minetest.set_node(pos, {name = glass_walls}) -- Always line water with glass.
@ -454,24 +471,24 @@ region = {
call_on_dignodes(pos, node, user)
end
end
end
--end
end,
[4] = -- Temporary endcaps.
function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local node = minetest.get_node(pos)
if ok_to_tunnel(user, pos, node.name) then
--if ok_to_tunnel(user, pos, node.name) then
if string.match(node.name, "water") then -- Place temporary endcap if water.
minetest.set_node(pos, {name = glass_walls})
call_on_dignodes(pos, node, user)
end
end
--end
end,
[5] = -- Reference markers.
function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local node = minetest.get_node(pos)
if ok_to_tunnel(user, pos, node.name) then
--if ok_to_tunnel(user, pos, node.name) then
local pname = user:get_player_name()
-- Figure out what replacement material should be.
local rep_mat
@ -491,13 +508,13 @@ region = {
call_on_dignodes(pos, node, user)
end
end
end
--end
end,
[6] = -- Embankment area.
function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local node = minetest.get_node(pos)
if ok_to_tunnel(user, pos, node.name) then
--if ok_to_tunnel(user, pos, node.name) then
local pname = user:get_player_name()
if user_config[pname].add_floors then -- Going to set all.
if user_config[pname].add_embankment then
@ -513,13 +530,13 @@ region = {
call_on_dignodes(pos, node, user)
end
end
end
--end
end,
[7] = -- Wide floors. (starting to refine)
function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local node = minetest.get_node(pos)
if ok_to_tunnel(user, pos, node.name) then
--if ok_to_tunnel(user, pos, node.name) then
local pname = user:get_player_name()
if user_config[pname].add_floors and user_config[pname].add_wide_floors then
local pos0 = vector.add(pos, {x=0, y=-1, z=0})
@ -536,16 +553,16 @@ region = {
call_on_dignodes(pos, node, user)
end
end
end
--end
end,
[8] = -- Underfloor, only used directly for slope up and slope down where embankment or brace is always needed.
function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local node = minetest.get_node(pos)
if ok_to_tunnel(user, pos, node.name) then
--if ok_to_tunnel(user, pos, node.name) then
minetest.set_node(pos, {name = lining_material(user, pos)})
call_on_dignodes(pos, node, user)
end
--end
end,
[10] = -- Bike slope down narrow (air or angled slab).
function(x, y, z, dir, user, pointed_thing)
@ -564,7 +581,7 @@ region = {
function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local node = minetest.get_node(pos)
if ok_to_tunnel(user, pos, node.name) then
--if ok_to_tunnel(user, pos, node.name) then
local pname = user:get_player_name()
if user_config[pname].add_bike_ramps and angledstairs_exists then
if is_desert(user, pos) then
@ -577,13 +594,13 @@ region = {
else
region[1](x, y, z, dir, user, pointed_thing)
end
end
--end
end,
[12] = -- Bike slope up or down narrow (slab or angled stair).
function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local node = minetest.get_node(pos)
if ok_to_tunnel(user, pos, node.name) then
--if ok_to_tunnel(user, pos, node.name) then
local pname = user:get_player_name()
if user_config[pname].add_bike_ramps then
if angledstairs_exists and math.fmod(dir.horiz, 4) == 2 then -- diagonal slope
@ -606,13 +623,13 @@ region = {
else
region[1](x, y, z, dir, user, pointed_thing)
end
end
--end
end,
[13] = -- Bike slope wide up or down (slabs).
function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local node = minetest.get_node(pos)
if ok_to_tunnel(user, pos, node.name) then
--if ok_to_tunnel(user, pos, node.name) then
local pname = user:get_player_name()
if user_config[pname].add_bike_ramps and user_config[pname].add_wide_floors then
if is_desert(user, pos) then
@ -625,7 +642,7 @@ region = {
else
region[1](x, y, z, dir, user, pointed_thing)
end
end
--end
end,
[19] = -- Bike slopes. Don't remove bike slopes placed by previous down slope.
function(x, y, z, dir, user, pointed_thing)
@ -668,7 +685,7 @@ region = {
function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local node = minetest.get_node(pos)
if ok_to_tunnel(user, pos, node.name) then
--if ok_to_tunnel(user, pos, node.name) then
local pname = user:get_player_name()
local pos1 = vector.add(pos, {x=0, y=1, z=0})
local name1 = minetest.get_node(pos1).name
@ -679,7 +696,7 @@ region = {
minetest.set_node(pos, {name = lining_material(user, pos)})
call_on_dignodes(pos, node, user)
end
end
--end
end,
[40] = -- Endcap or null (based on arches).
function(x, y, z, dir, user, pointed_thing)
@ -692,7 +709,7 @@ region = {
function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local name = minetest.get_node(pos).name
if ok_to_tunnel(user, pos, name) then
--if ok_to_tunnel(user, pos, name) then
region[1](x, y, z, dir, user, pointed_thing)
name = minetest.get_node(pos).name -- Should now be air, unless undiggable.
if add_lighting and name == "air" then
@ -712,7 +729,7 @@ region = {
end
end
end
end
--end
end,
[86] = -- Underfloor under embankment.
function(x, y, z, dir, user, pointed_thing)
@ -769,6 +786,36 @@ local run_list = function(dir_list, f, r, dir, user, pointed_thing)
end
end
-- Test that region allows digging.
local region_test = function(x, y, z, dir, user, pointed_thing)
local pos = vector.add(pointed_thing.under, {x=x, y=y, z=z})
local node = minetest.get_node(pos)
return ok_to_tunnel(user, pos, node.name)
end
-- Check all dig locations before doing any digging.
local run_test = function(dir_list, f, r, dir, user, pointed_thing)
local pname = user:get_player_name()
local height = user_config[pname].height
local ok = true
for _,v in ipairs(dir_list) do
local newpos = fliprot(v[1], f, r)
for i = 9, 6, -1 do -- ceiling
ok = region_test(newpos[1], i + height - 7, newpos[2], dir, user, pointed_thing)
if ok == false then return false end -- not ok to dig
end
for y = (height - 2), 2, -1 do -- variable mid region repeats element 5
ok = region_test(newpos[1], y, newpos[2], dir, user, pointed_thing)
if ok == false then return false end -- not ok to dig
end
for i = 4, 1, -1 do -- floor
ok = region_test(newpos[1], i-3, newpos[2], dir, user, pointed_thing)
if ok == false then return false end -- not ok to dig
end
end
return true -- everything ok to dig
end
-- Dig tunnel based on direction given.
-- [9] = h + 2 (up ceiling)
-- [8] = h + 1 (default ceiling)
@ -883,7 +930,15 @@ local dig_tunnel = function(cdir, user, pointed_thing)
local dig_list = dig_patterns[dig_lookup[cdir][1]]
local flip = dig_lookup[cdir][2]
local rotation = dig_lookup[cdir][3]
run_list(dig_list, flip, rotation, dir, user, pointed_thing)
-- Check that all nodes are ok to dig before digging any of them.
-- If you want these translated, contribute the translations.
if run_test(dig_list, flip, rotation, dir, user, pointed_thing) then
run_list(dig_list, flip, rotation, dir, user, pointed_thing)
minetest.log("action", user:get_player_name().." uses tunnelmaker at "..minetest.pos_to_string(pointed_thing.under))
else
minetest.chat_send_player(user:get_player_name(), "Tunnelmaker can't dig—area protected.")
minetest.log("action", user:get_player_name().." tried to use tunnelmaker at protected position "..minetest.pos_to_string(pointed_thing.under))
end
end
-- Display User Options menu.
@ -1095,7 +1150,7 @@ local remove_refs = function(player)
local ppos = player:get_pos()
local refpos = minetest.find_node_near(ppos, 1, reference_marks)
if refpos then
if not minetest.is_protected(refpos, player) then
if not minetest.is_protected(refpos, player:get_player_name()) then
local meta = minetest.get_meta(refpos)
local rep_mat = meta:get("replace_with")
if rep_mat and string.len(rep_mat) > 0 then
@ -1113,3 +1168,6 @@ minetest.register_globalstep(function(dtime)
end
end
end)
-- Allow other mods to use the dig_tunnel function.
tunnelmaker.dig_tunnel = dig_tunnel

View File

@ -2,6 +2,7 @@
# minetest.conf
# Default for digging mode in User config menu.
# 1 = General purpose, 2 = Advanced trains, 3 = Bike paths.
# (default = 2)
tunnel_digging_mode (Tunnel digging mode) int 2 1 3