forked from Mirrorlandia_minetest/digilines
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:
parent
a055b5045a
commit
f03cd02854
@ -12,4 +12,6 @@ read_globals = {
|
|||||||
|
|
||||||
globals = {
|
globals = {
|
||||||
"digilines",
|
"digilines",
|
||||||
|
"tubelib",
|
||||||
|
"tubelib2"
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,9 @@ overflow <itemstack> <count>
|
|||||||
Tricky situation:
|
Tricky situation:
|
||||||
if you have a blank spot and put say 82 torches down your pipeline, followed by 99 coal, the 82 torches will go in the chest, and the chest will see that 1 more torch can fit since that would only go to 83. Since 1 more torch can fit, no "full" message will fire off. Then when the coal hits the chest, the "fail" message will fire and the coal will bounce out. The chest couldn't predict that coal would be coming next, so it couldn't know that the chest is full, for coal, while not full for torches.
|
if you have a blank spot and put say 82 torches down your pipeline, followed by 99 coal, the 82 torches will go in the chest, and the chest will see that 1 more torch can fit since that would only go to 83. Since 1 more torch can fit, no "full" message will fire off. Then when the coal hits the chest, the "fail" message will fire and the coal will bounce out. The chest couldn't predict that coal would be coming next, so it couldn't know that the chest is full, for coal, while not full for torches.
|
||||||
|
|
||||||
|
The inventory is also compatible with [`tubelib`](https://github.com/joe7575/techpack/tree/master/tubelib), which generally works in the same way as [`pipeworks`](https://gitlab.com/VanessaE/pipeworks) but transfers happen immediately and do not "bounce". This means that the messages should be identical to the messages sent by [`pipeworks`](https://gitlab.com/VanessaE/pipeworks), except that items will not send the "lost" message when they cannot fit.
|
||||||
|
One oddity is that "take" messages will be asynchronous because, if an item does not fit in the chest, the event will need to be canceled. This means that it is possible (though highly unlikely) to recieve a "put" message into a slot which you have not yet recieved a "take" message for, there will not actually be two stacks in the same slot, though it may briefly appear that way until the "take" message is recieved.
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
- make chest.lua a mixin that gets both default and locked chests
|
- make chest.lua a mixin that gets both default and locked chests
|
||||||
- digiline aware furnaces
|
- digiline aware furnaces
|
||||||
|
216
inventory.lua
216
inventory.lua
@ -51,65 +51,7 @@ local last_inventory_put_stack
|
|||||||
-- that should be removed once that’s fixed.
|
-- that should be removed once that’s fixed.
|
||||||
local last_inventory_take_index
|
local last_inventory_take_index
|
||||||
|
|
||||||
minetest.register_alias("digilines_inventory:chest", "digilines:chest")
|
local tube_can_insert = function(pos, _, stack, direction)
|
||||||
minetest.register_node("digilines:chest", {
|
|
||||||
description = "Digiline Chest",
|
|
||||||
tiles = {
|
|
||||||
"default_chest_top.png"..tubeconn,
|
|
||||||
"default_chest_top.png"..tubeconn,
|
|
||||||
"default_chest_side.png"..tubeconn,
|
|
||||||
"default_chest_side.png"..tubeconn,
|
|
||||||
"default_chest_side.png"..tubeconn,
|
|
||||||
"default_chest_front.png",
|
|
||||||
},
|
|
||||||
paramtype2 = "facedir",
|
|
||||||
legacy_facedir_simple = true,
|
|
||||||
groups = {choppy=2, oddly_breakable_by_hand=2, tubedevice=1, tubedevice_receiver=1},
|
|
||||||
sounds = default.node_sound_wood_defaults(),
|
|
||||||
on_construct = function(pos)
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
meta:set_string("infotext", "Digiline Chest")
|
|
||||||
meta:set_string("formspec", "size[8,10]"..
|
|
||||||
((default and default.gui_bg) or "")..
|
|
||||||
((default and default.gui_bg_img) or "")..
|
|
||||||
((default and default.gui_slots) or "")..
|
|
||||||
"label[0,0;Digiline Chest]"..
|
|
||||||
"list[current_name;main;0,1;8,4;]"..
|
|
||||||
"field[2,5.5;5,1;channel;Channel;${channel}]"..
|
|
||||||
((default and default.get_hotbar_bg) and default.get_hotbar_bg(0,6) or "")..
|
|
||||||
"list[current_player;main;0,6;8,4;]"..
|
|
||||||
"listring[]")
|
|
||||||
local inv = meta:get_inventory()
|
|
||||||
inv:set_size("main", 8*4)
|
|
||||||
end,
|
|
||||||
after_place_node = tubescan,
|
|
||||||
after_dig_node = tubescan,
|
|
||||||
can_dig = function(pos)
|
|
||||||
return minetest.get_meta(pos):get_inventory():is_empty("main")
|
|
||||||
end,
|
|
||||||
on_receive_fields = function(pos, _, fields, sender)
|
|
||||||
local name = sender:get_player_name()
|
|
||||||
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
||||||
minetest.record_protection_violation(pos, name)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if fields.channel ~= nil then
|
|
||||||
minetest.get_meta(pos):set_string("channel",fields.channel)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
digilines = {
|
|
||||||
receptor = {},
|
|
||||||
effector = {
|
|
||||||
action = function() end
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tube = {
|
|
||||||
connect_sides = {left=1, right=1, back=1, front=1, bottom=1, top=1},
|
|
||||||
connects = function(i,param2)
|
|
||||||
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)
|
local ret = minetest.get_meta(pos):get_inventory():room_for_item("main", stack)
|
||||||
if not ret then
|
if not ret then
|
||||||
-- The stack cannot be accepted. It will never be passed to
|
-- The stack cannot be accepted. It will never be passed to
|
||||||
@ -120,8 +62,9 @@ minetest.register_node("digilines:chest", {
|
|||||||
send_message(pos, "toverflow", stack, nil, nil, side)
|
send_message(pos, "toverflow", stack, nil, nil, side)
|
||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
end,
|
end
|
||||||
insert_object = function(pos, _, original_stack, direction)
|
|
||||||
|
local tube_insert_object = function(pos, _, original_stack, direction)
|
||||||
-- Here, direction = direction item is moving, which is into side.
|
-- Here, direction = direction item is moving, which is into side.
|
||||||
local side = vector.multiply(direction, -1)
|
local side = vector.multiply(direction, -1)
|
||||||
local inv = minetest.get_meta(pos):get_inventory()
|
local inv = minetest.get_meta(pos):get_inventory()
|
||||||
@ -199,7 +142,68 @@ minetest.register_node("digilines:chest", {
|
|||||||
send_message(pos, "toverflow", stack, nil, nil, side)
|
send_message(pos, "toverflow", stack, nil, nil, side)
|
||||||
end
|
end
|
||||||
return stack
|
return stack
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_alias("digilines_inventory:chest", "digilines:chest")
|
||||||
|
minetest.register_node("digilines:chest", {
|
||||||
|
description = "Digiline Chest",
|
||||||
|
tiles = {
|
||||||
|
"default_chest_top.png"..tubeconn,
|
||||||
|
"default_chest_top.png"..tubeconn,
|
||||||
|
"default_chest_side.png"..tubeconn,
|
||||||
|
"default_chest_side.png"..tubeconn,
|
||||||
|
"default_chest_side.png"..tubeconn,
|
||||||
|
"default_chest_front.png",
|
||||||
|
},
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
legacy_facedir_simple = true,
|
||||||
|
groups = {choppy=2, oddly_breakable_by_hand=2, tubedevice=1, tubedevice_receiver=1},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
on_construct = function(pos)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
meta:set_string("infotext", "Digiline Chest")
|
||||||
|
meta:set_string("formspec", "size[8,10]"..
|
||||||
|
((default and default.gui_bg) or "")..
|
||||||
|
((default and default.gui_bg_img) or "")..
|
||||||
|
((default and default.gui_slots) or "")..
|
||||||
|
"label[0,0;Digiline Chest]"..
|
||||||
|
"list[current_name;main;0,1;8,4;]"..
|
||||||
|
"field[2,5.5;5,1;channel;Channel;${channel}]"..
|
||||||
|
((default and default.get_hotbar_bg) and default.get_hotbar_bg(0,6) or "")..
|
||||||
|
"list[current_player;main;0,6;8,4;]"..
|
||||||
|
"listring[]")
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
inv:set_size("main", 8*4)
|
||||||
end,
|
end,
|
||||||
|
after_place_node = tubescan,
|
||||||
|
after_dig_node = tubescan,
|
||||||
|
can_dig = function(pos)
|
||||||
|
return minetest.get_meta(pos):get_inventory():is_empty("main")
|
||||||
|
end,
|
||||||
|
on_receive_fields = function(pos, _, fields, sender)
|
||||||
|
local name = sender:get_player_name()
|
||||||
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
||||||
|
minetest.record_protection_violation(pos, name)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if fields.channel ~= nil then
|
||||||
|
minetest.get_meta(pos):set_string("channel",fields.channel)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
digilines = {
|
||||||
|
receptor = {},
|
||||||
|
effector = {
|
||||||
|
action = function() end
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tube = {
|
||||||
|
connect_sides = {left=1, right=1, back=1, front=1, bottom=1, top=1},
|
||||||
|
connects = function(i,param2)
|
||||||
|
return not pipeworks.connects.facingFront(i,param2)
|
||||||
|
end,
|
||||||
|
input_inventory = "main",
|
||||||
|
can_insert = tube_can_insert,
|
||||||
|
insert_object = tube_insert_object,
|
||||||
remove_items = function(pos, _, stack, dir, count)
|
remove_items = function(pos, _, stack, dir, count)
|
||||||
-- Here, stack is the ItemStack in our own inventory that is being
|
-- Here, stack is the ItemStack in our own inventory that is being
|
||||||
-- pulled from, NOT the stack that is actually pulled out.
|
-- pulled from, NOT the stack that is actually pulled out.
|
||||||
@ -310,6 +314,96 @@ minetest.register_node("digilines:chest", {
|
|||||||
end
|
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({
|
minetest.register_craft({
|
||||||
type = "shapeless",
|
type = "shapeless",
|
||||||
output = "digilines:chest",
|
output = "digilines:chest",
|
||||||
|
1
mod.conf
1
mod.conf
@ -1,5 +1,6 @@
|
|||||||
name = digilines
|
name = digilines
|
||||||
depends = default
|
depends = default
|
||||||
|
optional_depends = tubelib,tubelib2
|
||||||
description = """
|
description = """
|
||||||
This mod adds digiline wires, an RTC (Real Time Clock), a light sensor as well as an LCD Screen.
|
This mod adds digiline wires, an RTC (Real Time Clock), a light sensor as well as an LCD Screen.
|
||||||
Can be used together with the luacontroller from mesecons.
|
Can be used together with the luacontroller from mesecons.
|
||||||
|
Loading…
Reference in New Issue
Block a user