elepower/elepower_farming/machines/planter.lua

329 lines
8.6 KiB
Lua

-- see elepower_papi >> external_nodes_items.lua for explanation
-- shorten table ref
local eps = ele.external.sounds
local epi = ele.external.ing
-- How many seconds there are between runs
local PLANTER_TICK = 10
-- Growth regions for configured crops
local ranges = {
-- Slot 1 (starts from upper left corner)
{
{x = -4, z = 2, y = 1},
{x = -2, z = 4, y = 1},
},
-- Slot 2
{
{x = -1, z = 2, y = 1},
{x = 1, z = 4, y = 1},
},
-- Slot 3
{
{x = 2, z = 2, y = 1},
{x = 4, z = 4, y = 1},
},
-- Slot 4
{
{x = -4, z = -1, y = 1},
{x = -2, z = 1, y = 1},
},
-- Slot 5 (center)
{
{x = -1, z = -1, y = 1},
{x = 1, z = 1, y = 1},
},
-- Slot 6
{
{x = 2, z = -1, y = 1},
{x = 4, z = 1, y = 1},
},
-- Slot 7
{
{x = -4, z = -4, y = 1},
{x = -2, z = -2, y = 1},
},
-- Slot 8
{
{x = -1, z = -4, y = 1},
{x = 1, z = -2, y = 1},
},
-- Slot 9 (last one, bottom right)
{
{x = 2, z = -4, y = 1},
{x = 4, z = -2, y = 1},
},
}
local function get_formspec(timer, power, state)
local layout_tt = "Item placed here\n will be planted\nout in a 3x3 area"
local layout_bi = "elepower_planter_layout.png"
return "size[8,10]"..
ele.formspec.power_meter(power)..
ele.formspec.state_switcher(7, 0, state)..
ele.formspec.create_bar(1, 0, 100 - timer, "#00ff11", true)..
"list[context;layout;2.5,0;3,3;]"..
"image[2.5,0;1,1;"..layout_bi.."]"..
"image[3.5,0;1,1;"..layout_bi.."]"..
"image[4.5,0;1,1;"..layout_bi.."]"..
"image[2.5,1;1,1;"..layout_bi.."]"..
"image[3.5,1;1,1;"..layout_bi.."]"..
"image[4.5,1;1,1;"..layout_bi.."]"..
"image[2.5,2;1,1;"..layout_bi.."]"..
"image[3.5,2;1,1;"..layout_bi.."]"..
"image[4.5,2;1,1;"..layout_bi.."]"..
"tooltip[2.5,0;4.5,2;"..layout_tt..";"..eletome.tooltip_color.."]"..
"list[context;src;0,3.5;8,2;]"..
"tooltip[0,3.5;8,2; Place stacks of items\n here to keep planter\nsupplied with items to plant;"..eletome.tooltip_color.."]"..
"list[current_player;main;0,5.75;8,1;]"..
"list[current_player;main;0,7;8,3;8]"..
"listring[current_player;main]"..
"listring[context;src]"..
"listring[current_player;main]"
end
local function can_dig(pos, player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:is_empty("src")
end
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
if listname == "layout" then
local inv = minetest.get_meta(pos):get_inventory()
stack:set_count(1)
inv:set_stack(listname, index, stack)
return 0
end
return stack:get_count()
end
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local stack = inv:get_stack(from_list, from_index)
if from_list == "layout" then
inv:set_stack(from_list, from_index, ItemStack(nil))
return 0
end
return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
end
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
if listname == "layout" then
local inv = minetest.get_meta(pos):get_inventory()
inv:set_stack(listname, index, ItemStack(nil))
return 0
end
return stack:get_count()
end
local function plant(pos, range, stack, inv)
local planted = 0
local range_st = vector.add(ranges[range][1], pos)
local range_end = vector.add(ranges[range][2], pos)
local y_top = 0
if minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z}).name ~= "air" then
y_top = y_top + 1
end
if not stack or stack:is_empty() then
return 0
end
local to_plant = stack:get_name()
local to_place = nil
local amount = 0
local till = true
for _,stack in ipairs(inv:get_list("src")) do
if stack:get_name() == to_plant then
amount = amount + stack:get_count()
end
end
-- Saplings
if ele.helpers.get_item_group(to_plant, "sapling") then
to_place = to_plant
to_plant = nil
till = false
elseif ele.helpers.get_item_group(to_plant, "seed") then
to_place = nil
end
if (to_plant or to_place) and amount > 0 then
for x = range_st.x, range_end.x do
if amount == 0 then break end
for z = range_st.z, range_end.z do
if amount == 0 then break end
local place_pos = {x = x, y = range_st.y + y_top, z = z}
local base_pos = {x = place_pos.x, y = place_pos.y - 1, z = place_pos.z}
local base_node = minetest.get_node_or_nil(base_pos)
-- Make sure we're planting on soil, till it if necessary
if base_node and ele.helpers.get_item_group(base_node.name, "soil") then
local node = minetest.get_node_or_nil(place_pos)
if node and node.name == "air" then
if till then
local regN = minetest.registered_nodes
if (regN[base_node.name].soil == nil or
regN[base_node.name].soil.wet == nil or
regN[base_node.name].soil.dry == nil) and
regN[epi.farming_soil] == nil then
till = false
end
if till then
minetest.sound_play(eps.dig_crumbly, {
pos = base_pos,
gain = 0.5,
})
local soil = regN[base_node.name].soil
local wet_soil = epi.farming_soil_wet
-- Determine soil name
-- Make sure we don't replace wet soil
if soil then
wet_soil = soil.wet or epi_farming_soil_wet
soil = soil.dry
else
soil = epi.farming_soil
end
if base_node.name ~= soil and base_node.name ~= wet_soil then
minetest.set_node(base_pos, {name = soil})
end
end
end
local take = to_place
if to_place then
minetest.set_node(place_pos, {name = to_place})
else
local seeddef = minetest.registered_items[to_plant]
seeddef.on_place(ItemStack(to_plant), nil,
{type = "node", under = base_pos, above = place_pos})
take = to_plant
end
planted = planted + 1
amount = amount - 1
inv:remove_item("src", ItemStack(take, 1))
end
end
end
end
end
return planted
end
local function on_timer(pos, elapsed)
local refresh = false
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local capacity = ele.helpers.get_node_property(meta, pos, "capacity")
local usage = ele.helpers.get_node_property(meta, pos, "usage")
local storage = ele.helpers.get_node_property(meta, pos, "storage")
local work = meta:get_int("src_time")
local state = meta:get_int("state")
local is_enabled = ele.helpers.state_enabled(meta, pos, state)
local pow_buffer = {capacity = capacity, storage = storage, usage = 0}
local active = "Idle"
if pow_buffer.storage > usage and is_enabled then
if work == PLANTER_TICK then
local planted = 0
for index, slot in ipairs(inv:get_list("layout")) do
if planted >= 9 then break end
if not slot:is_empty() then
planted = planted + plant(pos, index, slot, inv)
end
end
work = 0
if planted > 0 then
pow_buffer.storage = pow_buffer.storage - usage
end
else
work = work + 1
end
active = "Active"
refresh = true
pow_buffer.usage = usage
elseif not is_enabled then
active = "Off"
end
local work_percent = math.floor((work / PLANTER_TICK)*100)
meta:set_string("formspec", get_formspec(work_percent, pow_buffer, state))
meta:set_string("infotext", ("Planter %s\n%s"):format(active,
ele.capacity_text(capacity, storage)))
meta:set_int("storage", pow_buffer.storage)
meta:set_int("src_time", work)
return refresh
end
ele.register_base_device("elepower_farming:planter", {
description = "Automatic Planter",
ele_capacity = 12000,
ele_inrush = 288,
ele_usage = 128,
tiles = {
"elefarming_machine_planter.png", "elefarming_machine_base.png", "elefarming_machine_side.png",
"elefarming_machine_side.png", "elefarming_machine_side.png", "elefarming_machine_side.png",
},
groups = {
oddly_breakable_by_hand = 1,
ele_machine = 1,
ele_user = 1,
cracky = 1,
tubedevice = 1,
tubedevice_receiver = 1,
},
on_construct = function (pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size("layout", 9)
inv:set_size("src", 16)
meta:set_int("src_time", 0)
local capacity = ele.helpers.get_node_property(meta, pos, "capacity")
meta:set_string("formspec", get_formspec(0, {capacity = capacity, storage = 0}))
end,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_take = allow_metadata_inventory_take,
allow_metadata_inventory_move = allow_metadata_inventory_move,
can_dig = can_dig,
on_timer = on_timer,
})