From 853a9e690eeeb48aa1a13faa66db0a91d5b49390 Mon Sep 17 00:00:00 2001 From: orwell96 Date: Wed, 4 Jan 2017 12:02:00 +0100 Subject: Add Automatic Train Control system --- advtrains/api_doc.txt | 2 +- advtrains/atc.lua | 292 ++++++++++++++++++++- advtrains/atc_command.txt | 68 +++++ advtrains/models/advtrains_dtrack_detector_st.b3d | Bin 17157 -> 17157 bytes .../models/advtrains_dtrack_detector_st_30.b3d | Bin 32779 -> 32779 bytes .../models/advtrains_dtrack_detector_st_45.b3d | Bin 17163 -> 17163 bytes .../models/advtrains_dtrack_detector_st_60.b3d | Bin 32779 -> 32779 bytes advtrains/models/blender/gleis/detectorpart.png | Bin 0 -> 857 bytes .../models/blender/gleis/rail_my_rt_final.blend | Bin 1094836 -> 1015668 bytes .../models/blender/gleis/rail_my_rt_final.blend1 | Bin 827052 -> 1106004 bytes advtrains/textures/advtrains_dtrack_atc_placer.png | Bin 0 -> 1259 bytes advtrains/textures/advtrains_dtrack_placer.png | Bin 5831 -> 1097 bytes advtrains/textures/advtrains_dtrack_rail.png | Bin 2810 -> 2814 bytes advtrains/textures/advtrains_dtrack_rail_atc.png | Bin 0 -> 2837 bytes .../textures/advtrains_dtrack_rail_detector_on.png | Bin 2844 -> 2818 bytes advtrains/trackplacer.lua | 25 +- advtrains/tracks.lua | 38 +-- advtrains/trainhud.lua | 2 +- advtrains/trainlogic.lua | 21 +- 19 files changed, 424 insertions(+), 24 deletions(-) create mode 100644 advtrains/atc_command.txt create mode 100644 advtrains/models/blender/gleis/detectorpart.png create mode 100644 advtrains/textures/advtrains_dtrack_atc_placer.png create mode 100644 advtrains/textures/advtrains_dtrack_rail_atc.png (limited to 'advtrains') 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" 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 . 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; +Execute code only if condition applies +IE; +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 Binary files a/advtrains/models/advtrains_dtrack_detector_st.b3d and b/advtrains/models/advtrains_dtrack_detector_st.b3d 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 Binary files a/advtrains/models/advtrains_dtrack_detector_st_30.b3d and b/advtrains/models/advtrains_dtrack_detector_st_30.b3d 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 Binary files a/advtrains/models/advtrains_dtrack_detector_st_45.b3d and b/advtrains/models/advtrains_dtrack_detector_st_45.b3d 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 Binary files a/advtrains/models/advtrains_dtrack_detector_st_60.b3d and b/advtrains/models/advtrains_dtrack_detector_st_60.b3d differ diff --git a/advtrains/models/blender/gleis/detectorpart.png b/advtrains/models/blender/gleis/detectorpart.png new file mode 100644 index 0000000..fc24181 Binary files /dev/null and b/advtrains/models/blender/gleis/detectorpart.png 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 Binary files a/advtrains/models/blender/gleis/rail_my_rt_final.blend and b/advtrains/models/blender/gleis/rail_my_rt_final.blend 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 Binary files a/advtrains/models/blender/gleis/rail_my_rt_final.blend1 and b/advtrains/models/blender/gleis/rail_my_rt_final.blend1 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 Binary files /dev/null and b/advtrains/textures/advtrains_dtrack_atc_placer.png differ diff --git a/advtrains/textures/advtrains_dtrack_placer.png b/advtrains/textures/advtrains_dtrack_placer.png index c49777c..7bef8a9 100644 Binary files a/advtrains/textures/advtrains_dtrack_placer.png and b/advtrains/textures/advtrains_dtrack_placer.png differ diff --git a/advtrains/textures/advtrains_dtrack_rail.png b/advtrains/textures/advtrains_dtrack_rail.png index 568e533..1cf7f83 100644 Binary files a/advtrains/textures/advtrains_dtrack_rail.png and b/advtrains/textures/advtrains_dtrack_rail.png 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 Binary files /dev/null and b/advtrains/textures/advtrains_dtrack_rail_atc.png 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 Binary files a/advtrains/textures/advtrains_dtrack_rail_detector_on.png and b/advtrains/textures/advtrains_dtrack_rail_detector_on.png 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)