master
D00Med 2017-02-08 07:03:29 +10:00
parent d6d1fe9a69
commit 0c43df23e9
20 changed files with 1995 additions and 757 deletions

View File

@ -1,37 +1,149 @@
Minetest Game mod: farming
==========================
See license.txt for license information.
Farming Redo Mod
by TenPlus1
Authors of source code
----------------------
Originally by PilzAdam (MIT)
webdesigner97 (MIT)
Various Minetest developers and contributors (MIT)
https://forum.minetest.net/viewtopic.php?id=9019
Authors of media (textures)
---------------------------
Created by PilzAdam (CC BY 3.0):
Farming Redo is a simplified version of the built-in farming mod in minetest and comes with wheat, cotton, carrot, cucumber, potato and tomato to start out with which spawn throughout the map... new foods need only be planted on tilled soil so no seeds are required, original wheat and cotton will require seeds which are found inside normal and jungle grass...
This mod works by adding your new plant to the {growing=1} group and numbering the stages from _1 to as many stages as you like, but the underscore MUST be used only once in the node name to separate plant from stage number e.g.
"farming:cotton_1" through to "farming:cotton_8"
"farming:wheat_1" through to "farming:wheat_8"
"farming:cucumber_4" through to "farming:cucumber_4"
Changelog:
1.22 - Added grape bushes at high climates which can be cultivated into grape vines using trellis (9 sticks).
1.21 - Added auto-refill code for planting crops (thanks crabman77), also fixed a few bugs
1.20b- Tidied code, made api compatible with new 0.4.13 changes and changed to soil texture overlays
1.20 - NEW growing routine added that allows crops to grow while player is away doing other things (thanks prestidigitator)
1.14 - Added Green Beans from Crops mod (thanks sofar), little bushels in the wild but need to be grown using beanpoles crafted with 4 sticks (2 either side)
1.13 - Fixed seed double-placement glitch. Mapgen now uses 0.4.12+ for plant generation
1.12 - Player cannot place seeds in protected area, also growing speeds changed to match defaults
1.11 - Added Straw Bale, streamlined growing abm a little, fixed melon rotation bug with screwdriver
1.10 - Added Blueberry Bush and Blueberry Muffins, also Pumpkin/Melon easier to pick up, added check for unloaded map
1.09 - Corn now uses single nodes instead of 1 ontop of the other, Ethanol recipe is more expensive (requires 5 corn) and some code cleanup.
1.08 - Added Farming Plus compatibility, plus can be removed and no more missing nodes
1.07 - Added Rhubarb and Rhubarb Pie
1.06 - register_hoe and register_plant added for compatibility with default farming mod, although any plants registered will use farming redo to grow
1.05 - Added Raspberry Bushels and Raspberry Smoothie
1.04 - Added Donuts... normal, chocolate and apple... and a few code cleanups and now compatible with jungletree's from MoreTrees mod
1.03 - Bug fixes and more compatibility as drop-in replacement for built-in farming mod
1.02 - Added farming.mod string to help other mods identify which farming mod is running, if it returns "redo" then you're using this one, "" empty is built-in mod
1.01 - Crafting coffee or ethanol returns empty bucket/bottle, also Cocoa spawns a little rarer
1.0 - Added Cocoa which randomly grows on jungle tree's, pods give cocoa beans which can be used to farm more pods on a jungle trunk or make Cookies which have been added (or other treats)
0.9 - Added Pumpkin, Jack 'O Lantern, Pumpkin Slice and Sugar
(a huge thanks to painterly.net for allowing me to use their textures)
0.8 - Added Watermelon and Melon Slice
0.7 - Added Coffee, Coffee Beans, Drinking Cup, Cold and Hot Cup of Coffee
0.6 - Added Corn, Corn on the Cob... Also reworked Abm
0.5 - Added Carrot, Cucumber, Potato (and Baked Potato), Tomato
0.4 - Checks for Protection, also performance changes
0.3 - Added Diamond and Mese hoe
0.2 - Fixed check for wet soil
0.1 - Fixed growing bug
0.0 - Initial release
License of media (textures):
----------------------------
Created by PilzAdam (License: WTFPL):
farming_bread.png
farming_soil.png
farming_soil_wet.png
farming_soil_wet_side.png
farming_string.png
Created by BlockMen (CC BY 3.0):
farming_tool_diamondhoe.png
farming_tool_mesehoe.png
Created by Calinou (License: CC BY-SA):
farming_tool_bronzehoe.png
farming_tool_steelhoe.png
farming_tool_stonehoe.png
farming_tool_woodhoe.png
farming_tool_mesehoe.png
farming_tool_diamondhoe.png
Created by MasterGollum (CC BY 3.0):
farming_straw.png
Created by Gambit (CC BY 3.0):
farming_wheat.png
farming_wheat_*.png
farming_cotton_*.png
farming_flour.png
Created by VanessaE (License: WTFPL):
farming_cotton_seed.png
farming_wheat_seed.png
farming_flour.png
farming_wheat.png
farming_wheat_1.png
farming_wheat_2.png
farming_wheat_3.png
farming_wheat_4.png
farming_wheat_5.png
farming_wheat_5.png
farming_wheat_7.png
farming_wheat_8.png
farming_cotton_1.png
farming_cotton_2.png
farming_cotton_3.png
farming_cotton_4.png
farming_cotton_5.png
farming_cotton_6.png
farming_cotton_7.png
farming_cotton_8.png
Created by Doc (License: WTFPL):
farming_cucumber.png
farming_cucumber_1.png
farming_cucumber_2.png
farming_cucumber_3.png
farming_cucumber_4.png
farming_potato.png
farming_potato_1.png
farming_potato_2.png
farming_potato_3.png
farming_potato_4.png
farming_raspberries.png
farming_raspberry_1.png
farming_raspberry_2.png
farming_raspberry_3.png
farming_raspberry_4.png
Created by Gambit:
default_junglegrass.png
farming_carrot.png
farming_carrot_1.png
farming_carrot_2.png
farming_carrot_3.png
farming_carrot_4.png
farming_carrot_5.png
farming_carrot_6.png
farming_carrot_7.png
farming_carrot_8.png
Created by JoseTheCrafter and edited by TenPlus1:
farming_tomato.png
farming_tomato_1.png
farming_tomato_2.png
farming_tomato_3.png
farming_tomato_4.png
farming_tomato_5.png
farming_tomato_6.png
farming_tomato_7.png
farming_tomato_8.png
Created by GeMinecraft and edited by TenPlus1:
farming_corn.png
farming_corn_cob.png
farming_corn_1.png
farming_corn_2.png
farming_corn_3.png
farming_corn_4.png
farming_corn_5.png
farming_corn_6.png
farming_corn_7.png
farming_corn_8.png
Created by TenPlus1
farming_cocoa_1.png
farming_cocoa_2.png
farming_cocoa_3.png
farming_cocoa_beans.png
farming_cookie.png
farming_raspberry_smoothie.png
farming_rhubarb_1.png
farming_rhubarb_2.png
farming_rhubarb_3.png
farming_rhubarb.png
farming_rhubarb_pie.png

View File

