Rework the privilege system completely
See privilege_guide.txt for information
This commit is contained in:
parent
481f6218a8
commit
8b576357ef
@ -151,6 +151,7 @@ dofile(advtrains.modpath.."/trackplacer.lua")
|
||||
dofile(advtrains.modpath.."/tracks.lua")
|
||||
dofile(advtrains.modpath.."/atc.lua")
|
||||
dofile(advtrains.modpath.."/wagons.lua")
|
||||
dofile(advtrains.modpath.."/protection.lua")
|
||||
|
||||
dofile(advtrains.modpath.."/trackdb_legacy.lua")
|
||||
dofile(advtrains.modpath.."/nodedb.lua")
|
||||
@ -272,7 +273,7 @@ advtrains.avt_save = function(remove_players_from_wagons)
|
||||
"last_pos", "last_pos_prev", "movedir", "velocity", "tarvelocity",
|
||||
"trainparts", "savedpos_off_track_index_offset", "recently_collided_with_env",
|
||||
"atc_brake_target", "atc_wait_finish", "atc_command", "atc_delay", "door_open",
|
||||
"text_outside", "text_inside", "couple_lck_front", "couple_lck_back"
|
||||
"text_outside", "text_inside", "couple_lck_front", "couple_lck_back", "line"
|
||||
})
|
||||
--then invalidate
|
||||
if train.index then
|
||||
|
148
advtrains/protection.lua
Normal file
148
advtrains/protection.lua
Normal file
@ -0,0 +1,148 @@
|
||||
-- advtrains
|
||||
-- protection.lua: privileges and rail protection, and some helpers
|
||||
|
||||
|
||||
-- Privileges to control TRAIN DRIVING/COUPLING
|
||||
minetest.register_privilege("train_operator", {
|
||||
description = "Without this privilege, a player can't do anything about trains, neither place or remove them nor drive or couple them (but he can build tracks if he has track_builder)",
|
||||
give_to_singleplayer= true,
|
||||
});
|
||||
|
||||
minetest.register_privilege("train_admin", {
|
||||
description = "Player may drive, place or remove any trains from/to anywhere, regardless of owner, whitelist or protection",
|
||||
give_to_singleplayer= true,
|
||||
});
|
||||
|
||||
-- Privileges to control TRACK BUILDING
|
||||
minetest.register_privilege("track_builder", {
|
||||
description = "Player can place and/or dig rails not protected from him. If he also has protection_bypass, he can place/dig any rails",
|
||||
give_to_singleplayer= true,
|
||||
});
|
||||
|
||||
-- Privileges to control OPERATING TURNOUTS/SIGNALS
|
||||
minetest.register_privilege("railway_operator", {
|
||||
description = "Player can operate turnouts and signals not protected from him. If he also has protection_bypass, he can operate any turnouts/signals",
|
||||
give_to_singleplayer= true,
|
||||
});
|
||||
|
||||
-- there is a configuration option "allow_build_only_owner". If this is active, a player having track_builder can only build rails and operate signals/turnouts in an area explicitly belonging to him
|
||||
-- (checked using a dummy player called "*dummy*" (which is not an allowed player name))
|
||||
|
||||
--[[
|
||||
Protection/privilege concept:
|
||||
Tracks:
|
||||
Protected 1 node all around a rail and 4 nodes upward (maybe make this dynamically determined by the rail...)
|
||||
if track_builder privilege:
|
||||
if not protected from* player:
|
||||
if allow_build_only_owner:
|
||||
if unprotected:
|
||||
deny
|
||||
else:
|
||||
allow
|
||||
deny
|
||||
Wagons in general:
|
||||
Players can only place/destroy wagons if they have train_operator
|
||||
Wagon driving controls:
|
||||
The former seat_access tables are unnecessary, instead there is a whitelist for the driving stands
|
||||
on player trying to access a driver stand:
|
||||
if is owner or is on whitelist:
|
||||
allow
|
||||
else:
|
||||
deny
|
||||
Wagon coupling:
|
||||
Derived from the privileges for driving stands. The whitelist is shared (and also settable on non-driverstand wagons)
|
||||
for each of the two bordering wagons:
|
||||
if is owner or is on whitelist:
|
||||
allow
|
||||
|
||||
*"protected from" means the player is not allowed to do things, while "protected by" means that the player is (one of) the owner(s) of this area
|
||||
|
||||
]]--
|
||||
|
||||
local boo = minetest.settings:get_bool("advtrains_allow_build_to_owner")
|
||||
|
||||
|
||||
local nocheck
|
||||
-- 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)
|
||||
if nocheck or pname=="" then
|
||||
return false
|
||||
end
|
||||
nocheck=true --prevent recursive calls, never check this again if we're already in
|
||||
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},
|
||||
{"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
|
||||
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
|
||||
return true
|
||||
end
|
||||
return old_is_protected(pos, pname)
|
||||
end
|
||||
|
||||
--WARN: true means here that the action is allowed!
|
||||
function advtrains.check_driving_couple_protection(pname, owner, whitelist)
|
||||
if minetest.check_player_privs(pname, {train_admin = true}) then
|
||||
return true
|
||||
end
|
||||
if not minetest.check_player_privs(pname, {train_operator = true}) then
|
||||
return false
|
||||
end
|
||||
if not owner or owner == pname then
|
||||
return true
|
||||
end
|
||||
if whitelist and string.find(" "..whitelist.." ", " "..pname.." ", nil, true) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
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
|
||||
nocheck=false
|
||||
return true
|
||||
else
|
||||
minetest.chat_send_player(pname, "You are not allowed to operate turnouts and signals (missing railway_operator privilege)")
|
||||
minetest.log("action", pname.." tried to operate turnout/signal at "..minetest.pos_to_string(pos).." but does not have railway_operator")
|
||||
nocheck=false
|
||||
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
|
||||
end
|
||||
nocheck=false
|
||||
return true
|
||||
end
|
@ -10,3 +10,8 @@ advtrains_enable_debugging (Enable debugging) bool false
|
||||
# Logs are saved in the world directory as advtrains.log
|
||||
# This setting is useful for multiplayer servers
|
||||
advtrains_enable_logging (Enable logging) bool false
|
||||
# If this is active, any player can do the following things inside (and only inside) an area that is explicitly protected by him
|
||||
# (checked using a dummy player called "*dummy*" (which is not an allowed player name)):
|
||||
# - build tracks and near tracks without the track_builder privilege
|
||||
# - operate turnouts and signals without the railway_operator privilege
|
||||
advtrains_allow_build_to_owner (Allow building/operating to privilegeless area owner) bool false
|
||||
|
@ -41,7 +41,7 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red",
|
||||
end
|
||||
}},
|
||||
on_rightclick=function(pos, node, player)
|
||||
if minetest.check_player_privs(player:get_player_name(), {train_operator=true}) then
|
||||
if advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
|
||||
advtrains.ndb.swap_node(pos, {name = "advtrains:retrosignal_"..f.as..rotation, param2 = node.param2}, true)
|
||||
end
|
||||
end,
|
||||
@ -84,7 +84,7 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red",
|
||||
end,
|
||||
},
|
||||
on_rightclick=function(pos, node, player)
|
||||
if minetest.check_player_privs(player:get_player_name(), {train_operator=true}) then
|
||||
if advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
|
||||
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_"..f.as..rotation, param2 = node.param2}, true)
|
||||
end
|
||||
end,
|
||||
@ -133,7 +133,7 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red",
|
||||
end,
|
||||
},
|
||||
on_rightclick=function(pos, node, player)
|
||||
if minetest.check_player_privs(player:get_player_name(), {train_operator=true}) then
|
||||
if advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
|
||||
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_wall_"..loc.."_"..f.as, param2 = node.param2}, true)
|
||||
end
|
||||
end,
|
||||
@ -179,7 +179,7 @@ minetest.register_node("advtrains:across_off", {
|
||||
end,
|
||||
},
|
||||
on_rightclick=function(pos, node, player)
|
||||
if minetest.check_player_privs(player:get_player_name(), {train_operator=true}) then
|
||||
if advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
|
||||
advtrains.ndb.swap_node(pos, {name = "advtrains:across_on", param2 = node.param2}, true)
|
||||
end
|
||||
end,
|
||||
@ -220,7 +220,7 @@ minetest.register_node("advtrains:across_on", {
|
||||
end,
|
||||
},
|
||||
on_rightclick=function(pos, node, player)
|
||||
if minetest.check_player_privs(player:get_player_name(), {train_operator=true}) then
|
||||
if advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
|
||||
advtrains.ndb.swap_node(pos, {name = "advtrains:across_off", param2 = node.param2}, true)
|
||||
end
|
||||
end,
|
||||
|
@ -269,6 +269,7 @@ function advtrains.register_tracks(tracktype, def, preset)
|
||||
|
||||
groups = {
|
||||
attached_node=1,
|
||||
advtrains_track=1,
|
||||
["advtrains_track_"..tracktype]=1,
|
||||
save_in_at_nodedb=1,
|
||||
dig_immediate=2,
|
||||
@ -309,7 +310,7 @@ function advtrains.register_tracks(tracktype, def, preset)
|
||||
end
|
||||
end
|
||||
ndef.on_rightclick = function(pos, node, player)
|
||||
if minetest.check_player_privs(player:get_player_name(), {train_operator=true}) then
|
||||
if advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
|
||||
switchfunc(pos, node)
|
||||
advtrains.log("Switch", player:get_player_name(), pos)
|
||||
end
|
||||
|
@ -1,19 +1,5 @@
|
||||
--atan2 counts angles clockwise, minetest does counterclockwise
|
||||
|
||||
minetest.register_privilege("train_place", {
|
||||
description = "Player can place trains on tracks not owned by player",
|
||||
give_to_singleplayer= false,
|
||||
});
|
||||
minetest.register_privilege("train_remove", {
|
||||
description = "Player can remove trains not owned by player",
|
||||
give_to_singleplayer= false,
|
||||
});
|
||||
minetest.register_privilege("train_operator", {
|
||||
description = "Player may operate trains and switch signals. Given by default. Revoke to prevent players from griefing automated subway systems.",
|
||||
give_to_singleplayer= true,
|
||||
default= true,
|
||||
});
|
||||
|
||||
local wagon={
|
||||
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
||||
--physical = true,
|
||||
@ -161,7 +147,7 @@ function wagon:on_punch(puncher, time_from_last_punch, tool_capabilities, direct
|
||||
if not puncher or not puncher:is_player() then
|
||||
return
|
||||
end
|
||||
if self.owner and puncher:get_player_name()~=self.owner and (not minetest.check_player_privs(puncher, {train_remove = true })) then
|
||||
if self.owner and puncher:get_player_name()~=self.owner and (not minetest.check_player_privs(puncher, {train_admin = true })) then
|
||||
minetest.chat_send_player(puncher:get_player_name(), attrans("This wagon is owned by @1, you can't destroy it.", self.owner));
|
||||
return
|
||||
end
|
||||
@ -250,8 +236,9 @@ function wagon:on_step(dtime)
|
||||
|
||||
--driver control
|
||||
for seatno, seat in ipairs(self.seats) do
|
||||
local driver=self.seatp[seatno] and minetest.get_player_by_name(self.seatp[seatno])
|
||||
local has_driverstand = self.seatp[seatno] and (minetest.check_player_privs(self.seatp[seatno], {train_operator=true}) or self.owner==self.seatp[seatno])
|
||||
local pname=self.seatp[seatno]
|
||||
local driver=pname and minetest.get_player_by_name(pname)
|
||||
local has_driverstand = pname and advtrains.check_driving_couple_protection(pname, self.owner, self.whitelist)
|
||||
if self.seat_groups then
|
||||
has_driverstand = has_driverstand and (seat.driving_ctrl_access or self.seat_groups[seat.group].driving_ctrl_access)
|
||||
else
|
||||
@ -577,13 +564,6 @@ function wagon:on_rightclick(clicker)
|
||||
if not clicker or not clicker:is_player() then
|
||||
return
|
||||
end
|
||||
if clicker:get_player_control().aux1 then
|
||||
--advtrains.dumppath(self:train().path)
|
||||
--minetest.chat_send_all("at index "..(self:train().index or "nil"))
|
||||
--advtrains.invert_train(self.train_id)
|
||||
atprint(dump(self))
|
||||
return
|
||||
end
|
||||
local pname=clicker:get_player_name()
|
||||
local no=self:get_seatno(pname)
|
||||
if no then
|
||||
@ -598,7 +578,7 @@ function wagon:on_rightclick(clicker)
|
||||
if self.has_inventory and self.get_inventory_formspec then
|
||||
poss[#poss+1]={name=attrans("Show Inventory"), key="inv"}
|
||||
end
|
||||
if self.seat_groups[sgr].driving_ctrl_access and minetest.check_player_privs(pname, "train_operator") then
|
||||
if self.seat_groups[sgr].driving_ctrl_access and advtrains.check_driving_couple_protection(pname, self.owner, self.whitelist) then
|
||||
poss[#poss+1]={name=attrans("Bord Computer"), key="bordcom"}
|
||||
end
|
||||
if self.owner==pname then
|
||||
@ -779,28 +759,15 @@ function wagon:show_get_on_form(pname)
|
||||
minetest.show_formspec(pname, "advtrains_geton_"..self.unique_id, form)
|
||||
end
|
||||
function wagon:show_wagon_properties(pname)
|
||||
local numsgr=0
|
||||
if self.seat_groups then
|
||||
numsgr=#self.seat_groups
|
||||
end
|
||||
if not self.seat_access then
|
||||
self.seat_access={}
|
||||
end
|
||||
--[[
|
||||
fields: seat access: empty: everyone
|
||||
checkbox: lock couples
|
||||
fields:
|
||||
field: driving/couple whitelist
|
||||
button: save
|
||||
]]
|
||||
local form="size[5,"..(numsgr*1.5+4).."]"
|
||||
local at=0
|
||||
if self.seat_groups then
|
||||
for sgr,sgrdef in pairs(self.seat_groups) do
|
||||
local text = attrans("Access to @1",sgrdef.name)
|
||||
form=form.."field[0.5,"..(0.5+at*1.5)..";4,1;sgr_"..sgr..";"..text..";"..(self.seat_access[sgr] or "").."]"
|
||||
at=at+1
|
||||
end
|
||||
end
|
||||
form=form.."button_exit[0.5,"..(at*1.5)..";4,1;save;"..attrans("Save wagon properties").."]"
|
||||
local form="size[5,5]"
|
||||
form = form .. "field[0.5,1;4,1;whitelist;Allow these players to drive your wagon:;"..(self.whitelist or "").."]"
|
||||
--seat groups access lists were here
|
||||
form=form.."button_exit[0.5,3;4,1;save;"..attrans("Save wagon properties").."]"
|
||||
minetest.show_formspec(pname, "advtrains_prop_"..self.unique_id, form)
|
||||
end
|
||||
|
||||
@ -819,9 +786,9 @@ local function checkcouple(eid)
|
||||
end
|
||||
return le
|
||||
end
|
||||
local function checklock(pname, own1, own2)
|
||||
return minetest.check_player_privs(pname, "train_remove") or
|
||||
((not own1 or own1==pname) or (not own2 or own2==pname))
|
||||
local function checklock(pname, own1, own2, wl1, wl2)
|
||||
return advtrains.check_driving_couple_protection(pname, own1, wl1)
|
||||
or advtrains.check_driving_couple_protection(pname, own2, wl2)
|
||||
end
|
||||
function wagon:show_bordcom(pname)
|
||||
if not self:train() then return end
|
||||
@ -834,7 +801,7 @@ function wagon:show_bordcom(pname)
|
||||
if train.velocity==0 then
|
||||
form=form.."label[0.5,4.5;Train overview /coupling control:]"
|
||||
linhei=5
|
||||
local pre_own, owns_any = nil, minetest.check_player_privs(pname, "train_remove")
|
||||
local pre_own, pre_wl, owns_any = nil, nil, minetest.check_player_privs(pname, "train_admin")
|
||||
for i, tpid in ipairs(train.trainparts) do
|
||||
local ent = advtrains.wagon_save[tpid]
|
||||
if ent then
|
||||
@ -843,7 +810,7 @@ function wagon:show_bordcom(pname)
|
||||
if i~=1 then
|
||||
if not ent.dcpl_lock then
|
||||
form = form .. "image_button["..(i-0.5)..","..(linhei+1)..";1,1;advtrains_discouple.png;dcpl_"..i..";]"
|
||||
if checklock(pname, ent.owner, pre_own) then
|
||||
if checklock(pname, ent.owner, pre_own, ent.whitelist, pre_wl) then
|
||||
form = form .. "image_button["..(i-0.5)..","..(linhei+2)..";1,1;advtrains_cpl_unlock.png;dcpl_lck_"..i..";]"
|
||||
end
|
||||
else
|
||||
@ -854,6 +821,7 @@ function wagon:show_bordcom(pname)
|
||||
form = form .. "box["..(i-0.1)..","..(linhei-0.1)..";1,1;green]"
|
||||
end
|
||||
pre_own = ent.owner
|
||||
pre_wl = ent.whitelist
|
||||
owns_any = owns_any or (not ent.owner or ent.owner==pname)
|
||||
end
|
||||
end
|
||||
@ -894,7 +862,7 @@ function wagon:show_bordcom(pname)
|
||||
end
|
||||
function wagon:handle_bordcom_fields(pname, formname, fields)
|
||||
local seatno=self:get_seatno(pname)
|
||||
if not seatno or not self.seat_groups[self.seats[seatno].group].driving_ctrl_access or not minetest.check_player_privs(pname, "train_operator") then
|
||||
if not seatno or not self.seat_groups[self.seats[seatno].group].driving_ctrl_access or not advtrains.check_driving_couple_protection(pname, self.owner, self.whitelist) then
|
||||
return
|
||||
end
|
||||
local train = self:train()
|
||||
@ -925,7 +893,7 @@ function wagon:handle_bordcom_fields(pname, formname, fields)
|
||||
local ent = advtrains.wagon_save[tpid]
|
||||
local pent = advtrains.wagon_save[train.trainparts[i-1]]
|
||||
if ent and pent then
|
||||
if checklock(pname, ent.owner, pent.owner) then
|
||||
if checklock(pname, ent.owner, pent.owner, ent.whitelist, pent.whitelist) then
|
||||
for _,wagon in pairs(minetest.luaentities) do
|
||||
if wagon.is_wagon and wagon.initialized and wagon.unique_id==tpid then
|
||||
wagon.dcpl_lock=true
|
||||
@ -939,7 +907,7 @@ function wagon:handle_bordcom_fields(pname, formname, fields)
|
||||
local ent = advtrains.wagon_save[tpid]
|
||||
local pent = advtrains.wagon_save[train.trainparts[i-1]]
|
||||
if ent and pent then
|
||||
if checklock(pname, ent.owner, pent.owner) then
|
||||
if checklock(pname, ent.owner, pent.owner, ent.whitelist, pent.whitelist) then
|
||||
for _,wagon in pairs(minetest.luaentities) do
|
||||
if wagon.is_wagon and wagon.initialized and wagon.unique_id==tpid then
|
||||
wagon.dcpl_lock=false
|
||||
@ -962,11 +930,11 @@ function wagon:handle_bordcom_fields(pname, formname, fields)
|
||||
end
|
||||
|
||||
local function chkownsany()
|
||||
local owns_any = minetest.check_player_privs(pname, "train_remove")
|
||||
local owns_any = minetest.check_player_privs(pname, "train_admin")
|
||||
for i, tpid in ipairs(train.trainparts) do
|
||||
local ent = advtrains.wagon_save[tpid]
|
||||
if ent then
|
||||
owns_any = owns_any or (not ent.owner or ent.owner==pname)
|
||||
owns_any = owns_any or advtrains.check_driving_couple_protection(pname, ent.owner, ent.whitelist)
|
||||
end
|
||||
end
|
||||
return owns_any
|
||||
@ -1031,14 +999,13 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
for _,wagon in pairs(minetest.luaentities) do
|
||||
if wagon.is_wagon and wagon.initialized and wagon.unique_id==uid then
|
||||
local pname=player:get_player_name()
|
||||
if pname~=wagon.owner then
|
||||
if pname~=wagon.owner and not minetest.check_player_privs(pname, {train_admin = true}) then
|
||||
return true
|
||||
end
|
||||
if fields.save or not fields.quit then
|
||||
for sgr,sgrdef in pairs(wagon.seat_groups) do
|
||||
if fields["sgr_"..sgr] then
|
||||
local fcont = fields["sgr_"..sgr]
|
||||
wagon.seat_access[sgr] = fcont~="" and fcont or nil
|
||||
if fields.whitelist then
|
||||
wagon.whitelist = fields.whitelist
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1073,7 +1040,7 @@ function wagon:seating_from_key_helper(pname, fields, no)
|
||||
if fields.prop and self.owner==pname then
|
||||
self:show_wagon_properties(pname)
|
||||
end
|
||||
if fields.bordcom and self.seat_groups[sgr].driving_ctrl_access and minetest.check_player_privs(pname, "train_operator") then
|
||||
if fields.bordcom and self.seat_groups[sgr].driving_ctrl_access and advtrains.check_driving_couple_protection(pname, self.owner, self.whitelist) then
|
||||
self:show_bordcom(pname)
|
||||
end
|
||||
if fields.dcwarn then
|
||||
@ -1084,25 +1051,13 @@ function wagon:seating_from_key_helper(pname, fields, no)
|
||||
end
|
||||
end
|
||||
function wagon:check_seat_group_access(pname, sgr)
|
||||
if self.seat_groups[sgr].driving_ctrl_access and not (minetest.check_player_privs(pname, "train_operator") or self.owner==pname) then
|
||||
return false, "Missing train_operator privilege."
|
||||
if self.seat_groups[sgr].driving_ctrl_access and not (advtrains.check_driving_couple_protection(pname, self.owner, self.whitelist)) then
|
||||
return false, "Not allowed to access a driver stand!"
|
||||
end
|
||||
if self.seat_groups[sgr].driving_ctrl_access then
|
||||
advtrains.log("Drive", pname, self.object:getpos(), self:train().text_outside)
|
||||
end
|
||||
if not self.seat_access then
|
||||
return true
|
||||
end
|
||||
local sae=self.seat_access[sgr]
|
||||
if not sae or sae=="" then
|
||||
return true
|
||||
end
|
||||
for name in string.gmatch(sae, "%S+") do
|
||||
if name==pname then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false, "Blacklisted by owner."
|
||||
return true
|
||||
end
|
||||
function wagon:reattach_all()
|
||||
if not self.seatp then self.seatp={} end
|
||||
@ -1158,9 +1113,12 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img)
|
||||
atprint("no track here, not placing.")
|
||||
return itemstack
|
||||
end
|
||||
if not minetest.check_player_privs(placer, {train_place = true }) and minetest.is_protected(pointed_thing.under, placer:get_player_name()) then
|
||||
minetest.record_protection_violation(pointed_thing.under, placer:get_player_name())
|
||||
return
|
||||
if not minetest.check_player_privs(placer, {train_operator = true }) then
|
||||
minetest.chat_send_player(placer:get_player_name(), "You don't have the train_operator privilege.")
|
||||
return itemstack
|
||||
end
|
||||
if not minetest.check_player_privs(placer, {train_admin = true }) and minetest.is_protected(pointed_thing.under, placer:get_player_name()) then
|
||||
return itemstack
|
||||
end
|
||||
local tconns=advtrains.get_track_connections(node.name, node.param2)
|
||||
local yaw = placer:get_look_horizontal() + (math.pi/2)
|
||||
@ -1191,9 +1149,4 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img)
|
||||
})
|
||||
end
|
||||
|
||||
--[[
|
||||
wagons can define update_animation(self, velocity) if they have a speed-dependent animation
|
||||
this function will be called when the velocity vector changes or every 2 seconds.
|
||||
]]
|
||||
|
||||
|
||||
|
33
privilege_guide.txt
Normal file
33
privilege_guide.txt
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
### Advtrains Privilege Guide
|
||||
All privileges are automatically granted to singleplayer, but for
|
||||
multiplayer servers this might be interesting.
|
||||
There are 3 groups of privileges introduced by advtrains:
|
||||
|
||||
## Trains
|
||||
For a player to build his own trains and driving them, the player needs
|
||||
the 'train_operator' privilege. This privilege no longer allows him to
|
||||
control any train, only the ones that he owns or that he is whitelisted on.
|
||||
The owner of a wagon can write a whitelist which players are allowed to
|
||||
operate his wagon using the wagon properties dialog.
|
||||
Players having the 'train_admin' privilege can always drive, build and
|
||||
destroy any train.
|
||||
|
||||
## Tracks*
|
||||
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
|
||||
dig (or modify) anything inside this area.
|
||||
If any player tries to modify anything that is in the area of a track
|
||||
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
|
||||
treated as the track node itself)
|
||||
|
||||
## Turnouts and Signals*
|
||||
Players without the 'railway_operator' privilege can not operate signals
|
||||
and turnouts.
|
||||
|
||||
* If the configuration option 'advtrains_allow_build_to_owner' is set,
|
||||
an exception applies to players missing the required privileges when
|
||||
they are in a protected area that they have access to. Whether the
|
||||
area is protected from others is checked by checking for protection
|
||||
against a dummy player called '*dummy*'
|
Loading…
x
Reference in New Issue
Block a user