aboutsummaryrefslogtreecommitdiff
path: root/advtrains/protection.lua
diff options
context:
space:
mode:
Diffstat (limited to 'advtrains/protection.lua')
-rw-r--r--advtrains/protection.lua110
1 files changed, 77 insertions, 33 deletions
diff --git a/advtrains/protection.lua b/advtrains/protection.lua
index 73b725f..1ea4957 100644
--- a/advtrains/protection.lua
+++ b/advtrains/protection.lua
@@ -61,50 +61,96 @@ Wagon coupling:
local boo = minetest.settings:get_bool("advtrains_allow_build_to_owner")
-
+-- temporarily prevent scanning for neighboring rail nodes recursively
local nocheck
+
+local old_is_protected = minetest.is_protected
+
-- Check if the node we are about to check is in the range of a track that is protected from a player
---WARN: true means here that the action is forbidden!
-function advtrains.check_track_protection(pos, pname)
+minetest.is_protected = function(pos, pname)
+
+ -- old_is_protected:
+ -- If an earlier callback decided that pos is protected, we wouldn't have been called
+ -- if a later callback decides it, get that here.
+ -- this effectively puts this function into a final-choice position
+ local oprot = old_is_protected(pos, pname)
+ if oprot then
+ return true
+ end
+
if nocheck or pname=="" then
return false
end
- nocheck=true --prevent recursive calls, never check this again if we're already in
+
+ -- Special exception: to allow seamless rail connections between 2 separately protected
+ -- networks, rails itself are not affected by the radius setting. So, if the node here is
+ -- a rail, we skip the check and just use check_track_protection on same pos.
+ local node = minetest.get_node(pos)
+ if minetest.get_item_group(node.name, "advtrains_track") > 0 then
+ -- by here, we know that no other protection callback has this protected, we can safely pass "false".
+ -- hope this doesn't lead to bugs!
+ return not advtrains.check_track_protection(pos, pname, nil, false)
+ end
+
local r, vr = 1, 3
local nodes = minetest.find_nodes_in_area(
{x = pos.x - r, y = pos.y - vr, z = pos.z - r},
- {x = pos.x + r, y = pos.y, z = pos.z + r},
+ {x = pos.x + r, y = pos.y + 1, z = pos.z + r},
{"group:advtrains_track"})
for _,npos in ipairs(nodes) do
- if not minetest.check_player_privs(pname, {track_builder = true}) then
- if boo and not minetest.is_protected(npos, pname) and minetest.is_protected(npos, "*dummy*") then
- nocheck = false
- return false
- else
- minetest.chat_send_player(pname, "You are not allowed to dig or place nodes near tracks (missing track_builder privilege)")
- minetest.log("action", pname.." tried to dig/place nodes near the track at "..minetest.pos_to_string(npos).." but does not have track_builder")
- nocheck = false
- return true
- end
- end
- if not minetest.check_player_privs(pname, {protection_bypass = true}) then
- if minetest.is_protected(npos, pname) then
- nocheck = false
- minetest.record_protection_violation(pos, pname)
- return true
- end
+ if not advtrains.check_track_protection(npos, pname, pos) then
+ return true
end
end
nocheck=false
return false
end
-local old_is_protected = minetest.is_protected
-minetest.is_protected = function(pos, pname)
- if advtrains.check_track_protection(pos, pname) then
+-- Check whether the player is permitted to modify this track
+-- Shall be called only for nodes that are or are about to become tracks.
+-- The range check from is_track_near_protected is disabled here.
+-- this splits in 1. track_builder privilege and 2. is_protected
+-- also respects the allow_build_to_owner property.
+--WARN: true means here that the action is allowed!
+function advtrains.check_track_protection(pos, pname, near, prot_p)
+ -- Parameter "near" is an optional position, the original node that the player
+ -- was about to affect, while "pos" represents the checked rail node
+ -- if "near" is not set, pos is the same node.
+ local nears = near and "near " or ""
+ local apos = near or pos
+
+ -- note that having protection_bypass implicitly implies having track_builder, because else it would be possible to dig rails
+ -- (only checked by is_protected, which is not respected) but not place them.
+ -- We won't impose restrictions on protection_bypass owners.
+ if minetest.check_player_privs(pname, {protection_bypass = true}) then
return true
end
- return old_is_protected(pos, pname)
+
+ nocheck = true
+ local priv = minetest.check_player_privs(pname, {track_builder = true})
+
+ -- note: is_protected above already checks the is_protected value against the current player, so checking it again is useless.
+ local prot = prot_p
+ if prot==nil then
+ prot = advtrains.is_protected(pos, pname)
+ end
+ local dprot = minetest.is_protected(pos, "*dummy*")
+ nocheck = false
+
+ --atdebug("CTP: ",pos,pname,near,prot_p,"priv=",priv,"prot=",prot,"dprot=",dprot)
+
+ if not priv and (not boo or prot or not dprot) then
+ minetest.chat_send_player(pname, "You are not allowed to build "..nears.."tracks without track_builder privilege")
+ minetest.log("action", pname.." tried to modify terrain "..nears.."track at "..minetest.pos_to_string(apos).." but is not permitted to (no privilege)")
+ return false
+ end
+ if prot then
+ minetest.chat_send_player(pname, "You are not allowed to build "..nears.."tracks at protected position!")
+ minetest.record_protection_violation(pos, pname)
+ minetest.log("action", pname.." tried to modify "..nears.."track at "..minetest.pos_to_string(apos).." but position is protected!")
+ return false
+ end
+ return true
end
--WARN: true means here that the action is allowed!
@@ -126,7 +172,7 @@ end
function advtrains.check_turnout_signal_protection(pos, pname)
nocheck=true
if not minetest.check_player_privs(pname, {railway_operator = true}) then
- if boo and not minetest.is_protected(pos, pname) and minetest.is_protected(pos, "*dummy*") then
+ if boo and not advtrains.is_protected(pos, pname) and minetest.is_protected(pos, "*dummy*") then
nocheck=false
return true
else
@@ -136,12 +182,10 @@ function advtrains.check_turnout_signal_protection(pos, pname)
return false
end
end
- if not minetest.check_player_privs(pname, {protection_bypass = true}) then
- if minetest.is_protected(pos, pname) then
- minetest.record_protection_violation(pos, pname)
- nocheck=false
- return false
- end
+ if advtrains.is_protected(pos, pname) then
+ minetest.record_protection_violation(pos, pname)
+ nocheck=false
+ return false
end
nocheck=false
return true