diff options
Diffstat (limited to 'advtrains')
-rw-r--r-- | advtrains/advtrains/atc.lua | 8 | ||||
-rw-r--r-- | advtrains/advtrains/trackplacer.lua | 4 | ||||
-rw-r--r-- | advtrains/advtrains/tracks.lua | 3 | ||||
-rw-r--r-- | advtrains/advtrains/trainlogic.lua | 203 | ||||
-rw-r--r-- | advtrains/advtrains/wagons.lua | 4 | ||||
-rw-r--r-- | advtrains/advtrains_itrainmap/init.lua | 13 | ||||
-rw-r--r-- | advtrains/advtrains_luaautomation/active_common.lua | 2 | ||||
-rw-r--r-- | advtrains/advtrains_luaautomation/atc_rail.lua | 2 | ||||
-rw-r--r-- | advtrains/advtrains_luaautomation/environment.lua | 40 | ||||
-rw-r--r-- | advtrains/advtrains_luaautomation/interrupt.lua | 2 |
10 files changed, 166 insertions, 115 deletions
diff --git a/advtrains/advtrains/atc.lua b/advtrains/advtrains/atc.lua index bf94ba5..5a8e76b 100644 --- a/advtrains/advtrains/atc.lua +++ b/advtrains/advtrains/atc.lua @@ -21,11 +21,11 @@ end --general -function atc.send_command(pos) +function atc.send_command(pos, par_tid) local pts=minetest.pos_to_string(pos) if atc.controllers[pts] then --atprint("Called send_command at "..pts) - local train_id = advtrains.detector.on_node[pts] + local train_id = par_tid or advtrains.detector.on_node[pts] if train_id then if advtrains.trains[train_id] then --atprint("send_command inside if: "..sid(train_id)) @@ -131,7 +131,9 @@ advtrains.register_tracks("default", { local pts=minetest.pos_to_string(pos) local _, conn1=advtrains.get_rail_info_at(pos, advtrains.all_tracktypes) atc.controllers[pts]={command=fields.command, arrowconn=conn1} - atc.send_command(pos) + if advtrains.detector.on_node[pts] then + atc.send_command(pos) + end end end, advtrains = { diff --git a/advtrains/advtrains/trackplacer.lua b/advtrains/advtrains/trackplacer.lua index e5e3340..9fee011 100644 --- a/advtrains/advtrains/trackplacer.lua +++ b/advtrains/advtrains/trackplacer.lua @@ -256,7 +256,6 @@ minetest.register_craftitem("advtrains:trackworker",{ end advtrains.ndb.swap_node(pos, {name=nnprefix.."_"..suffix..modext[modpos+1], param2=node.param2}) end - advtrains.invalidate_all_paths() end end, on_use=function(itemstack, user, pointed_thing) @@ -285,8 +284,7 @@ minetest.register_craftitem("advtrains:trackworker",{ end local nextsuffix=tp.tracks[nnprefix].twcycle[suffix] advtrains.ndb.swap_node(pos, {name=nnprefix.."_"..nextsuffix..rotation, param2=node.param2}) - --invalidate trains - advtrains.invalidate_all_paths() + else atprint(name, dump(tp.tracks)) end diff --git a/advtrains/advtrains/tracks.lua b/advtrains/advtrains/tracks.lua index 63c4f16..a645017 100644 --- a/advtrains/advtrains/tracks.lua +++ b/advtrains/advtrains/tracks.lua @@ -321,7 +321,6 @@ function advtrains.register_tracks(tracktype, def, preset) return not advtrains.get_train_at_pos(pos)
end,
after_dig_node=function(pos)
- advtrains.invalidate_all_paths()
advtrains.ndb.update(pos)
end,
after_place_node=function(pos)
@@ -419,8 +418,6 @@ function advtrains.detector.enter_node(pos, train_id) end
function advtrains.detector.leave_node(pos, train_id)
local ppos=advtrains.round_vector_floor_y(pos)
- local pts=minetest.pos_to_string(ppos)
- advtrains.detector.on_node[pts]=nil
advtrains.detector.call_leave_callback(ppos, train_id)
end
function advtrains.detector.stay_node(pos, train_id)
diff --git a/advtrains/advtrains/trainlogic.lua b/advtrains/advtrains/trainlogic.lua index 4b5edf5..5fafb89 100644 --- a/advtrains/advtrains/trainlogic.lua +++ b/advtrains/advtrains/trainlogic.lua @@ -159,6 +159,15 @@ function advtrains.train_step_a(id, train, dtime) train.path_dist[-1]=vector.distance(train.last_pos, train.last_pos_prev) train.path_extent_min=-1 train.path_extent_max=0 + --[[ + Bugfix for trains randomly ignoring ATC rails: + - Paths have been invalidated. 1 gets executed and ensures an initial path + - 2a sets train end index. The problem is that path_dist is not known for the whole path, so train end index will be nearly trainlen + - Since the detector indices are also unknown, they get set to the new (wrong) train_end_index. Enter_node calls are not executed for the nodes that lie in between real end_index and trainlen. + - The next step, mistake is recognized, train leaves some positions. From there, everything works again. + To overcome this, we will generate the full required path here so that path_dist is available for get_train_end_index(). + ]] + advtrains.pathpredict(id, train) end --- 2a. set train.end_index which is required in different places, IF IT IS NOT SET YET by STMT afterwards. --- @@ -186,17 +195,40 @@ function advtrains.train_step_a(id, train, dtime) end --apply off-track handling: - --won't take any effect immediately after path reset because index_on_track not set, but that's not severe. local front_off_track=train.max_index_on_track and train.index>train.max_index_on_track local back_off_track=train.min_index_on_track and train.end_index<train.min_index_on_track + local pprint if front_off_track and back_off_track then--allow movement in both directions - if train.tarvelocity>1 then train.tarvelocity=1 end + if train.tarvelocity>1 then + train.tarvelocity=1 + atwarn("Train",sid(id)," is off track at both ends. Clipping velocity to 1") + pprint=true + end elseif front_off_track then--allow movement only backward - if train.movedir==1 and train.tarvelocity>0 then train.tarvelocity=0 end - if train.movedir==-1 and train.tarvelocity>1 then train.tarvelocity=1 end + if train.movedir==1 and train.tarvelocity>0 then + train.tarvelocity=0 + atwarn("Train",sid(id)," is off track. Trying to drive further out. Velocity clipped to 0") + pprint=true + end + if train.movedir==-1 and train.tarvelocity>1 then + train.tarvelocity=1 + atwarn("Train",sid(id)," is off track. Velocity clipped to 1") + pprint=true + end elseif back_off_track then--allow movement only forward - if train.movedir==-1 and train.tarvelocity>0 then train.tarvelocity=0 end - if train.movedir==1 and train.tarvelocity>1 then train.tarvelocity=1 end + if train.movedir==-1 and train.tarvelocity>0 then + train.tarvelocity=0 + atwarn("Train",sid(id)," is off track. Trying to drive further out. Velocity clipped to 0") + pprint=true + end + if train.movedir==1 and train.tarvelocity>1 then + train.tarvelocity=1 + atwarn("Train",sid(id)," is off track. Velocity clipped to 1") + pprint=true + end + end + if pprint then + atprint("max_iot", train.max_index_on_track, "min_iot", train.min_index_on_track, "<> index", train.index, "end_index", train.end_index) end --interpret ATC command @@ -257,47 +289,8 @@ function advtrains.train_step_a(id, train, dtime) train.end_index=advtrains.get_train_end_index(train) --- 5. extend path as necessary --- - - local gen_front=math.max(train.index, train.detector_old_index) + 10 - local gen_back=math.min(train.end_index, train.detector_old_end_index) - 10 - - local maxn=train.path_extent_max or 0 - while maxn < gen_front do--pregenerate - --atprint("maxn conway for ",maxn,minetest.pos_to_string(path[maxn]),maxn-1,minetest.pos_to_string(path[maxn-1])) - local conway=advtrains.conway(train.path[maxn], train.path[maxn-1], train.drives_on) - if conway then - train.path[maxn+1]=conway - train.max_index_on_track=maxn - 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 "..minetest.pos_to_string(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=advtrains.maxN(train.path) - end - train.path_extent_max=maxn - - local minn=train.path_extent_min or -1 - while minn > gen_back do - --atprint("minn conway for ",minn,minetest.pos_to_string(path[minn]),minn+1,minetest.pos_to_string(path[minn+1])) - local conway=advtrains.conway(train.path[minn], train.path[minn+1], train.drives_on) - if conway then - train.path[minn-1]=conway - train.min_index_on_track=minn - 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 "..minetest.pos_to_string(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=advtrains.minN(train.path) - 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 + --why this is an extra function, see under 3. + advtrains.pathpredict(id, train, true) --make pos/yaw available for possible recover calls if train.max_index_on_track<train.index then --whoops, train went too far. the saved position will be the last one that lies on a track, and savedpos_off_track_index_offset will hold how far to go from here @@ -320,37 +313,49 @@ function advtrains.train_step_a(id, train, dtime) -- when paths get cleared, the old indices set above will be up-to-date and represent the state in which the last run of this code was made local ifo, ifn, ibo, ibn = train.detector_old_index, math.floor(train.index), train.detector_old_end_index, math.floor(train.end_index) - local path=train.path - for i=ibn, ifn do - if path[i] then - advtrains.detector.stay_node(path[i], id) - end - end + local path=train.path - if ifn>ifo then - for i=ifo+1, ifn do + if train.enter_node_all then + --field set by create_new_train_at. + --ensures that new train calls enter_node on all nodes + for i=ibn, ifn do if path[i] then advtrains.detector.enter_node(path[i], id) end end - elseif ifn<ifo then - for i=ifn, ifo-1 do + train.enter_node_all=nil + else + for i=ibn, ifn do if path[i] then - advtrains.detector.leave_node(path[i], id) + advtrains.detector.stay_node(path[i], id) end end - end - if ibn<ibo then - for i=ibn, ibo-1 do - if path[i] then - advtrains.detector.enter_node(path[i], id) + + if ifn>ifo then + for i=ifo+1, ifn do + if path[i] then + advtrains.detector.enter_node(path[i], id) + end + end + elseif ifn<ifo then + for i=ifn+1, ifo do + if path[i] then + advtrains.detector.leave_node(path[i], id) + end end end - elseif ibn>ibo then - for i=ibo+1, ibn do - if path[i] then - advtrains.detector.leave_node(path[i], id) + if ibn<ibo then + for i=ibn, ibo-1 do + if path[i] then + advtrains.detector.enter_node(path[i], id) + end + end + elseif ibn>ibo then + for i=ibo, ibn-1 do + if path[i] then + advtrains.detector.leave_node(path[i], id) + end end end end @@ -382,6 +387,57 @@ function advtrains.train_step_a(id, train, dtime) end end +--about regular: Used by 1. to ensure path gets generated far enough, since end index is not known at this time. +function advtrains.pathpredict(id, train, regular) + local path_pregen=10 + + local gen_front= path_pregen + local gen_back= - train.trainlen - path_pregen + if regular then + gen_front=math.max(train.index, train.detector_old_index) + path_pregen + gen_back=math.min(train.end_index, train.detector_old_end_index) - path_pregen + end + + local maxn=train.path_extent_max or 0 + while maxn < gen_front do--pregenerate + --atprint("maxn conway for ",maxn,minetest.pos_to_string(path[maxn]),maxn-1,minetest.pos_to_string(path[maxn-1])) + local conway=advtrains.conway(train.path[maxn], train.path[maxn-1], train.drives_on) + if conway then + train.path[maxn+1]=conway + train.max_index_on_track=maxn + 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 "..minetest.pos_to_string(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 + --atprint("minn conway for ",minn,minetest.pos_to_string(path[minn]),minn+1,minetest.pos_to_string(path[minn+1])) + local conway=advtrains.conway(train.path[minn], train.path[minn+1], train.drives_on) + if conway then + train.path[minn-1]=conway + train.min_index_on_track=minn + 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 "..minetest.pos_to_string(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 + + function advtrains.train_step_b(id, train, dtime) --- 8. check for collisions with other trains --- @@ -463,6 +519,9 @@ function advtrains.create_new_train_at(pos, pos_prev) advtrains.trains[newtrain_id].tarvelocity=0 advtrains.trains[newtrain_id].velocity=0 advtrains.trains[newtrain_id].trainparts={} + + advtrains.trains[newtrain_id].enter_node_all=true + return newtrain_id end @@ -600,6 +659,7 @@ function advtrains.split_train_at_wagon(wagon) train.tarvelocity=0 newtrain.velocity=train.velocity newtrain.tarvelocity=0 + newtrain.enter_node_all=true end --there are 4 cases: @@ -739,12 +799,19 @@ function advtrains.invert_train(train_id) local train=advtrains.trains[train_id] local old_path=train.path + local old_path_dist=train.path_dist train.path={} - train.index= - advtrains.get_train_end_index(train) + train.path_dist={} + train.index, train.end_index= -train.end_index, -train.index + train.path_extent_min, train.path_extent_max = -train.path_extent_max, -train.path_extent_min + train.min_index_on_track, train.max_index_on_track = -train.max_index_on_track, -train.min_index_on_track + train.detector_old_index, train.detector_old_end_index = -train.detector_old_end_index, -train.detector_old_index + train.velocity=-train.velocity train.tarvelocity=-train.tarvelocity for k,v in pairs(old_path) do train.path[-k]=v + train.path_dist[-k-1]=old_path_dist[k] end local old_trainparts=train.trainparts train.trainparts={} diff --git a/advtrains/advtrains/wagons.lua b/advtrains/advtrains/wagons.lua index 0109b19..3efa6b8 100644 --- a/advtrains/advtrains/wagons.lua +++ b/advtrains/advtrains/wagons.lua @@ -674,7 +674,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) wagon.seat_access[sgr] = fcont~="" and fcont or nil
end
end
- wagon.lock_couples = fields.lock_couples == "true"
+ if fields.lock_couples then
+ wagon.lock_couples = fields.lock_couples == "true"
+ end
end
end
end
diff --git a/advtrains/advtrains_itrainmap/init.lua b/advtrains/advtrains_itrainmap/init.lua index 02dbc9e..96e30c5 100644 --- a/advtrains/advtrains_itrainmap/init.lua +++ b/advtrains/advtrains_itrainmap/init.lua @@ -72,12 +72,15 @@ end local function cache_ndb() itm_cache={} local ndb_nodes=advtrains.ndb.get_nodes() - for phs,_ in pairs(ndb_nodes) do - local pos=minetest.get_position_from_hash(phs) - if not itm_cache[pos.x] then - itm_cache[pos.x]={} + for y, xzt in pairs(ndb_nodes) do + for x, zt in pairs(xzt) do + for z, _ in pairs(zt) do + if not itm_cache[x] then + itm_cache[x]={} + end + itm_cache[x][z]=y + end end - itm_cache[pos.x][pos.z]=pos.y end end diff --git a/advtrains/advtrains_luaautomation/active_common.lua b/advtrains/advtrains_luaautomation/active_common.lua index 0351c85..0b13a51 100644 --- a/advtrains/advtrains_luaautomation/active_common.lua +++ b/advtrains/advtrains_luaautomation/active_common.lua @@ -96,7 +96,7 @@ function ac.run_in_env(pos, evtdata, customfct_p) end local meta - if minetest.get_node(pos) then + if minetest.get_node_or_nil(pos) then meta=minetest.get_meta(pos) end diff --git a/advtrains/advtrains_luaautomation/atc_rail.lua b/advtrains/advtrains_luaautomation/atc_rail.lua index c2c8d6f..09c560f 100644 --- a/advtrains/advtrains_luaautomation/atc_rail.lua +++ b/advtrains/advtrains_luaautomation/atc_rail.lua @@ -42,8 +42,8 @@ function r.fire_event(pos, evtdata) if atc_arrow==nil then atwarn("LuaAutomation ATC rail at", pos, ": Rail not on train's path! Can't determine arrow direction. Assuming +!") atc_arrow=true - tvel=train.velocity end + tvel=train.velocity end local customfct={ atc_send = function(cmd) diff --git a/advtrains/advtrains_luaautomation/environment.lua b/advtrains/advtrains_luaautomation/environment.lua index 8dfdd39..ec1f7cb 100644 --- a/advtrains/advtrains_luaautomation/environment.lua +++ b/advtrains/advtrains_luaautomation/environment.lua @@ -25,28 +25,6 @@ function atlatc.remove_invalid_data(o, nested) nested[o] = nil return o end -function atlatc.replace_function_envs(o, fenv, nested) - if o==nil then return nil end - local valid_dt={["nil"]=true, boolean=true, number=true, string=true} - if type(o) ~= "table" then - --check valid data type - if type(o)=="function" then - setfenv(o, fenv) - end - return o - end - -- Contains table -> true/nil of currently nested tables - nested = nested or {} - if nested[o] then - return nil - end - nested[o] = true - for k, v in pairs(o) do - v = atlatc.replace_function_envs(v, fenv, nested) - end - nested[o] = nil - return o -end local env_proto={ @@ -195,8 +173,11 @@ end -- F - Table global to the environment, can contain volatile data that is deleted when server quits. -- The init code should populate this table with functions and other definitions. +local proxy_env={} +--proxy_env gets a new metatable in every run, but is the shared environment of all functions ever defined. + -- returns: true, fenv if successful; nil, error if error -function env_proto:execute_code(fenv, code, evtdata, customfct) +function env_proto:execute_code(localenv, code, evtdata, customfct) local metatbl ={ __index = function(t, i) if i=="S" then @@ -207,6 +188,8 @@ function env_proto:execute_code(fenv, code, evtdata, customfct) return evtdata elseif customfct and customfct[i] then return customfct[i] + elseif localenv and localenv[i] then + return localenv[i] end return static_env[i] end, @@ -215,21 +198,19 @@ function env_proto:execute_code(fenv, code, evtdata, customfct) debug.sethook() error("Trying to overwrite environment contents") end - rawset(t,i,v) + localenv[i]=v end, } - setmetatable(fenv, metatbl) + setmetatable(proxy_env, metatbl) local fun, err=loadstring(code) if not fun then return false, err end - --set function environment for all functions residing in F, so they get the right variables. Else it's a huge mess... - atlatc.replace_function_envs(self.fdata, fenv) - setfenv(fun, fenv) + setfenv(fun, proxy_env) local succ, data = pcall(fun) if succ then - data=fenv + data=localenv end return succ, data end @@ -240,6 +221,7 @@ function env_proto:run_initcode() atprint("[atlatc]Running initialization code for environment '"..self.name.."'") local succ, err = self:execute_code({}, self.init_code, {type="init", init=true}) if not succ then + atwarn("[atlatc]Executing InitCode for '"..self.name.."' failed:"..err) self.init_err=err end end diff --git a/advtrains/advtrains_luaautomation/interrupt.lua b/advtrains/advtrains_luaautomation/interrupt.lua index e9ad443..4d59db5 100644 --- a/advtrains/advtrains_luaautomation/interrupt.lua +++ b/advtrains/advtrains_luaautomation/interrupt.lua @@ -13,7 +13,7 @@ function iq.load(data) timer = d.timer or 0 end function iq.save() - return {queue = queue} + return {queue = queue, timer=timer} end function iq.add(t, pos, evtdata) |