This really breaks badly. Too many untranslatable characters that completely break things. These are meant to be technical and postion strings are not translatable either. Revert.
810 lines
23 KiB
Lua
810 lines
23 KiB
Lua
|
|
--[[
|
|
|
|
ITB (insidethebox) minetest game - Copyright (C) 2017-2018 sofar & nore
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public License
|
|
as published by the Free Software Foundation; either version 2.1
|
|
of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
MA 02111-1307 USA
|
|
|
|
]]--
|
|
|
|
local S = minetest.get_translator("tools")
|
|
|
|
--
|
|
-- hand tools
|
|
--
|
|
minetest.register_item(":", {
|
|
type = "none",
|
|
wield_image = "wieldhand.png",
|
|
inventory_image = "wieldhand.png",
|
|
wield_scale = {x = 1, y = 1, z = 2},
|
|
range = 4,
|
|
tool_capabilities = {
|
|
full_punch_interval = 0.5,
|
|
max_drop_level = 0,
|
|
-- can't pick up any node by hand
|
|
groupcaps = {
|
|
hand = {times={[1] = 0.2}, uses = 0, maxlevel = 1},
|
|
},
|
|
damage_groups = {},
|
|
},
|
|
groups = {not_in_creative_inventory = 1}
|
|
})
|
|
|
|
minetest.register_item("tools:edit", {
|
|
type = "none",
|
|
wield_image = "wieldhand_edit.png",
|
|
inventory_image = "wieldhand_edit.png",
|
|
wield_scale = {x = 1, y = 1, z = 2},
|
|
range = 4, -- to make sure we can reach as far as the player
|
|
tool_capabilities = {
|
|
full_punch_interval = 0.1,
|
|
max_drop_level = 0,
|
|
groupcaps = {
|
|
hand = {times={[1] = 0.2}, uses = 0, maxlevel = 1},
|
|
axe = {times={[1] = 0.2}, uses = 0, maxlevel = 1},
|
|
shovel = {times={[1] = 0.2}, uses = 0, maxlevel = 1},
|
|
pickaxe = {times={[1] = 0.2}, uses = 0, maxlevel = 1},
|
|
node = {times={[1] = 0.2}, uses = 0, maxlevel = 1},
|
|
unbreakable = {times={[1] = 0.2}, uses = 0, maxlevel = 1},
|
|
},
|
|
damage_groups = {},
|
|
},
|
|
groups = {not_in_creative_inventory = 1}
|
|
})
|
|
|
|
|
|
-- node tools
|
|
minetest.register_tool("tools:shovel", {
|
|
description = S("Shovel"),
|
|
inventory_image = "shovel.png",
|
|
tool_capabilities = {
|
|
groupcaps = {
|
|
shovel = {
|
|
times = {[1] = 1.5, [2] = 1.5, [3] = 1.5},
|
|
uses = 0,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
frame.register("tools:shovel")
|
|
|
|
minetest.register_tool("tools:axe", {
|
|
description = S("Axe"),
|
|
inventory_image = "axe.png",
|
|
tool_capabilities = {
|
|
groupcaps = {
|
|
axe = {
|
|
times = {[1] = 1.5, [2] = 1.5, [3] = 1.5},
|
|
uses = 0,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
frame.register("tools:axe")
|
|
|
|
minetest.register_tool("tools:pickaxe", {
|
|
description = S("Pickaxe"),
|
|
inventory_image = "pickaxe.png",
|
|
tool_capabilities = {
|
|
groupcaps = {
|
|
pickaxe = {
|
|
times = {[1] = 3, [2] = 3, [3] = 3},
|
|
uses = 0,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
frame.register("tools:pickaxe")
|
|
|
|
minetest.register_tool("tools:sword", {
|
|
description = S("Sword"),
|
|
inventory_image = "sword.png",
|
|
})
|
|
frame.register("tools:sword")
|
|
|
|
|
|
minetest.register_tool("tools:flint_and_steel", {
|
|
description = S("Flint and steel"),
|
|
inventory_image = "flint_and_steel.png",
|
|
})
|
|
frame.register("tools:flint_and_steel")
|
|
|
|
local function node_dig(pos, digger)
|
|
-- from builtin/item.lua core.node_dig():
|
|
local node = minetest.get_node(pos)
|
|
local def = minetest.registered_nodes[node.name]
|
|
|
|
local sounds = minetest.registered_nodes[node.name].sounds
|
|
if sounds and sounds.dig then
|
|
minetest.sound_play(sounds.dig, {pos = pos})
|
|
end
|
|
|
|
local oldmetadata = nil
|
|
if def and def.after_dig_node then
|
|
oldmetadata = core.get_meta(pos):to_table()
|
|
end
|
|
|
|
minetest.remove_node(pos, node)
|
|
|
|
if def and def.after_dig_node then
|
|
local pos_copy = {x=pos.x, y=pos.y, z=pos.z}
|
|
local node_copy = {name = node.name, param1 = node.param1, param2 = node.param2}
|
|
def.after_dig_node(pos_copy, node_copy, oldmetadata, digger)
|
|
end
|
|
|
|
for _, callback in ipairs(core.registered_on_dignodes) do
|
|
local origin = core.callback_origins[callback]
|
|
if origin then
|
|
core.set_last_run_mod(origin.mod)
|
|
end
|
|
|
|
-- Copy pos and node because callback can modify them
|
|
local pos_copy = {x=pos.x, y=pos.y, z=pos.z}
|
|
local node_copy = {name = node.name, param1 = node.param1, param2 = node.param2}
|
|
callback(pos_copy, node_copy, digger)
|
|
end
|
|
end
|
|
|
|
minetest.register_tool("tools:admin", {
|
|
description = S("Admin remove tool"),
|
|
inventory_image = "admin_tool.png",
|
|
liquids_pointable = true,
|
|
range = 10,
|
|
on_use = function(itemstack, digger, pointed_thing)
|
|
if not pointed_thing or not pointed_thing.under then
|
|
return
|
|
end
|
|
-- Prevent non-admins from using an admin tool if they ever get one
|
|
if not digger or not minetest.check_player_privs(digger, "server") then
|
|
return
|
|
end
|
|
node_dig(pointed_thing.under, digger)
|
|
return itemstack
|
|
end,
|
|
})
|
|
|
|
|
|
minetest.register_tool("tools:player", {
|
|
description = S("Remove tool").."\n"..
|
|
S("Left-click to remove a node").."\n"..
|
|
S("Right-click to remove a lot of nodes").."\n"..
|
|
S("Shift-left-click a placed node to restrict removal"),
|
|
inventory_image = "remove_tool.png",
|
|
liquids_pointable = true,
|
|
range = 6,
|
|
on_use = function(itemstack, digger, pointed_thing)
|
|
if not digger then
|
|
return
|
|
end
|
|
local name = digger:get_player_name()
|
|
if not boxes.players_editing_boxes[name] then
|
|
return
|
|
end
|
|
if not pointed_thing or not pointed_thing.under then
|
|
if not digger:get_player_control().sneak then
|
|
return itemstack
|
|
end
|
|
-- empty the contained node
|
|
local meta = itemstack:get_meta()
|
|
meta:set_string("nodes", "return {}")
|
|
minetest.chat_send_player(name, S("Remove tool unrestricted"))
|
|
meta:set_string("description", S("Remove tool").."\n"..
|
|
S("Left-click to remove a node").."\n"..
|
|
S("Right-click to remove a lot of nodes").."\n"..
|
|
S("Shift-left-click a placed node to restrict removal"))
|
|
return itemstack
|
|
end
|
|
if digger:get_player_control().sneak then
|
|
-- fill the itemstack
|
|
local meta = itemstack:get_meta()
|
|
local nodes = minetest.deserialize(meta:get_string("nodes") or {}) or {}
|
|
local node = minetest.get_node(pointed_thing.under)
|
|
nodes[#nodes + 1] = node.name
|
|
meta:set_string("nodes", minetest.serialize(nodes))
|
|
minetest.chat_send_player(name, S("Remove tool restricted to: @1", table.concat(nodes, ", ")))
|
|
meta:set_string("description", S("Remove tool").."\n"..S("Will remove: @1", table.concat(nodes, ", ")))
|
|
return itemstack
|
|
end
|
|
|
|
local box = boxes.players_editing_boxes[name]
|
|
local pos = pointed_thing.under
|
|
if pos.x <= box.minp.x or pos.x >= box.maxp.x or
|
|
pos.y <= box.minp.y or pos.y >= box.maxp.y or
|
|
pos.z <= box.minp.z or pos.z >= box.maxp.z
|
|
then
|
|
return
|
|
end
|
|
local meta = itemstack:get_meta()
|
|
local n = meta:get_string("nodes")
|
|
|
|
if n and n ~= "" and n ~= "return {}" then
|
|
local nodes = minetest.deserialize(n)
|
|
local t = minetest.get_node(pointed_thing.under)
|
|
for _, v in ipairs(nodes) do
|
|
if t.name == v then
|
|
node_dig(pointed_thing.under, digger)
|
|
end
|
|
end
|
|
return itemstack
|
|
end
|
|
|
|
node_dig(pointed_thing.under, digger)
|
|
|
|
return itemstack
|
|
end,
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
if not pointed_thing or not pointed_thing.under then
|
|
return
|
|
end
|
|
if not placer then
|
|
return
|
|
end
|
|
local name = placer:get_player_name()
|
|
if not boxes.players_editing_boxes[name] then
|
|
return
|
|
end
|
|
local box = boxes.players_editing_boxes[name]
|
|
local pos = pointed_thing.under
|
|
|
|
local meta = itemstack:get_meta()
|
|
local n = meta:get_string("nodes")
|
|
local nodes = {}
|
|
if n and n ~= "" and n ~= "return {}" then
|
|
nodes = minetest.deserialize(n)
|
|
end
|
|
|
|
for x = pos.x - 1, pos.x + 1 do
|
|
for y = pos.y + 1, pos.y - 1, -1 do
|
|
for z = pos.z - 1, pos.z + 1 do
|
|
if x > box.minp.x and x < box.maxp.x and
|
|
y > box.minp.y and y < box.maxp.y and
|
|
z > box.minp.z and z < box.maxp.z then
|
|
if #nodes == 0 then
|
|
node_dig({x = x, y = y, z = z}, placer)
|
|
else
|
|
for _, v in ipairs(nodes) do
|
|
local p = {x = x, y = y, z = z}
|
|
local t = minetest.get_node(p)
|
|
if t.name == v then
|
|
node_dig(p, placer)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return itemstack
|
|
end,
|
|
})
|
|
frame.register("tools:player")
|
|
|
|
local bulk_modes = {
|
|
[0] = "blob",
|
|
[1] = "sheet",
|
|
[2] = "large blob",
|
|
[3] = "large sheet",
|
|
[4] = "wall",
|
|
}
|
|
minetest.register_tool("tools:bulk", {
|
|
description = S("Bulk placement tool").."\n"..
|
|
S("Left-click air to toggle mode").."\n"..
|
|
S("Shift-left-click to toggle mode").."\n"..
|
|
S("Left-click a node to pick it up").."\n"..
|
|
S("Right-click to place nodes"),
|
|
inventory_image = "node_place_tool.png",
|
|
liquids_pointable = true,
|
|
range = 8,
|
|
on_use = function(itemstack, placer, pointed_thing)
|
|
if not pointed_thing or not pointed_thing.under or
|
|
placer:get_player_control().sneak then
|
|
-- toggle placement mode
|
|
local meta = itemstack:get_meta()
|
|
local mode = meta:get_int("mode") or 0
|
|
mode = mode + 1
|
|
if mode > #bulk_modes then
|
|
mode = 0
|
|
end
|
|
minetest.chat_send_player(placer:get_player_name(),
|
|
S("Bulk placement tool will place \"@1\".", bulk_modes[mode]))
|
|
|
|
meta:set_int("mode", mode)
|
|
return itemstack
|
|
end
|
|
local node = minetest.get_node(pointed_thing.under)
|
|
local def = minetest.registered_nodes[node.name]
|
|
if not def and not def.groups then
|
|
return itemstack
|
|
end
|
|
if def.groups.not_in_creative_inventory or
|
|
def.groups.trigger or def.groups.mech or
|
|
def.groups.door
|
|
then
|
|
if not minetest.check_player_privs(placer:get_player_name(), "server") then
|
|
return itemstack
|
|
end
|
|
end
|
|
itemstack:set_metadata(minetest.serialize(node))
|
|
minetest.chat_send_player(placer:get_player_name(),
|
|
"Bulk tool will place " .. node.name)
|
|
local meta = itemstack:get_meta()
|
|
meta:set_string("description", S("Bulk placement tool").."\n"..
|
|
S("Node: @1", node.name).."\n"..
|
|
S("Mode: @1", bulk_modes[meta:get_int("mode")]))
|
|
return itemstack
|
|
end,
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
if not pointed_thing or not pointed_thing.above or not placer then
|
|
return
|
|
end
|
|
local node = minetest.deserialize(itemstack:get_metadata())
|
|
if not node then
|
|
minetest.chat_send_player(placer:get_player_name(),
|
|
S("Pick up a node first by left-clicking it with this tool"))
|
|
return
|
|
end
|
|
local name = placer:get_player_name()
|
|
local box = boxes.players_editing_boxes[name]
|
|
if not box and not minetest.check_player_privs(name, "server") then
|
|
return
|
|
end
|
|
if not box then
|
|
box = {
|
|
minp = { x = -32768, y = -32768, z = -32768 },
|
|
maxp = { x = 32768, y = 32768, z = 32768 },
|
|
}
|
|
end
|
|
|
|
-- make sure we don't choke the player.
|
|
local head = vector.add(vector.round(placer:get_pos()), {x = 0, y = 1, z = 0})
|
|
|
|
local pos = pointed_thing.under
|
|
local pnode = minetest.get_node(pos)
|
|
if not minetest.registered_nodes[pnode.name].buildable_to then
|
|
pos = pointed_thing.above
|
|
end
|
|
local meta = itemstack:get_meta()
|
|
local mode = meta:get_int("mode") or 0
|
|
-- toggle size
|
|
local size = { 3, 20, 28 }
|
|
if mode == 2 or mode == 3 then
|
|
size = {7, 50, 68 }
|
|
end
|
|
|
|
local function can_place_at(p, b, h)
|
|
if p.x <= b.minp.x or p.x >= b.maxp.x or
|
|
p.y <= b.minp.y or p.y >= b.maxp.y or
|
|
p.z <= b.minp.z or p.z >= b.maxp.z then
|
|
return false
|
|
end
|
|
if vector.equals(p, h) then
|
|
return false
|
|
end
|
|
local n = minetest.get_node(p)
|
|
if n.name == "air" then
|
|
return true
|
|
end
|
|
local def = minetest.registered_nodes[n.name]
|
|
if def and def.liquidtype and def.liquidtype == "flowing" then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
if mode == 0 or mode == 2 then
|
|
for x = pos.x - size[1], pos.x + size[1] do
|
|
for y = pos.y - size[1], pos.y + size[1] do
|
|
for z = pos.z - size[1], pos.z + size[1] do
|
|
local ppos = {x = x, y = y, z = z}
|
|
if can_place_at(ppos, box, head) and
|
|
vector.distance(pos, ppos) <=
|
|
(math.random(size[2], size[3]) / 10)
|
|
then
|
|
minetest.set_node(ppos, node)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
elseif mode == 1 or mode == 3 then
|
|
for x = pos.x - size[1], pos.x + size[1] do
|
|
for z = pos.z - size[1], pos.z + size[1] do
|
|
local ppos = {x = x, y = pos.y, z = z}
|
|
if can_place_at(ppos, box, head) and
|
|
vector.distance(pos, ppos) <=
|
|
(math.random(size[2], size[3]) / 10)
|
|
then
|
|
minetest.set_node(ppos, node)
|
|
end
|
|
end
|
|
end
|
|
elseif mode == 4 then
|
|
local dir = minetest.yaw_to_dir(placer:get_look_yaw() - (math.pi / 2))
|
|
for i = 0, 4 do
|
|
for y = 0, 2 do
|
|
local ppos = vector.round(vector.add(pos, vector.multiply(dir, i)))
|
|
ppos.y = ppos.y + y
|
|
if can_place_at(ppos, box, head) then
|
|
minetest.set_node(ppos, node)
|
|
end
|
|
end
|
|
end
|
|
else
|
|
return itemstack
|
|
end
|
|
minetest.log("action", name .. " uses tools:bulk placing a " .. bulk_modes[mode] ..
|
|
" of " .. node.name .. " at " .. minetest.pos_to_string(pos))
|
|
return itemstack
|
|
end,
|
|
})
|
|
frame.register("tools:bulk")
|
|
|
|
minetest.register_tool("tools:paint", {
|
|
description = S("Paint tool").."\n"..
|
|
S("Paint nodes over with a different node").."\n"..
|
|
S("Left-click to fill the tool with a node").."\n"..
|
|
S("Right-click to paint"),
|
|
inventory_image = "node_paint_tool.png",
|
|
liquids_pointable = true,
|
|
range = 6,
|
|
on_use = function(itemstack, placer, pointed_thing)
|
|
if not pointed_thing or not pointed_thing.under then
|
|
return itemstack
|
|
end
|
|
local node = minetest.get_node(pointed_thing.under)
|
|
local def = minetest.registered_nodes[node.name]
|
|
if not def and not def.groups then
|
|
return itemstack
|
|
end
|
|
if def.groups.not_in_creative_inventory or
|
|
def.groups.door
|
|
then
|
|
if not minetest.check_player_privs(placer:get_player_name(), "server") then
|
|
return itemstack
|
|
end
|
|
end
|
|
local meta = itemstack:get_meta()
|
|
meta:set_string("node", minetest.serialize(node))
|
|
meta:set_string("meta", minetest.serialize(minetest.get_meta(pointed_thing.under):to_table()))
|
|
meta:set_string("description", "Paint tool\nNode: " .. node.name)
|
|
minetest.chat_send_player(placer:get_player_name(),
|
|
"Paint tool will paint " .. node.name)
|
|
return itemstack
|
|
end,
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
if not pointed_thing or not pointed_thing.above or not placer then
|
|
return
|
|
end
|
|
local meta = itemstack:get_meta()
|
|
local node = minetest.deserialize(meta:get_string("node"))
|
|
local nmeta = minetest.deserialize(meta:get_string("meta"))
|
|
if not node then
|
|
minetest.chat_send_player(placer:get_player_name(),
|
|
S("Pick up a node first by left-clicking it with this tool"))
|
|
return
|
|
end
|
|
local name = placer:get_player_name()
|
|
local box = boxes.players_editing_boxes[name]
|
|
if not box and not minetest.check_player_privs(name, "server") then
|
|
return
|
|
end
|
|
|
|
if not box then
|
|
box = {
|
|
minp = { x = -32768, y = -32768, z = -32768 },
|
|
maxp = { x = 32768, y = 32768, z = 32768 },
|
|
}
|
|
end
|
|
|
|
local pos = pointed_thing.under
|
|
if pos.x > box.minp.x and pos.x < box.maxp.x and
|
|
pos.y > box.minp.y and pos.y < box.maxp.y and
|
|
pos.z > box.minp.z and pos.z < box.maxp.z then
|
|
minetest.set_node(pos, node)
|
|
end
|
|
if nmeta then
|
|
local pmeta = minetest.get_meta(pos)
|
|
pmeta:from_table(nmeta)
|
|
end
|
|
|
|
return itemstack
|
|
end,
|
|
})
|
|
frame.register("tools:paint")
|
|
|
|
minetest.register_tool("tools:grow", {
|
|
description = S("Growth tool"),
|
|
inventory_image = "grow_tool.png",
|
|
range = 6,
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
if not pointed_thing or not pointed_thing.under or not placer then
|
|
return
|
|
end
|
|
local name = placer:get_player_name()
|
|
local box = boxes.players_editing_boxes[name]
|
|
if not box then
|
|
if not minetest.check_player_privs(placer, "server") then
|
|
return
|
|
end
|
|
box = {
|
|
minp = { x = -32768, y = -32768, z = -32768 },
|
|
maxp = { x = 32768, y = 32768, z = 32768 },
|
|
}
|
|
end
|
|
local pos = pointed_thing.under
|
|
local nname = minetest.get_node(pos).name
|
|
if nname == "nodes:dirt" then
|
|
for x = math.max(box.minp.x + 1, pos.x - 2), math.min(box.maxp.x - 1, pos.x + 2) do
|
|
for y = math.max(box.minp.y + 1, pos.y), math.min(box.maxp.y - 1, pos.y) do
|
|
for z = math.max(box.minp.z + 1, pos.z - 2), math.min(box.maxp.z - 1, pos.z + 2) do
|
|
local ppos = {x = x, y = y, z = z}
|
|
if vector.distance(pos, ppos) <= 2.3 then
|
|
local node = minetest.get_node(ppos)
|
|
local above_node = minetest.get_node({x = x, y = y + 1, z = z})
|
|
if node.name == "nodes:dirt" and
|
|
minetest.registered_nodes[above_node.name] and
|
|
minetest.registered_nodes[above_node.name].walkable == false then
|
|
node.name = "nodes:dirt_with_grass"
|
|
minetest.set_node(ppos, node)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
elseif nname == "nodes:grass" or nname == "nodes:dirt_with_grass" then
|
|
-- Grow grass and other things
|
|
for x = math.max(box.minp.x + 1, pos.x - 2), math.min(box.maxp.x - 1, pos.x + 2) do
|
|
for y = math.max(box.minp.y + 1, pos.y), math.min(box.maxp.y - 1, pos.y) do
|
|
for z = math.max(box.minp.z + 1, pos.z - 2), math.min(box.maxp.z - 1, pos.z + 2) do
|
|
local ppos = {x = x, y = y, z = z}
|
|
if vector.distance(pos, ppos) <= 2.3 then
|
|
local node = minetest.get_node(ppos)
|
|
local pos_above = {x = x, y = y + 1, z = z}
|
|
local above_node = minetest.get_node(pos_above)
|
|
if (node.name == "nodes:grass" or node.name == "nodes:dirt_with_grass") and
|
|
above_node.name == "air" and math.random() < 0.2 then
|
|
local plants = {
|
|
{"grass_1", 56},
|
|
{"grass_2", 56},
|
|
{"grass_3", 56},
|
|
{"grass_4", 56},
|
|
{"grass_5", 56},
|
|
{"grass_1", 56},
|
|
{"grass_2", 56},
|
|
{"grass_3", 56},
|
|
{"grass_4", 56},
|
|
{"grass_5", 56},
|
|
{"grass_1", 56},
|
|
{"grass_2", 56},
|
|
{"grass_3", 56},
|
|
{"grass_4", 56},
|
|
{"grass_5", 56},
|
|
{"grass_1", 56},
|
|
{"grass_2", 56},
|
|
{"grass_3", 56},
|
|
{"grass_4", 56},
|
|
{"grass_5", 56},
|
|
{"rose", 9},
|
|
{"dandelion", 9},
|
|
{"white_tulip", 9},
|
|
{"allium", 9},
|
|
{"orchid", 9},
|
|
{"daisy", 9},
|
|
{"houstonia", 9},
|
|
{"paeonia", 9},
|
|
}
|
|
local p = plants[math.random(1, 28)]
|
|
local nnode = {name = "nodes:" .. p[1], param2 = p[2]}
|
|
minetest.set_node(pos_above, nnode)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return itemstack
|
|
end,
|
|
})
|
|
frame.register("tools:grow")
|
|
|
|
local function dehash_vector(s)
|
|
return {
|
|
x = 256 * string.byte(s, 1) + string.byte(s, 2) - 32768,
|
|
y = 256 * string.byte(s, 3) + string.byte(s, 4) - 32768,
|
|
z = 256 * string.byte(s, 5) + string.byte(s, 6) - 32768,
|
|
}
|
|
end
|
|
|
|
local function particlestream(p, o, name)
|
|
local d = vector.length(o)
|
|
local c = 0
|
|
while c < d - 0.5 do
|
|
minetest.add_particle({
|
|
texture = "glowblock.png",
|
|
pos = vector.add(p, vector.multiply(o, c / d)),
|
|
velocity = vector.divide(o, d * 3),
|
|
expirationtime = 3,
|
|
size = 2,
|
|
glow = 14,
|
|
playername = name,
|
|
})
|
|
c = c + 0.5
|
|
end
|
|
end
|
|
|
|
minetest.register_tool("tools:reveal", {
|
|
description = S("Reveal tool").."\n"..
|
|
S("Reveal breakable nodes and placeholder nodes").."\n"..
|
|
S("Punch a node to see its connections"),
|
|
inventory_image = "reveal_tool.png",
|
|
on_use = function(itemstack, digger, pointed_thing)
|
|
if not digger then
|
|
return
|
|
end
|
|
local name = digger:get_player_name()
|
|
if not boxes.players_editing_boxes[name] and not minetest.check_player_privs(digger, "server") then
|
|
return
|
|
end
|
|
local box = boxes.players_editing_boxes[name]
|
|
|
|
if not box then
|
|
if not minetest.check_player_privs(digger, "server") then
|
|
return
|
|
end
|
|
box = {
|
|
minp = { x = -32768, y = -32768, z = -32768 },
|
|
maxp = { x = 32768, y = 32768, z = 32768 },
|
|
}
|
|
end
|
|
|
|
local off = {
|
|
{ x = 0, y = 0, z = -9/16},
|
|
{ x = 0, y = 0, z = 9/16},
|
|
{ x = 0, y = -9/16, z = 0},
|
|
{ x = 0, y = 9/16, z = 0},
|
|
{ x = -9/16, y = 0, z = 0},
|
|
{ x = 9/16, y = 0, z = 0},
|
|
}
|
|
|
|
-- if clicking a node, reveal mech connections
|
|
if pointed_thing.under then
|
|
local p = pointed_thing.under
|
|
local meta = minetest.get_meta(p)
|
|
local offsets = minetest.deserialize(meta:get_string("offsets")) or {}
|
|
for v, _ in pairs(offsets) do
|
|
local o = dehash_vector(v)
|
|
particlestream(p, o, name)
|
|
end
|
|
local roffsets = minetest.deserialize(meta:get_string("roffsets")) or {}
|
|
for v, _ in pairs(roffsets) do
|
|
local o = dehash_vector(v)
|
|
particlestream(vector.add(p, o), {x=-o.x, y=-o.y, z=-o.z}, name)
|
|
end
|
|
|
|
local dn = digger:get_player_name()
|
|
|
|
-- reveal callbacks, mech linkage info
|
|
local n = minetest.get_node(p)
|
|
if n and n.name and minetest.registered_nodes[n.name] then
|
|
local def = minetest.registered_nodes[n.name]
|
|
minetest.chat_send_player(dn, minetest.colorize("#ff8888",
|
|
"Detailed info for \"" .. def.description:gsub("\n.*", "") ..
|
|
"\" at " .. minetest.pos_to_string(p) .. ":"))
|
|
|
|
for so, _ in pairs(offsets) do
|
|
local offs = dehash_vector(so)
|
|
local npos = vector.add(p, offs)
|
|
local nname = minetest.registered_nodes[minetest.get_node(npos).name].description
|
|
minetest.chat_send_player(dn, minetest.colorize("#44ff88",
|
|
"> triggers " .. nname:gsub("[\n(].*", "") .. " at " ..
|
|
minetest.pos_to_string(npos) .. " (offset is " ..
|
|
minetest.pos_to_string(offs) .. ")"))
|
|
end
|
|
|
|
for so, _ in pairs(roffsets) do
|
|
local offs = dehash_vector(so)
|
|
local npos = vector.add(p, offs)
|
|
local nname = minetest.registered_nodes[minetest.get_node(npos).name].description
|
|
minetest.chat_send_player(dn, minetest.colorize("#8888ff",
|
|
"> triggered by " .. nname:gsub("[\n(].*", "") .. " at " ..
|
|
minetest.pos_to_string(npos) .. " (offset is " ..
|
|
minetest.pos_to_string(offs) .. ")"))
|
|
end
|
|
|
|
local cb = def.on_reveal
|
|
if cb then
|
|
cb(dn, p)
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
local limit = 32
|
|
local ppos = vector.floor(digger:get_pos())
|
|
local nodes = {}
|
|
local needle = {"group:axe", "group:shovel", "group:pickaxe", "group:hand"}
|
|
for d = 3, 6 do
|
|
if limit > 0 then
|
|
local poslist, _ = minetest.find_nodes_in_area(vector.subtract(ppos, d),
|
|
vector.add(ppos, d),
|
|
needle)
|
|
|
|
for _, v in pairs(poslist) do
|
|
if limit > 0 then
|
|
if v.x < box.maxp.x and v.y < box.maxp.y and v.z < box.maxp.z and
|
|
v.x > box.minp.x and v.y > box.minp.y and v.z > box.minp.z then
|
|
nodes[minetest.pos_to_string(v)] = 1
|
|
limit = limit - 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for k, _ in pairs(nodes) do
|
|
local pos = minetest.string_to_pos(k)
|
|
local node = minetest.get_node(pos)
|
|
local groups = minetest.registered_nodes[node.name] and
|
|
minetest.registered_nodes[node.name].groups
|
|
|
|
local texture
|
|
if groups.axe then
|
|
texture = "axe.png"
|
|
elseif groups.shovel then
|
|
texture = "shovel.png"
|
|
elseif groups.pickaxe then
|
|
texture = "pickaxe.png"
|
|
elseif groups.hand then
|
|
texture = "wieldhand.png"
|
|
end
|
|
--FIXME leaves somehow don't work?
|
|
if texture and vector.distance(pos, digger:get_pos()) < 8 and
|
|
node.name ~= "nodes:snow_ledge" then
|
|
for _, v in ipairs(off) do
|
|
minetest.add_particle({
|
|
pos = vector.add(pos, v),
|
|
expirationtime = 8,
|
|
size = 3,
|
|
texture = texture,
|
|
playername = name,
|
|
glow = 13,
|
|
})
|
|
end
|
|
end
|
|
|
|
if node.name == "nodes:placeholder" then
|
|
local meta = minetest.get_meta(pos)
|
|
local placeable = meta:get_string("placeable")
|
|
if placeable ~= "" then
|
|
local nodelist = minetest.parse_json(placeable)
|
|
--FIXME just do the first placeholder, only
|
|
local n, _ = next(nodelist)
|
|
minetest.add_particle({
|
|
pos = pos,
|
|
expirationtime = 8,
|
|
size = 3,
|
|
texture = nodes.get_tiles(n),
|
|
glow = 14,
|
|
playername = name,
|
|
})
|
|
end
|
|
end
|
|
end
|
|
|
|
return itemstack
|
|
end,
|
|
})
|
|
frame.register("tools:reveal")
|