aboutsummaryrefslogtreecommitdiff
path: root/ch_core/creative_inventory.lua
diff options
context:
space:
mode:
Diffstat (limited to 'ch_core/creative_inventory.lua')
-rw-r--r--ch_core/creative_inventory.lua1037
1 files changed, 1037 insertions, 0 deletions
diff --git a/ch_core/creative_inventory.lua b/ch_core/creative_inventory.lua
new file mode 100644
index 0000000..91b623d
--- /dev/null
+++ b/ch_core/creative_inventory.lua
@@ -0,0 +1,1037 @@
+ch_core.open_submod("creative_inventory", {lib = true})
+
+local none = {}
+local partition_defs = {
+ {
+ name = "empty_buckets",
+ groups = none,
+ items = {"bucket:bucket_empty", "bucket_wooden:bucket_empty"},
+ mods = none,
+ },
+ {
+ name = "caste_nastroje",
+ groups = none,
+ items = {"moreblocks:circular_saw", "unifieddyes:airbrush", "bike:painter",
+ "advtrains:trackworker", "wrench:wrench", "replacer:replacer",
+ "ch_extras:total_station", "ch_extras:jumptool", "ch_extras:teleporter_unsellable",
+ "technic:mining_drill", "technic:mining_drill_mk2", "technic:mining_drill_mk3",
+ "bridger:scaffolding", "ch_core:chisel",
+ "orienteering:builder_compass_1", "ch_extras:lupa", "ch_extras:periskop",
+ "binoculars:binoculars"},
+ mods = none,
+ },
+ {
+ name = "kladivo_kovadlina",
+ groups = none,
+ items = none,
+ mods = {"anvil"},
+ },
+ {
+ name = "krumpace",
+ groups = {"pickaxe"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "lopaty",
+ groups = {"shovel"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "motyky",
+ groups = {"hoe"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "sekery",
+ groups = {"axe"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "srpy",
+ groups = {"sickle"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "mitrkosa",
+ groups = none,
+ items = {"farming:scythe_mithril"},
+ mods = none,
+ },
+ {
+ name = "trojnástroje",
+ groups = {"multitool"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "klice",
+ groups = none,
+ items = none,
+ mods = {"rotate"},
+ },
+
+ {
+ name = "cestbudky",
+ groups = {"travelnet"},
+ items = none,
+ mods = none,
+ },
+
+ {
+ name = "drevo",
+ groups = {"wood"},
+ items = none,
+ mods = none,
+ exclude_items = {
+ "moreblocks:wood_tile",
+ "moreblocks:wood_tile_center",
+ "moreblocks:wood_tile_offset",
+ "moreblocks:wood_tile_full",
+ "pkarcs:acacia_wood_arc",
+ "pkarcs:acacia_wood_inner_arc",
+ "pkarcs:acacia_wood_outer_arc",
+ "pkarcs:acacia_wood_with_arc",
+ "pkarcs:aspen_wood_arc",
+ "pkarcs:aspen_wood_inner_arc",
+ "pkarcs:aspen_wood_outer_arc",
+ "pkarcs:aspen_wood_with_arc",
+ "pkarcs:junglewood_arc",
+ "pkarcs:junglewood_inner_arc",
+ "pkarcs:junglewood_outer_arc",
+ "pkarcs:junglewood_with_arc",
+ "pkarcs:pine_wood_arc",
+ "pkarcs:pine_wood_inner_arc",
+ "pkarcs:pine_wood_outer_arc",
+ "pkarcs:pine_wood_with_arc",
+ "pkarcs:wood_arc",
+ "pkarcs:wood_inner_arc",
+ "pkarcs:wood_outer_arc",
+ "pkarcs:wood_with_arc",
+ },
+ -- not_in_mods = {"pkarcs"},
+ -- not_in_mods = {"cottages", "moreblocks", "pkarcs"},
+ },
+ {
+ name = "drevokmeny",
+ groups = {"tree"},
+ items = none,
+ mods = none,
+ exclude_items = {"cottages:water_gen", "bamboo:trunk"},
+ },
+ --[[
+ {
+ name = "barvy",
+ groups = {"basic_dye"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "ploty",
+ groups = {"fence"},
+ items = none,
+ mods = none,
+ exclude_items = {"technic:insulator_clip_fencepost"},
+ }, ]]
+ {
+ name = "mesesloupky",
+ groups = {"mesepost_light"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "jil",
+ groups = {"bakedclay"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "kvetiny",
+ groups = {"flower"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "vlaky",
+ groups = {"at_wagon"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "elektrickestroje",
+ groups = {"technic_machine"},
+ items = none,
+ mods = none,
+ exclude_items = {"digtron:power_connector"},
+ },
+ --[[ {
+ name = "obleceni",
+ groups = {"clothing"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "pláště",
+ groups = {"cape"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "technic_nn",
+ groups = {"technic_lv"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "technic_sn",
+ groups = {"technic_mv"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "technic_vn",
+ groups = {"technic_hv"},
+ items = none,
+ mods = none,
+ }, ]]
+ {
+ name = "listy",
+ groups = {"leaves"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "ingoty",
+ groups = none,
+ items = {"basic_materials:brass_ingot", "default:bronze_ingot", "default:tin_ingot", "default:copper_ingot", "default:gold_ingot", "default:steel_ingot",
+ "moreores:mithril_ingot", "moreores:silver_ingot", "technic:chromium_ingot", "technic:cast_iron_ingot", "technic:stainless_steel_ingot",
+ "technic:lead_ingot", "technic:carbon_steel_ingot", "technic:mixed_metal_ingot", "technic:zinc_ingot", "technic:uranium0_ingot",
+ "technic:uranium_ingot", "technic:uranium35_ingot",
+ "aloz:aluminum_ingot"},
+ mods = none,
+ },
+ {
+ name = "loziska",
+ groups = none,
+ items = {"default:stone_with_tin", "default:stone_with_diamond", "default:stone_with_mese", "default:stone_with_copper", "default:stone_with_coal",
+ "default:stone_with_gold", "default:stone_with_iron", "denseores:large_tin_ore", "denseores:large_diamond_ore", "denseores:large_mese_ore",
+ "denseores:large_copper_ore", "denseores:large_mithril_ore", "denseores:large_silver_ore", "denseores:large_coal_ore",
+ "denseores:large_gold_ore", "denseores:large_iron_ore", "moreores:mineral_mithril", "moreores:mineral_silver",
+ "technic:mineral_chromium", "technic:mineral_lead", "technic:mineral_sulfur", "technic:mineral_uranium", "technic:mineral_zinc",
+ "aloz:stone_with_bauxite"},
+ mods = none,
+ },
+ {
+ name = "sklo",
+ groups = none,
+ items = {"building_blocks:woodglass", "building_blocks:smoothglass", "cucina_vegana:mushroomlight_glass", "darkage:glow_glass",
+ "darkage:glass", "default:obsidian_glass", "default:glass", "moreblocks:clean_glass", "moreblocks:clean_super_glow_glass",
+ "moreblocks:clean_glow_glass", "moreblocks:iron_glass", "moreblocks:super_glow_glass", "moreblocks:glow_glass", "moreblocks:coal_glass"},
+ mods = none,
+ },
+ {
+ name = "kombinace",
+ groups = none,
+ items = none,
+ mods = {"comboblock"},
+ },
+ {
+ name = "clothing_singlecolor",
+ groups = {"clothing_singlecolor", "cape_singlecolor"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "clothing_stripy",
+ groups = {"clothing_stripy", "cape_stripy"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "clothing_squared",
+ groups = {"clothing_squared", "cape_squared"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "clothing_fabric_singlecolor",
+ groups = {"clothing_fabric_singlecolor"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "clothing_fabric_stripy",
+ groups = {"clothing_fabric_stripy"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "clothing_fabric_squared",
+ groups = {"clothing_fabric_squared"},
+ items = none,
+ mods = none,
+ },
+ --[[
+ {
+ name = "trojdesky",
+ groups = {"slab"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "trojsvahy",
+ groups = {"slope"},
+ items = none,
+ mods = none,
+ }, ]]
+ {
+ name = "vypocetni_technika",
+ groups = none,
+ items = {
+ "homedecor:alarm_clock", "homedecor:digital_clock", "homedecor:dvd_vcr",
+ "homedecor:stereo", "homedecor:tv_stand",
+ },
+ mods = {"computers", "digiterms", "home_workshop_machines"},
+ },
+ {
+ name = "platforms_1",
+ groups = {"platform=1"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "platforms_2",
+ groups = {"platform=2"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "platforms_3",
+ groups = {"platform=3"},
+ items = none,
+ mods = none,
+ },
+ {
+ name = "platforms_4",
+ groups = {"platform=4"},
+ items = none,
+ mods = none,
+ },
+}
+
+function ch_core.overridable.is_clothing(item_name)
+ return minetest.get_item_group(item_name, "clothing") > 0 or
+ minetest.get_item_group(item_name, "cape") > 0
+end
+
+function ch_core.overridable.is_stairsplus_shape(item_name, item_def)
+ return false
+end
+
+function ch_core.overridable.is_cnc_shape(item_name, item_def)
+ return false
+end
+
+function ch_core.overridable.is_other_shape(item_name, groups)
+ return
+ (groups.fence and item_name ~= "technic:insulator_clip_fencepost") or
+ groups.gravestone or
+ groups.streets_manhole or
+ groups.streets_stormdrain or
+ item_name:sub(1, 7) == "pkarcs:" or
+ item_name:sub(1, 8) == "pillars:" or
+ item_name:sub(1, 10) == "si_frames:"
+end
+
+local function is_experimental(name, groups)
+ return name:sub(1, 8) == "ch_test:" or (groups.experimental or 0) > 0
+end
+
+local function is_streets_signs(name, groups)
+ return name:sub(1, 8) == "streets:" and (groups.streets_tool or groups.sign)
+end
+
+local categories = {
+ {
+ description = "výchozí paleta předmětů",
+ condition = function(itemstring, name, def, groups, palette_index)
+ local o = ch_core.overridable
+ return
+ not o.is_clothing(name) and
+ not o.is_stairsplus_shape(name, def) and
+ not o.is_cnc_shape(name, def) and
+ not o.is_other_shape(name, groups) and
+ not is_experimental(name, groups) and
+ not is_streets_signs(name, groups) and
+ (not groups.dye or groups.basic_dye) and
+ not groups.platform and
+ name:sub(1, 16) ~= "clothing:fabric_" and
+ name:sub(1, 15) ~= "letters:letter_"
+ end,
+ icon = {
+ {image = "ui_category_all.png^[resize:24x24", item = "unified_inventory:bag_large"},
+ },
+ },
+ {
+ description = "tvary",
+ condition = function(itemstring, name, def, groups, palette_index)
+ local o = ch_core.overridable
+ return o.is_stairsplus_shape(name, def) or
+ o.is_cnc_shape(name, def) or
+ o.is_other_shape(name, groups)
+ end,
+ icon = {
+ {image = "[combine:120x120:-4,-4=technic_cnc_bannerstone.png^[resize:20x20", item = "technic:cnc"},
+ },
+ },
+ {
+ description = "lakované předměty",
+ condition = function(itemstring, name, def, groups, palette_index)
+ return (groups.ud_param2_colorable or 0) > 0 and not is_experimental(name, groups)
+ end,
+ icon = {
+ {image = "lrfurn_armchair_inv.png^[resize:24x24", item = "lrfurn:armchair"},
+ },
+ },
+ {
+ description = "barviva",
+ condition = function(itemstring, name, def, groups, palette_index)
+ return groups.dye ~= nil
+ end,
+ icon = {
+ {image = "dye_green.png^[resize:24x24", item = "dye:green"},
+ },
+ },
+ {
+ description = "dopravní značení",
+ condition = function(itemstring, name, def, groups, palette_index)
+ return is_streets_signs(name, groups) or name == "streets:smallpole" or name == "streets:bigpole" or name == "streets:bigpole_short"
+ end,
+ icon = {
+ {image = "streets_sign_eu_50.png^[resize:24x24", item = "streets:sign_eu_50"},
+ },
+ },
+ {
+ description = "jídlo a pití",
+ condition = function(itemstring, name, def, groups, palette_index)
+ return groups.ch_food ~= nil or groups.drink ~= nil or groups.ch_poison ~= nil
+ end,
+ icon = {
+ {image = "ch_extras_parekvrohliku.png^[resize:24x24", item = "ch_extras:parekvrohliku"},
+ },
+ },
+ {
+ description = "látky (na šaty)",
+ condition = function(itemstring, name, def, groups, palette_index)
+ return name:sub(1, 16) == "clothing:fabric_"
+ end,
+ icon = {
+ {
+ image = "(clothing_fabric.png^[multiply:#f8f7f3)^(((clothing_fabric.png^clothing_inv_second_color.png)^[makealpha:0,0,0)^[multiply:#00b4e8)^[resize:24x24",
+ item = "clothing:fabric_white",
+ },
+ },
+ },
+ {
+ description = "lokomotivy a vagony",
+ condition = function(itemstring, name, def, groups, palette_index)
+ return groups.at_wagon ~= nil
+ end,
+ icon = {
+ {image = "moretrains_engine_japan_inv.png^[resize:24x24", item = "advtrains:moretrains_engine_japan"},
+ },
+ },
+ {
+ description = "nástroje",
+ condition = function(itemstring, name, def, groups, palette_index)
+ return minetest.registered_tools[name] ~= nil
+ end,
+ icon = {
+ {image = "moreores_tool_mithrilpick.png^[resize:24x24", item = "moreores:pick_mithril"},
+ {image = "default_tool_mesepick.png", item = "default:pick_mese"},
+ },
+ },
+ {
+ description = "nástupiště",
+ condition = function(itemstring, name, def, groups, palette_index)
+ return (groups.platform or 0) > 0
+ end,
+ icon = {
+ {image = "basic_materials_cement_block.png^[resize:128x128^advtrains_platform.png^[resize:16x16", item = "advtrains:platform_low_cement_block"}
+ },
+ },
+ {
+ description = "oblečení a obuv",
+ condition = function(itemstring, name, def, groups, palette_index)
+ return ch_core.overridable.is_clothing(name)
+ end,
+ icon = {
+ {image = "(clothing_inv_shirt.png^[multiply:#98cd61)^[resize:24x24", item = "clothing:shirt_green"},
+ },
+ },
+ {
+ description = "všechny předměty",
+ condition = function(itemstring, name, ndef, groups, palette_index)
+ return true
+ end,
+ icon = {
+ {image = "[combine:40x40:-11,-3=letters_pattern.png\\^letters_star_overlay.png\\^[makealpha\\:255,126,126^[resize:16x16", item = "letters:letter_star"},
+ },
+ },
+ {
+ description = "experimentální předměty",
+ condition = function(itemstring, name, ndef, groups, palette_index)
+ return is_experimental(name, groups)
+ end,
+ icon = {
+ {image = "ch_test_4dir_1.png^[resize:16x16", item = "ch_test:test_color"},
+ },
+ },
+ {
+ description = "test: svítící bloky",
+ condition = function(itemstring, name, def, groups, palette_index)
+ return minetest.registered_nodes[name] ~= nil and def.paramtype == "light" and (def.light_source or 0) > 0
+ end,
+ icon = {
+ {image = "default_fence_pine_wood.png^default_mese_post_light_side.png^[makealpha:0,0,0^[resize:16x16", item = "default:mese_post_light_pine_wood"},
+ },
+ },
+ {
+ description = "test: železnice kromě vozidel",
+ condition = function(itemstring, name, def, groups, palette_index)
+ return name:match("^advtrains") and not groups.at_wagon
+ end,
+ icon = {
+ {image = "advtrains_dtrack_placer.png^[resize:24x24", item = "advtrains:dtrack_placer"},
+ },
+ },
+}
+
+local function get_default_categories()
+ local descriptions, icons = {}, {}
+ for i, category_def in ipairs(categories) do
+ descriptions[i] = category_def.description.." [0]"
+ icons[i] = "unknown_item.png^[resize:16x16"
+ end
+ return { descriptions = descriptions, filter = {}, icons = icons }
+end
+
+local function compute_categories(itemstrings)
+ local counts = {}
+ local descriptions = {}
+ local filter = {}
+ local icons = {}
+ local itemstrings_set = {}
+ local registered_items = minetest.registered_items
+ local string_cache = {}
+
+ for i = 1, #categories do
+ counts[i] = 0
+ end
+
+ for _, itemstring in ipairs(itemstrings) do
+ if not itemstrings_set[itemstring] then
+ itemstrings_set[itemstring] = true
+ local stack = ItemStack(itemstring)
+ local name = stack:get_name()
+ local def = registered_items[name]
+ if def ~= nil then
+ local groups = def.groups or none
+ local palette_index
+ if name ~= itemstring then
+ palette_index = stack:get_meta():get_int("palette_index")
+ end
+ local mask = ""
+ for i, category_def in ipairs(categories) do
+ if category_def.condition(itemstring, name, def, groups, palette_index) then
+ mask = mask.."1"
+ counts[i] = counts[i] + 1
+ else
+ mask = mask.."0"
+ end
+ end
+ if string_cache[mask] ~= nil then
+ mask = string_cache[mask]
+ else
+ string_cache[mask] = mask
+ end
+ filter[itemstring] = mask
+ end
+ end
+ end
+ for i, category_def in ipairs(categories) do
+ descriptions[i] = category_def.description.." ["..counts[i].."]"
+ icons[i] = "unknown_item.png^[resize:16x16"
+ for _, icon_def in ipairs(category_def.icon) do
+ if icon_def.item == nil or minetest.registered_items[icon_def.item] ~= nil then
+ icons[i] = assert(icon_def.image)
+ break
+ end
+ end
+ end
+ return { descriptions = descriptions, filter = filter, icons = icons }
+end
+
+ch_core.creative_inventory = {
+ categories = get_default_categories(),
+ --[[
+ = {
+ descriptions[index] = popisek, -- velikost #descriptions udává počet existujících kategorií
+ filter = {
+ [itemstring] = "00100[...]", -- maska kategorií pro každý itemstring
+ },
+ icons[index] = textura, -- ikona kategorie (obrázek)
+ }
+ ]]
+ items_by_order = {},
+ partitions_by_name = {
+ others = {
+ name = "others",
+ items_by_order = {},
+ },
+ },
+ not_initialized = true,
+}
+
+local function generate_palette_itemstrings(name, paramtype2, limit, list_to_add)
+ if list_to_add == nil then
+ list_to_add = {}
+ end
+ if limit == nil then
+ limit = 256
+ end
+ local step
+ if paramtype2 == "color" then
+ step = 1
+ elseif paramtype2 == "colorfacedir" or paramtype2 == "colordegrotate" then
+ step = 32
+ elseif paramtype2 == "color4dir" then
+ step = 4
+ elseif paramtype2 == "colorwallmounted" then
+ step = 8
+ else
+ table.insert(list_to_add, name)
+ return list_to_add
+ end
+ local i = 0
+ while i < limit and i * step < 256 do
+ local itemstring = minetest.itemstring_with_palette(name, i * step)
+ table.insert(list_to_add, itemstring)
+ i = i + 1
+ end
+ return list_to_add
+end
+
+local function sort_items(itemstrings, group_by_mod)
+ -- items is expected to be a sequence of item strings, e. g. {"default:cobble", "default:stick", ...}
+ -- the original list is not changed; the new list is returned
+ local counter_nil, counter_same, counter_diff = 0, 0, 0
+ local itemstring_to_key = {}
+
+ for _, itemstring in ipairs(itemstrings) do
+ local stack = ItemStack(itemstring)
+ local name = stack:get_name()
+ local desc = stack:get_description() or ""
+ local tdesc = minetest.get_translated_string("cs", desc)
+ if tdesc == nil then
+ counter_nil = counter_nil + 1
+ tdesc = ""
+ else
+ if tdesc == desc then
+ counter_same = counter_same + 1
+ else
+ counter_diff = counter_diff + 1
+ end
+ end
+ if group_by_mod then
+ local index = name:find(":")
+ if index then
+ tdesc = name:sub(1, index)..tdesc
+ end
+ end
+ local palette_index = stack:get_meta():get_int("palette_index")
+ if palette_index > 0 then
+ tdesc = string.format("%s/%03d", tdesc, palette_index)
+ end
+ itemstring_to_key[itemstring] = ch_core.utf8_radici_klic(tdesc, false)
+ end
+
+ local result = table.copy(itemstrings)
+ table.sort(result, function(a, b) return itemstring_to_key[a] < itemstring_to_key[b] end)
+ -- minetest.log("info", "sort_items() stats: "..counter_diff.." differents, "..counter_same.." same, "..counter_nil.." nil, "..(counter_diff + counter_same + counter_nil).." total, count = "..#result..".")
+ return result
+end
+
+local creative_inventory_initialized = false
+
+-- should be called when any player logs in
+function ch_core.update_creative_inventory(force_update)
+ if creative_inventory_initialized and not force_update then
+ minetest.log("verbose", "will not update_creative_inventory(): "..(creative_inventory_initialized and "true" or "false").." "..(force_update and "true" or "false"))
+ return false
+ end
+ minetest.log("verbose", "will update_creative_inventory()")
+
+ -- 1. naplň překladové tabulky
+ local name_to_partition = {}
+ local group_to_partition = {}
+ local mod_to_partition = {}
+ local partition_to_exclude_items = {others = none}
+ for _ --[[order]], part_def in ipairs(partition_defs) do
+ if (part_def.exclude_items or none)[1] then
+ local set = {}
+ partition_to_exclude_items[part_def.name] = set
+ for _, name in ipairs(part_def.exclude_items) do
+ set[name] = true
+ end
+ else
+ partition_to_exclude_items[part_def.name] = none
+ end
+ for _, name in ipairs(part_def.items or none) do
+ if name_to_partition[name] then
+ minetest.log("warning", "ERROR in creative_inventory! Item "..name.." has been already set to partition "..name_to_partition[name].." while it is also set to partition "..part_def.name.."!")
+ else
+ name_to_partition[name] = part_def.name
+ end
+ end
+ for _, group in ipairs(part_def.groups or none) do
+ if group_to_partition[group] then
+ minetest.log("warning", "ERROR in creative_inventory! Group "..group.." has been already set to partition "..group_to_partition[group].." while it is also set to partition "..part_def.name.."!")
+ else
+ group_to_partition[group] = part_def.name
+ end
+ end
+ for _, mod in ipairs(part_def.mods or none) do
+ if mod_to_partition[mod] then
+ minetest.log("warning", "ERROR in creative_inventory! Mod "..mod.." has been already set to partition "..mod_to_partition[mod].." while it is also set to partition "..part_def.name.."!")
+ else
+ mod_to_partition[mod] = part_def.name
+ end
+ end
+ end
+
+ -- 2. projdi registrované předměty a zařaď je do příslušných oddílů
+ local existing_partitions = {}
+
+ for name, def in pairs(minetest.registered_items) do
+ local groups = def.groups or none
+ local nici = groups.not_in_creative_inventory
+ if (def.description or "") ~= "" and (nici == nil or nici <= 0) then -- not_in_creative_inventory => skip
+ local partition = "others"
+ if def._ch_partition then
+ partition = def._ch_partition
+ elseif name_to_partition[name] then
+ partition = name_to_partition[name]
+ else
+ local mod --[[, subname]] = name:match("^([^:]*):([^:]*)$")
+ local success = false
+ for group, rank in pairs(groups) do
+ if rank > 0 then
+ local groupplus = group.."="..rank
+ if group_to_partition[group] and not partition_to_exclude_items[group_to_partition[group]][name] then
+ partition = group_to_partition[group]
+ success = true
+ break
+ elseif group_to_partition[groupplus] and not partition_to_exclude_items[group_to_partition[groupplus]][name] then
+ partition = group_to_partition[groupplus]
+ success = true
+ break
+ end
+ end
+ end
+ if not success then
+ if mod and mod_to_partition[mod] and not partition_to_exclude_items[mod_to_partition[mod]][name] then
+ partition = mod_to_partition[mod]
+ end
+ end
+ end
+
+ if partition_to_exclude_items[partition][name] then
+ partition = "others"
+ end
+
+ local partition_list = existing_partitions[partition]
+ if not partition_list then
+ partition_list = {}
+ existing_partitions[partition] = partition_list
+ end
+ if groups.ui_generate_palette_items ~= nil and groups.ui_generate_palette_items > 0 then
+ generate_palette_itemstrings(name, def.paramtype2, groups.ui_generate_palette_items, partition_list)
+ else
+ table.insert(partition_list, name)
+ end
+ end
+ end
+
+ -- 3. vyjmi oddíl "others" pro samostatné zpracování
+ local partition_others_list = existing_partitions.others
+ existing_partitions.others = nil
+
+ -- 4. seřaď předměty v oddílech
+ for partition_name, item_list in pairs(table.copy(existing_partitions)) do
+ existing_partitions[partition_name] = sort_items(item_list, false)
+ end
+ if partition_others_list ~= nil then
+ partition_others_list = sort_items(partition_others_list, true)
+ end
+
+ -- 5. seřaď oddíly
+ local partitions_in_order = {}
+ for _, part_def in ipairs(partition_defs) do
+ local partition_list = existing_partitions[part_def.name]
+ if partition_list then
+ table.insert(partitions_in_order, { name = part_def.name, items_by_order = partition_list })
+ existing_partitions[part_def.name] = nil
+ end
+ end
+ local remaining_partitions = {}
+ for part_name, _ in pairs(existing_partitions) do
+ table.insert(remaining_partitions, part_name)
+ end
+ table.sort(remaining_partitions)
+ for _, part_name in ipairs(remaining_partitions) do
+ table.insert(partitions_in_order, { name = part_name, items_by_order = existing_partitions[part_name]})
+ end
+ if partition_others_list then
+ table.insert(partitions_in_order, { name = "others", items_by_order = partition_others_list})
+ end
+
+ -- 6. sestav z nich partitions_by_name a items_by_order
+ local partitions_by_name = {}
+ local items_by_order = {}
+ local partitions_by_name_count = 0
+
+ for _, part_info in pairs(partitions_in_order) do
+ partitions_by_name[part_info.name] = part_info.items_by_order
+ table.insert_all(items_by_order, part_info.items_by_order)
+ partitions_by_name_count = partitions_by_name_count + 1
+ end
+
+ -- 7. přidej kategorie
+ local ci_categories = compute_categories(items_by_order)
+
+ -- commit
+ local new_ci = {
+ categories = ci_categories,
+ items_by_order = items_by_order,
+ partitions_by_name = partitions_by_name,
+ }
+ ch_core.creative_inventory = new_ci
+ minetest.log("action", "ch_core creative_inventory updated: "..#items_by_order.." items in "..partitions_by_name_count.." partitions")
+ creative_inventory_initialized = true
+ return new_ci
+end
+
+local ifthenelse = ch_core.ifthenelse
+local function cmp_true_first(a, b)
+ if a then
+ return ifthenelse(b, 0, -1)
+ else
+ return ifthenelse(b, 1, 0)
+ end
+end
+local function cmp_str(a, b)
+ if a < b then
+ return -1
+ elseif a > b then
+ return 1
+ else
+ return 0
+ end
+end
+local function cmp_inv(f)
+ return function(a, b, options)
+ return -f(a, b, options)
+ end
+end
+
+local comparisons = {
+ {
+ name = "empty_last",
+ description_asc = "prázdná pole na konec",
+ description_desc = "prázdná pole první",
+ cmp = function(a, b)
+ local count_a, count_b = a:get_count(), b:get_count()
+ return cmp_true_first(count_a > 0, count_b > 0)
+ end,
+ },
+ {
+ name = "by_description",
+ description_asc = "podle popisku (vzestupně)",
+ description_desc = "podle popisku (sestupně)",
+ cmp = function(a, b, options)
+ local s_a, s_b = a:get_description(), b:get_description()
+ local lang_code = options.lang_code
+ if s_a ~= nil then
+ if lang_code ~= nil then
+ s_a = minetest.get_translated_string(lang_code, s_a)
+ end
+ else
+ s_a = a:get_name()
+ end
+ if s_b ~= nil then
+ if lang_code ~= nil then
+ s_b = minetest.get_translated_string(lang_code, s_b)
+ end
+ else
+ s_b = b:get_name()
+ end
+ return cmp_str(ch_core.utf8_radici_klic(s_a, true), ch_core.utf8_radici_klic(s_b, true))
+ end,
+ },
+ {
+ name = "by_modname",
+ description_asc = "podle módu (vzestupně)",
+ description_desc = "podle módu (sestupně)",
+ cmp = function(a, b)
+ local sa = a:get_name():match("^([^:]*):.*") or ""
+ local sb = b:get_name():match("^([^:]*):.*") or ""
+ return cmp_str(sa, sb)
+ end,
+ },
+ {
+ name = "by_itemname",
+ description_asc = "podle technického názvu (vzestupně)",
+ description_desc = "podle technického názvu (sestupně)",
+ cmp = function(a, b)
+ local sa = a:get_name():match("^[^:]*:(.*)$") or a:get_name()
+ local sb = b:get_name():match("^[^:]*:(.*)$") or b:get_name()
+ return cmp_str(sa, sb)
+ end,
+ },
+ {
+ name = "by_count",
+ description_asc = "podle počtu (od nejmenšího)",
+ description_desc = "podle počtu (od největšího)",
+ cmp = function(a, b)
+ return a:get_count() - b:get_count()
+ end,
+ },
+ {
+ name = "tools_first",
+ description_asc = "nástroje první",
+ description_desc = "nástroje na konec",
+ cmp = function(a, b)
+ return cmp_true_first(minetest.registered_tools[a:get_name()], minetest.registered_tools[b:get_name()])
+ end,
+ },
+ {
+ name = "tools_by_wear",
+ description_asc = "nástroje podle opotřebení (od nejmenšího)",
+ description_desc = "nástroje podle opotřebení (od největšího)",
+ cmp = function(a, b)
+ if minetest.registered_tools[a:get_name()] and minetest.registered_tools[b:get_name()]then
+ return a:get_wear() - b:get_wear()
+ else
+ return 0
+ end
+ end,
+ },
+ {
+ name = "books_by_ick",
+ description_asc = "knihy podle IČK (vzestupně)",
+ description_desc = "knihy podle IČK (sestupně)",
+ cmp = function(a, b)
+ if a:is_empty() or b:is_empty() then
+ return 0
+ end
+ local a_name, b_name = a:get_name(), b:get_name()
+ if minetest.get_item_group(a_name, "book") == 0 or minetest.get_item_group(b_name, "book") == 0 then
+ return 0
+ end
+ local a_meta, b_meta = a:get_meta(), b:get_meta()
+ local a_ick = ("0000000000000000"..a_meta:get_string("ick")):sub(-16, -1)
+ local b_ick = ("0000000000000000"..b_meta:get_string("ick")):sub(-16, -1)
+ return cmp_str(a_ick, b_ick)
+ end,
+ },
+ {
+ name = "books_first",
+ description_asc = "knihy první",
+ description_desc = "knihy na konec",
+ cmp = function(a, b)
+ return cmp_true_first(not a:is_empty() and minetest.get_item_group(a:get_name(), "book") ~= 0, not b:is_empty() and minetest.get_item_group(b:get_name(), "book") ~= 0)
+ end,
+ },
+ {
+ name = "books_by_author",
+ description_asc = "knihy podle autorství (vzestupně)",
+ description_desc = "knihy podle autorství (sestupně)",
+ cmp = function(a, b)
+ if a:is_empty() or minetest.get_item_group(a:get_name(), "book") == 0 or b:is_empty() or minetest.get_item_group(b:get_name(), "book") == 0 then
+ return 0
+ end
+ return cmp_str(ch_core.utf8_radici_klic(a:get_meta():get_string("author"), false), ch_core.utf8_radici_klic(b:get_meta():get_string("author"), false))
+ end,
+ },
+ {
+ name = "books_by_title",
+ description_asc = "knihy podle názvu (vzestupně)",
+ description_desc = "knihy podle názvu (sestupně)",
+ cmp = function(a, b)
+ if a:is_empty() or minetest.get_item_group(a:get_name(), "book") == 0 or b:is_empty() or minetest.get_item_group(b:get_name(), "book") == 0 then
+ return 0
+ end
+ return cmp_str(ch_core.utf8_radici_klic(a:get_meta():get_string("title"), false), ch_core.utf8_radici_klic(b:get_meta():get_string("title"), false))
+ end,
+ },
+}
+
+local name_to_comparison_index = {}
+local choices = {}
+for i, cmp_def in ipairs(comparisons) do
+ name_to_comparison_index[cmp_def.name] = i
+ if cmp_def.description_asc ~= nil then
+ table.insert(choices, {name = cmp_def.name, desc = false, description = cmp_def.description_asc})
+ end
+ if cmp_def.description_desc ~= nil then
+ table.insert(choices, {name = cmp_def.name, desc = true, description = cmp_def.description_desc})
+ end
+end
+
+function ch_core.sort_itemstacks(stacks, order_types, lang_code)
+ local cmps = {}
+ for _, otype in ipairs(order_types) do
+ local cmp_index = name_to_comparison_index[otype.name]
+ if cmp_index == nil then
+ error("Invalid order type '"..otype.name.."'!")
+ end
+ if otype.desc then
+ table.insert(cmps, cmp_inv(comparisons[cmp_index].cmp))
+ else
+ table.insert(cmps, comparisons[cmp_index].cmp)
+ end
+ end
+ local options = {lang_code = lang_code}
+ table.sort(stacks, function(a, b)
+ local result
+ for i = 1, #cmps do
+ result = cmps[i](a, b, options)
+ if result < 0 then
+ return true
+ elseif result > 0 then
+ return false
+ end
+ end
+ return 0
+ end)
+end
+
+--[[
+Příklad:
+ local stacks = inv:get_list("main")
+ ch_core.sort_itemstacks(stacks, {
+ {name = "empty_last"},
+ {name = "tools_first", desc = true},
+ {name = "by_description"},
+ {name = "by_modname"},
+ {name = "by_itemname"},
+ {name = "by_count", desc = true},
+ }, ch_data.online_charinfo[player_name].lang_code)
+]]
+
+ch_core.close_submod("creative_inventory")