end
end
})
+
+
+--
+-- Checks if specified volume intersects a protected volume
+--
+
+function default.intersects_protection(minp, maxp, player_name, interval)
+ -- 'interval' is the largest allowed interval for the 3D lattice of checks
+
+ -- Compute the optimal float step 'd' for each axis so that all corners and
+ -- borders are checked. 'd' will be smaller or equal to 'interval'.
+ -- Subtracting 1e-4 ensures that the max co-ordinate will be reached by the
+ -- for loop (which might otherwise not be the case due to rounding errors).
+ local d = {}
+ for _, c in pairs({"x", "y", "z"}) do
+ if maxp[c] > minp[c] then
+ d[c] = (maxp[c] - minp[c]) / math.ceil((maxp[c] - minp[c]) / interval) - 1e-4
+ elseif maxp[c] == minp[c] then
+ d[c] = 1 -- Any value larger than 0 to avoid division by zero
+ else -- maxp[c] < minp[c], print error and treat as protection intersected
+ minetest.log("error", "maxp < minp in 'default.intersects_protection()'")
+ return true
+ end
+ end
+
+ for zf = minp.z, maxp.z, d.z do
+ local z = math.floor(zf + 0.5)
+ for yf = minp.y, maxp.y, d.y do
+ local y = math.floor(yf + 0.5)
+ for xf = minp.x, maxp.x, d.x do
+ local x = math.floor(xf + 0.5)
+ if minetest.is_protected({x = x, y = y, z = z}, player_name) then
+ return true
+ end
+ end
+ end
+ end
+
+ return false
+end
sunlight_propagates = true,
walkable = false,
on_timer = default.grow_sapling,
- on_construct = function(pos)
- minetest.get_node_timer(pos):start(math.random(2400,4800))
- end,
selection_box = {
type = "fixed",
fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3}
groups = {snappy = 2, dig_immediate = 3, flammable = 2,
attached_node = 1, sapling = 1},
sounds = default.node_sound_leaves_defaults(),
+
+ on_construct = function(pos)
+ minetest.get_node_timer(pos):start(math.random(2400,4800))
+ end,
+
+ on_place = function(itemstack, placer, pointed_thing)
+ itemstack = default.sapling_on_place(itemstack, placer, pointed_thing,
+ "default:sapling",
+ -- minp, maxp to be checked, relative to sapling pos
+ -- minp_relative.y = 1 because sapling pos has been checked
+ {x = -2, y = 1, z = -2},
+ {x = 2, y = 6, z = 2},
+ -- maximum interval of interior volume check
+ 4)
+
+ return itemstack
+ end,
})
minetest.register_node("default:leaves", {
sunlight_propagates = true,
walkable = false,
on_timer = default.grow_sapling,
- on_construct = function(pos)
- minetest.get_node_timer(pos):start(math.random(2400,4800))
- end,
selection_box = {
type = "fixed",
fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3}
groups = {snappy = 2, dig_immediate = 3, flammable = 2,
attached_node = 1, sapling = 1},
sounds = default.node_sound_leaves_defaults(),
+
+ on_construct = function(pos)
+ minetest.get_node_timer(pos):start(math.random(2400,4800))
+ end,
+
+ on_place = function(itemstack, placer, pointed_thing)
+ itemstack = default.sapling_on_place(itemstack, placer, pointed_thing,
+ "default:junglesapling",
+ -- minp, maxp to be checked, relative to sapling pos
+ -- minp_relative.y = 1 because sapling pos has been checked
+ {x = -2, y = 1, z = -2},
+ {x = 2, y = 15, z = 2},
+ -- maximum interval of interior volume check
+ 4)
+
+ return itemstack
+ end,
})
sunlight_propagates = true,
walkable = false,
on_timer = default.grow_sapling,
- on_construct = function(pos)
- minetest.get_node_timer(pos):start(math.random(2400,4800))
- end,
selection_box = {
type = "fixed",
fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3}
groups = {snappy = 2, dig_immediate = 3, flammable = 2,
attached_node = 1, sapling = 1},
sounds = default.node_sound_leaves_defaults(),
+
+ on_construct = function(pos)
+ minetest.get_node_timer(pos):start(math.random(2400,4800))
+ end,
+
+ on_place = function(itemstack, placer, pointed_thing)
+ itemstack = default.sapling_on_place(itemstack, placer, pointed_thing,
+ "default:pine_sapling",
+ -- minp, maxp to be checked, relative to sapling pos
+ -- minp_relative.y = 1 because sapling pos has been checked
+ {x = -2, y = 1, z = -2},
+ {x = 2, y = 12, z = 2},
+ -- maximum interval of interior volume check
+ 4)
+
+ return itemstack
+ end,
})
sunlight_propagates = true,
walkable = false,
on_timer = default.grow_sapling,
- on_construct = function(pos)
- minetest.get_node_timer(pos):start(math.random(2400,4800))
- end,
selection_box = {
type = "fixed",
fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3}
groups = {snappy = 2, dig_immediate = 3, flammable = 2,
attached_node = 1, sapling = 1},
sounds = default.node_sound_leaves_defaults(),
+
+ on_construct = function(pos)
+ minetest.get_node_timer(pos):start(math.random(2400,4800))
+ end,
+
+ on_place = function(itemstack, placer, pointed_thing)
+ itemstack = default.sapling_on_place(itemstack, placer, pointed_thing,
+ "default:acacia_sapling",
+ -- minp, maxp to be checked, relative to sapling pos
+ -- minp_relative.y = 1 because sapling pos has been checked
+ {x = -4, y = 1, z = -4},
+ {x = 4, y = 6, z = 4},
+ -- maximum interval of interior volume check
+ 4)
+
+ return itemstack
+ end,
})
minetest.register_node("default:aspen_tree", {
sunlight_propagates = true,
walkable = false,
on_timer = default.grow_sapling,
- on_construct = function(pos)
- minetest.get_node_timer(pos):start(math.random(2400,4800))
- end,
selection_box = {
type = "fixed",
fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3}
groups = {snappy = 2, dig_immediate = 3, flammable = 2,
attached_node = 1, sapling = 1},
sounds = default.node_sound_leaves_defaults(),
+
+ on_construct = function(pos)
+ minetest.get_node_timer(pos):start(math.random(2400,4800))
+ end,
+
+ on_place = function(itemstack, placer, pointed_thing)
+ itemstack = default.sapling_on_place(itemstack, placer, pointed_thing,
+ "default:aspen_sapling",
+ -- minp, maxp to be checked, relative to sapling pos
+ -- minp_relative.y = 1 because sapling pos has been checked
+ {x = -2, y = 1, z = -2},
+ {x = 2, y = 12, z = 2},
+ -- maximum interval of interior volume check
+ 4)
+
+ return itemstack
+ end,
})
+
--
-- Ores
--
path, "random", nil, false)
end
+
-- New aspen tree
function default.grow_new_aspen_tree(pos)
minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2},
path, "0", nil, false)
end
+
+
+--
+-- Sapling 'on place' function to check protection of node and resulting tree volume
+--
+
+function default.sapling_on_place(itemstack, placer, pointed_thing,
+ sapling_name, minp_relative, maxp_relative, interval)
+ -- Position of sapling
+ local pos = pointed_thing.under
+ local node = minetest.get_node(pos)
+ local pdef = minetest.registered_nodes[node.name]
+ if not pdef or not pdef.buildable_to then
+ pos = pointed_thing.above
+ node = minetest.get_node(pos)
+ pdef = minetest.registered_nodes[node.name]
+ if not pdef or not pdef.buildable_to then
+ return itemstack
+ end
+ end
+
+ local player_name = placer:get_player_name()
+ -- Check sapling position for protection
+ if minetest.is_protected(pos, player_name) then
+ minetest.record_protection_violation(pos, player_name)
+ return itemstack
+ end
+ -- Check tree volume for protection
+ if not default.intersects_protection(
+ vector.add(pos, minp_relative),
+ vector.add(pos, maxp_relative),
+ player_name,
+ interval) then
+ minetest.set_node(pos, {name = sapling_name})
+ if not minetest.setting_getbool("creative_mode") then
+ itemstack:take_item()
+ end
+ else
+ minetest.record_protection_violation(pos, player_name)
+ -- Print extra information to explain
+ minetest.chat_send_player(player_name, "Tree will intersect protection")
+ end
+
+ return itemstack
+end