e7d4d54b1c
- Register groups for chiseling doors. - Make recipe digging not use player inventory, but drop as an item unconditionally. N.B. the old "replace with air then drop item" method only worked with explicit item names and not group detection.
183 lines
5.4 KiB
Lua
183 lines
5.4 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local ItemStack, ipairs, minetest, nodecore, pairs, type
|
|
= ItemStack, ipairs, minetest, nodecore, pairs, type
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local function addgroups(sum, pos)
|
|
local node = minetest.get_node(pos)
|
|
local def = minetest.registered_items[node.name] or {}
|
|
if not def.groups then return end
|
|
for k, v in pairs(def.groups) do
|
|
sum[k] = (sum[k] or 0) + v
|
|
end
|
|
end
|
|
|
|
local function craftcheck(recipe, pos, node, data, xx, xz, zx, zz)
|
|
local function rel(x, y, z)
|
|
return {
|
|
x = pos.x + xx * x + zx * z,
|
|
y = pos.y + y,
|
|
z = pos.z + xz * x + zz * z
|
|
}
|
|
end
|
|
data.rel = rel
|
|
data.wield = ItemStack(data.wield or data.crafter and data.crafter:get_wielded_item())
|
|
if recipe.check and not recipe.check(pos, data) then return end
|
|
if recipe.wield and (not data.wield or not nodecore.match(
|
|
{stack = data.wield}, recipe.wield)) then return end
|
|
if recipe.normal then
|
|
if data.pointed.type ~= "node" or
|
|
recipe.normal.y ~= data.pointed.above.y - data.pointed.under.y then return end
|
|
local rx = recipe.normal.x * xx + recipe.normal.z * zx
|
|
if rx ~= data.pointed.above.x - data.pointed.under.x then return end
|
|
local rz = recipe.normal.x * xz + recipe.normal.z * zz
|
|
if rz ~= data.pointed.above.z - data.pointed.under.z then return end
|
|
end
|
|
for _, v in pairs(recipe.nodes) do
|
|
if v ~= recipe.root and v.match then
|
|
local p = rel(v.x, v.y, v.z)
|
|
if not nodecore.match(p, v.match) then return end
|
|
end
|
|
end
|
|
if recipe.touchgroups then
|
|
local sum = {}
|
|
addgroups(sum, rel(1, 0, 0))
|
|
addgroups(sum, rel(-1, 0, 0))
|
|
addgroups(sum, rel(0, 1, 0))
|
|
addgroups(sum, rel(0, -1, 0))
|
|
addgroups(sum, rel(0, 0, 1))
|
|
addgroups(sum, rel(0, 0, -1))
|
|
for k, v in pairs(recipe.touchgroups) do
|
|
local w = sum[k] or 0
|
|
if v > 0 and w < v then return end
|
|
if v <= 0 and w > -v then return end
|
|
end
|
|
end
|
|
local mindur = recipe.duration or 0
|
|
if type(mindur) == "function" then mindur = mindur(recipe, pos, node, data) end
|
|
if recipe.toolgroups then
|
|
if not data.wield then return end
|
|
local dg = data.wield:get_tool_capabilities().groupcaps
|
|
local t
|
|
for gn, lv in pairs(recipe.toolgroups) do
|
|
local gt = dg[gn]
|
|
gt = gt and gt.times
|
|
gt = gt and gt[lv]
|
|
if gt and (gt <= 4) and (not t or t > gt) then t = gt end
|
|
end
|
|
if not t then return end
|
|
mindur = mindur + t
|
|
end
|
|
mindur = mindur / recipe.rate_adjust
|
|
if mindur > 0 then
|
|
if not data.duration then return end
|
|
local dur = data.duration
|
|
if type(dur) == "function" then dur = dur(pos, data) end
|
|
if not dur or dur < mindur then
|
|
if data.inprogress then data.inprogress(pos, data) end
|
|
return 1
|
|
end
|
|
end
|
|
if data.before then data.before(pos, data) end
|
|
if recipe.before then recipe.before(pos, data) end
|
|
for _, v in ipairs(recipe.nodes) do
|
|
if v.replace then
|
|
local p = rel(v.x, v.y, v.z)
|
|
local r = v.replace
|
|
while type(r) == "function" do
|
|
r = r(p, v)
|
|
end
|
|
if r and type(r) == "string" then
|
|
r = {name = r}
|
|
end
|
|
if v.match.excess then
|
|
local s = nodecore.stack_get(p)
|
|
local x = s:get_count() - (v.match.count or 1)
|
|
if x > 0 then
|
|
s:set_count(x)
|
|
nodecore.item_eject(p, s)
|
|
end
|
|
nodecore.stack_set(p, ItemStack(""))
|
|
end
|
|
if r then
|
|
local n = minetest.get_node(p)
|
|
r.param2 = n.param2
|
|
nodecore.set_loud(p, r)
|
|
nodecore.fallcheck(p)
|
|
end
|
|
end
|
|
if v.dig then
|
|
local p = rel(v.x, v.y, v.z)
|
|
minetest.node_dig(p, minetest.get_node(p))
|
|
end
|
|
end
|
|
if recipe.items then
|
|
for _, v in pairs(recipe.items) do
|
|
nodecore.item_eject(rel(v.x or 0, v.y or 0, v.z or 0),
|
|
v.name, v.scatter, v.count, v.velocity)
|
|
end
|
|
end
|
|
if recipe.consumewield then
|
|
nodecore.consume_wield(data.crafter, recipe.consumewield)
|
|
elseif recipe.toolgroups and recipe.toolwear and data.crafter then
|
|
nodecore.wear_wield(data.crafter, recipe.toolgroups, recipe.toolwear)
|
|
end
|
|
if recipe.after then recipe.after(pos, data) end
|
|
if data.after then data.after(pos, data) end
|
|
if nodecore.player_stat_add then
|
|
nodecore.player_stat_add(1, data.crafter, "craft", recipe.label)
|
|
end
|
|
if recipe.witness then
|
|
local lut = {}
|
|
for _, v in pairs(recipe.nodes) do
|
|
lut[minetest.hash_node_position(v)] = true
|
|
end
|
|
nodecore.witness(pos, {recipe.action, recipe.label},
|
|
type(recipe.witness) == "number" and recipe.witness or nil,
|
|
function(p) return lut[minetest.hash_node_position(p)] end
|
|
)
|
|
end
|
|
minetest.log((data.crafter and data.crafter:get_player_name() or "unknown")
|
|
.. " completed recipe \"" .. recipe.label .. "\" at " ..
|
|
minetest.pos_to_string(pos) .. " upon " .. node.name)
|
|
return true
|
|
end
|
|
|
|
local function tryall(rc, pos, node, data)
|
|
local function go(xx, xz, zx, zz)
|
|
return craftcheck(rc, pos, node, data, xx, xz, zx, zz)
|
|
end
|
|
local r = go(1, 0, 0, 1)
|
|
if r then return r end
|
|
if not rc.norotate then
|
|
r = go(0, -1, 1, 0)
|
|
or go(-1, 0, 0, -1)
|
|
or go(0, 1, -1, 0)
|
|
if r then return r end
|
|
if not rc.nomirror then
|
|
r = go(-1, 0, 0, 1)
|
|
or go(0, 1, 1, 0)
|
|
or go(1, 0, 0, -1)
|
|
or go(0, -1, -1, 0)
|
|
end
|
|
end
|
|
return r
|
|
end
|
|
|
|
function nodecore.craft_check(pos, node, data)
|
|
data = data or {}
|
|
node.x = pos.x
|
|
node.y = pos.y
|
|
node.z = pos.z
|
|
data.pos = pos
|
|
data.node = node
|
|
for _, rc in ipairs(nodecore.craft_recipes) do
|
|
if data.action == rc.action
|
|
and nodecore.match(node, rc.root.match) then
|
|
data.recipe = rc
|
|
local r = tryall(rc, pos, node, data)
|
|
if r then return r == true end
|
|
end
|
|
end
|
|
end
|