Make rakes at least somewhat useful with doors

- Normal non-selective raking mode works when
  pushing a rake with a door.
- The rake does not pick itself up.
- Collected things are dumped at the location of
  the direct raking target.

This doesn't seem super useful right now, but
a rake digging a full stack of some item will cause
all additional stacks of items in its range to settle
near the full stack, which could end up over a chute
allowing the item to fall down, and thus could be
used to collect items that scatter over a wider area.

Before releasing this we might consider making
rake digging selective by default, so these can be
used to sort and filter items.

May also consider making it possible to dig with a
rake in other circumstances, e.g. pushing a rake
against an open side of a storebox that has no room
for the rake will cause the rake to dig that stack and
all nearby matches?

May also consider cleaning up the raking API entirely
to make it easier to directly invoke a rake via
machine digging ... or tidy up the machine digging
API so it's no so hacky.
This commit is contained in:
Aaron Suen 2021-12-16 18:01:23 -05:00
parent 32df131204
commit b7e4809e85
2 changed files with 20 additions and 12 deletions

View File

@ -5,7 +5,7 @@ local math_abs, math_max, table_sort
= math.abs, math.max, table.sort
-- LUALOCALS > ---------------------------------------------------------
-- To register a tool as a rake, provie a callback:
-- To register a tool as a rake, provide a callback:
-- on_rake(pos, node, user) returns volume, checkfunc
-- volume: ordered array of relative positions to be dug by rake
-- checkfunc(pos, node, rel): determine if item can be dug
@ -62,7 +62,9 @@ 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()
local wield = nodecore.machine_digging and nodecore.machine_digging.tool
or user and user:is_player() and user:get_wielded_item()
print(wield and wield:to_string() or "nada")
lastraking = wield and (wield:get_definition() or {}).on_rake
if lastraking then return deferfall(old_node_dig, pos, node, user, ...) end
return old_node_dig(pos, node, user, ...)
@ -84,16 +86,19 @@ local function matching(_, na, pb, nb)
end
local function dorake(volume, check, pos, node, user, ...)
local sneak = user:get_player_control().sneak
local sneak = user and user:get_player_control().sneak
local objpos = {}
for _, rel in ipairs(volume) do
local p = vector.add(pos, rel)
local n = minetest.get_node(p)
local allow = (rel.d > 0 or nil) and check(p, n, rel)
if allow == false then break end
if allow and ((not sneak) or matching(pos, node, p, n)) then
minetest.node_dig(p, n, user, ...)
objpos[minetest.hash_node_position(p)] = true
if not (nodecore.machine_digging
and vector.equals(nodecore.machine_digging.toolpos, p)) then
local n = minetest.get_node(p)
local allow = (rel.d > 0 or nil) and check(p, n, rel)
if allow == false then break end
if allow and ((not sneak) or matching(pos, node, p, n)) then
minetest.node_dig(p, n, user, ...)
objpos[minetest.hash_node_position(p)] = true
end
end
end
for _, lua in pairs(minetest.luaentities) do
@ -114,11 +119,12 @@ nodecore.register_on_dignode("rake handling", function(pos, node, user, ...)
if not nowraking then return end
lastraking = nil
if not (pos and node and user and user:is_player()) then return end
if not (pos and node) then return end
local volume, check = nowraking(pos, node, user, ...)
if not (volume and check) then return end
local pname = user:get_player_name()
local pname = user and user:is_player()
and user:get_player_name() or nowraking
if rakelock[pname] then return end
rakelock[pname] = true
deferfall(dorake, volume, check, pos, node, user, ...)

View File

@ -48,7 +48,8 @@ local function checktarget(data, stack)
and nodecore.tool_digs(stack, def.groups) then
data.pressdig = {
pos = target,
tool = stack
tool = stack,
toolpos = data.pointed.under
}
return true
end
@ -105,6 +106,7 @@ local function doitemeject(pos, data)
toolfx(pos, data.presstarget)
nodecore.machine_digging = data.pressdig
minetest.dig_node(data.pressdig.pos)
nodecore.machine_digging = nil
nodecore.witness(pos, "door dig")
return
end