Aaron Suen 7b4d953c1f Prevent ticking-automation exploits
The soaking-tickling mechanism was intended only to speed up
otherwise very boring "waiting" gameplay gates in skyblock play,
by allowing players to trade attention for time.  It seems it has
been exploited in vanilla play, though, by triggering the tickling
recipes far faster than they normally should be triggered by
hand, using doors, breaking the time cost balance of things like
leaching or growing trees.

Add a "cuddly" dig group to the hand, and ONLY the hand, and make
the tickling recipes use this group so they only work with the
player's actual hand.

N.B. this group can be used for other pummel recipes in mods,
where a gentler touch is needed that cannot be gotten from a tool
or a machine, such as petting animals.
2023-04-26 07:10:34 -04:00

79 lines
2.2 KiB
Lua

-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore, pairs, string
= minetest, nodecore, pairs, string
local string_gsub
= string.gsub
-- LUALOCALS > ---------------------------------------------------------
function nodecore.register_dirt_leaching(fromnode, recipematch, tonode, rate)
local waters = {}
minetest.after(0, function()
for k, v in pairs(minetest.registered_nodes) do
if v.groups and v.groups.water and v.groups.water > 0 then
waters[k] = true
end
end
end)
local function waterat(pos, dx, dy, dz)
return waters[minetest.get_node(
{x = pos.x + dx, y = pos.y + dy, z = pos.z + dz}
).name]
end
local fieldname = "leach_" .. string_gsub(tonode, "%W+", "_")
nodecore.register_soaking_abm({
label = fromnode .. " leaching to " .. tonode,
fieldname = fieldname,
nodenames = {fromnode},
interval = 5,
arealoaded = 1,
quickcheck = function(pos)
return waterat(pos, 0, 1, 0)
end,
soakrate = function(pos)
local qty = 1
if waterat(pos, 1, 0, 0) then qty = qty * 1.5 end
if waterat(pos, -1, 0, 0) then qty = qty * 1.5 end
if waterat(pos, 0, 0, 1) then qty = qty * 1.5 end
if waterat(pos, 0, 0, -1) then qty = qty * 1.5 end
if waterat(pos, 0, -1, 0) then qty = qty * 1.5 end
return qty * (rate or 1)
end,
soakcheck = function(data, pos)
if data.total < 5000 then return end
nodecore.set_loud(pos, {name = tonode})
nodecore.witness(pos, "leach " .. fromnode)
return nodecore.fallcheck(pos)
end
})
nodecore.register_craft({
label = "tickle leach " .. fromnode,
action = "pummel",
toolgroups = {cuddly = 1},
normal = {y = 1},
indexkeys = {fromnode},
check = function(pos)
return waterat(pos, 0, 1, 0)
end,
nodes = {
{match = recipematch}
},
after = function(pos)
nodecore.soaking_abm_tickle(pos, fieldname)
nodecore.soaking_particles(pos, 25, 0.5, .45)
end
})
end
nodecore.register_dirt_leaching(
"group:dirt_raked",
{groups = {dirt_raked = true}, stacked = false},
"nc_terrain:sand"
)
nodecore.register_dirt_leaching(
"group:humus_raked",
{groups = {humus_raked = true}, stacked = false},
"nc_terrain:dirt",
3
)