]> git.lizzy.rs Git - Crafter.git/blob - mods/too_many_items/init.lua
986de9f1a2f3c74afbea500687f63245b69bbc69
[Crafter.git] / mods / too_many_items / init.lua
1 --Too Many Items (TMI)
2 --[[this is a recreation of an old minecraft mod]]--
3
4 local creative_mode = minetest.settings:get_bool("creative_mode")
5
6 --THIS IS EXTREMELY sloppy because it's a prototype
7 minetest.register_on_mods_loaded(function()
8         for index,data in pairs(minetest.registered_items) do
9                 if data.name ~= "" then
10                         if data.drop and data.drop ~= "" then
11                                 --single drop parents
12                                 if type(data.drop) == "string" then
13                                         --add parent to dropped items
14                                         local droppers = minetest.registered_items[data.drop].parent_dropper
15                                         if not droppers then
16                                                 --print(data.name)
17                                                 droppers = {}
18                                         end
19                                         
20                                         table.insert(droppers, data.name)
21                                         minetest.override_item(data.drop, {
22                                                 parent_dropper = droppers
23                                         })
24                                 --multiple drop parents
25                                 elseif type(data.drop) == "table" then
26                                         if data.drop.items then
27                                                 for index2,dropdata in pairs(data.drop.items) do
28                                                         if dropdata.items then
29                                                                 for index3,drop_item in pairs(dropdata.items) do
30                                                                         --add parent to dropped items
31                                                                         local droppers = minetest.registered_items[drop_item].parent_dropper
32                                                                         if not droppers then
33                                                                                 droppers = {}
34                                                                         end
35                                                                         
36                                                                         table.insert(droppers, data.name)
37                                                                         minetest.override_item(drop_item, {
38                                                                                 parent_dropper = droppers
39                                                                         })
40                                                                 end
41                                                         end
42                                                 end
43                                         end
44                                 end
45                         end
46                 end
47         end
48 end)
49
50 function minetest.get_dropper_nodes(node)
51         return(minetest.registered_items[node].parent_dropper)
52 end
53 --this is from Linuxdirk, thank you AspireMint for showing me this
54 local recipe_converter = function (items, width)
55     local usable_recipe = { {}, {}, {} }
56
57     -- The recipe is a shapeless recipe so all items are in one table
58     if width == 0 then
59         usable_recipe = items
60     end
61
62     -- x _ _
63     -- x _ _
64     -- x _ _
65     if width == 1 then
66         usable_recipe[1][1] = items[1] or ''
67         usable_recipe[2][1] = items[2] or ''
68         usable_recipe[3][1] = items[3] or ''
69     end
70
71     -- x x _
72     -- x x _
73     -- x x _
74     if width == 2 then
75         usable_recipe[1][1] = items[1] or ''
76         usable_recipe[1][2] = items[2] or ''
77         usable_recipe[2][1] = items[3] or ''
78         usable_recipe[2][2] = items[4] or ''
79         usable_recipe[3][1] = items[5] or ''
80         usable_recipe[3][2] = items[6] or ''
81     end
82
83     -- x x x
84     -- x x x
85     -- x x x
86     if width == 3 then
87         usable_recipe[1][1] = items[1] or ''
88         usable_recipe[1][2] = items[2] or ''
89         usable_recipe[1][3] = items[3] or ''
90         usable_recipe[2][1] = items[4] or ''
91         usable_recipe[2][2] = items[5] or ''
92         usable_recipe[2][3] = items[6] or ''
93         usable_recipe[3][1] = items[7] or ''
94         usable_recipe[3][2] = items[8] or ''
95         usable_recipe[3][3] = items[9] or ''
96     end
97
98     return(usable_recipe)
99 end
100
101 local map_group_to_item = {
102         ["coal"]  = "main:coal",
103         ["glass"] = "main:glass",
104         ["sand"]  = "main:sand",
105         ["stick"] = "main:stick",
106         ["stone"] = "main:cobble",
107         ["tree"]  = "main:tree",
108         ["wood"]  = "main:wood"
109 }
110
111 get_if_group = function(item)
112         if item ~= nil and item:sub(1,6) == "group:" then
113                 local group_name = item:sub(7, item:len())
114                 local mapped_item = map_group_to_item[group_name]
115                 if mapped_item ~= nil then
116                         return(mapped_item)
117                 end
118         end
119         return(item)
120 end
121         
122
123 function create_craft_formspec(item)
124         --don't do air
125         if item == "" then
126                 return("")
127         end
128         local recipe = minetest.get_craft_recipe(item)
129         
130         local usable_table = recipe_converter(recipe.items, recipe.width)
131         output = "size[17.2,8.75]"..
132                 "background[-0.19,-0.25;9.41,9.49;gui_hb_bg.png]"..
133                 "listcolors[#8b8a89;#c9c3c6;#3e3d3e;#000000;#FFFFFF]"..
134                 "list[current_player;main;0,4.5;9,1;]".. --hot bar
135                 "list[current_player;main;0,6;9,3;9]".. --big part
136                 "button[5,3.5;1,1;toomanyitems.back;back]" --back button
137         
138         local base_x = 0.75
139         local base_y = -0.5
140         if recipe.method == "normal" then
141                 if usable_table then
142                         --shaped (regular)
143                         if recipe.width > 0 then
144                                 for x = 1,3 do
145                                 for y = 1,3 do
146                                         local item = get_if_group(usable_table[x][y])
147                                         if item then
148                                                 output = output.."item_image_button["..base_x+y..","..base_y+x..";1,1;"..item..";"..item..";]"
149                                         else
150                                                 output = output.."item_image_button["..base_x+y..","..base_y+x..";1,1;;;]"
151                                         end
152                                 end
153                                 end
154                         --shapeless
155                         else
156                                 local i = 1
157                                 for x = 1,3 do
158                                 for y = 1,3 do
159                                         local item = get_if_group(usable_table[i])
160                                         if item then
161                                                 output = output.."item_image_button["..base_x+y..","..base_y+x..";1,1;"..item..";"..item..";]"
162                                         else
163                                                 output = output.."item_image_button["..base_x+y..","..base_y+x..";1,1;;;]"
164                                         end
165                                         i = i + 1
166                                 end
167                                 end
168                         end
169                 end
170         elseif recipe.method == "cooking" then
171                 local item = recipe.items[1]
172                 output = output.."item_image_button["..(base_x+2)..","..(base_y+1)..";1,1;"..item..";"..item..";]"
173                 output = output.."image[2.75,1.5;1,1;default_furnace_fire_fg.png]"
174         --this is an escape to check if diggable
175         else
176                 local dropper = minetest.get_dropper_nodes(item)
177                 local dug_node = nil
178                 if type(dropper) == "table" and table.getn(dropper) > 0 then
179                         local amount_of_droppers = table.getn(dropper)
180                         dug_node = dropper[math.random(1,amount_of_droppers)]
181                 else
182                         --print("failed")
183                 end             
184                 if dug_node then
185                         output = output.."item_image_button["..(base_x+2)..","..(base_y+1)..";1,1;"..dug_node..";"..dug_node..";]"
186                         output = output.."image[2.75,1.5;1,1;diamondpick.png]"
187                         
188                 else
189                         return("")
190                 end
191         end
192         return(output)
193 end
194
195
196 function show_cheat_button(player)
197         local cheat = get_player_cheat(player)
198         if cheat == 1 then
199                 return("button[11.5,7.6;2,2;toomanyitems.cheat;cheat:on]")
200         else
201                 return("button[11.5,7.6;2,2;toomanyitems.cheat;cheat:off]")
202         end
203 end
204
205
206 minetest.register_on_player_receive_fields(function(player, formname, fields)
207         --print(dump(fields))
208         local form
209         local id
210         if formname == "" then
211                 form = base_inv
212                 id = ""
213         elseif formname == "crafting" then
214                 form = crafting_table_inv
215                 id = "crafting"
216         end
217         
218         local cheating = get_player_cheat(player)
219         --"next" button
220         if fields["toomanyitems.next"] then
221                 local page = get_player_page(player)
222                 
223                 page = page + 1
224                 --page loops back to first
225                 if page > pages then
226                         page = 0
227                 end     
228                 
229                 set_player_page(player,page)
230                 
231                 set_inventory_page(player,form)
232                 local cheat_button = show_cheat_button(player)  
233                 minetest.show_formspec(player:get_player_name(),id, form..inv["page_"..page]..cheat_button)
234                 minetest.sound_play("lever", {to_player = player:get_player_name(),gain=0.7})
235         --"prev" button
236         elseif fields["toomanyitems.prev"] then
237                 local page = get_player_page(player)
238                 
239                 page = page - 1
240                 --page loops back to end
241                 if page < 0 then
242                         page = pages
243                 end     
244                 
245                 set_player_page(player,page)
246                 set_inventory_page(player,form)
247                 local cheat_button = show_cheat_button(player)  
248                 minetest.show_formspec(player:get_player_name(),id, form..inv["page_"..page]..cheat_button)
249                 minetest.sound_play("lever", {to_player = player:get_player_name(),gain=0.7})
250         elseif fields["toomanyitems.back"] then
251                 local page = get_player_page(player)
252                 local cheat_button = show_cheat_button(player)
253                 minetest.show_formspec(player:get_player_name(),id, form..inv["page_"..page]..cheat_button)
254                 minetest.sound_play("lever", {to_player = player:get_player_name(),gain=0.7})
255         --this resets the craft table
256         elseif fields.quit then
257                 local inv = player:get_inventory()
258                 dump_craft(player)
259                 inv:set_width("craft", 2)
260                 inv:set_size("craft", 4)
261                 --reset the player inv
262                 set_inventory_page(player,base_inv)
263         elseif fields["toomanyitems.cheat"] then
264                 --check if the player has the give priv
265                 local privved = minetest.get_player_privs(player:get_player_name()).give
266                 local cheating = get_player_cheat(player)
267                 if creative_mode or (cheating == 0 and privved == true) or cheating == 1 then
268                         local cheating = math.abs(cheating - 1)
269                         if creative_mode then
270                                 cheating = 1
271                         end
272                         set_player_cheat(player,cheating)
273                         local cheat_button = show_cheat_button(player)
274                         local page = get_player_page(player)
275                         minetest.show_formspec(player:get_player_name(),id, form..inv["page_"..page]..cheat_button)
276                         minetest.sound_play("lever", {to_player = player:get_player_name(),gain=0.7})
277                 else
278                         minetest.chat_send_player(player:get_player_name(), minetest.colorize("red", "YOU DO NOT HAVE THE 'GIVE' PRIVELAGE"))
279                         minetest.sound_play("lever", {to_player = player:get_player_name(),gain=0.7,pitch=0.7})
280                 end
281         --this is the "cheating" aka giveme function and craft recipe
282         elseif fields and type(fields) == "table" and string.match(next(fields),"toomanyitems.") then
283                 local item = string.gsub(next(fields), "toomanyitems.", "")
284                 local privved = minetest.get_player_privs(player:get_player_name()).give
285                 local cheating = get_player_cheat(player)
286
287
288                 if creative_mode or (cheating == 1 and privved == true) then
289                         local pos = player:getpos()
290                         local inv = player:get_inventory()
291                         local stack = ItemStack(item.." 64")
292                         
293                         --room for item
294                         if inv and inv:room_for_item("main",stack) then
295                                 inv:add_item("main", stack)
296                                 minetest.sound_play("pickup", {to_player = player:get_player_name(),gain=0.7,pitch = math.random(60,100)/100})
297                         --no room for item
298                         else
299                                 local namer = string.upper(minetest.registered_items[item].description)
300                                 minetest.chat_send_player(player:get_player_name(), minetest.colorize("red", "THERE IS NO ROOM FOR "..namer.." IN YOUR INVENTORY!"))
301                                 minetest.sound_play("lever", {to_player = player:get_player_name(),gain=0.7,pitch=0.7})
302                         end
303                         --minetest.show_formspec(player:get_player_name(),id, inv["page_"..page])
304                 --this is to get the craft recipe
305                 else
306                         local page = get_player_page(player)
307                         local craft_inv = create_craft_formspec(item)
308                         if craft_inv and craft_inv ~= "" then
309                                 local cheat_button = show_cheat_button(player)  
310                                 minetest.show_formspec(player:get_player_name(),id, craft_inv..inv["page_"..page]..cheat_button)
311                                 minetest.sound_play("lever", {to_player = player:get_player_name(),gain=0.7})
312                         end
313                 end
314
315         end
316 end)
317
318 get_player_page = function(player)
319         local meta = player:get_meta()
320         return(meta:get_int("page"))
321 end
322
323 set_player_page = function(player,page)
324         local meta = player:get_meta()
325         meta:set_int("page",page)
326 end
327
328 --
329
330 get_player_cheat = function(player)
331         local meta = player:get_meta()
332         return(meta:get_int("cheating"))
333 end
334
335 set_player_cheat = function(player,truth)
336         local meta = player:get_meta()
337         meta:set_int("cheating",truth)
338 end
339
340 local max = 7*7
341 --this is where the main 2x2 formspec is
342 base_inv = "size[17.2,8.75]"..
343     "background[-0.19,-0.25;9.41,9.49;main_inventory.png]"..
344     "listcolors[#8b8a89;#c9c3c6;#3e3d3e;#000000;#FFFFFF]"..
345     "list[current_player;main;0,4.5;9,1;]".. --hot bar
346         "list[current_player;main;0,6;9,3;9]".. --big part
347     "list[current_player;craft;2.5,1;2,2;]"..
348     "list[current_player;craftpreview;6.1,1.5;1,1;]"..
349     "listring[current_player;main]"..
350         "listring[current_player;craft]"
351 --this is the 3x3 crafting table formspec
352 crafting_table_inv = "size[17.2,8.75]"..
353                 "background[-0.19,-0.25;9.41,9.49;crafting_inventory_workbench.png]"..
354                 "listcolors[#8b8a89;#c9c3c6;#3e3d3e;#000000;#FFFFFF]"..
355                 "list[current_player;main;0,4.5;9,1;]".. --hot bar
356                 "list[current_player;main;0,6;9,3;9]".. --big part
357                 "list[current_player;craft;1.75,0.5;3,3;]"..
358                 "list[current_player;craftpreview;6.1,1.5;1,1;]"..
359                 "listring[current_player;main]"..
360                 "listring[current_player;craft]"
361
362
363 --the global page number
364 pages = 0
365
366 --run through the items and then set the pages
367 minetest.register_on_mods_loaded(function()
368 local item_counter = 0
369 inv = {}
370
371 local page = 0
372 inv["page_"..page] = ""
373
374 local x = 0
375 local y = 0
376
377 --dump all the items in
378 for index,data in pairs(minetest.registered_items) do
379         if data.name ~= "" then
380                 local recipe = minetest.get_craft_recipe(data.name)
381                 --only put in craftable items
382                 if recipe.method then
383                         inv["page_"..page] = inv["page_"..page].."item_image_button["..9.25+x..","..y..";1,1;"..data.name..";toomanyitems."..data.name..";]"
384                         x = x + 1
385                         if x > 7 then
386                                 x = 0
387                                 y = y + 1
388                         end
389                         if y > 7 then
390                                 y = 0
391                                 page = page + 1
392                                 inv["page_"..page] = ""
393                         end
394                 end
395         end
396 end
397
398 --add buttons and labels
399 for i = 0,page do
400         --set the last page
401         inv["page_"..i] = inv["page_"..i].."button[9.25,7.6;2,2;toomanyitems.prev;prev]"..
402         "button[15.25,7.6;2,2;toomanyitems.next;next]"..
403         --this is +1 so it makes more sense
404         "label[13.75,8.25;page "..(i+1).."/"..(page+1).."]"
405 end
406
407 --override crafting table
408 minetest.override_item("craftingtable:craftingtable", {
409          on_rightclick = function(pos, node, player, itemstack)
410                 player:get_inventory():set_width("craft", 3)
411                 player:get_inventory():set_size("craft", 9)
412                 local page = get_player_page(player)
413                 minetest.show_formspec(player:get_player_name(), "crafting", crafting_table_inv..inv["page_"..page])
414         end,
415 })
416 pages = page
417 end)
418
419 --this is how the player "turns" the page
420 set_inventory_page = function(player,inventory)
421         local page = get_player_page(player)
422         local cheat = get_player_cheat(player)
423         if cheat == 1 then
424                 inventory = inventory.."button[11.5,7.6;2,2;toomanyitems.cheat;cheat:on]"
425         else
426                 inventory = inventory.."button[11.5,7.6;2,2;toomanyitems.cheat;cheat:off]"
427         end
428                 
429         player:set_inventory_formspec(inventory..inv["page_"..page])
430 end
431
432 --set new players inventory up
433 minetest.register_on_joinplayer(function(player)
434         local cheat_mode = 0
435         if creative_mode then
436                 cheat_mode = 1
437         end
438         set_player_cheat(player, cheat_mode) -- this resets the cheating to false
439         set_player_page(player,0) -- this sets the meta "page" to remember what page they're on
440         set_inventory_page(player,base_inv) --this sets the "" (inventory button/main) inventory
441         
442         local inv = player:get_inventory()
443         inv:set_width("craft", 2)
444         inv:set_width("main", 9)
445         inv:set_size("main", 9*4)
446         inv:set_size("craft", 4)
447         player:hud_set_hotbar_itemcount(9)
448         player:hud_set_hotbar_image("inventory_hotbar.png")
449         player:hud_set_hotbar_selected_image("hotbar_selected.png")
450 end)