mirror of
https://git.minetest.land/MineClone2/MineClone2.git
synced 2024-11-24 11:53:46 +01:00
c34aecfcab
This modifies the behavior of kelp and bamboo so that neither breaks when an unloaded node is encountered. Reviewed-on: https://git.minetest.land/VoxeLibre/VoxeLibre/pulls/4551 Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land> Co-authored-by: teknomunk <teknomunk@protonmail.com> Co-committed-by: teknomunk <teknomunk@protonmail.com>
296 lines
8.9 KiB
Lua
296 lines
8.9 KiB
Lua
---
|
|
--- Generated by EmmyLua(https://github.com/EmmyLua)
|
|
--- Created by michieal.
|
|
--- DateTime: 12/29/22 12:34 PM -- Restructure Date
|
|
--- Copyright (C) 2022 - 2023, Michieal. See License.txt
|
|
|
|
local DEBUG = false
|
|
|
|
local rand = math.random
|
|
math.randomseed((os.time() + 31) * 31415) -- try to make a valid seed
|
|
local BAMBOO_MAX_HEIGHT = 16 -- base height check.
|
|
|
|
local BAMBOO_SOIL_DIST = BAMBOO_MAX_HEIGHT * -1
|
|
local BAM_MAX_HEIGHT_STPCHK = BAMBOO_MAX_HEIGHT - 5
|
|
local BAM_MAX_HEIGHT_TOP = BAMBOO_MAX_HEIGHT - 1
|
|
local GROW_DOUBLE_CHANCE = 32
|
|
|
|
--Bamboo can be planted on moss blocks, grass blocks, dirt, coarse dirt, rooted dirt, gravel, mycelium, podzol, sand, red sand, or mud
|
|
mcl_bamboo.bamboo_dirt_nodes = {
|
|
"mcl_core:redsand",
|
|
"mcl_core:sand",
|
|
"mcl_core:dirt",
|
|
"mcl_core:coarse_dirt",
|
|
"mcl_core:dirt_with_grass",
|
|
"mcl_core:podzol",
|
|
"mcl_core:mycelium",
|
|
"mcl_lush_caves:rooted_dirt",
|
|
"mcl_lush_caves:moss",
|
|
"mcl_mud:mud",
|
|
}
|
|
|
|
function mcl_bamboo.is_dirt(node_name)
|
|
local index = table.indexof(mcl_bamboo.bamboo_dirt_nodes, node_name)
|
|
if index == -1 then
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
|
|
mcl_bamboo.bamboo_index = {
|
|
"mcl_bamboo:bamboo",
|
|
"mcl_bamboo:bamboo_1",
|
|
"mcl_bamboo:bamboo_2",
|
|
"mcl_bamboo:bamboo_3",
|
|
}
|
|
|
|
function mcl_bamboo.is_bamboo(node_name)
|
|
local index = table.indexof(mcl_bamboo.bamboo_index, node_name)
|
|
if index == -1 then
|
|
return false
|
|
else
|
|
return index
|
|
end
|
|
end
|
|
|
|
--- pos: node position; placer: ObjectRef that is placing the item
|
|
--- returns: true if protected, otherwise false.
|
|
function mcl_bamboo.is_protected(pos, placer)
|
|
local name = placer:get_player_name()
|
|
if minetest.is_protected(pos, name) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
local BAMBOO_ENDCAP_NAME = "mcl_bamboo:bamboo_endcap"
|
|
|
|
-- check if supporting block is broken. pistons now break the bamboo plant.
|
|
function mcl_bamboo.break_orphaned(pos)
|
|
mcl_bamboo.mcl_log("Break_Orphaned called.")
|
|
local node_below = minetest.get_node(vector.offset(pos, 0, -1, 0))
|
|
local node_name = node_below.name
|
|
|
|
-- short circuit checks.
|
|
if node_name == "ignore" or mcl_bamboo.is_dirt(node_name) or mcl_bamboo.is_bamboo(node_name) or mcl_bamboo.is_bamboo(minetest.get_node(pos).name) == false then
|
|
return
|
|
end
|
|
|
|
-- dig the node.
|
|
minetest.remove_node(pos) -- if that fails, remove the node
|
|
local istack = ItemStack("mcl_bamboo:bamboo")
|
|
local sound_params = {
|
|
pos = pos,
|
|
gain = 1.0, -- default
|
|
max_hear_distance = 10, -- default, uses a Euclidean metric
|
|
}
|
|
|
|
minetest.remove_node(pos)
|
|
minetest.sound_play(mcl_sounds.node_sound_wood_defaults().dug, sound_params, true)
|
|
minetest.add_item(pos, istack)
|
|
end
|
|
--]]
|
|
|
|
function mcl_bamboo.grow_bamboo(pos, bonemeal_applied)
|
|
local node_above = minetest.get_node(vector.offset(pos, 0, 1, 0))
|
|
mcl_bamboo.mcl_log("Grow bamboo called; bonemeal: " .. tostring(bonemeal_applied))
|
|
|
|
if not bonemeal_applied and mcl_bamboo.is_bamboo(node_above.name) ~= false then
|
|
return false -- short circuit this function if we're trying to grow (std) the bamboo and it's not the top shoot.
|
|
end
|
|
if minetest.get_node_light(pos) < 8 then
|
|
return false
|
|
end
|
|
|
|
-- variables used in more than one spot.
|
|
local first_shoot
|
|
local chk_pos
|
|
local soil_pos
|
|
local node_name = ""
|
|
local dist = 0
|
|
local node_below
|
|
-- -------------------
|
|
|
|
mcl_bamboo.mcl_log("Grow bamboo; checking for soil: ")
|
|
-- the soil node below the bamboo.
|
|
for py = -1, BAMBOO_SOIL_DIST, -1 do
|
|
chk_pos = vector.offset(pos, 0, py, 0)
|
|
node_name = minetest.get_node(chk_pos).name
|
|
if mcl_bamboo.is_dirt(node_name) then
|
|
soil_pos = chk_pos
|
|
break
|
|
end
|
|
if mcl_bamboo.is_bamboo(node_name) == false then
|
|
break
|
|
end
|
|
end
|
|
-- requires knowing where the soil node is.
|
|
if soil_pos == nil then
|
|
return false -- returning false means don't use up the bonemeal.
|
|
end
|
|
|
|
mcl_bamboo.mcl_log("Grow bamboo; soil found. ")
|
|
local grow_amount = rand(1, GROW_DOUBLE_CHANCE)
|
|
grow_amount = rand(1, GROW_DOUBLE_CHANCE)
|
|
grow_amount = rand(1, GROW_DOUBLE_CHANCE) -- because yeah, not truly random, or even a good prng.
|
|
grow_amount = rand(1, GROW_DOUBLE_CHANCE)
|
|
local init_height = rand(BAM_MAX_HEIGHT_STPCHK + 1, BAM_MAX_HEIGHT_TOP + 1)
|
|
mcl_bamboo.mcl_log("Grow bamboo; random height: " .. init_height)
|
|
|
|
node_name = ""
|
|
|
|
-- update: add randomized max height to first node's meta data.
|
|
first_shoot = vector.offset(soil_pos, 0, 1, 0)
|
|
local meta = minetest.get_meta(first_shoot)
|
|
node_below = minetest.get_node(first_shoot).name
|
|
|
|
mcl_bamboo.mcl_log("Grow bamboo; checking height meta ")
|
|
-- check the meta data for the first node, to see how high to make the stalk.
|
|
if not meta then
|
|
-- if no metadata, set the metadata!!!
|
|
meta:set_int("height", init_height)
|
|
end
|
|
local height = meta:get_int("height", -1)
|
|
mcl_bamboo.mcl_log("Grow bamboo; meta-height: " .. height)
|
|
if height <= 10 then
|
|
height = init_height
|
|
meta:set_int("height", init_height)
|
|
end
|
|
|
|
mcl_bamboo.mcl_log("Grow bamboo; height: " .. height)
|
|
|
|
-- Bonemeal: Grows the bamboo by 1-2 stems. (per the minecraft wiki.)
|
|
if bonemeal_applied then
|
|
-- handle applying bonemeal.
|
|
for py = 1, BAM_MAX_HEIGHT_TOP do
|
|
-- find the top node of bamboo.
|
|
chk_pos = vector.offset(pos, 0, py, 0)
|
|
node_name = minetest.get_node(chk_pos).name
|
|
dist = vector.distance(soil_pos, chk_pos)
|
|
if mcl_bamboo.is_bamboo(node_name) == false or node_name == BAMBOO_ENDCAP_NAME then
|
|
break
|
|
end
|
|
end
|
|
|
|
mcl_bamboo.mcl_log("Grow bamboo; dist: " .. dist)
|
|
|
|
if node_name == BAMBOO_ENDCAP_NAME then
|
|
-- prevent overgrowth
|
|
return false
|
|
end
|
|
|
|
-- check to see if we have a full stalk of bamboo.
|
|
if dist >= height - 1 then
|
|
if dist == height - 1 then
|
|
-- equals top of the stalk before the cap
|
|
if node_name == "air" then
|
|
mcl_bamboo.mcl_log("Grow bamboo; Placing endcap")
|
|
minetest.set_node(vector.offset(chk_pos, 0, 1, 0), { name = BAMBOO_ENDCAP_NAME })
|
|
return true -- returning true means use up the bonemeal.
|
|
else
|
|
return false
|
|
end
|
|
else
|
|
-- okay, we're higher than the end cap, fail out.
|
|
return false -- returning false means don't use up the bonemeal.
|
|
end
|
|
end
|
|
|
|
-- and now, the meat of the section... add bamboo to the stalk.
|
|
-- at this point, we should be lower than the generated maximum height. ~ about height -2 or lower.
|
|
if dist <= height - 2 then
|
|
if node_name == "air" then
|
|
-- here we can check to see if we can do up to 2 bamboo shoots onto the stalk
|
|
mcl_bamboo.mcl_log("Grow bamboo; Placing bamboo.")
|
|
minetest.set_node(chk_pos, { name = node_below })
|
|
-- handle growing a second node.
|
|
if grow_amount == 2 then
|
|
chk_pos = vector.offset(chk_pos, 0, 1, 0)
|
|
if minetest.get_node(chk_pos).name == "air" then
|
|
mcl_bamboo.mcl_log("Grow bamboo; OOOH! It's twofer day!")
|
|
minetest.set_node(chk_pos, { name = node_below })
|
|
end
|
|
end
|
|
return true -- exit out with a success. We've added 1-2 nodes, per the wiki.
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Non-Bonemeal growth.
|
|
for py = 1, BAM_MAX_HEIGHT_TOP do
|
|
-- Find the topmost node above the stalk, and check it for "air"
|
|
chk_pos = vector.offset(pos, 0, py, 0)
|
|
node_below = minetest.get_node(pos).name
|
|
node_name = minetest.get_node(chk_pos).name
|
|
dist = vector.distance(soil_pos, chk_pos)
|
|
|
|
if node_name ~= "air" and mcl_bamboo.is_bamboo(node_name) == false then
|
|
break
|
|
end
|
|
|
|
-- stop growing check. ie, handle endcap placement.
|
|
if dist >= height - 1 then
|
|
local above_node_name = minetest.get_node(vector.offset(chk_pos, 0, 1, 0)).name
|
|
if node_name == "air" and above_node_name == "air" then
|
|
if height - 1 == dist then
|
|
mcl_bamboo.mcl_log("Grow bamboo; Placing endcap")
|
|
minetest.set_node(chk_pos, { name = BAMBOO_ENDCAP_NAME })
|
|
end
|
|
end
|
|
break
|
|
end
|
|
|
|
-- handle regular node placement.
|
|
-- find the air node above the top shoot. place a node. And then, if short enough,
|
|
-- check for second node placement.
|
|
if node_name == "air" then
|
|
mcl_bamboo.mcl_log("Grow bamboo; dist: " .. dist)
|
|
mcl_bamboo.mcl_log("Grow bamboo; Placing bamboo.")
|
|
minetest.set_node(chk_pos, { name = node_below })
|
|
-- handle growing a second node. (1 in 32 chance.)
|
|
if grow_amount == 2 and dist <= height - 2 then
|
|
chk_pos = vector.offset(chk_pos, 0, 1, 0)
|
|
if minetest.get_node(chk_pos).name == "air" then
|
|
mcl_bamboo.mcl_log("Grow bamboo; OOOH! It's twofer day!")
|
|
minetest.set_node(chk_pos, { name = node_below })
|
|
end
|
|
end
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Add Groups function, courtesy of Warr1024.
|
|
function mcl_bamboo.add_groups(name, ...)
|
|
local def = minetest.registered_items[name] or error(name .. " not found")
|
|
local groups = {}
|
|
for k, v in pairs(def.groups) do
|
|
groups[k] = v
|
|
end
|
|
local function add_all(x, ...)
|
|
if not x then
|
|
return
|
|
end
|
|
groups[x] = 1
|
|
return add_all(...)
|
|
end
|
|
addall(...)
|
|
return minetest.override_item(name, { groups = groups })
|
|
end
|
|
|
|
function mcl_bamboo.mcl_log(m, l)
|
|
if not m then
|
|
minetest.log("error", "expected string, received: " .. m)
|
|
return
|
|
end
|
|
if DEBUG then
|
|
if not l then
|
|
minetest.log("[mcl_bamboo]: " .. m)
|
|
else
|
|
minetest.log(l, "[mcl_bamboo]: " .. m)
|
|
end
|
|
end
|
|
end
|