From 2593b1af1625f9cc3db879541f8425217646b652 Mon Sep 17 00:00:00 2001
From: orwell96 <mono96.mml@gmail.com>
Date: Sun, 21 Aug 2016 21:46:16 +0200
Subject: repairing the trackworker

---
 trackplacer.lua | 76 +++++++++++++++++++++++++--------------------------------
 tracks.lua      | 13 ++++++++--
 trainlogic.lua  |  6 ++---
 3 files changed, 47 insertions(+), 48 deletions(-)

diff --git a/trackplacer.lua b/trackplacer.lua
index 2bba2ad..e5b3f84 100644
--- a/trackplacer.lua
+++ b/trackplacer.lua
@@ -1,6 +1,8 @@
 --trackplacer.lua
 --holds code for the track-placing system. the default 'track' item will be a craftitem that places rails as needed. this will neither place or change switches nor place vertical rails.
 
+local print=function(t, ...) minetest.log("action", table.concat({t, ...}, " ")) minetest.chat_send_all(table.concat({t, ...}, " ")) end
+
 --keys:conn1_conn2 (example:1_4)
 --values:{name=x, param2=x}
 advtrains.trackplacer_dir_to_node_mapping={}
@@ -16,26 +18,29 @@ function advtrains.trackplacer_register(nodename, conn1, conn2)
 end
 function advtrains.find_adjacent_tracks(pos)--TODO vertical calculations(check node below)
 	local conn1=0
-	while conn1<8 and not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.dirCoordSet(pos, conn1)).name, advtrains.all_tracktypes) do
+	while conn1<16 and not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.dirCoordSet(pos, conn1)).name, advtrains.all_tracktypes) do
 		conn1=conn1+1
 	end
-	if conn1>=8 then
+	if conn1>=16 then
 		return nil, nil
 	end
 	local conn2=0
-	while conn2<8 and not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.dirCoordSet(pos, conn2)).name, advtrains.all_tracktypes) or conn2==conn1 do
+	while conn2<16 and not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.dirCoordSet(pos, conn2)).name, advtrains.all_tracktypes) or conn2==conn1 do
 		conn2=conn2+1
 	end
-	if conn2>=8 then
+	if conn2>=16 then
 		return conn1, nil
 	end
 	return conn1, conn2
 end
-function advtrains.placetrack(pos)
+
+local modext={[0]="", "_30", "_45", "_60"}
+
+function advtrains.placetrack(pos, nnpref)
 	local conn1, conn2=advtrains.find_adjacent_tracks(pos)
 	
 	if not conn1 and not conn2 then
-		minetest.set_node(pos, {name="advtrains:track_st"})
+		minetest.set_node(pos, {name=nnpref.."_st"})
 	elseif conn1 and not conn2 then
 		local node1=minetest.get_node(advtrains.dirCoordSet(pos, conn1))
 		local node1_conn1, node1_conn2=advtrains.get_track_connections(node1.name, node1.param2)
@@ -55,14 +60,12 @@ function advtrains.placetrack(pos)
 			end
 		end
 		--second end will be free. place standard rail
-		if conn1%2==1 then
-			minetest.set_node(pos, {name="advtrains:track_st_45", param2=(conn1-1)/2})
-		else
-			minetest.set_node(pos, {name="advtrains:track_st", param2=conn1/2})
-		end
+		local modulo=conn1%4
+		minetest.set_node(pos, {name=nnpref.."_st"..modext[modulo], param2=(conn1-modulo)/4})
+
 	elseif conn1 and conn2 then
 		if not advtrains.trackplacer_dir_to_node_mapping[conn1.."_"..conn2] then
-			minetest.set_node(pos, {name="advtrains:track_st"})
+			minetest.set_node(pos, {name=nnpref.."_st"})
 			return
 		end
 		local node1=minetest.get_node(advtrains.dirCoordSet(pos, conn1))
