diff --git a/init.lua b/init.lua index 93c94e9..3f15b61 100644 --- a/init.lua +++ b/init.lua @@ -64,11 +64,6 @@ minetest.register_craft({ } }) --- For minetest 0.4 support returned nil are also tested: ~= false -if minetest.settings:get_bool("digilines_enable_inventory", true) ~= false then - dofile(modpath .. "/inventory.lua") -end - if minetest.settings:get_bool("digilines_enable_lcd", true) ~= false then dofile(modpath .. "/lcd.lua") end diff --git a/inventory.lua b/inventory.lua deleted file mode 100644 index 9412e99..0000000 --- a/inventory.lua +++ /dev/null @@ -1,411 +0,0 @@ -local pipeworks_enabled = minetest.get_modpath("pipeworks") ~= nil - --- Sends a message onto the Digilines network. --- pos: the position of the Digilines chest node. --- action: the action string indicating what happened. --- stack: the ItemStack that the action acted on (optional). --- from_slot: the slot number that is taken from (optional). --- to_slot: the slot number that is put into (optional). --- side: which side of the chest the action occurred (optional). -local function send_message(pos, action, stack, from_slot, to_slot, side) - local channel = minetest.get_meta(pos):get_string("channel") - local msg = { - action = action, - stack = stack and stack:to_table(), - from_slot = from_slot, - to_slot = to_slot, - -- Duplicate the vector in case the caller expects it not to change. - side = side and vector.new(side) - } - digilines.receptor_send(pos, digilines.rules.default, channel, msg) -end - --- Checks if the inventory has become empty and, if so, sends an empty message. -local function check_empty(pos) - if minetest.get_meta(pos):get_inventory():is_empty("main") then - send_message(pos, "empty") - end -end - --- Checks if the inventory has become full for a particular type of item and, --- if so, sends a full message. -local function check_full(pos, stack) - local one_item_stack = ItemStack(stack) - one_item_stack:set_count(1) - if not minetest.get_meta(pos):get_inventory():room_for_item("main", one_item_stack) then - send_message(pos, "full", one_item_stack) - end -end - -local tubeconn = pipeworks_enabled and "^pipeworks_tube_connection_wooden.png" or "" -local tubescan = pipeworks_enabled and function(pos) pipeworks.scan_for_tube_objects(pos) end or nil - --- A place to remember things from allow_metadata_inventory_put to --- on_metadata_inventory_put. This is a hack due to issue --- minetest/minetest#6534 that should be removed once that’s fixed. -local last_inventory_put_index -local last_inventory_put_stack - --- A place to remember things from allow_metadata_inventory_take to --- tube.remove_items. This is a hack due to issue minetest-mods/pipeworks#205 --- 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", - 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 = 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. - -- Combining it with count gives the stack that is pulled out. - -- Also, note that Pipeworks doesn’t pass the index to this - -- function, so we use the one recorded in - -- allow_metadata_inventory_take; because we don’t implement - -- tube.can_remove, Pipeworks will call - -- allow_metadata_inventory_take instead and will pass it the - -- index. - local taken = stack:take_item(count) - minetest.get_meta(pos):get_inventory():set_stack("main", last_inventory_take_index, stack) - send_message(pos, "ttake", taken, last_inventory_take_index, nil, dir) - check_empty(pos) - return taken - end, - }, - allow_metadata_inventory_put = function(pos, _, index, stack) - -- Remember what was in the target slot before the put; see - -- on_metadata_inventory_put for why we care. - last_inventory_put_index = index - last_inventory_put_stack = minetest.get_meta(pos):get_inventory():get_stack("main", index) - return stack:get_count() - end, - allow_metadata_inventory_take = function(_, _, index, stack) - -- Remember the index value; see tube.remove_items for why we care. - last_inventory_take_index = index - return stack:get_count() - end, - on_metadata_inventory_move = function(pos, _, from_index, _, to_index, count, player) - -- See what would happen if we were to move the items back from in the - -- opposite direction. In the event of a normal move, this must - -- succeed, because a normal move subtracts some items from the from - -- stack and adds them to the to stack; the two stacks naturally must - -- be compatible and so the reverse operation must succeed. However, if - -- the user *swaps* the two stacks instead, then due to issue - -- minetest/minetest#6534, this function is only called once; however, - -- when it is called, the stack that used to be in the to stack has - -- already been moved to the from stack, so we can detect the situation - -- by the fact that the reverse move will fail due to the from stack - -- being incompatible with its former contents. - local inv = minetest.get_meta(pos):get_inventory() - local from_stack = inv:get_stack("main", from_index) - local to_stack = inv:get_stack("main", to_index) - local reverse_move_stack = ItemStack(to_stack) - reverse_move_stack:set_count(count) - local swapped = from_stack:add_item(reverse_move_stack):get_count() == count - if swapped then - local channel = minetest.get_meta(pos):get_string("channel") - to_stack:set_count(count) - local msg = { - action = "uswap", - -- The slot and stack do not match because this function is - -- called after the action has taken place, but the Digilines - -- message is from the perspective of a viewer who hasn’t - -- observed the movement yet. - x_stack = to_stack:to_table(), - x_slot = from_index, - y_stack = from_stack:to_table(), - y_slot = to_index, - } - digilines.receptor_send(pos, digilines.rules.default, channel, msg) - else - to_stack:set_count(count) - send_message(pos, "umove", to_stack, from_index, to_index) - end - minetest.log("action", player:get_player_name().." moves stuff in chest at "..minetest.pos_to_string(pos)) - end, - on_metadata_inventory_put = function(pos, _, index, stack, player) - -- Get what was in the target slot before the put; it has disappeared - -- by now (been replaced by the result of the put action) but we saved - -- it in allow_metadata_inventory_put. This should always work - -- (allow_metadata_inventory_put should AFAICT always be called - -- immediately before on_metadata_inventory_put), but in case of - -- something weird happening, just fall back to using an empty - -- ItemStack rather than crashing. - local old_stack - if last_inventory_put_index == index then - old_stack = last_inventory_put_stack - last_inventory_put_index = nil - last_inventory_put_stack = nil - else - old_stack = ItemStack(nil) - end - -- If the player tries to place a stack into an inventory, there’s - -- already a stack there, and the existing stack is either of a - -- different item type or full, then obviously the stacks can’t be - -- merged; instead the stacks are swapped. This information is not - -- reported to mods (Minetest core neither tells us that a particular - -- action was a swap, nor tells us a take followed by a put). In core, - -- the condition for swapping is that you try to add the new stack to - -- the existing stack and the leftovers are as big as the original - -- stack to put. Replicate that logic here using the old stack saved in - -- allow_metadata_inventory_put. If a swap happened, report it to the - -- Digilines network as a utake followed by a uput. - local leftovers = old_stack:add_item(stack) - if leftovers:get_count() == stack:get_count() then - send_message(pos, "utake", old_stack, index) - end - send_message(pos, "uput", stack, nil, index) - check_full(pos, stack) - minetest.log("action", player:get_player_name().." puts stuff into chest at "..minetest.pos_to_string(pos)) - end, - on_metadata_inventory_take = function(pos, _, index, stack, player) - send_message(pos, "utake", stack, index) - check_empty(pos) - minetest.log("action", player:get_player_name().." takes stuff from chest at "..minetest.pos_to_string(pos)) - 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", - recipe = {"default:chest", "digilines:wire_std_00000000"} -}) diff --git a/mod.conf b/mod.conf index bfc83a5..ed1a543 100644 --- a/mod.conf +++ b/mod.conf @@ -1,5 +1,4 @@ name = digilines -depends = default optional_depends = tubelib,tubelib2 description = """ This mod adds digiline wires, an RTC (Real Time Clock), a light sensor as well as an LCD Screen.