From d202fd497f5cdf7026530adea377f32492e4e84b Mon Sep 17 00:00:00 2001 From: FaceDeer Date: Mon, 30 Jan 2017 01:56:44 -0700 Subject: [PATCH] Rewriting rope ladder and rope severing to be more robust, can now be done with a default axe --- crafts.lua | 6 +- functions.lua | 77 ++++++++++++++------- ladder.lua | 74 ++++++++++++--------- ropeboxes.lua | 181 ++++++++++++++++++++++++++------------------------ 4 files changed, 192 insertions(+), 146 deletions(-) diff --git a/crafts.lua b/crafts.lua index 271ae08..fa379b1 100644 --- a/crafts.lua +++ b/crafts.lua @@ -10,7 +10,7 @@ minetest.register_craft({ }) minetest.register_craftitem("vines:ropesegment", { - description = "Rope", - groups = {vines = 1}, - inventory_image = "vines_item.png", + description = "Rope", + groups = {vines = 1}, + inventory_image = "vines_item.png", }) diff --git a/functions.lua b/functions.lua index abd0dbe..966990f 100644 --- a/functions.lua +++ b/functions.lua @@ -132,42 +132,69 @@ end local c_air = minetest.get_content_id("air") -vines.destroy_rope_starting = function( p, targetnode, bottomnode, topnode ) - local n = minetest.get_node(p).name - if n ~= targetnode and n ~= bottomnode then +vines.destroy_rope_starting = function(pos, targetnode, bottomnode, topnode ) + local node_name = minetest.get_node(pos).name + if node_name ~= targetnode and node_name ~= bottomnode then return end - local y1 = p.y - local tab = {} - local i = 1 - while n == targetnode do - tab[i] = p - i = i+1 - p.y = p.y-1 - n = minetest.get_node(p).name + local y_top = pos.y + local y_bottom = y_top + local true_bottom = true + while true do + minetest.debug("loop", y_bottom) + node_name = minetest.get_node({x=pos.x, y=y_bottom - 1, z=pos.z}).name + if node_name == targetnode or node_name == bottomnode then + y_bottom = y_bottom - 1 + elseif node_name == "ignore" then + true_bottom = false + break + else + break + end end - if n == bottomnode then - tab[i] = p - end - local y0 = p.y local manip = minetest.get_voxel_manip() - local p0 = {x=p.x, y=y0, z=p.z} - local p1 = {x=p.x, y=y0+1, z=p.z} - local p2 = {x=p.x, y=y1, z=p.z} - local pos1, pos2 = manip:read_from_map(p0, p2) - area = VoxelArea:new({MinEdge=pos1, MaxEdge=pos2}) - nodes = manip:get_data() + local pos_bottom = {x=pos.x, y=y_bottom, z=pos.z} + local pos_top = {x=pos.x, y=y_top, z=pos.z} + local pos1, pos2 = manip:read_from_map(pos_bottom, pos_top) + local area = VoxelArea:new({MinEdge=pos1, MaxEdge=pos2}) + local nodes = manip:get_data() - for i in area:iterp(p1, p2) do + for i in area:iterp(pos_bottom, pos_top) do nodes[i] = c_air end - nodes[area:indexp(p0)] = minetest.get_content_id(topnode) + if not true_bottom then + nodes[area:indexp(pos_bottom)] = minetest.get_content_id(topnode) + end manip:set_data(nodes) manip:write_to_map() manip:update_map() -- <— this takes time - local timer = minetest.get_node_timer( p0 ) - timer:start( 1 ) + if not true_bottom then + minetest.get_node_timer(pos_bottom):start(1) + end end + +vines.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 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 + vines.destroy_rope_starting(pos, middle_node, bottom_node, top_node) + --minetest.swap_node(pos, {name="vines:ropeladder_falling", param2=node_below.param2}) + --minetest.get_node_timer(pos):start(0) + elseif node_below.name == bottom_node then + minetest.swap_node(pos, {name="air"}) + end +end \ No newline at end of file diff --git a/ladder.lua b/ladder.lua index 1fde826..e127652 100644 --- a/ladder.lua +++ b/ladder.lua @@ -18,24 +18,23 @@ minetest.register_node("vines:ropeladder_top", { }, groups = { choppy=2, oddly_breakable_by_hand=1,flammable=2}, - legacy_wallmounted = true, sounds = default.node_sound_wood_defaults(), after_place_node = function(pos) - local p = {x=pos.x, y=pos.y-1, z=pos.z} - local n = minetest.get_node(p) - local o = minetest.get_node(pos) + local pos_below = {x=pos.x, y=pos.y-1, z=pos.z} + local node_below = minetest.get_node(pos_below) + local this_node = minetest.get_node(pos) -- param2 holds the facing direction of this node. If it's 0 or 1 the node is "flat" and we don't want the ladder to extend. - if n.name == "air" and o.param2 > 1 then - minetest.add_node(p, {name="vines:ropeladder_bottom", param2=o.param2}) - local meta = minetest.get_meta(p) + if node_below.name == "air" and this_node.param2 > 1 then + minetest.add_node(pos_below, {name="vines:ropeladder_bottom", param2=this_node.param2}) + local meta = minetest.get_meta(pos_below) meta:set_int("length_remaining", vines.ropeLadderLength) end end, after_destruct = function(pos) - local p = {x=pos.x, y=pos.y-1, z=pos.z} - vines.destroy_rope_starting(p, 'vines:ropeladder', 'vines:ropeladder_bottom', 'vines:ropeladder_falling') - end + local pos_below = {x=pos.x, y=pos.y-1, z=pos.z} + vines.destroy_rope_starting(pos_below, "vines:ropeladder", "vines:ropeladder_bottom", "vines:ropeladder_falling") + end, }) minetest.register_craft({ @@ -48,6 +47,7 @@ minetest.register_craft({ minetest.register_node("vines:ropeladder", { description = "Rope ladder", + drop = "", drawtype = "signlike", tiles = {"default_ladder_wood.png^vines_ropeladder.png"}, is_ground_content = false, @@ -63,15 +63,18 @@ minetest.register_node("vines:ropeladder", { --wall_top = = --wall_bottom = = --wall_side = = - }, - groups = {flammable=2, not_in_creative_inventory=1}, - legacy_wallmounted = true, + groups = {choppy=2, flammable=2, not_in_creative_inventory=1}, sounds = default.node_sound_wood_defaults(), + + after_destruct = function(pos) + vines.hanging_after_destruct(pos, "vines:ropeladder_falling", "vines:ropeladder", "vines:ropeladder_bottom") + end, }) minetest.register_node("vines:ropeladder_bottom", { description = "Rope ladder", + drop = "", drawtype = "signlike", tiles = {"default_ladder_wood.png^vines_ropeladder_bottom.png"}, is_ground_content = false, @@ -89,8 +92,7 @@ minetest.register_node("vines:ropeladder_bottom", { --wall_side = = }, - groups = {flammable=2, not_in_creative_inventory=1}, - legacy_wallmounted = true, + groups = {choppy=2, flammable=2, not_in_creative_inventory=1}, sounds = default.node_sound_wood_defaults(), on_construct = function( pos ) local timer = minetest.get_node_timer( pos ) @@ -100,23 +102,30 @@ minetest.register_node("vines:ropeladder_bottom", { local currentend = minetest.get_node(pos) local currentmeta = minetest.get_meta(pos) local currentlength = currentmeta:get_int("length_remaining") - local p = {x=pos.x, y=pos.y-1, z=pos.z} - local n = minetest.get_node(p) - local o = minetest.get_node(pos) - if n.name == "air" and (currentlength > 1) then - minetest.add_node(p, {name="vines:ropeladder_bottom", param2=o.param2}) - local newmeta = minetest.get_meta(p) - newmeta:set_int("length_remaining", currentlength-1) - minetest.set_node(pos, {name="vines:ropeladder", param2=o.param2}) - else - local timer = minetest.get_node_timer( pos ) - timer:start( 1 ) + 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 then + if newnode.name == "air" then + minetest.add_node(newpos, {name="vines:ropeladder_bottom", param2=oldnode.param2}) + local newmeta = minetest.get_meta(newpos) + newmeta:set_int("length_remaining", currentlength-1) + minetest.set_node(pos, {name="vines:ropeladder", param2=oldnode.param2}) + else + local timer = minetest.get_node_timer( pos ) + timer:start( 1 ) + end end - end + end, + + after_destruct = function(pos) + vines.hanging_after_destruct(pos, "vines:ropeladder_falling", "vines:ropeladder", "vines:ropeladder_bottom") + end, }) minetest.register_node("vines:ropeladder_falling", { description = "Rope ladder", + drop = "", drawtype = "signlike", tiles = {"default_ladder_wood.png^vines_ropeladder.png"}, is_ground_content = false, @@ -135,19 +144,18 @@ minetest.register_node("vines:ropeladder_falling", { }, groups = {flammable=2, not_in_creative_inventory=1}, - legacy_wallmounted = true, sounds = default.node_sound_wood_defaults(), on_construct = function( pos ) local timer = minetest.get_node_timer( pos ) timer:start( 1 ) end, on_timer = function( pos, elapsed ) - local p = {x=pos.x, y=pos.y-1, z=pos.z} - local n = minetest.get_node(p) + local pos_below = {x=pos.x, y=pos.y-1, z=pos.z} + local node_below = minetest.get_node(pos_below) - if (n.name ~= "ignore") then - vines.destroy_rope_starting(p, 'vines:ropeladder', 'vines:ropeladder_bottom', 'vines:ropeladder_falling') - minetest.set_node(pos, {name="air"}) + if (node_below.name ~= "ignore") then + vines.destroy_rope_starting(pos_below, 'vines:ropeladder', 'vines:ropeladder_bottom', 'vines:ropeladder_falling') + minetest.swap_node(pos, {name="air"}) else local timer = minetest.get_node_timer( pos ) timer:start( 1 ) diff --git a/ropeboxes.lua b/ropeboxes.lua index 9cf7b06..b976201 100644 --- a/ropeboxes.lua +++ b/ropeboxes.lua @@ -26,20 +26,20 @@ local function register_rope_block(multiple, pixels) }, selection_box = {type="regular"}, collision_box = {type="regular"}, - groups = { flammable=2, choppy=2, oddly_breakable_by_hand=1 }, + groups = {flammable=2, choppy=2, oddly_breakable_by_hand=1}, after_place_node = function(pos) - local p = {x=pos.x, y=pos.y-1, z=pos.z} - local n = minetest.get_node(p) - if n.name == "air" then - minetest.add_node(p, {name="vines:rope_bottom"}) - local meta = minetest.get_meta(p) + local pos_below = {x=pos.x, y=pos.y-1, z=pos.z} + local node_below = minetest.get_node(pos_below) + if node_below.name == "air" then + minetest.add_node(pos_below, {name="vines:rope_bottom"}) + local meta = minetest.get_meta(pos_below) meta:set_int("length_remaining", vines.ropeLength*multiple) end end, after_destruct = function(pos) - local p = {x=pos.x, y=pos.y-1, z=pos.z} - vines.destroy_rope_starting(p, 'vines:rope', 'vines:rope_bottom', 'vines:rope_top') + local pos_below = {x=pos.x, y=pos.y-1, z=pos.z} + vines.destroy_rope_starting(pos_below, 'vines:rope', 'vines:rope_bottom', 'vines:rope_top') end }) @@ -82,88 +82,99 @@ register_rope_block(4, 10) register_rope_block(5, 12) minetest.register_node("vines:rope", { - description = "Rope", - walkable = false, - climbable = true, - sunlight_propagates = true, - paramtype = "light", - drop = "", - tiles = { "vines_rope.png" }, - drawtype = "plantlike", - groups = {flammable=2, not_in_creative_inventory=1}, - sounds = default.node_sound_leaves_defaults(), - selection_box = { - type = "fixed", - fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7}, - }, + description = "Rope", + walkable = false, + climbable = true, + sunlight_propagates = true, + paramtype = "light", + drop = "", + tiles = { "vines_rope.png" }, + drawtype = "plantlike", + groups = {choppy=2, flammable=2, not_in_creative_inventory=1}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7}, + }, + after_destruct = function(pos) + vines.hanging_after_destruct(pos, "vines:rope_top", "vines:rope", "vines:rope_bottom") + end, }) minetest.register_node("vines:rope_bottom", { - description = "Rope", - walkable = false, - climbable = true, - sunlight_propagates = true, - paramtype = "light", - drop = "", - tiles = { "vines_rope_bottom.png" }, - drawtype = "plantlike", - groups = {flammable=2, not_in_creative_inventory=1}, - sounds = default.node_sound_leaves_defaults(), - selection_box = { - type = "fixed", - fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7}, - }, - on_construct = function( pos ) - local timer = minetest.get_node_timer( pos ) - timer:start( 1 ) - end, - on_timer = function( pos, elapsed ) - local currentend = minetest.get_node(pos) - local currentmeta = minetest.get_meta(pos) - local currentlength = currentmeta:get_int("length_remaining") - local p = {x=pos.x, y=pos.y-1, z=pos.z} - local n = minetest.get_node(p) - if n.name == "air" and (currentlength > 1) then - minetest.add_node(p, {name="vines:rope_bottom"}) - local newmeta = minetest.get_meta(p) - newmeta:set_int("length_remaining", currentlength-1) - minetest.set_node(pos, {name="vines:rope"}) - else - local timer = minetest.get_node_timer( pos ) - timer:start( 1 ) - end - end + description = "Rope", + walkable = false, + climbable = true, + sunlight_propagates = true, + paramtype = "light", + drop = "", + tiles = { "vines_rope_bottom.png" }, + drawtype = "plantlike", + groups = {choppy=2, flammable=2, not_in_creative_inventory=1}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7}, + }, + + on_construct = function( pos ) + local timer = minetest.get_node_timer( pos ) + timer:start( 1 ) + end, + + on_timer = function( pos, elapsed ) + local currentend = minetest.get_node(pos) + local currentmeta = minetest.get_meta(pos) + local currentlength = currentmeta:get_int("length_remaining") + local pos_below = {x=pos.x, y=pos.y-1, z=pos.z} + local node_below = minetest.get_node(pos_below) + if node_below.name == "air" and (currentlength > 1) then + minetest.add_node(pos_below, {name="vines:rope_bottom"}) + local newmeta = minetest.get_meta(pos_below) + newmeta:set_int("length_remaining", currentlength-1) + minetest.set_node(pos, {name="vines:rope"}) + else + local timer = minetest.get_node_timer( pos ) + timer:start( 1 ) + end + end, + + after_destruct = function(pos) + vines.hanging_after_destruct(pos, "vines:rope_top", "vines:rope", "vines:rope_bottom") + end, }) minetest.register_node("vines:rope_top", { - description = "Rope", - walkable = false, - climbable = true, - sunlight_propagates = true, - paramtype = "light", - drop = "", - tiles = { "vines_rope_top.png" }, - drawtype = "plantlike", - groups = {not_in_creative_inventory=1}, - sounds = default.node_sound_leaves_defaults(), - selection_box = { - type = "fixed", - fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7}, - }, - on_construct = function( pos ) - local timer = minetest.get_node_timer( pos ) - timer:start( 1 ) - end, - on_timer = function( pos, elapsed ) - local p = {x=pos.x, y=pos.y-1, z=pos.z} - local n = minetest.get_node(p) - - if (n.name ~= "ignore") then - vines.destroy_rope_starting(p, 'vines:rope', 'vines:rope_bottom', 'vines:rope_top') - minetest.set_node(pos, {name="air"}) - else - local timer = minetest.get_node_timer( pos ) + description = "Rope", + walkable = false, + climbable = true, + sunlight_propagates = true, + paramtype = "light", + drop = "", + tiles = { "vines_rope_top.png" }, + drawtype = "plantlike", + groups = {not_in_creative_inventory=1}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7}, + }, + + on_construct = function( pos ) + local timer = minetest.get_node_timer( pos ) timer:start( 1 ) - end - end + end, + + on_timer = function( pos, elapsed ) + local p = {x=pos.x, y=pos.y-1, z=pos.z} + local n = minetest.get_node(p) + + if (n.name ~= "ignore") then + vines.destroy_rope_starting(p, 'vines:rope', 'vines:rope_bottom', 'vines:rope_top') + minetest.swap_node(pos, {name="air"}) + else + local timer = minetest.get_node_timer( pos ) + timer:start( 1 ) + end + end, })