Files

332 lines
9.9 KiB
Lua

--[[
X Farming. Extends Luanti farming mod with new plants, crops and ice fishing.
Copyright (C) 2025 SaKeL
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to juraj.vajda@gmail.com
--]]
local S = core.get_translator(core.get_current_modname())
x_farming.register_plant('x_farming:rice', {
description = S('Rice Seed') .. '\n' .. S('Compost chance') .. ': 30%',
short_description = S('Rice Seed'),
tiles = { 'x_farming_silt_loam_soil.png' },
inventory_image = 'x_farming_rice_seed_inv.png',
steps = 8,
minlight = 13,
maxlight = 14,
fertility = { 'grassland' },
drawtype = 'plantlike_rooted',
paramtype2 = 'none',
visual_scale = 3.0,
special_tiles = 'x_farming_rice_seed.png',
node_dig_prediction = 'x_farming:silt_loam_soil',
groups = {
-- MTG
attached_node = 0,
-- VL
plant = 1,
dig_by_water = 0,
destroy_by_lava_flow = 1,
dig_by_piston = 1,
compostability = 30,
-- X Farming
compost = 30,
},
node_placement_prediction = '',
buildable_to = false,
floodable = false,
selection_box = {
type = 'fixed',
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
{ -4 / 16, 0.5, -4 / 16, 4 / 16, 1.5, 4 / 16 },
},
},
selection_box_1 = {
type = 'fixed',
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
{ -4 / 16, 0.5, -4 / 16, 4 / 16, 1.5, 4 / 16 },
},
},
selection_box_2 = {
type = 'fixed',
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
{ -4 / 16, 0.5, -4 / 16, 4 / 16, 1.5, 4 / 16 },
},
},
selection_box_3 = {
type = 'fixed',
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
{ -4 / 16, 0.5, -4 / 16, 4 / 16, 2, 4 / 16 },
},
},
selection_box_4 = {
type = 'fixed',
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
{ -4 / 16, 0.5, -4 / 16, 4 / 16, 2.5, 4 / 16 },
},
},
selection_box_5 = {
type = 'fixed',
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
{ -4 / 16, 0.5, -4 / 16, 4 / 16, 2.5, 4 / 16 },
},
},
selection_box_6 = {
type = 'fixed',
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
{ -4 / 16, 0.5, -4 / 16, 4 / 16, 3, 4 / 16 },
},
},
selection_box_7 = {
type = 'fixed',
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
{ -4 / 16, 0.5, -4 / 16, 4 / 16, 3, 4 / 16 },
},
},
selection_box_8 = {
type = 'fixed',
fixed = {
{ -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
{ -4 / 16, 0.5, -4 / 16, 4 / 16, 3, 4 / 16 },
},
},
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= 'node' or not placer then
return itemstack
end
local player_name = placer:get_player_name()
local pos_under = pointed_thing.under
local pos_above = pointed_thing.above
local node_under = core.get_node(pos_under)
local def_under = core.registered_nodes[node_under.name]
if def_under and def_under.on_rightclick and not placer:get_player_control().sneak then
return def_under.on_rightclick(pos_under, node_under, placer, itemstack, pointed_thing) or itemstack
end
local water_above = core.find_nodes_in_area(
vector.new(pos_above),
vector.new(pos_above.x, pos_above.y + 2, pos_above.z),
{ 'group:water' }
)
if node_under.name ~= 'x_farming:silt_loam_soil'
or core.get_item_group(core.get_node(pos_above).name, 'water') == 0
or #water_above ~= 1
then
return itemstack
end
if core.is_protected(pos_under, player_name)
or core.is_protected(pos_above, player_name)
then
core.record_protection_violation(pos_under, player_name)
return itemstack
end
node_under.name = itemstack:get_name()
core.set_node(pos_under, node_under)
x_farming.tick(pos_under)
if not core.is_creative_enabled(player_name) then
itemstack:take_item()
end
return itemstack
end,
after_destruct = function(pos, oldnode)
core.set_node(pos, { name = 'x_farming:silt_loam_soil' })
end,
on_timer = function(pos, elapsed)
local node = core.get_node(pos)
local name = node.name
local def = core.registered_nodes[name]
if not def.next_plant then
-- disable timer for fully grown plant
return
end
-- grow seed
if core.get_item_group(node.name, 'seed') and def.fertility then
local water_above = core.find_nodes_in_area(
vector.new(pos),
vector.new(pos.x, pos.y + 2, pos.z),
{ 'default:water_source' }
)
if #water_above ~= 1 then
x_farming.tick_again(pos)
return
end
-- omitted is a check for light, we assume seeds can germinate in the dark.
local placenode = { name = def.next_plant }
if def.place_param2 then
placenode.param2 = def.place_param2
end
core.swap_node(pos, placenode)
if core.registered_nodes[def.next_plant].next_plant then
x_farming.tick(pos)
return
end
return
end
-- check if emerged in water
local water_above = core.find_nodes_in_area(
vector.new(pos),
vector.new(pos.x, pos.y + 2, pos.z),
{ 'default:water_source' }
)
local air_above = core.find_nodes_in_area(
vector.new(pos),
vector.new(pos.x, pos.y + 3, pos.z),
{ 'air' }
)
if #water_above ~= 1 or #air_above ~= 2 then
x_farming.tick_again(pos)
return
end
-- check light
local light = core.get_node_light(pos)
if not light or light < def.minlight or light > def.maxlight then
x_farming.tick_again(pos)
return
end
-- grow
local placenode = { name = def.next_plant }
if def.place_param2 then
placenode.param2 = def.place_param2
end
core.swap_node(pos, placenode)
-- new timer needed?
if core.registered_nodes[def.next_plant].next_plant then
x_farming.tick(pos)
end
end
})
-- Registered before the stairs so the stairs get fuel recipes.
core.register_craft({
type = 'fuel',
recipe = 'x_farming:rice_stack',
burntime = 3,
})
if core.get_modpath('stairs') then
do
local recipe = 'x_farming:rice'
local groups = { snappy = 3, flammable = 4 }
local images = { 'x_farming_rice_stack_side.png' }
local sounds = x_farming.node_sound_leaves_defaults()
stairs.register_stair('rice_stack', recipe, groups, images, S('Rice Stack Stair'),
sounds, true)
stairs.register_stair_inner('rice_stack', recipe, groups, images, '',
sounds, true, S('Inner Rice Stack Stair'))
stairs.register_stair_outer('rice_stack', recipe, groups, images, '',
sounds, true, S('Outer Rice Stack Stair'))
stairs.register_slab('rice_stack', recipe, groups, images, S('Rice Stack Slab'),
sounds, true)
end
end
-- crate
x_farming.register_crate('crate_rice_3', {
description = S('Rice Crate'),
short_description = S('Rice Crate'),
tiles = { 'x_farming_crate_rice_3.png' },
_custom = {
crate_item = 'x_farming:rice'
}
})
-- bag
x_farming.register_bag('bag_rice_grains', {
description = S('Rice Grain') .. ' Bag',
short_description = S('Rice Grain') .. ' Bag',
tiles = { 'x_farming_bag_rice_grains.png' },
_custom = {
bag_item = 'x_farming:rice_grains'
}
})
core.register_on_mods_loaded(function()
local deco_place_on = {}
local deco_biomes = {}
-- MTG
if core.get_modpath('default') then
table.insert(deco_place_on, 'default:dirt')
table.insert(deco_place_on, 'default:dry_dirt')
table.insert(deco_biomes, 'rainforest_swamp')
table.insert(deco_biomes, 'savanna_shore')
end
-- MCL
if core.get_modpath('mcl_core') then
table.insert(deco_place_on, 'mcl_core:sand')
table.insert(deco_biomes, 'Savanna_beach')
end
if next(deco_place_on) and next(deco_biomes) then
core.register_decoration({
name = 'x_farming:rice',
deco_type = 'simple',
place_on = deco_place_on,
sidelen = 16,
noise_params = {
offset = -0.3,
scale = 0.7,
spread = { x = 200, y = 200, z = 200 },
seed = 354,
octaves = 3,
persist = 0.7
},
biomes = deco_biomes,
y_max = -1,
y_min = -1,
decoration = {
'x_farming:rice_5',
'x_farming:rice_6',
'x_farming:rice_7',
'x_farming:rice_8'
},
flags = 'force_placement'
})
end
end)