492 lines
17 KiB
Lua
492 lines
17 KiB
Lua
-- mushroom_tools mod for Minetest
|
|
-- Copyright © 2020 Alex Yst <mailto:copyright@y.st>
|
|
|
|
-- This program 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 software 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 program. If not, see
|
|
-- <https://www.gnu.org./licenses/>.
|
|
|
|
-- This script includes code copied from the fire mod bundled as a part
|
|
-- of Minetest game. That mod was provided by the following people:
|
|
-- Originally by RealBadAngel, Maciej Kasatkin (LGPLv2.1+)
|
|
-- Various Minetest developers and contributors (LGPLv2.1+)
|
|
|
|
local colour = {
|
|
brown = minetest.get_color_escape_sequence("#6d544e"),
|
|
red = minetest.get_color_escape_sequence("#c36666"),
|
|
}
|
|
|
|
local function repair_tool(itemstack, player, old_craft_grid, craft_inv)
|
|
local tooldef = itemstack:get_definition()
|
|
if itemstack:get_name():sub(1, 15) == "mushroom_tools:" and tooldef.type == "tool" then
|
|
-- We gather a list of tools in the recipe that match the type of the
|
|
-- output. If there are two such tools, and no other items are
|
|
-- included, this is probably a tool repair recipe, so we should modify
|
|
-- the repair count. Repair count is pretty meaningless in-game, but
|
|
-- gives an idea of how much the tool has been kept and cared for. It's
|
|
-- just a sort of bonus feature for players.
|
|
local input_tools = {}
|
|
local input_count = 0
|
|
for _, item in next, old_craft_grid do
|
|
if not item:is_empty() then
|
|
input_count = input_count + 1
|
|
if item:get_name() == itemstack:get_name() then
|
|
input_tools[#input_tools+1] = item
|
|
end
|
|
end
|
|
end
|
|
if #input_tools == 2 and input_count == 2 then
|
|
local meta = itemstack:get_meta()
|
|
if itemstack:get_wear() == 0 then
|
|
meta:set_string("description", colour.red..tooldef.description..colour.brown.."\n(mangled)")
|
|
itemstack:set_name("mushroom_tools:mangled")
|
|
else
|
|
local repair_count = 1
|
|
for _, tool in next, input_tools do
|
|
local old_meta = tool:get_meta()
|
|
repair_count = repair_count + old_meta:get_int("repair")
|
|
end
|
|
meta:set_int("repair", repair_count)
|
|
meta:set_string("description", colour.red..tooldef.description..colour.brown.."\n(repair count: "..repair_count..")")
|
|
end
|
|
return itemstack
|
|
end
|
|
end
|
|
end
|
|
|
|
minetest.register_craft_predict(repair_tool)
|
|
|
|
minetest.register_on_craft(repair_tool)
|
|
|
|
-- Mushroom swords guarantee sapling drops and mushroom shovels
|
|
-- guarantee flint drops.
|
|
--
|
|
-- TO DO: This functionality is going to be removed from mushroom
|
|
-- swords and shovels and added as a potential buff for rune swords and
|
|
-- shovels.
|
|
for node, toolset in next, {
|
|
["default:acacia_bush_leaves" ] = {"mushroom_tools:sword"},
|
|
["default:acacia_leaves" ] = {"mushroom_tools:sword"},
|
|
["default:aspen_leaves" ] = {"mushroom_tools:sword"},
|
|
["default:blueberry_bush_leaves"] = {"mushroom_tools:sword"},
|
|
["default:bush_leaves" ] = {"mushroom_tools:sword"},
|
|
["default:gravel" ] = {"mushroom_tools:shovel"},
|
|
["default:junglegrass" ] = {"mushroom_tools:sword"},
|
|
["default:jungleleaves" ] = {"mushroom_tools:sword"},
|
|
["default:leaves" ] = {"mushroom_tools:sword"},
|
|
["default:pine_bush_needles" ] = {"mushroom_tools:sword"},
|
|
["default:pine_needles" ] = {"mushroom_tools:sword"},
|
|
} do
|
|
local old_drop = minetest.registered_nodes[node].drop.items
|
|
local new_drop_table = {
|
|
max_items = 1,
|
|
items = {
|
|
{
|
|
items = old_drop[1].items,
|
|
tools = toolset,
|
|
},
|
|
},
|
|
}
|
|
for index, drop in next, old_drop do
|
|
new_drop_table.items[index+1] = drop
|
|
end
|
|
minetest.override_item(node, {
|
|
drop = new_drop_table,
|
|
})
|
|
end
|
|
|
|
minetest.register_craftitem("mushroom_tools:lump_brown", {
|
|
description = "Brown Mushroom Lump",
|
|
inventory_image = "mushroom_tools.lump_brown.png",
|
|
})
|
|
|
|
minetest.register_craftitem("mushroom_tools:lump_red", {
|
|
description = "Red Mushroom Lump",
|
|
inventory_image = "mushroom_tools.lump_red.png",
|
|
})
|
|
|
|
minetest.register_craftitem("mushroom_tools:ingot_brown", {
|
|
description = "Brown Mushroom Ingot",
|
|
inventory_image = "mushroom_tools.ingot_brown.png",
|
|
})
|
|
|
|
minetest.register_craftitem("mushroom_tools:ingot_red", {
|
|
description = "Red Mushroom Ingot",
|
|
inventory_image = "mushroom_tools.ingot_red.png",
|
|
})
|
|
|
|
minetest.register_craftitem("mushroom_tools:mangled", {
|
|
description = "Mangled Mushroom Tool",
|
|
inventory_image = "mushroom_tools.mangled.png",
|
|
})
|
|
|
|
minetest.register_craft({
|
|
type = "cooking",
|
|
output = "mushroom_tools:ingot_brown",
|
|
recipe = "mushroom_tools:lump_brown",
|
|
cooktime = 99,
|
|
})
|
|
|
|
minetest.register_craft({
|
|
type = "cooking",
|
|
output = "mushroom_tools:ingot_red",
|
|
recipe = "mushroom_tools:lump_red",
|
|
cooktime = 99,
|
|
})
|
|
|
|
minetest.register_tool("mushroom_tools:pick", {
|
|
description = "Mushroom Pickaxe",
|
|
inventory_image = "mushroom_tools.pick.png",
|
|
tool_capabilities = {
|
|
full_punch_interval = 0.9,
|
|
max_drop_level=3,
|
|
groupcaps={
|
|
cracky = {times={[1]=2.0, [2]=1.0, [3]=0.50}, uses=2427, maxlevel=3},
|
|
},
|
|
damage_groups = {fleshy=5},
|
|
},
|
|
sound = {breaks = "default_tool_breaks"},
|
|
groups = {pickaxe = 1},
|
|
})
|
|
|
|
-- TO DO: This functionality is going to be removed from mushroom
|
|
-- shovels and added as a potential buff to rune shovels.
|
|
local spread_function
|
|
for _, ABM in next, minetest.registered_abms do
|
|
if ABM.mod_origin == "default" and ABM.label == "Grass spread" then
|
|
spread_function = ABM.action
|
|
end
|
|
end
|
|
|
|
minetest.register_tool("mushroom_tools:shovel", {
|
|
description = "Mushroom Shovel",
|
|
inventory_image = "mushroom_tools.shovel.png",
|
|
wield_image = "mushroom_tools.shovel.png^[transformR90",
|
|
tool_capabilities = {
|
|
full_punch_interval = 1.0,
|
|
max_drop_level=1,
|
|
groupcaps={
|
|
crumbly = {times={[1]=1.10, [2]=0.50, [3]=0.30}, uses=2427, maxlevel=3},
|
|
},
|
|
damage_groups = {fleshy=4},
|
|
},
|
|
sound = {breaks = "default_tool_breaks"},
|
|
groups = {shovel = 1},
|
|
on_place = function(itemstack, user, pointed_thing)
|
|
local target = minetest.get_node(pointed_thing.under)
|
|
if target.name == "default:dirt" then
|
|
spread_function(pointed_thing.under, target)
|
|
elseif minetest.registered_nodes[target.name]
|
|
and minetest.registered_nodes[target.name].on_rightclick then
|
|
return minetest.registered_nodes[target.name].on_rightclick(pointed_thing.under, target, user, itemstack, pointed_thing)
|
|
end
|
|
end,
|
|
})
|
|
|
|
minetest.register_tool("mushroom_tools:axe", {
|
|
description = "Mushroom Axe",
|
|
inventory_image = "mushroom_tools.axe.png",
|
|
tool_capabilities = {
|
|
full_punch_interval = 0.9,
|
|
max_drop_level=1,
|
|
groupcaps={
|
|
choppy={times={[1]=2.10, [2]=0.90, [3]=0.50}, uses=2427, maxlevel=3},
|
|
},
|
|
damage_groups = {fleshy=7},
|
|
},
|
|
sound = {breaks = "default_tool_breaks"},
|
|
groups = {axe = 1},
|
|
})
|
|
|
|
-- TO DO: This functionality is going to be removed from mushroom
|
|
-- swords and added as a potential buff to rune swords.
|
|
local prunable_trunk = {
|
|
["default:tree"] = {
|
|
leaves = {"default:apple", "default:apple_mark", "default:leaves"},
|
|
range = 3,
|
|
},
|
|
["default:jungletree"] = {
|
|
leaves = {"default:jungleleaves"},
|
|
range = 2,
|
|
},
|
|
["default:pine_tree"] = {
|
|
leaves = {"default:pine_needles"},
|
|
range = 3,
|
|
},
|
|
["default:acacia_tree"] = {
|
|
leaves = {"default:acacia_leaves"},
|
|
range = 2,
|
|
},
|
|
["default:aspen_tree"] = {
|
|
leaves = {"default:aspen_leaves"},
|
|
range = 3,
|
|
},
|
|
["default:bush_stem"] = {
|
|
leaves = {"default:bush_leaves"},
|
|
range = 1,
|
|
},
|
|
["default:acacia_bush_stem"] = {
|
|
leaves = {"default:acacia_bush_leaves"},
|
|
range = 1,
|
|
},
|
|
["default:pine_bush_stem"] = {
|
|
leaves = {"default:pine_bush_needles"},
|
|
range = 1,
|
|
},
|
|
}
|
|
|
|
minetest.register_tool("mushroom_tools:sword", {
|
|
description = "Mushroom Sword",
|
|
inventory_image = "mushroom_tools.sword.png",
|
|
tool_capabilities = {
|
|
full_punch_interval = 0.7,
|
|
max_drop_level=1,
|
|
groupcaps={
|
|
snappy={times={[1]=1.90, [2]=0.90, [3]=0.30}, uses=2427, maxlevel=3},
|
|
},
|
|
damage_groups = {fleshy=8},
|
|
},
|
|
sound = {breaks = "default_tool_breaks"},
|
|
groups = {sword = 1},
|
|
on_place = function(itemstack, user, pointed_thing)
|
|
local potential_log = minetest.get_node(pointed_thing.under)
|
|
if prunable_trunk[potential_log.name] then
|
|
local to_prune = minetest.find_nodes_in_area({
|
|
x = pointed_thing.under.x - prunable_trunk[potential_log.name].range,
|
|
y = pointed_thing.under.y - prunable_trunk[potential_log.name].range,
|
|
z = pointed_thing.under.z - prunable_trunk[potential_log.name].range,
|
|
}, {
|
|
x = pointed_thing.under.x + prunable_trunk[potential_log.name].range,
|
|
y = pointed_thing.under.y + prunable_trunk[potential_log.name].range,
|
|
z = pointed_thing.under.z + prunable_trunk[potential_log.name].range,
|
|
}, prunable_trunk[potential_log.name].leaves)
|
|
for _, pos in next, to_prune do
|
|
local node = minetest.get_node(pos)
|
|
minetest.node_dig(pos, node, user)
|
|
-- Apple marks are dealt with separately because minetest.node_dig()
|
|
-- doesn't work on them. It's probably because players can't normally
|
|
-- dig them. We also assume that apples have left behind apple marks
|
|
-- and remove those as well.
|
|
if node.name == "default:apple_mark"
|
|
or node.name == "default:apple" then
|
|
minetest.remove_node(pos)
|
|
end
|
|
end
|
|
-- This seems a bit unclean, but I'm not sure how else to handle the
|
|
-- situation. If no value is returned, Minetest restores the tool's
|
|
-- durability that was used to prune the leaves because it sets the
|
|
-- item stack to what it was before the player used this functionality.
|
|
-- On the other hand, if we return the itemstack the engine passed to
|
|
-- our callback, we've just restored the durability ourselves because
|
|
-- that copy came from before the tool was used to prune the leaves.
|
|
-- Likewise, we shouldn't manually add the wear ourselves because we
|
|
-- don't know if each leaf was harvested successfully or not (for
|
|
-- example, an area might be protected). The only thing to do seems to
|
|
-- be to get the item now wielded and return it, basically overwriting
|
|
-- the worn item with whatever the player now holds, which should
|
|
-- hopefully always be itself (or an empty stack if it broke).
|
|
return user:get_wielded_item()
|
|
elseif minetest.registered_nodes[potential_log.name]
|
|
and minetest.registered_nodes[potential_log.name].on_rightclick then
|
|
return minetest.registered_nodes[potential_log.name].on_rightclick(pointed_thing.under, potential_log, user, itemstack, pointed_thing)
|
|
end
|
|
end,
|
|
})
|
|
|
|
minetest.register_tool("mushroom_tools:screwdriver", {
|
|
description = "Mushroom Screwdriver\n(left-click rotates face, right-click rotates axis)",
|
|
inventory_image = "mushroom_tools.screwdriver.png",
|
|
groups = {tool = 1},
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
screwdriver.handler(itemstack, user, pointed_thing, screwdriver.ROTATE_FACE, 65536)
|
|
return itemstack
|
|
end,
|
|
on_place = function(itemstack, user, pointed_thing)
|
|
screwdriver.handler(itemstack, user, pointed_thing, screwdriver.ROTATE_AXIS, 65536)
|
|
return itemstack
|
|
end,
|
|
})
|
|
|
|
local function new_tool_itemstring(tool_name)
|
|
local tool = ItemStack(tool_name)
|
|
local meta = tool:get_meta()
|
|
local tooldef = tool:get_definition()
|
|
meta:set_int("repair", 0)
|
|
meta:set_string("description", colour.red..tooldef.description..colour.brown.."\n(repair count: 0)")
|
|
return tool:to_string()
|
|
end
|
|
|
|
minetest.register_craft({
|
|
output = new_tool_itemstring("mushroom_tools:pick"),
|
|
recipe = {
|
|
{"mushroom_tools:ingot_red", "mushroom_tools:ingot_red", "mushroom_tools:ingot_red"},
|
|
{"", "mushroom_tools:ingot_brown", ""},
|
|
{"", "mushroom_tools:ingot_brown", ""},
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = new_tool_itemstring("mushroom_tools:shovel"),
|
|
recipe = {
|
|
{"mushroom_tools:ingot_red"},
|
|
{"mushroom_tools:ingot_brown"},
|
|
{"mushroom_tools:ingot_brown"},
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = new_tool_itemstring("mushroom_tools:axe"),
|
|
recipe = {
|
|
{"mushroom_tools:ingot_red", "mushroom_tools:ingot_red"},
|
|
{"mushroom_tools:ingot_red", "mushroom_tools:ingot_brown"},
|
|
{"", "mushroom_tools:ingot_brown"},
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = new_tool_itemstring("mushroom_tools:sword"),
|
|
recipe = {
|
|
{"mushroom_tools:ingot_red"},
|
|
{"mushroom_tools:ingot_red"},
|
|
{"mushroom_tools:ingot_brown"},
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = new_tool_itemstring("mushroom_tools:screwdriver"),
|
|
recipe = {
|
|
{"mushroom_tools:ingot_red"},
|
|
{"mushroom_tools:ingot_brown"}
|
|
}
|
|
})
|
|
|
|
-----------------------------------------------------------------------
|
|
-- SHAMELESSLY COPIED VERBATIM FROM THE FIRE MOD, WITH ONLY THE WEAR
|
|
-- AMOUNT ALTERED. CREDIT GOES TO:
|
|
-- Originally by RealBadAngel, Maciej Kasatkin (LGPLv2.1+)
|
|
-- Various Minetest developers and contributors (LGPLv2.1+)
|
|
-----------------------------------------------------------------------
|
|
minetest.register_tool("mushroom_tools:fire_starter", {
|
|
description = "Mushroom Fire Starter",
|
|
inventory_image = "mushroom_tools.fire_starter.png",
|
|
sound = {breaks = "default_tool_breaks"},
|
|
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
local sound_pos = pointed_thing.above or user:get_pos()
|
|
minetest.sound_play(
|
|
"fire_flint_and_steel",
|
|
{pos = sound_pos, gain = 0.5, max_hear_distance = 8}
|
|
)
|
|
local player_name = user:get_player_name()
|
|
if pointed_thing.type == "node" then
|
|
local node_under = minetest.get_node(pointed_thing.under).name
|
|
local nodedef = minetest.registered_nodes[node_under]
|
|
if not nodedef then
|
|
return
|
|
end
|
|
if minetest.is_protected(pointed_thing.under, player_name) then
|
|
minetest.chat_send_player(player_name, "This area is protected")
|
|
return
|
|
end
|
|
if nodedef.on_ignite then
|
|
nodedef.on_ignite(pointed_thing.under, user)
|
|
elseif minetest.get_item_group(node_under, "flammable") >= 1
|
|
and minetest.get_node(pointed_thing.above).name == "air" then
|
|
minetest.set_node(pointed_thing.above, {name = "fire:basic_flame"})
|
|
end
|
|
end
|
|
if not (creative and creative.is_enabled_for
|
|
and creative.is_enabled_for(player_name)) then
|
|
-- Wear tool
|
|
local wdef = itemstack:get_definition()
|
|
itemstack:add_wear(1)
|
|
-- Tool break sound
|
|
if itemstack:get_count() == 0 and wdef.sound and wdef.sound.breaks then
|
|
minetest.sound_play(wdef.sound.breaks, {pos = sound_pos, gain = 0.5})
|
|
end
|
|
return itemstack
|
|
end
|
|
end,
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = new_tool_itemstring("mushroom_tools:fire_starter"),
|
|
recipe = {
|
|
{"mushroom_tools:ingot_brown", "mushroom_tools:ingot_red"}
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = new_tool_itemstring("mushroom_tools:lump_brown"),
|
|
recipe = {
|
|
{"piled:mushroom_brown", "piled:mushroom_brown", "piled:mushroom_brown"},
|
|
{"piled:mushroom_brown", "piled:mushroom_brown", "piled:mushroom_brown"},
|
|
{"piled:mushroom_brown", "piled:mushroom_brown", "piled:mushroom_brown"},
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = new_tool_itemstring("mushroom_tools:lump_red"),
|
|
recipe = {
|
|
{"piled:mushroom_red", "piled:mushroom_red", "piled:mushroom_red"},
|
|
{"piled:mushroom_red", "piled:mushroom_red", "piled:mushroom_red"},
|
|
{"piled:mushroom_red", "piled:mushroom_red", "piled:mushroom_red"},
|
|
}
|
|
})
|
|
|
|
--[[
|
|
|
|
MOVE THIS SECTION TO THE OTHER MOD!!
|
|
|
|
Update: The "other mod" was mushroom_tools_extended, which was
|
|
discontinued before release. Instead, something similar might get added
|
|
as a buff to the rune screwdriver or other rune tool.
|
|
|
|
-- Given a node name, we need to be able to look up what time-based
|
|
-- functions apply to it. Time-based functions are registered as either
|
|
-- on_timer() callbacks or ABMs. on_timer() callbacks can obviously be
|
|
-- looked up by node name easily, but to look up an ABM, we'd need to
|
|
-- search the entire table of ABMs every time and check each one
|
|
-- individually to see if it applies. That is, unless we index the ABMs
|
|
-- in terms of what nodes they apply to before we need to do any
|
|
-- lookups. Let's do that now.
|
|
local ABM_index = {}
|
|
|
|
minetest.register_on_mods_loaded(function()
|
|
for _, ABM in next, minetest.registered_abms do
|
|
local applies_to = {}
|
|
for _, affected_node in next, ABM.nodenames do
|
|
if affected_node:sub(1, 6) == "group:" then
|
|
local groups = affected_node:sub(7):split(",")
|
|
for node_name, _ in next, minetest.registered_nodes do
|
|
local is_in_groups = true
|
|
for _, group in next, groups do
|
|
if minetest.get_item_group(node_name, group) == 0 then
|
|
is_in_groups = false
|
|
end
|
|
end
|
|
if is_in_groups then
|
|
applies_to[node_name] = true
|
|
end
|
|
end
|
|
else
|
|
applies_to[affected_node] = true
|
|
end
|
|
end
|
|
for affected_node, _ in next, applies_to do
|
|
ABM_index[affected_node] = ABM_index[affected_node] or {}
|
|
ABM_index[affected_node][#ABM_index[affected_node] + 1] = ABM
|
|
end
|
|
end
|
|
end)
|
|
]]
|