From 08b09aab94471133a80fb8bc984f4f0689350959 Mon Sep 17 00:00:00 2001
From: Cristiano Magro <cristiano.magro@vola.it>
Date: Sun, 11 Oct 2020 17:16:52 +0200
Subject: [PATCH] mege treetrap e chainsaw

---
 technic/tools/xno_tree_tap.lua |  236 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 234 insertions(+), 2 deletions(-)

diff --git a/technic/tools/xno_tree_tap.lua b/technic/tools/xno_tree_tap.lua
index 7344645..dd81828 100644
--- a/technic/tools/xno_tree_tap.lua
+++ b/technic/tools/xno_tree_tap.lua
@@ -1,27 +1,244 @@
+-- Configuration
+
+local xnotreetrap_max_charge      = 30000 -- Maximum charge of the saw
+-- Gives 2500 nodes on a single charge (about 50 complete normal trees)
+local xnotreetrap_charge_per_node = 12
+-- Cut down tree leaves.  Leaf decay may cause slowness on large trees
+-- if this is disabled.
+local xnotreetrap_leaves = true
+
+-- First value is node name; second is whether the node is considered even if chainsaw_leaves is false.
+local nodes = {
+	-- 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},
+}
+
+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 mesecons_materials = minetest.get_modpath("mesecons_materials")
 
+technic.register_power_tool("technic:xnotreetap", xnotreetap_max_charge)
+
+-- This function checks if the specified node should be sawed
+local function check_if_node_sawed(pos)
+	local node_name = minetest.get_node(pos).name
+	if timber_nodenames[node_name]
+			or (xnotreetap_leaves and minetest.get_item_group(node_name, "leaves") ~= 0)
+			or minetest.get_item_group(node_name, "tree") ~= 0 then
+		return true
+	end
+
+	return false
+end
+
+-- Table for saving what was sawed down
+local produced = {}
+
+-- Save the items sawed down so that we can drop them in a nice single stack
+local function handle_drops(drops)
+	for _, item in ipairs(drops) do
+		local stack = ItemStack(item)
+		local name = stack:get_name()
+		local p = produced[name]
+		if not p then
+			produced[name] = stack
+		else
+			p:set_count(p:get_count() + stack:get_count())
+		end
+	end
+end
+
+--- Iterator over positions to try to saw around a sawed node.
+-- 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()
+		i = i + 1
+		-- Given a (top view) area like so (where 5 is the starting position):
+		-- X -->
+		-- Z 123
+		-- | 456
+		-- V 789
+		-- This will return positions 1, 4, 7, 2, 8 (skip 5), 3, 6, 9,
+		-- and the position above 5.
+		if i == 1 then
+			-- 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
+-- if it is in the table and then search the surroundings for more stuff to dig.
+local function recursive_dig(pos, remaining_charge)
+	if remaining_charge < xnotreetap_charge_per_node then
+		return remaining_charge
+	end
+	local node = minetest.get_node(pos)
+
+	if not check_if_node_sawed(pos) then
+		return remaining_charge
+	end
+
+	-- Wood found - cut it
+	handle_drops(minetest.get_node_drops(node.name, ""))
+	minetest.remove_node(pos)
+	remaining_charge = remaining_charge - xnotreetap_charge_per_node
+
+	-- Check surroundings and run recursively if any charge left
+	for npos in iterSawTries(pos) do
+		if remaining_charge < xnotreetap_charge_per_node then
+			break
+		end
+		if check_if_node_sawed(npos) then
+			remaining_charge = recursive_dig(npos, remaining_charge)
+		else
+			minetest.check_for_falling(npos)
+		end
+	end
+	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
+				-- Add variation to the entity drop position,
+				-- but don't let drops get too close to the edge
+				drop_pos.x = drop_pos.x + (math.random() * 0.8) - 0.5
+				drop_pos.z = drop_pos.z + (math.random() * 0.8) - 0.5
+				return drop_pos
+			end
+		end
+	end
+
+	-- Return the original position if this takes too long
+	return pos
+end
+
+-- Chainsaw entry point
+local function xnotreetap_dig(pos, current_charge)
+	-- Start sawing things down
+	local remaining_charge = recursive_dig(pos, current_charge)
+	minetest.sound_play("chainsaw", {pos = pos, gain = 1.0,
+			max_hear_distance = 10})
+
+	-- Now drop items for the player
+	for name, stack in pairs(produced) do
+		-- Drop stacks of stack max or less
+		local count, max = stack:get_count(), stack:get_stack_max()
+		stack:set_count(max)
+		while count > max do
+			minetest.add_item(get_drop_pos(pos), stack)
+			count = count - max
+		end
+		stack:set_count(count)
+		minetest.add_item(get_drop_pos(pos), stack)
+	end
+
+	-- Clean up
+	produced = {}
+
+	return remaining_charge
+end
+
 minetest.register_tool("technic:xnotreetap", {
 	description = S("Xno Tree Tap"),
 	inventory_image = "technic_tree_tap.png",
+	stack_max = 1,
+	wear_represents = "technic_RE_charge",
+	on_refill = technic.refill_RE_charge,
 	on_use = function(itemstack, user, pointed_thing)
 		if pointed_thing.type ~= "node" then
+			return itemstack
+		end
+
+		//check tool charge
+		local meta = minetest.deserialize(itemstack:get_metadata())
+		if not meta or not meta.charge or
+				meta.charge < xnotreetap_charge_per_node then
 			return
 		end
+
+		//check node protection
 		local pos = pointed_thing.under
 		if minetest.is_protected(pos, user:get_player_name()) then
 			minetest.record_protection_violation(pos, user:get_player_name())
 			return
 		end
+
+
 		local node = minetest.get_node(pos)
 		local node_name = node.name
 		if node_name ~= "moretrees:rubber_tree_trunk" then
 			return
 		end
+
+		//raccolta gomma
 		node.name = "moretrees:rubber_tree_trunk_empty"
 		minetest.swap_node(pos, node)
 		minetest.handle_node_drops(pointed_thing.above, {"technic:raw_latex"}, user)
+
 		if not technic.creative_mode then
 			local item_wear = tonumber(itemstack:get_wear())
 			item_wear = item_wear + 819
@@ -32,6 +249,16 @@
 			itemstack:set_wear(item_wear)
 		end
 		return itemstack
+
+		-- Send current charge to digging function so that the
+		-- chainsaw will stop after digging a number of nodes
+		meta.charge = xnotreetap_dig(pointed_thing.under, meta.charge)
+		if not technic.creative_mode then
+			technic.set_RE_wear(itemstack, meta.charge, xnotreetap_max_charge)
+			itemstack:set_metadata(minetest.serialize(meta))
+		end
+		return itemstack
+
 	end,
 })
 
@@ -39,8 +266,8 @@
 	output = "technic:xnotreetap",
 	recipe = {
 		{"pipeworks:tube_1", "group:wood",    "default:stick"},
-		{"",               "default:stick", "default:stick"}
-		{"",               "default:stick", "default:stick"}
+		{"technic:battery",  "default:stick", "default:stick"}
+		{"technic:battery",  "default:stick", "default:stick"}
 	},
 })
 
@@ -57,3 +284,8 @@
 	end
 })
 
+
+
+
+
+

--
Gitblit v1.8.0