aboutsummaryrefslogtreecommitdiff
path: root/advtrains
diff options
context:
space:
mode:
Diffstat (limited to 'advtrains')
-rw-r--r--advtrains/advtrains/atc.lua8
-rw-r--r--advtrains/advtrains/trackplacer.lua4
-rw-r--r--advtrains/advtrains/tracks.lua3
-rw-r--r--advtrains/advtrains/trainlogic.lua203
-rw-r--r--advtrains/advtrains/wagons.lua4
-rw-r--r--advtrains/advtrains_itrainmap/init.lua13
-rw-r--r--advtrains/advtrains_luaautomation/active_common.lua2
-rw-r--r--advtrains/advtrains_luaautomation/atc_rail.lua2
-rw-r--r--advtrains/advtrains_luaautomation/environment.lua40
-rw-r--r--advtrains/advtrains_luaautomation/interrupt.lua2
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)