mirror of
https://github.com/minetest-mods/digilines.git
synced 2025-06-30 15:30:22 +02:00
Send messages from digiline chest when items are moved with tubelib (#73)
Sends the same events from tubelib interaction as would be sent from pipeworks * Moved the tube_can_insert and tube_insert_object callbacks out of the node definition so they can be re-used in the tubelib registration * Optionally required tubelib and registered callbacks for pushing and pulling * Used "speculative pull" variable to only send a "take" event if tubelib's unpull is not called after a pull - this happens when it tries to take an item but there is no room, so it fails
This commit is contained in:
276
inventory.lua
276
inventory.lua
@ -51,6 +51,99 @@ local last_inventory_put_stack
|
||||
-- that should be removed once that’s fixed.
|
||||
local last_inventory_take_index
|
||||
|
||||
local tube_can_insert = function(pos, _, stack, direction)
|
||||
local ret = minetest.get_meta(pos):get_inventory():room_for_item("main", stack)
|
||||
if not ret then
|
||||
-- The stack cannot be accepted. It will never be passed to
|
||||
-- insert_object, but it should be reported as a toverflow.
|
||||
-- Here, direction = direction item is moving, which is into
|
||||
-- side.
|
||||
local side = vector.multiply(direction, -1)
|
||||
send_message(pos, "toverflow", stack, nil, nil, side)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local tube_insert_object = function(pos, _, original_stack, direction)
|
||||
-- Here, direction = direction item is moving, which is into side.
|
||||
local side = vector.multiply(direction, -1)
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
local inv_contents = inv:get_list("main")
|
||||
local any_put = false
|
||||
local stack = original_stack
|
||||
local stack_name = stack:get_name()
|
||||
local stack_count = stack:get_count()
|
||||
-- Walk the inventory, adding items to existing stacks of the same
|
||||
-- type.
|
||||
for i = 1, #inv_contents do
|
||||
local existing_stack = inv_contents[i]
|
||||
if not existing_stack:is_empty() and existing_stack:get_name() == stack_name then
|
||||
local leftover = existing_stack:add_item(stack)
|
||||
local leftover_count = leftover:get_count()
|
||||
if leftover_count ~= stack_count then
|
||||
-- We put some items into the slot. Update the slot in
|
||||
-- the inventory, tell Digilines listeners about it,
|
||||
-- and keep looking for the a place to put the
|
||||
-- leftovers if any.
|
||||
any_put = true
|
||||
inv:set_stack("main", i, existing_stack)
|
||||
local stack_that_was_put
|
||||
if leftover_count == 0 then
|
||||
stack_that_was_put = stack
|
||||
else
|
||||
stack_that_was_put = ItemStack(stack)
|
||||
stack_that_was_put:set_count(stack_count - leftover_count)
|
||||
end
|
||||
send_message(pos, "tput", stack_that_was_put, nil, i, side)
|
||||
stack = leftover
|
||||
stack_count = leftover_count
|
||||
if stack_count == 0 then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if stack_count ~= 0 then
|
||||
-- Walk the inventory, adding items to empty slots.
|
||||
for i = 1, #inv_contents do
|
||||
local existing_stack = inv_contents[i]
|
||||
if existing_stack:is_empty() then
|
||||
local leftover = existing_stack:add_item(stack)
|
||||
local leftover_count = leftover:get_count()
|
||||
if leftover_count ~= stack_count then
|
||||
-- We put some items into the slot. Update the slot in
|
||||
-- the inventory, tell Digilines listeners about it,
|
||||
-- and keep looking for the a place to put the
|
||||
-- leftovers if any.
|
||||
any_put = true
|
||||
inv:set_stack("main", i, existing_stack)
|
||||
local stack_that_was_put
|
||||
if leftover_count == 0 then
|
||||
stack_that_was_put = stack
|
||||
else
|
||||
stack_that_was_put = ItemStack(stack)
|
||||
stack_that_was_put:set_count(stack_count - leftover_count)
|
||||
end
|
||||
send_message(pos, "tput", stack_that_was_put, nil, i, side)
|
||||
stack = leftover
|
||||
stack_count = leftover_count
|
||||
if stack_count == 0 then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if any_put then
|
||||
check_full(pos, original_stack)
|
||||
end
|
||||
if stack_count ~= 0 then
|
||||
-- Some items could not be added and bounced back. Report them.
|
||||
send_message(pos, "toverflow", stack, nil, nil, side)
|
||||
end
|
||||
return stack
|
||||
end
|
||||
|
||||
minetest.register_alias("digilines_inventory:chest", "digilines:chest")
|
||||
minetest.register_node("digilines:chest", {
|
||||
description = "Digiline Chest",
|
||||
@ -109,97 +202,8 @@ minetest.register_node("digilines:chest", {
|
||||
return not pipeworks.connects.facingFront(i,param2)
|
||||
end,
|
||||
input_inventory = "main",
|
||||
can_insert = function(pos, _, stack, direction)
|
||||
local ret = minetest.get_meta(pos):get_inventory():room_for_item("main", stack)
|
||||
if not ret then
|
||||
-- The stack cannot be accepted. It will never be passed to
|
||||
-- insert_object, but it should be reported as a toverflow.
|
||||
-- Here, direction = direction item is moving, which is into
|
||||
-- side.
|
||||
local side = vector.multiply(direction, -1)
|
||||
send_message(pos, "toverflow", stack, nil, nil, side)
|
||||
end
|
||||
return ret
|
||||
end,
|
||||
insert_object = function(pos, _, original_stack, direction)
|
||||
-- Here, direction = direction item is moving, which is into side.
|
||||
local side = vector.multiply(direction, -1)
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
local inv_contents = inv:get_list("main")
|
||||
local any_put = false
|
||||
local stack = original_stack
|
||||
local stack_name = stack:get_name()
|
||||
local stack_count = stack:get_count()
|
||||
-- Walk the inventory, adding items to existing stacks of the same
|
||||
-- type.
|
||||
for i = 1, #inv_contents do
|
||||
local existing_stack = inv_contents[i]
|
||||
if not existing_stack:is_empty() and existing_stack:get_name() == stack_name then
|
||||
local leftover = existing_stack:add_item(stack)
|
||||
local leftover_count = leftover:get_count()
|
||||
if leftover_count ~= stack_count then
|
||||
-- We put some items into the slot. Update the slot in
|
||||
-- the inventory, tell Digilines listeners about it,
|
||||
-- and keep looking for the a place to put the
|
||||
-- leftovers if any.
|
||||
any_put = true
|
||||
inv:set_stack("main", i, existing_stack)
|
||||
local stack_that_was_put
|
||||
if leftover_count == 0 then
|
||||
stack_that_was_put = stack
|
||||
else
|
||||
stack_that_was_put = ItemStack(stack)
|
||||
stack_that_was_put:set_count(stack_count - leftover_count)
|
||||
end
|
||||
send_message(pos, "tput", stack_that_was_put, nil, i, side)
|
||||
stack = leftover
|
||||
stack_count = leftover_count
|
||||
if stack_count == 0 then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if stack_count ~= 0 then
|
||||
-- Walk the inventory, adding items to empty slots.
|
||||
for i = 1, #inv_contents do
|
||||
local existing_stack = inv_contents[i]
|
||||
if existing_stack:is_empty() then
|
||||
local leftover = existing_stack:add_item(stack)
|
||||
local leftover_count = leftover:get_count()
|
||||
if leftover_count ~= stack_count then
|
||||
-- We put some items into the slot. Update the slot in
|
||||
-- the inventory, tell Digilines listeners about it,
|
||||
-- and keep looking for the a place to put the
|
||||
-- leftovers if any.
|
||||
any_put = true
|
||||
inv:set_stack("main", i, existing_stack)
|
||||
local stack_that_was_put
|
||||
if leftover_count == 0 then
|
||||
stack_that_was_put = stack
|
||||
else
|
||||
stack_that_was_put = ItemStack(stack)
|
||||
stack_that_was_put:set_count(stack_count - leftover_count)
|
||||
end
|
||||
send_message(pos, "tput", stack_that_was_put, nil, i, side)
|
||||
stack = leftover
|
||||
stack_count = leftover_count
|
||||
if stack_count == 0 then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if any_put then
|
||||
check_full(pos, original_stack)
|
||||
end
|
||||
if stack_count ~= 0 then
|
||||
-- Some items could not be added and bounced back. Report them.
|
||||
send_message(pos, "toverflow", stack, nil, nil, side)
|
||||
end
|
||||
return stack
|
||||
end,
|
||||
can_insert = tube_can_insert,
|
||||
insert_object = tube_insert_object,
|
||||
remove_items = function(pos, _, stack, dir, count)
|
||||
-- Here, stack is the ItemStack in our own inventory that is being
|
||||
-- pulled from, NOT the stack that is actually pulled out.
|
||||
@ -310,6 +314,96 @@ minetest.register_node("digilines:chest", {
|
||||
end
|
||||
})
|
||||
|
||||
if minetest.global_exists("tubelib") then
|
||||
local speculative_pull = nil
|
||||
local pull_succeeded = function(passed_speculative_pull)
|
||||
if passed_speculative_pull.canceled then return end
|
||||
|
||||
send_message(passed_speculative_pull.pos, "ttake", passed_speculative_pull.taken,
|
||||
passed_speculative_pull.index, nil, vector.multiply(passed_speculative_pull.dir, -1))
|
||||
check_empty(passed_speculative_pull.pos)
|
||||
end
|
||||
local function tube_side(pos, side)
|
||||
if side == "U" then return {x=0,y=-1,z=0}
|
||||
elseif side == "D" then return {x=0,y=1,z=0}
|
||||
end
|
||||
local param2 = minetest.get_node(pos).param2
|
||||
return vector.multiply(
|
||||
minetest.facedir_to_dir(
|
||||
tubelib2.side_to_dir(side, param2) - 1),
|
||||
-1)
|
||||
end
|
||||
tubelib.register_node("digilines:chest", {}, {
|
||||
on_pull_stack = function(pos, side, _)
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
for i, stack in pairs(inv:get_list("main")) do
|
||||
if not stack:is_empty() then
|
||||
speculative_pull = {
|
||||
canceled = false,
|
||||
pos = pos,
|
||||
taken = stack,
|
||||
index = i,
|
||||
dir = tube_side(pos, side)
|
||||
}
|
||||
minetest.after(0, pull_succeeded, speculative_pull)
|
||||
inv:set_stack("main", i, nil)
|
||||
return stack
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
on_pull_item = function(pos, side, _)
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
for i, stack in pairs(inv:get_list("main")) do
|
||||
if not stack:is_empty() then
|
||||
local taken = stack:take_item(1)
|
||||
speculative_pull = {
|
||||
canceled = false,
|
||||
pos = pos,
|
||||
taken = taken,
|
||||
index = i,
|
||||
dir = tube_side(pos, side)
|
||||
}
|
||||
minetest.after(0, pull_succeeded, speculative_pull)
|
||||
inv:set_stack("main", i, stack)
|
||||
return taken
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
on_push_item = function(pos, side, item, _)
|
||||
local dir_vec = tube_side(pos, side)
|
||||
if not tube_can_insert(pos, nil, item, dir_vec) then
|
||||
return false
|
||||
end
|
||||
tube_insert_object(pos, nil, item, dir_vec)
|
||||
return true
|
||||
end,
|
||||
on_unpull_item = function(pos, _, item, _)
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
if not inv:room_for_item("main", item) then
|
||||
return false
|
||||
end
|
||||
|
||||
local existing_stack = inv:get_stack("main", speculative_pull.index)
|
||||
local leftover = existing_stack:add_item(item)
|
||||
if not leftover:is_empty() then
|
||||
return false
|
||||
end
|
||||
|
||||
inv:set_stack("main", speculative_pull.index, existing_stack)
|
||||
|
||||
-- Cancel speculative pull
|
||||
-- this on_unpull_item callback should be called
|
||||
-- immediately after on_pull_item if it fails
|
||||
-- so this should be procedural
|
||||
speculative_pull.canceled = true
|
||||
speculative_pull = nil
|
||||
return true
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "digilines:chest",
|
||||
|
Reference in New Issue
Block a user