Sires
2018-03-15 707fa5a97c0d56e18f16d56f7130ff6220a090a1
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)
87     local node = minetest.get_node(pos)
1bf52c 88     local formspec = data.base_formspec
11f20d 89     formspec = formspec..fs_helpers.cycling_button(
VE 90                 meta,
91                 "image_button[0,0.35;1,0.6",
92                 "splitstacks",
93                 {
fab2c4 94                     pipeworks.button_off,
d2fb24 95                     pipeworks.button_on
11f20d 96                 }
VE 97             )..allow_label
98
5c689a 99     if data.autosort then
R 100         local status = meta:get_int("autosort")
1bf52c 101         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 102     end
5c689a 103     if data.infotext then
78cacd 104         local formspec_infotext = minetest.formspec_escape(meta:get_string("infotext"))
5c689a 105         if page == "main" then
11f20d 106             formspec = formspec.."image_button["..(shift_edit_field+data.hileft+2.1)..",0.1;0.8,0.8;"
78cacd 107                     .."technic_pencil_icon.png;edit_infotext;]"
11f20d 108                     .."label["..(shift_edit_field+data.hileft+3)..",0;"..formspec_infotext.."]"
5c689a 109         elseif page == "edit_infotext" then
11f20d 110             formspec = formspec.."image_button["..(shift_edit_field+data.hileft+2.1)..",0.1;0.8,0.8;"
78cacd 111                     .."technic_checkmark_icon.png;save_infotext;]"
11f20d 112                     .."field["..(shift_edit_field+data.hileft+3.3)..",0.2;4.8,1;"
179364 113                     .."infotext_box;"..S("Edit chest description:")..";"
78cacd 114                     ..formspec_infotext.."]"
S 115         end
5c689a 116     end
R 117     if data.color then
118         local colorID = meta:get_int("color")
119         local colorName
120         if chest_mark_colors[colorID] then
121             colorName = chest_mark_colors[colorID][2]
122         else
123             colorName = S("None")
124         end
1bf52c 125         formspec = formspec.."label["..(data.coleft+0.2)..","..(data.lotop+3)..";"..S("Color Filter: %s"):format(colorName).."]"
5c689a 126     end
R 127     meta:set_string("formspec", formspec)
128 end
129
130 local function sort_inventory(inv)
131     local inlist = inv:get_list("main")
132     local typecnt = {}
133     local typekeys = {}
134     for _, st in ipairs(inlist) do
135         if not st:is_empty() then
136             local n = st:get_name()
137             local w = st:get_wear()
138             local m = st:get_metadata()
139             local k = string.format("%s %05d %s", n, w, m)
140             if not typecnt[k] then
930c51 141                 typecnt[k] = {st}
5c689a 142                 table.insert(typekeys, k)
930c51 143             else
D 144                 table.insert(typecnt[k], st)
5c689a 145             end
R 146         end
147     end
148     table.sort(typekeys)
930c51 149     inv:set_list("main", {})
5c689a 150     for _, k in ipairs(typekeys) do
930c51 151         for _, item in ipairs(typecnt[k]) do
D 152             inv:add_item("main", item)
5c689a 153         end
R 154     end
155 end
156
157 local function get_receive_fields(name, data)
158     local lname = name:lower()
159     return function(pos, formname, fields, sender)
160         local meta = minetest.get_meta(pos)
161         local page = "main"
162         if fields.sort or (data.autosort and fields.quit and meta:get_int("autosort") == 1) then
163             sort_inventory(meta:get_inventory())
164         end
165         if fields.edit_infotext then
166             page = "edit_infotext"
167         end
168         if fields.autosort_to_1 then meta:set_int("autosort", 1) end
169         if fields.autosort_to_0 then meta:set_int("autosort", 0) end
170         if fields.infotext_box then
171             meta:set_string("infotext", fields.infotext_box)
172         end
78cacd 173         if data.color then
S 174             -- This sets the node
175             local nn = "technic:"..lname..(data.locked and "_locked" or "").."_chest"
176             check_color_buttons(pos, meta, nn, fields)
177         end
11f20d 178         if fields["fs_helpers_cycling:0:splitstacks"]
VE 179           or fields["fs_helpers_cycling:1:splitstacks"] then
180             if not pipeworks.may_configure(pos, sender) then return end
181             fs_helpers.on_receive_fields(pos, fields)
182         end
183
96ad67 184         meta:get_inventory():set_size("main", data.width * data.height)
5c689a 185         set_formspec(pos, data, page)
78cacd 186     end
S 187 end
188
1d7cb7 189 function technic.chests:definition(name, data)
78cacd 190     local lname = name:lower()
179364 191     name = S(name)
1bf52c 192     local d = {}
Z 193     for k, v in pairs(data) do d[k] = v end
194     data = d
78cacd 195
1bf52c 196     data.lowidth = 8
Z 197     data.ovwidth = math.max(data.lowidth, data.width)
198     data.hileft = (data.ovwidth - data.width) / 2
199     data.loleft = (data.ovwidth - data.lowidth) / 2
200     if data.color then
201         if data.lowidth + 3 <= data.ovwidth then
202             data.coleft = data.ovwidth - 3
203             if data.loleft + data.lowidth > data.coleft then
204                 data.loleft = data.coleft - data.lowidth
205             end
206         else
207             data.loleft = 0
208             data.coleft = data.lowidth
209             data.ovwidth = data.lowidth + 3
210         end
211     end
212     data.lotop = data.height + 2
213     data.ovheight = data.lotop + 4
78cacd 214
S 215     local locked_after_place = nil
216     local front = {"technic_"..lname.."_chest_front.png"}
473505 217     data.base_formspec = "size["..data.ovwidth..","..data.ovheight.."]"..
39c41a 218             "label[0,0;"..S("%s Chest"):format(name).."]"..
473505 219             "list[context;main;"..data.hileft..",1;"..data.width..","..data.height..";]"..
1bf52c 220             "list[current_player;main;"..data.loleft..","..data.lotop..";8,4;]"..
24eca0 221             "background[-0.19,-0.25;"..(data.ovwidth+0.4)..","..(data.ovheight+0.75)..";technic_chest_form_bg.png]"..
1bf52c 222             "background["..data.hileft..",1;"..data.width..","..data.height..";technic_"..lname.."_chest_inventory.png]"..
d732c8 223             "background["..data.loleft..","..data.lotop..";8,4;technic_main_inventory.png]"..
E 224             "listring[]"
11f20d 225
5c689a 226     if data.sort then
1bf52c 227         data.base_formspec = data.base_formspec.."button["..data.hileft..","..(data.height+1.1)..";1,0.8;sort;"..S("Sort").."]"
5c689a 228     end
78cacd 229     if data.color then
1bf52c 230         data.base_formspec = data.base_formspec..get_color_buttons(data.coleft, data.lotop)
78cacd 231     end
S 232
233     if data.locked then
234         locked_after_place = function(pos, placer)
235             local meta = minetest.get_meta(pos)
236             meta:set_string("owner", placer:get_player_name() or "")
179364 237             meta:set_string("infotext",
S 238                     S("%s Locked Chest (owned by %s)")
239                     :format(name, meta:get_string("owner")))
cbfeb0 240             pipeworks.after_place(pos)
78cacd 241         end
S 242         table.insert(front, "technic_"..lname.."_chest_lock_overlay.png")
cbfeb0 243     else
VE 244         locked_after_place = pipeworks.after_place
78cacd 245     end
S 246
179364 247     local desc
S 248     if data.locked then
249         desc = S("%s Locked Chest"):format(name)
250     else
251         desc = S("%s Chest"):format(name)
252     end
253
b6d343 254     local tentry = tube_entry
VE 255     if tube_entry ~= "" then
256         if lname == "wooden" then
257             tentry = "^pipeworks_tube_connection_wooden.png"
258         elseif lname == "mithril" then
259             tentry = "^pipeworks_tube_connection_stony.png"
260         end
261     end
78cacd 262     local def = {
179364 263         description = desc,
b6d343 264         tiles = {
VE 265             "technic_"..lname.."_chest_top.png"..tentry,
266             "technic_"..lname.."_chest_top.png"..tentry,
267             "technic_"..lname.."_chest_side.png"..tentry,
268             "technic_"..lname.."_chest_side.png"..tentry,
269             "technic_"..lname.."_chest_side.png"..tentry,
270             table.concat(front, "^")
271         },
78cacd 272         paramtype2 = "facedir",
S 273         groups = self.groups,
274         tube = self.tube,
275         legacy_facedir_simple = true,
276         sounds = default.node_sound_wood_defaults(),
cbfeb0 277         after_place_node = locked_after_place,
d5db18 278         after_dig_node = pipeworks.after_dig,
VE 279
78cacd 280         on_construct = function(pos)
S 281             local meta = minetest.get_meta(pos)
179364 282             meta:set_string("infotext", S("%s Chest"):format(name))
5c689a 283             set_formspec(pos, data, "main")
78cacd 284             local inv = meta:get_inventory()
96ad67 285             inv:set_size("main", data.width * data.height)
78cacd 286         end,
S 287         can_dig = self.can_dig,
288         on_receive_fields = get_receive_fields(name, data),
289         on_metadata_inventory_move = self.on_inv_move,
290         on_metadata_inventory_put = self.on_inv_put,
930c51 291         on_metadata_inventory_take = self.on_inv_take,
6b52c7 292         on_blast = function(pos)
T 293             local drops = {}
294             default.get_inventory_drops(pos, "main", drops)
ec6354 295             drops[#drops+1] = "technic:"..name:lower()..(data.locked and "_locked" or "").."_chest"
6b52c7 296             minetest.remove_node(pos)
T 297             return drops
298         end,
78cacd 299     }
S 300     if data.locked then
301         def.allow_metadata_inventory_move = self.inv_move
302         def.allow_metadata_inventory_put = self.inv_put
303         def.allow_metadata_inventory_take = self.inv_take
35da22 304         def.on_blast = function() end
ec6354 305         def.can_dig = function(pos,player)
T 306             local meta = minetest.get_meta(pos);
307             local inv = meta:get_inventory()
308             return inv:is_empty("main") and default.can_interact_with_node(player, pos)
35da22 309         end
6b52c7 310         def.on_skeleton_key_use = function(pos, player, newsecret)
T 311             local meta = minetest.get_meta(pos)
312             local owner = meta:get_string("owner")
313             local name = player:get_player_name()
314
315             -- verify placer is owner of lockable chest
316             if owner ~= name then
317                 minetest.record_protection_violation(pos, name)
318                 minetest.chat_send_player(name, "You do not own this chest.")
319                 return nil
320             end
321
322             local secret = meta:get_string("key_lock_secret")
323             if secret == "" then
324                 secret = newsecret
325                 meta:set_string("key_lock_secret", secret)
326             end
327
328             return secret, "a locked chest", owner
35da22 329         end
78cacd 330     end
1d7cb7 331     return def
Z 332 end
78cacd 333
8a987b 334 local _TUBELIB_CALLBACKS = {
O 335     on_pull_item = function(pos, side, player_name)
336         if not minetest.is_protected(pos, player_name) then
337             local inv = minetest.get_meta(pos):get_inventory()
338             for _, stack in pairs(inv:get_list("main")) do
339                 if not stack:is_empty() then
340                     return inv:remove_item("main", stack:get_name())
341                 end
342             end
343         end
344         return nil
345     end,
346     on_push_item = function(pos, side, item, player_name)
347         local inv = minetest.get_meta(pos):get_inventory()
348         if inv:room_for_item("main", item) then
349             inv:add_item("main", item)
350             return true
351         end
352         return false
353     end,
354     on_unpull_item = function(pos, side, item, player_name)
355         local inv = minetest.get_meta(pos):get_inventory()
356         if inv:room_for_item("main", item) then
357             inv:add_item("main", item)
358             return true
359         end
360         return false
361     end,
362 }
363
1d7cb7 364 function technic.chests:register(name, data)
Z 365     local def = technic.chests:definition(name, data)
78cacd 366
1d7cb7 367     local nn = "technic:"..name:lower()..(data.locked and "_locked" or "").."_chest"
78cacd 368     minetest.register_node(":"..nn, def)
8a987b 369
O 370     if tubelib_exists then
371         tubelib.register_node(nn, {}, _TUBELIB_CALLBACKS)
372     end
78cacd 373
S 374     if data.color then
1d7cb7 375         local mk_front
Z 376         if string.find(def.tiles[6], "%^") then
377             mk_front = function (overlay) return def.tiles[6]:gsub("%^", "^"..overlay.."^") end
378         else
379             mk_front = function (overlay) return def.tiles[6].."^"..overlay end
380         end
78cacd 381         for i = 1, 15 do
S 382             local postfix = colorid_to_postfix(i)
383             local colordef = {}
384             for k, v in pairs(def) do
385                 colordef[k] = v
386             end
387             colordef.drop = nn
388             colordef.groups = self.groups_noinv
1d7cb7 389             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 390             minetest.register_node(":"..nn..postfix, colordef)
8a987b 391             if tubelib_exists then
O 392                 tubelib.register_node(nn..postfix, {}, _TUBELIB_CALLBACKS)
393             end
78cacd 394         end
S 395     end
396 end
397