42f125c716
Register a "rootmatch" property for all recipes that represents a broader, quicker test for recipe eligibility. False positives are allowed but false negatives are not. Since most recipes are eligible, we can use this to build an index for fast lookups of subsets of recipes to run and skip most of the other ones.
115 lines
3.2 KiB
Lua
115 lines
3.2 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local ipairs, minetest, nodecore, pairs, table, vector
|
|
= ipairs, minetest, nodecore, pairs, table, vector
|
|
local table_sort
|
|
= table.sort
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local modname = minetest.get_current_modname()
|
|
|
|
minetest.register_tool(modname .. ":rake", {
|
|
description = "Rake",
|
|
inventory_image = modname .. "_rake.png",
|
|
tool_capabilities = nodecore.toolcaps({
|
|
snappy = 1,
|
|
uses = 10
|
|
}),
|
|
groups = {flammable = 1},
|
|
sounds = nodecore.sounds("nc_tree_sticky")
|
|
})
|
|
|
|
local rakable = {}
|
|
local stackonly = {}
|
|
minetest.after(0, function()
|
|
for k, v in pairs(minetest.registered_nodes) do
|
|
if v.groups and v.groups.falling_node and v.groups.snappy == 1 then
|
|
rakable[k] = true
|
|
if v.groups.is_stack_only then stackonly[k] = true end
|
|
end
|
|
end
|
|
end)
|
|
|
|
local rakepos = {}
|
|
for dy = -1, 1 do
|
|
for dx = -2, 2 do
|
|
for dz = -2, 2 do
|
|
rakepos[#rakepos + 1] = {x = dx, y = dy, z = dz}
|
|
end
|
|
end
|
|
end
|
|
table_sort(rakepos, function(a, b) return vector.length(a) < vector.length(b) end)
|
|
|
|
local laststack
|
|
local lastraking
|
|
local old_node_dig = minetest.node_dig
|
|
minetest.node_dig = function(pos, node, user, ...)
|
|
laststack = nodecore.stack_get(pos)
|
|
local wield = user and user:is_player() and user:get_wielded_item()
|
|
lastraking = wield and wield:get_name() == modname .. ":rake"
|
|
return old_node_dig(pos, node, user, ...)
|
|
end
|
|
|
|
local function matching(_, na, pb, nb)
|
|
if stackonly[na.name] then
|
|
if not stackonly[nb.name] then return end
|
|
return (laststack and laststack:get_name()) == nodecore.stack_get(pb):get_name()
|
|
end
|
|
return na.name == nb.name
|
|
end
|
|
|
|
local function dorake(pos, node, user, ...)
|
|
local sneak = user:get_player_control().sneak
|
|
local objpos = {}
|
|
for _, rel in ipairs(rakepos) do
|
|
local p = vector.add(pos, rel)
|
|
local n = minetest.get_node(p)
|
|
if rakable[n.name] and ((not sneak) or matching(pos, node, p, n)) then
|
|
minetest.node_dig(p, n, user, ...)
|
|
end
|
|
objpos[minetest.hash_node_position(p)] = true
|
|
end
|
|
for _, lua in pairs(minetest.luaentities) do
|
|
if lua.name == "__builtin:item" then
|
|
local p = lua.object and lua.object:get_pos()
|
|
if p and objpos[minetest.hash_node_position(
|
|
vector.round(p))] then
|
|
lua.object:set_pos(pos)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local rakelock = {}
|
|
|
|
nodecore.register_on_dignode("rake handling", function(pos, node, user, ...)
|
|
if not lastraking then return end
|
|
|
|
if not (node and node.name and rakable[node.name]) then return end
|
|
if not user:is_player() then return end
|
|
|
|
local pname = user:get_player_name()
|
|
if rakelock[pname] then return end
|
|
rakelock[pname] = true
|
|
dorake(pos, node, user, ...)
|
|
rakelock[pname] = nil
|
|
|
|
lastraking = nil
|
|
end)
|
|
|
|
local adze = {name = modname .. ":adze", wear = 0.05}
|
|
nodecore.register_craft({
|
|
label = "assemble rake",
|
|
norotate = true,
|
|
rootmatch = {"nc_tree:stick"},
|
|
nodes = {
|
|
{match = "nc_tree:stick", replace = "air"},
|
|
{x = 0, z = -1, match = adze, replace = "air"},
|
|
{x = 0, z = 1, match = adze, replace = "air"},
|
|
{x = -1, z = 0, match = adze, replace = "air"},
|
|
{x = 1, z = 0, match = adze, replace = "air"},
|
|
},
|
|
items = {
|
|
modname .. ":rake"
|
|
}
|
|
})
|