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.master
parent
0c7144bcc4
commit
28717b4d65
BIN
advtrains.zip
BIN
advtrains.zip
Binary file not shown.
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,9 +900,22 @@ 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
|
||||
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
|
||||
|
@ -876,6 +931,7 @@ function advtrains.invalidate_all_paths()
|
|||
v.detector_old_index=nil
|
||||
v.detector_old_end_index=nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--not blocking trains group
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue