aboutsummaryrefslogtreecommitdiff
path: root/trackplacer.lua
diff options
context:
space:
mode:
Diffstat (limited to 'trackplacer.lua')
-rw-r--r--trackplacer.lua200
1 files changed, 200 insertions, 0 deletions
diff --git a/trackplacer.lua b/trackplacer.lua
new file mode 100644
index 0000000..68c1c7c
--- /dev/null
+++ b/trackplacer.lua
@@ -0,0 +1,200 @@
+--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.
+
+--keys:conn1_conn2 (example:1_4)
+--values:{name=x, param2=x}
+advtrains.trackplacer_dir_to_node_mapping={}
+--keys are nodenames!
+advtrains.trackplacer_modified_rails={}
+
+function advtrains.trackplacer_register(nodename, conn1, conn2)
+ for i=0,3 do
+ advtrains.trackplacer_dir_to_node_mapping[((conn1+2*i)%8).."_"..((conn2+2*i)%8)]={name=nodename, param2=i}
+ advtrains.trackplacer_dir_to_node_mapping[((conn2+2*i)%8).."_"..((conn1+2*i)%8)]={name=nodename, param2=i}
+ end
+ advtrains.trackplacer_modified_rails[nodename]=true
+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
+ conn1=conn1+1
+ end
+ if conn1>=8 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
+ conn2=conn2+1
+ end
+ if conn2>=8 then
+ return conn1, nil
+ end
+ return conn1, conn2
+end
+function advtrains.placetrack(pos)
+ local conn1, conn2=advtrains.find_adjacent_tracks(pos)
+
+ if not conn1 and not conn2 then
+ minetest.set_node(pos, {name="advtrains:track_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)
+ local node1_backconnects=(conn1+4)%8==node1_conn1 or (conn1+4)%8==node1_conn2
+
+ if not node1_backconnects and advtrains.trackplacer_modified_rails[node1.name] then
+ --check if this rail has a dangling connection
+ --TODO possible problems on |- situation
+ if not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.dirCoordSet(pos, node1_conn1)).name, advtrains.all_tracktypes) then
+ if advtrains.trackplacer_dir_to_node_mapping[node1_conn1.."_"..((conn1+4)%8)] then
+ minetest.set_node(advtrains.dirCoordSet(pos, conn1), advtrains.trackplacer_dir_to_node_mapping[node1_conn1.."_"..((conn1+4)%8)])
+ end
+ elseif not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.dirCoordSet(pos, node1_conn2)).name, advtrains.all_tracktypes) then
+ if advtrains.trackplacer_dir_to_node_mapping[node1_conn2.."_"..((conn1+4)%8)] then
+ minetest.set_node(advtrains.dirCoordSet(pos, conn1), advtrains.trackplacer_dir_to_node_mapping[node1_conn2.."_"..((conn1+4)%8)])
+ end
+ 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
+ elseif conn1 and conn2 then
+ if not advtrains.trackplacer_dir_to_node_mapping[conn1.."_"..conn2] then
+ minetest.set_node(pos, {name="advtrains:track_st"})
+ return
+ end
+ local node1=minetest.get_node(advtrains.dirCoordSet(pos, conn1))
+ local node1_conn1, node1_conn2=advtrains.get_track_connections(node1.name, node1.param2)
+ local node1_backconnects=(conn1+4)%8==node1_conn1 or (conn1+4)%8==node1_conn2
+ if not node1_backconnects and advtrains.trackplacer_modified_rails[node1.name] then
+ --check if this rail has a dangling connection
+ --TODO possible problems on |- situation
+ if not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.dirCoordSet(pos, node1_conn1)).name, advtrains.all_tracktypes) then
+ if advtrains.trackplacer_dir_to_node_mapping[node1_conn1.."_"..((conn1+4)%8)] then
+ minetest.set_node(advtrains.dirCoordSet(pos, conn1), advtrains.trackplacer_dir_to_node_mapping[node1_conn1.."_"..((conn1+4)%8)])
+ end
+ elseif not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.dirCoordSet(pos, node1_conn2)).name, advtrains.all_tracktypes) then
+ if advtrains.trackplacer_dir_to_node_mapping[node1_conn2.."_"..((conn1+4)%8)] then
+ minetest.set_node(advtrains.dirCoordSet(pos, conn1), advtrains.trackplacer_dir_to_node_mapping[node1_conn2.."_"..((conn1+4)%8)])
+ end
+ end
+ end
+
+ local node2=minetest.get_node(advtrains.dirCoordSet(pos, conn2))
+ local node2_conn1, node2_conn2=advtrains.get_track_connections(node2.name, node2.param2)
+ local node2_backconnects=(conn2+4)%8==node2_conn1 or (conn2+4)%8==node2_conn2
+ if not node2_backconnects and advtrains.trackplacer_modified_rails[node2.name] then
+ --check if this rail has a dangling connection
+ --TODO possible problems on |- situation
+ if not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.dirCoordSet(pos, node2_conn1)).name, advtrains.all_tracktypes) then
+ if advtrains.trackplacer_dir_to_node_mapping[node2_conn1.."_"..((conn2+4)%8)] then
+ minetest.set_node(advtrains.dirCoordSet(pos, conn2), advtrains.trackplacer_dir_to_node_mapping[node2_conn1.."_"..((conn2+4)%8)])
+ end
+ elseif not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.dirCoordSet(pos, node2_conn2)).name, advtrains.all_tracktypes) then
+ if advtrains.trackplacer_dir_to_node_mapping[node2_conn2.."_"..((conn1+4)%8)] then
+ minetest.set_node(advtrains.dirCoordSet(pos, conn2), advtrains.trackplacer_dir_to_node_mapping[node2_conn2.."_"..((conn2+4)%8)])
+ end
+ end
+ end
+ minetest.set_node(pos, advtrains.trackplacer_dir_to_node_mapping[conn1.."_"..conn2])
+ end
+end
+
+
+advtrains.trackworker_cycle_nodes={
+ ["swr_cr"]="st",
+ ["swr_st"]="st",
+ ["st"]="cr",
+ ["cr"]="swl_st",
+ ["swl_cr"]="swr_cr",
+ ["swl_st"]="swr_st",
+}
+
+function advtrains.register_track_placer(nnprefix, imgprefix, dispname)
+ minetest.register_craftitem(nnprefix.."_placer",{
+ description = dispname,
+ inventory_image = imgprefix.."_placer.png",
+ wield_image = imgprefix.."_placer.png",
+ on_place = function(itemstack, placer, pointed_thing)
+ if pointed_thing.type=="node" then
+ local pos=pointed_thing.above
+ if minetest.registered_nodes[minetest.get_node(pos).name] and minetest.registered_nodes[minetest.get_node(pos).name].buildable_to then
+ advtrains.placetrack(pos, nnprefix)
+ itemstack:take_item()
+ end
+ end
+ return itemstack
+ end,
+ })
+end
+
+
+
+minetest.register_craftitem("advtrains:trackworker",{
+ description = "Track Worker Tool\n\nLeft-click: change rail type (straight/curve/switch)\nRight-click: rotate rail",
+ groups = {cracky=1}, -- key=name, value=rating; rating=1..3.
+ inventory_image = "advtrains_trackworker.png",
+ wield_image = "advtrains_trackworker.png",
+ stack_max = 1,
+ on_place = function(itemstack, placer, pointed_thing)
+ if pointed_thing.type=="node" then
+ local pos=pointed_thing.under
+ local node=minetest.get_node(pos)
+
+ 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})
+ return
+ else
+ if not advtrains.trackworker_cycle_nodes[railtype] then
+ print("[advtrains]rail not workable by trackworker")
+ return
+ end
+ minetest.set_node(pos, {name=nodeprefix.."_"..railtype.."_45", param2=node.param2})
+ end
+ end
+ end,
+ on_use=function(itemstack, user, pointed_thing)
+ if pointed_thing.type=="node" then
+ local pos=pointed_thing.under
+ local node=minetest.get_node(pos)
+
+ 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]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})
+ 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
+ --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
+ end
+ end,
+}) \ No newline at end of file