diff options
Diffstat (limited to 'trackplacer.lua')
-rw-r--r-- | trackplacer.lua | 200 |
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 |