diff options
| -rw-r--r-- | advtrains/couple.lua | 36 | ||||
| -rw-r--r-- | advtrains/init.lua | 2 | ||||
| -rw-r--r-- | advtrains/trainlogic.lua | 148 | 
3 files changed, 100 insertions, 86 deletions
| diff --git a/advtrains/couple.lua b/advtrains/couple.lua index 7bab241..6741de8 100644 --- a/advtrains/couple.lua +++ b/advtrains/couple.lua @@ -154,27 +154,33 @@ minetest.register_entity("advtrains:couple", {  				return  			end -			local tp1 -			if not self.train1_is_backpos then -				tp1=advtrains.get_real_index_position(train1.path, train1.index) -			else -				tp1=advtrains.get_real_index_position(train1.path, train1.end_index) -			end -			local tp2 -			if not self.train2_is_backpos then -				tp2=advtrains.get_real_index_position(train2.path, train2.index) -			else -				tp2=advtrains.get_real_index_position(train2.path, train2.end_index) -			end -			if not tp1 or not tp2 or not (vector.distance(tp1,tp2)<couple_max_dist) then -				atprint("Couple: train end positions too distanced, destroying (distance is",vector.distance(tp1,tp2),")") +			if train1.velocity>0 or train2.velocity>0 then +				if not self.position_set then --ensures that train stands a single time before check fires. Using flag below +					return +				end +				atprint("Couple: train is moving, destroying")  				self.object:remove()  				return -			else +			end +			 +			if not self.position_set then +				local tp1 +				if not self.train1_is_backpos then +					tp1=advtrains.get_real_index_position(train1.path, train1.index) +				else +					tp1=advtrains.get_real_index_position(train1.path, train1.end_index) +				end +				local tp2 +				if not self.train2_is_backpos then +					tp2=advtrains.get_real_index_position(train2.path, train2.index) +				else +					tp2=advtrains.get_real_index_position(train2.path, train2.end_index) +				end  				local pos_median=advtrains.pos_median(tp1, tp2)  				if not vector.equals(pos_median, self.object:getpos()) then  					self.object:setpos(pos_median)  				end +				self.position_set=true  			end  			atprintbm("couple step", t)  			advtrains.atprint_context_tid=nil diff --git a/advtrains/init.lua b/advtrains/init.lua index 6255780..6f81a40 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -105,6 +105,8 @@ if minetest.settings:get_bool("advtrains_enable_debugging") then  		if not context then return end  		local text=advtrains.print_concat_table({t, ...})  		advtrains.drb_record(context, text) +		 +		--atlog("@@",advtrains.atprint_context_tid,t,...)  	end  	atdebug=function(t, ...)  		local text=advtrains.print_concat_table({t, ...}) diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua index d8130e9..6a0e61a 100644 --- a/advtrains/trainlogic.lua +++ b/advtrains/trainlogic.lua @@ -125,10 +125,11 @@ train step structure:  	- environment collision  - update index = move  - create path -- update node coverage +- call stay_node on all old positions to register train there, for collision system  - do less important stuff such as checking trainpartload or removing  -- break -- +- Call enter_node and leave_node callbacks (required here because stay_node needs to be called on all trains first)  - handle train collisions  ]] @@ -154,7 +155,7 @@ function advtrains.train_step_a(id, train, dtime)  	if not train.path then  		if not train.last_pos then  			--no chance to recover -			atprint("train hasn't saved last-pos, removing train.") +			atwarn("Unable to restore train ",id,": missing last_pos")  			advtrains.trains[id]=nil  			return false  		end @@ -166,14 +167,14 @@ function advtrains.train_step_a(id, train, dtime)  			atprint("last_pos", advtrains.round_vector_floor_y(train.last_pos), "not loaded and not in ndb, waiting")  			return nil  		elseif node_ok==false then -			atprint("no track here, (fail) removing train.") +			atwarn("Unable to restore train ",id,": No rail at train's position")  			advtrains.trains[id]=nil  			return false  		end  		if not train.last_pos_prev then  			--no chance to recover -			atprint("train hasn't saved last-pos_prev, removing train.") +			atwarn("Unable to restore train ",id,": missing last_pos_prev")  			advtrains.trains[id]=nil  			return false  		end @@ -185,7 +186,7 @@ function advtrains.train_step_a(id, train, dtime)  			atprint("last_pos_prev", advtrains.round_vector_floor_y(train.last_pos_prev), "not loaded and not in ndb, waiting")  			return nil  		elseif prevnode_ok==false then -			atprint("no track at prev, (fail) removing train.") +			atwarn("Unable to restore train ",id,": No rail at train's position")  			advtrains.trains[id]=nil  			return false  		end @@ -372,7 +373,7 @@ function advtrains.train_step_a(id, train, dtime)  	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) +		--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 @@ -381,7 +382,7 @@ function advtrains.train_step_a(id, train, dtime)  		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) +		--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 @@ -391,70 +392,16 @@ function advtrains.train_step_a(id, train, dtime)  		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 -	local ifo, ifn, ibo, ibn = train.detector_old_index, math.floor(train.index), train.detector_old_end_index, math.floor(train.end_index) +	--- 6b. call stay_node to register trains in the location table - actual enter_node stuff is done in step b --- +	local ifn, ibn = math.floor(train.index), math.floor(train.end_index)  	local path=train.path -	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 -		train.enter_node_all=nil -	else -		for i=ibn, ifn do -			if path[i] then -				local pts=minetest.pos_to_string(path[i]) -				if not (advtrains.detector.on_node[pts] and advtrains.detector.on_node[pts]~=id) then -					advtrains.detector.stay_node(path[i], id) -				end -			end -		end -		 -		if ifn>ifo then -			for i=ifo+1, ifn do -				if path[i] then -					local pts=minetest.pos_to_string(path[i]) -					if advtrains.detector.on_node[pts] and advtrains.detector.on_node[pts]~=id then -						--if another train has signed up for this position first, it won't be recognized in train_step_b. So do collision here. -						atprint("Collision detected in enter_node callbacks (front) @",pts,"with",sid(advtrains.detector.on_node[pts])) -						advtrains.collide_and_spawn_couple(id, path[i], advtrains.detector.on_node[pts], false) -					end -					atprint("enter_node (front) @index",i,"@",pts,"on_node",sid(advtrains.detector.on_node[pts])) -					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 -		if ibn<ibo then -			for i=ibn, ibo-1 do -				if path[i] then -					local pts=minetest.pos_to_string(path[i]) -					if advtrains.detector.on_node[pts] and advtrains.detector.on_node[pts]~=id then -						--if another train has signed up for this position first, it won't be recognized in train_step_b. So do collision here. -						atprint("Collision detected in enter_node callbacks (back) @",pts,"on_node",sid(advtrains.detector.on_node[pts])) -						advtrains.collide_and_spawn_couple(id, path[i], advtrains.detector.on_node[pts], true) -					end -					atprint("enter_node (back) @index",i,"@",pts,"with",sid(advtrains.detector.on_node[pts])) -					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 +	for i=ibn, ifn do +		if path[i] then +			local pts=minetest.pos_to_string(path[i]) +			if not (advtrains.detector.on_node[pts] and advtrains.detector.on_node[pts]~=id) then +				advtrains.detector.stay_node(path[i], id)  			end  		end  	end @@ -502,7 +449,7 @@ function advtrains.pathpredict(id, train, regular)  	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]) +			--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 @@ -523,7 +470,7 @@ function advtrains.pathpredict(id, train, regular)  	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]) +			--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 @@ -551,6 +498,65 @@ function advtrains.train_step_b(id, train, dtime)  	if not train.end_index then  		return  	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 +	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 +	 +	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 +		train.enter_node_all=nil +	else +		if ifn>ifo then +			for i=ifo+1, ifn do +				if path[i] then +					local pts=minetest.pos_to_string(path[i]) +					if advtrains.detector.on_node[pts] and advtrains.detector.on_node[pts]~=id then +						--if another train has signed up for this position first, it won't be recognized in train_step_b. So do collision here. +						atprint("Collision detected in enter_node callbacks (front) @",pts,"with",sid(advtrains.detector.on_node[pts])) +						advtrains.collide_and_spawn_couple(id, path[i], advtrains.detector.on_node[pts], false) +					end +					atprint("enter_node (front) @index",i,"@",pts,"on_node",sid(advtrains.detector.on_node[pts])) +					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 +		if ibn<ibo then +			for i=ibn, ibo-1 do +				if path[i] then +					local pts=minetest.pos_to_string(path[i]) +					if advtrains.detector.on_node[pts] and advtrains.detector.on_node[pts]~=id then +						--if another train has signed up for this position first, it won't be recognized in train_step_b. So do collision here. +						atprint("Collision detected in enter_node callbacks (back) @",pts,"on_node",sid(advtrains.detector.on_node[pts])) +						advtrains.collide_and_spawn_couple(id, path[i], advtrains.detector.on_node[pts], true) +					end +					atprint("enter_node (back) @index",i,"@",pts,"with",sid(advtrains.detector.on_node[pts])) +					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  	--- 8. check for collisions with other trains and damage players --- @@ -695,7 +701,7 @@ function advtrains.update_trainpart_properties(train_id, invert_flipstate)  			end  		else -			atprint(w_id.." not loaded and no save available") +			atwarn("Did not find save data for wagon",w_id,". The wagon will be deleted.")  			--what the hell...  			table.remove(train.trainparts, pit)  		end | 