@ -1,389 +0,0 @@
-- Wear out hoes, place soil
-- TODO Ignore group:flower
farming.registered_plants = {}
farming.hoe_on_use = function(itemstack, user, pointed_thing, uses)
local pt = pointed_thing
-- check if pointing at a node
if not pt then
return
end
if pt.type ~= "node" then
return
end
local under = minetest.get_node(pt.under)
local p = {x=pt.under.x, y=pt.under.y+1, z=pt.under.z}
local above = minetest.get_node(p)
-- return if any of the nodes is not registered
if not minetest.registered_nodes[under.name] then
return
end
if not minetest.registered_nodes[above.name] then
return
end
-- check if the node above the pointed thing is air
if above.name ~= "air" then
return
end
-- check if pointing at soil
if minetest.get_item_group(under.name, "soil") ~= 1 then
return
end
-- check if (wet) soil defined
local regN = minetest.registered_nodes
if regN[under.name].soil == nil or regN[under.name].soil.wet == nil or regN[under.name].soil.dry == nil then
return
end
if minetest.is_protected(pt.under, user:get_player_name()) then
minetest.record_protection_violation(pt.under, user:get_player_name())
return
end
if minetest.is_protected(pt.above, user:get_player_name()) then
minetest.record_protection_violation(pt.above, user:get_player_name())
return
end
-- turn the node into soil and play sound
minetest.set_node(pt.under, {name = regN[under.name].soil.dry})
minetest.sound_play("default_dig_crumbly", {
pos = pt.under,
gain = 0.5,
})
if not minetest.setting_getbool("creative_mode") then
-- wear tool
local wdef = itemstack:get_definition()
itemstack:add_wear(65535/(uses-1))
-- tool break sound
if itemstack:get_count() == 0 and wdef.sound and wdef.sound.breaks then
minetest.sound_play(wdef.sound.breaks, {pos = pt.above, gain = 0.5})
end
end
return itemstack
end
-- Register new hoes
farming.register_hoe = function(name, def)
-- Check for : prefix (register new hoes in your mod's namespace)
if name:sub(1,1) ~= ":" then
name = ":" .. name
end
-- Check def table
if def.description == nil then
def.description = "Hoe"
end
if def.inventory_image == nil then
def.inventory_image = "unknown_item.png"
end
if def.recipe == nil then
def.recipe = {
{"air","air",""},
{"","group:stick",""},
{"","group:stick",""}
}
end
if def.max_uses == nil then
def.max_uses = 30
end
-- Register the tool
minetest.register_tool(name, {
description = def.description,
inventory_image = def.inventory_image,
on_use = function(itemstack, user, pointed_thing)
return farming.hoe_on_use(itemstack, user, pointed_thing, def.max_uses)
end,
groups = def.groups,
sound = {breaks = "default_tool_breaks"},
})
-- Register its recipe
if def.material == nil then
minetest.register_craft({
output = name:sub(2),
recipe = def.recipe
})
else
minetest.register_craft({
output = name:sub(2),
recipe = {
{def.material, def.material, ""},
{"", "group:stick", ""},
{"", "group:stick", ""}
}
})
-- Reverse Recipe
minetest.register_craft({
output = name:sub(2),
recipe = {
{"", def.material, def.material},
{"", "group:stick", ""},
{"", "group:stick", ""}
}
})
end
end
-- how often node timers for plants will tick, +/- some random value
local function tick(pos)
minetest.get_node_timer(pos):start(math.random(166, 286))
end
-- how often a growth failure tick is retried (e.g. too dark)
local function tick_again(pos)
minetest.get_node_timer(pos):start(math.random(40, 80))
end
-- Seed placement
farming.place_seed = function(itemstack, placer, pointed_thing, plantname)
local pt = pointed_thing
-- check if pointing at a node
if not pt then
return itemstack
end
if pt.type ~= "node" then
return itemstack
end
local under = minetest.get_node(pt.under)
local above = minetest.get_node(pt.above)
if minetest.is_protected(pt.under, placer:get_player_name()) then
minetest.record_protection_violation(pt.under, placer:get_player_name())
return
end
if minetest.is_protected(pt.above, placer:get_player_name()) then
minetest.record_protection_violation(pt.above, placer:get_player_name())
return
end
-- return if any of the nodes is not registered
if not minetest.registered_nodes[under.name] then
return itemstack
end
if not minetest.registered_nodes[above.name] then
return itemstack
end
-- check if pointing at the top of the node
if pt.above.y ~= pt.under.y+1 then
return itemstack
end
-- check if you can replace the node above the pointed node
if not minetest.registered_nodes[above.name].buildable_to then
return itemstack
end
-- check if pointing at soil
if minetest.get_item_group(under.name, "soil") < 2 then
return itemstack
end
-- add the node and remove 1 item from the itemstack
minetest.add_node(pt.above, {name = plantname, param2 = 1})
tick(pt.above)
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end
farming.grow_plant = function(pos, elapsed)
local node = minetest.get_node(pos)
local name = node.name
local def = minetest.registered_nodes[name]
if not def.next_plant then
-- disable timer for fully grown plant
return
end
-- grow seed
if minetest.get_item_group(node.name, "seed") and def.fertility then
local soil_node = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z})
if not soil_node then
tick_again(pos)
return
end
-- omitted is a check for light, we assume seeds can germinate in the dark.
for _, v in pairs(def.fertility) do
if minetest.get_item_group(soil_node.name, v) ~= 0 then
local placenode = {name = def.next_plant}
if def.place_param2 then
placenode.param2 = def.place_param2
end
minetest.swap_node(pos, placenode)
if minetest.registered_nodes[def.next_plant].next_plant then
tick(pos)
return
end
end
end
return
end
-- check if on wet soil
local below = minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z})
if minetest.get_item_group(below.name, "soil") < 3 then
tick_again(pos)
return
end
-- check light
local light = minetest.get_node_light(pos)
if not light or light < def.minlight or light > def.maxlight then
tick_again(pos)
return
end
-- grow
local placenode = {name = def.next_plant}
if def.place_param2 then
placenode.param2 = def.place_param2
end
minetest.swap_node(pos, placenode)
-- new timer needed?
if minetest.registered_nodes[def.next_plant].next_plant then
tick(pos)
end
return
end
-- Register plants
farming.register_plant = function(name, def)
local mname = name:split(":")[1]
local pname = name:split(":")[2]
-- Check def table
if not def.description then
def.description = "Seed"
end
if not def.inventory_image then
def.inventory_image = "unknown_item.png"
end
if not def.steps then
return nil
end
if not def.minlight then
def.minlight = 1
end
if not def.maxlight then
def.maxlight = 14
end
if not def.fertility then
def.fertility = {}
end
farming.registered_plants[pname] = def
-- Register seed
local lbm_nodes = {mname .. ":seed_" .. pname}
local g = {seed = 1, snappy = 3, attached_node = 1, flammable = 2}
for k, v in pairs(def.fertility) do
g[v] = 1
end
minetest.register_node(":" .. mname .. ":seed_" .. pname, {
description = def.description,
tiles = {def.inventory_image},
inventory_image = def.inventory_image,
wield_image = def.inventory_image,
drawtype = "signlike",
groups = g,
paramtype = "light",
paramtype2 = "wallmounted",
place_param2 = def.place_param2 or nil, -- this isn't actually used for placement
walkable = false,
sunlight_propagates = true,
selection_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
},
fertility = def.fertility,
sounds = default.node_sound_dirt_defaults({
dig = {name = "", gain = 0},
dug = {name = "default_grass_footstep", gain = 0.2},
place = {name = "default_place_node", gain = 0.25},
}),
on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, mname .. ":seed_" .. pname)
end,
next_plant = mname .. ":" .. pname .. "_1",
on_timer = farming.grow_plant,
minlight = def.minlight,
maxlight = def.maxlight,
})
-- Register harvest
minetest.register_craftitem(":" .. mname .. ":" .. pname, {
description = pname:gsub("^%l", string.upper),
inventory_image = mname .. "_" .. pname .. ".png",
groups = {flammable = 2},
})
-- Register growing steps
for i = 1, def.steps do
local drop = {
items = {
{items = {mname .. ":" .. pname}, rarity = 9 - i},
{items = {mname .. ":" .. pname}, rarity= 18 - i * 2},
{items = {mname .. ":seed_" .. pname}, rarity = 9 - i},
{items = {mname .. ":seed_" .. pname}, rarity = 18 - i * 2},
}
}
local nodegroups = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1}
nodegroups[pname] = i
local next_plant = nil
if i < def.steps then
next_plant = mname .. ":" .. pname .. "_" .. (i + 1)
lbm_nodes[#lbm_nodes + 1] = mname .. ":" .. pname .. "_" .. i
end
minetest.register_node(":" .. mname .. ":" .. pname .. "_" .. i, {
drawtype = "plantlike",
waving = 1,
tiles = {mname .. "_" .. pname .. "_" .. i .. ".png"},
paramtype = "light",
paramtype2 = def.paramtype2 or nil,
place_param2 = def.place_param2 or nil,
walkable = false,
buildable_to = true,
drop = drop,
selection_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
},
groups = nodegroups,
sounds = default.node_sound_leaves_defaults(),
next_plant = next_plant,
on_timer = farming.grow_plant,
minlight = def.minlight,
maxlight = def.maxlight,
})
end
-- replacement LBM for pre-nodetimer plants
minetest.register_lbm({
name = ":" .. mname .. ":start_nodetimer_" .. pname,
nodenames = lbm_nodes,
action = function(pos, node)
tick_again(pos)
end,
})
-- Return
local r = {
seed = mname .. ":seed_" .. pname,
harvest = mname .. ":" .. pname
}
return r
end

101
mods/farming/carrot.lua Normal file
View File

