223 lines
8.1 KiB
Groff
223 lines
8.1 KiB
Groff
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)
|