diff --git a/mods/biome_lib/init.lua b/mods/biome_lib/init.lua index db565f0c..961a600d 100644 --- a/mods/biome_lib/init.lua +++ b/mods/biome_lib/init.lua @@ -34,7 +34,7 @@ local function tableize(s) return string.split(string.trim(string.gsub(s, " ", ""))) end -local c1 minetest.settings:get("biome_lib_default_grow_through_nodes") +local c1 = minetest.settings:get("biome_lib_default_grow_through_nodes") biome_lib.default_grow_through_nodes = {["air"] = true} if c1 then for _, i in ipairs(tableize(c1)) do @@ -44,7 +44,7 @@ else biome_lib.default_grow_through_nodes["default:snow"] = true end -local c2 minetest.settings:get("biome_lib_default_water_nodes") +local c2 = minetest.settings:get("biome_lib_default_water_nodes") biome_lib.default_water_nodes = {} if c2 then for _, i in ipairs(tableize(c2)) do diff --git a/mods/pipeworks/autocrafter.lua b/mods/pipeworks/autocrafter.lua index 313e1782..1d99bfe3 100644 --- a/mods/pipeworks/autocrafter.lua +++ b/mods/pipeworks/autocrafter.lua @@ -423,6 +423,7 @@ minetest.register_node("pipeworks:autocrafter", { }, }, }) +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:autocrafter" minetest.register_craft( { output = "pipeworks:autocrafter 2", diff --git a/mods/pipeworks/decorative_tubes.lua b/mods/pipeworks/decorative_tubes.lua index 1a4d386e..308330b2 100644 --- a/mods/pipeworks/decorative_tubes.lua +++ b/mods/pipeworks/decorative_tubes.lua @@ -28,6 +28,7 @@ minetest.register_node("pipeworks:steel_block_embedded_tube", { after_dig_node = pipeworks.after_dig, on_rotate = pipeworks.on_rotate, }) +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:steel_block_embedded_tube" minetest.register_craft( { output = "pipeworks:steel_block_embedded_tube 1", @@ -81,6 +82,7 @@ minetest.register_node("pipeworks:steel_pane_embedded_tube", { after_dig_node = pipeworks.after_dig, on_rotate = pipeworks.on_rotate, }) +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:steel_pane_embedded_tube" minetest.register_craft( { output = "pipeworks:steel_pane_embedded_tube 1", diff --git a/mods/pipeworks/devices.lua b/mods/pipeworks/devices.lua index 86b38eae..49875c8c 100644 --- a/mods/pipeworks/devices.lua +++ b/mods/pipeworks/devices.lua @@ -222,6 +222,8 @@ for s in ipairs(states) do new_flow_logic_register.directional_horizonal_rotate(nodename_valve_empty, true) end end +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:pump_off" +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:valve_off_empty" local nodename_valve_loaded = "pipeworks:valve_on_loaded" minetest.register_node(nodename_valve_loaded, { @@ -301,6 +303,7 @@ minetest.register_node("pipeworks:grating", { end, on_rotate = false }) +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:grating" -- outlet spigot @@ -378,6 +381,8 @@ minetest.register_node(nodename_spigot_loaded, { drop = "pipeworks:spigot", on_rotate = pipeworks.fix_after_rotation }) +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:spigot" + -- new flow logic does not currently distinguish between these two visual states. -- register both so existing flowing spigots continue to work (even if the visual doesn't match the spigot's behaviour). new_flow_logic_register.directional_horizonal_rotate(nodename_spigot_empty, false) @@ -441,6 +446,9 @@ minetest.register_node(nodename_panel_loaded, { drop = "pipeworks:entry_panel_empty", on_rotate = pipeworks.fix_after_rotation }) + +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:entry_panel_empty" + -- TODO: AFAIK the two panels have no visual difference, so are redundant under new flow logic - alias? new_flow_logic_register.directional_horizonal_rotate(nodename_panel_empty, true) new_flow_logic_register.directional_horizonal_rotate(nodename_panel_loaded, true) @@ -525,6 +533,8 @@ minetest.register_node(nodename_sensor_loaded, { mesecons = pipereceptor_on, on_rotate = pipeworks.fix_after_rotation }) +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:flow_sensor_empty" + new_flow_logic_register.directional_horizonal_rotate(nodename_sensor_empty, true) new_flow_logic_register.directional_horizonal_rotate(nodename_sensor_loaded, true) -- activate flow sensor at roughly half the pressure pumps drive pipes @@ -603,6 +613,7 @@ for fill = 0, 10 do on_rotate = false }) end +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:storage_tank_0" -- fountainhead @@ -639,6 +650,7 @@ minetest.register_node(nodename_fountain_empty, { }, on_rotate = false }) +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:fountainhead" local nodename_fountain_loaded = "pipeworks:fountainhead_pouring" minetest.register_node(nodename_fountain_loaded, { @@ -734,6 +746,7 @@ minetest.register_node(nodename_sp_loaded, { check_for_pole = pipeworks.check_for_vert_pipe, check_for_horiz_pole = pipeworks.check_for_horiz_pipe }) +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:straight_pipe_empty" new_flow_logic_register.directional_horizonal_rotate(nodename_sp_empty, true) new_flow_logic_register.directional_horizonal_rotate(nodename_sp_loaded, true) diff --git a/mods/pipeworks/filter-injector.lua b/mods/pipeworks/filter-injector.lua index a080a1f5..5ae3719f 100644 --- a/mods/pipeworks/filter-injector.lua +++ b/mods/pipeworks/filter-injector.lua @@ -14,17 +14,20 @@ local function set_filter_formspec(data, meta) local formspec if data.digiline then - formspec = "size[8,2.7]".. - "item_image[0,0;1,1;pipeworks:"..data.name.."]".. - "label[1,0;"..minetest.formspec_escape(itemname).."]".. - "field[0.3,1.5;8.0,1;channel;"..S("Channel")..";${channel}]".. - fs_helpers.cycling_button(meta, "button[0,2;4,1", "slotseq_mode", + formspec = + "size[8.5,3]".. + "item_image[0.2,0;1,1;pipeworks:"..data.name.."]".. + "label[1.2,0.2;"..minetest.formspec_escape(itemname).."]".. + "field[0.5,1.6;4.6,1;channel;"..S("Channel")..";${channel}]".. + "button[4.8,1.3;1.5,1;set_channel;"..S("Set").."]".. + fs_helpers.cycling_button(meta, "button[0.2,2.3;4.05,1", "slotseq_mode", {S("Sequence slots by Priority"), S("Sequence slots Randomly"), S("Sequence slots by Rotation")}).. - fs_helpers.cycling_button(meta, "button[4,2;4,1", "exmatch_mode", + fs_helpers.cycling_button(meta, "button[4.25,2.3;4.05,1", "exmatch_mode", {S("Exact match - off"), - S("Exact match - on")}) + S("Exact match - on")}).. + "button_exit[6.3,1.3;2,1;close;"..S("Close").."]" else local exmatch_button = "" if data.stackwise then @@ -425,10 +428,14 @@ for _, data in ipairs({ end node.on_receive_fields = function(pos, formname, fields, sender) - if not pipeworks.may_configure(pos, sender) then return end + if (fields.quit and not fields.key_enter_field) + or not pipeworks.may_configure(pos, sender) then + return + end + fs_helpers.on_receive_fields(pos, fields) - if fields.channel then + if fields.channel and (fields.key_enter_field == "channel" or fields.set_channel) then minetest.get_meta(pos):set_string("channel", fields.channel) end @@ -472,6 +479,7 @@ for _, data in ipairs({ minetest.register_node("pipeworks:"..data.name, node) + pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:"..data.name end minetest.register_craft( { diff --git a/mods/pipeworks/init.lua b/mods/pipeworks/init.lua index f13c2de8..f14b3ba3 100644 --- a/mods/pipeworks/init.lua +++ b/mods/pipeworks/init.lua @@ -5,6 +5,7 @@ -- pipeworks = {} +pipeworks.ui_cat_tube_list = {} pipeworks.worldpath = minetest.get_worldpath() pipeworks.modpath = minetest.get_modpath("pipeworks") @@ -148,4 +149,16 @@ end minetest.register_alias("pipeworks:pipe", "pipeworks:pipe_110000_empty") +-- Unified Inventory categories integration + +if unified_inventory and unified_inventory.registered_categories then + if not unified_inventory.registered_categories["automation"] then + unified_inventory.register_category("automation", { + symbol = "pipeworks:lua_tube000000", + label = "Automation components" + }) + end + unified_inventory.add_category_items("automation", pipeworks.ui_cat_tube_list) +end + minetest.log("info", "Pipeworks loaded!") diff --git a/mods/pipeworks/locale/pipeworks.fr.tr b/mods/pipeworks/locale/pipeworks.fr.tr index 4476431a..af5a45ed 100644 --- a/mods/pipeworks/locale/pipeworks.fr.tr +++ b/mods/pipeworks/locale/pipeworks.fr.tr @@ -3,6 +3,10 @@ # License: CC-by-SA 4.0 # Author: Louis Royer <4259825-lroyer@users.noreply.gitlab.com> +## generic interaction +Set=Fixer +Close=Fermer + ## digilines interfacing Channel=Canal @@ -86,11 +90,12 @@ Sorting pneumatic tube=Tuyau pneumatique triant ## teleport tube Receive=Reception -channels are public by default=Les canaux sont publics par défaut -use : for fully private channels=Utilisez : pour un canal entièrement privé -use ; for private receivers=Utilisez ; pour une réception privée +Channels are public by default=Les canaux sont publics par défaut +Use : for fully private channels=Utilisez : pour un canal entièrement privé +Use ; for private receivers=Utilisez ; pour une réception privée Teleporting Pneumatic Tube Segment=Segment de tuyau pneumatique téléporteur -unconfigured Teleportation Tube=Tuyau téléporteur non-configuré +Teleporting Tube=Tuyau pneumatique téléporteur +Unconfigured Teleportation Tube=Tuyau téléporteur non-configuré Sorry, channel '@1' is reserved for exclusive use by @2=Désolé, le canal '@1' est réservé exclusivement à l’utilisateur @2. Sorry, receiving from channel '@1' is reserved for @2=Désolé, la réception depuis le canal '@1' est réservée pour @2. Teleportation Tube @1 on '@2'=Tuyau de téléportation @1 sur '@2' @@ -102,7 +107,9 @@ Trash Can=Poubelle Pneumatic tube segment (legacy)=Segment de tuyau pneumatique (obsolète) ## vacuum tubes +Radius=Rayon Vacuuming Pneumatic Tube Segment=Segment de tuyau pneumatique aspirant +Adjustable Vacuuming Tube=Tuyau pneumatique aspirant réglable Adjustable Vacuuming Pneumatic Tube Segment=Segment de tuyau pneumatique aspirant réglable Adjustable Vacuuming Pneumatic Tube Segment (@1m)=Segment de tuyau pneumatique aspirant réglable (@1 m) diff --git a/mods/pipeworks/locale/pipeworks.zh_CN.tr b/mods/pipeworks/locale/pipeworks.zh_CN.tr index e71a67e3..c40b94d7 100644 --- a/mods/pipeworks/locale/pipeworks.zh_CN.tr +++ b/mods/pipeworks/locale/pipeworks.zh_CN.tr @@ -2,6 +2,10 @@ # License: CC-by-SA 4.0 # Author: pevernow <3450354617@qq.com> +## generic interaction +Set= +Cancel= + ## digilines interfacing Channel=频道 @@ -84,11 +88,12 @@ Sorting pneumatic tube=分类管道 ## teleport tube Receive=接收 -channels are public by default=频道默认为公开 -use : for fully private channels=将:用于完全私人的频道 -use ; for private receivers=使用;作为私人接收器 +Channels are public by default=频道默认为公开 +Use : for fully private channels=将:用于完全私人的频道 +Use ; for private receivers=使用;作为私人接收器 Teleporting Pneumatic Tube Segment=传送管道 -unconfigured Teleportation Tube=未配置的传送管道 +Teleporting Tube= +Unconfigured Teleportation Tube=未配置的传送管道 Sorry, channel '@1' is reserved for exclusive use by @2=抱歉,频道‘@1’保留供‘@2’专用 Sorry, receiving from channel '@1' is reserved for @2=抱歉,从频道'@1'接收的内容已保留给'@2' Teleportation Tube @1 on '@2'=传送管'@1'在'@2'上 @@ -100,7 +105,9 @@ Trash Can=垃圾箱 Pneumatic tube segment (legacy)=普通管道(旧式) ## vacuum tubes +Radius= Vacuuming Pneumatic Tube Segment=拾取管道 +Adjustable Vacuuming Tube= Adjustable Vacuuming Pneumatic Tube Segment=高级拾取管道 Adjustable Vacuuming Pneumatic Tube Segment (@1m)=高级拾取管道(@1m) diff --git a/mods/pipeworks/locale/template.txt b/mods/pipeworks/locale/template.txt index 4276875c..b9c5293f 100644 --- a/mods/pipeworks/locale/template.txt +++ b/mods/pipeworks/locale/template.txt @@ -3,6 +3,10 @@ # License: CC-by-SA 4.0 # Author: +## generic interaction +Set= +Cancel= + ## digilines interfacing Channel= @@ -86,11 +90,12 @@ Sorting pneumatic tube= ## teleport tube Receive= -channels are public by default= -use : for fully private channels= -use ; for private receivers= +Channels are public by default= +Use : for fully private channels= +Use ; for private receivers= Teleporting Pneumatic Tube Segment= -unconfigured Teleportation Tube= +Teleporting Tube= +Unconfigured Teleportation Tube= Sorry, channel '@1' is reserved for exclusive use by @2= Sorry, receiving from channel '@1' is reserved for @2= Teleportation Tube @1 on '@2'= @@ -102,7 +107,9 @@ Trash Can= Pneumatic tube segment (legacy)= ## vacuum tubes +Radius= Vacuuming Pneumatic Tube Segment= +Adjustable Vacuuming Tube= Adjustable Vacuuming Pneumatic Tube Segment= Adjustable Vacuuming Pneumatic Tube Segment (@1m)= diff --git a/mods/pipeworks/lua_tube.lua b/mods/pipeworks/lua_tube.lua index d5c7f8be..88001335 100644 --- a/mods/pipeworks/lua_tube.lua +++ b/mods/pipeworks/lua_tube.lua @@ -981,6 +981,8 @@ end end end +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = BASENAME.."000000" + ------------------------------------ -- Overheated Lua controlled Tube -- ------------------------------------ diff --git a/mods/pipeworks/mod.conf b/mods/pipeworks/mod.conf index 91ec0ef9..51979dc7 100644 --- a/mods/pipeworks/mod.conf +++ b/mods/pipeworks/mod.conf @@ -1,5 +1,5 @@ name = pipeworks description = This mod uses mesh nodes and nodeboxes to supply a complete set of 3D pipes and tubes, along with devices that work with them. depends = dreambuilder_theme_settings, default, basic_materials, screwdriver -optional_depends = mesecons, mesecons_mvps, digilines, signs_lib +optional_depends = mesecons, mesecons_mvps, digilines, signs_lib, unified_inventory min_minetest_version = 5.2.0 diff --git a/mods/pipeworks/pipes.lua b/mods/pipeworks/pipes.lua index 87877cba..befbbb9e 100644 --- a/mods/pipeworks/pipes.lua +++ b/mods/pipeworks/pipes.lua @@ -133,7 +133,7 @@ for index, connects in ipairs(cconnects) do new_flow_logic_register.simple(emptypipe) new_flow_logic_register.simple(fullpipe) end - +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:pipe_1_empty" if REGISTER_COMPATIBILITY then diff --git a/mods/pipeworks/routing_tubes.lua b/mods/pipeworks/routing_tubes.lua index 7a90fd4c..e7bc5968 100644 --- a/mods/pipeworks/routing_tubes.lua +++ b/mods/pipeworks/routing_tubes.lua @@ -31,7 +31,6 @@ end function pipeworks.check_and_wear_hammer(player) local itemstack = player:get_wielded_item() local wieldname = itemstack:get_name() - local playername = player:get_player_name() if allowed_hammers[wieldname] then itemstack:add_wear(1000) player:set_wielded_item(itemstack) @@ -193,6 +192,7 @@ if pipeworks.enable_one_way_tube then check_for_pole = pipeworks.check_for_vert_tube, check_for_horiz_pole = pipeworks.check_for_horiz_tube }) + pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:one_way_tube" minetest.register_craft({ output = "pipeworks:one_way_tube 2", recipe = { diff --git a/mods/pipeworks/signal_tubes.lua b/mods/pipeworks/signal_tubes.lua index d99afd3f..cabf4885 100644 --- a/mods/pipeworks/signal_tubes.lua +++ b/mods/pipeworks/signal_tubes.lua @@ -20,7 +20,6 @@ if pipeworks.enable_detector_tube then node_def = { tube = {can_go = function(pos, node, velocity, stack) local meta = minetest.get_meta(pos) - local name = minetest.get_node(pos).name local nitems = meta:get_int("nitems")+1 meta:set_int("nitems", nitems) local saved_pos = vector.new(pos) @@ -46,8 +45,6 @@ if pipeworks.enable_detector_tube then on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_int("nitems", 1) - local name = minetest.get_node(pos).name - local saved_pos = vector.new(pos) minetest.after(detector_tube_step, after_break, pos) end, }, @@ -99,13 +96,20 @@ if digiline_enabled and pipeworks.enable_digiline_detector_tube then on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_string("formspec", - "size[8.6,2.2]".. - "field[0.6,0.6;8,1;channel;"..S("Channel")..";${channel}]".. - "image[0.3,1.3;1,1;pipeworks_digiline_detector_tube_inv.png]".. - "label[1.6,1.2;"..S("Digiline Detecting Tube").."]" + "size[8.5,2.2]".. + "image[0.2,0;1,1;pipeworks_digiline_detector_tube_inv.png]".. + "label[1.2,0.2;"..S("Digiline Detecting Tube").."]".. + "field[0.5,1.6;4.6,1;channel;"..S("Channel")..";${channel}]".. + "button[4.8,1.3;1.5,1;set_channel;"..S("Set").."]".. + "button_exit[6.3,1.3;2,1;close;"..S("Close").."]" ) end, on_receive_fields = function(pos, formname, fields, sender) + if (fields.quit and not fields.key_enter_field) + or (fields.key_enter_field ~= "channel" and not fields.set_channel) + or not pipeworks.may_configure(pos, sender) then + return + end if fields.channel then minetest.get_meta(pos):set_string("channel", fields.channel) end diff --git a/mods/pipeworks/teleport_tube.lua b/mods/pipeworks/teleport_tube.lua index 0883c62f..0960a472 100644 --- a/mods/pipeworks/teleport_tube.lua +++ b/mods/pipeworks/teleport_tube.lua @@ -127,16 +127,22 @@ end local function update_meta(meta, can_receive) meta:set_int("can_receive", can_receive and 1 or 0) local cr_state = can_receive and "on" or "off" - meta:set_string("formspec","size[8.6,2.2]".. - "field[0.6,0.6;7,1;channel;"..S("Channel")..";${channel}]".. - "label[7.3,0;"..S("Receive").."]".. - "image_button[7.3,0.3;1,0.6;pipeworks_button_" .. cr_state .. ".png;cr" .. (can_receive and 0 or 1) .. ";;;false;pipeworks_button_interm.png]".. - "image[0.3,1.3;1,1;pipeworks_teleport_tube_inv.png]".. - "label[1.6,1.2;"..S("channels are public by default").."]" .. - "label[1.6,1.5;"..S("use : for fully private channels").."]" .. - "label[1.6,1.8;"..S("use \\; for private receivers").."]" .. - default.gui_bg.. - default.gui_bg_img) + local itext = S("Channels are public by default").."\n".. + S("Use : for fully private channels").."\n".. + S("Use \\; for private receivers") + + meta:set_string("formspec", + "size[8.5,3.5]".. + "image[0.2,o;1,1;pipeworks_teleport_tube_inv.png]".. + "label[1.2,0.2;"..S("Teleporting Tube").."]".. + "field[0.5,1.6;4.6,1;channel;"..S("Channel")..";${channel}]".. + "button[4.8,1.3;1.5,1;set_channel;"..S("Set").."]".. + "label[7.0,0;"..S("Receive").."]".. + "image_button[7.0,0.5;1,0.6;pipeworks_button_" .. cr_state .. ".png;cr" .. (can_receive and 0 or 1) .. ";;;false;pipeworks_button_interm.png]".. + "button_exit[6.3,1.3;2,1;close;"..S("Close").."]".. + "label[0.2,2.3;"..itext.."]".. + default.gui_bg.. + default.gui_bg_img) end pipeworks.register_tube("pipeworks:teleport_tube", { @@ -170,10 +176,11 @@ pipeworks.register_tube("pipeworks:teleport_tube", { on_construct = function(pos) local meta = minetest.get_meta(pos) update_meta(meta, true) - meta:set_string("infotext", S("unconfigured Teleportation Tube")) + meta:set_string("infotext", S("Unconfigured Teleportation Tube")) end, on_receive_fields = function(pos,formname,fields,sender) if not fields.channel -- ignore escaping or clientside manipulation of the form + or (fields.quit and not fields.key_enter_field) or not pipeworks.may_configure(pos, sender) then return end @@ -207,7 +214,7 @@ pipeworks.register_tube("pipeworks:teleport_tube", { -- was the channel changed? local channel = meta:get_string("channel") - if new_channel ~= channel then + if new_channel ~= channel and (fields.key_enter_field == "channel" or fields.set_channel) then channel = new_channel meta:set_string("channel", channel) dirty = true @@ -233,7 +240,7 @@ pipeworks.register_tube("pipeworks:teleport_tube", { else -- remove empty channel tubes, to not have to search through them remove_tube(pos) - meta:set_string("infotext", S("unconfigured Teleportation Tube")) + meta:set_string("infotext", S("Unconfigured Teleportation Tube")) end end end, diff --git a/mods/pipeworks/trashcan.lua b/mods/pipeworks/trashcan.lua index 20f3fb44..361d73ea 100644 --- a/mods/pipeworks/trashcan.lua +++ b/mods/pipeworks/trashcan.lua @@ -40,6 +40,7 @@ minetest.register_node("pipeworks:trashcan", { minetest.get_meta(pos):get_inventory():set_stack(listname, index, ItemStack("")) end, }) +pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:trashcan" minetest.register_craft({ output = "pipeworks:trashcan", diff --git a/mods/pipeworks/tube_registration.lua b/mods/pipeworks/tube_registration.lua index 60d7ff8e..e1859f98 100644 --- a/mods/pipeworks/tube_registration.lua +++ b/mods/pipeworks/tube_registration.lua @@ -200,6 +200,7 @@ local register_all_tubes = function(name, desc, plain, noctrs, ends, short, inv, end end end + pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = name.."_000000" else -- 6d tubes: uses only 10 nodes instead of 64, but the textures must be rotated local cconnects = {{}, {1}, {1, 2}, {1, 3}, {1, 3, 5}, {1, 2, 3}, {1, 2, 3, 5}, {1, 2, 3, 4}, {1, 2, 3, 4, 5}, {1, 2, 3, 4, 5, 6}} @@ -222,6 +223,7 @@ local register_all_tubes = function(name, desc, plain, noctrs, ends, short, inv, tube = {connect_sides = {front = 1, back = 1, left = 1, right = 1, top = 1, bottom = 1}}, drop = name.."_1", }) + pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = name.."_1" table.insert(tubenodes, cname) for xm = 0, 1 do for xp = 0, 1 do diff --git a/mods/pipeworks/vacuum_tubes.lua b/mods/pipeworks/vacuum_tubes.lua index b809f99b..927480b7 100644 --- a/mods/pipeworks/vacuum_tubes.lua +++ b/mods/pipeworks/vacuum_tubes.lua @@ -40,22 +40,31 @@ if pipeworks.enable_mese_sand_tube then on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_int("dist", 0) - meta:set_string("formspec", "size[2.1,0.8]".. - "image[0,0;1,1;pipeworks_mese_sand_tube_inv.png]".. - "field[1.3,0.4;1,1;dist;radius;${dist}]".. - default.gui_bg.. - default.gui_bg_img) + meta:set_string("formspec", + "size[6.0,2.2]".. + "image[0.2,0;1,1;pipeworks_mese_sand_tube_inv.png]".. + "label[1.2,0.2;"..S("Adjustable Vacuuming Tube").."]".. + "field[0.5,1.6;2.1,1;dist;"..S("Radius")..";${dist}]".. + "button[2.3,1.3;1.5,1;set_dist;"..S("Set").."]".. + "button_exit[3.8,1.3;2,1;close;"..S("Close").."]".. + default.gui_bg.. + default.gui_bg_img) meta:set_string("infotext", S("Adjustable Vacuuming Pneumatic Tube Segment")) end, on_receive_fields = function(pos,formname,fields,sender) - if not pipeworks.may_configure(pos, sender) then return end + if (fields.quit and not fields.key_enter_field) + or (fields.key_enter_field ~= "dist" and not fields.set_dist) + or not pipeworks.may_configure(pos, sender) then + return + end + local meta = minetest.get_meta(pos) local dist = tonumber(fields.dist) if dist then dist = math.max(0, dist) dist = math.min(8, dist) meta:set_int("dist", dist) - meta:set_string("infotext", (S("Adjustable Vacuuming Pneumatic Tube Segment (@1m)", dist))) + meta:set_string("infotext", S("Adjustable Vacuuming Pneumatic Tube Segment (@1m)", dist)) end end, }, diff --git a/mods/pipeworks/wielder.lua b/mods/pipeworks/wielder.lua index 393d91fc..f0d79e32 100644 --- a/mods/pipeworks/wielder.lua +++ b/mods/pipeworks/wielder.lua @@ -371,6 +371,7 @@ if pipeworks.enable_node_breaker then eject_drops = true, } register_wielder(data) + pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:nodebreaker_off" minetest.register_craft({ output = "pipeworks:nodebreaker_off", recipe = { @@ -422,6 +423,7 @@ if pipeworks.enable_deployer then end, eject_drops = false, }) + pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:deployer_off" minetest.register_craft({ output = "pipeworks:deployer_off", recipe = { @@ -457,6 +459,7 @@ if pipeworks.enable_dispenser then end, eject_drops = false, }) + pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:dispenser_off" minetest.register_craft({ output = "pipeworks:dispenser_off", recipe = { diff --git a/mods/unified_inventory/.luacheckrc b/mods/unified_inventory/.luacheckrc index 9fb6a7c1..e6fec97d 100644 --- a/mods/unified_inventory/.luacheckrc +++ b/mods/unified_inventory/.luacheckrc @@ -14,6 +14,7 @@ read_globals = { "ItemStack", "datastorage", "hb", + "doors", } files["callbacks.lua"].ignore = { "player", "draw_lite_mode" } diff --git a/mods/unified_inventory/callbacks.lua b/mods/unified_inventory/callbacks.lua index bc902375..1f43e398 100644 --- a/mods/unified_inventory/callbacks.lua +++ b/mods/unified_inventory/callbacks.lua @@ -19,6 +19,8 @@ minetest.register_on_joinplayer(function(player) unified_inventory.active_search_direction[player_name] = "nochange" unified_inventory.apply_filter(player, "", "nochange") unified_inventory.current_searchbox[player_name] = "" + unified_inventory.current_category[player_name] = "all" + unified_inventory.current_category_scroll[player_name] = 0 unified_inventory.alternate[player_name] = 1 unified_inventory.current_item[player_name] = nil unified_inventory.current_craft_direction[player_name] = "recipe" @@ -69,6 +71,41 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) unified_inventory.current_searchbox[player_name] = fields.searchbox end + + local clicked_category + for name, value in pairs(fields) do + local category_name = string.match(name, "^category_(.+)$") + if category_name then + clicked_category = category_name + break + end + end + + if clicked_category + and clicked_category ~= unified_inventory.current_category[player_name] then + unified_inventory.current_category[player_name] = clicked_category + unified_inventory.apply_filter(player, unified_inventory.current_searchbox[player_name], "nochange") + unified_inventory.set_inventory_formspec(player, + unified_inventory.current_page[player_name]) + end + + if fields.next_category then + local scroll = math.min(#unified_inventory.category_list-ui_peruser.pagecols, unified_inventory.current_category_scroll[player_name] + 1) + if scroll ~= unified_inventory.current_category_scroll[player_name] then + unified_inventory.current_category_scroll[player_name] = scroll + unified_inventory.set_inventory_formspec(player, + unified_inventory.current_page[player_name]) + end + end + if fields.prev_category then + local scroll = math.max(0, unified_inventory.current_category_scroll[player_name] - 1) + if scroll ~= unified_inventory.current_category_scroll[player_name] then + unified_inventory.current_category_scroll[player_name] = scroll + unified_inventory.set_inventory_formspec(player, + unified_inventory.current_page[player_name]) + end + end + for i, def in pairs(unified_inventory.buttons) do if fields[def.name] then def.action(player) @@ -126,6 +163,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) clicked_item = unified_inventory.demangle_for_formspec(mangled_item) if string.sub(clicked_item, 1, 6) == "group:" then -- Change search filter to this group + unified_inventory.current_category[player_name] = "all" apply_new_filter(player, clicked_item, new_dir) return end diff --git a/mods/unified_inventory/category.lua b/mods/unified_inventory/category.lua new file mode 100644 index 00000000..72e40382 --- /dev/null +++ b/mods/unified_inventory/category.lua @@ -0,0 +1,149 @@ +local S = minetest.get_translator("unified_inventory") + +unified_inventory.registered_categories = {} +unified_inventory.registered_category_items = {} +unified_inventory.category_list = {} + +local function char_to_sort_index(char_code) + if char_code <= 32 then + -- Command codes, no thanks + return 0 + end + if char_code <= 64 then + -- Sorts numbers, and some punctuation, after letters + return char_code + end + if char_code >= 158 then + -- Out of sortable range + return 0 + end + if char_code > 122 then + -- Avoids overlap with {, |, } and ~ + return char_code - 58 + end + if char_code > 96 then + -- Normalises lowercase with uppercase + return char_code - 96 + end + return char_code - 64 +end + +local function string_to_sort_index(str) + local max_chars = 5 + local power = 100 + local index = 0 + for i=1,math.min(#str, max_chars) do + index = index + (char_to_sort_index(string.byte(str, i))/(power^i)) + end + return index +end + +function update_category_list() + local category_list = {} + table.insert(category_list, { + name = "all", + label = S("All Items"), + symbol = "ui_category_all.png", + index = -2, + }) + table.insert(category_list, { + name = "uncategorized", + label = S("Misc. Items"), + symbol = "ui_category_none.png", + index = -1, + }) + for category, def in pairs(unified_inventory.registered_categories) do + table.insert(category_list, { + name = category, + label = def.label or category, + symbol = def.symbol, + index = def.index or -- sortby defined order + string_to_sort_index(category) -- or do a rudimentary alphabetical sort + }) + end + table.sort(category_list, function (a,b) + return a.index < b.index + end) + unified_inventory.category_list = category_list +end + +local function ensure_category_exists(category_name) + if not unified_inventory.registered_categories[category_name] then + unified_inventory.registered_categories[category_name] = { + symbol = "default:stick", + label = category_name + } + end + if not unified_inventory.registered_category_items[category_name] then + unified_inventory.registered_category_items[category_name] = {} + end +end + +function unified_inventory.register_category(category_name, config) + ensure_category_exists(category_name) + if config and config.symbol then + unified_inventory.set_category_symbol(category_name, config.symbol) + end + if config and config.label then + unified_inventory.set_category_label(category_name, config.label) + end + if config and config.index then + unified_inventory.set_category_index(category_name, config.index) + end + if config and config.items then + unified_inventory.add_category_items(category_name, config.items) + end + update_category_list() +end +function unified_inventory.set_category_symbol(category_name, symbol) + ensure_category_exists(category_name) + unified_inventory.registered_categories[category_name].symbol = symbol + update_category_list() +end +function unified_inventory.set_category_label(category_name, label) + ensure_category_exists(category_name) + unified_inventory.registered_categories[category_name].label = label + update_category_list() +end +function unified_inventory.set_category_index(category_name, index) + ensure_category_exists(category_name) + unified_inventory.registered_categories[category_name].index = index + update_category_list() +end +function unified_inventory.add_category_item(category_name, item) + ensure_category_exists(category_name) + unified_inventory.registered_category_items[category_name][item] = true +end +function unified_inventory.add_category_items(category_name, items) + for _,item in ipairs(items) do + unified_inventory.add_category_item(category_name, item) + end +end + +function unified_inventory.remove_category_item(category_name, item) + unified_inventory.registered_category_items[category_name][item] = nil +end +function unified_inventory.remove_category(category_name) + unified_inventory.registered_categories[category_name] = nil + unified_inventory.registered_category_items[category_name] = nil + update_category_list() +end + +function unified_inventory.find_category(item) + -- Returns the first category the item exists in + -- Best for checking if an item has any category at all + for category, items in pairs(unified_inventory.registered_category_items) do + if items[item] then return category end + end +end +function unified_inventory.find_categories(item) + -- Returns all the categories the item exists in + -- Best for listing all categories + local categories = {} + for category, items in pairs(unified_inventory.registered_category_items) do + if items[item] then + table.insert(categories, category) + end + end + return categories +end diff --git a/mods/unified_inventory/default-categories.lua b/mods/unified_inventory/default-categories.lua new file mode 100644 index 00000000..57d3e887 --- /dev/null +++ b/mods/unified_inventory/default-categories.lua @@ -0,0 +1,704 @@ +local S = minetest.get_translator("unified_inventory") + +unified_inventory.register_category('plants', { + symbol = "flowers:tulip", + label = S("Plant Life") +}) +unified_inventory.register_category('building', { + symbol = "default:brick", + label = S("Building Materials") +}) +unified_inventory.register_category('tools', { + symbol = "default:pick_diamond", + label = S("Tools") +}) +unified_inventory.register_category('minerals', { + symbol = "default:iron_lump", + label = S("Minerals and Metals") +}) +unified_inventory.register_category('environment', { + symbol = "default:dirt_with_grass", + label = S("Environment and Worldgen") +}) +unified_inventory.register_category('lighting', { + symbol = "default:torch", + label = S("Lighting") +}) + + +if unified_inventory.automatic_categorization then + minetest.register_on_mods_loaded(function() + + -- Add biome nodes to environment category + for _,def in pairs(minetest.registered_biomes) do + local env_nodes = { + def.node_riverbed, def.node_top, def.node_filler, def.node_dust, + } + for i,node in pairs(env_nodes) do + if node then + unified_inventory.add_category_item('environment', node) + end + end + end + + -- Add minable ores to minerals and everything else (pockets of stone & sand variations) to environment + for _,item in pairs(minetest.registered_ores) do + if item.ore_type == "scatter" then + local drop = minetest.registered_nodes[item.ore].drop + if drop and drop ~= "" then + unified_inventory.add_category_item('minerals', item.ore) + unified_inventory.add_category_item('minerals', drop) + else + unified_inventory.add_category_item('environment', item.ore) + end + else + unified_inventory.add_category_item('environment', item.ore) + end + end + + -- Add items by item definition + for name, def in pairs(minetest.registered_items) do + local group = def.groups or {} + if not group.not_in_creative_inventory then + if group.stair or + group.slab or + group.wall or + group.fence then + unified_inventory.add_category_item('building', name) + elseif group.flora or + group.flower or + group.seed or + group.leaves or + group.sapling or + group.tree then + unified_inventory.add_category_item('plants', name) + elseif def.type == 'tool' then + unified_inventory.add_category_item('tools', name) + elseif def.liquidtype == 'source' then + unified_inventory.add_category_item('environment', name) + elseif def.light_source and def.light_source > 0 then + unified_inventory.add_category_item('lighting', name) + elseif group.door or + minetest.global_exists("doors") and ( + doors.registered_doors and doors.registered_doors[name..'_a'] or + doors.registered_trapdoors and doors.registered_trapdoors[name] + ) then + unified_inventory.add_category_item('building', name) + end + end + end + end) +end + +-- [[ +unified_inventory.add_category_items('plants', { + "default:dry_grass_5", + "default:acacia_sapling", + "default:blueberry_bush_sapling", + "default:grass_2", + "default:pine_bush_stem", + "default:leaves", + "default:pine_needles", + "default:cactus", + "default:junglegrass", + "default:pine_sapling", + "default:sapling", + "default:bush_stem", + "default:dry_grass_2", + "default:fern_1", + "default:grass_3", + "default:marram_grass_1", + "default:pine_tree", + "default:dry_grass_3", + "default:dry_shrub", + "default:grass_4", + "default:marram_grass_2", + "default:jungleleaves", + "default:apple", + "default:tree", + "default:aspen_tree", + "default:bush_sapling", + "default:grass_5", + "default:blueberry_bush_leaves_with_berries", + "default:acacia_bush_sapling", + "default:grass_1", + "default:aspen_leaves", + "default:marram_grass_3", + "default:large_cactus_seedling", + "default:junglesapling", + "default:dry_grass_4", + "default:acacia_bush_stem", + "default:papyrus", + "default:pine_bush_needles", + "default:bush_leaves", + "default:fern_3", + "default:aspen_sapling", + "default:acacia_tree", + "default:apple_mark", + "default:acacia_leaves", + "default:jungletree", + "default:dry_grass_1", + "default:acacia_bush_leaves", + "default:emergent_jungle_sapling", + "default:fern_2", + "default:blueberries", + "default:sand_with_kelp", + "default:blueberry_bush_leaves", + "default:pine_bush_sapling", + + "farming:cotton", + "farming:cotton_1", + "farming:cotton_2", + "farming:cotton_3", + "farming:cotton_4", + "farming:cotton_5", + "farming:cotton_6", + "farming:cotton_7", + "farming:cotton_8", + "farming:cotton_wild", + "farming:seed_cotton", + "farming:seed_wheat", + "farming:straw", + "farming:wheat", + "farming:wheat_1", + "farming:wheat_2", + "farming:wheat_3", + "farming:wheat_4", + "farming:wheat_5", + "farming:wheat_6", + "farming:wheat_7", + "farming:wheat_8", + + "flowers:chrysanthemum_green", + "flowers:dandelion_white", + "flowers:dandelion_yellow", + "flowers:geranium", + "flowers:mushroom_brown", + "flowers:mushroom_red", + "flowers:rose", + "flowers:tulip", + "flowers:tulip_black", + "flowers:viola", + "flowers:waterlily", + "flowers:waterlily_waving", +}) + +unified_inventory.add_category_items('tools', { + "default:sword_diamond", + "default:axe_diamond", + "default:shovel_diamond", + "default:axe_steel", + "default:shovel_mese", + "default:sword_wood", + "default:pick_bronze", + "default:axe_stone", + "default:sword_stone", + "default:pick_stone", + "default:shovel_stone", + "default:sword_mese", + "default:shovel_bronze", + "default:sword_bronze", + "default:axe_bronze", + "default:shovel_steel", + "default:sword_steel", + "default:axe_mese", + "default:shovel_wood", + "default:pick_mese", + "default:axe_wood", + "default:pick_diamond", + "default:pick_wood", + "default:pick_steel", + + "farming:hoe_bronze", + "farming:hoe_diamond", + "farming:hoe_mese", + "farming:hoe_steel", + "farming:hoe_stone", + "farming:hoe_wood", + + "fire:flint_and_steel", + "map:mapping_kit", + "screwdriver:screwdriver", + + "fireflies:bug_net", + "bucket:bucket_empty", + + "binoculars:binoculars", + "default:skeleton_key", +}) + +unified_inventory.add_category_items('minerals', { + "default:stone_with_copper", + "default:stone_with_gold", + "default:stone_with_iron", + "default:copper_ingot", + "default:copper_lump", + "default:gold_lump", + "default:diamondblock", + "default:stone_with_diamond", + "default:stone_with_mese", + "default:steel_ingot", + "default:gold_ingot", + "default:iron_lump", + "default:tinblock", + "default:tin_lump", + "default:stone_with_tin", + "default:mese_crystal", + "default:diamond", + "default:bronze_ingot", + "default:mese", + "default:mese_crystal_fragment", + "default:copperblock", + "default:stone_with_coal", + "default:steelblock", + "default:tin_ingot", + "default:coalblock", + "default:coal_lump", + "default:bronzeblock", + "default:goldblock", + + "stairs:slab_bronzeblock", + "stairs:slab_copperblock", + "stairs:slab_steelblock", + "stairs:slab_tinblock", + "stairs:stair_bronzeblock", + "stairs:stair_copperblock", + "stairs:stair_inner_bronzeblock", + "stairs:stair_inner_copperblock", + "stairs:stair_inner_steelblock", + "stairs:stair_inner_tinblock", + "stairs:stair_outer_bronzeblock", + "stairs:stair_outer_copperblock", + "stairs:stair_outer_steelblock", + "stairs:stair_outer_tinblock", + "stairs:stair_steelblock", + "stairs:stair_tinblock", +}) + +unified_inventory.add_category_items('building', { + "default:fence_rail_aspen_wood", + "default:fence_rail_acacia_wood", + "default:fence_junglewood", + "default:fence_rail_junglewood", + "default:fence_aspen_wood", + "default:fence_pine_wood", + "default:fence_rail_wood", + "default:fence_rail_pine_wood", + "default:fence_acacia_wood", + "default:junglewood", + "default:acacia_wood", + "default:aspen_wood", + "default:fence_wood", + "default:pine_wood", + "default:silver_sandstone", + "default:desert_sandstone", + "default:sandstone_block", + "default:desert_sandstone_brick", + "default:stone_block", + "default:stonebrick", + "default:obsidian_glass", + "default:desert_sandstone_block", + "default:silver_sandstone_brick", + "default:brick", + "default:obsidianbrick", + "default:sandstonebrick", + "default:sandstone", + "default:desert_stone_block", + "default:silver_sandstone_block", + "default:wood", + "default:obsidian_block", + "default:glass", + "default:clay_brick", + "default:desert_stonebrick", + "default:desert_cobble", + "default:cobble", + "default:mossycobble", + + "doors:door_glass", + "doors:door_glass_a", + "doors:door_glass_b", + "doors:door_glass_c", + "doors:door_glass_d", + "doors:door_obsidian_glass", + "doors:door_obsidian_glass_a", + "doors:door_obsidian_glass_b", + "doors:door_obsidian_glass_c", + "doors:door_obsidian_glass_d", + "doors:door_steel", + "doors:door_steel_a", + "doors:door_steel_b", + "doors:door_steel_c", + "doors:door_steel_d", + "doors:door_wood", + "doors:door_wood_a", + "doors:door_wood_b", + "doors:door_wood_c", + "doors:door_wood_d", + "doors:gate_acacia_wood_closed", + "doors:gate_acacia_wood_open", + "doors:gate_aspen_wood_closed", + "doors:gate_aspen_wood_open", + "doors:gate_junglewood_closed", + "doors:gate_junglewood_open", + "doors:gate_pine_wood_closed", + "doors:gate_pine_wood_open", + "doors:gate_wood_closed", + "doors:gate_wood_open", + "doors:hidden", + "doors:trapdoor", + "doors:trapdoor_open", + "doors:trapdoor_steel", + "doors:trapdoor_steel_open", + + "stairs:slab_bronzeblock", + "stairs:slab_copperblock", + "stairs:slab_steelblock", + "stairs:slab_tinblock", + "stairs:stair_bronzeblock", + "stairs:stair_copperblock", + "stairs:stair_inner_bronzeblock", + "stairs:stair_inner_copperblock", + "stairs:stair_inner_steelblock", + "stairs:stair_inner_tinblock", + "stairs:stair_outer_bronzeblock", + "stairs:stair_outer_copperblock", + "stairs:stair_outer_steelblock", + "stairs:stair_outer_tinblock", + "stairs:stair_steelblock", + "stairs:stair_tinblock", + + "stairs:slab_acacia_wood", + "stairs:slab_aspen_wood", + "stairs:slab_brick", + "stairs:slab_cobble", + "stairs:slab_desert_cobble", + "stairs:slab_desert_sandstone", + "stairs:slab_desert_sandstone_block", + "stairs:slab_desert_sandstone_brick", + "stairs:slab_desert_stone", + "stairs:slab_desert_stone_block", + "stairs:slab_desert_stonebrick", + "stairs:slab_glass", + "stairs:slab_goldblock", + "stairs:slab_ice", + "stairs:slab_junglewood", + "stairs:slab_mossycobble", + "stairs:slab_obsidian", + "stairs:slab_obsidian_block", + "stairs:slab_obsidian_glass", + "stairs:slab_obsidianbrick", + "stairs:slab_pine_wood", + "stairs:slab_sandstone", + "stairs:slab_sandstone_block", + "stairs:slab_sandstonebrick", + "stairs:slab_silver_sandstone", + "stairs:slab_silver_sandstone_block", + "stairs:slab_silver_sandstone_brick", + "stairs:slab_snowblock", + "stairs:slab_stone", + "stairs:slab_stone_block", + "stairs:slab_stonebrick", + "stairs:slab_straw", + "stairs:slab_wood", + "stairs:stair_acacia_wood", + "stairs:stair_aspen_wood", + "stairs:stair_brick", + "stairs:stair_cobble", + "stairs:stair_desert_cobble", + "stairs:stair_desert_sandstone", + "stairs:stair_desert_sandstone_block", + "stairs:stair_desert_sandstone_brick", + "stairs:stair_desert_stone", + "stairs:stair_desert_stone_block", + "stairs:stair_desert_stonebrick", + "stairs:stair_glass", + "stairs:stair_goldblock", + "stairs:stair_ice", + "stairs:stair_inner_acacia_wood", + "stairs:stair_inner_aspen_wood", + "stairs:stair_inner_brick", + "stairs:stair_inner_cobble", + "stairs:stair_inner_desert_cobble", + "stairs:stair_inner_desert_sandstone", + "stairs:stair_inner_desert_sandstone_block", + "stairs:stair_inner_desert_sandstone_brick", + "stairs:stair_inner_desert_stone", + "stairs:stair_inner_desert_stone_block", + "stairs:stair_inner_desert_stonebrick", + "stairs:stair_inner_glass", + "stairs:stair_inner_goldblock", + "stairs:stair_inner_ice", + "stairs:stair_inner_junglewood", + "stairs:stair_inner_mossycobble", + "stairs:stair_inner_obsidian", + "stairs:stair_inner_obsidian_block", + "stairs:stair_inner_obsidian_glass", + "stairs:stair_inner_obsidianbrick", + "stairs:stair_inner_pine_wood", + "stairs:stair_inner_sandstone", + "stairs:stair_inner_sandstone_block", + "stairs:stair_inner_sandstonebrick", + "stairs:stair_inner_silver_sandstone", + "stairs:stair_inner_silver_sandstone_block", + "stairs:stair_inner_silver_sandstone_brick", + "stairs:stair_inner_snowblock", + "stairs:stair_inner_stone", + "stairs:stair_inner_stone_block", + "stairs:stair_inner_stonebrick", + "stairs:stair_inner_straw", + "stairs:stair_inner_wood", + "stairs:stair_junglewood", + "stairs:stair_mossycobble", + "stairs:stair_obsidian", + "stairs:stair_obsidian_block", + "stairs:stair_obsidian_glass", + "stairs:stair_obsidianbrick", + "stairs:stair_outer_acacia_wood", + "stairs:stair_outer_aspen_wood", + "stairs:stair_outer_brick", + "stairs:stair_outer_cobble", + "stairs:stair_outer_desert_cobble", + "stairs:stair_outer_desert_sandstone", + "stairs:stair_outer_desert_sandstone_block", + "stairs:stair_outer_desert_sandstone_brick", + "stairs:stair_outer_desert_stone", + "stairs:stair_outer_desert_stone_block", + "stairs:stair_outer_desert_stonebrick", + "stairs:stair_outer_glass", + "stairs:stair_outer_goldblock", + "stairs:stair_outer_ice", + "stairs:stair_outer_junglewood", + "stairs:stair_outer_mossycobble", + "stairs:stair_outer_obsidian", + "stairs:stair_outer_obsidian_block", + "stairs:stair_outer_obsidian_glass", + "stairs:stair_outer_obsidianbrick", + "stairs:stair_outer_pine_wood", + "stairs:stair_outer_sandstone", + "stairs:stair_outer_sandstone_block", + "stairs:stair_outer_sandstonebrick", + "stairs:stair_outer_silver_sandstone", + "stairs:stair_outer_silver_sandstone_block", + "stairs:stair_outer_silver_sandstone_brick", + "stairs:stair_outer_snowblock", + "stairs:stair_outer_stone", + "stairs:stair_outer_stone_block", + "stairs:stair_outer_stonebrick", + "stairs:stair_outer_straw", + "stairs:stair_outer_wood", + "stairs:stair_pine_wood", + "stairs:stair_sandstone", + "stairs:stair_sandstone_block", + "stairs:stair_sandstonebrick", + "stairs:stair_silver_sandstone", + "stairs:stair_silver_sandstone_block", + "stairs:stair_silver_sandstone_brick", + "stairs:stair_snowblock", + "stairs:stair_stone", + "stairs:stair_stone_block", + "stairs:stair_stonebrick", + "stairs:stair_straw", + "stairs:stair_wood", + + "xpanes:bar", + "xpanes:bar_flat", + "xpanes:door_steel_bar", + "xpanes:door_steel_bar_a", + "xpanes:door_steel_bar_b", + "xpanes:door_steel_bar_c", + "xpanes:door_steel_bar_d", + "xpanes:obsidian_pane", + "xpanes:obsidian_pane_flat", + "xpanes:pane", + "xpanes:pane_flat", + "xpanes:trapdoor_steel_bar", + "xpanes:trapdoor_steel_bar_open", + + "walls:cobble", + "walls:desertcobble", + "walls:mossycobble", +}) + +unified_inventory.add_category_items('environment', { + "air", + "default:cave_ice", + "default:dirt_with_rainforest_litter", + "default:gravel", + "default:dry_dirt_with_dry_grass", + "default:permafrost", + "default:desert_stone", + "default:ice", + "default:dry_dirt", + "default:obsidian", + "default:sand", + "default:river_water_source", + "default:dirt_with_snow", + "default:dirt_with_grass", + "default:water_flowing", + "default:dirt", + "default:desert_sand", + "default:permafrost_with_moss", + "default:dirt_with_coniferous_litter", + "default:water_source", + "default:dirt_with_dry_grass", + "default:river_water_flowing", + "default:stone", + "default:snow", + "default:lava_flowing", + "default:lava_source", + "default:permafrost_with_stones", + "default:dirt_with_grass_footsteps", + "default:silver_sand", + "default:snowblock", + "default:clay", + + "farming:desert_sand_soil", + "farming:desert_sand_soil_wet", + "farming:dry_soil", + "farming:dry_soil_wet", + "farming:soil", + "farming:soil_wet", +}) + +unified_inventory.add_category_items('lighting', { + "default:mese_post_light_junglewood", + "default:torch_ceiling", + "default:meselamp", + "default:torch", + "default:mese_post_light_acacia_wood", + "default:mese_post_light", + "default:torch_wall", + "default:mese_post_light_pine_wood", + "default:mese_post_light_aspen_wood" +}) +--]] + + +--[[ UNCATEGORISED + + "farming:string", + + "beds:bed_bottom", + "beds:bed_top", + "beds:fancy_bed_bottom", + "beds:fancy_bed_top", + "boats:boat", + "bones:bones", + + "bucket:bucket_lava", + "bucket:bucket_river_water", + "bucket:bucket_water", + + "butterflies:butterfly_red", + "butterflies:butterfly_violet", + "butterflies:butterfly_white", + "butterflies:hidden_butterfly_red", + "butterflies:hidden_butterfly_violet", + "butterflies:hidden_butterfly_white", + + "carts:brakerail", + "carts:cart", + "carts:powerrail", + "carts:rail", + + "default:book", + "default:book_written", + "default:bookshelf", + "default:chest", + "default:chest_locked", + "default:chest_locked_open", + "default:chest_open", + "default:clay_lump", + "default:cloud", + "default:coral_brown", + "default:coral_cyan", + "default:coral_green", + "default:coral_orange", + "default:coral_pink", + "default:coral_skeleton", + "default:flint", + "default:furnace", + "default:furnace_active", + "default:key", + "default:ladder_steel", + "default:ladder_wood", + "default:obsidian_shard", + "default:paper", + "default:sign_wall_steel", + "default:sign_wall_wood", + "default:stick", + + "fire:basic_flame", + "fire:permanent_flame", + "fireflies:firefly", + "fireflies:firefly_bottle", + "fireflies:hidden_firefly", + + "ignore", + "unknown", + + "tnt:boom", + "tnt:gunpowder", + "tnt:gunpowder_burning", + "tnt:tnt", + "tnt:tnt_burning", + "tnt:tnt_stick", + + "vessels:drinking_glass", + "vessels:glass_bottle", + "vessels:glass_fragments", + "vessels:shelf", + "vessels:steel_bottle", + + "dye:black", + "dye:blue", + "dye:brown", + "dye:cyan", + "dye:dark_green", + "dye:dark_grey", + "dye:green", + "dye:grey", + "dye:magenta", + "dye:orange", + "dye:pink", + "dye:red", + "dye:violet", + "dye:white", + "dye:yellow", + + "wool:black", + "wool:blue", + "wool:brown", + "wool:cyan", + "wool:dark_green", + "wool:dark_grey", + "wool:green", + "wool:grey", + "wool:magenta", + "wool:orange", + "wool:pink", + "wool:red", + "wool:violet", + "wool:white", + "wool:yellow", + + "unified_inventory:bag_large", + "unified_inventory:bag_medium", + "unified_inventory:bag_small", +--]] + +--[[ LIST UNCATEGORIZED AFTER LOAD +minetest.register_on_mods_loaded(function() + minetest.after(1, function ( ) + local l = {} + for name,_ in pairs(minetest.registered_items) do + if not unified_inventory.find_category(name) then + -- minetest.log("error", minetest.serialize(minetest.registered_items[name])) + table.insert(l, name) + end + end + table.sort(l) + minetest.log(table.concat(l, '",'.."\n"..'"')) + end) +end) +--]] \ No newline at end of file diff --git a/mods/unified_inventory/doc/mod_api.txt b/mods/unified_inventory/doc/mod_api.txt index 0d100a08..ff527920 100644 --- a/mods/unified_inventory/doc/mod_api.txt +++ b/mods/unified_inventory/doc/mod_api.txt @@ -101,3 +101,72 @@ Register a non-standard craft recipe: -- ^ Same as `minetest.register_recipe` }) + +Categories +---------- + +Register a new category: + The config table (second argument) is optional, and all its members are optional + See the unified_inventory.set_category_* functions for more details on the members of the config table + + unified_inventory.register_category("category_name", { + symbol = "mod_name:item_name" or "texture.png", + label = "Human Readable Label", + index = 5, + items = { + "mod_name:item_name", + "another_mod:different_item" + } + }) + +Add / override the symbol for a category: + The category does not need to exist first + The symbol can be an item name or a texture image + If unset this will default to "default:stick" + + unified_inventory.set_category_symbol("category_name", "mod_name:item_name" or "texture.png") + +Add / override the human readable label for a category: + If unset this will default to the category name + + unified_inventory.set_category_label("category_name", "Human Readable Label") + +Add / override the sorting index of the category: + Must be a number, can also be negative (-5) or fractional (2.345) + This determines the position the category appears in the list of categories + The "all" meta-category has index -2, the "misc"/"uncategorized" meta-category has index -1, use a negative number smaller than these to make a category appear before these in the list + By default categories are sorted alphabetically with an index between 0.0101(AA) and 0.2626(ZZ) + + unified_inventory.set_category_index("category_name", 5) + +Add a single item to a category: + + unified_inventory.add_category_item("category_name", "mod_name:item_name") + +Add multiple items to a category: + + unified_inventory.add_category_items("category_name", { + "mod_name:item_name", + "another_mod:different_item" + }) + +Remove an item from a category: + + unified_inventory.remove_category_item("category_name", "mod_name:item_name") + +Remove a category entirely: + + unified_inventory.remove_category("category_name") + +Finding existing items in categories: + This will find the first category an item exists in + It should be used for checking if an item is catgorised + Returns "category_name" or nil + + unified_inventory.find_category("mod_name:item_name") + + + This will find all the categories an item exists in + Returns a number indexed table (list) of category names + + unified_inventory.find_categories("mod_name:item_name") diff --git a/mods/unified_inventory/init.lua b/mods/unified_inventory/init.lua index f12ce477..6e24b865 100644 --- a/mods/unified_inventory/init.lua +++ b/mods/unified_inventory/init.lua @@ -10,6 +10,8 @@ unified_inventory = { alternate = {}, current_page = {}, current_searchbox = {}, + current_category = {}, + current_category_scroll = {}, current_index = {}, current_item = {}, current_craft_direction = {}, @@ -33,6 +35,9 @@ unified_inventory = { -- "Lite" mode lite_mode = minetest.settings:get_bool("unified_inventory_lite"), + -- Items automatically added to categories based on item definitions + automatic_categorization = (minetest.settings:get_bool("unified_inventory_automatic_categorization") ~= false), + -- Trash enabled trash_enabled = (minetest.settings:get_bool("unified_inventory_trash") ~= false), imgscale = 1.25, @@ -52,9 +57,9 @@ ui.style_full = { formw = 17.75, formh = 12.25, pagecols = 8, - pagerows = 10, + pagerows = 9, page_x = 10.75, - page_y = 1.45, + page_y = 2.30, craft_x = 2.8, craft_y = 1.15, craftresult_x = 7.8, @@ -85,9 +90,9 @@ ui.style_lite = { formw = 14, formh = 9.75, pagecols = 4, - pagerows = 6, + pagerows = 5, page_x = 10.5, - page_y = 1.25, + page_y = 2.15, craft_x = 2.6, craft_y = 0.75, craftresult_x = 5.75, @@ -100,9 +105,9 @@ ui.style_lite = { craft_guide_resultstr_y = 0.35, give_btn_x = 0.15, main_button_x = 10.5, - main_button_y = 7.9, + main_button_y = 8.15, page_buttons_x = 10.5, - page_buttons_y = 6.3, + page_buttons_y = 6.15, searchwidth = 1.6, form_header_x = 0.2, form_header_y = 0.2, @@ -149,6 +154,8 @@ if sfinv then end dofile(modpath.."/group.lua") +dofile(modpath.."/category.lua") +dofile(modpath.."/default-categories.lua") dofile(modpath.."/internal.lua") dofile(modpath.."/callbacks.lua") dofile(modpath.."/match_craft.lua") diff --git a/mods/unified_inventory/internal.lua b/mods/unified_inventory/internal.lua index 29097556..0249ee24 100644 --- a/mods/unified_inventory/internal.lua +++ b/mods/unified_inventory/internal.lua @@ -25,6 +25,20 @@ function ui.get_per_player_formspec(player_name) return table.copy(draw_lite_mode and ui.style_lite or ui.style_full), draw_lite_mode end +local function formspec_button(ui_peruser, name, image, offset, pos, scale, label) + local element = 'image_button' + if minetest.registered_items[image] then + element = 'item_image_button' + end + local spc = (1-scale)*ui_peruser.btn_size/2 + local size = ui_peruser.btn_size*scale + return string.format("%s[%f,%f;%f,%f;%s;%s;]", element, + (offset.x or offset[1]) + ( ui_peruser.btn_spc * (pos.x or pos[1]) ) + spc, + (offset.y or offset[2]) + ( ui_peruser.btn_spc * (pos.y or pos[2]) ) + spc, + size, size, image, name) .. + string.format("tooltip[%s;%s]", name, F(label or name)) +end + function ui.get_formspec(player, page) if not player then @@ -110,6 +124,48 @@ function ui.get_formspec(player, page) return table.concat(formspec, "") end + -- Category filters + + local categories_pos = { ui_peruser.page_x, ui_peruser.page_y-ui_peruser.btn_spc-0.5 } + local categories_scroll_pos = { ui_peruser.page_x, ui_peruser.form_header_y-(draw_lite_mode and 0 or 0.2) } + + formspec[n] = string.format("background9[%f,%f;%f,%f;%s;false;3]", + ui_peruser.page_x-0.1, categories_scroll_pos[2], + (ui_peruser.btn_spc * ui_peruser.pagecols) + 0.13, 1.4+(draw_lite_mode and 0 or 0.2), + "ui_smallbg_9_sliced.png") + n = n + 1 + + formspec[n] = string.format("label[%f,%f;%s]", ui_peruser.page_x, ui_peruser.form_header_y+(draw_lite_mode and 0.3 or 0.2), "Category:") + n = n + 1 + + local scroll_offset = 0 + local category_count = #unified_inventory.category_list + if category_count > ui_peruser.pagecols then + scroll_offset = unified_inventory.current_category_scroll[player_name] + end + + for index, category in ipairs(unified_inventory.category_list) do + local column = index - scroll_offset + if column > 0 and column <= ui_peruser.pagecols then + local scale = 0.8 + if unified_inventory.current_category[player_name] == category.name then + scale = 1 + end + formspec[n] = formspec_button(ui_peruser, "category_"..category.name, category.symbol, categories_pos, {column-1, 0}, scale, category.label) + n = n + 1 + end + end + if category_count > ui_peruser.pagecols and scroll_offset > 0 then + -- prev + formspec[n] = formspec_button(ui_peruser, "prev_category", "ui_left_icon.png", categories_scroll_pos, {ui_peruser.pagecols - 2, 0}, 0.8, S("Scroll categories left")) + n = n + 1 + end + if category_count > ui_peruser.pagecols and category_count - scroll_offset > ui_peruser.pagecols then + -- next + formspec[n] = formspec_button(ui_peruser, "next_category", "ui_right_icon.png", categories_scroll_pos, {ui_peruser.pagecols - 1, 0}, 0.8, S("Scroll categories right")) + n = n + 1 + end + -- Search box formspec[n] = "field_close_on_enter[searchbox;false]" @@ -208,16 +264,16 @@ function ui.get_formspec(player, page) end end formspec[n] = string.format("label[%f,%f;%s: %s]", - ui_peruser.page_x, ui_peruser.form_header_y, + ui_peruser.page_buttons_x + ui_peruser.btn_spc * (draw_lite_mode and 1 or 2), + ui_peruser.page_buttons_y + 0.1 + ui_peruser.btn_spc * 2, F(S("Page")), S("@1 of @2",page2,pagemax)) end n= n+1 if ui.activefilter[player_name] ~= "" then - formspec[n] = string.format("label[%f,%f;%s:]", - ui_peruser.page_x, ui_peruser.page_y - 0.65, F(S("Filter"))) - formspec[n+1] = string.format("label[%f,%f;%s]", - ui_peruser.page_x, ui_peruser.page_y - 0.25, F(ui.activefilter[player_name])) + formspec[n] = string.format("label[%f,%f;%s: %s]", + ui_peruser.page_x, ui_peruser.page_y - 0.25, + F(S("Filter")), F(ui.activefilter[player_name])) end return table.concat(formspec, "") end @@ -228,6 +284,13 @@ function ui.set_inventory_formspec(player, page) end end +local function valid_def(def) + return (not def.groups.not_in_creative_inventory + or def.groups.not_in_creative_inventory == 0) + and def.description + and def.description ~= "" +end + --apply filter to the inventory list (create filtered copy of full one) function ui.apply_filter(player, filter, search_dir) if not player then @@ -259,13 +322,30 @@ function ui.apply_filter(player, filter, search_dir) end end ui.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 ~= "" - and ffilter(name, def) then - table.insert(ui.filtered_items_list[player_name], name) + local category = ui.current_category[player_name] or 'all' + if category == 'all' then + for name, def in pairs(minetest.registered_items) do + if valid_def(def) + and ffilter(name, def) then + table.insert(ui.filtered_items_list[player_name], name) + end + end + elseif category == 'uncategorized' then + for name, def in pairs(minetest.registered_items) do + if (not ui.find_category(name)) + and valid_def(def) + and ffilter(name, def) then + table.insert(ui.filtered_items_list[player_name], name) + end + end + else + for name,exists in pairs(ui.registered_category_items[category]) do + local def = minetest.registered_items[name] + if exists and def + and valid_def(def) + and ffilter(name, def) then + table.insert(ui.filtered_items_list[player_name], name) + end end end table.sort(ui.filtered_items_list[player_name]) diff --git a/mods/unified_inventory/settingtypes.txt b/mods/unified_inventory/settingtypes.txt index 910989fd..27768ac2 100644 --- a/mods/unified_inventory/settingtypes.txt +++ b/mods/unified_inventory/settingtypes.txt @@ -9,3 +9,6 @@ unified_inventory_bags (Enable bags) bool true #If enabled, the trash slot can be used by those without both creative #and the give privilege. unified_inventory_trash (Enable trash) bool true + + +unified_inventory_automatic_categorization (Items automatically added to categories) bool true \ No newline at end of file diff --git a/mods/unified_inventory/textures/ui_category_all.png b/mods/unified_inventory/textures/ui_category_all.png new file mode 100644 index 00000000..0af7a537 Binary files /dev/null and b/mods/unified_inventory/textures/ui_category_all.png differ diff --git a/mods/unified_inventory/textures/ui_category_none.png b/mods/unified_inventory/textures/ui_category_none.png new file mode 100644 index 00000000..8976fb0e Binary files /dev/null and b/mods/unified_inventory/textures/ui_category_none.png differ diff --git a/mods/unified_inventory/textures/ui_smallbg_9_sliced.png b/mods/unified_inventory/textures/ui_smallbg_9_sliced.png new file mode 100644 index 00000000..865e0c96 Binary files /dev/null and b/mods/unified_inventory/textures/ui_smallbg_9_sliced.png differ