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