2017-04-01 03:54:58 +02:00
local plant_lists = { }
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
2017-03-13 23:09:27 +01:00
minetest.register_abm ( {
2017-05-15 00:45:54 +02:00
label = string.format ( " Farming plant growth (%s) " , identifier ) ,
2017-03-13 23:09:27 +01:00
nodenames = names ,
interval = interval ,
chance = chance ,
action = function ( pos , node )
2017-04-01 03:54:58 +02:00
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
2017-03-13 23:09:27 +01:00
return
2017-04-01 03:54:58 +02:00
else
mcl_farming : grow_plant ( identifier , pos , node )
2017-03-13 23:09:27 +01:00
end
2017-04-01 03:54:58 +02:00
end ,
2017-03-13 23:09:27 +01:00
} )
end
2017-04-01 03:54:58 +02:00
-- Attempts to advance a plant at pos by one or more growth stages (if possible)
-- identifier: Identifier of plant as defined by mcl_farming:add_plant
-- pos: Position
-- node: Node table
-- stages: Number of stages to advance (optional, defaults to 1)
2017-05-25 03:24:11 +02:00
-- Returns true if plant has been grown by 1 or more stages.
-- Returns false if nothing changed.
2017-04-01 03:54:58 +02:00
function mcl_farming : grow_plant ( identifier , pos , node , stages )
if not minetest.get_node_light ( pos ) then
2017-05-25 03:24:11 +02:00
return false
2017-04-01 03:54:58 +02:00
end
if minetest.get_node_light ( pos ) < 10 then
2017-05-25 03:24:11 +02:00
return false
2017-04-01 03:54:58 +02:00
end
local plant_info = plant_lists [ identifier ]
local step = nil
for i , name in ipairs ( plant_info.names ) do
if name == node.name then
step = i
break
end
end
if step == nil then
2017-05-25 03:24:11 +02:00
return false
2017-04-01 03:54:58 +02:00
end
if not stages then
stages = 1
end
local new_node = { name = plant_info.names [ step + stages ] }
if new_node.name == nil then
new_node.name = plant_info.full_grown
end
new_node.param = node.param
new_node.param2 = node.param2
minetest.set_node ( pos , new_node )
2017-05-25 03:24:11 +02:00
return true
2017-04-01 03:54:58 +02:00
end
2017-03-13 23:09:27 +01:00
function mcl_farming : place_seed ( itemstack , placer , pointed_thing , plantname )
local pt = pointed_thing
if not pt then
return
end
if pt.type ~= " node " then
return
end
-- Use pointed node's on_rightclick function first, if present
local node = minetest.get_node ( pt.under )
if placer and not placer : get_player_control ( ) . sneak then
if minetest.registered_nodes [ node.name ] and minetest.registered_nodes [ node.name ] . on_rightclick then
return minetest.registered_nodes [ node.name ] . on_rightclick ( pt.under , node , placer , itemstack ) or itemstack
end
end
2017-03-14 03:56:33 +01:00
2017-03-13 23:09:27 +01:00
local pos = { x = pt.above . x , y = pt.above . y - 1 , z = pt.above . z }
local farmland = minetest.get_node ( pos )
pos = { x = pt.above . x , y = pt.above . y , z = pt.above . z }
local place_s = minetest.get_node ( pos )
if string.find ( farmland.name , " mcl_farming:soil " ) and string.find ( place_s.name , " air " ) then
2017-03-15 00:04:51 +01:00
minetest.sound_play ( minetest.registered_nodes [ plantname ] . sounds.place , { pos = pos } )
2017-03-14 21:25:20 +01:00
minetest.add_node ( pos , { name = plantname , param2 = minetest.registered_nodes [ plantname ] . place_param2 } )
2017-03-13 23:09:27 +01:00
else
return
end
2017-08-09 16:17:00 +02:00
if not minetest.settings : get_bool ( " creative_mode " ) then
2017-03-13 23:09:27 +01:00
itemstack : take_item ( )
end
return itemstack
end
2017-03-13 22:30:37 +01:00
--[[ Helper function to create a gourd (e.g. melon, pumpkin), the connected stem nodes as
- full_unconnected_stem : itemstring of the full - grown but unconnceted stem node . This node must already be done
- connected_stem_basename : prefix of the itemstrings used for the 4 connected stem nodes to create
2017-03-14 04:17:35 +01:00
- stem_itemstring : Desired itemstring of the fully - grown unconnected stem node
- stem_def : Partial node definition of the fully - grown unconnected stem node . Many fields are already defined . You need to add ` tiles ` and ` description ` at minimum . Don ' t define on_construct without good reason
- stem_drop : Drop probability table for all stem
2017-03-13 22:30:37 +01:00
- gourd_itemstring : Desired itemstring of the full gourd node
2017-07-17 15:00:20 +02:00
- gourd_def : ( almost ) full definition of the gourd node . This function will add on_construct and after_dig_node to the definition for unconnecting any connected stems
2017-03-13 22:43:47 +01:00
- grow_interval : Will attempt to grow a gourd periodically at this interval in seconds
- grow_chance : Chance of 1 / grow_chance to grow a gourd next to the full unconnected stem after grow_interval has passed . Must be a natural number
2017-07-17 14:26:25 +02:00
- connected_stem_texture : Texture of the connected stem
2017-07-17 15:00:20 +02:00
- gourd_on_construct_extra : Custom on_construct extra function for the gourd . Will be called after the stem check code
2017-03-13 22:30:37 +01:00
] ]
2017-07-17 15:00:20 +02:00
function mcl_farming : add_gourd ( full_unconnected_stem , connected_stem_basename , stem_itemstring , stem_def , stem_drop , gourd_itemstring , gourd_def , grow_interval , grow_chance , connected_stem_texture , gourd_on_construct_extra )
2017-03-13 22:30:37 +01:00
local connected_stem_names = {
connected_stem_basename .. " _r " ,
connected_stem_basename .. " _l " ,
connected_stem_basename .. " _t " ,
connected_stem_basename .. " _b " ,
}
2017-03-14 03:56:33 +01:00
local neighbors = {
{ x =- 1 , y = 0 , z = 0 } ,
{ x = 1 , y = 0 , z = 0 } ,
{ x = 0 , y = 0 , z =- 1 } ,
{ x = 0 , y = 0 , z = 1 } ,
}
2017-03-14 04:17:35 +01:00
-- Connect the stem at stempos to the first neighboring gourd block.
-- No-op if not a stem or no gourd block found
2017-03-14 03:56:33 +01:00
local try_connect_stem = function ( stempos )
local stem = minetest.get_node ( stempos )
if stem.name ~= full_unconnected_stem then
return false
end
for n = 1 , # neighbors do
local offset = neighbors [ n ]
local blockpos = vector.add ( stempos , offset )
local block = minetest.get_node ( blockpos )
if block.name == gourd_itemstring then
if offset.x == 1 then
minetest.set_node ( stempos , { name = connected_stem_names [ 1 ] } )
elseif offset.x == - 1 then
minetest.set_node ( stempos , { name = connected_stem_names [ 2 ] } )
elseif offset.z == 1 then
minetest.set_node ( stempos , { name = connected_stem_names [ 3 ] } )
elseif offset.z == - 1 then
minetest.set_node ( stempos , { name = connected_stem_names [ 4 ] } )
end
return true
end
end
end
2017-03-13 22:30:37 +01:00
-- Register gourd
if not gourd_def.after_dig_node then
gourd_def.after_dig_node = function ( blockpos , oldnode , oldmetadata , user )
-- Disconnect any connected stems, turning them back to normal stems
for n = 1 , # neighbors do
local offset = neighbors [ n ]
local expected_stem = connected_stem_names [ n ]
local stempos = vector.add ( blockpos , offset )
local stem = minetest.get_node ( stempos )
if stem.name == expected_stem then
minetest.add_node ( stempos , { name = full_unconnected_stem } )
2017-03-14 03:56:33 +01:00
try_connect_stem ( stempos )
2017-03-13 22:30:37 +01:00
end
end
end
end
2017-03-14 03:56:33 +01:00
if not gourd_def.on_construct then
gourd_def.on_construct = function ( blockpos )
-- Connect all unconnected stems at full size
for n = 1 , # neighbors do
local stempos = vector.add ( blockpos , neighbors [ n ] )
2017-03-14 04:17:35 +01:00
try_connect_stem ( stempos )
2017-03-14 03:56:33 +01:00
end
2017-07-17 15:00:20 +02:00
-- Call custom on_construct
if gourd_on_construct_extra then
gourd_on_construct_extra ( blockpos )
end
2017-03-14 03:56:33 +01:00
end
end
2017-03-13 22:30:37 +01:00
minetest.register_node ( gourd_itemstring , gourd_def )
2017-03-14 04:17:35 +01:00
-- Register unconnected stem
-- Default values for the stem definition
if not stem_def.selection_box then
stem_def.selection_box = {
type = " fixed " ,
fixed = {
{ - 0.15 , - 0.5 , - 0.15 , 0.15 , 0.5 , 0.15 }
} ,
}
end
if not stem_def.paramtype then
stem_def.paramtype = " light "
end
if not stem_def.drawtype then
stem_def.drawtype = " plantlike "
end
if stem_def.walkable == nil then
stem_def.walkable = false
end
if stem_def.sunlight_propagates == nil then
stem_def.sunlight_propagates = true
end
if stem_def.drop == nil then
stem_def.drop = stem_drop
end
if stem_def.groups == nil then
2017-05-20 04:11:14 +02:00
stem_def.groups = { dig_immediate = 3 , not_in_creative_inventory = 1 , plant = 1 , attached_node = 1 , dig_by_water = 1 , destroy_by_lava_flow = 1 , }
2017-03-14 04:17:35 +01:00
end
if stem_def.sounds == nil then
stem_def.sounds = mcl_sounds.node_sound_leaves_defaults ( )
end
if not stem_def.on_construct then
stem_def.on_construct = function ( stempos )
-- Connect stem to gourd (if possible)
try_connect_stem ( stempos )
end
end
minetest.register_node ( stem_itemstring , stem_def )
2017-03-13 22:30:37 +01:00
-- Register connected stems
local connected_stem_tiles = {
{ " blank.png " , --top
" blank.png " , -- bottom
" blank.png " , -- right
" blank.png " , -- left
2017-07-17 14:26:25 +02:00
connected_stem_texture , -- back
connected_stem_texture .. " ^[transformFX90 " --front
2017-03-13 22:30:37 +01:00
} ,
{ " blank.png " , --top
" blank.png " , -- bottom
" blank.png " , -- right
" blank.png " , -- left
2017-07-17 14:26:25 +02:00
connected_stem_texture .. " ^[transformFX90 " , --back
connected_stem_texture , -- front
2017-03-13 22:30:37 +01:00
} ,
{ " blank.png " , --top
" blank.png " , -- bottom
2017-07-17 14:26:25 +02:00
connected_stem_texture .. " ^[transformFX90 " , -- right
connected_stem_texture , -- left
2017-03-13 22:30:37 +01:00
" blank.png " , --back
" blank.png " , -- front
} ,
{ " blank.png " , --top
" blank.png " , -- bottom
2017-07-17 14:26:25 +02:00
connected_stem_texture , -- right
connected_stem_texture .. " ^[transformFX90 " , -- left
2017-03-13 22:30:37 +01:00
" blank.png " , --back
" blank.png " , -- front
}
}
local connected_stem_nodebox = {
{ - 0.5 , - 0.5 , 0 , 0.5 , 0.5 , 0 } ,
{ - 0.5 , - 0.5 , 0 , 0.5 , 0.5 , 0 } ,
{ 0 , - 0.5 , - 0.5 , 0 , 0.5 , 0.5 } ,
{ 0 , - 0.5 , - 0.5 , 0 , 0.5 , 0.5 } ,
}
2017-03-14 02:43:48 +01:00
local connected_stem_selectionbox = {
{ - 0.1 , - 0.5 , - 0.1 , 0.5 , 0.2 , 0.1 } ,
{ - 0.5 , - 0.5 , - 0.1 , 0.1 , 0.2 , 0.1 } ,
{ - 0.1 , - 0.5 , - 0.1 , 0.1 , 0.2 , 0.5 } ,
{ - 0.1 , - 0.5 , - 0.5 , 0.1 , 0.2 , 0.1 } ,
}
2017-03-13 22:30:37 +01:00
for i = 1 , 4 do
minetest.register_node ( connected_stem_names [ i ] , {
_doc_items_create_entry = false ,
paramtype = " light " ,
sunlight_propagates = true ,
walkable = false ,
2017-03-14 04:17:35 +01:00
drop = stem_drop ,
2017-03-13 22:30:37 +01:00
drawtype = " nodebox " ,
node_box = {
type = " fixed " ,
fixed = connected_stem_nodebox [ i ]
} ,
selection_box = {
type = " fixed " ,
2017-03-14 02:43:48 +01:00
fixed = connected_stem_selectionbox [ i ]
2017-03-13 22:30:37 +01:00
} ,
t iles = connected_stem_tiles [ i ] ,
2017-05-20 04:11:14 +02:00
groups = { dig_immediate = 3 , not_in_creative_inventory = 1 , plant = 1 , attached_node = 1 , dig_by_water = 1 , destroy_by_lava_flow = 1 , } ,
2017-03-13 22:30:37 +01:00
sounds = mcl_sounds.node_sound_leaves_defaults ( ) ,
_mcl_blast_resistance = 0 ,
} )
2017-03-21 04:56:16 +01:00
if minetest.get_modpath ( " doc " ) then
doc.add_entry_alias ( " nodes " , full_unconnected_stem , " nodes " , connected_stem_names [ i ] )
end
2017-03-13 22:30:37 +01:00
end
minetest.register_abm ( {
label = " Grow gourd stem to gourd ( " .. full_unconnected_stem .. " → " .. gourd_itemstring .. " ) " ,
nodenames = { full_unconnected_stem } ,
neighbors = { " air " } ,
2017-03-13 22:43:47 +01:00
interval = grow_interval ,
chance = grow_chance ,
2017-03-13 22:30:37 +01:00
action = function ( stempos )
local light = minetest.get_node_light ( stempos )
if light and light > 10 then
-- Check the four neighbors and filter out neighbors where gourds can't grow
local neighbors = {
{ x =- 1 , y = 0 , z = 0 } ,
{ x = 1 , y = 0 , z = 0 } ,
{ x = 0 , y = 0 , z =- 1 } ,
{ x = 0 , y = 0 , z = 1 } ,
}
2017-05-15 21:55:01 +02:00
local floorpos , floor
2017-03-13 22:30:37 +01:00
for n =# neighbors , 1 , - 1 do
local offset = neighbors [ n ]
local blockpos = vector.add ( stempos , offset )
2017-05-15 21:55:01 +02:00
floorpos = { x = blockpos.x , y = blockpos.y - 1 , z = blockpos.z }
floor = minetest.get_node ( floorpos )
2017-03-13 22:30:37 +01:00
local block = minetest.get_node ( blockpos )
local soilgroup = minetest.get_item_group ( floor.name , " soil " )
2017-11-14 23:44:53 +01:00
if not ( ( minetest.get_item_group ( floor.name , " grass_block " ) == 1 or floor.name == " mcl_core:dirt " or soilgroup == 2 or soilgroup == 3 ) and block.name == " air " ) then
2017-03-13 22:30:37 +01:00
table.remove ( neighbors , n )
end
end
2017-05-15 21:55:01 +02:00
-- Gourd needs at least 1 free neighbor to grow
2017-03-13 22:30:37 +01:00
if # neighbors > 0 then
-- From the remaining neighbors, grow randomly
local r = math.random ( 1 , # neighbors )
local offset = neighbors [ r ]
local blockpos = vector.add ( stempos , offset )
local p2
if offset.x == 1 then
minetest.set_node ( stempos , { name = connected_stem_names [ 1 ] } )
p2 = 3
elseif offset.x == - 1 then
minetest.set_node ( stempos , { name = connected_stem_names [ 2 ] } )
p2 = 1
elseif offset.z == 1 then
minetest.set_node ( stempos , { name = connected_stem_names [ 3 ] } )
p2 = 2
elseif offset.z == - 1 then
minetest.set_node ( stempos , { name = connected_stem_names [ 4 ] } )
p2 = 0
end
2017-05-15 21:55:01 +02:00
-- Place the gourd
2017-03-13 23:13:48 +01:00
if gourd_def.paramtype2 == " facedir " then
minetest.add_node ( blockpos , { name = gourd_itemstring , param2 = p2 } )
else
minetest.add_node ( blockpos , { name = gourd_itemstring } )
end
2017-05-19 13:22:29 +02:00
-- Reset farmland, etc. to dirt when the gourd grows on top
if minetest.get_item_group ( floor.name , " dirtifies_below_solid " ) == 1 then
2017-05-15 21:55:01 +02:00
minetest.set_node ( floorpos , { name = " mcl_core:dirt " } )
end
2017-03-13 22:30:37 +01:00
end
end
end ,
} )
end
2017-07-21 19:47:20 +02:00
-- Used for growing gourd stems. Returns the intermediate color between startcolor and endcolor at a step
-- * startcolor: ColorSpec in table form for the stem in its lowest growing stage
-- * endcolor: ColorSpec in table form for the stem in its final growing stage
-- * step: The nth growth step. Counting starts at 1
-- * step_count: The number of total growth steps
function mcl_farming : stem_color ( startcolor , endcolor , step , step_count )
local color = { }
local function get_component ( startt , endd , step , step_count )
return math.floor ( math.max ( 0 , math.min ( 255 , ( startt + ( ( ( step - 1 ) / step_count ) * endd ) ) ) ) )
end
color.r = get_component ( startcolor.r , endcolor.r , step , step_count )
color.g = get_component ( startcolor.g , endcolor.g , step , step_count )
color.b = get_component ( startcolor.b , endcolor.b , step , step_count )
local colorstring = string.format ( " #%02X%02X%02X " , color.r , color.g , color.b )
return colorstring
end