stoprail.lua 7.7 KB

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