init.lua 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. -- LUALOCALS < ---------------------------------------------------------
  2. local math, minetest, pairs, tonumber
  3. = math, minetest, pairs, tonumber
  4. local math_sqrt
  5. = math.sqrt
  6. -- LUALOCALS > ---------------------------------------------------------
  7. local nodecore={}
  8. local modname = minetest.get_current_modname()
  9. local ext=loadfile(minetest.get_modpath(modname).."/ext.lua")
  10. ext(nodecore)
  11. -- Maximum distance at which custom nametags are visible.
  12. local distance = tonumber(minetest.settings:get(modname .. "_distance")) or 64
  13. ------------------------------------------------------------------------
  14. -- PLAYER JOIN/LEAVE
  15. -- On player joining, disable the built-in nametag by setting its
  16. -- text to whitespace and color to transparent.
  17. minetest.register_on_joinplayer(function(player)--"join hide nametag",
  18. player:set_nametag_attributes({
  19. text = " ",
  20. color = {a = 0, r = 0, g = 0, b = 0}
  21. })
  22. end)
  23. ------------------------------------------------------------------------
  24. -- GLOBAL TICK HUD MANAGEMENT
  25. local function fluidmedium(pos)
  26. local node = minetest.get_node(pos)
  27. local def = minetest.registered_items[node.name]
  28. if not def then return node.name end
  29. if def.sunlight_propagates then return "CLEAR" end
  30. return def.liquid_alternative_source or node.name
  31. end
  32. -- Determine if player 1 can see player 2's face, including
  33. -- checks for distance, line-of-sight, and facing direction.
  34. local function canseeface(p1, p2)
  35. if p1:get_hp() <= 0 or p2:get_hp() <= 0 then return end
  36. if p1:get_attach() or p2:get_attach() then return end
  37. if not nodecore.player_visible(p2) then return end
  38. -- Players must be within max distance of one another,
  39. -- determined by light level, but not too close.
  40. local o1 = p1:get_pos()
  41. local o2 = p2:get_pos()
  42. local e1 = p1:get_properties().eye_height or 1.625
  43. local e2 = p2:get_properties().eye_height or 1.625
  44. local dx = o1.x - o2.x
  45. local dy = o1.y - o2.y
  46. local dz = o1.z - o2.z
  47. local dsqr = (dx * dx + dy * dy + dz * dz)
  48. if dsqr < 1 then return end
  49. local ll = nodecore.get_node_light({x = o2.x, y = o2.y + e2, z = o2.z})
  50. if not ll then return end
  51. local ld = (ll / nodecore.light_sun * distance)
  52. if dsqr > (ld * ld) then return end
  53. -- Make sure players' eyes are inside the same fluid.
  54. o1.y = o1.y + e1
  55. o2.y = o2.y + e2
  56. local f1 = fluidmedium(o1)
  57. local f2 = fluidmedium(o2)
  58. if f1 ~= f2 then return end
  59. -- Check for line of sight from approximate eye level
  60. -- of one player to the other.
  61. for pt in minetest.raycast(o1, o2, true, true) do
  62. if pt.type == "node" then
  63. if fluidmedium(pt.under) ~= f1 then return end
  64. elseif pt.type == "object" then
  65. if pt.ref ~= p1 and pt.ref ~= p2 then return end
  66. else
  67. return
  68. end
  69. end
  70. -- Players must be facing each other; cannot identify another
  71. -- player's face when their back is turned. Note that
  72. -- minetest models don't show pitch, so ignore the y component.
  73. -- Compute normalized 2d vector from one player to another.
  74. --[[
  75. local d = dx * dx + dz * dz
  76. if d == 0 then return end
  77. d = math_sqrt(d)
  78. dx = dx / d
  79. dz = dz / d
  80. -- Compute normalized 2d facing direction vector for target player.
  81. local l2 = p2:get_look_dir()
  82. d = l2.x * l2.x + l2.z * l2.z
  83. if d == 0 then return end
  84. d = math_sqrt(d)
  85. l2.x = l2.x / d
  86. l2.z = l2.z / d
  87. -- Compare directions via dot product.
  88. if (dx * l2.x + dz * l2.z) <= 0.5 then return end
  89. --]]
  90. return true
  91. end
  92. -- On each global step, check all player visibility, and create/remove/update
  93. -- each player's HUDs accordingly.
  94. minetest.register_globalstep(function() --"player names",
  95. local conn = minetest.get_connected_players()
  96. for _, p1 in pairs(conn) do
  97. for _, p2 in pairs(conn) do
  98. if p2 ~= p1 then
  99. local n2 = p2:get_player_name()
  100. if canseeface(p1, p2) then
  101. local p = p2:get_pos()
  102. p.y = p.y + 1.25
  103. nodecore.hud_set(p1, {
  104. label = "pname:" .. n2,
  105. hud_elem_type = "waypoint",
  106. world_pos = p,
  107. name = n2,
  108. text = "",
  109. precision = 0,
  110. number = 0xffffff,
  111. quick = true
  112. })
  113. else
  114. nodecore.hud_set(p1, {
  115. label = "pname:" .. n2,
  116. ttl = 0,
  117. quick = true
  118. })
  119. end
  120. end
  121. end
  122. end
  123. end)
  124. minetest.register_on_leaveplayer(function(player)--"leave clear names",
  125. local pname = player:get_player_name()
  126. for _, peer in pairs(minetest.get_connected_players()) do
  127. nodecore.hud_set(peer, {
  128. label = "pname:" .. pname,
  129. ttl = 0,
  130. quick = true
  131. })
  132. end
  133. end)