57 Commits

Author SHA1 Message Date
03b077cd1b Merge remote-tracking branch 'upstream/master' 2021-04-08 13:39:49 +02:00
6e6383f082 Add filter-by-category functionality (#171)
- Added API for configuring categories
- Added display for categories above page
- Reduced height of page by 1 row to make room for categories
- Added L/R scroll through when there are more categories than columns
- Added pre-filter methods for categories and uncategorised items
- Added categories for (most) items in the default game


Co-authored-by: Oversword <bionc:oversword.co.uk>
2021-04-05 20:07:14 +02:00
829b38c6fc Merge remote-tracking branch 'upstream/master' 2021-04-04 21:05:40 +02:00
860371ecf8 more consistent formspec size decision 2021-03-31 00:52:30 -04:00
70fdb8556b Merge remote-tracking branch 'upstream/master' 2021-03-12 12:01:23 +01:00
c044f5e3b0 use the trash slot icon's alpha instead of [combine
also it's supposed to be 128px, not 256px.  fixed that.
2021-03-10 21:20:31 -05:00
608cdfb887 fix refill slot list[] offset also 2021-03-10 12:32:55 -05:00
afb295ec22 fix trash slot list[] offset
(only noticable when listcolors[] allows slots to be visible,
i.e. on mouseover)
2021-03-10 12:26:28 -05:00
a84ce24067 use the ui.list_img_offset variable for offsetting the std inv list[]
so that it'll match every other list that uses it.
2021-03-09 18:31:16 -05:00
a7556c5044 update minimum MT version number 2021-03-09 15:09:46 -05:00
3d58befe03 Document the API version 2021-03-09 15:04:11 -05:00
d0deba10c8 pngcrush+optipng the new slot textures
and remove the slot image .xcf project file
2021-03-09 15:04:11 -05:00
97b882ad23 add a version number variable to the main table 2021-03-09 15:04:11 -05:00
44e32df00a translate some strings inside their table 2021-03-09 15:04:11 -05:00
40d862298b replace excessive spaces with tabs 2021-03-09 15:04:11 -05:00
0ebc9402ed minor tweaks to the slot images
to make them better-resemble their pre-9-sliced versions
(going to that mode made them slightly bigger and the corners
slightly less round since they aren't blurry anymore)
2021-03-09 15:04:11 -05:00
2c16805ef9 Get rid of the image button left of the crafting guide
It had the same function as clicking the craft result on the
right (just inverted), making it redundant. Click either one more
than once and UI would alternately show usages or recipes.
2021-03-09 15:04:11 -05:00
dc61d2980a Move craft guide a little to the right to make some room. 2021-03-09 15:04:11 -05:00
21f122336f make craft arrow 128px
(same reason as the trash icon)
2021-03-09 15:04:11 -05:00
8ee0eb9fce swap the craft type icon with its word
(makes it look like it used to)
2021-03-09 15:04:11 -05:00
1210dbfe22 make trash slot icon 128px
MT nearest-neighbor-scales images to about 75px if they're 1x1
slot in size (at least on my screen).  Use the next power of 2
above that, so that MT can scale down instead of up.
2021-03-09 15:04:11 -05:00
b8a568d7eb remove unused var, excess whitespace 2021-03-09 15:04:11 -05:00
9ddea6eced fix missing "XYZ" and "no" icon on waypoints show coordinates button 2021-03-09 15:04:11 -05:00
76c9bb9517 Use 9-slicing to build inventory-type backgrounds
This way the slots are all nice and crisp regardless of GUI scale or
image size, and we only need the single slot and its bright version.

This also makes the standard crafting grid into a style table entry that
can be referenced to insert the crafting grid at its proper
style-specific position in any formspec.

And it also makes the craft grid arrow, its X position, and the crafting
grid's result slot X position into style table entries.

Includes a few public helper functions to do most of the work:

`ui.single_slot(xpos, ypos, bright)`

    Does just what it sounds like: it returns a single slot image.
    `xpos` and `ypos` are normal coordinates in slots, as you'd use in
    `image[]` element.  `bright` is a flag that switches to the brighter
    version of the slot image.

`ui.make_trash_slot(xpos, ypos)`

    Creates a single slot, with a one-item `list[]` and a trash can icon
    overlay.

`ui.make_inv_img_grid(xpos, ypos, width, height, bright)`

    Generates a `width` by `height` grid of slot images, using the
    single_slot function above, starting at (`xpos`,`ypos`) for the
    top-left.  Position is as in any `image[]` element, and dimensions
    are in integer numbers of slots (so 8,4 would be a standard inventory).
    `bright` is as above.

All three return a string that can be directly inserted into a formspec.
2021-03-09 15:04:11 -05:00
60d7a6d213 Draw the trash slot by overlaying the bare trash can icon
over the single slot image instead of baking it in.
2021-03-09 15:04:11 -05:00
8e94d86420 don't display the refill slot image if no creative priv/mode
(leftover from when it was part of the craft grid image)

Also fixed a typo in the corresponding list[] element that
made it not work.
2021-03-09 15:04:11 -05:00
6d892dda5b use local ui=unified_inventory shorthand in init.lua as elsewhere 2021-03-09 15:04:11 -05:00
37546289bc using a table.copy() to pass the style tables around requires
setting-up items_per_page, standard_inv, and standard_inv_bg
for both tables at init time.
2021-03-09 15:04:11 -05:00
3e7f005366 always modify and return a table.copy() of the style table 2021-03-09 15:04:11 -05:00
382219c466 move S() calls into waypoints' button table
instead of inside the loop
2021-03-09 15:04:11 -05:00
5ea0208ffe Multiple related changes to string handling
1) Convert most formspec elements to use string.format(), when the
result would be more readable, or less messy, or at least makes the line
shorter, assuming it looked like it really needed it to begin with.

2) Convert all long `foo..","..bar..";"..baz..bleh..` types of excessive
string concatenation into tables that then get concated only once, when
their containing functions return the final formspec string.

3) In some places in the code, such tables were already being used, and
were named "formspec", while others were named "fs".  I settled on just
one name, "formspec", as it's more readable, if longer.

4) There was a mix of styles of adding items to those tables:

* Some places used line after line of `t[#t + 1] = foo/bar/baz`.
* Others places used the form `t[1] = foo, t[2] = bar, ...`.
* Still others used the form `t[n] = foo, t[n+1] = bar...`,
  with `n` being increased or reset every so often.

