--advtrains by orwell96, see readme.txt --dev-time settings: --EDIT HERE --If the old non-model rails on straight tracks should be replaced by the new... --false: no --true: yes advtrains.register_straight_rep_lbm=true --[[TracksDefinition nodename_prefix texture_prefix description common={} straight={} straight45={} curve={} curve45={} lswitchst={} lswitchst45={} rswitchst={} rswitchst45={} lswitchcr={} lswitchcr45={} rswitchcr={} rswitchcr45={} vert1={ --you'll probably want to override mesh here } vert2={ --you'll probably want to override mesh here } ]]-- advtrains.all_tracktypes={} --definition preparation local function conns(c1, c2, r1, r2, rh, rots) return {conn1=c1, conn2=c2, rely1=r1, rely2=r2, railheight=rh} end local t_30deg={ regstep=1, variant={ st=conns(0,8), cr=conns(0,7), swlst=conns(0,8), swlcr=conns(0,7), swrst=conns(0,8), swrcr=conns(0,9), vst1=conns(8,0,0,0.5,0.25), vst2=conns(8,0,0.5,1,0.75), vst31=conns(8,0,0,0.33,0.16), vst32=conns(8,0,0.33,0.66,0.5), vst33=conns(8,0,0.66,1,0.83), }, description={ st="straight", cr="curve", swlst="left switch (straight)", swlcr="left switch (curve)", swrst="right switch (straight)", swrcr="right switch (curve)", vst1="steep uphill 1/2", vst2="steep uphill 2/2", vst31="uphill 1/3", vst32="uphill 2/3", vst33="uphill 3/3", }, switch={ swlst="swlcr", swlcr="swlst", swrst="swrcr", swrcr="swrst", }, switchmc={ swlst="on", swlcr="off", swrst="on", swrcr="off", }, trackplacer={ st=true, cr=true, }, tpsingle={ st=true, }, tpdefault="st", trackworker={ ["swrcr"]="st", ["swrst"]="st", ["st"]="cr", ["cr"]="swlst", ["swlcr"]="swrcr", ["swlst"]="swrst", }, rotation={"", "_30", "_45", "_60"}, increativeinv={vst1=true, vst2=true, vst31=true, vst32=true, vst33=true}, } local t_45deg={ regstep=2, variant={ st=conns(0,8), cr=conns(0,6), swlst=conns(0,8), swlcr=conns(0,6), swrst=conns(0,8), swrcr=conns(0,10), vst1=conns(8,0,0,0.5,0.25), vst2=conns(8,0,0.5,1,0.75), }, description={ st="straight", cr="curve", swlst="left switch (straight)", swlcr="left switch (curve)", swrst="right switch (straight)", swrcr="right switch (curve)", vst1="vertical lower node", vst2="vertical upper node", }, switch={ swlst="swlcr", swlcr="swlst", swrst="swrcr", swrcr="swrst", }, switchmc={ swlst="on", swlcr="off", swrst="on", swrcr="off", }, trackplacer={ st=true, cr=true, }, tpsingle={ st=true, }, tpdefault="st", trackworker={ ["swrcr"]="st", ["swrst"]="st", ["st"]="cr", ["cr"]="swlst", ["swlcr"]="swrcr", ["swlst"]="swrst", }, rotation={"", "_45"}, increativeinv={vst1=true, vst2=true} } --definition format: ([] optional) --[[{ nodename_prefix texture_prefix [shared_texture] models_prefix models_suffix (with dot) [shared_model] formats={ st,cr,swlst,swlcr,swrst,swrcr,vst1,vst2 (each a table with indices 0-3, for if to register a rail with this 'rotation' table entry. nil is assumed as 'all', set {} to not register at all) } common={} change something on common rail appearance }]] function advtrains.register_tracks(tracktype, def, preset) local function make_switchfunc(suffix_target, mesecon_state) local switchfunc=function(pos, node) if advtrains.is_train_at_pos(pos) then return end minetest.set_node(pos, {name=def.nodename_prefix.."_"..suffix_target, param2=node.param2}) advtrains.invalidate_all_paths() advtrains.reset_trackdb_position(pos) end return switchfunc, {effector = { ["action_"..mesecon_state] = switchfunc }} end local function make_overdef(suffix, rotation, conns, switchfunc, mesecontbl, in_creative_inv) local img_suffix=suffix..rotation return { mesh = def.shared_model or (def.models_prefix.."_"..img_suffix..def.models_suffix), tiles = {def.shared_texture or (def.texture_prefix.."_"..img_suffix..".png")}, --inventory_image = def.texture_prefix.."_"..img_suffix..".png", --wield_image = def.texture_prefix.."_"..img_suffix..".png", description=def.description.."("..preset.description[suffix]..rotation..")", connect1=conns.conn1, connect2=conns.conn2, rely1=conns.rely1 or 0, rely2=conns.rely2 or 0, railheight=conns.railheight or 0, on_rightclick=switchfunc, groups = { attached_node=1, ["advtrains_track_"..tracktype]=1, dig_immediate=2, not_in_creative_inventory=(not in_creative_inv and 1 or nil), not_blocking_trains=1, }, mesecons=mesecontbl, drop = increativeinv and def.nodename_prefix.."_"..suffix..rotation or def.nodename_prefix.."_placer", } end local function cycle_conns(conns, rotid) local add=(rotid-1)*preset.regstep return { conn1=(conns.conn1+add)%16, conn2=(conns.conn2+add)%16, rely1=conns.rely1 or 0, rely2=conns.rely2 or 0, railheight=conns.railheight or 0, } end local common_def=advtrains.merge_tables({ description = def.description, drawtype = "mesh", paramtype="light", paramtype2="facedir", walkable = false, selection_box = { type = "fixed", fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2}, }, rely1=0, rely2=0, railheight=0, drop=def.nodename_prefix.."_placer", can_dig=function(pos) return not advtrains.is_train_at_pos(pos) end, after_dig_node=function(pos) advtrains.invalidate_all_paths() advtrains.reset_trackdb_position(pos) end, after_place_node=function(pos) advtrains.reset_trackdb_position(pos) end, }, def.common or {}) --make trackplacer base def advtrains.trackplacer.register_tracktype(def.nodename_prefix, preset.tpdefault) advtrains.trackplacer.register_track_placer(def.nodename_prefix, def.texture_prefix, def.description) for suffix, conns in pairs(preset.variant) do for rotid, rotation in ipairs(preset.rotation) do if not def.formats[suffix] or def.formats[suffix][rotid] then local switchfunc, mesecontbl if preset.switch[suffix] then switchfunc, mesecontbl=make_switchfunc(preset.switch[suffix]..rotation, preset.switchmc[suffix]) end minetest.register_node(def.nodename_prefix.."_"..suffix..rotation, advtrains.merge_tables( common_def, make_overdef( suffix, rotation, cycle_conns(conns, rotid), switchfunc, mesecontbl, preset.increativeinv[suffix] ) ) ) --trackplacer if preset.trackplacer[suffix] then advtrains.trackplacer.add_double_conn(def.nodename_prefix, suffix, rotation, cycle_conns(conns, rotid)) end if preset.tpsingle[suffix] then advtrains.trackplacer.add_single_conn(def.nodename_prefix, suffix, rotation, cycle_conns(conns, rotid)) end advtrains.trackplacer.add_worked(def.nodename_prefix, suffix, rotation, preset.trackworker[suffix]) end end end table.insert(advtrains.all_tracktypes, tracktype) end function advtrains.is_track_and_drives_on(nodename, drives_on) if not minetest.registered_nodes[nodename] then return false end local nodedef=minetest.registered_nodes[nodename] for k,v in ipairs(drives_on) do if nodedef.groups["advtrains_track_"..v] then return true end end return false end function advtrains.get_track_connections(name, param2) local nodedef=minetest.registered_nodes[name] if not nodedef then print("[advtrains] get_track_connections couldn't find nodedef for nodename "..(name or "nil")) return 0, 8, 0, 0, 0 end local noderot=param2 if not param2 then noderot=0 end if noderot > 3 then print("[advtrains] get_track_connections: rail has invaild param2 of "..noderot) noderot=0 end return (nodedef.connect1 + 4 * noderot)%16, (nodedef.connect2 + 4 * noderot)%16, nodedef.rely1 or 0, nodedef.rely2 or 0, nodedef.railheight or 0 end --END code, BEGIN definition --definition format: ([] optional) --[[{ nodename_prefix texture_prefix [shared_texture] models_prefix models_suffix (with dot) [shared_model] formats={ st,cr,swlst,swlcr,swrst,swrcr,vst1,vst2 (each a table with indices 0-3, for if to register a rail with this 'rotation' table entry. nil is assumed as 'all', set {} to not register at all) } common={} change something on common rail appearance }]] advtrains.register_tracks("regular", { nodename_prefix="advtrains:track", texture_prefix="advtrains_track", shared_model="trackplane.b3d", description="Regular Train Track", formats={vst1={}, vst2={}}, }, t_45deg) advtrains.register_tracks("default", { nodename_prefix="advtrains:dtrack", texture_prefix="advtrains_dtrack", models_prefix="advtrains_dtrack", models_suffix=".b3d", shared_texture="advtrains_dtrack_rail.png", description="New Default Train Track", formats={vst1={true, false, true}, vst2={true, false, true}, vst31={true}, vst32={true}, vst33={true}}, }, t_30deg) --bumpers. temporary registration. later: integrate to register_tracks. function advtrains.register_bumpers(tracktype, def, preset) local common_def=advtrains.merge_tables({ description = def.description, drawtype = "mesh", paramtype="light", paramtype2="facedir", walkable = false, selection_box = { type = "fixed", fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2}, }, rely1=0, rely2=0, railheight=0, can_dig=function(pos) return not advtrains.is_train_at_pos(pos) end, after_dig_node=function(pos) advtrains.invalidate_all_paths() advtrains.reset_trackdb_position(pos) end, after_place_node=function(pos) advtrains.reset_trackdb_position(pos) end, }, def.common or {}) local function cycle_conns(conns, rotid) local add=(rotid-1)*preset.regstep return { conn1=(conns.conn1+add)%16, conn2=(conns.conn2+add)%16, rely1=conns.rely1 or 0, rely2=conns.rely2 or 0, railheight=conns.railheight or 0, } end for rotid, rotation in ipairs(preset.rotation) do local img_suffix="bumper"..rotation local crea=1 if rotid==1 then crea=0 end minetest.register_node(def.nodename_prefix.."_".."bumper"..rotation, advtrains.merge_tables( common_def, { mesh = def.shared_model or (def.models_prefix.."_"..img_suffix..def.models_suffix), tiles = {def.shared_texture or (def.texture_prefix.."_"..img_suffix..".png")}, --inventory_image = def.texture_prefix.."_"..img_suffix..".png", --wield_image = def.texture_prefix.."_"..img_suffix..".png", description=def.description.."(".."bumper"..rotation..")", on_rightclick=switchfunc, groups = { attached_node=1, --["advtrains_track_"..tracktype]=1, not a rail... dig_immediate=2, }, } )) --advtrains.trackplacer.add_single_conn(def.nodename_prefix, "bumper", rotation, cycle_conns({conn1=0, conn2=8}, rotid)) advtrains.trackplacer.add_worked(def.nodename_prefix, "bumper", rotation, nil) end end advtrains.register_bumpers("default", { nodename_prefix="advtrains:dtrack", texture_prefix="advtrains_dtrack", models_prefix="advtrains_dtrack", models_suffix=".b3d", shared_texture="advtrains_dtrack_rail.png", description="New Default Train Track", formats={vst1={true}, vst2={true}}, }, t_30deg) --TODO legacy --I know lbms are better for this purpose for name,rep in pairs({swl_st="swlst", swr_st="swrst", swl_cr="swlcr", swr_cr="swrcr", }) do minetest.register_abm({ -- In the following two fields, also group:groupname will work. nodenames = {"advtrains:track_"..name}, interval = 1.0, -- Operation interval in seconds chance = 1, -- Chance of trigger per-node per-interval is 1.0 / this action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:track_"..rep, param2=node.param2}) end, }) minetest.register_abm({ -- In the following two fields, also group:groupname will work. nodenames = {"advtrains:track_"..name.."_45"}, interval = 1.0, -- Operation interval in seconds chance = 1, -- Chance of trigger per-node per-interval is 1.0 / this action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:track_"..rep.."_45", param2=node.param2}) end, }) end minetest.register_lbm({ name = "advtrains:ramp_replacement_1", -- In the following two fields, also group:groupname will work. nodenames = {"advtrains:track_vert1"}, action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_vst1", param2=(node.param2+2)%4}) end, }) minetest.register_lbm({ name = "advtrains:ramp_replacement_1", -- -- In the following two fields, also group:groupname will work. nodenames = {"advtrains:track_vert2"}, action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_vst2", param2=(node.param2+2)%4}) end, }) if advtrains.register_straight_rep_lbm then minetest.register_abm({ name = "advtrains:st_rep_1", -- In the following two fields, also group:groupname will work. nodenames = {"advtrains:track_st"}, interval=1, chance=1, action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_st", param2=node.param2}) end, }) minetest.register_lbm({ name = "advtrains:st_rep_1", -- -- In the following two fields, also group:groupname will work. nodenames = {"advtrains:track_st_45"}, action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_st_45", param2=node.param2}) end, }) end