Chainsaw: Partial rewrite, various improvements
Introduces protection checks for the entire tree More efficient node digging (VoxelManip) Improved drop handling using detached inventories for correct stack sizes
This commit is contained in:
parent
4775d98fb7
commit
69aaf8a9c6
|
@ -1,338 +1,206 @@
|
||||||
-- Configuration
|
-- Configuration
|
||||||
|
|
||||||
local chainsaw_max_charge = 30000 -- Maximum charge of the saw
|
local chainsaw_max_charge = 30000 -- Maximum charge of the saw
|
||||||
-- Gives 2500 nodes on a single charge (about 50 complete normal trees)
|
|
||||||
local chainsaw_charge_per_node = 12
|
|
||||||
-- Cut down tree leaves. Leaf decay may cause slowness on large trees
|
-- Cut down tree leaves. Leaf decay may cause slowness on large trees
|
||||||
-- if this is disabled.
|
-- if this is disabled.
|
||||||
local chainsaw_leaves = true
|
local chainsaw_leaves = true
|
||||||
|
|
||||||
-- First value is node name; second is whether the node is considered even if chainsaw_leaves is false.
|
-- Maximal dimensions of the tree to cut
|
||||||
local nodes = {
|
local tree_max_radius = 10
|
||||||
-- The default trees
|
local tree_max_height = 100
|
||||||
{"default:acacia_tree", true},
|
|
||||||
{"default:aspen_tree", true},
|
|
||||||
{"default:jungletree", true},
|
|
||||||
{"default:papyrus", true},
|
|
||||||
{"default:cactus", true},
|
|
||||||
{"default:tree", true},
|
|
||||||
{"default:apple", true},
|
|
||||||
{"default:pine_tree", true},
|
|
||||||
{"default:acacia_leaves", false},
|
|
||||||
{"default:aspen_leaves", false},
|
|
||||||
{"default:leaves", false},
|
|
||||||
{"default:jungleleaves", false},
|
|
||||||
{"default:pine_needles", false},
|
|
||||||
|
|
||||||
-- The default bushes
|
|
||||||
{"default:acacia_bush_stem", true},
|
|
||||||
{"default:bush_stem", true},
|
|
||||||
{"default:pine_bush_stem", true},
|
|
||||||
{"default:acacia_bush_leaves", false},
|
|
||||||
{"default:blueberry_bush_leaves", false},
|
|
||||||
{"default:blueberry_bush_leaves_with_berries", false},
|
|
||||||
{"default:bush_leaves", false},
|
|
||||||
{"default:pine_bush_needles", false},
|
|
||||||
|
|
||||||
-- Rubber trees from moretrees or technic_worldgen if moretrees isn't installed
|
|
||||||
{"moretrees:rubber_tree_trunk_empty", true},
|
|
||||||
{"moretrees:rubber_tree_trunk", true},
|
|
||||||
{"moretrees:rubber_tree_leaves", false},
|
|
||||||
|
|
||||||
-- Support moretrees (trunk)
|
|
||||||
{"moretrees:acacia_trunk", true},
|
|
||||||
{"moretrees:apple_tree_trunk", true},
|
|
||||||
{"moretrees:beech_trunk", true},
|
|
||||||
{"moretrees:birch_trunk", true},
|
|
||||||
{"moretrees:cedar_trunk", true},
|
|
||||||
{"moretrees:date_palm_ffruit_trunk", true},
|
|
||||||
{"moretrees:date_palm_fruit_trunk", true},
|
|
||||||
{"moretrees:date_palm_mfruit_trunk", true},
|
|
||||||
{"moretrees:date_palm_trunk", true},
|
|
||||||
{"moretrees:fir_trunk", true},
|
|
||||||
{"moretrees:jungletree_trunk", true},
|
|
||||||
{"moretrees:oak_trunk", true},
|
|
||||||
{"moretrees:palm_trunk", true},
|
|
||||||
{"moretrees:palm_fruit_trunk", true},
|
|
||||||
{"moretrees:palm_fruit_trunk_gen", true},
|
|
||||||
{"moretrees:pine_trunk", true},
|
|
||||||
{"moretrees:poplar_trunk", true},
|
|
||||||
{"moretrees:sequoia_trunk", true},
|
|
||||||
{"moretrees:spruce_trunk", true},
|
|
||||||
{"moretrees:willow_trunk", true},
|
|
||||||
-- Support moretrees (leaves)
|
|
||||||
{"moretrees:acacia_leaves", false},
|
|
||||||
{"moretrees:apple_tree_leaves", false},
|
|
||||||
{"moretrees:beech_leaves", false},
|
|
||||||
{"moretrees:birch_leaves", false},
|
|
||||||
{"moretrees:cedar_leaves", false},
|
|
||||||
{"moretrees:date_palm_leaves", false},
|
|
||||||
{"moretrees:fir_leaves", false},
|
|
||||||
{"moretrees:fir_leaves_bright", false},
|
|
||||||
{"moretrees:jungletree_leaves_green", false},
|
|
||||||
{"moretrees:jungletree_leaves_yellow", false},
|
|
||||||
{"moretrees:jungletree_leaves_red", false},
|
|
||||||
{"moretrees:oak_leaves", false},
|
|
||||||
{"moretrees:palm_leaves", false},
|
|
||||||
{"moretrees:poplar_leaves", false},
|
|
||||||
{"moretrees:pine_leaves", false},
|
|
||||||
{"moretrees:sequoia_leaves", false},
|
|
||||||
{"moretrees:spruce_leaves", false},
|
|
||||||
{"moretrees:willow_leaves", false},
|
|
||||||
-- Support moretrees (fruit)
|
|
||||||
{"moretrees:acorn", false},
|
|
||||||
{"moretrees:apple_blossoms", false},
|
|
||||||
{"moretrees:cedar_cone", false},
|
|
||||||
{"moretrees:coconut", false},
|
|
||||||
{"moretrees:coconut_0", false},
|
|
||||||
{"moretrees:coconut_1", false},
|
|
||||||
{"moretrees:coconut_2", false},
|
|
||||||
{"moretrees:coconut_3", false},
|
|
||||||
{"moretrees:dates_f0", false},
|
|
||||||
{"moretrees:dates_f1", false},
|
|
||||||
{"moretrees:dates_f2", false},
|
|
||||||
{"moretrees:dates_f3", false},
|
|
||||||
{"moretrees:dates_f4", false},
|
|
||||||
{"moretrees:dates_fn", false},
|
|
||||||
{"moretrees:dates_m0", false},
|
|
||||||
{"moretrees:dates_n", false},
|
|
||||||
{"moretrees:fir_cone", false},
|
|
||||||
{"moretrees:pine_cone", false},
|
|
||||||
{"moretrees:spruce_cone", false},
|
|
||||||
|
|
||||||
-- Support growing_trees
|
|
||||||
{"growing_trees:trunk", true},
|
|
||||||
{"growing_trees:medium_trunk", true},
|
|
||||||
{"growing_trees:big_trunk", true},
|
|
||||||
{"growing_trees:trunk_top", true},
|
|
||||||
{"growing_trees:trunk_sprout", true},
|
|
||||||
{"growing_trees:branch_sprout", true},
|
|
||||||
{"growing_trees:branch", true},
|
|
||||||
{"growing_trees:branch_xmzm", true},
|
|
||||||
{"growing_trees:branch_xpzm", true},
|
|
||||||
{"growing_trees:branch_xmzp", true},
|
|
||||||
{"growing_trees:branch_xpzp", true},
|
|
||||||
{"growing_trees:branch_zz", true},
|
|
||||||
{"growing_trees:branch_xx", true},
|
|
||||||
{"growing_trees:leaves", false},
|
|
||||||
|
|
||||||
-- Support cool_trees
|
|
||||||
{"bamboo:trunk", true},
|
|
||||||
{"bamboo:leaves", false},
|
|
||||||
{"birch:trunk", true},
|
|
||||||
{"birch:leaves", false},
|
|
||||||
{"cherrytree:trunk", true},
|
|
||||||
{"cherrytree:blossom_leaves", false},
|
|
||||||
{"cherrytree:leaves", false},
|
|
||||||
{"chestnuttree:trunk", true},
|
|
||||||
{"chestnuttree:leaves", false},
|
|
||||||
{"clementinetree:trunk", true},
|
|
||||||
{"clementinetree:leaves", false},
|
|
||||||
{"ebony:trunk", true},
|
|
||||||
{"ebony:creeper", false},
|
|
||||||
{"ebony:creeper_leaves", false},
|
|
||||||
{"ebony:leaves", false},
|
|
||||||
{"jacaranda:trunk", true},
|
|
||||||
{"jacaranda:blossom_leaves", false},
|
|
||||||
{"larch:trunk", true},
|
|
||||||
{"larch:leaves", false},
|
|
||||||
{"lemontree:trunk", true},
|
|
||||||
{"lemontree:leaves", false},
|
|
||||||
{"mahogany:trunk", true},
|
|
||||||
{"mahogany:leaves", false},
|
|
||||||
{"palm:trunk", true},
|
|
||||||
{"palm:leaves", false},
|
|
||||||
|
|
||||||
-- Support growing_cactus
|
|
||||||
{"growing_cactus:sprout", true},
|
|
||||||
{"growing_cactus:branch_sprout_vertical", true},
|
|
||||||
{"growing_cactus:branch_sprout_vertical_fixed", true},
|
|
||||||
{"growing_cactus:branch_sprout_xp", true},
|
|
||||||
{"growing_cactus:branch_sprout_xm", true},
|
|
||||||
{"growing_cactus:branch_sprout_zp", true},
|
|
||||||
{"growing_cactus:branch_sprout_zm", true},
|
|
||||||
{"growing_cactus:trunk", true},
|
|
||||||
{"growing_cactus:branch_trunk", true},
|
|
||||||
{"growing_cactus:branch", true},
|
|
||||||
{"growing_cactus:branch_xp", true},
|
|
||||||
{"growing_cactus:branch_xm", true},
|
|
||||||
{"growing_cactus:branch_zp", true},
|
|
||||||
{"growing_cactus:branch_zm", true},
|
|
||||||
{"growing_cactus:branch_zz", true},
|
|
||||||
{"growing_cactus:branch_xx", true},
|
|
||||||
|
|
||||||
-- Support farming_plus
|
|
||||||
{"farming_plus:banana_leaves", false},
|
|
||||||
{"farming_plus:banana", false},
|
|
||||||
{"farming_plus:cocoa_leaves", false},
|
|
||||||
{"farming_plus:cocoa", false},
|
|
||||||
|
|
||||||
-- Support nature
|
|
||||||
{"nature:blossom", false},
|
|
||||||
|
|
||||||
-- Support snow
|
|
||||||
{"snow:needles", false},
|
|
||||||
{"snow:needles_decorated", false},
|
|
||||||
{"snow:star", false},
|
|
||||||
|
|
||||||
-- Support vines (also generated by moretrees if available)
|
|
||||||
{"vines:vines", false},
|
|
||||||
|
|
||||||
{"trunks:moss", false},
|
|
||||||
{"trunks:moss_fungus", false},
|
|
||||||
{"trunks:treeroot", false},
|
|
||||||
|
|
||||||
-- Support ethereal
|
|
||||||
{"ethereal:bamboo", true},
|
|
||||||
{"ethereal:bamboo_leaves", false},
|
|
||||||
{"ethereal:banana_trunk", true},
|
|
||||||
{"ethereal:bananaleaves", false},
|
|
||||||
{"ethereal:banana", false},
|
|
||||||
{"ethereal:birch_trunk", true},
|
|
||||||
{"ethereal:birch_leaves", false},
|
|
||||||
{"ethereal:frost_tree", true},
|
|
||||||
{"ethereal:frost_leaves", false},
|
|
||||||
{"ethereal:mushroom_trunk", true},
|
|
||||||
{"ethereal:mushroom", false},
|
|
||||||
{"ethereal:mushroom_pore", true},
|
|
||||||
{"ethereal:orangeleaves", false},
|
|
||||||
{"ethereal:orange", false},
|
|
||||||
{"ethereal:palm_trunk", true},
|
|
||||||
{"ethereal:palmleaves", false},
|
|
||||||
{"ethereal:coconut", false},
|
|
||||||
{"ethereal:redwood_trunk", true},
|
|
||||||
{"ethereal:redwood_leaves", false},
|
|
||||||
{"ethereal:sakura_trunk", true},
|
|
||||||
{"ethereal:sakura_leaves", false},
|
|
||||||
{"ethereal:sakura_leaves2", false},
|
|
||||||
{"ethereal:scorched_tree", true},
|
|
||||||
{"ethereal:willow_trunk", true},
|
|
||||||
{"ethereal:willow_twig", false},
|
|
||||||
{"ethereal:yellow_trunk", true},
|
|
||||||
{"ethereal:yellowleaves", false},
|
|
||||||
{"ethereal:golden_apple", false},
|
|
||||||
}
|
|
||||||
|
|
||||||
local timber_nodenames = {}
|
|
||||||
for _, node in pairs(nodes) do
|
|
||||||
if chainsaw_leaves or node[2] then
|
|
||||||
timber_nodenames[node[1]] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local S = technic.getter
|
local S = technic.getter
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Format: [node_name] = dig_cost
|
||||||
|
|
||||||
|
This table is filled automatically afterwards to support mods such as:
|
||||||
|
|
||||||
|
cool_trees
|
||||||
|
ethereal
|
||||||
|
moretrees
|
||||||
|
]]
|
||||||
|
local tree_nodes = {
|
||||||
|
-- For the sake of maintenance, keep this sorted alphabetically!
|
||||||
|
{"default:acacia_bush_stem", true},
|
||||||
|
{"default:bush_stem", true},
|
||||||
|
{"default:pine_bush_stem", true},
|
||||||
|
|
||||||
|
["default:cactus"] = -1,
|
||||||
|
["default:papyrus"] = -1,
|
||||||
|
|
||||||
|
["ethereal:bamboo"] = -1,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Function to decide whether or not to cut a certain node (and at which energy cost)
|
||||||
|
local function populate_costs(name, def)
|
||||||
|
repeat
|
||||||
|
if tree_nodes[name] == -1 then
|
||||||
|
tree_nodes[name] = nil
|
||||||
|
break -- Manually added, but need updating
|
||||||
|
end
|
||||||
|
if (def.groups.tree or 0) > 0 then
|
||||||
|
break -- Tree node
|
||||||
|
end
|
||||||
|
if (def.groups.leaves or 0) > 0 and chainsaw_leaves then
|
||||||
|
break -- Leaves
|
||||||
|
end
|
||||||
|
if (def.groups.leafdecay_drop or 0) > 0 then
|
||||||
|
break -- Food
|
||||||
|
end
|
||||||
|
return -- Abort function: do not dig this node
|
||||||
|
|
||||||
|
-- luacheck: push ignore 511
|
||||||
|
until 1
|
||||||
|
-- luacheck: pop
|
||||||
|
|
||||||
|
-- Function did not return! --> add content ID to the digging table
|
||||||
|
local content_id = minetest.get_content_id(name)
|
||||||
|
-- Get 12 in average
|
||||||
|
tree_nodes[content_id] = math.min(4,
|
||||||
|
(def.groups.choppy or 0) * 5 -- trunks
|
||||||
|
+ (def.groups.snappy or 0) * 2 -- leaves
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_on_mods_loaded(function()
|
||||||
|
local ndefs = minetest.registered_nodes
|
||||||
|
-- Populate hardcoded nodes
|
||||||
|
for name in pairs(tree_nodes) do
|
||||||
|
local ndef = ndefs[name]
|
||||||
|
if ndef and ndef.groups then
|
||||||
|
populate_costs(name, ndef)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find all trees and leaves
|
||||||
|
for name, def in pairs(ndefs) do
|
||||||
|
if def.groups then
|
||||||
|
populate_costs(name, def)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
technic.register_power_tool("technic:chainsaw", chainsaw_max_charge)
|
technic.register_power_tool("technic:chainsaw", chainsaw_max_charge)
|
||||||
|
|
||||||
-- This function checks if the specified node should be sawed
|
local pos9dir = {
|
||||||
local function check_if_node_sawed(pos)
|
{ 1, 0, 0},
|
||||||
local node_name = minetest.get_node(pos).name
|
{-1, 0, 0},
|
||||||
if timber_nodenames[node_name]
|
{ 0, 0, 1},
|
||||||
or (chainsaw_leaves and minetest.get_item_group(node_name, "leaves") ~= 0)
|
{ 0, 0, -1},
|
||||||
or minetest.get_item_group(node_name, "tree") ~= 0 then
|
{ 1, 0, 1},
|
||||||
return true
|
{-1, 0, -1},
|
||||||
|
{ 1, 0, -1},
|
||||||
|
{-1, 0, 1},
|
||||||
|
{ 0, 1, 0}, -- up
|
||||||
|
}
|
||||||
|
|
||||||
|
local cutter = {
|
||||||
|
-- See function cut_tree()
|
||||||
|
}
|
||||||
|
|
||||||
|
local c_air = minetest.get_content_id("air")
|
||||||
|
local function dig_recursive(x, y, z)
|
||||||
|
local i = cutter.area:index(x, y, z)
|
||||||
|
if cutter.seen[i] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
cutter.seen[i] = 1 -- Mark as visited
|
||||||
|
|
||||||
|
if cutter.param2[i] ~= 0 then
|
||||||
|
-- Do not dig manually placed nodes
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
local c_id = cutter.data[i]
|
||||||
end
|
local cost = tree_nodes[c_id]
|
||||||
|
if not cost or cost > cutter.charge then
|
||||||
|
return -- Cannot dig this node
|
||||||
|
end
|
||||||
|
|
||||||
-- Table for saving what was sawed down
|
-- Count dug nodes
|
||||||
local produced = {}
|
cutter.drops[c_id] = (cutter.drops[c_id] or 0) + 1
|
||||||
|
cutter.seen[i] = 2 -- Mark as dug (for callbacks)
|
||||||
|
cutter.data[i] = c_air
|
||||||
|
cutter.charge = cutter.charge - cost
|
||||||
|
|
||||||
-- Save the items sawed down so that we can drop them in a nice single stack
|
-- Expand maximal bounds for area protection check
|
||||||
local function handle_drops(drops)
|
if x < cutter.minp.x then cutter.minp.x = x end
|
||||||
for _, item in ipairs(drops) do
|
if y < cutter.minp.y then cutter.minp.y = y end
|
||||||
local stack = ItemStack(item)
|
if z < cutter.minp.z then cutter.minp.z = z end
|
||||||
local name = stack:get_name()
|
if x > cutter.maxp.x then cutter.maxp.x = x end
|
||||||
local p = produced[name]
|
if y > cutter.maxp.y then cutter.maxp.y = y end
|
||||||
if not p then
|
if z > cutter.maxp.z then cutter.maxp.z = z end
|
||||||
produced[name] = stack
|
|
||||||
else
|
-- Traverse neighbors
|
||||||
p:set_count(p:get_count() + stack:get_count())
|
local xn, yn, zn
|
||||||
|
for _, offset in ipairs(pos9dir) do
|
||||||
|
xn, yn, zn = x + offset[1], y + offset[2], z + offset[3]
|
||||||
|
if cutter.area:contains(xn, yn, zn) then
|
||||||
|
dig_recursive(xn, yn, zn)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Iterator over positions to try to saw around a sawed node.
|
local handle_drops
|
||||||
-- This returns positions in a 3x1x3 area around the position, plus the
|
|
||||||
-- position above it. This does not return the bottom position to prevent
|
|
||||||
-- the chainsaw from cutting down nodes below the cutting position.
|
|
||||||
-- @param pos Sawing position.
|
|
||||||
local function iterSawTries(pos)
|
|
||||||
-- Copy position to prevent mangling it
|
|
||||||
local pos = vector.new(pos)
|
|
||||||
local i = 0
|
|
||||||
|
|
||||||
return function()
|
local function chainsaw_dig(player, pos, remaining_charge)
|
||||||
i = i + 1
|
local minp = {
|
||||||
-- Given a (top view) area like so (where 5 is the starting position):
|
x = pos.x - (tree_max_radius + 1),
|
||||||
-- X -->
|
y = pos.y,
|
||||||
-- Z 123
|
z = pos.z - (tree_max_radius + 1)
|
||||||
-- | 456
|
}
|
||||||
-- V 789
|
local maxp = {
|
||||||
-- This will return positions 1, 4, 7, 2, 8 (skip 5), 3, 6, 9,
|
x = pos.x + (tree_max_radius + 1),
|
||||||
-- and the position above 5.
|
y = pos.y + tree_max_height,
|
||||||
if i == 1 then
|
z = pos.z + (tree_max_radius + 1)
|
||||||
-- Move to starting position
|
}
|
||||||
pos.x = pos.x - 1
|
|
||||||
pos.z = pos.z - 1
|
|
||||||
elseif i == 4 or i == 7 then
|
|
||||||
-- Move to next X and back to start of Z when we reach
|
|
||||||
-- the end of a Z line.
|
|
||||||
pos.x = pos.x + 1
|
|
||||||
pos.z = pos.z - 2
|
|
||||||
elseif i == 5 then
|
|
||||||
-- Skip the middle position (we've already run on it)
|
|
||||||
-- and double-increment the counter.
|
|
||||||
pos.z = pos.z + 2
|
|
||||||
i = i + 1
|
|
||||||
elseif i <= 9 then
|
|
||||||
-- Go to next Z.
|
|
||||||
pos.z = pos.z + 1
|
|
||||||
elseif i == 10 then
|
|
||||||
-- Move back to center and up.
|
|
||||||
-- The Y+ position must be last so that we don't dig
|
|
||||||
-- straight upward and not come down (since the Y-
|
|
||||||
-- position isn't checked).
|
|
||||||
pos.x = pos.x - 1
|
|
||||||
pos.z = pos.z - 1
|
|
||||||
pos.y = pos.y + 1
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return pos
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- This function does all the hard work. Recursively we dig the node at hand
|
local vm = minetest.get_voxel_manip()
|
||||||
-- if it is in the table and then search the surroundings for more stuff to dig.
|
local emin, emax = vm:read_from_map(minp, maxp)
|
||||||
local function recursive_dig(pos, remaining_charge)
|
|
||||||
if remaining_charge < chainsaw_charge_per_node then
|
|
||||||
return remaining_charge
|
|
||||||
end
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
|
|
||||||
if not check_if_node_sawed(pos) then
|
cutter = {
|
||||||
return remaining_charge
|
area = VoxelArea:new{MinEdge=emin, MaxEdge=emax},
|
||||||
|
data = vm:get_data(),
|
||||||
|
param2 = vm:get_param2_data(),
|
||||||
|
seen = {},
|
||||||
|
drops = {}, -- [content_id] = count
|
||||||
|
minp = vector.copy(pos),
|
||||||
|
maxp = vector.copy(pos),
|
||||||
|
charge = remaining_charge
|
||||||
|
}
|
||||||
|
|
||||||
|
dig_recursive(pos.x, pos.y, pos.z)
|
||||||
|
|
||||||
|
-- Check protection
|
||||||
|
local player_name = player:get_player_name()
|
||||||
|
if minetest.is_area_protected(cutter.minp, cutter.maxp, player_name, 6) then
|
||||||
|
minetest.chat_send_player(player_name, "The chainsaw cannot cut this tree. The cuboid " ..
|
||||||
|
minetest.pos_to_string(cutter.minp) .. ", " .. minetest.pos_to_string(cutter.maxp) ..
|
||||||
|
" contains protected nodes.")
|
||||||
|
minetest.record_protection_violation(pos, player_name)
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Wood found - cut it
|
minetest.sound_play("chainsaw", {
|
||||||
handle_drops(minetest.get_node_drops(node.name, ""))
|
pos = pos,
|
||||||
minetest.remove_node(pos)
|
gain = 1.0,
|
||||||
remaining_charge = remaining_charge - chainsaw_charge_per_node
|
max_hear_distance = 20
|
||||||
|
})
|
||||||
|
|
||||||
-- Check surroundings and run recursively if any charge left
|
handle_drops(pos)
|
||||||
for npos in iterSawTries(pos) do
|
|
||||||
if remaining_charge < chainsaw_charge_per_node then
|
vm:set_data(cutter.data)
|
||||||
break
|
vm:write_to_map(true)
|
||||||
end
|
vm:update_map()
|
||||||
if check_if_node_sawed(npos) then
|
|
||||||
remaining_charge = recursive_dig(npos, remaining_charge)
|
-- Update falling nodes
|
||||||
else
|
for i, status in pairs(cutter.seen) do
|
||||||
minetest.check_for_falling(npos)
|
if status == 2 then -- actually dug
|
||||||
|
minetest.check_for_falling(cutter.area:position(i))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return remaining_charge
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Function to randomize positions for new node drops
|
-- Function to randomize positions for new node drops
|
||||||
|
@ -369,30 +237,40 @@ local function get_drop_pos(pos)
|
||||||
return pos
|
return pos
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Chainsaw entry point
|
local drop_inv = minetest.create_detached_inventory("technic:chainsaw_drops", {}, ":technic")
|
||||||
local function chainsaw_dig(pos, current_charge)
|
handle_drops = function(pos)
|
||||||
-- Start sawing things down
|
local n_slots = 100
|
||||||
local remaining_charge = recursive_dig(pos, current_charge)
|
drop_inv:set_size("main", n_slots)
|
||||||
minetest.sound_play("chainsaw", {pos = pos, gain = 1.0,
|
drop_inv:set_list("main", {})
|
||||||
max_hear_distance = 10})
|
|
||||||
|
|
||||||
-- Now drop items for the player
|
-- Put all dropped items into the detached inventory
|
||||||
for name, stack in pairs(produced) do
|
for c_id, count in pairs(cutter.drops) do
|
||||||
-- Drop stacks of stack max or less
|
local name = minetest.get_name_from_content_id(c_id)
|
||||||
local count, max = stack:get_count(), stack:get_stack_max()
|
|
||||||
stack:set_count(max)
|
-- Add drops in bulk -> keep some randomness
|
||||||
while count > max do
|
while count > 0 do
|
||||||
minetest.add_item(get_drop_pos(pos), stack)
|
local drops = minetest.get_node_drops(name, "")
|
||||||
count = count - max
|
-- higher numbers are faster but return uneven sapling counts
|
||||||
|
local decrement = math.min(5, count)
|
||||||
|
for _, stack in ipairs(drops) do
|
||||||
|
for i = 1, decrement do
|
||||||
|
drop_inv:add_item("main", stack)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
count = count - decrement
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Drop in random places
|
||||||
|
for i = 1, n_slots do
|
||||||
|
local stack = drop_inv:get_stack("main", i)
|
||||||
|
if stack:is_empty() then
|
||||||
|
break
|
||||||
end
|
end
|
||||||
stack:set_count(count)
|
|
||||||
minetest.add_item(get_drop_pos(pos), stack)
|
minetest.add_item(get_drop_pos(pos), stack)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Clean up
|
drop_inv:set_size("main", 0) -- free RAM
|
||||||
produced = {}
|
|
||||||
|
|
||||||
return remaining_charge
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -408,8 +286,7 @@ minetest.register_tool("technic:chainsaw", {
|
||||||
end
|
end
|
||||||
|
|
||||||
local meta = minetest.deserialize(itemstack:get_metadata())
|
local meta = minetest.deserialize(itemstack:get_metadata())
|
||||||
if not meta or not meta.charge or
|
if not meta or not meta.charge then
|
||||||
meta.charge < chainsaw_charge_per_node then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -421,7 +298,11 @@ minetest.register_tool("technic:chainsaw", {
|
||||||
|
|
||||||
-- Send current charge to digging function so that the
|
-- Send current charge to digging function so that the
|
||||||
-- chainsaw will stop after digging a number of nodes
|
-- chainsaw will stop after digging a number of nodes
|
||||||
meta.charge = chainsaw_dig(pointed_thing.under, meta.charge)
|
chainsaw_dig(user, pointed_thing.under, meta.charge)
|
||||||
|
meta.charge = cutter.charge
|
||||||
|
|
||||||
|
cutter = {} -- Free RAM
|
||||||
|
|
||||||
if not technic.creative_mode then
|
if not technic.creative_mode then
|
||||||
technic.set_RE_wear(itemstack, meta.charge, chainsaw_max_charge)
|
technic.set_RE_wear(itemstack, meta.charge, chainsaw_max_charge)
|
||||||
itemstack:set_metadata(minetest.serialize(meta))
|
itemstack:set_metadata(minetest.serialize(meta))
|
||||||
|
|
Loading…
Reference in New Issue