Add files via upload

master
Grizzly-Adam 2018-01-07 19:49:45 -06:00 committed by GitHub
parent acee8f9778
commit 98cdce4a72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 2283 additions and 0 deletions

40
LICENSE Normal file
View File

@ -0,0 +1,40 @@
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
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~
Peppers by Grizzly Adam

10
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

5
depends.txt Normal file
View File

@ -0,0 +1,5 @@
craft_guide?
default
farming
intllib?
bbq?

5
description.txt Normal file
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

386
init.lua Normal file
View File

@ -0,0 +1,386 @@
--[[
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")
dofile(modpath .. "/pepper.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!"))

44
intllib.lua Normal file
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

48
mapgen.lua Normal file
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
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
mod.conf Normal file
View File

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

238
pepper.lua Normal file
View File

@ -0,0 +1,238 @@
--[[
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.
--]]
if minetest.registered_items["bbq:peppercorn"] ~= nil then
minetest.override_item("bbq:peppercorn", {
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:pepper_plant_1", param2 = 1})
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end
})
end
minetest.register_node("crops:pepper_ground", {
description = ("Ground Pepper"),
inventory_image = "crops_pepper_ground.png",
wield_image = "crops_pepper_ground.png",
drawtype = "plantlike",
tiles = {"crops_pepper_ground.png"},
groups = {vessel = 1, pepper_ground=1, dig_immediate = 3, attached_node = 1},
sounds = default.node_sound_glass_defaults(),
})
minetest.register_craft( {
output = "crops:pepper_ground",
recipe = {
{"", "", ""},
{"", "crops:peppercorn", ""},
{"", "vessels:glass_bottle", ""}
}
})
-- Intllib
local S = crops.intllib
minetest.register_node("crops:peppercorn", {
description = S("Peppercorn"),
inventory_image = "crops_peppercorn.png",
wield_image = "crops_peppercorn.png",
tiles = { "crops_pepper_plant_1.png" },
drawtype = "plantlike",
paramtype2 = "meshoptions",
waving = 1,
sunlight_propagates = true,
use_texture_alpha = true,
walkable = false,
paramtype = "light",
node_placement_prediction = "crops:pepper_plant_1",
groups = { peppercorn=1, 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:pepper_plant_1", param2 = 1})
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end
})
for stage = 1, 4 do
minetest.register_node("crops:pepper_plant_" .. stage , {
description = S("Pepper plant"),
tiles = { "crops_pepper_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_node("crops:pepper_plant_5" , {
description = S("Pepper plant"),
tiles = { "crops_pepper_plant_5.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.45, 0.45}
},
on_dig = function(pos, node, digger)
local drops = {}
for i = 1, math.random(1, 2) do
table.insert(drops, "crops:pepper")
end
core.handle_node_drops(pos, drops, digger)
local meta = minetest.get_meta(pos)
local ttl = meta:get_int("crops_pepper_ttl")
if ttl > 1 then
minetest.swap_node(pos, { name = "crops:pepper_plant_4", param2 = 1})
meta:set_int("crops_pepper_ttl", ttl - 1)
else
crops.die(pos)
end
end
})
minetest.register_node("crops:pepper_plant_6", {
description = S("Pepper plant"),
tiles = { "crops_pepper_plant_6.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.45, 0.45}
},
})
minetest.register_craftitem("crops:pepper", {
description = S("Pepper"),
inventory_image = "crops_pepper.png",
on_use = minetest.item_eat(1),
groups = { pepper=1 },
})
minetest.register_craft({
type = "shapeless",
output = "crops:peppercorn",
recipe = { "crops:pepper" }
})
--
-- grows a plant to mature size
--
minetest.register_abm({
nodenames = { "crops:pepper_plant_1", "crops:pepper_plant_2", "crops:pepper_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 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, param2 = 1 })
end
})
--
-- grows a pepper
--
minetest.register_abm({
nodenames = { "crops:pepper_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 meta = minetest.get_meta(pos)
local ttl = meta:get_int("crops_pepper_ttl")
local damage = meta:get_int("crops_damage")
if ttl == 0 then
-- damage 0 - drops 4-6
-- damage 50 - drops 2-3
-- damage 100 - drops 0-1
ttl = math.random(4 - (4 * (damage / 100)), 6 - (5 * (damage / 100)))
end
if ttl > 1 then
minetest.swap_node(pos, { name = "crops:pepper_plant_5", param2 = 1 })
meta:set_int("crops_pepper_ttl", ttl)
else
crops.die(pos)
end
end
})
crops.pepper_die = function(pos)
minetest.set_node(pos, { name = "crops:pepper_plant_6", param2 = 1 })
end
local properties = {
die = crops.pepper_die,
waterstart = 19,
wateruse = 1,
night = 5,
soak = 80,
soak_damage = 90,
wither = 20,
wither_damage = 10,
}
crops.register({ name = "crops:pepper_plant_1", properties = properties })
crops.register({ name = "crops:pepper_plant_2", properties = properties })
crops.register({ name = "crops:pepper_plant_3", properties = properties })
crops.register({ name = "crops:pepper_plant_4", properties = properties })
crops.register({ name = "crops:pepper_plant_5", properties = properties })

309
polebean.lua Normal file
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
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
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 })

166
readme.md Normal file
View File

@ -0,0 +1,166 @@
## 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!
6. Peppers
Peppers work the same as tomatoes. The seeds are peppercorns, when can be crafted with a glass bottle to make ground pepper.
## 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!

201
tomato.lua Normal file
View File

@ -0,0 +1,201 @@
--[[
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:tomato_seed", {
description = S("Tomato seed"),
inventory_image = "crops_tomato_seed.png",
wield_image = "crops_tomato_seed.png",
tiles = { "crops_tomato_plant_1.png" },
drawtype = "plantlike",
paramtype2 = "meshoptions",
waving = 1,
sunlight_propagates = true,
use_texture_alpha = true,
walkable = false,
paramtype = "light",
node_placement_prediction = "crops:tomato_plant_1",
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:tomato_plant_1", param2 = 1})
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end
})
for stage = 1, 4 do
minetest.register_node("crops:tomato_plant_" .. stage , {
description = S("Tomato plant"),
tiles = { "crops_tomato_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_node("crops:tomato_plant_5" , {
description = S("Tomato plant"),
tiles = { "crops_tomato_plant_5.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.45, 0.45}
},
on_dig = function(pos, node, digger)
local drops = {}
for i = 1, math.random(1, 2) do
table.insert(drops, "crops:tomato")
end
core.handle_node_drops(pos, drops, digger)
local meta = minetest.get_meta(pos)
local ttl = meta:get_int("crops_tomato_ttl")
if ttl > 1 then
minetest.swap_node(pos, { name = "crops:tomato_plant_4", param2 = 1})
meta:set_int("crops_tomato_ttl", ttl - 1)
else
crops.die(pos)
end
end
})
minetest.register_node("crops:tomato_plant_6", {
description = S("Tomato plant"),
tiles = { "crops_tomato_plant_6.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.45, 0.45}
},
})
minetest.register_craftitem("crops:tomato", {
description = S("Tomato"),
inventory_image = "crops_tomato.png",
on_use = minetest.item_eat(1)
})
minetest.register_craft({
type = "shapeless",
output = "crops:tomato_seed",
recipe = { "crops:tomato" }
})
--
-- grows a plant to mature size
--
minetest.register_abm({
nodenames = { "crops:tomato_plant_1", "crops:tomato_plant_2", "crops:tomato_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 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, param2 = 1 })
end
})
--
-- grows a tomato
--
minetest.register_abm({
nodenames = { "crops:tomato_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 meta = minetest.get_meta(pos)
local ttl = meta:get_int("crops_tomato_ttl")
local damage = meta:get_int("crops_damage")
if ttl == 0 then
-- damage 0 - drops 4-6
-- damage 50 - drops 2-3
-- damage 100 - drops 0-1
ttl = math.random(4 - (4 * (damage / 100)), 6 - (5 * (damage / 100)))
end
if ttl > 1 then
minetest.swap_node(pos, { name = "crops:tomato_plant_5", param2 = 1 })
meta:set_int("crops_tomato_ttl", ttl)
else
crops.die(pos)
end
end
})
crops.tomato_die = function(pos)
minetest.set_node(pos, { name = "crops:tomato_plant_6", param2 = 1 })
end
local properties = {
die = crops.tomato_die,
waterstart = 19,
wateruse = 1,
night = 5,
soak = 80,
soak_damage = 90,
wither = 20,
wither_damage = 10,
}
crops.register({ name = "crops:tomato_plant_1", properties = properties })
crops.register({ name = "crops:tomato_plant_2", properties = properties })
crops.register({ name = "crops:tomato_plant_3", properties = properties })
crops.register({ name = "crops:tomato_plant_4", properties = properties })
crops.register({ name = "crops:tomato_plant_5", properties = properties })

125
tools.lua Normal file
View File

@ -0,0 +1,125 @@
--[[
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_tool("crops:watering_can", {
description = S("Watering Can"),
inventory_image = "crops_watering_can.png",
liquids_pointable = true,
range = 2.5,
stack_max = 1,
wear = 65535,
tool_capabilities = {},
on_use = function(itemstack, user, pointed_thing)
local pos = pointed_thing.under
local ppos = pos
if not pos then
return itemstack
end
-- filling it up?
local wear = itemstack:get_wear()
if minetest.get_item_group(minetest.get_node(pos).name, "water") >= 3 then
if wear ~= 1 then
minetest.sound_play("crops_watercan_entering", {pos=pos, gain=0.8})
minetest.after(math.random()/2, function(p)
if math.random(2) == 1 then
minetest.sound_play("crops_watercan_splash_quiet", {pos=p, gain=0.1})
end
if math.random(3) == 1 then
minetest.after(math.random()/2, function(pp)
minetest.sound_play("crops_watercan_splash_small", {pos=pp, gain=0.7})
end, p)
end
if math.random(3) == 1 then
minetest.after(math.random()/2, function(pp)
minetest.sound_play("crops_watercan_splash_big", {pos=pp, gain=0.7})
end, p)
end
end, pos)
itemstack:set_wear(1)
end
return itemstack
end
-- using it on a top-half part of a plant?
local meta = minetest.get_meta(pos)
if meta:get_int("crops_top_half") == 1 then
meta = minetest.get_meta({x=pos.x, y=pos.y-1, z=pos.z})
end
-- using it on a plant?
local water = meta:get_int("crops_water")
if water < 1 then
return itemstack
end
-- empty?
if wear == 65534 then
return itemstack
end
crops.particles(ppos, 2)
minetest.sound_play("crops_watercan_watering", {pos=pos, gain=0.8})
water = math.min(water + crops.settings.watercan, crops.settings.watercan_max)
meta:set_int("crops_water", water)
if not minetest.setting_getbool("creative_mode") then
itemstack:set_wear(math.min(65534, wear + (65535 / crops.settings.watercan_uses)))
end
return itemstack
end,
})
minetest.register_tool("crops:hydrometer", {
description = S("Hydrometer"),
inventory_image = "crops_hydrometer.png",
liquids_pointable = false,
range = 2.5,
stack_max = 1,
tool_capabilities = {
},
on_use = function(itemstack, user, pointed_thing)
local pos = pointed_thing.under
if not pos then
return itemstack
end
-- doublesize plant?
local meta = minetest.get_meta(pos)
if meta:get_int("crops_top_half") == 1 then
meta = minetest.get_meta({x=pos.x, y=pos.y-1, z=pos.z})
end
-- using it on a plant?
local water = meta:get_int("crops_water")
if water == nil then
itemstack:set_wear(65534)
return itemstack
end
itemstack:set_wear(65535 - ((65534 / 100) * water))
return itemstack
end,
})
minetest.register_craft({
output = "crops:watering_can",
recipe = {
{ "default:steel_ingot", "", "" },
{ "default:steel_ingot", "", "default:steel_ingot" },
{ "", "default:steel_ingot", "" },
},
})
minetest.register_craft({
output = "crops:hydrometer",
recipe = {
{ "default:mese_crystal_fragment", "", "" },
{ "", "default:steel_ingot", "" },
{ "", "", "default:steel_ingot" },
},
})