@ -0,0 +1,101 @@
--carrot crop, textures by tobyplowy(aka toby109tt)
minetest.register_craftitem("farming:carrot", {
description = "Carrot",
inventory_image = "farming_carrot.png",
on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, "farming:carrot_1")
end,
on_use = minetest.item_eat(2),
})
minetest.register_node("farming:carrot_1", {
drawtype = "plantlike",
tiles = {"farming_carrot_1.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:carrot_2", {
drawtype = "plantlike",
tiles = {"farming_carrot_2.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:carrot_3", {
drawtype = "plantlike",
tiles = {"farming_carrot_3.png"},
paramtype = "light",
waving = 1,
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:carrot_4", {
drawtype = "plantlike",
tiles = {"farming_carrot_4.png"},
paramtype = "light",
waving = 1,
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = {
items = {
{items = {'farming:carrot'}, rarity = 1},
{items = {'farming:carrot'}, rarity = 2},
{items = {'farming:carrot'}, rarity = 3},
}
},
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:carrot_5", {
drawtype = "plantlike",
tiles = {"farming_carrot_5.png^[colorize:brown:50"},
paramtype = "light",
waving = 1,
drop = "",
walkable = false,
buildable_to = true,
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})

View File

@ -0,0 +1,97 @@
-- is Ethereal mod installed?
local eth = minetest.get_modpath("ethereal") or nil
-- Banana
if eth then
minetest.register_alias("farming_plus:banana_sapling", "ethereal:banana_tree_sapling")
minetest.register_alias("farming_plus:banana_leaves", "ethereal:bananaleaves")
minetest.register_alias("farming_plus:banana", "ethereal:banana")
else
minetest.register_alias("farming_plus:banana_sapling", "default:sapling")
minetest.register_alias("farming_plus:banana_leaves", "default:leaves")
minetest.register_alias("farming_plus:banana", "default:apple")
end
-- Carrot
minetest.register_alias("farming_plus:carrot_seed", "farming:carrot")
minetest.register_alias("farming_plus:carrot_1", "farming:carrot_1")
minetest.register_alias("farming_plus:carrot_2", "farming:carrot_4")
minetest.register_alias("farming_plus:carrot_3", "farming:carrot_6")
minetest.register_alias("farming_plus:carrot", "farming:carrot_8")
-- Cocoa
minetest.register_alias("farming_plus:cocoa_sapling", "farming:cocoa_beans")
minetest.register_alias("farming_plus:cocoa_leaves", "default:leaves")
minetest.register_alias("farming_plus:cocoa", "default:apple")
minetest.register_alias("farming_plus:cocoa_bean", "farming:cocoa_beans")
-- Orange
minetest.register_alias("farming_plus:orange_1", "farming:tomato_1")
minetest.register_alias("farming_plus:orange_2", "farming:tomato_4")
minetest.register_alias("farming_plus:orange_3", "farming:tomato_6")
minetest.register_alias("farming_plus:orange", "farming:tomato_8")
if eth then
minetest.register_alias("farming_plus:orange_item", "ethereal:orange")
minetest.register_alias("farming_plus:orange_seed", "ethereal:orange_tree_sapling")
else
minetest.register_alias("farming_plus:orange_item", "default:apple")
minetest.register_alias("farming_plus:orange_seed", "default:sapling")
end
-- Potato
minetest.register_alias("farming_plus:potato_item", "farming:potato")
minetest.register_alias("farming_plus:potato_1", "farming:potato_1")
minetest.register_alias("farming_plus:potato_2", "farming:potato_2")
minetest.register_alias("farming_plus:potato", "farming:potato_3")
minetest.register_alias("farming_plus:potato_seed", "farming:potato")
-- Pumpkin
minetest.register_alias("farming:pumpkin_seed", "farming:pumpkin_slice")
minetest.register_alias("farming:pumpkin_face", "farming:pumpkin")
minetest.register_alias("farming:pumpkin_face_light", "farming:jackolantern")
minetest.register_alias("farming:big_pumpkin", "farming:pumpkin")
minetest.register_alias("farming:big_pumpkin_side", "air")
minetest.register_alias("farming:big_pumpkin_corner", "air")
minetest.register_alias("farming:big_pumpkin_top", "air")
minetest.register_alias("farming:scarecrow", "farming:pumpkin")
minetest.register_alias("farming:scarecrow_bottom", "default:fence_wood")
minetest.register_alias("farming:scarecrow_light", "farming:jackolantern")
minetest.register_alias("farming:pumpkin_flour", "farming:pumpkin_dough")
-- Rhubarb
minetest.register_alias("farming_plus:rhubarb_seed", "farming:rhubarb")
minetest.register_alias("farming_plus:rhubarb_1", "farming:rhubarb_1")
minetest.register_alias("farming_plus:rhubarb_2", "farming:rhubarb_2")
minetest.register_alias("farming_plus:rhubarb", "farming:rhubarb_3")
minetest.register_alias("farming_plus:rhubarb_item", "farming:rhubarb")
-- Strawberry
if eth then
minetest.register_alias("farming_plus:strawberry_item", "ethereal:strawberry")
minetest.register_alias("farming_plus:strawberry_seed", "ethereal:strawberry")
minetest.register_alias("farming_plus:strawberry_1", "ethereal:strawberry_1")
minetest.register_alias("farming_plus:strawberry_2", "ethereal:strawberry_3")
minetest.register_alias("farming_plus:strawberry_3", "ethereal:strawberry_5")
minetest.register_alias("farming_plus:strawberry", "ethereal:strawberry_7")
else
minetest.register_alias("farming_plus:strawberry_item", "farming:raspberries")
minetest.register_alias("farming_plus:strawberry_seed", "farming:raspberries")
minetest.register_alias("farming_plus:strawberry_1", "farming:raspberry_1")
minetest.register_alias("farming_plus:strawberry_2", "farming:raspberry_2")
minetest.register_alias("farming_plus:strawberry_3", "farming:raspberry_3")
minetest.register_alias("farming_plus:strawberry", "farming:raspberry_4")
end
-- Tomato
minetest.register_alias("farming_plus:tomato_seed", "farming:tomato")
minetest.register_alias("farming_plus:tomato_item", "farming:tomato")
minetest.register_alias("farming_plus:tomato_1", "farming:tomato_2")
minetest.register_alias("farming_plus:tomato_2", "farming:tomato_4")
minetest.register_alias("farming_plus:tomato_3", "farming:tomato_6")
minetest.register_alias("farming_plus:tomato", "farming:tomato_8")
-- Weed
minetest.register_alias("farming:weed", "default:grass_2")

103
mods/farming/corn.lua Normal file
View File

@ -0,0 +1,103 @@
--corn crop, textures by tobyplowy(aka toby109tt)
minetest.register_craftitem("farming:corn", {
description = "Corn",
inventory_image = "farming_corn.png",
on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, "farming:corn_1")
end,
on_use = minetest.item_eat(3),
})
minetest.register_node("farming:corn_1", {
drawtype = "plantlike",
tiles = {"farming_corn_1.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:corn_2", {
drawtype = "plantlike",
tiles = {"farming_corn_2.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:corn_3", {
drawtype = "plantlike",
tiles = {"farming_corn_3.png"},
paramtype = "light",
waving = 1,
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:corn_4", {
drawtype = "plantlike",
tiles = {"farming_corn_4.png"},
visual_scale = 1.45,
paramtype = "light",
waving = 1,
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = {
items = {
{items = {'farming:corn'}, rarity = 1},
{items = {'farming:corn'}, rarity = 2},
{items = {'farming:corn'}, rarity = 3},
}
},
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:corn_5", {
drawtype = "plantlike",
tiles = {"farming_corn_5.png^[colorize:brown:50"},
visual_scale = 1.45,
paramtype = "light",
waving = 1,
drop = "",
walkable = false,
buildable_to = true,
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})

205
mods/farming/cotton.lua Normal file
View File

@ -0,0 +1,205 @@
-- Cotton Seed
--minetest.register_craftitem("farming:seed_cotton", {
-- description = "Cotton Seed",
-- inventory_image = "farming_cotton_seed.png",
-- on_place = function(itemstack, placer, pointed_thing)
-- return farming.place_seed(itemstack, placer, pointed_thing, "farming:cotton_1")
-- end,
--})
minetest.register_node("farming:seed_cotton", {
description = "Cotton Seed",
tiles = {"farming_cotton_seed.png"},
inventory_image = "farming_cotton_seed.png",
wield_image = "farming_cotton_seed.png",
drawtype = "signlike",
groups = {seed = 1, snappy = 3, attached_node = 1},
paramtype = "light",
paramtype2 = "wallmounted",
walkable = false,
sunlight_propagates = true,
selection_box = farming.select,
on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, "farming:cotton_1")
end,
})
-- Cotton
minetest.register_craftitem("farming:cotton", {
description = "Cotton",
inventory_image = "farming_cotton.png",
})
minetest.register_alias("farming:string", "farming:cotton")
-- String to Wool
minetest.register_craft({
output = "wool:white",
recipe = {
{"farming:string", "farming:string"},
{"farming:string", "farming:string"},
}
})
-- Define Cotton growth stages
minetest.register_node("farming:cotton_1", {
drawtype = "plantlike",
tiles = {"farming_cotton_1.png"},
paramtype = "light",
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:cotton_2", {
drawtype = "plantlike",
tiles = {"farming_cotton_2.png"},
paramtype = "light",
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:cotton_3", {
drawtype = "plantlike",
tiles = {"farming_cotton_3.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:cotton_4", {
drawtype = "plantlike",
tiles = {"farming_cotton_4.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:cotton_5", {
drawtype = "plantlike",
tiles = {"farming_cotton_5.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = {
items = {
{items = {"farming:seed_cotton"}, rarity = 1},
}
},
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:cotton_6", {
drawtype = "plantlike",
tiles = {"farming_cotton_6.png"},
paramtype = "light",
waving = 1,
walkable = false,
buildable_to = true,
drop = {
items = {
{items = {"farming:cotton"}, rarity = 1},
{items = {"farming:cotton"}, rarity = 2},
}
},
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:cotton_7", {
drawtype = "plantlike",
tiles = {"farming_cotton_7.png"},
paramtype = "light",
waving = 1,
walkable = false,
buildable_to = true,
drop = {
items = {
{items = {"farming:cotton"}, rarity = 1},
{items = {"farming:cotton"}, rarity = 2},
{items = {"farming:seed_cotton"}, rarity = 1},
{items = {"farming:seed_cotton"}, rarity = 2},
}
},
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
-- Last stage of growth does not have growing group so abm never checks these
minetest.register_node("farming:cotton_8", {
drawtype = "plantlike",
tiles = {"farming_cotton_8.png"},
paramtype = "light",
waving = 1,
walkable = false,
buildable_to = true,
drop = {
items = {
{items = {"farming:string"}, rarity = 1},
{items = {"farming:string"}, rarity = 2},
{items = {"farming:string"}, rarity = 3},
{items = {"farming:seed_cotton"}, rarity = 1},
{items = {"farming:seed_cotton"}, rarity = 2},
{items = {"farming:seed_cotton"}, rarity = 3},
}
},
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1
},
sounds = default.node_sound_leaves_defaults(),
})

View File

@ -1,2 +1,2 @@
default
wool
wool

28
mods/farming/grass.lua Normal file
View File

@ -0,0 +1,28 @@
-- Override default grass and have it drop Wheat Seeds
for i = 1, 5 do
minetest.override_item("default:grass_" .. i, {
drop = {
max_items = 1,
items = {
{items = {'farming:seed_wheat'}, rarity = 5},
{items = {'default:grass_1'}},
}
},
})
end
-- Override default Jungle Grass and have it drop Cotton Seeds
minetest.override_item("default:junglegrass", {
drop = {
max_items = 1,
items = {
{items = {'farming:seed_cotton'}, rarity = 8},
{items = {'default:junglegrass'}},
}
},
})

View File

@ -1,9 +1,106 @@
-- Hoe registration function
farming.register_hoe = function(name, def)
-- Check for : prefix (register new hoes in your mod's namespace)
if name:sub(1,1) ~= ":" then
name = ":" .. name
end
-- Check def table
if def.description == nil then
def.description = "Hoe"
end
if def.inventory_image == nil then
def.inventory_image = "unknown_item.png"
end
if def.recipe == nil then
def.recipe = {
{"air","air",""},
{"","group:stick",""},
{"","group:stick",""}
}
end
if def.max_uses == nil then
def.max_uses = 30
end
-- Register the tool
minetest.register_tool(name, {
description = def.description,
inventory_image = def.inventory_image,
on_use = function(itemstack, user, pointed_thing)
return farming.hoe_on_use(itemstack, user, pointed_thing, def.max_uses)
end
})
-- Register its recipe
if def.material == nil then
minetest.register_craft({
output = name:sub(2),
recipe = def.recipe
})
else
minetest.register_craft({
output = name:sub(2),
recipe = {
{def.material, def.material, ""},
{"", "group:stick", ""},
{"", "group:stick", ""}
}
})
end
end
-- Turns dirt with group soil=1 into soil
function farming.hoe_on_use(itemstack, user, pointed_thing, uses)
local pt = pointed_thing
-- check if pointing at a node
if not pt or pt.type ~= "node" then
return
end
local under = minetest.get_node(pt.under)
local upos = pointed_thing.under
if minetest.is_protected(upos, user:get_player_name()) then
minetest.record_protection_violation(upos, user:get_player_name())
return
end
local p = {x = pt.under.x, y = pt.under.y + 1, z = pt.under.z}
local above = minetest.get_node(p)
-- return if any of the nodes is not registered
if not minetest.registered_nodes[under.name]
or not minetest.registered_nodes[above.name] then
return
end
-- check if the node above the pointed thing is air
if above.name ~= "air" then
return
end
-- check if pointing at dirt
if minetest.get_item_group(under.name, "soil") ~= 1 then
return
end
-- turn the node into soil, wear out item and play sound
minetest.set_node(pt.under, {name = "farming:soil"})
minetest.sound_play("default_dig_crumbly", {pos = pt.under, gain = 0.5})
if not minetest.setting_getbool("creative_mode") then
itemstack:add_wear(65535/(uses-1))
end
return itemstack
end
-- Define Hoes
farming.register_hoe(":farming:hoe_wood", {
description = "Wooden Hoe",
inventory_image = "farming_tool_woodhoe.png",
max_uses = 30,
material = "group:wood",
groups = {flammable = 2},
material = "group:wood"
})
farming.register_hoe(":farming:hoe_stone", {
@ -20,13 +117,6 @@ farming.register_hoe(":farming:hoe_steel", {
material = "default:steel_ingot"
})
farming.register_hoe(":farming:hoe_gold", {
description = "Golden Hoe",
inventory_image = "farming_tool_goldhoe.png",
max_uses = 220,
material = "default:gold_ingot"
})
farming.register_hoe(":farming:hoe_bronze", {
description = "Bronze Hoe",
inventory_image = "farming_tool_bronzehoe.png",
@ -46,4 +136,4 @@ farming.register_hoe(":farming:hoe_diamond", {
inventory_image = "farming_tool_diamondhoe.png",
max_uses = 500,
material = "default:diamond"
})
})

View File

@ -1,129 +1,553 @@
-- Global farming namespace
--[[
Minetest Farming Redo Mod 1.22 (26th October 2015)
by TenPlus1
NEW growing routine by prestidigitator
auto-refill by crabman77
]]
farming = {}
farming.mod = "redo"
farming.path = minetest.get_modpath("farming")
farming.hoe_on_use = default.hoe_on_use
farming.select = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5}
}
-- Load files
dofile(farming.path .. "/api.lua")
dofile(farming.path .. "/nodes.lua")
dofile(farming.path .. "/hoes.lua")
farming.DEBUG = false
-- farming.DEBUG = {} -- Uncomment to turn on profiling code/functions
--Carrot
farming.register_plant("farming:carrot", {
description = "Carrot seed",
paramtype2 = "meshoptions",
inventory_image = "farming_carrot_seed.png",
steps = 8,
minlight = 13,
maxlight = default.LIGHT_MAX,
fertility = {"grassland"},
groups = {flammable = 4},
place_param2 = 3,
})
local DEBUG_abm_runs = 0
local DEBUG_abm_time = 0
local DEBUG_timer_runs = 0
local DEBUG_timer_time = 0
if farming.DEBUG then
function farming.DEBUG.reset_times()
DEBUG_abm_runs = 0
DEBUG_abm_time = 0
DEBUG_timer_runs = 0
DEBUG_timer_time = 0
end
minetest.register_craftitem("farming:carrot", {
description = "Carrot",
inventory_image = "farming_carrot.png",
on_use = minetest.item_eat(2),
groups = {flammable = 2},
})
function farming.DEBUG.report_times()
local abm_n = DEBUG_abm_runs
local abm_dt = DEBUG_abm_time
local abm_avg = (abm_n > 0 and abm_dt / abm_n) or 0
local timer_n = DEBUG_timer_runs
local timer_dt = DEBUG_timer_time
local timer_avg = (timer_n > 0 and timer_dt / timer_n) or 0
local dt = abm_dt + timer_dt
print("ABM ran for "..abm_dt.."µs over "..abm_n.." runs: "..
abm_avg.."µs/run")
print("Timer ran for "..timer_dt.."µs over "..timer_n.." runs: "..
timer_avg.."µs/run")
print("Total farming time: "..dt.."µs")
end
end
-- WHEAT
farming.register_plant("farming:wheat", {
description = "Wheat seed",
paramtype2 = "meshoptions",
inventory_image = "farming_wheat_seed.png",
steps = 8,
minlight = 13,
maxlight = default.LIGHT_MAX,
fertility = {"grassland"},
groups = {flammable = 4},
place_param2 = 3,
})
minetest.register_craftitem("farming:flour", {
description = "Flour",
inventory_image = "farming_flour.png",
groups = {flammable = 1},
})
local statistics = dofile(farming.path.."/statistics.lua")
dofile(farming.path.."/soil.lua")
dofile(farming.path.."/hoes.lua")
dofile(farming.path.."/grass.lua")
dofile(farming.path.."/wheat.lua")
dofile(farming.path.."/cotton.lua")
dofile(farming.path.."/carrot.lua")
dofile(farming.path.."/potato.lua")
dofile(farming.path.."/corn.lua")
dofile(farming.path.."/raddish.lua")
dofile(farming.path.."/sugar.lua")
dofile(farming.path.."/mapgen.lua")
dofile(farming.path.."/compatibility.lua") -- Farming Plus compatibility
minetest.register_craftitem("farming:bread", {
description = "Bread",
inventory_image = "farming_bread.png",
on_use = minetest.item_eat(5),
groups = {flammable = 2},
})
-- Utility Functions
minetest.register_craft({
type = "shapeless",
output = "farming:flour",
recipe = {"farming:wheat", "farming:wheat", "farming:wheat", "farming:wheat"}
})
local time_speed = tonumber(minetest.setting_get("time_speed")) or 72
local SECS_PER_CYCLE = (time_speed > 0 and 24 * 60 * 60 / time_speed) or 0 --nil
minetest.register_craft({
type = "cooking",
cooktime = 15,
output = "farming:bread",
recipe = "farming:flour"
})
local function clamp(x, min, max)
return (x < min and min) or (x > max and max) or x
end
-- Cotton
local function in_range(x, min, max)
return min <= x and x <= max
end
--- Tests the amount of day or night time between two times.
--
-- @param t_game
-- The current time, as reported by mintest.get_gametime().
-- @param t_day
-- The current time, as reported by mintest.get_timeofday().
-- @param dt
-- The amount of elapsed time.
-- @param count_day
-- If true, count elapsed day time. Otherwise, count elapsed night time.
-- @return
-- The amount of day or night time that has elapsed.
--
local function day_or_night_time(t_game, t_day, dt, count_day)
local t1_day = t_day - dt / SECS_PER_CYCLE
local t1_c, t2_c -- t1_c < t2_c and t2_c always in [0, 1)
if count_day then
if t_day < 0.25 then
t1_c = t1_day + 0.75 -- Relative to sunup, yesterday
t2_c = t_day + 0.75
else
t1_c = t1_day - 0.25 -- Relative to sunup, today
t2_c = t_day - 0.25
end
else
if t_day < 0.75 then
t1_c = t1_day + 0.25 -- Relative to sundown, yesterday
t2_c = t_day + 0.25
else
t1_c = t1_day - 0.75 -- Relative to sundown, today
t2_c = t_day - 0.75
end
end
local dt_c = clamp(t2_c, 0, 0.5) - clamp(t1_c, 0, 0.5) -- this cycle
if t1_c < -0.5 then
local nc = math.floor(-t1_c)
t1_c = t1_c + nc
dt_c = dt_c + 0.5 * nc + clamp(-t1_c - 0.5, 0, 0.5)
end
return dt_c * SECS_PER_CYCLE
end
--- Tests the amount of elapsed day time.
--
-- @param dt
-- The amount of elapsed time.
-- @return
-- The amount of day time that has elapsed.
--
local function day_time(dt)
return day_or_night_time(minetest.get_gametime(), minetest.get_timeofday(), dt, true)
end
--- Tests the amount of elapsed night time.
--
-- @param dt
-- The amount of elapsed time.
-- @return
-- The amount of night time that has elapsed.
--
local function night_time(time_game, time_day, dt, count_day)
return day_or_night_time(minetest.get_gametime(), minetest.get_timeofday(), dt, false)
end
-- Growth Logic
local STAGE_LENGTH_AVG = 160.0
local STAGE_LENGTH_DEV = STAGE_LENGTH_AVG / 6
local MIN_LIGHT = 13
local MAX_LIGHT = 1000
--- Determines plant name and stage from node.
--
-- Separates node name on the last underscore (_).
--
-- @param node
-- Node or position table, or node name.
-- @return
-- List (plant_name, stage), or nothing (nil) if node isn't loaded
--
local function plant_name_stage(node)
local name
if type(node) == 'table' then
if node.name then
name = node.name
elseif node.x and node.y and node.z then
node = minetest.get_node_or_nil(node)
name = node and node.name
end
else
name = tostring(node)
end
if not name or name == "ignore" then return nil end
local sep_pos = name:find("_[^_]+$")
if sep_pos and sep_pos > 1 then
local stage = tonumber(name:sub(sep_pos + 1))
if stage and stage >= 0 then
return name:sub(1, sep_pos - 1), stage
end
end
return name, 0
end
--- Map from node name to
-- { plant_name = ..., name = ..., stage = n, stages_left = { node_name, ... } }
local plant_stages = {}
farming.plant_stages = plant_stages
--- Registers the stages of growth of a (possible plant) node.
--
-- @param node
-- Node or position table, or node name.
-- @return
-- The (possibly zero) number of stages of growth the plant will go through
-- before being fully grown, or nil if not a plant.
--
local register_plant_node
-- Recursive helper
local function reg_plant_stages(plant_name, stage, force_last)
local node_name = plant_name and plant_name .. "_" .. stage
local node_def = node_name and minetest.registered_nodes[node_name]
if not node_def then return nil end
local stages = plant_stages[node_name]
if stages then return stages end
if minetest.get_item_group(node_name, "growing") > 0 then
local ns = reg_plant_stages(plant_name, stage + 1, true)
local stages_left = (ns and { ns.name, unpack(ns.stages_left) }) or {}
stages = {
plant_name = plant_name,
name = node_name,
stage = stage,
stages_left = stages_left
}
if #stages_left > 0 then
local old_constr = node_def.on_construct
local old_destr = node_def.on_destruct
minetest.override_item(node_name,
{
on_construct = function(pos)
if old_constr then old_constr(pos) end
farming.handle_growth(pos)
end,
on_destruct = function(pos)
minetest.get_node_timer(pos):stop()
if old_destr then old_destr(pos) end
end,
on_timer = function(pos, elapsed)
return farming.plant_growth_timer(pos, elapsed, node_name)
end,
})
end
elseif force_last then
stages = {
plant_name = plant_name,
name = node_name,
stage = stage,
stages_left = {}
}
else
return nil
end
plant_stages[node_name] = stages
return stages
end
register_plant_node = function(node)
local plant_name, stage = plant_name_stage(node)
if plant_name then
local stages = reg_plant_stages(plant_name, stage, false)
return stages and #stages.stages_left
else
return nil
end
end
local function set_growing(pos, stages_left)
if not stages_left then return end
local timer = minetest.get_node_timer(pos)
if stages_left > 0 then
if not timer:is_started() then
local stage_length = statistics.normal(STAGE_LENGTH_AVG, STAGE_LENGTH_DEV)
stage_length = clamp(stage_length, 0.5 * STAGE_LENGTH_AVG, 3.0 * STAGE_LENGTH_AVG)
timer:set(stage_length, -0.5 * math.random() * STAGE_LENGTH_AVG)
end
elseif timer:is_started() then
timer:stop()
end
end
--- Detects a plant type node at the given position, starting or stopping the plant growth timer as appopriate
--
-- @param pos
-- The node's position.
-- @param node
-- The cached node table if available, or nil.
--
function farming.handle_growth(pos, node)
if not pos then return end
local stages_left = register_plant_node(node or pos)
if stages_left then set_growing(pos, stages_left) end
end
minetest.after(0,
function()
for _, node_def in pairs(minetest.registered_nodes) do
register_plant_node(node_def)
end
end)
local abm_func = farming.handle_growth
if farming.DEBUG then
local normal_abm_func = abm_func
abm_func = function(...)
local t0 = minetest.get_us_time()
local r = { normal_abm_func(...) }
local t1 = minetest.get_us_time()
DEBUG_abm_runs = DEBUG_abm_runs + 1
DEBUG_abm_time = DEBUG_abm_time + (t1 - t0)
return unpack(r)
end
end
-- Just in case a growing type or added node is missed (also catches existing
-- nodes added to map before timers were incorporated).
minetest.register_abm({
nodenames = { "group:growing" },
interval = 300,
chance = 1,
action = abm_func})
--- Plant timer function.
--
-- Grows plants under the right conditions.
--
function farming.plant_growth_timer(pos, elapsed, node_name)
local stages = plant_stages[node_name]
if not stages then return false end
local max_growth = #stages.stages_left
if max_growth <= 0 then return false end
if stages.plant_name == "farming:cocoa" then
if not minetest.find_node_near(pos, 1, { "default:jungletree", "moretrees:jungletree_leaves_green" }) then
return true
end
else
local under = minetest.get_node_or_nil({ x = pos.x, y = pos.y - 1, z = pos.z })
if not under or under.name ~= "farming:soil_wet" then return true end
end
local growth
local light_pos = { x = pos.x, y = pos.y, z = pos.z }
local lambda = elapsed / STAGE_LENGTH_AVG
if lambda < 0.1 then return true end
if max_growth == 1 or lambda < 2.0 then
local light = (minetest.get_node_light(light_pos) or 0) -- CHANGED
--print ("light level:", light)
if not in_range(light, MIN_LIGHT, MAX_LIGHT) then return true end
growth = 1
else
local night_light = (minetest.get_node_light(light_pos, 0) or 0) -- CHANGED
local day_light = (minetest.get_node_light(light_pos, 0.5) or 0) -- ChANGED
local night_growth = in_range(night_light, MIN_LIGHT, MAX_LIGHT)
local day_growth = in_range(day_light, MIN_LIGHT, MAX_LIGHT)
if not night_growth then
if not day_growth then return true end
lambda = day_time(elapsed) / STAGE_LENGTH_AVG
elseif not day_growth then
lambda = night_time(elapsed) / STAGE_LENGTH_AVG
end
growth = statistics.poisson(lambda, max_growth)
if growth < 1 then return true end
end
minetest.swap_node(pos, { name = stages.stages_left[growth] })
return growth ~= max_growth
end
if farming.DEBUG then
local timer_func = farming.plant_growth_timer;
farming.plant_growth_timer = function(pos, elapsed, node_name)
local t0 = minetest.get_us_time()
local r = { timer_func(pos, elapsed, node_name) }
local t1 = minetest.get_us_time()
DEBUG_timer_runs = DEBUG_timer_runs + 1
DEBUG_timer_time = DEBUG_timer_time + (t1 - t0)
return unpack(r)
end
end
-- refill placed plant by crabman (26/08/2015)
local can_refill_plant = {
["farming:blueberry_1"] = "farming:blueberries",
["farming:carrot_1"] = "farming:carrot",
["farming:coffee_1"] = "farming:coffee_beans",
["farming:corn_1"] = "farming:corn",
["farming:cotton_1"] = "farming:seed_cotton",
["farming:cucumber_1"] = "farming:cucumber",
["farming:melon_1"] = "farming:melon_slice",
["farming:potato_1"] = "farming:potato",
["farming:pumpkin_1"] = "farming:pumpkin_slice",
["farming:raspberry_1"] = "farming:raspberries",
["farming:rhubarb_1"] = "farming:rhubarb",
["farming:tomato_1"] = "farming:tomato",
["farming:wheat_1"] = "farming:seed_wheat"
}
function farming.refill_plant(player, plantname, index)
local inv = player:get_inventory()
local old_stack = inv:get_stack("main", index)
if old_stack:get_name() ~= "" then return end
for i,stack in ipairs(inv:get_list("main")) do
if stack:get_name() == plantname and i ~= index then
inv:set_stack("main", index, stack)
stack:clear()
inv:set_stack("main", i, stack)
--minetest.log("action", "farming: refilled stack("..plantname..") of " .. player:get_player_name() )
return
end
end
end -- END refill
-- Place Seeds on Soil
function farming.place_seed(itemstack, placer, pointed_thing, plantname)
local pt = pointed_thing
-- check if pointing at a node
if not pt or pt.type ~= "node" then
return
end
local under = minetest.get_node(pt.under)
local above = minetest.get_node(pt.above)
-- check if pointing at the top of the node
if pt.above.y ~= pt.under.y + 1 then
return
end
-- return if any of the nodes is not registered
if not minetest.registered_nodes[under.name]
or not minetest.registered_nodes[above.name] then
return
end
-- can I replace above node, and am I pointing at soil
if not minetest.registered_nodes[above.name].buildable_to
or minetest.get_item_group(under.name, "soil") < 2
-- avoid multiple seed placement bug
or minetest.get_item_group(above.name, "plant") ~= 0 then
return
end
-- if not protected then add node and remove 1 item from the itemstack
if not minetest.is_protected(pt.above, placer:get_player_name()) then
minetest.set_node(pt.above, {name = plantname, param2 = 1})
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
-- check for refill
if itemstack:get_count() == 0
and can_refill_plant[plantname] then
minetest.after(0.10,
farming.refill_plant,
placer,
can_refill_plant[plantname],
placer:get_wield_index()
)
end -- END refill
end
return itemstack
end
end
-- Function to register plants (for compatibility)
farming.register_plant = function(name, def)
local mname = name:split(":")[1]
local pname = name:split(":")[2]
-- Check def table
if not def.description then
def.description = "Seed"
end
if not def.inventory_image then
def.inventory_image = "unknown_item.png"
end
if not def.steps then
return nil
end
-- Register seed
minetest.register_node(":" .. mname .. ":seed_" .. pname, {
description = def.description,
tiles = {def.inventory_image},
inventory_image = def.inventory_image,
wield_image = def.inventory_image,
drawtype = "signlike",
groups = {seed = 1, snappy = 3, attached_node = 1},
paramtype = "light",
paramtype2 = "wallmounted",
walkable = false,
sunlight_propagates = true,
selection_box = farming.select,
on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, mname .. ":"..pname.."_1")
end
})
-- Register harvest
minetest.register_craftitem(":" .. mname .. ":" .. pname, {
description = pname:gsub("^%l", string.upper),
inventory_image = mname .. "_" .. pname .. ".png",
})
-- Register growing steps
for i = 1, def.steps do
local drop = {
items = {
{items = {mname .. ":" .. pname}, rarity = 9 - i},
{items = {mname .. ":" .. pname}, rarity= 18 - i * 2},
{items = {mname .. ":seed_" .. pname}, rarity = 9 - i},
{items = {mname .. ":seed_" .. pname}, rarity = 18 - i * 2},
}
}
local g = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1, growing = 1}
-- Last step doesn't need growing=1 so Abm never has to check these
if i == def.steps then
g = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1}
end
local node_name = mname .. ":" .. pname .. "_" .. i
minetest.register_node(node_name, {
drawtype = "plantlike",
waving = 1,
tiles = {mname .. "_" .. pname .. "_" .. i .. ".png"},
paramtype = "light",
walkable = false,
buildable_to = true,
drop = drop,
selection_box = farming.select,
groups = g,
sounds = default.node_sound_leaves_defaults(),
})
register_plant_node(node_name)
end
-- Return info
local r = {seed = mname .. ":seed_" .. pname, harvest = mname .. ":" .. pname}
return r
end
--[[ Cotton (example, is already registered in cotton.lua)
farming.register_plant("farming:cotton", {
description = "Cotton seed",
description = "Cotton2 seed",
inventory_image = "farming_cotton_seed.png",
steps = 8,
minlight = 13,
maxlight = default.LIGHT_MAX,
fertility = {"grassland", "desert"},
groups = {flammable = 4},
})
minetest.register_alias("farming:string", "farming:cotton")
minetest.register_craft({
output = "wool:white",
recipe = {
{"farming:cotton", "farming:cotton"},
{"farming:cotton", "farming:cotton"},
}
})
-- Straw
minetest.register_craft({
output = "farming:straw 3",
recipe = {
{"farming:wheat", "farming:wheat", "farming:wheat"},
{"farming:wheat", "farming:wheat", "farming:wheat"},
{"farming:wheat", "farming:wheat", "farming:wheat"},
}
})
minetest.register_craft({
output = "farming:wheat 3",
recipe = {
{"farming:straw"},
}
})
-- Fuels
minetest.register_craft({
type = "fuel",
recipe = "farming:straw",
burntime = 3,
})
minetest.register_craft({
type = "fuel",
recipe = "farming:wheat",
burntime = 1,
})
minetest.register_craft({
type = "fuel",
recipe = "farming:cotton",
burntime = 1,
})
minetest.register_craft({
type = "fuel",
recipe = "farming:hoe_wood",
burntime = 5,
})
})]]

View File

@ -1,61 +1,14 @@
License of source code
----------------------
The MIT License (MIT)
Copyright (C) 2012-2016 PilzAdam
Copyright (C) 2014-2016 webdesigner97
Copyright (C) 2012-2016 Various Minetest developers and contributors
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the following conditions:
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
For more details:
https://opensource.org/licenses/MIT
License of media (textures)
---------------------------
Attribution 3.0 Unported (CC BY 3.0)
Copyright (C) 2012-2016 PilzAdam
Copyright (C) 2014-2016 BlockMen
Copyright (C) 2015-2016 MasterGollum
Copyright (C) 2015-2016 Gambit
You are free to:
Share — copy and redistribute the material in any medium or format.
Adapt — remix, transform, and build upon the material for any purpose, even commercially.
The licensor cannot revoke these freedoms as long as you follow the license terms.
Under the following terms:
Attribution — You must give appropriate credit, provide a link to the license, and
indicate if changes were made. You may do so in any reasonable manner, but not in any way
that suggests the licensor endorses you or your use.
No additional restrictions — You may not apply legal terms or technological measures that
legally restrict others from doing anything the license permits.
Notices:
You do not have to comply with the license for elements of the material in the public
domain or where your use is permitted by an applicable exception or limitation.
No warranties are given. The license may not give you all of the permissions necessary
for your intended use. For example, other rights such as publicity, privacy, or moral
rights may limit how you use the material.
For more details:
http://creativecommons.org/licenses/by/3.0/
0. You just DO WHAT THE FUCK YOU WANT TO.

0
mods/farming/mapgen.lua Normal file
View File

View File

@ -1,163 +0,0 @@
minetest.override_item("default:dirt", {
soil = {
base = "default:dirt",
dry = "farming:soil",
wet = "farming:soil_wet"
}
})
minetest.override_item("default:dirt_with_grass", {
soil = {
base = "default:dirt_with_grass",
dry = "farming:soil",
wet = "farming:soil_wet"
}
})
minetest.override_item("default:dirt_with_dry_grass", {
soil = {
base = "default:dirt_with_dry_grass",
dry = "farming:soil",
wet = "farming:soil_wet"
}
})
minetest.register_node("farming:soil", {
description = "Soil",
tiles = {"default_dirt.png^farming_soil.png", "default_dirt.png"},
drop = "default:dirt",
groups = {crumbly=3, not_in_creative_inventory=1, soil=2, grassland = 1, field = 1},
sounds = default.node_sound_dirt_defaults(),
soil = {
base = "default:dirt",
dry = "farming:soil",
wet = "farming:soil_wet"
}
})
minetest.register_node("farming:soil_wet", {
description = "Wet Soil",
tiles = {"default_dirt.png^farming_soil_wet.png", "default_dirt.png^farming_soil_wet_side.png"},
drop = "default:dirt",
groups = {crumbly=3, not_in_creative_inventory=1, soil=3, wet = 1, grassland = 1, field = 1},
sounds = default.node_sound_dirt_defaults(),
soil = {
base = "default:dirt",
dry = "farming:soil",
wet = "farming:soil_wet"
}
})
minetest.override_item("default:desert_sand", {
groups = {crumbly=3, falling_node=1, sand=1, soil = 1},
soil = {
base = "default:desert_sand",
dry = "farming:desert_sand_soil",
wet = "farming:desert_sand_soil_wet"
}
})
minetest.register_node("farming:desert_sand_soil", {
description = "Desert Sand Soil",
drop = "default:desert_sand",
tiles = {"farming_desert_sand_soil.png", "default_desert_sand.png"},
groups = {crumbly=3, not_in_creative_inventory = 1, falling_node=1, sand=1, soil = 2, desert = 1, field = 1},
sounds = default.node_sound_sand_defaults(),
soil = {
base = "default:desert_sand",
dry = "farming:desert_sand_soil",
wet = "farming:desert_sand_soil_wet"
}
})
minetest.register_node("farming:desert_sand_soil_wet", {
description = "Wet Desert Sand Soil",
drop = "default:desert_sand",
tiles = {"farming_desert_sand_soil_wet.png", "farming_desert_sand_soil_wet_side.png"},
groups = {crumbly=3, falling_node=1, sand=1, not_in_creative_inventory=1, soil=3, wet = 1, desert = 1, field = 1},
sounds = default.node_sound_sand_defaults(),
soil = {
base = "default:desert_sand",
dry = "farming:desert_sand_soil",
wet = "farming:desert_sand_soil_wet"
}
})
minetest.register_node("farming:straw", {
description = "Straw",
tiles = {"farming_straw_top.png", "farming_straw_top.png", "farming_straw.png"},
is_ground_content = false,
groups = {snappy=3, flammable=4, fall_damage_add_percent=-30},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_abm({
label = "Farming soil",
nodenames = {"group:field"},
interval = 15,
chance = 4,
action = function(pos, node)
local n_def = minetest.registered_nodes[node.name] or nil
local wet = n_def.soil.wet or nil
local base = n_def.soil.base or nil
local dry = n_def.soil.dry or nil
if not n_def or not n_def.soil or not wet or not base or not dry then
return
end
pos.y = pos.y + 1
local nn = minetest.get_node_or_nil(pos)
if not nn or not nn.name then
return
end
local nn_def = minetest.registered_nodes[nn.name] or nil
pos.y = pos.y - 1
if nn_def and nn_def.walkable and minetest.get_item_group(nn.name, "plant") == 0 then
minetest.set_node(pos, {name = base})
return
end
-- check if there is water nearby
local wet_lvl = minetest.get_item_group(node.name, "wet")
if minetest.find_node_near(pos, 3, {"group:water"}) then
-- if it is dry soil and not base node, turn it into wet soil
if wet_lvl == 0 then
minetest.set_node(pos, {name = wet})
end
else
-- only turn back if there are no unloaded blocks (and therefore
-- possible water sources) nearby
if not minetest.find_node_near(pos, 3, {"ignore"}) then
-- turn it back into base if it is already dry
if wet_lvl == 0 then
-- only turn it back if there is no plant/seed on top of it
if minetest.get_item_group(nn.name, "plant") == 0 and minetest.get_item_group(nn.name, "seed") == 0 then
minetest.set_node(pos, {name = base})
end
-- if its wet turn it back into dry soil
elseif wet_lvl == 1 then
minetest.set_node(pos, {name = dry})
end
end
end
end,
})
for i = 1, 5 do
minetest.override_item("default:grass_"..i, {drop = {
max_items = 1,
items = {
{items = {'farming:seed_wheat'},rarity = 5},
{items = {'default:grass_1'}},
}
}})
end
minetest.override_item("default:junglegrass", {drop = {
max_items = 1,
items = {
{items = {'farming:seed_cotton'},rarity = 8},
{items = {'default:junglegrass'}},
}
}})

101
mods/farming/potato.lua Normal file
View File

@ -0,0 +1,101 @@
--potato crop, textures by tobyplowy(aka toby109tt)
minetest.register_craftitem("farming:potato", {
description = "Potato",
inventory_image = "farming_potato.png",
on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, "farming:potato_1")
end,
on_use = minetest.item_eat(2),
})
minetest.register_node("farming:potato_1", {
drawtype = "plantlike",
tiles = {"farming_potato_1.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:potato_2", {
drawtype = "plantlike",
tiles = {"farming_potato_2.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:potato_3", {
drawtype = "plantlike",
tiles = {"farming_potato_3.png"},
paramtype = "light",
waving = 1,
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:potato_4", {
drawtype = "plantlike",
tiles = {"farming_potato_4.png"},
paramtype = "light",
waving = 1,
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = {
items = {
{items = {'farming:potato'}, rarity = 1},
{items = {'farming:potato'}, rarity = 2},
{items = {'farming:potato'}, rarity = 3},
}
},
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:potato_5", {
drawtype = "plantlike",
tiles = {"farming_potato_5.png^[colorize:brown:50"},
paramtype = "light",
waving = 1,
drop = "",
walkable = false,
buildable_to = true,
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})

101
mods/farming/raddish.lua Normal file
View File

@ -0,0 +1,101 @@
--raddish crop, textures by tobyplowy(aka toby109tt)
minetest.register_craftitem("farming:raddish", {
description = "Raddish",
inventory_image = "farming_raddish.png",
on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, "farming:raddish_1")
end,
on_use = minetest.item_eat(1),
})
minetest.register_node("farming:raddish_1", {
drawtype = "plantlike",
tiles = {"farming_raddish_1.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:raddish_2", {
drawtype = "plantlike",
tiles = {"farming_raddish_2.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:raddish_3", {
drawtype = "plantlike",
tiles = {"farming_raddish_3.png"},
paramtype = "light",
waving = 1,
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:raddish_4", {
drawtype = "plantlike",
tiles = {"farming_raddish_4.png"},
paramtype = "light",
waving = 1,
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = {
items = {
{items = {'farming:raddish'}, rarity = 1},
{items = {'farming:raddish'}, rarity = 2},
{items = {'farming:raddish'}, rarity = 3},
}
},
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:raddish_5", {
drawtype = "plantlike",
tiles = {"farming_raddish_5.png^[colorize:brown:50"},
paramtype = "light",
waving = 1,
drop = "",
walkable = false,
buildable_to = true,
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})

60
mods/farming/soil.lua Normal file
View File

@ -0,0 +1,60 @@
-- normal soil
minetest.register_node("farming:soil", {
description = "Soil",
tiles = {"default_dirt.png^farming_soil.png", "default_dirt.png"},
drop = "default:dirt",
groups = {crumbly = 3, not_in_creative_inventory = 1, soil = 2},
sounds = default.node_sound_dirt_defaults(),
})
-- wet soil
minetest.register_node("farming:soil_wet", {
description = "Wet Soil",
tiles = {"default_dirt.png^farming_soil_wet.png", "default_dirt.png^farming_soil_wet_side.png"},
drop = "default:dirt",
groups = {crumbly = 3, not_in_creative_inventory = 1, soil = 3},
sounds = default.node_sound_dirt_defaults(),
})
-- sand is not soil, change existing sand-soil to use normal soil
minetest.register_alias("farming:desert_sand_soil", "farming:soil")
minetest.register_alias("farming:desert_sand_soil_wet", "farming:soil_wet")
-- if water near soil then change to wet soil
minetest.register_abm({
nodenames = {"farming:soil", "farming:soil_wet"},
interval = 15,
chance = 4,
action = function(pos, node)
pos.y = pos.y + 1
local nn = minetest.get_node_or_nil(pos)
pos.y = pos.y - 1
if nn then nn = nn.name else return end
-- what's on top of soil, if solid/not plant change soil to dirt
if minetest.registered_nodes[nn]
and minetest.registered_nodes[nn].walkable
and minetest.get_item_group(nn, "plant") == 0 then
minetest.set_node(pos, {name = "default:dirt"})
return
end
-- if map around soil not loaded then skip until loaded
if minetest.find_node_near(pos, 3, {"ignore"}) then
return
end
-- check if there is water nearby and change soil accordingly
if minetest.find_node_near(pos, 3, {"group:water"}) then
if node.name == "farming:soil" then
minetest.set_node(pos, {name = "farming:soil_wet"})
end
elseif node.name == "farming:soil_wet" then
minetest.set_node(pos, {name = "farming:soil"})
elseif node.name == "farming:soil" then
minetest.set_node(pos, {name = "default:dirt"})
end
end,
})

150
mods/farming/statistics.lua Normal file
View File

@ -0,0 +1,150 @@
local statistics = {}
local ROOT_2 = math.sqrt(2.0)
-- Approximations for erf(x) and erfInv(x) from
-- https://en.wikipedia.org/wiki/Error_function
local erf
local erf_inv
local A = 8 * (math.pi - 3.0)/(3.0 * math.pi * (4.0 - math.pi))
local B = 4.0 / math.pi
local C = 2.0/(math.pi * A)
local D = 1.0 / A
erf = function(x)
if x == 0 then return 0; end
local xSq = x * x
local aXSq = A * xSq
local v = math.sqrt(1.0 - math.exp(-xSq * (B + aXSq) / (1.0 + aXSq)))
return (x > 0 and v) or -v
end
erf_inv = function(x)
if x == 0 then return 0; end
if x <= -1 or x >= 1 then return nil; end
local y = math.log(1 - x * x)
local u = C + 0.5 * y
local v = math.sqrt(math.sqrt(u * u - D * y) - u)
return (x > 0 and v) or -v
end
local function std_normal(u)
return ROOT_2 * erf_inv(2.0 * u - 1.0)
end
local poisson
local cdf_table = {}
local function generate_cdf(lambda_index, lambda)
local max = math.ceil(4 * lambda)
local pdf = math.exp(-lambda)
local cdf = pdf
local t = { [0] = pdf }
for i = 1, max - 1 do
pdf = pdf * lambda / i
cdf = cdf + pdf
t[i] = cdf
end
return t
end
for li = 1, 100 do
cdf_table[li] = generate_cdf(li, 0.25 * li)
end
poisson = function(lambda, max)
if max < 2 then
return (math.random() < math.exp(-lambda) and 0) or 1
elseif lambda >= 2 * max then
return max
end
local u = math.random()
local lambda_index = math.floor(4 * lambda + 0.5)
local cdfs = cdf_table[lambda_index]
if cdfs then
lambda = 0.25 * lambda_index
if u < cdfs[0] then return 0; end
if max > #cdfs then max = #cdfs + 1 else max = math.floor(max); end
if u >= cdfs[max - 1] then return max; end
if max > 4 then -- Binary search
local s = 0
while s + 1 < max do
local m = math.floor(0.5 * (s + max))
if u < cdfs[m] then max = m; else s = m; end
end
else
for i = 1, max - 1 do
if u < cdfs[i] then return i; end
end
end
return max
else
local x = lambda + math.sqrt(lambda) * std_normal(u)
return (x < 0.5 and 0) or (x >= max - 0.5 and max) or math.floor(x + 0.5)
end
end
-- Error function.
statistics.erf = erf
-- Inverse error function.
statistics.erf_inv = erf_inv
--- Standard normal distribution function (mean 0, standard deviation 1).
--
-- @return
-- Any real number (actually between -3.0 and 3.0).
--
statistics.std_normal = function()
local u = math.random()
if u < 0.001 then
return -3.0
elseif u > 0.999 then
return 3.0
end
return std_normal(u)
end
--- Standard normal distribution function (mean 0, standard deviation 1).
--
-- @param mu
-- The distribution mean.
-- @param sigma
-- The distribution standard deviation.
-- @return
-- Any real number (actually between -3*sigma and 3*sigma).
--
statistics.normal = function(mu, sigma)
local u = math.random()
if u < 0.001 then
return mu - 3.0 * sigma
elseif u > 0.999 then
return mu + 3.0 * sigma
end
return mu + sigma * std_normal(u)
end
--- Poisson distribution function.
--
-- @param lambda
-- The distribution mean and variance.
-- @param max
-- The distribution maximum.
-- @return
-- An integer between 0 and max (both inclusive).
--
statistics.poisson = function(lambda, max)
lambda, max = tonumber(lambda), tonumber(max)
if not lambda or not max or lambda <= 0 or max < 1 then return 0; end
return poisson(lambda, max)
end
return statistics

14
mods/farming/sugar.lua Normal file
View File

@ -0,0 +1,14 @@
--= Sugar
minetest.register_craftitem("farming:sugar", {
description = "Sugar",
inventory_image = "farming_sugar.png",
})
minetest.register_craft({
type = "cooking",
cooktime = 3,
output = "farming:sugar 2",
recipe = "default:papyrus",
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

251
mods/farming/wheat.lua Normal file
View File

@ -0,0 +1,251 @@
--= Wheat
-- Wheat Seed
--minetest.register_craftitem("farming:seed_wheat", {
-- description = "Wheat Seed",
-- inventory_image = "farming_wheat_seed.png",
-- on_place = function(itemstack, placer, pointed_thing)
-- return farming.place_seed(itemstack, placer, pointed_thing, "farming:wheat_1")
-- end,
--})
minetest.register_node("farming:seed_wheat", {
description = "Wheat Seed",
tiles = {"farming_wheat_seed.png"},
inventory_image = "farming_wheat_seed.png",
wield_image = "farming_wheat_seed.png",
drawtype = "signlike",
groups = {seed = 1, snappy = 3, attached_node = 1},
paramtype = "light",
paramtype2 = "wallmounted",
walkable = false,
sunlight_propagates = true,
selection_box = farming.select,
on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, "farming:wheat_1")
end,
})
-- Harvested Wheat
minetest.register_craftitem("farming:wheat", {
description = "Wheat",
inventory_image = "farming_wheat.png",
})
-- Straw
minetest.register_node("farming:straw", {
description = "Straw",
tiles = {"farming_straw.png"},
is_ground_content = false,
groups = {snappy = 3, flammable = 4},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_craft({
output = "farming:straw 3",
recipe = {
{"farming:wheat", "farming:wheat", "farming:wheat"},
{"farming:wheat", "farming:wheat", "farming:wheat"},
{"farming:wheat", "farming:wheat", "farming:wheat"},
}
})
minetest.register_craft({
output = "farming:wheat 3",
recipe = {
{"farming:straw"},
}
})
-- flour
minetest.register_craftitem("farming:flour", {
description = "Flour",
inventory_image = "farming_flour.png",
})
minetest.register_craft({
type = "shapeless",
output = "farming:flour",
recipe = {"farming:wheat", "farming:wheat", "farming:wheat", "farming:wheat"}
})
-- Bread
minetest.register_craftitem("farming:bread", {
description = "Bread",
inventory_image = "farming_bread.png",
on_use = minetest.item_eat(5),
})
minetest.register_craft({
type = "cooking",
cooktime = 15,
output = "farming:bread",
recipe = "farming:flour"
})
-- Define Wheat growth stages
minetest.register_node("farming:wheat_1", {
drawtype = "plantlike",
tiles = {"farming_wheat_1.png"},
paramtype = "light",
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing=1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:wheat_2", {
drawtype = "plantlike",
tiles = {"farming_wheat_2.png"},
paramtype = "light",
sunlight_propagates = true,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:wheat_3", {
drawtype = "plantlike",
tiles = {"farming_wheat_3.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:wheat_4", {
drawtype = "plantlike",
tiles = {"farming_wheat_4.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = "",
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:wheat_5", {
drawtype = "plantlike",
tiles = {"farming_wheat_5.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = {
items = {
{items = {'farming:wheat'}, rarity = 2},
{items = {'farming:seed_wheat'}, rarity = 2},
}
},
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:wheat_6", {
drawtype = "plantlike",
tiles = {"farming_wheat_6.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = {
items = {
{items = {'farming:wheat'}, rarity = 2},
{items = {'farming:seed_wheat'}, rarity = 1},
}
},
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
minetest.register_node("farming:wheat_7", {
drawtype = "plantlike",
tiles = {"farming_wheat_7.png"},
paramtype = "light",
sunlight_propagates = true,
waving = 1,
walkable = false,
buildable_to = true,
drop = {
items = {
{items = {'farming:wheat'}, rarity = 1},
{items = {'farming:wheat'}, rarity = 3},
{items = {'farming:seed_wheat'}, rarity = 1},
{items = {'farming:seed_wheat'}, rarity = 3},
}
},
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults(),
})
-- Last stage of growth does not have growing group so abm never checks these
minetest.register_node("farming:wheat_8", {
drawtype = "plantlike",
tiles = {"farming_wheat_8.png"},
paramtype = "light",
waving = 1,
walkable = false,
buildable_to = true,
drop = {
items = {
{items = {'farming:wheat'}, rarity = 1},
{items = {'farming:wheat'}, rarity = 2},
{items = {'farming:seed_wheat'}, rarity = 1},
{items = {'farming:seed_wheat'}, rarity = 2},
}
},
selection_box = farming.select,
groups = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1
},
sounds = default.node_sound_leaves_defaults(),
})