station.lua 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. --[[
  2. Hyperloop Mod
  3. =============
  4. Copyright (C) 2017-2019 Joachim Stolberg
  5. LGPLv2.1+
  6. See LICENSE.txt for more information
  7. ]]--
  8. -- for lazy programmers
  9. local SP = function(pos) if pos then return minetest.pos_to_string(pos) end end
  10. local P = minetest.string_to_pos
  11. local M = minetest.get_meta
  12. -- Load support for intllib.
  13. local S = vents.S
  14. local NS = vents.NS
  15. local Tube = vents.Tube
  16. local Stations = vents.Stations
  17. -- Used to store the Station list for each vent:
  18. -- tStationList[SP(pos)] = {pos1, pos2, ...}
  19. local tStationList = {}
  20. local function store_station(pos, placer)
  21. local facedir = vents.get_facedir(placer)
  22. -- do a facedir correction
  23. facedir = (facedir + 3) % 4 -- face to LCD
  24. Stations:set(pos, 'Station', {
  25. owner = placer:get_player_name(),
  26. facedir = facedir,
  27. time_blocked = 0})
  28. end
  29. local function naming_formspec(pos)
  30. local data = Stations:get(pos)
  31. local vent = data.name or 'vent'
  32. local info = data.booking_info or ''
  33. local formspec =
  34. 'size[7,4.4]'..
  35. 'label[0,0;'..S('Please enter the vent name.')..']' ..
  36. 'label[0,.35;Punch the vent to see locations you can teleport too.]' ..
  37. 'field[0.2,1.5;7.1,1;name;'..S('Vent name')..';'..vent..']' ..
  38. 'field[0.2,2.7;7.1,1;info;'..S('Additional vent information')..';'..info..']' ..
  39. 'button_exit[2.5,3.7;2,1;exit;Save]'
  40. return formspec
  41. end
  42. -- Form spec for the station list
  43. local function generate_string(sortedList)
  44. local tRes = {'size[12,8]'..
  45. 'label[4,0; '..S('Select your destination')..']'}
  46. tRes[2] = 'tablecolumns[text,width=20;text,width=6,align=right;text]'
  47. local stations = {}
  48. for idx,tDest in ipairs(sortedList) do
  49. local name = tDest.name or S('<unknown>')
  50. local distance = tDest.distance or 0
  51. local info = tDest.booking_info or ''
  52. stations[#stations+1] = minetest.formspec_escape(string.sub(name, 1, 28))
  53. stations[#stations+1] = distance..'m'
  54. stations[#stations+1] = minetest.formspec_escape(info)
  55. end
  56. if #stations>0 then
  57. tRes[#tRes+1] = 'table[0,1;11.8,7.2;button;'..table.concat(stations, ',')..']'
  58. else
  59. tRes[#tRes+1] = 'button_exit[4,4;3,1;button;Update]'
  60. end
  61. return table.concat(tRes)
  62. end
  63. local function store_station_list(pos, sortedList)
  64. local tbl = {}
  65. for idx,item in ipairs(sortedList) do
  66. tbl[#tbl+1] = item.pos
  67. end
  68. tStationList[SP(pos)] = tbl
  69. end
  70. local function remove_junctions(sortedList)
  71. local tbl = {}
  72. for idx,item in ipairs(sortedList) do
  73. if not item.junction and item.booking_pos then
  74. tbl[#tbl+1] = item
  75. end
  76. end
  77. return tbl
  78. end
  79. local function filter_subnet(sortedList, subnet)
  80. if vents.subnet_enabled then
  81. if subnet == '' then
  82. subnet = nil
  83. end
  84. local tbl = {}
  85. for idx,item in ipairs(sortedList) do
  86. if item.subnet == subnet then
  87. tbl[#tbl+1] = item
  88. end
  89. end
  90. return tbl
  91. end
  92. return sortedList
  93. end
  94. -- Used to update the station list for booking machine
  95. -- and teleport list.
  96. local function station_list_as_string(pos, subnet)
  97. local meta = M(pos)
  98. -- Generate a name sorted list of all connected stations
  99. local sortedList = Stations:station_list(pos, pos, 'name')
  100. -- remove all junctions from the list
  101. sortedList = remove_junctions(sortedList)
  102. -- use subnet pattern to reduce the list
  103. sortedList = filter_subnet(sortedList, subnet)
  104. -- store the list for later use
  105. store_station_list(pos, sortedList)
  106. -- Generate the formspec string
  107. return generate_string(sortedList)
  108. end
  109. minetest.register_on_player_receive_fields(function(player, formname, fields)
  110. local name = player:get_player_name()
  111. local pos = vents.player_pos[name]
  112. if formname == 'vents:setup' then
  113. if fields.exit then
  114. if fields.name ~= nil then
  115. local station_name = string.trim(fields.name)
  116. if station_name == '' then
  117. return
  118. end
  119. --if Stations:get(pos).booking_pos then
  120. -- minetest.chat_send_player(name, S('Remove and replace to change name.'))
  121. --Figure out how to allow a builder to update station.
  122. -- return
  123. --end
  124. -- store meta and generate station formspec
  125. Stations:update(pos, {
  126. name = station_name,
  127. booking_pos = pos,
  128. booking_info = string.trim(fields.info),
  129. })
  130. local meta = minetest.get_meta(pos)
  131. meta:set_string('infotext', 'Station: '..station_name)
  132. minetest.chat_send_player(name, 'Saving data')
  133. else
  134. vents.chat(player, S('Invalid station name!'))
  135. end
  136. end
  137. elseif formname == 'vents:station_list' then
  138. local te = minetest.explode_table_event(fields.button)
  139. local idx = tonumber(te.row)
  140. if idx and te.type=='CHG' then
  141. local tStation, src_pos = vents.get_base_station(pos)
  142. local dest_pos = tStationList[SP(pos)] and tStationList[SP(pos)][idx]
  143. if dest_pos and tStation then
  144. local air = minetest.find_node_near(dest_pos, 2, {'air'})
  145. if air then
  146. player:set_pos(air)
  147. else
  148. minetest.chat_send_player(name, 'Sorry, can\'t teleport you there.')
  149. end
  150. --Should there be some sort of freeze on movement or health loss for using the vents?
  151. end
  152. minetest.close_formspec(player:get_player_name(), formname)
  153. end
  154. end
  155. end)
  156. local function on_destruct(pos)
  157. Stations:update((pos), {
  158. booking_pos = 'nil',
  159. booking_info = 'nil',
  160. name = 'Station',
  161. })
  162. end
  163. minetest.register_node('vents:station', {
  164. description = S('Vent Access'),
  165. drawtype = 'nodebox',
  166. tiles = {'vents_station.png'},
  167. after_place_node = function(pos, placer, itemstack, pointed_thing)
  168. vents.check_network_level(pos, placer)
  169. M(pos):set_string('infotext', S('Access Point'))
  170. store_station(pos, placer)
  171. Tube:after_place_node(pos)
  172. end,
  173. on_rightclick = function(pos, node, clicker)
  174. local name = clicker:get_player_name()
  175. local player_attributes = clicker:get_meta()
  176. local mode = player_attributes:get_string('mode')
  177. vents.player_pos[name] = pos
  178. if mode == 'traitor' or mode == 'solo' or mode == 'ghost' then
  179. minetest.show_formspec(name, 'vents:station_list', station_list_as_string(pos))
  180. elseif mode == 'builder' then
  181. minetest.show_formspec(name, 'vents:setup', naming_formspec(pos))
  182. else
  183. minetest.chat_send_player(name, 'Sorry, you can\'t use this.')
  184. end
  185. end,
  186. on_punch = function(pos, node, puncher)
  187. local wield = puncher:get_wielded_item()
  188. local wield_name = wield:get_name()
  189. if wield_name == 'creative:tool_breaking' then
  190. return
  191. else
  192. local name = puncher:get_player_name()
  193. local player_attributes = puncher:get_meta()
  194. local mode = player_attributes:get_string('mode')
  195. vents.player_pos[name] = pos
  196. if mode == 'builder' then
  197. minetest.show_formspec(name, 'vents:station_list', station_list_as_string(pos))
  198. end
  199. end
  200. end,
  201. after_dig_node = function(pos, oldnode, oldmetadata, digger)
  202. Tube:after_dig_node(pos)
  203. Stations:delete(pos)
  204. end,
  205. on_destruct = on_destruct,
  206. on_rotate = screwdriver.disallow,
  207. paramtype = 'light',
  208. paramtype2 = 'facedir',
  209. groups = {breakable=1},
  210. is_ground_content = false,
  211. sounds = {footstep = {name = 'metal', gain = 1}},
  212. })