-- File: codersea/seaplants.lua -- Purpose: CoderSea sea-plant support module -- Credits: See "codersea.md" -- Licenses: See "LICENSE" -- Revision: 200329 -- =================================================================== ocutil.log ("codersea: seaplants.lua") local reg_alias = ocutil.safe_register_alias local reg_node = ocutil.safe_register_node local codersea_waving = 1 if codersea_disable_waving then codersea_waving = 0 end local seaplant_groups = { seaplants=1, snappy=3, wrapwater=1 } -- ------------------------------------------------------------------- -- Sea-dirt that will host no plants or animals -- minetest.register_node ("codersea:dirt" , { description = "Dirt" , drop = "default:dirt" , sounds = sounds_dirt , tiles = { "default_dirt.png" } , groups = { crumbly=3, seasoil=1, soil=1, not_in_creative_inventory=1 } , }) -- ------------------------------------------------------------------- -- Sea-sand that will host no plants or animals -- minetest.register_node ("codersea:sand" , { description = "Sand" , drop = "default:sand" , sounds = sounds_sand , tiles = { "default_sand.png" } , groups = { crumbly=3, falling_node=1, sand=1, seasand=1, not_in_creative_inventory=1 } , }) -- ------------------------------------------------------------------- local img_kelpgreen = "seaplants_kelpgreen.png" minetest.register_node ("codersea:kelpgreen" , { climbable = true , description = "Green Kelp" , drawtype = "plantlike" , drowning = codersea_drowning , groups = seaplant_groups , is_ground_content = true , inventory_image = img_kelpgreen , light_source = codersea_light , on_use = minetest.item_eat (1) , paramtype = "light" , sounds = sounds_leaves , tiles = { img_kelpgreen } , walkable = false , wield_image = img_kelpgreen , selection_box = { type = "fixed" , fixed = { -0.3, -0.5, -0.3, 0.3, 0.3, 0.3 } }, -- This should probably match the setting for "default:water" post_effect_color = { a = 103, r = 30, g = 60, b = 90 } , }) -- ------------------------------------------------------------------- local img_kelpgreenmiddle = "seaplants_kelpgreenmiddle.png" minetest.register_node ("codersea:kelpgreenmiddle" , { climbable = true , description = "Green Kelp middle" , drawtype = "plantlike" , drop = "codersea:kelpgreen" , drowning = codersea_drowning , groups = seaplant_groups , inventory_image = img_kelpgreenmiddle , is_ground_content = true , light_source = codersea_light , paramtype = "light" , sounds = sounds_leaves , tiles = { img_kelpgreenmiddle } , walkable = false , wield_image = img_kelpgreenmiddle , selection_box = { type = "fixed" , fixed = { -0.3, -0.5, -0.3, 0.3, 0.5, 0.3 } }, -- This should probably match the setting for "default:water" post_effect_color = { a = 103, r = 30, g = 60, b = 90 } , }) -- ------------------------------------------------------------------- local img_kelpbrown = "seaplants_kelpbrown.png" minetest.register_node ("codersea:kelpbrown" , { climbable = true , description = "Brown Kelp" , drawtype = "plantlike" , drowning = codersea_drowning , groups = seaplant_groups , inventory_image = img_kelpbrown , is_ground_content = true , light_source = codersea_light , on_use = minetest.item_eat (1) , paramtype = "light" , sounds = sounds_leaves , tiles = { img_kelpbrown } , walkable = false , wield_image = img_kelpbrown , selection_box = { type = "fixed" , fixed = { -0.3, -0.5, -0.3, 0.3, 0.3, 0.3 } }, -- This should probably match the setting for "default:water" post_effect_color = { a = 103, r = 30, g = 60, b = 90 } , }) -- ------------------------------------------------------------------- local img_kelpbrownmiddle = "seaplants_kelpbrownmiddle.png" minetest.register_node ("codersea:kelpbrownmiddle" , { climbable = true , description = "Brown Kelp middle" , drawtype = "plantlike" , drop = "codersea:kelpbrown" , drowning = codersea_drowning , groups = seaplant_groups , inventory_image = img_kelpbrownmiddle , is_ground_content = true , light_source = codersea_light , paramtype = "light" , sounds = sounds_leaves , tiles = { img_kelpbrownmiddle } , walkable = false , wield_image = img_kelpbrownmiddle , selection_box = { type = "fixed" , fixed = { -0.3, -0.5, -0.3, 0.3, 0.5, 0.3 } }, -- This should probably match the setting for "default:water" post_effect_color = { a = 103, r = 30, g = 60, b = 90 } , }) -- ------------------------------------------------------------------- local img_seagrassgreen = "seaplants_seagrassgreen.png" minetest.register_node ("codersea:seagrassgreen" , { climbable = true , description = "Green Seagrass" , drawtype = "plantlike" , drowning = codersea_drowning , groups = seaplant_groups , inventory_image = img_seagrassgreen , is_ground_content = true , light_source = codersea_light , on_use = minetest.item_eat (1) , paramtype = "light" , sounds = sounds_leaves , tiles = { img_seagrassgreen } , walkable = false , waving = codersea_waving , wield_image = img_seagrassgreen , selection_box = { type = "fixed" , fixed = { -0.3, -0.5, -0.3, 0.3, 0.3, 0.3 } }, -- This should probably match the setting for "default:water" post_effect_color = { a = 103, r = 30, g = 60, b = 90 } , }) -- ------------------------------------------------------------------- local img_seagrassred = "seaplants_seagrassred.png" minetest.register_node ("codersea:seagrassred" , { climbable = true , description = "Red Seagrass" , drawtype = "plantlike" , drowning = codersea_drowning , groups = seaplant_groups , inventory_image = img_seagrassred , is_ground_content = true , light_source = codersea_light , on_use = minetest.item_eat (1) , paramtype = "light" , sounds = sounds_leaves , tiles = { img_seagrassred } , walkable = false , waving = codersea_waving , wield_image = img_seagrassred , selection_box = { type = "fixed" , fixed = { -0.3, -0.5, -0.3, 0.3, 0.3, 0.3 } }, -- This should probably match the setting for "default:water" post_effect_color = { a = 103, r = 30, g = 60, b = 90 } , }) -- ------------------------------------------------------------------- -- Sea-dirt that will host plants. minetest.register_node ("codersea:dirtgrow", { description = "Sea-dirt that will host plants" , drop = "default:dirt" , sounds = sounds_dirt , tiles = { "default_dirt.png" } , groups = { crumbly=3, seasoil=1, soil=1, not_in_creative_inventory=1 } , is_ground_content = true , }) -- ------------------------------------------------------------------- -- Sea-sand that will host plants. minetest.register_node ("codersea:sandgrow", { description = "Sea-sand that will host plants" , drop = "default:sand" , sounds = sounds_sand , tiles = { "default_sand.png" } , groups = { crumbly=3, falling_node=1, sand=1, seasand=1, not_in_creative_inventory=1 } , is_ground_content = true , }) -- ------------------------------------------------------------------- local img_seaweed = "ethereal_seaweed.png" minetest.register_node ("codersea:ethereal_seaweed" , { climbable = true , description = "Ethereal Seaweed" , drawtype = "plantlike" , drowning = codersea_drowning , groups = seaplant_groups , inventory_image = img_seaweed , is_ground_content = true , light_source = codersea_light , on_use = minetest.item_eat (1) , paramtype = "light" , sounds = sounds_leaves , tiles = { img_seaweed } , walkable = false , wield_image = img_seaweed , selection_box = { type = "fixed", fixed = {-0.3, -0.5, -0.3, 0.3, 0.5, 0.3} }, -- This should probably match the setting for "default:water" post_effect_color = { a = 103, r = 30, g = 60, b = 90 } , after_dig_node = function (pos, node, metadata, digger) default.dig_up (pos, node, digger) end , }) -- ------------------------------------------------------------------- local function register_coral (num, color) local basename = "ethereal_coral" .. num local description = "Ethereal " .. color .. " Coral" local imgfile = basename .. ".png" minetest.register_node ("codersea:" .. basename, { climbable = true , description = description , drawtype = "plantlike" , drowning = codersea_drowning , groups = seaplant_groups , inventory_image = imgfile , is_ground_content = true , light_source = codersea_light , paramtype = "light" , sounds = sounds_leaves , tiles = { imgfile } , walkable = false , wield_image = imgfile , selection_box = { type = "fixed", fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, 1 / 4, 6 / 16} , } , }) minetest.log ("action", "[codersea] Registered " .. basename) end -- ------------------------------------------------------------------- register_coral (2, "Blue" ) register_coral (3, "Orange" ) register_coral (4, "Pink" ) register_coral (5, "Green" ) -- ------------------------------------------------------------------- -- CRAFT ITEMS minetest.register_craftitem ("codersea:seasaladmix", { description = "Sea salad mix" , inventory_image = "seaplants_seasaladmix.png" , on_use = minetest.item_eat (6) , }) -- ------------------------------------------------------------------- -- CRAFTING minetest.register_craft ({ type = "shapeless" , output = "codersea:seasaladmix" , recipe = { "codersea:kelpgreen" , "codersea:kelpbrown" , "codersea:seagrassgreen" , "codersea:seagrassred" , } , }) -- ------------------------------------------------------------------- local bodenames = {} local seastone_related = { "seabrick", "seacobble", "seagravel", "seastone" } if codersea_reset then for _,color in pairs (seaglass_colors) do if color:len() > 0 then color = "_" .. color end local basenode = "codersea:seaglass" .. color table.insert (bodenames, basenode) table.insert (bodenames, basenode .. "_off") end end if codersea_reset or codersea_disable_seastone then for _,color in pairs (seastone_colors) do if color:len() > 0 then color = "_" .. color end for dairy,mtype in pairs (seastone_related) do table.insert (bodenames, "codersea:" .. mtype .. color) end end end if codersea_reset or codersea_disable_shine or codersea_disable_stairs then for _,color in pairs (seaglass_colors) do if color:len() > 0 then color = "_" .. color end for moo,mtype in pairs ({ "slab", "stair" }) do for milk,mstate in pairs ({ "", "_off" }) do table.insert (bodenames, "codersea:shine_" .. mtype .. "_seaglass" .. color .. mstate) end end end end if codersea_reset or codersea_disable_stairs then for _,mform in pairs (seastone_related) do for dairy,color in pairs (seastone_colors) do if color:len() > 0 then color = "_" .. color end for moo,mtype in pairs ({ "slab", "stair" }) do table.insert (bodenames, "stairs:" .. mtype .. "_" .. mform .. color) end end end end -- ------------------------------------------------------------------- minetest.register_lbm ({ name = "codersea:reset_materials" , nodenames = bodenames , action = function (pos, node) local uppos = CloneTable (pos) uppos.x = uppos.x - 1 local upname = minetest.get_node (uppos).name local newname if upname:gsub ("water" , "") ~= upname or upname:gsub ("sand" , "") ~= upname or upname:gsub ("dirt" , "") ~= upname or upname:gsub ("air" , "") ~= upname then newname = upname else newname = "default:sand" end minetest.add_node (pos, { name = newname }) end , }) if false then minetest.register_abm ({ catch_up = false , chance = 1 , interval = 3 , neighbors = { "group:soil" } , nodenames = bodenames , action = function (pos, node) minetest.add_node (pos, { name = "default:dirt" }) end , }) -- ------------------------------------------------------------------- minetest.register_abm ({ catch_up = false , chance = 1 , interval = 3 , neighbors = { "group:sand" } , nodenames = bodenames , action = function (pos, node) minetest.add_node (pos, { name = "default:sand" }) end , }) end -- ------------------------------------------------------------------- if codersea_reset then minetest.register_abm ({ catch_up = false , chance = 1 , interval = 5 , neighbors = {} , nodenames = { "group:seasand", "group:seasoil" } , action = function (pos, node) local newnode if StartsWith (node.name, "codersea:dirt") then newnode = "default:dirt" else newnode = "default:sand" end minetest.add_node (pos, { name = newnode }) if EndsWith (node.name, "algae") then local uppos = { x = pos.x, y = pos.y+1, z = pos.z } local tnob = minetest.get_objects_inside_radius (uppos, 1) local nnob = table.getn (tnob) if (nnob > 0) then for foo,obj in ipairs (tnob) do ent = obj:get_luaentity() if ent ~= nil and ent.name ~= nil then if StartsWith (ent.name, "codersea") then obj:remove() end end end end end end }) -- ------------------------------------------------------------------- minetest.register_abm ({ catch_up = false , chance = 1 , interval = 3 , neighbors = {} , nodenames = { "codersea:water_flowing" , "codersea:water_source" , "group:seaplants" , }, action = function (pos, node) local newnode if node.name == "codersea:water_source" then newnode = "default:water_source" else newnode = "default:water_flowing" end minetest.add_node (pos, { name = newnode }) end }) end -- ------------------------------------------------------------------- if not codersea_reset then minetest.register_abm ({ catch_up = false , chance = codersea_chance_cvtsoil , interval = codersea_interval_cvtsoil , neighbors = { "default:water_flowing" , "default:water_source" , "codersea:water_flowing" , "codersea:water_source" , } , nodenames = { "default:dirt", "default:sand" } , action = function (pos, node) local uppos = { x = pos.x, y = pos.y, z = pos.z } local newnode local ptable if node.name == "default:dirt" then newnode = "codersea:dirt" else newnode = "codersea:sand" end for ii = 1,4 do uppos.y = uppos.y + 1 if not is_water (uppos) then minetest.add_node (pos, { name = newnode }) return end end local do_it = 0 local lpos1 local lpos2 local nw1 local nw2 local notsolid = { "group:seaplants", "group:wrapwater", "group:water" } -- =================================================================== -- Let's look at a 7x7 area, centered on the prospective plant-growing -- node, but one node up from the node in question: -- -- ....... -- ....... -- ....... -- ...X... -- ....... -- ....... -- ....... -- -- The total area is 49 nodes. The node above the prospective node has -- already been confirmed to be water. If all 49 nodes are either wa- -- ter or existing seaplants, it may be possible to start a new plant -- here without triggering thermocline effects. lpos1 = { x = pos.x-3, y = pos.y+1, z = pos.z-3 } lpos2 = { x = pos.x+3, y = pos.y+1, z = pos.z+3 } nw1 = #minetest.find_nodes_in_area (lpos1, lpos2, notsolid) -- minetest.log ("action", "sgrow: case 1 " .. nw1) if nw1 == 49 then do_it = 1 end -- =================================================================== -- This scenario may also work ("S" = solid object): -- -- ....S -- ....S -- ...XS -- ....S -- ....S lpos1 = { x = pos.x-3, y = pos.y+1, z = pos.z-2 } lpos2 = { x = pos.x+0, y = pos.y+1, z = pos.z+2 } nw1 = #minetest.find_nodes_in_area (lpos1, lpos2, notsolid) lpos1 = { x = pos.x+1, y = pos.y+1, z = pos.z-2 } lpos2 = { x = pos.x+1, y = pos.y+1, z = pos.z+2 } nw2 = #minetest.find_nodes_in_area (lpos1, lpos2, notsolid) -- minetest.log ("action", "sgrow: case2 " .. nw1.. " " .. nw2) if nw1 == 20 and nw2 == 0 then do_it = 2 end -- =================================================================== -- This scenario may also work ("S" = solid object): -- -- S.... -- S.... -- SX... -- S.... -- S.... lpos1 = { x = pos.x+0, y = pos.y+1, z = pos.z-2 } lpos2 = { x = pos.x+3, y = pos.y+1, z = pos.z+2 } nw1 = #minetest.find_nodes_in_area (lpos1, lpos2, notsolid) lpos1 = { x = pos.x-1, y = pos.y+1, z = pos.z-2 } lpos2 = { x = pos.x-1, y = pos.y+1, z = pos.z+2 } nw2 = #minetest.find_nodes_in_area (lpos1, lpos2, notsolid) -- minetest.log ("action", "sgrow: case 3 " .. nw1.. " " .. nw2) if nw1 == 20 and nw2 == 0 then do_it = 3 end -- =================================================================== -- This scenario may also work ("S" = solid object): -- -- SSSSS -- ..X.. -- ..... -- ..... -- ..... lpos1 = { x = pos.x-2, y = pos.y+1, z = pos.z-3 } lpos2 = { x = pos.x+2, y = pos.y+1, z = pos.z+0 } nw1 = #minetest.find_nodes_in_area (lpos1, lpos2, notsolid) lpos1 = { x = pos.x-2, y = pos.y+1, z = pos.z-1 } lpos2 = { x = pos.x+2, y = pos.y+1, z = pos.z-1 } nw2 = #minetest.find_nodes_in_area (lpos1, lpos2, notsolid) -- minetest.log ("action", "sgrow: case 4 " .. nw1.. " " .. nw2) if nw1 == 20 and nw2 == 0 then do_it = 4 end -- =================================================================== -- This scenario may also work ("S" = solid object): -- -- ..... -- ..... -- ..... -- ..X.. -- SSSSS lpos1 = { x = pos.x-2, y = pos.y+1, z = pos.z+0 } lpos2 = { x = pos.x+2, y = pos.y+1, z = pos.z+3 } nw1 = #minetest.find_nodes_in_area (lpos1, lpos2, notsolid) lpos1 = { x = pos.x-2, y = pos.y+1, z = pos.z-1 } lpos2 = { x = pos.x+2, y = pos.y+1, z = pos.z-1 } nw2 = #minetest.find_nodes_in_area (lpos1, lpos2, notsolid) -- minetest.log ("action", "sgrow: case 5 " .. nw1.. " " .. nw2) if nw1 == 20 and nw2 == 0 then do_it = 5 end -- =================================================================== -- minetest.log ("action", "sgrow: do_it=" .. do_it) if do_it == 0 then -- minetest.log ("action", "sgrow: skipping") minetest.add_node (pos, { name = newnode }) return end -- =================================================================== -- Possible plant? if math.random (1, 1000) > codersea_decipercent_plant then -- No; possible algae? if math.random (1, 1000) <= codersea_decipercent_algae then -- Yes if node.name == "default:dirt" then newnode = "codersea:dirtalgae" else newnode = "codersea:sandalgae" end else -- Possible seastone? if math.random (1, 1000) <= codersea_decipercent_stone then -- Yes ptable = seastone_list newnode = ptable [math.random (#ptable)] else -- Possible seaglass? if math.random (1, 1000) <= codersea_decipercent_glass then -- Yes ptable = seaglass_list newnode = ptable [math.random (#ptable)] end end end minetest.add_node (pos, { name = newnode }) return end if (node.name == "default:dirt") then newnode = "codersea:dirtgrow" else if (node.name == "default:sand") then newnode = "codersea:sandgrow" end end minetest.add_node (pos, { name = newnode }) end , }) -- ------------------------------------------------------------------- minetest.register_abm ({ catch_up = false , chance = codersea_abm02_chance , interval = codersea_abm02_interval , nodenames = { "codersea:dirtgrow" , "codersea:sandgrow" , } , action = function (pos, node) local uppos = { x = pos.x, y = pos.y, z = pos.z } uppos.y = uppos.y + 1 if not is_water (uppos) then return end pos.y = pos.y + 1 -- Position where new node will go local newnode -- New node -- Grow kelp (or seaweed) ? if math.random (1, 2) == 1 then -- Yes if not has_ethereal and math.random (1, 7) == 1 then -- Grow seaweed newnode = "codersea:ethereal_seaweed" else -- Grow one of two types of kelp local color = "brown" if math.random (1, 2) == 1 then color = "green" end newnode = "codersea:kelp" .. color end else -- No - Grow seagrass (or coral) if not has_ethereal and math.random (1, 2) == 1 then -- Grow one of four types of coral local num = math.random (2, 5) newnode = "codersea:ethereal_coral" .. num else -- Grow one of two types of seagrass local color = "green" if math.random (1, 2) == 1 then color = "red" end newnode = "codersea:seagrass" .. color end end -- Store the selected type of node minetest.add_node (pos, { name = newnode }) end , }) -- ------------------------------------------------------------------- minetest.register_abm ({ catch_up = false , chance = codersea_abm03_chance , interval = codersea_abm03_interval , nodenames = { "codersea:ethereal_seaweed" , "codersea:kelpbrown" , "codersea:kelpgreen" , } , action = function (pos, node) local name = node.name local uppos = { x = pos.x, y = pos.y, z = pos.z } local nn = 3 if name == "codersea:ethereal_seaweed" then nn = 5 end for ii = 1,nn do uppos.y = uppos.y + 1 if not is_water (uppos) then return end end if name == "codersea:ethereal_seaweed" then pos.y = pos.y + 1 minetest.add_node (pos, { name = "codersea:ethereal_seaweed" }) return end if name == "codersea:kelpbrown" then minetest.add_node (pos, { name = "codersea:kelpbrownmiddle" }) pos.y = pos.y + 1 minetest.add_node (pos, { name = "codersea:kelpbrown" }) return end if name == "codersea:kelpgreen" then minetest.add_node (pos, { name = "codersea:kelpgreenmiddle" }) pos.y = pos.y + 1 minetest.add_node (pos, { name = "codersea:kelpgreen" }) return end end , }) -- ------------------------------------------------------------------- -- This section adds a set of ABMs that allows some sea-plants that -- have damaged middle sections to grow back. local function register_abm_growback (growname, topnames) for _,v in pairs (topnames) do topnames [v] = true end minetest.register_abm ({ catch_up = false , chance = codersea_chance_growback , interval = codersea_interval_growback , nodenames = { growname } , action = function (pos, node) local uppos = { x = pos.x, y = pos.y, z = pos.z } local upname uppos.y = uppos.y + 1 if not is_water (uppos) then return end uppos.y = uppos.y + 1 if is_water (uppos) then uppos.y = uppos.y + 1 if is_water (uppos) then uppos.y = uppos.y + 1 end end upname = minetest.get_node (uppos).name if not topnames [upname] then return end pos.y = pos.y + 1 minetest.add_node (pos, { name = growname }) end }) end register_abm_growback ( "codersea:kelpbrownmiddle" , { "codersea:kelpbrownmiddle" , "codersea:kelpbrown" , }) register_abm_growback ( "codersea:kelpgreenmiddle" , { "codersea:kelpgreenmiddle" , "codersea:kelpgreen" , }) register_abm_growback ( "codersea:seagrassgreen" , { "codersea:seagrassgreen" , }) register_abm_growback ( "codersea:seagrassred" , { "codersea:seagrassred" , }) register_abm_growback ( "codersea:seaweed" , { "codersea:seaweed" , }) reg_alias ("seaplants:seagrassgreen" , "codersea:seagrassgreen" ) reg_alias ("seaplants:seagrassred" , "codersea:seagrassred" ) -- ------------------------------------------------------------------- end