From e64f48dbc50ba2906b7879029fc15e67d012c30c Mon Sep 17 00:00:00 2001 From: Pitriss Date: Sun, 15 Dec 2013 12:18:53 +0100 Subject: [PATCH] Updated unified inventory with slight tuning (creative forced off). To enable creative put uniinv_creative = true into minetest.conf --- unified_inventory/README.md | 6 + unified_inventory/api.lua | 682 ++---------------- unified_inventory/bags.lua | 102 ++- unified_inventory/callbacks.lua | 179 +++++ unified_inventory/depends.txt | 2 +- unified_inventory/init.lua | 52 +- unified_inventory/internal.lua | 136 ++++ unified_inventory/register.lua | 305 ++++++++ unified_inventory/textures/ui_blank_image.png | Bin 0 -> 143 bytes .../textures/ui_craftguide_form.png | Bin 14631 -> 13594 bytes .../textures/ui_crafting_form.png | Bin 15015 -> 11733 bytes unified_inventory/textures/ui_group.png | Bin 0 -> 29697 bytes 12 files changed, 813 insertions(+), 651 deletions(-) create mode 100644 unified_inventory/README.md create mode 100644 unified_inventory/callbacks.lua create mode 100644 unified_inventory/internal.lua create mode 100644 unified_inventory/register.lua create mode 100644 unified_inventory/textures/ui_blank_image.png create mode 100644 unified_inventory/textures/ui_group.png diff --git a/unified_inventory/README.md b/unified_inventory/README.md new file mode 100644 index 0000000..bcb3698 --- /dev/null +++ b/unified_inventory/README.md @@ -0,0 +1,6 @@ +unified_inventory +================= + +Replacement for Minetest creative inventory. + +Unified Inventory replaces the survival and creative inventory; it also functions as a crafting guide. diff --git a/unified_inventory/api.lua b/unified_inventory/api.lua index e027c0d..ea19aca 100644 --- a/unified_inventory/api.lua +++ b/unified_inventory/api.lua @@ -1,43 +1,14 @@ ---data tables definitions -unified_inventory = {} -unified_inventory.players = {} -unified_inventory.current_page = {} -unified_inventory.current_index = {} -unified_inventory.items_list_size = 0 -unified_inventory.items_list = {} -unified_inventory.filtered_items_list_size = {} -unified_inventory.filtered_items_list = {} -unified_inventory.activefilter = {} -unified_inventory.alternate = {} -unified_inventory.current_item = {} -unified_inventory.crafts_table ={} -unified_inventory.crafts_table_count=0 - --- default inventory page -unified_inventory.default = "craft" - --- homepos stuff -local home_gui = {} -local homepos = {} -unified_inventory.home_filename = minetest.get_worldpath()..'/unified_inventory_home' -- Create detached creative inventory after loading all mods --- Also 2nd attempt to disable default creative mod minetest.after(0.01, function() - - if creative_inventory then - creative_inventory.set_creative_formspec = function(player, start_i, pagenum) - return - end - end - unified_inventory.items_list = {} - for name,def in pairs(minetest.registered_items) do - if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) - and def.description and def.description ~= "" then + for name, def in pairs(minetest.registered_items) do + if (not def.groups.not_in_creative_inventory or + def.groups.not_in_creative_inventory == 0) and + def.description and def.description ~= "" then table.insert(unified_inventory.items_list, name) - local recipes=minetest.get_all_craft_recipes(name) - if unified_inventory.crafts_table[name]==nil then + local recipes = minetest.get_all_craft_recipes(name) + if unified_inventory.crafts_table[name] == nil then unified_inventory.crafts_table[name] = {} end if recipes then @@ -47,611 +18,58 @@ minetest.after(0.01, function() end end end - --print(dump(unified_inventory.crafts_table)) table.sort(unified_inventory.items_list) unified_inventory.items_list_size = #unified_inventory.items_list - print ("Unified Inventory. inventory size: "..unified_inventory.items_list_size) + print("Unified Inventory. inventory size: "..#unified_inventory.items_list) end) --- register_on_joinplayer -minetest.register_on_joinplayer(function(player) - local player_name = player:get_player_name() - unified_inventory.players[player_name]={} - unified_inventory.current_index[player_name] = 1 - unified_inventory.filtered_items_list[player_name] = {} - unified_inventory.filtered_items_list[player_name] = unified_inventory.items_list - unified_inventory.filtered_items_list_size[player_name]=unified_inventory.items_list_size - unified_inventory.activefilter[player_name]="" - unified_inventory.apply_filter(player, "") - unified_inventory.alternate[player_name] = 1 - unified_inventory.current_item[player_name] =nil - unified_inventory.set_inventory_formspec(player,unified_inventory.get_formspec(player, unified_inventory.default)) - ---crafting guide inventories -local inv = minetest.create_detached_inventory(player:get_player_name().."craftrecipe",{ - allow_put = function(inv, listname, index, stack, player) - return 0 - end, - allow_take = function(inv, listname, index, stack, player) - if minetest.setting_getbool("creative_mode") then - return stack:get_count() - else - return 0 - end - end, - allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) - return 0 - end, - }) -inv:set_size("output", 1) -inv:set_size("build", 3*3) - --- refill slot -unified_inventory.refill = minetest.create_detached_inventory(player_name.."refill", { - allow_put = function(inv, listname, index, stack, player) - if minetest.setting_getbool("creative_mode") then - return stack:get_count() - else - return 0 - end - end, - on_put = function(inv, listname, index, stack, player) - inv:set_stack(listname, index, ItemStack(stack:get_name().." "..stack:get_stack_max())) - minetest.sound_play("electricity", {to_player=player_name, gain = 1.0}) - end, -}) -unified_inventory.refill:set_size("main", 1) - --- trash slot -unified_inventory.trash = minetest.create_detached_inventory("trash", { - allow_put = function(inv, listname, index, stack, player) - if minetest.setting_getbool("creative_mode") then - return stack:get_count() - else --- HACK: override creative check --- return 0 - return stack:get_count() - end - end, - on_put = function(inv, listname, index, stack, player) - inv:set_stack(listname, index, nil) - local player_name=player:get_player_name() - minetest.sound_play("trash", {to_player=player_name, gain = 1.0}) - end, -}) -unified_inventory.trash:set_size("main", 1) -end) - --- set_inventory_formspec -unified_inventory.set_inventory_formspec = function(player,formspec) - if player then - player:set_inventory_formspec(formspec) - end -end - --- get_formspec -unified_inventory.get_formspec = function(player,page) - if player==nil then return "" end - local player_name = player:get_player_name() - unified_inventory.current_page[player_name]=page - - local formspec = "size[14,10]" - - -- player inventory - formspec = formspec .. "list[current_player;main;0,4.5;8,4;]" - - -- backgrounds - formspec = formspec .. "background[-0.19,-0.2;14.38,10.55;ui_form_bg.png]" - if page=="craft" then - formspec = formspec .. "background[0.06,0.99;7.92,7.52;ui_crafting_form.png]" - end - if page=="craftguide" then - formspec = formspec .. "background[0.06,0.99;7.92,7.52;ui_craftguide_form.png]" - end - if page=="misc" then - formspec = formspec .. "background[0.06,0.99;7.92,7.52;ui_misc_form.png]" - end - if page=="bags" then - formspec = formspec .. "background[0.06,0.99;7.92,7.52;ui_bags_main_form.png]" - end - - for i=1,4 do - if page=="bag"..i then - local slots = player:get_inventory():get_stack(page, 1):get_definition().groups.bagslots - if slots == 8 then - formspec = formspec .. "background[0.06,0.99;7.92,7.52;ui_bags_sm_form.png]" - elseif slots == 16 then - formspec = formspec .. "background[0.06,0.99;7.92,7.52;ui_bags_med_form.png]" - elseif slots == 24 then - formspec = formspec .. "background[0.06,0.99;7.92,7.52;ui_bags_lg_form.png]" - end - end - end - - -- main buttons - local start_x=0 - formspec = formspec .. "image_button["..(start_x+.65*0)..",9;.8,.8;ui_craft_icon.png;craft;]" - formspec = formspec .. "image_button["..(start_x+.65*1)..",9;.8,.8;ui_craftguide_icon.png;craftguide;]" - formspec = formspec .. "image_button["..(start_x+.65*2)..",9;.8,.8;ui_bags_icon.png;bags;]" - formspec = formspec .. "image_button["..(start_x+.65*3)..",9;.8,.8;ui_sethome_icon.png;home_gui_set;]" - formspec = formspec .. "image_button["..(start_x+.65*4)..",9;.8,.8;ui_gohome_icon.png;home_gui_go;]" - if minetest.setting_getbool("creative_mode") then - formspec = formspec .. "image_button["..(start_x+.65*5)..",9;.8,.8;ui_sun_icon.png;misc_set_day;]" - formspec = formspec .. "image_button["..(start_x+.65*6)..",9;.8,.8;ui_moon_icon.png;misc_set_night;]" - formspec = formspec .. "image_button["..(start_x+.65*7)..",9;.8,.8;ui_trash_icon.png;clear_inv;]" - end - - --controls to flip items pages - start_x=9.2 - formspec = formspec .. "image_button["..(start_x+.6*0)..",9;.8,.8;ui_skip_backward_icon.png;start_list;]" - formspec = formspec .. "image_button["..(start_x+.6*1)..",9;.8,.8;ui_doubleleft_icon.png;rewind3;]" - formspec = formspec .. "image_button["..(start_x+.6*2)..",9;.8,.8;ui_left_icon.png;rewind1;]" - formspec = formspec .. "image_button["..(start_x+.6*3)..",9;.8,.8;ui_right_icon.png;forward1;]" - formspec = formspec .. "image_button["..(start_x+.6*4)..",9;.8,.8;ui_doubleright_icon.png;forward3;]" - formspec = formspec .. "image_button["..(start_x+.6*5)..",9;.8,.8;ui_skip_forward_icon.png;end_list;]" - - -- search box - formspec = formspec .. "field[9.5,8.325;3,1;searchbox;;]" - formspec = formspec .. "image_button[12.2,8.1;.8,.8;ui_search_icon.png;searchbutton;]" - - -- craft page - if page=="craft" then - formspec = formspec.."label[0,0;Crafting]" - formspec = formspec.."list[current_player;craftpreview;6,1;1,1;]" - formspec = formspec.."list[current_player;craft;2,1;3,3;]" --- HACK: override creative check & disabling refill at all. needs code cleanup --- if minetest.setting_getbool("creative_mode") then --- formspec = formspec.."label[0,2.5;Refill:]" --- formspec = formspec.."list[detached:"..player_name.."refill;main;0,3;1,1;]" - formspec = formspec.."label[7,2.5;Trash:]" - formspec = formspec.."list[detached:trash;main;7,3;1,1;]" --- end - end - - -- craft guide page - if page=="craftguide" then - formspec = formspec.."label[0,0;Crafting Guide]" - formspec = formspec.."list[detached:"..player_name.."craftrecipe;build;2,1;3,3;]" - formspec = formspec.."list[detached:"..player_name.."craftrecipe;output;6,1;1,1;]" - formspec = formspec.."label[2,0.5;Input:]" - formspec = formspec.."label[6,0.5;Output:]" - formspec = formspec.."label[6,2.6;Method:]" - local item_name=unified_inventory.current_item[player_name] - if item_name then - formspec = formspec.."label[2,0;"..item_name.."]" - local alternates = 0 - local alternate = unified_inventory.alternate[player_name] - local crafts = unified_inventory.crafts_table[item_name] - - if crafts ~= nil and #crafts>0 then - alternates = #crafts - local craft = crafts[alternate] - local method = "Crafting" - if craft.type == "shapeless" then - method="Crafting" - end - if craft.type == "cooking" then - method="Cooking" - end - if craft.type == "fuel" then - method="Fuel" - end - if craft.type == "grinding" then - method="Grinding" - end - if craft.type == "alloy" then - method="Alloy cooking" - end - if craft.type == "extracting" then - method="Extracting" - end - if craft.type == "compressing" then - method="Compressing" - end - formspec = formspec.."label[6,3;"..method.."]" - end - - if alternates > 1 then - formspec = formspec.."label[0,2.6;Recipe "..tostring(alternate).." of "..tostring(alternates).."]" - formspec = formspec.."button[0,3.15;2,1;alternate;Alternate]" - end - end - end - - -- bags - if page=="bags" then - formspec = formspec.."label[0,0;Bags]" - formspec=formspec.."button[0,2;2,0.5;bag1;Bag 1]" - formspec=formspec.."button[2,2;2,0.5;bag2;Bag 2]" - formspec=formspec.."button[4,2;2,0.5;bag3;Bag 3]" - formspec=formspec.."button[6,2;2,0.5;bag4;Bag 4]" - formspec=formspec.."list[detached:"..player_name.."_bags;bag1;0.5,1;1,1;]" - formspec=formspec.."list[detached:"..player_name.."_bags;bag2;2.5,1;1,1;]" - formspec=formspec.."list[detached:"..player_name.."_bags;bag3;4.5,1;1,1;]" - formspec=formspec.."list[detached:"..player_name.."_bags;bag4;6.5,1;1,1;]" - end - - for i=1,4 do - if page=="bag"..i then - local image = player:get_inventory():get_stack("bag"..i, 1):get_definition().inventory_image - formspec=formspec.."image[7,0;1,1;"..image.."]" - formspec=formspec.."list[current_player;bag"..i.."contents;0,1;8,3;]" - end - end - - --Items list - local list_index=unified_inventory.current_index[player_name] - local page=math.floor(list_index / (80) + 1) - local pagemax = math.floor((unified_inventory.filtered_items_list_size[player_name]-1) / (80) + 1) - local image - local item={} - for y=0,9,1 do - for x=0,7,1 do - name=unified_inventory.filtered_items_list[player_name][list_index] - if minetest.registered_items[name] then - formspec=formspec.."item_image_button["..(8.2+x*.7)..","..(1+y*.7)..";.81,.81;"..name..";item_button"..list_index..";]" - list_index=list_index+1 - end - end - end - formspec=formspec.."label[8.2,0;Page:]" - formspec=formspec.."label[9,0;"..page.." of "..pagemax.."]" - formspec=formspec.."label[8.2,0.4;Filter:]" - formspec=formspec.."label[9,0.4;"..unified_inventory.activefilter[player_name].."]" - return formspec -end - --- register_on_player_receive_fields -minetest.register_on_player_receive_fields(function(player, formname, fields) - local player_name = player:get_player_name() - - -- main buttons - if fields.craft then - unified_inventory.set_inventory_formspec(player, unified_inventory.get_formspec(player,"craft")) - minetest.sound_play("click", {to_player=player_name, gain = 0.1}) - return - end - - if fields.craftguide then - unified_inventory.set_inventory_formspec(player, unified_inventory.get_formspec(player,"craftguide")) - minetest.sound_play("click", {to_player=player_name, gain = 0.1}) - return - end - - if fields.bags then - unified_inventory.set_inventory_formspec(player, unified_inventory.get_formspec(player,"bags")) - minetest.sound_play("click", {to_player=player_name, gain = 0.1}) - return - end - - -- bags - for i=1,4 do - local page = "bag"..i - if fields[page] then - if player:get_inventory():get_stack(page, 1):get_definition().groups.bagslots==nil then - page = "bags" - end - unified_inventory.set_inventory_formspec(player, unified_inventory.get_formspec(player,page)) - minetest.sound_play("click", {to_player=player_name, gain = 0.1}) - return - end - end - - -- Miscellaneous - if fields.home_gui_set then - unified_inventory.set_home(player, player:getpos()) - local home = homepos[player_name] - if home ~= nil then - minetest.sound_play("dingdong", {to_player=player_name, gain = 1.0}) - minetest.chat_send_player(player_name, "Home position set to: "..math.floor(home.x)..","..math.floor(home.y)..","..math.floor(home.z)) - end - end - if fields.home_gui_go then - unified_inventory.set_inventory_formspec(player, unified_inventory.get_formspec(player,"craft")) - minetest.sound_play("teleport", {to_player=player_name, gain = 1.0}) - unified_inventory.go_home(player) - end - if fields.misc_set_day then - if minetest.get_player_privs(player_name).settime==true then - minetest.sound_play("birds", {to_player=player_name, gain = 1.0}) - minetest.env:set_timeofday((6000 % 24000) / 24000) - minetest.chat_send_player(player_name, "Time of day set to 6am") - else - minetest.chat_send_player(player_name, "You don't have settime priviledge!") - end - end - if fields.misc_set_night then - if minetest.get_player_privs(player_name).settime==true then - minetest.sound_play("owl", {to_player=player_name, gain = 1.0}) - minetest.env:set_timeofday((21000 % 24000) / 24000) - minetest.chat_send_player(player_name, "Time of day set to 9pm") - else - minetest.chat_send_player(player_name, "You don't have settime priviledge!") - end - end - - if fields.clear_inv then - local inventory = {} - player:get_inventory():set_list("main", inventory) - minetest.chat_send_player(player_name, 'Inventory Cleared!') - minetest.sound_play("trash_all", {to_player=player_name, gain = 1.0}) - end - - -- Inventory page controls - local start=math.floor(unified_inventory.current_index[player_name]/80 +1 ) - local start_i=start - local pagemax = math.floor((unified_inventory.filtered_items_list_size[player_name]-1) / (80) + 1) - - if fields.start_list then - minetest.sound_play("paperflip1", {to_player=player_name, gain = 1.0}) - start_i = 1 - end - if fields.rewind1 then - minetest.sound_play("paperflip1", {to_player=player_name, gain = 1.0}) - start_i = start_i - 1 - end - if fields.forward1 then - minetest.sound_play("paperflip1", {to_player=player_name, gain = 1.0}) - start_i = start_i + 1 - end - if fields.rewind3 then - minetest.sound_play("paperflip1", {to_player=player_name, gain = 1.0}) - start_i = start_i - 3 - end - if fields.forward3 then - minetest.sound_play("paperflip1", {to_player=player_name, gain = 1.0}) - start_i = start_i + 3 - end - if fields.end_list then - minetest.sound_play("paperflip1", {to_player=player_name, gain = 1.0}) - start_i = pagemax - end - if start_i < 1 then - start_i = 1 - end - if start_i > pagemax then - start_i = pagemax - end - if not (start_i ==start) then - unified_inventory.current_index[player_name] = (start_i-1)*80+1 - unified_inventory.set_inventory_formspec(player, unified_inventory.get_formspec(player,unified_inventory.current_page[player_name])) - end - - -- Item list buttons - local list_index=unified_inventory.current_index[player_name] - local page=unified_inventory.current_page[player_name] - for i=0,80,1 do - local button="item_button"..list_index - if fields[button] then - minetest.sound_play("click", {to_player=player_name, gain = 0.1}) - if minetest.setting_getbool("creative_mode")==false then - unified_inventory.set_inventory_formspec(player, unified_inventory.get_formspec(player,"craftguide")) - page="craftguide" - end - if page=="craftguide" then - unified_inventory.current_item[player_name] = unified_inventory.filtered_items_list[player_name][list_index] - unified_inventory.alternate[player_name] = 1 - unified_inventory.update_recipe (player, unified_inventory.filtered_items_list[player_name][list_index], 1) - unified_inventory.set_inventory_formspec(player, unified_inventory.get_formspec(player,unified_inventory.current_page[player_name])) - else - if minetest.setting_getbool("creative_mode") then - local inv = player:get_inventory() - dst_stack={} - dst_stack["name"] = unified_inventory.filtered_items_list[player_name][list_index] - dst_stack["count"]=99 - if inv:room_for_item("main",dst_stack) then - inv:add_item("main",dst_stack) - end - end - end - end - list_index=list_index+1 - end - - if fields.searchbutton then - unified_inventory.apply_filter(player, fields.searchbox) - unified_inventory.set_inventory_formspec(player, unified_inventory.get_formspec(player,unified_inventory.current_page[player_name])) - minetest.sound_play("paperflip2", {to_player=player_name, gain = 1.0}) - end - - -- alternate button - if fields.alternate then - minetest.sound_play("click", {to_player=player_name, gain = 0.1}) - local item_name=unified_inventory.current_item[player_name] - if item_name then - local alternates = 0 - local alternate=unified_inventory.alternate[player_name] - local crafts = unified_inventory.crafts_table[item_name] - if crafts ~= nil then - alternates = #crafts - end - if alternates > 1 then - alternate=alternate+1 - if alternate>alternates then - alternate=1 - end - unified_inventory.alternate[player_name]=alternate - unified_inventory.update_recipe (player, unified_inventory.current_item[player_name], alternate) - unified_inventory.set_inventory_formspec(player, unified_inventory.get_formspec(player,unified_inventory.current_page[player_name])) - end - end - end -end) -- load_home -local load_home = function() - local input = io.open(unified_inventory.home_filename..".home", "r") - if input then - while true do - local x = input:read("*n") - if x == nil then - break - end - local y = input:read("*n") - local z = input:read("*n") - local name = input:read("*l") - homepos[name:sub(2)] = {x = x, y = y, z = z} - end - io.close(input) - else - homepos = {} - end +local function load_home() + local input = io.open(unified_inventory.home_filename, "r") + if input then + while true do + local x = input:read("*n") + if x == nil then + break + end + local y = input:read("*n") + local z = input:read("*n") + local name = input:read("*l") + unified_inventory.home_pos[name:sub(2)] = {x = x, y = y, z = z} + end + io.close(input) + else + unified_inventory.home_pos = {} + end end -load_home() -- run it now +load_home() --- set_home -unified_inventory.set_home = function(player, pos) - local player_name=player:get_player_name() - homepos[player_name] = pos +function unified_inventory.set_home(player, pos) + local player_name = player:get_player_name() + unified_inventory.home_pos[player_name] = pos -- save the home data from the table to the file - local output = io.open(unified_inventory.home_filename..".home", "w") - for k, v in pairs(homepos) do + local output = io.open(unified_inventory.home_filename, "w") + for k, v in pairs(unified_inventory.home_pos) do if v ~= nil then - output:write(math.floor(v.x).." "..math.floor(v.y).." "..math.floor(v.z).." "..k.."\n") + output:write(math.floor(v.x).." " + ..math.floor(v.y).." " + ..math.floor(v.z).." " + ..k.."\n") end end io.close(output) end --- go_home -unified_inventory.go_home = function(player) - local pos = homepos[player:get_player_name()] - if pos~=nil then +function unified_inventory.go_home(player) + local pos = unified_inventory.home_pos[player:get_player_name()] + if pos ~= nil then player:setpos(pos) end end ---apply filter to the inventory list (create filtered copy of full one) -unified_inventory.apply_filter = function(player,filter) - local player_name = player:get_player_name() - local size=0 - local str_temp1=string.lower(filter) - if str_temp1 ~= "" then - for i=1,str_temp1:len(),1 do - if string.byte(str_temp1,i) == 91 then - str_temp1="" - end - end - end - local str_temp2 - local str_temp3 - unified_inventory.filtered_items_list[player_name]={} - for name,def in pairs(minetest.registered_items) do - if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) - and def.description and def.description ~= "" then - str_temp2=string.lower(def.name) - str_temp3=string.lower(def.description) - if string.find(str_temp2, str_temp1) or string.find(str_temp3, str_temp1) then - table.insert(unified_inventory.filtered_items_list[player_name], name) - size=size+1 - end - end - - end - table.sort(unified_inventory.filtered_items_list[player_name]) - unified_inventory.filtered_items_list_size[player_name]=size - unified_inventory.current_index[player_name]=1 - unified_inventory.activefilter[player_name]=filter - unified_inventory.set_inventory_formspec(player, unified_inventory.get_formspec(player,unified_inventory.current_page[player_name])) -end - - --- update_recipe -unified_inventory.update_recipe = function(player, stack_name, alternate) - local inv = minetest.get_inventory({type="detached", name=player:get_player_name().."craftrecipe"}) - for i=0,inv:get_size("build"),1 do - inv:set_stack("build", i, nil) - end - inv:set_stack("output", 1, nil) - alternate = tonumber(alternate) or 1 - local crafts = unified_inventory.crafts_table[stack_name] - print(dump(crafts)) - local next=next - if next(crafts) == nil then return end -- no craft recipes - if alternate < 1 or alternate > #crafts then - alternate = 1 - end - local craft = crafts[alternate] - inv:set_stack("output", 1, craft.output) - local items=craft.items - - -- cooking, fuel, grinding, and extracting recipes - if craft.type == "cooking" or - craft.type == "fuel" or - craft.type == "grinding" or - craft.type == "extracting" or - craft.type == "compressing" then - def=unified_inventory.find_item_def(craft["items"][1]) - if def then - inv:set_stack("build", 1, def) - end - return - end - if craft.width==0 then - local build_table={1,2,3} - for i=1,3,1 do - if craft.items[i] then - def=unified_inventory.find_item_def(craft.items[i]) - if def then inv:set_stack("build", build_table[i], def) end - end - end - end - if craft.width==1 then - local build_table={1,4,7} - for i=1,3,1 do - if craft.items[i] then - def=unified_inventory.find_item_def(craft.items[i]) - if def then inv:set_stack("build", build_table[i], def) end - end - end - end - if craft.width==2 then - local build_table={1,2,4,5,7,8} - for i=1,6,1 do - if craft.items[i] then - def=unified_inventory.find_item_def(craft.items[i]) - if def then inv:set_stack("build", build_table[i], def) end - end - end - end - if craft.width==3 then - for i=1,9,1 do - if craft.items[i] then - def=unified_inventory.find_item_def(craft.items[i]) - if def then inv:set_stack("build", i, def) end - end - end - end -end - -unified_inventory.find_item_def = function(def1) -if type(def1)=="string" then - if string.find(def1, "group:") then - def1=string.gsub(def1, "group:", "") - def1=string.gsub(def1, '\"', "") - local items=unified_inventory.items_in_group(def1) - return items[1] - else - return def1 - end -end -return nil -end - -unified_inventory.items_in_group = function(group) - local items = {} - for name, item in pairs(minetest.registered_items) do - for _, g in ipairs(group:split(',')) do - if item.groups[g] then - table.insert(items,name) - end - end - end - return items -end - -- register_craft -unified_inventory.register_craft = function(options) +function unified_inventory.register_craft(options) if options.output == nil then return end @@ -659,9 +77,29 @@ unified_inventory.register_craft = function(options) if itemstack:is_empty() then return end - if unified_inventory.crafts_table[itemstack:get_name()]==nil then + if unified_inventory.crafts_table[itemstack:get_name()] == nil then unified_inventory.crafts_table[itemstack:get_name()] = {} end table.insert(unified_inventory.crafts_table[itemstack:get_name()],options) - --crafts_table_count=crafts_table_count+1 +end + +function unified_inventory.register_page(name, def) + unified_inventory.pages[name] = def +end + +function unified_inventory.register_button(name, def) + if not def.action then + def.action = function(player) + unified_inventory.set_inventory_formspec(player, name) + end + end + def.name = name + table.insert(unified_inventory.buttons, def) +end + +function unified_inventory.is_creative(playername) + if (minetest.check_player_privs(playername, {creative=true}) and uniinv_creative) or + (minetest.setting_getbool("creative_mode") and uniinv_creative) then + return true + end end diff --git a/unified_inventory/bags.lua b/unified_inventory/bags.lua index b0ec4b8..2a21d5d 100644 --- a/unified_inventory/bags.lua +++ b/unified_inventory/bags.lua @@ -1,20 +1,75 @@ ---[[ +-- Bags for Minetest -Bags for Minetest +-- Copyright (c) 2012 cornernote, Brett O'Donnell +-- License: GPLv3 -Copyright (c) 2012 cornernote, Brett O'Donnell -Source Code: https://github.com/cornernote/minetest-particles -License: GPLv3 +unified_inventory.register_page("bags", { + get_formspec = function(player) + local player_name = player:get_player_name() + local formspec = "background[0.06,0.99;7.92,7.52;ui_bags_main_form.png]" + formspec = formspec.."label[0,0;Bags]" + formspec = formspec.."button[0,2;2,0.5;bag1;Bag 1]" + formspec = formspec.."button[2,2;2,0.5;bag2;Bag 2]" + formspec = formspec.."button[4,2;2,0.5;bag3;Bag 3]" + formspec = formspec.."button[6,2;2,0.5;bag4;Bag 4]" + formspec = formspec.."listcolors[#00000000;#00000000]" + formspec = formspec.."list[detached:"..player_name.."_bags;bag1;0.5,1;1,1;]" + formspec = formspec.."list[detached:"..player_name.."_bags;bag2;2.5,1;1,1;]" + formspec = formspec.."list[detached:"..player_name.."_bags;bag3;4.5,1;1,1;]" + formspec = formspec.."list[detached:"..player_name.."_bags;bag4;6.5,1;1,1;]" + return {formspec=formspec} + end, +}) -]]-- +unified_inventory.register_button("bags", { + type = "image", + image = "ui_bags_icon.png", +}) + +for i = 1, 4 do + unified_inventory.register_page("bag"..i, { + get_formspec = function(player) + local stack = player:get_inventory():get_stack("bag"..i, 1) + local image = stack:get_definition().inventory_image + local formspec = "image[7,0;1,1;"..image.."]" + formspec = formspec.."listcolors[#00000000;#00000000]" + formspec = formspec.."list[current_player;bag"..i.."contents;0,1;8,3;]" + local slots = stack:get_definition().groups.bagslots + if slots == 8 then + formspec = formspec.."background[0.06,0.99;7.92,7.52;ui_bags_sm_form.png]" + elseif slots == 16 then + formspec = formspec.."background[0.06,0.99;7.92,7.52;ui_bags_med_form.png]" + elseif slots == 24 then + formspec = formspec.."background[0.06,0.99;7.92,7.52;ui_bags_lg_form.png]" + end + return {formspec=formspec} + end, + }) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "" then + return + end + for i = 1, 4 do + if fields["bag"..i] then + local stack = player:get_inventory():get_stack("bag"..i, 1) + if not stack:get_definition().groups.bagslots then + return + end + unified_inventory.set_inventory_formspec(player, "bag"..i) + return + end + end +end) --- register_on_joinplayer minetest.register_on_joinplayer(function(player) local player_inv = player:get_inventory() local bags_inv = minetest.create_detached_inventory(player:get_player_name().."_bags",{ on_put = function(inv, listname, index, stack, player) player:get_inventory():set_stack(listname, index, stack) - player:get_inventory():set_size(listname.."contents", stack:get_definition().groups.bagslots) + player:get_inventory():set_size(listname.."contents", + stack:get_definition().groups.bagslots) end, on_take = function(inv, listname, index, stack, player) player:get_inventory():set_stack(listname, index, nil) @@ -27,7 +82,7 @@ minetest.register_on_joinplayer(function(player) end end, allow_take = function(inv, listname, index, stack, player) - if player:get_inventory():is_empty(listname.."contents")==true then + if player:get_inventory():is_empty(listname.."contents") then return stack:get_count() else return 0 @@ -41,7 +96,7 @@ minetest.register_on_joinplayer(function(player) local bag = "bag"..i player_inv:set_size(bag, 1) bags_inv:set_size(bag, 1) - bags_inv:set_stack(bag,1,player_inv:get_stack(bag,1)) + bags_inv:set_stack(bag, 1, player_inv:get_stack(bag, 1)) end end) @@ -51,11 +106,13 @@ minetest.register_tool("unified_inventory:bag_small", { inventory_image = "bags_small.png", groups = {bagslots=8}, }) + minetest.register_tool("unified_inventory:bag_medium", { description = "Medium Bag", inventory_image = "bags_medium.png", groups = {bagslots=16}, }) + minetest.register_tool("unified_inventory:bag_large", { description = "Large Bag", inventory_image = "bags_large.png", @@ -66,24 +123,27 @@ minetest.register_tool("unified_inventory:bag_large", { minetest.register_craft({ output = "unified_inventory:bag_small", recipe = { - {"", "default:stick", ""}, - {"default:wood", "default:wood", "default:wood"}, - {"default:wood", "default:wood", "default:wood"}, - }, + {"", "default:stick", ""}, + {"group:wood", "group:wood", "group:wood"}, + {"group:wood", "group:wood", "group:wood"}, + }, }) + minetest.register_craft({ output = "unified_inventory:bag_medium", recipe = { - {"", "default:stick", ""}, - {"unified_inventory:bag_small", "unified_inventory:bag_small", "unified_inventory:bag_small"}, - {"unified_inventory:bag_small", "unified_inventory:bag_small", "unified_inventory:bag_small"}, - }, + {"", "", ""}, + {"default:stick", "unified_inventory:bag_small", "default:stick"}, + {"default:stick", "unified_inventory:bag_small", "default:stick"}, + }, }) + minetest.register_craft({ output = "unified_inventory:bag_large", recipe = { - {"", "default:stick", ""}, - {"unified_inventory:bag_medium", "unified_inventory:bag_medium", "unified_inventory:bag_medium"}, - {"unified_inventory:bag_medium", "unified_inventory:bag_medium", "unified_inventory:bag_medium"}, + {"", "", ""}, + {"default:stick", "unified_inventory:bag_medium", "default:stick"}, + {"default:stick", "unified_inventory:bag_medium", "default:stick"}, }, }) + diff --git a/unified_inventory/callbacks.lua b/unified_inventory/callbacks.lua new file mode 100644 index 0000000..4640081 --- /dev/null +++ b/unified_inventory/callbacks.lua @@ -0,0 +1,179 @@ + +minetest.register_on_joinplayer(function(player) + local player_name = player:get_player_name() + unified_inventory.players[player_name] = {} + unified_inventory.current_index[player_name] = 1 + unified_inventory.filtered_items_list[player_name] = + unified_inventory.items_list + unified_inventory.activefilter[player_name] = "" + unified_inventory.apply_filter(player, "") + unified_inventory.alternate[player_name] = 1 + unified_inventory.current_item[player_name] = nil + unified_inventory.set_inventory_formspec(player, + unified_inventory.default) + + -- Crafting guide inventories + local inv = minetest.create_detached_inventory(player_name.."craftrecipe", { + allow_put = function(inv, listname, index, stack, player) + return 0 + end, + allow_take = function(inv, listname, index, stack, player) + return 0 + end, + allow_move = function(inv, from_list, from_index, to_list, + to_index, count, player) + return 0 + end, + }) + inv:set_size("output", 1) + + -- Refill slot + local refill = minetest.create_detached_inventory(player_name.."refill", { + allow_put = function(inv, listname, index, stack, player) + local player_name = player:get_player_name() + if unified_inventory.is_creative(player_name) then + return stack:get_count() + else + return 0 + end + end, + on_put = function(inv, listname, index, stack, player) + local player_name = player:get_player_name() + stack:set_count(stack:get_stack_max()) + inv:set_stack(listname, index, stack) + minetest.sound_play("electricity", + {to_player=player_name, gain = 1.0}) + end, + }) + refill:set_size("main", 1) +end) + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "" then + return + end + local player_name = player:get_player_name() + + for i, def in pairs(unified_inventory.buttons) do + if fields[def.name] then + def.action(player) + minetest.sound_play("click", + {to_player=player_name, gain = 0.1}) + return + end + end + + -- Inventory page controls + local start = math.floor( + unified_inventory.current_index[player_name] / 80 + 1) + local start_i = start + local pagemax = math.floor( + (#unified_inventory.filtered_items_list[player_name] - 1) + / (80) + 1) + + if fields.start_list then + minetest.sound_play("paperflip1", + {to_player=player_name, gain = 1.0}) + start_i = 1 + end + if fields.rewind1 then + minetest.sound_play("paperflip1", + {to_player=player_name, gain = 1.0}) + start_i = start_i - 1 + end + if fields.forward1 then + minetest.sound_play("paperflip1", + {to_player=player_name, gain = 1.0}) + start_i = start_i + 1 + end + if fields.rewind3 then + minetest.sound_play("paperflip1", + {to_player=player_name, gain = 1.0}) + start_i = start_i - 3 + end + if fields.forward3 then + minetest.sound_play("paperflip1", + {to_player=player_name, gain = 1.0}) + start_i = start_i + 3 + end + if fields.end_list then + minetest.sound_play("paperflip1", + {to_player=player_name, gain = 1.0}) + start_i = pagemax + end + if start_i < 1 then + start_i = 1 + end + if start_i > pagemax then + start_i = pagemax + end + if not (start_i == start) then + unified_inventory.current_index[player_name] = (start_i - 1) * 80 + 1 + unified_inventory.set_inventory_formspec(player, + unified_inventory.current_page[player_name]) + end + + local clicked_item = nil + for name, value in pairs(fields) do + if string.sub(name, 1, 12) == "item_button_" then + clicked_item = string.sub(name, 13) + break + end + end + if clicked_item then + minetest.sound_play("click", + {to_player=player_name, gain = 0.1}) + local page = unified_inventory.current_page[player_name] + if not unified_inventory.is_creative(player_name) then + page = "craftguide" + end + if page == "craftguide" then + unified_inventory.current_item[player_name] = clicked_item + unified_inventory.alternate[player_name] = 1 + unified_inventory.set_inventory_formspec(player, + "craftguide") + else + if unified_inventory.is_creative(player_name) then + local inv = player:get_inventory() + local stack = ItemStack(clicked_item) + stack:set_count(stack:get_stack_max()) + if inv:room_for_item("main", stack) then + inv:add_item("main", stack) + end + end + end + end + + if fields.searchbutton then + unified_inventory.apply_filter(player, fields.searchbox) + unified_inventory.set_inventory_formspec(player, + unified_inventory.current_page[player_name]) + minetest.sound_play("paperflip2", + {to_player=player_name, gain = 1.0}) + end + + -- alternate button + if fields.alternate then + minetest.sound_play("click", + {to_player=player_name, gain = 0.1}) + local item_name = unified_inventory.current_item[player_name] + if item_name then + local alternates = 0 + local alternate = unified_inventory.alternate[player_name] + local crafts = unified_inventory.crafts_table[item_name] + if crafts ~= nil then + alternates = #crafts + end + if alternates > 1 then + alternate = alternate + 1 + if alternate > alternates then + alternate = 1 + end + unified_inventory.alternate[player_name] = alternate + unified_inventory.set_inventory_formspec(player, + unified_inventory.current_page[player_name]) + end + end + end +end) + diff --git a/unified_inventory/depends.txt b/unified_inventory/depends.txt index 8b13789..8d390c8 100644 --- a/unified_inventory/depends.txt +++ b/unified_inventory/depends.txt @@ -1 +1 @@ - +creative? diff --git a/unified_inventory/init.lua b/unified_inventory/init.lua index cc170a0..b80f96a 100644 --- a/unified_inventory/init.lua +++ b/unified_inventory/init.lua @@ -1,11 +1,49 @@ --- Unified Inventory mod 0.4.6 +-- Unified Inventory for Minetest 0.4.8+ --- disable default creative inventory -if creative_inventory then - creative_inventory.set_creative_formspec = function(player, start_i, pagenum) - return +uniinv_creative = false + +if minetest.setting_getbool('uniinv_creative') ~= nil then + uniinv_creative = minetest.setting_getbool('uniinv_creative') +end + + +local modpath = minetest.get_modpath(minetest.get_current_modname()) +local worldpath = minetest.get_worldpath() + +-- Data tables definitions +unified_inventory = {} +unified_inventory.activefilter = {} +unified_inventory.alternate = {} +unified_inventory.current_page = {} +unified_inventory.current_index = {} +unified_inventory.current_item = {} +unified_inventory.crafts_table = {} +unified_inventory.crafts_table_count = 0 +unified_inventory.players = {} +unified_inventory.items_list_size = 0 +unified_inventory.items_list = {} +unified_inventory.filtered_items_list_size = {} +unified_inventory.filtered_items_list = {} +unified_inventory.pages = {} +unified_inventory.buttons = {} + +-- Homepos stuff +unified_inventory.home_pos = {} +unified_inventory.home_filename = + worldpath.."/unified_inventory_home.home" + +-- Default inventory page +unified_inventory.default = "craft" + +-- Disable default creative inventory +if creative_inventory and uniinv_creative then + function creative_inventory.set_creative_formspec(player, start_i, pagenum) + return end end -dofile(minetest.get_modpath("unified_inventory").."/api.lua") -dofile(minetest.get_modpath("unified_inventory").."/bags.lua") +dofile(modpath.."/api.lua") +dofile(modpath.."/internal.lua") +dofile(modpath.."/callbacks.lua") +dofile(modpath.."/register.lua") +dofile(modpath.."/bags.lua") diff --git a/unified_inventory/internal.lua b/unified_inventory/internal.lua new file mode 100644 index 0000000..3ea410e --- /dev/null +++ b/unified_inventory/internal.lua @@ -0,0 +1,136 @@ + +function unified_inventory.get_formspec(player, page) + if not player then + return "" + end + local player_name = player:get_player_name() + unified_inventory.current_page[player_name] = page + local pagedef = unified_inventory.pages[page] + + local formspec = "size[14,10]" + local fsdata = nil + + -- Background + formspec = formspec .. "background[-0.19,-0.25;14.4,10.75;ui_form_bg.png]" + -- Current page + if unified_inventory.pages[page] then + fsdata = pagedef.get_formspec(player) + formspec = formspec .. fsdata.formspec + else + return "" -- Invalid page name + end + + -- Main buttons + for i, def in pairs(unified_inventory.buttons) do + if def.type == "image" then + formspec = formspec.."image_button[" + ..(0.65 * (i - 1))..",9;0.8,0.8;" + ..minetest.formspec_escape(def.image)..";" + ..minetest.formspec_escape(def.name)..";]" + end + end + + if fsdata.draw_inventory ~= false then + -- Player inventory + formspec = formspec.."listcolors[#00000000;#00000000]" + formspec = formspec .. "list[current_player;main;0,4.5;8,4;]" + end + + if fsdata.draw_item_list == false then + return formspec + end + + -- Controls to flip items pages + local start_x = 9.2 + formspec = formspec .. "image_button["..(start_x + 0.6 * 0)..",9;.8,.8;ui_skip_backward_icon.png;start_list;]" + formspec = formspec .. "image_button["..(start_x + 0.6 * 1)..",9;.8,.8;ui_doubleleft_icon.png;rewind3;]" + formspec = formspec .. "image_button["..(start_x + 0.6 * 2)..",9;.8,.8;ui_left_icon.png;rewind1;]" + formspec = formspec .. "image_button["..(start_x + 0.6 * 3)..",9;.8,.8;ui_right_icon.png;forward1;]" + formspec = formspec .. "image_button["..(start_x + 0.6 * 4)..",9;.8,.8;ui_doubleright_icon.png;forward3;]" + formspec = formspec .. "image_button["..(start_x + 0.6 * 5)..",9;.8,.8;ui_skip_forward_icon.png;end_list;]" + + -- Search box + formspec = formspec .. "field[9.5,8.325;3,1;searchbox;;]" + formspec = formspec .. "image_button[12.2,8.1;.8,.8;ui_search_icon.png;searchbutton;]" + + -- Items list + local list_index = unified_inventory.current_index[player_name] + local page = math.floor(list_index / (80) + 1) + local pagemax = math.floor( + (#unified_inventory.filtered_items_list[player_name] - 1) + / (80) + 1) + local item = {} + for y = 0, 9 do + for x = 0, 7 do + name = unified_inventory.filtered_items_list[player_name][list_index] + if minetest.registered_items[name] then + formspec = formspec.."item_image_button[" + ..(8.2 + x * 0.7).."," + ..(1 + y * 0.7)..";.81,.81;" + ..name..";item_button_" + ..name..";]" + list_index = list_index + 1 + end + end + end + formspec = formspec.."label[8.2,0;Page:]" + formspec = formspec.."label[9,0;"..page.." of "..pagemax.."]" + formspec = formspec.."label[8.2,0.4;Filter:]" + formspec = formspec.."label[9,0.4;"..unified_inventory.activefilter[player_name].."]" + return formspec +end + +function unified_inventory.set_inventory_formspec(player, page) + if player then + local formspec = unified_inventory.get_formspec(player, page) + player:set_inventory_formspec(formspec) + end +end + +--apply filter to the inventory list (create filtered copy of full one) +function unified_inventory.apply_filter(player, filter) + local player_name = player:get_player_name() + local size = 0 + local lfilter = string.lower(filter) + if lfilter ~= "" then + for c in lfilter:gmatch(".") do + if c == '[' or c == ']' or c == '{' or c == '}' or + c == '(' or c == ')' or c == '%' then + lfilter = "" + break + end + end + end + unified_inventory.filtered_items_list[player_name]={} + for name, def in pairs(minetest.registered_items) do + if (not def.groups.not_in_creative_inventory or + def.groups.not_in_creative_inventory == 0) + and def.description and def.description ~= "" then + local lname = string.lower(name) + local ldesc = string.lower(def.description) + if string.find(lname, lfilter) or string.find(ldesc, lfilter) then + table.insert(unified_inventory.filtered_items_list[player_name], name) + size = size + 1 + end + end + + end + table.sort(unified_inventory.filtered_items_list[player_name]) + unified_inventory.filtered_items_list_size[player_name] = size + unified_inventory.current_index[player_name] = 1 + unified_inventory.activefilter[player_name] = filter + unified_inventory.set_inventory_formspec(player, + unified_inventory.current_page[player_name]) +end + +function unified_inventory.items_in_group(groups) + local items = {} + for name, item in pairs(minetest.registered_items) do + for _, group in pairs(groups:split(',')) do + if item.groups[group] then + table.insert(items, name) + end + end + end + return items +end diff --git a/unified_inventory/register.lua b/unified_inventory/register.lua new file mode 100644 index 0000000..2786642 --- /dev/null +++ b/unified_inventory/register.lua @@ -0,0 +1,305 @@ + +minetest.register_privilege("creative", { + description = "Can use the creative inventory", + give_to_singleplayer = false, +}) + +local trash = minetest.create_detached_inventory("trash", { + --allow_put = function(inv, listname, index, stack, player) + -- if unified_inventory.is_creative(player:get_player_name()) then + -- return stack:get_count() + -- else + -- return 0 + -- end + --end, + on_put = function(inv, listname, index, stack, player) + inv:set_stack(listname, index, nil) + local player_name = player:get_player_name() + minetest.sound_play("trash", {to_player=player_name, gain = 1.0}) + end, +}) +trash:set_size("main", 1) + +unified_inventory.register_button("craft", { + type = "image", + image = "ui_craft_icon.png", +}) + +unified_inventory.register_button("craftguide", { + type = "image", + image = "ui_craftguide_icon.png", +}) + +unified_inventory.register_button("home_gui_set", { + type = "image", + image = "ui_sethome_icon.png", + action = function(player) + local player_name = player:get_player_name() + unified_inventory.set_home(player, player:getpos()) + local home = unified_inventory.home_pos[player_name] + if home ~= nil then + minetest.sound_play("dingdong", + {to_player=player_name, gain = 1.0}) + minetest.chat_send_player(player_name, + "Home position set to: " + ..minetest.pos_to_string(home)) + end + end, +}) + +unified_inventory.register_button("home_gui_go", { + type = "image", + image = "ui_gohome_icon.png", + action = function(player) + minetest.sound_play("teleport", + {to_player=player:get_player_name(), gain = 1.0}) + unified_inventory.go_home(player) + end, +}) +if uniinv_creative then + unified_inventory.register_button("misc_set_day", { + type = "image", + image = "ui_sun_icon.png", + action = function(player) + local player_name = player:get_player_name() + if minetest.check_player_privs(player_name, {settime=true}) then + minetest.sound_play("birds", + {to_player=player_name, gain = 1.0}) + minetest.set_timeofday((6000 % 24000) / 24000) + minetest.chat_send_player(player_name, + "Time of day set to 6am") + else + minetest.chat_send_player(player_name, + "You don't have the" + .." settime priviledge!") + end + end, + }) + + unified_inventory.register_button("misc_set_night", { + type = "image", + image = "ui_moon_icon.png", + action = function(player) + local player_name = player:get_player_name() + if minetest.check_player_privs(player_name, {settime=true}) then + minetest.sound_play("owl", + {to_player=player_name, gain = 1.0}) + minetest.set_timeofday((21000 % 24000) / 24000) + minetest.chat_send_player(player_name, + "Time of day set to 9pm") + else + minetest.chat_send_player(player_name, + "You don't have the" + .." settime priviledge!") + end + end, + }) + + unified_inventory.register_button("clear_inv", { + type = "image", + image = "ui_trash_icon.png", + action = function(player) + local player_name = player:get_player_name() + if not unified_inventory.is_creative(player_name) then + minetest.chat_send_player(player_name, + "This button has been disabled outside" + .." of creative mode to prevent" + .." accidental inventory trashing." + .." Use the trash slot instead.") + return + end + player:get_inventory():set_list("main", {}) + minetest.chat_send_player(player_name, 'Inventory Cleared!') + minetest.sound_play("trash_all", + {to_player=player_name, gain = 1.0}) + end, + }) +end + +unified_inventory.register_page("craft", { + get_formspec = function(player, formspec) + local player_name = player:get_player_name() + local formspec = "background[0,1;8,3;ui_crafting_form.png]" + formspec = formspec.."background[0,4.5;8,4;ui_main_inventory.png]" + formspec = formspec.."label[0,0;Crafting]" + formspec = formspec.."listcolors[#00000000;#00000000]" + formspec = formspec.."list[current_player;craftpreview;6,1;1,1;]" + formspec = formspec.."list[current_player;craft;2,1;3,3;]" + formspec = formspec.."label[7,2.5;Trash:]" + formspec = formspec.."list[detached:trash;main;7,3;1,1;]" + if unified_inventory.is_creative(player_name) then + formspec = formspec.."label[0,2.5;Refill:]" + formspec = formspec.."list[detached:"..player_name.."refill;main;0,3;1,1;]" + end + return {formspec=formspec} + end, +}) + +unified_inventory.register_page("craftguide", { + get_formspec = function(player) + local player_name = player:get_player_name() + local formspec = "background[0,1;8,3;ui_craftguide_form.png]" + formspec = formspec.."background[0,4.5;8,4;ui_main_inventory.png]" + formspec = formspec.."label[0,0;Crafting Guide]" + formspec = formspec.."listcolors[#00000000;#00000000]" + formspec = formspec.."list[detached:"..player_name.."craftrecipe;output;6,1;1,1;]" + formspec = formspec.."label[6,3.35;Method:]" + local item_name = unified_inventory.current_item[player_name] + local craft = nil + if item_name then + formspec = formspec.."textarea[0.3,0.6;10,1;;Result: "..item_name..";]" + local alternates = 0 + local alternate = unified_inventory.alternate[player_name] + local crafts = unified_inventory.crafts_table[item_name] + if crafts ~= nil and #crafts > 0 then + alternates = #crafts + craft = crafts[alternate] + local method = craft.type + local allow_auto_craft = ((method == "normal") or (method == "shapeless")) + if craft.type == "normal" then + method = "crafting" + elseif craft.type == "shapeless" then + method = "shapeless crafting" + elseif craft.type == "alloy" then + method = "alloy cooking" + end + formspec = formspec.."label[6,3.75;"..method.."]" + if allow_auto_craft and uniinv_creative then + formspec = formspec.."label[6,1.95;Copy to craft grid:]" + formspec = formspec.."button[6,2.5;0.6,0.5;craftguide_craft_1;1]" + formspec = formspec.."button[6.6,2.5;0.6,0.5;craftguide_craft_10;10]" + formspec = formspec.."button[7.2,2.5;0.6,0.5;craftguide_craft_max;All]" + end + end + if alternates > 1 then + formspec = formspec.."label[0,2.6;Recipe " + ..tostring(alternate).." of " + ..tostring(alternates).."]" + formspec = formspec.."button[0,3.15;2,1;alternate;Alternate]" + end + end + + local craftinv = minetest.get_inventory({ + type = "detached", + name = player_name.."craftrecipe" + }) + + -- fake buttons just to make 3x3 grid + for y = 1, 3 do + for x = 1, 3 do + formspec = formspec.."image_button[" + ..(1.0 + x)..","..(0.0 + y)..";1.1,1.1;ui_blank_image.png;;]" + end + end + + if not craft then + craftinv:set_stack("output", 1, nil) + return {formspec=formspec} + end + + craftinv:set_stack("output", 1, craft.output) + + local width = craft.width + if width == 0 then + -- Shapeless recipe + width = 3 + end + + local i = 1 + for y = 1, 3 do + for x = 1, width do + local item = craft.items[i] + if item then + if string.sub(item, 1, 6) == "group:" then + local group = string.sub(item, 7) + formspec = formspec.."image_button[" + ..(1.0 + x)..","..(0.0 + y)..";1.1,1.1;" + .."ui_group.png;;" + ..minetest.formspec_escape(group).."]" + else + formspec = formspec.."item_image_button[" + ..(1.0 + x)..","..(0.0 + y)..";1.1,1.1;" + ..minetest.formspec_escape(item)..";" + .."item_button_" + ..minetest.formspec_escape(item)..";]" + end + end + i = i + 1 + end + end + return {formspec=formspec} + end, +}) + +minetest.register_on_player_receive_fields(function(player, formname, fields) + local amount + for k, v in pairs(fields) do + amount = k:match("craftguide_craft_(.*)") + if amount then break end + end + if not amount then return end + local player_name = player:get_player_name() + local recipe_inv = minetest.get_inventory({ + type="detached", + name=player_name.."craftrecipe", + }) + + local output = unified_inventory.current_item[player_name] + if (not output) or (output == "") then return end + + local player_inv = player:get_inventory() + + local crafts = unified_inventory.crafts_table[output] + if (not crafts) or (#crafts == 0) then return end + + local alternate = unified_inventory.alternate[player_name] + + local craft = crafts[alternate] + if craft.width > 3 then return end + + local needed = craft.items + + local craft_list = player_inv:get_list("craft") + + local width = craft.width + if width == 0 then + -- Shapeless recipe + width = 3 + end + + if amount == "max" then + amount = 99 -- Arbitrary; need better way to do this. + else + amount = tonumber(amount) + end + + for iter = 1, amount do + local index = 1 + for y = 1, 3 do + for x = 1, width do + local needed_item = needed[index] + if needed_item then + local craft_index = ((y - 1) * 3) + x + local craft_item = craft_list[craft_index] + if (not craft_item) or (craft_item:is_empty()) or (craft_item:get_name() == needed_item) then + itemname = craft_item and craft_item:get_name() or needed_item + local needed_stack = ItemStack(needed_item) + if player_inv:contains_item("main", needed_stack) then + local count = (craft_item and craft_item:get_count() or 0) + 1 + if count <= needed_stack:get_definition().stack_max then + local stack = ItemStack({name=needed_item, count=count}) + craft_list[craft_index] = stack + player_inv:remove_item("main", needed_stack) + end + end + end + end + index = index + 1 + end + end + end + + player_inv:set_list("craft", craft_list) + + unified_inventory.set_inventory_formspec(player, "craft") +end) diff --git a/unified_inventory/textures/ui_blank_image.png b/unified_inventory/textures/ui_blank_image.png new file mode 100644 index 0000000000000000000000000000000000000000..f9bcda27766a13c304f4070b0457303a68cebca5 GIT binary patch literal 143 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 literal 14631 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 FzX4^Gr9}V$ diff --git a/unified_inventory/textures/ui_crafting_form.png b/unified_inventory/textures/ui_crafting_form.png index bd21046c82be6ae85e598f8b17049f0bdd24e694..74389ed3f1cad297222836f2de39687adf380045 100644 GIT binary patch literal 11733 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 z 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 Un=G~BDgXcg07*qoM6N<$f@Jy7GXMYp literal 0 HcmV?d00001