Add crops mod

master
elite 2017-07-02 15:29:28 -04:00
parent 99e9793916
commit b178cbc565
105 changed files with 3135 additions and 0 deletions

View File

@ -0,0 +1,15 @@
unused_args = false
allow_defined_top = true
read_globals = {
"DIR_DELIM",
"minetest", "core",
"dump",
"vector", "nodeupdate",
"VoxelManip", "VoxelArea",
"PseudoRandom", "ItemStack",
"intllib",
"default",
table = { fields = { "copy", "getn" } }
}

38
worldmods/crops/LICENSE Normal file
View File

@ -0,0 +1,38 @@
Crops - a minetest mod that adds more farming crops
See spdx.org/licenses to see what the License Identifiers used below mean.
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~
All source code (lua):
(C) Auke Kok <sofar@foo-projects.org>
LGPL-2.0+
All textures, models:
(C) Auke Kok <sofar@foo-projects.org>
CC-BY-SA-3.0
Translations:
- de.po
(C) 2017 LNJ <git@lnj.li>
LGPL-2.0+
Sounds:
- crops_watercan_splash*
http://freesound.org/people/junggle/sounds/27361/
http://profiles.google.com/jun66le
CC-BY-3.0
- crops_watercan_entering.ogg
http://freesound.org/people/Quistard/sounds/166824/
CC-BY-3.0
- crops_flies.ogg
http://www.freesound.org/people/galeku/sounds/46938/
CC0-1.0
- crops_watercan_watering.ogg
http://www.freesound.org/people/Eakoontz/sounds/151736/
CC0-1.0
* Sounds edited with audacity
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~

10
worldmods/crops/Makefile Normal file
View File

@ -0,0 +1,10 @@
PROJECT = crops
all: release
release:
VERSION=`git describe --tags`; \
git archive --format zip --output "$(PROJECT)-$${VERSION}.zip" --prefix=$(PROJECT)/ master
poupdate:
../intllib/tools/xgettext.sh *.lua

View File

@ -0,0 +1,75 @@
--[[
Copyright (C) 2015 - Auke Kok <sofar@foo-projects.org>
"crops" is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1
of the license, or (at your option) any later version.
--]]
--
-- cooking recipes that don't go directly with any of the
-- crops in this mod - either these combine them in new
-- ways or use other items
--
-- Intllib
local S = crops.intllib
minetest.register_craftitem("crops:unbaked_clay_bowl", {
description = S("Unbaked clay bowl"),
inventory_image = "crops_unbaked_clay_bowl.png",
})
minetest.register_craft({
output = "crops:unbaked_clay_bowl",
recipe = {
{ "", "", "" },
{ "default:clay_lump", "", "default:clay_lump" },
{ "", "default:clay_lump", "" }
}
})
minetest.register_craftitem("crops:clay_bowl", {
description = S("Clay bowl"),
inventory_image = "crops_clay_bowl.png",
groups = { food_bowl=1 }
})
minetest.register_craft({
type = "cooking",
output = "crops:clay_bowl",
recipe = "crops:unbaked_clay_bowl"
})
minetest.register_craftitem("crops:vegetable_stew", {
description = S("Bowl of vegetable stew"),
inventory_image = "crops_bowl_vegetable_stew.png",
groups = { eatable=1 },
on_use = minetest.item_eat(8, "crops:clay_bowl"),
})
minetest.register_craft({
type = "cooking",
output = "crops:vegetable_stew",
recipe = "crops:uncooked_vegetable_stew"
})
minetest.register_craftitem("crops:uncooked_vegetable_stew", {
description = S("Bowl of uncooked vegetable stew"),
inventory_image = "crops_bowl_uncooked_vegetable_stew.png",
groups = { eatable=1 },
on_use = minetest.item_eat(2, "crops:clay_bowl")
})
minetest.register_craft({
output = "crops:uncooked_vegetable_stew",
recipe = {
{ "", "", "" },
{ "crops:green_bean", "crops:potato", "crops:tomato" },
{ "", "group:food_bowl", "" }
}
})

347
worldmods/crops/corn.lua Normal file
View File

