aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authororwell96 <orwell@bleipb.de>2023-09-04 19:34:47 +0200
committerorwell96 <orwell@bleipb.de>2023-09-04 19:34:47 +0200
commit950d6f640cae76d28253fadb7974a064017b104c (patch)
tree3d288c4e752fc92908c932af32849f736d2a382d
parent7ca8ac8d00ed8b6e707f932cc012c1eb4ace1932 (diff)
downloadadvtrains-950d6f640cae76d28253fadb7974a064017b104c.tar.gz
advtrains-950d6f640cae76d28253fadb7974a064017b104c.tar.bz2
advtrains-950d6f640cae76d28253fadb7974a064017b104c.zip
Begin major rework of track registration system
-rw-r--r--advtrains/api_doc.txt2
-rw-r--r--advtrains/copytool.lua2
-rw-r--r--advtrains/helpers.lua6
-rw-r--r--advtrains/nodedb.lua6
-rw-r--r--advtrains/oldtracks.lua751
-rw-r--r--advtrains/passive.lua90
-rw-r--r--advtrains/path.lua7
-rw-r--r--advtrains/signals.lua7
-rw-r--r--advtrains/trackplacer.lua592
-rw-r--r--advtrains/tracks.lua1038
-rw-r--r--advtrains/trainlogic.lua12
-rw-r--r--advtrains/wagons.lua5
-rw-r--r--advtrains_interlocking/init.lua4
-rw-r--r--advtrains_line_automation/init.lua4
-rwxr-xr-xadvtrains_signals_ks/init.lua21
-rwxr-xr-xadvtrains_train_track/init.lua1109
-rw-r--r--advtrains_train_track/oldinit.lua937
17 files changed, 2443 insertions, 2150 deletions
diff --git a/advtrains/api_doc.txt b/advtrains/api_doc.txt
index 5668ba3..6b338a7 100644
--- a/advtrains/api_doc.txt
+++ b/advtrains/api_doc.txt
@@ -18,8 +18,6 @@ advtrains.register_wagon(name, prototype, description, inventory_image)
# Wagon prototype properties
{
... all regular luaentity properties (mesh, textures, collisionbox a.s.o)...
- drives_on = {default=true},
- ^- used to define the tracktypes (see below) that wagon can drive on. The tracktype identifiers are given as keys, similar to privileges)
max_speed = 10,
^- optional, default 10: defines the maximum speed this wagon can drive. The maximum speed of a train is determined by the wagon with the lowest max_speed value.
seats = {
diff --git a/advtrains/copytool.lua b/advtrains/copytool.lua
index 0c1cdfe..8a6d2f7 100644
--- a/advtrains/copytool.lua
+++ b/advtrains/copytool.lua
@@ -21,7 +21,7 @@ minetest.register_tool("advtrains:copytool", {
local node=minetest.get_node_or_nil(pointed_thing.under)
if not node then atprint("[advtrains]Ignore at placer position") return itemstack end
local nodename=node.name
- if(not advtrains.is_track_and_drives_on(nodename, {default=true})) then
+ if(not advtrains.is_track(nodename)) then
atprint("no track here, not placing.")
return itemstack
end
diff --git a/advtrains/helpers.lua b/advtrains/helpers.lua
index 7e078fb..7a774d9 100644
--- a/advtrains/helpers.lua
+++ b/advtrains/helpers.lua
@@ -294,7 +294,7 @@ end
-- Going from the rail at pos (does not need to be rounded) along connection with id conn_idx, if there is a matching rail, return it and the matching connid
-- returns: <adjacent pos>, <conn index of adjacent>, <my conn index>, <railheight of adjacent>
-- parameter this_conns_p is connection table of this rail and is optional, is determined by get_rail_info_at if not provided.
-function advtrains.get_adjacent_rail(this_posnr, this_conns_p, conn_idx, drives_on)
+function advtrains.get_adjacent_rail(this_posnr, this_conns_p, conn_idx)
local this_pos = advtrains.round_vector_floor_y(this_posnr)
local this_conns = this_conns_p
local _
@@ -318,11 +318,11 @@ function advtrains.get_adjacent_rail(this_posnr, this_conns_p, conn_idx, drives_
adj_pos.y = adj_pos.y + 1
end
- local nextnode_ok, nextconns, nextrail_y=advtrains.get_rail_info_at(adj_pos, drives_on)
+ local nextnode_ok, nextconns, nextrail_y=advtrains.get_rail_info_at(adj_pos)
if not nextnode_ok then
adj_pos.y = adj_pos.y - 1
conn_y = conn_y + 1
- nextnode_ok, nextconns, nextrail_y=advtrains.get_rail_info_at(adj_pos, drives_on)
+ nextnode_ok, nextconns, nextrail_y=advtrains.get_rail_info_at(adj_pos)
if not nextnode_ok then
return nil
end
diff --git a/advtrains/nodedb.lua b/advtrains/nodedb.lua
index 41ac089..39106b2 100644
--- a/advtrains/nodedb.lua
+++ b/advtrains/nodedb.lua
@@ -268,17 +268,17 @@ end
--false if it's not a rail or the train does not drive on this rail, but it is loaded or
--nil if the node is neither loaded nor in trackdb
--the distraction between false and nil will be needed only in special cases.(train initpos)
-function advtrains.get_rail_info_at(pos, drives_on)
+function advtrains.get_rail_info_at(pos)
local rdp=advtrains.round_vector_floor_y(pos)
local node=ndb.get_node_or_nil(rdp)
if not node then return end
local nodename=node.name
- if(not advtrains.is_track_and_drives_on(nodename, drives_on)) then
+ if(not advtrains.is_track(nodename)) then
return false
end
- local conns, railheight, tracktype=advtrains.get_track_connections(node.name, node.param2)
+ local conns, railheight = advtrains.get_track_connections(node.name, node.param2)
return true, conns, railheight
end
diff --git a/advtrains/oldtracks.lua b/advtrains/oldtracks.lua
new file mode 100644
index 0000000..c415143
--- /dev/null
+++ b/advtrains/oldtracks.lua
@@ -0,0 +1,751 @@
+--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_replacement_lbms=false
+
+--[[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) return {{c=c1, y=r1}, {c=c2, y=r2}} end
+local function conns3(c1, c2, c3, r1, r2, r3) return {{c=c1, y=r1}, {c=c2, y=r2}, {c=c3, y=r3}} end
+
+advtrains.ap={}
+advtrains.ap.t_30deg_flat={
+ regstep=1,
+ variant={
+ st={
+ conns = conns(0,8),
+ desc = "straight",
+ tpdouble = true,
+ tpsingle = true,
+ trackworker = "cr",
+ },
+ cr={
+ conns = conns(0,7),
+ desc = "curve",
+ tpdouble = true,
+ trackworker = "swlst",
+ },
+ swlst={
+ conns = conns3(0,8,7),
+ desc = "left switch (straight)",
+ trackworker = "swrst",
+ switchalt = "cr",
+ switchmc = "on",
+ switchst = "st",
+ switchprefix = "swl",
+ },
+ swlcr={
+ conns = conns3(0,7,8),
+ desc = "left switch (curve)",
+ trackworker = "swrcr",
+ switchalt = "st",
+ switchmc = "off",
+ switchst = "cr",
+ switchprefix = "swl",
+ },
+ swrst={
+ conns = conns3(0,8,9),
+ desc = "right switch (straight)",
+ trackworker = "st",
+ switchalt = "cr",
+ switchmc = "on",
+ switchst = "st",
+ switchprefix = "swr",
+ },
+ swrcr={
+ conns = conns3(0,9,8),
+ desc = "right switch (curve)",
+ trackworker = "st",
+ switchalt = "st",
+ switchmc = "off",
+ switchst = "cr",
+ switchprefix = "swr",
+ },
+ },
+ regtp=true,
+ tpdefault="st",
+ trackworker={
+ ["swrcr"]="st",
+ ["swrst"]="st",
+ ["cr"]="swlst",
+ ["swlcr"]="swrcr",
+ ["swlst"]="swrst",
+ },
+ rotation={"", "_30", "_45", "_60"},
+}
+advtrains.ap.t_yturnout={
+ regstep=1,
+ variant={
+ l={
+ conns = conns3(0,7,9),
+ desc = "Y-turnout (left)",
+ switchalt = "r",
+ switchmc = "off",
+ switchst = "l",
+ switchprefix = "",
+ },
+ r={
+ conns = conns3(0,9,7),
+ desc = "Y-turnout (right)",
+ switchalt = "l",
+ switchmc = "on",
+ switchst = "r",
+ switchprefix = "",
+ }
+ },
+ regtp=true,
+ tpdefault="l",
+ rotation={"", "_30", "_45", "_60"},
+}
+advtrains.ap.t_s3way={
+ regstep=1,
+ variant={
+ l={
+ conns = { {c=0}, {c=7}, {c=8}, {c=9}, {c=0} },
+ desc = "3-way turnout (left)",
+ switchalt = "s",
+ switchst="l",
+ switchprefix = "",
+ },
+ s={
+ conns = { {c=0}, {c=8}, {c=7}, {c=9}, {c=0} },
+ desc = "3-way turnout (straight)",
+ switchalt ="r",
+ switchst = "s",
+ switchprefix = "",
+ },
+ r={
+ conns = { {c=0}, {c=9}, {c=8}, {c=7}, {c=0} },
+ desc = "3-way turnout (right)",
+ switchalt = "l",
+ switchst="r",
+ switchprefix = "",
+ }
+ },
+ regtp=true,
+ tpdefault="l",
+ rotation={"", "_30", "_45", "_60"},
+}
+advtrains.ap.t_30deg_slope={
+ regstep=1,
+ variant={
+ vst1={conns = conns(8,0,0,0.5), rail_y = 0.25, desc = "steep uphill 1/2", slope=true},
+ vst2={conns = conns(8,0,0.5,1), rail_y = 0.75, desc = "steep uphill 2/2", slope=true},
+ vst31={conns = conns(8,0,0,0.33), rail_y = 0.16, desc = "uphill 1/3", slope=true},
+ vst32={conns = conns(8,0,0.33,0.66), rail_y = 0.5, desc = "uphill 2/3", slope=true},
+ vst33={conns = conns(8,0,0.66,1), rail_y = 0.83, desc = "uphill 3/3", slope=true},
+ },
+ regsp=true,
+ slopeplacer={
+ [2]={"vst1", "vst2"},
+ [3]={"vst31", "vst32", "vst33"},
+ max=3,--highest entry
+ },
+ slopeplacer_45={
+ [2]={"vst1_45", "vst2_45"},
+ max=2,
+ },
+ rotation={"", "_30", "_45", "_60"},
+ trackworker={},
+ increativeinv={},
+}
+advtrains.ap.t_30deg_straightonly={
+ regstep=1,
+ variant={
+ st={
+ conns = conns(0,8),
+ desc = "straight",
+ tpdouble = true,
+ tpsingle = true,
+ trackworker = "st",
+ },
+ },
+ regtp=true,
+ tpdefault="st",
+ rotation={"", "_30", "_45", "_60"},
+}
+advtrains.ap.t_30deg_straightonly_noplacer={
+ regstep=1,
+ variant={
+ st={
+ conns = conns(0,8),
+ desc = "straight",
+ tpdouble = true,
+ tpsingle = true,
+ trackworker = "st",
+ },
+ },
+ tpdefault="st",
+ rotation={"", "_30", "_45", "_60"},
+}
+advtrains.ap.t_45deg={
+ regstep=2,
+ variant={
+ st={
+ conns = conns(0,8),
+ desc = "straight",
+ tpdouble = true,
+ tpsingle = true,
+ trackworker = "cr",
+ },
+ cr={
+ conns = conns(0,6),
+ desc = "curve",
+ tpdouble = true,
+ trackworker = "swlst",
+ },
+ swlst={
+ conns = conns3(0,8,6),
+ desc = "left switch (straight)",
+ trackworker = "swrst",
+ switchalt = "cr",
+ switchmc = "on",
+ switchst = "st",
+ },
+ swlcr={
+ conns = conns3(0,6,8),
+ desc = "left switch (curve)",
+ trackworker = "swrcr",
+ switchalt = "st",
+ switchmc = "off",
+ switchst = "cr",
+ },
+ swrst={
+ conns = conns3(0,8,10),
+ desc = "right switch (straight)",
+ trackworker = "st",
+ switchalt = "cr",
+ switchmc = "on",
+ switchst = "st",
+ },
+ swrcr={
+ conns = conns3(0,10,8),
+ desc = "right switch (curve)",
+ trackworker = "st",
+ switchalt = "st",
+ switchmc = "off",
+ switchst = "cr",
+ },
+ },
+ regtp=true,
+ tpdefault="st",
+ trackworker={
+ ["swrcr"]="st",
+ ["swrst"]="st",
+ ["cr"]="swlst",
+ ["swlcr"]="swrcr",
+ ["swlst"]="swrst",
+ },
+ rotation={"", "_30", "_45", "_60"},
+}
+advtrains.ap.t_perpcrossing={
+ regstep = 1,
+ variant={
+ st={
+ conns = { {c=0}, {c=8}, {c=4}, {c=12} },
+ desc = "perpendicular crossing",
+ tpdouble = true,
+ tpsingle = true,
+ trackworker = "st",
+ },
+ },
+ regtp=true,
+ tpdefault="st",
+ rotation={"", "_30", "_45", "_60"},
+}
+advtrains.ap.t_90plusx_crossing={
+ regstep = 1,
+ variant={
+ ["30l"]={
+ conns = { {c=0}, {c=8}, {c=1}, {c=9} },
+ desc = "30/90 degree crossing (left)",
+ tpdouble = true,
+ tpsingle = true,
+ trackworker = "45l"
+ },
+ ["45l"]={
+ conns = { {c=0}, {c=8}, {c=2}, {c=10} },
+ desc = "45/90 degree crossing (left)",
+ tpdouble = true,
+ tpsingle = true,
+ trackworker = "60l",
+ },
+ ["60l"]={
+ conns = { {c=0}, {c=8}, {c=3}, {c=11}},
+ desc = "60/90 degree crossing (left)",
+ tpdouble = true,
+ tpsingle = true,
+ trackworker = "60r",
+ },
+ ["60r"]={
+ conns = { {c=0}, {c=8}, {c=5}, {c=13} },
+ desc = "60/90 degree crossing (right)",
+ tpdouble = true,
+ tpsingle = true,
+ trackworker = "45r"
+ },
+ ["45r"]={
+ conns = { {c=0}, {c=8}, {c=6}, {c=14} },
+ desc = "45/90 degree crossing (right)",
+ tpdouble = true,
+ tpsingle = true,
+ trackworker = "30r",
+ },
+ ["30r"]={
+ conns = { {c=0}, {c=8}, {c=7}, {c=15}},
+ desc = "30/90 degree crossing (right)",
+ tpdouble = true,
+ tpsingle = true,
+ trackworker = "30l",
+ },
+ },
+ regtp=true,
+ tpdefault="30l",
+ rotation={""},
+ trackworker = {
+ ["30l"] = "45l",
+ ["45l"] = "60l",
+ ["60l"] = "60r",
+ ["60r"] = "45r",
+ ["45r"] = "30r",
+ ["30r"] = "30l",
+ }
+}
+
+advtrains.ap.t_diagonalcrossing = {
+ regstep=1,
+ variant={
+ ["30l45r"]={
+ conns = {{c=1}, {c=9}, {c=6}, {c=14}},
+ desc = "30left-45right diagonal crossing",
+ tpdouble=true,
+ tpsingle=true,
+ trackworker="60l30l",
+ },
+ ["60l30l"]={
+ conns = {{c=3}, {c=11}, {c=1}, {c=9}},
+ desc = "30left-60right diagonal crossing",
+ tpdouble=true,
+ tpsingle=true,
+ trackworker="60l45r"
+ },
+ ["60l45r"]={
+ conns = {{c=3}, {c=11}, {c=6}, {c=14}},
+ desc = "60left-45right diagonal crossing",
+ tpdouble=true,
+ tpsingle=true,
+ trackworker="60l60r"
+ },
+ ["60l60r"]={
+ conns = {{c=3}, {c=11}, {c=5}, {c=13}},
+ desc = "60left-60right diagonal crossing",
+ tpdouble=true,
+ tpsingle=true,
+ trackworker="60r45l",
+ },
+ --If 60l60r had a mirror image, it would be here, but it's symmetric.
+ -- 60l60r is also equivalent to 30l30r but rotated 90 degrees.
+ ["60r45l"]={
+ conns = {{c=5}, {c=13}, {c=2}, {c=10}},
+ desc = "60right-45left diagonal crossing",
+ tpdouble=true,
+ tpsingle=true,
+ trackworker="60r30r",
+ },
+ ["60r30r"]={
+ conns = {{c=5}, {c=13}, {c=7}, {c=15}},
+ desc = "60right-30right diagonal crossing",
+ tpdouble=true,
+ tpsingle=true,
+ trackworker="30r45l",
+ },
+ ["30r45l"]={
+ conns = {{c=7}, {c=15}, {c=2}, {c=10}},
+ desc = "30right-45left diagonal crossing",
+ tpdouble=true,
+ tpsingle=true,
+ trackworker="30l45r",
+ },
+
+ },
+ regtp=true,
+ tpdefault="30l45r",
+ rotation={""},
+ trackworker = {
+ ["30l45r"] = "60l30l",
+ ["60l30l"] = "60l45r",
+ ["60l45r"] = "60l60r",
+ ["60l60r"] = "60r45l",
+ ["60r45l"] = "60r30r",
+ ["60r30r"] = "30r45l",
+ ["30r45l"] = "30l45r",
+ }
+}
+
+advtrains.trackpresets = advtrains.ap
+
+--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
+}
+[18.12.17] Note on new connection system:
+In order to support real rail crossing nodes and finally make the trackplacer respect switches, I changed the connection system.
+There can be a variable number of connections available. These are specified as tuples {c=<connection>, y=<rely>}
+The table "at_conns" consists of {<conn1>, <conn2>...}
+the "at_rail_y" property holds the value that was previously called "railheight"
+Depending on the number of connections:
+2 conns: regular rail
+3 conns: switch:
+ - when train passes in at conn1, will move out of conn2
+ - when train passes in at conn2 or conn3, will move out of conn1
+4 conns: cross (or cross switch, depending on arrangement of conns):
+ - conn1 <> conn2
+ - conn3 <> conn4
+]]
+
+-- Notify the user if digging the rail is not allowed
+local function can_dig_callback(pos, player)
+ local ok, reason = advtrains.can_dig_or_modify_track(pos)
+ if not ok and player then
+ minetest.chat_send_player(player:get_player_name(), attrans("This track can not be removed!") .. " " .. reason)
+ end
+ return ok
+end
+
+function advtrains.register_tracks(tracktype, def, preset)
+ advtrains.trackplacer.register_tracktype(def.nodename_prefix, preset.tpdefault)
+ if preset.regtp then
+ advtrains.trackplacer.register_track_placer(def.nodename_prefix, def.texture_prefix, def.description, def)
+ end
+ if preset.regsp then
+ advtrains.slope.register_placer(def, preset)
+ end
+ for suffix, var 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 img_suffix = suffix..rotation
+ local ndef = advtrains.merge_tables({
+ description=def.description.."("..(var.desc or "any")..rotation..")",
+ drawtype = "mesh",
+ paramtype="light",
+ paramtype2="facedir",
+ walkable = false,
+ selection_box = {
+ type = "fixed",
+ fixed = {-1/2-1/16, -1/2, -1/2, 1/2+1/16, -1/2+2/16, 1/2},
+ },
+
+ mesh = def.shared_model or (def.models_prefix.."_"..img_suffix..def.models_suffix),
+ tiles = {def.shared_texture or (def.texture_prefix.."_"..img_suffix..".png"), def.second_texture},
+
+ groups = {
+ attached_node = advtrains.IGNORE_WORLD and 0 or 1,
+ advtrains_track=1,
+ ["advtrains_track_"..tracktype]=1,
+ save_in_at_nodedb=1,
+ dig_immediate=2,
+ not_in_creative_inventory=1,
+ not_blocking_trains=1,
+ },
+
+ can_dig = can_dig_callback,
+ after_dig_node=function(pos)
+ advtrains.ndb.update(pos)
+ end,
+ after_place_node=function(pos)
+ advtrains.ndb.update(pos)
+ end,
+ at_nnpref = def.nodename_prefix,
+ at_suffix = suffix,
+ at_rotation = rotation,
+ at_rail_y = var.rail_y
+ }, def.common or {})
+
+ if preset.regtp then
+ ndef.drop = def.nodename_prefix.."_placer"
+ end
+ if preset.regsp and var.slope then
+ ndef.drop = def.nodename_prefix.."_slopeplacer"
+ end
+
+ --connections
+ ndef.at_conns = advtrains.rotate_conn_by(var.conns, (rotid-1)*preset.regstep)
+
+ local ndef_avt_table
+
+ if var.switchalt and var.switchst then
+ local switchfunc=function(pos, node, newstate)
+ newstate = newstate or var.switchalt -- support for 3 (or more) state switches
+ -- this code is only called from the internal setstate function, which
+ -- ensures that it is safe to switch the turnout
+ if newstate~=var.switchst then
+ advtrains.ndb.swap_node(pos, {name=def.nodename_prefix.."_"..(var.switchprefix or "")..newstate..rotation, param2=node.param2})
+ advtrains.invalidate_all_paths(pos)
+ end
+ end
+ ndef.on_rightclick = function(pos, node, player)
+ if advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
+ advtrains.setstate(pos, nil, node)
+ advtrains.log("Switch", player:get_player_name(), pos)
+ end
+ end
+ if var.switchmc then
+ ndef.mesecons = {effector = {
+ ["action_"..var.switchmc] = function(pos, node)
+ advtrains.setstate(pos, nil, node)
+ end,
+ rules=advtrains.meseconrules
+ }}
+ end
+ ndef_avt_table = {
+ getstate = var.switchst,
+ setstate = switchfunc,
+ }
+ end
+
+ local adef={}
+ if def.get_additional_definiton then
+ adef=def.get_additional_definiton(def, preset, suffix, rotation)
+ end
+ ndef = advtrains.merge_tables(ndef, adef)
+
+ -- insert getstate/setstate functions after merging the additional definitions
+ if ndef_avt_table then
+ ndef.advtrains = advtrains.merge_tables(ndef.advtrains or {}, ndef_avt_table)
+ end
+
+ minetest.register_node(":"..def.nodename_prefix.."_"..suffix..rotation, ndef)
+ --trackplacer
+ if preset.regtp then
+ local tpconns = {conn1=ndef.at_conns[1].c, conn2=ndef.at_conns[2].c}
+ if var.tpdouble then
+ advtrains.trackplacer.add_double_conn(def.nodename_prefix, suffix, rotation, tpconns)
+ end
+ if var.tpsingle then
+ advtrains.trackplacer.add_single_conn(def.nodename_prefix, suffix, rotation, tpconns)
+ end
+ end
+ advtrains.trackplacer.add_worked(def.nodename_prefix, suffix, rotation, var.trackworker)
+ end
+ end
+ end
+ advtrains.all_tracktypes[tracktype]=true
+end
+
+function advtrains.is_track_and_drives_on(nodename, drives_on_p)
+ local drives_on = drives_on_p
+ if not drives_on then drives_on = advtrains.all_tracktypes end
+ local hasentry = false
+ for _,_ in pairs(drives_on) do
+ hasentry=true
+ end
+ if not hasentry then drives_on = advtrains.all_tracktypes end
+
+ if not minetest.registered_nodes[nodename] then
+ return false
+ end
+ local nodedef=minetest.registered_nodes[nodename]
+ for k,v in pairs(drives_on) do
+ if nodedef.groups["advtrains_track_"..k] 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 atprint(" get_track_connections couldn't find nodedef for nodename "..(name or "nil")) return nil end
+ local noderot=param2
+ if not param2 then noderot=0 end
+ if noderot > 3 then atprint(" get_track_connections: rail has invaild param2 of "..noderot) noderot=0 end
+
+ local tracktype
+ for k,_ in pairs(nodedef.groups) do
+ local tt=string.match(k, "^advtrains_track_(.+)$")
+ if tt then
+ tracktype=tt
+ end
+ end
+ return advtrains.rotate_conn_by(nodedef.at_conns, noderot*AT_CMAX/4), (nodedef.at_rail_y or 0), tracktype
+end
+
+-- Function called when a track is about to be dug or modified by the trackworker
+-- Returns either true (ok) or false,"translated string describing reason why it isn't allowed"
+function advtrains.can_dig_or_modify_track(pos)
+ if advtrains.get_train_at_pos(pos) then
+ return false, attrans("Position is occupied by a train.")
+ end
+ -- interlocking: tcb, signal IP a.s.o.
+ if advtrains.interlocking then
+ -- TCB?
+ if advtrains.interlocking.db.get_tcb(pos) then
+ return false, attrans("There's a Track Circuit Break here.")
+ end
+ -- signal ip?
+ if advtrains.interlocking.db.is_ip_at(pos, true) then -- is_ip_at with purge parameter
+ return false, attrans("There's a Signal Influence Point here.")
+ end
+ end
+ return true
+end
+
+-- slope placer. Defined in register_tracks.
+--crafted with rail and gravel
+local sl={}
+function sl.register_placer(def, preset)
+ minetest.register_craftitem(":"..def.nodename_prefix.."_slopeplacer",{
+ description = attrans("@1 Slope", def.description),
+ inventory_image = def.texture_prefix.."_slopeplacer.png",
+ wield_image = def.texture_prefix.."_slopeplacer.png",
+ groups={},
+ on_place = sl.create_slopeplacer_on_place(def, preset)
+ })
+end
+--(itemstack, placer, pointed_thing)
+function sl.create_slopeplacer_on_place(def, preset)
+ return function(istack, player, pt)
+ if not pt.type=="node" then
+ minetest.chat_send_player(player:get_player_name(), attrans("Can't place: not pointing at node"))
+ return istack
+ end
+ local pos=pt.above
+ if not pos then
+ minetest.chat_send_player(player:get_player_name(), attrans("Can't place: not pointing at node"))
+ return istack
+ end
+ local node=minetest.get_node(pos)
+ if not minetest.registered_nodes[node.name] or not minetest.registered_nodes[node.name].buildable_to then
+ minetest.chat_send_player(player:get_player_name(), attrans("Can't place: space occupied!"))
+ return istack
+ end
+ if not advtrains.check_track_protection(pos, player:get_player_name()) then
+ minetest.record_protection_violation(pos, player:get_player_name())
+ return istack
+ end
+ --determine player orientation (only horizontal component)
+ --get_look_horizontal may not be available
+ local yaw=player.get_look_horizontal and player:get_look_horizontal() or (player:get_look_yaw() - math.pi/2)
+
+ --rounding unit vectors is a nice way for selecting 1 of 8 directions since sin(30°) is 0.5.
+ local dirvec={x=math.floor(math.sin(-yaw)+0.5), y=0, z=math.floor(math.cos(-yaw)+0.5)}
+ --translate to direction to look up inside the preset table
+ local param2, rot45=({
+ [-1]={
+ [-1]=2,
+ [0]=3,
+ [1]=3,
+ },
+ [0]={
+ [-1]=2,
+ [1]=0,
+ },
+ [1]={
+ [-1]=1,
+ [0]=1,
+ [1]=0,
+ },
+ })[dirvec.x][dirvec.z], dirvec.x~=0 and dirvec.z~=0
+ local lookup=preset.slopeplacer
+ if rot45 then lookup=preset.slopeplacer_45 end
+
+ --go unitvector forward and look how far the next node is
+ local step=1
+ while step<=lookup.max do
+ local node=minetest.get_node(vector.add(pos, dirvec))
+ --next node solid?
+ if not minetest.registered_nodes[node.name] or not minetest.registered_nodes[node.name].buildable_to or advtrains.is_protected(pos, player:get_player_name()) then
+ --do slopes of this distance exist?
+ if lookup[step] then
+ if minetest.settings:get_bool("creative_mode") or istack:get_count()>=step then
+ --start placing
+ local placenodes=lookup[step]
+ while step>0 do
+ minetest.set_node(pos, {name=def.nodename_prefix.."_"..placenodes[step], param2=param2})
+ if not minetest.settings:get_bool("creative_mode") then
+ istack:take_item()
+ end
+ step=step-1
+ pos=vector.subtract(pos, dirvec)
+ end
+ else
+ minetest.chat_send_player(player:get_player_name(), attrans("Can't place: Not enough slope items left (@1 required)", step))
+ end
+ else
+ minetest.chat_send_player(player:get_player_name(), attrans("Can't place: There's no slope of length @1",step))
+ end
+ return istack
+ end
+ step=step+1
+ pos=vector.add(pos, dirvec)
+ end
+ minetest.chat_send_player(player:get_player_name(), attrans("Can't place: no supporting node at upper end."))
+ return itemstack
+ end
+end
+
+advtrains.slope=sl
+
+--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
+}]]
+
+
+
+
+
+
+
+
+
diff --git a/advtrains/passive.lua b/advtrains/passive.lua
index fe4790c..76da720 100644
--- a/advtrains/passive.lua
+++ b/advtrains/passive.lua
@@ -1,9 +1,5 @@
-- passive.lua
--- API to passive components, as described in passive_api.txt of advtrains_luaautomation
--- This has been moved to the advtrains core in turn with the interlocking system,
--- to prevent a dependency on luaautomation.
-
-local deprecation_warned = {}
+-- Rework for advtrains 2.5: The passive API now uses the reworked node_state system. Please see the comment in tracks.lua
function advtrains.getstate(parpos, pnode)
local pos
@@ -19,20 +15,8 @@ function advtrains.getstate(parpos, pnode)
local node=pnode or advtrains.ndb.get_node(pos)
local ndef=minetest.registered_nodes[node.name]
local st
- if ndef and ndef.advtrains and ndef.advtrains.getstate then
- st=ndef.advtrains.getstate
- elseif ndef and ndef.luaautomation and ndef.luaautomation.getstate then
- if not deprecation_warned[node.name] then
- minetest.log("warning", node.name.." uses deprecated definition of ATLATC functions in the 'luaautomation' field. Please move them to the 'advtrains' field!")
- end
- st=ndef.luaautomation.getstate
- else
- return nil
- end
- if type(st)=="function" then
- return st(pos, node)
- else
- return st
+ if ndef and ndef.advtrains then
+ return ndef.advtrains.node_state
end
end
@@ -45,31 +29,46 @@ function advtrains.setstate(parpos, newstate, pnode)
end
if type(pos)~="table" or (not pos.x or not pos.y or not pos.z) then
debug.sethook()
- error("Invalid position supplied to getstate")
+ error("Invalid position supplied to setstate")
end
local node=pnode or advtrains.ndb.get_node(pos)
local ndef=minetest.registered_nodes[node.name]
- local st
- if ndef and ndef.advtrains and ndef.advtrains.setstate then
- st=ndef.advtrains.setstate
- elseif ndef and ndef.luaautomation and ndef.luaautomation.setstate then
- if not deprecation_warned[node.name] then
- minetest.log("warning", node.name.." uses deprecated definition of ATLATC functions in the 'luaautomation' field. Please move them to the 'advtrains' field!")
- end
- st=ndef.luaautomation.setstate
- else
- return nil
+
+ if not ndef or not ndef.advtrains then
+ return false, "missing_node_def"
+ end
+ local old_state = ndef.advtrains.node_state
+
+ if old_state == newstate then
+ -- nothing needs to be done
+ return true
end
+ if not ndef.advtrains.node_state_map then
+ return false, "missing_node_state_map"
+ end
+ local new_node_name = ndef.advtrains.node_state_map[newstate]
+ if not new_node_name then
+ return false, "no_such_state"
+ end
+
+ -- prevent state switching when route lock or train is present
if advtrains.get_train_at_pos(pos) then
- return false
+ return false, "train_here"
end
if advtrains.interlocking and advtrains.interlocking.route.has_route_lock(minetest.pos_to_string(pos)) then
- return false
+ return false, "route_lock_here"
end
- st(pos, node, newstate)
+ -- perform the switch
+ local new_node = {name = new_node_name, param2 = node.param2}
+ advtrains.ndb.swap_node(pos, new_node)
+ -- if callback is present, call it
+ if ndef.advtrains.node_on_switch_state then
+ ndef.advtrains.node_on_switch_state(pos, new_node, old_state, newstate)
+ end
+
return true
end
@@ -86,12 +85,7 @@ function advtrains.is_passive(parpos, pnode)
end
local node=pnode or advtrains.ndb.get_node(pos)
local ndef=minetest.registered_nodes[node.name]
- if ndef and ndef.advtrains and ndef.advtrains.getstate then
- return true
- elseif ndef and ndef.luaautomation and ndef.luaautomation.getstate then
- if not deprecation_warned[node.name] then
- minetest.log("warning", node.name.." uses deprecated definition of ATLATC functions in the 'luaautomation' field. Please move them to the 'advtrains' field!")
- end
+ if ndef and ndef.advtrains and ndef.advtrains.node_state_map then
return true
else
return false
@@ -102,20 +96,10 @@ end
function advtrains.set_fallback_state(pos, pnode)
local node=pnode or advtrains.ndb.get_node(pos)
local ndef=minetest.registered_nodes[node.name]
- local st
- if ndef and ndef.advtrains and ndef.advtrains.setstate
- and ndef.advtrains.fallback_state then
- if advtrains.get_train_at_pos(pos) then
- return false
- end
-
- if advtrains.interlocking and advtrains.interlocking.route.has_route_lock(minetest.pos_to_string(pos)) then
- return false
- end
-
- ndef.advtrains.setstate(pos, node, ndef.advtrains.fallback_state)
- return true
- end
+ if not ndef or not ndef.advtrains or not ndef.advtrains.node_fallback_state then
+ return false, "no_fallback_state"
+ end
+ return advtrains.setstate(pos, ndef.advtrains.node_fallback_state, node)
end
diff --git a/advtrains/path.lua b/advtrains/path.lua
index 19387b1..72ee05d 100644
--- a/advtrains/path.lua
+++ b/advtrains/path.lua
@@ -33,13 +33,12 @@
-- If you need to proceed along the path by a specific actual distance, it does NOT work to simply add it to the index. You should use the path_get_index_by_offset() function.
-- creates the path data structure, reconstructing the train from a position and a connid
--- Important! train.drives_on must exist while calling this method
-- returns: true - successful
-- nil - node not yet available/unloaded, please wait
-- false - node definitely gone, remove train
function advtrains.path_create(train, pos, connid, rel_index)
local posr = advtrains.round_vector_floor_y(pos)
- local node_ok, conns, rhe = advtrains.get_rail_info_at(pos, train.drives_on)
+ local node_ok, conns, rhe = advtrains.get_rail_info_at(pos)
if not node_ok then
return node_ok
end
@@ -211,7 +210,7 @@ function advtrains.path_get(train, index)
if pef == train.path_trk_f then
node_ok, this_conns = advtrains.get_rail_info_at(pos)
if not node_ok then error("For train "..train.id..": Path item "..pef.." on-track but not a valid node!") end
- adj_pos, adj_connid, conn_idx, nextrail_y, next_conns = advtrains.get_adjacent_rail(pos, this_conns, connid, train.drives_on)
+ adj_pos, adj_connid, conn_idx, nextrail_y, next_conns = advtrains.get_adjacent_rail(pos, this_conns, connid)
end
pef = pef + 1
if adj_pos then
@@ -250,7 +249,7 @@ function advtrains.path_get(train, index)
if peb == train.path_trk_b then
node_ok, this_conns = advtrains.get_rail_info_at(pos)
if not node_ok then error("For train "..train.id..": Path item "..peb.." on-track but not a valid node!") end
- adj_pos, adj_connid, conn_idx, nextrail_y, next_conns = advtrains.get_adjacent_rail(pos, this_conns, connid, train.drives_on)
+ adj_pos, adj_connid, conn_idx, nextrail_y, next_conns = advtrains.get_adjacent_rail(pos, this_conns, connid)
end
peb = peb - 1
if adj_pos then
diff --git a/advtrains/signals.lua b/advtrains/signals.lua
index b26c950..58d28a5 100644
--- a/advtrains/signals.lua
+++ b/advtrains/signals.lua
@@ -40,9 +40,6 @@ local suppasp = {
for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red", als="green"}}) do
- advtrains.trackplacer.register_tracktype("advtrains:retrosignal", "")
- advtrains.trackplacer.register_tracktype("advtrains:signal", "")
-
for rotid, rotation in ipairs({"", "_30", "_45", "_60"}) do
local crea=1
if rotid==1 and r=="off" then crea=0 end
@@ -108,8 +105,8 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red",
},
can_dig = can_dig_func,
after_dig_node = after_dig_func,
+ --TODO add rotation using trackworker
})
- advtrains.trackplacer.add_worked("advtrains:retrosignal", r, rotation, nil)
minetest.register_node("advtrains:signal_"..r..rotation, {
drawtype = "mesh",
@@ -179,8 +176,8 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red",
},
can_dig = can_dig_func,
after_dig_node = after_dig_func,
+ --TODO add rotation using trackworker
})
- advtrains.trackplacer.add_worked("advtrains:signal", r, rotation, nil)
end
local crea=1
diff --git a/advtrains/trackplacer.lua b/advtrains/trackplacer.lua
index fe76290..9d63199 100644
--- a/advtrains/trackplacer.lua
+++ b/advtrains/trackplacer.lua
@@ -3,311 +3,204 @@
--all new trackplacer code
local tp={
- tracks={}
+ groups={}
}
-function tp.register_tracktype(nnprefix, n_suffix)
- if tp.tracks[nnprefix] then return end--due to the separate registration of slopes and flats for the same nnpref, definition would be overridden here. just don't.
- tp.tracks[nnprefix]={
- default=n_suffix,
- single_conn={},
- single_conn_1={},
- single_conn_2={},
- double_conn={},
- double_conn_1={},
- double_conn_2={},
- --keys:conn1_conn2 (example:1_4)
- --values:{name=x, param2=x}
- twcycle={},
- twrotate={},--indexed by suffix, list, tells order of rotations
- modify={},
- }
-end
-function tp.add_double_conn(nnprefix, suffix, rotation, conns)
- local nodename=nnprefix.."_"..suffix..rotation
- for i=0,3 do
- tp.tracks[nnprefix].double_conn[((conns.conn1+4*i)%16).."_"..((conns.conn2+4*i)%16)]={name=nodename, param2=i}
- tp.tracks[nnprefix].double_conn[((conns.conn2+4*i)%16).."_"..((conns.conn1+4*i)%16)]={name=nodename, param2=i}
- tp.tracks[nnprefix].double_conn_1[((conns.conn1+4*i)%16).."_"..((conns.conn2+4*i)%16)]={name=nodename, param2=i}
- tp.tracks[nnprefix].double_conn_2[((conns.conn2+4*i)%16).."_"..((conns.conn1+4*i)%16)]={name=nodename, param2=i}
- end
- tp.tracks[nnprefix].modify[nodename]=true
-end
-function tp.add_single_conn(nnprefix, suffix, rotation, conns)
- local nodename=nnprefix.."_"..suffix..rotation
- for i=0,3 do
- tp.tracks[nnprefix].single_conn[((conns.conn1+4*i)%16)]={name=nodename, param2=i}
- tp.tracks[nnprefix].single_conn[((conns.conn2+4*i)%16)]={name=nodename, param2=i}
- tp.tracks[nnprefix].single_conn_1[((conns.conn1+4*i)%16)]={name=nodename, param2=i}
- tp.tracks[nnprefix].single_conn_2[((conns.conn2+4*i)%16)]={name=nodename, param2=i}
- end
- tp.tracks[nnprefix].modify[nodename]=true
-end
+--[[ New in version 2.5:
+The track placer no longer uses hacky nodename pattern matching.
+The base criterion for rotating or matching tracks is the common "ndef.advtrains.track_place_group" property.
+Only rails where this field is set are considered for replacement. Other rails can still be considered for connection.
+Replacement ("bending") of rails can only happen within their respective track place group. Only two-conn rails are allowed in the trackplacer.
-function tp.add_worked(nnprefix, suffix, rotation, cycle_follows)
- tp.tracks[nnprefix].twcycle[suffix]=cycle_follows
- if not tp.tracks[nnprefix].twrotate[suffix] then tp.tracks[nnprefix].twrotate[suffix]={} end
- table.insert(tp.tracks[nnprefix].twrotate[suffix], rotation)
-end
+The track registration functions register the candidates for any given track_place_group in two separate collections:
+- double: tracks that can be used to connect both ends of the rail
+- single: tracks that will be used to connect conn1 when only a single end is to be connected
+When track placing is requested, the calling code just supplies the track_place_group to be placed.
---[[
- rewrite algorithm.
- selection criteria: these will never be changed or even selected:
- - tracks being already connected on both sides
- - tracks that are already connected on one side but are not bendable to the desired position
- the following situations can occur:
- 1. there are two more than two rails around
- 1.1 there is one or more subset(s) that can be directly connected
- -> choose the first possibility
- 2.2 not
- -> choose the first one and orient straight
- 2. there's exactly 1 rail around
- -> choose and orient straight
- 3. there's no rail around
- -> set straight
-]]
+]]--
-local function istrackandbc(pos_p, conn)
- local tpos = pos_p
- local cnode=minetest.get_node(advtrains.dirCoordSet(tpos, conn.c))
- if advtrains.is_track_and_drives_on(cnode.name, advtrains.all_tracktypes) then
- local cconns=advtrains.get_track_connections(cnode.name, cnode.param2)
- return advtrains.conn_matches_to(conn, cconns)
- end
- --try the same 1 node below
- tpos = {x=tpos.x, y=tpos.y-1, z=tpos.z}
- cnode=minetest.get_node(advtrains.dirCoordSet(tpos, conn.c))
- if advtrains.is_track_and_drives_on(cnode.name, advtrains.all_tracktypes) then
- local cconns=advtrains.get_track_connections(cnode.name, cnode.param2)
- return advtrains.conn_matches_to(conn, cconns)
- end
- return false
+local function rotate(conn, rot)
+ return (conn + rot) % 16
end
-function tp.find_already_connected(pos)
- local dnode=minetest.get_node(pos)
- local dconns=advtrains.get_track_connections(dnode.name, dnode.param2)
- local found_conn
- for connid, conn in ipairs(dconns) do
- if istrackandbc(pos, conn) then
- if found_conn then --we found one in previous iteration
- return true, true --signal that it's connected
- else
- found_conn = conn.c
+-- Register a track node as candidate
+-- tpg: the track place group to register the candidates for
+-- name, ndef: the node name and node definition table to register
+-- as_single: whether the rail should be considered as candidate for one-endpoint connection
+-- Typically only set for the straight rail variants
+-- as_double: whether the rail should be considered as candidate for two-endpoint connection
+-- Typically set for straights and curves
+function tp.register_candidate(tpg, name, ndef, as_single, as_double)
+ --get or create TP group
+ if not tp.groups[tpg] then
+ tp.groups[tpg] = {double = {}, single1 = {}, single2 = {}, default = {name = name, param2 = 0} }
+ -- note: this causes the first candidate to ever be registered to be the default (which is typically what you want)
+ end
+ local g = tp.groups[tpg]
+
+ -- get conns
+ assert(#ndef.at_conns == 2)
+ local c1, c2 = ndef.at_conns[1].c, ndef.at_conns[2].c
+ local is_symmetrical = (rotate(c1, 8) == c2)
+
+ -- store all possible rotations (param2 values)
+ for i=0,3 do
+ if as_double then
+ g.double[rotate(c1,i*4).."_"..rotate(c2,i*4)] = {name=name, param2=i}
+ if not is_symmmetrical then
+ g.double[rotate(c2,i*4).."_"..rotate(c1,i*4)] = {name=name, param2=i}
+ -- if the track is unsymmetric (e.g. a curve), we may require the "wrong" orientation to fill a gap.
end
end
+ if as_single then
+ g.single1[rotate(c1,i*4)] = {name=name, param2=i}
+ g.single2[rotate(c2,i*4)] = {name=name, param2=i}
+ end
end
- return found_conn
end
-function tp.rail_and_can_be_bent(originpos, conn)
- local pos=advtrains.dirCoordSet(originpos, conn)
- local newdir=(conn+8)%16
- local node=minetest.get_node(pos)
- if not advtrains.is_track_and_drives_on(node.name, advtrains.all_tracktypes) then
+
+local function check_or_bend_rail(origin, dir, pname, commit)
+ local pos = advtrains.pos_add_dir(origin, dir)
+ local back_dir = advtrains.oppd(dir);
+
+ local node_ok, conns = advtrains.get_rail_info_at(pos)
+ if not node_ok then
+ -- try the node one level below
+ pos.y = pos.y - 1
+ node_ok, conns = advtrains.get_rail_info_at(pos)
+ end
+ if not node_ok then
return false
end
- local ndef=minetest.registered_nodes[node.name]
- local nnpref = ndef and ndef.at_nnpref
- if not nnpref then return false end
- local tr=tp.tracks[nnpref]
- if not tr then return false end
- if not tr.modify[node.name] then
- --we actually can use this rail, but only if it already points to the desired direction.
- if advtrains.is_track_and_drives_on(node.name, advtrains.all_tracktypes) then
- local cconns=advtrains.get_track_connections(node.name, node.param2)
- return advtrains.conn_matches_to(conn, cconns)
+ -- if one conn of the node here already points towards us, nothing to do
+ for connid, conn in ipairs(conns) do
+ if back_dir == conn.c then
+ return true
end
end
- -- If the rail is not allowed to be modified, also only use if already in desired direction
+ -- can we bend the node here?
+ local node = advtrains.ndb.get_node(pos)
+ local ndef = minetest.registered_nodes[node.name]
+ if not ndef or not ndef.advtrains or not ndef.advtrains.track_place_group then
+ return false
+ end
+ -- now the track must be two-conn, else it wouldn't be allowed to have track_place_group set.
+ assert(#conns == 2)
+ -- Is player and game allowed to do this?
if not advtrains.can_dig_or_modify_track(pos) then
- local cconns=advtrains.get_track_connections(node.name, node.param2)
- return advtrains.conn_matches_to(conn, cconns)
+ return false
end
- --rail at other end?
- local adj1, adj2=tp.find_already_connected(pos)
- if adj1 and adj2 then
- return false--dont destroy existing track
- elseif adj1 and not adj2 then
- if tr.double_conn[adj1.."_"..newdir] then
- return true--if exists, connect new rail and old end
- end
+ if not advtrains.check_track_protection(pos, pname) then
return false
- else
- if tr.single_conn[newdir] then--just rotate old rail to right orientation
- return true
+ end
+ -- we confirmed that track can be modified. Does there exist a suitable connection candidate?
+ -- check if there are any unbound ends
+ local bound_connids = {}
+ for connid, conn in ipairs(conns) do
+ local adj_pos, adj_connid = advtrains.get_adjacent_rail(pos, conns, connid)
+ if adj_pos then
+ bound_connids[#bound_connids+1] = connid
end
- return false
end
-end
-function tp.bend_rail(originpos, conn)
- local pos=advtrains.dirCoordSet(originpos, conn)
- local newdir=advtrains.oppd(conn)
- local node=minetest.get_node(pos)
- local ndef=minetest.registered_nodes[node.name]
- local nnpref = ndef and ndef.at_nnpref
- if not nnpref then return false end
- local tr=tp.tracks[nnpref]
- if not tr then return false end
- --is rail already connected? no need to bend.
- local conns=advtrains.get_track_connections(node.name, node.param2)
- if advtrains.conn_matches_to(conn, conns) then
- return
+ -- depending on the nummber of ends, decide
+ if #bound_connids == 2 then
+ -- rail is within a fixed track, do not break up
+ return false
end
- --rail at other end?
- local adj1, adj2=tp.find_already_connected(pos)
- if adj1 and adj2 then
- return false--dont destroy existing track
- elseif adj1 and not adj2 then
- if tr.double_conn[adj1.."_"..newdir] then
- advtrains.ndb.swap_node(pos, tr.double_conn[adj1.."_"..newdir])
- return true--if exists, connect new rail and old end
+ -- obtain the group table
+ local g = tp.groups[ndef.advtrains.track_place_group]
+ if #bound_connids == 1 then
+ -- we can attempt double
+ local bound_dir = conns[bound_connids[1]].c
+ if g.double[back_dir.."_"..bound_dir] then
+ if commit then
+ advtrains.ndb.swap_node(pos, g.double[back_dir.."_"..bound_dir])
+ end
+ return true
end
- return false
else
- if tr.single_conn[newdir] then--just rotate old rail to right orientation
- advtrains.ndb.swap_node(pos, tr.single_conn[newdir])
+ -- rail is entirely unbound, we can attempt single1
+ if g.single1[back_dir] then
+ if commit then
+ advtrains.ndb.swap_node(pos, g.single1[back_dir])
+ end
return true
end
- return false
end
end
-function tp.placetrack(pos, nnpref, placer, itemstack, pointed_thing, yaw)
- --1. find all rails that are likely to be connected
- local tr=tp.tracks[nnpref]
- local p_rails={}
- local p_railpos={}
+
+local function track_place_node(pos, node, ndef)
+ advtrains.ndb.swap_node(pos, node)
+ local ndef = minetest.registered_nodes[node.name]
+ if ndef and ndef.after_place_node then
+ ndef.after_place_node(pos)
+ end
+end
+
+
+-- Main API function to place a track. Replaces the older "placetrack"
+-- This function will attempt to place a track of the specified track placing group at the specified position, connecting it
+-- with neighboring rails. Neighboring rails can themselves be replaced ("bent") within their own track place group,
+-- if the player is permitted to do this.
+-- Order of preference is:
+-- Connect two track ends if possible
+-- Connect one track end if any rail is near
+-- Place the default track if no tracks are near
+-- The function returns true on success.
+function tp.place_track(pos, tpg, pname, yaw)
+ -- 1. collect neighboring tracks and whether they can be connected
+ local cand = {}
for i=0,15 do
- if tp.rail_and_can_be_bent(pos, i, nnpref) then
- p_rails[#p_rails+1]=i
- p_railpos[i] = pos
- else
- local upos = {x=pos.x, y=pos.y-1, z=pos.z}
- if tp.rail_and_can_be_bent(upos, i, nnpref) then
- p_rails[#p_rails+1]=i
- p_railpos[i] = upos
- end
+ if check_or_bend_rail(pos, i, pname) then
+ cand[#cand+1] = i
end
end
-
- -- try double_conn
- if #p_rails > 1 then
- --iterate subsets
- for k1, conn1 in ipairs(p_rails) do
- for k2, conn2 in ipairs(p_rails) do
- if k1~=k2 then
- local dconn1 = tr.double_conn_1
- local dconn2 = tr.double_conn_2
- if not (advtrains.yawToDirection(yaw, conn1, conn2) == conn1) then
- dconn1 = tr.double_conn_2
- dconn2 = tr.double_conn_1
- end
- -- Checks are made this way round so that dconn1 has priority (this will make arrows of atc rails
- -- point in the right direction)
- local using
- if (dconn2[conn1.."_"..conn2]) then
- using = dconn2[conn1.."_"..conn2]
- end
- if (dconn1[conn1.."_"..conn2]) then
- using = dconn1[conn1.."_"..conn2]
- end
- if using then
- -- has found a fitting rail in either direction
- -- if not, continue loop
- tp.bend_rail(p_railpos[conn1], conn1, nnpref)
- tp.bend_rail(p_railpos[conn2], conn2, nnpref)
- advtrains.ndb.swap_node(pos, using)
- local nname=using.name
- if minetest.registered_nodes[nname] and minetest.registered_nodes[nname].after_place_node then
- minetest.registered_nodes[nname].after_place_node(pos, placer, itemstack, pointed_thing)
- end
- return
+ -- obtain the group table
+ local g = tp.groups[tpg]
+ -- 2. try all possible two-endpoint connections
+ for k1, conn1 in ipairs(cand) do
+ for k2, conn2 in ipairs(cand) do
+ if k1~=k2 then
+ -- order of conn1/conn2: prefer conn2 being in the direction of the player facing.
+ -- the combination the other way round will be run through in a later loop iteration
+ if advtrains.yawToDirection(yaw, conn1, conn2) == conn2 then
+ -- does there exist a suitable double-connection rail?
+ local node = g.double[conn1.."_"..conn2]
+ if node then
+ check_or_bend_rail(pos, conn1, pname, true)
+ check_or_bend_rail(pos, conn2, pname, true)
+ track_place_node(pos, node) -- calls after_place_node implicitly
+ return true
end
end
end
end
end
- -- try single_conn
- if #p_rails > 0 then
- for ix, p_rail in ipairs(p_rails) do
- local sconn1 = tr.single_conn_1
- local sconn2 = tr.single_conn_2
- if not (advtrains.yawToDirection(yaw, p_rail, (p_rail+8)%16) == p_rail) then
- sconn1 = tr.single_conn_2
- sconn2 = tr.single_conn_1
- end
- if sconn1[p_rail] then
- local using = sconn1[p_rail]
- tp.bend_rail(p_railpos[p_rail], p_rail, nnpref)
- advtrains.ndb.swap_node(pos, using)
- local nname=using.name
- if minetest.registered_nodes[nname] and minetest.registered_nodes[nname].after_place_node then
- minetest.registered_nodes[nname].after_place_node(pos, placer, itemstack, pointed_thing)
- end
- return
- end
- if sconn2[p_rail] then
- local using = sconn2[p_rail]
- tp.bend_rail(p_railpos[p_rail], p_rail, nnpref)
- advtrains.ndb.swap_node(pos, using)
- local nname=using.name
- if minetest.registered_nodes[nname] and minetest.registered_nodes[nname].after_place_node then
- minetest.registered_nodes[nname].after_place_node(pos, placer, itemstack, pointed_thing)
- end
- return
- end
+ -- 3. try all possible one_endpoint connections
+ for k1, conn1 in ipairs(cand) do
+ -- select single1 or single2? depending on yaw
+ local single
+ if advtrains.yawToDirection(yaw, conn1, advtrains.oppd(conn1)) == conn1 then
+ single = g.single1
+ else
+ single = g.single2
+ end
+ local node = single[conn1]
+ if node then
+ check_or_bend_rail(pos, conn1, pname, true)
+ track_place_node(pos, node) -- calls after_place_node implicitly
+ return true
end
end
- --use default
- minetest.set_node(pos, {name=nnpref.."_"..tr.default})
- if minetest.registered_nodes[nnpref.."_"..tr.default] and minetest.registered_nodes[nnpref.."_"..tr.default].after_place_node then
- minetest.registered_nodes[nnpref.."_"..tr.default].after_place_node(pos, placer, itemstack, pointed_thing)
- end
+ -- 4. if nothing worked, set the default
+ local node = g.default
+ track_place_node(pos, node) -- calls after_place_node implicitly
+ return true
end
-
-function tp.register_track_placer(nnprefix, imgprefix, dispname, def)
- minetest.register_craftitem(":"..nnprefix.."_placer",{
- description = dispname,
- inventory_image = imgprefix.."_placer.png",
- wield_image = imgprefix.."_placer.png",
- groups={advtrains_trackplacer=1, digtron_on_place=1},
- liquids_pointable = def.liquids_pointable,
- on_place = function(itemstack, placer, pointed_thing)
- local name = placer:get_player_name()
- if not name then
- return itemstack, false
- end
- if pointed_thing.type=="node" then
- local pos=pointed_thing.above
- local upos=vector.subtract(pointed_thing.above, {x=0, y=1, z=0})
- if not advtrains.check_track_protection(pos, name) then
- return itemstack, false
- end
- if minetest.registered_nodes[minetest.get_node(pos).name] and minetest.registered_nodes[minetest.get_node(pos).name].buildable_to then
- local s
- if def.suitable_substrate then
- s = def.suitable_substrate(upos)
- else
- s = minetest.registered_nodes[minetest.get_node(upos).name] and minetest.registered_nodes[minetest.get_node(upos).name].walkable
- end
- if s then
--- minetest.chat_send_all(nnprefix)
- local yaw = placer:get_look_horizontal()
- tp.placetrack(pos, nnprefix, placer, itemstack, pointed_thing, yaw)
- if not advtrains.is_creative(name) then
- itemstack:take_item()
- end
- end
- end
- end
- return itemstack, true
- end,
- })
-end
-
-
+-- TRACK WORKER --
minetest.register_craftitem("advtrains:trackworker",{
description = attrans("Track Worker Tool\n\nLeft-click: change rail type (straight/curve/switch)\nRight-click: rotate rail/bumper/signal/etc."),
@@ -316,116 +209,93 @@ minetest.register_craftitem("advtrains:trackworker",{
wield_image = "advtrains_trackworker.png",
stack_max = 1,
on_place = function(itemstack, placer, pointed_thing)
- local name = placer:get_player_name()
- if not name then
+ local name = placer:get_player_name()
+ if not name then
+ return
+ end
+ local has_aux1_down = placer:get_player_control().aux1
+ if pointed_thing.type=="node" then
+ local pos=pointed_thing.under
+ if not advtrains.check_track_protection(pos, name) then
return
end
- local has_aux1_down = placer:get_player_control().aux1
- if pointed_thing.type=="node" then
- local pos=pointed_thing.under
- if not advtrains.check_track_protection(pos, name) then
- return
- end
- local node=minetest.get_node(pos)
+ 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
-
- local nnprefix, suffix, rotation=string.match(node.name, "^(.+)_([^_]+)(_[^_]+)$")
- --atdebug(node.name.."\npattern recognizes:"..nnprefix.." / "..suffix.." / "..rotation)
- --atdebug("nntab: ",tp.tracks[nnprefix])
- if not tp.tracks[nnprefix] or not tp.tracks[nnprefix].twrotate[suffix] then
- nnprefix, suffix=string.match(node.name, "^(.+)_([^_]+)$")
- rotation = ""
- if not tp.tracks[nnprefix] or not tp.tracks[nnprefix].twrotate[suffix] then
- minetest.chat_send_player(placer:get_player_name(), attrans("This node can't be rotated using the trackworker!"))
- return
- end
- end
-
- -- check if the node is modify-protected
- if advtrains.is_track_and_drives_on(minetest.get_node(pos).name, advtrains.all_tracktypes) then
- -- is a track, we can query
- local can_modify, reason = advtrains.can_dig_or_modify_track(pos)
- if not can_modify then
- local str = attrans("This track can not be rotated!")
- if reason then
- str = str .. " " .. reason
- end
- minetest.chat_send_player(placer:get_player_name(), str)
- return
+ -- New since 2.5: only the fields in the node definition are considered, no more hacky pattern matching on the nodename
+
+ local ndef = minetest.registered_nodes[node.name]
+
+ if not ndef.advtrains or not ndef.advtrains.trackworker_next_rot then
+ minetest.chat_send_player(placer:get_player_name(), attrans("This node can't be rotated using the trackworker!"))
+ return
+ end
+
+ -- check if the node is modify-protected
+ if advtrains.is_track(node.name) then
+ -- is a track, we can query
+ local can_modify, reason = advtrains.can_dig_or_modify_track(pos)
+ if not can_modify then
+ local str = attrans("This track can not be rotated!")
+ if reason then
+ str = str .. " " .. reason
end
- end
-
- if has_aux1_down then
- --feature: flip the node by 180°
- --i've always wanted this!
- advtrains.ndb.swap_node(pos, {name=node.name, param2=(node.param2+2)%4})
+ minetest.chat_send_player(placer:get_player_name(), str)
return
end
-
- local modext=tp.tracks[nnprefix].twrotate[suffix]
-
- if rotation==modext[#modext] then --increase param2
- advtrains.ndb.swap_node(pos, {name=nnprefix.."_"..suffix..modext[1], param2=(node.param2+1)%4})
- return
- else
- local modpos
- for k,v in pairs(modext) do
- if v==rotation then modpos=k end
- end
- if not modpos then
- minetest.chat_send_player(placer:get_player_name(), attrans("This node can't be rotated using the trackworker!"))
- return
- end
- advtrains.ndb.swap_node(pos, {name=nnprefix.."_"..suffix..modext[modpos+1], param2=node.param2})
- end
end
+
+ if has_aux1_down then
+ --feature: flip the node by 180°
+ --i've always wanted this!
+ advtrains.ndb.swap_node(pos, {name=node.name, param2=(node.param2+2)%4})
+ return
+ end
+
+ local new_node = {name = ndef.advtrains.trackworker_next_rot, param2 = node.param2}
+ if ndef.advtrains.trackworker_rot_incr_param2 then
+ new_node.param2 = ((node.param2 + 1) % 4)
+ end
+ advtrains.ndb.swap_node(pos, new_node)
+ end
end,
on_use=function(itemstack, user, pointed_thing)
- local name = user:get_player_name()
- if not name then
- return
+ local name = user:get_player_name()
+ if not name then
+ return
+ end
+ if pointed_thing.type=="node" then
+ local pos=pointed_thing.under
+ local node=minetest.get_node(pos)
+ if not advtrains.check_track_protection(pos, name) then
+ return
end
- if pointed_thing.type=="node" then
- local pos=pointed_thing.under
- local node=minetest.get_node(pos)
- if not advtrains.check_track_protection(pos, name) then
- return
- end
-
- --if not advtrains.is_track_and_drives_on(minetest.get_node(pos).name, advtrains.all_tracktypes) then return end
- if advtrains.get_train_at_pos(pos) then return end
- local nnprefix, suffix, rotation=string.match(node.name, "^(.+)_([^_]+)(_[^_]+)$")
- --atdebug(node.name.."\npattern recognizes:"..nodeprefix.." / "..railtype.." / "..rotation)
- if not tp.tracks[nnprefix] or not tp.tracks[nnprefix].twcycle[suffix] then
- nnprefix, suffix=string.match(node.name, "^(.+)_([^_]+)$")
- rotation = ""
- if not tp.tracks[nnprefix] or not tp.tracks[nnprefix].twcycle[suffix] then
- minetest.chat_send_player(user:get_player_name(), attrans("This node can't be changed using the trackworker!"))
- return
- end
- end
-
- -- check if the node is modify-protected
- if advtrains.is_track_and_drives_on(minetest.get_node(pos).name, advtrains.all_tracktypes) then
- -- is a track, we can query
- local can_modify, reason = advtrains.can_dig_or_modify_track(pos)
- if not can_modify then
- local str = attrans("This track can not be changed!")
- if reason then
- str = str .. " " .. reason
- end
- minetest.chat_send_player(user:get_player_name(), str)
- return
+
+ -- New since 2.5: only the fields in the node definition are considered, no more hacky pattern matching on the nodename
+
+ local ndef = minetest.registered_nodes[node.name]
+
+ if not ndef.advtrains or not ndef.advtrains.trackworker_next_var then
+ minetest.chat_send_player(placer:get_player_name(), attrans("This node can't be changed using the trackworker!"))
+ return
+ end
+
+ -- check if the node is modify-protected
+ if advtrains.is_track(node.name) then
+ -- is a track, we can query
+ local can_modify, reason = advtrains.can_dig_or_modify_track(pos)
+ if not can_modify then
+ local str = attrans("This track can not be rotated!")
+ if reason then
+ str = str .. " " .. reason
end
+ minetest.chat_send_player(placer:get_player_name(), str)
+ return
end
-
- local nextsuffix=tp.tracks[nnprefix].twcycle[suffix]
- advtrains.ndb.swap_node(pos, {name=nnprefix.."_"..nextsuffix..rotation, param2=node.param2})
-
- else
- atprint(name, dump(tp.tracks))
end
+
+ local new_node = {name = ndef.advtrains.trackworker_next_var, param2 = node.param2}
+ advtrains.ndb.swap_node(pos, new_node)
+ end
end,
})
diff --git a/advtrains/tracks.lua b/advtrains/tracks.lua
index c415143..dc2d909 100644
--- a/advtrains/tracks.lua
+++ b/advtrains/tracks.lua
@@ -1,751 +1,287 @@
---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_replacement_lbms=false
-
---[[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) return {{c=c1, y=r1}, {c=c2, y=r2}} end
-local function conns3(c1, c2, c3, r1, r2, r3) return {{c=c1, y=r1}, {c=c2, y=r2}, {c=c3, y=r3}} end
-
-advtrains.ap={}
-advtrains.ap.t_30deg_flat={
- regstep=1,
- variant={
- st={
- conns = conns(0,8),
- desc = "straight",
- tpdouble = true,
- tpsingle = true,
- trackworker = "cr",
- },
- cr={
- conns = conns(0,7),
- desc = "curve",
- tpdouble = true,
- trackworker = "swlst",
- },
- swlst={
- conns = conns3(0,8,7),
- desc = "left switch (straight)",
- trackworker = "swrst",
- switchalt = "cr",
- switchmc = "on",
- switchst = "st",
- switchprefix = "swl",
- },
- swlcr={
- conns = conns3(0,7,8),
- desc = "left switch (curve)",
- trackworker = "swrcr",
- switchalt = "st",
- switchmc = "off",
- switchst = "cr",
- switchprefix = "swl",
- },
- swrst={
- conns = conns3(0,8,9),
- desc = "right switch (straight)",
- trackworker = "st",
- switchalt = "cr",
- switchmc = "on",
- switchst = "st",
- switchprefix = "swr",
- },
- swrcr={
- conns = conns3(0,9,8),
- desc = "right switch (curve)",
- trackworker = "st",
- switchalt = "st",
- switchmc = "off",
- switchst = "cr",
- switchprefix = "swr",
- },
- },
- regtp=true,
- tpdefault="st",
- trackworker={
- ["swrcr"]="st",
- ["swrst"]="st",
- ["cr"]="swlst",
- ["swlcr"]="swrcr",
- ["swlst"]="swrst",
- },
- rotation={"", "_30", "_45", "_60"},
-}
-advtrains.ap.t_yturnout={
- regstep=1,
- variant={
- l={
- conns = conns3(0,7,9),
- desc = "Y-turnout (left)",
- switchalt = "r",
- switchmc = "off",
- switchst = "l",
- switchprefix = "",
- },
- r={
- conns = conns3(0,9,7),
- desc = "Y-turnout (right)",
- switchalt = "l",
- switchmc = "on",
- switchst = "r",
- switchprefix = "",
- }
- },
- regtp=true,
- tpdefault="l",
- rotation={"", "_30", "_45", "_60"},
-}
-advtrains.ap.t_s3way={
- regstep=1,
- variant={
- l={
- conns = { {c=0}, {c=7}, {c=8}, {c=9}, {c=0} },
- desc = "3-way turnout (left)",
- switchalt = "s",
- switchst="l",
- switchprefix = "",
- },
- s={
- conns = { {c=0}, {c=8}, {c=7}, {c=9}, {c=0} },
- desc = "3-way turnout (straight)",
- switchalt ="r",
- switchst = "s",
- switchprefix = "",
- },
- r={
- conns = { {c=0}, {c=9}, {c=8}, {c=7}, {c=0} },
- desc = "3-way turnout (right)",
- switchalt = "l",
- switchst="r",
- switchprefix = "",
- }
- },
- regtp=true,
- tpdefault="l",
- rotation={"", "_30", "_45", "_60"},
-}
-advtrains.ap.t_30deg_slope={
- regstep=1,
- variant={
- vst1={conns = conns(8,0,0,0.5), rail_y = 0.25, desc = "steep uphill 1/2", slope=true},
- vst2={conns = conns(8,0,0.5,1), rail_y = 0.75, desc = "steep uphill 2/2", slope=true},
- vst31={conns = conns(8,0,0,0.33), rail_y = 0.16, desc = "uphill 1/3", slope=true},
- vst32={conns = conns(8,0,0.33,0.66), rail_y = 0.5, desc = "uphill 2/3", slope=true},
- vst33={conns = conns(8,0,0.66,1), rail_y = 0.83, desc = "uphill 3/3", slope=true},
- },
- regsp=true,
- slopeplacer={
- [2]={"vst1", "vst2"},
- [3]={"vst31", "vst32", "vst33"},
- max=3,--highest entry
- },
- slopeplacer_45={
- [2]={"vst1_45", "vst2_45"},
- max=2,
- },
- rotation={"", "_30", "_45", "_60"},
- trackworker={},
- increativeinv={},
-}
-advtrains.ap.t_30deg_straightonly={
- regstep=1,
- variant={
- st={
- conns = conns(0,8),
- desc = "straight",
- tpdouble = true,
- tpsingle = true,
- trackworker = "st",
- },
- },
- regtp=true,
- tpdefault="st",
- rotation={"", "_30", "_45", "_60"},
-}
-advtrains.ap.t_30deg_straightonly_noplacer={
- regstep=1,
- variant={
- st={
- conns = conns(0,8),
- desc = "straight",
- tpdouble = true,
- tpsingle = true,
- trackworker = "st",
- },
- },
- tpdefault="st",
- rotation={"", "_30", "_45", "_60"},
-}
-advtrains.ap.t_45deg={
- regstep=2,
- variant={
- st={
- conns = conns(0,8),
- desc = "straight",
- tpdouble = true,
- tpsingle = true,
- trackworker = "cr",
- },
- cr={
- conns = conns(0,6),
- desc = "curve",
- tpdouble = true,
- trackworker = "swlst",
- },
- swlst={
- conns = conns3(0,8,6),
- desc = "left switch (straight)",
- trackworker = "swrst",
- switchalt = "cr",
- switchmc = "on",
- switchst = "st",
- },
- swlcr={
- conns = conns3(0,6,8),
- desc = "left switch (curve)",
- trackworker = "swrcr",
- switchalt = "st",
- switchmc = "off",
- switchst = "cr",
- },
- swrst={
- conns = conns3(0,8,10),
- desc = "right switch (straight)",
- trackworker = "st",
- switchalt = "cr",
- switchmc = "on",
- switchst = "st",
- },
- swrcr={
- conns = conns3(0,10,8),
- desc = "right switch (curve)",
- trackworker = "st",
- switchalt = "st",
- switchmc = "off",
- switchst = "cr",
- },
- },
- regtp=true,
- tpdefault="st",
- trackworker={
- ["swrcr"]="st",
- ["swrst"]="st",
- ["cr"]="swlst",
- ["swlcr"]="swrcr",
- ["swlst"]="swrst",
- },
- rotation={"", "_30", "_45", "_60"},
-}
-advtrains.ap.t_perpcrossing={
- regstep = 1,
- variant={
- st={
- conns = { {c=0}, {c=8}, {c=4}, {c=12} },
- desc = "perpendicular crossing",
- tpdouble = true,
- tpsingle = true,
- trackworker = "st",
- },
- },
- regtp=true,
- tpdefault="st",
- rotation={"", "_30", "_45", "_60"},
-}
-advtrains.ap.t_90plusx_crossing={
- regstep = 1,
- variant={
- ["30l"]={
- conns = { {c=0}, {c=8}, {c=1}, {c=9} },
- desc = "30/90 degree crossing (left)",
- tpdouble = true,
- tpsingle = true,
- trackworker = "45l"
- },
- ["45l"]={
- conns = { {c=0}, {c=8}, {c=2}, {c=10} },
- desc = "45/90 degree crossing (left)",
- tpdouble = true,
- tpsingle = true,
- trackworker = "60l",
- },
- ["60l"]={
- conns = { {c=0}, {c=8}, {c=3}, {c=11}},
- desc = "60/90 degree crossing (left)",
- tpdouble = true,
- tpsingle = true,
- trackworker = "60r",
- },
- ["60r"]={
- conns = { {c=0}, {c=8}, {c=5}, {c=13} },
- desc = "60/90 degree crossing (right)",
- tpdouble = true,
- tpsingle = true,
- trackworker = "45r"
- },
- ["45r"]={
- conns = { {c=0}, {c=8}, {c=6}, {c=14} },
- desc = "45/90 degree crossing (right)",
- tpdouble = true,
- tpsingle = true,
- trackworker = "30r",
- },
- ["30r"]={
- conns = { {c=0}, {c=8}, {c=7}, {c=15}},
- desc = "30/90 degree crossing (right)",
- tpdouble = true,
- tpsingle = true,
- trackworker = "30l",
- },
- },
- regtp=true,
- tpdefault="30l",
- rotation={""},
- trackworker = {
- ["30l"] = "45l",
- ["45l"] = "60l",
- ["60l"] = "60r",
- ["60r"] = "45r",
- ["45r"] = "30r",
- ["30r"] = "30l",
- }
-}
-
-advtrains.ap.t_diagonalcrossing = {
- regstep=1,
- variant={
- ["30l45r"]={
- conns = {{c=1}, {c=9}, {c=6}, {c=14}},
- desc = "30left-45right diagonal crossing",
- tpdouble=true,
- tpsingle=true,
- trackworker="60l30l",
- },
- ["60l30l"]={
- conns = {{c=3}, {c=11}, {c=1}, {c=9}},
- desc = "30left-60right diagonal crossing",
- tpdouble=true,
- tpsingle=true,
- trackworker="60l45r"
- },
- ["60l45r"]={
- conns = {{c=3}, {c=11}, {c=6}, {c=14}},
- desc = "60left-45right diagonal crossing",
- tpdouble=true,
- tpsingle=true,
- trackworker="60l60r"
- },
- ["60l60r"]={
- conns = {{c=3}, {c=11}, {c=5}, {c=13}},
- desc = "60left-60right diagonal crossing",
- tpdouble=true,
- tpsingle=true,
- trackworker="60r45l",
- },
- --If 60l60r had a mirror image, it would be here, but it's symmetric.
- -- 60l60r is also equivalent to 30l30r but rotated 90 degrees.
- ["60r45l"]={
- conns = {{c=5}, {c=13}, {c=2}, {c=10}},
- desc = "60right-45left diagonal crossing",
- tpdouble=true,
- tpsingle=true,
- trackworker="60r30r",
- },
- ["60r30r"]={
- conns = {{c=5}, {c=13}, {c=7}, {c=15}},
- desc = "60right-30right diagonal crossing",
- tpdouble=true,
- tpsingle=true,
- trackworker="30r45l",
- },
- ["30r45l"]={
- conns = {{c=7}, {c=15}, {c=2}, {c=10}},
- desc = "30right-45left diagonal crossing",
- tpdouble=true,
- tpsingle=true,
- trackworker="30l45r",
- },
-
- },
- regtp=true,
- tpdefault="30l45r",
- rotation={""},
- trackworker = {
- ["30l45r"] = "60l30l",
- ["60l30l"] = "60l45r",
- ["60l45r"] = "60l60r",
- ["60l60r"] = "60r45l",
- ["60r45l"] = "60r30r",
- ["60r30r"] = "30r45l",
- ["30r45l"] = "30l45r",
- }
-}
-
-advtrains.trackpresets = advtrains.ap
-
---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
-}
-[18.12.17] Note on new connection system:
-In order to support real rail crossing nodes and finally make the trackplacer respect switches, I changed the connection system.
-There can be a variable number of connections available. These are specified as tuples {c=<connection>, y=<rely>}
-The table "at_conns" consists of {<conn1>, <conn2>...}
-the "at_rail_y" property holds the value that was previously called "railheight"
-Depending on the number of connections:
-2 conns: regular rail
-3 conns: switch:
- - when train passes in at conn1, will move out of conn2
- - when train passes in at conn2 or conn3, will move out of conn1
-4 conns: cross (or cross switch, depending on arrangement of conns):
- - conn1 <> conn2
- - conn3 <> conn4
-]]
-
--- Notify the user if digging the rail is not allowed
-local function can_dig_callback(pos, player)
- local ok, reason = advtrains.can_dig_or_modify_track(pos)
- if not ok and player then
- minetest.chat_send_player(player:get_player_name(), attrans("This track can not be removed!") .. " " .. reason)
- end
- return ok
-end
-
-function advtrains.register_tracks(tracktype, def, preset)
- advtrains.trackplacer.register_tracktype(def.nodename_prefix, preset.tpdefault)
- if preset.regtp then
- advtrains.trackplacer.register_track_placer(def.nodename_prefix, def.texture_prefix, def.description, def)
- end
- if preset.regsp then
- advtrains.slope.register_placer(def, preset)
- end
- for suffix, var 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 img_suffix = suffix..rotation
- local ndef = advtrains.merge_tables({
- description=def.description.."("..(var.desc or "any")..rotation..")",
- drawtype = "mesh",
- paramtype="light",
- paramtype2="facedir",
- walkable = false,
- selection_box = {
- type = "fixed",
- fixed = {-1/2-1/16, -1/2, -1/2, 1/2+1/16, -1/2+2/16, 1/2},
- },
-
- mesh = def.shared_model or (def.models_prefix.."_"..img_suffix..def.models_suffix),
- tiles = {def.shared_texture or (def.texture_prefix.."_"..img_suffix..".png"), def.second_texture},
-
- groups = {
- attached_node = advtrains.IGNORE_WORLD and 0 or 1,
- advtrains_track=1,
- ["advtrains_track_"..tracktype]=1,
- save_in_at_nodedb=1,
- dig_immediate=2,
- not_in_creative_inventory=1,
- not_blocking_trains=1,
- },
-
- can_dig = can_dig_callback,
- after_dig_node=function(pos)
- advtrains.ndb.update(pos)
- end,
- after_place_node=function(pos)
- advtrains.ndb.update(pos)
- end,
- at_nnpref = def.nodename_prefix,
- at_suffix = suffix,
- at_rotation = rotation,
- at_rail_y = var.rail_y
- }, def.common or {})
-
- if preset.regtp then
- ndef.drop = def.nodename_prefix.."_placer"
- end
- if preset.regsp and var.slope then
- ndef.drop = def.nodename_prefix.."_slopeplacer"
- end
-
- --connections
- ndef.at_conns = advtrains.rotate_conn_by(var.conns, (rotid-1)*preset.regstep)
-
- local ndef_avt_table
-
- if var.switchalt and var.switchst then
- local switchfunc=function(pos, node, newstate)
- newstate = newstate or var.switchalt -- support for 3 (or more) state switches
- -- this code is only called from the internal setstate function, which
- -- ensures that it is safe to switch the turnout
- if newstate~=var.switchst then
- advtrains.ndb.swap_node(pos, {name=def.nodename_prefix.."_"..(var.switchprefix or "")..newstate..rotation, param2=node.param2})
- advtrains.invalidate_all_paths(pos)
- end
- end
- ndef.on_rightclick = function(pos, node, player)
- if advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
- advtrains.setstate(pos, nil, node)
- advtrains.log("Switch", player:get_player_name(), pos)
- end
- end
- if var.switchmc then
- ndef.mesecons = {effector = {
- ["action_"..var.switchmc] = function(pos, node)
- advtrains.setstate(pos, nil, node)
- end,
- rules=advtrains.meseconrules
- }}
- end
- ndef_avt_table = {
- getstate = var.switchst,
- setstate = switchfunc,
- }
- end
-
- local adef={}
- if def.get_additional_definiton then
- adef=def.get_additional_definiton(def, preset, suffix, rotation)
- end
- ndef = advtrains.merge_tables(ndef, adef)
-
- -- insert getstate/setstate functions after merging the additional definitions
- if ndef_avt_table then
- ndef.advtrains = advtrains.merge_tables(ndef.advtrains or {}, ndef_avt_table)
- end
-
- minetest.register_node(":"..def.nodename_prefix.."_"..suffix..rotation, ndef)
- --trackplacer
- if preset.regtp then
- local tpconns = {conn1=ndef.at_conns[1].c, conn2=ndef.at_conns[2].c}
- if var.tpdouble then
- advtrains.trackplacer.add_double_conn(def.nodename_prefix, suffix, rotation, tpconns)
- end
- if var.tpsingle then
- advtrains.trackplacer.add_single_conn(def.nodename_prefix, suffix, rotation, tpconns)
- end
- end
- advtrains.trackplacer.add_worked(def.nodename_prefix, suffix, rotation, var.trackworker)
- end
- end
- end
- advtrains.all_tracktypes[tracktype]=true
-end
-
-function advtrains.is_track_and_drives_on(nodename, drives_on_p)
- local drives_on = drives_on_p
- if not drives_on then drives_on = advtrains.all_tracktypes end
- local hasentry = false
- for _,_ in pairs(drives_on) do
- hasentry=true
- end
- if not hasentry then drives_on = advtrains.all_tracktypes end
-
- if not minetest.registered_nodes[nodename] then
- return false
- end
- local nodedef=minetest.registered_nodes[nodename]
- for k,v in pairs(drives_on) do
- if nodedef.groups["advtrains_track_"..k] 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 atprint(" get_track_connections couldn't find nodedef for nodename "..(name or "nil")) return nil end
- local noderot=param2
- if not param2 then noderot=0 end
- if noderot > 3 then atprint(" get_track_connections: rail has invaild param2 of "..noderot) noderot=0 end
-
- local tracktype
- for k,_ in pairs(nodedef.groups) do
- local tt=string.match(k, "^advtrains_track_(.+)$")
- if tt then
- tracktype=tt
- end
- end
- return advtrains.rotate_conn_by(nodedef.at_conns, noderot*AT_CMAX/4), (nodedef.at_rail_y or 0), tracktype
-end
-
--- Function called when a track is about to be dug or modified by the trackworker
--- Returns either true (ok) or false,"translated string describing reason why it isn't allowed"
-function advtrains.can_dig_or_modify_track(pos)
- if advtrains.get_train_at_pos(pos) then
- return false, attrans("Position is occupied by a train.")
- end
- -- interlocking: tcb, signal IP a.s.o.
- if advtrains.interlocking then
- -- TCB?
- if advtrains.interlocking.db.get_tcb(pos) then
- return false, attrans("There's a Track Circuit Break here.")
- end
- -- signal ip?
- if advtrains.interlocking.db.is_ip_at(pos, true) then -- is_ip_at with purge parameter
- return false, attrans("There's a Signal Influence Point here.")
- end
- end
- return true
-end
-
--- slope placer. Defined in register_tracks.
---crafted with rail and gravel
-local sl={}
-function sl.register_placer(def, preset)
- minetest.register_craftitem(":"..def.nodename_prefix.."_slopeplacer",{
- description = attrans("@1 Slope", def.description),
- inventory_image = def.texture_prefix.."_slopeplacer.png",
- wield_image = def.texture_prefix.."_slopeplacer.png",
- groups={},
- on_place = sl.create_slopeplacer_on_place(def, preset)
- })
-end
---(itemstack, placer, pointed_thing)
-function sl.create_slopeplacer_on_place(def, preset)
- return function(istack, player, pt)
- if not pt.type=="node" then
- minetest.chat_send_player(player:get_player_name(), attrans("Can't place: not pointing at node"))
- return istack
- end
- local pos=pt.above
- if not pos then
- minetest.chat_send_player(player:get_player_name(), attrans("Can't place: not pointing at node"))
- return istack
- end
- local node=minetest.get_node(pos)
- if not minetest.registered_nodes[node.name] or not minetest.registered_nodes[node.name].buildable_to then
- minetest.chat_send_player(player:get_player_name(), attrans("Can't place: space occupied!"))
- return istack
- end
- if not advtrains.check_track_protection(pos, player:get_player_name()) then
- minetest.record_protection_violation(pos, player:get_player_name())
- return istack
- end
- --determine player orientation (only horizontal component)
- --get_look_horizontal may not be available
- local yaw=player.get_look_horizontal and player:get_look_horizontal() or (player:get_look_yaw() - math.pi/2)
-
- --rounding unit vectors is a nice way for selecting 1 of 8 directions since sin(30°) is 0.5.
- local dirvec={x=math.floor(math.sin(-yaw)+0.5), y=0, z=math.floor(math.cos(-yaw)+0.5)}
- --translate to direction to look up inside the preset table
- local param2, rot45=({
- [-1]={
- [-1]=2,
- [0]=3,
- [1]=3,
- },
- [0]={
- [-1]=2,
- [1]=0,
- },
- [1]={
- [-1]=1,
- [0]=1,
- [1]=0,
- },
- })[dirvec.x][dirvec.z], dirvec.x~=0 and dirvec.z~=0
- local lookup=preset.slopeplacer
- if rot45 then lookup=preset.slopeplacer_45 end
-
- --go unitvector forward and look how far the next node is
- local step=1
- while step<=lookup.max do
- local node=minetest.get_node(vector.add(pos, dirvec))
- --next node solid?
- if not minetest.registered_nodes[node.name] or not minetest.registered_nodes[node.name].buildable_to or advtrains.is_protected(pos, player:get_player_name()) then
- --do slopes of this distance exist?
- if lookup[step] then
- if minetest.settings:get_bool("creative_mode") or istack:get_count()>=step then
- --start placing
- local placenodes=lookup[step]
- while step>0 do
- minetest.set_node(pos, {name=def.nodename_prefix.."_"..placenodes[step], param2=param2})
- if not minetest.settings:get_bool("creative_mode") then
- istack:take_item()
- end
- step=step-1
- pos=vector.subtract(pos, dirvec)
- end
- else
- minetest.chat_send_player(player:get_player_name(), attrans("Can't place: Not enough slope items left (@1 required)", step))
- end
- else
- minetest.chat_send_player(player:get_player_name(), attrans("Can't place: There's no slope of length @1",step))
- end
- return istack
- end
- step=step+1
- pos=vector.add(pos, dirvec)
- end
- minetest.chat_send_player(player:get_player_name(), attrans("Can't place: no supporting node at upper end."))
- return itemstack
- end
-end
-
-advtrains.slope=sl
-
---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
-}]]
-
-
-
-
-
-
-
-
-
+-- tracks.lua
+-- rewritten with advtrains 2.5 according to new track registration system
+
+
+--[[
+
+Tracks in advtrains are defined by the node definition. They must have at least 2 connections, but can have any number.
+Switchable nodes (turnouts, single/double-slip switches) are implemented by having a separate node (node name) for each of the possible states.
+
+ minetest.register_node(nodename, {
+ ... usual node definition ...
+ groups = {
+ advtrains_track = 1,
+ advtrains_track_<tracktype>=1
+ ^- these groups tell that the node is a track
+ not_blocking_trains=1,
+ ^- this group tells that the node should not block trains although it's walkable.
+ },
+
+ at_rail_y = 0,
+ ^- Height of this rail node (the y position of a wagon that stands centered on this rail)
+ at_conns = {
+ [1] = { c=0..15, y=0..1 },
+ [2] = { c=0..15, y=0..1 },
+ ( [3] = { c=0..15, y=0..1 }, )
+ ( [4] = { c=0..15, y=0..1 }, )
+ ( ... )
+ }
+ ^- Connections of this rail. There are two general cases:
+ a) SIMPLE TRACK - the track has exactly 2 connections, and does not feature a turnout, crossing or other contraption
+ For simple tracks, except for the at_conns table no further setup needs to be specified. A train entering on conn 1 will go out at conn 2 and vice versa.
+ A track with only one connection defined is not permitted.
+ b) COMPOUND TRACK - the track has more than 2 connections
+ This will be used for turnouts and crossings. Tracks with more than 2 conns MUST define 'at_conn_map'.
+ Switchable nodes, whose state can be changed (e.g. turnouts) MUST define a 'state_map' within the advtrains table as well.
+ This differs from the behavior up until 2.4.2, where the conn mapping was fixed.
+ ^- Connection definition:
+ - c is the direction of the connection (0-16). For the mapping to world directions see helpers.lua.
+ - Connections will be auto-rotated with param2 of the node (horizontal, param2 values 0-3 only)
+ - y is the height of the connection (rail will only connect when this matches)
+ ^- The index of a connection inside the conns table (1, 2, 3, ...) is referred throughout advtrains code as 'connid'
+ ^- IMPORTANT: For switchable nodes (any kind of turnout), it is crucial that for all of the node's variants the at_conns table stays the same. See below.
+
+ at_conn_map = {
+ [1] = 2,
+ [2] = 1,
+ [3] = 1,
+ }
+ ^- Connection map of this rail. It specifies when a train enters the track on connid X, on which connid it will leave
+ This field MUST be specified when the number of connections in at_conns is greater than 2
+ This field may, and obviously will, vary between nodes for switchable nodes.
+
+ can_dig = advtrains.track_can_dig_callback
+ after_dig_node = advtrains.track_update_callback
+ after_place_node = advtrains.track_update_callback
+ ^- the code in these 3 default minetest API functions is required for advtrains to work, however you can add your own code
+
+ on_rightclick = advtrains.state_node_on_rightclick_callback
+ ^- Must be added if the node is a turnout and if it should be switched by right-click. It will cause the turnout to be switched to next_state.
+
+ advtrains = {
+ on_train_enter=function(pos, train_id, train, index) end
+ ^- called when a train enters the rail
+ on_train_leave=function(pos, train_id, train, index) end
+ ^- called when a train leaves the rail
+
+ -- The following function is only in effect when interlocking is enabled:
+ on_train_approach = function(pos, train_id, train, index, has_entered, lzbdata)
+ ^- called when a train is approaching this position, called exactly once for every path recalculation (which can happen at any time)
+ ^- This is called so that if the train would start braking now, it would come to halt about(wide approx) 5 nodes before the rail.
+ ^- has_entered: when true, the train is already standing on this node with its front tip, and the enter callback has already been called.
+ Possibly, some actions need not to be taken in this case. Only set if it's the very first node the train is standing on.
+ ^- lzbdata should be ignored and nothing should be assigned to it
+
+ -- The following information is required if the node is a turnout (e.g. can be switched into different positions)
+ node_state = "st"
+ ^- The name of the state this node represents
+ ^- Conventions for this field are as follows:
+ - Two-way straight/turn switches: 'st'=straight branch, 'cr'=diverting/turn branch
+ - 3-way turnouts, Y-turnouts: 'l'=left branch, 's'=straight branch, 'r'=right branch
+
+ node_next_state = "cr"
+ ^- The name of the state that the turnout should be switched to when it is right-clicked
+
+ node_fallback_state = "st"
+ ^- The name of the state that the turnout should "fall back" to when it is released
+ Only used by the interlocking system, when a route on the node is released it is switched back to this state.
+
+ node_state_map = {
+ ["st"] = "<node name of the st variant>",
+ ["cr"] = "<node name of the cr variant>",
+ ... etc ...
+ }
+ ^- Map of state name to the appropriate node name that should be set by advtrains when a switch is requested
+ Note that for all of those nodes, the at_conns table must be identical (however the conn_map will vary)
+
+ node_on_switch_state = function(pos, node, oldstate, newstate)
+ ^- Called when the node state is switched by advtrains, after the node replacement has commenced.
+
+ Turnout switching can happen programmatically via advtrains.setstate(pos, state), via user right_click or via the interlocking system.
+ In no other situation is it permissible to exchange track nodes in-place, unless both at_conns and at_conn_map stay identical.
+
+ Note that the fields node_state, node_next_state and node_state_map completely replace the getstate/setstate functions.
+ There must be a one-to-one mapping between states and node names and no function can be defined for state switching.
+ This principle enables the seamless working of the interlocking autorouter and reduces failure points.
+ The node_state_* system can also be used as drop-in replacement for the passive-API-enabled nodes (andrews-cross, mesecon_switch etc.)
+ The advtrains API functions advtrains.getstate() and advtrains.setstate() remain the programmatic access points, but will now utilize the new state system.
+
+
+ trackworker_next_rot = <nodename of next rotation step>,
+ ^- if set, right-click with trackworker will set this node
+ trackworker_rot_incr_param2 = true
+ ^- if set, trackworker will increase node param2 on rightclick
+
+ trackworker_next_var = <nodename of next variant>
+ ^- if set, left-click with trackworker will set this node
+ }
+ })
+
+]]--
+
+-- This file provides some utilities to register tracks, but tries to not get into the way too much
+
+
+function advtrains.track_can_dig_callback(pos, player)
+ local ok, reason = advtrains.can_dig_or_modify_track(pos)
+ if not ok and player then
+ minetest.chat_send_player(player:get_player_name(), attrans("This track can not be removed!") .. " " .. reason)
+ end
+ return ok
+end
+
+function advtrains.track_update_callback(pos)
+ advtrains.ndb.update(pos)
+end
+
+function advtrains.state_node_on_rightclick_callback(pos, node, player)
+ if advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
+ local ndef = minetest.registered_nodes[node.name]
+ if ndef and ndef.advtrains and ndef.advtrains.node_next_state then
+ advtrains.setstate(pos, ndef.advtrains.node_next_state, node)
+ advtrains.log("Switch", player:get_player_name(), pos)
+ end
+ end
+end
+
+-- advtrains.register_node_4rot(name, nodedef)
+-- Registers four rotations for the node defined by nodedef (0°, 30°, 45° and 60°; the 4 90°-steps are already handled by the param2, resulting in 16 directions total).
+-- You must provide the definition for the base node, and certain fields are altered automatically for the 3 additional rotations:
+-- name: appends the suffix "_30", "_45" or "_60"
+-- description: appends the rotation (human-readable) in parenthesis
+-- tiles_prefix: if defined, "tiles" field will be set as prefix..rotationExtension..".png"
+-- mesh_prefix, mesh_suffix: if defined, "mesh" field will be set as prefix..rotationExtension..suffix
+-- at_conns: are rotated according to the node rotation
+-- node_state_map, trackworker_next_var: appends the suffix appropriately.
+-- groups: applies save_in_at_nodedb and not_blocking_trains groups if not already present
+-- The nodes are registered in the trackworker to be rotated with right-click.
+-- definition_mangling_function is an optional parameter. For each of the 4 rotations, it gets passed the modified node definition and may perform final modifications to it.
+-- signature: function definition_mangling_function(name, nodedef, rotationIndex, rotationSuffix)
+-- Example usage: define the setstate function of turnouts (if that is not done via the "automatic" way of state_node_map)
+local rotations = {
+ {i = 0, s = "", h = " (0)", n = "_30"},
+ {i = 1, s = "_30", h = " (30)", n = "_45"},
+ {i = 2, s = "_45", h = " (45)", n = "_60"},
+ {i = 3, s = "_60", h = " (60)", n = ""},
+}
+function advtrains.register_node_4rot(ori_name, ori_ndef, definition_mangling_function)
+ for _, rot in ipairs(rotations) do
+ local ndef = table.copy(ori_ndef)
+ if ori_ndef.advtrains then
+ -- make sure advtrains table is deep-copied because we may need to replace node_state_map
+ ndef.advtrains = table.copy(ori_ndef.advtrains)
+ else
+ ndef.advtrains = {} -- we need the table later for trackworker
+ end
+ -- Perform the name mangling
+ local suffix = rot.s
+ local name = ori_name..suffix
+ ndef.description = ori_ndef.description .. rot.h
+ if ori_ndef.tiles_prefix then
+ ndef.tiles = { ori_ndef.tiles_prefix .. suffix .. ".png" }
+ end
+ if ori_ndef.mesh_prefix then
+ ndef.mesh = ori_ndef.mesh_prefix .. suffix .. ori_ndef.mesh_suffix
+ end
+ -- rotate connections
+ if ori_ndef.at_conns then
+ ndef.at_conns = advtrains.rotate_conn_by(ori_ndef.at_conns, rot.i)
+ end
+ -- update node state map if present
+ if ori_ndef.advtrains then
+ if ori_ndef.advtrains.node_state_map then
+ local new_nsm = {}
+ for state, nname in pairs(ori_ndef.advtrains.node_state_map) do
+ new_nsm[state] = nname .. suffix
+ end
+ ndef.advtrains.node_state_map = new_nsm
+ end
+ if ori_ndef.advtrains.trackworker_next_var then
+ ndef.advtrains.trackworker_next_var = ori_ndef.advtrains.trackworker_next_var .. suffix
+ end
+ -- apply trackworker rot field
+ ndef.advtrains.trackworker_next_rot = ori_name .. rot.n
+ ndef.advtrains.trackworker_rot_incr_param2 = (rot.n=="")
+ end
+ -- apply groups
+ ndef.groups.save_in_at_nodedb = 1
+ ndef.groups.not_blocking_trains = 1
+
+ -- give the definition mangling function an option to do some adjustments
+ if definition_mangling_function then
+ definition_mangling_function(name, ndef, rot.i, suffix)
+ end
+
+ -- register node
+ atdebug("Registering: ",name, ndef)
+ minetest.register_node(":"..name, ndef)
+
+ -- if this has the track_place_group set, register as a candidate for the track_place_group
+ if ndef.advtrains.track_place_group then
+ advtrains.trackplacer.register_candidate(ndef.advtrains.track_place_group, name, ndef, ndef.advtrains.track_place_single, true)
+ end
+ end
+end
+
+
+-- Registers an item to place and automatically connect nearby tracks
+function advtrains.register_track_placer(...)
+
+end
+
+-- Registers an item to place and adjust slope tracks
+function advtrains.register_slope_placer(...)
+
+end
+
+
+
+-- track-related helper functions
+
+function advtrains.is_track(nodename)
+ if not minetest.registered_nodes[nodename] then
+ return false
+ end
+ local nodedef=minetest.registered_nodes[nodename]
+ if nodedef and nodedef.groups.advtrains_track then
+ return true
+ end
+ return false
+end
+
+function advtrains.get_track_connections(name, param2)
+ local nodedef=minetest.registered_nodes[name]
+ if not nodedef then atprint(" get_track_connections couldn't find nodedef for nodename "..(name or "nil")) return nil end
+ local noderot=param2
+ if not param2 then noderot=0 end
+ if noderot > 3 then atprint(" get_track_connections: rail has invaild param2 of "..noderot) noderot=0 end
+
+ local tracktype
+ for k,_ in pairs(nodedef.groups) do
+ local tt=string.match(k, "^advtrains_track_(.+)$")
+ if tt then
+ tracktype=tt
+ end
+ end
+ return advtrains.rotate_conn_by(nodedef.at_conns, noderot*AT_CMAX/4), (nodedef.at_rail_y or 0), tracktype
+end
+
+-- Function called when a track is about to be dug or modified by the trackworker
+-- Returns either true (ok) or false,"translated string describing reason why it isn't allowed"
+function advtrains.can_dig_or_modify_track(pos)
+ if advtrains.get_train_at_pos(pos) then
+ return false, attrans("Position is occupied by a train.")
+ end
+ -- interlocking: tcb, signal IP a.s.o.
+ if advtrains.interlocking then
+ -- TCB?
+ if advtrains.interlocking.db.get_tcb(pos) then
+ return false, attrans("There's a Track Circuit Break here.")
+ end
+ -- signal ip?
+ if advtrains.interlocking.db.is_ip_at(pos, true) then -- is_ip_at with purge parameter
+ return false, attrans("There's a Signal Influence Point here.")
+ end
+ end
+ return true
+end \ No newline at end of file
diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua
index 288e224..c6762c9 100644
--- a/advtrains/trainlogic.lua
+++ b/advtrains/trainlogic.lua
@@ -283,7 +283,7 @@ function advtrains.train_ensure_init(id, train)
assertdef(train, "id", id)
- if not train.drives_on or not train.max_speed then
+ if not train.max_speed then
--atprint("in ensure_init: missing properties, updating!")
advtrains.update_trainpart_properties(id)
end
@@ -1034,10 +1034,9 @@ end
-- Note: safe_decouple_wagon() has been moved to wagons.lua
--- this function sets wagon's pos_in_train(parts) properties and train's max_speed and drives_on (and more)
+-- this function sets wagon's pos_in_train(parts) properties and train's max_speed (and more)
function advtrains.update_trainpart_properties(train_id, invert_flipstate)
local train=advtrains.trains[train_id]
- train.drives_on=advtrains.merge_tables(advtrains.all_tracktypes)
--FIX: deep-copy the table!!!
train.max_speed=20
train.extent_h = 0;
@@ -1079,13 +1078,6 @@ function advtrains.update_trainpart_properties(train_id, invert_flipstate)
end
rel_pos=rel_pos+wagon.wagon_span
- if wagon.drives_on then
- for k,_ in pairs(train.drives_on) do
- if not wagon.drives_on[k] then
- train.drives_on[k]=nil
- end
- end
- end
train.max_speed=math.min(train.max_speed, wagon.max_speed)
train.extent_h = math.max(train.extent_h, wagon.extent_h or 1);
end
diff --git a/advtrains/wagons.lua b/advtrains/wagons.lua
index b0fb575..f231546 100644
--- a/advtrains/wagons.lua
+++ b/advtrains/wagons.lua
@@ -1367,7 +1367,7 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img, nincreati
local node=minetest.get_node_or_nil(pointed_thing.under)
if not node then atprint("[advtrains]Ignore at placer position") return itemstack end
local nodename=node.name
- if(not advtrains.is_track_and_drives_on(nodename, prototype.drives_on)) then
+ if(not advtrains.is_track(nodename)) then
atprint("no track here, not placing.")
return itemstack
end
@@ -1382,7 +1382,7 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img, nincreati
local yaw = placer:get_look_horizontal()
local plconnid = advtrains.yawToClosestConn(yaw, tconns)
- local prevpos = advtrains.get_adjacent_rail(pointed_thing.under, tconns, plconnid, prototype.drives_on)
+ local prevpos = advtrains.get_adjacent_rail(pointed_thing.under, tconns, plconnid)
if not prevpos then
minetest.chat_send_player(pname, "The track you are trying to place the wagon on is not long enough!")
return
@@ -1407,7 +1407,6 @@ advtrains.register_wagon("advtrains:wagon_placeholder", {
collisionbox = {-0.3,-0.3,-0.3, 0.3,0.3,0.3},
visual_size = {x=0.7, y=0.7},
initial_sprite_basepos = {x=0, y=0},
- drives_on = advtrains.all_tracktypes,
max_speed = 5,
seats = {
},
diff --git a/advtrains_interlocking/init.lua b/advtrains_interlocking/init.lua
index a2f5882..cc46b83 100644
--- a/advtrains_interlocking/init.lua
+++ b/advtrains_interlocking/init.lua
@@ -24,7 +24,9 @@ dofile(modpath.."tool.lua")
dofile(modpath.."approach.lua")
dofile(modpath.."ars.lua")
-dofile(modpath.."tsr_rail.lua")
+
+--TODO reenable tsr rail
+--dofile(modpath.."tsr_rail.lua")
minetest.register_privilege("interlocking", {description = "Can set up track sections, routes and signals.", give_to_singleplayer = true})
diff --git a/advtrains_line_automation/init.lua b/advtrains_line_automation/init.lua
index 7b758bc..cc8df3c 100644
--- a/advtrains_line_automation/init.lua
+++ b/advtrains_line_automation/init.lua
@@ -20,7 +20,9 @@ local modpath = minetest.get_modpath(minetest.get_current_modname()) .. DIR_DELI
dofile(modpath.."railwaytime.lua")
dofile(modpath.."scheduler.lua")
-dofile(modpath.."stoprail.lua")
+
+--TODO reenable stop rail
+--dofile(modpath.."stoprail.lua")
function advtrains.lines.load(data)
diff --git a/advtrains_signals_ks/init.lua b/advtrains_signals_ks/init.lua
index bdbd50d..99d059a 100755
--- a/advtrains_signals_ks/init.lua
+++ b/advtrains_signals_ks/init.lua
@@ -113,15 +113,6 @@ local suppasp_ra = {
}
}
-advtrains.trackplacer.register_tracktype("advtrains_signals_ks:hs")
-advtrains.trackplacer.register_tracktype("advtrains_signals_ks:ra")
-advtrains.trackplacer.register_tracktype("advtrains_signals_ks:sign")
-advtrains.trackplacer.register_tracktype("advtrains_signals_ks:sign_lf")
-advtrains.trackplacer.register_tracktype("advtrains_signals_ks:sign_lf7")
-advtrains.trackplacer.register_tracktype("advtrains_signals_ks:zs3")
-advtrains.trackplacer.register_tracktype("advtrains_signals_ks:zs3v")
-advtrains.trackplacer.register_tracktype("advtrains_signals_ks:mast")
-
for _, rtab in ipairs({
{rot = "0", sbox = {-1/8, -1/2, -1/2, 1/8, 1/2, -1/4}, ici=true},
{rot = "30", sbox = {-3/8, -1/2, -1/2, -1/8, 1/2, -1/4},},
@@ -201,7 +192,7 @@ for _, rtab in ipairs({
after_dig_node = advtrains.interlocking.signal_after_dig,
})
-- rotatable by trackworker
- advtrains.trackplacer.add_worked("advtrains_signals_ks:hs", typ, "_"..rot)
+ --TODO add rotation using trackworker
end
@@ -246,7 +237,7 @@ for _, rtab in ipairs({
after_dig_node = advtrains.interlocking.signal_after_dig,
})
-- rotatable by trackworker
- advtrains.trackplacer.add_worked("advtrains_signals_ks:ra", typ, "_"..rot)
+ --TODO add rotation using trackworker
end
-- Schilder:
@@ -283,7 +274,7 @@ for _, rtab in ipairs({
after_dig_node = advtrains.interlocking.signal_after_dig,
})
-- rotatable by trackworker
- advtrains.trackplacer.add_worked("advtrains_signals_ks:"..prefix, typ, "_"..rot, nxt)
+ --TODO add rotation using trackworker
end
for typ, prts in pairs {
@@ -378,7 +369,7 @@ for _, rtab in ipairs({
t.drop = "advtrains_signals_ks:zs3_off_0"
t.selection_box.fixed[1][5] = 0
minetest.register_node("advtrains_signals_ks:zs3_"..typ.."_"..rot, t)
- advtrains.trackplacer.add_worked("advtrains_signals_ks:zs3", typ, "_"..rot)
+ --TODO add rotation using trackworker
-- Zs 3v
local t = table.copy(def)
@@ -387,7 +378,7 @@ for _, rtab in ipairs({
t.drop = "advtrains_signals_ks:zs3v_off_0"
t.tiles[3] = t.tiles[3] .. "^[multiply:yellow"
minetest.register_node("advtrains_signals_ks:zs3v_"..typ.."_"..rot, t)
- advtrains.trackplacer.add_worked("advtrains_signals_ks:zs3v", typ, "_"..rot)
+ --TODO add rotation using trackworker
end
minetest.register_node("advtrains_signals_ks:mast_mast_"..rot, {
@@ -412,7 +403,7 @@ for _, rtab in ipairs({
},
drop = "advtrains_signals_ks:mast_mast_0",
})
- advtrains.trackplacer.add_worked("advtrains_signals_ks:mast","mast", "_"..rot)
+ --TODO add rotation using trackworker
end
-- Crafting
diff --git a/advtrains_train_track/init.lua b/advtrains_train_track/init.lua
index 5065155..55b1367 100755
--- a/advtrains_train_track/init.lua
+++ b/advtrains_train_track/init.lua
@@ -1,937 +1,172 @@
--- Default tracks for advtrains
--- (c) orwell96 and contributors
-
-local default_boxen = {
- ["st"] = {
- [""] = {
- selection_box = {
- type = "fixed",
- fixed = {-1/2-1/16, -1/2, -1/2, 1/2+1/16, -1/2+2/16, 1/2},
- }
- },
- ["_30"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
- {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
- {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
- {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
- }
- }
- },
- ["_45"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750},
- {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
- {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000}
- }
- }
- },
- ["_60"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
- {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
- {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
- {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
- }
- }
- },
- },
-
- ["cr"] = {
- [""] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -0.5000, 0.6875, -0.3750, 0.5000},
- {-0.3750, -0.5000, -1.000, 1.000, -0.3750, 0.000}
- }
- }
- },
- ["_30"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -0.5000, 0.7500, -0.3750, 0.8750},
- {-0.3750, -0.5000, 0.8750, 0.2500, -0.3750, 1.188},
- {0.7500, -0.5000, 0.2500, 1.063, -0.3750, 0.8750}
- }
- }
- },
- ["_45"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -1.125, 0.5000, -0.3750, 0.6875},
- {-0.8750, -0.5000, -0.9375, -0.5000, -0.3750, 0.06250},
- {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}
- }
- }
- },
- ["_60"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.8125, -0.5000, -0.5000, 1.188, -0.3750, 0.5000},
- {-0.1875, -0.5000, 0.5000, 0.8750, -0.3125, 0.8750},
- {-0.2500, -0.5000, -0.9375, 0.3125, -0.3125, -0.5000}
- }
- }
- },
- },
-
- ["swlst"] = {
- [""] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -0.5000, 0.6250, -0.3750, 0.5000},
- {-0.3125, -0.5000, -1.000, 0.9375, -0.3125, -0.06250}
- }
- }
- },
- ["_30"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
- {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
- {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
- {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
- }
- }
- },
- ["_45"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -1.1875, 0.5000, -0.3750, 0.8750},
- {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
- {-0.8750, -0.5000, -0.8125, -0.5000, -0.3750, 0.5000}
- }
- }
- },
- ["_60"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
- {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
- {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
- {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
- }
- }
- },
- },
-
- ["swrst"] = {
- [""] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -0.5000, 0.6250, -0.3750, 0.5000},
- {-0.8125, -0.5000, -1.000, 0.4375, -0.3125, -0.06250}
- }
- }
- },
- ["_30"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
- {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
- {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
- {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
- }
- }
- },
- ["_45"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-1.1875, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
- {-0.5000, -0.5000, 0.5000, 0.5000, -0.3750, 0.8750},
- {-0.8125, -0.5000, -0.8750, 0.5000, -0.3750, -0.5000}
- }
- }
- },
- ["_60"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
- {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
- {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
- {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
- }
- }
- },
- },
-}
-
-default_boxen["swlcr"] = default_boxen["swlst"]
-default_boxen["swrcr"] = default_boxen["swrst"]
-
---flat
-advtrains.register_tracks("default", {
- nodename_prefix="advtrains:dtrack",
- texture_prefix="advtrains_dtrack",
- models_prefix="advtrains_dtrack",
- models_suffix=".b3d",
- shared_texture="advtrains_dtrack_shared.png",
- description=attrans("Track"),
- formats={},
-
- get_additional_definiton = function(def, preset, suffix, rotation)
- if default_boxen[suffix] ~= nil and default_boxen[suffix][rotation] ~= nil then
- return default_boxen[suffix][rotation]
- else
- return {}
- end
- end,
-}, advtrains.ap.t_30deg_flat)
-
-minetest.register_craft({
- output = 'advtrains:dtrack_placer 50',
- recipe = {
- {'default:steel_ingot', 'group:stick', 'default:steel_ingot'},
- {'default:steel_ingot', 'group:stick', 'default:steel_ingot'},
- {'default:steel_ingot', 'group:stick', 'default:steel_ingot'},
- },
-})
-
-local y3_boxen = {
- [""] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.8750, -0.5000, -1.125, 0.8750, -0.3750, 0.4375}
- }
- }
- },
-
- ["_30"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -0.875, 0.5000, -0.3750, 1.000},
- {-0.8750, -0.5000, -0.4375, -0.5000, -0.3750, 0.5625},
- {0.5000, -0.5000, -0.2500, 0.8125, -0.3750, 1.000},
- }
- }
- },
-
- --UX FIXME: - 3way - have to place straight route before l and r or the
- --nodebox overlaps too much and can't place the straight track node.
- ["_45"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -1.1250, 0.5000, -0.3750, 0.8750},
- {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
- {-1.1250, -0.5000, -0.9375, -0.5000, -0.3750, 0.5000}
- }
- }
- },
-
- ["_60"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- --{-0.5000, -0.5000, -0.875, 0.5000, -0.3750, 1.000},
- {-0.875, -0.5000, -0.5, 1.0, -0.3750, 0.5},
- --{-0.8750, -0.5000, -0.4375, -0.5000, -0.3750, 0.5625},
- {-0.4375, -0.5000, -0.8750, 0.5625, -0.3750, -0.5000},
- --{0.5000, -0.5000, -0.2500, 0.8125, -0.3750, 1.000},
- {-0.2500, -0.5000, -0.2500, 1.0000, -0.3750, 0.8125},
- }
- }
- },
-}
-
-
-local function y3_turnouts_addef(def, preset, suffix, rotation)
- return y3_boxen[rotation] or {}
-end
--- y-turnout
-advtrains.register_tracks("default", {
- nodename_prefix="advtrains:dtrack_sy",
- texture_prefix="advtrains_dtrack_sy",
- models_prefix="advtrains_dtrack_sy",
- models_suffix=".obj",
- shared_texture="advtrains_dtrack_shared.png",
- description=attrans("Y-turnout"),
- formats = {},
- get_additional_definiton = y3_turnouts_addef,
-}, advtrains.ap.t_yturnout)
-minetest.register_craft({
- output = 'advtrains:dtrack_sy_placer 2',
- recipe = {
- {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'},
- {'', 'advtrains:dtrack_placer', ''},
- {'', 'advtrains:dtrack_placer', ''},
- },
-})
---3-way turnout
-advtrains.register_tracks("default", {
- nodename_prefix="advtrains:dtrack_s3",
- texture_prefix="advtrains_dtrack_s3",
- models_prefix="advtrains_dtrack_s3",
- models_suffix=".obj",
- shared_texture="advtrains_dtrack_shared.png",
- description=attrans("3-way turnout"),
- formats = {},
- get_additional_definiton = y3_turnouts_addef,
-}, advtrains.ap.t_s3way)
-minetest.register_craft({
- output = 'advtrains:dtrack_s3_placer 1',
- recipe = {
- {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'},
- {'', 'advtrains:dtrack_placer', ''},
- {'', '', ''},
- },
-})
-
--- Diamond Crossings
-
-local perp_boxen = {
- [""] = {}, --default size
- ["_30"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000}
- }
- }
- },
- ["_45"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.8125, -0.5000, -0.8125, 0.8125, -0.3750, 0.8125}
- }
- }
- },
- ["_60"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000}
- }
- }
- },
-}
-
--- perpendicular
-advtrains.register_tracks("default", {
- nodename_prefix="advtrains:dtrack_xing",
- texture_prefix="advtrains_dtrack_xing",
- models_prefix="advtrains_dtrack_xing",
- models_suffix=".obj",
- shared_texture="advtrains_dtrack_shared.png",
- description=attrans("Perpendicular Diamond Crossing Track"),
- formats = {},
- get_additional_definiton = function(def, preset, suffix, rotation)
- return perp_boxen[rotation] or {}
- end
-}, advtrains.ap.t_perpcrossing)
-
-minetest.register_craft({
- output = 'advtrains:dtrack_xing_placer 3',
- recipe = {
- {'', 'advtrains:dtrack_placer', ''},
- {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'},
- {'', 'advtrains:dtrack_placer', ''}
- }
-})
-
-local ninety_plus_boxen = {
- ["30l"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
- {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
- {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
- {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
- }
- }
- },
- ["30r"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {0.5000, -0.5000, -1.000, -0.5000, -0.3750, 1.000},
- {0.8750, -0.5000, -1.000, 0.5000, -0.3750, 0.2500},
- {-0.5000, -0.5000, -0.2500, -0.8750, -0.3750, 1.000},
- {0.1250, -0.5000, -1.375, -0.1875, -0.3750, -1.000}
- }
- }
- },
- ["45l"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750},
- {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
- {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000}
- }
- }
- },
- ["45r"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750},
- {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
- {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000}
- }
- }
- },
- ["60l"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
- {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
- {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
- {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
- }
- }
- },
- ["60r"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000},
- {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000},
- {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750},
- {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875}
- }
- }
- },
-}
-
--- 90plusx
--- When you face east and param2=0, then this set of rails has a rail at 90
--- degrees to the viewer, plus another rail crossing at 30, 45 or 60 degrees.
-advtrains.register_tracks("default", {
- nodename_prefix="advtrains:dtrack_xing90plusx",
- texture_prefix="advtrains_dtrack_xing4590",
- models_prefix="advtrains_dtrack_xing90plusx",
- models_suffix=".obj",
- shared_texture="advtrains_dtrack_shared.png",
- description=attrans("90+Angle Diamond Crossing Track"),
- formats = {},
- get_additional_definiton = function(def, preset, suffix, rotation)
- return ninety_plus_boxen[suffix] or {}
- end,
-}, advtrains.ap.t_90plusx_crossing)
-minetest.register_craft({
- output = 'advtrains:dtrack_xing90plusx_placer 2',
- recipe = {
- {'advtrains:dtrack_placer', '', ''},
- {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'},
- {'', '', 'advtrains:dtrack_placer'}
- }
-})
-
--- Deprecate any rails using the old name scheme
-minetest.register_lbm({
- label = "Upgrade legacy 4590 rails",
- name = "advtrains_train_track:replace_legacy_4590",
- nodenames = {"advtrains:dtrack_xing4590_st"},
- run_at_every_load = true,
- action = function(pos, node)
- minetest.log("actionPos!: " .. pos.x .. "," .. pos.y .. "," .. pos.z)
- minetest.log("node!: " .. node.name .. "," .. node.param1 .. "," .. node.param2)
- advtrains.ndb.swap_node(pos,
- {
- name="advtrains:dtrack_xing90plusx_45l",
- param1=node.param1,
- param2=node.param2,
- })
- end
-})
--- This will replace any items left in the inventory
-minetest.register_alias("advtrains:dtrack_xing4590_placer", "advtrains:dtrack_xing90plusx_placer")
-
-local diagonal_boxen = {
- ["30r45l"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {0.5000, -0.5000, -1.000, -0.5000, -0.3750, 1.000},
- {0.8750, -0.5000, -1.000, 0.5000, -0.3750, 0.2500},
- {-0.5000, -0.5000, -0.2500, -0.8750, -0.3750, 1.000},
- {0.1250, -0.5000, -1.375, -0.1875, -0.3750, -1.000}
- }
- }
- },
- ["60l30l"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
- {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
- {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
- {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
- }
- }
- },
- ["60l60r"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000}
- }
- }
- },
- ["60r30r"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000},
- {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000},
- {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750},
- {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875}
- }
- }
- },
- ["30l45r"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
- {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
- {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
- {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
- }
- }
- },
- ["60l45r"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
- {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
- {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
- {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
- }
- }
- },
- ["60r45l"] = {
- selection_box = {
- type = "fixed",
- fixed = {
- {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000},
- {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000},
- {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750},
- {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875}
- }
- }
- },
-}
-
--- Diagonal
--- This set of rail crossings is named based on the angle of each intersecting
--- direction when facing east and param2=0. Rails with l/r swapped are mirror
--- images. For example, 30r45l is the mirror image of 30l45r.
-advtrains.register_tracks("default", {
- nodename_prefix="advtrains:dtrack_xingdiag",
- texture_prefix="advtrains_dtrack_xingdiag",
- models_prefix="advtrains_dtrack_xingdiag",
- models_suffix=".obj",
- shared_texture="advtrains_dtrack_shared.png",
- description=attrans("Diagonal Diamond Crossing Track"),
- formats = {},
- get_additional_definiton = function(def, preset, suffix, rotation)
- return diagonal_boxen[suffix] or {}
- end,
-}, advtrains.ap.t_diagonalcrossing)
-minetest.register_craft({
- output = 'advtrains:dtrack_xingdiag_placer 2',
- recipe = {
- {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'},
- {'', 'advtrains:dtrack_placer', ''},
- {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'}
- }
-})
----- Not included: very shallow crossings like (30/60)+45.
----- At an angle of only 18.4 degrees, the models would not
----- translate well to a block game.
--- END crossings
-
---slopes
-advtrains.register_tracks("default", {
- nodename_prefix="advtrains:dtrack",
- texture_prefix="advtrains_dtrack",
- models_prefix="advtrains_dtrack",
- models_suffix=".obj",
- shared_texture="advtrains_dtrack_shared.png",
- second_texture="default_gravel.png",
- description=attrans("Track"),
- formats={vst1={true, false, true}, vst2={true, false, true}, vst31={true}, vst32={true}, vst33={true}},
-}, advtrains.ap.t_30deg_slope)
-
-minetest.register_craft({
- type = "shapeless",
- output = 'advtrains:dtrack_slopeplacer 2',
- recipe = {
- "advtrains:dtrack_placer",
- "advtrains:dtrack_placer",
- "default:gravel",
- },
-})
-
-
---bumpers
-advtrains.register_tracks("default", {
- nodename_prefix="advtrains:dtrack_bumper",
- texture_prefix="advtrains_dtrack_bumper",
- models_prefix="advtrains_dtrack_bumper",
- models_suffix=".b3d",
- shared_texture="advtrains_dtrack_rail.png",
- --bumpers still use the old texture until the models are redone.
- description=attrans("Bumper"),
- formats={},
-}, advtrains.ap.t_30deg_straightonly)
-minetest.register_craft({
- output = 'advtrains:dtrack_bumper_placer 2',
- recipe = {
- {'group:wood', 'dye:red'},
- {'default:steel_ingot', 'default:steel_ingot'},
- {'advtrains:dtrack_placer', 'advtrains:dtrack_placer'},
- },
-})
---legacy bumpers
-for _,rot in ipairs({"", "_30", "_45", "_60"}) do
- minetest.register_alias("advtrains:dtrack_bumper"..rot, "advtrains:dtrack_bumper_st"..rot)
-end
--- atc track
-advtrains.register_tracks("default", {
- nodename_prefix="advtrains:dtrack_atc",
- texture_prefix="advtrains_dtrack_atc",
- models_prefix="advtrains_dtrack",
- models_suffix=".b3d",
- shared_texture="advtrains_dtrack_shared_atc.png",
- description=attrans("ATC controller"),
- formats={},
- get_additional_definiton = advtrains.atc_function
-}, advtrains.trackpresets.t_30deg_straightonly)
-
-
--- Tracks for loading and unloading trains
--- Copyright (C) 2017 Gabriel Pérez-Cerezo <gabriel@gpcf.eu>
-
-local function get_far_node(pos)
- local node = minetest.get_node(pos)
- if node.name == "ignore" then
- minetest.get_voxel_manip():read_from_map(pos, pos)
- node = minetest.get_node(pos)
- end
- return node
-end
-
-
-local function show_fc_formspec(pos,player)
- local pname = player:get_player_name()
- if minetest.is_protected(pos,pname) then
- minetest.chat_send_player(pname, "Position is protected!")
- return
- end
-
- local meta = minetest.get_meta(pos)
- local fc = meta:get_string("fc") or ""
-
- local form = 'formspec_version[4]'..
- 'size[10,5]'..
- 'label[0.5,0.4;Advtrains Loading/Unloading Track]'..
- 'label[0.5,1.1;Set the code to match against the wagon\'s freight code]'..
- 'label[0.5,1.6;A blank field matches all wagons (default)]'..
- 'label[0.5,2.1;Use code # to disable the track section]'..
- 'field[0.5,3;5.5,1;fc;FC;'..minetest.formspec_escape(fc)..']'..
- 'button[6.5,3;3,1;save;Submit]'
- minetest.show_formspec(pname, "at_load_unload_"..advtrains.encode_pos(pos), form)
-end
-
-minetest.register_on_player_receive_fields(function(player, formname, fields)
- local pname = player:get_player_name()
- local pe = string.match(formname, "^at_load_unload_(............)$")
- local pos = advtrains.decode_pos(pe)
- if pos then
- if minetest.is_protected(pos, pname) then
- minetest.chat_send_player(pname, "Position is protected!")
- return
- end
-
- if fields.save then
- minetest.get_meta(pos):set_string("fc",tostring(fields.fc))
- minetest.chat_send_player(pname,"Freight code set: "..tostring(fields.fc))
- show_fc_formspec(pos,player)
- end
- end
-end)
-
-
-local function train_load(pos, train_id, unload)
- local train=advtrains.trains[train_id]
- local below = get_far_node({x=pos.x, y=pos.y-1, z=pos.z})
- if not string.match(below.name, "chest") then
- atprint("this is not a chest! at "..minetest.pos_to_string(pos))
- return
- end
-
- local node_fc = minetest.get_meta(pos):get_string("fc") or ""
- if node_fc == "#" then
- --track section is disabled
- return
- end
-
- local inv = minetest.get_inventory({type="node", pos={x=pos.x, y=pos.y-1, z=pos.z}})
- if inv and train.velocity < 2 then
- for k, v in ipairs(train.trainparts) do
- local i=minetest.get_inventory({type="detached", name="advtrains_wgn_"..v})
- if i and i:get_list("box") then
-
- local wagon_data = advtrains.wagons[v]
- local wagon_fc
- if wagon_data.fc then
- if not wagon_data.fcind then wagon_data.fcind = 1 end
- wagon_fc = tostring(wagon_data.fc[wagon_data.fcind]) or ""
- end
-
- if node_fc == "" or wagon_fc == node_fc then
- if not unload then
- for _, item in ipairs(inv:get_list("main")) do
- if i:get_list("box") and i:room_for_item("box", item) then
- i:add_item("box", item)
- inv:remove_item("main", item)
- end
- end
- else
- for _, item in ipairs(i:get_list("box")) do
- if inv:get_list("main") and inv:room_for_item("main", item) then
- i:remove_item("box", item)
- inv:add_item("main", item)
- end
- end
- end
- end
- end
- end
- end
-end
-
-
-
-advtrains.register_tracks("default", {
- nodename_prefix="advtrains:dtrack_unload",
- texture_prefix="advtrains_dtrack_unload",
- models_prefix="advtrains_dtrack",
- models_suffix=".b3d",
- shared_texture="advtrains_dtrack_shared_unload.png",
- description=attrans("Unloading Track"),
- formats={},
- get_additional_definiton = function(def, preset, suffix, rotation)
- return {
- after_dig_node=function(pos)
- advtrains.invalidate_all_paths()
- advtrains.ndb.clear(pos)
- end,
- on_rightclick = function(pos, node, player)
- show_fc_formspec(pos, player)
- end,
- advtrains = {
- on_train_enter = function(pos, train_id)
- train_load(pos, train_id, true)
- end,
- },
- }
- end
- }, advtrains.trackpresets.t_30deg_straightonly)
-advtrains.register_tracks("default", {
- nodename_prefix="advtrains:dtrack_load",
- texture_prefix="advtrains_dtrack_load",
- models_prefix="advtrains_dtrack",
- models_suffix=".b3d",
- shared_texture="advtrains_dtrack_shared_load.png",
- description=attrans("Loading Track"),
- formats={},
- get_additional_definiton = function(def, preset, suffix, rotation)
- return {
- after_dig_node=function(pos)
- advtrains.invalidate_all_paths()
- advtrains.ndb.clear(pos)
- end,
- on_rightclick = function(pos, node, player)
- show_fc_formspec(pos, player)
- end,
- advtrains = {
- on_train_enter = function(pos, train_id)
- train_load(pos, train_id, false)
- end,
- },
- }
- end
- }, advtrains.trackpresets.t_30deg_straightonly)
-
--- mod-dependent crafts
-local loader_core = "default:mese_crystal" --fallback
-if minetest.get_modpath("basic_materials") then
- loader_core = "basic_materials:ic"
-elseif minetest.get_modpath("technic") then
- loader_core = "technic:control_logic_unit"
-end
---print("Loader Core: "..loader_core)
-
-minetest.register_craft({
- type="shapeless",
- output = 'advtrains:dtrack_load_placer',
- recipe = {
- "advtrains:dtrack_placer",
- loader_core,
- "default:chest"
- },
-})
-loader_core = nil --nil the crafting variable
-
---craft between load/unload tracks
-minetest.register_craft({
- type="shapeless",
- output = 'advtrains:dtrack_unload_placer',
- recipe = {
- "advtrains:dtrack_load_placer",
- },
-})
-minetest.register_craft({
- type="shapeless",
- output = 'advtrains:dtrack_load_placer',
- recipe = {
- "advtrains:dtrack_unload_placer",
- },
-})
-
-
-if mesecon then
- advtrains.register_tracks("default", {
- nodename_prefix="advtrains:dtrack_detector_off",
- texture_prefix="advtrains_dtrack_detector",
- models_prefix="advtrains_dtrack",
- models_suffix=".b3d",
- shared_texture="advtrains_dtrack_shared_detector_off.png",
- description=attrans("Detector Rail"),
- formats={},
- get_additional_definiton = function(def, preset, suffix, rotation)
- return {
- mesecons = {
- receptor = {
- state = mesecon.state.off,
- rules = advtrains.meseconrules
- }
- },
- advtrains = {
- on_updated_from_nodedb = function(pos, node)
- mesecon.receptor_off(pos, advtrains.meseconrules)
- end,
- on_train_enter=function(pos, train_id)
- advtrains.ndb.swap_node(pos, {name="advtrains:dtrack_detector_on".."_"..suffix..rotation, param2=advtrains.ndb.get_node(pos).param2})
- if advtrains.is_node_loaded(pos) then
- mesecon.receptor_on(pos, advtrains.meseconrules)
- end
- end
- }
- }
- end
- }, advtrains.ap.t_30deg_straightonly)
- advtrains.register_tracks("default", {
- nodename_prefix="advtrains:dtrack_detector_on",
- texture_prefix="advtrains_dtrack",
- models_prefix="advtrains_dtrack",
- models_suffix=".b3d",
- shared_texture="advtrains_dtrack_shared_detector_on.png",
- description="Detector(on)(you hacker you)",
- formats={},
- get_additional_definiton = function(def, preset, suffix, rotation)
- return {
- mesecons = {
- receptor = {
- state = mesecon.state.on,
- rules = advtrains.meseconrules
- }
- },
- advtrains = {
- on_updated_from_nodedb = function(pos, node)
- mesecon.receptor_on(pos, advtrains.meseconrules)
- end,
- on_train_leave=function(pos, train_id)
- advtrains.ndb.swap_node(pos, {name="advtrains:dtrack_detector_off".."_"..suffix..rotation, param2=advtrains.ndb.get_node(pos).param2})
- if advtrains.is_node_loaded(pos) then
- mesecon.receptor_off(pos, advtrains.meseconrules)
- end
- end
- }
- }
- end
- }, advtrains.ap.t_30deg_straightonly_noplacer)
-minetest.register_craft({
- type="shapeless",
- output = 'advtrains:dtrack_detector_off_placer',
- recipe = {
- "advtrains:dtrack_placer",
- "mesecons:wire_00000000_off"
- },
-})
-end
---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
-
-if advtrains.register_replacement_lbms then
-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,
-})
- 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
+-- advtrains_train_track
+-- rewritten to work with advtrains 2.5 track system
+
+local function conns(c1, c2, r1, r2) return {{c=c1, y=r1}, {c=c2, y=r2}} end
+local function conns3(c1, c2, c3, r1, r2, r3) return {{c=c1, y=r1}, {c=c2, y=r2}, {c=c3, y=r3}} end
+
+
+local common_def = {
+ drawtype = "mesh",
+ paramtype = "light",
+ paramtype2 = "facedir",
+ walkable = false,
+ selection_box = {
+ type = "fixed",
+ fixed = {-1/2-1/16, -1/2, -1/2, 1/2+1/16, -1/2+2/16, 1/2},
+ },
+
+ mesh_suffix = ".b3d",
+ tiles = { "advtrains_dtrack_shared.png" },
+
+ groups = {
+ advtrains_track=1,
+ advtrains_track_default=1,
+ dig_immediate=2,
+ --not_in_creative_inventory=1,
+ },
+
+ can_dig = advtrains.track_can_dig_callback,
+ after_dig_node = advtrains.track_update_callback,
+ after_place_node = advtrains.track_update_callback,
+
+ drop = "advtrains:dtrack_placer"
+}
+
+-- Normal tracks, straight and curved
+advtrains.register_node_4rot("advtrains:dtrack_st",
+ advtrains.merge_tables(common_def, {
+ description=attrans("Track Straight"),
+ mesh_prefix="advtrains_dtrack_st",
+ at_conns = conns(0,8),
+ advtrains = {
+ trackworker_next_var = "advtrains:dtrack_cr",
+ track_place_group = "advtrains:dtrack",
+ track_place_single = true,
+ },
+ })
+)
+
+advtrains.register_node_4rot("advtrains:dtrack_cr",
+ advtrains.merge_tables(common_def, {
+ description=attrans("Track Curve"),
+ mesh_prefix="advtrains_dtrack_cr",
+ at_conns = conns(0,7),
+ advtrains = {
+ trackworker_next_var = "advtrains:dtrack_swlst",
+ track_place_group = "advtrains:dtrack",
+ },
+ })
+)
+
+-- simple turnouts left and right
+
+local stm_left = {
+ st = "advtrains:dtrack_swlst",
+ cr = "advtrains:dtrack_swlcr",
+}
+
+advtrains.register_node_4rot("advtrains:dtrack_swlst",
+ advtrains.merge_tables(common_def, {
+ description=attrans("Track Turnout Left Straight"),
+ mesh_prefix="advtrains_dtrack_swlst",
+ at_conns = conns3(0,8,7),
+ at_conn_map = {2,1,1},
+ on_rightclick = advtrains.state_node_on_rightclick_callback,
+ advtrains = {
+ node_state = "st",
+ node_next_state = "cr",
+ node_state_map = stm_left,
+ trackworker_next_var = "advtrains:dtrack_swrst"
+ },
+ })
+)
+
+advtrains.register_node_4rot("advtrains:dtrack_swlcr",
+ advtrains.merge_tables(common_def, {
+ description=attrans("Track Turnout Left Curve"),
+ mesh_prefix="advtrains_dtrack_swlcr",
+ at_conns = conns3(0,8,7), -- note: conns must stay identical
+ at_conn_map = {3,1,1}, -- now points to curve branch
+ on_rightclick = advtrains.state_node_on_rightclick_callback,
+ advtrains = {
+ node_state = "cr",
+ node_next_state = "st",
+ node_state_map = stm_left,
+ trackworker_next_var = "advtrains:dtrack_swrcr"
+ },
+ })
+)
+
+local stm_right = {
+ st = "advtrains:dtrack_swrst",
+ cr = "advtrains:dtrack_swrcr",
+}
+
+advtrains.register_node_4rot("advtrains:dtrack_swrst",
+ advtrains.merge_tables(common_def, {
+ description=attrans("Track Turnout Right Straight"),
+ mesh_prefix="advtrains_dtrack_swrst",
+ at_conns = conns3(0,8,9),
+ at_conn_map = {2,1,1},
+ on_rightclick = advtrains.state_node_on_rightclick_callback,
+ advtrains = {
+ node_state = "st",
+ node_next_state = "cr",
+ node_state_map = stm_right,
+ trackworker_next_var = "advtrains:dtrack_st"
+ },
+ })
+)
+
+advtrains.register_node_4rot("advtrains:dtrack_swrcr",
+ advtrains.merge_tables(common_def, {
+ description=attrans("Track Turnout Right Curve"),
+ mesh_prefix="advtrains_dtrack_swrcr",
+ at_conns = conns3(0,8,9), -- note: conns must stay identical
+ at_conn_map = {3,1,1}, -- now points to curve branch
+ on_rightclick = advtrains.state_node_on_rightclick_callback,
+ advtrains = {
+ node_state = "cr",
+ node_next_state = "st",
+ node_state_map = stm_right,
+ trackworker_next_var = "advtrains:dtrack_st"
+ },
+ })
+)
+
+-- register placer item
+minetest.register_craftitem(":advtrains:dtrack_placer", {
+ description = attrans("Track"),
+ inventory_image = "advtrains_dtrack_placer.png",
+ wield_image = "advtrains_dtrack_placer.png",
+ groups={advtrains_trackplacer=1, digtron_on_place=1},
+ liquids_pointable = false,
+ on_place = function(itemstack, placer, pointed_thing)
+ local name = placer:get_player_name()
+ if not name then
+ return itemstack, false
+ end
+ if pointed_thing.type=="node" then
+ local pos=pointed_thing.above
+ local upos=vector.subtract(pointed_thing.above, {x=0, y=1, z=0})
+ if not advtrains.check_track_protection(pos, name) then
+ return itemstack, false
+ end
+ if minetest.registered_nodes[minetest.get_node(pos).name] and minetest.registered_nodes[minetest.get_node(pos).name].buildable_to then
+ local s = minetest.registered_nodes[minetest.get_node(upos).name] and minetest.registered_nodes[minetest.get_node(upos).name].walkable
+ if s then
+-- minetest.chat_send_all(nnprefix)
+ local yaw = placer:get_look_horizontal()
+ advtrains.trackplacer.place_track(pos, "advtrains:dtrack", name, yaw)
+ if not advtrains.is_creative(name) then
+ itemstack:take_item()
+ end
+ end
+ end
+ end
+ return itemstack, true
+ end,
+})
+
+
+--TODO restore mesecons! \ No newline at end of file
diff --git a/advtrains_train_track/oldinit.lua b/advtrains_train_track/oldinit.lua
new file mode 100644
index 0000000..5065155
--- /dev/null
+++ b/advtrains_train_track/oldinit.lua
@@ -0,0 +1,937 @@
+-- Default tracks for advtrains
+-- (c) orwell96 and contributors
+
+local default_boxen = {
+ ["st"] = {
+ [""] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {-1/2-1/16, -1/2, -1/2, 1/2+1/16, -1/2+2/16, 1/2},
+ }
+ },
+ ["_30"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
+ {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
+ {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
+ {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
+ }
+ }
+ },
+ ["_45"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750},
+ {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
+ {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000}
+ }
+ }
+ },
+ ["_60"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
+ {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
+ {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
+ {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
+ }
+ }
+ },
+ },
+
+ ["cr"] = {
+ [""] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -0.5000, 0.6875, -0.3750, 0.5000},
+ {-0.3750, -0.5000, -1.000, 1.000, -0.3750, 0.000}
+ }
+ }
+ },
+ ["_30"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -0.5000, 0.7500, -0.3750, 0.8750},
+ {-0.3750, -0.5000, 0.8750, 0.2500, -0.3750, 1.188},
+ {0.7500, -0.5000, 0.2500, 1.063, -0.3750, 0.8750}
+ }
+ }
+ },
+ ["_45"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -1.125, 0.5000, -0.3750, 0.6875},
+ {-0.8750, -0.5000, -0.9375, -0.5000, -0.3750, 0.06250},
+ {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}
+ }
+ }
+ },
+ ["_60"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.8125, -0.5000, -0.5000, 1.188, -0.3750, 0.5000},
+ {-0.1875, -0.5000, 0.5000, 0.8750, -0.3125, 0.8750},
+ {-0.2500, -0.5000, -0.9375, 0.3125, -0.3125, -0.5000}
+ }
+ }
+ },
+ },
+
+ ["swlst"] = {
+ [""] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -0.5000, 0.6250, -0.3750, 0.5000},
+ {-0.3125, -0.5000, -1.000, 0.9375, -0.3125, -0.06250}
+ }
+ }
+ },
+ ["_30"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
+ {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
+ {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
+ {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
+ }
+ }
+ },
+ ["_45"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -1.1875, 0.5000, -0.3750, 0.8750},
+ {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
+ {-0.8750, -0.5000, -0.8125, -0.5000, -0.3750, 0.5000}
+ }
+ }
+ },
+ ["_60"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
+ {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
+ {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
+ {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
+ }
+ }
+ },
+ },
+
+ ["swrst"] = {
+ [""] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -0.5000, 0.6250, -0.3750, 0.5000},
+ {-0.8125, -0.5000, -1.000, 0.4375, -0.3125, -0.06250}
+ }
+ }
+ },
+ ["_30"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
+ {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
+ {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
+ {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
+ }
+ }
+ },
+ ["_45"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-1.1875, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
+ {-0.5000, -0.5000, 0.5000, 0.5000, -0.3750, 0.8750},
+ {-0.8125, -0.5000, -0.8750, 0.5000, -0.3750, -0.5000}
+ }
+ }
+ },
+ ["_60"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
+ {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
+ {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
+ {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
+ }
+ }
+ },
+ },
+}
+
+default_boxen["swlcr"] = default_boxen["swlst"]
+default_boxen["swrcr"] = default_boxen["swrst"]
+
+--flat
+advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack",
+ texture_prefix="advtrains_dtrack",
+ models_prefix="advtrains_dtrack",
+ models_suffix=".b3d",
+ shared_texture="advtrains_dtrack_shared.png",
+ description=attrans("Track"),
+ formats={},
+
+ get_additional_definiton = function(def, preset, suffix, rotation)
+ if default_boxen[suffix] ~= nil and default_boxen[suffix][rotation] ~= nil then
+ return default_boxen[suffix][rotation]
+ else
+ return {}
+ end
+ end,
+}, advtrains.ap.t_30deg_flat)
+
+minetest.register_craft({
+ output = 'advtrains:dtrack_placer 50',
+ recipe = {
+ {'default:steel_ingot', 'group:stick', 'default:steel_ingot'},
+ {'default:steel_ingot', 'group:stick', 'default:steel_ingot'},
+ {'default:steel_ingot', 'group:stick', 'default:steel_ingot'},
+ },
+})
+
+local y3_boxen = {
+ [""] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.8750, -0.5000, -1.125, 0.8750, -0.3750, 0.4375}
+ }
+ }
+ },
+
+ ["_30"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -0.875, 0.5000, -0.3750, 1.000},
+ {-0.8750, -0.5000, -0.4375, -0.5000, -0.3750, 0.5625},
+ {0.5000, -0.5000, -0.2500, 0.8125, -0.3750, 1.000},
+ }
+ }
+ },
+
+ --UX FIXME: - 3way - have to place straight route before l and r or the
+ --nodebox overlaps too much and can't place the straight track node.
+ ["_45"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -1.1250, 0.5000, -0.3750, 0.8750},
+ {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
+ {-1.1250, -0.5000, -0.9375, -0.5000, -0.3750, 0.5000}
+ }
+ }
+ },
+
+ ["_60"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ --{-0.5000, -0.5000, -0.875, 0.5000, -0.3750, 1.000},
+ {-0.875, -0.5000, -0.5, 1.0, -0.3750, 0.5},
+ --{-0.8750, -0.5000, -0.4375, -0.5000, -0.3750, 0.5625},
+ {-0.4375, -0.5000, -0.8750, 0.5625, -0.3750, -0.5000},
+ --{0.5000, -0.5000, -0.2500, 0.8125, -0.3750, 1.000},
+ {-0.2500, -0.5000, -0.2500, 1.0000, -0.3750, 0.8125},
+ }
+ }
+ },
+}
+
+
+local function y3_turnouts_addef(def, preset, suffix, rotation)
+ return y3_boxen[rotation] or {}
+end
+-- y-turnout
+advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack_sy",
+ texture_prefix="advtrains_dtrack_sy",
+ models_prefix="advtrains_dtrack_sy",
+ models_suffix=".obj",
+ shared_texture="advtrains_dtrack_shared.png",
+ description=attrans("Y-turnout"),
+ formats = {},
+ get_additional_definiton = y3_turnouts_addef,
+}, advtrains.ap.t_yturnout)
+minetest.register_craft({
+ output = 'advtrains:dtrack_sy_placer 2',
+ recipe = {
+ {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'},
+ {'', 'advtrains:dtrack_placer', ''},
+ {'', 'advtrains:dtrack_placer', ''},
+ },
+})
+--3-way turnout
+advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack_s3",
+ texture_prefix="advtrains_dtrack_s3",
+ models_prefix="advtrains_dtrack_s3",
+ models_suffix=".obj",
+ shared_texture="advtrains_dtrack_shared.png",
+ description=attrans("3-way turnout"),
+ formats = {},
+ get_additional_definiton = y3_turnouts_addef,
+}, advtrains.ap.t_s3way)
+minetest.register_craft({
+ output = 'advtrains:dtrack_s3_placer 1',
+ recipe = {
+ {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'},
+ {'', 'advtrains:dtrack_placer', ''},
+ {'', '', ''},
+ },
+})
+
+-- Diamond Crossings
+
+local perp_boxen = {
+ [""] = {}, --default size
+ ["_30"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000}
+ }
+ }
+ },
+ ["_45"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.8125, -0.5000, -0.8125, 0.8125, -0.3750, 0.8125}
+ }
+ }
+ },
+ ["_60"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000}
+ }
+ }
+ },
+}
+
+-- perpendicular
+advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack_xing",
+ texture_prefix="advtrains_dtrack_xing",
+ models_prefix="advtrains_dtrack_xing",
+ models_suffix=".obj",
+ shared_texture="advtrains_dtrack_shared.png",
+ description=attrans("Perpendicular Diamond Crossing Track"),
+ formats = {},
+ get_additional_definiton = function(def, preset, suffix, rotation)
+ return perp_boxen[rotation] or {}
+ end
+}, advtrains.ap.t_perpcrossing)
+
+minetest.register_craft({
+ output = 'advtrains:dtrack_xing_placer 3',
+ recipe = {
+ {'', 'advtrains:dtrack_placer', ''},
+ {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'},
+ {'', 'advtrains:dtrack_placer', ''}
+ }
+})
+
+local ninety_plus_boxen = {
+ ["30l"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
+ {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
+ {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
+ {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
+ }
+ }
+ },
+ ["30r"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {0.5000, -0.5000, -1.000, -0.5000, -0.3750, 1.000},
+ {0.8750, -0.5000, -1.000, 0.5000, -0.3750, 0.2500},
+ {-0.5000, -0.5000, -0.2500, -0.8750, -0.3750, 1.000},
+ {0.1250, -0.5000, -1.375, -0.1875, -0.3750, -1.000}
+ }
+ }
+ },
+ ["45l"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750},
+ {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
+ {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000}
+ }
+ }
+ },
+ ["45r"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750},
+ {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
+ {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000}
+ }
+ }
+ },
+ ["60l"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
+ {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
+ {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
+ {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
+ }
+ }
+ },
+ ["60r"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000},
+ {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000},
+ {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750},
+ {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875}
+ }
+ }
+ },
+}
+
+-- 90plusx
+-- When you face east and param2=0, then this set of rails has a rail at 90
+-- degrees to the viewer, plus another rail crossing at 30, 45 or 60 degrees.
+advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack_xing90plusx",
+ texture_prefix="advtrains_dtrack_xing4590",
+ models_prefix="advtrains_dtrack_xing90plusx",
+ models_suffix=".obj",
+ shared_texture="advtrains_dtrack_shared.png",
+ description=attrans("90+Angle Diamond Crossing Track"),
+ formats = {},
+ get_additional_definiton = function(def, preset, suffix, rotation)
+ return ninety_plus_boxen[suffix] or {}
+ end,
+}, advtrains.ap.t_90plusx_crossing)
+minetest.register_craft({
+ output = 'advtrains:dtrack_xing90plusx_placer 2',
+ recipe = {
+ {'advtrains:dtrack_placer', '', ''},
+ {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'},
+ {'', '', 'advtrains:dtrack_placer'}
+ }
+})
+
+-- Deprecate any rails using the old name scheme
+minetest.register_lbm({
+ label = "Upgrade legacy 4590 rails",
+ name = "advtrains_train_track:replace_legacy_4590",
+ nodenames = {"advtrains:dtrack_xing4590_st"},
+ run_at_every_load = true,
+ action = function(pos, node)
+ minetest.log("actionPos!: " .. pos.x .. "," .. pos.y .. "," .. pos.z)
+ minetest.log("node!: " .. node.name .. "," .. node.param1 .. "," .. node.param2)
+ advtrains.ndb.swap_node(pos,
+ {
+ name="advtrains:dtrack_xing90plusx_45l",
+ param1=node.param1,
+ param2=node.param2,
+ })
+ end
+})
+-- This will replace any items left in the inventory
+minetest.register_alias("advtrains:dtrack_xing4590_placer", "advtrains:dtrack_xing90plusx_placer")
+
+local diagonal_boxen = {
+ ["30r45l"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {0.5000, -0.5000, -1.000, -0.5000, -0.3750, 1.000},
+ {0.8750, -0.5000, -1.000, 0.5000, -0.3750, 0.2500},
+ {-0.5000, -0.5000, -0.2500, -0.8750, -0.3750, 1.000},
+ {0.1250, -0.5000, -1.375, -0.1875, -0.3750, -1.000}
+ }
+ }
+ },
+ ["60l30l"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
+ {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
+ {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
+ {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
+ }
+ }
+ },
+ ["60l60r"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000}
+ }
+ }
+ },
+ ["60r30r"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000},
+ {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000},
+ {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750},
+ {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875}
+ }
+ }
+ },
+ ["30l45r"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
+ {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
+ {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
+ {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
+ }
+ }
+ },
+ ["60l45r"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
+ {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
+ {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
+ {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
+ }
+ }
+ },
+ ["60r45l"] = {
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000},
+ {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000},
+ {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750},
+ {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875}
+ }
+ }
+ },
+}
+
+-- Diagonal
+-- This set of rail crossings is named based on the angle of each intersecting
+-- direction when facing east and param2=0. Rails with l/r swapped are mirror
+-- images. For example, 30r45l is the mirror image of 30l45r.
+advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack_xingdiag",
+ texture_prefix="advtrains_dtrack_xingdiag",
+ models_prefix="advtrains_dtrack_xingdiag",
+ models_suffix=".obj",
+ shared_texture="advtrains_dtrack_shared.png",
+ description=attrans("Diagonal Diamond Crossing Track"),
+ formats = {},
+ get_additional_definiton = function(def, preset, suffix, rotation)
+ return diagonal_boxen[suffix] or {}
+ end,
+}, advtrains.ap.t_diagonalcrossing)
+minetest.register_craft({
+ output = 'advtrains:dtrack_xingdiag_placer 2',
+ recipe = {
+ {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'},
+ {'', 'advtrains:dtrack_placer', ''},
+ {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'}
+ }
+})
+---- Not included: very shallow crossings like (30/60)+45.
+---- At an angle of only 18.4 degrees, the models would not
+---- translate well to a block game.
+-- END crossings
+
+--slopes
+advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack",
+ texture_prefix="advtrains_dtrack",
+ models_prefix="advtrains_dtrack",
+ models_suffix=".obj",
+ shared_texture="advtrains_dtrack_shared.png",
+ second_texture="default_gravel.png",
+ description=attrans("Track"),
+ formats={vst1={true, false, true}, vst2={true, false, true}, vst31={true}, vst32={true}, vst33={true}},
+}, advtrains.ap.t_30deg_slope)
+
+minetest.register_craft({
+ type = "shapeless",
+ output = 'advtrains:dtrack_slopeplacer 2',
+ recipe = {
+ "advtrains:dtrack_placer",
+ "advtrains:dtrack_placer",
+ "default:gravel",
+ },
+})
+
+
+--bumpers
+advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack_bumper",
+ texture_prefix="advtrains_dtrack_bumper",
+ models_prefix="advtrains_dtrack_bumper",
+ models_suffix=".b3d",
+ shared_texture="advtrains_dtrack_rail.png",
+ --bumpers still use the old texture until the models are redone.
+ description=attrans("Bumper"),
+ formats={},
+}, advtrains.ap.t_30deg_straightonly)
+minetest.register_craft({
+ output = 'advtrains:dtrack_bumper_placer 2',
+ recipe = {
+ {'group:wood', 'dye:red'},
+ {'default:steel_ingot', 'default:steel_ingot'},
+ {'advtrains:dtrack_placer', 'advtrains:dtrack_placer'},
+ },
+})
+--legacy bumpers
+for _,rot in ipairs({"", "_30", "_45", "_60"}) do
+ minetest.register_alias("advtrains:dtrack_bumper"..rot, "advtrains:dtrack_bumper_st"..rot)
+end
+-- atc track
+advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack_atc",
+ texture_prefix="advtrains_dtrack_atc",
+ models_prefix="advtrains_dtrack",
+ models_suffix=".b3d",
+ shared_texture="advtrains_dtrack_shared_atc.png",
+ description=attrans("ATC controller"),
+ formats={},
+ get_additional_definiton = advtrains.atc_function
+}, advtrains.trackpresets.t_30deg_straightonly)
+
+
+-- Tracks for loading and unloading trains
+-- Copyright (C) 2017 Gabriel Pérez-Cerezo <gabriel@gpcf.eu>
+
+local function get_far_node(pos)
+ local node = minetest.get_node(pos)
+ if node.name == "ignore" then
+ minetest.get_voxel_manip():read_from_map(pos, pos)
+ node = minetest.get_node(pos)
+ end
+ return node
+end
+
+
+local function show_fc_formspec(pos,player)
+ local pname = player:get_player_name()
+ if minetest.is_protected(pos,pname) then
+ minetest.chat_send_player(pname, "Position is protected!")
+ return
+ end
+
+ local meta = minetest.get_meta(pos)
+ local fc = meta:get_string("fc") or ""
+
+ local form = 'formspec_version[4]'..
+ 'size[10,5]'..
+ 'label[0.5,0.4;Advtrains Loading/Unloading Track]'..
+ 'label[0.5,1.1;Set the code to match against the wagon\'s freight code]'..
+ 'label[0.5,1.6;A blank field matches all wagons (default)]'..
+ 'label[0.5,2.1;Use code # to disable the track section]'..
+ 'field[0.5,3;5.5,1;fc;FC;'..minetest.formspec_escape(fc)..']'..
+ 'button[6.5,3;3,1;save;Submit]'
+ minetest.show_formspec(pname, "at_load_unload_"..advtrains.encode_pos(pos), form)
+end
+
+minetest.register_on_player_receive_fields(function(player, formname, fields)
+ local pname = player:get_player_name()
+ local pe = string.match(formname, "^at_load_unload_(............)$")
+ local pos = advtrains.decode_pos(pe)
+ if pos then
+ if minetest.is_protected(pos, pname) then
+ minetest.chat_send_player(pname, "Position is protected!")
+ return
+ end
+
+ if fields.save then
+ minetest.get_meta(pos):set_string("fc",tostring(fields.fc))
+ minetest.chat_send_player(pname,"Freight code set: "..tostring(fields.fc))
+ show_fc_formspec(pos,player)
+ end
+ end
+end)
+
+
+local function train_load(pos, train_id, unload)
+ local train=advtrains.trains[train_id]
+ local below = get_far_node({x=pos.x, y=pos.y-1, z=pos.z})
+ if not string.match(below.name, "chest") then
+ atprint("this is not a chest! at "..minetest.pos_to_string(pos))
+ return
+ end
+
+ local node_fc = minetest.get_meta(pos):get_string("fc") or ""
+ if node_fc == "#" then
+ --track section is disabled
+ return
+ end
+
+ local inv = minetest.get_inventory({type="node", pos={x=pos.x, y=pos.y-1, z=pos.z}})
+ if inv and train.velocity < 2 then
+ for k, v in ipairs(train.trainparts) do
+ local i=minetest.get_inventory({type="detached", name="advtrains_wgn_"..v})
+ if i and i:get_list("box") then
+
+ local wagon_data = advtrains.wagons[v]
+ local wagon_fc
+ if wagon_data.fc then
+ if not wagon_data.fcind then wagon_data.fcind = 1 end
+ wagon_fc = tostring(wagon_data.fc[wagon_data.fcind]) or ""
+ end
+
+ if node_fc == "" or wagon_fc == node_fc then
+ if not unload then
+ for _, item in ipairs(inv:get_list("main")) do
+ if i:get_list("box") and i:room_for_item("box", item) then
+ i:add_item("box", item)
+ inv:remove_item("main", item)
+ end
+ end
+ else
+ for _, item in ipairs(i:get_list("box")) do
+ if inv:get_list("main") and inv:room_for_item("main", item) then
+ i:remove_item("box", item)
+ inv:add_item("main", item)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+
+
+advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack_unload",
+ texture_prefix="advtrains_dtrack_unload",
+ models_prefix="advtrains_dtrack",
+ models_suffix=".b3d",
+ shared_texture="advtrains_dtrack_shared_unload.png",
+ description=attrans("Unloading Track"),
+ formats={},
+ get_additional_definiton = function(def, preset, suffix, rotation)
+ return {
+ after_dig_node=function(pos)
+ advtrains.invalidate_all_paths()
+ advtrains.ndb.clear(pos)
+ end,
+ on_rightclick = function(pos, node, player)
+ show_fc_formspec(pos, player)
+ end,
+ advtrains = {
+ on_train_enter = function(pos, train_id)
+ train_load(pos, train_id, true)
+ end,
+ },
+ }
+ end
+ }, advtrains.trackpresets.t_30deg_straightonly)
+advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack_load",
+ texture_prefix="advtrains_dtrack_load",
+ models_prefix="advtrains_dtrack",
+ models_suffix=".b3d",
+ shared_texture="advtrains_dtrack_shared_load.png",
+ description=attrans("Loading Track"),
+ formats={},
+ get_additional_definiton = function(def, preset, suffix, rotation)
+ return {
+ after_dig_node=function(pos)
+ advtrains.invalidate_all_paths()
+ advtrains.ndb.clear(pos)
+ end,
+ on_rightclick = function(pos, node, player)
+ show_fc_formspec(pos, player)
+ end,
+ advtrains = {
+ on_train_enter = function(pos, train_id)
+ train_load(pos, train_id, false)
+ end,
+ },
+ }
+ end
+ }, advtrains.trackpresets.t_30deg_straightonly)
+
+-- mod-dependent crafts
+local loader_core = "default:mese_crystal" --fallback
+if minetest.get_modpath("basic_materials") then
+ loader_core = "basic_materials:ic"
+elseif minetest.get_modpath("technic") then
+ loader_core = "technic:control_logic_unit"
+end
+--print("Loader Core: "..loader_core)
+
+minetest.register_craft({
+ type="shapeless",
+ output = 'advtrains:dtrack_load_placer',
+ recipe = {
+ "advtrains:dtrack_placer",
+ loader_core,
+ "default:chest"
+ },
+})
+loader_core = nil --nil the crafting variable
+
+--craft between load/unload tracks
+minetest.register_craft({
+ type="shapeless",
+ output = 'advtrains:dtrack_unload_placer',
+ recipe = {
+ "advtrains:dtrack_load_placer",
+ },
+})
+minetest.register_craft({
+ type="shapeless",
+ output = 'advtrains:dtrack_load_placer',
+ recipe = {
+ "advtrains:dtrack_unload_placer",
+ },
+})
+
+
+if mesecon then
+ advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack_detector_off",
+ texture_prefix="advtrains_dtrack_detector",
+ models_prefix="advtrains_dtrack",
+ models_suffix=".b3d",
+ shared_texture="advtrains_dtrack_shared_detector_off.png",
+ description=attrans("Detector Rail"),
+ formats={},
+ get_additional_definiton = function(def, preset, suffix, rotation)
+ return {
+ mesecons = {
+ receptor = {
+ state = mesecon.state.off,
+ rules = advtrains.meseconrules
+ }
+ },
+ advtrains = {
+ on_updated_from_nodedb = function(pos, node)
+ mesecon.receptor_off(pos, advtrains.meseconrules)
+ end,
+ on_train_enter=function(pos, train_id)
+ advtrains.ndb.swap_node(pos, {name="advtrains:dtrack_detector_on".."_"..suffix..rotation, param2=advtrains.ndb.get_node(pos).param2})
+ if advtrains.is_node_loaded(pos) then
+ mesecon.receptor_on(pos, advtrains.meseconrules)
+ end
+ end
+ }
+ }
+ end
+ }, advtrains.ap.t_30deg_straightonly)
+ advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack_detector_on",
+ texture_prefix="advtrains_dtrack",
+ models_prefix="advtrains_dtrack",
+ models_suffix=".b3d",
+ shared_texture="advtrains_dtrack_shared_detector_on.png",
+ description="Detector(on)(you hacker you)",
+ formats={},
+ get_additional_definiton = function(def, preset, suffix, rotation)
+ return {
+ mesecons = {
+ receptor = {
+ state = mesecon.state.on,
+ rules = advtrains.meseconrules
+ }
+ },
+ advtrains = {
+ on_updated_from_nodedb = function(pos, node)
+ mesecon.receptor_on(pos, advtrains.meseconrules)
+ end,
+ on_train_leave=function(pos, train_id)
+ advtrains.ndb.swap_node(pos, {name="advtrains:dtrack_detector_off".."_"..suffix..rotation, param2=advtrains.ndb.get_node(pos).param2})
+ if advtrains.is_node_loaded(pos) then
+ mesecon.receptor_off(pos, advtrains.meseconrules)
+ end
+ end
+ }
+ }
+ end
+ }, advtrains.ap.t_30deg_straightonly_noplacer)
+minetest.register_craft({
+ type="shapeless",
+ output = 'advtrains:dtrack_detector_off_placer',
+ recipe = {
+ "advtrains:dtrack_placer",
+ "mesecons:wire_00000000_off"
+ },
+})
+end
+--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
+
+if advtrains.register_replacement_lbms then
+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,
+})
+ 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