diff --git a/digilines/util.lua b/digilines/util.lua index dad6579..9982257 100644 --- a/digilines/util.lua +++ b/digilines/util.lua @@ -50,3 +50,18 @@ function digiline:rotate_rules_up(rules) end return nr end + +function digiline:tablecopy(table) -- deep table copy + if type(table) ~= "table" then return table end -- no need to copy + local newtable = {} + + for idx, item in pairs(table) do + if type(item) == "table" then + newtable[idx] = mesecon:tablecopy(item) + else + newtable[idx] = item + end + end + + return newtable +end diff --git a/digilines_inventory/chest.lua b/digilines_inventory/chest.lua deleted file mode 100644 index c7a0ea8..0000000 --- a/digilines_inventory/chest.lua +++ /dev/null @@ -1,149 +0,0 @@ -local defaultChest = minetest.registered_nodes['default:chest'] - -if table.copy == nil then - -- http://lua-users.org/wiki/CopyTable - table.copy = function(orig) - local orig_type = type(orig) - local copy - if orig_type == 'table' then - copy = {} - for orig_key, orig_value in pairs(orig) do - copy[orig_key] = orig_value - end - else -- number, string, boolean, etc - copy = orig - end - return copy - end -end - -local sendMessage = function (pos, msg, channel) - if channel == nil then - channel = minetest.get_meta(pos):get_string("channel") - end - digiline:receptor_send(pos,digiline.rules.default,channel,msg) -end - -tableMerge = function(first_table,second_table) - if second_table == nil then return end - for k,v in pairs(second_table) do first_table[k] = v end -end - -tableMergeImmutable = function(first_table, second_table) - if first_table == nil then return second_table end - if second_table == nil then return first_table end - copy = table.copy(first_table) - for k,v in pairs(second_table) do copy[k] = v end - return copy -end - -local mychest = table.copy(defaultChest) - -function defer(what,...) - if what then - return what(...) - end -end - -function maybeString(stack) - if type(stack)=='string' then return stack - elseif type(stack)=='table' then return dump(stack) - else return stack:to_string() - end -end - -mychest = tableMergeImmutable(defaultChest,{ - description = "Digiline Chest", - digiline = { - receptor = {}, - effector = { - action = function(pos,node,channel,msg) end - } - }, - on_construct = function(pos) - defaultChest.on_construct(pos) - local meta = minetest.get_meta(pos) - -- we'll sneak into row 4 thanks - meta:set_string("formspec",meta:get_string("formspec").."\nfield[2,4.5;5,1;channel;Channel;${channel}]") - end, - on_receive_fields = function(pos, formname, fields, sender) - minetest.get_meta(pos):set_string("channel",fields.channel) - return defer(defaultChest.on_receive_fields, pos, formname, fields, sender) - end, - tube = tableMergeImmutable(defaultChest.tube, { - -- note: mese filters cannot put part of a stack in the destination. - -- space for 50 coal with 99 added will pop out 99, not 49. - connects = function(i,param2) - return not pipeworks.connects.facingFront(i,param2) - end, - insert_object = function(pos, node, stack, direction) - local leftover = defaultChest.tube.insert_object(pos,node,stack,direction) - local count = leftover:get_count() - if count == 0 then - local derpstack = stack:get_name()..' 1' - if not defaultChest.tube.can_insert(pos, node, derpstack, direction) then - -- when you can't put a single more of whatever you just put, - -- you'll get a put for it, then a full - sendMessage(pos,"full "..maybeString(stack)..' '..tostring(count)) - end - else - -- this happens when the chest has received two stacks in a row and - -- filled up exactly with the first one. - -- You get a put for the first stack, a put for the second - -- and then a overflow with the first in stack and the second in leftover - -- and NO full? - sendMessage(pos,"overflow "..maybeString(stack)..' '..tostring(count)) - end - return leftover - end, - can_insert = function(pos, node, stack, direction) - local can = defaultChest.tube.can_insert(pos, node, stack, direction) - if can then - sendMessage(pos,"put "..maybeString(stack)) - else - -- overflow and lost means that items are gonna be out as entities :/ - sendMessage(pos,"lost "..maybeString(stack)) - end - return can - end, - }), - allow_metadata_inventory_put = function(pos, listname, index, stack, player) - if not mychest.tube.can_insert(pos,nil,stack,nil) then - sendMessage(pos,"uoverflow "..maybeString(stack)) - end - local ret = defer(defaultChest.allow_metadata_inventory_put, pos, listname, index, stack, player) - if ret then return ret end - return stack:get_count() - end, - on_metadata_inventory_put = function(pos, listname, index, stack, player) - local channel = minetest.get_meta(pos):get_string("channel") - local send = function(msg) - sendMessage(pos,msg,channel) - end - -- direction is only for furnaces - -- as the item has already been put, can_insert should return false if the chest is now full. - local derpstack = stack:get_name()..' 1' - if mychest.tube.can_insert(pos,nil,derpstack,nil) then - send("uput "..maybeString(stack)) - else - send("ufull "..maybeString(stack)) - end - return defer(defaultChest.on_metadata_inventory_put, pos, listname, index, stack, player) - end, - on_metadata_inventory_take = function(pos, listname, index, stack, player) - sendMessage(pos,"utake "..maybeString(stack)) - return defaultChest.on_metadata_inventory_take(pos, listname, index, stack, player) - end -}) - -if mychest.tube.can_insert == nil then - -- we can use the can_insert function from pipeworks, but will duplicate if not found. - mychest.tube.can_insert = function(pos,node,stack,direction) - local meta=minetest.get_meta(pos) - local inv=meta:get_inventory() - return inv:room_for_item("main",stack) - end -end - --- minetest.register_node(":default:chest", mychest) -minetest.register_node("digilines_inventory:chest", mychest) diff --git a/digilines_inventory/depends.txt b/digilines_inventory/depends.txt index de5f01d..da1d119 100644 --- a/digilines_inventory/depends.txt +++ b/digilines_inventory/depends.txt @@ -1,3 +1 @@ digilines -require -pipeworks? diff --git a/digilines_inventory/init.lua b/digilines_inventory/init.lua index 5a2e96d..d40f7e6 100644 --- a/digilines_inventory/init.lua +++ b/digilines_inventory/init.lua @@ -1,6 +1,137 @@ -value, err = minetest.require('digilines_inventory','chest') -if err then - error(err) +if not minetest.get_modpath("pipeworks") then + print("[Digilines] Install pipeworks if you want to use the digilines chest") + return end -print("Digilines Inventory loaded") +local defaultChest = minetest.registered_nodes['default:chest'] + +local sendMessage = function (pos, msg, channel) + if channel == nil then + channel = minetest.get_meta(pos):get_string("channel") + end + digiline:receptor_send(pos,digiline.rules.default,channel,msg) +end + +tableMerge = function(first_table,second_table) + if second_table == nil then return end + for k,v in pairs(second_table) do first_table[k] = v end +end + +tableMergeImmutable = function(first_table, second_table) + if first_table == nil then return second_table end + if second_table == nil then return first_table end + copy = digiline:tablecopy(first_table) + for k,v in pairs(second_table) do copy[k] = v end + return copy +end + +local mychest = digiline:tablecopy(defaultChest) + +function defer(what,...) + if what then + return what(...) + end +end + +function maybeString(stack) + if type(stack)=='string' then return stack + elseif type(stack)=='table' then return dump(stack) + else return stack:to_string() + end +end + +mychest = tableMergeImmutable(defaultChest,{ + description = "Digiline Chest", + digiline = { + receptor = {}, + effector = { + action = function(pos,node,channel,msg) end + } + }, + on_construct = function(pos) + defaultChest.on_construct(pos) + local meta = minetest.get_meta(pos) + -- we'll sneak into row 4 thanks + meta:set_string("formspec",meta:get_string("formspec").."\nfield[2,4.5;5,1;channel;Channel;${channel}]") + end, + on_receive_fields = function(pos, formname, fields, sender) + minetest.get_meta(pos):set_string("channel",fields.channel) + return defer(defaultChest.on_receive_fields, pos, formname, fields, sender) + end, + tube = tableMergeImmutable(defaultChest.tube, { + -- note: mese filters cannot put part of a stack in the destination. + -- space for 50 coal with 99 added will pop out 99, not 49. + connects = function(i,param2) + return not pipeworks.connects.facingFront(i,param2) + end, + insert_object = function(pos, node, stack, direction) + local leftover = defaultChest.tube.insert_object(pos,node,stack,direction) + local count = leftover:get_count() + if count == 0 then + local derpstack = stack:get_name()..' 1' + if not defaultChest.tube.can_insert(pos, node, derpstack, direction) then + -- when you can't put a single more of whatever you just put, + -- you'll get a put for it, then a full + sendMessage(pos,"full "..maybeString(stack)..' '..tostring(count)) + end + else + -- this happens when the chest has received two stacks in a row and + -- filled up exactly with the first one. + -- You get a put for the first stack, a put for the second + -- and then a overflow with the first in stack and the second in leftover + -- and NO full? + sendMessage(pos,"overflow "..maybeString(stack)..' '..tostring(count)) + end + return leftover + end, + can_insert = function(pos, node, stack, direction) + local can = defaultChest.tube.can_insert(pos, node, stack, direction) + if can then + sendMessage(pos,"put "..maybeString(stack)) + else + -- overflow and lost means that items are gonna be out as entities :/ + sendMessage(pos,"lost "..maybeString(stack)) + end + return can + end, + }), + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + if not mychest.tube.can_insert(pos,nil,stack,nil) then + sendMessage(pos,"uoverflow "..maybeString(stack)) + end + local ret = defer(defaultChest.allow_metadata_inventory_put, pos, listname, index, stack, player) + if ret then return ret end + return stack:get_count() + end, + on_metadata_inventory_put = function(pos, listname, index, stack, player) + local channel = minetest.get_meta(pos):get_string("channel") + local send = function(msg) + sendMessage(pos,msg,channel) + end + -- direction is only for furnaces + -- as the item has already been put, can_insert should return false if the chest is now full. + local derpstack = stack:get_name()..' 1' + if mychest.tube.can_insert(pos,nil,derpstack,nil) then + send("uput "..maybeString(stack)) + else + send("ufull "..maybeString(stack)) + end + return defer(defaultChest.on_metadata_inventory_put, pos, listname, index, stack, player) + end, + on_metadata_inventory_take = function(pos, listname, index, stack, player) + sendMessage(pos,"utake "..maybeString(stack)) + return defaultChest.on_metadata_inventory_take(pos, listname, index, stack, player) + end +}) + +if mychest.tube.can_insert == nil then + -- we can use the can_insert function from pipeworks, but will duplicate if not found. + mychest.tube.can_insert = function(pos,node,stack,direction) + local meta=minetest.get_meta(pos) + local inv=meta:get_inventory() + return inv:room_for_item("main",stack) + end +end + +-- minetest.register_node(":default:chest", mychest) +minetest.register_node("digilines_inventory:chest", mychest)