288 lines
7.4 KiB
Lua

local load_time_start = os.clock()
treecapitator = {}
--------------------------------------Settings----------------------------------------------
treecapitator.drop_items = false --drop them / get them in the inventory
treecapitator.drop_leaf = false
treecapitator.default_tree = { --replaces not defined stuff (see below)
trees = {"default:tree"},
leaves = {"default:leaves"},
range = 2,
fruits = {},
}
---------------------------------------------------------------------------------------------
--the table where the trees are stored at
treecapitator.trees = {}
--a table of trunks which couldn't be redefined
treecapitator.rest_tree_nodes = {}
--------------------------------------------fcts----------------------------------------------
--definitions of functions for the destruction of nodes
local destroy_node, drop_leaf, remove_leaf
if treecapitator.drop_items then
function drop_leaf(pos, item, inv)
minetest.add_item(pos, item)
end
function destroy_node(pos, node, digger)
local drops = minetest.get_node_drops(node.name)
for _,item in ipairs(drops) do
minetest.add_item(pos, item)
end
minetest.remove_node(pos)
end
else
function drop_leaf(pos, item, inv)
if inv
and inv:room_for_item("main", item) then
inv:add_item("main", item)
else
minetest.add_item(pos, item)
end
end
function destroy_node(pos, node, digger)
minetest.node_dig(pos, node, digger)
end
end
if not treecapitator.drop_leaf then
function remove_leaf(p, leaf, inv)
local leaves_drops = minetest.get_node_drops(leaf)
for _, itemname in ipairs(leaves_drops) do
if itemname ~= leaf then
drop_leaf(p, itemname, inv)
end
end
minetest.remove_node(p) --remove the leaves
end
else
function remove_leaf(p, _, _, node, digger)
destroy_node(p, node, digger)
end
end
table.icontains = table.icontains or function(t, v)
for _,i in ipairs(t) do
if i == v then
return true
end
end
return false
end
--tests if the node is a trunk
local function findtree(node)
if node == 0 then
return true
end
if table.icontains(treecapitator.rest_tree_nodes, node.name) then
return true
end
return false
end
--returns positions for leaves allowed to be dug
local function find_next_trees(pos, range, trees, leaves, fruits)
local tab = {}
local r = 2*range
for i = -r, r do
for j = -r, r do
for h = r,-r,-1 do
local p = {x=pos.x+j, y=pos.y+h, z=pos.z+i}
local leaf = minetest.get_node({x=p.x, y=p.y+1, z=p.z}).name
local leaf_found = table.icontains(leaves, leaf) or table.icontains(fruits, leaf)
if not leaf_found then
leaf = minetest.get_node({x=p.x, y=p.y, z=p.z+1}).name
leaf_found = table.icontains(leaves, leaf) or table.icontains(fruits, leaf)
end
if table.icontains(trees, minetest.get_node(p).name)
and leaf_found then
for z = -range+i,range+i do
for y = -range+h,range+h do
for x = -range+j,range+j do
if math.abs(z) <= range
and math.abs(y) <= range
and math.abs(x) <= range then
tab[z.." "..y.." "..x] = true
end
end
end
end
end
end
end
end
--minetest.chat_send_all(dump(tab)) <— I used these to find my mistake
local tab2,n = {},1
for z = -range,range do
for y = -range,range do
for x = -range,range do
if not tab[z.." "..y.." "..x] then
local p = {x=x, y=y, z=z}
tab2[n] = p
n = n+1
end
end
end
end
return tab2
end
--the function which is used for capitating
local capitating = false --necessary if minetest.node_dig is used
local function capitate_tree(pos, node, digger)
if capitating then
return
end
--minetest.chat_send_all("test0") <— and this
if digger == nil then
return
end
if digger:get_player_control().sneak
or not findtree(node) then
return
end
local t1 = os.clock()
capitating = true
local np = {x=pos.x, y=pos.y+1, z=pos.z}
local nd = minetest.get_node(np)
for _,tr in ipairs(treecapitator.trees) do
local trees = tr.trees
local tree_found = table.icontains(trees, nd.name)
if tree_found then
local tab, n = {}, 1
while tree_found do
tab[n] = {vector.new(np), nd}
n = n+1
np.y = np.y+1
nd = minetest.get_node(np)
tree_found = table.icontains(trees, nd.name)
end
local leaves = tr.leaves
local fruits = tr.fruits
np.y = np.y-1
local leaf_found = table.icontains(leaves, nd.name) or table.icontains(fruits, nd.name)
if not leaf_found then
local leaf = minetest.get_node({x=np.x, y=np.y, z=np.z+1}).name
leaf_found = table.icontains(leaves, leaf) or table.icontains(fruits, leaf)
end
if leaf_found then
for _,i in ipairs(tab) do
destroy_node(i[1], i[2], digger)
end
local range = tr.range
local inv = digger:get_inventory()
local head_ps = find_next_trees(np, range, trees, leaves, fruits) --definition of the leavespositions
--minetest.chat_send_all("test1") <— this too
for _,i in ipairs(head_ps) do
local p = vector.add(np, i)
local node = minetest.get_node(p)
local nodename = node.name
if table.icontains(leaves, nodename) then
remove_leaf(p, leaf, inv, node, digger)
elseif table.icontains(fruits, nodename) then
destroy_node(p, node, digger)
end
end
end
end
end
capitating = false
print(string.format("[treecapitator] tree capitated at ("..pos.x.."|"..pos.y.."|"..pos.z..") after ca. %.2fs", os.clock() - t1))
end
--adds trunks to rest_tree_nodes if they were overwritten by other mods
local tmp_trees = {}
local function test_overwritten(tree)
table.insert(tmp_trees, tree)
end
minetest.after(0, function()
for _,tree in pairs(tmp_trees) do
if not minetest.registered_nodes[tree].after_dig_node then
print("[treecapitator] Error: Overwriting "..tree.." went wrong.")
table.insert(treecapitator.rest_tree_nodes, tree)
end
end
tmp_trees = nil
end)
--tests if minetest.override_item is aviable
local new_version = minetest.override_item and true
if not new_version then
table.copy = table.copy or function(tab)
local tab2 = {}
for n,i in pairs(tab) do
tab2[n] = i
end
return tab2
end
end
--the function to register trees to become capitated
local num = 1
function treecapitator.register_tree(tab)
for name,value in pairs(treecapitator.default_tree) do
tab[name] = tab[name] or value --replaces not defined stuff
end
treecapitator.trees[num] = tab
num = num+1
for _,tree in pairs(tab.trees) do
local data = minetest.registered_nodes[tree]
if not data then
print("[treecapitator] Info: "..tree.." isn't registered yet.")
table.insert(treecapitator.rest_tree_nodes, tree)
else
if data.after_dig_node then
print("[treecapitator] Info: "..tree.." already has an after_dig_node.")
table.insert(treecapitator.rest_tree_nodes, tree)
else
if new_version then
minetest.override_item(tree, {
after_dig_node = function(pos, _, _, digger)
capitate_tree(pos, 0, digger)
end
})
else
data = table.copy(data)
data.after_dig_node = function(pos, _, _, digger)
capitate_tree(pos, 0, digger)
end
minetest.register_node(":"..tree, data)
end
test_overwritten(tree)
end
end
end
end
dofile(minetest.get_modpath("treecapitator").."/trees.lua")
---------------------------------------------------------------------------------------------
--use register_on_dignode if trunks are left
if treecapitator.rest_tree_nodes[1] then
minetest.register_on_dignode(capitate_tree)
end
print(string.format("[treecapitator] loaded after ca. %.2fs", os.clock() - load_time_start))