]> git.lizzy.rs Git - Crafter.git/blob - mods/inventory/init.lua
Fixed invalid 3rd person wielditem rotation for tools; Fixed broken craft recipe...
[Crafter.git] / mods / inventory / init.lua
1 local minetest,pairs = minetest,pairs
2
3 inventory = {}
4 local tmi_master_inventory = {}
5 local is_crafting = {}
6 local pool = {}
7 local max = 7*7
8 --2x2 formspec
9 local base_inv = 
10 "size[17.2,8.75]"..
11 "background[-0.19,-0.25;9.41,9.49;main_inventory.png]"..
12 "listcolors[#8b8a89;#c9c3c6;#3e3d3e;#000000;#FFFFFF]"..
13 "list[current_player;main;0,4.5;9,1;]".. --hot bar
14 "list[current_player;main;0,6;9,3;9]".. --big part
15 "list[current_player;craft;2.5,1;2,2;]"..
16 --armor slots
17 "list[current_player;armor_head;0.25,0;1,1;]"..
18 "list[current_player;armor_torso;0.25,1;1,1;]"..
19 "list[current_player;armor_legs;0.25,2;1,1;]"..
20 "list[current_player;armor_feet;0.25,3;1,1;]"..
21 --craft preview with ring
22 "list[current_player;craftpreview;6.1,1.5;1,1;]"..
23 "listring[current_player;main]"..
24 "listring[current_player;craft]"
25 --this is the 3x3 crafting table formspec
26 local crafting_table_inv = 
27 "size[17.2,8.75]"..
28 "background[-0.19,-0.25;9.41,9.49;crafting_inventory_workbench.png]"..
29 "listcolors[#8b8a89;#c9c3c6;#3e3d3e;#000000;#FFFFFF]"..
30 "list[current_player;main;0,4.5;9,1;]".. --hot bar
31 "list[current_player;main;0,6;9,3;9]".. --big part
32 "list[current_player;craft;1.75,0.5;3,3;]"..
33 --armor slots
34 "list[current_player;armor_head;0.25,0;1,1;]"..
35 "list[current_player;armor_torso;0.25,1;1,1;]"..
36 "list[current_player;armor_legs;0.25,2;1,1;]"..
37 "list[current_player;armor_feet;0.25,3;1,1;]"..
38 --craft preview with ring
39 "list[current_player;craftpreview;6.1,1.5;1,1;]"..
40 "listring[current_player;main]"..
41 "listring[current_player;craft]"
42 --this is from Linuxdirk, thank you AspireMint for showing me this
43 local recipe_converter = function (items, width)
44     local usable_recipe = { {}, {}, {} }
45
46     -- The recipe is a shapeless recipe so all items are in one table
47     if width == 0 then
48         usable_recipe = items
49     end
50
51     -- x _ _
52     -- x _ _
53     -- x _ _
54     if width == 1 then
55         usable_recipe[1][1] = items[1] or ''
56         usable_recipe[2][1] = items[2] or ''
57         usable_recipe[3][1] = items[3] or ''
58     end
59
60     -- x x _
61     -- x x _
62     -- x x _
63     if width == 2 then
64         usable_recipe[1][1] = items[1] or ''
65         usable_recipe[1][2] = items[2] or ''
66         usable_recipe[2][1] = items[3] or ''
67         usable_recipe[2][2] = items[4] or ''
68         usable_recipe[3][1] = items[5] or ''
69         usable_recipe[3][2] = items[6] or ''
70     end
71
72     -- x x x
73     -- x x x
74     -- x x x
75     if width == 3 then
76         usable_recipe[1][1] = items[1] or ''
77         usable_recipe[1][2] = items[2] or ''
78         usable_recipe[1][3] = items[3] or ''
79         usable_recipe[2][1] = items[4] or ''
80         usable_recipe[2][2] = items[5] or ''
81         usable_recipe[2][3] = items[6] or ''
82         usable_recipe[3][1] = items[7] or ''
83         usable_recipe[3][2] = items[8] or ''
84         usable_recipe[3][3] = items[9] or ''
85     end
86     return(usable_recipe)
87 end
88
89 local map_group_to_item = {
90         ["coal"]  = "main:coal",
91         ["glass"] = "main:glass",
92         ["sand"]  = "main:sand",
93         ["stick"] = "main:stick",
94         ["stone"] = "main:cobble",
95         ["tree"]  = "main:tree",
96         ["wood"]  = "main:wood"
97 }
98
99 local get_if_group = function(item)
100         if item ~= nil and item:sub(1,6) == "group:" then
101                 local group_name = item:sub(7, item:len())
102                 local mapped_item = map_group_to_item[group_name]
103                 if mapped_item ~= nil then
104                         return(mapped_item)
105                 end
106         end
107         return(item)
108 end
109
110
111 local base_x = 0.75
112 local base_y = -0.5
113 local output_constant = 
114 "listcolors[#8b8a89;#c9c3c6;#3e3d3e;#000000;#FFFFFF]"..
115 "list[current_player;main;0,4.5;9,1;]"..   --hot bar
116 "list[current_player;main;0,6;9,3;9]"..    --main inventory
117 "button[5,3.5;1,1;inventory.back;back]" --back button
118 local output
119 local recipe
120 local usable_table
121 local function create_craft_formspec(item)
122         --don't do air
123         if item == "" then
124                 return("")
125         end
126
127         recipe = minetest.get_craft_recipe(item)
128         
129         usable_table = recipe_converter(recipe.items, recipe.width)
130
131         output = output_constant
132         
133         if recipe.method == "normal" then
134                 if usable_table then
135                         --shaped (regular)
136                         if recipe.width > 0 then
137                                 for x = 1,3 do
138                                         for y = 1,3 do
139                                                 item = get_if_group(usable_table[x][y])
140                                                 if item then
141                                                         output = output.."item_image_button["..base_x+y..","..base_y+x..";1,1;"..item..";"..item..";]"
142                                                 else
143                                                         output = output.."item_image_button["..base_x+y..","..base_y+x..";1,1;;;]"
144                                                 end
145                                         end
146                                 end
147                         --shapeless
148                         else
149                                 local i = 1
150                                 for x = 1,3 do
151                                         for y = 1,3 do
152                                                 item = get_if_group(usable_table[i])
153                                                 if item then
154                                                         output = output.."item_image_button["..base_x+y..","..base_y+x..";1,1;"..item..";"..item..";]"
155                                                 else
156                                                         output = output.."item_image_button["..base_x+y..","..base_y+x..";1,1;;;]"
157                                                 end
158                                                 i = i + 1
159                                         end
160                                 end
161                         end
162                 end
163         elseif recipe.method == "cooking" then
164                 item = recipe.items[1]
165                 output = output.."item_image_button["..(base_x+2)..","..(base_y+1)..";1,1;"..item..";"..item..";]"
166                 output = output.."image[2.75,1.5;1,1;default_furnace_fire_fg.png]"
167         end
168         return(output)
169 end
170
171 local function cheat_button(name)
172         if pool[name] and pool[name].cheating then
173                 return "button[12.75,7.6;2,2;inventory.cheat;cheat:on]"
174         elseif minetest.check_player_privs(name, {give = true}) then
175                 return "button[12.75,7.6;2,2;inventory.cheat;cheat:off]"
176         else
177                 return ""
178         end
179 end
180
181 local function empty_armor_slots(player)
182         local fs = "formspec_version[3]"
183         local inv = player:get_inventory()
184         for i, comp in ipairs({"head", "torso", "legs", "feet"}) do
185                 if inv:get_stack("armor_" .. comp, 1):get_name() == "" then
186                         fs = fs .. "image[0.25," .. (i - 1) .. ";1,1;inventory_empty_armor_slot_" .. comp .. ".png]"
187                 end
188         end
189         return fs
190 end
191
192 local form
193 local id
194 local inv
195 local item
196 local stack
197 local craft_inv
198 local name
199 local temp_pool
200 minetest.register_on_player_receive_fields(function(player, formname, fields)
201         name = player:get_player_name()
202         temp_pool = pool[name]
203
204         if formname == "" then
205                 form = base_inv
206                 id = ""
207         elseif formname == "crafting" then
208                 form = crafting_table_inv
209                 id = "crafting"
210                 if fields.quit then
211                         is_crafting[name] = nil
212                 end
213         end
214         
215         --"next" button
216         if fields["inventory.next"] then
217                 temp_pool.page = temp_pool.page + 1
218                 --page loops back to first
219                 if temp_pool.page > tmi_master_inventory.page_limit then
220                         temp_pool.page = 1
221                 end     
222                 minetest.show_formspec(name,id, form..empty_armor_slots(player)..tmi_master_inventory["page_"..temp_pool.page]..cheat_button(name))
223                 minetest.sound_play("lever", {to_player = name,gain=0.7})
224                 player:set_inventory_formspec(base_inv..empty_armor_slots(player)..tmi_master_inventory["page_"..temp_pool.page]..cheat_button(name))
225         --"prev" button
226         elseif fields["inventory.prev"] then
227                 temp_pool.page = temp_pool.page - 1
228                 --page loops back to end
229                 if temp_pool.page < 1 then
230                         temp_pool.page = tmi_master_inventory.page_limit
231                 end     
232                 
233                 minetest.show_formspec(name,id, form..empty_armor_slots(player)..tmi_master_inventory["page_"..temp_pool.page]..cheat_button(name))
234                 minetest.sound_play("lever", {to_player = name,gain=0.7})
235                 player:set_inventory_formspec(base_inv..empty_armor_slots(player)..tmi_master_inventory["page_"..temp_pool.page]..cheat_button(name))
236         elseif fields["inventory.back"] then
237
238                 minetest.show_formspec(name,id, form..empty_armor_slots(player)..tmi_master_inventory["page_"..temp_pool.page]..cheat_button(name))
239                 minetest.sound_play("lever", {to_player = name,gain=0.7})
240         --this resets the craft table
241         elseif fields.quit then
242                 inv = player:get_inventory()
243                 dump_craft(player)
244                 inv:set_width("craft", 2)
245                 inv:set_size("craft", 4)
246                 --reset the player inv
247                 --minetest.show_formspec(name,id, form..empty_armor_slots(player)..tmi_master_inventory["page_"..temp_pool.page]..cheat_button(name))
248         elseif fields["inventory.cheat"] then
249                 --check if the player has the give priv
250                 if (not temp_pool.cheating and minetest.get_player_privs(name).give == true) or temp_pool.cheating == true then
251                         temp_pool.cheating = not temp_pool.cheating
252
253                         minetest.show_formspec(name,id, form..empty_armor_slots(player)..tmi_master_inventory["page_"..temp_pool.page]..cheat_button(name))
254                         minetest.sound_play("lever", {to_player = name,gain=0.7})
255                         player:set_inventory_formspec(base_inv..empty_armor_slots(player)..tmi_master_inventory["page_"..temp_pool.page]..cheat_button(name))
256                 else
257                         minetest.chat_send_player(name, "Sorry m8, server says I can't let you do that :(")
258                         minetest.sound_play("lever", {to_player = name,gain=0.7,pitch=0.7})
259                 end
260         --this is the "cheating" aka giveme function and craft recipe
261         elseif fields and type(fields) == "table" and string.match(next(fields),"inventory.") then
262
263                 item = string.gsub(next(fields), "inventory.", "")
264                 stack = ItemStack(item.." 64")
265                 inv = player:get_inventory()
266                 if temp_pool.cheating and minetest.get_player_privs(name).give then
267                         
268                         --room for item
269                         if inv and inv:room_for_item("main",stack) then
270                                 inv:add_item("main", stack)
271                                 minetest.sound_play("pickup", {to_player = name,gain=0.7,pitch = math.random(60,100)/100})
272                         --no room for item
273                         else
274                                 minetest.chat_send_player(name, "Might want to clean up your inventory")
275                                 minetest.sound_play("lever", {to_player = name,gain=0.7,pitch=0.7})
276                         end
277
278                 --this is to get the craft recipe
279                 else
280                         craft_inv = create_craft_formspec(item)
281                         if craft_inv and craft_inv ~= "" then
282                                 minetest.show_formspec(name, id, tmi_master_inventory["page_"..temp_pool.page]..craft_inv..cheat_button(name))
283                                 minetest.sound_play("lever", {to_player = name,gain=0.7})
284                         end
285                 end
286
287         end
288 end)
289
290
291 --run through the items and then set the pages
292 local item_counter = 0
293 local page = 1
294 local x = 0
295 local y = 0
296
297 minetest.register_on_mods_loaded(function()
298
299 --sort all items (There is definitely a better way to do this)
300
301 --get all craftable items
302 local all_items_table = {}
303 for index,data in pairs(minetest.registered_items) do
304         if data.name ~= "" then
305                 local recipe = minetest.get_craft_recipe(data.name)
306                 --only put in craftable items
307                 if recipe.method then                   
308                         table.insert(all_items_table,data.name)
309                 end
310         end
311 end
312
313 table.sort(all_items_table)
314
315 --dump all the items in
316
317 tmi_master_inventory["page_"..page] = "size[17.2,8.75]background[-0.19,-0.25;9.41,9.49;crafting_inventory_workbench.png]"
318
319 for _,item in pairs(all_items_table) do
320         tmi_master_inventory["page_"..page] = tmi_master_inventory["page_"..page].."item_image_button["..(9.25+x)..","..y..";1,1;"..item..";inventory."..item..";]"
321         x = x + 1
322         if x > 7 then
323                 x = 0
324                 y = y + 1
325         end
326         if y > 7 then
327                 y = 0
328                 page = page + 1
329                 tmi_master_inventory["page_"..page] = "size[17.2,8.75]background[-0.19,-0.25;9.41,9.49;crafting_inventory_workbench.png]"
330         end
331 end
332
333 --add buttons and labels
334 for i = 1,page do
335         --set the last page
336         tmi_master_inventory["page_"..i] = tmi_master_inventory["page_"..i].."button[9.25,7.6;2,2;inventory.prev;prev]"..
337         "button[15.25,7.6;2,2;inventory.next;next]"..
338         --this is +1 so it makes more sense
339         "label[11.5,8.25;page "..i.."/"..page.."]"
340 end
341
342 tmi_master_inventory.page_limit = page
343
344 --override crafting table
345 local name
346 local temp_pool
347
348 minetest.override_item("craftingtable:craftingtable", {
349          on_rightclick = function(pos, node, player, itemstack)
350                 name = player:get_player_name()
351                 is_crafting[name] = true
352                 temp_pool = pool[name]
353                 player:get_inventory():set_width("craft", 3)
354                 player:get_inventory():set_size("craft", 9)
355                 minetest.show_formspec(name, "crafting", crafting_table_inv..empty_armor_slots(player)..tmi_master_inventory["page_"..temp_pool.page]..cheat_button(name))
356         end
357 })
358 end)
359
360 function inventory.set(player)
361         player:set_inventory_formspec(base_inv..empty_armor_slots(player)..tmi_master_inventory["page_1"]..cheat_button(player:get_player_name()))
362 end
363
364 function inventory.reload(player)
365         inventory.set(player)
366         local name = player:get_player_name()
367         if is_crafting[name] then
368                 minetest.show_formspec(name, "crafting", crafting_table_inv..empty_armor_slots(player)..tmi_master_inventory["page_1"]..cheat_button(name))
369         else
370                 minetest.show_formspec(name, "", base_inv..empty_armor_slots(player)..tmi_master_inventory["page_1"]..cheat_button(name))
371         end
372 end
373
374
375 --set new players inventory up
376 local name
377 local temp_pool
378 local inv
379 minetest.register_on_joinplayer(function(player)
380         name = player:get_player_name()
381         pool[name] = {}
382         temp_pool = pool[name]
383
384         temp_pool.page = 1
385         temp_pool.cheating = false
386
387         inv = player:get_inventory()
388         inv:set_width("craft", 2)
389         inv:set_width("main", 9)
390         inv:set_size("main", 9*4)
391         inv:set_size("craft", 4)
392
393         inventory.set(player)
394
395         player:hud_set_hotbar_itemcount(9)
396         player:hud_set_hotbar_image("inventory_hotbar.png")
397         player:hud_set_hotbar_selected_image("hotbar_selected.png")
398 end)
399
400 local name
401 minetest.register_on_leaveplayer(function(player)
402         name = player:get_player_name()
403         pool[name] = nil
404         is_crafting[name] = nil
405 end)