techage_modpack/signs_bot/cmd_sign.lua

375 lines
11 KiB
Lua
Raw Normal View History

2020-05-31 23:31:18 +03:00
--[[
Signs Bot
=========
2021-05-14 19:50:16 +03:00
Copyright (C) 2019-2021 Joachim Stolberg
2020-05-31 23:31:18 +03:00
GPL v3
See LICENSE.txt for more information
2022-09-24 12:01:30 +03:00
2020-05-31 23:31:18 +03:00
Bot sign commands and nodes
]]--
-- for lazy programmers
local M = minetest.get_meta
2021-05-14 19:50:16 +03:00
-- Load support for I18n.
local S = signs_bot.S
2020-05-31 23:31:18 +03:00
local lib = signs_bot.lib
local sCmnds = ""
local lCmnds = {}
local tCmndIdx = {}
2022-09-24 12:01:30 +03:00
minetest.after(2, function()
2020-05-31 23:31:18 +03:00
for idx,cmnd in ipairs(signs_bot.get_commands()) do
cmnd = minetest.formspec_escape(cmnd)
lCmnds[#lCmnds+1] = cmnd
tCmndIdx[cmnd] = idx
end
sCmnds = table.concat(lCmnds, ",")
end)
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]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
2020-08-08 13:52:38 +03:00
"style_type[textarea,table;font=mono]"..
2021-05-14 19:50:16 +03:00
"tabheader[0,0;tab;"..S("Commands,Help")..";1;;true]"..
"field[0.3,0.5;9,1;name;"..S("Sign name:")..";"..name.."]"..
2020-05-31 23:31:18 +03:00
"textarea[0.3,1.2;9,7.2;cmnd;;"..cmnd.."]"..
"label[0.3,7.5;"..err_msg.."]"..
2021-05-14 19:50:16 +03:00
"button_exit[5,7.5;2,1;cancel;"..S("Cancel").."]"..
"button[7,7.5;2,1;check;"..S("Check").."]"
2020-05-31 23:31:18 +03:00
end
local function formspec2(pos, text)
return "size[9,8]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
2020-08-08 13:52:38 +03:00
"style_type[textarea,table;font=mono]"..
2021-05-14 19:50:16 +03:00
"tabheader[0,0;tab;"..S("Commands,Help")..";2;;true]"..
2020-05-31 23:31:18 +03:00
"table[0.1,0;8.6,4;command;"..sCmnds..";"..pos.."]"..
2021-05-14 19:50:16 +03:00
"textarea[0.3,4.5;9,3.5;help;"..S("Help")..":;"..text.."]"..
"button[3,7.5;3,1;copy;"..S("Copy Cmnd").."]"
2020-05-31 23:31:18 +03:00
end
local function add_arrow(text, line_num)
local tbl = {}
for idx,line in ipairs(string.split(text, "\n", true)) do
if idx == line_num and not string.find(line, '--<<== error') then
tbl[#tbl+1] = line.." --<<== error"
else
tbl[#tbl+1] = line
end
end
return table.concat(tbl, "\n")
2022-09-24 12:01:30 +03:00
end
2020-05-31 23:31:18 +03:00
local function check_syntax(pos, meta, text)
local res,err_msg, line_num = 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)
if line_num > 0 then
meta:set_string("signs_bot_cmnd", add_arrow(text, line_num))
end
end
local function append_line(pos, meta, line)
line = line and line:trim() or ""
local text = meta:get_string("signs_bot_cmnd").."\n"..line
meta:set_string("signs_bot_cmnd", text)
meta:set_int("err_code", 1) -- zero means OK
2021-05-14 19:50:16 +03:00
meta:set_string("err_msg", S("please check the added line(s)"))
2022-09-24 12:01:30 +03:00
end
local function check_and_store(pos, meta, fields)
2020-05-31 23:31:18 +03:00
meta:set_string("sign_name", fields.name)
meta:set_string("signs_bot_cmnd", fields.cmnd)
check_syntax(pos, meta, fields.cmnd)
meta:set_string("formspec", formspec1(meta))
meta:set_string("infotext", meta:get_string("sign_name"))
end
minetest.register_node("signs_bot:sign_cmnd", {
2021-05-14 19:50:16 +03:00
description = S('Sign "command"'),
2020-05-31 23:31:18 +03:00
drawtype = "nodebox",
inventory_image = "signs_bot_sign_cmnd.png",
node_box = {
type = "fixed",
fixed = {
{ -1/16, -8/16, -1/16, 1/16, 4/16, 1/16},
{ -6/16, -5/16, -2/16, 6/16, 3/16, -1/16},
},
},
paramtype2 = "facedir",
tiles = {
"default_wood.png",
"default_wood.png",
"default_wood.png",
"default_wood.png",
"default_wood.png",
"default_wood.png^signs_bot_sign_cmnd.png",
},
after_place_node = function(pos, placer, itemstack)
local imeta = itemstack:get_meta()
local nmeta = minetest.get_meta(pos)
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
2021-05-14 19:50:16 +03:00
nmeta:set_string("sign_name", S('Sign "command"'))
nmeta:set_string("signs_bot_cmnd", S("-- enter or copy commands from help page"))
2020-05-31 23:31:18 +03:00
nmeta:set_int("err_code", 0)
end
nmeta:set_string("infotext", nmeta:get_string("sign_name"))
nmeta:set_string("formspec", formspec1(nmeta))
end,
2022-09-24 12:01:30 +03:00
2020-05-31 23:31:18 +03:00
on_receive_fields = function(pos, formname, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
return
end
local meta = minetest.get_meta(pos)
if fields.check then
check_and_store(pos, meta, fields)
elseif fields.key_enter_field then
check_and_store(pos, meta, fields)
elseif fields.copy then
append_line(pos, meta, lCmnds[meta:get_int("help_pos")])
elseif fields.tab == "1" then
meta:set_string("formspec", formspec1(meta))
elseif fields.tab == "2" then
check_and_store(pos, meta, fields)
local pos = meta:get_int("help_pos")
local cmnd = lCmnds[pos] or ""
meta:set_string("formspec", formspec2(pos, signs_bot.get_help_text(cmnd)))
elseif fields.command then
local evt = minetest.explode_table_event(fields.command)
if evt.type == "DCL" then
append_line(pos, meta, lCmnds[tonumber(evt.row)])
elseif evt.type == "CHG" then
local pos = tonumber(evt.row)
meta:set_int("help_pos", pos)
local cmnd = lCmnds[pos] or ""
meta:set_string("formspec", formspec2(pos, signs_bot.get_help_text(cmnd)))
end
end
end,
2022-09-24 12:01:30 +03:00
2020-05-31 23:31:18 +03:00
after_dig_node = lib.after_dig_sign_node,
paramtype = "light",
2021-05-14 19:50:16 +03:00
use_texture_alpha = signs_bot.CLIP,
2020-05-31 23:31:18 +03:00
sunlight_propagates = true,
is_ground_content = false,
drop = "",
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, sign_bot_sign = 1},
sounds = default.node_sound_wood_defaults(),
})
-- 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)
local taken = stack:take_item(1)
if taken:get_count() == 1 then
inv:set_stack("sign", slot, stack)
return taken
end
end
2022-09-24 12:01:30 +03:00
2020-05-31 23:31:18 +03:00
-- 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)
local leftovers = stack:add_item(item)
if leftovers:get_count() == 0 then
inv:set_stack("sign", slot, stack)
return true
end
return false
end
local function place_sign(base_pos, robot_pos, param2, slot)
local pos1 = lib.dest_pos(robot_pos, param2, {0})
if lib.not_protected(base_pos, pos1) then
if lib.is_air_like(pos1) then
local sign = get_inv_sign(base_pos, slot)
if sign then
lib.place_sign(pos1, sign, param2)
return signs_bot.DONE
else
2021-05-14 19:50:16 +03:00
return signs_bot.ERROR, S("Error: Signs inventory empty")
2020-05-31 23:31:18 +03:00
end
end
end
2021-05-14 19:50:16 +03:00
return signs_bot.ERROR, S("Error: Position protected or occupied")
2020-05-31 23:31:18 +03:00
end
signs_bot.register_botcommand("place_sign", {
mod = "sign",
params = "<slot>",
num_param = 1,
2021-05-14 19:50:16 +03:00
description = S("Place a sign in front of the robot\ntaken from the signs inventory\n"..
2020-05-31 23:31:18 +03:00
"<slot> is the inventory slot (1..6)"),
check = function(slot)
slot = tonumber(slot) or 1
return slot and slot > 0 and slot < 7
end,
cmnd = function(base_pos, mem, slot)
slot = tonumber(slot) or 1
return place_sign(base_pos, mem.robot_pos, mem.robot_param2, slot)
end,
})
local function place_sign_behind(base_pos, robot_pos, param2, slot)
local pos1 = lib.dest_pos(robot_pos, param2, {2})
if lib.not_protected(base_pos, pos1) then
if lib.is_air_like(pos1) then
local sign = get_inv_sign(base_pos, slot)
if sign then
lib.place_sign(pos1, sign, param2)
return signs_bot.DONE
else
2021-05-14 19:50:16 +03:00
return signs_bot.ERROR, S("Error: Signs inventory empty")
2020-05-31 23:31:18 +03:00
end
end
end
2021-05-14 19:50:16 +03:00
return signs_bot.ERROR, S("Error: Position protected or occupied")
2020-05-31 23:31:18 +03:00
end
signs_bot.register_botcommand("place_sign_behind", {
mod = "sign",
params = "<slot>",
num_param = 1,
2021-05-14 19:50:16 +03:00
description = S("Place a sign behind the robot\ntaken from the signs inventory\n"..
2020-05-31 23:31:18 +03:00
"<slot> is the inventory slot (1..6)"),
check = function(slot)
slot = tonumber(slot) or 1
return slot and slot > 0 and slot < 7
end,
cmnd = function(base_pos, mem, slot)
slot = tonumber(slot) or 1
return place_sign_behind(base_pos, mem.robot_pos, mem.robot_param2, slot)
end,
})
local function dig_sign(base_pos, robot_pos, param2, slot)
local pos1 = lib.dest_pos(robot_pos, param2, {0})
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
2021-05-14 19:50:16 +03:00
return signs_bot.ERROR, S("Error: No sign available")
2020-05-31 23:31:18 +03:00
end
if lib.not_protected(base_pos, pos1) then
2021-02-07 16:37:07 +03:00
local node = tubelib2.get_node_lvm(pos1)
2020-05-31 23:31:18 +03:00
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)
2022-09-24 12:01:30 +03:00
if not put_inv_sign(base_pos, slot, sign) then
2020-05-31 23:31:18 +03:00
signs_bot.lib.drop_items(robot_pos, sign)
2021-05-14 19:50:16 +03:00
return signs_bot.ERROR, S("Error: Signs inventory slot is occupied")
2020-05-31 23:31:18 +03:00
end
return signs_bot.DONE
end
2021-05-14 19:50:16 +03:00
return signs_bot.ERROR, S("Error: Position is protected")
2020-05-31 23:31:18 +03:00
end
signs_bot.register_botcommand("dig_sign", {
mod = "sign",
params = "<slot>",
num_param = 1,
2021-05-14 19:50:16 +03:00
description = S("Dig the sign in front of the robot\n"..
2020-05-31 23:31:18 +03:00
"and add it to the signs inventory.\n"..
"<slot> is the inventory slot (1..6)"),
check = function(slot)
slot = tonumber(slot) or 1
return slot and slot > 0 and slot < 7
end,
cmnd = function(base_pos, mem, slot)
slot = tonumber(slot) or 1
return dig_sign(base_pos, mem.robot_pos, mem.robot_param2, slot)
end,
})
local function trash_sign(base_pos, robot_pos, param2, slot)
local pos1 = lib.dest_pos(robot_pos, param2, {0})
local cmnd = M(pos1):get_string("signs_bot_cmnd")
if cmnd == "" then
2021-05-14 19:50:16 +03:00
return signs_bot.ERROR, S("Error: No sign available")
2020-05-31 23:31:18 +03:00
end
if lib.not_protected(base_pos, pos1) then
2021-02-07 16:37:07 +03:00
local node = tubelib2.get_node_lvm(pos1)
2020-05-31 23:31:18 +03:00
local sign = ItemStack("signs_bot:sign_cmnd")
minetest.remove_node(pos1)
2021-05-14 19:50:16 +03:00
local leftover = signs_bot.bot_inv_put_item(base_pos, slot, sign)
if leftover and leftover:get_count() > 0 then
signs_bot.lib.drop_items(robot_pos, leftover)
end
2020-05-31 23:31:18 +03:00
return signs_bot.DONE
end
2021-05-14 19:50:16 +03:00
return signs_bot.ERROR, S("Error: Position is protected")
2020-05-31 23:31:18 +03:00
end
signs_bot.register_botcommand("trash_sign", {
mod = "sign",
2022-09-24 12:01:30 +03:00
params = "<slot>",
2020-05-31 23:31:18 +03:00
num_param = 1,
2021-05-14 19:50:16 +03:00
description = S("Dig the sign in front of the robot\n"..
2020-05-31 23:31:18 +03:00
"and add the cleared sign to\nthe item iventory.\n"..
"<slot> is the inventory slot (1..8)"),
check = function(slot)
slot = tonumber(slot) or 1
return slot and slot > 0 and slot < 9
end,
cmnd = function(base_pos, mem, slot)
slot = tonumber(slot) or 1
return trash_sign(base_pos, mem.robot_pos, mem.robot_param2, slot)
end,
})
2022-09-24 12:01:30 +03:00
2020-05-31 23:31:18 +03:00
minetest.register_craft({
output = "signs_bot:sign_cmnd 4",
recipe = {
{"group:wood", "default:stick", "group:wood"},
{"dye:yellow", "default:stick", "dye:yellow"},
{"", "dye:black", ""}
}
})
if minetest.get_modpath("doc") then
doc.add_entry("signs_bot", "sign_cmnd", {
2021-05-14 19:50:16 +03:00
name = S("Sign 'command'"),
2020-05-31 23:31:18 +03:00
data = {
item = "signs_bot:sign_cmnd",
text = table.concat({
2021-05-14 19:50:16 +03:00
S("The 'command' sign can be programmed by the player."),
2022-09-24 12:01:30 +03:00
S("Place the sign in front of you and use the node menu to program your sequence of bot commands."),
2021-05-14 19:50:16 +03:00
S("The menu has an edit field for your commands and a help page with all available commands."),
S("The help page has a copy button to simplify the programming."),
2022-09-24 12:01:30 +03:00
}, "\n")
2020-05-31 23:31:18 +03:00
},
})
end