summaryrefslogtreecommitdiff
path: root/digilines_inventory/chest.lua
blob: c7a0ea808d04d1ccadf364e1f7eea0c07e639b98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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)