-- check for air and exit if not found
if node_name ~= "air" then
return
end
place_node()
But it doesn't seem to work 100% of the time. Does anyone have an idea of why this might be? Is there a better way to write this check? Is there a one node equivalent of the "find_nodes_in_area_under_air" function?
It would be useful to show with what you initialize this node_name variable. The issue is probably there. Also, if this code is a callback, the return value may be important because it can cancel the action of the player in some cases. In other words, show us the full function if it is not too long (it shouldn't! :-) and if possible.
Moreover, it could be that when it doesn't work, the node is actually an "air-like" node rather than an "air" node. If you expect it to work in this scenarios, you might want to check that the node is not "walkable" (that includes e.g. plants typically though).
function spawn_the_node(pos, node)
-- This block needs to be soil.
if core.get_item_group(core.get_node(pos).name, "soil") == 0 then
return
end
-- Block above needs to be air.
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
local above_node_name = core.get_node(above).name
if above_node_name ~= "air" then
return
end
-- ...more checks...
-- If everything worked, place a node.
core.set_node(above, {name = node_name})
end
I did a test in a flat field full of mese post lamps, with "chat_send_all(above_node_name)" right before the node placement line and it even sent to the chat "mese_post_lamp", so it's setting the "above_node_name" variable correctly.
What do you mean that it doesn't work 100% of the time. Is it running in cases where it shouldn't, or isn't in cases where it should?
The most recent bit of code you shared looks like the soil check is ignored, as the above node check will run every time regardless of the results of the soil check. If you want the function to only run when both cases are true (the node is soil with air above) you need to put both checks into the same if conditional, or nest the air check inside the soil check.
What do you mean that it doesn't work 100% of the time. Is it running in cases where it shouldn't, or isn't in cases where it should?
The most recent bit of code you shared looks like the soil check is ignored, as the above node check will run every time regardless of the results of the soil check. If you want the function to only run when both cases are true (the node is soil with air above) you need to put both checks into the same if conditional, or nest the air check inside the soil check.
The nodes are spawning, replacing nodes that already exist on top of the soil blocks. I want it to only spawn them where the space on top of the soil block is air.
There are several other checks in the function, each bailing out with a "return" if the check fails. The intention is that every check must pass and at the very end a node is placed on a soil block with nothing already on top of it.
-- ...but it can be flora
if core.get_item_group(above_node_name, "flora") ~= 0 then
I think this should be == 0 because you want to exit if it's not flora
In the future, I recommend using print statements or asserts to check your assumptions
When asking for help, you should also make a minimal reproducible example and actually test it to narrow things down and make sure it's not a silly mistake like this
Also, you probably want to be using airlike and buildable_to rather than checking for specific node names and groups
if core.registered_nodes[above_node_name].drawtype ~= "airlike" then
And I'm still getting inconsistent results. In my debug print statements that I have in my private testing version, I see two nodes both fail the check for being airlike, but even though they're both mese post lights, one is then replaced by a sapling but the other is not.
-- sapling_spawn/init.lua
-- Namespace
sapling_spawn = {}
-- Tree name -> sapling name lookup table
sapling_ref = {} -- used {[default:tree] = "default:sapling"} for testing
-- Load support for other mods' trees
local modpath = core.get_modpath("sapling_spawn")
--dofile(modpath.."/other_mods.lua")
-- Spawn saplings
function sapling_spawn.spawn_saplings(pos, node)
-- get block above
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
local above_node_name = core.get_node(above).name
local above_node_def = core.registered_nodes[above_node_name]
-- block above must be buildable_to (air, grass, flowers etc.)
if not above_node_def or not above_node_def.buildable_to then
return
end
-- block above cannot be water
if above_node_def.liquidtype ~= "none" then
return
end
-- do we have enough light
local light = core.get_node_light(above) or 0
if light < 13 then
return
end
-- look for tree within area
local proximity = 15
local nearest_tree = core.find_node_near(pos, proximity, {"group:tree"})
-- if no tree found return
if not nearest_tree then
return
end
-- define area and check for tree dentity
local pos0 = {x = pos.x - 9, y = pos.y - 3, z = pos.z - 9}
local pos1 = {x = pos.x + 9, y = pos.y + 3, z = pos.z + 9}
-- observe a maximum density of trees, in the volume defined, there are 2527 blocks.
-- 500 is approximately 20% of that space. 100 is 3-4%.
if #core.find_nodes_in_area(pos0, pos1, {"group:tree"}) >= 100 then
return
end
-- do we already have saplings within observable area
if #core.find_nodes_in_area(pos0, pos1, {"group:sapling"}) >= 1 then
return
end
-- select sapling from nearest tree found above
local sapling_name = sapling_ref[core.get_node(nearest_tree).name]
-- if tree type not found then bail
if sapling_name == nil then
return
end
-- if everything worked out, place a sapling
core.set_node(above, {name = sapling_name})
end
core.register_abm({
label = "Spawn saplings",
nodenames = {"group:soil"}, -- we already know it will find soil
neighbors = {"group:air"}, -- make sure it's surface soil
without_neighbors = {"group:tree"}, -- not near a tree
interval = 240,
chance = 2048,
action = function(...)
sapling_spawn.spawn_saplings(...)
end,
})
The flora test is not the issue here. And in my case, I want it to continue if it is part of the flora group.
You've got the test the wrong way around - it will return if it is in the flora group and will continue if it is not in the flora group. A node group is 0 if absent, >0 otherwise
But I see you'd been sent some preexisting code which does the task for you, this code is much better than checking for air or the flora group
You've got the test the wrong way around - it will return if it is in the flora group and will continue if it is not in the flora group. A node group is 0 if absent, >0 otherwise
But I see you'd been sent some preexisting code which does the task for you, this code is much better than checking for air or the flora group
Aha, yeah you're correct of course. I've gotta stop working on this only late at night so I can think more clearly.
And I agree - using the buildable_to check is better and accomplishes the same goal.