stoprail.lua 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. -- stoprail.lua
  2. -- adds "stop rail". Recognized by lzb. (part of behavior is implemented there)
  3. -- Get current translator
  4. local S = advtrains.lines.translate
  5. local function to_int(n)
  6. --- Disallow floating-point numbers
  7. local k = tonumber(n)
  8. if k then
  9. return math.floor(k)
  10. end
  11. end
  12. local function updatemeta(pos)
  13. local meta = minetest.get_meta(pos)
  14. local pe = advtrains.encode_pos(pos)
  15. local stdata = advtrains.lines.stops[pe]
  16. if not stdata then
  17. meta:set_string("infotext", "Error")
  18. end
  19. meta:set_string("infotext", "Stn. "..stdata.stn.." T. "..stdata.track)
  20. end
  21. local door_dropdown = {L=1, R=2, C=3}
  22. --local door_dropdown_rev = {Right="R", Left="L", Closed="C"} -- Code review : why are the value in an order different than the one in the dropdown box ?
  23. local door_dropdown_code = {"L", "R", "C"} -- switch to numerical index of selection : for conversion of the numerical index in the opening side selection dropdown box to the internal codification
  24. local function show_stoprailform(pos, player)
  25. local pe = advtrains.encode_pos(pos)
  26. local pname = player:get_player_name()
  27. if minetest.is_protected(pos, pname) then
  28. minetest.chat_send_player(pname, S("You are not allowed to configure this track."))
  29. return
  30. end
  31. local stdata = advtrains.lines.stops[pe]
  32. if not stdata then
  33. advtrains.lines.stops[pe] = {
  34. stn="", track="", doors="R", wait=10, ars={default=true}, ddelay=1,speed="M"
  35. }
  36. stdata = advtrains.lines.stops[pe]
  37. end
  38. local stn = advtrains.lines.stations[stdata.stn]
  39. local stnname = stn and stn.name or ""
  40. if not stdata.ddelay then
  41. stdata.ddelay = 1
  42. end
  43. if not stdata.speed then
  44. stdata.speed = "M"
  45. end
  46. local form = "size[8,7]"
  47. form = form.."style[stn,ars;font=mono]"
  48. form = form.."field[0.8,0.8;2,1;stn;"..S("Station Code")..";"..minetest.formspec_escape(stdata.stn).."]"
  49. form = form.."field[2.8,0.8;5,1;stnname;"..S("Station Name")..";"..minetest.formspec_escape(stnname).."]"
  50. form = form.."field[0.80,2.0;1.75,1;ddelay;"..S("Door Delay")..";"..minetest.formspec_escape(stdata.ddelay).."]"
  51. form = form.."field[2.55,2.0;1.75,1;speed;"..S("Dep. Speed")..";"..minetest.formspec_escape(stdata.speed).."]"
  52. form = form.."field[4.30,2.0;1.75,1;track;"..S("Track")..";"..minetest.formspec_escape(stdata.track).."]"
  53. form = form.."field[6.05,2.0;1.75,1;wait;"..S("Stop Time")..";"..stdata.wait.."]"
  54. form = form.."label[0.5,2.6;"..S("Door Side").."]"
  55. form = form.."dropdown[0.51,3.0;2;doors;"..S("Left")..","..S("Right")..","..S("Closed")..";"..door_dropdown[stdata.doors]..";true]" -- switch to numerical index of the selection
  56. form = form.."checkbox[3.00,2.4;reverse;"..S("Reverse train")..";"..(stdata.reverse and "true" or "false").."]"
  57. form = form.."checkbox[3.00,2.8;kick;"..S("Kick out passengers")..";"..(stdata.kick and "true" or "false").."]"
  58. form = form.."checkbox[3.00,3.2;waitsig;"..S("Wait for signal to clear")..";"..(stdata.waitsig and "true" or "false").."]"
  59. form = form.."textarea[0.8,4.2;7,2;ars;"..S("Trains stopping here (ARS rules)")..";"..advtrains.interlocking.ars_to_text(stdata.ars).."]"
  60. form = form.."button[0.5,6;7,1;save;"..S("Save").."]"
  61. minetest.show_formspec(pname, "at_lines_stop_"..pe, form)
  62. end
  63. local tmp_checkboxes = {}
  64. minetest.register_on_player_receive_fields(function(player, formname, fields)
  65. local pname = player:get_player_name()
  66. local pe = string.match(formname, "^at_lines_stop_(............)$")
  67. local pos = advtrains.decode_pos(pe)
  68. if pos then
  69. if minetest.is_protected(pos, pname) then
  70. minetest.chat_send_player(pname, S("You are not allowed to configure this track."))
  71. return
  72. end
  73. local stdata = advtrains.lines.stops[pe]
  74. if not tmp_checkboxes[pe] then
  75. tmp_checkboxes[pe] = {}
  76. end
  77. if fields.kick then -- handle checkboxes due to MT's weird handling
  78. tmp_checkboxes[pe].kick = (fields.kick == "true")
  79. end
  80. if fields.reverse then
  81. tmp_checkboxes[pe].reverse = (fields.reverse == "true")
  82. end
  83. if fields.waitsig then
  84. tmp_checkboxes[pe].waitsig = (fields.waitsig == "true")
  85. end
  86. if fields.save then
  87. if fields.stn and stdata.stn ~= fields.stn and fields.stn ~= "" then
  88. local stn = advtrains.lines.stations[fields.stn]
  89. if stn then
  90. if (stn.owner == pname or minetest.check_player_privs(pname, "train_admin")) then
  91. stdata.stn = fields.stn
  92. else
  93. minetest.chat_send_player(pname, S("Station code \"@1\" already exists and is owned by @2.", fields.stn, stn.owner))
  94. show_stoprailform(pos,player)
  95. return
  96. end
  97. else
  98. advtrains.lines.stations[fields.stn] = {name = fields.stnname, owner = pname}
  99. stdata.stn = fields.stn
  100. end
  101. end
  102. local stn = advtrains.lines.stations[stdata.stn]
  103. if stn and fields.stnname and fields.stnname~="" and fields.stnname ~= stn.name then
  104. if (stn.owner == pname or minetest.check_player_privs(pname, "train_admin")) then
  105. stn.name = fields.stnname
  106. else
  107. minetest.chat_send_player(pname, S("This station is owned by @1. You are not allowed to edit its name.", stn.owner))
  108. end
  109. end
  110. -- dropdowns
  111. if fields.doors then
  112. stdata.doors = door_dropdown_code[tonumber(fields.doors)] or "C" -- switch to numerical index of selection; attention : fields.doors is string typed, needed to be converted to an integer typed index in door_dropdown_code table
  113. end
  114. if fields.track then
  115. stdata.track = fields.track
  116. end
  117. if fields.wait then
  118. stdata.wait = to_int(fields.wait) or 10
  119. end
  120. if fields.ars then
  121. stdata.ars = advtrains.interlocking.text_to_ars(fields.ars)
  122. end
  123. if fields.ddelay then
  124. stdata.ddelay = to_int(fields.ddelay) or 1
  125. end
  126. if fields.speed then
  127. stdata.speed = to_int(fields.speed) or "M"
  128. end
  129. for k,v in pairs(tmp_checkboxes[pe]) do --handle checkboxes
  130. stdata[k] = v or nil
  131. end
  132. tmp_checkboxes[pe] = nil
  133. --TODO: signal
  134. updatemeta(pos)
  135. show_stoprailform(pos, player)
  136. end
  137. end
  138. end)
  139. local adefunc = function(def, preset, suffix, rotation)
  140. return {
  141. after_place_node=function(pos)
  142. local pe = advtrains.encode_pos(pos)
  143. advtrains.lines.stops[pe] = {
  144. stn="", track="", doors="R", wait=10, waitsig = true
  145. }
  146. updatemeta(pos)
  147. end,
  148. after_dig_node=function(pos)
  149. local pe = advtrains.encode_pos(pos)
  150. advtrains.lines.stops[pe] = nil
  151. end,
  152. on_rightclick = function(pos, node, player)
  153. show_stoprailform(pos, player)
  154. end,
  155. advtrains = {
  156. on_train_approach = function(pos,train_id, train, index, has_entered)
  157. if has_entered then return end -- do not stop again!
  158. if train.path_cn[index] == 1 then
  159. local pe = advtrains.encode_pos(pos)
  160. local stdata = advtrains.lines.stops[pe]
  161. if stdata and stdata.stn then
  162. --TODO REMOVE AFTER SOME TIME (only migration)
  163. if not stdata.ars then
  164. stdata.ars = {default=true}
  165. end
  166. if stdata.ars and (stdata.ars.default or advtrains.interlocking.ars_check_rule_match(stdata.ars, train) ) then
  167. advtrains.lzb_add_checkpoint(train, index, 2, nil)
  168. local stn = advtrains.lines.stations[stdata.stn]
  169. local stnname = stn and stn.name or S("Unknown Station")
  170. train.text_inside = S("Next Stop:\n")..stnname
  171. advtrains.interlocking.ars_set_disable(train, true)
  172. end
  173. end
  174. end
  175. end,
  176. on_train_enter = function(pos, train_id, train, index)
  177. if train.path_cn[index] == 1 then
  178. local pe = advtrains.encode_pos(pos)
  179. local stdata = advtrains.lines.stops[pe]
  180. if not stdata then
  181. return
  182. end
  183. if stdata.ars and (stdata.ars.default or advtrains.interlocking.ars_check_rule_match(stdata.ars, train) ) then
  184. local stn = advtrains.lines.stations[stdata.stn]
  185. local stnname = stn and stn.name or S("Unknown Station")
  186. -- Send ATC command and set text
  187. advtrains.atc.train_set_command(train, "B0 W O"..stdata.doors..(stdata.kick and "K" or "")
  188. .." D"..stdata.wait.." "..(stdata.reverse and "R" or "")
  189. .." A1 "..(stdata.waitsig and "G" or "")
  190. .." OC D"..(stdata.ddelay or 1) .. " S" ..(stdata.speed or "M"), true)
  191. train.text_inside = stnname
  192. if tonumber(stdata.wait) then
  193. minetest.after(tonumber(stdata.wait), function() train.text_inside = "" end)
  194. end
  195. end
  196. end
  197. end
  198. },
  199. }
  200. end
  201. if minetest.get_modpath("advtrains_train_track") ~= nil then
  202. advtrains.register_tracks("default", {
  203. nodename_prefix="advtrains_line_automation:dtrack_stop",
  204. texture_prefix="advtrains_dtrack_stop",
  205. models_prefix="advtrains_dtrack",
  206. models_suffix=".b3d",
  207. shared_texture="advtrains_dtrack_shared_stop.png",
  208. description=S("Station/Stop Track"),
  209. formats={},
  210. get_additional_definiton = adefunc,
  211. }, advtrains.trackpresets.t_30deg_straightonly)
  212. end