node_behaviors.lua 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. minetest.register_abm({
  2. nodenames = {"meseportals:portal_collider"},
  3. interval = 1,
  4. chance = 1,
  5. action = function(pos)
  6. local portalpos = minetest.string_to_pos(minetest.get_meta(pos):get_string("portal"))
  7. if portalpos then
  8. local nodeName = minetest.get_node(portalpos).name
  9. if nodeName ~= "ignore" then --If the portal is on the edge of the loaded world, wait to update
  10. if nodeName ~= "meseportals:portalnode_on" and nodeName ~= "meseportals:portalnode_off" then
  11. minetest.remove_node(pos)
  12. end
  13. end
  14. end
  15. end
  16. })
  17. minetest.register_abm({
  18. nodenames = {"meseportals:portalnode_on", "meseportals:portalnode_off"},
  19. interval = 1,
  20. chance = 1,
  21. action = function(pos)
  22. local current_portal = meseportals.findPortal(pos)
  23. if not current_portal then
  24. minetest.remove_node(pos)
  25. return
  26. end
  27. end
  28. })
  29. minetest.register_globalstep(function(dtime)
  30. local meta, infotext, pos1, pos, dir, dir1, hdiff, dest_portal
  31. for _, skip in pairs(meseportals_network) do
  32. for __, portal in pairs(skip) do
  33. if portal then
  34. pos = portal["pos"]
  35. if portal["time"] and not portal["admin_lock"] then -- Close portals automatically after a while
  36. if portal["time"] > 0 then
  37. portal["time"] = portal["time"] - dtime
  38. else
  39. portal["time"] = nil
  40. if portal["destination"] then
  41. meseportals.deactivatePortal(portal["destination"])
  42. end
  43. meseportals.deactivatePortal(pos)
  44. end
  45. end
  46. if minetest.get_node_or_nil(pos) then -- Do the complicated stuff only if the portal is loaded
  47. if minetest.get_node(pos).name ~= "meseportals:portalnode_off"
  48. and minetest.get_node(pos).name ~= "meseportals:portalnode_on"
  49. then --Portal broke
  50. if portal["destination"] then
  51. meseportals.deactivatePortal(portal["destination"])
  52. end
  53. meseportals.unregisterPortal(pos)
  54. elseif portal["updateme"] then -- Node needs to update
  55. if portal["destination"] == nil then
  56. if minetest.get_node(pos).name ~= "meseportals:portalnode_off" then
  57. minetest.sound_play("meseportal_close", {pos = pos, gain=0.6, max_hear_distance = 40})
  58. end
  59. meseportals.swap_portal_node(pos,"meseportals:portalnode_off",portal["dir"])
  60. else
  61. meseportals.swap_portal_node(pos,"meseportals:portalnode_on",portal["dir"])
  62. minetest.sound_play("meseportal_open", {pos = pos, gain=0.6, max_hear_distance = 40})
  63. end
  64. portal["updateme"] = false
  65. meseportals.save_data(portal["owner"])
  66. meta = minetest.get_meta(pos)
  67. if portal["type"]=="private" and meseportals.allowPrivatePortals then
  68. infotext="Private Portal"
  69. else
  70. infotext=(portal["description"])
  71. if meseportals.allowPrivatePortals then
  72. infotext=infotext.." ("..portal["owner"].."'s Public Portal)"
  73. end
  74. dest_portal = meseportals.findPortal(portal["destination"])
  75. if dest_portal then
  76. if dest_portal["type"] == "public" or not meseportals.allowPrivatePortals then
  77. infotext=infotext.."\nDestination: " ..portal["destination_description"] .." ("..portal["destination"].x..","..portal["destination"].y..","..portal["destination"].z..") "
  78. else
  79. infotext=infotext.."\nDestination: Private Portal"
  80. end
  81. end
  82. end
  83. if portal.admin_lock then
  84. infotext=infotext.."\nAdmin connection (Can not be closed)"
  85. end
  86. meta:set_string("infotext",infotext)
  87. end
  88. --Teleport players
  89. dest_portal=meseportals.findPortal(portal["destination"])
  90. if dest_portal then
  91. pos1 = vector.new(dest_portal["pos"])
  92. dir = portal.dir
  93. dir1 = portal.destination_dir
  94. for _,object in pairs(core.get_objects_inside_radius({x = pos.x, y = pos.y, z = pos.z}, 2)) do
  95. hdiff = nil
  96. if dir == 1
  97. or dir == 3 then
  98. if math.floor(object:get_pos().x + 0.5) == pos.x then
  99. hdiff = (object:get_pos().z - pos.z)
  100. end
  101. else
  102. if math.floor(object:get_pos().z + 0.5) == pos.z then
  103. hdiff = (object:get_pos().x - pos.x)
  104. end
  105. end
  106. if hdiff then
  107. pos1.y = pos1.y + (object:get_pos().y - pos.y) + 0.2
  108. local dest_angle = ((dir1 - 2) * -90)
  109. dest_angle = ((object:get_look_horizontal() or object:get_yaw()) + math.pi) + ((dir1 - dir) * -(math.pi/2))
  110. if dir == 1 or dir == 2 then
  111. hdiff = -hdiff
  112. end
  113. --hdiff = -1
  114. if dir1 == 0 then --ALL CORRECT
  115. pos1.z = pos1.z-1.25
  116. pos1.x = pos1.x - hdiff
  117. elseif dir1 == 1 then
  118. pos1.x = pos1.x-1.25
  119. pos1.z = pos1.z + hdiff
  120. elseif dir1 == 2 then
  121. pos1.z=pos1.z+1.25
  122. pos1.x = pos1.x + hdiff
  123. elseif dir1 == 3 then
  124. pos1.x = pos1.x+1.25
  125. pos1.z = pos1.z - hdiff
  126. end
  127. local vel = object:get_velocity() or object:get_player_velocity()
  128. vel.x = -vel.x
  129. local magnitude = math.sqrt((vel.x*vel.x) + (vel.z*vel.z))
  130. if math.abs(vel.z) < 0.01 then
  131. vel.z = 0.01
  132. end
  133. local direction = math.atan(vel.x/vel.z)
  134. -- Direction of velocity plus the change in look direction
  135. if vel.z < 0 then
  136. direction = direction + math.pi
  137. end
  138. direction = direction + math.pi + ((dir1 - dir) * -(math.pi/2))
  139. vel.x = magnitude * -math.sin(direction)
  140. vel.z = magnitude * math.cos(direction)
  141. local moved = false
  142. if object:is_player() then
  143. object:set_pos(pos1)
  144. if vector.equals(vector.round(object:get_pos()), vector.round(pos1)) then moved = true end
  145. elseif object:get_properties().physical == true then
  146. object:set_pos(pos1)
  147. moved = true
  148. end
  149. if moved then
  150. if object:is_player() then
  151. --player:set_player_velocity(vel) -- TODO: Bother the devs more about this
  152. object:set_look_horizontal(dest_angle)
  153. minetest.sound_play("meseportal_warp", {to_player=object:get_player_name(), gain=0.6, max_hear_distance=15})
  154. else
  155. object:set_velocity(vel)
  156. object:set_yaw(dest_angle)
  157. end
  158. minetest.sound_play("meseportal_warp", {pos = pos, gain=0.6, max_hear_distance=15})
  159. minetest.sound_play("meseportal_warp", {pos = pos1, gain=0.6, max_hear_distance=15})
  160. end
  161. end
  162. end
  163. else
  164. if portal["destination"] then --Destination portal broke/vanished
  165. meseportals.deactivatePortal(pos)
  166. end
  167. end
  168. end
  169. end
  170. end
  171. end
  172. end)