diff options
author | orwell96 <mono96.mml@gmail.com> | 2017-01-04 12:02:00 +0100 |
---|---|---|
committer | orwell96 <mono96.mml@gmail.com> | 2017-01-04 12:02:00 +0100 |
commit | 853a9e690eeeb48aa1a13faa66db0a91d5b49390 (patch) | |
tree | 51451d08e10cedda4128c1e29848524a00baf2a7 /advtrains | |
parent | a9d43ce2ca3bfd703428d248c0839e53ffd76f27 (diff) | |
download | advtrains-853a9e690eeeb48aa1a13faa66db0a91d5b49390.tar.gz advtrains-853a9e690eeeb48aa1a13faa66db0a91d5b49390.tar.bz2 advtrains-853a9e690eeeb48aa1a13faa66db0a91d5b49390.zip |
Add Automatic Train Control system
Diffstat (limited to 'advtrains')
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 Binary files differindex 893c8cd..6762bc3 100644 --- a/advtrains/models/advtrains_dtrack_detector_st.b3d +++ b/advtrains/models/advtrains_dtrack_detector_st.b3d diff --git a/advtrains/models/advtrains_dtrack_detector_st_30.b3d b/advtrains/models/advtrains_dtrack_detector_st_30.b3d Binary files differindex 2e59e93..f2d5991 100644 --- a/advtrains/models/advtrains_dtrack_detector_st_30.b3d +++ b/advtrains/models/advtrains_dtrack_detector_st_30.b3d diff --git a/advtrains/models/advtrains_dtrack_detector_st_45.b3d b/advtrains/models/advtrains_dtrack_detector_st_45.b3d Binary files differindex c73166f..9ecb4a6 100644 --- a/advtrains/models/advtrains_dtrack_detector_st_45.b3d +++ b/advtrains/models/advtrains_dtrack_detector_st_45.b3d diff --git a/advtrains/models/advtrains_dtrack_detector_st_60.b3d b/advtrains/models/advtrains_dtrack_detector_st_60.b3d Binary files differindex b6bc9af..bd102cb 100644 --- a/advtrains/models/advtrains_dtrack_detector_st_60.b3d +++ b/advtrains/models/advtrains_dtrack_detector_st_60.b3d diff --git a/advtrains/models/blender/gleis/detectorpart.png b/advtrains/models/blender/gleis/detectorpart.png Binary files differnew file mode 100644 index 0000000..fc24181 --- /dev/null +++ b/advtrains/models/blender/gleis/detectorpart.png diff --git a/advtrains/models/blender/gleis/rail_my_rt_final.blend b/advtrains/models/blender/gleis/rail_my_rt_final.blend Binary files differindex 6a9a088..d07a65d 100644 --- a/advtrains/models/blender/gleis/rail_my_rt_final.blend +++ b/advtrains/models/blender/gleis/rail_my_rt_final.blend diff --git a/advtrains/models/blender/gleis/rail_my_rt_final.blend1 b/advtrains/models/blender/gleis/rail_my_rt_final.blend1 Binary files differindex 1f346ae..8a2d213 100644 --- a/advtrains/models/blender/gleis/rail_my_rt_final.blend1 +++ b/advtrains/models/blender/gleis/rail_my_rt_final.blend1 diff --git a/advtrains/textures/advtrains_dtrack_atc_placer.png b/advtrains/textures/advtrains_dtrack_atc_placer.png Binary files differnew file mode 100644 index 0000000..31c2b30 --- /dev/null +++ b/advtrains/textures/advtrains_dtrack_atc_placer.png diff --git a/advtrains/textures/advtrains_dtrack_placer.png b/advtrains/textures/advtrains_dtrack_placer.png Binary files differindex c49777c..7bef8a9 100644 --- a/advtrains/textures/advtrains_dtrack_placer.png +++ b/advtrains/textures/advtrains_dtrack_placer.png diff --git a/advtrains/textures/advtrains_dtrack_rail.png b/advtrains/textures/advtrains_dtrack_rail.png Binary files differindex 568e533..1cf7f83 100644 --- a/advtrains/textures/advtrains_dtrack_rail.png +++ b/advtrains/textures/advtrains_dtrack_rail.png diff --git a/advtrains/textures/advtrains_dtrack_rail_atc.png b/advtrains/textures/advtrains_dtrack_rail_atc.png Binary files differnew file mode 100644 index 0000000..d171985 --- /dev/null +++ b/advtrains/textures/advtrains_dtrack_rail_atc.png diff --git a/advtrains/textures/advtrains_dtrack_rail_detector_on.png b/advtrains/textures/advtrains_dtrack_rail_detector_on.png Binary files differindex 3ae0dac..4f09b35 100644 --- a/advtrains/textures/advtrains_dtrack_rail_detector_on.png +++ b/advtrains/textures/advtrains_dtrack_rail_detector_on.png 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. |