An advanced-ish waypoints mod for Minetest.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

246 lignes
8.2 KiB

  1. --
  2. -- Minetest advmarkers SSCSM
  3. --
  4. -- Copyright © 2019 by luk3yx
  5. -- License: https://git.minetest.land/luk3yx/advmarkers/src/branch/master/LICENSE.md
  6. --
  7. advmarkers = {}
  8. local data = {}
  9. local loaded = false
  10. assert(not sscsm.restrictions or not sscsm.restrictions.chat_messages,
  11. 'The advmarkers SSCSM needs to be able to send chat messages!')
  12. -- Convert positions to/from strings
  13. local function pos_to_string(pos)
  14. if type(pos) == 'table' then
  15. pos = minetest.pos_to_string(vector.round(pos))
  16. end
  17. if type(pos) == 'string' then
  18. return pos
  19. end
  20. end
  21. local function string_to_pos(pos)
  22. if type(pos) == 'string' then
  23. pos = minetest.string_to_pos(pos)
  24. end
  25. if type(pos) == 'table' then
  26. return vector.round(pos)
  27. end
  28. end
  29. -- Run remote command
  30. -- This is easier to do with chatcommands because servers cannot send mod
  31. -- channel messages to specific clients.
  32. local function run_remote_command(cmd, param)
  33. sscsm.com_send('advmarkers:cmd', cmd .. (param or ''))
  34. end
  35. -- Display a waypoint
  36. function advmarkers.display_waypoint(name)
  37. name = tostring(name)
  38. if data['marker-' .. name] then
  39. run_remote_command('0', tostring(name))
  40. return true
  41. else
  42. return false
  43. end
  44. end
  45. -- Get a waypoint
  46. function advmarkers.get_waypoint(name)
  47. return string_to_pos(data['marker-' .. tostring(name)])
  48. end
  49. advmarkers.get_marker = advmarkers.get_waypoint
  50. -- Delete a waypoint
  51. function advmarkers.delete_waypoint(name)
  52. name = tostring(name)
  53. if data['marker-' .. name] ~= nil then
  54. data['marker-' .. name] = nil
  55. run_remote_command('D', name)
  56. end
  57. end
  58. advmarkers.delete_marker = advmarkers.delete_waypoint
  59. -- Set a waypoint
  60. function advmarkers.set_waypoint(pos, name)
  61. pos = pos_to_string(pos)
  62. if not pos then return end
  63. name = tostring(name)
  64. data['marker-' .. name] = pos
  65. run_remote_command('S', pos:gsub(' ', '') .. ' ' .. name)
  66. return true
  67. end
  68. advmarkers.set_marker = advmarkers.set_waypoint
  69. -- Rename a waypoint and re-interpret the position.
  70. function advmarkers.rename_waypoint(oldname, newname)
  71. oldname, newname = tostring(oldname), tostring(newname)
  72. local pos = advmarkers.get_waypoint(oldname)
  73. if not pos or not advmarkers.set_waypoint(pos, newname) then return end
  74. if oldname ~= newname then
  75. advmarkers.delete_waypoint(oldname)
  76. end
  77. return true
  78. end
  79. advmarkers.rename_marker = advmarkers.rename_waypoint
  80. -- Get waypoint names
  81. function advmarkers.get_waypoint_names(sorted)
  82. local res = {}
  83. for name, _ in pairs(data) do
  84. if name:sub(1, 7) == 'marker-' then
  85. table.insert(res, name:sub(8))
  86. end
  87. end
  88. if sorted or sorted == nil then table.sort(res) end
  89. return res
  90. end
  91. -- Display the formspec
  92. local formspec_list = {}
  93. local selected_name = false
  94. function advmarkers.display_formspec()
  95. if not loaded then
  96. minetest.run_server_chatcommand('wp')
  97. return
  98. end
  99. local formspec = 'size[5.25,8]' ..
  100. 'label[0,0;Waypoint list ' ..
  101. minetest.colorize('#888888', '(SSCSM)') .. ']' ..
  102. 'button_exit[0,7.5;1.3125,0.5;display;Display]' ..
  103. 'button[1.3125,7.5;1.3125,0.5;teleport;Teleport]' ..
  104. 'button[2.625,7.5;1.3125,0.5;rename;Rename]' ..
  105. 'button[3.9375,7.5;1.3125,0.5;delete;Delete]' ..
  106. 'textlist[0,0.75;5,6;marker;'
  107. -- Iterate over all the markers
  108. local selected = 1
  109. formspec_list = advmarkers.get_waypoint_names()
  110. for id, name in ipairs(formspec_list) do
  111. if id > 1 then formspec = formspec .. ',' end
  112. if not selected_name then selected_name = name end
  113. if name == selected_name then selected = id end
  114. formspec = formspec .. '##' .. minetest.formspec_escape(name)
  115. end
  116. -- Close the text list and display the selected marker position
  117. formspec = formspec .. ';' .. tostring(selected) .. ']'
  118. if selected_name then
  119. local pos = advmarkers.get_marker(selected_name)
  120. if pos then
  121. pos = minetest.formspec_escape(tostring(pos.x) .. ', ' ..
  122. tostring(pos.y) .. ', ' .. tostring(pos.z))
  123. pos = 'Waypoint position: ' .. pos
  124. formspec = formspec .. 'label[0,6.75;' .. pos .. ']'
  125. end
  126. else
  127. -- Draw over the buttons
  128. formspec = formspec .. 'button_exit[0,7.5;5.25,0.5;quit;Close dialog]' ..
  129. 'label[0,6.75;No waypoints. Add one with "/add_wp".]'
  130. end
  131. -- Display the formspec
  132. return minetest.show_formspec('advmarkers-sscsm', formspec)
  133. end
  134. -- Register chatcommands
  135. local function mrkr_cmd(param)
  136. if param == '' then return advmarkers.display_formspec() end
  137. minetest.run_server_chatcommand('wp', param)
  138. end
  139. sscsm.register_chatcommand('mrkr', mrkr_cmd)
  140. sscsm.register_chatcommand('wp', mrkr_cmd)
  141. sscsm.register_chatcommand('wps', mrkr_cmd)
  142. sscsm.register_chatcommand('waypoint', mrkr_cmd)
  143. sscsm.register_chatcommand('waypoints', mrkr_cmd)
  144. -- Set the HUD
  145. minetest.register_on_formspec_input(function(formname, fields)
  146. if formname == 'advmarkers-ignore' then
  147. return true
  148. elseif formname ~= 'advmarkers-sscsm' then
  149. return
  150. end
  151. local name = false
  152. if fields.marker then
  153. local event = minetest.explode_textlist_event(fields.marker)
  154. if event.index then
  155. name = formspec_list[event.index]
  156. end
  157. else
  158. name = selected_name
  159. end
  160. if name then
  161. if fields.display then
  162. if not advmarkers.display_waypoint(name) then
  163. minetest.display_chat_message('Error displaying waypoint!')
  164. end
  165. elseif fields.rename then
  166. minetest.show_formspec('advmarkers-sscsm', 'size[6,3]' ..
  167. 'label[0.35,0.2;Rename waypoint]' ..
  168. 'field[0.3,1.3;6,1;new_name;New name;' ..
  169. minetest.formspec_escape(name) .. ']' ..
  170. 'button[0,2;3,1;cancel;Cancel]' ..
  171. 'button[3,2;3,1;rename_confirm;Rename]')
  172. elseif fields.rename_confirm then
  173. if fields.new_name and #fields.new_name > 0 then
  174. if advmarkers.rename_waypoint(name, fields.new_name) then
  175. selected_name = fields.new_name
  176. else
  177. minetest.display_chat_message('Error renaming waypoint!')
  178. end
  179. advmarkers.display_formspec()
  180. else
  181. minetest.display_chat_message(
  182. 'Please enter a new name for the waypoint.'
  183. )
  184. end
  185. elseif fields.teleport then
  186. minetest.show_formspec('advmarkers-sscsm', 'size[6,2.2]' ..
  187. 'label[0.35,0.25;' .. minetest.formspec_escape(
  188. 'Teleport to a waypoint\n - ' .. name
  189. ) .. ']' ..
  190. 'button[0,1.25;3,1;cancel;Cancel]' ..
  191. 'button_exit[3,1.25;3,1;teleport_confirm;Teleport]')
  192. elseif fields.teleport_confirm then
  193. -- Teleport with /teleport
  194. local pos = advmarkers.get_waypoint(name)
  195. if pos then
  196. minetest.run_server_chatcommand('teleport',
  197. pos.x .. ', ' .. pos.y .. ', ' .. pos.z)
  198. else
  199. minetest.display_chat_message('Error teleporting to waypoint!')
  200. end
  201. elseif fields.delete then
  202. minetest.show_formspec('advmarkers-sscsm', 'size[6,2]' ..
  203. 'label[0.35,0.25;Are you sure you want to delete this waypoint?]' ..
  204. 'button[0,1;3,1;cancel;Cancel]' ..
  205. 'button[3,1;3,1;delete_confirm;Delete]')
  206. elseif fields.delete_confirm then
  207. advmarkers.delete_waypoint(name)
  208. selected_name = false
  209. advmarkers.display_formspec()
  210. elseif fields.cancel then
  211. advmarkers.display_formspec()
  212. elseif name ~= selected_name then
  213. selected_name = name
  214. advmarkers.display_formspec()
  215. end
  216. elseif fields.display or fields.delete then
  217. minetest.display_chat_message('Please select a waypoint.')
  218. end
  219. return true
  220. end)
  221. -- Update the waypoint list
  222. sscsm.register_on_com_receive('advmarkers:update', function(msg)
  223. data = msg or {}
  224. loaded = true
  225. end)