registered commands added

master
Joachim Stolberg 2019-03-24 19:03:12 +01:00
parent ec80816b74
commit a05cca9ee1
7 changed files with 550 additions and 291 deletions

View File

@ -25,7 +25,7 @@ local lib = signs_bot.lib
local CYCLE_TIME = 1
local function output(pos, text)
function signs_bot.output(pos, text)
local meta = minetest.get_meta(pos)
text = meta:get_string("output") .. "\n" .. (text or "")
text = text:sub(-500,-1)
@ -109,34 +109,20 @@ local function start_robot(pos)
return true
end
function signs_bot.stop_robot(pos)
local mem = tubelib2.get_mem(pos)
local meta = minetest.get_meta(pos)
function signs_bot.stop_robot(base_pos, mem)
local meta = minetest.get_meta(base_pos)
local number = meta:get_string("number")
mem.running = false
mem.lCmnd = nil
minetest.get_node_timer(pos):stop()
minetest.get_node_timer(base_pos):stop()
meta:set_string("infotext", I("Robot Box ")..number..I(": stopped"))
meta:set_string("formspec", formspec1(pos, mem))
meta:set_string("formspec", formspec1(base_pos, mem))
signs_bot.remove_robot(mem.robot_pos)
end
local function node_timer(pos, elapsed)
local mem = tubelib2.get_mem(pos)
local cmnd
if mem.lCmnd and next(mem.lCmnd) then
cmnd = table.remove(mem.lCmnd, 1)
else
cmnd = "move"
end
print(cmnd)
local res, err = signs_bot.command(pos, mem, cmnd)
if err then
error(pos, err)
return false
end
return res
return signs_bot.run_next_command(pos, mem)
end
local function on_receive_fields(pos, formname, fields, player)
@ -155,7 +141,7 @@ local function on_receive_fields(pos, formname, fields, player)
elseif fields.start == I("Start") then
start_robot(pos)
elseif fields.stop == I("Stop") then
signs_bot.stop_robot(pos)
signs_bot.stop_robot(pos, mem)
end
end

View File

