From 3b9d57e88357c0864a1c9cbcc740e3731e10a292 Mon Sep 17 00:00:00 2001 From: rainer Date: Thu, 12 Feb 2026 13:39:26 +0100 Subject: [PATCH] updated search, itemlist and much more... --- init.lua | 268 +++++++++++++++++++++++++++---------------------- init.lua.bak | 144 +++++++++++++++++++------- init.lua.bak.1 | 213 +++++++++++++++++++++++++++++++++++++++ init.lua.bak.2 | 202 +++++++++++++++++++++++++++++++++++++ init.lua.bak.3 | 219 ++++++++++++++++++++++++++++++++++++++++ init.lua.bak.4 | 208 ++++++++++++++++++++++++++++++++++++++ init.lua.bak.5 | 223 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1320 insertions(+), 157 deletions(-) create mode 100644 init.lua.bak.1 create mode 100644 init.lua.bak.2 create mode 100644 init.lua.bak.3 create mode 100644 init.lua.bak.4 create mode 100644 init.lua.bak.5 diff --git a/init.lua b/init.lua index 8f1b682..b8233c7 100644 --- a/init.lua +++ b/init.lua @@ -1,11 +1,12 @@ local modname = minetest.get_current_modname() local ci = {} -ci.blocks = {} -- Die komplette Master-Liste aller Items -ci.pages = {} -- Speichert die aktuelle Seite pro Spieler -ci.searches = {} -- Speichert den aktuellen Suchbegriff pro Spieler +ci.blocks = {all = {}, nodes = {}, tools = {}, items = {}} +ci.pages = {} +ci.searches = {} +-- Layout-Einstellungen local columns = 15 -local rows = 7 +local rows = 10 local nodes_per_page = columns * rows minetest.register_privilege("ci", { @@ -17,37 +18,70 @@ 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() - local list_items = minetest.settings:get_bool("ci_list_items") - local list_tools = minetest.settings:get_bool("ci_list_tools") - for name, def in pairs(minetest.registered_items) do - if def.type ~= "alias" and (def.type == "node" or - (list_items and def.type == "craftitem") or - (list_tools and def.type == "tool")) then - table.insert(ci.blocks, name) + 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 - end - table.sort(ci.blocks) - print("[ci] Loaded " .. #ci.blocks .. " items.") + + 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) -minetest.register_on_leaveplayer(function(player) - local player_name = player:get_player_name() - ci.pages[player_name] = nil - ci.searches[player_name] = nil -end) - -function ci.get_filtered_blocks(player_name) +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 ci.blocks - end + + if not search_term or search_term == "" then return raw_list end local filtered = {} - local term_lower = search_term:lower() - for _, item_name in ipairs(ci.blocks) do - if item_name:lower():find(term_lower, 1, true) then - table.insert(filtered, item_name) + 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 @@ -55,134 +89,128 @@ end function ci.get_formspec(player) local player_name = player:get_player_name() - local filtered_blocks = ci.get_filtered_blocks(player_name) - local current_page = ci.pages[player_name] or 1 - local total_pages = math.ceil(#filtered_blocks / nodes_per_page) - - if current_page > total_pages then - current_page = math.max(1, total_pages) - ci.pages[player_name] = current_page + 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 current_search = ci.searches[player_name] or "" + 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,12.8]" .. - "label[0.5,0.2;Select an item to add to your inventory:]" + 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]" - local start_index = (current_page - 1) * nodes_per_page + 1 - local end_index = math.min(current_page * nodes_per_page, #filtered_blocks) - - for i = start_index, end_index do - local block = filtered_blocks[i] - local rel = i - start_index - local col = rel % columns - local row = math.floor(rel / columns) - local x = 0.5 + col * 1.1 - local y = 1 + row * 1.1 - - -- RÜCKGÄNGIG GEMACHT: Die gesamte Tooltip-Logik wurde entfernt. - -- Der item_image_button wird jetzt wieder in seiner einfachsten Form ohne Label erstellt. - formspec = formspec .. - string.format("item_image_button[%f,%f;1,1;%s;add_%s;]", - x, y, - minetest.formspec_escape(block), - minetest.formspec_escape(block)) - end - - -- Steuerelemente + -- 1. Controls oben + local search = ci.searches[player_name] or "" formspec = formspec .. - "field[0.5,9.2;5.5,1;search;Search:;" .. minetest.formspec_escape(current_search) .. "]" .. - "button[6.1,8.85;2,1;do_search;Search]" .. - "button[8.2,8.85;1,1;reset_search;X]" .. - "field[13.0,9.2;4,1;quantity;Amount:;1]" + "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[8,10.4;Page " .. current_page .. " of " .. total_pages .. "]" - if current_page > 1 then - formspec = formspec .. "button[6.8,10.4;1.2,1;prev;<<]" + "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 current_page < total_pages then - formspec = formspec .. "button[9.5,10.4;1.2,1;next;>>]" + 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[7.75,11.5;2,1;exit;Close]" + formspec = formspec .. "button_exit[15.0," .. (footer_y - 0.2) .. ";2,0.8;exit;Schließen]" return formspec end minetest.register_chatcommand("ci", { - description = "Open creative inventory GUI", + description = "Kreativ-Inventar öffnen", privs = {ci=true}, - func = function(name, param) - if not has_permission(name) then - return false, "You do not have permission to use this command." - end - ci.pages[name] = 1 - ci.searches[name] = nil + func = function(name) local player = minetest.get_player_by_name(name) - if not player then - return false, "Player not found." + 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 - minetest.show_formspec(name, modname .. ":form", ci.get_formspec(player)) - return true, "Opening creative inventory..." + return true end, }) minetest.register_on_player_receive_fields(function(player, formname, fields) - if formname ~= modname .. ":form" then - return - end - local player_name = player:get_player_name() - if not has_permission(player_name) then - minetest.chat_send_player(player_name, "You do not have permission to use this.") + 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.do_search or (fields.key_enter_field and fields.key_enter_field == "search") then - ci.searches[player_name] = fields.search - ci.pages[player_name] = 1 - minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + 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[player_name] = nil - ci.pages[player_name] = 1 - minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + ci.searches[name] = nil + state.page = 1 + minetest.show_formspec(name, modname .. ":form", ci.get_formspec(player)) return end if fields.next then - local filtered_blocks = ci.get_filtered_blocks(player_name) - local total_pages = math.ceil(#filtered_blocks / nodes_per_page) - local current_page = ci.pages[player_name] or 1 - if current_page < total_pages then - ci.pages[player_name] = current_page + 1 - end - minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) - return + state.page = state.page + 1 + minetest.show_formspec(name, modname .. ":form", ci.get_formspec(player)) elseif fields.prev then - local current_page = ci.pages[player_name] or 1 - if current_page > 1 then - ci.pages[player_name] = current_page - 1 - end - minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) - return - end - - local quantity = tonumber(fields.quantity) - if not quantity or quantity < 1 then - minetest.chat_send_player(player_name, "Invalid quantity, giving 1 instead.") - quantity = 1 + 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 itemname = field:sub(5) + local item = field:sub(5) local inv = player:get_inventory() - if inv then - inv:add_item("main", itemname .. " " .. quantity) - minetest.chat_send_player(player_name, "Added " .. quantity .. " of: " .. itemname) - end - minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + 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 @@ -192,7 +220,7 @@ minetest.after(0, function() if minetest.global_exists("i3_extrabuttons") then i3_extrabuttons.new_tab("cinventory", { description = "Kreativ-Inventar", - priv = "ci", -- optional: nur Spieler mit ci-Priv sehen den Tab + priv = "ci", formspec = function(player, data, fs) end, fields = function(player, data, fields) i3.set_tab(player, "inventory") diff --git a/init.lua.bak b/init.lua.bak index 94b2329..8f1b682 100644 --- a/init.lua.bak +++ b/init.lua.bak @@ -1,11 +1,12 @@ local modname = minetest.get_current_modname() local ci = {} -ci.blocks = {} -- complete list of node names -ci.pages = {} -- current page per player -ci.selected_item = {} -- store selected item per player +ci.blocks = {} -- Die komplette Master-Liste aller Items +ci.pages = {} -- Speichert die aktuelle Seite pro Spieler +ci.searches = {} -- Speichert den aktuellen Suchbegriff pro Spieler + local columns = 15 local rows = 7 -local nodes_per_page = columns * rows -- 105 nodes per page +local nodes_per_page = columns * rows minetest.register_privilege("ci", { description = "Allows the player to use the ci command", @@ -16,43 +17,71 @@ local function has_permission(player_name) return minetest.check_player_privs(player_name, {ci=true}) end --- Build the list of nodes after all mods are loaded. minetest.register_on_mods_loaded(function() local list_items = minetest.settings:get_bool("ci_list_items") local list_tools = minetest.settings:get_bool("ci_list_tools") for name, def in pairs(minetest.registered_items) do - if def.type == "node" or (list_items and def.type == "craftitem") or (list_tools and def.type == "tool") then - table.insert(ci.blocks, name) + if def.type ~= "alias" and (def.type == "node" or + (list_items and def.type == "craftitem") or + (list_tools and def.type == "tool")) then + table.insert(ci.blocks, name) end end table.sort(ci.blocks) + print("[ci] Loaded " .. #ci.blocks .. " items.") end) -function ci.get_total_pages() - return math.ceil(#ci.blocks / nodes_per_page) +minetest.register_on_leaveplayer(function(player) + local player_name = player:get_player_name() + ci.pages[player_name] = nil + ci.searches[player_name] = nil +end) + +function ci.get_filtered_blocks(player_name) + local search_term = ci.searches[player_name] + if not search_term or search_term == "" then + return ci.blocks + end + + local filtered = {} + local term_lower = search_term:lower() + for _, item_name in ipairs(ci.blocks) do + if item_name:lower():find(term_lower, 1, true) then + table.insert(filtered, item_name) + end + end + return filtered end function ci.get_formspec(player) local player_name = player:get_player_name() + local filtered_blocks = ci.get_filtered_blocks(player_name) local current_page = ci.pages[player_name] or 1 - local total_pages = ci.get_total_pages() + local total_pages = math.ceil(#filtered_blocks / nodes_per_page) - local formspec = "size[17.5,10.5]" .. - "label[0.5,0.2;Select a block to add to your inventory:]" .. - "field[4,9.1;2,1;quantity;Amount:;1]" .. - "label[8.5,9;Page " .. current_page .. " of " .. total_pages .. "]" + if current_page > total_pages then + current_page = math.max(1, total_pages) + ci.pages[player_name] = current_page + end + + local current_search = ci.searches[player_name] or "" + + local formspec = "size[17.5,12.8]" .. + "label[0.5,0.2;Select an item to add to your inventory:]" local start_index = (current_page - 1) * nodes_per_page + 1 - local end_index = math.min(current_page * nodes_per_page, #ci.blocks) + local end_index = math.min(current_page * nodes_per_page, #filtered_blocks) - -- Place the block buttons in a grid. for i = start_index, end_index do - local block = ci.blocks[i] - local rel = i - start_index -- relative index on this page + local block = filtered_blocks[i] + local rel = i - start_index local col = rel % columns local row = math.floor(rel / columns) local x = 0.5 + col * 1.1 local y = 1 + row * 1.1 + + -- RÜCKGÄNGIG GEMACHT: Die gesamte Tooltip-Logik wurde entfernt. + -- Der item_image_button wird jetzt wieder in seiner einfachsten Form ohne Label erstellt. formspec = formspec .. string.format("item_image_button[%f,%f;1,1;%s;add_%s;]", x, y, @@ -60,32 +89,42 @@ function ci.get_formspec(player) minetest.formspec_escape(block)) end + -- Steuerelemente + formspec = formspec .. + "field[0.5,9.2;5.5,1;search;Search:;" .. minetest.formspec_escape(current_search) .. "]" .. + "button[6.1,8.85;2,1;do_search;Search]" .. + "button[8.2,8.85;1,1;reset_search;X]" .. + "field[13.0,9.2;4,1;quantity;Amount:;1]" + + formspec = formspec .. + "label[8,10.4;Page " .. current_page .. " of " .. total_pages .. "]" if current_page > 1 then - formspec = formspec .. "button[6.25,9;2,0.5;prev;Previous]" + formspec = formspec .. "button[6.8,10.4;1.2,1;prev;<<]" end if current_page < total_pages then - formspec = formspec .. "button[10.25,9;2,0.5;next;Next]" + formspec = formspec .. "button[9.5,10.4;1.2,1;next;>>]" end - formspec = formspec .. "button_exit[8.25,9.75;2,0.5;exit;Close]" + + formspec = formspec .. "button_exit[7.75,11.5;2,1;exit;Close]" + return formspec end minetest.register_chatcommand("ci", { - description = "Open block list GUI with pages", + description = "Open creative inventory GUI", privs = {ci=true}, func = function(name, param) if not has_permission(name) then return false, "You do not have permission to use this command." end - ci.pages[name] = 1 + ci.searches[name] = nil local player = minetest.get_player_by_name(name) if not player then return false, "Player not found." end - local formspec = ci.get_formspec(player) - minetest.show_formspec(name, modname .. ":form", formspec) - return true, "Opening block list..." + minetest.show_formspec(name, modname .. ":form", ci.get_formspec(player)) + return true, "Opening creative inventory..." end, }) @@ -94,40 +133,71 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) return end local player_name = player:get_player_name() - if not has_permission(player_name) then + if not has_permission(player_name) then minetest.chat_send_player(player_name, "You do not have permission to use this.") return end + if fields.do_search or (fields.key_enter_field and fields.key_enter_field == "search") then + ci.searches[player_name] = fields.search + ci.pages[player_name] = 1 + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + elseif fields.reset_search then + ci.searches[player_name] = nil + ci.pages[player_name] = 1 + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + end + if fields.next then - local total_pages = ci.get_total_pages() + local filtered_blocks = ci.get_filtered_blocks(player_name) + local total_pages = math.ceil(#filtered_blocks / nodes_per_page) local current_page = ci.pages[player_name] or 1 if current_page < total_pages then ci.pages[player_name] = current_page + 1 end minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) - return true + return elseif fields.prev then local current_page = ci.pages[player_name] or 1 if current_page > 1 then ci.pages[player_name] = current_page - 1 end minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) - return true + return + end + + local quantity = tonumber(fields.quantity) + if not quantity or quantity < 1 then + minetest.chat_send_player(player_name, "Invalid quantity, giving 1 instead.") + quantity = 1 end - -- If a block button was pressed, add that block in specified quantity. - local quantity = tonumber(fields.quantity) or 1 - if quantity < 1 then quantity = 1 end for field, _ in pairs(fields) do if field:sub(1, 4) == "add_" then - local blockname = field:sub(5) + local itemname = field:sub(5) local inv = player:get_inventory() if inv then - inv:add_item("main", blockname .. " " .. quantity) - minetest.chat_send_player(player_name, "Added " .. quantity .. " of: " .. blockname) + inv:add_item("main", itemname .. " " .. quantity) + minetest.chat_send_player(player_name, "Added " .. quantity .. " of: " .. itemname) end - return true + minetest.show_formspec(player_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", -- optional: nur Spieler mit ci-Priv sehen den Tab + 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) diff --git a/init.lua.bak.1 b/init.lua.bak.1 new file mode 100644 index 0000000..4489aa5 --- /dev/null +++ b/init.lua.bak.1 @@ -0,0 +1,213 @@ +local modname = minetest.get_current_modname() +local ci = {} +ci.blocks = {} -- Die komplette Master-Liste aller Items +ci.pages = {} -- Speichert die aktuelle Seite pro Spieler +ci.searches = {} -- Speichert den aktuellen Suchbegriff pro Spieler + +local columns = 15 +local rows = 7 +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 + +-- Optimierte Lade-Logik für Items und Tools +minetest.register_on_mods_loaded(function() + minetest.after(0, function() + -- Settings abrufen (Standardmäßig true, wenn nicht anders gesetzt) + local list_items = minetest.settings:get_bool("ci_list_items") ~= false + local list_tools = minetest.settings:get_bool("ci_list_tools") ~= false + + ci.blocks = {} + + for name, def in pairs(minetest.registered_items) do + -- Nur existierende Items aufnehmen, keine reinen Aliase (verhindert Dubletten) + if def and name ~= "" and not name:find("alias:") then + local is_node = (def.type == "node") + local is_tool = (list_tools and def.type == "tool") + -- Craftitems haben oft "none" oder gar keinen Typ hinterlegt + local is_item = (list_items and (def.type == "craftitem" or def.type == "none" or not def.type)) + + if is_node or is_tool or is_item then + table.insert(ci.blocks, name) + end + end + end + + table.sort(ci.blocks) + print("[ci] " .. #ci.blocks .. " Einträge geladen (Items: " .. tostring(list_items) .. ", Tools: " .. tostring(list_tools) .. ")") + end) +end) + +minetest.register_on_leaveplayer(function(player) + local player_name = player:get_player_name() + ci.pages[player_name] = nil + ci.searches[player_name] = nil +end) + +function ci.get_filtered_blocks(player_name) + local search_term = ci.searches[player_name] + if not search_term or search_term == "" then + return ci.blocks + end + + local filtered = {} + local term_lower = search_term:lower() + for _, item_name in ipairs(ci.blocks) do + if item_name:lower():find(term_lower, 1, true) then + table.insert(filtered, item_name) + end + end + return filtered +end + +function ci.get_formspec(player) + local player_name = player:get_player_name() + local filtered_blocks = ci.get_filtered_blocks(player_name) + local current_page = ci.pages[player_name] or 1 + local total_pages = math.ceil(#filtered_blocks / nodes_per_page) + + if current_page > total_pages then + current_page = math.max(1, total_pages) + ci.pages[player_name] = current_page + end + + local current_search = ci.searches[player_name] or "" + + local formspec = "size[17.5,12.8]" .. + "label[0.5,0.2;Wähle ein Item für dein Inventar:]" + + local start_index = (current_page - 1) * nodes_per_page + 1 + local end_index = math.min(current_page * nodes_per_page, #filtered_blocks) + + for i = start_index, end_index do + local block = filtered_blocks[i] + local rel = i - start_index + local col = rel % columns + local row = math.floor(rel / columns) + local x = 0.5 + col * 1.1 + local y = 1 + row * 1.1 + + formspec = formspec .. + string.format("item_image_button[%f,%f;1,1;%s;add_%s;]", + x, y, + minetest.formspec_escape(block), + minetest.formspec_escape(block)) + end + + -- Steuerelemente + formspec = formspec .. + "field[0.5,9.2;5.5,1;search;Suche:;" .. minetest.formspec_escape(current_search) .. "]" .. + "button[6.1,8.85;2,1;do_search;Suchen]" .. + "button[8.2,8.85;1,1;reset_search;X]" .. + "field[13.0,9.2;4,1;quantity;Anzahl:;1]" + + formspec = formspec .. + "label[8,10.4;Seite " .. current_page .. " von " .. total_pages .. "]" + if current_page > 1 then + formspec = formspec .. "button[6.8,10.4;1.2,1;prev;<<]" + end + if current_page < total_pages then + formspec = formspec .. "button[9.5,10.4;1.2,1;next;>>]" + end + + formspec = formspec .. "button_exit[7.75,11.5;2,1;exit;Schließen]" + + return formspec +end + +minetest.register_chatcommand("ci", { + description = "Kreativ-Inventar öffnen", + privs = {ci=true}, + func = function(name, param) + if not has_permission(name) then + return false, "Du hast keine Berechtigung dafür." + end + ci.pages[name] = 1 + ci.searches[name] = nil + local player = minetest.get_player_by_name(name) + if not player then + return false, "Spieler nicht gefunden." + end + minetest.show_formspec(name, modname .. ":form", ci.get_formspec(player)) + return true, "Öffne Kreativ-Inventar..." + end, +}) + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= modname .. ":form" then + return + end + local player_name = player:get_player_name() + if not has_permission(player_name) then + return + end + + if fields.do_search or (fields.key_enter_field and fields.key_enter_field == "search") then + ci.searches[player_name] = fields.search + ci.pages[player_name] = 1 + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + elseif fields.reset_search then + ci.searches[player_name] = nil + ci.pages[player_name] = 1 + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + end + + if fields.next then + local filtered_blocks = ci.get_filtered_blocks(player_name) + local total_pages = math.ceil(#filtered_blocks / nodes_per_page) + local current_page = ci.pages[player_name] or 1 + if current_page < total_pages then + ci.pages[player_name] = current_page + 1 + end + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + elseif fields.prev then + local current_page = ci.pages[player_name] or 1 + if current_page > 1 then + ci.pages[player_name] = current_page - 1 + end + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + end + + local quantity = tonumber(fields.quantity) + if not quantity or quantity < 1 then + quantity = 1 + end + + for field, _ in pairs(fields) do + if field:sub(1, 4) == "add_" then + local itemname = field:sub(5) + local inv = player:get_inventory() + if inv then + inv:add_item("main", itemname .. " " .. quantity) + end + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + end + end +end) + +-- Integration in i3 (falls vorhanden) +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) diff --git a/init.lua.bak.2 b/init.lua.bak.2 new file mode 100644 index 0000000..3fdd10a --- /dev/null +++ b/init.lua.bak.2 @@ -0,0 +1,202 @@ +local modname = minetest.get_current_modname() +local ci = {} +ci.blocks = {} -- Die komplette Master-Liste aller Items +ci.pages = {} -- Speichert Seite UND Anzahl pro Spieler +ci.searches = {} -- Speichert den aktuellen Suchbegriff pro Spieler + +local columns = 15 +local rows = 7 +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 + +-- Items laden +minetest.register_on_mods_loaded(function() + minetest.after(0, function() + local list_items = minetest.settings:get_bool("ci_list_items") ~= false + local list_tools = minetest.settings:get_bool("ci_list_tools") ~= false + + ci.blocks = {} + for name, def in pairs(minetest.registered_items) do + if def and name ~= "" and not name:find("alias:") then + local is_node = (def.type == "node") + local is_tool = (list_tools and def.type == "tool") + local is_item = (list_items and (def.type == "craftitem" or def.type == "none" or not def.type)) + + if is_node or is_tool or is_item then + table.insert(ci.blocks, name) + end + end + end + table.sort(ci.blocks) + print("[ci] " .. #ci.blocks .. " Einträge geladen.") + end) +end) + +minetest.register_on_leaveplayer(function(player) + local player_name = player:get_player_name() + ci.pages[player_name] = nil + ci.searches[player_name] = nil +end) + +function ci.get_filtered_blocks(player_name) + local search_term = ci.searches[player_name] + if not search_term or search_term == "" then return ci.blocks end + + local filtered = {} + local term_lower = search_term:lower() + for _, item_name in ipairs(ci.blocks) do + if item_name:lower():find(term_lower, 1, true) then + table.insert(filtered, item_name) + end + end + return filtered +end + +function ci.get_formspec(player) + local player_name = player:get_player_name() + local filtered_blocks = ci.get_filtered_blocks(player_name) + + -- Struktur für Spieler-Status sicherstellen + if not ci.pages[player_name] then + ci.pages[player_name] = {page = 1, quantity = 1} + end + + local current_page = ci.pages[player_name].page + local current_qty = ci.pages[player_name].quantity + local total_pages = math.ceil(#filtered_blocks / nodes_per_page) + + if current_page > total_pages then + current_page = math.max(1, total_pages) + ci.pages[player_name].page = current_page + end + + local current_search = ci.searches[player_name] or "" + + local formspec = "size[17.5,12.8]" .. + "label[0.5,0.2;Wähle ein Item für dein Inventar:]" + + local start_index = (current_page - 1) * nodes_per_page + 1 + local end_index = math.min(current_page * nodes_per_page, #filtered_blocks) + + for i = start_index, end_index do + local block = filtered_blocks[i] + local rel = i - start_index + local col = rel % columns + local row = math.floor(rel / columns) + local x = 0.5 + col * 1.1 + local y = 1 + row * 1.1 + + -- Button mit technischem Namen im Tooltip + formspec = formspec .. + string.format("item_image_button[%f,%f;1,1;%s;add_%s;]", + x, y, minetest.formspec_escape(block), minetest.formspec_escape(block)) .. + string.format("tooltip[add_%s;%s\n[%s]]", + minetest.formspec_escape(block), + minetest.formspec_escape(minetest.registered_items[block].description or ""), + minetest.formspec_escape(block)) + end + + -- Steuerelemente (Anzahl-Feld nutzt jetzt current_qty) + formspec = formspec .. + "field[0.5,9.2;5.5,1;search;Suche:;" .. minetest.formspec_escape(current_search) .. "]" .. + "button[6.1,8.85;2,1;do_search;Suchen]" .. + "button[8.2,8.85;1,1;reset_search;X]" .. + "field[13.0,9.2;4,1;quantity;Anzahl:;" .. current_qty .. "]" + + formspec = formspec .. + "label[8,10.4;Seite " .. current_page .. " von " .. total_pages .. "]" + if current_page > 1 then + formspec = formspec .. "button[6.8,10.4;1.2,1;prev;<<]" + end + if current_page < total_pages then + formspec = formspec .. "button[9.5,10.4;1.2,1;next;>>]" + end + + formspec = formspec .. "button_exit[7.75,11.5;2,1;exit;Schließen]" + + return formspec +end + +minetest.register_chatcommand("ci", { + description = "Kreativ-Inventar öffnen", + privs = {ci=true}, + func = function(name) + if not has_permission(name) then return false, "Keine Rechte." end + ci.pages[name] = {page = 1, quantity = 1} + ci.searches[name] = nil + local player = minetest.get_player_by_name(name) + if player then 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 player_name = player:get_player_name() + if not has_permission(player_name) then return end + + -- Aktuelle Anzahl immer zwischenspeichern, wenn ein Feld gesendet wird + if fields.quantity then + ci.pages[player_name].quantity = tonumber(fields.quantity) or 1 + end + + if fields.do_search or (fields.key_enter_field and fields.key_enter_field == "search") then + ci.searches[player_name] = fields.search + ci.pages[player_name].page = 1 + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + elseif fields.reset_search then + ci.searches[player_name] = nil + ci.pages[player_name].page = 1 + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + end + + if fields.next then + ci.pages[player_name].page = ci.pages[player_name].page + 1 + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + elseif fields.prev then + ci.pages[player_name].page = math.max(1, ci.pages[player_name].page - 1) + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + end + + for field, _ in pairs(fields) do + if field:sub(1, 4) == "add_" then + local itemname = field:sub(5) + local qty = ci.pages[player_name].quantity + local inv = player:get_inventory() + if inv then + inv:add_item("main", itemname .. " " .. qty) + minetest.chat_send_player(player_name, "Hinzugefügt: " .. qty .. "x " .. itemname) + end + -- Formspec bleibt offen, Anzahl bleibt erhalten + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + end + end +end) + +-- i3 Integration +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) diff --git a/init.lua.bak.3 b/init.lua.bak.3 new file mode 100644 index 0000000..24b1757 --- /dev/null +++ b/init.lua.bak.3 @@ -0,0 +1,219 @@ +local modname = minetest.get_current_modname() +local ci = {} +ci.blocks = {} +ci.pages = {} +ci.searches = {} + +local columns = 15 +local rows = 7 +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 + +-- DER "BRECHEISEN"-SCAN: Startet erst nach 1 Sekunde Laufzeit +minetest.register_on_mods_loaded(function() + minetest.after(1, function() + local list_items = minetest.settings:get_bool("ci_list_items") ~= false + local list_tools = minetest.settings:get_bool("ci_list_tools") ~= false + + ci.blocks = {} + local added = {} + + -- Funktion zum sicheren Hinzufügen + local function add_to_list(name, def) + if not name or name == "" or added[name] then return end + + -- Wir filtern nur noch nach den groben Kategorien Tools/Items + if def.type == "tool" and not list_tools then return end + if (def.type == "craftitem" or not def.type or def.type == "none") and not list_items then + -- Falls es kein Node ist, aber Items deaktiviert sind -> weg damit + if def.type ~= "node" then return end + end + + -- Nur Items mit Bild oder Beschreibung (verhindert Geister-Items) + if (def.description and def.description ~= "") or + (def.inventory_image and def.inventory_image ~= "") or + (def.type == "node") then + table.insert(ci.blocks, name) + added[name] = true + end + end + + -- 1. Scan alle registrierten Items + for name, def in pairs(minetest.registered_items) do + add_to_list(name, def) + end + + -- 2. Scan alle Aliase (Wichtig für Eimer!) + 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 + + table.sort(ci.blocks) + print("[ci] Deep Scan fertig: " .. #ci.blocks .. " Items gefunden.") + end) +end) + +-- [Rest der Funktionen bleibt identisch zur Vorversion, um Bugs zu vermeiden] +-- [Ich kapsele hier nur die Logik, die sich geändert hat] + +function ci.get_filtered_blocks(player_name) + local search_term = ci.searches[player_name] + if not search_term or search_term == "" then return ci.blocks end + + local filtered = {} + local term_lower = search_term:lower() + for _, item_name in ipairs(ci.blocks) do + local def = minetest.registered_items[item_name] + -- Suche in Name ODER Beschreibung + if item_name:lower():find(term_lower, 1, true) or + (def and def.description and def.description:lower():find(term_lower, 1, true)) then + table.insert(filtered, item_name) + end + end + return filtered +end + +function ci.get_formspec(player) + local player_name = player:get_player_name() + local filtered_blocks = ci.get_filtered_blocks(player_name) + + if not ci.pages[player_name] then + ci.pages[player_name] = {page = 1, quantity = 1} + end + + local current_page = ci.pages[player_name].page + local current_qty = ci.pages[player_name].quantity + local total_pages = math.max(1, math.ceil(#filtered_blocks / nodes_per_page)) + + if current_page > total_pages then + current_page = total_pages + ci.pages[player_name].page = current_page + end + + local current_search = ci.searches[player_name] or "" + local formspec = "size[17.5,12.8]" .. + "label[0.5,0.2;Kreativ-Inventar (Deep Scan):]" + + local start_index = (current_page - 1) * nodes_per_page + 1 + local end_index = math.min(current_page * nodes_per_page, #filtered_blocks) + + for i = start_index, end_index do + local block = filtered_blocks[i] + local rel = i - start_index + local col = rel % columns + local row = math.floor(rel / columns) + local x = 0.5 + col * 1.1 + local y = 1 + row * 1.1 + + formspec = formspec .. + string.format("item_image_button[%f,%f;1,1;%s;add_%s;]", + x, y, minetest.formspec_escape(block), minetest.formspec_escape(block)) .. + string.format("tooltip[add_%s;%s\n[%s]]", + minetest.formspec_escape(block), + minetest.formspec_escape(minetest.registered_items[block] and minetest.registered_items[block].description or ""), + minetest.formspec_escape(block)) + end + + formspec = formspec .. + "field[0.5,9.2;5.5,1;search;Suche:;" .. minetest.formspec_escape(current_search) .. "]" .. + "button[6.1,8.85;2,1;do_search;Suchen]" .. + "button[8.2,8.85;1,1;reset_search;X]" .. + "field[13.0,9.2;4,1;quantity;Anzahl:;" .. current_qty .. "]" .. + "label[8,10.4;Seite " .. current_page .. " von " .. total_pages .. "]" + + if current_page > 1 then + formspec = formspec .. "button[6.8,10.4;1.2,1;prev;<<]" + end + if current_page < total_pages then + formspec = formspec .. "button[9.5,10.4;1.2,1;next;>>]" + end + + formspec = formspec .. "button_exit[7.75,11.5;2,1;exit;Schließen]" + return formspec +end + +-- Chatcommand Registrierung +minetest.register_chatcommand("ci", { + description = "Kreativ-Inventar öffnen", + privs = {ci=true}, + func = function(name) + if not has_permission(name) then return false, "Keine Rechte." end + local player = minetest.get_player_by_name(name) + if player then + if not ci.pages[name] then ci.pages[name] = {page = 1, quantity = 1} end + minetest.show_formspec(name, modname .. ":form", ci.get_formspec(player)) + end + return true + end, +}) + +-- Fields Handler +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= modname .. ":form" then return end + local player_name = player:get_player_name() + if not has_permission(player_name) then return end + + if fields.quantity then ci.pages[player_name].quantity = tonumber(fields.quantity) or 1 end + + if fields.do_search or (fields.key_enter_field and fields.key_enter_field == "search") then + ci.searches[player_name] = fields.search + ci.pages[player_name].page = 1 + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + elseif fields.reset_search then + ci.searches[player_name] = nil + ci.pages[player_name].page = 1 + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + end + + if fields.next then + ci.pages[player_name].page = ci.pages[player_name].page + 1 + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + elseif fields.prev then + ci.pages[player_name].page = math.max(1, ci.pages[player_name].page - 1) + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + end + + for field, _ in pairs(fields) do + if field:sub(1, 4) == "add_" then + local itemname = field:sub(5) + local qty = ci.pages[player_name].quantity + local inv = player:get_inventory() + if inv then + inv:add_item("main", itemname .. " " .. qty) + minetest.chat_send_player(player_name, "Hinzugefügt: " .. qty .. "x " .. itemname) + end + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + end + end +end) + +-- Integration i3 +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) diff --git a/init.lua.bak.4 b/init.lua.bak.4 new file mode 100644 index 0000000..cd4e369 --- /dev/null +++ b/init.lua.bak.4 @@ -0,0 +1,208 @@ +local modname = minetest.get_current_modname() +local ci = {} +ci.blocks = {} +ci.pages = {} +ci.searches = {} + +local columns = 15 +local rows = 7 +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 Logik +minetest.register_on_mods_loaded(function() + minetest.after(1, function() + local list_items = minetest.settings:get_bool("ci_list_items") ~= false + local list_tools = minetest.settings:get_bool("ci_list_tools") ~= false + + ci.blocks = {} + local added = {} + + local function add_to_list(name, def) + if not name or name == "" or added[name] then return end + if def.type == "tool" and not list_tools then return end + if (def.type == "craftitem" or not def.type or def.type == "none") and not list_items then + if def.type ~= "node" then return end + end + + if (def.description and def.description ~= "") or + (def.inventory_image and def.inventory_image ~= "") or + (def.type == "node") then + table.insert(ci.blocks, name) + added[name] = true + end + 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 + + table.sort(ci.blocks) + print("[ci] Deep Scan fertig: " .. #ci.blocks .. " Items gefunden.") + end) +end) + +function ci.get_filtered_blocks(player_name) + local search_term = ci.searches[player_name] + if not search_term or search_term == "" then return ci.blocks end + + local filtered = {} + local term_lower = search_term:lower() + for _, item_name in ipairs(ci.blocks) do + local def = minetest.registered_items[item_name] + if item_name:lower():find(term_lower, 1, true) or + (def and def.description and def.description:lower():find(term_lower, 1, true)) then + table.insert(filtered, item_name) + end + end + return filtered +end + +function ci.get_formspec(player) + local player_name = player:get_player_name() + local filtered_blocks = ci.get_filtered_blocks(player_name) + + if not ci.pages[player_name] then + ci.pages[player_name] = {page = 1, quantity = 1} + end + + local current_page = ci.pages[player_name].page + local current_qty = ci.pages[player_name].quantity + local total_pages = math.max(1, math.ceil(#filtered_blocks / nodes_per_page)) + + if current_page > total_pages then + current_page = total_pages + ci.pages[player_name].page = current_page + end + + local current_search = ci.searches[player_name] or "" + local formspec = "size[17.5,12.8]" .. + "label[0.5,0.2;Kreativ-Inventar:]" + + local start_index = (current_page - 1) * nodes_per_page + 1 + local end_index = math.min(current_page * nodes_per_page, #filtered_blocks) + + for i = start_index, end_index do + local block = filtered_blocks[i] + local rel = i - start_index + local col = rel % columns + local row = math.floor(rel / columns) + local x = 0.5 + col * 1.1 + local y = 1 + row * 1.1 + + local def = minetest.registered_items[block] + local desc = def and def.description or "No description" + + formspec = formspec .. + string.format("item_image_button[%f,%f;1,1;%s;add_%s;]", + x, y, minetest.formspec_escape(block), minetest.formspec_escape(block)) .. + string.format("tooltip[add_%s;%s\n[%s]]", + minetest.formspec_escape(block), + minetest.formspec_escape(desc), + minetest.formspec_escape(block)) + end + + formspec = formspec .. + "field[0.5,9.2;5.5,1;search;Suche:;" .. minetest.formspec_escape(current_search) .. "]" .. + "button[6.1,8.85;2,1;do_search;Suchen]" .. + "button[8.2,8.85;1,1;reset_search;X]" .. + "field[13.0,9.2;4,1;quantity;Anzahl:;" .. current_qty .. "]" .. + "label[8,10.4;Seite " .. current_page .. " von " .. total_pages .. "]" + + if current_page > 1 then + formspec = formspec .. "button[6.8,10.4;1.2,1;prev;<<]" + end + if current_page < total_pages then + formspec = formspec .. "button[9.5,10.4;1.2,1;next;>>]" + end + + formspec = formspec .. "button_exit[7.75,11.5;2,1;exit;Schließen]" + return formspec +end + +minetest.register_chatcommand("ci", { + description = "Kreativ-Inventar öffnen", + privs = {ci=true}, + func = function(name) + if not has_permission(name) then return false, "Keine Rechte." end + local player = minetest.get_player_by_name(name) + if player then + if not ci.pages[name] then ci.pages[name] = {page = 1, quantity = 1} 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 player_name = player:get_player_name() + if not has_permission(player_name) then return end + + if fields.quantity then ci.pages[player_name].quantity = tonumber(fields.quantity) or 1 end + + if fields.do_search or (fields.key_enter_field and fields.key_enter_field == "search") then + ci.searches[player_name] = fields.search + ci.pages[player_name].page = 1 + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + elseif fields.reset_search then + ci.searches[player_name] = nil + ci.pages[player_name].page = 1 + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + end + + if fields.next then + ci.pages[player_name].page = ci.pages[player_name].page + 1 + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + elseif fields.prev then + ci.pages[player_name].page = math.max(1, ci.pages[player_name].page - 1) + minetest.show_formspec(player_name, modname .. ":form", ci.get_formspec(player)) + return + end + + for field, _ in pairs(fields) do + if field:sub(1, 4) == "add_" then + local itemname = field:sub(5) + local qty = ci.pages[player_name].quantity + local inv = player:get_inventory() + if inv then + inv:add_item("main", itemname .. " " .. qty) + local def = minetest.registered_items[itemname] + local desc = def and def.description or itemname + minetest.chat_send_player(player_name, "Hinzugefügt: " .. qty .. "x " .. desc .. " [" .. itemname .. "]") + end + minetest.show_formspec(player_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) diff --git a/init.lua.bak.5 b/init.lua.bak.5 new file mode 100644 index 0000000..3b5f0f8 --- /dev/null +++ b/init.lua.bak.5 @@ -0,0 +1,223 @@ +local modname = minetest.get_current_modname() +local ci = {} +ci.blocks = {all = {}, nodes = {}, tools = {}, items = {}} +ci.pages = {} +ci.searches = {} + +local columns = 15 +local rows = 7 +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 (Repariert: Sortier-Bug behoben) +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 + + -- Sicherstellen, dass desc ein String ist (für die Sortierung wichtig!) + 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 + + -- Robuste Sortierung: Vergleicht Strings und fängt nil ab + 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,12.8]" .. + "background[0,0;17.5,12.8;gui_formbg.png;true]" .. + "tabheader[0,0;tab;" .. table.concat(tab_labels, ",") .. ";" .. current_tab_idx .. ";true;false]" + + 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 = 0.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 + + local search = ci.searches[player_name] or "" + formspec = formspec .. + "field[0.5,9.2;5.5,1;search;Suche im Tab:;" .. minetest.formspec_escape(search) .. "]" .. + "button[6.1,8.85;1.5,1;do_search;Suchen]" .. + "button[7.6,8.85;0.8,1;reset_search;X]" .. + "field[13.0,9.2;4,1;quantity;Anzahl:;" .. state.quantity .. "]" .. + "label[0.5,10.4;Seite " .. state.page .. " von " .. total_pages .. " (" .. #filtered .. " Items)]" + + if state.page > 1 then + formspec = formspec .. "button[7.5,10.2;1.5,0.8;prev;<<]" + end + if state.page < total_pages then + formspec = formspec .. "button[9.5,10.2;1.5,0.8;next;>>]" + end + + formspec = formspec .. "button_exit[7.75,11.5;2,1;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)