From 2a76d4a960aa29621dc8020f84eee241b41e10c0 Mon Sep 17 00:00:00 2001 From: orwell96 Date: Tue, 29 May 2018 12:27:02 +0200 Subject: Fix final bugs and to-do's (u.a.save/load system) --- advtrains/couple.lua | 4 +-- advtrains/helpers.lua | 4 +-- advtrains/init.lua | 65 +++++++++++++---------------------- advtrains/occupation.lua | 6 ++-- advtrains/path.lua | 88 +++++++----------------------------------------- advtrains/trainlogic.lua | 75 ++++++++++++++++++++++++++--------------- advtrains/wagons.lua | 38 +++++---------------- 7 files changed, 100 insertions(+), 180 deletions(-) diff --git a/advtrains/couple.lua b/advtrains/couple.lua index a4eecf4..1aac0b3 100644 --- a/advtrains/couple.lua +++ b/advtrains/couple.lua @@ -34,7 +34,7 @@ minetest.register_entity("advtrains:discouple", { return advtrains.pcall(function() local pname = player:get_player_name() if pname and pname~="" and self.wagon then - if self.wagon:safe_decouple(pname) then + if advtrains.safe_decouple_wagon(self.wagon.id, pname) then self.object:remove() else minetest.add_entity(self.object:getpos(), "advtrains:lockmarker") @@ -53,7 +53,7 @@ minetest.register_entity("advtrains:discouple", { self.object:remove() return end - if not self.wagon:train() and self.wagon:train().velocity > 0 then + if not self.wagon:train() or self.wagon:train().velocity > 0 then self.object:remove() return end diff --git a/advtrains/helpers.lua b/advtrains/helpers.lua index e060920..ce059de 100644 --- a/advtrains/helpers.lua +++ b/advtrains/helpers.lua @@ -37,7 +37,7 @@ advtrains.pos_add_dir = advtrains.dirCoordSet function advtrains.pos_add_angle(pos, ang) -- 0 is +Z -> meaning of sin/cos swapped - return vector.add(pos, {x = -math.cos(ang), y = 0, z = math.sin(ang)}) + return vector.add(pos, {x = -math.sin(ang), y = 0, z = math.cos(ang)}) end function advtrains.dirToCoord(dir) @@ -103,7 +103,7 @@ function advtrains.yawToClosestConn(yaw, conns) local min_connid, min_diff=1, 10 for connid, conn in ipairs(conns) do local yaw1 = advtrains.dir_to_angle(conn.c) - local diff = advtrains.minAngleDiffRad(yaw, yaw1) + local diff = math.abs(advtrains.minAngleDiffRad(yaw, yaw1)) if diff < min_diff then min_connid = connid min_diff = diff diff --git a/advtrains/init.lua b/advtrains/init.lua index d68b188..323d55a 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -41,14 +41,12 @@ function advtrains.pcall(fun) local succ, return1, return2, return3, return4=xpcall(fun, function(err) atwarn("Lua Error occured: ", err) atwarn(debug.traceback()) - if advtrains.atprint_context_tid_full then - advtrains.path_print(advtrains.trains[advtrains.atprint_context_tid_full], atdebug) + if advtrains.atprint_context_tid then + advtrains.path_print(advtrains.trains[advtrains.atprint_context_tid], atdebug) end end) if not succ then - --reload_saves() - no_action=true --this does also not belong here! - minetest.request_shutdown() + reload_saves() else return return1, return2, return3, return4 end @@ -123,6 +121,7 @@ if minetest.settings:get_bool("advtrains_enable_debugging") then --atlog("@@",advtrains.atprint_context_tid,t,...) end dofile(advtrains.modpath.."/debugringbuffer.lua") + end function assertt(var, typ) @@ -185,7 +184,8 @@ dofile(advtrains.modpath.."/log.lua") function advtrains.avt_load() local file, err = io.open(advtrains.fpath, "r") if not file then - minetest.log("error", " Failed to read advtrains save data from file "..advtrains.fpath..": "..(err or "Unknown Error")) + minetest.log("warning", " Failed to read advtrains save data from file "..advtrains.fpath..": "..(err or "Unknown Error")) + minetest.log("warning", " (this is normal when first enabling advtrains on this world)") else local tbl = minetest.deserialize(file:read("*a")) if type(tbl) == "table" then @@ -196,7 +196,7 @@ function advtrains.avt_load() for id, train in pairs(advtrains.trains) do train.id = id end - advtrains.wagon_save = tbl.wagon_save + advtrains.wagons = tbl.wagon_save advtrains.player_to_train_mapping = tbl.ptmap or {} advtrains.ndb.load_data(tbl.ndb) advtrains.atc.load_data(tbl.atc) @@ -251,48 +251,30 @@ end advtrains.avt_save = function(remove_players_from_wagons) --atprint("saving") - --No more invalidating. - --Instead, remove path a.s.o from the saved table manually - -- update wagon saves - for _,wagon in pairs(minetest.luaentities) do - if wagon.is_wagon and wagon.initialized then - wagon:get_staticdata() - end - end - --cross out userdata - for w_id, data in pairs(advtrains.wagon_save) do - data.name=nil - data.object=nil - if data.driver then - data.driver_name=data.driver:get_player_name() - data.driver=nil - else - data.driver_name=nil - end - if data.discouple then - data.discouple.object:remove() - data.discouple=nil - end - if remove_players_from_wagons then + if remove_players_from_wagons then + for w_id, data in pairs(advtrains.wagons) do data.seatp={} end - end - if remove_players_from_wagons then advtrains.player_to_train_mapping={} end local tmp_trains={} for id, train in pairs(advtrains.trains) do --first, deep_copy the train - local v=advtrains.save_keys(train, { - "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" - }) - --then save it - tmp_trains[id]=v + if #train.trainparts > 0 then + local v=advtrains.save_keys(train, { + "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" + }) + --then save it + tmp_trains[id]=v + else + atwarn("Train",id,"had no wagons left because of some bug. It is being deleted. Wave it goodbye!") + advtrains.remove_train(id) + end end --versions: @@ -356,7 +338,7 @@ minetest.register_globalstep(function(dtime_mt) if save_timer<=0 then local t=os.clock() --save - --advtrains.save() + advtrains.save() save_timer=save_interval atprintbm("saving", t) end @@ -430,3 +412,4 @@ minetest.register_chatcommand("at_reroute", local tot=(os.clock()-lot)*1000 minetest.log("action", "[advtrains] Loaded in "..tot.."ms") + diff --git a/advtrains/occupation.lua b/advtrains/occupation.lua index 99de521..dd0235a 100644 --- a/advtrains/occupation.lua +++ b/advtrains/occupation.lua @@ -172,9 +172,9 @@ function o.check_collision(pos, train_id) if ti~=train_id then local idx = t[i+1] local train = advtrains.trains[ti] - atdebug("checking train",t[i],"index",idx,"<>",train.index,train.end_index) + --atdebug("checking train",t[i],"index",idx,"<>",train.index,train.end_index) if idx >= train.end_index and idx <= train.index then - atdebug("collides.") + --atdebug("collides.") return true end end @@ -190,7 +190,7 @@ end function o.get_occupations(train, index) local ppos, ontrack = advtrains.path_get(train, index) if not ontrack then - atdebug("Train",train.id,"get_occupations requested off-track",index) + atwarn("Train",train.id,"get_occupations requested off-track",index) return {}, ppos end local pos = advtrains.round_vector_floor_y(ppos) diff --git a/advtrains/path.lua b/advtrains/path.lua index d810fd7..8bdb72b 100644 --- a/advtrains/path.lua +++ b/advtrains/path.lua @@ -1,76 +1,6 @@ -- path.lua -- Functions for pathpredicting, put in a separate file. -function advtrains.conway(midreal, prev, drives_on)--in order prev,mid,return - local mid=advtrains.round_vector_floor_y(midreal) - - local midnode_ok, midconns=advtrains.get_rail_info_at(mid, drives_on) - if not midnode_ok then - return nil - end - local pconnid - for connid, conn in ipairs(midconns) do - local tps = advtrains.dirCoordSet(mid, conn.c) - if tps.x==prev.x and tps.z==prev.z then - pconnid=connid - end - end - local nconnid = advtrains.get_matching_conn(pconnid, #midconns) - - local next, next_connid, _, nextrailheight = advtrains.get_adjacent_rail(mid, midconns, nconnid, drives_on) - if not next then - return nil - end - return vector.add(advtrains.round_vector_floor_y(next), {x=0, y=nextrailheight, z=0}), midconns[nconnid].c -end - -function advtrains.pathpredict(id, train, gen_front, gen_back) - - local maxn=train.path_extent_max or 0 - while maxn < gen_front do--pregenerate - local conway - if train.max_index_on_track == maxn then - --atprint("maxn conway for ",maxn,train.path[maxn],maxn-1,train.path[maxn-1]) - conway=advtrains.conway(train.path[maxn], train.path[maxn-1], train.drives_on) - end - if conway then - train.path[maxn+1]=conway - train.max_index_on_track=maxn+1 - else - --do as if nothing has happened and preceed with path - --but do not update max_index_on_track - atprint("over-generating path max to index ",(maxn+1)," (position ",train.path[maxn]," )") - train.path[maxn+1]=vector.add(train.path[maxn], vector.subtract(train.path[maxn], train.path[maxn-1])) - end - train.path_dist[maxn]=vector.distance(train.path[maxn+1], train.path[maxn]) - maxn=maxn+1 - end - train.path_extent_max=maxn - - local minn=train.path_extent_min or -1 - while minn > gen_back do - local conway - if train.min_index_on_track == minn then - --atprint("minn conway for ",minn,train.path[minn],minn+1,train.path[minn+1]) - conway=advtrains.conway(train.path[minn], train.path[minn+1], train.drives_on) - end - if conway then - train.path[minn-1]=conway - train.min_index_on_track=minn-1 - else - --do as if nothing has happened and preceed with path - --but do not update min_index_on_track - atprint("over-generating path min to index ",(minn-1)," (position ",train.path[minn]," )") - train.path[minn-1]=vector.add(train.path[minn], vector.subtract(train.path[minn], train.path[minn+1])) - end - train.path_dist[minn-1]=vector.distance(train.path[minn], train.path[minn-1]) - minn=minn-1 - end - train.path_extent_min=minn - if not train.min_index_on_track then train.min_index_on_track=-1 end - if not train.max_index_on_track then train.max_index_on_track=0 end -end - -- Naming conventions: -- 'index' - An index of the train.path table. -- 'offset' - A value in meters that determines how far on the path to walk relative to a certain index @@ -145,7 +75,7 @@ function advtrains.path_setrestore(train, invert) end -- Get restore position, connid and frac (in this order) for a train that will originate at the passed index -- If invert is set, it will return path_cp and multiply frac by -1, in order to reverse the train there. -function advtrains.path_getrestore(train, index, invert, tmp) +function advtrains.path_getrestore(train, index, invert) local idx = index local cns = train.path_cn @@ -153,7 +83,7 @@ function advtrains.path_getrestore(train, index, invert, tmp) cns = train.path_cp end - fli = atfloor(index) + local fli = atfloor(index) advtrains.path_get(train, fli) if fli > train.path_trk_f then fli = train.path_trk_f @@ -161,9 +91,6 @@ function advtrains.path_getrestore(train, index, invert, tmp) if fli < train.path_trk_b then fli = train.path_trk_b end - if not tmp then - atdebug ("getrestore ",atround(train.index),"calc",atround(index),fli) - end return advtrains.path_get(train, fli), cns[fli], (idx - fli) * (invert and -1 or 1) @@ -195,7 +122,13 @@ end function advtrains.path_print(train, printf) printf("i: CP Position Dir CN ->Dist->") for i = train.path_ext_b, train.path_ext_f do + if i==train.path_trk_b then + printf("--Back on-track border here--") + end printf(i,": ",train.path_cp[i]," ",train.path[i]," ",train.path_dir[i]," ",train.path_cn[i]," ->",train.path_dist[i],"->") + if i==train.path_trk_f then + printf("--Front on-track border here--") + end end end @@ -231,6 +164,7 @@ function advtrains.path_get(train, index) else -- off-track fallback behavior adj_pos = advtrains.pos_add_angle(pos, train.path_dir[pef-1]) + --atdebug("Offtrack overgenerating(front) at",adj_pos,"index",peb,"trkf",train.path_trk_f) train.path_dir[pef] = train.path_dir[pef-1] end train.path[pef] = adj_pos @@ -260,6 +194,7 @@ function advtrains.path_get(train, index) else -- off-track fallback behavior adj_pos = advtrains.pos_add_angle(pos, train.path_dir[peb+1] + math.pi) + --atdebug("Offtrack overgenerating(back) at",adj_pos,"index",peb,"trkb",train.path_trk_b) train.path_dir[peb] = train.path_dir[peb+1] end train.path[peb] = adj_pos @@ -326,7 +261,6 @@ function advtrains.path_get_index_by_offset(train, index, offset) idx = idx - 1 advtrains.path_get_adjacent(train, idx) if not train.path_dist[idx] then - atdebug("second while",idx) for i=-5,5 do atdebug(idx+i,train.path_dist[idx+i]) end @@ -363,6 +297,8 @@ function advtrains.path_clear_unused(train) train.path_dir[i+1] = nil train.path_ext_f = i - 1 end + train.path_trk_b = math.max(train.path_trk_b, train.path_ext_b) + train.path_trk_f = math.min(train.path_trk_f, train.path_ext_f) train.path_req_f = math.ceil(train.index) train.path_req_b = math.floor(train.end_index or train.index) diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua index feb35b5..df3ec92 100644 --- a/advtrains/trainlogic.lua +++ b/advtrains/trainlogic.lua @@ -1,7 +1,6 @@ --trainlogic.lua --controls train entities stuff about connecting/disconnecting/colliding trains and other things --- TODO: what should happen when a train has no trainparts anymore? local benchmark=false local bm={} @@ -68,17 +67,17 @@ advtrains.mainloop_trainlogic=function(dtime) local t=os.clock() for k,v in pairs(advtrains.trains) do - advtrains.atprint_context_tid=sid(k) + advtrains.atprint_context_tid=k advtrains.train_ensure_init(k, v) end for k,v in pairs(advtrains.trains) do - advtrains.atprint_context_tid=sid(k) + advtrains.atprint_context_tid=k advtrains.train_step_b(k, v, dtime) end for k,v in pairs(advtrains.trains) do - advtrains.atprint_context_tid=sid(k) + advtrains.atprint_context_tid=k advtrains.train_step_c(k, v, dtime) end @@ -242,7 +241,7 @@ function advtrains.train_ensure_init(id, train) advtrains.update_trainpart_properties(id) recalc_end_index(train) - atdebug("Train",id,": Successfully restored path at",train.last_pos," connid",train.last_connid," frac",train.last_frac) + --atdebug("Train",id,": Successfully restored path at",train.last_pos," connid",train.last_connid," frac",train.last_frac) -- run on_new_path callbacks run_callbacks_new_path(id, train) @@ -470,8 +469,7 @@ end -- asserted to rely on this) local function tnc_call_enter_callback(pos, train_id) - --atprint("instructed to call enter calback") - + --atdebug("tnc enter",pos,train_id) local node = advtrains.ndb.get_node(pos) --this spares the check if node is nil, it has a name in any case local mregnode=minetest.registered_nodes[node.name] if mregnode and mregnode.advtrains and mregnode.advtrains.on_train_enter then @@ -479,8 +477,7 @@ local function tnc_call_enter_callback(pos, train_id) end end local function tnc_call_leave_callback(pos, train_id) - --atprint("instructed to call leave calback") - + --atdebug("tnc leave",pos,train_id) local node = advtrains.ndb.get_node(pos) --this spares the check if node is nil, it has a name in any case local mregnode=minetest.registered_nodes[node.name] if mregnode and mregnode.advtrains and mregnode.advtrains.on_train_leave then @@ -493,7 +490,7 @@ advtrains.te_register_on_new_path(function(id, train) old_index = atround(train.index), old_end_index = atround(train.end_index), } - atdebug(id,"tnc init",train.index,train.end_index) + --atdebug(id,"tnc init",train.index,train.end_index) end) advtrains.te_register_on_update(function(id, train) @@ -523,7 +520,7 @@ advtrains.te_register_on_create(function(id, train) tnc_call_enter_callback(pos, id) end_index = end_index + 1 end - atdebug(id,"tnc create",train.index,train.end_index) + --atdebug(id,"tnc create",train.index,train.end_index) end) advtrains.te_register_on_remove(function(id, train) @@ -534,7 +531,7 @@ advtrains.te_register_on_remove(function(id, train) tnc_call_leave_callback(pos, id) end_index = end_index + 1 end - atdebug(id,"tnc remove",train.index,train.end_index) + --atdebug(id,"tnc remove",train.index,train.end_index) end) -- Calculates the indices where the window borders of the occupation windows are. @@ -570,8 +567,6 @@ local function calc_occwindows(id, train) } end ---TODO: Collisions! - --returns new id function advtrains.create_new_train_at(pos, connid, ioff, trainparts) @@ -590,7 +585,7 @@ function advtrains.create_new_train_at(pos, connid, ioff, trainparts) t.trainparts=trainparts advtrains.trains[new_id] = t - atdebug("Created new train:",t) + --atdebug("Created new train:",t) advtrains.train_ensure_init(new_id, advtrains.trains[new_id]) @@ -610,7 +605,7 @@ function advtrains.remove_train(id) advtrains.couple_invalidate(train) local tp = train.trainparts - atdebug("Removing train",id,"leftover trainparts:",tp) + --atdebug("Removing train",id,"leftover trainparts:",tp) advtrains.trains[id] = nil @@ -635,6 +630,23 @@ 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 + -- 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) local train=advtrains.trains[train_id] @@ -692,14 +704,15 @@ local ablkrng = minetest.settings:get("active_block_range")*16 function advtrains.spawn_wagons(train_id) local train = advtrains.trains[train_id] - for i, w_id in ipairs(train.trainparts) do + for i = 1, #train.trainparts do + local w_id = train.trainparts[i] local data = advtrains.wagons[w_id] if data then if data.train_id ~= train_id then atwarn("Train",train_id,"Wagon #",1,": Saved train ID",data.train_id,"did not match!") data.train_id = train_id end - if not data.object or not data.object:getyaw() then + if not advtrains.wagon_objects[w_id] or not advtrains.wagon_objects[w_id]:getyaw() then -- eventually need to spawn new object. check if position is loaded. local index = advtrains.path_get_index_by_offset(train, train.index, -data.pos_in_train) local pos = advtrains.path_get(train, atfloor(index)) @@ -717,6 +730,10 @@ function advtrains.spawn_wagons(train_id) wagon:set_id(w_id) end end + else + atwarn("Train",train_id,"Wagon #",1,": A wagon with id",w_id,"does not exist! Wagon will be removed from train.") + table.remove(train.trainparts, i) + i = i - 1 end end end @@ -745,6 +762,11 @@ function advtrains.split_train_at_wagon(wagon_id) end end + --update train parts + advtrains.update_trainpart_properties(old_id) + recalc_end_index(train) + run_callbacks_update(old_id, train) + --create subtrain local newtrain_id=advtrains.create_new_train_at(pos, connid, frac, tp) local newtrain=advtrains.trains[newtrain_id] @@ -757,11 +779,6 @@ function advtrains.split_train_at_wagon(wagon_id) newtrain.couple_lck_front=false train.couple_lck_back=false - --update train parts - advtrains.update_trainpart_properties(old_id) - recalc_end_index(train) - run_callbacks_update(old_id, train) - end -- coupling @@ -778,7 +795,7 @@ local function createcouple(pos, train1, t1_is_front, train2, t2_is_front) le.train_id_2=train2.id le.t1_is_front=t1_is_front le.t2_is_front=t2_is_front - atdebug("created couple between",train1.id,t1_is_front,train2.id,t2_is_front) + --atdebug("created couple between",train1.id,t1_is_front,train2.id,t2_is_front) if t1_is_front then train1.cpl_front = obj else @@ -793,7 +810,7 @@ local function createcouple(pos, train1, t1_is_front, train2, t2_is_front) end function advtrains.train_check_couples(train) - atdebug("rechecking couples") + --atdebug("rechecking couples") if train.cpl_front then if not train.cpl_front:getyaw() then -- objectref is no longer valid. reset. @@ -806,7 +823,7 @@ function advtrains.train_check_couples(train) for tid, idx in pairs(front_trains) do local other_train = advtrains.trains[tid] advtrains.train_ensure_init(tid, other_train) - atdebug(train.id,"front: ",idx,"on",tid,atround(other_train.index),atround(other_train.end_index)) + --atdebug(train.id,"front: ",idx,"on",tid,atround(other_train.index),atround(other_train.end_index)) if other_train.velocity == 0 then if idx>=other_train.index and idx<=other_train.index + CPL_ZONE then createcouple(pos, train, true, other_train, true) @@ -924,8 +941,12 @@ function advtrains.invert_train(train_id) advtrains.update_trainpart_properties(train_id, true) end +-- returns: train id, index of one of the trains that stand at this position. function advtrains.get_train_at_pos(pos) - return advtrains.occ.get_trains_at(pos)[1] + local t = advtrains.occ.get_trains_at(pos) + for tid,idx in pairs(t) do + return tid, idx + end end function advtrains.invalidate_all_paths(pos) diff --git a/advtrains/wagons.lua b/advtrains/wagons.lua index 9ee44b2..5a2fffb 100644 --- a/advtrains/wagons.lua +++ b/advtrains/wagons.lua @@ -9,6 +9,7 @@ advtrains.wagons = {} advtrains.wagon_prototypes = {} +advtrains.wagon_objects = {} -- function advtrains.create_wagon(wtype, owner) @@ -21,7 +22,7 @@ function advtrains.create_wagon(wtype, owner) wgn.id = new_id ---wgn.train_id = train_id --- will get this via update_trainpart_properties advtrains.wagons[new_id] = wgn - atdebug("Created new wagon:",wgn) + --atdebug("Created new wagon:",wgn) return new_id end @@ -60,9 +61,9 @@ function wagon:set_id(wid) self.initialized = true local data = advtrains.wagons[self.id] + advtrains.wagon_objects[self.id] = self.object - data.object = self.object - atdebug("Created wagon entity:",self.name," w_id",wid," t_id",data.train_id) + --atdebug("Created wagon entity:",self.name," w_id",wid," t_id",data.train_id) if self.has_inventory then --to be used later @@ -196,7 +197,7 @@ function wagon:destroy() if self.discouple then self.discouple.object:remove() end--will have no effect on unloaded objects end end - atdebug("[wagon ", self.id, "]: destroying") + --atdebug("[wagon ", self.id, "]: destroying") self.object:remove() end @@ -210,7 +211,7 @@ function wagon:on_step(dtime) local data = advtrains.wagons[self.id] if not pos then - atdebug("["..self.id.."][fatal] missing position (object:getpos() returned nil)") + --atdebug("["..self.id.."][fatal] missing position (object:getpos() returned nil)") return end @@ -437,7 +438,6 @@ function wagon:on_step(dtime) else train.recently_collided_with_env=true train.velocity=0 - -- TODO what should happen when a train collides? train.tarvelocity=0 self.collision_count=(self.collision_count or 0)+1 end @@ -852,11 +852,7 @@ function wagon:handle_bordcom_fields(pname, formname, fields) end for i, tpid in ipairs(train.trainparts) do if fields["dcpl_"..i] then - for _,wagon in pairs(minetest.luaentities) do - if wagon.is_wagon and wagon.initialized and wagon.id==tpid then - wagon:safe_decouple(pname) -- TODO: Move this into external function (don't search entity?) - end - end + advtrains.safe_decouple_wagon(tpid, pname) end if i>1 and fields["dcpl_lck_"..i] then local ent = advtrains.wagons[tpid] @@ -1026,26 +1022,10 @@ function wagon:reattach_all() end end -function wagon:safe_decouple(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[self.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", self.train_id) - advtrains.log("Discouple", pname, self.object:getpos(), self:train().text_outside) - advtrains.split_train_at_wagon(self.id)--found in trainlogic.lua - return true -end - function advtrains.get_wagon_prototype(data) local wt = data.type - if not advtrains.wagon_prototypes[wt] then - atprint("Unable to load wagon type",wt,", using placeholder") + if not data.type or not advtrains.wagon_prototypes[wt] then + atwarn("Unable to load wagon type",wt,", using placeholder") wt="advtrains:wagon_placeholder" end return wt, advtrains.wagon_prototypes[wt] -- cgit v1.2.3