Split plantlife open

This commit is contained in:
DanDuncombe 2013-11-03 17:11:51 +00:00
parent 67813afa80
commit b4907343c2
81 changed files with 1645 additions and 1 deletions

View File

@ -0,0 +1,108 @@
-- Basket
minetest.register_craft({
output = "bushes:basket_empty",
recipe = {
{ "default:stick", "default:stick", "default:stick" },
{ "", "default:stick", "" },
},
})
-- Sugar
minetest.register_craftitem(":bushes:sugar", {
description = "Sugar",
inventory_image = "bushes_sugar.png",
on_use = minetest.item_eat(1),
})
minetest.register_craft({
output = "bushes:sugar 1",
recipe = {
{ "default:papyrus", "default:papyrus" },
},
})
for i, berry in ipairs(bushes_classic.bushes) do
local desc = bushes_classic.bushes_descriptions[i]
minetest.register_craftitem(":bushes:"..berry.."_pie_raw", {
description = "Raw "..desc.." pie",
inventory_image = "bushes_"..berry.."_pie_raw.png",
on_use = minetest.item_eat(4),
})
if berry ~= "mixed_berry" then
minetest.register_craftitem(":bushes:"..berry, {
description = desc,
inventory_image = "bushes_"..berry..".png",
groups = {berry = 1},
on_use = minetest.item_eat(1),
})
minetest.register_craft({
output = "bushes:"..berry.."_pie_raw 1",
recipe = {
{ "bushes:sugar", "group:junglegrass", "bushes:sugar" },
{ "bushes:"..berry, "bushes:"..berry, "bushes:"..berry },
},
})
end
-- Cooked pie
minetest.register_craftitem(":bushes:"..berry.."_pie_cooked", {
description = "Cooked "..desc.." pie",
inventory_image = "bushes_"..berry.."_pie_cooked.png",
on_use = minetest.item_eat(6),
})
minetest.register_craft({
type = "cooking",
output = "bushes:"..berry.."_pie_cooked",
recipe = "bushes:"..berry.."_pie_raw",
cooktime = 30,
})
-- slice of pie
minetest.register_craftitem(":bushes:"..berry.."_pie_slice", {
description = "Slice of "..desc.." pie",
inventory_image = "bushes_"..berry.."_pie_slice.png",
on_use = minetest.item_eat(1),
})
minetest.register_craft({
output = "bushes:"..berry.."_pie_slice 6",
recipe = {
{ "bushes:"..berry.."_pie_cooked" },
},
})
-- Basket with pies
minetest.register_craft({
output = "bushes:basket_"..berry.." 1",
recipe = {
{ "bushes:"..berry.."_pie_cooked", "bushes:"..berry.."_pie_cooked", "bushes:"..berry.."_pie_cooked" },
{ "", "bushes:basket_empty", "" },
},
})
end
minetest.register_craft({
output = "bushes:strawberry_pie_raw 1",
recipe = {
{ "bushes:sugar", "group:junglegrass", "bushes:sugar" },
{ "farming_plus:strawberry_item", "farming_plus:strawberry_item", "farming_plus:strawberry_item" },
},
})
minetest.register_craft({
output = "bushes:mixed_berry_pie_raw 2",
recipe = {
{ "bushes:sugar", "group:junglegrass", "bushes:sugar" },
{ "group:berry", "group:berry", "group:berry" },
{ "group:berry", "group:berry", "group:berry" },
},
})

View File

@ -0,0 +1 @@
plants_lib

View File

@ -0,0 +1,5 @@
strawberry: http://www.clker.com/clipart-4060.html
blueberry: http://www.clker.com/clipart-cerezafiro12.html
blackberry: http://www.clker.com/clipart-blackberry-2.html
raspberry: http://www.clker.com/clipart-simple-raspberry.html
gooseberry: http://www.clker.com/clipart-26281.html

View File

@ -0,0 +1,54 @@
-- Bushes classic mod originally by unknown
-- now maintained by VanessaE
--
-- License: WTFPL
bushes_classic = {}
bushes_classic.bushes = {
"strawberry",
"blackberry",
"blueberry",
"raspberry",
"gooseberry",
"mixed_berry"
}
bushes_classic.bushes_descriptions = {
"Strawberry",
"Blackberry",
"Blueberry",
"Raspberry",
"Gooseberry",
"Mixed Berry"
}
bushes_classic.spawn_list = {}
dofile(minetest.get_modpath('bushes_classic') .. '/cooking.lua')
dofile(minetest.get_modpath('bushes_classic') .. '/nodes.lua')
plantslib:spawn_on_surfaces({
spawn_delay = 3600,
spawn_plants = bushes_classic.spawn_list,
avoid_radius = 10,
spawn_chance = 100,
spawn_surfaces = {
"default:dirt_with_grass",
"woodsoils:dirt_with_leaves_1",
"woodsoils:grass_with_leaves_1",
"woodsoils:grass_with_leaves_2"
},
avoid_nodes = {"group:bush"},
seed_diff = 545342534, -- chosen by a fair mashing of the keyboard - guaranteed to be random :P
plantlife_limit = -0.1,
light_min = 10,
temp_min = 0.15, -- approx 20C
temp_max = -0.15, -- approx 35C
humidity_min = 0, -- 50% RH
humidity_max = -1, -- 100% RH
})
minetest.register_alias("bushes:basket_pies", "bushes:basket_strawberry")
print("[Bushes] Loaded.")

View File

