mirror of
https://github.com/minetest-mods/ropes.git
synced 2024-11-28 10:23:44 +01:00
52a32fe1f2
This change includes some extensive rewriting of the shared underlying functions as well as the cosmetic changes. Rope destruction should happen instantly down its entire length now. Rope boxes themselves are now "climbable", making it easier to transfer from one rope to another. There's also a new user setting for limiting the number of rope box types available to the player.
98 lines
3.1 KiB
Lua
98 lines
3.1 KiB
Lua
ropes.make_rope_on_timer = function(rope_node_name)
|
|
return function(pos, elapsed)
|
|
local currentend = minetest.get_node(pos)
|
|
local currentmeta = minetest.get_meta(pos)
|
|
local currentlength = currentmeta:get_int("length_remaining")
|
|
local placer_name = currentmeta:get_string("placer")
|
|
local newpos = {x=pos.x, y=pos.y-1, z=pos.z}
|
|
local newnode = minetest.get_node(newpos)
|
|
local oldnode = minetest.get_node(pos)
|
|
if currentlength > 1 and (not minetest.is_protected(newpos, placer_name)
|
|
or minetest.check_player_privs(placer_name, "protection_bypass")) then
|
|
if newnode.name == "air" then
|
|
minetest.add_node(newpos, {name=currentend.name, param2=oldnode.param2})
|
|
local newmeta = minetest.get_meta(newpos)
|
|
newmeta:set_int("length_remaining", currentlength-1)
|
|
newmeta:set_string("placer", placer_name)
|
|
minetest.set_node(pos, {name=rope_node_name, param2=oldnode.param2})
|
|
ropes.move_players_down(pos, 1)
|
|
else
|
|
local timer = minetest.get_node_timer( pos )
|
|
timer:start( 1 )
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local data = {}
|
|
local c_air = minetest.get_content_id("air")
|
|
|
|
ropes.destroy_rope = function(pos, nodes)
|
|
local top = pos.y
|
|
local bottom = pos.y-15
|
|
local voxel_manip = minetest.get_voxel_manip()
|
|
|
|
local finished = false
|
|
local ids_to_destroy = {}
|
|
for _, node in pairs(nodes) do
|
|
ids_to_destroy[minetest.get_content_id(node)] = true
|
|
end
|
|
|
|
while not finished do
|
|
local emin, emax = voxel_manip:read_from_map({x=pos.x, y=bottom, z=pos.z}, {x=pos.x, y=top, z=pos.z})
|
|
voxel_manip:get_data(data)
|
|
local voxel_area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
|
|
bottom = emin.y
|
|
for y = top, bottom, -1 do
|
|
local index = voxel_area:index(pos.x, y, pos.z)
|
|
if ids_to_destroy[data[index]] then
|
|
data[index] = c_air
|
|
else
|
|
finished = true
|
|
break
|
|
end
|
|
end
|
|
voxel_manip:set_data(data)
|
|
voxel_manip:write_to_map()
|
|
voxel_manip:update_map()
|
|
top = bottom - 1
|
|
bottom = bottom - 15
|
|
end
|
|
end
|
|
|
|
|
|
ropes.hanging_after_destruct = function(pos, top_node, middle_node, bottom_node)
|
|
local node = minetest.get_node(pos)
|
|
if node.name == top_node or node.name == middle_node or node.name == bottom_node then
|
|
return -- this was done by another ladder or rope node changing this one, don't react
|
|
end
|
|
|
|
pos.y = pos.y + 1 -- one up
|
|
local node_above = minetest.get_node(pos)
|
|
if node_above.name == middle_node then
|
|
minetest.swap_node(pos, {name=bottom_node, param2=node_above.param2})
|
|
end
|
|
|
|
pos.y = pos.y - 2 -- one down
|
|
local node_below = minetest.get_node(pos)
|
|
if node_below.name == middle_node then
|
|
ropes.destroy_rope(pos, {middle_node, bottom_node})
|
|
elseif node_below.name == bottom_node then
|
|
minetest.swap_node(pos, {name="air"})
|
|
end
|
|
end
|
|
|
|
ropes.move_players_down = function(pos, radius)
|
|
local all_objects = minetest.get_objects_inside_radius({x=pos.x, y=pos.y+radius, z=pos.z}, radius)
|
|
local players = {}
|
|
local _,obj
|
|
for _,obj in pairs(all_objects) do
|
|
if obj:is_player() then
|
|
local obj_pos = obj:getpos()
|
|
if math.abs(obj_pos.x-pos.x) < 0.5 and math.abs(obj_pos.z-pos.z) < 0.5 then
|
|
obj:moveto({x=obj_pos.x, y=obj_pos.y-1, z=obj_pos.z}, true)
|
|
end
|
|
end
|
|
end
|
|
end
|