247 lines
5.8 KiB
Lua
247 lines
5.8 KiB
Lua
--[[
|
|
|
|
Signs Bot
|
|
=========
|
|
|
|
Copyright (C) 2019-2021 Joachim Stolberg
|
|
|
|
GPL v3
|
|
See LICENSE.txt for more information
|
|
|
|
Bot cloning/pattern commands, signs, and nodes
|
|
|
|
]]--
|
|
|
|
-- Load support for I18n.
|
|
local S = signs_bot.S
|
|
|
|
local lib = signs_bot.lib
|
|
|
|
local ValidSizes = {
|
|
["3x1"] = true,
|
|
["3x2"] = true,
|
|
["3x3"] = true,
|
|
["5x1"] = true,
|
|
["5x2"] = true,
|
|
["5x3"] = true,
|
|
}
|
|
|
|
--
|
|
-- Helper function to rotate nodes by the Y-axis
|
|
--
|
|
local Param2Matrix = {
|
|
{0,1,2,3}, -- y+
|
|
{6,15,8,17}, -- z+
|
|
{4,13,10,19}, -- z-
|
|
{5,14,11,16}, -- x+
|
|
{7,12,9,18}, -- x-
|
|
{22,21,20,23}, -- y-
|
|
}
|
|
local tWallmountedRot = {[0]=3,5,4,2}
|
|
local tFacedirRot = {}
|
|
|
|
for _,row in ipairs(Param2Matrix) do
|
|
for idx,elem in ipairs(row) do
|
|
local tbl = {}
|
|
for i = 0,3 do
|
|
tbl[i] = row[((i+idx-1) % 4) + 1]
|
|
end
|
|
tFacedirRot[elem] = tbl
|
|
end
|
|
end
|
|
|
|
local function param2_conversion(node, offs)
|
|
local ndef = minetest.registered_nodes[node.name]
|
|
if not ndef or not ndef.paramtype2 then return end
|
|
if ndef.paramtype2 == "facedir" then
|
|
node.param2 = tFacedirRot[node.param2][offs]
|
|
elseif ndef.paramtype2 == "wallmounted" and node.param2 > 1 then
|
|
node.param2 = tWallmountedRot[(node.param2 + offs - 2) % 4]
|
|
end
|
|
end
|
|
|
|
--
|
|
-- Inventory functions
|
|
--
|
|
local function inv_get_item(pos, name)
|
|
-- air can be copied for free
|
|
if name == "air" then
|
|
return "air"
|
|
end
|
|
-- try to get the item
|
|
local inv = minetest.get_inventory({type="node", pos=pos})
|
|
if not inv then return "signs_bot:missing" end
|
|
local taken = inv:remove_item("main", ItemStack(name))
|
|
if taken:get_count() == 0 then
|
|
return "signs_bot:missing"
|
|
end
|
|
return name
|
|
end
|
|
|
|
local function inv_put_item(pos, mem, name)
|
|
if name == "air" then
|
|
return
|
|
end
|
|
local inv = minetest.get_inventory({type="node", pos=pos})
|
|
if not inv then return end
|
|
local leftover = inv:add_item("main", ItemStack(name))
|
|
if leftover:get_count() > 0 then
|
|
lib.drop_items(mem.robot_pos, leftover)
|
|
end
|
|
end
|
|
|
|
local function pattern_copy(base_pos, mem)
|
|
local src_pos = mem.src_pos_tbl[mem.steps]
|
|
local dst_pos = mem.dst_pos_tbl[mem.steps]
|
|
mem.steps = mem.steps + 1
|
|
|
|
if lib.not_protected(base_pos, dst_pos) then
|
|
local src_node = tubelib2.get_node_lvm(src_pos)
|
|
src_node.name = inv_get_item(base_pos, src_node.name)
|
|
|
|
local dst_node = tubelib2.get_node_lvm(dst_pos)
|
|
inv_put_item(base_pos, mem, dst_node.name)
|
|
param2_conversion(src_node, mem.dir_offs)
|
|
minetest.set_node(dst_pos, src_node)
|
|
end
|
|
end
|
|
|
|
|
|
signs_bot.register_botcommand("pattern", {
|
|
mod = "copy",
|
|
params = "",
|
|
num_param = 0,
|
|
description = S("Store pattern to be cloned."),
|
|
cmnd = function(base_pos, mem)
|
|
mem.pttrn_pos = lib.next_pos(mem.robot_pos, mem.robot_param2)
|
|
mem.pttrn_param2 = mem.robot_param2
|
|
return signs_bot.DONE
|
|
end,
|
|
})
|
|
|
|
signs_bot.register_botcommand("copy", {
|
|
mod = "copy",
|
|
params = "<size> <lvl>",
|
|
num_param = 2,
|
|
description = S("Copy the nodes from\n"..
|
|
"the stored pattern position\n"..
|
|
"<size> is: 3x1, 3x2, 3x3,\n"..
|
|
"5x1, 5x2, 5x3 (wide x deep)\n"..
|
|
"<lvl> pattern level offset (0..4)"),
|
|
check = function(size, lvl)
|
|
lvl = tonumber(lvl) or 0
|
|
if not lvl or lvl < 0 or lvl > 4 then
|
|
return false
|
|
end
|
|
return ValidSizes[size]
|
|
end,
|
|
cmnd = function(base_pos, mem, size, lvl)
|
|
if not mem.pttrn_pos then return true end
|
|
if not mem.steps then
|
|
local x,z = size:match('(%d)x(%d)')
|
|
lvl = tonumber(lvl) or 0
|
|
mem.x_size = tonumber(x)
|
|
mem.z_size = tonumber(z)
|
|
mem.src_pos_tbl = signs_bot.lib.gen_position_table(mem.pttrn_pos, mem.pttrn_param2, x, z, lvl)
|
|
mem.dst_pos_tbl = signs_bot.lib.gen_position_table(mem.robot_pos, mem.robot_param2, x, z, 0)
|
|
mem.dir_offs = mem.robot_param2 - mem.pttrn_param2
|
|
mem.steps = 1
|
|
end
|
|
pattern_copy(base_pos, mem)
|
|
if mem.steps > #mem.src_pos_tbl then
|
|
mem.steps = nil
|
|
return signs_bot.DONE
|
|
end
|
|
return signs_bot.BUSY
|
|
end,
|
|
})
|
|
|
|
|
|
minetest.register_node("signs_bot:missing", {
|
|
description = "Missing Node",
|
|
tiles = {"signs_bot_missing_node.png"},
|
|
drawtype = "glasslike",
|
|
paramtype = "light",
|
|
sunlight_propagates = true,
|
|
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "blend" or true,
|
|
is_ground_content = false,
|
|
groups = {snappy=3,cracky=3,oddly_breakable_by_hand=3, not_in_creative_inventory = 1},
|
|
drop = "",
|
|
sounds = default.node_sound_glass_defaults(),
|
|
})
|
|
|
|
signs_bot.register_sign({
|
|
name = "pattern",
|
|
description = S('Sign "pattern"'),
|
|
commands = "pattern\nturn_around",
|
|
image = "signs_bot_sign_pattern.png",
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "signs_bot:pattern 2",
|
|
recipe = {
|
|
{"group:wood", "default:stick", "group:wood"},
|
|
{"dye:red", "default:stick", "dye:black"},
|
|
{"", "", ""}
|
|
}
|
|
})
|
|
|
|
local CMND = [[dig_sign 1
|
|
move
|
|
copy 3x3
|
|
move_up
|
|
copy 3x3 1
|
|
move_up
|
|
copy 3x3 2
|
|
move_down
|
|
move_down
|
|
backward
|
|
place_sign 1
|
|
turn_around]]
|
|
|
|
signs_bot.register_sign({
|
|
name = "copy3x3x3",
|
|
description = S('Sign "copy 3x3x3"'),
|
|
commands = CMND,
|
|
image = "signs_bot_sign_copy3x3x3.png",
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "signs_bot:copy3x3x3 2",
|
|
recipe = {
|
|
{"group:wood", "default:stick", "group:wood"},
|
|
{"dye:black", "default:stick", "dye:red"},
|
|
{"", "", ""}
|
|
}
|
|
})
|
|
|
|
if minetest.get_modpath("doc") then
|
|
doc.add_entry("signs_bot", "pattern", {
|
|
name = S("Sign 'pattern'"),
|
|
data = {
|
|
item = "signs_bot:pattern",
|
|
text = table.concat({
|
|
S("Used to make a copy of a 3x3x3 cube."),
|
|
S("Place the sign in front of the pattern to be copied."),
|
|
S("Use the copy sign to make the copy of this pattern on a different location."),
|
|
S("The bot must first reach the pattern sign, then the copy sign."),
|
|
}, "\n")
|
|
},
|
|
})
|
|
end
|
|
|
|
if minetest.get_modpath("doc") then
|
|
doc.add_entry("signs_bot", "copy3x3x3", {
|
|
name = S("Sign 'copy3x3x3'"),
|
|
data = {
|
|
item = "signs_bot:copy3x3x3",
|
|
text = table.concat({
|
|
S("Used to make a copy of a 3x3x3 cube."),
|
|
S("Place the sign in front of the location, where the copy should be made."),
|
|
S("Use the pattern sign to mark the pattern."),
|
|
}, "\n")
|
|
},
|
|
})
|
|
end
|
|
|