local modname = minetest.get_current_modname() local ci = {} ci.blocks = {all = {}, nodes = {}, tools = {}, items = {}} ci.pages = {} ci.searches = {} -- Layout-Einstellungen local columns = 15 local rows = 10 local nodes_per_page = columns * rows minetest.register_privilege("ci", { description = "Allows the player to use the ci command", give_to_singleplayer = false }) local function has_permission(player_name) return minetest.check_player_privs(player_name, {ci=true}) end -- Deep Scan mit Kategorisierung minetest.register_on_mods_loaded(function() minetest.after(1, function() ci.blocks = {all = {}, nodes = {}, tools = {}, items = {}} local added = {} local function add_to_list(name, def) if not name or name == "" or added[name] or not def then return end local d = name if def.description and def.description ~= "" then d = def.description:split("\n")[1] end local entry = {name = name, desc = d} if def.type == "node" then table.insert(ci.blocks.nodes, entry) elseif def.type == "tool" then table.insert(ci.blocks.tools, entry) else table.insert(ci.blocks.items, entry) end table.insert(ci.blocks.all, entry) added[name] = true end for name, def in pairs(minetest.registered_items) do add_to_list(name, def) end for name, target in pairs(minetest.registered_aliases) do local def = minetest.registered_items[target] if def then add_to_list(name, def) end end local function sort_func(a, b) local val_a = a.desc or a.name or "" local val_b = b.desc or b.name or "" return val_a:lower() < val_b:lower() end table.sort(ci.blocks.all, sort_func) table.sort(ci.blocks.nodes, sort_func) table.sort(ci.blocks.tools, sort_func) table.sort(ci.blocks.items, sort_func) print("[ci] Scan fertig. " .. #ci.blocks.all .. " Items bereit.") end) end) function ci.get_filtered_list(player_name) local state = ci.pages[player_name] local category = state.tab or "all" local raw_list = ci.blocks[category] or ci.blocks.all local search_term = ci.searches[player_name] if not search_term or search_term == "" then return raw_list end local filtered = {} local term = search_term:lower() for i=1, #raw_list do local entry = raw_list[i] if entry.name:lower():find(term, 1, true) or entry.desc:lower():find(term, 1, true) then table.insert(filtered, entry) end end return filtered end function ci.get_formspec(player) local player_name = player:get_player_name() if not ci.pages[player_name] then ci.pages[player_name] = {page = 1, quantity = 1, tab = "all"} end local state = ci.pages[player_name] local filtered = ci.get_filtered_list(player_name) local total_pages = math.max(1, math.ceil(#filtered / nodes_per_page)) if state.page > total_pages then state.page = total_pages end local tabs = {"all", "nodes", "tools", "items"} local tab_labels = {"Alle", "Blöcke", "Werkzeuge", "Gegenstände"} local current_tab_idx = 1 for i, t in ipairs(tabs) do if t == state.tab then current_tab_idx = i end end local formspec = "size[17.5,14.2]" .. "background[0,0;17.5,14.2;gui_formbg.png;true]" .. "tabheader[0,0;tab;" .. table.concat(tab_labels, ",") .. ";" .. current_tab_idx .. ";true;false]" -- 1. Controls oben local search = ci.searches[player_name] or "" formspec = formspec .. "field[0.75,0.8;5.5,1;search;Suche im Tab:;" .. minetest.formspec_escape(search) .. "]" .. "button[6.1,0.45;1.5,1;do_search;Suchen]" .. "button[7.6,0.45;0.8,1;reset_search;X]" .. "field[13.0,0.8;4,1;quantity;Anzahl:;" .. state.quantity .. "]" -- 2. Item-Grid local start_idx = (state.page - 1) * nodes_per_page + 1 local end_idx = math.min(state.page * nodes_per_page, #filtered) for i = start_idx, end_idx do local entry = filtered[i] local rel = i - start_idx local x = 0.5 + (rel % columns) * 1.1 local y = 1.8 + math.floor(rel / columns) * 1.1 local name_esc = minetest.formspec_escape(entry.name) local desc_esc = minetest.formspec_escape(entry.desc or entry.name) formspec = formspec .. "box[" .. x .. "," .. y .. ";1,1;#33333355]" .. "item_image_button[" .. x .. "," .. y .. ";1,1;" .. name_esc .. ";add_" .. name_esc .. ";]" .. "tooltip[add_" .. name_esc .. ";" .. desc_esc .. "\n" .. name_esc .. " ]" end -- 3. Navigation local footer_y = 13.5 -- Label ÜBER den Buttons formspec = formspec .. "label[7.5," .. (footer_y - 0.75) .. ";Seite " .. state.page .. " von " .. total_pages .. " (" .. #filtered .. " Items)]" if state.page > 1 then formspec = formspec .. "button[6.0," .. (footer_y - 0.2) .. ";1.2,0.8;prev;<<]" end if state.page < total_pages then formspec = formspec .. "button[10.3," .. (footer_y - 0.2) .. ";1.2,0.8;next;>>]" end formspec = formspec .. "button_exit[15.0," .. (footer_y - 0.2) .. ";2,0.8;exit;Schließen]" return formspec end minetest.register_chatcommand("ci", { description = "Kreativ-Inventar öffnen", privs = {ci=true}, func = function(name) local player = minetest.get_player_by_name(name) if player then if not ci.pages[name] then ci.pages[name] = {page = 1, quantity = 1, tab = "all"} end minetest.show_formspec(name, modname .. ":form", ci.get_formspec(player)) end return true end, }) minetest.register_on_player_receive_fields(function(player, formname, fields) if formname ~= modname .. ":form" then return end local name = player:get_player_name() local state = ci.pages[name] if not state then return end if fields.tab then local tabs = {"all", "nodes", "tools", "items"} state.tab = tabs[tonumber(fields.tab)] or "all" state.page = 1 minetest.show_formspec(name, modname .. ":form", ci.get_formspec(player)) return end if fields.quantity then state.quantity = tonumber(fields.quantity) or 1 end if fields.do_search or (fields.key_enter_field == "search") then ci.searches[name] = fields.search state.page = 1 minetest.show_formspec(name, modname .. ":form", ci.get_formspec(player)) return elseif fields.reset_search then ci.searches[name] = nil state.page = 1 minetest.show_formspec(name, modname .. ":form", ci.get_formspec(player)) return end if fields.next then state.page = state.page + 1 minetest.show_formspec(name, modname .. ":form", ci.get_formspec(player)) elseif fields.prev then state.page = math.max(1, state.page - 1) minetest.show_formspec(name, modname .. ":form", ci.get_formspec(player)) end for field, _ in pairs(fields) do if field:sub(1, 4) == "add_" then local item = field:sub(5) local inv = player:get_inventory() inv:add_item("main", item .. " " .. state.quantity) local def = minetest.registered_items[item] local desc = (def and def.description and def.description ~= "") and def.description:split("\n")[1] or item minetest.chat_send_player(name, "Hinzugefügt: " .. state.quantity .. "x " .. desc .. " [" .. item .. "]") minetest.show_formspec(name, modname .. ":form", ci.get_formspec(player)) return end end end) minetest.after(0, function() if minetest.global_exists("i3_extrabuttons") then i3_extrabuttons.new_tab("cinventory", { description = "Kreativ-Inventar", priv = "ci", formspec = function(player, data, fs) end, fields = function(player, data, fields) i3.set_tab(player, "inventory") minetest.show_formspec(player:get_player_name(), modname .. ":form", ci.get_formspec(player)) end, }) end end)