functions.lua 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. ropes.make_rope_on_timer = function(rope_node_name)
  2. return function(pos, elapsed)
  3. local currentend = minetest.get_node(pos)
  4. local currentmeta = minetest.get_meta(pos)
  5. local currentlength = currentmeta:get_int("length_remaining")
  6. local placer_name = currentmeta:get_string("placer")
  7. local newpos = {x=pos.x, y=pos.y-1, z=pos.z}
  8. local newnode = minetest.get_node(newpos)
  9. local oldnode = minetest.get_node(pos)
  10. if currentlength > 1 and (not minetest.is_protected(newpos, placer_name)
  11. or minetest.check_player_privs(placer_name, "protection_bypass")) then
  12. if newnode.name == "air" then
  13. minetest.add_node(newpos, {name=currentend.name, param2=oldnode.param2})
  14. local newmeta = minetest.get_meta(newpos)
  15. newmeta:set_int("length_remaining", currentlength-1)
  16. newmeta:set_string("placer", placer_name)
  17. local infotext
  18. if currentlength > 2 then
  19. infotext = "Remaining length: " .. (currentlength-2)
  20. else
  21. infotext = "Reached end!"
  22. end
  23. newmeta:set_string("infotext", infotext)
  24. minetest.set_node(pos, {name=rope_node_name, param2=oldnode.param2})
  25. ropes.move_players_down(pos, 1)
  26. else
  27. local timer = minetest.get_node_timer( pos )
  28. timer:start( 1 )
  29. end
  30. end
  31. end
  32. end
  33. local data = {}
  34. local c_air = minetest.get_content_id("air")
  35. ropes.destroy_rope = function(pos, nodes)
  36. local top = pos.y
  37. local bottom = pos.y-15
  38. local voxel_manip = minetest.get_voxel_manip()
  39. local finished = false
  40. local ids_to_destroy = {}
  41. for _, node in pairs(nodes) do
  42. ids_to_destroy[minetest.get_content_id(node)] = true
  43. end
  44. while not finished do
  45. local emin, emax = voxel_manip:read_from_map({x=pos.x, y=bottom, z=pos.z}, {x=pos.x, y=top, z=pos.z})
  46. voxel_manip:get_data(data)
  47. local voxel_area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
  48. bottom = emin.y
  49. for y = top, bottom, -1 do
  50. local index = voxel_area:index(pos.x, y, pos.z)
  51. if ids_to_destroy[data[index]] then
  52. data[index] = c_air
  53. else
  54. finished = true
  55. break
  56. end
  57. end
  58. voxel_manip:set_data(data)
  59. voxel_manip:write_to_map()
  60. voxel_manip:update_map()
  61. top = bottom - 1
  62. bottom = bottom - 15
  63. end
  64. end
  65. ropes.hanging_after_destruct = function(pos, top_node, middle_node, bottom_node)
  66. local node = minetest.get_node(pos)
  67. if node.name == top_node or node.name == middle_node or node.name == bottom_node then
  68. return -- this was done by another ladder or rope node changing this one, don't react
  69. end
  70. pos.y = pos.y + 1 -- one up
  71. local node_above = minetest.get_node(pos)
  72. if node_above.name == middle_node then
  73. minetest.swap_node(pos, {name=bottom_node, param2=node_above.param2})
  74. end
  75. pos.y = pos.y - 2 -- one down
  76. local node_below = minetest.get_node(pos)
  77. if node_below.name == middle_node then
  78. ropes.destroy_rope(pos, {middle_node, bottom_node})
  79. elseif node_below.name == bottom_node then
  80. minetest.swap_node(pos, {name="air"})
  81. end
  82. end
  83. ropes.move_players_down = function(pos, radius)
  84. local all_objects = minetest.get_objects_inside_radius({x=pos.x, y=pos.y+radius, z=pos.z}, radius)
  85. local players = {}
  86. local _,obj
  87. for _,obj in pairs(all_objects) do
  88. if obj:is_player() then
  89. local obj_pos = obj:getpos()
  90. if math.abs(obj_pos.x-pos.x) < 0.5 and math.abs(obj_pos.z-pos.z) < 0.5 then
  91. obj:moveto({x=obj_pos.x, y=obj_pos.y-1, z=obj_pos.z}, true)
  92. end
  93. end
  94. end
  95. end