--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, })