288 lines
8.6 KiB
Lua
288 lines
8.6 KiB
Lua
local S = minetest.get_translator("rp_farming")
|
|
|
|
--
|
|
-- Farming and plant growing API
|
|
--
|
|
|
|
farming.registered_plants = {}
|
|
|
|
function farming.register_plant(name, plant)
|
|
-- Note: You'll have to register 4 plant growing nodes before calling this!
|
|
-- Format: "[mod:plant]_[stage from 1-4]"
|
|
|
|
farming.registered_plants[name] = plant -- Might need to fully copy here?
|
|
|
|
local lbm_name = string.gsub(name, ":", "_")
|
|
minetest.register_lbm(
|
|
{
|
|
label = "Grow legacy farming plants ("..name..")",
|
|
name = "rp_farming:grow_legacy_plants_v2_"..lbm_name,
|
|
|
|
nodenames = {
|
|
name .. "_1",
|
|
name .. "_2",
|
|
name .. "_3",
|
|
},
|
|
|
|
action = function(pos, node)
|
|
local timer = minetest.get_node_timer(pos)
|
|
if not timer:is_started() then
|
|
farming.begin_growing_plant(pos)
|
|
end
|
|
end,
|
|
}
|
|
)
|
|
|
|
local function add_callbacks(nodename)
|
|
minetest.override_item(
|
|
nodename,
|
|
{
|
|
on_timer = function(pos)
|
|
local name = string.gsub(minetest.get_node(pos).name, "_(%d+)", "")
|
|
|
|
farming.grow_plant(pos, name)
|
|
end,
|
|
|
|
on_construct = function(pos)
|
|
farming.begin_growing_plant(pos)
|
|
end,
|
|
|
|
on_place = farming.place_plant,
|
|
}
|
|
)
|
|
end
|
|
|
|
add_callbacks(name .. "_1")
|
|
add_callbacks(name .. "_2")
|
|
add_callbacks(name .. "_3")
|
|
end
|
|
|
|
function farming.register_plant_nodes(name, def)
|
|
local selbox = {
|
|
type = "fixed",
|
|
fixed = {-0.5, -0.5, -0.5, 0.5, -0.5+(4/16), 0.5}
|
|
}
|
|
local paramtype2, place_param2
|
|
if def.meshoptions then
|
|
paramtype2 = "meshoptions"
|
|
place_param2 = def.meshoptions
|
|
end
|
|
local sounds_plant
|
|
if not def.sounds_plant then
|
|
sounds_plant = rp_sounds.node_sound_grass_defaults()
|
|
end
|
|
local sounds_seed = table.copy(sounds_plant)
|
|
if def.sound_seed_place then
|
|
sounds_seed.place = def.sound_seed_place
|
|
else
|
|
sounds_seed.place = { name = "rp_farming_place_seed", gain = 0.4 }
|
|
end
|
|
|
|
local defs = {}
|
|
defs[1] = {
|
|
description = def.description_stage_1,
|
|
_tt_help = def.tooltip_stage_1,
|
|
drawtype = "plantlike",
|
|
tiles = {def.texture_prefix.."_1.png"},
|
|
inventory_image = def.texture_prefix.."_seed.png",
|
|
wield_image = def.texture_prefix.."_seed.png",
|
|
paramtype = "light",
|
|
sunlight_propagates = true,
|
|
paramtype2 = paramtype2,
|
|
place_param2 = place_param2,
|
|
node_placement_prediction = "",
|
|
waving = 1,
|
|
walkable = false,
|
|
floodable = true,
|
|
buildable_to = true,
|
|
is_ground_content = true,
|
|
drop = def.drop_stages[1],
|
|
selection_box = selbox,
|
|
groups = {snappy=3, handy=2, attached_node=1, seed=1, plant=1, farming_plant=1, ["plant_"..name]=1},
|
|
sounds = sounds_seed,
|
|
_rp_farming_plant_name = name,
|
|
}
|
|
|
|
for s=2, 4 do
|
|
defs[s] = {
|
|
description = S(def.description_general, s),
|
|
drawtype = "plantlike",
|
|
tiles = {def.texture_prefix.."_"..s..".png"},
|
|
inventory_image = def.texture_prefix.."_"..s..".png",
|
|
wield_image = def.texture_prefix.."_"..s..".png",
|
|
paramtype = "light",
|
|
sunlight_propagates = true,
|
|
paramtype2 = paramtype2,
|
|
place_param2 = place_param2,
|
|
node_placement_prediction = "",
|
|
waving = 1,
|
|
walkable = false,
|
|
floodable = true,
|
|
buildable_to = true,
|
|
is_ground_content = true,
|
|
drop = def.drop_stages[s],
|
|
selection_box = selbox,
|
|
groups = {snappy=3, handy=2, attached_node=1, plant=1, farming_plant=1, ["plant_"..name]=s, not_in_craft_guide = 1, not_in_creative_inventory = 1},
|
|
sounds = sounds_plant,
|
|
_rp_farming_plant_name = name,
|
|
}
|
|
end
|
|
|
|
-- Add custom node definition additions
|
|
if def.stage_extras then
|
|
for e=1, 4 do
|
|
if def.stage_extras[e] then
|
|
local extra = def.stage_extras[e]
|
|
for k,v in pairs(extra) do
|
|
defs[e][k] = v
|
|
end
|
|
end
|
|
end
|
|
end
|
|
-- Add custom group definition additions
|
|
if def.stage_extra_groups then
|
|
for e=1, 4 do
|
|
if def.stage_extra_groups[e] then
|
|
local extra = def.stage_extra_groups[e]
|
|
for k,v in pairs(extra) do
|
|
defs[e].groups[k] = v
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Register plants
|
|
for s=1, 4 do
|
|
minetest.register_node(name.."_"..s, defs[s])
|
|
end
|
|
|
|
end
|
|
|
|
function farming.begin_growing_plant(pos)
|
|
local name = string.gsub(minetest.get_node(pos).name, "_(%d+)", "")
|
|
|
|
local plant = farming.registered_plants[name]
|
|
|
|
minetest.get_node_timer(pos):start(
|
|
math.random(plant.grow_time / 8, plant.grow_time / 4))
|
|
end
|
|
|
|
function farming.place_plant(itemstack, placer, pointed_thing)
|
|
-- Boilerplace to handle pointed node's rightclick handler
|
|
if not placer or not placer:is_player() then
|
|
return itemstack
|
|
end
|
|
if pointed_thing.type ~= "node" then
|
|
return minetest.item_place_node(itemstack, placer, pointed_thing)
|
|
end
|
|
local node = minetest.get_node(pointed_thing.under)
|
|
local def = minetest.registered_nodes[node.name]
|
|
if def and def.on_rightclick and
|
|
((not placer) or (placer and not placer:get_player_control().sneak)) then
|
|
return def.on_rightclick(pointed_thing.under, node, placer, itemstack,
|
|
pointed_thing) or itemstack
|
|
end
|
|
|
|
-- Get plant ID
|
|
local name = string.gsub(itemstack:get_name(), "_(%d+)", "")
|
|
|
|
local plant = farming.registered_plants[name]
|
|
|
|
-- Find placement position
|
|
local place_in, place_on = util.pointed_thing_to_place_pos(pointed_thing)
|
|
if not place_in then
|
|
rp_sounds.play_place_failed_sound(placer)
|
|
return itemstack
|
|
end
|
|
|
|
-- Can't place plant on itself to prevent wasting seeds
|
|
local place_in_node = minetest.get_node(place_in)
|
|
local pidef = minetest.registered_nodes[place_in_node.name]
|
|
if pidef and pidef._rp_farming_plant_name == name then
|
|
rp_sounds.play_place_failed_sound(placer)
|
|
return itemstack
|
|
end
|
|
|
|
local place_on_node = minetest.get_node(place_on)
|
|
-- Find plant definition and grow plant
|
|
for _, can_grow_on in ipairs(plant.grows_on) do
|
|
local group = string.match(can_grow_on, "group:(.*)")
|
|
|
|
if (group ~= nil and minetest.get_item_group(place_on_node.name, group) > 0) or
|
|
(place_on_node.name == can_grow_on) then
|
|
local idef = itemstack:get_definition()
|
|
itemstack = minetest.item_place(itemstack, placer, pointed_thing)
|
|
if idef and idef.sounds and idef.sounds.place then
|
|
minetest.sound_play(idef.sounds.place, {pos=place_on}, true)
|
|
end
|
|
return itemstack
|
|
end
|
|
end
|
|
|
|
rp_sounds.play_place_failed_sound(placer)
|
|
return itemstack
|
|
end
|
|
|
|
-- Grow plant to next stage.
|
|
-- Returns true if plant has grown, false if not (e.g. because of max stage)
|
|
function farming.next_stage(pos, plant_name)
|
|
local my_node = minetest.get_node(pos)
|
|
local p2 = my_node.param2
|
|
|
|
if my_node.name == plant_name .. "_1" then
|
|
minetest.set_node(pos, {name = plant_name .. "_2", param2 = p2})
|
|
return true
|
|
elseif my_node.name == plant_name .. "_2" then
|
|
minetest.set_node(pos, {name = plant_name .. "_3", param2 = p2})
|
|
return true
|
|
elseif my_node.name == plant_name .. "_3" then
|
|
minetest.set_node(pos, {name = plant_name .. "_4", param2 = p2})
|
|
|
|
-- Stop the timer on the node so no more growing occurs until needed
|
|
|
|
minetest.get_node_timer(pos):stop()
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function farming.grow_plant(pos, name)
|
|
local plant = farming.registered_plants[name]
|
|
|
|
-- Check nearby nodes such as water
|
|
|
|
local my_node = minetest.get_node(pos)
|
|
|
|
if plant.grows_near and
|
|
minetest.find_node_near(pos, plant.growing_distance, plant.grows_near) == nil then
|
|
minetest.get_node_timer(pos):start(
|
|
math.random(plant.grow_time / 16, plant.grow_time / 4))
|
|
|
|
return
|
|
end
|
|
|
|
-- Check light; if too dark check again soon
|
|
|
|
local light = minetest.get_node_light(pos)
|
|
|
|
if light ~= nil and (light < plant.light_min or light > plant.light_max) then
|
|
minetest.get_node_timer(pos):start(
|
|
math.random(plant.grow_time / 16, plant.grow_time / 4))
|
|
|
|
return
|
|
end
|
|
|
|
-- Grow and check for rain and fertilizer
|
|
|
|
farming.next_stage(pos, name)
|
|
|
|
local under = vector.add(pos, vector.new(0, -1, 0))
|
|
if minetest.get_item_group(under.name, "plantable_fertilizer") > 0 then
|
|
farming.next_stage(pos, name)
|
|
end
|
|
|
|
if weather.weather == "storm" then
|
|
farming.next_stage(pos, name)
|
|
end
|
|
end
|