--- --- 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", } mcl_bamboo.bamboo_set = {} for _,key in pairs(mcl_bamboo.bamboo_index) do mcl_bamboo.bamboo_set[key] = true end 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 log = mcl_bamboo.mcl_log local node_above = minetest.get_node(vector.offset(pos, 0, 1, 0)) log("Grow bamboo called; bonemeal: " .. tostring(bonemeal_applied)) if not bonemeal_applied then -- Only allow natural growth at the top of the bamboo if mcl_bamboo.is_bamboo(node_above.name) ~= false then return false end -- Don't perform natual growth in low light if minetest.get_node_light(pos) < 8 then return false end end -- Determine the location of soil local soil_pos soil_pos,a,b = mcl_util.trace_nodes(pos, -1, mcl_bamboo.bamboo_set, BAMBOO_MAX_HEIGHT - 1) -- No soil found, return false so that bonemeal isn't used if not soil_pos then return false end log("Grow bamboo; soil found. ") -- Find the first bamboo shoot and retrieve data about it local first_shoot = vector.offset(soil_pos, 0, 1, 0) local first_shoot_meta = minetest.get_meta(first_shoot) -- Get or initialize bamboo height local height = (first_shoot_meta and first_shoot_meta:get_int("height", -1)) or -1 if height == -1 then height = rand(BAM_MAX_HEIGHT_STPCHK + 1, BAM_MAX_HEIGHT_TOP + 1) first_shoot_meta:set_int("height", height) end log("Grow bamboo; height: " .. height) -- Locate the bamboo tip local bamboo_tip,actual_height,bamboo_tip_node = mcl_util.trace_nodes(first_shoot, 1, mcl_bamboo.bamboo_set, height - 1) log("Current height: "..tostring(actual_height)) -- Short circuit growth if the bamboo is already finished growing if not bamboo_tip or not actual_height or actual_height >= height then log("Bamboo is already as large as it can grow") return false end -- Now that we are actually going to add nodes, initialize some more information local first_shoot_node_name = minetest.get_node(first_shoot).name -- If applying bonemeal, randomly grow two segments instead of one local grow_amount = 1 if bonemeal_applied then local rng = PcgRandom(minetest.hash_node_position(pos) + minetest.get_us_time()) if rng:next(1, GROW_DOUBLE_CHANGE) == 1 then grow_amount = 2 end end log("Growing up to "..grow_amount.." segments") -- Perform bamboo growth for i = 1,grow_amount do -- Check for air to grow into local bamboo_tip_node = minetest.get_node(bamboo_tip) if not bamboo_tip_node or bamboo_tip_node.name ~= "air" then -- Something is blocking growth, stop and signal that use bonemeal has been used if at least on segment has grown return i ~= 1 end if actual_height + 1 == height then -- This is the end cap minetest.set_node(bamboo_tip, { name = BAMBOO_ENDCAP_NAME }) return true else -- This isn't the end cap, add a bamboo segment minetest.set_node(bamboo_tip, { name = first_shoot_node_name }) actual_height = actual_height + 1 end bamboo_tip = vector.offset(bamboo_tip, 0, 1, 0) end return true 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