@ -0,0 +1,347 @@
--[[
Copyright (C) 2015 - Auke Kok <sofar@foo-projects.org>
"crops" is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1
of the license, or (at your option) any later version.
--]]
-- Intllib
local S = crops.intllib
minetest.register_node("crops:corn", {
description = S("Corn"),
inventory_image = "crops_corn.png",
wield_image = "crops_corn.png",
tiles = { "crops_corn_base_seed.png" },
drawtype = "plantlike",
paramtype2 = "meshoptions",
waving = 1,
sunlight_propagates = true,
use_texture_alpha = true,
walkable = true,
paramtype = "light",
node_placement_prediction = "crops:corn_base_seed",
groups = { snappy=3,flammable=3,flora=1,attached_node=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
on_place = function(itemstack, placer, pointed_thing)
local under = minetest.get_node(pointed_thing.under)
if minetest.get_item_group(under.name, "soil") <= 1 then
return
end
crops.plant(pointed_thing.above, {name="crops:corn_base_seed", param2 = 3})
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end
})
minetest.register_craftitem("crops:corn_cob", {
description = S("Corn Cob"),
inventory_image = "crops_corn_cob.png",
})
minetest.register_craft({
type = "shapeless",
output = "crops:corn",
recipe = { "crops:corn_cob" }
})
minetest.register_craftitem("crops:corn_on_the_cob", {
description = S("Corn on the Cob"),
inventory_image = "crops_corn_on_the_cob.png",
on_use = minetest.item_eat(1)
})
minetest.register_craft({
type = "cooking",
output = "crops:corn_on_the_cob",
recipe = "crops:corn_cob"
})
minetest.register_node("crops:corn_base_seed", {
visual = "mesh",
description = S("Corn plant"),
drawtype = "plantlike",
paramtype2 = "meshoptions",
waving = 1,
tiles = { "crops_corn_base_seed.png" },
use_texture_alpha = true,
walkable = false,
sunlight_propagates = true,
paramtype = "light",
groups = { snappy=3,flammable=3,flora=1,attached_node=1,not_in_creative_inventory=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -0.3, 0.5}
}
})
minetest.register_abm({
nodenames = { "crops:corn_base_seed" },
neighbors = { "group:soil" },
interval = crops.settings.interval,
chance = crops.settings.chance,
action = function(pos, node, active_object_count, active_object_count_wider)
if not crops.can_grow(pos) then
return
end
minetest.swap_node(pos, { name = "crops:corn_base_1", param2 = 3 })
end
})
minetest.register_node("crops:corn_base_1", {
visual = "mesh",
description = S("Corn plant"),
drawtype = "plantlike",
paramtype2 = "meshoptions",
tiles = { "crops_corn_base_1.png" },
waving = 1,
use_texture_alpha = true,
walkable = false,
sunlight_propagates = true,
paramtype = "light",
groups = { snappy=3,flammable=3,flora=1,attached_node=1,not_in_creative_inventory=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_abm({
nodenames = { "crops:corn_base_1" },
neighbors = { "group:soil" },
interval = crops.settings.interval,
chance = crops.settings.chance,
action = function(pos, node, active_object_count, active_object_count_wider)
if not crops.can_grow(pos) then
return
end
if not minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z}).name == "air" then
return
end
minetest.swap_node(pos, { name = "crops:corn_base_2", param2 = 3 })
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
minetest.set_node(above , { name = "crops:corn_top_1", param2 = 3 })
local meta = minetest.get_meta(above)
meta:set_int("crops_top_half", 1)
end
})
minetest.register_node("crops:corn_base_2", {
description = S("Corn plant"),
drawtype = "plantlike",
paramtype2 = "meshoptions",
tiles = { "crops_corn_base_2.png" },
use_texture_alpha = true,
walkable = false,
sunlight_propagates = true,
paramtype = "light",
groups = { snappy=3,flammable=3,flora=1,attached_node=1,not_in_creative_inventory=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
on_dig = function(pos, node, digger)
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
if minetest.get_node(above).name == "crops:corn_top_1" or minetest.get_node(above).name == "crops:corn_top_2" then
minetest.remove_node(above)
minetest.remove_node(pos)
return
end
if not minetest.get_node(above).name == "crops:corn_top_3" then
minetest.remove_node(pos)
end
local meta = minetest.get_meta(pos)
local damage = meta:get_int("crops_damage")
local drops = {}
-- 0 - 2-4
-- 50 - 2-3
-- 100 - 1-1
for i = 1,math.random(2 - (damage / 100), 4 - (3 * (damage / 100))) do
table.insert(drops, ('crops:corn_cob'))
end
minetest.set_node(pos, { name = "crops:corn_base_3", param2 = 3 })
minetest.set_node(above, { name = "crops:corn_top_4", param2 = 3 })
core.handle_node_drops(above, drops, digger)
end
})
minetest.register_node("crops:corn_base_3", {
description = S("Corn plant"),
drawtype = "plantlike",
paramtype2 = "meshoptions",
tiles = { "crops_corn_base_3.png" },
use_texture_alpha = true,
walkable = false,
sunlight_propagates = true,
paramtype = "light",
groups = { snappy=3,flammable=3,flora=1,attached_node=1,not_in_creative_inventory=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
on_dig = function(pos, node, digger)
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
if minetest.get_node(above).name == "crops:corn_top_4" then
minetest.remove_node(above)
end
minetest.remove_node(pos)
end
})
minetest.register_node("crops:corn_top_1", {
description = S("Corn plant"),
drawtype = "plantlike",
paramtype2 = "meshoptions",
tiles = { "crops_corn_base_1.png" },
waving = 1,
use_texture_alpha = true,
walkable = false,
sunlight_propagates = true,
paramtype = "light",
groups = { snappy=3,flammable=3,flora=1,not_in_creative_inventory=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
on_dig = function(pos, node, digger)
local below = {x = pos.x, y = pos.y - 1, z = pos.z}
if not minetest.get_node(below).name == "crops:base_2" then
return
end
minetest.remove_node(below)
minetest.remove_node(pos)
end
})
minetest.register_abm({
nodenames = { "crops:corn_top_1" },
neighbors = { "crops:corn_base_2" },
interval = crops.settings.interval,
chance = crops.settings.chance,
action = function(pos, node, active_object_count, active_object_count_wider)
if minetest.get_node_light(pos, nil) < crops.settings.light then
return
end
minetest.swap_node(pos, { name = "crops:corn_top_2", param2 = 3 })
end
})
minetest.register_node("crops:corn_top_2", {
description = S("Corn plant"),
drawtype = "plantlike",
paramtype2 = "meshoptions",
tiles = { "crops_corn_top_1.png" },
waving = 1,
use_texture_alpha = true,
walkable = false,
sunlight_propagates = true,
paramtype = "light",
groups = { snappy=3,flammable=3,flora=1,not_in_creative_inventory=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
on_dig = function(pos, node, digger)
local below = {x = pos.x, y = pos.y - 1, z = pos.z}
if not minetest.get_node(below).name == "crops:base_2" then
return
end
minetest.remove_node(below)
minetest.remove_node(pos)
end
})
minetest.register_abm({
nodenames = { "crops:corn_top_2" },
neighbors = { "crops:corn_base_2" },
interval = crops.settings.interval,
chance = crops.settings.chance,
action = function(pos, node, active_object_count, active_object_count_wider)
-- we don't call crops.grow here otherwise there would be 2 abm's hitting
-- this stack, and dmg needs to be applied to the bottom part
if minetest.get_node_light(pos, nil) < crops.settings.light then
return
end
minetest.swap_node(pos, { name = "crops:corn_top_3", param2 = 3 })
end
})
minetest.register_node("crops:corn_top_3", {
description = S("Corn plant"),
drawtype = "plantlike",
paramtype2 = "meshoptions",
tiles = { "crops_corn_top_2.png" },
waving = 1,
use_texture_alpha = true,
walkable = false,
sunlight_propagates = true,
paramtype = "light",
groups = { snappy=3,flammable=3,flora=1,not_in_creative_inventory=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
on_dig = function(pos, node, digger)
local below = { x = pos.x, y = pos.y - 1, z = pos.z }
local meta = minetest.get_meta(below)
local damage = meta:get_int("crops_damage")
local drops = {}
-- 0 - 2-4
-- 50 - 2-3
-- 100 - 1-1
for i = 1,math.random(2 - (damage / 100), 4 - (3 * (damage / 100))) do
table.insert(drops, ('crops:corn_cob'))
end
crops.die(below)
core.handle_node_drops(pos, drops, digger)
end
})
minetest.register_node("crops:corn_top_4", {
description = S("Corn plant"),
drawtype = "plantlike",
paramtype2 = "meshoptions",
tiles = { "crops_corn_top_3.png" },
waving = 1,
use_texture_alpha = true,
walkable = false,
sunlight_propagates = true,
paramtype = "light",
groups = { snappy=3,flammable=3,flora=1,not_in_creative_inventory=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
on_dig = function(pos, node, digger)
local below = {x = pos.x, y = pos.y - 1, z = pos.z}
if minetest.get_node(below).name == "crops:corn_base_3" then
minetest.remove_node(below)
end
minetest.remove_node(pos)
end
})
crops.corn_die = function(pos)
minetest.set_node(pos, { name = "crops:corn_base_3", param2 = 3 })
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
minetest.set_node(above, { name = "crops:corn_top_4", param2 = 3 })
end
local properties = {
die = crops.corn_die,
waterstart = 40,
wateruse = 1,
night = 5,
soak = 60,
soak_damage = 75,
wither = 10,
wither_damage = 5,
doublesize = true,
}
crops.register({ name = "crops:corn_base_seed", properties = properties })
crops.register({ name = "crops:corn_base_1", properties = properties })
crops.register({ name = "crops:corn_base_2", properties = properties })
crops.register({ name = "crops:corn_base_3", properties = properties })

View File

@ -0,0 +1,10 @@
--
-- crops_settings.txt
--
-- These are the default difficulty settings for the crops mod. You can uncomment
-- the "easy" or "difficult" settings if you wish, or come up with your own values.
--
-- Valid values are "easy", "normal", and "difficult"
crops.difficulty = "normal"

View File

@ -0,0 +1,3 @@
default
farming
intllib?

View File

@ -0,0 +1,5 @@
This mod expands the basic set of farming-related crops that minetest_game offers. It adds melons, potatoes, tomatoes, green beans and corn. The mod also implements plant humidity - you will have to water plants to make sure they're not dried out, or make sure they don't get over-watered.
Mod specific settings can be changed in the "crops_settings.txt" file in the world folder.
For more information, go to: http://goo.gl/wf0XLh

385
worldmods/crops/init.lua Normal file
View File

@ -0,0 +1,385 @@
--[[
Copyright (C) 2015 - Auke Kok <sofar@foo-projects.org>
"crops" is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1
of the license, or (at your option) any later version.
--]]
crops = {}
crops.plants = {}
crops.settings = {}
local settings = {}
settings.easy = {
chance = 4,
interval = 30,
light = 8,
watercan = 25,
watercan_max = 90,
watercan_uses = 20,
damage_chance = 8,
damage_interval = 30,
damage_tick_min = 0,
damage_tick_max = 1,
damage_max = 25,
hydration = false,
}
settings.normal = {
chance = 8,
interval = 30,
light = 10,
watercan = 25,
watercan_max = 90,
watercan_uses = 20,
damage_chance = 8,
damage_interval = 30,
damage_tick_min = 0,
damage_tick_max = 5,
damage_max = 50,
hydration = true,
}
settings.difficult = {
chance = 16,
interval = 30,
light = 13,
watercan = 25,
watercan_max = 100,
watercan_uses = 20,
damage_chance = 4,
damage_interval = 30,
damage_tick_min = 3,
damage_tick_max = 7,
damage_max = 100,
hydration = true,
}
local worldpath = minetest.get_worldpath()
local modpath = minetest.get_modpath(minetest.get_current_modname())
-- Load support for intllib.
local S, _ = dofile(modpath .. "/intllib.lua")
crops.intllib = S
dofile(modpath .. "/crops_settings.txt")
if io.open(worldpath .. "/crops_settings.txt", "r") == nil then
io.input(modpath .. "/crops_settings.txt")
io.output(worldpath .. "/crops_settings.txt")
local size = 4096
while true do
local buf = io.read(size)
if not buf then
io.close()
break
end
io.write(buf)
end
else
dofile(worldpath .. "/crops_settings.txt")
end
if not crops.difficulty then
crops.difficulty = "normal"
minetest.log("error", "[crops] "..S("Defaulting to \"normal\" difficulty settings"))
end
crops.settings = settings[crops.difficulty]
if not crops.settings then
minetest.log("error", "[crops] "..S("Defaulting to \"normal\" difficulty settings"))
crops.settings = settings.normal
end
if crops.settings.hydration then
minetest.log("action", "[crops] "..S("Hydration and dehydration mechanics are enabled."))
end
local find_plant = function(node)
for i = 1,table.getn(crops.plants) do
if crops.plants[i].name == node.name then
return crops.plants[i]
end
end
minetest.log("error", "[crops] "..S("Unable to find plant \"@1\" in crops table", node.name))
return nil
end
crops.register = function(plantdef)
table.insert(crops.plants, plantdef)
end
crops.plant = function(pos, node)
minetest.set_node(pos, node)
local meta = minetest.get_meta(pos)
local plant = find_plant(node)
meta:set_int("crops_water", math.max(plant.properties.waterstart, 1))
meta:set_int("crops_damage", 0)
end
crops.can_grow = function(pos)
if minetest.get_node_light(pos) < crops.settings.light then
return false
end
local node = minetest.get_node(pos)
local plant = find_plant(node)
if not plant then
return false
end
local meta = minetest.get_meta(pos)
if crops.settings.hydration then
local water = meta:get_int("crops_water")
if water < plant.properties.wither or water > plant.properties.soak then
if math.random(0,1) == 0 then
return false
end
end
-- growing costs water!
meta:set_int("crops_water", math.max(1, water - 10))
end
-- damaged plants are less likely to grow
local damage = meta:get_int("crops_damage")
if not damage == 0 then
if math.random(math.min(50, damage), 100) > 75 then
return false
end
end
-- allow the plant to grow
return true
end
crops.particles = function(pos, flag)
if flag == 0 then
-- wither (0)
minetest.add_particlespawner({
amount = 1 * crops.settings.interval,
time = crops.settings.interval,
minpos = { x = pos.x - 0.4, y = pos.y - 0.4, z = pos.z - 0.4 },
maxpos = { x = pos.x + 0.4, y = pos.y + 0.4, z = pos.z + 0.4 },
minvel = { x = 0, y = 0.2, z = 0 },
maxvel = { x = 0, y = 0.4, z = 0 },
minacc = { x = 0, y = 0, z = 0 },
maxacc = { x = 0, y = 0.2, z = 0 },
minexptime = 3,
maxexptime = 5,
minsize = 1,
maxsize = 2,
collisiondetection = false,
texture = "crops_wither.png",
vertical = true,
})
elseif flag == 1 then
-- soak (1)
minetest.add_particlespawner({
amount = 8 * crops.settings.interval,
time = crops.settings.interval,
minpos = { x = pos.x - 0.4, y = pos.y - 0.4, z = pos.z - 0.4 },
maxpos = { x = pos.x + 0.4, y = pos.y - 0.4, z = pos.z + 0.4 },
minvel = { x = -0.04, y = 0, z = -0.04 },
maxvel = { x = 0.04, y = 0, z = 0.04 },
minacc = { x = 0, y = 0, z = 0 },
maxacc = { x = 0, y = 0, z = 0 },
minexptime = 3,
maxexptime = 5,
minsize = 1,
maxsize = 2,
collisiondetection = false,
texture = "crops_soak.png",
vertical = false,
})
elseif flag == 2 then
-- watering (2)
minetest.add_particlespawner({
amount = 30,
time = 3,
minpos = { x = pos.x - 0.4, y = pos.y - 0.4, z = pos.z - 0.4 },
maxpos = { x = pos.x + 0.4, y = pos.y + 0.4, z = pos.z + 0.4 },
minvel = { x = 0, y = 0.0, z = 0 },
maxvel = { x = 0, y = 0.0, z = 0 },
minacc = { x = 0, y = -9.81, z = 0 },
maxacc = { x = 0, y = -9.81, z = 0 },
minexptime = 2,
maxexptime = 2,
minsize = 1,
maxsize = 3,
collisiondetection = false,
texture = "crops_watering.png",
vertical = true,
})
else
-- withered/rotting (3)
minetest.add_particlespawner({
amount = 20,
time = 30,
minpos = { x = pos.x + 0.3, y = pos.y - 0.5, z = pos.z - 0.5 },
maxpos = { x = pos.x + 0.5, y = pos.y + 0.5, z = pos.z + 0.5 },
minvel = { x = -0.6, y = -0.1, z = -0.2 },
maxvel = { x = -0.4, y = 0.1, z = 0.2 },
minacc = { x = 0.4, y = 0, z = -0.1 },
maxacc = { x = 0.5, y = 0, z = 0.1 },
minexptime = 2,
maxexptime = 4,
minsize = 1,
maxsize = 1,
collisiondetection = false,
texture = "crops_flies.png",
vertical = true,
})
minetest.add_particlespawner({
amount = 20,
time = 30,
minpos = { x = pos.x - 0.3, y = pos.y - 0.5, z = pos.z - 0.5 },
maxpos = { x = pos.x - 0.5, y = pos.y + 0.5, z = pos.z + 0.5 },
minvel = { x = 0.6, y = -0.1, z = -0.2 },
maxvel = { x = 0.4, y = 0.1, z = 0.2 },
minacc = { x = -0.4, y = 0, z = -0.1 },
maxacc = { x = -0.5, y = 0, z = 0.1 },
minexptime = 2,
maxexptime = 4,
minsize = 1,
maxsize = 1,
collisiondetection = false,
texture = "crops_flies.png",
vertical = true,
})
minetest.add_particlespawner({
amount = 20,
time = 30,
minpos = { x = pos.x - 0.5, y = pos.y - 0.5, z = pos.z + 0.3 },
maxpos = { x = pos.x + 0.5, y = pos.y + 0.5, z = pos.z + 0.5 },
minvel = { z = -0.6, y = -0.1, x = -0.2 },
maxvel = { z = -0.4, y = 0.1, x = 0.2 },
minacc = { z = 0.4, y = 0, x = -0.1 },
maxacc = { z = 0.5, y = 0, x = 0.1 },
minexptime = 2,
maxexptime = 4,
minsize = 1,
maxsize = 1,
collisiondetection = false,
texture = "crops_flies.png",
vertical = true,
})
minetest.add_particlespawner({
amount = 20,
time = 30,
minpos = { x = pos.x - 0.5, y = pos.y - 0.5, z = pos.z - 0.3 },
maxpos = { x = pos.x + 0.5, y = pos.y + 0.5, z = pos.z - 0.5 },
minvel = { z = 0.6, y = -0.1, x = -0.2 },
maxvel = { z = 0.4, y = 0.1, x = 0.2 },
minacc = { z = -0.4, y = 0, x = -0.1 },
maxacc = { z = -0.5, y = 0, x = 0.1 },
minexptime = 2,
maxexptime = 4,
minsize = 1,
maxsize = 1,
collisiondetection = false,
texture = "crops_flies.png",
vertical = true,
})
end
end
crops.die = function(pos)
crops.particles(pos, 3)
local node = minetest.get_node(pos)
local plant = find_plant(node)
plant.properties.die(pos)
minetest.sound_play("crops_flies", {pos=pos, gain=0.8})
end
if crops.settings.hydration then
dofile(modpath .. "/tools.lua")
end
-- crop nodes, crafts, craftitems
dofile(modpath .. "/melon.lua")
dofile(modpath .. "/pumpkin.lua")
dofile(modpath .. "/corn.lua")
dofile(modpath .. "/tomato.lua")
dofile(modpath .. "/potato.lua")
dofile(modpath .. "/polebean.lua")
local nodenames = {}
for i = 1,table.getn(crops.plants) do
table.insert(nodenames, crops.plants[i].name)
end
-- water handling code
if crops.settings.hydration then
minetest.register_abm({
nodenames = nodenames,
interval = crops.settings.damage_interval,
chance = crops.settings.damage_chance,
action = function(pos, node, active_object_count, active_object_count_wider)
local meta = minetest.get_meta(pos)
local water = meta:get_int("crops_water")
local damage = meta:get_int("crops_damage")
-- get plant specific data
local plant = find_plant(node)
if plant == nil then
return
end
-- increase water for nearby water sources
local f = minetest.find_node_near(pos, 1, {"default:water_source", "default:water_flowing"})
if not f == nil then
water = math.min(100, water + 2)
else
f = minetest.find_node_near(pos, 2, {"default:water_source", "default:water_flowing"})
if not f == nil then
water = math.min(100, water + 1)
end
end
if minetest.get_node_light(pos, nil) < plant.properties.night then
-- compensate for light: at night give some water back to the plant
water = math.min(100, water + 1)
else
-- dry out the plant
water = math.max(1, water - plant.properties.wateruse)
end
meta:set_int("crops_water", water)
-- for convenience, copy water attribute to top half
if not plant.properties.doublesize == nil and plant.properties.doublesize then
local above = { x = pos.x, y = pos.y + 1, z = pos.z}
local abovemeta = minetest.get_meta(above)
abovemeta:set_int("crops_water", water)
end
if water <= plant.properties.wither_damage then
crops.particles(pos, 0)
damage = damage + math.random(crops.settings.damage_tick_min, crops.settings.damage_tick_max)
elseif water <= plant.properties.wither then
crops.particles(pos, 0)
return
elseif water >= plant.properties.soak_damage then
crops.particles(pos, 1)
damage = damage + math.random(crops.settings.damage_tick_min, crops.settings.damage_tick_max)
elseif water >= plant.properties.soak then
crops.particles(pos, 1)
return
end
meta:set_int("crops_damage", math.min(crops.settings.damage_max, damage))
-- is it dead?
if damage >= 100 then
crops.die(pos)
end
end
})
end
-- cooking recipes that mix craftitems
dofile(modpath .. "/cooking.lua")
dofile(modpath .. "/mapgen.lua")
minetest.log("action", "[crops] "..S("Loaded!"))

View File

@ -0,0 +1,44 @@
-- Fallback functions for when `intllib` is not installed.
-- Code released under Unlicense <http://unlicense.org>.
-- Get the latest version of this file at:
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
local function format(str, ...)
local args = { ... }
local function repl(escape, open, num, close)
if escape == "" then
local replacement = tostring(args[tonumber(num)])
if open == "" then
replacement = replacement..close
end
return replacement
else
return "@"..open..num..close
end
end
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
end
local gettext, ngettext
if minetest.get_modpath("intllib") then
if intllib.make_gettext_pair then
-- New method using gettext.
gettext, ngettext = intllib.make_gettext_pair()
else
-- Old method using text files.
gettext = intllib.Getter()
end
end
-- Fill in missing functions.
gettext = gettext or function(msgid, ...)
return format(msgid, ...)
end
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
return format(n==1 and msgid or msgid_plural, ...)
end
return gettext, ngettext

View File

@ -0,0 +1,152 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-20 17:17-0300\n"
"PO-Revision-Date: 2017-02-20 16:54-0300\n"
"Last-Translator: LNJ2\n"
"Language-Team: German\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: melon.lua
msgid "Melon seed"
msgstr "Melonensamen"
#: melon.lua
msgid "Melon plant"
msgstr "Melonenpflanze"
#: melon.lua
msgid "Melon slice"
msgstr "Melonenscheibe"
#: melon.lua
msgid "Melon"
msgstr "Melone"
#: tomato.lua
msgid "Tomato seed"
msgstr "Tomatensamen"
#: tomato.lua
msgid "Tomato plant"
msgstr "Tomatenpflanze"
#: tomato.lua
msgid "Tomato"
msgstr "Tomate"
#: polebean.lua
msgid "Green Bean"
msgstr "Grne Bohne"
#: polebean.lua
msgid "Beanpoles"
msgstr "Bohnenstangen"
#: polebean.lua
msgid "Green bean seed"
msgstr "Samen einer Grnen Bohne"
#: polebean.lua
msgid "Green Bean plant"
msgstr "Grne Bohnenpflanze"
#: tools.lua
msgid "Watering Can"
msgstr "Giekanne"
#: tools.lua
msgid "Hydrometer"
msgstr "Hydrometer"
#: pumpkin.lua
msgid "Pumpkin seed"
msgstr "Krbissamen"
#: pumpkin.lua
msgid "Pumpkin plant"
msgstr "Krbispflanze"
#: pumpkin.lua
msgid "Roasted pumpkin"
msgstr "Gersteter Krbis"
#: pumpkin.lua
msgid "Pumpkin"
msgstr "Krbis"
#: init.lua
msgid "Defaulting to \"normal\" difficulty settings"
msgstr "Benutze standard Schwierigkeitsgrad \"normal\""
#: init.lua
msgid "Hydration and dehydration mechanics are enabled."
msgstr "Hydrierungs- und Dehydrierungsmechaniken sind aktiviert."
#: init.lua
#, fuzzy
msgid "Unable to find plant \"@1\" in crops table"
msgstr "Konnte Pflanze \"@1\" nicht in der Tabelle finden"
#: init.lua
msgid "Loaded!"
msgstr ""
#: potato.lua
msgid "Potato eyes"
msgstr "Kartoffelaugen"
#: potato.lua
msgid "Potato plant"
msgstr "Kartoffelpflanze"
#: potato.lua
msgid "Potato"
msgstr "Kartoffel"
#: potato.lua
msgid "Soil with potatoes"
msgstr "Acker mit Kartoffeln"
#: cooking.lua
msgid "Unbaked clay bowl"
msgstr "Ungebackene Lehmschale"
#: cooking.lua
msgid "Clay bowl"
msgstr "Lehmschale"
#: cooking.lua
msgid "Bowl of vegetable stew"
msgstr "Schale voll Gemseeintopf"
#: cooking.lua
msgid "Bowl of uncooked vegetable stew"
msgstr "Schale voll mit roher Gemseeintopf"
#: corn.lua
msgid "Corn"
msgstr "Mais"
#: corn.lua
msgid "Corn Cob"
msgstr "Maiskolben"
#: corn.lua
msgid "Corn on the Cob"
msgstr "Gebackener Maiskolben"
#: corn.lua
msgid "Corn plant"
msgstr "Maispflanze"

View File

@ -0,0 +1,151 @@
# Spanish translations for PACKAGE package
# Traducciones al español para el paquete PACKAGE.
# Copyright (C) 2017 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Diego Martínez <kaeza@users.noreply.github.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-20 17:17-0300\n"
"PO-Revision-Date: 2017-02-20 16:54-0300\n"
"Last-Translator: Diego Martínez <kaeza@users.noreply.github.com>\n"
"Language-Team: Spanish\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: melon.lua
msgid "Melon seed"
msgstr "Semilla de sandía"
#: melon.lua
msgid "Melon plant"
msgstr "Planta de sandía"
#: melon.lua
msgid "Melon slice"
msgstr "Trozo de sandía"
#: melon.lua
msgid "Melon"
msgstr "Sandía"
#: tomato.lua
msgid "Tomato seed"
msgstr "Semilla de tomate"
#: tomato.lua
msgid "Tomato plant"
msgstr "Planta de tomate"
#: tomato.lua
msgid "Tomato"
msgstr "Tomate"
#: polebean.lua
msgid "Green Bean"
msgstr "Frijol verde"
#: polebean.lua
msgid "Beanpoles"
msgstr "Poste para frijoles"
#: polebean.lua
msgid "Green bean seed"
msgstr "Semilla de frijoles verdes"
#: polebean.lua
msgid "Green Bean plant"
msgstr "Planta de frijoles verdes"
#: tools.lua
msgid "Watering Can"
msgstr "Regadera"
#: tools.lua
msgid "Hydrometer"
msgstr "Hidrómetro"
#: pumpkin.lua
msgid "Pumpkin seed"
msgstr "Semillas de calabaza"
#: pumpkin.lua
msgid "Pumpkin plant"
msgstr "Planta de calabaza"
#: pumpkin.lua
msgid "Roasted pumpkin"
msgstr "Calabaza asada"
#: pumpkin.lua
msgid "Pumpkin"
msgstr "Calabaza"
#: init.lua
msgid "Defaulting to \"normal\" difficulty settings"
msgstr "Se usará la dificultad \"normal\" por defecto"
#: init.lua
msgid "Hydration and dehydration mechanics are enabled."
msgstr "Mecánica de hidratación y deshidratación activada."
#: init.lua
msgid "Unable to find plant \"@1\" in crops table"
msgstr "No se pudo encontrar la planta \"@1\" en la tabla de cosechas"
#: init.lua
msgid "Loaded!"
msgstr "¡Cargado!"
#: potato.lua
msgid "Potato eyes"
msgstr "Ojos de patata"
#: potato.lua
msgid "Potato plant"
msgstr "Planta de patata"
#: potato.lua
msgid "Potato"
msgstr "Patata"
#: potato.lua
msgid "Soil with potatoes"
msgstr "Suelo con patatas"
#: cooking.lua
msgid "Unbaked clay bowl"
msgstr "Tazón de arcilla sin cocer"
#: cooking.lua
msgid "Clay bowl"
msgstr "Tazón de arcilla"
#: cooking.lua
msgid "Bowl of vegetable stew"
msgstr "Tazón de sopa de vegetales"
#: cooking.lua
msgid "Bowl of uncooked vegetable stew"
msgstr "Tazón de sopa de vegetales sin cocer"
#: corn.lua
msgid "Corn"
msgstr "Maíz"
#: corn.lua
msgid "Corn Cob"
msgstr "Elote"
#: corn.lua
msgid "Corn on the Cob"
msgstr "Maíz en mazorca"
#: corn.lua
msgid "Corn plant"
msgstr "Planta de maíz"

View File

@ -0,0 +1,150 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-20 17:17-0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: xisd\n"
"Language-Team: French\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: melon.lua
msgid "Melon seed"
msgstr "Graine de Pastèque"
#: melon.lua
msgid "Melon plant"
msgstr "Pied de Pastèque"
#: melon.lua
msgid "Melon slice"
msgstr "Tranche de Pastèque"
#: melon.lua
msgid "Melon"
msgstr "Pastèque"
#: tomato.lua
msgid "Tomato seed"
msgstr "Graines de tomate"
#: tomato.lua
msgid "Tomato plant"
msgstr "Pied de tomate"
#: tomato.lua
msgid "Tomato"
msgstr "Tomate"
#: polebean.lua
msgid "Green Bean"
msgstr "Haricot vert"
#: polebean.lua
msgid "Beanpoles"
msgstr "Tuteur pour haricots"
#: polebean.lua
msgid "Green bean seed"
msgstr "Graine de haricot vert"
#: polebean.lua
msgid "Green Bean plant"
msgstr "Plant de haricot vert"
#: tools.lua
msgid "Watering Can"
msgstr "Arrosoir"
#: tools.lua
msgid "Hydrometer"
msgstr "Hydromètre"
#: pumpkin.lua
msgid "Pumpkin seed"
msgstr "Graines de citrouille"
#: pumpkin.lua
msgid "Pumpkin plant"
msgstr "Plant de citrouille"
#: pumpkin.lua
msgid "Roasted pumpkin"
msgstr "Citrouille grillée"
#: pumpkin.lua
msgid "Pumpkin"
msgstr "Citrouille"
#: init.lua
msgid "Defaulting to \"normal\" difficulty settings"
msgstr "Réglage par default : \"normal\""
#: init.lua
msgid "Hydration and dehydration mechanics are enabled."
msgstr "Les mécaniques d'hydratation et déshydratation sont activées."
#: init.lua
msgid "Unable to find plant \"@1\" in crops table"
msgstr "Impossible de trouver la plante \"@1\" dans le tableau crops"
#: init.lua
msgid "Loaded!"
msgstr "Chargé !"
#: potato.lua
msgid "Potato eyes"
msgstr "Yeux de pomme de terre"
#: potato.lua
msgid "Potato plant"
msgstr "Plant de pomme de terre"
#: potato.lua
msgid "Potato"
msgstr "Pomme de terre"
#: potato.lua
msgid "Soil with potatoes"
msgstr "Terre labourée avec pommes de terres"
#: cooking.lua
msgid "Unbaked clay bowl"
msgstr "Bol en argile crue"
#: cooking.lua
msgid "Clay bowl"
msgstr "Bol en terre cuite"
#: cooking.lua
msgid "Bowl of vegetable stew"
msgstr "Bol de soupe de légumes"
#: cooking.lua
msgid "Bowl of uncooked vegetable stew"
msgstr "Bol de soupe de légumes non-cuite"
#: corn.lua
msgid "Corn"
msgstr "Mais"
#: corn.lua
msgid "Corn Cob"
msgstr "Epis de mais"
#: corn.lua
msgid "Corn on the Cob"
msgstr "Epis de mais grillé"
#: corn.lua
msgid "Corn plant"
msgstr "Plant de Mais"

View File

@ -0,0 +1,150 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-20 17:17-0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: melon.lua
msgid "Melon seed"
msgstr ""
#: melon.lua
msgid "Melon plant"
msgstr ""
#: melon.lua
msgid "Melon slice"
msgstr ""
#: melon.lua
msgid "Melon"
msgstr ""
#: tomato.lua
msgid "Tomato seed"
msgstr ""
#: tomato.lua
msgid "Tomato plant"
msgstr ""
#: tomato.lua
msgid "Tomato"
msgstr ""
#: polebean.lua
msgid "Green Bean"
msgstr ""
#: polebean.lua
msgid "Beanpoles"
msgstr ""
#: polebean.lua
msgid "Green bean seed"
msgstr ""
#: polebean.lua
msgid "Green Bean plant"
msgstr ""
#: tools.lua
msgid "Watering Can"
msgstr ""
#: tools.lua
msgid "Hydrometer"
msgstr ""
#: pumpkin.lua
msgid "Pumpkin seed"
msgstr ""
#: pumpkin.lua
msgid "Pumpkin plant"
msgstr ""
#: pumpkin.lua
msgid "Roasted pumpkin"
msgstr ""
#: pumpkin.lua
msgid "Pumpkin"
msgstr ""
#: init.lua
msgid "Defaulting to \"normal\" difficulty settings"
msgstr ""
#: init.lua
msgid "Hydration and dehydration mechanics are enabled."
msgstr ""
#: init.lua
msgid "Unable to find plant \"@1\" in crops table"
msgstr ""
#: init.lua
msgid "Loaded!"
msgstr ""
#: potato.lua
msgid "Potato eyes"
msgstr ""
#: potato.lua
msgid "Potato plant"
msgstr ""
#: potato.lua
msgid "Potato"
msgstr ""
#: potato.lua
msgid "Soil with potatoes"
msgstr ""
#: cooking.lua
msgid "Unbaked clay bowl"
msgstr ""
#: cooking.lua
msgid "Clay bowl"
msgstr ""
#: cooking.lua
msgid "Bowl of vegetable stew"
msgstr ""
#: cooking.lua
msgid "Bowl of uncooked vegetable stew"
msgstr ""
#: corn.lua
msgid "Corn"
msgstr ""
#: corn.lua
msgid "Corn Cob"
msgstr ""
#: corn.lua
msgid "Corn on the Cob"
msgstr ""
#: corn.lua
msgid "Corn plant"
msgstr ""

View File

@ -0,0 +1,48 @@
local mg_params = minetest.get_mapgen_params()
if mg_params.mgname ~= "v6" and mg_params.mgname ~= "singlenode" then
minetest.register_decoration({
deco_type = "simple",
place_on = { "default:dirt_with_grass" },
sidelen = 16,
noise_params = {
offset = -0.02,
scale = 0.02,
spread = {x = 200, y = 200, z = 200},
seed = 90459126,
octaves = 3,
persist = 0.6
},
biomes = {"grassland", "deciduous_forest", "coniferous_forest"},
y_min = 1,
y_max = 31000,
decoration = "crops:melon_plant_4"
})
minetest.register_decoration({
deco_type = "simple",
place_on = { "default:dirt_with_grass" },
sidelen = 16,
noise_params = {
offset = -0.02,
scale = 0.02,
spread = {x = 200, y = 200, z = 200},
seed = 26294592,
octaves = 3,
persist = 0.6
},
biomes = {"deciduous_forest", "coniferous_forest", "tundra"},
y_min = 1,
y_max = 31000,
decoration = "crops:pumpkin_plant_4"
})
end
-- drop potatoes when digging in dirt
minetest.override_item("default:dirt_with_grass", {
drop = {
items = {
{ items = {'default:dirt'}},
{ items = {'crops:potato'}, rarity = 500 }
}
}
})

249
worldmods/crops/melon.lua Normal file
View File

@ -0,0 +1,249 @@
--[[
Copyright (C) 2015 - Auke Kok <sofar@foo-projects.org>
"crops" is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1
of the license, or (at your option) any later version.
--]]
-- Intllib
local S = crops.intllib
local faces = {
[1] = { x = -1, z = 0, r = 3, o = 1, m = 14 },
[2] = { x = 1, z = 0, r = 1, o = 3, m = 16 },
[3] = { x = 0, z = -1, r = 2, o = 0, m = 5 },
[4] = { x = 0, z = 1, r = 0, o = 2, m = 11 }
}
minetest.register_node("crops:melon_seed", {
description = S("Melon seed"),
inventory_image = "crops_melon_seed.png",
wield_image = "crops_melon_seed.png",
tiles = { "crops_melon_plant_1.png" },
drawtype = "plantlike",
waving = 1,
sunlight_propagates = false,
use_texture_alpha = true,
walkable = false,
paramtype = "light",
node_placement_prediction = "crops:melon_plant_1",
groups = { snappy=3,flammable=3,flora=1,attached_node=1 },
on_place = function(itemstack, placer, pointed_thing)
local under = minetest.get_node(pointed_thing.under)
if minetest.get_item_group(under.name, "soil") <= 1 then
return
end
crops.plant(pointed_thing.above, {name="crops:melon_plant_1"})
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end
})
for stage = 1, 6 do
minetest.register_node("crops:melon_plant_" .. stage , {
description = S("Melon plant"),
tiles = { "crops_melon_plant_" .. stage .. ".png" },
drawtype = "plantlike",
waving = 1,
sunlight_propagates = true,
use_texture_alpha = true,
walkable = false,
paramtype = "light",
groups = { snappy=3, flammable=3, flora=1, attached_node=1, not_in_creative_inventory=1 },
drop = "crops:melon_seed",
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -0.5 + (((math.min(stage, 4)) + 1) / 5), 0.5}
}
})
end
minetest.register_node("crops:melon_plant_5_attached", {
visual = "mesh",
mesh = "crops_plant_extra_face.obj",
description = S("Melon plant"),
tiles = { "crops_melon_stem.png", "crops_melon_plant_4.png" },
drawtype = "mesh",
paramtype2 = "facedir",
sunlight_propagates = true,
use_texture_alpha = true,
walkable = false,
paramtype = "light",
groups = { snappy=3, flammable=3, flora=1, attached_node=1, not_in_creative_inventory=1 },
drop = "crops:melon_seed",
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_craftitem("crops:melon_slice", {
description = S("Melon slice"),
inventory_image = "crops_melon_slice.png",
on_use = minetest.item_eat(1)
})
minetest.register_craft({
type = "shapeless",
output = "crops:melon_seed",
recipe = { "crops:melon_slice" }
})
--
-- the melon "block"
--
minetest.register_node("crops:melon", {
description = S("Melon"),
tiles = {
"crops_melon_top.png",
"crops_melon_bottom.png",
"crops_melon.png",
},
sunlight_propagates = false,
use_texture_alpha = false,
walkable = true,
groups = { snappy=3, flammable=3, oddly_breakable_by_hand=2 },
paramtype2 = "facedir",
drop = {},
sounds = default.node_sound_wood_defaults({
dig = { name = "default_dig_oddly_breakable_by_hand" },
dug = { name = "default_dig_choppy" }
}),
on_dig = function(pos, node, digger)
for face = 1, 4 do
local s = { x = pos.x + faces[face].x, y = pos.y, z = pos.z + faces[face].z }
local n = minetest.get_node(s)
if n.name == "crops:melon_plant_5_attached" then
-- make sure it was actually attached to this stem
if n.param2 == faces[face].o then
minetest.swap_node(s, { name = "crops:melon_plant_4" })
end
end
end
local meta = minetest.get_meta(pos)
local damage = meta:get_int("crops_damage")
local drops = {}
-- 0 dmg - 3-5
-- 50 dmg - 2-3
-- 100 dmg - 1-1
for i = 1,math.random(3 - (2 * (damage / 100)), 5 - (4 * (damage / 100))) do
table.insert(drops, ('crops:melon_slice'))
end
core.handle_node_drops(pos, drops, digger)
minetest.remove_node(pos)
end
})
--
-- grows a plant to mature size
--
minetest.register_abm({
nodenames = { "crops:melon_plant_1", "crops:melon_plant_2", "crops:melon_plant_3","crops:melon_plant_4" },
neighbors = { "group:soil" },
interval = crops.settings.interval,
chance = crops.settings.chance,
action = function(pos, node, active_object_count, active_object_count_wider)
if not crops.can_grow(pos) then
return
end
local n = string.gsub(node.name, "4", "5")
n = string.gsub(n, "3", "4")
n = string.gsub(n, "2", "3")
n = string.gsub(n, "1", "2")
minetest.swap_node(pos, { name = n })
end
})
--
-- grows a melon
--
minetest.register_abm({
nodenames = { "crops:melon_plant_5" },
neighbors = { "group:soil" },
interval = crops.settings.interval,
chance = crops.settings.chance,
action = function(pos, node, active_object_count, active_object_count_wider)
if not crops.can_grow(pos) then
return
end
for face = 1, 4 do
local t = { x = pos.x + faces[face].x, y = pos.y, z = pos.z + faces[face].z }
if minetest.get_node(t).name == "crops:melon" then
return
end
end
local r = math.random(1, 4)
local t = { x = pos.x + faces[r].x, y = pos.y, z = pos.z + faces[r].z }
local n = minetest.get_node(t)
if n.name == "ignore" then
return
end
if minetest.registered_nodes[minetest.get_node({ x = t.x, y = t.y - 1, z = t.z }).name].walkable == false then
return
end
if minetest.registered_nodes[n.name].drawtype == "plantlike" or
minetest.registered_nodes[n.name].groups.flora == 1 or
n.name == "air" then
minetest.swap_node(pos, {name = "crops:melon_plant_5_attached", param2 = faces[r].r})
minetest.set_node(t, {name = "crops:melon", param2 = faces[r].m})
local meta = minetest.get_meta(pos)
local damage = meta:get_int("crops_damage")
local water = meta:get_int("crops_water")
-- growing a melon costs 25 water!
meta:set_int("crops_water", math.max(0, water - 25))
meta = minetest.get_meta(t)
-- reflect plants' damage in the melon yield
meta:set_int("crops_damage", damage)
end
end
})
--
-- return a melon to a normal one if there is no melon attached, so it can
-- grow a new melon again
--
minetest.register_abm({
nodenames = { "crops:melon_plant_5_attached" },
interval = crops.settings.interval,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
for face = 1, 4 do
local t = { x = pos.x + faces[face].x, y = pos.y, z = pos.z + faces[face].z }
if minetest.get_node(t).name == "crops:melon" then
return
end
end
minetest.swap_node(pos, {name = "crops:melon_plant_4" })
end
})
crops.melon_die = function(pos)
minetest.set_node(pos, { name = "crops:melon_plant_6" })
end
local properties = {
die = crops.melon_die,
waterstart = 20,
wateruse = 1,
night = 5,
soak = 80,
soak_damage = 90,
wither = 20,
wither_damage = 10,
}
crops.register({ name = "crops:melon_plant_1", properties = properties })
crops.register({ name = "crops:melon_plant_2", properties = properties })
crops.register({ name = "crops:melon_plant_3", properties = properties })
crops.register({ name = "crops:melon_plant_4", properties = properties })
crops.register({ name = "crops:melon_plant_5", properties = properties })
crops.register({ name = "crops:melon_plant_5_attached", properties = properties })

1
worldmods/crops/mod.conf Normal file
View File

@ -0,0 +1 @@
name = crops

View File

@ -0,0 +1,49 @@
# Blender v2.60 (sub 0) OBJ File: 'p1.blend'
# www.blender.org
mtllib crops_plant_extra_face.mtl
o Mesh_Stem_Stem
v -0.000000 0.500000 0.500000
v 0.000000 -0.500000 0.500000
v 0.000000 -0.500000 -0.500000
v -0.000000 0.500000 -0.500000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vn 1.000000 0.000000 -0.000000
g Mesh_Stem_Stem_Material.002
usemtl Material.002
s off
f 1/1/1 2/2/1 3/3/1 4/4/1
o Mesh_Plant_Plant
v 0.359670 -0.500000 0.347329
v 0.359670 0.500000 0.347329
v -0.359670 0.500000 -0.347329
v -0.359670 -0.500000 -0.347329
v -0.347329 -0.500000 0.359670
v -0.347329 0.500000 0.359670
v 0.347329 0.500000 -0.359670
v 0.347329 -0.500000 -0.359670
v 0.359670 -0.500000 0.347329
v -0.359670 -0.500000 -0.347329
v -0.359670 0.500000 -0.347329
v 0.359670 0.500000 0.347329
v -0.347329 -0.500000 0.359670
v 0.347329 -0.500000 -0.359670
v 0.347329 0.500000 -0.359670
v -0.347329 0.500000 0.359670
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vn -0.694658 0.000000 0.719340
vn -0.719340 -0.000000 -0.694658
vn 0.694658 -0.000000 -0.719340
vn 0.719340 0.000000 0.694658
g Mesh_Plant_Plant_Material.001
usemtl Material.001
s off
f 5/5/2 6/6/2 7/7/2 8/8/2
f 9/5/3 10/6/3 11/7/3 12/8/3
f 13/5/4 14/8/4 15/7/4 16/6/4
f 17/5/5 18/8/5 19/7/5 20/6/5

View File

@ -0,0 +1,309 @@
--[[
Copyright (C) 2015 - Auke Kok <sofar@foo-projects.org>
"crops" is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1
of the license, or (at your option) any later version.
--]]
-- Intllib
local S = crops.intllib
minetest.register_craft({
output = "crops:beanpoles",
recipe = {
{'', '', ''},
{'default:stick', '', 'default:stick'},
{'default:stick', '', 'default:stick'},
}
})
minetest.register_craftitem("crops:green_bean", {
description = S("Green Bean"),
inventory_image = "crops_green_bean.png",
on_use = minetest.item_eat(1)
})
minetest.register_craft({
type = "shapeless",
output = "crops:green_bean_seed",
recipe = { "crops:green_bean" }
})
local function crops_beanpole_on_dig(pos, node, digger)
local bottom
local bottom_n
local top
local top_n
local drops = {}
if node.name == "crops:beanpole_base" or
node.name == "crops:beanpole_plant_base_1" or
node.name == "crops:beanpole_plant_base_2" or
node.name == "crops:beanpole_plant_base_3" or --grown tall enough for top section
node.name == "crops:beanpole_plant_base_4" or --flowering
node.name == "crops:beanpole_plant_base_5" or --ripe
node.name == "crops:beanpole_plant_base_6" --harvested
then
bottom = pos
bottom_n = node
top = { x = pos.x, y = pos.y + 1, z = pos.z }
top_n = minetest.get_node(top)
elseif node.name == "crops:beanpole_top" or
node.name == "crops:beanpole_plant_top_1" or
node.name == "crops:beanpole_plant_top_2" or --flowering
node.name == "crops:beanpole_plant_top_3" or --ripe
node.name == "crops:beanpole_plant_top_4" --harvested
then
top = pos
top_n = node
bottom = { x = pos.x, y = pos.y - 1, z = pos.z }
bottom_n = minetest.get_node(bottom)
else
-- ouch, this shouldn't happen
print("beanpole on_dig falsely attached to: " .. pos.x .. "," .. pos.y .. "," .. pos.z)
return
end
if bottom_n.name == "crops:beanpole_base" and top_n.name == "crops:beanpole_top" then
-- bare beanpole
table.insert(drops, "crops:beanpoles")
minetest.remove_node(bottom)
minetest.remove_node(top)
elseif (
bottom_n.name == "crops:beanpole_plant_base_1" or
bottom_n.name == "crops:beanpole_plant_base_2" or
bottom_n.name == "crops:beanpole_plant_base_3" or
bottom_n.name == "crops:beanpole_plant_base_4"
) and (
top_n.name == "crops:beanpole_top" or
top_n.name == "crops:beanpole_plant_top_1" or
top_n.name == "crops:beanpole_plant_top_2"
) then
-- non-ripe
for i = 1,4 do
table.insert(drops, "default:stick")
end
minetest.set_node(bottom, { name = "crops:beanpole_base"})
minetest.set_node(top, { name = "crops:beanpole_top"})
elseif bottom_n.name == "crops:beanpole_plant_base_5" and top_n.name == "crops:beanpole_plant_top_3" then
-- ripe beanpole
local meta = minetest.get_meta(bottom)
local damage = meta:get_int("crops_damage")
-- 0 - 3-7
-- 50 - 2-4
-- 100 - 1-1
for i = 1,math.random(3 - (2 * (damage / 100)),7 - (6 * (damage / 100))) do
table.insert(drops, "crops:green_bean")
end
crops.die(bottom)
elseif bottom_n.name == "crops:beanpole_plant_base_6" and top_n.name == "crops:beanpole_plant_top_4" then
-- harvested beans
for i = 1,math.random(3,4) do
table.insert(drops, "default:stick")
end
minetest.remove_node(bottom)
minetest.remove_node(top)
else
-- ouch, this shouldn't happen
print("beanpole on_dig can't handle blocks at to: " ..
bottom.x .. "," .. bottom.y .. "," .. bottom.z ..
" and " .. top.x .. "," .. top.y .. "," .. top.z)
print("removing a " .. node.name .. " at " ..
pos.x .. "," .. pos.y .. "," .. pos.z)
minetest.remove_node(pos)
return
end
core.handle_node_drops(pos, drops, digger)
end
minetest.register_node("crops:beanpole_base", {
description = "",
drawtype = "plantlike",
tiles = { "crops_beanpole_base.png" },
use_texture_alpha = true,
walkable = true,
sunlight_propagates = true,
paramtype = "light",
groups = { snappy=3,flammable=3,flora=1,attached_node=1,not_in_creative_inventory=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
on_dig = crops_beanpole_on_dig,
})
minetest.register_node("crops:beanpole_top", {
description = "",
drawtype = "plantlike",
tiles = { "crops_beanpole_top.png" },
use_texture_alpha = true,
walkable = true,
sunlight_propagates = true,
paramtype = "light",
groups = { snappy=3,flammable=3,flora=1,not_in_creative_inventory=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
on_dig = crops_beanpole_on_dig,
})
minetest.register_node("crops:beanpoles", {
description = S("Beanpoles"),
inventory_image = "crops_beanpole_top.png",
wield_image = "crops_beanpole_top.png",
tiles = { "crops_beanpole_base.png" },
drawtype = "plantlike",
sunlight_propagates = true,
use_texture_alpha = true,
paramtype = "light",
groups = { snappy=3,flammable=3,flora=1,attached_node=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
node_placement_prediction = "crops:beanpole_base",
on_place = function(itemstack, placer, pointed_thing)
local under = minetest.get_node(pointed_thing.under)
if minetest.get_item_group(under.name, "soil") <= 1 then
return
end
local top = { x = pointed_thing.above.x, y = pointed_thing.above.y + 1, z = pointed_thing.above.z }
if not minetest.get_node(top).name == "air" then
return
end
minetest.set_node(pointed_thing.above, {name="crops:beanpole_base"})
minetest.set_node(top, {name="crops:beanpole_top"})
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end
})
minetest.register_craftitem("crops:green_bean_seed", {
description = S("Green bean seed"),
inventory_image = "crops_green_bean_seed.png",
wield_image = "crops_green_bean_seed.png",
node_placement_prediction = "", -- disabled, prediction assumes pointed_think.above!
on_place = function(itemstack, placer, pointed_thing)
local under = minetest.get_node(pointed_thing.under)
if under.name == "crops:beanpole_base" then
crops.plant(pointed_thing.under, {name="crops:beanpole_plant_base_1"})
local above = { x = pointed_thing.under.x, y = pointed_thing.under.y + 1, z = pointed_thing.under.z}
local meta = minetest.get_meta(above)
meta:set_int("crops_top_half", 1)
elseif under.name == "crops:beanpole_top" then
local below = { x = pointed_thing.under.x, y = pointed_thing.under.y - 1, z = pointed_thing.under.z }
if minetest.get_node(below).name == "crops:beanpole_base" then
crops.plant(below, {name="crops:beanpole_plant_base_1"})
local meta = minetest.get_meta(pointed_thing.under)
meta:set_int("crops_top_half", 1)
else
return
end
else
return
end
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end
})
for stage = 1,6 do
minetest.register_node("crops:beanpole_plant_base_" .. stage, {
description = S("Green Bean plant"),
tiles = { "crops_beanpole_plant_base_" .. stage .. ".png" },
drawtype = "plantlike",
sunlight_propagates = true,
use_texture_alpha = true,
paramtype = "light",
walkable = false,
groups = { snappy=3,flammable=3,flora=1,attached_node=1,not_in_creative_inventory=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
on_dig = crops_beanpole_on_dig
})
end
for stage = 1,4 do
minetest.register_node("crops:beanpole_plant_top_" .. stage, {
description = S("Green Bean plant"),
tiles = { "crops_beanpole_plant_top_" .. stage .. ".png" },
drawtype = "plantlike",
sunlight_propagates = true,
use_texture_alpha = true,
paramtype = "light",
walkable = true,
groups = { snappy=3,flammable=3,flora=1,not_in_creative_inventory=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
on_dig = crops_beanpole_on_dig
})
end
minetest.register_abm({
nodenames = {
"crops:beanpole_plant_base_1",
"crops:beanpole_plant_base_2",
"crops:beanpole_plant_base_3",
"crops:beanpole_plant_base_4"
},
interval = crops.settings.interval,
chance = crops.settings.chance,
neighbors = { "group:soil" },
action = function(pos, node, active_object_count, active_object_count_wider)
if not crops.can_grow(pos) then
return
end
if node.name == "crops:beanpole_plant_base_1" then
minetest.swap_node(pos, { name = "crops:beanpole_plant_base_2"})
elseif node.name == "crops:beanpole_plant_base_2" then
minetest.swap_node(pos, { name = "crops:beanpole_plant_base_3"})
elseif node.name == "crops:beanpole_plant_base_3" then
local apos = {x = pos.x, y = pos.y + 1, z = pos.z}
local above = minetest.get_node(apos)
if above.name == "crops:beanpole_top" then
minetest.set_node(apos, { name = "crops:beanpole_plant_top_1" })
local meta = minetest.get_meta(apos)
meta:set_int("crops_top_half", 1)
elseif above.name == "crops:beanpole_plant_top_1" then
minetest.swap_node(pos, { name = "crops:beanpole_plant_base_4" })
minetest.swap_node(apos, { name = "crops:beanpole_plant_top_2" })
end
elseif node.name == "crops:beanpole_plant_base_4" then
local apos = {x = pos.x, y = pos.y + 1, z = pos.z}
minetest.swap_node(pos, { name = "crops:beanpole_plant_base_5" })
minetest.swap_node(apos, { name = "crops:beanpole_plant_top_3" })
end
end
})
crops.beanpole_die = function(pos)
minetest.set_node(pos, { name = "crops:beanpole_plant_base_6" })
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
minetest.set_node(above, { name = "crops:beanpole_plant_top_4" })
end
local properties = {
die = crops.beanpole_die,
waterstart = 30,
wateruse = 1,
night = 5,
soak = 60,
soak_damage = 75,
wither = 25,
wither_damage = 15,
doublesize = true,
}
crops.register({ name = "crops:beanpole_plant_base_1", properties = properties })
crops.register({ name = "crops:beanpole_plant_base_2", properties = properties })
crops.register({ name = "crops:beanpole_plant_base_3", properties = properties })
crops.register({ name = "crops:beanpole_plant_base_4", properties = properties })
crops.register({ name = "crops:beanpole_plant_base_5", properties = properties })

196
worldmods/crops/potato.lua Normal file
View File

@ -0,0 +1,196 @@
--[[
Copyright (C) 2015 - Auke Kok <sofar@foo-projects.org>
"crops" is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1
of the license, or (at your option) any later version.
--]]
-- Intllib
local S = crops.intllib
minetest.register_node("crops:potato_eyes", {
description = S("Potato eyes"),
inventory_image = "crops_potato_eyes.png",
wield_image = "crops_potato_eyes.png",
tiles = { "crops_potato_plant_1.png" },
drawtype = "plantlike",
paramtype2 = "meshoptions",
waving = 1,
sunlight_propagates = false,
use_texture_alpha = true,
walkable = false,
paramtype = "light",
node_placement_prediction = "crops:potato_plant_1",
groups = { snappy=3,flammable=3,flora=1,attached_node=1 },
selection_box = {
type = "fixed",
fixed = {-0.45, -0.5, -0.45, 0.45, -0.4, 0.45}
},
on_place = function(itemstack, placer, pointed_thing)
local under = minetest.get_node(pointed_thing.under)
if minetest.get_item_group(under.name, "soil") <= 1 then
return
end
crops.plant(pointed_thing.above, {name="crops:potato_plant_1", param2 = 3})
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end
})
for stage = 1, 5 do
minetest.register_node("crops:potato_plant_" .. stage , {
description = S("Potato plant"),
tiles = { "crops_potato_plant_" .. stage .. ".png" },
drawtype = "plantlike",
paramtype2 = "meshoptions",
waving = 1,
sunlight_propagates = true,
use_texture_alpha = true,
walkable = false,
paramtype = "light",
groups = { snappy=3, flammable=3, flora=1, attached_node=1, not_in_creative_inventory=1 },
drop = {},
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
fixed = {-0.45, -0.5, -0.45, 0.45, -0.6 + (((math.min(stage, 4)) + 1) / 5), 0.45}
}
})
end
minetest.register_craftitem("crops:potato", {
description = S("Potato"),
inventory_image = "crops_potato.png",
on_use = minetest.item_eat(1)
})
minetest.register_craft({
type = "shapeless",
output = "crops:potato_eyes",
recipe = { "crops:potato" }
})
--
-- the potatoes "block"
--
minetest.register_node("crops:soil_with_potatoes", {
description = S("Soil with potatoes"),
tiles = { "default_dirt.png^crops_potato_soil.png", "default_dirt.png" },
sunlight_propagates = false,
use_texture_alpha = false,
walkable = true,
groups = { snappy=3, flammable=3, oddly_breakable_by_hand=2, soil=1 },
paramtype2 = "facedir",
drop = {max_items = 5, items = {
{ items = {'crops:potato'}, rarity = 1 },
{ items = {'crops:potato'}, rarity = 1 },
{ items = {'crops:potato'}, rarity = 1 },
{ items = {'crops:potato'}, rarity = 2 },
{ items = {'crops:potato'}, rarity = 5 },
}},
sounds = default.node_sound_dirt_defaults(),
on_dig = function(pos, node, digger)
local drops = {}
-- damage 0 = drops 3-5
-- damage 50 = drops 1-3
-- damage 100 = drops 0-1
local meta = minetest.get_meta(pos)
local damage = meta:get_int("crops_damage")
for i = 1, math.random(3 - (3 * damage / 100), 5 - (4 * (damage / 100))) do
table.insert(drops, "crops:potato")
end
core.handle_node_drops(pos, drops, digger)
minetest.set_node(pos, { name = "farming:soil" })
local above = { x = pos.x, y = pos.y + 1, z = pos.z }
if minetest.get_node(above).name == "crops:potato_plant_4" then
minetest.set_node(above, { name = "air" })
end
end
})
--
-- grows a plant to mature size
--
minetest.register_abm({
nodenames = { "crops:potato_plant_1", "crops:potato_plant_2", "crops:potato_plant_3" },
neighbors = { "group:soil" },
interval = crops.settings.interval,
chance = crops.settings.chance,
action = function(pos, node, active_object_count, active_object_count_wider)
if not crops.can_grow(pos) then
return
end
local below = { x = pos.x, y = pos.y - 1, z = pos.z }
if not minetest.registered_nodes[minetest.get_node(below).name].groups.soil then
return
end
local meta = minetest.get_meta(pos)
local damage = meta:get_int("crops_damage")
if damage == 100 then
crops.die(pos)
return
end
local n = string.gsub(node.name, "3", "4")
n = string.gsub(n, "2", "3")
n = string.gsub(n, "1", "2")
minetest.swap_node(pos, { name = n, param2 = 3 })
end
})
--
-- grows the final potatoes in the soil beneath
--
minetest.register_abm({
nodenames = { "crops:potato_plant_4" },
neighbors = { "group:soil" },
interval = crops.settings.interval,
chance = crops.settings.chance,
action = function(pos, node, active_object_count, active_object_count_wider)
if not crops.can_grow(pos) then
return
end
local below = { x = pos.x, y = pos.y - 1, z = pos.z }
if not minetest.registered_nodes[minetest.get_node(below).name].groups.soil then
return
end
local meta = minetest.get_meta(pos)
local damage = meta:get_int("crops_damage")
minetest.set_node(below, { name = "crops:soil_with_potatoes" })
meta = minetest.get_meta(below)
meta:set_int("crops_damage", damage)
end
})
crops.potato_die = function(pos)
minetest.set_node(pos, { name = "crops:potato_plant_5", param2 = 3 })
local below = { x = pos.x, y = pos.y - 1, z = pos.z }
local node = minetest.get_node(below)
if node.name == "crops:soil_with_potatoes" then
local meta = minetest.get_meta(below)
meta:set_int("crops_damage", 100)
end
end
local properties = {
die = crops.potato_die,
waterstart = 30,
wateruse = 1,
night = 5,
soak = 80,
soak_damage = 90,
wither = 20,
wither_damage = 10,
}
crops.register({ name = "crops:potato_plant_1", properties = properties })
crops.register({ name = "crops:potato_plant_2", properties = properties })
crops.register({ name = "crops:potato_plant_3", properties = properties })
crops.register({ name = "crops:potato_plant_4", properties = properties })

260
worldmods/crops/pumpkin.lua Normal file
View File

@ -0,0 +1,260 @@
--[[
Copyright (C) 2015 - Auke Kok <sofar@foo-projects.org>
"crops" is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1
of the license, or (at your option) any later version.
--]]
-- Intllib
local S = crops.intllib
local faces = {
[1] = { x = -1, z = 0, r = 3, o = 1, m = 14 },
[2] = { x = 1, z = 0, r = 1, o = 3, m = 16 },
[3] = { x = 0, z = -1, r = 2, o = 0, m = 5 },
[4] = { x = 0, z = 1, r = 0, o = 2, m = 11 }
}
minetest.register_node("crops:pumpkin_seed", {
description = S("Pumpkin seed"),
inventory_image = "crops_pumpkin_seed.png",
wield_image = "crops_pumpkin_seed.png",
tiles = { "crops_pumpkin_plant_1.png" },
drawtype = "plantlike",
waving = 1,
sunlight_propagates = false,
use_texture_alpha = true,
walkable = false,
paramtype = "light",
node_placement_prediction = "crops:pumpkin_plant_1",
groups = { snappy=3,flammable=3,flora=1,attached_node=1 },
on_place = function(itemstack, placer, pointed_thing)
local under = minetest.get_node(pointed_thing.under)
if minetest.get_item_group(under.name, "soil") <= 1 then
return
end
crops.plant(pointed_thing.above, {name="crops:pumpkin_plant_1"})
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end
})
for stage = 1, 6 do
minetest.register_node("crops:pumpkin_plant_" .. stage , {
description = S("Pumpkin plant"),
tiles = { "crops_pumpkin_plant_" .. stage .. ".png" },
drawtype = "plantlike",
waving = 1,
sunlight_propagates = true,
use_texture_alpha = true,
walkable = false,
paramtype = "light",
groups = { snappy=3, flammable=3, flora=1, attached_node=1, not_in_creative_inventory=1 },
drop = "crops:pumpkin_seed",
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -0.5 + (((math.min(stage, 4)) + 1) / 5), 0.5}
}
})
end
minetest.register_node("crops:pumpkin_plant_5_attached", {
visual = "mesh",
mesh = "crops_plant_extra_face.obj",
description = S("Pumpkin plant"),
tiles = { "crops_pumpkin_stem.png", "crops_pumpkin_plant_4.png" },
drawtype = "mesh",
paramtype2 = "facedir",
sunlight_propagates = true,
use_texture_alpha = true,
walkable = false,
paramtype = "light",
groups = { snappy=3, flammable=3, flora=1, attached_node=1, not_in_creative_inventory=1 },
drop = "crops:pumpkin_seed",
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_craftitem("crops:roasted_pumpkin", {
description = S("Roasted pumpkin"),
inventory_image = "crops_roasted_pumpkin.png",
on_use = minetest.item_eat(2)
})
minetest.register_craft({
type = "shapeless",
output = "crops:pumpkin_seed",
recipe = { "crops:pumpkin" }
})
minetest.register_craft({
type = "cooking",
output = "crops:roasted_pumpkin",
recipe = "crops:pumpkin"
})
--
-- the pumpkin "block"
--
minetest.register_node("crops:pumpkin", {
description = S("Pumpkin"),
tiles = {
"crops_pumpkin_top.png",
"crops_pumpkin_bottom.png",
"crops_pumpkin.png"
},
sunlight_propagates = false,
use_texture_alpha = false,
walkable = true,
groups = { snappy=3, flammable=3, oddly_breakable_by_hand=2 },
paramtype2 = "facedir",
sounds = default.node_sound_wood_defaults({
dig = { name = "default_dig_oddly_breakable_by_hand" },
dug = { name = "default_dig_choppy" }
}),
after_dig_node = function(pos, node)
for face = 1, 4 do
local s = { x = pos.x + faces[face].x, y = pos.y, z = pos.z + faces[face].z }
local n = minetest.get_node(s)
if n.name == "crops:pumpkin_plant_5_attached" then
-- make sure it was actually attached to this stem
if n.param2 == faces[face].o then
minetest.swap_node(s, { name = "crops:pumpkin_plant_4" })
end
end
end
end
})
--
-- grows a plant to mature size
--
minetest.register_abm({
nodenames = { "crops:pumpkin_plant_1", "crops:pumpkin_plant_2", "crops:pumpkin_plant_3","crops:pumpkin_plant_4" },
neighbors = { "group:soil" },
interval = crops.settings.interval,
chance = crops.settings.chance,
action = function(pos, node, active_object_count, active_object_count_wider)
if not crops.can_grow(pos) then
return
end
local n = string.gsub(node.name, "4", "5")
n = string.gsub(n, "3", "4")
n = string.gsub(n, "2", "3")
n = string.gsub(n, "1", "2")
minetest.swap_node(pos, { name = n })
end
})
--
-- grows a pumpkin
--
minetest.register_abm({
nodenames = { "crops:pumpkin_plant_5" },
neighbors = { "group:soil" },
interval = crops.settings.interval,
chance = crops.settings.chance,
action = function(pos, node, active_object_count, active_object_count_wider)
if not crops.can_grow(pos) then
return
end
for face = 1, 4 do
local t = { x = pos.x + faces[face].x, y = pos.y, z = pos.z + faces[face].z }
if minetest.get_node(t).name == "crops:pumpkin" then
return
end
end
local r = math.random(1, 4)
local t = { x = pos.x + faces[r].x, y = pos.y, z = pos.z + faces[r].z }
local n = minetest.get_node(t)
if n.name == "ignore" then
return
end
if minetest.registered_nodes[minetest.get_node({ x = t.x, y = t.y - 1, z = t.z }).name].walkable == false then
return
end
if minetest.registered_nodes[n.name].drawtype == "plantlike" or
minetest.registered_nodes[n.name].groups.flora == 1 or
n.name == "air" then
minetest.set_node(t, {name = "crops:pumpkin", param2 = faces[r].m})
local meta = minetest.get_meta(pos)
local ttl = meta:get_int("crops_pumpkin_ttl")
local damage = meta:get_int("crops_damage")
if ttl == 0 then
-- damage 0 - regrows 3-4
-- damage 50 - drops 1-2
-- damage 100 - drops 0-1
ttl = math.random(3 - (3 * (damage / 100)), 4 - (3 * (damage / 100)))
end
if ttl > 1 then
minetest.swap_node(pos, {name = "crops:pumpkin_plant_5_attached", param2 = faces[r].r})
meta:set_int("crops_pumpkin_ttl", ttl - 1)
else
crops.die(pos)
end
local water = meta:get_int("crops_water")
-- growing a pumpkin costs 25 water!
meta:set_int("crops_water", math.max(0, water - 25))
end
end
})
--
-- return a pumpkin to a normal one if there is no pumpkin attached, so it can
-- grow a new pumpkin again
--
minetest.register_abm({
nodenames = { "crops:pumpkin_plant_5_attached" },
interval = crops.settings.interval,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
for face = 1, 4 do
local t = { x = pos.x + faces[face].x, y = pos.y, z = pos.z + faces[face].z }
if minetest.get_node(t).name == "crops:pumpkin" then
return
end
end
local meta = minetest.get_meta(pos)
local ttl = meta:get_int("crops_pumpkin_ttl")
if ttl > 1 then
minetest.swap_node(pos, { name = "crops:pumpkin_plant_4" })
meta:set_int("crops_pumpkin_ttl", ttl)
else
crops.die(pos)
end
end
})
crops.pumpkin_die = function(pos)
minetest.set_node(pos, { name = "crops:pumpkin_plant_6" })
end
local properties = {
die = crops.pumpkin_die,
waterstart = 40,
wateruse = 1,
night = 5,
soak = 80,
soak_damage = 90,
wither = 10,
wither_damage = 5,
}
crops.register({ name = "crops:pumpkin_plant_1", properties = properties })
crops.register({ name = "crops:pumpkin_plant_2", properties = properties })
crops.register({ name = "crops:pumpkin_plant_3", properties = properties })
crops.register({ name = "crops:pumpkin_plant_4", properties = properties })
crops.register({ name = "crops:pumpkin_plant_5", properties = properties })
crops.register({ name = "crops:pumpkin_plant_5_attached", properties = properties })

162
worldmods/crops/readme.md Normal file
View File

@ -0,0 +1,162 @@
## Crops - more farming crops mod for minetest
Copyright (C) 2015 - Auke Kok <sofar@foo-projects.org>
This minetest mod expands the basic set of farming-related crops that
`minetest_game` offers. A list of crops/crafts is below.
## Configuration
A default configuration file, `crops_settings.txt` will be added
to your world folder that contains suggested `easy`, `normal` (the
default) and `difficult` settings for this mod. You can currently tune
the ABM interval/chance, and required light level for plant growth.
## Hydration mechanic
This feature is disabled in the `easy` setting.
Plants need water. Plants need more water when they grow. This mod
implements mechanics of plant hydration and what happens when you
over-water or not water your plants properly: Plants may wither or
soak, and if they wither/soak too much, the plant will get damaged.
You can see that plants are under stress visually. When a plant
withers, there will be particles that are steam/smoke-like floating
upwards from the plant. When a plant is over-watered, water bubbles
can be seen at the plant base. These are implemented as particles.
In the default difficulty settings, plants don't accrue enough damage
to kill the plant. But at difficult settings, withering will end up
resulting in plant death, or the loss of crop entirely. At default
settings, plants will yield significantly less harvest if not taken
care of! So if you do decide to not water your plants, make sure you
don't let them sit around for days and harvest them as soon as they
are ripe to limit the effects.
Environment factors can influence hydration: nearby water, night time
moisture. And of course, the watering can. The watering can holds
20 watering charges, and it takes 3-4 charges to water a plant from
completely dry to maximum wetness. Some plants will want more water,
some will do better with less, so make sure you use a hydrometer to
measure plant humidity. Recipes for the watering can and hydrometer
are listed below.
## Plants
1. Melons and pumpkins
Melon plants grow from melon seeds. Once a plant is mature (there
are 5 stages) it will spawn a melon block adjacent to the plant.
The melon block can be harvested by punching, and yields 3-5
melon slices. The melon slice can be crafted to a melon seed.
Pumpkins grow from pumpkin seeds, and are harvested to yield a
pumpkin block. Each block can be cooked to yield one or more
roast pumpkin chunks, which can be eaten. You can also craft
the blocks to seeds. A pumpkin plant will only yield limited amounts
of pumpkins. After a while they automatically wither.
2. Corn.
Corn plants are 2 blocks high, and yield corn cobs. These can be
cooked to corn-on-the-cob, or processed to make corn seed (corn
kernels, basically).
Digging a mature plant yields the corn cob. A harvested corn plant
"wilts", and needs to be dug away to make the land usable, or can
be left as ornamental 2-block plant. Digging either top or bottom
block works in all cases.
3. Tomatoes.
Tomatoes appear to work simple enough, until you harvest them
the first time: The plant stays! However, after the 3rd to 5th
harvest, the plant wilts and needs to be removed, since no more
tomatoes will grow on the plant. Per harvest you can get 1-2
tomatoes only. You can craft the tomatoes to tomato seeds, as
expected.
4. Potatoes.
The plants themselves don't drop anything. Only if the plant matures
can you dig potatoes from the soil. If you can reach the soil from the
side you can save yourself one dig by digging the soil as that will
remove the plant from the top, but otherwise you need to dig twice:
once to remove the plant, once to dig out the potatoes.
You get 3-5 potatoes. Each potato gives one (set of) "potato eyes"
which are the clones that can grow back to potatoes. Be careful not
to dig the plant when there's flowers! You have to wait until the soil
below shows potatoes. It's fairly easy to see the difference, though.
5. Green Beans
These green beans are unnaturally green, but there's so many
of them that grow on a vine! Sadly, these beans don't grow beans
unsupported, so you stick some sticks together to make a beanpole,
something like this way:
empty empty empty
stick empty stick
stick empty stick
There, that should help the viney bean plant to grow to 2 meters
high. It has remarkable purple flowers, that pop all over the plant
just before the beans grow.
Sadly, once the beans are picked, this plant turns into an unusable
mess that makes it hard for the next plant to grow on the beanpole,
so you salvage the beanpole's sticks after harvesting in order to
make more beanpoles again. It's a bit of work, but worth it, these
beans are delicious!
## Cooking / Crafting
The corn cobs can be cooked directly to make Corn-on-the-Cob.
This mod includes a bowl recipe. The bowl is made from clay lumps,
which results in an unbaked clay bowl that needs to be baked in an
oven to be usable:
empty empty empty
clay_lump empty clay_lump
empty clay_lump empty
Pumpkin blocks can be cooked whole, and yield roasted pumpkin. It's
okay as food, but it takes a lot of work.
You can fill these bowls (or any group:food_bowl) with vegetables to
craft an uncooked vegetable stew:
empty empty empty
grean_beans potato tomato
empty clay_bowl empty
The uncooked vegetable stew obviously needs to be cooked as well in
an oven. The resulting Vegetable Stew bowl gives a lot of hears back,
which is worth the effort.
The watering can can be made as follows:
steel_ingot empty empty
steel_ingot empty steel_ingot
empty steel_ingot empty
To fill the watering can, left click any block of water. To use,
left click a plant. The damage bar on the icon indicates the fill
level of the watering can.
The hydrometer can be crafted like this:
mese_crystal_fragment empty empty
empty steel_ingot empty
empty empty steel_ingot
Left-click any plant with the hydrometer, and the charge bar indicates
the humidity level of the plant: a dry plant will have 0% humidity
and be a small red bar or no bar at all, and a soaked plant will
have a full green bar. Be careful though! Some plants prefer to be
at mid-level (yellow) instead of full wetness!

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Some files were not shown because too many files have changed in this diff Show More