auouymous
2020-09-09 d7336670f2bdc69c343ddac76b6e2d2e64f930c0
commit | author | age
41a10a 1 local S = rawget(_G, "intllib") and intllib.Getter() or function(s) return s end
179364 2
fcef0e 3 local pipeworks = rawget(_G, "pipeworks")
11f20d 4 local fs_helpers = rawget(_G, "fs_helpers")
8a987b 5 local tubelib_exists = minetest.global_exists("tubelib")
11f20d 6
VE 7 local allow_label = ""
b6d343 8 local tube_entry = ""
11f20d 9 local shift_edit_field = 0
VE 10
fcef0e 11 if not minetest.get_modpath("pipeworks") then
R 12     -- Pipeworks is not installed. Simulate using a dummy table...
13     pipeworks = {}
11f20d 14     fs_helpers = {}
fcef0e 15     local pipeworks_meta = {}
R 16     setmetatable(pipeworks, pipeworks_meta)
17     local dummy = function()
18         end
19     pipeworks_meta.__index = function(table, key)
20             print("[technic_chests] WARNING: variable or method '"..key.."' not present in dummy pipeworks table - assuming it is a method...")
21             pipeworks[key] = dummy
22             return dummy
23         end
24     pipeworks.after_place = dummy
25     pipeworks.after_dig = dummy
11f20d 26     fs_helpers.cycling_button = function() return "" end
VE 27 else
28     fs_helpers = pipeworks.fs_helpers
29     allow_label = "label[0.9,0.36;Allow splitting incoming stacks from tubes]"
30     shift_edit_field = 3
b6d343 31     tube_entry = "^pipeworks_tube_connection_metallic.png"
fcef0e 32 end
R 33
78cacd 34 local chest_mark_colors = {
179364 35     {"black", S("Black")},
S 36     {"blue", S("Blue")},
37     {"brown", S("Brown")},
39c41a 38     {"cyan", S("Cyan")},
179364 39     {"dark_green", S("Dark Green")},
S 40     {"dark_grey", S("Dark Grey")},
41     {"green", S("Green")},
42     {"grey", S("Grey")},
43     {"magenta", S("Magenta")},
44     {"orange", S("Orange")},
45     {"pink", S("Pink")},
46     {"red", S("Red")},
47     {"violet", S("Violet")},
48     {"white", S("White")},
49     {"yellow", S("Yellow")},
78cacd 50 }
S 51
52
53 local function colorid_to_postfix(id)
179364 54     return chest_mark_colors[id] and "_"..chest_mark_colors[id][1] or ""
78cacd 55 end
S 56
57
1bf52c 58 local function get_color_buttons(coleft, lotop)
78cacd 59     local buttons_string = ""
S 60     for y = 0, 3 do
61         for x = 0, 3 do
62             local file_name = "technic_colorbutton"..(y * 4 + x)..".png"
63             buttons_string = buttons_string.."image_button["
1bf52c 64                 ..(coleft + 0.1 + x * 0.7)..","..(lotop + 0.1 + y * 0.7)
78cacd 65                 ..";0.8,0.8;"..file_name..";color_button"
S 66                 ..(y * 4 + x + 1)..";]"
67         end
68     end
69     return buttons_string
70 end
71
72
73 local function check_color_buttons(pos, meta, chest_name, fields)
74     for i = 1, 16 do
75         if fields["color_button"..i] then
d60e3f 76             local node = minetest.get_node(pos)
Z 77             node.name = chest_name..colorid_to_postfix(i)
78             minetest.swap_node(pos, node)
179364 79             meta:set_string("color", i)
78cacd 80             return
S 81         end
82     end
83 end
84
5c689a 85 local function set_formspec(pos, data, page)
R 86     local meta = minetest.get_meta(pos)
1bf52c 87     local formspec = data.base_formspec
11f20d 88     formspec = formspec..fs_helpers.cycling_button(
VE 89                 meta,
90                 "image_button[0,0.35;1,0.6",
91                 "splitstacks",
92                 {
fab2c4 93                     pipeworks.button_off,
d2fb24 94                     pipeworks.button_on
11f20d 95                 }
VE 96             )..allow_label
97
5c689a 98     if data.autosort then
R 99         local status = meta:get_int("autosort")
1bf52c 100         formspec = formspec.."button["..(data.hileft+2)..","..(data.height+1.1)..";3,0.8;autosort_to_"..(1-status)..";"..S("Auto-sort is %s"):format(status == 1 and S("On") or S("Off")).."]"
78cacd 101     end
5c689a 102     if data.infotext then
78cacd 103         local formspec_infotext = minetest.formspec_escape(meta:get_string("infotext"))
5c689a 104         if page == "main" then
11f20d 105             formspec = formspec.."image_button["..(shift_edit_field+data.hileft+2.1)..",0.1;0.8,0.8;"
78cacd 106                     .."technic_pencil_icon.png;edit_infotext;]"
11f20d 107                     .."label["..(shift_edit_field+data.hileft+3)..",0;"..formspec_infotext.."]"
5c689a 108         elseif page == "edit_infotext" then
11f20d 109             formspec = formspec.."image_button["..(shift_edit_field+data.hileft+2.1)..",0.1;0.8,0.8;"
78cacd 110                     .."technic_checkmark_icon.png;save_infotext;]"
11f20d 111                     .."field["..(shift_edit_field+data.hileft+3.3)..",0.2;4.8,1;"
179364 112                     .."infotext_box;"..S("Edit chest description:")..";"
78cacd 113                     ..formspec_infotext.."]"
S 114         end
5c689a 115     end
R 116     if data.color then
117         local colorID = meta:get_int("color")
118         local colorName
119         if chest_mark_colors[colorID] then
120             colorName = chest_mark_colors[colorID][2]
121         else
122             colorName = S("None")
123         end
1bf52c 124         formspec = formspec.."label["..(data.coleft+0.2)..","..(data.lotop+3)..";"..S("Color Filter: %s"):format(colorName).."]"
5c689a 125     end
R 126     meta:set_string("formspec", formspec)
127 end
128
129 local function sort_inventory(inv)
130     local inlist = inv:get_list("main")
131     local typecnt = {}
132     local typekeys = {}
133     for _, st in ipairs(inlist) do
134         if not st:is_empty() then
135             local n = st:get_name()
136             local w = st:get_wear()
137             local m = st:get_metadata()
138             local k = string.format("%s %05d %s", n, w, m)
139             if not typecnt[k] then
930c51 140                 typecnt[k] = {st}
5c689a 141                 table.insert(typekeys, k)
930c51 142             else
D 143                 table.insert(typecnt[k], st)
5c689a 144             end
R 145         end
146     end
147     table.sort(typekeys)
930c51 148     inv:set_list("main", {})
5c689a 149     for _, k in ipairs(typekeys) do
930c51 150         for _, item in ipairs(typecnt[k]) do
D 151             inv:add_item("main", item)
5c689a 152         end
R 153     end
154 end
155
156 local function get_receive_fields(name, data)
157     local lname = name:lower()
158     return function(pos, formname, fields, sender)
159         local meta = minetest.get_meta(pos)
160         local page = "main"
4a9ad9 161
HL 162         local owner = meta:get_string("owner")
163         if owner ~= "" then
164             -- prevent modification of locked chests
165             if owner ~= sender:get_player_name() then return end
166         elseif not fields.quit then
167             -- prevent modification of protected chests
168             if minetest.is_protected(pos, sender:get_player_name()) then return end
169         end
170
5c689a 171         if fields.sort or (data.autosort and fields.quit and meta:get_int("autosort") == 1) then
R 172             sort_inventory(meta:get_inventory())
173         end
174         if fields.edit_infotext then
175             page = "edit_infotext"
176         end
177         if fields.autosort_to_1 then meta:set_int("autosort", 1) end
178         if fields.autosort_to_0 then meta:set_int("autosort", 0) end
179         if fields.infotext_box then
180             meta:set_string("infotext", fields.infotext_box)
181         end
78cacd 182         if data.color then
S 183             -- This sets the node
184             local nn = "technic:"..lname..(data.locked and "_locked" or "").."_chest"
185             check_color_buttons(pos, meta, nn, fields)
186         end
11f20d 187         if fields["fs_helpers_cycling:0:splitstacks"]
VE 188           or fields["fs_helpers_cycling:1:splitstacks"] then
189             if not pipeworks.may_configure(pos, sender) then return end
190             fs_helpers.on_receive_fields(pos, fields)
191         end
192
96ad67 193         meta:get_inventory():set_size("main", data.width * data.height)
5c689a 194         set_formspec(pos, data, page)
78cacd 195     end
S 196 end
197
1d7cb7 198 function technic.chests:definition(name, data)
78cacd 199     local lname = name:lower()
179364 200     name = S(name)
1bf52c 201     local d = {}
Z 202     for k, v in pairs(data) do d[k] = v end
203     data = d
78cacd 204
1bf52c 205     data.lowidth = 8
Z 206     data.ovwidth = math.max(data.lowidth, data.width)
207     data.hileft = (data.ovwidth - data.width) / 2
208     data.loleft = (data.ovwidth - data.lowidth) / 2
209     if data.color then
210         if data.lowidth + 3 <= data.ovwidth then
211             data.coleft = data.ovwidth - 3
212             if data.loleft + data.lowidth > data.coleft then
213                 data.loleft = data.coleft - data.lowidth
214             end
215         else
216             data.loleft = 0
217             data.coleft = data.lowidth
218             data.ovwidth = data.lowidth + 3
219         end
220     end
221     data.lotop = data.height + 2
222     data.ovheight = data.lotop + 4
78cacd 223
S 224     local locked_after_place = nil
225     local front = {"technic_"..lname.."_chest_front.png"}
473505 226     data.base_formspec = "size["..data.ovwidth..","..data.ovheight.."]"..
39c41a 227             "label[0,0;"..S("%s Chest"):format(name).."]"..
473505 228             "list[context;main;"..data.hileft..",1;"..data.width..","..data.height..";]"..
1bf52c 229             "list[current_player;main;"..data.loleft..","..data.lotop..";8,4;]"..
24eca0 230             "background[-0.19,-0.25;"..(data.ovwidth+0.4)..","..(data.ovheight+0.75)..";technic_chest_form_bg.png]"..
1bf52c 231             "background["..data.hileft..",1;"..data.width..","..data.height..";technic_"..lname.."_chest_inventory.png]"..
d732c8 232             "background["..data.loleft..","..data.lotop..";8,4;technic_main_inventory.png]"..
E 233             "listring[]"
11f20d 234
5c689a 235     if data.sort then
1bf52c 236         data.base_formspec = data.base_formspec.."button["..data.hileft..","..(data.height+1.1)..";1,0.8;sort;"..S("Sort").."]"
5c689a 237     end
78cacd 238     if data.color then
1bf52c 239         data.base_formspec = data.base_formspec..get_color_buttons(data.coleft, data.lotop)
78cacd 240     end
S 241
242     if data.locked then
243         locked_after_place = function(pos, placer)
244             local meta = minetest.get_meta(pos)
245             meta:set_string("owner", placer:get_player_name() or "")
179364 246             meta:set_string("infotext",
S 247                     S("%s Locked Chest (owned by %s)")
248                     :format(name, meta:get_string("owner")))
cbfeb0 249             pipeworks.after_place(pos)
78cacd 250         end
S 251         table.insert(front, "technic_"..lname.."_chest_lock_overlay.png")
cbfeb0 252     else
VE 253         locked_after_place = pipeworks.after_place
78cacd 254     end
S 255
179364 256     local desc
S 257     if data.locked then
258         desc = S("%s Locked Chest"):format(name)
259     else
260         desc = S("%s Chest"):format(name)
261     end
262
b6d343 263     local tentry = tube_entry
VE 264     if tube_entry ~= "" then
265         if lname == "wooden" then
266             tentry = "^pipeworks_tube_connection_wooden.png"
267         elseif lname == "mithril" then
268             tentry = "^pipeworks_tube_connection_stony.png"
269         end
270     end
78cacd 271     local def = {
179364 272         description = desc,
b6d343 273         tiles = {
VE 274             "technic_"..lname.."_chest_top.png"..tentry,
275             "technic_"..lname.."_chest_top.png"..tentry,
276             "technic_"..lname.."_chest_side.png"..tentry,
277             "technic_"..lname.."_chest_side.png"..tentry,
278             "technic_"..lname.."_chest_side.png"..tentry,
279             table.concat(front, "^")
280         },
78cacd 281         paramtype2 = "facedir",
S 282         groups = self.groups,
283         tube = self.tube,
284         legacy_facedir_simple = true,
285         sounds = default.node_sound_wood_defaults(),
cbfeb0 286         after_place_node = locked_after_place,
d5db18 287         after_dig_node = pipeworks.after_dig,
VE 288
78cacd 289         on_construct = function(pos)
S 290             local meta = minetest.get_meta(pos)
179364 291             meta:set_string("infotext", S("%s Chest"):format(name))
5c689a 292             set_formspec(pos, data, "main")
78cacd 293             local inv = meta:get_inventory()
96ad67 294             inv:set_size("main", data.width * data.height)
78cacd 295         end,
S 296         can_dig = self.can_dig,
297         on_receive_fields = get_receive_fields(name, data),
298         on_metadata_inventory_move = self.on_inv_move,
299         on_metadata_inventory_put = self.on_inv_put,
930c51 300         on_metadata_inventory_take = self.on_inv_take,
6b52c7 301         on_blast = function(pos)
T 302             local drops = {}
303             default.get_inventory_drops(pos, "main", drops)
ec6354 304             drops[#drops+1] = "technic:"..name:lower()..(data.locked and "_locked" or "").."_chest"
6b52c7 305             minetest.remove_node(pos)
T 306             return drops
307         end,
78cacd 308     }
S 309     if data.locked then
310         def.allow_metadata_inventory_move = self.inv_move
311         def.allow_metadata_inventory_put = self.inv_put
312         def.allow_metadata_inventory_take = self.inv_take
35da22 313         def.on_blast = function() end
ec6354 314         def.can_dig = function(pos,player)
T 315             local meta = minetest.get_meta(pos);
316             local inv = meta:get_inventory()
317             return inv:is_empty("main") and default.can_interact_with_node(player, pos)
35da22 318         end
6b52c7 319         def.on_skeleton_key_use = function(pos, player, newsecret)
T 320             local meta = minetest.get_meta(pos)
321             local owner = meta:get_string("owner")
322             local name = player:get_player_name()
323
324             -- verify placer is owner of lockable chest
325             if owner ~= name then
326                 minetest.record_protection_violation(pos, name)
327                 minetest.chat_send_player(name, "You do not own this chest.")
328                 return nil
329             end
330
331             local secret = meta:get_string("key_lock_secret")
332             if secret == "" then
333                 secret = newsecret
334                 meta:set_string("key_lock_secret", secret)
335             end
336
337             return secret, "a locked chest", owner
35da22 338         end
78cacd 339     end
1d7cb7 340     return def
Z 341 end
78cacd 342
8a987b 343 local _TUBELIB_CALLBACKS = {
O 344     on_pull_item = function(pos, side, player_name)
345         if not minetest.is_protected(pos, player_name) then
346             local inv = minetest.get_meta(pos):get_inventory()
347             for _, stack in pairs(inv:get_list("main")) do
348                 if not stack:is_empty() then
349                     return inv:remove_item("main", stack:get_name())
350                 end
351             end
352         end
353         return nil
354     end,
355     on_push_item = function(pos, side, item, player_name)
356         local inv = minetest.get_meta(pos):get_inventory()
357         if inv:room_for_item("main", item) then
358             inv:add_item("main", item)
359             return true
360         end
361         return false
362     end,
363     on_unpull_item = function(pos, side, item, player_name)
364         local inv = minetest.get_meta(pos):get_inventory()
365         if inv:room_for_item("main", item) then
366             inv:add_item("main", item)
367             return true
368         end
369         return false
370     end,
371 }
372
1d7cb7 373 function technic.chests:register(name, data)
Z 374     local def = technic.chests:definition(name, data)
78cacd 375
1d7cb7 376     local nn = "technic:"..name:lower()..(data.locked and "_locked" or "").."_chest"
78cacd 377     minetest.register_node(":"..nn, def)
8a987b 378
O 379     if tubelib_exists then
380         tubelib.register_node(nn, {}, _TUBELIB_CALLBACKS)
381     end
78cacd 382
S 383     if data.color then
1d7cb7 384         local mk_front
Z 385         if string.find(def.tiles[6], "%^") then
386             mk_front = function (overlay) return def.tiles[6]:gsub("%^", "^"..overlay.."^") end
387         else
388             mk_front = function (overlay) return def.tiles[6].."^"..overlay end
389         end
78cacd 390         for i = 1, 15 do
S 391             local postfix = colorid_to_postfix(i)
392             local colordef = {}
393             for k, v in pairs(def) do
394                 colordef[k] = v
395             end
396             colordef.drop = nn
397             colordef.groups = self.groups_noinv
1d7cb7 398             colordef.tiles = { def.tiles[1], def.tiles[2], def.tiles[3], def.tiles[4], def.tiles[5], mk_front("technic_chest_overlay"..postfix..".png") }
78cacd 399             minetest.register_node(":"..nn..postfix, colordef)
8a987b 400             if tubelib_exists then
O 401                 tubelib.register_node(nn..postfix, {}, _TUBELIB_CALLBACKS)
402             end
78cacd 403         end
S 404     end
405 end
406