signs_bot/cmd_soup.lua

324 lines
10 KiB
Lua

--[[
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 = "<slot>",
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 = "<slot>",
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 = "<slot>",
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