@ -23,39 +23,86 @@ local I,_ = dofile(MP.."/intllib.lua")
local lib = signs_bot.lib
local BUSY = 1
local OK = 2
local STOP = 3
local ERROR = 4
local tPos2Dir = {l = "l", r = "r", L = "l", R = "l", f = "f", F = "f"}
local tPos2Dirs = {
["2"] = {"l","r"}, ["3"] = {"l","f","r"}, l = {"l"}, r = {"r"},
L = {"l"}, R = {"l"}, f = {"f"}, F = {"f"}
}
local tValidLevels = {["-1"] = -1, ["0"] = 0, ["+1"] = 1}
local tCommands = {}
local function check_cmnd_block(pos, mem, meta)
local cmnd = meta:get_string("signs_bot_cmnd")
if cmnd ~= "" then -- command block?
if meta:get_int("err_code") ~= 0 then -- code not valid?
return false
end
if mem.robot_param2 ~= lib.get_node_lvm(pos).param2 then -- wrong sign direction?
return false
end
-- read code
mem.lCmnd = {}
for _,s in ipairs(string.split(cmnd, "\n")) do
table.insert(mem.lCmnd, s)
end
return true
end
return false
end
local function no_cmnd_block(pos, mem)
local pos1 = lib.next_pos(mem.robot_pos, mem.robot_param2)
local cmnd = M(pos1):get_string("signs_bot_cmnd")
if cmnd ~= "" then
mem.lCmnd = {}
for s in cmnd:gmatch("[^\r\n]+") do
table.insert(mem.lCmnd, s)
end
local meta = M(pos1)
if check_cmnd_block(pos1, mem, meta) then
return false
end
cmnd = M({x=pos1.x, y=pos1.y+1, z=pos1.z}):get_string("signs_bot_cmnd")
if cmnd ~= "" then
mem.lCmnd = {}
for s in cmnd:gmatch("[^\r\n]+") do
table.insert(mem.lCmnd, s)
else
local pos2 = {x=pos1.x, y=pos1.y+1, z=pos1.z}
meta = M(pos2)
if check_cmnd_block(pos2, mem, meta) then
return false
end
return false
end
return true
end
local Commands = {
move = function(base_pos, mem, steps)
--
-- Command register API function
--
-- def = {
-- params = "<lvl> <slot>",
-- description = "...",
-- check = function(param1 param2)...end,
-- func = function(base_pos, mem, param1, param2)...end,
-- }
function signs_bot.register_botcommand(name, def)
tCommands[name] = def
tCommands[name].name = name
end
signs_bot.register_botcommand("move", {
params = "<steps>",
description = I("Move the robot 1..9 steps forward. Default: 1"),
check = function(steps)
steps = tonumber(steps)
return steps > 0 and steps < 10
end,
func = function(base_pos, mem, steps)
steps = tonumber(steps)
if no_cmnd_block(base_pos, mem) then
local new_pos = signs_bot.move_robot(mem.robot_pos, mem.robot_param2, steps)
local new_pos = signs_bot.move_robot(mem.robot_pos, mem.robot_param2)
if new_pos then -- not blocked?
mem.robot_pos = new_pos
end
-- more than one move step?
steps = tonumber(steps)
if steps and steps > 1 then
steps = steps - 1
-- add to the command table again
@ -64,99 +111,306 @@ local Commands = {
end
return true
end,
turn_left = function(base_pos, mem)
})
signs_bot.register_botcommand("turn_left", {
params = "",
description = I("Turn the robot to the left"),
func = function(base_pos, mem)
mem.robot_param2 = signs_bot.turn_robot(mem.robot_pos, mem.robot_param2, "L")
return true
end,
turn_right = function(base_pos, mem)
})
signs_bot.register_botcommand("turn_right", {
params = "",
description = I("Turn the robot to the right"),
func = function(base_pos, mem)
mem.robot_param2 = signs_bot.turn_robot(mem.robot_pos, mem.robot_param2, "R")
return true
end,
turn_back = function(base_pos, mem)
})
signs_bot.register_botcommand("turn_around", {
params = "",
description = I("Turn the robot around"),
func = function(base_pos, mem)
mem.robot_param2 = signs_bot.turn_robot(mem.robot_pos, mem.robot_param2, "R")
mem.robot_param2 = signs_bot.turn_robot(mem.robot_pos, mem.robot_param2, "R")
return true
end,
backward = function(base_pos, mem)
})
signs_bot.register_botcommand("backward", {
params = "",
description = I("Move the robot one step back"),
func = function(base_pos, mem)
local new_pos = signs_bot.backward_robot(mem.robot_pos, mem.robot_param2)
if new_pos then -- not blocked?
mem.robot_pos = new_pos
end
return true
end,
turn_off = function(pos, mem)
signs_bot.stop_robot(pos)
})
signs_bot.register_botcommand("turn_off", {
params = "",
description = I("Turn the robot off\n"..
"and put it back in the box."),
func = function(base_pos, mem)
signs_bot.stop_robot(base_pos, mem)
return false
end,
pause = function(base_pos, mem, steps)
-- more than one move step?
steps = tonumber(steps)
if steps and steps > 1 then
steps = steps - 1
})
signs_bot.register_botcommand("pause", {
params = "<sec>",
description = I("Stop the robot for <sec> seconds (1..9999)"),
check = function(sec)
sec = tonumber(sec or 1)
return sec > 0 and sec < 10000
end,
func = function(base_pos, mem, sec)
-- more than one second?
sec = tonumber(sec or 1)
if sec and sec > 1 then
sec = sec - 1
-- add to the command table again
table.insert(mem.lCmnd, 1, "pause "..steps)
table.insert(mem.lCmnd, 1, "pause "..sec)
end
return true
end,
move_up = function(base_pos, mem)
})
signs_bot.register_botcommand("move_up", {
params = "",
description = I("Move the robot upwards"),
func = function(base_pos, mem)
local new_pos = signs_bot.robot_up(mem.robot_pos, mem.robot_param2)
if new_pos then -- not blocked?
mem.robot_pos = new_pos
end
return true
end,
move_down = function(base_pos, mem)
})
signs_bot.register_botcommand("move_down", {
params = "",
description = I("Move the robot down"),
func = function(base_pos, mem)
local new_pos = signs_bot.robot_down(mem.robot_pos, mem.robot_param2)
if new_pos then -- not blocked?
mem.robot_pos = new_pos
end
return true
end,
take_item = function(base_pos, mem, pos, slot)
signs_bot.robot_take(base_pos, mem.robot_pos, mem.robot_param2, pos, slot)
})
signs_bot.register_botcommand("take_item", {
params = "<num> <slot>",
description = I("Take <num> items from a chest like node\nand put it into the item inventory.\n"..
"Param <slot> (1..8) is optional"),
check = function(num, slot)
num = tonumber(num)
if num == nil or num < 1 or num > 99 then
return false
end
slot = tonumber(slot)
if slot and (slot < 1 or slot > 8) then
return false
end
return true
end,
add_item = function(base_pos, mem, pos, slot)
signs_bot.robot_add(base_pos, mem.robot_pos, mem.robot_param2, pos, slot)
func = function(base_pos, mem, num, slot)
num = tonumber(num)
slot = tonumber(slot)
signs_bot.robot_take(base_pos, mem.robot_pos, mem.robot_param2, num, slot)
return true
end,
place_item = function(base_pos, mem, pos, slot, level)
signs_bot.place_item(base_pos, mem.robot_pos, mem.robot_param2, pos, slot, level)
})
signs_bot.register_botcommand("add_item", {
params = "<num> <slot>",
description = I("Add <num> items to a chest like node\ntaken from the item inventory.\n"..
"Param <slot> (1..8) is optional"),
check = function(num, slot)
num = tonumber(num)
if num == nil or num < 1 or num > 99 then
return false
end
slot = tonumber(slot)
if slot and (slot < 1 or slot > 8) then
return false
end
return true
end,
dig_item = function(base_pos, mem, pos, slot, level)
signs_bot.dig_item(base_pos, mem.robot_pos, mem.robot_param2, pos, slot, level)
func = function(base_pos, mem, num, slot)
num = tonumber(num)
slot = tonumber(slot)
signs_bot.robot_add(base_pos, mem.robot_pos, mem.robot_param2, num, slot)
return true
end,
place_sign = function(base_pos, mem, slot)
})
signs_bot.register_botcommand("place_item", {
params = "<slot> <pos> <lvl>",
description = I("Place an item from the item inventory\non the specified position (<pos> <lvl>)"..
"<slot> is the inventory slot (1..8)\n"..
"<pos> is one of: l f r 2 3\n"..
"<lvl> is one of: -1 0 +1"),
check = function(slot, pos, lvl)
slot = tonumber(slot)
if slot and (slot < 1 or slot > 8) then
return false
end
local dirs = tPos2Dirs[pos]
local level = tValidLevels[lvl]
return dirs and level
end,
func = function(base_pos, mem, slot, pos, lvl)
slot = tonumber(slot)
local dirs = tPos2Dirs[pos]
local level = tValidLevels[lvl]
signs_bot.place_item(base_pos, mem.robot_pos, mem.robot_param2, slot, dirs, level)
return true
end,
})
signs_bot.register_botcommand("dig_item", {
params = "<slot> <pos> <lvl>",
description = I("Dig an item on the specified position (<pos> <lvl>)\n and add it to the item inventory\n"..
"<slot> is the inventory slot (1..8)\n"..
"<pos> is one of: l f r 2 3\n"..
"<lvl> is one of: -1 0 +1"),
check = function(slot, pos, lvl)
slot = tonumber(slot)
if slot and (slot < 1 or slot > 8) then
return false
end
local dirs = tPos2Dirs[pos]
local level = tValidLevels[lvl]
return dirs and level
end,
func = function(base_pos, mem, slot, pos, lvl)
slot = tonumber(slot)
local dirs = tPos2Dirs[pos]
local level = tValidLevels[lvl]
signs_bot.dig_item(base_pos, mem.robot_pos, mem.robot_param2, slot, dirs, level)
return true
end,
})
signs_bot.register_botcommand("rotate_item", {
params = "<pos> <lvl> <steps>",
description = I("Rotate an item on the specified position (<pos> <lvl>)\n"..
"<pos> is one of: l f r 2 3\n"..
"<lvl> is one of: -1 0 +1\n"..
"<steps> is one of: 1 2 3"),
check = function(pos, lvl, steps)
local dir = tPos2Dir[pos]
local level = tValidLevels[lvl]
steps = tValidRotSteps[steps]
return dirs and level and steps
end,
func = function(base_pos, mem, pos, lvl, steps)
local dir = tPos2Dir[pos]
local level = tValidLevels[lvl]
steps = tValidRotSteps[steps]
signs_bot.rotate_item(base_pos, mem.robot_pos, mem.robot_param2, pos, level, steps)
return true
end,
})
signs_bot.register_botcommand("place_sign", {
params = "<slot>",
description = I("Place a sign in front of the robot\ntaken from the signs inventory\n"..
"<slot> is the inventory slot (1..4)"),
check = function(slot)
slot = tonumber(slot)
return slot and slot > 0 and slot < 5
end,
func = function(base_pos, mem, slot)
slot = tonumber(slot)
signs_bot.place_sign(base_pos, mem.robot_pos, mem.robot_param2, slot)
return true
end,
dig_sign = function(base_pos, mem, slot)
})
signs_bot.register_botcommand("dig_sign", {
params = "<slot>",
description = I("Dig the sign in front of the robot\n"..
"and add it to the signs inventory.\n"..
"<slot> is the inventory slot (1..4)"),
check = function(slot)
slot = tonumber(slot)
return slot and slot > 0 and slot < 5
end,
func = function(base_pos, mem, slot)
slot = tonumber(slot)
signs_bot.dig_sign(base_pos, mem.robot_pos, mem.robot_param2, slot)
return true
end,
trash_sign = function(base_pos, mem, slot)
})
signs_bot.register_botcommand("trash_sign", {
params = "<slot>",
description = I("Dig the sign in front of the robot\n"..
"and add the cleared sign to the item iventory.\n"..
"<slot> is the inventory slot (1..8)"),
check = function(slot)
slot = tonumber(slot)
return slot and slot > 0 and slot < 5
end,
func = function(base_pos, mem, slot)
slot = tonumber(slot)
signs_bot.trash_sign(base_pos, mem.robot_pos, mem.robot_param2, slot)
return true
end,
stop_robot = function(base_pos, mem, pos, slot)
})
signs_bot.register_botcommand("stop_robot", {
params = "",
description = I("Stop the robot."),
func = function(base_pos, mem, slot)
signs_bot.dig_sign(base_pos, mem.robot_pos, mem.robot_param2, slot)
return true
end,
rotate_item = function(base_pos, mem, pos, level, steps)
signs_bot.rotate_item(base_pos, mem.robot_pos, mem.robot_param2, pos, level, steps)
return true
end,
}
end,
})
function signs_bot.command(pos, mem, s)
local cmnd, param1, param2, param3 = unpack(string.split(s, " "))
if cmnd == "--" then -- comment
return true
elseif Commands[cmnd] then
return Commands[cmnd](pos, mem, param1, param2, param3)
else
return false, I("Syntax error in command '")..cmnd.."'"
function signs_bot.check_commands(pos, text)
--local idx = 1
for idx,line in ipairs(string.split(text, "\n", true)) do
local cmnd, param1, param2, param3 = unpack(string.split(line, " "))
print(cmnd)
if cmnd ~= "--" and cmnd ~= nil then -- No comment or empty line?
if tCommands[cmnd] then
if not tCommands[cmnd].check(param1, param2, param3) then
return false, I("Parameter error in line ")..idx..":\n"..
cmnd.." "..tCommands[cmnd].params
end
else
return false, I("Command error in line ")..idx..":\n"..line
end
end
--idx = idx + 1
end
return true, I("Checked and approved")
end
function signs_bot.run_next_command(base_pos, mem)
mem.lCmnd = mem.lCmnd or {}
local res = nil
while res == nil do
local line = table.remove(mem.lCmnd, 1)
if line then
local cmnd, param1, param2, param3 = unpack(string.split(line, " "))
if cmnd ~= "--" then -- No comment?
res = tCommands[cmnd].func(base_pos, mem, param1, param2, param3)
end
else
res = tCommands["move"].func(base_pos, mem)
end
end
return res
end

View File

@ -48,88 +48,10 @@ local Inventories = {
-- [""] = {take = "", add = ""},
}
--
-- Determine inventory slot number of not predefined
--
local function get_not_empty_slot(inv, listname)
for idx,stack in ipairs(inv:get_list(listname)) do
if stack:get_count() > 0 then
return idx
end
end
end
-- Determine next not-full inventory list number
local function get_not_full_slot(inv, listname, item)
for idx,stack in ipairs(inv:get_list(listname)) do
if stack:item_fits(item) then
return idx
end
end
end
--
-- Get/put one item from/to the robot inventory
--
local function get_inv_item(base_pos, slot)
local inv = minetest.get_inventory({type="node", pos=base_pos})
local stack = inv:get_stack("main", slot or get_not_empty_slot(inv, "main"))
local taken = stack:take_item(1)
if taken:get_count() == 1 then
inv:set_stack("main", slot, stack)
return taken
end
end
local function put_inv_item(base_pos, slot, item)
local inv = minetest.get_inventory({type="node", pos=base_pos})
slot = slot or get_not_full_slot(inv, "main", item)
if slot then
local stack = inv:get_stack("main", slot)
local leftovers = stack:add_item(item)
if leftovers:get_count() == 0 then
inv:set_stack("main", slot, stack)
return true
end
end
return false
end
-- Inventory helper functions
--
-- Try to get/put a number of items from/to any kind of inventory
--
local function get_inv_items(src_inv, src_list, slot)
slot = slot or get_not_empty_slot(src_inv, src_list)
if slot then
local stack = src_inv:get_stack(src_list, slot)
local taken = stack:take_item(NUM_ITEMS)
return taken, stack, slot
end
end
local function put_inv_items(dst_inv, dst_list, slot, taken)
slot = slot or get_not_full_slot(dst_inv, dst_list, taken)
if slot then
local stack = dst_inv:get_stack(dst_list, slot)
stack:add_item(taken)
dst_inv:set_stack(dst_list, slot, stack)
return true
end
return false
end
local function release_inv_items(src_inv, src_list, slot, stack)
src_inv:set_stack(src_list, slot, stack)
end
--
-- Protection, inventory helper functions
--
local function not_protected(base_pos, pos)
local owner = M(base_pos):get_string("owner")
return not minetest.is_protected(pos, owner)
end
local function get_other_inv(pos, take)
local inv = minetest.get_inventory({type="node", pos=pos})
@ -151,32 +73,30 @@ end
-- Move from/to inventories
--
-- From chest to robot
function signs_bot.robot_take(base_pos, robot_pos, param2, slot)
function signs_bot.robot_take(base_pos, robot_pos, param2, num, slot)
local pos1 = lib.next_pos(robot_pos, param2)
slot = tValidSlots[slot]
if not_protected(base_pos, pos1) then
if lib.not_protected(base_pos, pos1) then
local src_inv, src_list = get_other_inv(pos1)
local dst_inv, dst_list = get_own_inv(base_pos)
local taken, rest, src_slot = get_inv_items(src_inv, src_list, slot)
local taken, rest, src_slot = lib.get_inv_items(src_inv, src_list, slot, num)
if taken then
if put_inv_items(dst_inv, dst_list, slot, taken) then
release_inv_items(src_inv, src_list, src_slot, rest)
if lib.put_inv_items(dst_inv, dst_list, slot, taken) then
lib.release_inv_items(src_inv, src_list, src_slot, rest)
end
end
end
end
-- From robot to chest
function signs_bot.robot_add(base_pos, robot_pos, param2, slot)
function signs_bot.robot_add(base_pos, robot_pos, param2, num, slot)
local pos1 = lib.next_pos(robot_pos, param2)
slot = tValidSlots[slot]
if not_protected(base_pos, pos1) then
if lib.not_protected(base_pos, pos1) and not lib.is_air_like(base_pos, pos1) then
local src_inv, src_list = get_own_inv(base_pos)
local dst_inv, dst_list = get_other_inv(pos1)
local taken, rest, src_slot = get_inv_items(src_inv, src_list, slot)
local taken, rest, src_slot = lib.get_inv_items(src_inv, src_list, slot, num)
if taken then
if put_inv_items(dst_inv, dst_list, slot, taken) then
release_inv_items(src_inv, src_list, src_slot, rest)
if lib.put_inv_items(dst_inv, dst_list, slot, taken) then
lib.release_inv_items(src_inv, src_list, src_slot, rest)
end
end
end
@ -186,58 +106,39 @@ end
--
-- Place/dig items
--
function signs_bot.place_item(base_pos, robot_pos, param2, slot, item_pos, level)
local owner = M(base_pos):get_string("owner")
local dirs = tPos2Dirs[item_pos or 'f']
local lvl = tValidLevels[level or "0"]
slot = tValidSlots[slot]
if dirs and lvl then
for _,dir in ipairs(dirs) do
local pos1, p2 = lib.work_pos(robot_pos, param2, dir)
pos1.y = pos1.y + lvl
print("pos1", S(pos1))
if not minetest.is_protected(pos1, owner) and lib.is_air_like(pos1) then
local taken = get_inv_item(base_pos, slot)
if taken then
lib.after_set_node(robot_pos, pos1, taken, owner, p2)
end
function signs_bot.place_item(base_pos, robot_pos, param2, slot, dirs, level)
for _,dir in ipairs(dirs) do
local pos1, p2 = lib.work_pos(robot_pos, param2, dir)
pos1.y = pos1.y + level
if lib.not_protected(base_pos, pos1) and lib.is_air_like(base_pos, pos1) then
local taken = lib.get_inv_item(base_pos, slot)
if taken then
lib.after_set_node(robot_pos, pos1, taken, M(base_pos):get_string("owner"), p2)
end
end
end
end
function signs_bot.dig_item(base_pos, robot_pos, param2, slot, item_pos, level)
local owner = M(base_pos):get_string("owner")
local dirs = tPos2Dirs[item_pos or 'f']
local lvl = tValidLevels[level or "0"]
slot = tValidSlots[slot]
if dirs and lvl then
for _,dir in ipairs(dirs) do
local pos1 = lib.work_pos(robot_pos, param2, dir)
pos1.y = pos1.y + lvl
local node = lib.get_node_lvm(pos1)
if not minetest.is_protected(pos1, owner) and lib.is_simple_node(node) then
minetest.remove_node(pos1)
put_inv_item(base_pos, slot, ItemStack(node.name))
end
end
end
end
function signs_bot.rotate_item(base_pos, robot_pos, param2, item_pos, level, steps)
local owner = M(base_pos):get_string("owner")
local lvl = tValidLevels[level or "0"]
local dir = tPos2Dir[item_pos or 'f']
steps = tValidSteps[steps or '1']
if lvl and steps and dir then
function signs_bot.dig_item(base_pos, robot_pos, param2, slot, dirs, level)
for _,dir in ipairs(dirs) do
local pos1 = lib.work_pos(robot_pos, param2, dir)
pos1.y = pos1.y + lvl
pos1.y = pos1.y + level
local node = lib.get_node_lvm(pos1)
if not minetest.is_protected(pos1, owner) and lib.is_simple_node(node) then
local p2 = tRotations[node.param2] and tRotations[node.param2][steps]
if p2 then
minetest.swap_node(pos1, {name=node.name, param2=p2})
end
if lib.not_protected(base_pos, pos1) and lib.is_simple_node(node) then
minetest.remove_node(pos1)
lib.put_inv_item(base_pos, slot, ItemStack(node.name))
end
end
end
function signs_bot.rotate_item(base_pos, robot_pos, param2, pos, level, steps)
local pos1 = lib.work_pos(robot_pos, param2, pos)
pos1.y = pos1.y + level
local node = lib.get_node_lvm(pos1)
if lib.not_protected(base_pos, pos1) and lib.is_simple_node(node) then
local p2 = tRotations[node.param2] and tRotations[node.param2][steps]
if p2 then
minetest.swap_node(pos1, {name=node.name, param2=p2})
end
end
end

98
lib.lua
View File

@ -17,6 +17,10 @@ local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local P = minetest.string_to_pos
local M = minetest.get_meta
-- Load support for intllib.
local MP = minetest.get_modpath("signs_bot")
local I,_ = dofile(MP.."/intllib.lua")
signs_bot.lib = {}
local Face2Dir = {[0]=
@ -96,9 +100,12 @@ function signs_bot.lib.check_pos(posA, posB)
return false
end
function signs_bot.lib.is_air_like(pos)
function signs_bot.lib.is_air_like(base_pos, pos)
local node = get_node_lvm(pos)
return not minetest.registered_nodes[node.name].walkable
if minetest.registered_nodes[node.name].walkable then
return false
end
return true
end
function signs_bot.lib.is_simple_node(node)
@ -124,3 +131,90 @@ function signs_bot.lib.after_set_node(robot_pos, pos, itemstack, owner, param2)
minetest.set_node(pos, {name=name, param2=param2})
end
end
function signs_bot.lib.not_protected(base_pos, pos)
local owner = M(base_pos):get_string("owner")
if minetest.is_protected(pos, owner) then
signs_bot.output(base_pos, I("Error: Protected or invalid position"))
return false
end
return true
end
--
-- Determine inventory slot number if not predefined
--
local function get_not_empty_slot(inv, listname)
for idx,stack in ipairs(inv:get_list(listname)) do
if stack:get_count() > 0 then
return idx
end
end
end
-- Determine next not-full inventory list number
local function get_not_full_slot(inv, listname, item)
for idx,stack in ipairs(inv:get_list(listname)) do
if stack:item_fits(item) then
return idx
end
end
end
--
-- Get/put exactly one item from/to the robot inventory and
-- generate an error if not possible.
--
function signs_bot.lib.get_inv_item(base_pos, slot)
local inv = minetest.get_inventory({type="node", pos=base_pos})
local stack = inv:get_stack("main", slot or get_not_empty_slot(inv, "main"))
local taken = stack:take_item(1)
if taken:get_count() == 1 then
inv:set_stack("main", slot, stack)
return taken
end
signs_bot.output(base_pos, I("Error: Item inventory is empty"))
end
function signs_bot.lib.put_inv_item(base_pos, slot, item)
local inv = minetest.get_inventory({type="node", pos=base_pos})
slot = slot or get_not_full_slot(inv, "main", item)
if slot then
local stack = inv:get_stack("main", slot)
local leftovers = stack:add_item(item)
if leftovers:get_count() == 0 then
inv:set_stack("main", slot, stack)
return true
end
end
signs_bot.output(base_pos, I("Error: Item inventory is full"))
return false
end
--
-- Try to get/put a number of items from/to any kind of inventory.
--
function signs_bot.lib.get_inv_items(src_inv, src_list, slot, num)
slot = slot or get_not_empty_slot(src_inv, src_list)
if slot then
local stack = src_inv:get_stack(src_list, slot)
local taken = stack:take_item(num)
return taken, stack, slot
end
end
function signs_bot.lib.put_inv_items(dst_inv, dst_list, slot, taken)
slot = slot or get_not_full_slot(dst_inv, dst_list, taken)
if slot then
local stack = dst_inv:get_stack(dst_list, slot)
stack:add_item(taken)
dst_inv:set_stack(dst_list, slot, stack)
return true
end
return false
end
function signs_bot.lib.release_inv_items(src_inv, src_list, slot, stack)
src_inv:set_stack(src_list, slot, stack)
end

View File

@ -19,6 +19,7 @@ local M = minetest.get_meta
local lib = signs_bot.lib
-- Positions to check:
-- 3
-- [R]1

View File

@ -22,7 +22,6 @@ local MP = minetest.get_modpath("signs_bot")
local I,_ = dofile(MP.."/intllib.lua")
local lib = signs_bot.lib
local tValidSlots = {["1"] = 1, ["2"] = 2, ["3"] = 3, ["4"] = 4}
local HELP = I([[Robot Commands
@ -87,6 +86,7 @@ local lHelp = string.split(HELP, ",")
local function formspec1(meta)
local cmnd = meta:get_string("signs_bot_cmnd")
local name = meta:get_string("sign_name")
local err_msg = meta:get_string("err_msg")
cmnd = minetest.formspec_escape(cmnd)
name = minetest.formspec_escape(name)
return "size[9,8]"..
@ -94,10 +94,11 @@ local function formspec1(meta)
default.gui_bg_img..
default.gui_slots..
"tabheader[0,0;tab;"..I("Commands,Help")..";1;;true]"..
"field[0.3,0.5;8,1;name;"..I("Sign name:")..";"..name.."]"..
"field[0.3,0.5;9,1;name;"..I("Sign name:")..";"..name.."]"..
"textarea[0.3,1.2;9,7.2;cmnd;;"..cmnd.."]"..
"button_exit[2.5,7.5;2,1;cancel;"..I("Cancel").."]"..
"button[4.5,7.5;2,1;save;"..I("Save").."]"
"label[0.3,7.5;"..err_msg.."]"..
"button_exit[5,7.5;2,1;cancel;"..I("Cancel").."]"..
"button[7,7.5;2,1;check;"..I("Check").."]"
end
local function formspec2()
@ -114,14 +115,26 @@ local function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
local function append_line(meta, line)
local function append_line(pos, meta, line)
line = trim(line or "")
local text = meta:get_string("signs_bot_cmnd").."\n"..line
meta:set_string("signs_bot_cmnd", text)
local res,err_msg = signs_bot.check_commands(pos, text)
meta:set_int("err_code", res and 0 or 1) -- zero means OK
meta:set_string("err_msg", err_msg)
end
local function check_and_store(pos, meta, fields)
meta:set_string("signs_bot_cmnd", fields.cmnd)
meta:set_string("sign_name", fields.name)
local res,err_msg = signs_bot.check_commands(pos, fields.cmnd)
meta:set_int("err_code", res and 0 or 1) -- zero means OK
meta:set_string("err_msg", err_msg)
meta:set_string("formspec", formspec1(meta))
end
minetest.register_node("signs_bot:sign_cmnd", {
description = I("Robot Command Sign"),
description = I('Sign "command"'),
drawtype = "nodebox",
inventory_image = "signs_bot_sign_cmnd.png",
node_box = {
@ -146,36 +159,33 @@ minetest.register_node("signs_bot:sign_cmnd", {
if imeta:get_string("description") ~= "" then
nmeta:set_string("signs_bot_cmnd", imeta:get_string("cmnd"))
nmeta:set_string("sign_name", imeta:get_string("description"))
nmeta:set_string("err_msg", imeta:get_string("err_msg"))
nmeta:set_int("err_code", imeta:get_int("err_code"))
else
nmeta:set_string("sign_name", I("Sign commands"))
nmeta:set_string("sign_name", I('Sign "command"'))
nmeta:set_string("signs_bot_cmnd", I("-- enter or copy commands from help page"))
nmeta:set_int("err_code", 0)
end
nmeta:set_string("formspec", formspec1(nmeta))
end,
on_receive_fields = function(pos, formname, fields, player)
local meta = minetest.get_meta(pos)
if fields.save then
meta:set_string("signs_bot_cmnd", fields.cmnd)
meta:set_string("sign_name", fields.name)
meta:set_string("formspec", formspec1(meta))
if fields.check then
check_and_store(pos, meta, fields)
elseif fields.key_enter_field then
meta:set_string("signs_bot_cmnd", fields.cmnd)
meta:set_string("sign_name", fields.name)
meta:set_string("formspec", formspec1(meta))
check_and_store(pos, meta, fields)
elseif fields.copy then
append_line(meta, lHelp[meta:get_int("help_pos")])
append_line(pos, meta, lHelp[meta:get_int("help_pos")])
elseif fields.tab == "1" then
meta:set_string("formspec", formspec1(meta))
elseif fields.tab == "2" then
meta:set_string("signs_bot_cmnd", fields.cmnd)
meta:set_string("sign_name", fields.name)
check_and_store(pos, meta, fields)
meta:set_string("formspec", formspec2(meta))
elseif fields.help then
local evt = minetest.explode_table_event(fields.help)
print(dump(evt))
if evt.type == "DCL" then
append_line(meta, lHelp[tonumber(evt.row)])
append_line(pos, meta, lHelp[tonumber(evt.row)])
elseif evt.type == "CHG" then
meta:set_int("help_pos", tonumber(evt.row))
end
@ -186,10 +196,14 @@ minetest.register_node("signs_bot:sign_cmnd", {
if not minetest.is_protected(pos, digger:get_player_name()) then
local nmeta = minetest.get_meta(pos)
local cmnd = nmeta:get_string("signs_bot_cmnd")
local err_code = nmeta:get_int("err_code")
local err_msg = nmeta:get_string("err_msg")
local name = nmeta:get_string("sign_name")
local sign = ItemStack("signs_bot:sign_cmnd")
local smeta = sign:get_meta()
smeta:set_string("cmnd", cmnd)
smeta:set_int("err_code", err_code)
smeta:set_string("err_msg", err_msg)
smeta:set_string("description", name)
minetest.remove_node(pos)
local inv = minetest.get_inventory({type="player", name=digger:get_player_name()})
@ -206,18 +220,19 @@ minetest.register_node("signs_bot:sign_cmnd", {
})
-- Get one sign from the robot inventory
-- Get one sign from the robot signs inventory
local function get_inv_sign(base_pos, slot)
local inv = minetest.get_inventory({type="node", pos=base_pos})
local stack = inv:get_stack("sign", slot or 1)
local stack = inv:get_stack("sign", slot)
local taken = stack:take_item(1)
if taken:get_count() == 1 then
inv:set_stack("sign", slot, stack)
return taken
end
signs_bot.output(base_pos, I("Error: Signs inventory slot is empty"))
end
-- Put one sign into the robot inventory
-- Put one sign into the robot signs inventory
local function put_inv_sign(base_pos, slot, item)
local inv = minetest.get_inventory({type="node", pos=base_pos})
local stack = inv:get_stack("sign", slot)
@ -226,68 +241,76 @@ local function put_inv_sign(base_pos, slot, item)
inv:set_stack("sign", slot, stack)
return true
end
return false
end
-- Put one sign into the robot inventory
local function put_inv_main(base_pos, slot, item)
local inv = minetest.get_inventory({type="node", pos=base_pos})
local stack = inv:get_stack("main", slot)
local leftovers = stack:add_item(item)
if leftovers:get_count() == 0 then
inv:set_stack("main", slot, stack)
return true
end
signs_bot.output(base_pos, I("Error: Signs inventory slot is full"))
return false
end
function signs_bot.place_sign(base_pos, robot_pos, param2, slot)
local owner = M(base_pos):get_string("owner")
slot = tValidSlots[slot]
local pos1 = lib.work_pos(robot_pos, param2, "f")
if not minetest.is_protected(pos1, owner) and lib.is_air_like(pos1) then
local sign = get_inv_sign(base_pos, slot)
if sign then
local meta = sign:get_meta()
local cmnd = meta:get_string("cmnd")
local name = meta:get_string("description")
minetest.set_node(pos1, {name=sign:get_name(), param2=param2})
local under = {x=pos1.x, y=pos1.y-1, z=pos1.z}
local pointed_thing = {type="node", under=under, above=pos1}
minetest.registered_nodes[sign:get_name()].after_place_node(pos1, nil, sign, pointed_thing)
--pcall(minetest.after_place_node, pos1, nil, sign, pointed_thing)
M(pos1):set_string("signs_bot_cmnd", cmnd)
M(pos1):set_string("sign_name", name)
if lib.not_protected(base_pos, pos1) then
if lib.is_air_like(base_pos, pos1) then
local sign = get_inv_sign(base_pos, slot)
if sign then
local meta = sign:get_meta()
local cmnd = meta:get_string("cmnd")
local err_code = meta:get_int("err_code")
local err_msg = meta:get_string("err_msg")
local name = meta:get_string("description")
minetest.set_node(pos1, {name=sign:get_name(), param2=param2})
local under = {x=pos1.x, y=pos1.y-1, z=pos1.z}
local pointed_thing = {type="node", under=under, above=pos1}
minetest.registered_nodes[sign:get_name()].after_place_node(pos1, nil, sign, pointed_thing)
--pcall(minetest.after_place_node, pos1, nil, sign, pointed_thing)
meta = M(pos1)
meta:set_string("signs_bot_cmnd", cmnd)
meta:set_int("err_code", err_code)
meta:set_string("err_msg", err_msg)
meta:set_string("sign_name", name)
return true
else
signs_bot.output(base_pos, I("Error: Signs inventory empty"))
return false
end
end
end
return false
end
function signs_bot.dig_sign(base_pos, robot_pos, param2, slot)
local owner = M(base_pos):get_string("owner")
slot = tValidSlots[slot]
local pos1 = lib.work_pos(robot_pos, param2, "f")
local cmnd = M(pos1):get_string("signs_bot_cmnd")
local name = M(pos1):get_string("sign_name")
if slot and not minetest.is_protected(pos1, owner) and cmnd ~= "" then
local meta = M(pos1)
local cmnd = meta:get_string("signs_bot_cmnd")
local err_code = meta:get_int("err_code")
local name = meta:get_string("sign_name")
if cmnd == "" then
signs_bot.output(base_pos, I("Error: No sign available"))
return false
end
if lib.not_protected(base_pos, pos1) then
local node = lib.get_node_lvm(pos1)
local sign = ItemStack(node.name)
local meta = sign:get_meta()
meta:set_string("description", name)
meta:set_string("cmnd", cmnd)
meta:set_int("err_code", err_code)
minetest.remove_node(pos1)
return put_inv_sign(base_pos, slot, sign)
end
return false
end
function signs_bot.trash_sign(base_pos, robot_pos, param2, slot)
local owner = M(base_pos):get_string("owner")
slot = tValidSlots[slot]
local pos1 = lib.work_pos(robot_pos, param2, "f")
local cmnd = M(pos1):get_string("signs_bot_cmnd")
if slot and not minetest.is_protected(pos1, owner) and cmnd ~= "" then
if cmnd == "" then
signs_bot.output(base_pos, I("Error: No sign available"))
return false
end
if lib.not_protected(base_pos, pos1) then
local node = lib.get_node_lvm(pos1)
local sign = ItemStack("signs_bot:sign_cmnd")
minetest.remove_node(pos1)
return put_inv_main(base_pos, slot, sign)
return lib.put_inv_item(base_pos, slot, sign)
end
return false
end

View File

@ -67,56 +67,56 @@ end
register_sign({
name = "sign_right",
description = I("Sign turn right"),
description = I('Sign "turn right"'),
commands = "turn_right",
image = "signs_bot_sign_right.png",
})
register_sign({
name = "sign_left",
description = I("Sign turn left "),
description = I('Sign "turn left"'),
commands = "turn_left",
image = "signs_bot_sign_left.png",
})
register_sign({
name = "sign_take",
description = I("Sign take item"),
commands = "take_item\nturn_back",
description = I('Sign "take item"'),
commands = "take_item 99\nturn_around",
image = "signs_bot_sign_take.png",
})
register_sign({
name = "sign_add",
description = I("Sign add item"),
commands = "add_item\nturn_back",
description = I('Sign "add item"'),
commands = "add_item 99\nturn_around",
image = "signs_bot_sign_add.png",
})
register_sign({
name = "sign_stop",
description = I("Sign stop"),
description = I('Sign "stop"'),
commands = "stop",
image = "signs_bot_sign_stop.png",
})
register_sign({
name = "sign_tree",
description = I("Sign cut tree"),
commands = "cut_tree\npause 10\ncollect_items\nturn_back",
description = I('Sign "cut tree"'),
commands = "cut_tree\npause 10\ncollect_items\nturn_around",
image = "signs_bot_sign_tree.png",
})
register_sign({
name = "sign_crops",
description = I("Sign harvest crops"),
commands = "harvest_crops\nturn_back",
description = I('Sign "harvest crops"'),
commands = "harvest_crops\nturn_around",
image = "signs_bot_sign_crops.png",
})
register_sign({
name = "sign_flowers",
description = I("Sign pick flowers"),
commands = "pick_flowers\nturn_back",
description = I('Sign "pick flowers"'),
commands = "pick_flowers\nturn_around",
image = "signs_bot_sign_flowers.png",
})