@@ -147,23 +150,25 @@ minetest.register_craftitem("advtrains:trackworker",{
 			
 			if not advtrains.is_track_and_drives_on(minetest.get_node(pos).name, advtrains.all_tracktypes) then return end
 			if advtrains.is_train_at_pos(pos) then return end
-			local nodeprefix, railtype=string.match(node.name, "^(.-)_(.+)$")
-			
-			local basename=string.match(railtype, "^(.+)_45$")
-			if basename then
-				if not advtrains.trackworker_cycle_nodes[basename] then
-					print("[advtrains]rail not workable by trackworker")
-					return
-				end
-				minetest.set_node(pos, {name=nodeprefix.."_"..basename, param2=(node.param2+1)%4})
+			local nodeprefix, railtype, rotation=string.match(node.name, "^([^_]+)_([^_]+)(_?.*)$")
+			--print(node.name.."\npattern recognizes:"..nodeprefix.." / "..railtype.." / "..rotation)
+			if not advtrains.trackworker_cycle_nodes[railtype] then
+				print("[advtrains]rail not workable by trackworker")
+				return
+			end
+			if rotation==modext[#modext] then --increase param2
+				minetest.set_node(pos, {name=nodeprefix.."_"..railtype..modext[0], param2=(node.param2+1)%4})
 				return
 			else
-				if not advtrains.trackworker_cycle_nodes[railtype] then
+				local modpos
+				for k,v in pairs(modext) do if v==rotation then modpos=k end end
+				if not modpos then
 					print("[advtrains]rail not workable by trackworker")
 					return
 				end
-				minetest.set_node(pos, {name=nodeprefix.."_"..railtype.."_45", param2=node.param2})
+				minetest.set_node(pos, {name=nodeprefix.."_"..railtype..modext[modpos+1], param2=node.param2})
 			end
+			advtrains.invalidate_all_paths()
 		end
 	end,
 	on_use=function(itemstack, user, pointed_thing)
@@ -173,30 +178,15 @@ minetest.register_craftitem("advtrains:trackworker",{
 			
 			if not advtrains.is_track_and_drives_on(minetest.get_node(pos).name, advtrains.all_tracktypes) then return end
 			if advtrains.is_train_at_pos(pos) then return end
-			local nodeprefix, railtype=string.match(node.name, "^(.-)_(.+)$")
+			local nodeprefix, railtype, rotation=string.match(node.name, "^([^_]+)_([^_]+)(_?.*)$")
 			
-			local basename=string.match(railtype, "^(.+)_45$")
-			if basename then
-				if not advtrains.trackworker_cycle_nodes[basename] then
-					print("[advtrains]trackworker does not know what to set here...")
-					return
-				end
-				print(advtrains.trackworker_cycle_nodes[basename].."_45")
-				minetest.set_node(pos, {name=nodeprefix.."_"..advtrains.trackworker_cycle_nodes[basename].."_45", param2=node.param2})
+			if not advtrains.trackworker_cycle_nodes[railtype] then
+				print("[advtrains]trackworker does not know what to set here...")
 				return
-			else
-				if not advtrains.trackworker_cycle_nodes[railtype] then
-					print("[advtrains]trackworker does not know what to set here...")
-					return
-				end
-				minetest.set_node(pos, {name=nodeprefix.."_"..advtrains.trackworker_cycle_nodes[railtype], param2=node.param2})
 			end
+			minetest.set_node(pos, {name=nodeprefix.."_"..advtrains.trackworker_cycle_nodes[railtype]..rotation, param2=node.param2})
 			--invalidate trains
-			for k,v in pairs(advtrains.trains) do
-				v.restore_add_index=v.index-math.floor(v.index+0.5)
-				v.path=nil
-				v.index=nil
-			end
+			advtrains.invalidate_all_paths()
 		end
 	end,
 })
diff --git a/tracks.lua b/tracks.lua
index 260cd81..0f08e74 100644
--- a/tracks.lua
+++ b/tracks.lua
@@ -259,7 +259,7 @@ function advtrains.register_tracks_modeled(tracktype, def)
 			attached_node=1,
 			["advtrains_track_"..tracktype]=1,
 			dig_immediate=2,
-			--not_in_creative_inventory=1,
+			not_in_creative_inventory=1,
 		},
 		rely1=0,
 		rely2=0,
@@ -303,7 +303,16 @@ function advtrains.register_tracks_modeled(tracktype, def)
 			railheight=0.75,
 		},
 		def.vst2 or {}))
-	
+
+	advtrains.trackplacer_register(def.nodename_prefix.."_st", 0, 8)
+	advtrains.trackplacer_register(def.nodename_prefix.."_st_30", 1, 9)
+	advtrains.trackplacer_register(def.nodename_prefix.."_st_45", 2, 10)
+	advtrains.trackplacer_register(def.nodename_prefix.."_st_60", 3, 11)
+	advtrains.trackplacer_register(def.nodename_prefix.."_cr", 0, 7)
+	advtrains.trackplacer_register(def.nodename_prefix.."_cr_30", 1, 8)
+	advtrains.trackplacer_register(def.nodename_prefix.."_cr_45", 2, 9)
+	advtrains.trackplacer_register(def.nodename_prefix.."_cr_60", 3, 10)
+
 	--[[advtrains.trackplacer_register(def.nodename_prefix.."_st", 0, 8)
 	advtrains.trackplacer_register(def.nodename_prefix.."_st_45", 2, 10)
 	advtrains.trackplacer_register(def.nodename_prefix.."_cr", 0, 6)
diff --git a/trainlogic.lua b/trainlogic.lua
index dca2863..1ec27e0 100644
--- a/trainlogic.lua
+++ b/trainlogic.lua
@@ -601,15 +601,15 @@ function advtrains.try_connect_trains_and_check_collision(id1, id2)
 end
 --true when trains are facing each other. needed on colliding.
 -- check done by iterating paths and checking their direction
---returns nil when not on the same track at all. this distinction may not always be needed.
+--returns nil when not on the same track at all OR when required path items are not generated. this distinction may not always be needed.
 function advtrains.trains_facing(train1, train2)
 	local sr_pos=train1.path[math.floor(train1.index)]
 	local sr_pos_p=train1.path[math.floor(train1.index)-1]
 
 	for i=advtrains.minN(train2.path), advtrains.maxN(train2.path) do
 		if vector.equals(sr_pos, train2.path[i]) then
-			if vector.equals(sr_pos_p, train2.path[i+1]) then return true end
-			if vector.equals(sr_pos_p, train2.path[i-1]) then return false end
+			if train2.path[i+1] and vector.equals(sr_pos_p, train2.path[i+1]) then return true end
+			if train2.path[i-1] and vector.equals(sr_pos_p, train2.path[i-1]) then return false end
 			return nil
 		end
 	end
-- 
cgit v1.2.3