aboutsummaryrefslogtreecommitdiff
path: root/advtrains
diff options
context:
space:
mode:
authororwell96 <mono96.mml@gmail.com>2017-05-03 16:31:13 +0200
committerorwell96 <mono96.mml@gmail.com>2017-05-03 16:31:13 +0200
commit28717b4d65dc2e4080d5c7bde799fb4b87ef9a9d (patch)
tree81511699486ff8130ed23a43622bf73662f2be59 /advtrains
parent0c7144bcc49449eba9f6ab8f2c1d8efa72b0307a (diff)
downloadadvtrains-28717b4d65dc2e4080d5c7bde799fb4b87ef9a9d.tar.gz
advtrains-28717b4d65dc2e4080d5c7bde799fb4b87ef9a9d.tar.bz2
advtrains-28717b4d65dc2e4080d5c7bde799fb4b87ef9a9d.zip
Performance improvements: Don't clear paths unless absolutely necessary
instead delete path elements that are too far from the train one-by-one Also when switching a switch or changing rails, only clear train paths of trains that are nearby.
Diffstat (limited to 'advtrains')
-rw-r--r--advtrains/advtrains/atc.lua2
-rw-r--r--advtrains/advtrains/init.lua38
-rw-r--r--advtrains/advtrains/tracks.lua4
-rw-r--r--advtrains/advtrains/trainlogic.lua108
-rw-r--r--advtrains/advtrains_luaautomation/active_common.lua2
5 files changed, 119 insertions, 35 deletions
diff --git a/advtrains/advtrains/atc.lua b/advtrains/advtrains/atc.lua
index ed631a3..5f1f64d 100644
--- a/advtrains/advtrains/atc.lua
+++ b/advtrains/advtrains/atc.lua
@@ -93,7 +93,7 @@ advtrains.register_tracks("default", {
after_place_node=apn_func,
after_dig_node=function(pos)
return advtrains.pcall(function()
- advtrains.invalidate_all_paths()
+ advtrains.invalidate_all_paths(pos)
advtrains.ndb.clear(pos)
local pts=minetest.pos_to_string(pos)
atc.controllers[pts]=nil
diff --git a/advtrains/advtrains/init.lua b/advtrains/advtrains/init.lua
index 022fcee..3fc16ed 100644
--- a/advtrains/advtrains/init.lua
+++ b/advtrains/advtrains/init.lua
@@ -37,7 +37,7 @@ advtrains.modpath = minetest.get_modpath("advtrains")
function advtrains.print_concat_table(a)
local str=""
local stra=""
- for i=1,50 do
+ for i=1,10 do
t=a[i]
if t==nil then
stra=stra.."nil "
@@ -67,9 +67,12 @@ end
atprint=function() end
if minetest.setting_getbool("advtrains_debug") then
atprint=function(t, ...)
+ local context=advtrains.atprint_context_tid
+ if not context then context="" end
+ --if context~="4527" then return end
local text=advtrains.print_concat_table({t, ...})
- minetest.log("action", "[advtrains]"..text)
- minetest.chat_send_all("[advtrains]"..text)
+ minetest.log("action", "[advtrains]"..context..">"..text)
+ minetest.chat_send_all("[advtrains]"..context..">"..text)
end
end
atwarn=function(t, ...)
@@ -171,7 +174,8 @@ end
advtrains.avt_save = function()
--atprint("saving")
- advtrains.invalidate_all_paths()
+ --No more invalidating.
+ --Instead, remove path a.s.o from the saved table manually
-- update wagon saves
for _,wagon in pairs(minetest.luaentities) do
@@ -195,10 +199,34 @@ advtrains.avt_save = function()
end
end
+ local tmp_trains={}
+ for id, train in pairs(advtrains.trains) do
+ --first, deep_copy the train
+ local v=advtrains.merge_tables(train)
+ --then invalidate
+ if v.index then
+ v.restore_add_index=v.index-math.floor(v.index+0.5)
+ end
+ v.path=nil
+ v.path_dist=nil
+ v.index=nil
+ v.end_index=nil
+ v.min_index_on_track=nil
+ v.max_index_on_track=nil
+ v.path_extent_min=nil
+ v.path_extent_max=nil
+
+ v.detector_old_index=nil
+ v.detector_old_end_index=nil
+
+ --then save it
+ tmp_trains[id]=v
+ end
+
--versions:
-- 1 - Initial new save format.
local save_tbl={
- trains = advtrains.trains,
+ trains = tmp_trains,
wagon_save = advtrains.wagon_save,
ptmap = advtrains.player_to_train_mapping,
atc = advtrains.atc.save_data(),
diff --git a/advtrains/advtrains/tracks.lua b/advtrains/advtrains/tracks.lua
index 86c87ba..b390c6a 100644
--- a/advtrains/advtrains/tracks.lua
+++ b/advtrains/advtrains/tracks.lua
@@ -263,13 +263,13 @@ function advtrains.register_tracks(tracktype, def, preset)
local rcswitchfunc=function(pos, node, player)
if minetest.check_player_privs(player:get_player_name(), {train_operator=true}) then
advtrains.ndb.swap_node(pos, {name=def.nodename_prefix.."_"..suffix_target, param2=node.param2})
- advtrains.invalidate_all_paths()
+ advtrains.invalidate_all_paths(pos)
end
end
local switchfunc=function(pos, node, newstate)
if newstate~=is_state then
advtrains.ndb.swap_node(pos, {name=def.nodename_prefix.."_"..suffix_target, param2=node.param2})
- advtrains.invalidate_all_paths()
+ advtrains.invalidate_all_paths(pos)
end
end
local mesec
diff --git a/advtrains/advtrains/trainlogic.lua b/advtrains/advtrains/trainlogic.lua
index 7dad80c..e62c864 100644
--- a/advtrains/advtrains/trainlogic.lua
+++ b/advtrains/advtrains/trainlogic.lua
@@ -55,12 +55,16 @@ advtrains.mainloop_trainlogic=function(dtime)
local t=os.clock()
advtrains.detector.on_node={}
for k,v in pairs(advtrains.trains) do
+ advtrains.atprint_context_tid=sid(k)
advtrains.train_step_a(k, v, dtime)
end
for k,v in pairs(advtrains.trains) do
+ advtrains.atprint_context_tid=sid(k)
advtrains.train_step_b(k, v, dtime)
end
+ advtrains.atprint_context_tid=nil
+
atprintbm("trainsteps", t)
endstep()
end
@@ -140,7 +144,7 @@ function advtrains.train_step_a(id, train, dtime)
end
--- 2. prepare initial path and index if needed ---
if not train.index then train.index=0 end
- if not train.path or #train.path<2 then
+ if not train.path then
if not train.last_pos then
--no chance to recover
atprint("train hasn't saved last-pos, removing train.")
@@ -224,36 +228,43 @@ function advtrains.train_step_a(id, train, dtime)
train.tarvelocity=0
end
+ --- 3a. this can be useful for debugs/warnings and is used for check_trainpartload ---
+ local t_info, train_pos=sid(id), train.path[math.floor(train.index)]
+ if train_pos then
+ t_info=t_info.." @"..minetest.pos_to_string(train_pos)
+ end
+
--apply off-track handling:
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
- atwarn("Train",sid(id)," is off track at both ends. Clipping velocity to 1")
+ atwarn("Train",t_info,"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
- atwarn("Train",sid(id)," is off track. Trying to drive further out. Velocity clipped to 0")
+ atwarn("Train",t_info,"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")
+ atwarn("Train",t_info,"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
- atwarn("Train",sid(id)," is off track. Trying to drive further out. Velocity clipped to 0")
+ atwarn("Train",t_info,"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")
+ atwarn("Train",t_info,"is off track. Velocity clipped to 1")
pprint=true
end
end
@@ -322,7 +333,7 @@ function advtrains.train_step_a(id, train, dtime)
--why this is an extra function, see under 3.
advtrains.pathpredict(id, train, true)
- --make pos/yaw available for possible recover calls
+ --- 5a. 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
train.savedpos_off_track_index_offset=train.index-train.max_index_on_track
train.last_pos=train.path[train.max_index_on_track]
@@ -339,6 +350,36 @@ function advtrains.train_step_a(id, train, dtime)
train.last_pos_prev=train.path[math.floor(train.index-0.5)]
end
+ --- 5b. Remove path items that are no longer used ---
+ -- Necessary since path items are no longer invalidated in save steps
+ local path_pregen_keep=20
+ local offtrack_keep=4
+ local gen_front_keep= path_pregen_keep
+ local gen_back_keep= - train.trainlen - path_pregen_keep
+
+ local delete_min=math.min(train.max_index_on_track - offtrack_keep, math.floor(train.index)+gen_back_keep)
+ local delete_max=math.max(train.min_index_on_track + offtrack_keep, math.floor(train.index)+gen_front_keep)
+
+ if train.path_extent_min<delete_min then
+ atprint(sid(id),"clearing path min ",train.path_extent_min," to ",delete_min)
+ for i=train.path_extent_min,delete_min-1 do
+ train.path[i]=nil
+ train.path_dist[i]=nil
+ end
+ train.path_extent_min=delete_min
+ train.min_index_on_track=math.max(train.min_index_on_track, delete_min)
+ end
+ if train.path_extent_max>delete_max then
+ atprint(sid(id),"clearing path max ",train.path_extent_max," to ",delete_max)
+ train.path_dist[delete_max]=nil
+ for i=delete_max+1,train.path_extent_max do
+ train.path[i]=nil
+ train.path_dist[i]=nil
+ end
+ train.path_extent_max=delete_max
+ train.max_index_on_track=math.min(train.max_index_on_track, delete_max)
+ end
+
--- 6. update node coverage ---
-- 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
@@ -406,7 +447,7 @@ function advtrains.train_step_a(id, train, dtime)
train.check_trainpartload=(train.check_trainpartload or 0)-dtime
local node_range=(math.max((minetest.setting_get("active_block_range") or 0),1)*16)
if train.check_trainpartload<=0 then
- local ori_pos=advtrains.get_real_index_position(path, train.index) --not much to calculate
+ local ori_pos=train_pos --see 3a.
--atprint("[train "..id.."] at "..minetest.pos_to_string(vector.round(ori_pos)))
local should_check=false
@@ -429,6 +470,7 @@ 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)
+ --TODO duplicate code under 5b.
local path_pregen=10
local gen_front= path_pregen
@@ -440,7 +482,7 @@ function advtrains.pathpredict(id, train, regular)
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]))
+ atprint("maxn conway for ",maxn,minetest.pos_to_string(train.path[maxn]),maxn-1,minetest.pos_to_string(train.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
@@ -458,7 +500,7 @@ function advtrains.pathpredict(id, train, regular)
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]))
+ atprint("minn conway for ",minn,minetest.pos_to_string(train.path[minn]),minn+1,minetest.pos_to_string(train.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
@@ -858,23 +900,37 @@ function advtrains.get_train_at_pos(pos)
return advtrains.detector.on_node[ph]
end
-function advtrains.invalidate_all_paths()
- --atprint("invalidating all paths")
+function advtrains.invalidate_all_paths(pos)
+ --if a position is given, only invalidate inside a radius to save performance
+ local inv_radius=50
+ atprint("invalidating all paths")
for k,v in pairs(advtrains.trains) do
- if v.index then
- v.restore_add_index=v.index-math.floor(v.index+0.5)
- end
- v.path=nil
- v.path_dist=nil
- v.index=nil
- v.end_index=nil
- v.min_index_on_track=nil
- v.max_index_on_track=nil
- v.path_extent_min=nil
- v.path_extent_max=nil
-
- v.detector_old_index=nil
- v.detector_old_end_index=nil
+ local exec=true
+ if pos and v.path and v.index and v.end_index then
+ --start and end pos of the train
+ local cmp1=v.path[math.floor(v.index)]
+ local cmp2=v.path[math.floor(v.end_index)]
+ if vector.distance(pos, cmp1)>inv_radius and vector.distance(pos, cmp2)>inv_radius then
+ exec=false
+ end
+ end
+ if exec then
+ --TODO duplicate code in init.lua avt_save()!
+ if v.index then
+ v.restore_add_index=v.index-math.floor(v.index+0.5)
+ end
+ v.path=nil
+ v.path_dist=nil
+ v.index=nil
+ v.end_index=nil
+ v.min_index_on_track=nil
+ v.max_index_on_track=nil
+ v.path_extent_min=nil
+ v.path_extent_max=nil
+
+ v.detector_old_index=nil
+ v.detector_old_end_index=nil
+ end
end
end
diff --git a/advtrains/advtrains_luaautomation/active_common.lua b/advtrains/advtrains_luaautomation/active_common.lua
index e17af91..8c910c6 100644
--- a/advtrains/advtrains_luaautomation/active_common.lua
+++ b/advtrains/advtrains_luaautomation/active_common.lua
@@ -49,7 +49,7 @@ function ac.getform(pos, meta_p)
end
function ac.after_dig_node(pos, node, player)
- advtrains.invalidate_all_paths()
+ advtrains.invalidate_all_paths(pos)
advtrains.ndb.clear(pos)
local ph=minetest.pos_to_string(pos)
ac.nodes[ph]=nil