--[[ Signs Bot ========= Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2021 Michal 'Micu' Cieslakiewicz GPL v3 See LICENSE.txt for more information Bot soup cooking commands Allows bot to use pot (xdecor:cauldron) to cook a vegetable soup ]]-- if not minetest.global_exists("bucket") or not minetest.global_exists("fire") or not minetest.global_exists("xdecor") then return end local M = minetest.get_meta -- Load support for I18n. local S = signs_bot.S local lib = signs_bot.lib local bucket_empty, bucket_water = ItemStack("bucket:bucket_empty 1"), ItemStack("bucket:bucket_water 1") local bowl_empty_farming, bowl_empty_xdecor = ItemStack("farming:bowl 1"), ItemStack("xdecor:bowl 1") local bowl_soup = ItemStack("xdecor:bowl_soup 1") local function find_item_slot(base_pos, item) local inv = M(base_pos):get_inventory() local s = nil for i = 1, 8 do local t = inv:get_stack("main", i) if t and t:get_name() == item:get_name() then s = i break end end return s end signs_bot.register_botcommand("take_water", { mod = "soup", params = "", num_param = 1, description = S("Take water into empty bucket when standing on a shore\n(use specified slot number or 0 for auto selection)"), check = function(slot) slot = tonumber(slot) return slot and slot >= 0 and slot <= 8 end, cmnd = function(base_pos, mem, slot) slot = tonumber(slot) local pos = lib.dest_pos(mem.robot_pos, mem.robot_param2, { 0 }) pos.y = pos.y - 1 if not lib.not_protected(base_pos, pos) then return signs_bot.ERROR, S("Error: Position protected") end local node = minetest.get_node_or_nil(pos) if not node or node.name ~= "default:water_source" then return signs_bot.ERROR, S("Error: No still water around") end local itemslot = slot if slot == 0 then itemslot = find_item_slot(base_pos, bucket_empty) if not itemslot then return signs_bot.ERROR, S("Error: No empty bucket in inventory") end end local item = signs_bot.bot_inv_take_item(base_pos, itemslot, 1) if not item or item:is_empty() or item:get_name() ~= bucket_empty:get_name() then return signs_bot.ERROR, S("Error: No empty bucket in inventory slot " .. itemslot) end item = signs_bot.bot_inv_put_item(base_pos, slot, bucket_water) if item:is_empty() then minetest.remove_node(pos) else signs_bot.bot_inv_put_item(base_pos, itemslot, bucket_empty) return signs_bot.ERROR, S("Error: No inventory space for full bucket") end return signs_bot.DONE end, }) signs_bot.register_botcommand("fill_cauldron", { mod = "soup", params = "", num_param = 1, description = S("Pour water from bucket to empty cauldron in front of a robot\n(use specified slot number or 0 for auto selection)"), check = function(slot) slot = tonumber(slot) return slot and slot >= 0 and slot <= 8 end, cmnd = function(base_pos, mem, slot) slot = tonumber(slot) local pos = lib.dest_pos(mem.robot_pos, mem.robot_param2, { 0 }) if not lib.not_protected(base_pos, pos) then return signs_bot.ERROR, S("Error: Position protected") end local node = minetest.get_node_or_nil(pos) if not node or node.name ~= "xdecor:cauldron_empty" then return signs_bot.ERROR, S("Error: No empty cauldron in front of a robot") end local itemslot = slot if slot == 0 then itemslot = find_item_slot(base_pos, bucket_water) if not itemslot then return signs_bot.ERROR, S("Error: No full bucket in inventory") end end local item = signs_bot.bot_inv_take_item(base_pos, itemslot, 1) if not item or item:is_empty() or item:get_name() ~= bucket_water:get_name() then return signs_bot.ERROR, S("Error: No full bucket in inventory slot " .. itemslot) end item = signs_bot.bot_inv_put_item(base_pos, slot, bucket_empty) if item:is_empty() then minetest.set_node(pos, { name = "xdecor:cauldron_idle", param2 = node.param2 }) else signs_bot.bot_inv_put_item(base_pos, itemslot, bucket_water) return signs_bot.ERROR, S("Error: No inventory space for empty bucket") end return signs_bot.DONE end, }) signs_bot.register_botcommand("flame_on", { mod = "soup", params = "", num_param = 0, description = S("Set fire under cauldron (requires flammable material)\n(command is ignored when fire is already burning)"), cmnd = function(base_pos, mem) local pos = lib.dest_pos(mem.robot_pos, mem.robot_param2, { 0 }) local fire_pos = { x = pos.x, y = pos.y - 1, z = pos.z } local fuel_pos = { x = pos.x, y = pos.y - 2, z = pos.z } if not (lib.not_protected(base_pos, pos) and lib.not_protected(base_pos, fire_pos) and lib.not_protected(base_pos, fuel_pos)) then return signs_bot.ERROR, S("Error: Position protected") end local node = minetest.get_node_or_nil(pos) if not node or not node.name:find("xdecor:cauldron") then return signs_bot.ERROR, S("Error: No cauldron in front of a robot") end local fire_node = minetest.get_node_or_nil(fire_pos) if fire_node and fire_node.name:match("fire:[%w_]*flame") then return signs_bot.DONE elseif not fire_node or fire_node.name ~= "air" then return signs_bot.ERROR, S("Error: No space for fire under cauldron") end local fuel_node = minetest.get_node_or_nil(fuel_pos) if fuel_node and minetest.registered_nodes[fuel_node.name].on_ignite then minetest.registered_nodes[fuel_node.name].on_ignite(fuel_pos) elseif fuel_node and minetest.get_item_group(fuel_node.name, "flammable") >= 1 then minetest.set_node(fire_pos, { name = "fire:basic_flame" }) else return signs_bot.ERROR, S("Error: No flammable material under cauldron") end return signs_bot.DONE end, }) signs_bot.register_botcommand("flame_off", { mod = "soup", params = "", num_param = 0, description = S("Put out (extinguish) fire under cauldron\n(command is ignored when there is no fire)"), cmnd = function(base_pos, mem) local pos = lib.dest_pos(mem.robot_pos, mem.robot_param2, { 0 }) local fire_pos = { x = pos.x, y = pos.y - 1, z = pos.z } if not (lib.not_protected(base_pos, pos) and lib.not_protected(base_pos, fire_pos)) then return signs_bot.ERROR, S("Error: Position protected") end local node = minetest.get_node_or_nil(pos) if not node or not node.name:find("xdecor:cauldron") then return signs_bot.ERROR, S("Error: No cauldron in front of a robot") end local node = minetest.get_node_or_nil(fire_pos) if node and node.name:match("fire:[%w_]*flame") then minetest.remove_node(fire_pos) end return signs_bot.DONE end, }) signs_bot.register_botcommand("take_soup", { mod = "soup", params = "", num_param = 1, description = S("Take boiling soup into empty bowl from cauldron\nin front of a robot\n(use specified slot number or 0 for auto selection)"), check = function(slot) slot = tonumber(slot) return slot and slot >= 0 and slot <= 8 end, cmnd = function(base_pos, mem, slot) slot = tonumber(slot) local pos = lib.dest_pos(mem.robot_pos, mem.robot_param2, { 0 }) if not lib.not_protected(base_pos, pos) then return signs_bot.ERROR, S("Error: Position protected") end local node = minetest.get_node_or_nil(pos) if not node or node.name ~= "xdecor:cauldron_soup" then return signs_bot.ERROR, S("Error: No cauldron with a soup in front of a robot") end local itemslot = slot if slot == 0 then itemslot = find_item_slot(base_pos, bowl_empty_xdecor) or find_item_slot(base_pos, bowl_empty_farming) if not itemslot then return signs_bot.ERROR, S("Error: No empty bowl in inventory") end end local item = signs_bot.bot_inv_take_item(base_pos, itemslot, 1) if not item or item:is_empty() or (item:get_name() ~= bowl_empty_farming:get_name() and item:get_name() ~= bowl_empty_xdecor:get_name()) then return signs_bot.ERROR, S("Error: No empty bowl in inventory slot " .. itemslot) end local item_full = signs_bot.bot_inv_put_item(base_pos, slot, bowl_soup) if item_full:is_empty() then minetest.set_node(pos, { name = "xdecor:cauldron_empty", param2 = node.param2 }) else signs_bot.bot_inv_put_item(base_pos, itemslot, item) return signs_bot.ERROR, S("Error: No inventory space for full bowl") end return signs_bot.DONE end, }) local CMD_WATER = [[ dig_sign 1 move take_water 1 backward place_sign 1 turn_around ]] local CMD_SOUP = [[ dig_sign 1 move 2 fill_cauldron 1 flame_on pause 11 move_up drop_items 1 2 drop_items 1 3 move_down pause 6 take_soup 4 flame_off backward backward place_sign 1 turn_around ]] signs_bot.register_sign({ name = "water", description = S('Sign "take water"'), commands = CMD_WATER, image = "signs_bot_sign_water.png", }) signs_bot.register_sign({ name = "soup", description = S('Sign "cook soup"'), commands = CMD_SOUP, image = "signs_bot_sign_soup.png", }) minetest.register_craft({ output = "signs_bot:water", recipe = { {"group:wood", "bucket:bucket_empty", "group:wood"}, {"dye:black", "default:stick", "dye:yellow"}, {"dye:blue", "", ""} } }) minetest.register_craft({ output = "signs_bot:soup", recipe = { {"group:wood", "xdecor:bowl", "group:wood"}, {"dye:black", "default:stick", "dye:yellow"}, {"dye:orange", "", ""} } }) if minetest.get_modpath("doc") then doc.add_entry("signs_bot", "water", { name = S("Sign 'take water'"), data = { item = "signs_bot:water", text = table.concat({ S("Used to take water into bucket."), S("Place the sign on a shore, in front of the still water pool."), S("Items in slots:"), S(" 1 - empty bucket"), S("The result is one bucket with water in selected inventory slot."), S("When finished, the bot turns around."), }, "\n") }, }) doc.add_entry("signs_bot", "soup", { name = S("Sign 'cook soup'"), data = { item = "signs_bot:soup", text = table.concat({ S("Used to cook a vegetable soup in cauldron."), S("Cauldon should be empty and located above flammable material."), S("Place the sign in front of the cauldron with one field space,"), S("to prevent wooden sign from catching fire."), S("Items in slots:"), S(" 1 - water bucket"), S(" 2 - vegetable #1 (i.e. tomato)"), S(" 3 - vegetable #2 (i.e. carrot)"), S(" 4 - empty bowl (from farming or xdecor mods)"), S("The result is one bowl with vegetable soup in selected inventory slot."), S("When finished, the bot turns around."), }, "\n") }, }) end