From 7d93272caa4503979abb9b98a05a9b801870a72b Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Thu, 31 Mar 2016 21:58:59 -0700 Subject: [PATCH] Change how dirt turns to dirt_with_(something) This changes how dirt blocks turn to dirt_with -grass, -dry_grass or -snow. Previously, dirt that was sunlit would turn to dirt_with_grass no matter what, but this happened without any context, so you could get green patches of dirt_with_grass in the middle of a savannah or even desert. Dirt no longer turns to covered dirt unless it's within 1 node from another dirt_with_grass or dirt_with_dry_grass or dirt_with_snow. This makes dirt_with_grass "growback" a lot slower, since it now only happens on the edges, but it retains the context nicely now. If there is any dirt with a grass or dry grass plant, or snow on top, and enough light, we'll convert it sporadically to dirt_with_grass or dirt_with_dry_grass or dirt_with_snow. This allows us to plant grass of our choice in a large dirt patch, or in a region where otherwise that type of grass is not present. This used to be done by 2 abms, but I've combined them in to a single ABM that is ordered to run with maximum efficiency, solving for the most common outcome first before attempting more complex checks. --- mods/default/functions.lua | 61 ++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/mods/default/functions.lua b/mods/default/functions.lua index bd55d32f..775803bc 100644 --- a/mods/default/functions.lua +++ b/mods/default/functions.lua @@ -353,32 +353,69 @@ minetest.register_abm({ -- --- Grass growing on well-lit dirt +-- Convert dirt to something that fits the environment -- minetest.register_abm({ nodenames = {"default:dirt"}, - neighbors = {"air"}, + neighbors = { + "default:dirt_with_grass", + "default:dirt_with_dry_grass", + "default:dirt_with_snow", + "default:grass_1", + "default:grass_2", + "default:grass_3", + "default:grass_4", + "default:grass_5", + "default:dry_grass_1", + "default:dry_grass_2", + "default:dry_grass_3", + "default:dry_grass_4", + "default:dry_grass_5", + "default:snow", + }, interval = 6, chance = 67, catch_up = false, action = function(pos, node) + -- Most likely case, half the time it's too dark for this. local above = {x = pos.x, y = pos.y + 1, z = pos.z} - local name = minetest.get_node(above).name - local nodedef = minetest.registered_nodes[name] - if nodedef and (nodedef.sunlight_propagates or nodedef.paramtype == "light") and - nodedef.liquidtype == "none" and - (minetest.get_node_light(above) or 0) >= 13 then - if name == "default:snow" or name == "default:snowblock" then - minetest.set_node(pos, {name = "default:dirt_with_snow"}) - else - minetest.set_node(pos, {name = "default:dirt_with_grass"}) + if (minetest.get_node_light(above) or 0) < 13 then + return + end + + -- Look for likely neighbors. + local p2 = minetest.find_node_near(pos, 1, {"default:dirt_with_grass", + "default:dirt_with_dry_grass", "default:dirt_with_snow"}) + if p2 then + -- But the node needs to be under air in this case. + local n2 = minetest.get_node(above) + if n2 and n2.name == "air" then + local n3 = minetest.get_node(p2) + minetest.set_node(pos, {name = n3.name}) + return end end + + -- Anything on top? + local n2 = minetest.get_node(above) + if not n2 then + return + end + + local name = n2.name + -- Snow check is cheapest, so comes first. + if name == "default:snow" then + minetest.set_node(pos, {name = "default:dirt_with_snow"}) + -- Most likely case first. + elseif name:sub(1, 13) == "default:grass" then + minetest.set_node(pos, {name = "default:dirt_with_grass"}) + elseif name:sub(1, 17) == "default:dry_grass" then + minetest.set_node(pos, {name = "default:dirt_with_dry_grass"}) + end end }) - -- -- Grass and dry grass removed in darkness --