pos.lua 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. -- I could depend on WorldEdit for this, but you need to have the 'worldedit'
  2. -- permission to use those commands and you don't have
  3. -- /area_pos{1,2} [X Y Z|X,Y,Z].
  4. -- Since this is mostly copied from WorldEdit it is mostly
  5. -- licensed under the AGPL. (select_area is a exception)
  6. areas.marker1 = {}
  7. areas.marker2 = {}
  8. areas.set_pos = {}
  9. areas.pos1 = {}
  10. areas.pos2 = {}
  11. minetest.register_chatcommand("select_area", {
  12. params = "<ID>",
  13. description = "Select a area by id.",
  14. func = function(name, param)
  15. local id = tonumber(param)
  16. if not id then
  17. return false, "Invalid usage, see /help select_area."
  18. end
  19. if not areas.areas[id] then
  20. return false, "The area "..id.." does not exist."
  21. end
  22. areas:setPos1(name, areas.areas[id].pos1)
  23. areas:setPos2(name, areas.areas[id].pos2)
  24. return true, "Area "..id.." selected."
  25. end,
  26. })
  27. minetest.register_chatcommand("area_pos1", {
  28. params = "[X Y Z|X,Y,Z]",
  29. description = "Set area protection region position 1 to your"
  30. .." location or the one specified",
  31. privs = {},
  32. func = function(name, param)
  33. local pos = nil
  34. local found, _, x, y, z = param:find(
  35. "^(-?%d+)[, ](-?%d+)[, ](-?%d+)$")
  36. if found then
  37. pos = {x=tonumber(x), y=tonumber(y), z=tonumber(z)}
  38. elseif param == "" then
  39. local player = minetest.get_player_by_name(name)
  40. if player then
  41. pos = player:getpos()
  42. else
  43. return false, "Unable to get position."
  44. end
  45. else
  46. return false, "Invalid usage, see /help area_pos1."
  47. end
  48. pos = vector.round(pos)
  49. areas:setPos1(name, pos)
  50. return true, "Area position 1 set to "
  51. ..minetest.pos_to_string(pos)
  52. end,
  53. })
  54. minetest.register_chatcommand("area_pos2", {
  55. params = "[X Y Z|X,Y,Z]",
  56. description = "Set area protection region position 2 to your"
  57. .." location or the one specified",
  58. func = function(name, param)
  59. local pos = nil
  60. local found, _, x, y, z = param:find(
  61. "^(-?%d+)[, ](-?%d+)[, ](-?%d+)$")
  62. if found then
  63. pos = {x=tonumber(x), y=tonumber(y), z=tonumber(z)}
  64. elseif param == "" then
  65. local player = minetest.get_player_by_name(name)
  66. if player then
  67. pos = player:getpos()
  68. else
  69. return false, "Unable to get position."
  70. end
  71. else
  72. return false, "Invalid usage, see /help area_pos2."
  73. end
  74. pos = vector.round(pos)
  75. areas:setPos2(name, pos)
  76. return true, "Area position 2 set to "
  77. ..minetest.pos_to_string(pos)
  78. end,
  79. })
  80. minetest.register_chatcommand("area_pos", {
  81. params = "set/set1/set2/get",
  82. description = "Set area protection region, position 1, or position 2"
  83. .." by punching nodes, or display the region",
  84. func = function(name, param)
  85. if param == "set" then -- Set both area positions
  86. areas.set_pos[name] = "pos1"
  87. return true, "Select positions by punching two nodes."
  88. elseif param == "set1" then -- Set area position 1
  89. areas.set_pos[name] = "pos1only"
  90. return true, "Select position 1 by punching a node."
  91. elseif param == "set2" then -- Set area position 2
  92. areas.set_pos[name] = "pos2"
  93. return true, "Select position 2 by punching a node."
  94. elseif param == "get" then -- Display current area positions
  95. local pos1str, pos2str = "Position 1: ", "Position 2: "
  96. if areas.pos1[name] then
  97. pos1str = pos1str..minetest.pos_to_string(areas.pos1[name])
  98. else
  99. pos1str = pos1str.."<not set>"
  100. end
  101. if areas.pos2[name] then
  102. pos2str = pos2str..minetest.pos_to_string(areas.pos2[name])
  103. else
  104. pos2str = pos2str.."<not set>"
  105. end
  106. return true, pos1str.."\n"..pos2str
  107. else
  108. return false, "Unknown subcommand: "..param
  109. end
  110. end,
  111. })
  112. function areas:getPos(playerName)
  113. local pos1, pos2 = areas.pos1[playerName], areas.pos2[playerName]
  114. if not (pos1 and pos2) then
  115. return nil
  116. end
  117. -- Copy positions so that the area table doesn't contain multiple
  118. -- references to the same position.
  119. pos1, pos2 = vector.new(pos1), vector.new(pos2)
  120. return areas:sortPos(pos1, pos2)
  121. end
  122. function areas:setPos1(playerName, pos)
  123. areas.pos1[playerName] = pos
  124. areas.markPos1(playerName)
  125. end
  126. function areas:setPos2(playerName, pos)
  127. areas.pos2[playerName] = pos
  128. areas.markPos2(playerName)
  129. end
  130. minetest.register_on_punchnode(function(pos, node, puncher)
  131. local name = puncher:get_player_name()
  132. -- Currently setting position
  133. if name ~= "" and areas.set_pos[name] then
  134. if areas.set_pos[name] == "pos1" then
  135. areas.pos1[name] = pos
  136. areas.markPos1(name)
  137. areas.set_pos[name] = "pos2"
  138. minetest.chat_send_player(name,
  139. "Position 1 set to "
  140. ..minetest.pos_to_string(pos))
  141. elseif areas.set_pos[name] == "pos1only" then
  142. areas.pos1[name] = pos
  143. areas.markPos1(name)
  144. areas.set_pos[name] = nil
  145. minetest.chat_send_player(name,
  146. "Position 1 set to "
  147. ..minetest.pos_to_string(pos))
  148. elseif areas.set_pos[name] == "pos2" then
  149. areas.pos2[name] = pos
  150. areas.markPos2(name)
  151. areas.set_pos[name] = nil
  152. minetest.chat_send_player(name,
  153. "Position 2 set to "
  154. ..minetest.pos_to_string(pos))
  155. end
  156. end
  157. end)
  158. -- Modifies positions `pos1` and `pos2` so that each component of `pos1`
  159. -- is less than or equal to its corresponding component of `pos2`,
  160. -- returning the two positions.
  161. function areas:sortPos(pos1, pos2)
  162. if pos1.x > pos2.x then
  163. pos2.x, pos1.x = pos1.x, pos2.x
  164. end
  165. if pos1.y > pos2.y then
  166. pos2.y, pos1.y = pos1.y, pos2.y
  167. end
  168. if pos1.z > pos2.z then
  169. pos2.z, pos1.z = pos1.z, pos2.z
  170. end
  171. return pos1, pos2
  172. end
  173. -- Marks area position 1
  174. areas.markPos1 = function(name)
  175. local pos = areas.pos1[name]
  176. if areas.marker1[name] ~= nil then -- Marker already exists
  177. areas.marker1[name]:remove() -- Remove marker
  178. areas.marker1[name] = nil
  179. end
  180. if pos ~= nil then -- Add marker
  181. areas.marker1[name] = minetest.add_entity(pos, "areas:pos1")
  182. areas.marker1[name]:get_luaentity().active = true
  183. end
  184. end
  185. -- Marks area position 2
  186. areas.markPos2 = function(name)
  187. local pos = areas.pos2[name]
  188. if areas.marker2[name] ~= nil then -- Marker already exists
  189. areas.marker2[name]:remove() -- Remove marker
  190. areas.marker2[name] = nil
  191. end
  192. if pos ~= nil then -- Add marker
  193. areas.marker2[name] = minetest.add_entity(pos, "areas:pos2")
  194. areas.marker2[name]:get_luaentity().active = true
  195. end
  196. end
  197. minetest.register_entity("areas:pos1", {
  198. initial_properties = {
  199. visual = "cube",
  200. visual_size = {x=1.1, y=1.1},
  201. textures = {"areas_pos1.png", "areas_pos1.png",
  202. "areas_pos1.png", "areas_pos1.png",
  203. "areas_pos1.png", "areas_pos1.png"},
  204. collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55},
  205. },
  206. on_step = function(self, dtime)
  207. if self.active == nil then
  208. self.object:remove()
  209. end
  210. end,
  211. on_punch = function(self, hitter)
  212. self.object:remove()
  213. local name = hitter:get_player_name()
  214. areas.marker1[name] = nil
  215. end,
  216. })
  217. minetest.register_entity("areas:pos2", {
  218. initial_properties = {
  219. visual = "cube",
  220. visual_size = {x=1.1, y=1.1},
  221. textures = {"areas_pos2.png", "areas_pos2.png",
  222. "areas_pos2.png", "areas_pos2.png",
  223. "areas_pos2.png", "areas_pos2.png"},
  224. collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55},
  225. },
  226. on_step = function(self, dtime)
  227. if self.active == nil then
  228. self.object:remove()
  229. end
  230. end,
  231. on_punch = function(self, hitter)
  232. self.object:remove()
  233. local name = hitter:get_player_name()
  234. areas.marker2[name] = nil
  235. end,
  236. })