@ -0,0 +1,197 @@
plantlife_bushes = {}
-- TODO: add support for nodebreakers? those dig like mese picks
plantlife_bushes.after_dig_node = function(pos, oldnode, oldmetadata, digger)
if( not( digger ) or not( pos ) or not (oldnode )) then
return nil;
end
-- find out which bush type we are dealing with
local bush_name = "";
local can_harvest = false;
if( oldnode.name == 'bushes:fruitless_bush' ) then
-- this bush has not grown fruits yet (but will eventually)
bush_name = oldmetadata[ 'fields' ][ 'bush_type' ];
-- no fruits to be found, so can_harvest stays false
else
local name_parts = oldnode.name:split( ":" );
if( #name_parts >= 2 and name_parts[2]~=nil ) then
name_parts = name_parts[2]:split( "_" );
if( #name_parts >= 2 and name_parts[1]~=nil ) then
bush_name = name_parts[1];
-- this bush really carries fruits
can_harvest = true;
end
end
end
-- find out which tool the digger was wielding (if any)
local toolstack = digger:get_wielded_item();
local capabilities = toolstack:get_tool_capabilities();
-- what the player will get
local harvested = "";
local amount = "";
-- failure to find out what the tool can do: destroy the bush and return nothing
if( not( capabilities["groupcaps"] )) then
return nil;
-- digging with the hand or something like that
elseif( capabilities["groupcaps"]["snappy"] ) then
-- plant a new bush without fruits
minetest.env:add_node(pos,{type='node',name='bushes:fruitless_bush'})
local meta = minetest.env:get_meta( pos );
meta:set_string( 'bush_type', bush_name );
-- construct the stack of fruits the player will get
-- only bushes that have grown fruits can actually give fruits
if( can_harvest == true ) then
amount = "4";
harvested = "bushes:"..bush_name.." "..amount;
end
-- something like a shovel
elseif( capabilities["groupcaps"]["crumbly"] ) then
-- with a chance of 1/3, return 2 bushes
if( math.random(1,3)==1 ) then
amount = "2";
else
amount = "1";
end
-- return the bush itself
harvested = "bushes:" .. bush_name .. "_bush "..amount;
-- something like an axe
elseif( capabilities["groupcaps"]["choppy"] ) then
-- the amount of sticks may vary
amount = math.random( 4, 20 );
-- return some sticks
harvested = "default:stick "..amount;
-- nothing known - destroy the plant
else
return nil;
end
-- give the harvested result to the player
if( harvested ~= "" ) then
--minetest.chat_send_player("singleplayer","you would now get "..tostring( harvested ) );
digger:get_inventory():add_item( "main", harvested );
end
end
plantlife_bushes.after_place_node = function(pos, placer, itemstack)
if( not( itemstack ) or not( pos )) then
return nil;
end
local name_parts = itemstack:get_name():split( ":" );
if( #name_parts <2 or name_parts[2]==nil ) then
return nil;
end
name_parts = name_parts[2]:split( "_" );
if( #name_parts <2 or name_parts[1]==nil ) then
return nil;
end
minetest.env:set_node( pos, {type='node',name='bushes:fruitless_bush'});
local meta = minetest.env:get_meta( pos );
meta:set_string( 'bush_type', name_parts[1] );
return nil;
end
-- regrow berries (uses a base abm instead of plants_lib because of the use of metadata).
minetest.register_abm({
nodenames = { "bushes:fruitless_bush" },
interval = 500,
chance = 10,
action = function(pos, node, active_object_count, active_object_count_wider)
local meta = minetest.env:get_meta( pos );
local bush_name = meta:get_string( 'bush_type' );
if( bush_name ~= nil and bush_name ~= '' ) then
minetest.env:set_node( pos, {type='node',name='bushes:'..bush_name..'_bush'});
end
end
})
-- Define the basket and bush nodes
for i, bush_name in ipairs(bushes_classic.bushes) do
local desc = bushes_classic.bushes_descriptions[i]
minetest.register_node(":bushes:basket_"..bush_name, {
description = "Basket with "..desc.." Pies",
tiles = {
"bushes_basket_"..bush_name.."_top.png",
"bushes_basket_bottom.png",
"bushes_basket_side.png"
},
on_use = minetest.item_eat(18),
groups = { dig_immediate = 3 },
})
if bush_name == "mixed_berry" then
bush_name = "fruitless";
desc = "currently fruitless";
end
minetest.register_node(":bushes:" .. bush_name .. "_bush", {
description = desc.." Bush",
drawtype = "plantlike",
visual_scale = 1.3,
tiles = { "bushes_" .. bush_name .. "_bush.png" },
inventory_image = "bushes_" .. bush_name .. "_bush.png",
paramtype = "light",
sunlight_propagates = true,
walkable = false,
groups = { snappy = 3, bush = 1, flammable = 2},
sounds = default.node_sound_leaves_defaults(),
drop = "",
after_dig_node = function( pos, oldnode, oldmetadata, digger )
return plantlife_bushes.after_dig_node(pos, oldnode, oldmetadata, digger);
end,
after_place_node = function( pos, placer, itemstack )
return plantlife_bushes.after_place_node(pos, placer, itemstack);
end,
})
-- do not spawn fruitless bushes
if bush_name ~= "fruitless" then
table.insert(bushes_classic.spawn_list, "bushes:"..bush_name.."_bush")
end
end
minetest.register_node(":bushes:basket_empty", {
description = "Basket",
tiles = {
"bushes_basket_empty_top.png",
"bushes_basket_bottom.png",
"bushes_basket_side.png"
},
groups = { dig_immediate = 3 },
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 725 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 734 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 708 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 671 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1 @@
plants_lib

View File

@ -0,0 +1,24 @@
Changelog
---------
2012-08-06: Tweaked selection boxes on all nodes. Tweaked seaweed to use
signlike instead of raillike drawtype, (still forced to only spawn flat as
usual). Adjusted light level limits to give it more time to grow. Created
this changelog file using github commit messages as the basis. Shrunk the
geranium flower down a bit to better match the others.
2012-08-03: Tuned out the random-numbers-inside-ABM stuff. Uses the ABM's
chance setting instead. Should be approximately the same as before, but
hopefully using a tad less CPU. Minor tweak to ABM interval/growing delay.
2012-08-01: Added blue geranium to the collection of flowers.
2012-07-31: Disable debug by default.
2012-07-30: many updates over the course of the day - first commit, removed
some redundant files, added wield/inventory image entries for each item, to
force the game to draw them properly (these shouldn't be needed, must be a
bug). Tweaked spawn code so that the radius check also includes the name of
the item being spawned as well as items in group:flower, that way all items can
have a radius test, and not just those in group:flower. Fiddled with the spawn
rates a bit.

469
mods/flowers_plus/init.lua Normal file
View File

@ -0,0 +1,469 @@
-- This file supplies a few additional plants and some related crafts
-- for the plantlife modpack. Last revision: 2013-04-24
flowers_plus = {}
local SPAWN_DELAY = 1000
local SPAWN_CHANCE = 200
local flowers_seed_diff = 329
local lilies_max_count = 320
local lilies_rarity = 33
local seaweed_max_count = 320
local seaweed_rarity = 33
-- register the various rotations of waterlilies
local lilies_list = {
{ nil , nil , 1 },
{ "225", "22.5" , 2 },
{ "45" , "45" , 3 },
{ "675", "67.5" , 4 },
{ "s1" , "small_1" , 5 },
{ "s2" , "small_2" , 6 },
{ "s3" , "small_3" , 7 },
{ "s4" , "small_4" , 8 },
}
for i in ipairs(lilies_list) do
local deg1 = ""
local deg2 = ""
local lily_groups = {snappy = 3,flammable=2,flower=1}
if lilies_list[i][1] ~= nil then
deg1 = "_"..lilies_list[i][1]
deg2 = "_"..lilies_list[i][2]
lily_groups = { snappy = 3,flammable=2,flower=1, not_in_creative_inventory=1 }
end
minetest.register_node(":flowers:waterlily"..deg1, {
description = "Waterlily",
drawtype = "nodebox",
tiles = {
"flowers_waterlily"..deg2..".png",
"flowers_waterlily"..deg2..".png^[transformFY"
},
inventory_image = "flowers_waterlily.png",
wield_image = "flowers_waterlily.png",
sunlight_propagates = true,
paramtype = "light",
paramtype2 = "facedir",
walkable = false,
groups = lily_groups,
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
fixed = { -0.4, -0.5, -0.4, 0.4, -0.45, 0.4 },
},
node_box = {
type = "fixed",
fixed = { -0.5, -0.49, -0.5, 0.5, -0.49, 0.5 },
},
buildable_to = true,
liquids_pointable = true,
drop = "flowers:waterlily",
on_place = function(itemstack, placer, pointed_thing)
local keys=placer:get_player_control()
local pt = pointed_thing
local place_pos = nil
local top_pos = {x=pt.under.x, y=pt.under.y+1, z=pt.under.z}
local under_node = minetest.get_node(pt.under)
local above_node = minetest.get_node(pt.above)
local top_node = minetest.get_node(top_pos)
if plantslib:get_nodedef_field(under_node.name, "buildable_to") then
if under_node.name ~= "default:water_source" then
place_pos = pt.under
elseif top_node.name ~= "default:water_source"
and plantslib:get_nodedef_field(top_node.name, "buildable_to") then
place_pos = top_pos
else
return
end
elseif plantslib:get_nodedef_field(above_node.name, "buildable_to") then
place_pos = pt.above
end
if not plantslib:node_is_owned(place_pos, placer) then
local nodename = "default:cobble" -- if this block appears, something went....wrong :-)
if not keys["sneak"] then
local node = minetest.env:get_node(pt.under)
local waterlily = math.random(1,8)
if waterlily == 1 then
nodename = "flowers:waterlily"
elseif waterlily == 2 then
nodename = "flowers:waterlily_225"
elseif waterlily == 3 then
nodename = "flowers:waterlily_45"
elseif waterlily == 4 then
nodename = "flowers:waterlily_675"
elseif waterlily == 5 then
nodename = "flowers:waterlily_s1"
elseif waterlily == 6 then
nodename = "flowers:waterlily_s2"
elseif waterlily == 7 then
nodename = "flowers:waterlily_s3"
elseif waterlily == 8 then
nodename = "flowers:waterlily_s4"
end
minetest.add_node(place_pos, {name = nodename, param2 = math.random(0,3) })
else
local fdir = minetest.dir_to_facedir(placer:get_look_dir())
minetest.add_node(place_pos, {name = "flowers:waterlily", param2 = fdir})
end
if not plantslib.expect_infinite_stacks then
itemstack:take_item()
end
return itemstack
end
end,
})
end
local algae_list = { {nil}, {2}, {3}, {4} }
for i in ipairs(algae_list) do
local num = ""
local algae_groups = {snappy = 3,flammable=2,flower=1}
if algae_list[i][1] ~= nil then
num = "_"..algae_list[i][1]
algae_groups = { snappy = 3,flammable=2,flower=1, not_in_creative_inventory=1 }
end
minetest.register_node(":flowers:seaweed"..num, {
description = "Seaweed",
drawtype = "nodebox",
tiles = {
"flowers_seaweed"..num..".png",
"flowers_seaweed"..num..".png^[transformFY"
},
inventory_image = "flowers_seaweed_2.png",
wield_image = "flowers_seaweed_2.png",
sunlight_propagates = true,
paramtype = "light",
paramtype2 = "facedir",
walkable = false,
groups = algae_groups,
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
fixed = { -0.4, -0.5, -0.4, 0.4, -0.45, 0.4 },
},
node_box = {
type = "fixed",
fixed = { -0.5, -0.49, -0.5, 0.5, -0.49, 0.5 },
},
buildable_to = true,
liquids_pointable = true,
drop = "flowers:seaweed",
on_place = function(itemstack, placer, pointed_thing)
local keys=placer:get_player_control()
local pt = pointed_thing
local place_pos = nil
local top_pos = {x=pt.under.x, y=pt.under.y+1, z=pt.under.z}
local under_node = minetest.get_node(pt.under)
local above_node = minetest.get_node(pt.above)
local top_node = minetest.get_node(top_pos)
if plantslib:get_nodedef_field(under_node.name, "buildable_to") then
if under_node.name ~= "default:water_source" then
place_pos = pt.under
elseif top_node.name ~= "default:water_source"
and plantslib:get_nodedef_field(top_node.name, "buildable_to") then
place_pos = top_pos
else
return
end
elseif plantslib:get_nodedef_field(above_node.name, "buildable_to") then
place_pos = pt.above
end
if not plantslib:node_is_owned(place_pos, placer) then
local nodename = "default:cobble" -- :D
if not keys["sneak"] then
--local node = minetest.env:get_node(pt.under)
local seaweed = math.random(1,4)
if seaweed == 1 then
nodename = "flowers:seaweed"
elseif seaweed == 2 then
nodename = "flowers:seaweed_2"
elseif seaweed == 3 then
nodename = "flowers:seaweed_3"
elseif seaweed == 4 then
nodename = "flowers:seaweed_4"
end
minetest.add_node(place_pos, {name = nodename, param2 = math.random(0,3) })
else
local fdir = minetest.dir_to_facedir(placer:get_look_dir())
minetest.add_node(place_pos, {name = "flowers:seaweed", param2 = fdir})
end
if not plantslib.expect_infinite_stacks then
itemstack:take_item()
end
return itemstack
end
end,
})
end
-- register all potted plant nodes, crafts, and most backward-compat aliases
local flowers_list = {
{ "Rose", "rose"},
{ "Tulip", "tulip"},
{ "Yellow Dandelion", "dandelion_yellow"},
{ "White Dandelion", "dandelion_white"},
{ "Blue Geranium", "geranium"},
{ "Viola", "viola"},
}
for i in ipairs(flowers_list) do
local flowerdesc = flowers_list[i][1]
local flower = flowers_list[i][2]
minetest.register_node(":flowers:potted_"..flower, {
description = "Potted "..flowerdesc,
drawtype = "plantlike",
tiles = { "flowers_potted_"..flower..".png" },
inventory_image = "flowers_potted_"..flower..".png",
wield_image = "flowers_potted_"..flower..".png",
sunlight_propagates = true,
paramtype = "light",
walkable = false,
groups = { snappy = 3,flammable=2 },
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
fixed = { -0.25, -0.5, -0.25, 0.25, 0.5, 0.25 },
},
})
minetest.register_craft( {
type = "shapeless",
output = "flowers:potted_"..flower,
recipe = {
"flowers:flower_pot",
"flowers:"..flower
}
})
minetest.register_alias("flowers:flower_"..flower.."_pot", "flowers:potted_"..flower)
end
local extra_aliases = {
"waterlily",
"waterlily_225",
"waterlily_45",
"waterlily_675",
"seaweed"
}
for i in ipairs(extra_aliases) do
flower = extra_aliases[i]
minetest.register_alias("flowers:flower_"..flower, "flowers:"..flower)
end
minetest.register_alias( "trunks:lilypad" , "flowers:waterlily_s1" )
minetest.register_alias( "along_shore:lilypads_1" , "flowers:waterlily_s1" )
minetest.register_alias( "along_shore:lilypads_2" , "flowers:waterlily_s2" )
minetest.register_alias( "along_shore:lilypads_3" , "flowers:waterlily_s3" )
minetest.register_alias( "along_shore:lilypads_4" , "flowers:waterlily_s4" )
minetest.register_alias( "along_shore:pondscum_1" , "flowers:seaweed" )
minetest.register_alias( "along_shore:seaweed_1" , "flowers:seaweed" )
minetest.register_alias( "along_shore:seaweed_2" , "flowers:seaweed_2" )
minetest.register_alias( "along_shore:seaweed_3" , "flowers:seaweed_3" )
minetest.register_alias( "along_shore:seaweed_4" , "flowers:seaweed_4" )
-- ongen registrations
flowers_plus.grow_waterlily = function(pos)
local right_here = {x=pos.x, y=pos.y+1, z=pos.z}
for i in ipairs(lilies_list) do
local chance = math.random(1,8)
local ext = ""
local num = lilies_list[i][3]
if lilies_list[i][1] ~= nil then
ext = "_"..lilies_list[i][1]
end
if chance == num then
minetest.add_node(right_here, {name="flowers:waterlily"..ext, param2=math.random(0,3)})
end
end
end
plantslib:register_generate_plant({
surface = {"default:water_source"},
max_count = lilypads_max_count,
rarity = lilypads_rarity,
min_elevation = 1,
max_elevation = 40,
near_nodes = {"default:dirt_with_grass"},
near_nodes_size = 4,
near_nodes_vertical = 1,
near_nodes_count = 1,
plantlife_limit = -0.9,
temp_max = -0.22,
temp_min = 0.22,
},
"flowers_plus.grow_waterlily"
)
flowers_plus.grow_seaweed = function(pos)
local right_here = {x=pos.x, y=pos.y+1, z=pos.z}
minetest.add_node(right_here, {name="along_shore:seaweed_"..math.random(1,4), param2=math.random(1,3)})
end
plantslib:register_generate_plant({
surface = {"default:water_source"},
max_count = seaweed_max_count,
rarity = seaweed_rarity,
min_elevation = 1,
max_elevation = 40,
near_nodes = {"default:dirt_with_grass"},
near_nodes_size = 4,
near_nodes_vertical = 1,
near_nodes_count = 1,
plantlife_limit = -0.9,
},
"flowers_plus.grow_seaweed"
)
-- seaweed at beaches
-- MM: not satisfied with it, but IMHO some beaches should have some algae
plantslib:register_generate_plant({
surface = {"default:water_source"},
max_count = seaweed_max_count,
rarity = seaweed_rarity,
min_elevation = 1,
max_elevation = 40,
near_nodes = {"default:sand"},
near_nodes_size = 1,
near_nodes_vertical = 0,
near_nodes_count = 3,
plantlife_limit = -0.9,
temp_max = -0.64, -- MM: more or less random values, just to make sure it's not everywhere
temp_min = -0.22, -- MM: more or less random values, just to make sure it's not everywhere
},
"flowers_plus.grow_seaweed"
)
plantslib:register_generate_plant({
surface = {"default:sand"},
max_count = seaweed_max_count*2,
rarity = seaweed_rarity/2,
min_elevation = 1,
max_elevation = 40,
near_nodes = {"default:water_source"},
near_nodes_size = 1,
near_nodes_vertical = 0,
near_nodes_count = 3,
plantlife_limit = -0.9,
temp_max = -0.64, -- MM: more or less random values, just to make sure it's not everywhere
temp_min = -0.22, -- MM: more or less random values, just to make sure it's not everywhere
},
"flowers_plus.grow_seaweed"
)
-- spawn ABM registrations
plantslib:spawn_on_surfaces({
spawn_delay = SPAWN_DELAY/2,
spawn_plants = {
"flowers:waterlily",
"flowers:waterlily_225",
"flowers:waterlily_45",
"flowers:waterlily_675",
"flowers:waterlily_s1",
"flowers:waterlily_s2",
"flowers:waterlily_s3",
"flowers:waterlily_s4"
},
avoid_radius = 2.5,
spawn_chance = SPAWN_CHANCE*4,
spawn_surfaces = {"default:water_source"},
avoid_nodes = {"group:flower", "group:flora" },
seed_diff = flowers_seed_diff,
light_min = 9,
depth_max = 2,
random_facedir = {0,3}
})
plantslib:spawn_on_surfaces({
spawn_delay = SPAWN_DELAY*2,
spawn_plants = {"flowers:seaweed"},
spawn_chance = SPAWN_CHANCE*2,
spawn_surfaces = {"default:water_source"},
avoid_nodes = {"group:flower", "group:flora"},
seed_diff = flowers_seed_diff,
light_min = 4,
light_max = 10,
neighbors = {"default:dirt_with_grass"},
facedir = 1
})
plantslib:spawn_on_surfaces({
spawn_delay = SPAWN_DELAY*2,
spawn_plants = {"flowers:seaweed"},
spawn_chance = SPAWN_CHANCE*2,
spawn_surfaces = {"default:dirt_with_grass"},
avoid_nodes = {"group:flower", "group:flora" },
seed_diff = flowers_seed_diff,
light_min = 4,
light_max = 10,
neighbors = {"default:water_source"},
ncount = 1,
facedir = 1
})
plantslib:spawn_on_surfaces({
spawn_delay = SPAWN_DELAY*2,
spawn_plants = {"flowers:seaweed"},
spawn_chance = SPAWN_CHANCE*2,
spawn_surfaces = {"default:stone"},
avoid_nodes = {"group:flower", "group:flora" },
seed_diff = flowers_seed_diff,
light_min = 4,
light_max = 10,
neighbors = {"default:water_source"},
ncount = 6,
facedir = 1
})
-- crafting recipes!
minetest.register_craftitem(":flowers:flower_pot", {
description = "Flower Pot",
inventory_image = "flowers_flowerpot.png",
})
minetest.register_craft( {
output = "flowers:flower_pot",
recipe = {
{ "default:clay_brick", "", "default:clay_brick" },
{ "", "default:clay_brick", "" }
},
})
-- Cotton plants are now provided by the default "farming" mod.
-- old cotton plants -> farming cotton stage 8
-- cotton wads -> string (can be crafted into wool blocks)
-- potted cotton plants -> potted white dandelions
minetest.register_alias("flowers:cotton_plant", "farming:cotton_8")
minetest.register_alias("flowers:flower_cotton", "farming:cotton_8")
minetest.register_alias("flowers:flower_cotton_pot", "flowers:potted_dandelion_white")
minetest.register_alias("flowers:potted_cotton_plant", "flowers:potted_dandelion_white")
minetest.register_alias("flowers:cotton", "farming:string")
minetest.register_alias("flowers:cotton_wad", "farming:string")
print("[Flowers] Loaded.")

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 575 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

View File

@ -0,0 +1,2 @@
default
plants_lib

153
mods/junglegrass/init.lua Normal file
View File

@ -0,0 +1,153 @@
-- This file supplies jungle grass for the plantlife modpack
-- Last revision: 2013-01-24
local SPAWN_DELAY = 1000
local SPAWN_CHANCE = 200
local GROW_DELAY = 500
local GROW_CHANCE = 30
local junglegrass_seed_diff = 329
local grasses_list = {
{"junglegrass:shortest","junglegrass:short" },
{"junglegrass:short" ,"junglegrass:medium" },
{"junglegrass:medium" ,"default:junglegrass" },
{"default:junglegrass" , nil}
}
function clone_node(name)
node2={}
node=minetest.registered_nodes[name]
for k,v in pairs(node) do
node2[k]=v
end
return node2
end
if not minetest.registered_nodes["default:junglegrass"] then
minetest.register_node(":default:junglegrass", {
description = "Jungle Grass",
drawtype = "plantlike",
visual_scale = 1.3,
tiles = {"default_junglegrass.png"},
inventory_image = "default_junglegrass.png",
wield_image = "default_junglegrass.png",
paramtype = "light",
walkable = false,
buildable_to = true,
is_ground_content = true,
groups = {snappy=3,flammable=2,flora=1,attached_node=1, junglegrass=1},
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
},
})
else
new_junglegrass=clone_node("default:junglegrass")
new_junglegrass.groups.junglegrass = 1
minetest.register_node(":default:junglegrass", new_junglegrass)
end
minetest.register_node('junglegrass:medium', {
description = "Jungle Grass (medium height)",
drawtype = 'plantlike',
tile_images = { 'junglegrass_medium.png' },
inventory_image = 'junglegrass_medium.png',
wield_image = 'junglegrass_medium.png',
sunlight_propagates = true,
paramtype = 'light',
walkable = false,
groups = { snappy = 3, flammable=2, junglegrass=1, flora=1 },
sounds = default.node_sound_leaves_defaults(),
drop = 'default:junglegrass',
selection_box = {
type = "fixed",
fixed = {-0.4, -0.5, -0.4, 0.4, 0.5, 0.4},
},
buildable_to = true,
})
minetest.register_node('junglegrass:short', {
description = "Jungle Grass (short)",
drawtype = 'plantlike',
tile_images = { 'junglegrass_short.png' },
inventory_image = 'junglegrass_short.png',
wield_image = 'junglegrass_short.png',
sunlight_propagates = true,
paramtype = 'light',
walkable = false,
groups = { snappy = 3, flammable=2, junglegrass=1, flora=1 },
sounds = default.node_sound_leaves_defaults(),
drop = 'default:junglegrass',
selection_box = {
type = "fixed",
fixed = {-0.4, -0.5, -0.4, 0.4, 0.3, 0.4},
},
buildable_to = true,
})
minetest.register_node('junglegrass:shortest', {
description = "Jungle Grass (very short)",
drawtype = 'plantlike',
tile_images = { 'junglegrass_shortest.png' },
inventory_image = 'junglegrass_shortest.png',
wield_image = 'junglegrass_shortest.png',
sunlight_propagates = true,
paramtype = 'light',
walkable = false,
groups = { snappy = 3, flammable=2, junglegrass=1, flora=1 },
sounds = default.node_sound_leaves_defaults(),
drop = 'default:junglegrass',
selection_box = {
type = "fixed",
fixed = {-0.3, -0.5, -0.3, 0.3, 0, 0.3},
},
buildable_to = true,
})
plantslib:spawn_on_surfaces({
spawn_delay = SPAWN_DELAY,
spawn_plants = {"junglegrass:shortest"},
avoid_radius = 4,
spawn_chance = SPAWN_CHANCE,
spawn_surfaces = {"default:dirt_with_grass", "default:cactus", "default:papyrus"},
avoid_nodes = {"group:junglegrass", "default:junglegrass", "default:dry_shrub"},
seed_diff = junglegrass_seed_diff,
light_min = 5
})
plantslib:spawn_on_surfaces({
spawn_delay = SPAWN_DELAY,
spawn_plants = {"junglegrass:shortest"},
avoid_radius = 4,
spawn_chance = SPAWN_CHANCE*2,
spawn_surfaces = {"default:sand"},
avoid_nodes = {"group:junglegrass", "default:junglegrass", "default:dry_shrub"},
seed_diff = junglegrass_seed_diff,
light_min = 5
})
plantslib:spawn_on_surfaces({
spawn_delay = SPAWN_DELAY,
spawn_plants = {"junglegrass:shortest"},
avoid_radius = 4,
spawn_chance = SPAWN_CHANCE*5,
spawn_surfaces = {"default:desert_sand"},
avoid_nodes = {"group:junglegrass", "default:junglegrass", "default:dry_shrub"},
seed_diff = junglegrass_seed_diff,
light_min = 5
})
for i in ipairs(grasses_list) do
plantslib:grow_plants({
grow_delay = GROW_DELAY,
grow_chance = GROW_CHANCE/2,
grow_plant = grasses_list[i][1],
grow_result = grasses_list[i][2],
dry_early_node = "default:desert_sand",
grow_nodes = {"default:dirt_with_grass", "default:sand", "default:desert_sand"}
})
end
print("[Junglegrass] Loaded.")

View File

@ -0,0 +1,24 @@
Changelog
---------
2012-08-03: Mild rewrite to adapt the mod to use perlin noise while spawning.
Also got rid of the random-numbers-inside-abm stuff, now using the abm's own
'chance' parameter instead. Tuned various settings to try to retain the same
overall density and growth rates as in the previous version. Moved this
changelog into a separate file.
2012-07-12: moved project to github.
2012-07-09 (a bit later): tuned the spawn/grow rates a bit more, made the
numbers more sane. Added a radius check to limit the density of the spawned
grasses (they won't grow near each other or near dry shrubs or cactus, though
they still grow on the top of said cacti).
2012-07-09: Added cactus, sand, and desert sand as spawning surfaces. Reduced
and tuned the spawn rates a bit to try to balance things out. Made that which
spawns on grass, dirt, or sand start out at any size, grow over time, and
eventually die off. Limited desert sand to only the first two sizes (the
smallest size will grow one step, eventually), which will eventually die and
turn into dry shrubs. Only the two smallest sizes can spawn on cactus or
papyrus (and they don't grow or die). Fixed slightly off-center smallest size.
Fixed selection boxes.

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

@ -1 +0,0 @@
Subproject commit f6ffe4bbff0aab504cd78f0871f64fd38222cc25

View File

@ -0,0 +1 @@
default

506
mods/plants_lib/init.lua Normal file
View File

@ -0,0 +1,506 @@
-- Plantlife library mod by Vanessa Ezekowitz
-- last revision, 2013-01-24
--
-- License: WTFPL
--
-- I got the temperature map idea from "hmmmm", values used for it came from
-- Splizard's snow mod.
--
-- Various settings - most of these probably won't need to be changed
plantslib = {}
plantslib.modpath = minetest.get_modpath("plants_lib")
plantslib.intllib_modpath = minetest.get_modpath("intllib")
local S
if plantslib.intllib_modpath then
dofile(plantslib.intllib_modpath.."/intllib.lua")
S = intllib.Getter(minetest.get_current_modname())
else
S = function ( s ) return s end
end
local DEBUG = false --... except if you want to spam the console with debugging info :-)
plantslib.plantlife_seed_diff = 329 -- needs to be global so other mods can see it
local perlin_octaves = 3
local perlin_persistence = 0.6
local perlin_scale = 100
local temperature_seeddiff = 112
local temperature_octaves = 3
local temperature_persistence = 0.5
local temperature_scale = 150
local humidity_seeddiff = 9130
local humidity_octaves = 3
local humidity_persistence = 0.5
local humidity_scale = 250
--PerlinNoise(seed, octaves, persistence, scale)
plantslib.perlin_temperature = PerlinNoise(temperature_seeddiff, temperature_octaves, temperature_persistence, temperature_scale)
plantslib.perlin_humidity = PerlinNoise(humidity_seeddiff, humidity_octaves, humidity_persistence, humidity_scale)
-- Local functions
local function dump_pos(pos)
return "{x="..pos.x..",y="..pos.y..",z="..pos.z.."}"
end
function plantslib:is_node_loaded(node_pos)
n = minetest.get_node_or_nil(node_pos)
if (not n) or (n.name == "ignore") then
return false
end
return true
end
function plantslib:dbg(msg)
if DEBUG then
print("[Plantlife] "..msg)
minetest.log("verbose", "[Plantlife] "..msg)
end
end
function plantslib:set_defaults(biome)
biome.seed_diff = biome.seed_diff or 0
biome.min_elevation = biome.min_elevation or -31000
biome.max_elevation = biome.max_elevation or 31000
biome.temp_min = biome.temp_min or 1
biome.temp_max = biome.temp_max or -1
biome.humidity_min = biome.humidity_min or 1
biome.humidity_max = biome.humidity_max or -1
biome.plantlife_limit = biome.plantlife_limit or 0.1
biome.near_nodes_vertical = biome.near_nodes_vertical or 1
-- specific to on-generate
biome.neighbors = biome.neighbors or biome.surface
biome.near_nodes_size = biome.near_nodes_size or 0
biome.near_nodes_count = biome.near_nodes_count or 1
biome.rarity = biome.rarity or 50
biome.max_count = biome.max_count or 5
if biome.check_air ~= false then biome.check_air = true end
-- specific to abm spawner
biome.seed_diff = biome.seed_diff or 0
biome.light_min = biome.light_min or 0
biome.light_max = biome.light_max or 15
biome.depth_max = biome.depth_max or 1
biome.facedir = biome.facedir or 0
end
-- Spawn plants using the map generator
function plantslib:register_generate_plant(biomedef, node_or_function_or_model)
plantslib:dbg("Registered mapgen spawner:")
plantslib:dbg(dump(biomedef))
minetest.register_on_generated(plantslib:search_for_surfaces(minp, maxp, biomedef, node_or_function_or_model))
end
function plantslib:search_for_surfaces(minp, maxp, biomedef, node_or_function_or_model)
return function(minp, maxp, blockseed)
local t1=os.clock()
local biome = biomedef
plantslib:set_defaults(biome)
plantslib:dbg("Started checking generated mapblock volume...")
local searchnodes = minetest.find_nodes_in_area(minp, maxp, biome.surface)
local in_biome_nodes = {}
local num_in_biome_nodes = 0
for i in ipairs(searchnodes) do
local pos = searchnodes[i]
local p_top = { x = pos.x, y = pos.y + 1, z = pos.z }
local perlin1 = minetest.get_perlin(biome.seed_diff, perlin_octaves, perlin_persistence, perlin_scale)
local noise1 = perlin1:get2d({x=p_top.x, y=p_top.z})
local noise2 = plantslib.perlin_temperature:get2d({x=p_top.x, y=p_top.z})
local noise3 = plantslib.perlin_humidity:get2d({x=p_top.x+150, y=p_top.z+50})
if (not biome.depth or minetest.get_node({ x = pos.x, y = pos.y-biome.depth-1, z = pos.z }).name ~= biome.surface)
and (not biome.check_air or (biome.check_air and minetest.get_node(p_top).name == "air"))
and pos.y >= biome.min_elevation
and pos.y <= biome.max_elevation
and noise1 > biome.plantlife_limit
and noise2 <= biome.temp_min
and noise2 >= biome.temp_max
and noise3 <= biome.humidity_min
and noise3 >= biome.humidity_max
and (not biome.ncount or table.getn(minetest.find_nodes_in_area({x=pos.x-1, y=pos.y, z=pos.z-1}, {x=pos.x+1, y=pos.y, z=pos.z+1}, biome.neighbors)) > biome.ncount)
and (not biome.near_nodes or table.getn(minetest.find_nodes_in_area({x=pos.x-biome.near_nodes_size, y=pos.y-biome.near_nodes_vertical, z=pos.z-biome.near_nodes_size}, {x=pos.x+biome.near_nodes_size, y=pos.y+biome.near_nodes_vertical, z=pos.z+biome.near_nodes_size}, biome.near_nodes)) >= biome.near_nodes_count)
and math.random(1,100) > biome.rarity
and (not biome.below_nodes or string.find(dump(biome.below_nodes), minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name) )
then
table.insert(in_biome_nodes, pos)
num_in_biome_nodes = num_in_biome_nodes + 1
end
end
plantslib:dbg("Found "..num_in_biome_nodes.." surface nodes of type(s) "..dump(biome.surface).." in 5x5x5 mapblock volume at {"..dump(minp)..":"..dump(maxp).."} to check.")
if num_in_biome_nodes > 0 then
plantslib:dbg("Calculated maximum of "..math.min(biome.max_count*3, num_in_biome_nodes).." nodes to be checked in that list.")
for i = 1, math.min(biome.max_count, num_in_biome_nodes) do
local tries = 0
local spawned = false
while tries < 2 and not spawned do
local pos = in_biome_nodes[math.random(1, num_in_biome_nodes)]
if biome.spawn_replace_node then
pos.y = pos.y-1
end
local p_top = { x = pos.x, y = pos.y + 1, z = pos.z }
if not (biome.avoid_nodes and biome.avoid_radius and minetest.find_node_near(p_top, biome.avoid_radius + math.random(-1.5,2), biome.avoid_nodes)) then
if biome.delete_above then
minetest.remove_node(p_top)
minetest.remove_node({x=p_top.x, y=p_top.y+1, z=p_top.z})
end
if biome.delete_above_surround then
minetest.remove_node({x=p_top.x-1, y=p_top.y, z=p_top.z})
minetest.remove_node({x=p_top.x+1, y=p_top.y, z=p_top.z})
minetest.remove_node({x=p_top.x, y=p_top.y, z=p_top.z-1})
minetest.remove_node({x=p_top.x, y=p_top.y, z=p_top.z+1})
minetest.remove_node({x=p_top.x-1, y=p_top.y+1, z=p_top.z})
minetest.remove_node({x=p_top.x+1, y=p_top.y+1, z=p_top.z})
minetest.remove_node({x=p_top.x, y=p_top.y+1, z=p_top.z-1})
minetest.remove_node({x=p_top.x, y=p_top.y+1, z=p_top.z+1})
end
if biome.spawn_replace_node then
minetest.remove_node(pos)
end
if type(node_or_function_or_model) == "table" then
plantslib:dbg("Spawn tree at {"..dump(pos).."}")
plantslib:generate_tree(pos, node_or_function_or_model)
elseif type(node_or_function_or_model) == "string" then
if not minetest.registered_nodes[node_or_function_or_model] then
plantslib:dbg("Call function: "..node_or_function_or_model.."("..dump_pos(pos)..")")
local t2=os.clock()
assert(loadstring(node_or_function_or_model.."("..dump_pos(pos)..")"))()
plantslib:dbg("Executed that function in ".. (os.clock()-t2)*1000 .."ms")
else
plantslib:dbg("Add node: "..node_or_function_or_model.." at ("..dump(p_top)..")")
minetest.add_node(p_top, { name = node_or_function_or_model })
end
end
spawned = true
else
tries = tries + 1
plantslib:dbg("No room to spawn object at {"..dump(pos).."} -- trying again elsewhere")
end
end
if tries == 2 then
plantslib:dbg("Unable to spawn that object. Giving up on it.")
end
end
end
plantslib:dbg("Evaluated/populated chunk in ".. (os.clock()-t1)*1000 .."ms")
end
end
-- The spawning ABM
function plantslib:spawn_on_surfaces(sd,sp,sr,sc,ss,sa)
local biome = {}
if type(sd) ~= "table" then
biome.spawn_delay = sd -- old api expects ABM interval param here.
biome.spawn_plants = {sp}
biome.avoid_radius = sr
biome.spawn_chance = sc
biome.spawn_surfaces = {ss}
biome.avoid_nodes = sa
else
biome = sd
end
plantslib:set_defaults(biome)
biome.spawn_plants_count = table.getn(biome.spawn_plants)
plantslib:dbg("Registered spawning ABM:")
plantslib:dbg(dump(biome))
plantslib:dbg("Number of trigger nodes in this ABM: "..biome.spawn_plants_count )
minetest.register_abm({
nodenames = biome.spawn_surfaces,
interval = biome.spawn_delay,
chance = biome.spawn_chance,
neighbors = biome.neighbors,
action = function(pos, node, active_object_count, active_object_count_wider)
local p_top = { x = pos.x, y = pos.y + 1, z = pos.z }
local n_top = minetest.get_node(p_top)
local perlin1 = minetest.get_perlin(biome.seed_diff, perlin_octaves, perlin_persistence, perlin_scale)
local noise1 = perlin1:get2d({x=p_top.x, y=p_top.z})
local noise2 = plantslib.perlin_temperature:get2d({x=p_top.x, y=p_top.z})
local noise3 = plantslib.perlin_humidity:get2d({x=p_top.x+150, y=p_top.z+50})
if noise1 > biome.plantlife_limit
and noise2 <= biome.temp_min
and noise2 >= biome.temp_max
and noise3 <= biome.humidity_min
and noise3 >= biome.humidity_max
and plantslib:is_node_loaded(p_top) then
local n_light = minetest.get_node_light(p_top, nil)
if not (biome.avoid_nodes and biome.avoid_radius and minetest.find_node_near(p_top, biome.avoid_radius + math.random(-1.5,2), biome.avoid_nodes))
and n_light >= biome.light_min
and n_light <= biome.light_max
and (not(biome.neighbors and biome.ncount) or table.getn(minetest.find_nodes_in_area({x=pos.x-1, y=pos.y, z=pos.z-1}, {x=pos.x+1, y=pos.y, z=pos.z+1}, biome.neighbors)) > biome.ncount )
and (not(biome.near_nodes and biome.near_nodes_count and biome.near_nodes_size) or table.getn(minetest.find_nodes_in_area({x=pos.x-biome.near_nodes_size, y=pos.y-biome.near_nodes_vertical, z=pos.z-biome.near_nodes_size}, {x=pos.x+biome.near_nodes_size, y=pos.y+biome.near_nodes_vertical, z=pos.z+biome.near_nodes_size}, biome.near_nodes)) >= biome.near_nodes_count)
and (not(biome.air_count and biome.air_size) or table.getn(minetest.find_nodes_in_area({x=p_top.x-biome.air_size, y=p_top.y, z=p_top.z-biome.air_size}, {x=p_top.x+biome.air_size, y=p_top.y, z=p_top.z+biome.air_size}, "air")) >= biome.air_count)
and pos.y >= biome.min_elevation
and pos.y <= biome.max_elevation
then
local walldir = plantslib:find_adjacent_wall(p_top, biome.verticals_list)
if biome.alt_wallnode and walldir then
if n_top.name == "air" then
plantslib:dbg("Spawn: "..biome.alt_wallnode.." on top of ("..dump(pos)..") against wall "..walldir)
minetest.add_node(p_top, { name = biome.alt_wallnode, param2 = walldir })
end
else
local currentsurface = minetest.get_node(pos).name
if currentsurface ~= "default:water_source"
or (currentsurface == "default:water_source" and table.getn(minetest.find_nodes_in_area({x=pos.x, y=pos.y-biome.depth_max-1, z=pos.z}, {x=pos.x, y=pos.y, z=pos.z}, {"default:dirt", "default:dirt_with_grass", "default:sand"})) > 0 )
then
local rnd = math.random(1, biome.spawn_plants_count)
local plant_to_spawn = biome.spawn_plants[rnd]
plantslib:dbg("Chose entry number "..rnd.." of "..biome.spawn_plants_count)
local fdir = biome.facedir
if biome.random_facedir then
fdir = math.random(biome.random_facedir[1],biome.random_facedir[2])
plantslib:dbg("Gave it a random facedir: "..fdir)
end
if type(spawn_plants) == "string" then
plantslib:dbg("Call function: "..spawn_plants.."("..dump_pos(pos)..")")
assert(loadstring(spawn_plants.."("..dump_pos(pos)..")"))()
elseif not biome.spawn_on_side and not biome.spawn_on_bottom and not biome.spawn_replace_node then
if n_top.name == "air" then
plantslib:dbg("Spawn: "..plant_to_spawn.." on top of ("..dump(pos).."); facedir="..fdir)
minetest.add_node(p_top, { name = plant_to_spawn, param2 = fdir })
end
elseif biome.spawn_replace_node then
plantslib:dbg("Spawn: "..plant_to_spawn.." to replace "..minetest.get_node(pos).name.." at ("..dump(pos)..")")
minetest.add_node(pos, { name = plant_to_spawn, param2 = fdir })
elseif biome.spawn_on_side then
local onside = plantslib:find_open_side(pos)
if onside then
plantslib:dbg("Spawn: "..plant_to_spawn.." at side of ("..dump(pos).."), facedir "..onside.facedir.."")
minetest.add_node(onside.newpos, { name = plant_to_spawn, param2 = onside.facedir })
end
elseif biome.spawn_on_bottom then
if minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name == "air" then
plantslib:dbg("Spawn: "..plant_to_spawn.." on bottom of ("..dump(pos)..")")
minetest.add_node({x=pos.x, y=pos.y-1, z=pos.z}, { name = plant_to_spawn, param2 = fdir} )
end
end
end
end
end
end
end
})
end
-- The growing ABM
function plantslib:grow_plants(opts)
local options = opts
options.height_limit = options.height_limit or 5
options.ground_nodes = options.ground_nodes or { "default:dirt_with_grass" }
options.grow_nodes = options.grow_nodes or { "default:dirt_with_grass" }
options.seed_diff = options.seed_diff or 0
plantslib:dbg("Registered growing ABM:")
plantslib:dbg(dump(options))
minetest.register_abm({
nodenames = { options.grow_plant },
interval = options.grow_delay,
chance = options.grow_chance,
action = function(pos, node, active_object_count, active_object_count_wider)
local p_top = {x=pos.x, y=pos.y+1, z=pos.z}
local p_bot = {x=pos.x, y=pos.y-1, z=pos.z}
local n_top = minetest.get_node(p_top)
local n_bot = minetest.get_node(p_bot)
local root_node = minetest.get_node({x=pos.x, y=pos.y-options.height_limit, z=pos.z})
local walldir = nil
if options.need_wall and options.verticals_list then
walldir = plantslib:find_adjacent_wall(p_top, options.verticals_list)
end
if n_top.name == "air" and (not options.need_wall or (options.need_wall and walldir))
then
-- corner case for changing short junglegrass
-- to dry shrub in desert
if n_bot.name == options.dry_early_node and options.grow_plant == "junglegrass:short" then
plantslib:dbg("Die: "..options.grow_plant.." becomes default:dry_shrub at ("..dump(pos)..")")
minetest.add_node(pos, { name = "default:dry_shrub" })
elseif options.grow_vertically and walldir then
if plantslib:search_downward(pos, options.height_limit, options.ground_nodes) then
plantslib:dbg("Grow "..options.grow_plant.." vertically to "..dump(p_top))
minetest.add_node(p_top, { name = options.grow_plant, param2 = walldir})
end
elseif not options.grow_result and not options.grow_function then
plantslib:dbg("Die: "..options.grow_plant.." at ("..dump(pos)..")")
minetest.remove_node(pos)
else
plantslib:replace_object(pos, options.grow_result, options.grow_function, options.facedir, options.seed_diff)
end
end
end
})
end
-- Function to decide how to replace a plant - either grow it, replace it with
-- a tree, run a function, or die with an error.
function plantslib:replace_object(pos, replacement, grow_function, walldir, seeddiff)
local growtype = type(grow_function)
plantslib:dbg("replace_object called, growtype="..dump(grow_function))
if growtype == "table" then
plantslib:dbg("Grow: spawn tree at "..dump(pos))
minetest.remove_node(pos)
plantslib:grow_tree(pos, grow_function)
return
elseif growtype == "string" then
local perlin1 = minetest.get_perlin(seeddiff, perlin_octaves, perlin_persistence, perlin_scale)
local noise1 = perlin1:get2d({x=pos.x, y=pos.z})
local noise2 = plantslib.perlin_temperature:get2d({x=pos.x, y=pos.z})
plantslib:dbg("Grow: call function "..grow_function.."("..dump_pos(pos)..","..noise1..","..noise2..","..dump(walldir)..")")
assert(loadstring(grow_function.."("..dump_pos(pos)..","..noise1..","..noise2..","..dump(walldir)..")"))()
return
elseif growtype == "nil" then
plantslib:dbg("Grow: place "..replacement.." at ("..dump(pos)..") on wall "..dump(walldir))
minetest.add_node(pos, { name = replacement, param2 = walldir})
return
elseif growtype ~= "nil" and growtype ~= "string" and growtype ~= "table" then
error("Invalid grow function "..dump(grow_function).." used on object at ("..dump(pos)..")")
end
end
-- function to decide if a node has a wall that's in verticals_list{}
-- returns wall direction of valid node, or nil if invalid.
function plantslib:find_adjacent_wall(pos, verticals)
local verts = dump(verticals)
if string.find(verts, minetest.get_node({ x=pos.x-1, y=pos.y, z=pos.z }).name) then return 3 end
if string.find(verts, minetest.get_node({ x=pos.x+1, y=pos.y, z=pos.z }).name) then return 2 end
if string.find(verts, minetest.get_node({ x=pos.x , y=pos.y, z=pos.z-1 }).name) then return 5 end
if string.find(verts, minetest.get_node({ x=pos.x , y=pos.y, z=pos.z+1 }).name) then return 4 end
return nil
end
-- Function to search downward from the given position, looking for the first
-- node that matches the ground table. Returns the new position, or nil if
-- height limit is exceeded before finding it.
function plantslib:search_downward(pos, heightlimit, ground)
for i = 0, heightlimit do
if string.find(dump(ground), minetest.get_node({x=pos.x, y=pos.y-i, z = pos.z}).name) then
return {x=pos.x, y=pos.y-i, z = pos.z}
end
end
return false
end
function plantslib:find_open_side(pos)
if minetest.get_node({ x=pos.x-1, y=pos.y, z=pos.z }).name == "air" then
return {newpos = { x=pos.x-1, y=pos.y, z=pos.z }, facedir = 2}
end
if minetest.get_node({ x=pos.x+1, y=pos.y, z=pos.z }).name == "air" then
return {newpos = { x=pos.x+1, y=pos.y, z=pos.z }, facedir = 3}
end
if minetest.get_node({ x=pos.x, y=pos.y, z=pos.z-1 }).name == "air" then
return {newpos = { x=pos.x, y=pos.y, z=pos.z-1 }, facedir = 4}
end
if minetest.get_node({ x=pos.x, y=pos.y, z=pos.z+1 }).name == "air" then
return {newpos = { x=pos.x, y=pos.y, z=pos.z+1 }, facedir = 5}
end
return nil
end
-- spawn_tree() on generate is routed through here so that other mods can hook
-- into it.
function plantslib:generate_tree(pos, node_or_function_or_model)
local t=os.clock()
minetest.spawn_tree(pos, node_or_function_or_model)
plantslib:dbg("Generated one tree in ".. (os.clock()-t)*1000 .."ms")
end
-- and this one's for the call used in the growing code
function plantslib:grow_tree(pos, node_or_function_or_model)
local t=os.clock()
minetest.spawn_tree(pos, node_or_function_or_model)
plantslib:dbg("Generated one tree in ".. (os.clock()-t)*1000 .."ms")
end
-- check if a node is owned before allowing manual placement of a node
-- (used by flowers_plus)
function plantslib:node_is_owned(pos, placer)
local ownername = false
if type(IsPlayerNodeOwner) == "function" then -- node_ownership mod
if HasOwner(pos, placer) then -- returns true if the node is owned
if not IsPlayerNodeOwner(pos, placer:get_player_name()) then
if type(getLastOwner) == "function" then -- ...is an old version
ownername = getLastOwner(pos)
elseif type(GetNodeOwnerName) == "function" then -- ...is a recent version
ownername = GetNodeOwnerName(pos)
else
ownername = S("someone")
end
end
end
elseif type(isprotect)=="function" then -- glomie's protection mod
if not isprotect(5, pos, placer) then
ownername = S("someone")
end
elseif type(protector)=="table" and type(protector.can_dig)=="function" then -- Zeg9's protection mod
if not protector.can_dig(5, pos, placer) then
ownername = S("someone")
end
end
if ownername ~= false then
minetest.chat_send_player( placer:get_player_name(), S("Sorry, %s owns that spot."):format(ownername) )
return true
else
return false
end
end
-- Check for infinite stacks
if minetest.get_modpath("unified_inventory") or not minetest.setting_getbool("creative_mode") then
plantslib.expect_infinite_stacks = false
else
plantslib.expect_infinite_stacks = true
end
-- read a field from a node's definition
function plantslib:get_nodedef_field(nodename, fieldname)
if not minetest.registered_nodes[nodename] then
return nil
end
return minetest.registered_nodes[nodename][fieldname]
end
print("[Plantlife Library] Loaded")

View File

@ -0,0 +1 @@
plants_lib

99
mods/poisonivy/init.lua Normal file
View File

@ -0,0 +1,99 @@
-- This file supplies poison ivy for the plantlife modpack
-- Last revision: 2013-01-24
local SPAWN_DELAY = 1000
local SPAWN_CHANCE = 200
local GROW_DELAY = 500
local GROW_CHANCE = 30
local poisonivy_seed_diff = 339
local walls_list = {
"default:dirt",
"default:dirt_with_grass",
"default:stone",
"default:cobble",
"default:mossycobble",
"default:brick",
"default:tree",
"default:jungletree",
"default:stone_with_coal",
"default:stone_with_iron"
},
minetest.register_node('poisonivy:seedling', {
description = "Poison ivy (seedling)",
drawtype = 'plantlike',
tile_images = { 'poisonivy_seedling.png' },
inventory_image = 'poisonivy_seedling.png',
wield_image = 'poisonivy_seedling.png',
sunlight_propagates = true,
paramtype = 'light',
walkable = false,
groups = { snappy = 3, poisonivy=1, flora_block=1 },
sounds = default.node_sound_leaves_defaults(),
buildable_to = true,
})
minetest.register_node('poisonivy:sproutling', {
description = "Poison ivy (sproutling)",
drawtype = 'plantlike',
tile_images = { 'poisonivy_sproutling.png' },
inventory_image = 'poisonivy_sproutling.png',
wield_image = 'poisonivy_sproutling.png',
sunlight_propagates = true,
paramtype = 'light',
walkable = false,
groups = { snappy = 3, poisonivy=1, flora_block=1 },
sounds = default.node_sound_leaves_defaults(),
buildable_to = true,
})
minetest.register_node('poisonivy:climbing', {
description = "Poison ivy (climbing plant)",
drawtype = 'signlike',
tile_images = { 'poisonivy_climbing.png' },
inventory_image = 'poisonivy_climbing.png',
wield_image = 'poisonivy_climbing.png',
sunlight_propagates = true,
paramtype = 'light',
paramtype2 = 'wallmounted',
walkable = false,
groups = { snappy = 3, poisonivy=1, flora_block=1 },
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "wallmounted",
--wall_side = = <default>
},
buildable_to = true,
})
plantslib:spawn_on_surfaces({
spawn_delay = SPAWN_DELAY,
spawn_plants = {"poisonivy:seedling"},
avoid_radius = 10,
spawn_chance = SPAWN_CHANCE/10,
spawn_surfaces = {"default:dirt_with_grass"},
avoid_nodes = {"group:poisonivy", "group:flower", "group:flora"},
seed_diff = poisonivy_seed_diff,
light_min = 7,
alt_wallnode = "poisonivy:climbing",
verticals_list = walls_list
})
plantslib:grow_plants({
grow_delay = SPAWN_DELAY,
grow_chance = GROW_CHANCE,
grow_plant = "poisonivy:seedling",
grow_result = "poisonivy:sproutling",
grow_nodes = {"default:dirt_with_grass"}
})
plantslib:grow_plants({
grow_delay = GROW_DELAY,
grow_chance = GROW_CHANCE*2,
grow_plant = "poisonivy:climbing",
need_wall = true,
grow_vertically = true,
verticals_list = walls_list,
ground_nodes = {"default:dirt_with_grass"}
})
print("[Poison Ivy] Loaded.")

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B