From b872bdae82b41398d2322ee848ade2c1cc652ce0 Mon Sep 17 00:00:00 2001 From: orwell96 Date: Sat, 10 Nov 2018 12:12:52 +0100 Subject: [PATCH] Remove "couple locks" and apply protection to the actual coupling process, and fix permissions on that --- advtrains/couple.lua | 59 +------------- advtrains/init.lua | 4 +- advtrains/trainlogic.lua | 33 +------- advtrains/wagons.lua | 163 +++++++++++++++++++++++---------------- 4 files changed, 105 insertions(+), 154 deletions(-) diff --git a/advtrains/couple.lua b/advtrains/couple.lua index e092696..1b213c2 100644 --- a/advtrains/couple.lua +++ b/advtrains/couple.lua @@ -65,7 +65,7 @@ minetest.register_entity("advtrains:discouple", { -- advtrains:couple -- Couple entity local function lockmarker(obj) - minetest.spawn_entity(obj:get_pos(), "advtrains.lockmarker") + minetest.add_entity(obj:get_pos(), "advtrains:lockmarker") obj:remove() end @@ -96,63 +96,12 @@ minetest.register_entity("advtrains:couple", { local pname=clicker if type(clicker)~="string" then pname=clicker:get_player_name() end - if not minetest.check_player_privs(pname, "train_operator") then return end - local train1=advtrains.trains[self.train_id_1] - local train2=advtrains.trains[self.train_id_2] - if not advtrains.train_ensure_init(self.train_id_1, train1) then - atwarn("Train",self.train_id_1,"is not initialized! Operation aborted!") - return - end - if not advtrains.train_ensure_init(self.train_id_2, train2) then - atwarn("Train",self.train_id_2,"is not initialized! Operation aborted!") - return - end - - local id1, id2=self.train_id_1, self.train_id_2 - local bp1, bp2 = self.t1_is_front, self.t2_is_front - if bp1 then - if train1.couple_lock_front then - lockmarker(self.object) - return - end - if bp2 then - if train2.couple_lock_front then - lockmarker(self.object) - return - end - advtrains.invert_train(id1) - advtrains.do_connect_trains(id1, id2, clicker) - else - if train2.couple_lock_back then - lockmarker(self.object) - return - end - advtrains.do_connect_trains(id2, id1, clicker) - end + if advtrains.safe_couple_trains(self.train_id_1, self.train_id_2, self.t1_is_front, self.t2_is_front, pname) then + self.object:remove() else - if train1.couple_lock_back then - lockmarker(self.object) - return - end - if bp2 then - if train2.couple_lock_front then - lockmarker(self.object) - return - end - advtrains.do_connect_trains(id1, id2, clicker) - else - if train2.couple_lock_back then - lockmarker(self.object) - return - end - advtrains.invert_train(id2) - advtrains.do_connect_trains(id1, id2, clicker) - end + lockmarker(self.object) end - - atprint("Coupled trains", id1, id2) - self.object:remove() end) end, on_step=function(self, dtime) diff --git a/advtrains/init.lua b/advtrains/init.lua index 3d420e6..3af679a 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -287,7 +287,7 @@ advtrains.avt_save = function(remove_players_from_wagons) "last_pos", "last_connid", "last_frac", "velocity", "tarvelocity", "trainparts", "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", "line", "il_sections", "speed_restriction", }) --then save it @@ -308,6 +308,8 @@ advtrains.avt_save = function(remove_players_from_wagons) end end -- TODO apply save-keys here too + -- TODO temp + wdata.dcpl_lock = nil end --versions: diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua index 47d9542..e8518e7 100644 --- a/advtrains/trainlogic.lua +++ b/advtrains/trainlogic.lua @@ -736,22 +736,7 @@ function advtrains.add_wagon_to_train(wagon_id, train_id, index) run_callbacks_update(train_id, train) end -function advtrains.safe_decouple_wagon(w_id, pname) - if not minetest.check_player_privs(pname, "train_operator") then - minetest.chat_send_player(pname, "Missing train_operator privilege") - return false - end - local data = advtrains.wagons[w_id] - if data.dcpl_lock then - minetest.chat_send_player(pname, "Couple is locked (ask owner or admin to unlock it)") - return false - end - atprint("wagon:discouple() Splitting train", data.train_id) - local train = advtrains.trains[data.train_id] - advtrains.log("Discouple", pname, train.last_pos, train.text_outside) - advtrains.split_train_at_wagon(w_id) - return true -end +-- Note: safe_decouple_wagon() has been moved to wagons.lua -- this function sets wagon's pos_in_train(parts) properties and train's max_speed and drives_on (and more) function advtrains.update_trainpart_properties(train_id, invert_flipstate) @@ -881,13 +866,7 @@ function advtrains.split_train_at_wagon(wagon_id) local newtrain_id=advtrains.create_new_train_at(pos, connid, frac, tp) local newtrain=advtrains.trains[newtrain_id] - train.tarvelocity=0 newtrain.velocity=train.velocity - newtrain.tarvelocity=0 - - newtrain.couple_lck_back=train.couple_lck_back - newtrain.couple_lck_front=false - train.couple_lck_back=false end @@ -1013,12 +992,6 @@ function advtrains.do_connect_trains(first_id, second_id) return end - if first.couple_lck_back or second.couple_lck_front then - -- trains are ordered correctly! - -- Note, this is already checked in the rightclick step of the couple entity before trains are actually reversed - return - end - local first_wagoncnt=#first.trainparts local second_wagoncnt=#second.trainparts @@ -1026,13 +999,10 @@ function advtrains.do_connect_trains(first_id, second_id) table.insert(first.trainparts, v) end - local tmp_cpl_lck=second.couple_lck_back - advtrains.remove_train(second_id) first.velocity=0 first.tarvelocity=0 - first.couple_lck_back=tmp_cpl_lck advtrains.update_trainpart_properties(first_id) advtrains.couple_invalidate(first) @@ -1050,7 +1020,6 @@ function advtrains.invert_train(train_id) advtrains.path_setrestore(train, true) -- rotate some other stuff - train.couple_lck_back, train.couple_lck_front = train.couple_lck_front, train.couple_lck_back if train.door_open then train.door_open = - train.door_open end diff --git a/advtrains/wagons.lua b/advtrains/wagons.lua index 1621da8..1a02d3c 100644 --- a/advtrains/wagons.lua +++ b/advtrains/wagons.lua @@ -300,7 +300,7 @@ function wagon:on_step(dtime) --check infotext local outside=self:train().text_outside or "" if setting_show_ids then - outside = outside .. "\nT:" .. data.train_id .. " W:" .. self.id + outside = outside .. "\nT:" .. data.train_id .. " W:" .. self.id .. " O:" .. data.owner end local train=self:train() @@ -361,7 +361,7 @@ function wagon:on_step(dtime) --DisCouple if data.pos_in_trainparts and data.pos_in_trainparts>1 then - if train.velocity==0 and not data.dcpl_lock then + if train.velocity==0 then if not self.discouple or not self.discouple.object:getyaw() then atprint(self.id,"trying to spawn discouple") local yaw = self.object:getyaw() @@ -374,9 +374,6 @@ function wagon:on_step(dtime) --box is hidden when attached, so unuseful. --object:set_attach(self.object, "", {x=0, y=0, z=self.wagon_span*10}, {x=0, y=0, z=0}) self.discouple=le - atprint(self.id,"success") - else - atprint("Couldn't spawn DisCouple") end end else @@ -474,12 +471,13 @@ function wagon:on_step(dtime) end self.updatepct_timer=(self.updatepct_timer or 0)-dtime + local updatepct_timer_elapsed = self.updatepct_timer<=0 if not self.old_velocity_vector or not vector.equals(velocityvec, self.old_velocity_vector) or not self.old_acceleration_vector or not vector.equals(accelerationvec, self.old_acceleration_vector) or self.old_yaw~=yaw - or self.updatepct_timer<=0 then--only send update packet if something changed + or updatepct_timer_elapsed then--only send update packet if something changed self.object:setpos(pos) self.object:setvelocity(velocityvec) @@ -518,7 +516,7 @@ function wagon:on_step(dtime) self:custom_on_velocity_change(train.velocity, self.old_velocity or 0, dtime) end -- remove discouple object, because it will be in a wrong location - if self.discouple then + if not updatepct_timer_elapsed and self.discouple then self.discouple.object:remove() end end @@ -792,13 +790,8 @@ function wagon:show_bordcom(pname) local ename = ent.type form = form .. "item_image["..i..","..linhei..";1,1;"..ename.."]" if i~=1 then - if not ent.dcpl_lock then + if checklock(pname, ent.owner, pre_own, ent.whitelist, pre_wl) 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 - form = form .. "image_button["..(i-0.5)..","..(linhei+2)..";1,1;advtrains_cpl_unlock.png;dcpl_lck_"..i..";]" - end - else - form = form .. "image_button["..(i-0.5)..","..(linhei+2)..";1,1;advtrains_cpl_lock.png;dcpl_ulck_"..i..";]" end end if i == data.pos_in_trainparts then @@ -824,18 +817,6 @@ function wagon:show_bordcom(pname) if couple_back then form = form .. "image_button["..(#train.trainparts+0.5)..","..(linhei+1)..";1,1;advtrains_couple.png;cpl_b;]" end - if owns_any then - if train.couple_lck_front then - form = form .. "image_button[0.5,"..(linhei+2)..";1,1;advtrains_cpl_lock.png;cpl_ulck_f;]" - else - form = form .. "image_button[0.5,"..(linhei+2)..";1,1;advtrains_cpl_unlock.png;cpl_lck_f;]" - end - if train.couple_lck_back then - form = form .. "image_button["..(#train.trainparts+0.5)..","..(linhei+2)..";1,1;advtrains_cpl_lock.png;cpl_ulck_b;]" - else - form = form .. "image_button["..(#train.trainparts+0.5)..","..(linhei+2)..";1,1;advtrains_cpl_unlock.png;cpl_lck_b;]" - end - end else form=form.."label[0.5,4.5;Train overview / coupling control is only shown when the train stands.]" @@ -887,24 +868,6 @@ function wagon:handle_bordcom_fields(pname, formname, fields) if fields["dcpl_"..i] then advtrains.safe_decouple_wagon(tpid, pname) end - if i>1 and fields["dcpl_lck_"..i] then - local ent = advtrains.wagons[tpid] - local pent = advtrains.wagons[train.trainparts[i-1]] - if ent and pent then - if checklock(pname, ent.owner, pent.owner, ent.whitelist, pent.whitelist) then - ent.dcpl_lock = true - end - end - end - if i>1 and fields["dcpl_ulck_"..i] then - local ent = advtrains.wagons[tpid] - local pent = advtrains.wagons[train.trainparts[i-1]] - if ent and pent then - if checklock(pname, ent.owner, pent.owner, ent.whitelist, pent.whitelist) then - ent.dcpl_lock = false - end - end - end end --check cpl_eid_front and _back of train local couple_front = checkcouple(train.cpl_front) @@ -917,29 +880,6 @@ function wagon:handle_bordcom_fields(pname, formname, fields) couple_back:on_rightclick(pname) end - local function chkownsany() - local owns_any = minetest.check_player_privs(pname, "train_admin") - for i, tpid in ipairs(train.trainparts) do - local ent = advtrains.wagons[tpid] - if ent then - owns_any = owns_any or advtrains.check_driving_couple_protection(pname, ent.owner, ent.whitelist) - end - end - return owns_any - end - if fields.cpl_lck_f and chkownsany() then - train.couple_lck_front=true - end - if fields.cpl_lck_b and chkownsany() then - train.couple_lck_back=true - end - if fields.cpl_ulck_f and chkownsany() then - train.couple_lck_front=false - end - if fields.cpl_ulck_b and chkownsany() then - train.couple_lck_back=false - end - -- Interlocking functionality: If the interlocking module is loaded, you can set the signal aspect -- from inside the train if fields.ilrs and advtrains.interlocking and train.lzb and #train.lzb.oncoming > 0 then @@ -1073,6 +1013,97 @@ function wagon:reattach_all() end end +local function check_twagon_owner(train, b_first, pname) + local wtp = b_first and 1 or #train.trainparts + atdebug("wtp",wtp) + local wid = train.trainparts[wtp] + local wdata = advtrains.wagons[wid] + if wdata then + return advtrains.check_driving_couple_protection(pname, wdata.owner, wdata.whitelist) + end + return false +end + +function advtrains.safe_couple_trains(id1, id2, t1f, t2f, pname, try_run) + + if not minetest.check_player_privs(pname, "train_operator") then + minetest.chat_send_player(pname, "Missing train_operator privilege") + return false + end + + local train1=advtrains.trains[id1] + local train2=advtrains.trains[id2] + + if not advtrains.train_ensure_init(id1, train1) + or not advtrains.train_ensure_init(id2, train2) then + return false + end + + local wck_t1 = check_twagon_owner(train1, t1f, pname) + local wck_t2 = check_twagon_owner(train2, t2f, pname) + + if wck_t1 or wck_t2 then + if try_run then + return true + end + if t1f then + if t2f then + advtrains.invert_train(id1) + advtrains.do_connect_trains(id1, id2) + else + advtrains.do_connect_trains(id2, id1) + end + else + if t2f then + advtrains.do_connect_trains(id1, id2) + else + advtrains.invert_train(id2) + advtrains.do_connect_trains(id1, id2) + end + end + return true + else + minetest.chat_send_player(pname, "You must be authorized for at least one wagon.") + return false + end +end + + +function advtrains.safe_decouple_wagon(w_id, pname, try_run) + if not minetest.check_player_privs(pname, "train_operator") then + minetest.chat_send_player(pname, "Missing train_operator privilege") + return false + end + local data = advtrains.wagons[w_id] + + local dpt = data.pos_in_trainparts + if not dpt or dpt <= 1 then + return false + end + local train = advtrains.trains[data.train_id] + local owid = train.trainparts[dpt-1] + local owdata = advtrains.wagons[owid] + + if not owdata then + return + end + + if not checklock(pname, data.owner, owdata.owner, data.whitelist, owdata.whitelist) then + minetest.chat_send_player(pname, "Not allowed to do this.") + return false + end + + if try_run then + return true + end + + advtrains.log("Discouple", pname, train.last_pos, train.text_outside) + advtrains.split_train_at_wagon(w_id) + return true +end + + + function advtrains.get_wagon_prototype(data) local wt = data.type if not wt then