Add some growth for unloaded farming plants

This commit is contained in:
kay27 2020-09-05 21:49:12 +04:00
parent 766c76831d
commit f2d68d909e

View File

@ -1,22 +1,74 @@
local plant_lists = {}
local plant_nodename_to_id_list = {}
local function get_intervals_counter(pos, interval, chance)
local meta = minetest.get_meta(pos)
local time_speed = tonumber(minetest.settings:get('time_speed') or 72)
local current_game_time
if time_speed == nil then
return 1
end
if (time_speed < 0.1) then
return 1
end
local time_multiplier = 86400 / time_speed
current_game_time = .0 + ((minetest.get_day_count() + minetest.get_timeofday()) * time_multiplier)
local approx_interval = math.max(interval, 1) * math.max(chance, 1)
local last_game_time = meta:get_string("last_gametime")
if last_game_time then
last_game_time = tonumber(last_game_time)
end
if not last_game_time or last_game_time < 1 then
last_game_time = current_game_time - approx_interval / 10
elseif last_game_time == current_game_time then
current_game_time = current_game_time + approx_interval
end
local elapsed_game_time = .0 + current_game_time - last_game_time
meta:set_string("last_gametime", tostring(current_game_time))
return elapsed_game_time / approx_interval
end
local function get_avg_light_level(pos)
local node_light = tonumber(minetest.get_node_light(pos) or 0)
local meta = minetest.get_meta(pos)
local counter = meta:get_int("avg_light_count")
local summary = meta:get_int("avg_light_summary")
if counter > 99 then
counter = 51
summary = math.ceil((summary + 0.0) / 2.0)
else
counter = counter + 1
end
summary = summary + node_light
meta:set_int("avg_light_count", counter)
meta:set_int("avg_light_summary", summary)
return math.ceil((summary + 0.0) / counter)
end
function mcl_farming:add_plant(identifier, full_grown, names, interval, chance)
plant_lists[identifier] = {}
plant_lists[identifier].full_grown = full_grown
plant_lists[identifier].names = names
plant_lists[identifier].interval = interval
plant_lists[identifier].chance = chance
minetest.register_abm({
label = string.format("Farming plant growth (%s)", identifier),
nodenames = names,
interval = interval,
chance = chance,
action = function(pos, node)
if minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name ~= "mcl_farming:soil_wet" and math.random(0, 9) > 0 then
return
else
mcl_farming:grow_plant(identifier, pos, node)
end
local low_speed = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name ~= "mcl_farming:soil_wet"
mcl_farming:grow_plant(identifier, pos, node, false, false, low_speed)
end,
})
for _, nodename in pairs(names) do
plant_nodename_to_id_list[nodename] = identifier
end
end
-- Attempts to advance a plant at pos by one or more growth stages (if possible)
@ -28,15 +80,34 @@ end
-- Returns true if plant has been grown by 1 or more stages.
-- Returns false if nothing changed.
function mcl_farming:grow_plant(identifier, pos, node, stages, ignore_light)
if not minetest.get_node_light(pos) and not ignore_light then
function mcl_farming:grow_plant(identifier, pos, node, stages, ignore_light, low_speed)
local average_light_level = get_avg_light_level(pos)
local plant_info = plant_lists[identifier]
local intervals_counter = get_intervals_counter(pos, plant_info.interval, plant_info.chance)
local low_speed = low_speed or false
if low_speed then
if intervals_counter < 1.01 and math.random(0, 9) > 0 then
return
else
intervals_counter = intervals_counter / 10
end
end
if not minetest.get_node_light(pos) and not ignore_light and intervals_counter < 1.5 then
return false
end
if minetest.get_node_light(pos) < 10 and not ignore_light then
if minetest.get_node_light(pos) < 10 and not ignore_light and intervals_counter < 1.5 then
return false
end
local plant_info = plant_lists[identifier]
if intervals_counter >= 1.5 then
if average_light_level < 0.1 then
return false
end
if average_light_level < 10 then
intervals_counter = intervals_counter * average_light_level / 10
end
end
local step = nil
for i, name in ipairs(plant_info.names) do
@ -51,6 +122,7 @@ function mcl_farming:grow_plant(identifier, pos, node, stages, ignore_light)
if not stages then
stages = 1
end
stages = stages + math.ceil(intervals_counter)
local new_node = {name = plant_info.names[step+stages]}
if new_node.name == nil then
new_node.name = plant_info.full_grown
@ -86,6 +158,7 @@ function mcl_farming:place_seed(itemstack, placer, pointed_thing, plantname)
if string.find(farmland.name, "mcl_farming:soil") and string.find(place_s.name, "air") then
minetest.sound_play(minetest.registered_nodes[plantname].sounds.place, {pos = pos}, true)
minetest.add_node(pos, {name=plantname, param2 = minetest.registered_nodes[plantname].place_param2})
local intervals_counter = get_intervals_counter(pos, 1, 1)
else
return
end
@ -379,3 +452,18 @@ function mcl_farming:stem_color(startcolor, endcolor, step, step_count)
local colorstring = string.format("#%02X%02X%02X", color.r, color.g, color.b)
return colorstring
end
minetest.register_lbm({
label = "Add growth for unloaded farming plants",
name = "mcl_farming:growth",
nodenames = {"group:plant"},
run_at_every_load = true,
action = function(pos, node)
local identifier = plant_nodename_to_id_list[node.name]
if not identifier then
return
end
local low_speed = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name ~= "mcl_farming:soil_wet"
mcl_farming:grow_plant(identifier, pos, node, false, false, low_speed)
end,
})