aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authororwell96 <mono96.mml@gmail.com>2017-01-04 12:02:00 +0100
committerorwell96 <mono96.mml@gmail.com>2017-01-04 12:02:00 +0100
commit853a9e690eeeb48aa1a13faa66db0a91d5b49390 (patch)
tree51451d08e10cedda4128c1e29848524a00baf2a7
parenta9d43ce2ca3bfd703428d248c0839e53ffd76f27 (diff)
downloadadvtrains-853a9e690eeeb48aa1a13faa66db0a91d5b49390.tar.gz
advtrains-853a9e690eeeb48aa1a13faa66db0a91d5b49390.tar.bz2
advtrains-853a9e690eeeb48aa1a13faa66db0a91d5b49390.zip
Add Automatic Train Control system
-rw-r--r--advtrains/api_doc.txt2
-rw-r--r--advtrains/atc.lua292
-rw-r--r--advtrains/atc_command.txt68
-rw-r--r--advtrains/models/advtrains_dtrack_detector_st.b3dbin17157 -> 17157 bytes
-rw-r--r--advtrains/models/advtrains_dtrack_detector_st_30.b3dbin32779 -> 32779 bytes
-rw-r--r--advtrains/models/advtrains_dtrack_detector_st_45.b3dbin17163 -> 17163 bytes
-rw-r--r--advtrains/models/advtrains_dtrack_detector_st_60.b3dbin32779 -> 32779 bytes
-rw-r--r--advtrains/models/blender/gleis/detectorpart.pngbin0 -> 857 bytes
-rw-r--r--advtrains/models/blender/gleis/rail_my_rt_final.blendbin1094836 -> 1015668 bytes
-rw-r--r--advtrains/models/blender/gleis/rail_my_rt_final.blend1bin827052 -> 1106004 bytes
-rw-r--r--advtrains/textures/advtrains_dtrack_atc_placer.pngbin0 -> 1259 bytes
-rw-r--r--advtrains/textures/advtrains_dtrack_placer.pngbin5831 -> 1097 bytes
-rw-r--r--advtrains/textures/advtrains_dtrack_rail.pngbin2810 -> 2814 bytes
-rw-r--r--advtrains/textures/advtrains_dtrack_rail_atc.pngbin0 -> 2837 bytes
-rw-r--r--advtrains/textures/advtrains_dtrack_rail_detector_on.pngbin2844 -> 2818 bytes
-rw-r--r--advtrains/trackplacer.lua25
-rw-r--r--advtrains/tracks.lua38
-rw-r--r--advtrains/trainhud.lua2
-rw-r--r--advtrains/trainlogic.lua21
19 files changed, 424 insertions, 24 deletions
diff --git a/advtrains/api_doc.txt b/advtrains/api_doc.txt
index 22132c3..6b1aa2e 100644
--- a/advtrains/api_doc.txt
+++ b/advtrains/api_doc.txt
@@ -103,7 +103,7 @@ minetest.register_node(nodename, {
after_place_node=function(pos)
advtrains.reset_trackdb_position(pos)
end,
- ^- the code in these 3 functions is required for advtrains to work.
+ ^- the code in these 3 default minetest API functions is required for advtrains to work, however you can add your own code
advtrains = {
on_train_enter=function(pos, train_id) end
diff --git a/advtrains/atc.lua b/advtrains/atc.lua
index 0afddb0..f070b20 100644
--- a/advtrains/atc.lua
+++ b/advtrains/atc.lua
@@ -1,4 +1,294 @@
--atc.lua
--registers and controls the ATC system
---(simple)mesecon detector rails
+local atc={}
+-- ATC persistence table
+atc.controllers = {}
+--contents: {command="...", arrowconn=0-15 where arrow points}
+
+advtrains.fpath_atc=minetest.get_worldpath().."/advtrains_atc"
+local file, err = io.open(advtrains.fpath_atc, "r")
+if not file then
+ local er=err or "Unknown Error"
+ print("[advtrains]Failed loading advtrains atc save file "..er)
+else
+ local tbl = minetest.deserialize(file:read("*a"))
+ if type(tbl) == "table" then
+ atc.controllers=tbl.controllers
+ end
+ file:close()
+end
+function atc.save()
+ --leave space for more save data.
+ local datastr = minetest.serialize({controllers = atc.controllers})
+ if not datastr then
+ minetest.log("error", "[advtrains] Failed to serialize trackdb data!")
+ return
+ end
+ local file, err = io.open(advtrains.fpath_atc, "w")
+ if err then
+ return err
+ end
+ file:write(datastr)
+ file:close()
+end
+
+--call from advtrains.detector subprogram
+
+function atc.trigger_controller_train_enter(pos, train_id)
+ atc.send_command(pos)
+end
+
+--general
+
+function atc.send_command(pos)
+ local pts=minetest.pos_to_string(pos)
+ if atc.controllers[pts] then
+ print("Called send_command at "..pts)
+ local train_id = advtrains.detector.on_node[pts]
+ if train_id then
+ if advtrains.trains[train_id] then
+ print("send_command inside if: "..sid(train_id))
+ atc.train_reset_command(train_id)
+ local arrowconn=atc.controllers[pts].arrowconn
+ local train=advtrains.trains[train_id]
+ for index, ppos in pairs(train.path) do
+ if vector.equals(advtrains.round_vector_floor_y(ppos), pos) then
+ advtrains.trains[train_id].atc_arrow =
+ vector.equals(
+ advtrains.dirCoordSet(pos, arrowconn),
+ advtrains.round_vector_floor_y(train.path[index+train.movedir])
+ )
+ advtrains.trains[train_id].atc_command=atc.controllers[pts].command
+ print("Sending ATC Command: "..atc.controllers[pts].command)
+ end
+ end
+ end
+ end
+ end
+ return false
+end
+
+function atc.train_reset_command(train_id)
+ advtrains.trains[train_id].atc_command=nil
+ advtrains.trains[train_id].atc_delay=0
+ advtrains.trains[train_id].atc_brake_target=nil
+ advtrains.trains[train_id].atc_wait_finish=nil
+ advtrains.trains[train_id].atc_arrow=nil
+end
+
+--nodes
+local idxtrans={static=1, mesecon=2, digiline=3}
+local apn_func=function(pos)
+ advtrains.reset_trackdb_position(pos)
+ local meta=minetest.get_meta(pos)
+ if meta then
+ meta:set_string("infotext", "ATC controller, unconfigured.")
+ meta:set_string("formspec", atc.get_atc_controller_formspec(pos, meta))
+ end
+end
+
+advtrains.register_tracks("default", {
+ nodename_prefix="advtrains:dtrack_atc",
+ texture_prefix="advtrains_dtrack_atc",
+ models_prefix="advtrains_dtrack_detector",
+ models_suffix=".b3d",
+ shared_texture="advtrains_dtrack_rail_atc.png",
+ description="ATC controller",
+ formats={},
+ get_additional_definiton = function(def, preset, suffix, rotation)
+ return {
+ after_place_node=apn_func,
+ on_place_rail=apn_func,
+ after_dig_node=function(pos)
+ advtrains.invalidate_all_paths()
+ advtrains.reset_trackdb_position(pos)
+ local pts=minetest.pos_to_string(pos)
+ atc.controllers[pts]=nil
+ end,
+ on_receive_fields = function(pos, formname, fields, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ minetest.chat_send_player(player:get_player_name(), "This position is protected!")
+ return
+ end
+ local meta=minetest.get_meta(pos)
+ if meta then
+ if not fields.save then
+ --maybe only the dropdown changed
+ if fields.mode then
+ meta:set_string("mode", idxtrans[fields.mode])
+ meta:set_string("infotext", "ATC controller, mode "..fields.mode.."\n"..( fields.mode=="digiline" and "Channel: "..meta:get_string("channel") or "Command: "..meta:get_string("command") ) )
+ meta:set_string("formspec", atc.get_atc_controller_formspec(pos, meta))
+ end
+ return
+ end
+ meta:set_string("mode", idxtrans[fields.mode])
+ meta:set_string("command", fields.command)
+ meta:set_string("command_on", fields.command_on)
+ meta:set_string("channel", fields.channel)
+ meta:set_string("infotext", "ATC controller, mode "..fields.mode.."\n"..( fields.mode=="digiline" and "Channel: "..meta:get_string("channel") or "Command: "..meta:get_string("command") ) )
+ meta:set_string("formspec", atc.get_atc_controller_formspec(pos, meta))
+
+ local pts=minetest.pos_to_string(pos)
+ local _, conn1=advtrains.get_rail_info_at(pos, advtrains.all_tracktypes)
+ atc.controllers[pts]={command=fields.command, arrowconn=conn1}
+ atc.send_command(pos)
+ end
+ end,
+ }
+ end
+}, advtrains.trackpresets.t_30deg_straightonly)
+
+
+function atc.get_atc_controller_formspec(pos, meta)
+ local mode=tonumber(meta:get_string("mode")) or 1
+ local command=meta:get_string("command")
+ local command_on=meta:get_string("command_on")
+ local channel=meta:get_string("channel")
+ local formspec="size[8,6]"..
+ "dropdown[0,0;3;mode;static,mesecon,digiline;"..mode.."]"
+ if mode<3 then
+ formspec=formspec.."field[0.5,1.5;7,1;command;Command;"..minetest.formspec_escape(command).."]"
+ if tonumber(mode)==2 then
+ formspec=formspec.."field[0.5,3;7,1;command_on;Command (on);"..minetest.formspec_escape(command_on).."]"
+ end
+ else
+ formspec=formspec.."field[0.5,1.5;7,1;channel;Digiline channel;"..minetest.formspec_escape(channel).."]"
+ end
+ return formspec.."button_exit[0.5,4.5;7,1;save;Save]"
+end
+
+--from trainlogic.lua train step
+local matchptn={
+ ["SM"]=function(id, train)
+ train.tarvelocity=train.max_speed
+ return 2
+ end,
+ ["S([0-9]+)"]=function(id, train, match)
+ train.tarvelocity=tonumber(match)
+ return #match+1
+ end,
+ ["B([0-9]+)"]=function(id, train, match)
+ if train.velocity>tonumber(match) then
+ train.atc_brake_target=tonumber(match)
+ if train.tarvelocity>train.atc_brake_target then
+ train.tarvelocity=train.atc_brake_target
+ end
+ end
+ return #match+1
+ end,
+ ["W"]=function(id, train)
+ train.atc_wait_finish=true
+ return 1
+ end,
+ ["D([0-9]+)"]=function(id, train, match)
+ train.atc_delay=tonumber(match)
+ return #match+1
+ end,
+ ["R"]=function(id, train)
+ if train.velocity<=0 then
+ train.movedir=train.movedir*-1
+ train.atc_arrow = not train.atc_arrow
+ else
+ print("ATC Reverse command warning: didn't reverse train!")
+ end
+ return 1
+ end,
+}
+
+function atc.execute_atc_command(id, train)
+ --strip whitespaces
+ local command=string.match(train.atc_command, "^%s*(.*)$")
+
+
+ if string.match(command, "^%s*$") then
+ train.atc_command=nil
+ return
+ end
+ --conditional statement?
+ local is_cond, cond_applies
+ local cond, rest=string.match(command, "^I([%+%-])(.+)$")
+ if cond then
+ is_cond=true
+ if cond=="+" then
+ cond_applies=train.atc_arrow
+ end
+ if cond=="-" then
+ cond_applies=not train.atc_arrow
+ end
+ else
+ cond, compare, rest=string.match(command, "^I([<>]=?)([0-9]+)(.+)$")
+ if cond and compare then
+ is_cond=true
+ if cond=="<" then
+ cond_applies=train.velocity<tonumber(compare)
+ end
+ if cond==">" then
+ cond_applies=train.velocity>tonumber(compare)
+ end
+ if cond=="<=" then
+ cond_applies=train.velocity<=tonumber(compare)
+ end
+ if cond==">=" then
+ cond_applies=train.velocity>=tonumber(compare)
+ end
+ end
+ end
+ if is_cond then
+ print("Evaluating if statement: "..command)
+ print("Cond: "..(cond or "nil"))
+ print("Applies: "..(cond_applies and "true" or "false"))
+ print("Rest: "..rest)
+ --find end of conditional statement
+ local nest, pos, elsepos=0, 1
+ while nest>=0 do
+ if pos>#rest then
+ print("ATC command syntax error: I statement not closed: "..command)
+ atc.train_reset_command(id)
+ return
+ end
+ local char=string.sub(rest, pos, pos)
+ if char=="I" then
+ nest=nest+1
+ end
+ if char==";" then
+ nest=nest-1
+ end
+ if nest==0 and char=="E" then
+ elsepos=pos+0
+ end
+ pos=pos+1
+ end
+ if not elsepos then elsepos=pos-1 end
+ if cond_applies then
+ command=string.sub(rest, 1, elsepos-1)..string.sub(rest, pos)
+ else
+ command=string.sub(rest, elsepos+1, pos-2)..string.sub(rest, pos)
+ end
+ print("Result: "..command)
+ train.atc_command=command
+ atc.execute_atc_command(id, train)
+ return
+ else
+ for pattern, func in pairs(matchptn) do
+ local match=string.match(command, "^"..pattern)
+ if match then
+ local patlen=func(id, train, match)
+
+ print("Executing: "..string.sub(command, 1, patlen))
+
+ train.atc_command=string.sub(command, patlen+1)
+ if train.atc_delay<=0 and not train.atc_wait_finish then
+ --continue (recursive, cmds shouldn't get too long, and it's a end-recursion.)
+ atc.execute_atc_command(id, train)
+ end
+ return
+ end
+ end
+ end
+ print("ATC command parse error: "..command)
+ atc.train_reset_command(id)
+end
+
+--move table to desired place
+advtrains.atc=atc
diff --git a/advtrains/atc_command.txt b/advtrains/atc_command.txt
new file mode 100644
index 0000000..fa846e3
--- /dev/null
+++ b/advtrains/atc_command.txt
@@ -0,0 +1,68 @@
+ATC Command Syntax
+
+A train runs the current ATC command once it receives it, including delayed instructions. If the train receives a new command, the current command is discarded.
+Spaces can be inserted into commands as needed and are ignored.
+
+# simple commands:
+
+S<[0-9]+ speed or 'M'>
+Set target speed of train to <speed>. Accelerates if slower, rolls if faster. 'M' means maximum speed.
+Execution of command continues immediately.
+
+B<[0-9]+ speed>
+Brake until speed is reached. If faster, apply brakes, if slower, do nothing.
+Execution of command continues immediately.
+
+Examples:
+SM : accelerate to maximum speed
+S0 : roll to stand
+B0 : brake to stand
+S0B3 or B3S0: brake to 3, then roll to stand.
+
+W
+Wait until S and/or B commands reached the desired speed before continuing execution.
+
+D<[0-9]+ time>
+Delay: Wait for time seconds before continuing execution.
+
+R
+Reverse: change movement direction of train. ONLY WORKS WHEN TRAIN STANDS, else no-op.
+Use B0WR to definitely change direction.
+
+Examples:
+B0 W R D10 SM
+Subway train stopping in dead end station and returning in opposite direction
+
+# conditional statements:
+
+I<condition><code>;
+Execute code only if condition applies
+I<condition><code1>E<code2>;
+Execute code1 only if condition applies, else execute code2
+
+Conditions:
++ / -
+Tests the train's movement direction against the arrow on the ATC rail: M+ is true when train drives in direction of arrow.
+
+[</>/<=/>=][speed]
+Test if train's speed is greater or smaller than the given value
+
+Examples:
+I- B0 W R ; S8
+If the train drives in the 'wrong' direction, stop and reverse; independently accelerate to speed 8 afterwards.
+
+I<8 S8 ;
+If the train is slower than 8, accelerate to 8.
+
+# ATC controller operation modes
+static: Only give 1 static command.
+mesecon: Give 2 different commands depending on if the controller is mesecon-powered or not
+digiline: Don't give any commands by itself. When a train passes, a digiline message in the form of "[+/-][speed]" is sent on the set channel (where +/- means the same as with conditions). Any digiline message sent to the controller will be interpreted as ATC command and sent to the train.
+
+# Persistence
+ATC controllers that are configured as 'static' or 'mesecon' are persistent over mapblock unloads and will even command the train when the mapblock is unloaded. This is not possible with digilines since these do not work in unloaded mapchunks.
+
+# LUA ATC controller (in development)
+The LUA ATC Controller will operate by using LUA code. All operations shown above will have a function equivalent. Additionally all LUA ATC controllers share an environment and setting signal and switch status will be possible to allow for complicated railway systems/fully automated subways a.s.o.
+Also planned:
+- digicompute add-on to allow computer access to the ATC environment (railway maps... ... ... ... ...)
diff --git a/advtrains/models/advtrains_dtrack_detector_st.b3d b/advtrains/models/advtrains_dtrack_detector_st.b3d
index 893c8cd..6762bc3 100644
--- a/advtrains/models/advtrains_dtrack_detector_st.b3d
+++ b/advtrains/models/advtrains_dtrack_detector_st.b3d
Binary files differ
diff --git a/advtrains/models/advtrains_dtrack_detector_st_30.b3d b/advtrains/models/advtrains_dtrack_detector_st_30.b3d
index 2e59e93..f2d5991 100644
--- a/advtrains/models/advtrains_dtrack_detector_st_30.b3d
+++ b/advtrains/models/advtrains_dtrack_detector_st_30.b3d
Binary files differ
diff --git a/advtrains/models/advtrains_dtrack_detector_st_45.b3d b/advtrains/models/advtrains_dtrack_detector_st_45.b3d
index c73166f..9ecb4a6 100644
--- a/advtrains/models/advtrains_dtrack_detector_st_45.b3d
+++ b/advtrains/models/advtrains_dtrack_detector_st_45.b3d
Binary files differ
diff --git a/advtrains/models/advtrains_dtrack_detector_st_60.b3d b/advtrains/models/advtrains_dtrack_detector_st_60.b3d
index b6bc9af..bd102cb 100644
--- a/advtrains/models/advtrains_dtrack_detector_st_60.b3d
+++ b/advtrains/models/advtrains_dtrack_detector_st_60.b3d
Binary files differ
diff --git a/advtrains/models/blender/gleis/detectorpart.png b/advtrains/models/blender/gleis/detectorpart.png
new file mode 100644
index 0000000..fc24181
--- /dev/null
+++ b/advtrains/models/blender/gleis/detectorpart.png
Binary files differ
diff --git a/advtrains/models/blender/gleis/rail_my_rt_final.blend b/advtrains/models/blender/gleis/rail_my_rt_final.blend
index 6a9a088..d07a65d 100644
--- a/advtrains/models/blender/gleis/rail_my_rt_final.blend
+++ b/advtrains/models/blender/gleis/rail_my_rt_final.blend
Binary files differ
diff --git a/advtrains/models/blender/gleis/rail_my_rt_final.blend1 b/advtrains/models/blender/gleis/rail_my_rt_final.blend1
index 1f346ae..8a2d213 100644
--- a/advtrains/models/blender/gleis/rail_my_rt_final.blend1
+++ b/advtrains/models/blender/gleis/rail_my_rt_final.blend1
Binary files differ
diff --git a/advtrains/textures/advtrains_dtrack_atc_placer.png b/advtrains/textures/advtrains_dtrack_atc_placer.png
new file mode 100644
index 0000000..31c2b30
--- /dev/null
+++ b/advtrains/textures/advtrains_dtrack_atc_placer.png
Binary files differ
diff --git a/advtrains/textures/advtrains_dtrack_placer.png b/advtrains/textures/advtrains_dtrack_placer.png
index c49777c..7bef8a9 100644
--- a/advtrains/textures/advtrains_dtrack_placer.png
+++ b/advtrains/textures/advtrains_dtrack_placer.png
Binary files differ
diff --git a/advtrains/textures/advtrains_dtrack_rail.png b/advtrains/textures/advtrains_dtrack_rail.png
index 568e533..1cf7f83 100644
--- a/advtrains/textures/advtrains_dtrack_rail.png
+++ b/advtrains/textures/advtrains_dtrack_rail.png
Binary files differ
diff --git a/advtrains/textures/advtrains_dtrack_rail_atc.png b/advtrains/textures/advtrains_dtrack_rail_atc.png
new file mode 100644
index 0000000..d171985
--- /dev/null
+++ b/advtrains/textures/advtrains_dtrack_rail_atc.png
Binary files differ
diff --git a/advtrains/textures/advtrains_dtrack_rail_detector_on.png b/advtrains/textures/advtrains_dtrack_rail_detector_on.png
index 3ae0dac..4f09b35 100644
--- a/advtrains/textures/advtrains_dtrack_rail_detector_on.png
+++ b/advtrains/textures/advtrains_dtrack_rail_detector_on.png
Binary files differ
diff --git a/advtrains/trackplacer.lua b/advtrains/trackplacer.lua
index eebf2ae..b24103a 100644
--- a/advtrains/trackplacer.lua
+++ b/advtrains/trackplacer.lua
@@ -129,7 +129,7 @@ function tp.bend_rail(originpos, conn, nnpref)
return false
end
end
-function tp.placetrack(pos, nnpref)
+function tp.placetrack(pos, nnpref, placer, itemstack, pointed_thing)
--1. find all rails that are likely to be connected
local tr=tp.tracks[nnpref]
local p_rails={}
@@ -140,9 +140,16 @@ function tp.placetrack(pos, nnpref)
end
if #p_rails==0 then
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
elseif #p_rails==1 then
tp.bend_rail(pos, p_rails[1], nnpref)
minetest.set_node(pos, tr.single_conn[p_rails[1]])
+ local nname=tr.single_conn[p_rails[1]].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
else
--iterate subsets
for k1, conn1 in ipairs(p_rails) do
@@ -152,6 +159,10 @@ function tp.placetrack(pos, nnpref)
tp.bend_rail(pos, conn1, nnpref)
tp.bend_rail(pos, conn2, nnpref)
minetest.set_node(pos, tr.double_conn[conn1.."_"..conn2])
+ local nname=tr.double_conn[conn1.."_"..conn2].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
end
@@ -160,6 +171,10 @@ function tp.placetrack(pos, nnpref)
--not found
tp.bend_rail(pos, p_rails[1], nnpref)
minetest.set_node(pos, tr.single_conn[p_rails[1]])
+ local nname=tr.single_conn[p_rails[1]].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
end
end
@@ -183,7 +198,7 @@ function tp.register_track_placer(nnprefix, imgprefix, dispname)
end
if minetest.registered_nodes[minetest.get_node(pos).name] and minetest.registered_nodes[minetest.get_node(pos).name].buildable_to
and minetest.registered_nodes[minetest.get_node(upos).name] and minetest.registered_nodes[minetest.get_node(upos).name].walkable then
- tp.placetrack(pos, nnprefix)
+ tp.placetrack(pos, nnprefix, placer, itemstack, pointed_thing)
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
@@ -230,7 +245,7 @@ minetest.register_craftitem("advtrains:trackworker",{
local modext=tp.tracks[nnprefix].twrotate[suffix]
if rotation==modext[#modext] then --increase param2
- minetest.set_node(pos, {name=nnprefix.."_"..suffix..modext[1], param2=(node.param2+1)%4})
+ minetest.swap_node(pos, {name=nnprefix.."_"..suffix..modext[1], param2=(node.param2+1)%4})
return
else
local modpos
@@ -239,7 +254,7 @@ minetest.register_craftitem("advtrains:trackworker",{
minetest.chat_send_player(placer:get_player_name(), "This node can't be rotated using the trackworker!")
return
end
- minetest.set_node(pos, {name=nnprefix.."_"..suffix..modext[modpos+1], param2=node.param2})
+ minetest.swap_node(pos, {name=nnprefix.."_"..suffix..modext[modpos+1], param2=node.param2})
end
advtrains.invalidate_all_paths()
end
@@ -269,7 +284,7 @@ minetest.register_craftitem("advtrains:trackworker",{
end
end
local nextsuffix=tp.tracks[nnprefix].twcycle[suffix]
- minetest.set_node(pos, {name=nnprefix.."_"..nextsuffix..rotation, param2=node.param2})
+ minetest.swap_node(pos, {name=nnprefix.."_"..nextsuffix..rotation, param2=node.param2})
--invalidate trains
advtrains.invalidate_all_paths()
else
diff --git a/advtrains/tracks.lua b/advtrains/tracks.lua
index 07883c5..beb0bbc 100644
--- a/advtrains/tracks.lua
+++ b/advtrains/tracks.lua
@@ -36,7 +36,8 @@ advtrains.all_tracktypes={}
--definition preparation
local function conns(c1, c2, r1, r2, rh, rots) return {conn1=c1, conn2=c2, rely1=r1, rely2=r2, railheight=rh} end
-local t_30deg={
+local ap={}
+ap.t_30deg={
regstep=1,
variant={
st=conns(0,8),
@@ -110,7 +111,7 @@ local t_30deg={
rotation={"", "_30", "_45", "_60"},
increativeinv={},
}
-local t_30deg_straightonly={
+ap.t_30deg_straightonly={
regstep=1,
variant={
st=conns(0,8),
@@ -135,7 +136,7 @@ local t_30deg_straightonly={
rotation={"", "_30", "_45", "_60"},
increativeinv={st},
}
-local t_30deg_straightonly_noplacer={
+ap.t_30deg_straightonly_noplacer={
regstep=1,
variant={
st=conns(0,8),
@@ -160,7 +161,7 @@ local t_30deg_straightonly_noplacer={
rotation={"", "_30", "_45", "_60"},
increativeinv={st},
}
-local t_45deg={
+ap.t_45deg={
regstep=2,
variant={
st=conns(0,8),
@@ -215,6 +216,7 @@ local t_45deg={
rotation={"", "_45"},
increativeinv={vst1=true, vst2=true}
}
+advtrains.trackpresets = ap
--definition format: ([] optional)
--[[{
@@ -302,6 +304,9 @@ function advtrains.register_tracks(tracktype, def, preset)
after_place_node=function(pos)
advtrains.reset_trackdb_position(pos)
end,
+ on_place_rail=function(pos)
+ advtrains.reset_trackdb_position(pos)
+ end,
}, def.common or {})
--make trackplacer base def
advtrains.trackplacer.register_tracktype(def.nodename_prefix, preset.tpdefault)
@@ -386,10 +391,10 @@ advtrains.detector.clean_step_before = false
--The entry already being contained in advtrains.detector.on_node_restore will not trigger an on_train_enter event on the node. (when path is reset, this is saved).
function advtrains.detector.enter_node(pos, train_id)
local pts = minetest.pos_to_string(advtrains.round_vector_floor_y(pos))
- print("enterNode "..pts.." "..sid(train_id))
+ --print("enterNode "..pts.." "..sid(train_id))
if advtrains.detector.on_node[pts] then
if advtrains.trains[advtrains.detector.on_node[pts]] then
- print(""..pts.." already occupied")
+ --print(""..pts.." already occupied")
return false
else
advtrains.detector.leave_node(pos, advtrains.detector.on_node[pts])
@@ -405,9 +410,9 @@ function advtrains.detector.enter_node(pos, train_id)
end
function advtrains.detector.leave_node(pos, train_id)
local pts = minetest.pos_to_string(advtrains.round_vector_floor_y(pos))
- print("leaveNode "..pts.." "..sid(train_id))
+ --print("leaveNode "..pts.." "..sid(train_id))
if not advtrains.detector.on_node[pts] then
- print(""..pts.." leave: nothing here")
+ --print(""..pts.." leave: nothing here")
return false
end
if advtrains.detector.on_node[pts]==train_id then
@@ -415,7 +420,7 @@ function advtrains.detector.leave_node(pos, train_id)
advtrains.detector.on_node[pts]=nil
else
if advtrains.trains[advtrains.detector.on_node[pts]] then
- print(""..pts.." occupied by another train")
+ --print(""..pts.." occupied by another train")
return false
else
advtrains.detector.leave_node(pos, advtrains.detector.on_node[pts])
@@ -446,7 +451,10 @@ function advtrains.detector.call_enter_callback(pos, train_id)
local mregnode=minetest.registered_nodes[node.name]
if mregnode and mregnode.advtrains and mregnode.advtrains.on_train_enter then
mregnode.advtrains.on_train_enter(pos, train_id)
- end
+ end
+
+ --atc code wants to be notified too
+ advtrains.atc.trigger_controller_train_enter(pos, train_id)
end
function advtrains.detector.call_leave_callback(pos, train_id)
--print("instructed to call leave calback")
@@ -576,7 +584,7 @@ advtrains.register_tracks("regular", {
shared_model="trackplane.b3d",
description="Deprecated Track",
formats={vst1={}, vst2={}},
-}, t_45deg)
+}, ap.t_45deg)
advtrains.register_tracks("default", {
@@ -587,7 +595,7 @@ advtrains.register_tracks("default", {
shared_texture="advtrains_dtrack_rail.png",
description="Track",
formats={vst1={true, false, true}, vst2={true, false, true}, vst31={true}, vst32={true}, vst33={true}},
-}, t_30deg)
+}, ap.t_30deg)
--bumpers
advtrains.register_tracks("default", {
@@ -598,7 +606,7 @@ advtrains.register_tracks("default", {
shared_texture="advtrains_dtrack_rail.png",
description="Bumper",
formats={},
-}, t_30deg_straightonly)
+}, ap.t_30deg_straightonly)
--legacy bumpers
for _,rot in ipairs({"", "_30", "_45", "_60"}) do
minetest.register_alias("advtrains:dtrack_bumper"..rot, "advtrains:dtrack_bumper_st"..rot)
@@ -629,7 +637,7 @@ if mesecon then
}
}
end
- }, t_30deg_straightonly)
+ }, ap.t_30deg_straightonly)
advtrains.register_tracks("default", {
nodename_prefix="advtrains:dtrack_detector_on",
texture_prefix="advtrains_dtrack_detector",
@@ -654,7 +662,7 @@ if mesecon then
}
}
end
- }, t_30deg_straightonly_noplacer)
+ }, ap.t_30deg_straightonly_noplacer)
end
--TODO legacy
--I know lbms are better for this purpose
diff --git a/advtrains/trainhud.lua b/advtrains/trainhud.lua
index 19e4f6f..e69f04a 100644
--- a/advtrains/trainhud.lua
+++ b/advtrains/trainhud.lua
@@ -11,7 +11,7 @@ local mletter={[1]="F", [-1]="R", [0]="N"}
function advtrains.on_control_change(pc, train, flip)
if pc.sneak then
if pc.up then
- train.tarvelocity = advtrains.all_traintypes[train.traintype].max_speed or 10
+ train.tarvelocity = train.max_speed or 10
end
if pc.down then
train.tarvelocity = 0
diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua
index 4ac4b29..eb45500 100644
--- a/advtrains/trainlogic.lua
+++ b/advtrains/trainlogic.lua
@@ -119,6 +119,7 @@ advtrains.save = function()
file:close()
advtrains.save_trackdb()
+ advtrains.atc.save()
end
minetest.register_on_shutdown(advtrains.save)
@@ -302,6 +303,24 @@ function advtrains.train_step(id, train, dtime)
if train.locomotives_in_train==0 then
train.tarvelocity=0
end
+
+ --interpret ATC command
+ if train.atc_brake_target and train.atc_brake_target>=train.velocity then
+ train.atc_brake_target=nil
+ end
+ if train.atc_wait_finish then
+ if not train.atc_brake_target and train.velocity==train.tarvelocity then
+ train.atc_wait_finish=nil
+ end
+ end
+ if train.atc_command then
+ if train.atc_delay<=0 and not train.atc_wait_finish then
+ advtrains.atc.execute_atc_command(id, train)
+ else
+ train.atc_delay=train.atc_delay-dtime
+ end
+ end
+
--make brake adjust the tarvelocity if necessary
if train.brake and (math.ceil(train.velocity)-1)<train.tarvelocity then
train.tarvelocity=math.max((math.ceil(train.velocity)-1), 0)
@@ -318,7 +337,7 @@ function advtrains.train_step(id, train, dtime)
if front_off_track or back_off_track or train.recently_collided_with_env then --every wagon has a brake, so not divided by mass.
--print("braking with emergency force")
applydiff= -(math.min((advtrains.train_emerg_force*dtime), math.abs(diff)))
- elseif train.brake then
+ elseif train.brake or (train.atc_brake_target and train.atc_brake_target<train.velocity) then
--print("braking with default force")
--no math.min, because it can grow beyond tarvelocity, see up there
--dont worry, it will never fall below zero.