farming_nextgen/seeder.lua
2017-11-04 18:26:08 +01:00

429 lines
14 KiB
Lua

--*******************************************************
--**** The Seeder
--**** All coding made by Gundul except recursive_dig
--**** was taken from technic:chainsaw mod coded by
--**** Maciej Kasatkin (RealBadAngel)
--*******************************************************
-- Configuration
local seeder_max_charge = 900000 -- Maximum charge of the seeder
-- Gives 500 plants a new life
local seeder_charge_per_node = 1800
-- Is technic mod present ? If not use wearout tool instead
local havetech = minetest.get_modpath("technic")
-- turn on/off chat messages
local chaton = false
local easy = false
-- different values if technic not present
if not havetech then
seeder_charge_per_node = math.floor(65535 / seeder_max_charge * seeder_charge_per_node)
seeder_max_charge = 65535
end
-- grapes and beans from farming_plus need helpers to grow
if minetest.get_modpath("farming_plus") then
minetest.register_craftitem("farming_nextgen:grape_seedling", {
description = "A grape seedling for the seeder",
inventory_image = "farming_grapes_1.png"
})
minetest.register_craftitem("farming_nextgen:bean_seedling", {
description = "A bean seedling for the seeder",
inventory_image = "farming_beanpole_1.png"
})
minetest.register_craft({
type = "shapeless",
output = "farming_nextgen:grape_seedling",
recipe = {"farming_plus:trellis","farming_plus:grapes"}
})
minetest.register_craft({
type = "shapeless",
output = "farming_nextgen:bean_seedling",
recipe = {"farming_plus:beanpole","farming_plus:beans"}
})
end
-- The default soils
local soil_nodenames = {
["farming:soil"] = true,
["farming:soil_wet"] = true,
["farming:desert_sand_soil"] = true,
["farming:desert_sand_soil_wet"]= true
}
-- the seed library { name of seed, name after beeing planted }
local seeder_seed = {
{"farming_plus:seed_barley", "farming_plus:barley_1"},
{"farming_plus:carrot_seed", "farming_plus:carrot_1"},
{"farming_plus:chilli_seeds", "farming_plus:chilli_1"},
{"farming_plus:coffee_beans", "farming_plus:coffee_1"},
{"farming_plus:corn_seed", "farming_plus:corn_1"},
{"farming_plus:cucumber_seed", "farming_plus:cucumber_1"},
{"farming_plus:garlic_seed", "farming_plus:garlic_1"},
{"farming_plus:seed_hemp", "farming_plus:hemp_1"},
{"farming_plus:melon_seed", "farming_plus:melon_1"},
{"farming_plus:potato_seed", "farming_plus:potato_1"},
{"farming:pumpkin_seed", "farming:pumpkin_1"},
{"farming_plus:rhubarb_seed", "farming_plus:rhubarb_1"},
{"farming_plus:raspberry_seed", "farming_plus:raspberry_1"},
{"farming_plus:strawberry_seed", "farming_plus:strawberry_1"},
{"farming_plus:soy_seed", "farming_plus:soy_plant_1"},
{"farming_plus:tomato_seed", "farming_plus:tomato_1"},
{"farming_plus:walnut_item", "farming_plus:walnut_1"},
{"farming_plus:orange_seed", "farming_plus:orange_1"},
{"farming_plus:lemon_seed", "farming_plus:lemon_1"},
{"farming_plus:peach_seed", "farming_plus:peach_1"},
{"farming:seed_wheat", "farming:seed_wheat"},
{"beer_test:seed_oats", "beer_test:seed_oats"},
{"farming:seed_cotton", "farming:seed_cotton"}
}
local seeder_utils = {
{"farming_nextgen:grape_seedling", "farming_plus:grapes_1"},
{"farming_nextgen:bean_seedling", "farming_plus:beanpole_1"}
}
local function check_valid_util(sname)
for i in ipairs(seeder_utils) do
if sname == seeder_utils[i][1] then return true end
end
return false
end
-- function to check for valid seeds
local function check_valid_seed(sname)
for i in ipairs(seeder_seed) do
if sname == seeder_seed[i][1] then return true end
end
return false
end
--function to give name of seedlings
local function give_seedling(sname, util)
if not util then
for i in ipairs(seeder_seed) do
if sname == seeder_seed[i][1] then return seeder_seed[i][2] end
end
else
for i in ipairs(seeder_utils) do
if sname == seeder_utils[i][1] then return seeder_utils[i][2] end
end
end
return nil
end
--- Iterator over positions to try to saw around a sawed node.
-- This returns positions in a 3x1x3 area around the position, plus the
-- position above it. This does not return the bottom position to prevent
-- the seeder from cutting down nodes below the cutting position.
-- @param pos Sawing position.
local function iterSawTries(pos)
-- Copy position to prevent mangling it
local pos = vector.new(pos)
local i = 0
return function()
i = i + 1
-- Given a (top view) area like so (where 5 is the starting position):
-- X -->
-- Z 123
-- | 456
-- V 789
-- This will return positions 1, 4, 7, 2, 8 (skip 5), 3, 6, 9,
-- and the position above 5.
if i == 1 then
-- Move to starting position
pos.x = pos.x - 1
pos.z = pos.z - 1
elseif i == 4 or i == 7 then
-- Move to next X and back to start of Z when we reach
-- the end of a Z line.
pos.x = pos.x + 1
pos.z = pos.z - 2
elseif i == 5 then
-- Skip the middle position (we've already run on it)
-- and double-increment the counter.
pos.z = pos.z + 2
i = i + 1
elseif i <= 9 then
-- Go to next Z.
pos.z = pos.z + 1
elseif i == 10 then
-- Move back to center and up.
-- The Y+ position must be last so that we don't dig
-- straight upward and not come down (since the Y-
-- position isn't checked).
pos.x = pos.x - 1
pos.z = pos.z - 1
pos.y = pos.y + 1
else
return nil
end
return pos
end
end
-- This function does all the hard work. Recursively we dig the node at hand
-- if it is in the table and then search the surroundings for more stuff to dig.
local function recursive_dig(pos, remaining_charge, seednum,seedstack, user)
local uppos = {x =pos.x, y =(pos.y) +1,z =pos.z}
local toppos = {x =pos.x, y =(pos.y) +2,z =pos.z}
local name = user:get_player_name()
if remaining_charge < seeder_charge_per_node or seedstack:is_empty() then
return remaining_charge, seednum, seedstack
end
local node = minetest.get_node(pos)
local upper = minetest.get_node(uppos)
local top = minetest.get_node(toppos)
local seedname = seedstack:get_name()
local helpers = check_valid_util(upper.name)
if node.name == "farming:weed" then
remaining_charge, seednum, seedstack = recursive_dig( {x=pos.x, y=pos.y-1, z=pos.z}, remaining_charge, seednum, seedstack, user)
return remaining_charge, seednum, seedstack
end
if not soil_nodenames[node.name] then
return remaining_charge, seednum, seedstack
end
if not check_valid_util(seedname) then
if upper.name == "air" or upper.name == "farming:weed" then
minetest.set_node(uppos, {name="air"})
remaining_charge = remaining_charge - seeder_charge_per_node
seednum = seednum +1
seedstack:take_item()
if give_seedling(seedname,false) then
minetest.add_node(uppos, {name = give_seedling(seedname,false), param2 = 1})
minetest.get_node_timer(uppos):start(math.random(166, 286))
end
else
return remaining_charge, seednum, seedstack
end
else
if (upper.name == "air" or upper.name == "farming:weed") and top.name == "air" then
minetest.set_node(uppos, {name="air"})
remaining_charge = remaining_charge - seeder_charge_per_node
seednum = seednum +1
seedstack:take_item()
if give_seedling(seedname, true) then
minetest.add_node(uppos, {name = give_seedling(seedname, true), param2 = 1})
minetest.get_node_timer(uppos):start(math.random(166, 286))
end
else
return remaining_charge, seednum, seedstack
end
end
-- Check surroundings and run recursively if any charge left
for npos in iterSawTries(pos) do
if remaining_charge < seeder_charge_per_node then
break
end
if soil_nodenames[minetest.get_node(npos).name] then
remaining_charge, seednum, seedstack = recursive_dig(npos, remaining_charge, seednum, seedstack, user)
end
end
return remaining_charge, seednum, seedstack
end
-- Seeder entry point
local function seeder_dig(pos, current_charge, seednum, seedstack, user)
-- Start sawing things down
local remaining_charge, seednum, seedstack = recursive_dig(pos, current_charge, seednum, seedstack, user)
minetest.sound_play("farming_nextgen_seeder", {pos = pos, gain = 1.0, max_hear_distance = 10})
return remaining_charge, seednum, seedstack
end
if havetech then
local S = technic.getter
technic.register_power_tool("farming_nextgen:seeder", seeder_max_charge)
minetest.register_tool("farming_nextgen:seeder", {
description = S("Seed Machine"),
inventory_image = "farming_nextgen_seeder.png",
stack_max = 1,
wear_represents = "technic_RE_charge",
on_refill = technic.refill_RE_charge,
on_use = function(itemstack, user, pointed_thing)
local seednum=0
local name = user:get_player_name()
local privs = minetest.get_player_privs(name)
if pointed_thing.type ~= "node" then
return itemstack
end
local meta = minetest.deserialize(itemstack:get_metadata())
if not meta or not meta.charge or
meta.charge < seeder_charge_per_node then
return
end
local inv = user:get_inventory()
local indexnumber = user:get_wield_index()+1
local seedstack = inv:get_stack("main", indexnumber)
local seedname = seedstack:get_name()
if minetest.is_protected(pointed_thing.under, name) then
minetest.record_protection_violation(pointed_thing.under, name)
return
end
-- Send current charge to digging function so that the
-- seeder will stop after digging a number of nodes
if seedname then
if check_valid_seed(seedname) or check_valid_util(seedname) then
meta.charge, seednum, seedstack = seeder_dig(pointed_thing.under, meta.charge, seednum, seedstack, user)
minetest.chat_send_player(name,"*** You used : "..seednum.." seeds")
else
minetest.chat_send_player(name," *** you need valid seeds on the right side of your device")
end
else
minetest.chat_send_player(name," *** you need valid seeds on the right side of your device")
end
if not technic.creative_mode then
technic.set_RE_wear(itemstack, meta.charge, seeder_max_charge)
itemstack:set_metadata(minetest.serialize(meta))
end
inv:set_stack("main", indexnumber, seedstack)
return itemstack
end,
})
local mesecons_button = minetest.get_modpath("mesecons_button")
local trigger = mesecons_button and "mesecons_button:button_off" or "default:mese_crystal_fragment"
if easy then
minetest.register_craft({
output = "farming_nextgen:seeder",
recipe = {
{"technic:battery", trigger, "technic:battery" },
{"technic:stainless_steel_ingot", "technic:stainless_steel_ingot", "technic:stainless_steel_ingot"},
{"default:diamond", "", "default:diamond"},
}
})
else
minetest.register_craft({
output = "farming_nextgen:seeder",
recipe = {
{"technic:red_energy_crystal", trigger, "technic:red_energy_crystal" },
{"technic:composite_plate", "technic:composite_plate", "technic:composite_plate"},
{"technic:rubber", "", "technic:rubber"},
}
})
end
else
minetest.register_tool("farming_nextgen:seeder", {
description = "Automatik seeding tool",
groups = {soil=3,soil=2},
inventory_image = "farming_nextgen_seeder.png",
stack_max=1,
liquids_pointable = false,
on_use = function(itemstack, user, pointed_thing)
local seednum=0
local name = user:get_player_name()
local privs = minetest.get_player_privs(name)
if pointed_thing.type ~= "node" then
return itemstack
end
local charge = 65535 - itemstack:get_wear()
if not charge or
charge < seeder_charge_per_node then
return
end
local inv = user:get_inventory()
local indexnumber = user:get_wield_index()+1
local seedstack = inv:get_stack("main", indexnumber)
local seedname = seedstack:get_name()
if minetest.is_protected(pointed_thing.under, name) then
minetest.record_protection_violation(pointed_thing.under, name)
return
end
if seedname then
if check_valid_seed(seedname) or check_valid_util(seedname) then
charge, seednum, seedstack = seeder_dig(pointed_thing.under, charge, seednum, seedstack, user)
if chaton then
minetest.chat_send_player(name,"*** You used : "..seednum.." seeds ".."Charge for "..math.floor(charge/seeder_charge_per_node).." seeds left")
end
else
minetest.chat_send_player(name," *** you need valid seeds on the right side of your device")
end
else
minetest.chat_send_player(name," *** you need valid seeds on the right side of your device")
end
itemstack:set_wear(65535-charge)
inv:set_stack("main", indexnumber, seedstack)
return itemstack
end,
})
minetest.register_craft({
output = "farming_nextgen:seeder",
recipe = {
{"default:mese", "default:mese_crystal_fragment", "default:mese" },
{"default:gold_ingot", "default:bronze_ingot", "default:gold_ingot"},
{"default:diamond", "", "default:diamond"},
}
})
end