295 lines
8.9 KiB
Lua
295 lines
8.9 KiB
Lua
local S, PS = minetest.get_translator("lzr_tools")
|
|
|
|
local instadig = { times = { [1] = 0, [2] = 0, [3] = 0}, uses=0, maxlevel=255}
|
|
|
|
lzr_tools = {}
|
|
|
|
-- Cheat tools and weapons
|
|
|
|
|
|
-- Digs (almost) any block
|
|
minetest.register_tool("lzr_tools:ultra_pickaxe", {
|
|
--~ Tool that digs blocks
|
|
description = S("Ultra Pickaxe"),
|
|
_tt_help = S("Removes blocks except liquids"),
|
|
inventory_image = "lzr_tools_ultra_pickaxe.png",
|
|
groups = { pickaxe = 1, editor_tool = 1 },
|
|
|
|
-- CAN point the normally non-pointable
|
|
-- level barriers
|
|
pointabilities = {
|
|
nodes = {
|
|
["group:barrier"] = true,
|
|
["group:skull"] = true,
|
|
},
|
|
},
|
|
|
|
range = 20,
|
|
tool_capabilities = {
|
|
groupcaps = {
|
|
choppy = instadig,
|
|
cracky = instadig,
|
|
snappy = instadig,
|
|
crumbly = instadig,
|
|
oddly_breakable_by_hand = instadig,
|
|
dig_immediate = instadig,
|
|
takable = instadig,
|
|
breakable = instadig,
|
|
},
|
|
},
|
|
})
|
|
|
|
|
|
-- Digs liquids
|
|
minetest.register_tool("lzr_tools:ultra_bucket", {
|
|
--~ Tool that digs liquids
|
|
description = S("Ultra Bucket"),
|
|
_tt_help = S("Removes liquids"),
|
|
inventory_image = "lzr_tools_ultra_bucket.png",
|
|
groups = { bucket = 1, editor_tool = 1 },
|
|
|
|
range = 20,
|
|
liquids_pointable = true,
|
|
tool_capabilities = {
|
|
groupcaps = {
|
|
liquid = instadig,
|
|
},
|
|
},
|
|
})
|
|
|
|
|
|
-- Add laser debug tools (requires a hidden setting)
|
|
if minetest.settings:get_bool("lzr_debug", false) then
|
|
|
|
-- This tool digs lasers. Usually this is only useful when lasers
|
|
-- are frozen because otherwise they instantly regenerate.
|
|
minetest.register_tool("lzr_tools:laser_absorber", {
|
|
--~ Hidden tool that digs lasers
|
|
description = S("Laser Absorber"),
|
|
_tt_help = S("Removes lasers"),
|
|
inventory_image = "lzr_tools_laser_absorber.png",
|
|
groups = { dev_tool = 1, not_in_creative_inventory = 1 },
|
|
|
|
-- Can point and dig lasers
|
|
pointabilities = {
|
|
nodes = {
|
|
["group:laser"] = true,
|
|
},
|
|
},
|
|
|
|
range = 20,
|
|
tool_capabilities = {
|
|
groupcaps = {
|
|
laser = instadig,
|
|
},
|
|
},
|
|
})
|
|
|
|
|
|
local ls_max_iterations = 0
|
|
|
|
local function emit_lasers_raw(max_iterations)
|
|
local minpos, maxpos = lzr_world.get_level_pos(), vector.add(lzr_world.get_level_pos(), lzr_world.get_level_size())
|
|
local vmanip = minetest.get_voxel_manip(minpos, maxpos)
|
|
local vpos1, vpos2 = vmanip:get_emerged_area()
|
|
local varea = VoxelArea:new({MinEdge = vpos1, MaxEdge = vpos2})
|
|
local vdata = vmanip:get_data()
|
|
local vdata_p2 = vmanip:get_param2_data()
|
|
local extra_state = {
|
|
detections = {},
|
|
out_of_bounds = {},
|
|
}
|
|
lzr_laser.emit_lasers_in_area(minpos, maxpos, varea, vdata, vdata_p2, extra_state, max_iterations)
|
|
|
|
-- Write laser changes to map
|
|
vmanip:set_data(vdata)
|
|
vmanip:set_param2_data(vdata_p2)
|
|
vmanip:write_to_map()
|
|
end
|
|
|
|
local clear_lasers = function(itemstack, user)
|
|
local minpos, maxpos = lzr_world.get_level_pos(), vector.add(lzr_world.get_level_pos(), lzr_world.get_level_size())
|
|
local vmanip = minetest.get_voxel_manip(minpos, maxpos)
|
|
local vpos1, vpos2 = vmanip:get_emerged_area()
|
|
local varea = VoxelArea:new({MinEdge = vpos1, MaxEdge = vpos2})
|
|
local vdata = vmanip:get_data()
|
|
|
|
lzr_laser.clear_lasers_in_area(minpos, maxpos, varea, vdata)
|
|
|
|
-- Write laser changes to map
|
|
vmanip:set_data(vdata)
|
|
vmanip:write_to_map()
|
|
|
|
return itemstack
|
|
end
|
|
|
|
local step_msg = function(user, iter)
|
|
--~ Message shown when the 'laser stepper' debug tool was used to simulate the laser travel algorithm with a set number of iterations
|
|
minetest.chat_send_player(user:get_player_name(), PS("Emitted lasers with @1 iteration.", "Emitted lasers with @1 iterations", iter, iter))
|
|
end
|
|
|
|
-- Debug tool to test the laser travel algorithm.
|
|
-- Simulates the laser travelling up to a certain maximum number of iterations.
|
|
minetest.register_tool("lzr_tools:laser_stepper", {
|
|
--~ Hidden debug tool to test the laser travel algorithm.
|
|
description = S("Laser Stepper"),
|
|
_tt_help = S("Simulates the laser travel algorithm up to a given number of iterations").."\n"..
|
|
S("Punch: Increase laser iterations by 1").."\n"..
|
|
S("Place: Decrease laser iterations by 1").."\n"..
|
|
S("Place/Punch + Sneak: Multiply iterations change by 10"),
|
|
inventory_image = "lzr_tools_laser_stepper.png",
|
|
groups = { dev_tool = 1, not_in_creative_inventory = 1 },
|
|
on_use = function(itemstack, user)
|
|
clear_lasers(itemstack, user)
|
|
if user:get_player_control().sneak then
|
|
ls_max_iterations = ls_max_iterations + 10
|
|
else
|
|
ls_max_iterations = ls_max_iterations + 1
|
|
end
|
|
emit_lasers_raw(ls_max_iterations)
|
|
step_msg(user, ls_max_iterations)
|
|
return itemstack
|
|
end,
|
|
on_place = function(itemstack, user)
|
|
clear_lasers(itemstack, user)
|
|
if user:get_player_control().sneak then
|
|
ls_max_iterations = ls_max_iterations - 10
|
|
else
|
|
ls_max_iterations = ls_max_iterations - 1
|
|
end
|
|
ls_max_iterations = math.max(0, ls_max_iterations)
|
|
emit_lasers_raw(ls_max_iterations)
|
|
step_msg(user, ls_max_iterations)
|
|
return itemstack
|
|
end,
|
|
on_secondary_use = function(itemstack, user)
|
|
clear_lasers(itemstack, user)
|
|
if user:get_player_control().sneak then
|
|
ls_max_iterations = ls_max_iterations - 10
|
|
else
|
|
ls_max_iterations = ls_max_iterations - 1
|
|
end
|
|
ls_max_iterations = math.max(0, ls_max_iterations)
|
|
emit_lasers_raw(ls_max_iterations)
|
|
step_msg(user, ls_max_iterations)
|
|
return itemstack
|
|
end,
|
|
})
|
|
|
|
end
|
|
|
|
local variant_cycles = {
|
|
next_nodes = {},
|
|
prev_nodes = {},
|
|
}
|
|
lzr_tools.register_variant_cycle = function(cycle)
|
|
for c=1, #cycle do
|
|
local cn = c + 1
|
|
if cn > #cycle then
|
|
cn = 1
|
|
end
|
|
local cp = c - 1
|
|
if cp < 1 then
|
|
cp = #cycle
|
|
end
|
|
local node_self = cycle[c]
|
|
local node_next = cycle[cn]
|
|
local node_prev = cycle[cp]
|
|
|
|
if variant_cycles.next_nodes[node_self] or variant_cycles.prev_nodes[node_self] then
|
|
minetest.log("warning", "[lzr_tools] register_variant_cycle: Node '"..node_self.."' already was part of a variant cycle. Overwriting ...")
|
|
end
|
|
variant_cycles.next_nodes[node_self] = node_next
|
|
variant_cycles.prev_nodes[node_self] = node_prev
|
|
end
|
|
end
|
|
|
|
-- Add a new node `new_node` into an existing variant cycle after `node_after`.
|
|
-- `new_node` must not be already part of a variant cycle and `node_after`
|
|
-- must be part of a variant cycle.
|
|
lzr_tools.extend_variant_cycle = function(node_after, new_node)
|
|
local added = false
|
|
if variant_cycles.next_nodes[new_node] or variant_cycles.prev_nodes[new_node] then
|
|
-- Can't extend cycle if new_node is already part of a cycle
|
|
return false
|
|
elseif variant_cycles.next_nodes[node_after] and variant_cycles.prev_nodes[node_after] then
|
|
local old_next = variant_cycles.next_nodes[node_after]
|
|
local old_prev = variant_cycles.prev_nodes[node_after]
|
|
variant_cycles.next_nodes[node_after] = new_node
|
|
variant_cycles.prev_nodes[old_next] = new_node
|
|
variant_cycles.next_nodes[new_node] = old_next
|
|
variant_cycles.prev_nodes[new_node] = old_prev
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
local use_variant_changer = function(itemstack, user, pointed_thing, forwards)
|
|
if pointed_thing.type ~= "node" then
|
|
return itemstack
|
|
end
|
|
local state = lzr_gamestate.get_state()
|
|
if state ~= lzr_gamestate.EDITOR and state ~= lzr_gamestate.DEV then
|
|
minetest.chat_send_player(user:get_player_name(), S("This tool only works in the level editor or development mode."))
|
|
return itemstack
|
|
end
|
|
local pos = pointed_thing.under
|
|
if minetest.is_protected(pos, user:get_player_name()) then
|
|
minetest.record_protection_violation(pos, user:get_player_name())
|
|
return itemstack
|
|
end
|
|
local node = minetest.get_node(pos)
|
|
local new_node
|
|
if forwards then
|
|
new_node = variant_cycles.next_nodes[node.name]
|
|
else
|
|
new_node = variant_cycles.prev_nodes[node.name]
|
|
end
|
|
local deactivated = false
|
|
if not new_node then
|
|
local def = minetest.registered_nodes[node.name]
|
|
-- If node is not part of a cycle, try the
|
|
-- inactive state instead (if one exists). That way, variants will
|
|
-- also work for nodes with a laser in it, e.g. iron bars with laser.
|
|
if def and def._lzr_inactive then
|
|
if forwards then
|
|
new_node = variant_cycles.next_nodes[def._lzr_inactive]
|
|
else
|
|
new_node = variant_cycles.prev_nodes[def._lzr_inactive]
|
|
end
|
|
deactivated = true
|
|
end
|
|
end
|
|
if new_node then
|
|
node.name = new_node
|
|
minetest.swap_node(pos, node)
|
|
local def = minetest.registered_nodes[node.name]
|
|
if def and def.sounds and def.sounds.place then
|
|
minetest.sound_play(def.sounds.place, {pos=pos}, true)
|
|
end
|
|
if deactivated then
|
|
if state == lzr_gamestate.EDITOR then
|
|
lzr_laser.full_laser_update()
|
|
end
|
|
end
|
|
end
|
|
return itemstack
|
|
end
|
|
|
|
minetest.register_tool("lzr_tools:variant_changer", {
|
|
description = S("Block Variant Changer"),
|
|
_tt_help = S("Changes a block to different variant"),
|
|
inventory_image = "lzr_tools_variant_changer.png",
|
|
groups = { editor_tool = 1 },
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
return use_variant_changer(itemstack, user, pointed_thing, true)
|
|
end,
|
|
on_place = function(itemstack, user, pointed_thing)
|
|
return use_variant_changer(itemstack, user, pointed_thing, false)
|
|
end,
|
|
})
|
|
|
|
-- Register node variants
|
|
dofile(minetest.get_modpath("lzr_tools").."/variants.lua")
|