Code tweak and tidy, fixed rhubarb spawning

This commit is contained in:
TenPlus1 2015-12-08 14:47:22 +00:00
parent dc894725c7
commit 171a67ebf2
5 changed files with 168 additions and 44 deletions

View File

@ -2,17 +2,21 @@
-- Hoe registration function -- Hoe registration function
farming.register_hoe = function(name, def) farming.register_hoe = function(name, def)
-- Check for : prefix (register new hoes in your mod's namespace) -- Check for : prefix (register new hoes in your mod's namespace)
if name:sub(1,1) ~= ":" then if name:sub(1,1) ~= ":" then
name = ":" .. name name = ":" .. name
end end
-- Check def table -- Check def table
if def.description == nil then if def.description == nil then
def.description = "Hoe" def.description = "Hoe"
end end
if def.inventory_image == nil then if def.inventory_image == nil then
def.inventory_image = "unknown_item.png" def.inventory_image = "unknown_item.png"
end end
if def.recipe == nil then if def.recipe == nil then
def.recipe = { def.recipe = {
{"air","air",""}, {"air","air",""},
@ -20,9 +24,11 @@ farming.register_hoe = function(name, def)
{"","group:stick",""} {"","group:stick",""}
} }
end end
if def.max_uses == nil then if def.max_uses == nil then
def.max_uses = 30 def.max_uses = 30
end end
-- Register the tool -- Register the tool
minetest.register_tool(name, { minetest.register_tool(name, {
description = def.description, description = def.description,
@ -31,6 +37,7 @@ farming.register_hoe = function(name, def)
return farming.hoe_on_use(itemstack, user, pointed_thing, def.max_uses) return farming.hoe_on_use(itemstack, user, pointed_thing, def.max_uses)
end end
}) })
-- Register its recipe -- Register its recipe
if def.material == nil then if def.material == nil then
minetest.register_craft({ minetest.register_craft({
@ -52,7 +59,9 @@ end
-- Turns dirt with group soil=1 into soil -- Turns dirt with group soil=1 into soil
function farming.hoe_on_use(itemstack, user, pointed_thing, uses) function farming.hoe_on_use(itemstack, user, pointed_thing, uses)
local pt = pointed_thing local pt = pointed_thing
-- check if pointing at a node -- check if pointing at a node
if not pt or pt.type ~= "node" then if not pt or pt.type ~= "node" then
return return
@ -87,10 +96,13 @@ function farming.hoe_on_use(itemstack, user, pointed_thing, uses)
-- turn the node into soil, wear out item and play sound -- turn the node into soil, wear out item and play sound
minetest.set_node(pt.under, {name = "farming:soil"}) minetest.set_node(pt.under, {name = "farming:soil"})
minetest.sound_play("default_dig_crumbly", {pos = pt.under, gain = 0.5}) minetest.sound_play("default_dig_crumbly", {pos = pt.under, gain = 0.5})
if not minetest.setting_getbool("creative_mode") then if not minetest.setting_getbool("creative_mode") then
itemstack:add_wear(65535/(uses-1)) itemstack:add_wear(65535/(uses-1))
end end
return itemstack return itemstack
end end
@ -136,4 +148,4 @@ farming.register_hoe(":farming:hoe_diamond", {
inventory_image = "farming_tool_diamondhoe.png", inventory_image = "farming_tool_diamondhoe.png",
max_uses = 500, max_uses = 500,
material = "default:diamond" material = "default:diamond"
}) })

153
init.lua
View File

@ -1,5 +1,5 @@
--[[ --[[
Minetest Farming Redo Mod 1.22 (26th October 2015) Minetest Farming Redo Mod 1.22 (8th December 2015)
by TenPlus1 by TenPlus1
NEW growing routine by prestidigitator NEW growing routine by prestidigitator
auto-refill by crabman77 auto-refill by crabman77
@ -21,7 +21,9 @@ local DEBUG_abm_runs = 0
local DEBUG_abm_time = 0 local DEBUG_abm_time = 0
local DEBUG_timer_runs = 0 local DEBUG_timer_runs = 0
local DEBUG_timer_time = 0 local DEBUG_timer_time = 0
if farming.DEBUG then if farming.DEBUG then
function farming.DEBUG.reset_times() function farming.DEBUG.reset_times()
DEBUG_abm_runs = 0 DEBUG_abm_runs = 0
DEBUG_abm_time = 0 DEBUG_abm_time = 0
@ -30,6 +32,7 @@ if farming.DEBUG then
end end
function farming.DEBUG.report_times() function farming.DEBUG.report_times()
local abm_n = DEBUG_abm_runs local abm_n = DEBUG_abm_runs
local abm_dt = DEBUG_abm_time local abm_dt = DEBUG_abm_time
local abm_avg = (abm_n > 0 and abm_dt / abm_n) or 0 local abm_avg = (abm_n > 0 and abm_dt / abm_n) or 0
@ -37,15 +40,15 @@ if farming.DEBUG then
local timer_dt = DEBUG_timer_time local timer_dt = DEBUG_timer_time
local timer_avg = (timer_n > 0 and timer_dt / timer_n) or 0 local timer_avg = (timer_n > 0 and timer_dt / timer_n) or 0
local dt = abm_dt + timer_dt local dt = abm_dt + timer_dt
print("ABM ran for "..abm_dt.."µs over "..abm_n.." runs: "..
abm_avg.."µs/run") 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: ".. print("Timer ran for "..timer_dt.."µs over "..timer_n.." runs: "..timer_avg.."µs/run")
timer_avg.."µs/run")
print("Total farming time: "..dt.."µs") print("Total farming time: "..dt.."µs")
end end
end end
local statistics = dofile(farming.path.."/statistics.lua") local statistics = dofile(farming.path.."/statistics.lua")
dofile(farming.path.."/soil.lua") dofile(farming.path.."/soil.lua")
dofile(farming.path.."/hoes.lua") dofile(farming.path.."/hoes.lua")
dofile(farming.path.."/grass.lua") dofile(farming.path.."/grass.lua")
@ -95,12 +98,14 @@ end
-- If true, count elapsed day time. Otherwise, count elapsed night time. -- If true, count elapsed day time. Otherwise, count elapsed night time.
-- @return -- @return
-- The amount of day or night time that has elapsed. -- 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 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) local t1_c, t2_c -- t1_c < t2_c and t2_c always in [0, 1)
if count_day then if count_day then
if t_day < 0.25 then if t_day < 0.25 then
t1_c = t1_day + 0.75 -- Relative to sunup, yesterday t1_c = t1_day + 0.75 -- Relative to sunup, yesterday
t2_c = t_day + 0.75 t2_c = t_day + 0.75
@ -119,6 +124,7 @@ local function day_or_night_time(t_game, t_day, dt, count_day)
end end
local dt_c = clamp(t2_c, 0, 0.5) - clamp(t1_c, 0, 0.5) -- this cycle local dt_c = clamp(t2_c, 0, 0.5) - clamp(t1_c, 0, 0.5) -- this cycle
if t1_c < -0.5 then if t1_c < -0.5 then
local nc = math.floor(-t1_c) local nc = math.floor(-t1_c)
t1_c = t1_c + nc t1_c = t1_c + nc
@ -166,10 +172,13 @@ local MAX_LIGHT = 1000
-- Node or position table, or node name. -- Node or position table, or node name.
-- @return -- @return
-- List (plant_name, stage), or nothing (nil) if node isn't loaded -- List (plant_name, stage), or nothing (nil) if node isn't loaded
--
local function plant_name_stage(node) local function plant_name_stage(node)
local name local name
if type(node) == 'table' then if type(node) == 'table' then
if node.name then if node.name then
name = node.name name = node.name
elseif node.x and node.y and node.z then elseif node.x and node.y and node.z then
@ -179,11 +188,15 @@ local function plant_name_stage(node)
else else
name = tostring(node) name = tostring(node)
end end
if not name or name == "ignore" then return nil end if not name or name == "ignore" then return nil end
local sep_pos = name:find("_[^_]+$") local sep_pos = name:find("_[^_]+$")
if sep_pos and sep_pos > 1 then if sep_pos and sep_pos > 1 then
local stage = tonumber(name:sub(sep_pos + 1)) local stage = tonumber(name:sub(sep_pos + 1))
if stage and stage >= 0 then if stage and stage >= 0 then
return name:sub(1, sep_pos - 1), stage return name:sub(1, sep_pos - 1), stage
end end
@ -195,6 +208,7 @@ end
--- Map from node name to --- Map from node name to
-- { plant_name = ..., name = ..., stage = n, stages_left = { node_name, ... } } -- { plant_name = ..., name = ..., stage = n, stages_left = { node_name, ... } }
local plant_stages = {} local plant_stages = {}
farming.plant_stages = plant_stages farming.plant_stages = plant_stages
--- Registers the stages of growth of a (possible plant) node. --- Registers the stages of growth of a (possible plant) node.
@ -204,21 +218,26 @@ farming.plant_stages = plant_stages
-- @return -- @return
-- The (possibly zero) number of stages of growth the plant will go through -- The (possibly zero) number of stages of growth the plant will go through
-- before being fully grown, or nil if not a plant. -- before being fully grown, or nil if not a plant.
--
local register_plant_node local register_plant_node
-- Recursive helper -- Recursive helper
local function reg_plant_stages(plant_name, stage, force_last) local function reg_plant_stages(plant_name, stage, force_last)
local node_name = plant_name and plant_name .. "_" .. stage local node_name = plant_name and plant_name .. "_" .. stage
local node_def = node_name and minetest.registered_nodes[node_name] local node_def = node_name and minetest.registered_nodes[node_name]
if not node_def then return nil end if not node_def then return nil end
local stages = plant_stages[node_name] local stages = plant_stages[node_name]
if stages then return stages end if stages then return stages end
if minetest.get_item_group(node_name, "growing") > 0 then if minetest.get_item_group(node_name, "growing") > 0 then
local ns = reg_plant_stages(plant_name, stage + 1, true)
local ns = reg_plant_stages(plant_name, stage + 1, true)
local stages_left = (ns and { ns.name, unpack(ns.stages_left) }) or {} local stages_left = (ns and { ns.name, unpack(ns.stages_left) }) or {}
stages = { stages = {
plant_name = plant_name, plant_name = plant_name,
name = node_name, name = node_name,
@ -227,8 +246,10 @@ local function reg_plant_stages(plant_name, stage, force_last)
} }
if #stages_left > 0 then if #stages_left > 0 then
local old_constr = node_def.on_construct local old_constr = node_def.on_construct
local old_destr = node_def.on_destruct local old_destr = node_def.on_destruct
minetest.override_item(node_name, minetest.override_item(node_name,
{ {
on_construct = function(pos) on_construct = function(pos)
@ -246,7 +267,9 @@ local function reg_plant_stages(plant_name, stage, force_last)
end, end,
}) })
end end
elseif force_last then elseif force_last then
stages = { stages = {
plant_name = plant_name, plant_name = plant_name,
name = node_name, name = node_name,
@ -258,11 +281,14 @@ local function reg_plant_stages(plant_name, stage, force_last)
end end
plant_stages[node_name] = stages plant_stages[node_name] = stages
return stages return stages
end end
register_plant_node = function(node) register_plant_node = function(node)
local plant_name, stage = plant_name_stage(node) local plant_name, stage = plant_name_stage(node)
if plant_name then if plant_name then
local stages = reg_plant_stages(plant_name, stage, false) local stages = reg_plant_stages(plant_name, stage, false)
return stages and #stages.stages_left return stages and #stages.stages_left
@ -272,15 +298,22 @@ register_plant_node = function(node)
end end
local function set_growing(pos, stages_left) local function set_growing(pos, stages_left)
if not stages_left then return end if not stages_left then return end
local timer = minetest.get_node_timer(pos) local timer = minetest.get_node_timer(pos)
if stages_left > 0 then if stages_left > 0 then
if not timer:is_started() then if not timer:is_started() then
local stage_length = statistics.normal(STAGE_LENGTH_AVG, STAGE_LENGTH_DEV) 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) 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) timer:set(stage_length, -0.5 * math.random() * STAGE_LENGTH_AVG)
end end
elseif timer:is_started() then elseif timer:is_started() then
timer:stop() timer:stop()
end end
@ -292,10 +325,13 @@ end
-- The node's position. -- The node's position.
-- @param node -- @param node
-- The cached node table if available, or nil. -- The cached node table if available, or nil.
--
function farming.handle_growth(pos, node) function farming.handle_growth(pos, node)
if not pos then return end if not pos then return end
local stages_left = register_plant_node(node or pos) local stages_left = register_plant_node(node or pos)
if stages_left then set_growing(pos, stages_left) end if stages_left then set_growing(pos, stages_left) end
end end
@ -307,14 +343,19 @@ minetest.after(0,
end) end)
local abm_func = farming.handle_growth local abm_func = farming.handle_growth
if farming.DEBUG then if farming.DEBUG then
local normal_abm_func = abm_func local normal_abm_func = abm_func
abm_func = function(...) abm_func = function(...)
local t0 = minetest.get_us_time() local t0 = minetest.get_us_time()
local r = { normal_abm_func(...) } local r = { normal_abm_func(...) }
local t1 = minetest.get_us_time() local t1 = minetest.get_us_time()
DEBUG_abm_runs = DEBUG_abm_runs + 1 DEBUG_abm_runs = DEBUG_abm_runs + 1
DEBUG_abm_time = DEBUG_abm_time + (t1 - t0) DEBUG_abm_time = DEBUG_abm_time + (t1 - t0)
return unpack(r) return unpack(r)
end end
end end
@ -322,40 +363,51 @@ end
-- Just in case a growing type or added node is missed (also catches existing -- Just in case a growing type or added node is missed (also catches existing
-- nodes added to map before timers were incorporated). -- nodes added to map before timers were incorporated).
minetest.register_abm({ minetest.register_abm({
nodenames = { "group:growing" }, nodenames = { "group:growing" },
interval = 300, interval = 300,
chance = 1, chance = 1,
action = abm_func}) action = abm_func
})
--- Plant timer function. --- Plant timer function.
-- --
-- Grows plants under the right conditions. -- Grows plants under the right conditions.
--
function farming.plant_growth_timer(pos, elapsed, node_name) function farming.plant_growth_timer(pos, elapsed, node_name)
local stages = plant_stages[node_name] local stages = plant_stages[node_name]
if not stages then return false end if not stages then return false end
local max_growth = #stages.stages_left local max_growth = #stages.stages_left
if max_growth <= 0 then return false end if max_growth <= 0 then return false end
if stages.plant_name == "farming:cocoa" then if stages.plant_name == "farming:cocoa" then
if not minetest.find_node_near(pos, 1, { "default:jungletree", "moretrees:jungletree_leaves_green" }) then if not minetest.find_node_near(pos, 1, { "default:jungletree", "moretrees:jungletree_leaves_green" }) then
return true return true
end end
else else
local under = minetest.get_node_or_nil({ x = pos.x, y = pos.y - 1, z = pos.z }) 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 if not under or under.name ~= "farming:soil_wet" then return true end
end end
local growth local growth
local light_pos = { x = pos.x, y = pos.y, z = pos.z } local light_pos = { x = pos.x, y = pos.y, z = pos.z }
local lambda = elapsed / STAGE_LENGTH_AVG local lambda = elapsed / STAGE_LENGTH_AVG
if lambda < 0.1 then return true end if lambda < 0.1 then return true end
if max_growth == 1 or lambda < 2.0 then if max_growth == 1 or lambda < 2.0 then
local light = (minetest.get_node_light(light_pos) or 0) -- CHANGED local light = (minetest.get_node_light(light_pos) or 0) -- CHANGED
--print ("light level:", light) --print ("light level:", light)
if not in_range(light, MIN_LIGHT, MAX_LIGHT) then return true end if not in_range(light, MIN_LIGHT, MAX_LIGHT) then return true end
growth = 1 growth = 1
else else
local night_light = (minetest.get_node_light(light_pos, 0) or 0) -- CHANGED local night_light = (minetest.get_node_light(light_pos, 0) or 0) -- CHANGED
@ -371,51 +423,68 @@ function farming.plant_growth_timer(pos, elapsed, node_name)
end end
growth = statistics.poisson(lambda, max_growth) growth = statistics.poisson(lambda, max_growth)
if growth < 1 then return true end if growth < 1 then return true end
end end
minetest.swap_node(pos, { name = stages.stages_left[growth] }) if minetest.registered_nodes[stages.stages_left[growth]] then
minetest.swap_node(pos, { name = stages.stages_left[growth] })
else
return true
end
return growth ~= max_growth return growth ~= max_growth
end end
if farming.DEBUG then if farming.DEBUG then
local timer_func = farming.plant_growth_timer; local timer_func = farming.plant_growth_timer;
farming.plant_growth_timer = function(pos, elapsed, node_name) farming.plant_growth_timer = function(pos, elapsed, node_name)
local t0 = minetest.get_us_time() local t0 = minetest.get_us_time()
local r = { timer_func(pos, elapsed, node_name) } local r = { timer_func(pos, elapsed, node_name) }
local t1 = minetest.get_us_time() local t1 = minetest.get_us_time()
DEBUG_timer_runs = DEBUG_timer_runs + 1 DEBUG_timer_runs = DEBUG_timer_runs + 1
DEBUG_timer_time = DEBUG_timer_time + (t1 - t0) DEBUG_timer_time = DEBUG_timer_time + (t1 - t0)
return unpack(r) return unpack(r)
end end
end end
-- refill placed plant by crabman (26/08/2015) -- refill placed plant by crabman (26/08/2015)
local can_refill_plant = { local can_refill_plant = {
["farming:blueberry_1"] = "farming:blueberries", ["farming:blueberry_1"] = "farming:blueberries",
["farming:carrot_1"] = "farming:carrot", ["farming:carrot_1"] = "farming:carrot",
["farming:coffee_1"] = "farming:coffee_beans", ["farming:coffee_1"] = "farming:coffee_beans",
["farming:corn_1"] = "farming:corn", ["farming:corn_1"] = "farming:corn",
["farming:cotton_1"] = "farming:seed_cotton", ["farming:cotton_1"] = "farming:seed_cotton",
["farming:cucumber_1"] = "farming:cucumber", ["farming:cucumber_1"] = "farming:cucumber",
["farming:melon_1"] = "farming:melon_slice", ["farming:melon_1"] = "farming:melon_slice",
["farming:potato_1"] = "farming:potato", ["farming:potato_1"] = "farming:potato",
["farming:pumpkin_1"] = "farming:pumpkin_slice", ["farming:pumpkin_1"] = "farming:pumpkin_slice",
["farming:raspberry_1"] = "farming:raspberries", ["farming:raspberry_1"] = "farming:raspberries",
["farming:rhubarb_1"] = "farming:rhubarb", ["farming:rhubarb_1"] = "farming:rhubarb",
["farming:tomato_1"] = "farming:tomato", ["farming:tomato_1"] = "farming:tomato",
["farming:wheat_1"] = "farming:seed_wheat" ["farming:wheat_1"] = "farming:seed_wheat",
["farming:grapes_1"] = "farming:grapes",
["farming:beans_1"] = "farming:beans",
["farming:rhubarb_1"] = "farming:rhubarb",
["farming:cocoa_1"] = "farming:cocoa_beans",
} }
function farming.refill_plant(player, plantname, index) function farming.refill_plant(player, plantname, index)
local inv = player:get_inventory() local inv = player:get_inventory()
local old_stack = inv:get_stack("main", index) local old_stack = inv:get_stack("main", index)
if old_stack:get_name() ~= "" then return end if old_stack:get_name() ~= "" then return end
for i,stack in ipairs(inv:get_list("main")) do
for i, stack in ipairs(inv:get_list("main")) do
if stack:get_name() == plantname and i ~= index then if stack:get_name() == plantname and i ~= index then
inv:set_stack("main", index, stack) inv:set_stack("main", index, stack)
stack:clear() stack:clear()
inv:set_stack("main", i, stack) inv:set_stack("main", i, stack)
@ -428,6 +497,7 @@ end -- END refill
-- Place Seeds on Soil -- Place Seeds on Soil
function farming.place_seed(itemstack, placer, pointed_thing, plantname) function farming.place_seed(itemstack, placer, pointed_thing, plantname)
local pt = pointed_thing local pt = pointed_thing
-- check if pointing at a node -- check if pointing at a node
@ -459,20 +529,26 @@ function farming.place_seed(itemstack, placer, pointed_thing, plantname)
-- if not protected then add node and remove 1 item from the itemstack -- 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 if not minetest.is_protected(pt.above, placer:get_player_name()) then
minetest.set_node(pt.above, {name = plantname, param2 = 1}) minetest.set_node(pt.above, {name = plantname, param2 = 1})
if not minetest.setting_getbool("creative_mode") then if not minetest.setting_getbool("creative_mode") then
itemstack:take_item() itemstack:take_item()
-- check for refill -- check for refill
if itemstack:get_count() == 0 if itemstack:get_count() == 0
and can_refill_plant[plantname] then and can_refill_plant[plantname] then
minetest.after(0.10, minetest.after(0.10,
farming.refill_plant, farming.refill_plant,
placer, placer,
can_refill_plant[plantname], can_refill_plant[plantname],
placer:get_wield_index() placer:get_wield_index()
) )
end -- END refill end
end end
return itemstack return itemstack
end end
end end
@ -480,6 +556,7 @@ end
-- Function to register plants (for compatibility) -- Function to register plants (for compatibility)
farming.register_plant = function(name, def) farming.register_plant = function(name, def)
local mname = name:split(":")[1] local mname = name:split(":")[1]
local pname = name:split(":")[2] local pname = name:split(":")[2]
@ -487,15 +564,18 @@ farming.register_plant = function(name, def)
if not def.description then if not def.description then
def.description = "Seed" def.description = "Seed"
end end
if not def.inventory_image then if not def.inventory_image then
def.inventory_image = "unknown_item.png" def.inventory_image = "unknown_item.png"
end end
if not def.steps then if not def.steps then
return nil return nil
end end
-- Register seed -- Register seed
minetest.register_node(":" .. mname .. ":seed_" .. pname, { minetest.register_node(":" .. mname .. ":seed_" .. pname, {
description = def.description, description = def.description,
tiles = {def.inventory_image}, tiles = {def.inventory_image},
inventory_image = def.inventory_image, inventory_image = def.inventory_image,
@ -507,6 +587,7 @@ farming.register_plant = function(name, def)
walkable = false, walkable = false,
sunlight_propagates = true, sunlight_propagates = true,
selection_box = farming.select, selection_box = farming.select,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, mname .. ":"..pname.."_1") return farming.place_seed(itemstack, placer, pointed_thing, mname .. ":"..pname.."_1")
end end
@ -520,6 +601,7 @@ farming.register_plant = function(name, def)
-- Register growing steps -- Register growing steps
for i = 1, def.steps do for i = 1, def.steps do
local drop = { local drop = {
items = { items = {
{items = {mname .. ":" .. pname}, rarity = 9 - i}, {items = {mname .. ":" .. pname}, rarity = 9 - i},
@ -530,12 +612,14 @@ farming.register_plant = function(name, def)
} }
local g = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1, growing = 1} 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 -- Last step doesn't need growing=1 so Abm never has to check these
if i == def.steps then if i == def.steps then
g = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1} g = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1}
end end
local node_name = mname .. ":" .. pname .. "_" .. i local node_name = mname .. ":" .. pname .. "_" .. i
minetest.register_node(node_name, { minetest.register_node(node_name, {
drawtype = "plantlike", drawtype = "plantlike",
waving = 1, waving = 1,
@ -548,6 +632,7 @@ farming.register_plant = function(name, def)
groups = g, groups = g,
sounds = default.node_sound_leaves_defaults(), sounds = default.node_sound_leaves_defaults(),
}) })
register_plant_node(node_name) register_plant_node(node_name)
end end

View File

@ -31,13 +31,13 @@ function farming.register_mgv6_decorations()
register_plant("melon_8", 1, 20, "group:water", 1) register_plant("melon_8", 1, 20, "group:water", 1)
register_plant("pumpkin_8", 1, 20, "group:water", 1) register_plant("pumpkin_8", 1, 20, "group:water", 1)
register_plant("raspberry_4", 3, 10, "", -1) register_plant("raspberry_4", 3, 10, "", -1)
register_plant("rhubarb_3", 3, 15, "group:tree", 1) register_plant("rhubarb_3", 3, 15, "", -1)
register_plant("blueberry_4", 3, 10, "", -1) register_plant("blueberry_4", 3, 10, "", -1)
register_plant("beanbush", 18, 35, "", -1) register_plant("beanbush", 18, 35, "", -1)
register_plant("grapebush", 25, 45, "", -1) register_plant("grapebush", 25, 45, "", -1)
end end
-- v7 maps have a beach so plants growing near water is limited to 6- high -- v7 maps have a beach so plants growing near water is limited to 6 high
function farming.register_mgv7_decorations() function farming.register_mgv7_decorations()
register_plant("potato_3", 15, 40, "", -1) register_plant("potato_3", 15, 40, "", -1)
register_plant("tomato_7", 5, 20, "", -1) register_plant("tomato_7", 5, 20, "", -1)
@ -49,7 +49,7 @@ function farming.register_mgv7_decorations()
register_plant("melon_8", 1, 6, "", -1) register_plant("melon_8", 1, 6, "", -1)
register_plant("pumpkin_8", 1, 6, "", -1) register_plant("pumpkin_8", 1, 6, "", -1)
register_plant("raspberry_4", 3, 10, "", -1) register_plant("raspberry_4", 3, 10, "", -1)
register_plant("rhubarb_3", 3, 15, "group:tree", 1) register_plant("rhubarb_3", 3, 15, "", -1)
register_plant("blueberry_4", 3, 10, "", -1) register_plant("blueberry_4", 3, 10, "", -1)
register_plant("beanbush", 18, 35, "", -1) register_plant("beanbush", 18, 35, "", -1)
register_plant("grapebush", 25, 45, "", -1) register_plant("grapebush", 25, 45, "", -1)

View File

@ -26,6 +26,7 @@ minetest.register_abm({
interval = 15, interval = 15,
chance = 4, chance = 4,
catch_up = false, catch_up = false,
action = function(pos, node) action = function(pos, node)
pos.y = pos.y + 1 pos.y = pos.y + 1
@ -52,8 +53,10 @@ minetest.register_abm({
if node.name == "farming:soil" then if node.name == "farming:soil" then
minetest.set_node(pos, {name = "farming:soil_wet"}) minetest.set_node(pos, {name = "farming:soil_wet"})
end end
elseif node.name == "farming:soil_wet" then elseif node.name == "farming:soil_wet" then
minetest.set_node(pos, {name = "farming:soil"}) minetest.set_node(pos, {name = "farming:soil"})
elseif node.name == "farming:soil" then elseif node.name == "farming:soil" then
minetest.set_node(pos, {name = "default:dirt"}) minetest.set_node(pos, {name = "default:dirt"})
end end

View File

@ -1,9 +1,9 @@
local statistics = {} local statistics = {}
local ROOT_2 = math.sqrt(2.0) local ROOT_2 = math.sqrt(2.0)
-- Approximations for erf(x) and erfInv(x) from -- Approximations for erf(x) and erfInv(x) from
-- https://en.wikipedia.org/wiki/Error_function -- https://en.wikipedia.org/wiki/Error_function
local erf local erf
local erf_inv local erf_inv
@ -13,19 +13,26 @@ local C = 2.0/(math.pi * A)
local D = 1.0 / A local D = 1.0 / A
erf = function(x) erf = function(x)
if x == 0 then return 0; end if x == 0 then return 0; end
local xSq = x * x local xSq = x * x
local aXSq = A * xSq local aXSq = A * xSq
local v = math.sqrt(1.0 - math.exp(-xSq * (B + aXSq) / (1.0 + aXSq))) local v = math.sqrt(1.0 - math.exp(-xSq * (B + aXSq) / (1.0 + aXSq)))
return (x > 0 and v) or -v return (x > 0 and v) or -v
end end
erf_inv = function(x) erf_inv = function(x)
if x == 0 then return 0; end if x == 0 then return 0; end
if x <= -1 or x >= 1 then return nil; end if x <= -1 or x >= 1 then return nil; end
local y = math.log(1 - x * x) local y = math.log(1 - x * x)
local u = C + 0.5 * y local u = C + 0.5 * y
local v = math.sqrt(math.sqrt(u * u - D * y) - u) local v = math.sqrt(math.sqrt(u * u - D * y) - u)
return (x > 0 and v) or -v return (x > 0 and v) or -v
end end
@ -37,6 +44,7 @@ local poisson
local cdf_table = {} local cdf_table = {}
local function generate_cdf(lambda_index, lambda) local function generate_cdf(lambda_index, lambda)
local max = math.ceil(4 * lambda) local max = math.ceil(4 * lambda)
local pdf = math.exp(-lambda) local pdf = math.exp(-lambda)
local cdf = pdf local cdf = pdf
@ -56,6 +64,7 @@ for li = 1, 100 do
end end
poisson = function(lambda, max) poisson = function(lambda, max)
if max < 2 then if max < 2 then
return (math.random() < math.exp(-lambda) and 0) or 1 return (math.random() < math.exp(-lambda) and 0) or 1
elseif lambda >= 2 * max then elseif lambda >= 2 * max then
@ -67,6 +76,7 @@ poisson = function(lambda, max)
local cdfs = cdf_table[lambda_index] local cdfs = cdf_table[lambda_index]
if cdfs then if cdfs then
lambda = 0.25 * lambda_index lambda = 0.25 * lambda_index
if u < cdfs[0] then return 0; end if u < cdfs[0] then return 0; end
@ -74,9 +84,13 @@ poisson = function(lambda, max)
if u >= cdfs[max - 1] then return max; end if u >= cdfs[max - 1] then return max; end
if max > 4 then -- Binary search if max > 4 then -- Binary search
local s = 0 local s = 0
while s + 1 < max do while s + 1 < max do
local m = math.floor(0.5 * (s + max)) local m = math.floor(0.5 * (s + max))
if u < cdfs[m] then max = m; else s = m; end if u < cdfs[m] then max = m; else s = m; end
end end
else else
@ -88,6 +102,7 @@ poisson = function(lambda, max)
return max return max
else else
local x = lambda + math.sqrt(lambda) * std_normal(u) 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) return (x < 0.5 and 0) or (x >= max - 0.5 and max) or math.floor(x + 0.5)
end end
end end
@ -102,14 +117,17 @@ statistics.erf_inv = erf_inv
-- --
-- @return -- @return
-- Any real number (actually between -3.0 and 3.0). -- Any real number (actually between -3.0 and 3.0).
--
statistics.std_normal = function() statistics.std_normal = function()
local u = math.random() local u = math.random()
if u < 0.001 then if u < 0.001 then
return -3.0 return -3.0
elseif u > 0.999 then elseif u > 0.999 then
return 3.0 return 3.0
end end
return std_normal(u) return std_normal(u)
end end
@ -121,14 +139,17 @@ end
-- The distribution standard deviation. -- The distribution standard deviation.
-- @return -- @return
-- Any real number (actually between -3*sigma and 3*sigma). -- Any real number (actually between -3*sigma and 3*sigma).
--
statistics.normal = function(mu, sigma) statistics.normal = function(mu, sigma)
local u = math.random() local u = math.random()
if u < 0.001 then if u < 0.001 then
return mu - 3.0 * sigma return mu - 3.0 * sigma
elseif u > 0.999 then elseif u > 0.999 then
return mu + 3.0 * sigma return mu + 3.0 * sigma
end end
return mu + sigma * std_normal(u) return mu + sigma * std_normal(u)
end end
@ -140,11 +161,14 @@ end
-- The distribution maximum. -- The distribution maximum.
-- @return -- @return
-- An integer between 0 and max (both inclusive). -- An integer between 0 and max (both inclusive).
--
statistics.poisson = function(lambda, max) statistics.poisson = function(lambda, max)
lambda, max = tonumber(lambda), tonumber(max) lambda, max = tonumber(lambda), tonumber(max)
if not lambda or not max or lambda <= 0 or max < 1 then return 0; end if not lambda or not max or lambda <= 0 or max < 1 then return 0; end
return poisson(lambda, max) return poisson(lambda, max)
end end
return statistics return statistics