active_common.lua 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. local S = atltrans
  2. local ac = {nodes={}}
  3. function ac.load(data)
  4. if data then
  5. ac.nodes=data.nodes
  6. end
  7. end
  8. function ac.save()
  9. return {nodes = ac.nodes}
  10. end
  11. function ac.after_place_node(pos, player)
  12. local meta=minetest.get_meta(pos)
  13. meta:set_string("formspec", ac.getform(pos, meta))
  14. meta:set_string("infotext", S("Unconfigured LuaATC component"))
  15. local ph=minetest.pos_to_string(pos)
  16. --just get first available key!
  17. for en,_ in pairs(atlatc.envs) do
  18. ac.nodes[ph]={env=en}
  19. return
  20. end
  21. end
  22. function ac.getform(pos, meta_p)
  23. local meta = meta_p or minetest.get_meta(pos)
  24. local envs_asvalues={}
  25. local ph=minetest.pos_to_string(pos)
  26. local nodetbl = ac.nodes[ph]
  27. local env, code, err = nil, "", ""
  28. if nodetbl then
  29. code=nodetbl.code or ""
  30. err=nodetbl.err or ""
  31. env=nodetbl.env or ""
  32. end
  33. local sel = 1
  34. for n,_ in pairs(atlatc.envs) do
  35. envs_asvalues[#envs_asvalues+1]=minetest.formspec_escape(n)
  36. if n==env then
  37. sel=#envs_asvalues
  38. end
  39. end
  40. local form = "size["..atlatc.CODE_FORM_SIZE.."]"
  41. .."style[code;font=mono]"
  42. .."label[0,-0.1;"..S("LuaATC Environment").."]"
  43. .."dropdown[0,0.3;3;env;"..table.concat(envs_asvalues, ",")..";"..sel.."]"
  44. .."button[5,0.2;2,1;save;"..S("Save").."]"
  45. .."button[7,0.2;3,1;cle;"..S("Clear Local Environment").."]"
  46. .."textarea[0.3,1.5;"..atlatc.CODE_FORM_SIZE..";code;"..S("Code")..";"..minetest.formspec_escape(code).."]"
  47. .."label["..atlatc.CODE_FORM_ERRLABELPOS..";"..err.."]"
  48. return form
  49. end
  50. function ac.after_dig_node(pos, node, player)
  51. advtrains.invalidate_all_paths(pos)
  52. advtrains.ndb.clear(pos)
  53. atlatc.interrupt.clear_ints_at_pos(pos)
  54. if advtrains.lines and advtrains.lines.sched then
  55. advtrains.lines.sched.discard_all(advtrains.encode_pos(pos))
  56. end
  57. local ph=minetest.pos_to_string(pos)
  58. ac.nodes[ph]=nil
  59. end
  60. function ac.on_receive_fields(pos, formname, fields, player)
  61. if not minetest.check_player_privs(player:get_player_name(), {atlatc=true}) then
  62. minetest.chat_send_player(player:get_player_name(), S("You are not allowed to configure this LuaATC component without the @1 privilege.", "atlatc"))
  63. return
  64. end
  65. local meta=minetest.get_meta(pos)
  66. local ph=minetest.pos_to_string(pos)
  67. local nodetbl = ac.nodes[ph] or {}
  68. --if fields.quit then return end
  69. if fields.env then
  70. nodetbl.env=fields.env
  71. end
  72. if fields.code then
  73. nodetbl.code=fields.code
  74. end
  75. if fields.save then
  76. -- reset certain things
  77. nodetbl.err=nil
  78. if advtrains.lines and advtrains.lines.sched then
  79. -- discard all schedules for this node
  80. advtrains.lines.sched.discard_all(advtrains.encode_pos(pos))
  81. end
  82. end
  83. if fields.cle then
  84. nodetbl.data={}
  85. end
  86. ac.nodes[ph]=nodetbl
  87. meta:set_string("formspec", ac.getform(pos, meta))
  88. if nodetbl.env then
  89. meta:set_string("infotext", S("LuaATC component assigned to environment '@1'", nodetbl.env))
  90. else
  91. meta:set_string("infotext", S("LuaATC component assigned to an invalid environment"))
  92. end
  93. end
  94. function ac.run_in_env(pos, evtdata, customfct_p, ignore_no_code)
  95. local ph=minetest.pos_to_string(pos)
  96. local nodetbl = ac.nodes[ph]
  97. if not nodetbl then
  98. atwarn("LuaATC component at",ph,": Data not in memory! Please visit component and click 'Save'!")
  99. return
  100. end
  101. local meta
  102. if advtrains.is_node_loaded(pos) then
  103. meta=minetest.get_meta(pos)
  104. end
  105. if not nodetbl.env or not atlatc.envs[nodetbl.env] then
  106. atwarn("LuaATC component at",ph,": Not an existing environment: "..(nodetbl.env or "<nil>"))
  107. return false
  108. end
  109. local env = atlatc.envs[nodetbl.env]
  110. if not nodetbl.code or nodetbl.code=="" then
  111. if not ignore_no_code then
  112. env:log("warning", "LuaATC component at",ph,": No code to run! (insert -- to suppress warning)")
  113. end
  114. return false
  115. end
  116. local customfct=customfct_p or {}
  117. -- add interrupt function
  118. customfct.interrupt=function(t, imesg)
  119. assertt(t, "number")
  120. assert(t >= 0)
  121. atlatc.interrupt.add(t, pos, {type="int", int=true, message=imesg, msg=imesg}) --Compatiblity "message" field.
  122. end
  123. customfct.interrupt_safe=function(t, imesg)
  124. assertt(t, "number")
  125. assert(t >= 0)
  126. if atlatc.interrupt.has_at_pos(pos) then
  127. return false
  128. end
  129. atlatc.interrupt.add(t, pos, {type="int", int=true, message=imesg, msg=imesg}) --Compatiblity "message" field.
  130. return true
  131. end
  132. customfct.clear_interrupts=function()
  133. atlatc.interrupt.clear_ints_at_pos(pos)
  134. end
  135. -- add digiline_send function, if digiline is loaded
  136. if minetest.global_exists("digiline") then
  137. customfct.digiline_send=function(channel, msg)
  138. assertt(channel, "string")
  139. if advtrains.is_node_loaded(pos) then
  140. digiline:receptor_send(pos, digiline.rules.default, channel, msg)
  141. end
  142. end
  143. end
  144. -- add lines scheduler if enabled
  145. if advtrains.lines and advtrains.lines.sched then
  146. customfct.schedule = function(rwtime, msg)
  147. return advtrains.lines.sched.enqueue(rwtime, "atlatc_env", {pos=pos, msg=msg}, advtrains.encode_pos(pos), 1)
  148. end
  149. customfct.schedule_in = function(rwtime, msg)
  150. return advtrains.lines.sched.enqueue_in(rwtime, "atlatc_env", {pos=pos, msg=msg}, advtrains.encode_pos(pos), 1)
  151. end
  152. end
  153. local datain=nodetbl.data or {}
  154. local succ, dataout = env:execute_code(datain, nodetbl.code, evtdata, customfct)
  155. if succ then
  156. atlatc.active.nodes[ph].data=atlatc.remove_invalid_data(dataout)
  157. else
  158. atlatc.active.nodes[ph].err=dataout
  159. env:log("error", "LuaATC component at",ph,": LUA Error:",dataout)
  160. if meta then
  161. meta:set_string("infotext", S("LuaATC component with error: @1", dataout))
  162. end
  163. --TODO temporary
  164. --if customfct.atc_id then
  165. -- advtrains.drb_dump(customfct.atc_id)
  166. -- error("Debug: LuaATC error hit!")
  167. --end
  168. end
  169. if meta then
  170. meta:set_string("formspec", ac.getform(pos, meta))
  171. end
  172. end
  173. function ac.on_digiline_receive(pos, node, channel, msg)
  174. atlatc.interrupt.add(0, pos, {type="digiline", digiline=true, channel = channel, msg = msg})
  175. end
  176. if advtrains.lines and advtrains.lines.sched then
  177. advtrains.lines.sched.register_callback("atlatc_env", function(data)
  178. -- This adds another interrupt to the atlatc queue... there might be a better way
  179. atlatc.interrupt.add(0, data.pos, {type="schedule",schedule=true, msg=data.msg})
  180. end)
  181. end
  182. ac.trackdef_advtrains_defs = {
  183. on_train_enter = function(pos, train_id)
  184. --do async. Event is fired in train steps
  185. atlatc.interrupt.add(0, pos, {type="train", train=true, id=train_id})
  186. end,
  187. }
  188. atlatc.active=ac