--[[ Signs Bot ========= Copyright (C) 2019-2021 Joachim Stolberg GPL v3 See LICENSE.txt for more information Bot farming commands ]]-- -- Load support for I18n. local S = signs_bot.S local lib = signs_bot.lib local not_farming_redo = farming.mod ~= "redo" local bot_inv_put_item = signs_bot.bot_inv_put_item local bot_inv_take_item = signs_bot.bot_inv_take_item local function soil_availabe(pos, trellis) local node = minetest.get_node_or_nil(pos) if node.name == (trellis or "air") then node = minetest.get_node_or_nil({x=pos.x, y=pos.y-1, z=pos.z}) if node and minetest.get_item_group(node.name, "soil") >= 1 then return true end end return false end local function planting(base_pos, mem, slot) local pos = mem.pos_tbl and mem.pos_tbl[mem.steps] mem.steps = (mem.steps or 1) + 1 if pos and lib.not_protected(base_pos, pos) then local stack = bot_inv_take_item(base_pos, slot, 1) if stack and stack ~= "" then local plant = stack:get_name() if plant then local item = signs_bot.FarmingSeed[plant] if item and soil_availabe(pos, signs_bot.FarmingNeedTrellis[item]) then if minetest.registered_nodes[item] then local p2 = minetest.registered_nodes[item].place_param2 or 1 minetest.set_node(pos, {name = item, param2 = p2}) else minetest.set_node(pos, {name = item}) end minetest.sound_play("default_place_node", {pos = pos, gain = 1.0}) if not_farming_redo then minetest.get_node_timer(pos):start(math.random(166, 286)) end else bot_inv_put_item(base_pos, 0, ItemStack(plant)) end end end end end signs_bot.register_botcommand("sow_seed", { mod = "farming", params = "", num_param = 1, description = S("Sow farming seeds\nin front of the robot"), check = function(slot) slot = tonumber(slot) return slot and slot > 0 and slot < 9 end, cmnd = function(base_pos, mem, slot) slot = tonumber(slot) if not mem.steps then mem.pos_tbl = signs_bot.lib.gen_position_table(mem.robot_pos, mem.robot_param2, 3, 3, 0) mem.steps = 1 end mem.pos_tbl = mem.pos_tbl or {} planting(base_pos, mem, slot) if mem.steps > #mem.pos_tbl then mem.steps = nil return signs_bot.DONE end return signs_bot.BUSY end, }) local function harvesting(base_pos, mem) local pos = mem.pos_tbl and mem.pos_tbl[mem.steps] mem.steps = (mem.steps or 1) + 1 if pos and lib.not_protected(base_pos, pos) then local node = minetest.get_node_or_nil(pos) if signs_bot.FarmingCrop[node.name] then local trellis = signs_bot.FarmingKeepTrellis[node.name] if trellis then minetest.set_node(pos, {name = trellis}) elseif not trellis then minetest.remove_node(pos) end -- Do not cache the result of get_node_drops; it is a probabilistic function! local drops = minetest.get_node_drops(node.name) for _,itemstring in ipairs(drops) do if not trellis or trellis ~= itemstring then local leftover = bot_inv_put_item(base_pos, 0, ItemStack(itemstring)) if leftover and leftover:get_count() > 0 then signs_bot.lib.drop_items(mem.robot_pos, leftover) end end end end end end signs_bot.register_botcommand("harvest", { mod = "farming", params = "", num_param = 0, description = S("Harvest farming products\nin front of the robot\non a 3x3 field."), cmnd = function(base_pos, mem) if not mem.steps then mem.pos_tbl = signs_bot.lib.gen_position_table(mem.robot_pos, mem.robot_param2, 3, 3, 0) mem.steps = 1 end mem.pos_tbl = mem.pos_tbl or {} harvesting(base_pos, mem) if mem.steps > #mem.pos_tbl then mem.steps = nil return signs_bot.DONE end return signs_bot.BUSY end, }) local function plant_sapling(base_pos, mem, slot) local pos = lib.dest_pos(mem.robot_pos, mem.robot_param2, {0}) if lib.not_protected(base_pos, pos) and soil_availabe(pos) then local stack = bot_inv_take_item(base_pos, slot, 1) local item = stack and signs_bot.TreeSaplings[stack:get_name()] if item and item.sapling then minetest.set_node(pos, {name = item.sapling, paramtype2 = "wallmounted", param2 = 1}) if item.t1 ~= nil then -- We have to simulate "on_place" and start the timer by hand -- because the after_place_node function checks player rights and can't therefore -- be used. minetest.get_node_timer(pos):start(math.random(item.t1, item.t2)) end end end end signs_bot.register_botcommand("plant_sapling", { mod = "farming", params = "", num_param = 1, description = S("Plant a sapling\nin front of the robot"), check = function(slot) slot = tonumber(slot) return slot and slot > 0 and slot < 9 end, cmnd = function(base_pos, mem, slot) slot = tonumber(slot) plant_sapling(base_pos, mem, slot) return signs_bot.DONE end, }) local CMD = [[dig_sign 1 move harvest sow_seed 1 backward place_sign 1 turn_around]] signs_bot.register_sign({ name = "farming", description = S('Sign "farming"'), commands = CMD, image = "signs_bot_sign_farming.png", }) minetest.register_craft({ output = "signs_bot:farming 2", recipe = { {"group:wood", "default:stick", "group:wood"}, {"dye:black", "default:stick", "dye:yellow"}, {"dye:grey", "", ""} } }) if minetest.get_modpath("doc") then doc.add_entry("signs_bot", "farming", { name = S("Sign 'farming'"), data = { item = "signs_bot:farming", text = table.concat({ S("Used to harvest and seed a 3x3 field."), S("Place the sign in front of the field."), S("The seed to be placed has to be in the first inventory slot of the bot."), S("When finished, the bot turns."), }, "\n") }, }) end