Most of them should now be of the third form, with a few of the second.
2021-03-09 15:04:11 -05:00
694553e68b use local "ui" to reference "unified_inventory", where practical
(makes code shorter, easier to read and write)
2021-03-09 15:04:11 -05:00
2d200eb9ae Ditto for bags. 2021-03-09 15:04:11 -05:00
b3077898a7 make waypoints explicitly reference full-style vars
(since it does not support lite mode)
2021-03-09 15:04:11 -05:00
5a8a75f43b put style-specific settings in their own tables
and switch between them directly, instead of copy-and-modify.
2021-03-09 15:04:11 -05:00
0c05f06fa8 "Please continue to use string.format here to avoid messy code"
Derp :-)
2021-03-09 15:04:11 -05:00
c3679eaf7b fix indent 2021-03-09 15:04:11 -05:00
23a089f174 remove a used-only-once variable 2021-03-09 15:04:11 -05:00
82bc2d3f95 use string.format() to create the standard_inv variables
do it just once, after the lite mode settings are applied
(if applicable)
2021-03-09 15:04:11 -05:00
603b5d1d4e get rid of uninv global
make all uses of it back into `unified_inventory.`
2021-03-09 15:04:11 -05:00
eb4cf5bf47 increase spacing around the text above the items page
("Filter:" and its search key, and the page or "No matches)
Adjust main and page flipping buttons' positions to compensate
2021-03-09 15:04:11 -05:00
97960c552b increase size and tweak position of "give/to grid" buttons
and make them vary in pos with lite vs full mode
2021-03-09 15:04:11 -05:00
81d6a1e796 shift the craft grid and guide down a bit
to make more room for the result string
(and shift the result string down a hair to follow)
2021-03-09 15:04:11 -05:00
de575a6513 9-slice the background image 2021-03-09 15:04:11 -05:00
7a0a44037a remove a couple of unused variables 2021-03-09 15:04:11 -05:00
cc93288a6b bump minimum version to 5.4.0 2021-03-09 15:04:11 -05:00
167dddaa84 Convert over to formspec version 4
I recreated the original layout as best as practical, but by necessity
there are a few minor positioning changes, since the underlying
hard-wired inventory slots are square now and image positioning is now
scaled by exactly 1.250 in both dimensions (as opposed to roughly 1.25
by 1.16).

Backstage, I also needed to fix the aspect ratios of the various
inventory slot elements.  That meant redesigning the single-slot image
from scratch.  It was already blurry/grainy and a little ugly, and
trying to alter it would have only made it worse.

The slot image is now exactly 56x56 pixels square, set on a 64x64
canvas, so there's a 4 pixel empty space around the edges. The full
256px .xcf workfile is included in the UI folder.

I've re-tiled all slot/inv images from the new single slot.

I also re-rendered the trash can icon from it since it was blurry and
oddly-sized. I couldn't find the original upstream image, so since
they're free, I used one of my Linux system's icons which happens to
resemble it.

I also removed a couple more improper uses of `background[]` where
`image[]` is more appropriate.

There are tons of minor tweaks throughout the code to re-align
everything, and I had to rewrite a few sections to avoid code
duplication and to allow for a little more flexibility (mainly to make
"lite" mode look right).
2021-03-09 15:04:11 -05:00
d1a4396fbe Fix bags backwards compatibility breakage since 4403b69 (#167) 2021-03-09 11:12:50 +01:00
fbbf786caf Tweak spacing between bags page top row and bag's inv 2021-03-01 18:57:50 +01:00
ae124b02c2 Tweak trash can icon 2021-03-01 18:57:50 +01:00
ebd1d1f245 Improve consistency of inventory (and alike) imagery
In a number of places, background[] is misused to place the
inventory backdrop images.  Where appropriate, image[] is used
instead, so that "ui_form_bg.png" actually serves as the one
and only true background image.

In so doing, I was able to remake the bag inventory images,
making them only big as is actually needed to hold 1, 2, or 3
rows of inventory slots.

This, in turn, allows a standardized main inventory image to
occupy the lower part of the window, which allows for
consistent inventory image positioning and sizing from one
page to another.

I also removed ui_misc_form.png.  Nothing in UI uses it, and
any external mods that used it can just use the standard
inventory and its background.

Lastly, I reduced the background image to 512x384 px.  It was
unnecessarily large before, considering it has no real detail.

The larger inventory images are all 512px wide, and multiples
of 64px in height.  Before, they were oddly sized.
2021-03-01 18:57:50 +01:00
497c632b24 Merge remote-tracking branch 'upstream/master' 2020-12-18 12:20:14 +01:00
0f756a5d33 Update translation for zh_CN and zh_TW (#161) 2020-12-15 19:17:10 +01:00
46eeb36784 Merge remote-tracking branch 'upstream/master' 2020-07-18 11:28:21 +02:00
341a438267 Search items by English and translated description (#156)
This works only with Minetest version >= 5.3.0, nothing is changed for
older versions.
2020-07-15 20:21:06 +02:00
d86592841e Remove unused 0.4.x files, multiline description 2020-07-11 19:51:42 +02:00
f25426911d Fix teleport sounds when teleport fails (#155) 2020-07-10 21:58:45 +02:00
38 changed files with 1598 additions and 437 deletions

View File

@ -14,6 +14,7 @@ read_globals = {
"ItemStack", "datastorage", "ItemStack", "datastorage",
"hb", "hb",
"doors",
} }
files["callbacks.lua"].ignore = { "player", "draw_lite_mode" } files["callbacks.lua"].ignore = { "player", "draw_lite_mode" }

View File

@ -24,7 +24,7 @@ Unified Inventory replaces the default survival and creative inventory.
## Requirements ## Requirements
* Minetest 5.0.0+ * Minetest 5.4.0+
# Licenses # Licenses

118
api.lua
View File

@ -1,5 +1,6 @@
local S = minetest.get_translator("unified_inventory") local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape local F = minetest.formspec_escape
local ui = unified_inventory
-- Create detached creative inventory after loading all mods -- Create detached creative inventory after loading all mods
minetest.after(0.01, function() minetest.after(0.01, function()
@ -8,12 +9,12 @@ minetest.after(0.01, function()
if not rev_aliases[target] then rev_aliases[target] = {} end if not rev_aliases[target] then rev_aliases[target] = {} end
table.insert(rev_aliases[target], source) table.insert(rev_aliases[target], source)
end end
unified_inventory.items_list = {} ui.items_list = {}
for name, def in pairs(minetest.registered_items) do for name, def in pairs(minetest.registered_items) do
if (not def.groups.not_in_creative_inventory or if (not def.groups.not_in_creative_inventory or
def.groups.not_in_creative_inventory == 0) and def.groups.not_in_creative_inventory == 0) and
def.description and def.description ~= "" then def.description and def.description ~= "" then
table.insert(unified_inventory.items_list, name) table.insert(ui.items_list, name)
local all_names = rev_aliases[name] or {} local all_names = rev_aliases[name] or {}
table.insert(all_names, name) table.insert(all_names, name)
for _, player_name in ipairs(all_names) do for _, player_name in ipairs(all_names) do
@ -26,30 +27,30 @@ minetest.after(0.01, function()
for _,chk in pairs(recipe.items) do for _,chk in pairs(recipe.items) do
local groupchk = string.find(chk, "group:") local groupchk = string.find(chk, "group:")
if (not groupchk and not minetest.registered_items[chk]) if (not groupchk and not minetest.registered_items[chk])
or (groupchk and not unified_inventory.get_group_item(string.gsub(chk, "group:", "")).item) or (groupchk and not ui.get_group_item(string.gsub(chk, "group:", "")).item)
or minetest.get_item_group(chk, "not_in_craft_guide") ~= 0 then or minetest.get_item_group(chk, "not_in_craft_guide") ~= 0 then
unknowns = true unknowns = true
end end
end end
if not unknowns then if not unknowns then
unified_inventory.register_craft(recipe) ui.register_craft(recipe)
end end
end end
end end
end end
end end
end end
table.sort(unified_inventory.items_list) table.sort(ui.items_list)
unified_inventory.items_list_size = #unified_inventory.items_list ui.items_list_size = #ui.items_list
print("Unified Inventory. inventory size: "..unified_inventory.items_list_size) print("Unified Inventory. inventory size: "..ui.items_list_size)
for _, name in ipairs(unified_inventory.items_list) do for _, name in ipairs(ui.items_list) do
local def = minetest.registered_items[name] local def = minetest.registered_items[name]
-- Simple drops -- Simple drops
if type(def.drop) == "string" then if type(def.drop) == "string" then
local dstack = ItemStack(def.drop) local dstack = ItemStack(def.drop)
if not dstack:is_empty() and dstack:get_name() ~= name then if not dstack:is_empty() and dstack:get_name() ~= name then
unified_inventory.register_craft({ ui.register_craft({
type = "digging", type = "digging",
items = {name}, items = {name},
output = def.drop, output = def.drop,
@ -115,7 +116,7 @@ minetest.after(0.01, function()
end end
end end
for itemstring, count in pairs(drop_guaranteed) do for itemstring, count in pairs(drop_guaranteed) do
unified_inventory.register_craft({ ui.register_craft({
type = "digging", type = "digging",
items = {name}, items = {name},
output = itemstring .. " " .. count, output = itemstring .. " " .. count,
@ -123,7 +124,7 @@ minetest.after(0.01, function()
}) })
end end
for itemstring, count in pairs(drop_maybe) do for itemstring, count in pairs(drop_maybe) do
unified_inventory.register_craft({ ui.register_craft({
type = "digging_chance", type = "digging_chance",
items = {name}, items = {name},
output = itemstring .. " " .. count, output = itemstring .. " " .. count,
@ -132,22 +133,22 @@ minetest.after(0.01, function()
end end
end end
end end
for _, recipes in pairs(unified_inventory.crafts_for.recipe) do for _, recipes in pairs(ui.crafts_for.recipe) do
for _, recipe in ipairs(recipes) do for _, recipe in ipairs(recipes) do
local ingredient_items = {} local ingredient_items = {}
for _, spec in pairs(recipe.items) do for _, spec in pairs(recipe.items) do
local matches_spec = unified_inventory.canonical_item_spec_matcher(spec) local matches_spec = ui.canonical_item_spec_matcher(spec)
for _, name in ipairs(unified_inventory.items_list) do for _, name in ipairs(ui.items_list) do
if matches_spec(name) then if matches_spec(name) then
ingredient_items[name] = true ingredient_items[name] = true
end end
end end
end end
for name, _ in pairs(ingredient_items) do for name, _ in pairs(ingredient_items) do
if unified_inventory.crafts_for.usage[name] == nil then if ui.crafts_for.usage[name] == nil then
unified_inventory.crafts_for.usage[name] = {} ui.crafts_for.usage[name] = {}
end end
table.insert(unified_inventory.crafts_for.usage[name], recipe) table.insert(ui.crafts_for.usage[name], recipe)
end end
end end
end end
@ -156,9 +157,9 @@ end)
-- load_home -- load_home
local function load_home() local function load_home()
local input = io.open(unified_inventory.home_filename, "r") local input = io.open(ui.home_filename, "r")
if not input then if not input then
unified_inventory.home_pos = {} ui.home_pos = {}
return return
end end
while true do while true do
@ -167,32 +168,34 @@ local function load_home()
local y = input:read("*n") local y = input:read("*n")
local z = input:read("*n") local z = input:read("*n")
local name = input:read("*l") local name = input:read("*l")
unified_inventory.home_pos[name:sub(2)] = {x = x, y = y, z = z} ui.home_pos[name:sub(2)] = {x = x, y = y, z = z}
end end
io.close(input) io.close(input)
end end
load_home() load_home()
function unified_inventory.set_home(player, pos) function ui.set_home(player, pos)
local player_name = player:get_player_name() local player_name = player:get_player_name()
unified_inventory.home_pos[player_name] = vector.round(pos) ui.home_pos[player_name] = vector.round(pos)
-- save the home data from the table to the file -- save the home data from the table to the file
local output = io.open(unified_inventory.home_filename, "w") local output = io.open(ui.home_filename, "w")
for k, v in pairs(unified_inventory.home_pos) do for k, v in pairs(ui.home_pos) do
output:write(v.x.." "..v.y.." "..v.z.." "..k.."\n") output:write(v.x.." "..v.y.." "..v.z.." "..k.."\n")
end end
io.close(output) io.close(output)
end end
function unified_inventory.go_home(player) function ui.go_home(player)
local pos = unified_inventory.home_pos[player:get_player_name()] local pos = ui.home_pos[player:get_player_name()]
if pos then if pos then
player:set_pos(pos) player:set_pos(pos)
return true
end end
return false
end end
-- register_craft -- register_craft
function unified_inventory.register_craft(options) function ui.register_craft(options)
if not options.output then if not options.output then
return return
end end
@ -203,10 +206,10 @@ function unified_inventory.register_craft(options)
if options.type == "normal" and options.width == 0 then if options.type == "normal" and options.width == 0 then
options = { type = "shapeless", items = options.items, output = options.output, width = 0 } options = { type = "shapeless", items = options.items, output = options.output, width = 0 }
end end
if not unified_inventory.crafts_for.recipe[itemstack:get_name()] then if not ui.crafts_for.recipe[itemstack:get_name()] then
unified_inventory.crafts_for.recipe[itemstack:get_name()] = {} ui.crafts_for.recipe[itemstack:get_name()] = {}
end end
table.insert(unified_inventory.crafts_for.recipe[itemstack:get_name()],options) table.insert(ui.crafts_for.recipe[itemstack:get_name()],options)
end end
@ -217,7 +220,7 @@ local craft_type_defaults = {
} }
function unified_inventory.craft_type_defaults(name, options) function ui.craft_type_defaults(name, options)
if not options.description then if not options.description then
options.description = name options.description = name
end end
@ -226,13 +229,13 @@ function unified_inventory.craft_type_defaults(name, options)
end end
function unified_inventory.register_craft_type(name, options) function ui.register_craft_type(name, options)
unified_inventory.registered_craft_types[name] = ui.registered_craft_types[name] =
unified_inventory.craft_type_defaults(name, options) ui.craft_type_defaults(name, options)
end end
unified_inventory.register_craft_type("normal", { ui.register_craft_type("normal", {
description = F(S("Crafting")), description = F(S("Crafting")),
icon = "ui_craftgrid_icon.png", icon = "ui_craftgrid_icon.png",
width = 3, width = 3,
@ -248,7 +251,7 @@ unified_inventory.register_craft_type("normal", {
}) })
unified_inventory.register_craft_type("shapeless", { ui.register_craft_type("shapeless", {
description = F(S("Mixing")), description = F(S("Mixing")),
icon = "ui_craftgrid_icon.png", icon = "ui_craftgrid_icon.png",
width = 3, width = 3,
@ -263,7 +266,7 @@ unified_inventory.register_craft_type("shapeless", {
}) })
unified_inventory.register_craft_type("cooking", { ui.register_craft_type("cooking", {
description = F(S("Cooking")), description = F(S("Cooking")),
icon = "default_furnace_front.png", icon = "default_furnace_front.png",
width = 1, width = 1,
@ -271,37 +274,60 @@ unified_inventory.register_craft_type("cooking", {
}) })
unified_inventory.register_craft_type("digging", { ui.register_craft_type("digging", {
description = F(S("Digging")), description = F(S("Digging")),
icon = "default_tool_steelpick.png", icon = "default_tool_steelpick.png",
width = 1, width = 1,
height = 1, height = 1,
}) })
unified_inventory.register_craft_type("digging_chance", { ui.register_craft_type("digging_chance", {
description = "Digging (by chance)", description = "Digging (by chance)",
icon = "default_tool_steelpick.png^[transformFY.png", icon = "default_tool_steelpick.png^[transformFY.png",
width = 1, width = 1,
height = 1, height = 1,
}) })
function unified_inventory.register_page(name, def) function ui.register_page(name, def)
unified_inventory.pages[name] = def ui.pages[name] = def
end end
function unified_inventory.register_button(name, def) function ui.register_button(name, def)
if not def.action then if not def.action then
def.action = function(player) def.action = function(player)
unified_inventory.set_inventory_formspec(player, name) ui.set_inventory_formspec(player, name)
end end
end end
def.name = name def.name = name
table.insert(unified_inventory.buttons, def) table.insert(ui.buttons, def)
end end
function ui.is_creative(playername)
function unified_inventory.is_creative(playername)
return minetest.check_player_privs(playername, {creative=true}) return minetest.check_player_privs(playername, {creative=true})
or minetest.settings:get_bool("creative_mode") or minetest.settings:get_bool("creative_mode")
end end
function ui.single_slot(xpos, ypos, bright)
return string.format("background9[%f,%f;%f,%f;ui_single_slot%s.png;false;16]",
xpos, ypos, ui.imgscale, ui.imgscale, (bright and "_bright" or "") )
end
function ui.make_trash_slot(xpos, ypos)
return
ui.single_slot(xpos, ypos)..
"image["..xpos..","..ypos..";1.25,1.25;ui_trash_slot_icon.png]"..
"list[detached:trash;main;"..(xpos + ui.list_img_offset)..","..(ypos + ui.list_img_offset)..";1,1;]"
end
function ui.make_inv_img_grid(xpos, ypos, width, height, bright)
local tiled = {}
local n=1
for y = 0, (height - 1) do
for x = 0, (width -1) do
tiled[n] = ui.single_slot(xpos + (ui.imgscale * x), ypos + (ui.imgscale * y), bright)
n = n + 1
end
end
return table.concat(tiled)
end

View File

@ -7,27 +7,32 @@ License: GPLv3
local S = minetest.get_translator("unified_inventory") local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape local F = minetest.formspec_escape
local ui = unified_inventory
unified_inventory.register_page("bags", { ui.register_page("bags", {
get_formspec = function(player) get_formspec = function(player)
local player_name = player:get_player_name() local player_name = player:get_player_name()
return { formspec = table.concat({ return { formspec = table.concat({
"background[0.06,0.99;7.92,7.52;ui_bags_main_form.png]", ui.style_full.standard_inv_bg,
"label[0,0;" .. F(S("Bags")) .. "]", ui.single_slot(0.925, 1.5),
"button[0,2;2,0.5;bag1;" .. F(S("Bag @1", 1)) .. "]", ui.single_slot(3.425, 1.5),
"button[2,2;2,0.5;bag2;" .. F(S("Bag @1", 2)) .. "]", ui.single_slot(5.925, 1.5),
"button[4,2;2,0.5;bag3;" .. F(S("Bag @1", 3)) .. "]", ui.single_slot(8.425, 1.5),
"button[6,2;2,0.5;bag4;" .. F(S("Bag @1", 4)) .. "]", "label["..ui.style_full.form_header_x..","..ui.style_full.form_header_y..";" .. F(S("Bags")) .. "]",
"button[0.6125,2.75;1.875,0.75;bag1;" .. F(S("Bag @1", 1)) .. "]",
"button[3.1125,2.75;1.875,0.75;bag2;" .. F(S("Bag @1", 2)) .. "]",
"button[5.6125,2.75;1.875,0.75;bag3;" .. F(S("Bag @1", 3)) .. "]",
"button[8.1125,2.75;1.875,0.75;bag4;" .. F(S("Bag @1", 4)) .. "]",
"listcolors[#00000000;#00000000]", "listcolors[#00000000;#00000000]",
"list[detached:" .. F(player_name) .. "_bags;bag1;0.5,1;1,1;]", "list[detached:" .. F(player_name) .. "_bags;bag1;1.075,1.65;1,1;]",
"list[detached:" .. F(player_name) .. "_bags;bag2;2.5,1;1,1;]", "list[detached:" .. F(player_name) .. "_bags;bag2;3.575,1.65;1,1;]",
"list[detached:" .. F(player_name) .. "_bags;bag3;4.5,1;1,1;]", "list[detached:" .. F(player_name) .. "_bags;bag3;6.075,1.65;1,1;]",
"list[detached:" .. F(player_name) .. "_bags;bag4;6.5,1;1,1;]" "list[detached:" .. F(player_name) .. "_bags;bag4;8.575,1.65;1,1;]"
}) } }) }
end, end,
}) })
unified_inventory.register_button("bags", { ui.register_button("bags", {
type = "image", type = "image",
image = "ui_bags_icon.png", image = "ui_bags_icon.png",
tooltip = S("Bags"), tooltip = S("Bags"),
@ -42,32 +47,31 @@ local function get_player_bag_stack(player, i)
end end
for bag_i = 1, 4 do for bag_i = 1, 4 do
unified_inventory.register_page("bag" .. bag_i, { ui.register_page("bag" .. bag_i, {
get_formspec = function(player) get_formspec = function(player)
local stack = get_player_bag_stack(player, bag_i) local stack = get_player_bag_stack(player, bag_i)
local image = stack:get_definition().inventory_image local image = stack:get_definition().inventory_image
local fs = {
"image[7,0;1,1;" .. image .. "]",
"label[0,0;" .. F(S("Bag @1", bag_i)) .. "]",
"listcolors[#00000000;#00000000]",
"list[current_player;bag" .. bag_i .. "contents;0,1;8,3;]",
"listring[current_name;bag" .. bag_i .. "contents]",
"listring[current_player;main]"
}
local slots = stack:get_definition().groups.bagslots local slots = stack:get_definition().groups.bagslots
if slots == 8 then
fs[#fs + 1] = "background[0.06,0.99;7.92,7.52;ui_bags_sm_form.png]" local formspec = {
elseif slots == 16 then ui.style_full.standard_inv_bg,
fs[#fs + 1] = "background[0.06,0.99;7.92,7.52;ui_bags_med_form.png]" ui.make_inv_img_grid(0.3, 1.5, 8, slots/8),
elseif slots == 24 then "image[9.2,0.4;1,1;" .. image .. "]",
fs[#fs + 1] = "background[0.06,0.99;7.92,7.52;ui_bags_lg_form.png]" "label[0.3,0.65;" .. F(S("Bag @1", bag_i)) .. "]",
end "listcolors[#00000000;#00000000]",
"listring[current_player;main]",
string.format("list[current_player;bag%icontents;%f,%f;8,3;]",
bag_i, 0.3 + ui.list_img_offset, 1.5 + ui.list_img_offset),
"listring[current_name;bag" .. bag_i .. "contents]",
}
local n = #formspec + 1
local player_name = player:get_player_name() -- For if statement. local player_name = player:get_player_name() -- For if statement.
if unified_inventory.trash_enabled if ui.trash_enabled
or unified_inventory.is_creative(player_name) or ui.is_creative(player_name)
or minetest.get_player_privs(player_name).give then or minetest.get_player_privs(player_name).give then
fs[#fs + 1] = "background[6.06,0;0.92,0.92;ui_bags_trash.png]" formspec[n] = ui.make_trash_slot(7.8, 0.25)
.. "list[detached:trash;main;6,0.1;1,1;]" n = n + 1
end end
local inv = player:get_inventory() local inv = player:get_inventory()
for i = 1, 4 do for i = 1, 4 do
@ -84,11 +88,12 @@ for bag_i = 1, 4 do
end end
local img = def.inventory_image local img = def.inventory_image
local label = F(S("Bag @1", i)) .. "\n" .. used .. "/" .. size local label = F(S("Bag @1", i)) .. "\n" .. used .. "/" .. size
fs[#fs + 1] = string.format("image_button[%i,0;1,1;%s;bag%i;%s]", formspec[n] = string.format("image_button[%f,0.4;1,1;%s;bag%i;%s]",
i + 1, img, i, label) (i + 1.35)*1.25, img, i, label)
n = n + 1
end end
end end
return { formspec = table.concat(fs) } return { formspec = table.concat(formspec) }
end, end,
}) })
end end
@ -103,7 +108,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if not stack:get_definition().groups.bagslots then if not stack:get_definition().groups.bagslots then
return return
end end
unified_inventory.set_inventory_formspec(player, "bag" .. i) ui.set_inventory_formspec(player, "bag" .. i)
return return
end end
end end
@ -132,7 +137,7 @@ end
local function load_bags_metadata(player, bags_inv) local function load_bags_metadata(player, bags_inv)
local player_inv = player:get_inventory() local player_inv = player:get_inventory()
local meta = player:get_meta() local meta = player:get_meta()
local bags_meta = meta:get_string("unified_inventory:bags") local bags_meta = meta:get("unified_inventory:bags")
local bags = bags_meta and minetest.deserialize(bags_meta) or {} local bags = bags_meta and minetest.deserialize(bags_meta) or {}
local dirty_meta = false local dirty_meta = false
if not bags_meta then if not bags_meta then

View File

@ -19,6 +19,8 @@ minetest.register_on_joinplayer(function(player)
unified_inventory.active_search_direction[player_name] = "nochange" unified_inventory.active_search_direction[player_name] = "nochange"
unified_inventory.apply_filter(player, "", "nochange") unified_inventory.apply_filter(player, "", "nochange")
unified_inventory.current_searchbox[player_name] = "" unified_inventory.current_searchbox[player_name] = ""
unified_inventory.current_category[player_name] = "all"
unified_inventory.current_category_scroll[player_name] = 0
unified_inventory.alternate[player_name] = 1 unified_inventory.alternate[player_name] = 1
unified_inventory.current_item[player_name] = nil unified_inventory.current_item[player_name] = nil
unified_inventory.current_craft_direction[player_name] = "recipe" unified_inventory.current_craft_direction[player_name] = "recipe"
@ -69,6 +71,41 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
unified_inventory.current_searchbox[player_name] = fields.searchbox unified_inventory.current_searchbox[player_name] = fields.searchbox
end end
local clicked_category
for name, value in pairs(fields) do
local category_name = string.match(name, "^category_(.+)$")
if category_name then
clicked_category = category_name
break
end
end
if clicked_category
and clicked_category ~= unified_inventory.current_category[player_name] then
unified_inventory.current_category[player_name] = clicked_category
unified_inventory.apply_filter(player, unified_inventory.current_searchbox[player_name], "nochange")
unified_inventory.set_inventory_formspec(player,
unified_inventory.current_page[player_name])
end
if fields.next_category then
local scroll = math.min(#unified_inventory.category_list-ui_peruser.pagecols, unified_inventory.current_category_scroll[player_name] + 1)
if scroll ~= unified_inventory.current_category_scroll[player_name] then
unified_inventory.current_category_scroll[player_name] = scroll
unified_inventory.set_inventory_formspec(player,
unified_inventory.current_page[player_name])
end
end
if fields.prev_category then
local scroll = math.max(0, unified_inventory.current_category_scroll[player_name] - 1)
if scroll ~= unified_inventory.current_category_scroll[player_name] then
unified_inventory.current_category_scroll[player_name] = scroll
unified_inventory.set_inventory_formspec(player,
unified_inventory.current_page[player_name])
end
end
for i, def in pairs(unified_inventory.buttons) do for i, def in pairs(unified_inventory.buttons) do
if fields[def.name] then if fields[def.name] then
def.action(player) def.action(player)
@ -126,6 +163,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
clicked_item = unified_inventory.demangle_for_formspec(mangled_item) clicked_item = unified_inventory.demangle_for_formspec(mangled_item)
if string.sub(clicked_item, 1, 6) == "group:" then if string.sub(clicked_item, 1, 6) == "group:" then
-- Change search filter to this group -- Change search filter to this group
unified_inventory.current_category[player_name] = "all"
apply_new_filter(player, clicked_item, new_dir) apply_new_filter(player, clicked_item, new_dir)
return return
end end

149
category.lua Normal file
View File

@ -0,0 +1,149 @@
local S = minetest.get_translator("unified_inventory")
unified_inventory.registered_categories = {}
unified_inventory.registered_category_items = {}
unified_inventory.category_list = {}
local function char_to_sort_index(char_code)
if char_code <= 32 then
-- Command codes, no thanks
return 0
end
if char_code <= 64 then
-- Sorts numbers, and some punctuation, after letters
return char_code
end
if char_code >= 158 then
-- Out of sortable range
return 0
end
if char_code > 122 then
-- Avoids overlap with {, |, } and ~
return char_code - 58
end
if char_code > 96 then
-- Normalises lowercase with uppercase
return char_code - 96
end
return char_code - 64
end
local function string_to_sort_index(str)
local max_chars = 5
local power = 100
local index = 0
for i=1,math.min(#str, max_chars) do
index = index + (char_to_sort_index(string.byte(str, i))/(power^i))
end
return index
end
function update_category_list()
local category_list = {}
table.insert(category_list, {
name = "all",
label = S("All Items"),
symbol = "ui_category_all.png",
index = -2,
})
table.insert(category_list, {
name = "uncategorized",
label = S("Misc. Items"),
symbol = "ui_category_none.png",
index = -1,
})
for category, def in pairs(unified_inventory.registered_categories) do
table.insert(category_list, {
name = category,
label = def.label or category,
symbol = def.symbol,
index = def.index or -- sortby defined order
string_to_sort_index(category) -- or do a rudimentary alphabetical sort
})
end
table.sort(category_list, function (a,b)
return a.index < b.index
end)
unified_inventory.category_list = category_list
end
local function ensure_category_exists(category_name)
if not unified_inventory.registered_categories[category_name] then
unified_inventory.registered_categories[category_name] = {
symbol = "default:stick",
label = category_name
}
end
if not unified_inventory.registered_category_items[category_name] then
unified_inventory.registered_category_items[category_name] = {}
end
end
function unified_inventory.register_category(category_name, config)
ensure_category_exists(category_name)
if config and config.symbol then
unified_inventory.set_category_symbol(category_name, config.symbol)
end
if config and config.label then
unified_inventory.set_category_label(category_name, config.label)
end
if config and config.index then
unified_inventory.set_category_index(category_name, config.index)
end
if config and config.items then
unified_inventory.add_category_items(category_name, config.items)
end
update_category_list()
end
function unified_inventory.set_category_symbol(category_name, symbol)
ensure_category_exists(category_name)
unified_inventory.registered_categories[category_name].symbol = symbol
update_category_list()
end
function unified_inventory.set_category_label(category_name, label)
ensure_category_exists(category_name)
unified_inventory.registered_categories[category_name].label = label
update_category_list()
end
function unified_inventory.set_category_index(category_name, index)
ensure_category_exists(category_name)
unified_inventory.registered_categories[category_name].index = index
update_category_list()
end
function unified_inventory.add_category_item(category_name, item)
ensure_category_exists(category_name)
unified_inventory.registered_category_items[category_name][item] = true
end
function unified_inventory.add_category_items(category_name, items)
for _,item in ipairs(items) do
unified_inventory.add_category_item(category_name, item)
end
end
function unified_inventory.remove_category_item(category_name, item)
unified_inventory.registered_category_items[category_name][item] = nil
end
function unified_inventory.remove_category(category_name)
unified_inventory.registered_categories[category_name] = nil
unified_inventory.registered_category_items[category_name] = nil
update_category_list()
end
function unified_inventory.find_category(item)
-- Returns the first category the item exists in
-- Best for checking if an item has any category at all
for category, items in pairs(unified_inventory.registered_category_items) do
if items[item] then return category end
end
end
function unified_inventory.find_categories(item)
-- Returns all the categories the item exists in
-- Best for listing all categories
local categories = {}
for category, items in pairs(unified_inventory.registered_category_items) do
if items[item] then
table.insert(categories, category)
end
end
return categories
end

704
default-categories.lua Normal file
View File

@ -0,0 +1,704 @@
local S = minetest.get_translator("unified_inventory")
unified_inventory.register_category('plants', {
symbol = "flowers:tulip",
label = S("Plant Life")
})
unified_inventory.register_category('building', {
symbol = "default:brick",
label = S("Building Materials")
})
unified_inventory.register_category('tools', {
symbol = "default:pick_diamond",
label = S("Tools")
})
unified_inventory.register_category('minerals', {
symbol = "default:iron_lump",
label = S("Minerals and Metals")
})
unified_inventory.register_category('environment', {
symbol = "default:dirt_with_grass",
label = S("Environment and Worldgen")
})
unified_inventory.register_category('lighting', {
symbol = "default:torch",
label = S("Lighting")
})
if unified_inventory.automatic_categorization then
minetest.register_on_mods_loaded(function()
-- Add biome nodes to environment category
for _,def in pairs(minetest.registered_biomes) do
local env_nodes = {
def.node_riverbed, def.node_top, def.node_filler, def.node_dust,
}
for i,node in pairs(env_nodes) do
if node then
unified_inventory.add_category_item('environment', node)
end
end
end
-- Add minable ores to minerals and everything else (pockets of stone & sand variations) to environment
for _,item in pairs(minetest.registered_ores) do
if item.ore_type == "scatter" then
local drop = minetest.registered_nodes[item.ore].drop
if drop and drop ~= "" then
unified_inventory.add_category_item('minerals', item.ore)
unified_inventory.add_category_item('minerals', drop)
else
unified_inventory.add_category_item('environment', item.ore)
end
else
unified_inventory.add_category_item('environment', item.ore)
end
end
-- Add items by item definition
for name, def in pairs(minetest.registered_items) do
local group = def.groups or {}
if not group.not_in_creative_inventory then
if group.stair or
group.slab or
group.wall or
group.fence then
unified_inventory.add_category_item('building', name)
elseif group.flora or
group.flower or
group.seed or
group.leaves or
group.sapling or
group.tree then
unified_inventory.add_category_item('plants', name)
elseif def.type == 'tool' then
unified_inventory.add_category_item('tools', name)
elseif def.liquidtype == 'source' then
unified_inventory.add_category_item('environment', name)
elseif def.light_source and def.light_source > 0 then
unified_inventory.add_category_item('lighting', name)
elseif group.door or
minetest.global_exists("doors") and (
doors.registered_doors and doors.registered_doors[name..'_a'] or
doors.registered_trapdoors and doors.registered_trapdoors[name]
) then
unified_inventory.add_category_item('building', name)
end
end
end
end)
end
-- [[
unified_inventory.add_category_items('plants', {
"default:dry_grass_5",
"default:acacia_sapling",
"default:blueberry_bush_sapling",
"default:grass_2",
"default:pine_bush_stem",
"default:leaves",
"default:pine_needles",
"default:cactus",
"default:junglegrass",
"default:pine_sapling",
"default:sapling",
"default:bush_stem",
"default:dry_grass_2",
"default:fern_1",
"default:grass_3",
"default:marram_grass_1",
"default:pine_tree",
"default:dry_grass_3",
"default:dry_shrub",
"default:grass_4",
"default:marram_grass_2",
"default:jungleleaves",
"default:apple",
"default:tree",
"default:aspen_tree",
"default:bush_sapling",
"default:grass_5",
"default:blueberry_bush_leaves_with_berries",
"default:acacia_bush_sapling",
"default:grass_1",
"default:aspen_leaves",
"default:marram_grass_3",
"default:large_cactus_seedling",
"default:junglesapling",
"default:dry_grass_4",
"default:acacia_bush_stem",
"default:papyrus",
"default:pine_bush_needles",
"default:bush_leaves",
"default:fern_3",
"default:aspen_sapling",
"default:acacia_tree",
"default:apple_mark",
"default:acacia_leaves",
"default:jungletree",
"default:dry_grass_1",
"default:acacia_bush_leaves",
"default:emergent_jungle_sapling",
"default:fern_2",
"default:blueberries",
"default:sand_with_kelp",
"default:blueberry_bush_leaves",
"default:pine_bush_sapling",
"farming:cotton",
"farming:cotton_1",
"farming:cotton_2",
"farming:cotton_3",
"farming:cotton_4",
"farming:cotton_5",
"farming:cotton_6",
"farming:cotton_7",
"farming:cotton_8",
"farming:cotton_wild",
"farming:seed_cotton",
"farming:seed_wheat",
"farming:straw",
"farming:wheat",
"farming:wheat_1",
"farming:wheat_2",
"farming:wheat_3",
"farming:wheat_4",
"farming:wheat_5",
"farming:wheat_6",
"farming:wheat_7",
"farming:wheat_8",
"flowers:chrysanthemum_green",
"flowers:dandelion_white",
"flowers:dandelion_yellow",
"flowers:geranium",
"flowers:mushroom_brown",
"flowers:mushroom_red",
"flowers:rose",
"flowers:tulip",
"flowers:tulip_black",
"flowers:viola",
"flowers:waterlily",
"flowers:waterlily_waving",
})
unified_inventory.add_category_items('tools', {
"default:sword_diamond",
"default:axe_diamond",
"default:shovel_diamond",
"default:axe_steel",
"default:shovel_mese",
"default:sword_wood",
"default:pick_bronze",
"default:axe_stone",
"default:sword_stone",
"default:pick_stone",
"default:shovel_stone",
"default:sword_mese",
"default:shovel_bronze",
"default:sword_bronze",
"default:axe_bronze",
"default:shovel_steel",
"default:sword_steel",
"default:axe_mese",
"default:shovel_wood",
"default:pick_mese",
"default:axe_wood",
"default:pick_diamond",
"default:pick_wood",
"default:pick_steel",
"farming:hoe_bronze",
"farming:hoe_diamond",
"farming:hoe_mese",
"farming:hoe_steel",
"farming:hoe_stone",
"farming:hoe_wood",
"fire:flint_and_steel",
"map:mapping_kit",
"screwdriver:screwdriver",
"fireflies:bug_net",
"bucket:bucket_empty",
"binoculars:binoculars",
"default:skeleton_key",
})
unified_inventory.add_category_items('minerals', {
"default:stone_with_copper",
"default:stone_with_gold",
"default:stone_with_iron",
"default:copper_ingot",
"default:copper_lump",
"default:gold_lump",
"default:diamondblock",
"default:stone_with_diamond",
"default:stone_with_mese",
"default:steel_ingot",
"default:gold_ingot",
"default:iron_lump",
"default:tinblock",
"default:tin_lump",
"default:stone_with_tin",
"default:mese_crystal",
"default:diamond",
"default:bronze_ingot",
"default:mese",
"default:mese_crystal_fragment",
"default:copperblock",
"default:stone_with_coal",
"default:steelblock",
"default:tin_ingot",
"default:coalblock",
"default:coal_lump",
"default:bronzeblock",
"default:goldblock",
"stairs:slab_bronzeblock",
"stairs:slab_copperblock",
"stairs:slab_steelblock",
"stairs:slab_tinblock",
"stairs:stair_bronzeblock",
"stairs:stair_copperblock",
"stairs:stair_inner_bronzeblock",
"stairs:stair_inner_copperblock",
"stairs:stair_inner_steelblock",
"stairs:stair_inner_tinblock",
"stairs:stair_outer_bronzeblock",
"stairs:stair_outer_copperblock",
"stairs:stair_outer_steelblock",
"stairs:stair_outer_tinblock",
"stairs:stair_steelblock",
"stairs:stair_tinblock",
})
unified_inventory.add_category_items('building', {
"default:fence_rail_aspen_wood",
"default:fence_rail_acacia_wood",
"default:fence_junglewood",
"default:fence_rail_junglewood",
"default:fence_aspen_wood",
"default:fence_pine_wood",
"default:fence_rail_wood",
"default:fence_rail_pine_wood",
"default:fence_acacia_wood",
"default:junglewood",
"default:acacia_wood",
"default:aspen_wood",
"default:fence_wood",
"default:pine_wood",
"default:silver_sandstone",
"default:desert_sandstone",
"default:sandstone_block",
"default:desert_sandstone_brick",
"default:stone_block",
"default:stonebrick",
"default:obsidian_glass",
"default:desert_sandstone_block",
"default:silver_sandstone_brick",
"default:brick",
"default:obsidianbrick",
"default:sandstonebrick",
"default:sandstone",
"default:desert_stone_block",
"default:silver_sandstone_block",
"default:wood",
"default:obsidian_block",
"default:glass",
"default:clay_brick",
"default:desert_stonebrick",
"default:desert_cobble",
"default:cobble",
"default:mossycobble",
"doors:door_glass",
"doors:door_glass_a",
"doors:door_glass_b",
"doors:door_glass_c",
"doors:door_glass_d",
"doors:door_obsidian_glass",
"doors:door_obsidian_glass_a",
"doors:door_obsidian_glass_b",
"doors:door_obsidian_glass_c",
"doors:door_obsidian_glass_d",
"doors:door_steel",
"doors:door_steel_a",
"doors:door_steel_b",
"doors:door_steel_c",
"doors:door_steel_d",
"doors:door_wood",
"doors:door_wood_a",
"doors:door_wood_b",
"doors:door_wood_c",
"doors:door_wood_d",
"doors:gate_acacia_wood_closed",
"doors:gate_acacia_wood_open",
"doors:gate_aspen_wood_closed",
"doors:gate_aspen_wood_open",
"doors:gate_junglewood_closed",
"doors:gate_junglewood_open",
"doors:gate_pine_wood_closed",
"doors:gate_pine_wood_open",
"doors:gate_wood_closed",
"doors:gate_wood_open",
"doors:hidden",
"doors:trapdoor",
"doors:trapdoor_open",
"doors:trapdoor_steel",
"doors:trapdoor_steel_open",
"stairs:slab_bronzeblock",
"stairs:slab_copperblock",
"stairs:slab_steelblock",
"stairs:slab_tinblock",
"stairs:stair_bronzeblock",
"stairs:stair_copperblock",
"stairs:stair_inner_bronzeblock",
"stairs:stair_inner_copperblock",
"stairs:stair_inner_steelblock",
"stairs:stair_inner_tinblock",
"stairs:stair_outer_bronzeblock",
"stairs:stair_outer_copperblock",
"stairs:stair_outer_steelblock",
"stairs:stair_outer_tinblock",
"stairs:stair_steelblock",
"stairs:stair_tinblock",
"stairs:slab_acacia_wood",
"stairs:slab_aspen_wood",
"stairs:slab_brick",
"stairs:slab_cobble",
"stairs:slab_desert_cobble",
"stairs:slab_desert_sandstone",
"stairs:slab_desert_sandstone_block",
"stairs:slab_desert_sandstone_brick",
"stairs:slab_desert_stone",
"stairs:slab_desert_stone_block",
"stairs:slab_desert_stonebrick",
"stairs:slab_glass",
"stairs:slab_goldblock",
"stairs:slab_ice",
"stairs:slab_junglewood",
"stairs:slab_mossycobble",
"stairs:slab_obsidian",
"stairs:slab_obsidian_block",
"stairs:slab_obsidian_glass",
"stairs:slab_obsidianbrick",
"stairs:slab_pine_wood",
"stairs:slab_sandstone",
"stairs:slab_sandstone_block",
"stairs:slab_sandstonebrick",
"stairs:slab_silver_sandstone",
"stairs:slab_silver_sandstone_block",
"stairs:slab_silver_sandstone_brick",
"stairs:slab_snowblock",
"stairs:slab_stone",
"stairs:slab_stone_block",
"stairs:slab_stonebrick",
"stairs:slab_straw",
"stairs:slab_wood",
"stairs:stair_acacia_wood",
"stairs:stair_aspen_wood",
"stairs:stair_brick",
"stairs:stair_cobble",
"stairs:stair_desert_cobble",
"stairs:stair_desert_sandstone",
"stairs:stair_desert_sandstone_block",
"stairs:stair_desert_sandstone_brick",
"stairs:stair_desert_stone",
"stairs:stair_desert_stone_block",
"stairs:stair_desert_stonebrick",
"stairs:stair_glass",
"stairs:stair_goldblock",
"stairs:stair_ice",
"stairs:stair_inner_acacia_wood",
"stairs:stair_inner_aspen_wood",
"stairs:stair_inner_brick",
"stairs:stair_inner_cobble",
"stairs:stair_inner_desert_cobble",
"stairs:stair_inner_desert_sandstone",
"stairs:stair_inner_desert_sandstone_block",
"stairs:stair_inner_desert_sandstone_brick",
"stairs:stair_inner_desert_stone",
"stairs:stair_inner_desert_stone_block",
"stairs:stair_inner_desert_stonebrick",
"stairs:stair_inner_glass",
"stairs:stair_inner_goldblock",
"stairs:stair_inner_ice",
"stairs:stair_inner_junglewood",
"stairs:stair_inner_mossycobble",
"stairs:stair_inner_obsidian",
"stairs:stair_inner_obsidian_block",
"stairs:stair_inner_obsidian_glass",
"stairs:stair_inner_obsidianbrick",
"stairs:stair_inner_pine_wood",
"stairs:stair_inner_sandstone",
"stairs:stair_inner_sandstone_block",
"stairs:stair_inner_sandstonebrick",
"stairs:stair_inner_silver_sandstone",
"stairs:stair_inner_silver_sandstone_block",
"stairs:stair_inner_silver_sandstone_brick",
"stairs:stair_inner_snowblock",
"stairs:stair_inner_stone",
"stairs:stair_inner_stone_block",
"stairs:stair_inner_stonebrick",
"stairs:stair_inner_straw",
"stairs:stair_inner_wood",
"stairs:stair_junglewood",
"stairs:stair_mossycobble",
"stairs:stair_obsidian",
"stairs:stair_obsidian_block",
"stairs:stair_obsidian_glass",
"stairs:stair_obsidianbrick",
"stairs:stair_outer_acacia_wood",
"stairs:stair_outer_aspen_wood",
"stairs:stair_outer_brick",
"stairs:stair_outer_cobble",
"stairs:stair_outer_desert_cobble",
"stairs:stair_outer_desert_sandstone",
"stairs:stair_outer_desert_sandstone_block",
"stairs:stair_outer_desert_sandstone_brick",
"stairs:stair_outer_desert_stone",
"stairs:stair_outer_desert_stone_block",
"stairs:stair_outer_desert_stonebrick",
"stairs:stair_outer_glass",
"stairs:stair_outer_goldblock",
"stairs:stair_outer_ice",
"stairs:stair_outer_junglewood",
"stairs:stair_outer_mossycobble",
"stairs:stair_outer_obsidian",
"stairs:stair_outer_obsidian_block",
"stairs:stair_outer_obsidian_glass",
"stairs:stair_outer_obsidianbrick",
"stairs:stair_outer_pine_wood",
"stairs:stair_outer_sandstone",
"stairs:stair_outer_sandstone_block",
"stairs:stair_outer_sandstonebrick",
"stairs:stair_outer_silver_sandstone",
"stairs:stair_outer_silver_sandstone_block",
"stairs:stair_outer_silver_sandstone_brick",
"stairs:stair_outer_snowblock",
"stairs:stair_outer_stone",
"stairs:stair_outer_stone_block",
"stairs:stair_outer_stonebrick",
"stairs:stair_outer_straw",
"stairs:stair_outer_wood",
"stairs:stair_pine_wood",
"stairs:stair_sandstone",
"stairs:stair_sandstone_block",
"stairs:stair_sandstonebrick",
"stairs:stair_silver_sandstone",
"stairs:stair_silver_sandstone_block",
"stairs:stair_silver_sandstone_brick",
"stairs:stair_snowblock",
"stairs:stair_stone",
"stairs:stair_stone_block",
"stairs:stair_stonebrick",
"stairs:stair_straw",
"stairs:stair_wood",
"xpanes:bar",
"xpanes:bar_flat",
"xpanes:door_steel_bar",
"xpanes:door_steel_bar_a",
"xpanes:door_steel_bar_b",
"xpanes:door_steel_bar_c",
"xpanes:door_steel_bar_d",
"xpanes:obsidian_pane",
"xpanes:obsidian_pane_flat",
"xpanes:pane",
"xpanes:pane_flat",
"xpanes:trapdoor_steel_bar",
"xpanes:trapdoor_steel_bar_open",
"walls:cobble",
"walls:desertcobble",
"walls:mossycobble",
})
unified_inventory.add_category_items('environment', {
"air",
"default:cave_ice",
"default:dirt_with_rainforest_litter",
"default:gravel",
"default:dry_dirt_with_dry_grass",
"default:permafrost",
"default:desert_stone",
"default:ice",
"default:dry_dirt",
"default:obsidian",
"default:sand",
"default:river_water_source",
"default:dirt_with_snow",
"default:dirt_with_grass",
"default:water_flowing",
"default:dirt",
"default:desert_sand",
"default:permafrost_with_moss",
"default:dirt_with_coniferous_litter",
"default:water_source",
"default:dirt_with_dry_grass",
"default:river_water_flowing",
"default:stone",
"default:snow",
"default:lava_flowing",
"default:lava_source",
"default:permafrost_with_stones",
"default:dirt_with_grass_footsteps",
"default:silver_sand",
"default:snowblock",
"default:clay",
"farming:desert_sand_soil",
"farming:desert_sand_soil_wet",
"farming:dry_soil",
"farming:dry_soil_wet",
"farming:soil",
"farming:soil_wet",
})
unified_inventory.add_category_items('lighting', {
"default:mese_post_light_junglewood",
"default:torch_ceiling",
"default:meselamp",
"default:torch",
"default:mese_post_light_acacia_wood",
"default:mese_post_light",
"default:torch_wall",
"default:mese_post_light_pine_wood",
"default:mese_post_light_aspen_wood"
})
--]]
--[[ UNCATEGORISED
"farming:string",
"beds:bed_bottom",
"beds:bed_top",
"beds:fancy_bed_bottom",
"beds:fancy_bed_top",
"boats:boat",
"bones:bones",
"bucket:bucket_lava",
"bucket:bucket_river_water",
"bucket:bucket_water",
"butterflies:butterfly_red",
"butterflies:butterfly_violet",
"butterflies:butterfly_white",
"butterflies:hidden_butterfly_red",
"butterflies:hidden_butterfly_violet",
"butterflies:hidden_butterfly_white",
"carts:brakerail",
"carts:cart",
"carts:powerrail",
"carts:rail",
"default:book",
"default:book_written",
"default:bookshelf",
"default:chest",
"default:chest_locked",
"default:chest_locked_open",
"default:chest_open",
"default:clay_lump",
"default:cloud",
"default:coral_brown",
"default:coral_cyan",
"default:coral_green",
"default:coral_orange",
"default:coral_pink",
"default:coral_skeleton",
"default:flint",
"default:furnace",
"default:furnace_active",
"default:key",
"default:ladder_steel",
"default:ladder_wood",
"default:obsidian_shard",
"default:paper",
"default:sign_wall_steel",
"default:sign_wall_wood",
"default:stick",
"fire:basic_flame",
"fire:permanent_flame",
"fireflies:firefly",
"fireflies:firefly_bottle",
"fireflies:hidden_firefly",
"ignore",
"unknown",
"tnt:boom",
"tnt:gunpowder",
"tnt:gunpowder_burning",
"tnt:tnt",
"tnt:tnt_burning",
"tnt:tnt_stick",
"vessels:drinking_glass",
"vessels:glass_bottle",
"vessels:glass_fragments",
"vessels:shelf",
"vessels:steel_bottle",
"dye:black",
"dye:blue",
"dye:brown",
"dye:cyan",
"dye:dark_green",
"dye:dark_grey",
"dye:green",
"dye:grey",
"dye:magenta",
"dye:orange",
"dye:pink",
"dye:red",
"dye:violet",
"dye:white",
"dye:yellow",
"wool:black",
"wool:blue",
"wool:brown",
"wool:cyan",
"wool:dark_green",
"wool:dark_grey",
"wool:green",
"wool:grey",
"wool:magenta",
"wool:orange",
"wool:pink",
"wool:red",
"wool:violet",
"wool:white",
"wool:yellow",
"unified_inventory:bag_large",
"unified_inventory:bag_medium",
"unified_inventory:bag_small",
--]]
--[[ LIST UNCATEGORIZED AFTER LOAD
minetest.register_on_mods_loaded(function()
minetest.after(1, function ( )
local l = {}
for name,_ in pairs(minetest.registered_items) do
if not unified_inventory.find_category(name) then
-- minetest.log("error", minetest.serialize(minetest.registered_items[name]))
table.insert(l, name)
end
end
table.sort(l)
minetest.log(table.concat(l, '",'.."\n"..'"'))
end)
end)
--]]

View File

@ -1,5 +0,0 @@
default
creative?
sfinv?
datastorage?
farming?

View File

@ -1 +0,0 @@
Unified Inventory replaces the default survival and creative inventory. It adds a nicer interface and a number of features, such as a crafting guide.

View File

@ -3,6 +3,14 @@ unified_inventory API
This file provides information about the API of unified_inventory. This file provides information about the API of unified_inventory.
API revisions within unified_inventory can be checked using:
(unified_inventory.version or 1)
**Revision history**
* Version `1`: Classic formspec layout (no real_coordinates)
* Version `2`: Force formspec version 4 (includes real_coordinates)
Misc functions Misc functions
-------------- --------------
@ -93,3 +101,72 @@ Register a non-standard craft recipe:
-- ^ Same as `minetest.register_recipe` -- ^ Same as `minetest.register_recipe`
}) })
Categories
----------
Register a new category:
The config table (second argument) is optional, and all its members are optional
See the unified_inventory.set_category_* functions for more details on the members of the config table
unified_inventory.register_category("category_name", {
symbol = "mod_name:item_name" or "texture.png",
label = "Human Readable Label",
index = 5,
items = {
"mod_name:item_name",
"another_mod:different_item"
}
})
Add / override the symbol for a category:
The category does not need to exist first
The symbol can be an item name or a texture image
If unset this will default to "default:stick"
unified_inventory.set_category_symbol("category_name", "mod_name:item_name" or "texture.png")
Add / override the human readable label for a category:
If unset this will default to the category name
unified_inventory.set_category_label("category_name", "Human Readable Label")
Add / override the sorting index of the category:
Must be a number, can also be negative (-5) or fractional (2.345)
This determines the position the category appears in the list of categories
The "all" meta-category has index -2, the "misc"/"uncategorized" meta-category has index -1, use a negative number smaller than these to make a category appear before these in the list
By default categories are sorted alphabetically with an index between 0.0101(AA) and 0.2626(ZZ)
unified_inventory.set_category_index("category_name", 5)
Add a single item to a category:
unified_inventory.add_category_item("category_name", "mod_name:item_name")
Add multiple items to a category:
unified_inventory.add_category_items("category_name", {
"mod_name:item_name",
"another_mod:different_item"
})
Remove an item from a category:
unified_inventory.remove_category_item("category_name", "mod_name:item_name")
Remove a category entirely:
unified_inventory.remove_category("category_name")
Finding existing items in categories:
This will find the first category an item exists in
It should be used for checking if an item is catgorised
Returns "category_name" or nil
unified_inventory.find_category("mod_name:item_name")
This will find all the categories an item exists in
Returns a number indexed table (list) of category names
unified_inventory.find_categories("mod_name:item_name")

115
init.lua
View File

@ -10,6 +10,8 @@ unified_inventory = {
alternate = {}, alternate = {},
current_page = {}, current_page = {},
current_searchbox = {}, current_searchbox = {},
current_category = {},
current_category_scroll = {},
current_index = {}, current_index = {},
current_item = {}, current_item = {},
current_craft_direction = {}, current_craft_direction = {},
@ -33,20 +35,110 @@ unified_inventory = {
-- "Lite" mode -- "Lite" mode
lite_mode = minetest.settings:get_bool("unified_inventory_lite"), lite_mode = minetest.settings:get_bool("unified_inventory_lite"),
-- Items automatically added to categories based on item definitions
automatic_categorization = (minetest.settings:get_bool("unified_inventory_automatic_categorization") ~= false),
-- Trash enabled -- Trash enabled
trash_enabled = (minetest.settings:get_bool("unified_inventory_trash") ~= false), trash_enabled = (minetest.settings:get_bool("unified_inventory_trash") ~= false),
imgscale = 1.25,
pagecols = 8, list_img_offset = 0.13,
pagerows = 10, standard_background = "background9[0,0;1,1;ui_formbg_9_sliced.png;true;16]",
page_y = 0, version = 2
formspec_y = 1,
main_button_x = 0,
main_button_y = 9,
craft_result_x = 0.3,
craft_result_y = 0.5,
form_header_y = 0
} }
local ui = unified_inventory
-- These tables establish position and layout for the two UI styles.
-- UI doesn't use formspec_[xy] anymore, but other mods may need them.
ui.style_full = {
formspec_x = 1,
formspec_y = 1,
formw = 17.75,
formh = 12.25,
pagecols = 8,
pagerows = 9,
page_x = 10.75,
page_y = 2.30,
craft_x = 2.8,
craft_y = 1.15,
craftresult_x = 7.8,
craft_arrow_x = 6.55,
craft_guide_x = 3.3,
craft_guide_y = 1.15,
craft_guide_arrow_x = 7.05,
craft_guide_result_x = 8.3,
craft_guide_resultstr_x = 0.3,
craft_guide_resultstr_y = 0.6,
give_btn_x = 0.25,
main_button_x = 0.4,
main_button_y = 11.0,
page_buttons_x = 11.60,
page_buttons_y = 10.15,
searchwidth = 3.4,
form_header_x = 0.4,
form_header_y = 0.4,
btn_spc = 0.85,
btn_size = 0.75,
std_inv_x = 0.3,
std_inv_y = 5.75,
}
ui.style_lite = {
formspec_x = 0.6,
formspec_y = 0.6,
formw = 14,
formh = 9.75,
pagecols = 4,
pagerows = 5,
page_x = 10.5,
page_y = 2.15,
craft_x = 2.6,
craft_y = 0.75,
craftresult_x = 5.75,
craft_arrow_x = 6.35,
craft_guide_x = 3.1,
craft_guide_y = 0.75,
craft_guide_arrow_x = 7.05,
craft_guide_result_x = 8.3,
craft_guide_resultstr_x = 0.15,
craft_guide_resultstr_y = 0.35,
give_btn_x = 0.15,
main_button_x = 10.5,
main_button_y = 8.15,
page_buttons_x = 10.5,
page_buttons_y = 6.15,
searchwidth = 1.6,
form_header_x = 0.2,
form_header_y = 0.2,
btn_spc = 0.8,
btn_size = 0.7,
std_inv_x = 0.1,
std_inv_y = 4.6,
}
dofile(modpath.."/api.lua")
for _, style in ipairs({ui.style_full, ui.style_lite}) do
style.items_per_page = style.pagecols * style.pagerows
style.standard_inv = string.format("list[current_player;main;%f,%f;8,4;]",
style.std_inv_x + ui.list_img_offset, style.std_inv_y + ui.list_img_offset)
style.standard_inv_bg = ui.make_inv_img_grid(style.std_inv_x, style.std_inv_y, 8, 1, true)..
ui.make_inv_img_grid(style.std_inv_x, style.std_inv_y + ui.imgscale, 8, 3)
style.craft_grid = table.concat({
ui.make_inv_img_grid(style.craft_x, style.craft_y, 3, 3),
ui.single_slot(style.craft_x + ui.imgscale*4, style.craft_y), -- the craft result slot
string.format("image[%f,%f;%f,%f;ui_crafting_arrow.png]",
style.craft_arrow_x, style.craft_y, ui.imgscale, ui.imgscale),
string.format("list[current_player;craft;%f,%f;3,3;]",
style.craft_x + ui.list_img_offset, style.craft_y + ui.list_img_offset),
string.format("list[current_player;craftpreview;%f,%f;1,1;]",
style.craftresult_x + ui.list_img_offset, style.craft_y + ui.list_img_offset)
})
end
-- Disable default creative inventory -- Disable default creative inventory
local creative = rawget(_G, "creative") or rawget(_G, "creative_inventory") local creative = rawget(_G, "creative") or rawget(_G, "creative_inventory")
if creative then if creative then
@ -62,7 +154,8 @@ if sfinv then
end end
dofile(modpath.."/group.lua") dofile(modpath.."/group.lua")
dofile(modpath.."/api.lua") dofile(modpath.."/category.lua")
dofile(modpath.."/default-categories.lua")
dofile(modpath.."/internal.lua") dofile(modpath.."/internal.lua")
dofile(modpath.."/callbacks.lua") dofile(modpath.."/callbacks.lua")
dofile(modpath.."/match_craft.lua") dofile(modpath.."/match_craft.lua")

View File

@ -1,5 +1,6 @@
local S = minetest.get_translator("unified_inventory") local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape local F = minetest.formspec_escape
local ui = unified_inventory
-- This pair of encoding functions is used where variable text must go in -- This pair of encoding functions is used where variable text must go in
-- button names, where the text might contain formspec metacharacters. -- button names, where the text might contain formspec metacharacters.
@ -9,78 +10,61 @@ local F = minetest.formspec_escape
-- This is a game engine bug, and in the anticipation that it might be -- This is a game engine bug, and in the anticipation that it might be
-- fixed some day we don't want to rely on it. So for safety we apply -- fixed some day we don't want to rely on it. So for safety we apply
-- an encoding that avoids all formspec metacharacters. -- an encoding that avoids all formspec metacharacters.
function unified_inventory.mangle_for_formspec(str)
function ui.mangle_for_formspec(str)
return string.gsub(str, "([^A-Za-z0-9])", function (c) return string.format("_%d_", string.byte(c)) end) return string.gsub(str, "([^A-Za-z0-9])", function (c) return string.format("_%d_", string.byte(c)) end)
end end
function unified_inventory.demangle_for_formspec(str) function ui.demangle_for_formspec(str)
return string.gsub(str, "_([0-9]+)_", function (v) return string.char(v) end) return string.gsub(str, "_([0-9]+)_", function (v) return string.char(v) end)
end end
function unified_inventory.get_per_player_formspec(player_name)
local lite = unified_inventory.lite_mode and not minetest.check_player_privs(player_name, {ui_full=true})
local ui = {} function ui.get_per_player_formspec(player_name)
ui.pagecols = unified_inventory.pagecols local draw_lite_mode = ui.lite_mode and not minetest.check_player_privs(player_name, {ui_full=true})
ui.pagerows = unified_inventory.pagerows
ui.page_y = unified_inventory.page_y
ui.formspec_y = unified_inventory.formspec_y
ui.main_button_x = unified_inventory.main_button_x
ui.main_button_y = unified_inventory.main_button_y
ui.craft_result_x = unified_inventory.craft_result_x
ui.craft_result_y = unified_inventory.craft_result_y
ui.form_header_y = unified_inventory.form_header_y
if lite then return table.copy(draw_lite_mode and ui.style_lite or ui.style_full), draw_lite_mode
ui.pagecols = 4
ui.pagerows = 6
ui.page_y = 0.25
ui.formspec_y = 0.47
ui.main_button_x = 8.2
ui.main_button_y = 6.5
ui.craft_result_x = 2.8
ui.craft_result_y = 3.4
ui.form_header_y = -0.1
end
ui.items_per_page = ui.pagecols * ui.pagerows
return ui, lite
end end
function unified_inventory.get_formspec(player, page) local function formspec_button(ui_peruser, name, image, offset, pos, scale, label)
local element = 'image_button'
if minetest.registered_items[image] then
element = 'item_image_button'
end
local spc = (1-scale)*ui_peruser.btn_size/2
local size = ui_peruser.btn_size*scale
return string.format("%s[%f,%f;%f,%f;%s;%s;]", element,
(offset.x or offset[1]) + ( ui_peruser.btn_spc * (pos.x or pos[1]) ) + spc,
(offset.y or offset[2]) + ( ui_peruser.btn_spc * (pos.y or pos[2]) ) + spc,
size, size, image, name) ..
string.format("tooltip[%s;%s]", name, F(label or name))
end
function ui.get_formspec(player, page)
if not player then if not player then
return "" return ""
end end
local player_name = player:get_player_name() local player_name = player:get_player_name()
local ui_peruser,draw_lite_mode = unified_inventory.get_per_player_formspec(player_name) local ui_peruser,draw_lite_mode = ui.get_per_player_formspec(player_name)
unified_inventory.current_page[player_name] = page ui.current_page[player_name] = page
local pagedef = unified_inventory.pages[page] local pagedef = ui.pages[page]
if not pagedef then if not pagedef then
return "" -- Invalid page name return "" -- Invalid page name
end end
local formspec = { local formspec = {
"size[14,10]", "formspec_version[4]",
"size["..ui_peruser.formw..","..ui_peruser.formh.."]",
pagedef.formspec_prepend and "" or "no_prepend[]", pagedef.formspec_prepend and "" or "no_prepend[]",
"background[-0.19,-0.25;14.4,10.75;ui_form_bg.png]" -- Background ui.standard_background
} }
local n = 4
if draw_lite_mode then local n = 5
formspec[1] = "size[11,7.7]"
formspec[3] = "background[-0.19,-0.2;11.4,8.4;ui_form_bg.png]"
end
if unified_inventory.is_creative(player_name) local perplayer_formspec = ui.get_per_player_formspec(player_name)
and page == "craft" then
formspec[n] = "background[0,"..(ui_peruser.formspec_y + 2)..";1,1;ui_single_slot.png]"
n = n+1
end
local perplayer_formspec = unified_inventory.get_per_player_formspec(player_name)
local fsdata = pagedef.get_formspec(player, perplayer_formspec) local fsdata = pagedef.get_formspec(player, perplayer_formspec)
formspec[n] = fsdata.formspec formspec[n] = fsdata.formspec
@ -93,7 +77,7 @@ function unified_inventory.get_formspec(player, page)
local filtered_inv_buttons = {} local filtered_inv_buttons = {}
for i, def in pairs(unified_inventory.buttons) do for i, def in pairs(ui.buttons) do
if not (draw_lite_mode and def.hide_lite) then if not (draw_lite_mode and def.hide_lite) then
table.insert(filtered_inv_buttons, def) table.insert(filtered_inv_buttons, def)
end end
@ -112,21 +96,20 @@ function unified_inventory.get_formspec(player, page)
if def.type == "image" then if def.type == "image" then
if (def.condition == nil or def.condition(player) == true) then if (def.condition == nil or def.condition(player) == true) then
formspec[n] = "image_button[" formspec[n] = string.format("image_button[%f,%f;%f,%f;%s;%s;]",
formspec[n+1] = ( ui_peruser.main_button_x + 0.65 * (j - 1) - button_col * 0.65 * 4) -- Modif NALC ui_peruser.main_button_x + ui_peruser.btn_spc * (j - 1) - button_col * ui_peruser.btn_spc * 4, -- Modif NALC
formspec[n+2] = ","..(ui_peruser.main_button_y + button_row * 0.7)..";0.8,0.8;" ui_peruser.main_button_y + button_row * ui_peruser.btn_spc,
formspec[n+3] = F(def.image)..";" ui_peruser.btn_size,ui_peruser.btn_size,
formspec[n+4] = F(def.name)..";]" F(def.image),
formspec[n+5] = "tooltip["..F(def.name) F(def.name))
formspec[n+6] = ";"..(def.tooltip or "").."]" formspec[n+1] = "tooltip["..F(def.name)..";"..(def.tooltip or "").."]"
n = n+7 n = n+2
else else
formspec[n] = "image[" formspec[n] = string.format("image[%f,%f;%f,%f;%s^[colorize:#808080:alpha]",
formspec[n+1] = ( ui_peruser.main_button_x + 0.65 * (j - 1) - button_col * 0.65 * 4) -- Modif NALC ui_peruser.main_button_x + ui_peruser.btn_spc * (j - 1) - button_col * ui_peruser.btn_spc * 4, -- Modif NALC
formspec[n+2] = ","..(ui_peruser.main_button_y + button_row * 0.7)..";0.8,0.8;" ui_peruser.main_button_y + button_row * ui_peruser.btn_spc,
formspec[n+3] = F(def.image).."^[colorize:#808080:alpha]" ui_peruser.btn_size,ui_peruser.btn_size,def.image)
n = n+4 n = n+1
end end
end end
j = j + 1 -- Modif NALC j = j + 1 -- Modif NALC
@ -135,7 +118,7 @@ function unified_inventory.get_formspec(player, page)
if fsdata.draw_inventory ~= false then if fsdata.draw_inventory ~= false then
-- Player inventory -- Player inventory
formspec[n] = "listcolors[#00000000;#00000000]" formspec[n] = "listcolors[#00000000;#00000000]"
formspec[n+1] = "list[current_player;main;0,"..(ui_peruser.formspec_y + 3.5)..";8,4;]" formspec[n+1] = ui_peruser.standard_inv
n = n+2 n = n+2
end end
@ -143,71 +126,94 @@ function unified_inventory.get_formspec(player, page)
return table.concat(formspec, "") return table.concat(formspec, "")
end end
-- Controls to flip items pages -- Category filters
local start_x = 9.2
if not draw_lite_mode then local categories_pos = { ui_peruser.page_x, ui_peruser.page_y-ui_peruser.btn_spc-0.5 }
formspec[n] = local categories_scroll_pos = { ui_peruser.page_x, ui_peruser.form_header_y-(draw_lite_mode and 0 or 0.2) }
"image_button[" .. (start_x + 0.6 * 0)
.. ",9;.8,.8;ui_skip_backward_icon.png;start_list;]"
.. "tooltip[start_list;" .. F(S("First page")) .. "]"
.. "image_button[" .. (start_x + 0.6 * 1) formspec[n] = string.format("background9[%f,%f;%f,%f;%s;false;3]",
.. ",9;.8,.8;ui_doubleleft_icon.png;rewind3;]" ui_peruser.page_x-0.1, categories_scroll_pos[2],
.. "tooltip[rewind3;" .. F(S("Back three pages")) .. "]" (ui_peruser.btn_spc * ui_peruser.pagecols) + 0.13, 1.4+(draw_lite_mode and 0 or 0.2),
.. "image_button[" .. (start_x + 0.6 * 2) "ui_smallbg_9_sliced.png")
.. ",9;.8,.8;ui_left_icon.png;rewind1;]" n = n + 1
.. "tooltip[rewind1;" .. F(S("Back one page")) .. "]"
.. "image_button[" .. (start_x + 0.6 * 3) formspec[n] = string.format("label[%f,%f;%s]", ui_peruser.page_x, ui_peruser.form_header_y+(draw_lite_mode and 0.3 or 0.2), "Category:")
.. ",9;.8,.8;ui_right_icon.png;forward1;]" n = n + 1
.. "tooltip[forward1;" .. F(S("Forward one page")) .. "]"
.. "image_button[" .. (start_x + 0.6 * 4)
.. ",9;.8,.8;ui_doubleright_icon.png;forward3;]"
.. "tooltip[forward3;" .. F(S("Forward three pages")) .. "]"
.. "image_button[" .. (start_x + 0.6 * 5) local scroll_offset = 0
.. ",9;.8,.8;ui_skip_forward_icon.png;end_list;]" local category_count = #unified_inventory.category_list
.. "tooltip[end_list;" .. F(S("Last page")) .. "]" if category_count > ui_peruser.pagecols then
else scroll_offset = unified_inventory.current_category_scroll[player_name]
formspec[n] = end
"image_button[" .. (8.2 + 0.65 * 0)
.. ",5.8;.8,.8;ui_skip_backward_icon.png;start_list;]" for index, category in ipairs(unified_inventory.category_list) do
.. "tooltip[start_list;" .. F(S("First page")) .. "]" local column = index - scroll_offset
.. "image_button[" .. (8.2 + 0.65 * 1) if column > 0 and column <= ui_peruser.pagecols then
.. ",5.8;.8,.8;ui_left_icon.png;rewind1;]" local scale = 0.8
.. "tooltip[rewind1;" .. F(S("Back one page")) .. "]" if unified_inventory.current_category[player_name] == category.name then
.. "image_button[" .. (8.2 + 0.65 * 2) scale = 1
.. ",5.8;.8,.8;ui_right_icon.png;forward1;]" end
.. "tooltip[forward1;" .. F(S("Forward one page")) .. "]" formspec[n] = formspec_button(ui_peruser, "category_"..category.name, category.symbol, categories_pos, {column-1, 0}, scale, category.label)
.. "image_button[" .. (8.2 + 0.65 * 3) n = n + 1
.. ",5.8;.8,.8;ui_skip_forward_icon.png;end_list;]" end
.. "tooltip[end_list;" .. F(S("Last page")) .. "]" end
if category_count > ui_peruser.pagecols and scroll_offset > 0 then
-- prev
formspec[n] = formspec_button(ui_peruser, "prev_category", "ui_left_icon.png", categories_scroll_pos, {ui_peruser.pagecols - 2, 0}, 0.8, S("Scroll categories left"))
n = n + 1
end
if category_count > ui_peruser.pagecols and category_count - scroll_offset > ui_peruser.pagecols then
-- next
formspec[n] = formspec_button(ui_peruser, "next_category", "ui_right_icon.png", categories_scroll_pos, {ui_peruser.pagecols - 1, 0}, 0.8, S("Scroll categories right"))
n = n + 1
end end
n = n+1
-- Search box -- Search box
formspec[n] = "field_close_on_enter[searchbox;false]" formspec[n] = "field_close_on_enter[searchbox;false]"
n = n+1
if not draw_lite_mode then formspec[n+1] = string.format("field[%f,%f;%f,%f;searchbox;;%s]",
formspec[n] = "field[9.5,8.325;3,1;searchbox;;" ui_peruser.page_buttons_x, ui_peruser.page_buttons_y,
.. F(unified_inventory.current_searchbox[player_name]) .. "]" ui_peruser.searchwidth - 0.1, ui_peruser.btn_size,
formspec[n+1] = "image_button[12.2,8.1;.8,.8;ui_search_icon.png;searchbutton;]" F(ui.current_searchbox[player_name]))
.. "tooltip[searchbutton;" ..F(S("Search")) .. "]" formspec[n+2] = string.format("image_button[%f,%f;%f,%f;ui_search_icon.png;searchbutton;]",
formspec[n+2] = "image_button[12.9,8.1;.8,.8;ui_reset_icon.png;searchresetbutton;]" ui_peruser.page_buttons_x + ui_peruser.searchwidth, ui_peruser.page_buttons_y,
.. "tooltip[searchbutton;" ..F(S("Search")) .. "]" ui_peruser.btn_size,ui_peruser.btn_size)
.. "tooltip[searchresetbutton;" ..F(S("Reset search and display everything")) .. "]" formspec[n+3] = "tooltip[searchbutton;" ..F(S("Search")) .. "]"
else formspec[n+4] = string.format("image_button[%f,%f;%f,%f;ui_reset_icon.png;searchresetbutton;]",
formspec[n] = "field[8.5,5.225;2.2,1;searchbox;;" ui_peruser.page_buttons_x + ui_peruser.searchwidth + ui_peruser.btn_spc,
.. F(unified_inventory.current_searchbox[player_name]) .. "]" ui_peruser.page_buttons_y,
formspec[n+1] = "image_button[10.3,5;.8,.8;ui_search_icon.png;searchbutton;]" ui_peruser.btn_size, ui_peruser.btn_size)
.. "tooltip[searchbutton;" ..F(S("Search")) .. "]" formspec[n+5] = "tooltip[searchresetbutton;"..F(S("Reset search and display everything")).."]"
formspec[n+2] = "image_button[11,5;.8,.8;ui_reset_icon.png;searchresetbutton;]"
.. "tooltip[searchbutton;" ..F(S("Search")) .. "]" n = n + 6
.. "tooltip[searchresetbutton;" ..F(S("Reset search and display everything")) .. "]"
-- Controls to flip items pages
local btnlist = {
{ "ui_skip_backward_icon.png", "start_list", S("First page") },
{ "ui_doubleleft_icon.png", "rewind3", S("Back three pages") },
{ "ui_left_icon.png", "rewind1", S("Back one page") },
{ "ui_right_icon.png", "forward1", S("Forward one page") },
{ "ui_doubleright_icon.png", "forward3", S("Forward three pages") },
{ "ui_skip_forward_icon.png", "end_list", S("Last page") },
}
if draw_lite_mode then
btnlist[5] = nil
btnlist[2] = nil
end
local bn = 0
for _, b in pairs(btnlist) do
formspec[n] = string.format("image_button[%f,%f;%f,%f;%s;%s;]",
ui_peruser.page_buttons_x + ui_peruser.btn_spc*bn,
ui_peruser.page_buttons_y + ui_peruser.btn_spc,
ui_peruser.btn_size, ui_peruser.btn_size,
b[1],b[2])
formspec[n+1] = "tooltip["..b[2]..";"..F(b[3]).."]"
bn = bn + 1
n = n + 2
end end
n = n+3
local no_matches = S("No matching items") local no_matches = S("No matching items")
if draw_lite_mode then if draw_lite_mode then
@ -215,23 +221,23 @@ function unified_inventory.get_formspec(player, page)
end end
-- Items list -- Items list
if #unified_inventory.filtered_items_list[player_name] == 0 then if #ui.filtered_items_list[player_name] == 0 then
formspec[n] = "label[8.2,"..ui_peruser.form_header_y..";" .. F(no_matches) .. "]" formspec[n] = "label["..ui_peruser.page_x..","..(ui_peruser.page_y+0.15)..";" .. F(no_matches) .. "]"
else else
local dir = unified_inventory.active_search_direction[player_name] local dir = ui.active_search_direction[player_name]
local list_index = unified_inventory.current_index[player_name] local list_index = ui.current_index[player_name]
local page2 = math.floor(list_index / (ui_peruser.items_per_page) + 1) local page2 = math.floor(list_index / (ui_peruser.items_per_page) + 1)
local pagemax = math.floor( local pagemax = math.floor(
(#unified_inventory.filtered_items_list[player_name] - 1) (#ui.filtered_items_list[player_name] - 1)
/ (ui_peruser.items_per_page) + 1) / (ui_peruser.items_per_page) + 1)
for y = 0, ui_peruser.pagerows - 1 do for y = 0, ui_peruser.pagerows - 1 do
for x = 0, ui_peruser.pagecols - 1 do for x = 0, ui_peruser.pagecols - 1 do
local name = unified_inventory.filtered_items_list[player_name][list_index] local name = ui.filtered_items_list[player_name][list_index]
local item = minetest.registered_items[name] local item = minetest.registered_items[name]
if item then if item then
-- Clicked on current item: Flip crafting direction -- Clicked on current item: Flip crafting direction
if name == unified_inventory.current_item[player_name] then if name == ui.current_item[player_name] then
local cdir = unified_inventory.current_craft_direction[player_name] local cdir = ui.current_craft_direction[player_name]
if cdir == "recipe" then if cdir == "recipe" then
dir = "usage" dir = "usage"
elseif cdir == "usage" then elseif cdir == "usage" then
@ -239,13 +245,15 @@ function unified_inventory.get_formspec(player, page)
end end
else else
-- Default: use active search direction by default -- Default: use active search direction by default
dir = unified_inventory.active_search_direction[player_name] dir = ui.active_search_direction[player_name]
end end
local button_name = "item_button_" .. dir .. "_" local button_name = "item_button_" .. dir .. "_"
.. unified_inventory.mangle_for_formspec(name) .. ui.mangle_for_formspec(name)
formspec[n] = ("item_image_button[%f,%f;.81,.81;%s;%s;]"):format( formspec[n] = ("item_image_button[%f,%f;%f,%f;%s;%s;]"):format(
8.2 + x * 0.7, ui_peruser.formspec_y + ui_peruser.page_y + y * 0.7, ui_peruser.page_x + x * ui_peruser.btn_spc,
ui_peruser.page_y + y * ui_peruser.btn_spc,
ui_peruser.btn_size, ui_peruser.btn_size,
name, button_name name, button_name
) )
formspec[n + 1] = ("tooltip[%s;%s \\[%s\\]]"):format( formspec[n + 1] = ("tooltip[%s;%s \\[%s\\]]"):format(
@ -257,26 +265,36 @@ function unified_inventory.get_formspec(player, page)
end end
end end
end end
formspec[n] = "label[8.2,"..ui_peruser.form_header_y..";"..F(S("Page")) .. ": " formspec[n] = string.format("label[%f,%f;%s: %s]",
.. S("@1 of @2",page2,pagemax).."]" ui_peruser.page_buttons_x + ui_peruser.btn_spc * (draw_lite_mode and 1 or 2),
ui_peruser.page_buttons_y + 0.1 + ui_peruser.btn_spc * 2,
F(S("Page")), S("@1 of @2",page2,pagemax))
end end
n= n+1 n= n+1
if unified_inventory.activefilter[player_name] ~= "" then if ui.activefilter[player_name] ~= "" then
formspec[n] = "label[8.2,"..(ui_peruser.form_header_y + 0.4)..";" .. F(S("Filter")) .. ":]" formspec[n] = string.format("label[%f,%f;%s: %s]",
formspec[n+1] = "label[9.1,"..(ui_peruser.form_header_y + 0.4)..";"..F(unified_inventory.activefilter[player_name]).."]" ui_peruser.page_x, ui_peruser.page_y - 0.25,
F(S("Filter")), F(ui.activefilter[player_name]))
end end
return table.concat(formspec, "") return table.concat(formspec, "")
end end
function unified_inventory.set_inventory_formspec(player, page) function ui.set_inventory_formspec(player, page)
if player then if player then
player:set_inventory_formspec(unified_inventory.get_formspec(player, page)) player:set_inventory_formspec(ui.get_formspec(player, page))
end end
end end
local function valid_def(def)
return (not def.groups.not_in_creative_inventory
or def.groups.not_in_creative_inventory == 0)
and def.description
and def.description ~= ""
end
--apply filter to the inventory list (create filtered copy of full one) --apply filter to the inventory list (create filtered copy of full one)
function unified_inventory.apply_filter(player, filter, search_dir) function ui.apply_filter(player, filter, search_dir)
if not player then if not player then
return false return false
end end
@ -295,32 +313,53 @@ function unified_inventory.apply_filter(player, filter, search_dir)
return true return true
end end
else else
local lang = minetest.get_player_information(player_name).lang_code
ffilter = function(name, def) ffilter = function(name, def)
local lname = string.lower(name) local lname = string.lower(name)
local ldesc = string.lower(def.description) local ldesc = string.lower(def.description)
local llocaldesc = minetest.get_translated_string
and string.lower(minetest.get_translated_string(lang, def.description))
return string.find(lname, lfilter, 1, true) or string.find(ldesc, lfilter, 1, true) return string.find(lname, lfilter, 1, true) or string.find(ldesc, lfilter, 1, true)
or llocaldesc and string.find(llocaldesc, lfilter, 1, true)
end end
end end
unified_inventory.filtered_items_list[player_name]={} ui.filtered_items_list[player_name]={}
for name, def in pairs(minetest.registered_items) do local category = ui.current_category[player_name] or 'all'
if (not def.groups.not_in_creative_inventory if category == 'all' then
or def.groups.not_in_creative_inventory == 0) for name, def in pairs(minetest.registered_items) do
and def.description if valid_def(def)
and def.description ~= "" and ffilter(name, def) then
and ffilter(name, def) then table.insert(ui.filtered_items_list[player_name], name)
table.insert(unified_inventory.filtered_items_list[player_name], name) end
end
elseif category == 'uncategorized' then
for name, def in pairs(minetest.registered_items) do
if (not ui.find_category(name))
and valid_def(def)
and ffilter(name, def) then
table.insert(ui.filtered_items_list[player_name], name)
end
end
else
for name,exists in pairs(ui.registered_category_items[category]) do
local def = minetest.registered_items[name]
if exists and def
and valid_def(def)
and ffilter(name, def) then
table.insert(ui.filtered_items_list[player_name], name)
end
end end
end end
table.sort(unified_inventory.filtered_items_list[player_name]) table.sort(ui.filtered_items_list[player_name])
unified_inventory.filtered_items_list_size[player_name] = #unified_inventory.filtered_items_list[player_name] ui.filtered_items_list_size[player_name] = #ui.filtered_items_list[player_name]
unified_inventory.current_index[player_name] = 1 ui.current_index[player_name] = 1
unified_inventory.activefilter[player_name] = filter ui.activefilter[player_name] = filter
unified_inventory.active_search_direction[player_name] = search_dir ui.active_search_direction[player_name] = search_dir
unified_inventory.set_inventory_formspec(player, ui.set_inventory_formspec(player,
unified_inventory.current_page[player_name]) ui.current_page[player_name])
end end
function unified_inventory.items_in_group(groups) function ui.items_in_group(groups)
local items = {} local items = {}
for name, item in pairs(minetest.registered_items) do for name, item in pairs(minetest.registered_items) do
for _, group in pairs(groups:split(',')) do for _, group in pairs(groups:split(',')) do
@ -332,7 +371,7 @@ function unified_inventory.items_in_group(groups)
return items return items
end end
function unified_inventory.sort_inventory(inv) function ui.sort_inventory(inv)
local inlist = inv:get_list("main") local inlist = inv:get_list("main")
local typecnt = {} local typecnt = {}
local typekeys = {} local typekeys = {}

View File

@ -73,6 +73,7 @@ World position=世界位置
Name=名称 Name=名称
HUD text color=HUD文本颜色 HUD text color=HUD文本颜色
#new
Reset search and display everything=重置搜索并显示所有物品 Reset search and display everything=重置搜索并显示所有物品
Any item belonging to the @1 group=属于@1组的任何项目
Any item belonging to the groups @1=属于组@1的任何项目

View File

@ -73,6 +73,7 @@ World position=世界位置
Name=名稱 Name=名稱
HUD text color=HUD文本顏色 HUD text color=HUD文本顏色
#new
Reset search and display everything=重置搜索並顯示所有物品 Reset search and display everything=重置搜索並顯示所有物品
Any item belonging to the @1 group=屬於@1組的任何項目
Any item belonging to the groups @1=屬於組@1的任何項目

View File

@ -1,4 +1,8 @@
name = unified_inventory name = unified_inventory
depends = default depends = default
optional_depends = creative, sfinv, datastorage, farming optional_depends = creative, sfinv, datastorage, farming
description = Unified Inventory replaces the default survival and creative inventory. It adds a nicer interface and a number of features, such as a crafting guide. description = """
Unified Inventory replaces the default survival and creative inventory.
It adds a nicer interface and a number of features, such as a crafting guide.
"""
min_minetest_version = 5.4.0

View File

@ -1,6 +1,7 @@
local S = minetest.get_translator("unified_inventory") local S = minetest.get_translator("unified_inventory")
local NS = function(s) return s end local NS = function(s) return s end
local F = minetest.formspec_escape local F = minetest.formspec_escape
local ui = unified_inventory
minetest.register_privilege("creative", { minetest.register_privilege("creative", {
description = S("Can use the creative inventory"), description = S("Can use the creative inventory"),
@ -12,10 +13,9 @@ minetest.register_privilege("ui_full", {
give_to_singleplayer = false, give_to_singleplayer = false,
}) })
local trash = minetest.create_detached_inventory("trash", { local trash = minetest.create_detached_inventory("trash", {
--allow_put = function(inv, listname, index, stack, player) --allow_put = function(inv, listname, index, stack, player)
-- if unified_inventory.is_creative(player:get_player_name()) then -- if ui.is_creative(player:get_player_name()) then
-- return stack:get_count() -- return stack:get_count()
-- else -- else
-- return 0 -- return 0
@ -29,19 +29,19 @@ local trash = minetest.create_detached_inventory("trash", {
}) })
trash:set_size("main", 1) trash:set_size("main", 1)
unified_inventory.register_button("craft", { ui.register_button("craft", {
type = "image", type = "image",
image = "ui_craft_icon.png", image = "ui_craft_icon.png",
tooltip = S("Crafting Grid") tooltip = S("Crafting Grid")
}) })
unified_inventory.register_button("craftguide", { ui.register_button("craftguide", {
type = "image", type = "image",
image = "ui_craftguide_icon.png", image = "ui_craftguide_icon.png",
tooltip = S("Crafting Guide") tooltip = S("Crafting Guide")
}) })
unified_inventory.register_button("misc_set_day", { ui.register_button("misc_set_day", {
type = "image", type = "image",
image = "ui_sun_icon.png", image = "ui_sun_icon.png",
tooltip = S("Set time to day"), tooltip = S("Set time to day"),
@ -57,7 +57,7 @@ unified_inventory.register_button("misc_set_day", {
else else
minetest.chat_send_player(player_name, minetest.chat_send_player(player_name,
S("You don't have the settime privilege!")) S("You don't have the settime privilege!"))
unified_inventory.set_inventory_formspec(player, unified_inventory.current_page[player_name]) ui.set_inventory_formspec(player, ui.current_page[player_name])
end end
end, end,
condition = function(player) condition = function(player)
@ -65,7 +65,7 @@ unified_inventory.register_button("misc_set_day", {
end, end,
}) })
unified_inventory.register_button("misc_set_night", { ui.register_button("misc_set_night", {
type = "image", type = "image",
image = "ui_moon_icon.png", image = "ui_moon_icon.png",
tooltip = S("Set time to night"), tooltip = S("Set time to night"),
@ -81,7 +81,7 @@ unified_inventory.register_button("misc_set_night", {
else else
minetest.chat_send_player(player_name, minetest.chat_send_player(player_name,
S("You don't have the settime privilege!")) S("You don't have the settime privilege!"))
unified_inventory.set_inventory_formspec(player, unified_inventory.current_page[player_name]) ui.set_inventory_formspec(player, ui.current_page[player_name])
end end
end, end,
condition = function(player) condition = function(player)
@ -89,19 +89,19 @@ unified_inventory.register_button("misc_set_night", {
end, end,
}) })
unified_inventory.register_button("clear_inv", { ui.register_button("clear_inv", {
type = "image", type = "image",
image = "ui_trash_icon.png", image = "ui_trash_icon.png",
tooltip = S("Clear inventory"), tooltip = S("Clear inventory"),
action = function(player) action = function(player)
local player_name = player:get_player_name() local player_name = player:get_player_name()
if not unified_inventory.is_creative(player_name) then if not ui.is_creative(player_name) then
minetest.chat_send_player(player_name, minetest.chat_send_player(player_name,
S("This button has been disabled outside" S("This button has been disabled outside"
.." of creative mode to prevent" .." of creative mode to prevent"
.." accidental inventory trashing." .." accidental inventory trashing."
.."\nUse the trash slot instead.")) .."\nUse the trash slot instead."))
unified_inventory.set_inventory_formspec(player, unified_inventory.current_page[player_name]) ui.set_inventory_formspec(player, ui.current_page[player_name])
return return
end end
player:get_inventory():set_list("main", {}) player:get_inventory():set_list("main", {})
@ -110,35 +110,42 @@ unified_inventory.register_button("clear_inv", {
{to_player=player_name, gain = 1.0}) {to_player=player_name, gain = 1.0})
end, end,
condition = function(player) condition = function(player)
return unified_inventory.is_creative(player:get_player_name()) return ui.is_creative(player:get_player_name())
end, end,
}) })
unified_inventory.register_page("craft", { ui.register_page("craft", {
get_formspec = function(player, perplayer_formspec) get_formspec = function(player, perplayer_formspec)
local formspecy = perplayer_formspec.formspec_y local formheaderx = perplayer_formspec.form_header_x
local formheadery = perplayer_formspec.form_header_y local formheadery = perplayer_formspec.form_header_y
local craftx = perplayer_formspec.craft_x
local crafty = perplayer_formspec.craft_y
local player_name = player:get_player_name() local player_name = player:get_player_name()
local formspec = "background[2,"..formspecy..";6,3;ui_crafting_form.png]" local formspec = {
formspec = formspec.."background[0,"..(formspecy + 3.5)..";8,4;ui_main_inventory.png]" perplayer_formspec.standard_inv_bg,
formspec = formspec.."label[0,"..formheadery..";" ..F(S("Crafting")).."]" perplayer_formspec.craft_grid,
formspec = formspec.."listcolors[#00000000;#00000000]" "label["..formheaderx..","..formheadery..";" ..F(S("Crafting")).."]",
formspec = formspec.."list[current_player;craftpreview;6,"..formspecy..";1,1;]" "listcolors[#00000000;#00000000]",
formspec = formspec.."list[current_player;craft;2,"..formspecy..";3,3;]" "listring[current_name;craft]",
if unified_inventory.trash_enabled or unified_inventory.is_creative(player_name) or minetest.get_player_privs(player_name).give then "listring[current_player;main]"
formspec = formspec.."label[7,"..(formspecy + 1.5)..";" .. F(S("Trash:")) .. "]" }
formspec = formspec.."background[7,"..(formspecy + 2)..";1,1;ui_single_slot.png]" local n=#formspec+1
formspec = formspec.."list[detached:trash;main;7,"..(formspecy + 2)..";1,1;]"
if ui.trash_enabled or ui.is_creative(player_name) or minetest.get_player_privs(player_name).give then
formspec[n] = string.format("label[%f,%f;%s]", craftx + 6.45, crafty + 2.4, F(S("Trash:")))
formspec[n+1] = ui.make_trash_slot(craftx + 6.25, crafty + 2.5)
n=n + 2
end end
formspec = formspec.."listring[current_name;craft]"
formspec = formspec.."listring[current_player;main]" if ui.is_creative(player_name) then
if unified_inventory.is_creative(player_name) then formspec[n] = ui.single_slot(craftx - 2.5, crafty + 2.5)
formspec = formspec.."label[0,"..(formspecy + 1.5)..";" .. F(S("Refill:")) .. "]" formspec[n+1] = string.format("label[%f,%f;%s]", craftx - 2.3, crafty + 2.4,F(S("Refill:")))
formspec = formspec.."list[detached:"..F(player_name).."refill;main;0,"..(formspecy +2)..";1,1;]" formspec[n+2] = string.format("list[detached:%srefill;main;%f,%f;1,1;]",
F(player_name), craftx - 2.5 + ui.list_img_offset, crafty + 2.5 + ui.list_img_offset)
end end
return {formspec=formspec} return {formspec=table.concat(formspec)}
end, end,
}) })
@ -157,18 +164,18 @@ local function stack_image_button(x, y, w, h, buttonname_prefix, item)
local selectitem = name local selectitem = name
if name:sub(1, 6) == "group:" then if name:sub(1, 6) == "group:" then
local group_name = name:sub(7) local group_name = name:sub(7)
local group_item = unified_inventory.get_group_item(group_name) local group_item = ui.get_group_item(group_name)
show_is_group = not group_item.sole show_is_group = not group_item.sole
displayitem = group_item.item or "unknown" displayitem = group_item.item or "unknown"
selectitem = group_item.sole and displayitem or name selectitem = group_item.sole and displayitem or name
end end
local label = show_is_group and "G" or "" local label = show_is_group and "G" or ""
local buttonname = F(buttonname_prefix..unified_inventory.mangle_for_formspec(selectitem)) local buttonname = F(buttonname_prefix..ui.mangle_for_formspec(selectitem))
local button = string.format("item_image_button[%f,%f;%f,%f;%s;%s;%s]", local button = string.format("item_image_button[%f,%f;%f,%f;%s;%s;%s]",
x, y, w, h, x, y, w, h,
F(displayitem), buttonname, label) F(displayitem), buttonname, label)
if show_is_group then if show_is_group then
local groupstring, andcount = unified_inventory.extract_groupnames(name) local groupstring, andcount = ui.extract_groupnames(name)
local grouptip local grouptip
if andcount == 1 then if andcount == 1 then
grouptip = S("Any item belonging to the @1 group", groupstring) grouptip = S("Any item belonging to the @1 group", groupstring)
@ -208,26 +215,33 @@ local other_dir = {
usage = "recipe", usage = "recipe",
} }
unified_inventory.register_page("craftguide", { ui.register_page("craftguide", {
get_formspec = function(player, perplayer_formspec) get_formspec = function(player, perplayer_formspec)
local formspecy = perplayer_formspec.formspec_y local craftguidex = perplayer_formspec.craft_guide_x
local formheadery = perplayer_formspec.form_header_y local craftguidey = perplayer_formspec.craft_guide_y
local craftresultx = perplayer_formspec.craft_result_x local craftguidearrowx = perplayer_formspec.craft_guide_arrow_x
local craftresulty = perplayer_formspec.craft_result_y local craftguideresultx = perplayer_formspec.craft_guide_result_x
local formheaderx = perplayer_formspec.form_header_x
local formheadery = perplayer_formspec.form_header_y
local give_x = perplayer_formspec.give_btn_x
local player_name = player:get_player_name() local player_name = player:get_player_name()
local player_privs = minetest.get_player_privs(player_name) local player_privs = minetest.get_player_privs(player_name)
local fs = {
"background[0,"..(formspecy + 3.5)..";8,4;ui_main_inventory.png]", local formspec = {
"label[0,"..formheadery..";" .. F(S("Crafting Guide")) .. "]", perplayer_formspec.standard_inv_bg,
"label["..formheaderx..","..formheadery..";" .. F(S("Crafting Guide")) .. "]",
"listcolors[#00000000;#00000000]" "listcolors[#00000000;#00000000]"
} }
local item_name = unified_inventory.current_item[player_name]
local item_name = ui.current_item[player_name]
if not item_name then if not item_name then
return { formspec = table.concat(fs) } return { formspec = table.concat(formspec) }
end end
local n = 4
local item_name_shown local item_name_shown
if minetest.registered_items[item_name] if minetest.registered_items[item_name]
and minetest.registered_items[item_name].description then and minetest.registered_items[item_name].description then
@ -237,51 +251,60 @@ unified_inventory.register_page("craftguide", {
item_name_shown = item_name item_name_shown = item_name
end end
local dir = unified_inventory.current_craft_direction[player_name] local dir = ui.current_craft_direction[player_name]
local rdir = dir == "recipe" and "usage" or "recipe" local rdir = dir == "recipe" and "usage" or "recipe"
local crafts = unified_inventory.crafts_for[dir][item_name] local crafts = ui.crafts_for[dir][item_name]
local alternate = unified_inventory.alternate[player_name] local alternate = ui.alternate[player_name]
local alternates, craft local alternates, craft
if crafts and #crafts > 0 then if crafts and #crafts > 0 then
alternates = #crafts alternates = #crafts
craft = crafts[alternate] craft = crafts[alternate]
end end
local has_give = player_privs.give or unified_inventory.is_creative(player_name) local has_give = player_privs.give or ui.is_creative(player_name)
fs[#fs + 1] = "background[0.5,"..(formspecy + 0.2)..";8,3;ui_craftguide_form.png]" formspec[n] = string.format("image[%f,%f;%f,%f;ui_crafting_arrow.png]",
fs[#fs + 1] = string.format("textarea[%f,%f;10,1;;%s: %s;]", craftguidearrowx, craftguidey, ui.imgscale, ui.imgscale)
craftresultx, craftresulty, F(role_text[dir]), item_name_shown)
fs[#fs + 1] = stack_image_button(0, formspecy, 1.1, 1.1, formspec[n+1] = string.format("textarea[%f,%f;10,1;;%s: %s;]",
"item_button_" .. rdir .. "_", ItemStack(item_name)) perplayer_formspec.craft_guide_resultstr_x, perplayer_formspec.craft_guide_resultstr_y,
F(role_text[dir]), item_name_shown)
n = n + 2
local giveme_form = table.concat({
"label[".. (give_x+0.1)..",".. (craftguidey + 2.7) .. ";" .. F(S("Give me:")) .. "]",
"button["..(give_x)..",".. (craftguidey + 2.9) .. ";0.75,0.5;craftguide_giveme_1;1]",
"button["..(give_x+0.8)..",".. (craftguidey + 2.9) .. ";0.75,0.5;craftguide_giveme_10;10]",
"button["..(give_x+1.6)..",".. (craftguidey + 2.9) .. ";0.75,0.5;craftguide_giveme_99;99]"
})
if not craft then if not craft then
-- No craft recipes available for this item. -- No craft recipes available for this item.
fs[#fs + 1] = "label[5.5,"..(formspecy + 2.35)..";" formspec[n] = string.format("label[%f,%f;%s]", craftguidex+2.5, craftguidey+1.5, F(no_recipe_text[dir]))
.. F(no_recipe_text[dir]) .. "]" local no_pos = dir == "recipe" and (craftguidex+2.5) or craftguideresultx
local no_pos = dir == "recipe" and 4.5 or 6.5 local item_pos = dir == "recipe" and craftguideresultx or (craftguidex+2.5)
local item_pos = dir == "recipe" and 6.5 or 4.5 formspec[n+1] = "image["..no_pos..","..craftguidey..";1.2,1.2;ui_no.png]"
fs[#fs + 1] = "image["..no_pos..","..formspecy..";1.1,1.1;ui_no.png]" formspec[n+2] = stack_image_button(item_pos, craftguidey, 1.2, 1.2,
fs[#fs + 1] = stack_image_button(item_pos, formspecy, 1.1, 1.1,
"item_button_" .. other_dir[dir] .. "_", ItemStack(item_name)) "item_button_" .. other_dir[dir] .. "_", ItemStack(item_name))
if has_give then if has_give then
fs[#fs + 1] = "label[0," .. (formspecy + 2.10) .. ";" .. F(S("Give me:")) .. "]" formspec[n+3] = giveme_form
.. "button[0, " .. (formspecy + 2.7) .. ";0.6,0.5;craftguide_giveme_1;1]"
.. "button[0.6," .. (formspecy + 2.7) .. ";0.7,0.5;craftguide_giveme_10;10]"
.. "button[1.3," .. (formspecy + 2.7) .. ";0.8,0.5;craftguide_giveme_99;99]"
end end
return { formspec = table.concat(fs) } return { formspec = table.concat(formspec) }
else
formspec[n] = stack_image_button(craftguideresultx, craftguidey, 1.2, 1.2,
"item_button_" .. rdir .. "_", ItemStack(craft.output))
n = n + 1
end end
local craft_type = unified_inventory.registered_craft_types[craft.type] or local craft_type = ui.registered_craft_types[craft.type] or
unified_inventory.craft_type_defaults(craft.type, {}) ui.craft_type_defaults(craft.type, {})
if craft_type.icon then if craft_type.icon then
fs[#fs + 1] = string.format("image[%f,%f;%f,%f;%s]", formspec[n] = string.format("image[%f,%f;%f,%f;%s]",
5.7, (formspecy + 0.05), 0.5, 0.5, craft_type.icon) craftguidearrowx+0.35, craftguidey, 0.5, 0.5, craft_type.icon)
n = n + 1
end end
fs[#fs + 1] = "label[5.5,"..(formspecy + 1)..";" .. F(craft_type.description).."]" formspec[n] = string.format("label[%f,%f;%s]", craftguidearrowx + 0.15, craftguidey + 1.4, F(craft_type.description))
fs[#fs + 1] = stack_image_button(6.5, formspecy, 1.1, 1.1, n = n + 1
"item_button_usage_", ItemStack(craft.output))
local display_size = craft_type.dynamic_display_size local display_size = craft_type.dynamic_display_size
and craft_type.dynamic_display_size(craft) and craft_type.dynamic_display_size(craft)
@ -292,11 +315,12 @@ unified_inventory.register_page("craftguide", {
-- This keeps recipes aligned to the right, -- This keeps recipes aligned to the right,
-- so that they're close to the arrow. -- so that they're close to the arrow.
local xoffset = 5.5 local xoffset = craftguidex+3.75
local bspc = 1.25
-- Offset factor for crafting grids with side length > 4 -- Offset factor for crafting grids with side length > 4
local of = (3/math.max(3, math.max(display_size.width, display_size.height))) local of = (3/math.max(3, math.max(display_size.width, display_size.height)))
local od = 0 local od = 0
-- Minimum grid size at which size optimazation measures kick in -- Minimum grid size at which size optimization measures kick in
local mini_craft_size = 6 local mini_craft_size = 6
if display_size.width >= mini_craft_size then if display_size.width >= mini_craft_size then
od = math.max(1, display_size.width - 2) od = math.max(1, display_size.width - 2)
@ -305,12 +329,12 @@ unified_inventory.register_page("craftguide", {
-- Size modifier factor -- Size modifier factor
local sf = math.min(1, of * (1.05 + 0.05*od)) local sf = math.min(1, of * (1.05 + 0.05*od))
-- Button size -- Button size
local bsize_h = 1.1 * sf local bsize = 1.2 * sf
local bsize_w = bsize_h
if display_size.width >= mini_craft_size then if display_size.width >= mini_craft_size then -- it's not a normal 3x3 grid
bsize_w = 1.175 * sf bsize = 0.8 * sf
end end
if (bsize_h > 0.35 and display_size.width) then if (bsize > 0.35 and display_size.width) then
for y = 1, display_size.height do for y = 1, display_size.height do
for x = 1, display_size.width do for x = 1, display_size.width do
local item local item
@ -320,48 +344,53 @@ unified_inventory.register_page("craftguide", {
-- Flipped x, used to build formspec buttons from right to left -- Flipped x, used to build formspec buttons from right to left
local fx = display_size.width - (x-1) local fx = display_size.width - (x-1)
-- x offset, y offset -- x offset, y offset
local xof = (fx-1) * of + of local xof = ((fx-1) * of + of) * bspc
local yof = (y-1) * of + 1 local yof = ((y-1) * of + 1) * bspc
if item then if item then
fs[#fs + 1] = stack_image_button( formspec[n] = stack_image_button(
xoffset - xof, formspecy - 1 + yof, bsize_w, bsize_h, xoffset - xof, craftguidey - 1.25 + yof, bsize, bsize,
"item_button_recipe_", "item_button_recipe_",
ItemStack(item)) ItemStack(item))
else else
-- Fake buttons just to make grid -- Fake buttons just to make grid
fs[#fs + 1] = string.format("image_button[%f,%f;%f,%f;ui_blank_image.png;;]", formspec[n] = string.format("image_button[%f,%f;%f,%f;ui_blank_image.png;;]",
xoffset - xof, formspecy - 1 + yof, bsize_w, bsize_h) xoffset - xof, craftguidey - 1.25 + yof, bsize, bsize)
end end
n = n + 1
end end
end end
else else
-- Error -- Error
fs[#fs + 1] = string.format("label[2,%f;%s]", formspec[n] = string.format("label[2,%f;%s]",
formspecy, F(S("This recipe is too@nlarge to be displayed."))) craftguidey, F(S("This recipe is too@nlarge to be displayed.")))
n = n + 1
end end
if craft_type.uses_crafting_grid and display_size.width <= 3 then if craft_type.uses_crafting_grid and display_size.width <= 3 then
fs[#fs + 1] = "label[0," .. (formspecy + 0.9) .. ";" .. F(S("To craft grid:")) .. "]" formspec[n] = "label["..(give_x+0.1)..",".. (craftguidey + 1.7) .. ";" .. F(S("To craft grid:")) .. "]"
.. "button[0, " .. (formspecy + 1.5) .. ";0.6,0.5;craftguide_craft_1;1]" formspec[n+1] = "button[".. (give_x)..",".. (craftguidey + 1.9) .. ";0.75,0.5;craftguide_craft_1;1]"
.. "button[0.6," .. (formspecy + 1.5) .. ";0.7,0.5;craftguide_craft_10;10]" formspec[n+2] = "button[".. (give_x+0.8)..",".. (craftguidey + 1.9) .. ";0.75,0.5;craftguide_craft_10;10]"
.. "button[1.3," .. (formspecy + 1.5) .. ";0.8,0.5;craftguide_craft_max;" .. F(S("All")) .. "]" formspec[n+3] = "button[".. (give_x+1.6)..",".. (craftguidey + 1.9) .. ";0.75,0.5;craftguide_craft_max;" .. F(S("All")) .. "]"
n = n + 4
end end
if has_give then if has_give then
fs[#fs + 1] = "label[0," .. (formspecy + 2.1) .. ";" .. F(S("Give me:")) .. "]" formspec[n] = giveme_form
.. "button[0, " .. (formspecy + 2.7) .. ";0.6,0.5;craftguide_giveme_1;1]" n = n + 1
.. "button[0.6," .. (formspecy + 2.7) .. ";0.7,0.5;craftguide_giveme_10;10]"
.. "button[1.3," .. (formspecy + 2.7) .. ";0.8,0.5;craftguide_giveme_99;99]"
end end
if alternates and alternates > 1 then if alternates and alternates > 1 then
fs[#fs + 1] = "label[5.5," .. (formspecy + 1.6) .. ";" formspec[n] = string.format("label[%f,%f;%s]",
.. F(S(recipe_text[dir], alternate, alternates)) .. "]" craftguidex+4, craftguidey + 2.3, F(S(recipe_text[dir], alternate, alternates)))
.. "image_button[5.5," .. (formspecy + 2) .. ";1,1;ui_left_icon.png;alternate_prev;]" formspec[n+1] = string.format("image_button[%f,%f;1.1,1.1;ui_left_icon.png;alternate_prev;]",
.. "image_button[6.5," .. (formspecy + 2) .. ";1,1;ui_right_icon.png;alternate;]" craftguidearrowx+0.2, craftguidey + 2.6)
.. "tooltip[alternate_prev;" .. F(prev_alt_text[dir]) .. "]" formspec[n+2] = string.format("image_button[%f,%f;1.1,1.1;ui_right_icon.png;alternate;]",
.. "tooltip[alternate;" .. F(next_alt_text[dir]) .. "]" craftguidearrowx+1.35, craftguidey + 2.6)
formspec[n+3] = "tooltip[alternate_prev;" .. F(prev_alt_text[dir]) .. "]"
formspec[n+4] = "tooltip[alternate;" .. F(next_alt_text[dir]) .. "]"
end end
return { formspec = table.concat(fs) }
return { formspec = table.concat(formspec) }
end, end,
}) })
@ -369,7 +398,7 @@ local function craftguide_giveme(player, formname, fields)
local player_name = player:get_player_name() local player_name = player:get_player_name()
local player_privs = minetest.get_player_privs(player_name) local player_privs = minetest.get_player_privs(player_name)
if not player_privs.give and if not player_privs.give and
not unified_inventory.is_creative(player_name) then not ui.is_creative(player_name) then
minetest.log("action", "[unified_inventory] Denied give action to player " .. minetest.log("action", "[unified_inventory] Denied give action to player " ..
player_name) player_name)
return return
@ -384,7 +413,7 @@ local function craftguide_giveme(player, formname, fields)
amount = tonumber(amount) or 0 amount = tonumber(amount) or 0
if amount == 0 then return end if amount == 0 then return end
local output = unified_inventory.current_item[player_name] local output = ui.current_item[player_name]
if (not output) or (output == "") then return end if (not output) or (output == "") then return end
local player_inv = player:get_inventory() local player_inv = player:get_inventory()
@ -405,21 +434,21 @@ local function craftguide_craft(player, formname, fields)
local player_name = player:get_player_name() local player_name = player:get_player_name()
local output = unified_inventory.current_item[player_name] or "" local output = ui.current_item[player_name] or ""
if output == "" then return end if output == "" then return end
local crafts = unified_inventory.crafts_for[ local crafts = ui.crafts_for[
unified_inventory.current_craft_direction[player_name]][output] or {} ui.current_craft_direction[player_name]][output] or {}
if #crafts == 0 then return end if #crafts == 0 then return end
local alternate = unified_inventory.alternate[player_name] local alternate = ui.alternate[player_name]
local craft = crafts[alternate] local craft = crafts[alternate]
if craft.width > 3 then return end if craft.width > 3 then return end
unified_inventory.craftguide_match_craft(player, "main", "craft", craft, amount) ui.craftguide_match_craft(player, "main", "craft", craft, amount)
unified_inventory.set_inventory_formspec(player, "craft") ui.set_inventory_formspec(player, "craft")
end end
minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.register_on_player_receive_fields(function(player, formname, fields)

View File

@ -9,3 +9,6 @@ unified_inventory_bags (Enable bags) bool true
#If enabled, the trash slot can be used by those without both creative #If enabled, the trash slot can be used by those without both creative
#and the give privilege. #and the give privilege.
unified_inventory_trash (Enable trash) bool true unified_inventory_trash (Enable trash) bool true
unified_inventory_automatic_categorization (Items automatically added to categories) bool true

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 629 B

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1,5 +1,6 @@
local S = minetest.get_translator("unified_inventory") local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape local F = minetest.formspec_escape
local ui = unified_inventory
local hud_colors = { local hud_colors = {
{"#FFFFFF", 0xFFFFFF, S("White")}, {"#FFFFFF", 0xFFFFFF, S("White")},
@ -14,28 +15,38 @@ local hud_colors_max = #hud_colors
-- Stores temporary player data (persists until player leaves) -- Stores temporary player data (persists until player leaves)
local waypoints_temp = {} local waypoints_temp = {}
unified_inventory.register_page("waypoints", { ui.register_page("waypoints", {
get_formspec = function(player) get_formspec = function(player)
local player_name = player:get_player_name() local player_name = player:get_player_name()
local wp_info_x = ui.style_full.form_header_x + 1.25
local wp_info_y = ui.style_full.form_header_y + 0.5
local wp_bottom_row = ui.style_full.std_inv_y - 1
local wp_buttons_rj = ui.style_full.std_inv_x + 10.1 - ui.style_full.btn_spc
local wp_edit_w = ui.style_full.btn_spc * 4 - 0.1
-- build a "fake" temp entry if the server took too long -- build a "fake" temp entry if the server took too long
-- during sign-on and returned an empty entry -- during sign-on and returned an empty entry
if not waypoints_temp[player_name] then waypoints_temp[player_name] = {hud = 1} end if not waypoints_temp[player_name] then waypoints_temp[player_name] = {hud = 1} end
local waypoints = datastorage.get(player_name, "waypoints") local waypoints = datastorage.get(player_name, "waypoints")
local formspec = "background[0,4.5;8,4;ui_main_inventory.png]" .. local formspec = { ui.style_full.standard_inv_bg,
"image[0,0;1,1;ui_waypoints_icon.png]" .. string.format("label[%f,%f;%s]",
"label[1,0;" .. F(S("Waypoints")) .. "]" ui.style_full.form_header_x, ui.style_full.form_header_y,
F(S("Waypoints"))),
"image["..wp_info_x..","..wp_info_y..";1,1;ui_waypoints_icon.png]"
}
local n=4
-- Tabs buttons: -- Tabs buttons:
for i = 1, 5, 1 do for i = 1, 5 do
formspec = formspec .. local sw="select_waypoint"..i
"image_button[0.0," .. 0.2 + i * 0.7 .. ";.8,.8;" .. formspec[n] = string.format("image_button[%f,%f;%f,%f;%sui_%i_icon.png;%s;]",
(i == waypoints.selected and "ui_blue_icon_background.png^" or "") .. ui.style_full.main_button_x, wp_bottom_row - (5-i) * ui.style_full.btn_spc,
"ui_" .. i .. "_icon.png;" .. ui.style_full.btn_size, ui.style_full.btn_size,
"select_waypoint" .. i .. ";]" .. (i == waypoints.selected) and "ui_blue_icon_background.png^" or "",
"tooltip[select_waypoint" .. i .. ";" i, sw)
.. S("Select Waypoint #@1", i).."]" formspec[n+1] = "tooltip["..sw..";"..S("Select Waypoint #@1", i).."]"
n = n + 2
end end
local i = waypoints.selected or 1 local i = waypoints.selected or 1
@ -44,72 +55,58 @@ unified_inventory.register_page("waypoints", {
local default_name = S("Waypoint @1", i) local default_name = S("Waypoint @1", i)
-- Main buttons: -- Main buttons:
formspec = formspec .. local btnlist = {
"image_button[4.5,3.7;.8,.8;".. { "ui_waypoint_set_icon.png", "set_waypoint", S("Set waypoint to current location") },
"ui_waypoint_set_icon.png;".. { waypoint.active and "ui_on_icon.png" or "ui_off_icon.png", "toggle_waypoint", S("Make waypoint @1", waypoint.active and "invisible" or "visible") },
"set_waypoint"..i..";]".. { waypoint.display_pos and "ui_green_icon_background.png^ui_xyz_icon.png" or "ui_red_icon_background.png^ui_xyz_icon.png^(ui_no.png^[transformR90)", "toggle_display_pos", S("@1 display of waypoint coordinates", waypoint.display_pos and "Disable" or "Enable") },
"tooltip[set_waypoint" .. i .. ";" { "ui_circular_arrows_icon.png", "toggle_color", S("Change color of waypoint display") },
.. F(S("Set waypoint to current location")).."]" { "ui_pencil_icon.png", "rename_waypoint", S("Edit waypoint name") }
}
formspec = formspec .. local x = 4
"image_button[5.2,3.7;.8,.8;".. for _, b in pairs(btnlist) do
(waypoint.active and "ui_on_icon.png" or "ui_off_icon.png")..";".. formspec[n] = string.format("image_button[%f,%f;%f,%f;%s;%s%i;]",
"toggle_waypoint"..i..";]".. wp_buttons_rj - ui.style_full.btn_spc * x, wp_bottom_row,
"tooltip[toggle_waypoint" .. i .. ";" ui.style_full.btn_size, ui.style_full.btn_size,
.. F(S("Make waypoint @1", b[1], b[2], i)
waypoint.active and S("invisible") or S("visible"))).."]" formspec[n+1] = "tooltip["..b[2]..i..";"..F(b[3]).."]"
x = x - 1
formspec = formspec .. n = n + 2
"image_button[5.9,3.7;.8,.8;".. end
(waypoint.display_pos and "ui_green_icon_background.png" or "ui_red_icon_background.png").."^ui_xyz_icon.png;"..
"toggle_display_pos" .. i .. ";]"..
"tooltip[toggle_display_pos" .. i .. ";"
.. F(S("@1 display of waypoint coordinates",
waypoint.display_pos and S("Disable") or S("Enable"))) .."]"
formspec = formspec ..
"image_button[6.6,3.7;.8,.8;"..
"ui_circular_arrows_icon.png;"..
"toggle_color"..i..";]"..
"tooltip[toggle_color" .. i .. ";"
.. F(S("Change color of waypoint display")).."]"
formspec = formspec ..
"image_button[7.3,3.7;.8,.8;"..
"ui_pencil_icon.png;"..
"rename_waypoint"..i..";]"..
"tooltip[rename_waypoint" .. i .. ";"
.. F(S("Edit waypoint name")).."]"
-- Waypoint's info: -- Waypoint's info:
formspec[n] = "label["..wp_info_x..","..(wp_info_y+1.1)..";"
if waypoint.active then if waypoint.active then
formspec = formspec .. "label[1,0.8;"..F(S("Waypoint active")).."]" formspec[n+1] = F(S("Waypoint active")).."]"
else else
formspec = formspec .. "label[1,0.8;"..F(S("Waypoint inactive")).."]" formspec[n+1] = F(S("Waypoint inactive")).."]"
end end
n = n + 2
if temp.edit then if temp.edit then
formspec = formspec .. formspec[n] = string.format("field[%f,%f;%f,%f;rename_box%i;;%s]",
"field[1.3,3.2;6,.8;rename_box" .. i .. ";;" wp_buttons_rj - wp_edit_w - 0.1, wp_bottom_row - ui.style_full.btn_spc,
..(waypoint.name or default_name).."]" .. wp_edit_w, ui.style_full.btn_size, i, (waypoint.name or default_name))
"image_button[7.3,2.9;.8,.8;".. formspec[n+1] = string.format("image_button[%f,%f;%f,%f;ui_ok_icon.png;confirm_rename%i;]",
"ui_ok_icon.png;".. wp_buttons_rj, wp_bottom_row - ui.style_full.btn_spc,
"confirm_rename"..i.. ";]".. ui.style_full.btn_size, ui.style_full.btn_size, i)
"tooltip[confirm_rename" .. i .. ";" formspec[n+2] = "tooltip[confirm_rename"..i..";"..F(S("Finish editing")).."]"
.. F(S("Finish editing")).."]" n = n + 3
end end
formspec = formspec .. "label[1,1.3;"..F(S("World position"))..": " .. formspec[n] = string.format("label[%f,%f;%s: %s]",
minetest.pos_to_string(waypoint.world_pos or vector.new()) .. "]" .. wp_info_x, wp_info_y+1.6, F(S("World position")),
"label[1,1.8;"..F(S("Name"))..": ".. (waypoint.name or default_name) .. "]" .. minetest.pos_to_string(waypoint.world_pos or vector.new()))
"label[1,2.3;"..F(S("HUD text color"))..": " .. formspec[n+1] = string.format("label[%f,%f;%s: %s]",
hud_colors[waypoint.color or 1][3] .. "]" wp_info_x, wp_info_y+2.10, F(S("Name")), (waypoint.name or default_name))
formspec[n+2] = string.format("label[%f,%f;%s: %s]",
wp_info_x, wp_info_y+2.60, F(S("HUD text color")), hud_colors[waypoint.color or 1][3])
return {formspec=formspec} return {formspec=table.concat(formspec)}
end, end,
}) })
unified_inventory.register_button("waypoints", { ui.register_button("waypoints", {
type = "image", type = "image",
image = "ui_waypoints_icon.png", image = "ui_waypoints_icon.png",
tooltip = S("Waypoints"), tooltip = S("Waypoints"),
@ -224,7 +221,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
update_hud(player, waypoints, temp, i) update_hud(player, waypoints, temp, i)
end end
if update_formspec then if update_formspec then
unified_inventory.set_inventory_formspec(player, "waypoints") ui.set_inventory_formspec(player, "waypoints")
end end
if hit then return end if hit then return end
end end