init.lua 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. tape_measure = {}
  2. local WAYPOINT_DISTANCE_LIMIT = 256
  3. local function measure(stack, player, pointed)
  4. if not stack or not player or not pointed then
  5. return
  6. end
  7. local controls = player:get_player_control()
  8. local pos
  9. if controls.aux1 then
  10. pos = vector.round(player:get_pos())
  11. elseif pointed.type == "node" then
  12. if controls.sneak then
  13. pos = pointed.above
  14. else
  15. pos = pointed.under
  16. end
  17. else
  18. return
  19. end
  20. if not pos then
  21. return
  22. end
  23. if not rc.is_valid_realm_pos(pos) then
  24. return
  25. end
  26. local pname = player:get_player_name()
  27. local meta = stack:get_meta()
  28. local realm = meta:get("start_realm") -- Returns nil if not present.
  29. local start = meta:get("start_pos") -- Returns nil if not present.
  30. local spos = minetest.pos_to_string(pos)
  31. if (not start) or (rc.current_realm_at_pos(pos) ~= realm) then
  32. meta:set_string("start_pos", spos)
  33. meta:set_string("start_realm", rc.current_realm_at_pos(pos))
  34. minetest.chat_send_player(pname, "# Server: Start position set to " .. rc.pos_to_namestr(pos) .. ".")
  35. return stack
  36. end
  37. start = minetest.string_to_pos(start)
  38. minetest.chat_send_player(pname, "# Server: End position set to " .. rc.pos_to_namestr(pos) .. ".")
  39. meta:set_string("start_pos", "")
  40. meta:set_string("start_realm", "")
  41. local dist = vector.distance(start, pos)
  42. dist = string.format("%s", math.floor(dist * 100) / 100).."m"
  43. local offset = vector.subtract(pos, start)
  44. local x, y, z = math.abs(offset.x), math.abs(offset.y), math.abs(offset.z)
  45. local size = {x=x+1, y=y+1, z=z+1}
  46. minetest.chat_send_player(
  47. pname, "# Server: Distance: " .. dist .. " | Size: " ..
  48. minetest.pos_to_string(size) .. ".")
  49. return stack
  50. end
  51. local player_waypoints = {}
  52. minetest.register_on_leaveplayer(function(player)
  53. local pname = player:get_player_name()
  54. player_waypoints[pname] = nil
  55. end)
  56. minetest.register_on_dieplayer(function(player)
  57. local pname = player:get_player_name()
  58. local data = player_waypoints[pname]
  59. if data then
  60. player:hud_remove(data.id)
  61. player_waypoints[pname] = nil
  62. end
  63. end)
  64. function tape_measure.realm_check(pname)
  65. local data = player_waypoints[pname]
  66. if not data then
  67. return
  68. end
  69. local pref = minetest.get_player_by_name(pname)
  70. if not pref then
  71. return
  72. end
  73. local realm = rc.current_realm(pref)
  74. -- Remove waypoint if realm changed.
  75. if realm ~= data.realm then
  76. pref:hud_remove(data.id)
  77. player_waypoints[pname] = nil
  78. return
  79. end
  80. -- Remove waypoint if player went too far.
  81. if vector.distance(data.pos, pref:get_pos()) > WAYPOINT_DISTANCE_LIMIT then
  82. pref:hud_remove(data.id)
  83. player_waypoints[pname] = nil
  84. return
  85. end
  86. minetest.after(1, function()
  87. tape_measure.realm_check(pname)
  88. end)
  89. end
  90. local function waypoint(stack, player, pointed)
  91. if not player or not pointed then
  92. return
  93. end
  94. local controls = player:get_player_control()
  95. if pointed.type == "node" and not controls.sneak then
  96. local pos = pointed.under
  97. local node = minetest.get_node(pos)
  98. local def = minetest.registered_nodes[node.name]
  99. if def and def.on_rightclick then
  100. return def.on_rightclick(pos, node, player, stack, pointed) or stack, nil
  101. end
  102. end
  103. local pos
  104. if controls.aux1 then
  105. pos = vector.round(player:get_pos())
  106. elseif pointed.type == "node" then
  107. if controls.sneak then
  108. pos = pointed.above
  109. else
  110. pos = pointed.under
  111. end
  112. end
  113. local pname = player:get_player_name()
  114. local point = player_waypoints[pname]
  115. if point then
  116. if pos and not vector.equals(pos, point.pos) then
  117. player:hud_change(point.id, "world_pos", pos)
  118. player_waypoints[pname].pos = pos
  119. player_waypoints[pname].realm = rc.current_realm_at_pos(pos)
  120. else
  121. player:hud_remove(point.id)
  122. player_waypoints[pname] = nil
  123. end
  124. return
  125. end
  126. if not pos then
  127. return
  128. end
  129. local id = player:hud_add({
  130. type = "waypoint",
  131. name = "Tape Measure Mark",
  132. number = 0xFFFFFF,
  133. world_pos = pos,
  134. })
  135. player_waypoints[pname] = {
  136. id = id,
  137. pos = pos,
  138. realm = rc.current_realm_at_pos(pos),
  139. }
  140. minetest.after(1, function()
  141. tape_measure.realm_check(pname)
  142. end)
  143. end
  144. minetest.register_tool("tape_measure:tape_measure", {
  145. description = "Tape Measure",
  146. inventory_image = "tape_measure_inv.png",
  147. wield_image = "tape_measure_wield.png",
  148. groups = {tool = 1},
  149. on_use = measure,
  150. on_place = waypoint,
  151. on_secondary_use = waypoint,
  152. })
  153. dofile(minetest.get_modpath("tape_measure") .. "/crafting.lua")