From e6700c5c7d0e1e8afb8f6fd5021b50f645655588 Mon Sep 17 00:00:00 2001 From: orwell96 Date: Tue, 17 Jul 2018 21:03:08 +0200 Subject: Revert "Rework the privilege system completely" This caused much trouble on Linuxworks recently. Please see http://www.linux-forks.de/advtrains/22.html for current discussion on that topic This reverts commit 8b576357ef1d2346e9af112e115ac92a5f4d222d. --- advtrains/init.lua | 3 +- advtrains/protection.lua | 148 --------------------------------------------- advtrains/settingtypes.txt | 5 -- advtrains/signals.lua | 10 +-- advtrains/tracks.lua | 3 +- advtrains/wagons.lua | 117 ++++++++++++++++++++++++----------- privilege_guide.txt | 33 ---------- 7 files changed, 89 insertions(+), 230 deletions(-) delete mode 100644 advtrains/protection.lua delete mode 100644 privilege_guide.txt diff --git a/advtrains/init.lua b/advtrains/init.lua index 65e5048..d7bff4d 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -151,7 +151,6 @@ 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") @@ -276,7 +275,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", "line" + "text_outside", "text_inside", "couple_lck_front", "couple_lck_back" }) --then invalidate if train.index then diff --git a/advtrains/protection.lua b/advtrains/protection.lua deleted file mode 100644 index 73b725f..0000000 --- a/advtrains/protection.lua +++ /dev/null @@ -1,148 +0,0 @@ --- 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 diff --git a/advtrains/settingtypes.txt b/advtrains/settingtypes.txt index 3b4863d..d0c27ec 100644 --- a/advtrains/settingtypes.txt +++ b/advtrains/settingtypes.txt @@ -10,8 +10,3 @@ 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 diff --git a/advtrains/signals.lua b/advtrains/signals.lua index 53145f5..b01314e 100644 --- a/advtrains/signals.lua +++ b/advtrains/signals.lua @@ -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 advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then + if minetest.check_player_privs(player:get_player_name(), {train_operator=true}) 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 advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then + if minetest.check_player_privs(player:get_player_name(), {train_operator=true}) 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 advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then + if minetest.check_player_privs(player:get_player_name(), {train_operator=true}) 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 advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then + if minetest.check_player_privs(player:get_player_name(), {train_operator=true}) 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 advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then + if minetest.check_player_privs(player:get_player_name(), {train_operator=true}) then advtrains.ndb.swap_node(pos, {name = "advtrains:across_off", param2 = node.param2}, true) end end, diff --git a/advtrains/tracks.lua b/advtrains/tracks.lua index f31fef6..4b2b17c 100644 --- a/advtrains/tracks.lua +++ b/advtrains/tracks.lua @@ -269,7 +269,6 @@ 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, @@ -310,7 +309,7 @@ function advtrains.register_tracks(tracktype, def, preset) end end ndef.on_rightclick = function(pos, node, player) - if advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then + if minetest.check_player_privs(player:get_player_name(), {train_operator=true}) then switchfunc(pos, node) advtrains.log("Switch", player:get_player_name(), pos) end diff --git a/advtrains/wagons.lua b/advtrains/wagons.lua index d9b467c..2dce41b 100644 --- a/advtrains/wagons.lua +++ b/advtrains/wagons.lua @@ -1,5 +1,19 @@ --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, @@ -147,7 +161,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_admin = true })) then + if self.owner and puncher:get_player_name()~=self.owner and (not minetest.check_player_privs(puncher, {train_remove = 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 @@ -236,9 +250,8 @@ function wagon:on_step(dtime) --driver control for seatno, seat in ipairs(self.seats) do - 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) + 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]) if self.seat_groups then has_driverstand = has_driverstand and (seat.driving_ctrl_access or self.seat_groups[seat.group].driving_ctrl_access) else @@ -564,6 +577,13 @@ 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 @@ -578,7 +598,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 advtrains.check_driving_couple_protection(pname, self.owner, self.whitelist) then + if self.seat_groups[sgr].driving_ctrl_access and minetest.check_player_privs(pname, "train_operator") then poss[#poss+1]={name=attrans("Bord Computer"), key="bordcom"} end if self.owner==pname then @@ -759,15 +779,28 @@ 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: - field: driving/couple whitelist + fields: seat access: empty: everyone + checkbox: lock couples button: save ]] - 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").."]" + 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").."]" minetest.show_formspec(pname, "advtrains_prop_"..self.unique_id, form) end @@ -786,9 +819,9 @@ local function checkcouple(eid) end return le end -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) +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)) end function wagon:show_bordcom(pname) if not self:train() then return end @@ -801,7 +834,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, pre_wl, owns_any = nil, nil, minetest.check_player_privs(pname, "train_admin") + local pre_own, owns_any = nil, minetest.check_player_privs(pname, "train_remove") for i, tpid in ipairs(train.trainparts) do local ent = advtrains.wagon_save[tpid] if ent then @@ -810,7 +843,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, ent.whitelist, pre_wl) then + if checklock(pname, ent.owner, pre_own) then form = form .. "image_button["..(i-0.5)..","..(linhei+2)..";1,1;advtrains_cpl_unlock.png;dcpl_lck_"..i..";]" end else @@ -821,7 +854,6 @@ 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 @@ -862,7 +894,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 advtrains.check_driving_couple_protection(pname, self.owner, self.whitelist) then + 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 return end local train = self:train() @@ -893,7 +925,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, ent.whitelist, pent.whitelist) then + if checklock(pname, ent.owner, pent.owner) 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 @@ -907,7 +939,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, ent.whitelist, pent.whitelist) then + if checklock(pname, ent.owner, pent.owner) 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 @@ -930,11 +962,11 @@ function wagon:handle_bordcom_fields(pname, formname, fields) end local function chkownsany() - local owns_any = minetest.check_player_privs(pname, "train_admin") + local owns_any = minetest.check_player_privs(pname, "train_remove") for i, tpid in ipairs(train.trainparts) do local ent = advtrains.wagon_save[tpid] if ent then - owns_any = owns_any or advtrains.check_driving_couple_protection(pname, ent.owner, ent.whitelist) + owns_any = owns_any or (not ent.owner or ent.owner==pname) end end return owns_any @@ -999,13 +1031,14 @@ 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 and not minetest.check_player_privs(pname, {train_admin = true}) then + if pname~=wagon.owner then return true end if fields.save or not fields.quit then for sgr,sgrdef in pairs(wagon.seat_groups) do - if fields.whitelist then - wagon.whitelist = fields.whitelist + if fields["sgr_"..sgr] then + local fcont = fields["sgr_"..sgr] + wagon.seat_access[sgr] = fcont~="" and fcont or nil end end end @@ -1040,7 +1073,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 advtrains.check_driving_couple_protection(pname, self.owner, self.whitelist) then + if fields.bordcom and self.seat_groups[sgr].driving_ctrl_access and minetest.check_player_privs(pname, "train_operator") then self:show_bordcom(pname) end if fields.dcwarn then @@ -1051,13 +1084,25 @@ 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 (advtrains.check_driving_couple_protection(pname, self.owner, self.whitelist)) then - return false, "Not allowed to access a driver stand!" + 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." end if self.seat_groups[sgr].driving_ctrl_access then advtrains.log("Drive", pname, self.object:getpos(), self:train().text_outside) end - return true + 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." end function wagon:reattach_all() if not self.seatp then self.seatp={} end @@ -1113,12 +1158,9 @@ 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_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 + 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 end local tconns=advtrains.get_track_connections(node.name, node.param2) local yaw = placer:get_look_horizontal() + (math.pi/2) @@ -1149,4 +1191,9 @@ 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. +]] + diff --git a/privilege_guide.txt b/privilege_guide.txt deleted file mode 100644 index 7c4952f..0000000 --- a/privilege_guide.txt +++ /dev/null @@ -1,33 +0,0 @@ - -### 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*' -- cgit v1.2.3