From c6365827077185524f206020cbd1c6b9b7cf18f8 Mon Sep 17 00:00:00 2001 From: Phvli Date: Sun, 4 May 2014 19:59:37 +0300 Subject: [PATCH] Make sure chainsaw drops appear above ground A fix for https://github.com/minetest-technic/technic/issues/137 Chainsaw drops are forced to pop above ground. Also, as asl suggested, they must not end up too high on a ledge or a pillar. This also cleans up the code style of chainsaw.lua. --- technic/tools/chainsaw.lua | 396 +++++++++++++++++++------------------ 1 file changed, 208 insertions(+), 188 deletions(-) diff --git a/technic/tools/chainsaw.lua b/technic/tools/chainsaw.lua index 42e93ef..c40244f 100644 --- a/technic/tools/chainsaw.lua +++ b/technic/tools/chainsaw.lua @@ -22,102 +22,102 @@ if minetest.get_modpath("technic_worldgen") or timber_nodenames["moretrees:rubber_tree_trunk_empty"] = true timber_nodenames["moretrees:rubber_tree_trunk"] = true if chainsaw_leaves then - timber_nodenames["moretrees:rubber_tree_leaves"] = true + timber_nodenames["moretrees:rubber_tree_leaves"] = true end end -- Support moretrees if it is there if( minetest.get_modpath("moretrees") ~= nil ) then - timber_nodenames["moretrees:apple_tree_trunk"] = true - timber_nodenames["moretrees:apple_tree_trunk_sideways"] = true - timber_nodenames["moretrees:beech_trunk"] = true - timber_nodenames["moretrees:beech_trunk_sideways"] = true - timber_nodenames["moretrees:birch_trunk"] = true - timber_nodenames["moretrees:birch_trunk_sideways"] = true - timber_nodenames["moretrees:fir_trunk"] = true - timber_nodenames["moretrees:fir_trunk_sideways"] = true - timber_nodenames["moretrees:oak_trunk"] = true - timber_nodenames["moretrees:oak_trunk_sideways"] = true - timber_nodenames["moretrees:palm_trunk"] = true - timber_nodenames["moretrees:palm_trunk_sideways"] = true - timber_nodenames["moretrees:pine_trunk"] = true - timber_nodenames["moretrees:pine_trunk_sideways"] = true - timber_nodenames["moretrees:rubber_tree_trunk_sideways"] = true - timber_nodenames["moretrees:rubber_tree_trunk_sideways_empty"] = true - timber_nodenames["moretrees:sequoia_trunk"] = true - timber_nodenames["moretrees:sequoia_trunk_sideways"] = true - timber_nodenames["moretrees:spruce_trunk"] = true - timber_nodenames["moretrees:spruce_trunk_sideways"] = true - timber_nodenames["moretrees:willow_trunk"] = true - timber_nodenames["moretrees:willow_trunk_sideways"] = true - timber_nodenames["moretrees:jungletree_trunk"] = true - timber_nodenames["moretrees:jungletree_trunk_sideways"] = true - - if chainsaw_leaves then - timber_nodenames["moretrees:apple_tree_leaves"] = true - timber_nodenames["moretrees:oak_leaves"] = true - timber_nodenames["moretrees:fir_leaves"] = true - timber_nodenames["moretrees:fir_leaves_bright"] = true - timber_nodenames["moretrees:sequoia_leaves"] = true - timber_nodenames["moretrees:birch_leaves"] = true - timber_nodenames["moretrees:birch_leaves"] = true - timber_nodenames["moretrees:palm_leaves"] = true - timber_nodenames["moretrees:spruce_leaves"] = true - timber_nodenames["moretrees:spruce_leaves"] = true - timber_nodenames["moretrees:pine_leaves"] = true - timber_nodenames["moretrees:willow_leaves"] = true - timber_nodenames["moretrees:jungletree_leaves_green"] = true - timber_nodenames["moretrees:jungletree_leaves_yellow"] = true - timber_nodenames["moretrees:jungletree_leaves_red"] = true - end + timber_nodenames["moretrees:apple_tree_trunk"] = true + timber_nodenames["moretrees:apple_tree_trunk_sideways"] = true + timber_nodenames["moretrees:beech_trunk"] = true + timber_nodenames["moretrees:beech_trunk_sideways"] = true + timber_nodenames["moretrees:birch_trunk"] = true + timber_nodenames["moretrees:birch_trunk_sideways"] = true + timber_nodenames["moretrees:fir_trunk"] = true + timber_nodenames["moretrees:fir_trunk_sideways"] = true + timber_nodenames["moretrees:oak_trunk"] = true + timber_nodenames["moretrees:oak_trunk_sideways"] = true + timber_nodenames["moretrees:palm_trunk"] = true + timber_nodenames["moretrees:palm_trunk_sideways"] = true + timber_nodenames["moretrees:pine_trunk"] = true + timber_nodenames["moretrees:pine_trunk_sideways"] = true + timber_nodenames["moretrees:rubber_tree_trunk_sideways"] = true + timber_nodenames["moretrees:rubber_tree_trunk_sideways_empty"] = true + timber_nodenames["moretrees:sequoia_trunk"] = true + timber_nodenames["moretrees:sequoia_trunk_sideways"] = true + timber_nodenames["moretrees:spruce_trunk"] = true + timber_nodenames["moretrees:spruce_trunk_sideways"] = true + timber_nodenames["moretrees:willow_trunk"] = true + timber_nodenames["moretrees:willow_trunk_sideways"] = true + timber_nodenames["moretrees:jungletree_trunk"] = true + timber_nodenames["moretrees:jungletree_trunk_sideways"] = true + + if chainsaw_leaves then + timber_nodenames["moretrees:apple_tree_leaves"] = true + timber_nodenames["moretrees:oak_leaves"] = true + timber_nodenames["moretrees:fir_leaves"] = true + timber_nodenames["moretrees:fir_leaves_bright"] = true + timber_nodenames["moretrees:sequoia_leaves"] = true + timber_nodenames["moretrees:birch_leaves"] = true + timber_nodenames["moretrees:birch_leaves"] = true + timber_nodenames["moretrees:palm_leaves"] = true + timber_nodenames["moretrees:spruce_leaves"] = true + timber_nodenames["moretrees:spruce_leaves"] = true + timber_nodenames["moretrees:pine_leaves"] = true + timber_nodenames["moretrees:willow_leaves"] = true + timber_nodenames["moretrees:jungletree_leaves_green"] = true + timber_nodenames["moretrees:jungletree_leaves_yellow"] = true + timber_nodenames["moretrees:jungletree_leaves_red"] = true + end end -- Support growing_trees if it is there if( minetest.get_modpath("growing_trees") ~= nil ) then - timber_nodenames["growing_trees:trunk"] = true - timber_nodenames["growing_trees:medium_trunk"] = true - timber_nodenames["growing_trees:big_trunk"] = true - timber_nodenames["growing_trees:trunk_top"] = true - timber_nodenames["growing_trees:trunk_sprout"] = true - timber_nodenames["growing_trees:branch_sprout"] = true - timber_nodenames["growing_trees:branch"] = true - timber_nodenames["growing_trees:branch_xmzm"] = true - timber_nodenames["growing_trees:branch_xpzm"] = true - timber_nodenames["growing_trees:branch_xmzp"] = true - timber_nodenames["growing_trees:branch_xpzp"] = true - timber_nodenames["growing_trees:branch_zz"] = true - timber_nodenames["growing_trees:branch_xx"] = true - - if chainsaw_leaves == true then - timber_nodenames["growing_trees:leaves"] = true - end + timber_nodenames["growing_trees:trunk"] = true + timber_nodenames["growing_trees:medium_trunk"] = true + timber_nodenames["growing_trees:big_trunk"] = true + timber_nodenames["growing_trees:trunk_top"] = true + timber_nodenames["growing_trees:trunk_sprout"] = true + timber_nodenames["growing_trees:branch_sprout"] = true + timber_nodenames["growing_trees:branch"] = true + timber_nodenames["growing_trees:branch_xmzm"] = true + timber_nodenames["growing_trees:branch_xpzm"] = true + timber_nodenames["growing_trees:branch_xmzp"] = true + timber_nodenames["growing_trees:branch_xpzp"] = true + timber_nodenames["growing_trees:branch_zz"] = true + timber_nodenames["growing_trees:branch_xx"] = true + + if chainsaw_leaves == true then + timber_nodenames["growing_trees:leaves"] = true + end end -- Support growing_cactus if it is there if( minetest.get_modpath("growing_cactus") ~= nil ) then - timber_nodenames["growing_cactus:sprout"] = true - timber_nodenames["growing_cactus:branch_sprout_vertical"] = true - timber_nodenames["growing_cactus:branch_sprout_vertical_fixed"] = true - timber_nodenames["growing_cactus:branch_sprout_xp"] = true - timber_nodenames["growing_cactus:branch_sprout_xm"] = true - timber_nodenames["growing_cactus:branch_sprout_zp"] = true - timber_nodenames["growing_cactus:branch_sprout_zm"] = true - timber_nodenames["growing_cactus:trunk"] = true - timber_nodenames["growing_cactus:branch_trunk"] = true - timber_nodenames["growing_cactus:branch"] = true - timber_nodenames["growing_cactus:branch_xp"] = true - timber_nodenames["growing_cactus:branch_xm"] = true - timber_nodenames["growing_cactus:branch_zp"] = true - timber_nodenames["growing_cactus:branch_zm"] = true - timber_nodenames["growing_cactus:branch_zz"] = true - timber_nodenames["growing_cactus:branch_xx"] = true + timber_nodenames["growing_cactus:sprout"] = true + timber_nodenames["growing_cactus:branch_sprout_vertical"] = true + timber_nodenames["growing_cactus:branch_sprout_vertical_fixed"] = true + timber_nodenames["growing_cactus:branch_sprout_xp"] = true + timber_nodenames["growing_cactus:branch_sprout_xm"] = true + timber_nodenames["growing_cactus:branch_sprout_zp"] = true + timber_nodenames["growing_cactus:branch_sprout_zm"] = true + timber_nodenames["growing_cactus:trunk"] = true + timber_nodenames["growing_cactus:branch_trunk"] = true + timber_nodenames["growing_cactus:branch"] = true + timber_nodenames["growing_cactus:branch_xp"] = true + timber_nodenames["growing_cactus:branch_xm"] = true + timber_nodenames["growing_cactus:branch_zp"] = true + timber_nodenames["growing_cactus:branch_zm"] = true + timber_nodenames["growing_cactus:branch_zz"] = true + timber_nodenames["growing_cactus:branch_xx"] = true end -- Support farming_plus if it is there if( minetest.get_modpath("farming_plus") ~= nil ) then - if chainsaw_leaves == true then - timber_nodenames["farming_plus:cocoa_leaves"] = true - end + if chainsaw_leaves == true then + timber_nodenames["farming_plus:cocoa_leaves"] = true + end end @@ -131,77 +131,106 @@ local produced = nil -- Override the default handling routine to be able to count up the -- items sawed down so that we can drop them i an nice single stack local function chainsaw_handle_node_drops(pos, drops, digger) - -- Add dropped items to list of collected nodes - local _, dropped_item - for _, dropped_item in ipairs(drops) do - if produced[dropped_item] == nil then - produced[dropped_item] = 1 - else - produced[dropped_item] = produced[dropped_item] + 1 - end - end + -- Add dropped items to list of collected nodes + for _, dropped_item in ipairs(drops) do + if produced[dropped_item] == nil then + produced[dropped_item] = 1 + else + produced[dropped_item] = produced[dropped_item] + 1 + end + end end -- This function does all the hard work. Recursively we dig the node at hand -- if it is in the table and then search the surroundings for more stuff to dig. local function recursive_dig(pos, remaining_charge, player) - local node=minetest.env:get_node(pos) - local i=1 - -- Lookup node name in timber table: - if timber_nodenames[node.name] ~= nil then - -- Return if we are out of power - if remaining_charge < chainsaw_charge_per_node then - return 0 - end - local np - -- wood found - cut it. - minetest.env:dig_node(pos) - - remaining_charge=remaining_charge-chainsaw_charge_per_node - -- check surroundings and run recursively if any charge left - np={x=pos.x+1, y=pos.y, z=pos.z} - if timber_nodenames[minetest.env:get_node(np).name] ~= nil then - remaining_charge = recursive_dig(np, remaining_charge) - end - np={x=pos.x+1, y=pos.y, z=pos.z+1} - if timber_nodenames[minetest.env:get_node(np).name] ~= nil then - remaining_charge = recursive_dig(np, remaining_charge) - end - np={x=pos.x+1, y=pos.y, z=pos.z-1} - if timber_nodenames[minetest.env:get_node(np).name] ~= nil then - remaining_charge = recursive_dig(np, remaining_charge) - end - - np={x=pos.x-1, y=pos.y, z=pos.z} - if timber_nodenames[minetest.env:get_node(np).name] ~= nil then - remaining_charge = recursive_dig(np, remaining_charge) - end - np={x=pos.x-1, y=pos.y, z=pos.z+1} - if timber_nodenames[minetest.env:get_node(np).name] ~= nil then - remaining_charge = recursive_dig(np, remaining_charge) - end - np={x=pos.x-1, y=pos.y, z=pos.z-1} - if timber_nodenames[minetest.env:get_node(np).name] ~= nil then - remaining_charge = recursive_dig(np, remaining_charge) - end - - np={x=pos.x, y=pos.y+1, z=pos.z} - if timber_nodenames[minetest.env:get_node(np).name] ~= nil then - remaining_charge = recursive_dig(np, remaining_charge) - end - - np={x=pos.x, y=pos.y, z=pos.z+1} - if timber_nodenames[minetest.env:get_node(np).name] ~= nil then - remaining_charge = recursive_dig(np, remaining_charge) - end - np={x=pos.x, y=pos.y, z=pos.z-1} - if timber_nodenames[minetest.env:get_node(np).name] ~= nil then - remaining_charge = recursive_dig(np, remaining_charge) - end - return remaining_charge - end - -- Nothing sawed down - return remaining_charge + local node=minetest.env:get_node(pos) + local i=1 + -- Lookup node name in timber table: + if timber_nodenames[node.name] ~= nil then + -- Return if we are out of power + if remaining_charge < chainsaw_charge_per_node then + return 0 + end + local np + -- wood found - cut it. + minetest.env:dig_node(pos) + + remaining_charge=remaining_charge-chainsaw_charge_per_node + -- check surroundings and run recursively if any charge left + np={x=pos.x+1, y=pos.y, z=pos.z} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + np={x=pos.x+1, y=pos.y, z=pos.z+1} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + np={x=pos.x+1, y=pos.y, z=pos.z-1} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + + np={x=pos.x-1, y=pos.y, z=pos.z} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + np={x=pos.x-1, y=pos.y, z=pos.z+1} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + np={x=pos.x-1, y=pos.y, z=pos.z-1} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + + np={x=pos.x, y=pos.y+1, z=pos.z} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + + np={x=pos.x, y=pos.y, z=pos.z+1} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + np={x=pos.x, y=pos.y, z=pos.z-1} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + return remaining_charge + end + -- Nothing sawed down + return remaining_charge +end + +-- Function to randomize positions for new node drops +local function get_drop_pos(pos) + local drop_pos = {} + + for i = 0, 8 do + -- Randomize position for a new drop + drop_pos.x = pos.x + math.random(-3, 3) + drop_pos.y = pos.y - 1 + drop_pos.z = pos.z + math.random(-3, 3) + + -- Move the randomized position upwards until + -- the node is air or unloaded. + for y = drop_pos.y, drop_pos.y + 5 do + drop_pos.y = y + local node = minetest.get_node_or_nil(drop_pos) + + if not node then + -- If the node is not loaded yet simply drop + -- the item at the original digging position. + return pos + elseif node.name == "air" then + return drop_pos + end + end + end + + -- Return the original position if this takes too long + return pos end -- Saw down trees entry point @@ -210,45 +239,37 @@ local function chainsaw_dig_it(pos, player,current_charge) minetest.record_protection_violation(pos, player:get_player_name()) return current_charge end - local remaining_charge=current_charge + local remaining_charge=current_charge - -- Save the currently installed dropping mechanism so we can restore it. + -- Save the currently installed dropping mechanism so we can restore it. local original_handle_node_drops = minetest.handle_node_drops - -- A bit of trickery here: use a different node drop callback - -- and restore the original afterwards. - minetest.handle_node_drops = chainsaw_handle_node_drops - - -- clear result and start sawing things down - produced = {} - remaining_charge = recursive_dig(pos, remaining_charge, player) - minetest.sound_play("chainsaw", {pos = pos, gain = 1.0, max_hear_distance = 10,}) - - -- Restore the original noder drop handler - minetest.handle_node_drops = original_handle_node_drops - - -- Now drop items for the player - local number, produced_item, p - for produced_item,number in pairs(produced) do - --print("ADDING ITEM: " .. produced_item .. " " .. number) - -- Drop stacks of 99 or less - p = { - x = pos.x + math.random()*4, - y = pos.y, - z = pos.z + math.random()*4 - } - while number > 99 do - minetest.env:add_item(p, produced_item .. " 99") - p = { - x = pos.x + math.random()*4, - y = pos.y, - z = pos.z + math.random()*4 - } - number = number - 99 - end - minetest.env:add_item(p, produced_item .. " " .. number) - end - return remaining_charge + -- A bit of trickery here: use a different node drop callback + -- and restore the original afterwards. + minetest.handle_node_drops = chainsaw_handle_node_drops + + -- clear result and start sawing things down + produced = {} + remaining_charge = recursive_dig(pos, remaining_charge, player) + minetest.sound_play("chainsaw", {pos = pos, gain = 1.0, max_hear_distance = 10,}) + + -- Restore the original noder drop handler + minetest.handle_node_drops = original_handle_node_drops + + -- Now drop items for the player + local number, produced_item, p + for produced_item,number in pairs(produced) do + --print("ADDING ITEM: " .. produced_item .. " " .. number) + -- Drop stacks of 99 or less + p = get_drop_pos(pos) + while number > 99 do + minetest.env:add_item(p, produced_item .. " 99") + p = get_drop_pos(pos) + number = number - 99 + end + minetest.env:add_item(p, produced_item .. " " .. number) + end + return remaining_charge end @@ -280,11 +301,10 @@ minetest.register_tool("technic:chainsaw", { }) minetest.register_craft({ - output = 'technic:chainsaw', - recipe = { - {'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot', 'technic:battery'}, - {'technic:stainless_steel_ingot', 'technic:motor', 'technic:battery'}, - {'', '', 'default:copper_ingot'}, - } + output = 'technic:chainsaw', + recipe = { + {'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot', 'technic:battery'}, + {'technic:stainless_steel_ingot', 'technic:motor', 'technic:battery'}, + {'', '', 'default:copper_ingot'}, + } }) - -- 2.30.2