Fix protection regarding tracks (track_builder and railway_operator) and documentation on privileges

h137
orwell96 2018-11-12 22:24:56 +01:00
parent 07fa21f992
commit 5874a6d3f4
4 changed files with 94 additions and 43 deletions

View File

@ -11,7 +11,7 @@ end
--advtrains --advtrains
DUMP_DEBUG_SAVE = true DUMP_DEBUG_SAVE = false
--Constant for maximum connection value/division of the circle --Constant for maximum connection value/division of the circle
AT_CMAX = 16 AT_CMAX = 16

View File

@ -61,50 +61,96 @@ Wagon coupling:
local boo = minetest.settings:get_bool("advtrains_allow_build_to_owner") local boo = minetest.settings:get_bool("advtrains_allow_build_to_owner")
-- temporarily prevent scanning for neighboring rail nodes recursively
local nocheck 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 -- 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! minetest.is_protected = function(pos, pname)
function advtrains.check_track_protection(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 if nocheck or pname=="" then
return false return false
end 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 r, vr = 1, 3
local nodes = minetest.find_nodes_in_area( 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 - 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"}) {"group:advtrains_track"})
for _,npos in ipairs(nodes) do for _,npos in ipairs(nodes) do
if not minetest.check_player_privs(pname, {track_builder = true}) then if not advtrains.check_track_protection(npos, pname, pos) then
if boo and not minetest.is_protected(npos, pname) and minetest.is_protected(npos, "*dummy*") then return true
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
end end
end end
nocheck=false nocheck=false
return false return false
end end
local old_is_protected = minetest.is_protected -- Check whether the player is permitted to modify this track
minetest.is_protected = function(pos, pname) -- Shall be called only for nodes that are or are about to become tracks.
if advtrains.check_track_protection(pos, pname) then -- 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 return true
end 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 end
--WARN: true means here that the action is allowed! --WARN: true means here that the action is allowed!
@ -126,7 +172,7 @@ end
function advtrains.check_turnout_signal_protection(pos, pname) function advtrains.check_turnout_signal_protection(pos, pname)
nocheck=true nocheck=true
if not minetest.check_player_privs(pname, {railway_operator = true}) then 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 nocheck=false
return true return true
else else
@ -136,12 +182,10 @@ function advtrains.check_turnout_signal_protection(pos, pname)
return false return false
end end
end end
if not minetest.check_player_privs(pname, {protection_bypass = true}) then if advtrains.is_protected(pos, pname) then
if minetest.is_protected(pos, pname) then minetest.record_protection_violation(pos, pname)
minetest.record_protection_violation(pos, pname) nocheck=false
nocheck=false return false
return false
end
end end
nocheck=false nocheck=false
return true return true

View File

@ -277,8 +277,7 @@ function tp.register_track_placer(nnprefix, imgprefix, dispname)
if pointed_thing.type=="node" then if pointed_thing.type=="node" then
local pos=pointed_thing.above local pos=pointed_thing.above
local upos=vector.subtract(pointed_thing.above, {x=0, y=1, z=0}) local upos=vector.subtract(pointed_thing.above, {x=0, y=1, z=0})
if advtrains.is_protected(pos,name) then if not advtrains.check_track_protection(pos, name) then
minetest.record_protection_violation(pos, name)
return itemstack, false return itemstack, false
end end
if minetest.registered_nodes[minetest.get_node(pos).name] and minetest.registered_nodes[minetest.get_node(pos).name].buildable_to if minetest.registered_nodes[minetest.get_node(pos).name] and minetest.registered_nodes[minetest.get_node(pos).name].buildable_to
@ -286,7 +285,7 @@ function tp.register_track_placer(nnprefix, imgprefix, dispname)
-- minetest.chat_send_all(nnprefix) -- minetest.chat_send_all(nnprefix)
local yaw = placer:get_look_horizontal() local yaw = placer:get_look_horizontal()
tp.placetrack(pos, nnprefix, placer, itemstack, pointed_thing, yaw) tp.placetrack(pos, nnprefix, placer, itemstack, pointed_thing, yaw)
if not minetest.settings:get_bool("creative_mode") then if not advtrains.is_creative(name) then
itemstack:take_item() itemstack:take_item()
end end
end end
@ -314,8 +313,7 @@ minetest.register_craftitem("advtrains:trackworker",{
local has_aux1_down = placer:get_player_control().aux1 local has_aux1_down = placer:get_player_control().aux1
if pointed_thing.type=="node" then if pointed_thing.type=="node" then
local pos=pointed_thing.under local pos=pointed_thing.under
if advtrains.is_protected(pos, name) then if not advtrains.check_track_protection(pos, name) then
minetest.record_protection_violation(pos, name)
return return
end end
local node=minetest.get_node(pos) local node=minetest.get_node(pos)
@ -369,8 +367,7 @@ minetest.register_craftitem("advtrains:trackworker",{
if pointed_thing.type=="node" then if pointed_thing.type=="node" then
local pos=pointed_thing.under local pos=pointed_thing.under
local node=minetest.get_node(pos) local node=minetest.get_node(pos)
if advtrains.is_protected(pos, name) then if not advtrains.check_track_protection(pos, name) then
minetest.record_protection_violation(pos, name)
return return
end end

View File

@ -2,6 +2,7 @@
### Advtrains Privilege Guide ### Advtrains Privilege Guide
All privileges are automatically granted to singleplayer, but for All privileges are automatically granted to singleplayer, but for
multiplayer servers this might be interesting. multiplayer servers this might be interesting.
In this document, "protected from" means the player does NOT have access to the area, while "protected by" means the player has (semi-)exclusive access to the area.
There are 3 groups of privileges introduced by advtrains: There are 3 groups of privileges introduced by advtrains:
## Trains ## Trains
@ -17,10 +18,10 @@ destroy any train.
The area 1 node around and 4 nodes up from each track node is protected. The area 1 node around and 4 nodes up from each track node is protected.
Players that don't have the 'track_builder' privilege can not build or Players that don't have the 'track_builder' privilege can not build or
dig (or modify) anything inside this area. dig (or modify) anything inside this area.
If any player tries to modify anything that is in the area of a track If a player has this privilege and tries to modify anything that is in the area of a track node which is protected from him, he also can not do this.
node and this track node is protected from him, he also can not do this.
(that said, while checking protection, the area around a track is (that said, while checking protection, the area around a track is
treated as the track node itself) treated as the track node itself)
Note that having 'protection_bypass' automatically implies 'track_builder' due to internal engine mechanics. (see comments in source code)
## Turnouts and Signals* ## Turnouts and Signals*
Players without the 'railway_operator' privilege can not operate signals Players without the 'railway_operator' privilege can not operate signals
@ -31,3 +32,12 @@ an exception applies to players missing the required privileges when
they are in a protected area that they have access to. Whether the they are in a protected area that they have access to. Whether the
area is protected from others is checked by checking for protection area is protected from others is checked by checking for protection
against a dummy player called '*dummy*' against a dummy player called '*dummy*'
## Privileges of extensions:
* atlatc:
This privilege allows to create and modify LUA code in LuaATC rails added by the advtrains_luaautomation mod, as well as to create and manage code environments.
* interlocking:
This privilege allows to build, set up, configure and control all sorts of interlocking equipment.
Players without this privilege are still allowed to set and cancel routes (under the condition that they have train_operator).