Compare commits

...

115 Commits

Author SHA1 Message Date
bri cassa cb6e602497 Merge remote-tracking branch 'github/master' 2023-11-25 15:40:23 +01:00
SmallJoker 693ca112b8 Add setting to disable waypoints 2023-11-20 17:54:44 +01:00
SmallJoker 380b77d0fb Improve settings descriptions 2023-11-20 17:51:34 +01:00
fmmaks 43c9b50800
Add `unified_inventory_enable_item_names` setting (#235)
Show only names settings: in case of multi-line descriptions, only the first line is shown
Shorten long descriptions: Removes all characters after x index, and add `[...]`
Max length before truncation: x for Shorten long descriptions
Notes: If Max length == 0, then item names won't be displayed
2023-10-15 21:02:35 +02:00
Niklp 5d233a0f0a
Clean itemname before checking existence (#234)
important when the item string contains metadata
2023-07-11 18:12:35 +02:00
Nolt 2426b6c912
Full polish translation (#231) 2023-06-24 08:43:04 +02:00
SmallJoker d6d4bea819 Bags: Prevent error caused by moving the opened bag 2023-06-18 18:48:15 +02:00
bri cassa aa04d4539f Merge remote-tracking branch 'github/master' 2023-06-07 22:58:05 +02:00
SmallJoker 15d729c351 Waypoints: Add teleportation button
This also adds button click sounds and makes use of the teleport sound for consistency.
2023-06-06 19:41:03 +02:00
SmallJoker b2cc3d1532 Fix search not working after page flip 2023-01-27 15:57:28 +01:00
luk3yx 37969b2a1b Make bags support lite mode 2023-01-12 22:16:06 +01:00
SmallJoker 1b074828a6 Document and replace sounds
A few sounds were replaced because I could not find them on freesound.org
2023-01-10 21:27:56 +01:00
SmallJoker de0063835c Purge recipes with invalid ingredients 2023-01-09 17:42:41 +01:00
SmallJoker bda9f2598f Improve group matching for 'copy to craft' 2023-01-09 17:42:41 +01:00
luk3yx b590764026
Centre page number label and move refill/trash labels (#221)
* Centre page number label

* Move refill and trash labels
2023-01-04 14:35:46 +01:00
luk3yx 82cdf24045
Improve scroll height calculation (#220) 2022-12-30 21:43:46 +01:00
fluxionary 31c35dcd59
Remove dependency on farming (#219)
Avoids circular dependencies of 3rd party mods with unified_inventory -> farming -> stairs.
2022-12-12 17:45:53 +01:00
fluxionary 826d5f4683
Add setting to hide disabled buttons (#217) 2022-10-26 10:05:03 +02:00
SmallJoker db1c3c10b8 API doc: use Minetest style 2022-10-05 21:07:41 +02:00
SmallJoker 9533200e25 Tidy and comment filtering functions 2022-10-05 21:07:11 +02:00
SmallJoker 177debd13c Bags: Disallow moving bags into themselves
Previously, the bag and its list would disappear immediately.
2022-09-15 12:53:41 +02:00
SmallJoker 8e9ea34ae8 Elaborate the use of NS() 2022-09-15 10:56:01 +02:00
Thomas--S 574de91971
Craft guide: Add support for colored items (#213) 2022-09-15 10:48:29 +02:00
reusityback fc562ecaa0
Update German translation (#211)
Added categories, waypoint etc. translations updated, inventory trashing button still missing
2022-09-04 18:35:00 +02:00
bri cassa a977ec47fd Merge remote-tracking branch 'upstream/master' 2022-08-26 15:24:41 +02:00
Worrizit 182ab493c3 Update CN translation 2022-07-29 21:42:59 +02:00
bri cassa 8c56e27c94 Merge remote-tracking branch 'github/master' 2022-05-27 18:54:23 +02:00
SmallJoker 14da1a3dd0 Fix reverse item lookup ("usage") broken by 5ac2558
> return { specname }

This returned a number-indexed table whereas the code expects a name-indexed table
2022-04-22 22:01:15 +02:00
SmallJoker fa079c31b6 Obligatory screenshot update 2022-04-11 20:11:31 +02:00
SmallJoker c1fef26c87 Fix error caused by slow starts and mod dependencies 2022-04-11 19:42:06 +02:00
SmallJoker 477acd2f89
Change background to rounded corners (#200)
This change is supposed to match the rounded inventory slot design.
2022-04-03 22:30:21 +02:00
SmallJoker 19efce45ed Revert "Remove mod name from tooltips"
This reverts commit 64b0248c77.

The mod name may differ from the item name, in which cases it is
helpful to have this information contained in the tooltip.
No information is shown in case the mod name is missing.
2022-03-20 13:45:59 +01:00
bri cassa 6da71e1819 Merge remote-tracking branch 'upstream/master' 2022-03-05 11:37:32 +01:00
SmallJoker dbe06be68b
Add scroll bar for overflowing tab buttons (#195) 2022-02-26 11:41:15 +01:00
SmallJoker 3074d625e2 Version 4: Feature checks and deprecate internal functions 2022-02-26 11:38:45 +01:00
James William Fletcher 5ac2558da4 Speed up group filtering code
This improves the startup time dramatically by lowering the algorithm complexity.
Mainly noticeable with large inventory sizes.

Written by Test_User, post-edited by SmallJoker
2022-02-26 11:03:21 +01:00
SmallJoker 25c40fea6c Fix filter reset for empty search boxes 2022-01-24 15:20:57 +01:00
SmallJoker 23a45b8131 Only update formspec on search filter changes 2022-01-23 18:15:17 +01:00
bri cassa 9649c0ed0e Merge remote-tracking branch 'github/master' 2022-01-22 20:08:35 +01:00
Oversword d6688872c8
Fix two occasional runtime errors (#191) 2021-12-25 17:31:18 +01:00
bri cassa 4633a276a2 Merge remote-tracking branch 'upstream/master' 2021-12-17 18:16:48 +01:00
SmallJoker 64b0248c77 Remove mod name from tooltips
Requested in #190. The mod name is not relevant for most players, and the full item name can still be seen in the craft recipe viewer mode.
2021-12-11 17:15:58 +01:00
bri cassa 1ac54a017d Merge remote-tracking branch 'github/master' 2021-11-26 21:45:26 +01:00
OgelGames 28a5d4db49
Show wear and description in crafting guide (#189) 2021-11-21 19:42:54 +01:00
bri cassa 4c4fb3ba88 Merge remote-tracking branch 'github/master' 2021-11-01 10:43:50 +01:00
Oversword 8c84751ff8
Add u_i initialization and craft registration callbacks (#184)
Main purpose: custom recipe sorting provided by cuszom mods.
2021-10-14 18:38:07 +02:00
bri cassa 9d66a21271 Merge remote-tracking branch 'upstream/master' 2021-08-31 20:12:45 +02:00
SmallJoker b1c85a2cb8 Fix waypoint initialization order 2021-08-29 07:47:32 +02:00
SmallJoker 3fffa41eaf Remove unused internal functions 2021-08-24 19:44:36 +02:00
SmallJoker 077bed90eb Move default inventory draw calls to separate functions 2021-08-14 15:25:55 +02:00
bri cassa 15a84bdbf4 Merge remote-tracking branch 'upstream/master' 2021-07-24 13:14:48 +02:00
SmallJoker 6d123da61c Update translation strings 2021-07-20 20:41:23 +02:00
SmallJoker d39dd78cb5 Use player meta for waypoints 2021-07-20 20:41:23 +02:00
bri cassa 838c67ae86 Merge remote-tracking branch 'upstream/master' 2021-07-17 20:48:14 +02:00
SmallJoker aeb9841e3a Remove default hard dependency for use in devtest 2021-07-17 10:35:39 +02:00
bri cassa 132a362f85 Merge remote-tracking branch 'upstream/master' 2021-06-20 17:33:07 +02:00
David Leal afd38e0c73
Fix LuaCheck warning (#175) 2021-05-25 19:31:34 +02:00
SmallJoker 4d4355a741 Home: Fix error on missing write permission 2021-05-13 15:19:46 +02:00
bri cassa 03b077cd1b Merge remote-tracking branch 'upstream/master' 2021-04-08 13:39:49 +02:00
Oversword 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
bri cassa 829b38c6fc Merge remote-tracking branch 'upstream/master' 2021-04-04 21:05:40 +02:00
Vanessa Dannenberg 860371ecf8 more consistent formspec size decision 2021-03-31 00:52:30 -04:00
bri cassa 70fdb8556b Merge remote-tracking branch 'upstream/master' 2021-03-12 12:01:23 +01:00
Vanessa Dannenberg 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
Vanessa Dannenberg 608cdfb887 fix refill slot list[] offset also 2021-03-10 12:32:55 -05:00
Vanessa Dannenberg 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
Vanessa Dannenberg 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
Vanessa Dannenberg a7556c5044 update minimum MT version number 2021-03-09 15:09:46 -05:00
SmallJoker 3d58befe03 Document the API version 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg d0deba10c8 pngcrush+optipng the new slot textures
and remove the slot image .xcf project file
2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 97b882ad23 add a version number variable to the main table 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 44e32df00a translate some strings inside their table 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 40d862298b replace excessive spaces with tabs 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 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
Vanessa Dannenberg 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
Vanessa Dannenberg dc61d2980a Move craft guide a little to the right to make some room. 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 21f122336f make craft arrow 128px
(same reason as the trash icon)
2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 8ee0eb9fce swap the craft type icon with its word
(makes it look like it used to)
2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 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
Vanessa Dannenberg b8a568d7eb remove unused var, excess whitespace 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 9ddea6eced fix missing "XYZ" and "no" icon on waypoints show coordinates button 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 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
Vanessa Dannenberg 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
Vanessa Dannenberg 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
Vanessa Dannenberg 6d892dda5b use local ui=unified_inventory shorthand in init.lua as elsewhere 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 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
Vanessa Dannenberg 3e7f005366 always modify and return a table.copy() of the style table 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 382219c466 move S() calls into waypoints' button table
instead of inside the loop
2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 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
Vanessa Dannenberg 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
Vanessa Dannenberg 2d200eb9ae Ditto for bags. 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg b3077898a7 make waypoints explicitly reference full-style vars
(since it does not support lite mode)
2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 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
Vanessa Dannenberg 0c05f06fa8 "Please continue to use string.format here to avoid messy code"
Derp :-)
2021-03-09 15:04:11 -05:00
Vanessa Dannenberg c3679eaf7b fix indent 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 23a089f174 remove a used-only-once variable 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 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
Vanessa Dannenberg 603b5d1d4e get rid of `uninv` global
make all uses of it back into `unified_inventory.`
2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 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
Vanessa Dannenberg 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
Vanessa Dannenberg 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
Vanessa Dannenberg de575a6513 9-slice the background image 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 7a0a44037a remove a couple of unused variables 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg cc93288a6b bump minimum version to 5.4.0 2021-03-09 15:04:11 -05:00
Vanessa Dannenberg 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
SmallJoker d1a4396fbe
Fix bags backwards compatibility breakage since 4403b69 (#167) 2021-03-09 11:12:50 +01:00
Vanessa Dannenberg fbbf786caf Tweak spacing between bags page top row and bag's inv 2021-03-01 18:57:50 +01:00
Vanessa Dannenberg ae124b02c2 Tweak trash can icon 2021-03-01 18:57:50 +01:00
Vanessa Dannenberg 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
Sys Quatre 497c632b24 Merge remote-tracking branch 'upstream/master' 2020-12-18 12:20:14 +01:00
IFRFSX 0f756a5d33
Update translation for zh_CN and zh_TW (#161) 2020-12-15 19:17:10 +01:00
Sys Quatre 46eeb36784 Merge remote-tracking branch 'upstream/master' 2020-07-18 11:28:21 +02:00
Louis Royer 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
SmallJoker d86592841e Remove unused 0.4.x files, multiline description 2020-07-11 19:51:42 +02:00
Maksim f25426911d
Fix teleport sounds when teleport fails (#155) 2020-07-10 21:58:45 +02:00
59 changed files with 2904 additions and 1042 deletions

View File

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

View File

@ -15,7 +15,8 @@ Unified Inventory replaces the default survival and creative inventory.
* Recipe search function by ingredients
* Up to four bags with up to 24 slots each
* Home function to teleport
* Trash slot
* Trash slot and refill slot for creative
* Waypoints to keep track of important locations
* Lite mode: reduces the item browser width
* `minetest.conf` setting `unified_inventory_lite = true`
* Mod API for modders: see [mod_api.txt](doc/mod_api.txt)
@ -24,7 +25,11 @@ Unified Inventory replaces the default survival and creative inventory.
## Requirements
* Minetest 5.0.0+
* Minetest 5.4.0+
* Mod `default` for category filters (contained in Minetest Game)
* Mod `farming` for craftable bags (contained in Minetest Game)
* For waypoint migration: `datastorage`
# Licenses
@ -66,6 +71,9 @@ From http://www.clker.com (Public Domain, CC-BY-4.0):
* [`ui_pencil_icon.pnc`](http://www.clker.com/clipart-2256.html)
* [`ui_waypoint_set_icon.png`](http://www.clker.com/clipart-larger-flag.html)
From https://www.svgrepo.com (CC-BY)
* [`ui_teleport.png`](https://www.svgrepo.com/svg/321565/teleport)
Everaldo Coelho (YellowIcon) (LGPL v2.1+):
* [`ui_craftguide_icon.png` / `ui_craft_icon.png`](http://commons.wikimedia.org/wiki/File:Advancedsettings.png)
@ -96,4 +104,17 @@ Other files from Wikimedia Commons:
RealBadAngel: (CC-BY-4.0)
* Everything else.
* Everything else.
## Sounds
* [`bell.ogg`](https://freesound.org/people/bennstir/sounds/81072/) by bennstir, CC 4.0
* [`electricity.ogg`](https://freesound.org/people/Halleck/sounds/19486/) by Halleck, CC 4.0 (cut)
* [`pageflip1.ogg`](https://freesound.org/people/themfish/sounds/45823/) by themfish, CC 4.0 (cut, slowed down)
* `pageflip2.ogg` (derived from `pageflip1.ogg`)
* [`trash.ogg`](https://freesound.org/people/OwlStorm/sounds/151231/) by OwlStorm, CC 0 (speed up)
* [`trash_all.ogg`](https://freesound.org/people/abel_K/sounds/68280/) by abel_K, Sampling Plus 1.0 (speed up)
* [`ui_click.ogg`](https://freesound.org/people/lartti/sounds/527569/) by lartti, CC 0 (cut)
* [`ui_morning.ogg`](https://freesound.org/people/InspectorJ/sounds/439472/) by InspectorJ, CC 4.0
* [`ui_owl.ogg`](https://freesound.org/people/manda_g/sounds/54987/) by manda_g, Sampling Plus 1.0 (cut)

256
api.lua
View File

@ -1,55 +1,68 @@
local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape
local ui = unified_inventory
local function is_recipe_craftable(recipe)
-- Ensure the ingedients exist
for _, itemname in pairs(recipe.items) do
local groups = string.find(itemname, "group:")
if groups then
if not ui.get_group_item(string.sub(groups, 8)).item then
return false
end
else
-- Possibly an item
local itemname_cleaned = ItemStack(itemname):get_name()
if not minetest.registered_items[itemname_cleaned]
or minetest.get_item_group(itemname_cleaned, "not_in_craft_guide") ~= 0 then
return false
end
end
end
return true
end
-- Create detached creative inventory after loading all mods
minetest.after(0.01, function()
local rev_aliases = {}
for source, target in pairs(minetest.registered_aliases) do
if not rev_aliases[target] then rev_aliases[target] = {} end
table.insert(rev_aliases[target], source)
for original, newname in pairs(minetest.registered_aliases) do
if not rev_aliases[newname] then
rev_aliases[newname] = {}
end
table.insert(rev_aliases[newname], original)
end
unified_inventory.items_list = {}
-- Filtered item list
ui.items_list = {}
for name, def in pairs(minetest.registered_items) do
if (not def.groups.not_in_creative_inventory or
def.groups.not_in_creative_inventory == 0) and
def.description and def.description ~= "" then
table.insert(unified_inventory.items_list, name)
if ui.is_itemdef_listable(def) then
table.insert(ui.items_list, name)
-- Alias processing: Find recipes that belong to the current item name
local all_names = rev_aliases[name] or {}
table.insert(all_names, name)
for _, player_name in ipairs(all_names) do
local recipes = minetest.get_all_craft_recipes(player_name)
if recipes then
for _, recipe in ipairs(recipes) do
local unknowns
for _,chk in pairs(recipe.items) do
local groupchk = string.find(chk, "group:")
if (not groupchk and not minetest.registered_items[chk])
or (groupchk and not unified_inventory.get_group_item(string.gsub(chk, "group:", "")).item)
or minetest.get_item_group(chk, "not_in_craft_guide") ~= 0 then
unknowns = true
end
end
if not unknowns then
unified_inventory.register_craft(recipe)
end
for _, itemname in ipairs(all_names) do
local recipes = minetest.get_all_craft_recipes(itemname)
for _, recipe in ipairs(recipes or {}) do
if is_recipe_craftable(recipe) then
ui.register_craft(recipe)
end
end
end
end
end
table.sort(unified_inventory.items_list)
unified_inventory.items_list_size = #unified_inventory.items_list
print("Unified Inventory. inventory size: "..unified_inventory.items_list_size)
for _, name in ipairs(unified_inventory.items_list) do
table.sort(ui.items_list)
ui.items_list_size = #ui.items_list
print("Unified Inventory. Inventory size: "..ui.items_list_size)
-- Analyse dropped items -> custom "digging" recipes
for _, name in ipairs(ui.items_list) do
local def = minetest.registered_items[name]
-- Simple drops
if type(def.drop) == "string" then
local dstack = ItemStack(def.drop)
if not dstack:is_empty() and dstack:get_name() ~= name then
unified_inventory.register_craft({
ui.register_craft({
type = "digging",
items = {name},
output = def.drop,
@ -115,7 +128,7 @@ minetest.after(0.01, function()
end
end
for itemstring, count in pairs(drop_guaranteed) do
unified_inventory.register_craft({
ui.register_craft({
type = "digging",
items = {name},
output = itemstring .. " " .. count,
@ -123,7 +136,7 @@ minetest.after(0.01, function()
})
end
for itemstring, count in pairs(drop_maybe) do
unified_inventory.register_craft({
ui.register_craft({
type = "digging_chance",
items = {name},
output = itemstring .. " " .. count,
@ -132,33 +145,55 @@ minetest.after(0.01, function()
end
end
end
for _, recipes in pairs(unified_inventory.crafts_for.recipe) do
-- Step 1: Initialize cache for looking up groups
unified_inventory.init_matching_cache()
-- Step 2: Find all matching items for the given spec (groups)
local get_matching_spec_items = unified_inventory.get_matching_items
for outputitemname, recipes in pairs(ui.crafts_for.recipe) do
-- List of crafts that return this item string (variable "_")
-- Problem: The group cache must be initialized after all mods finished loading
-- thus, invalid recipes might be indexed. Hence perform filtering with `new_recipe_list`
local new_recipe_list = {}
for _, recipe in ipairs(recipes) do
local ingredient_items = {}
for _, spec in pairs(recipe.items) do
local matches_spec = unified_inventory.canonical_item_spec_matcher(spec)
for _, name in ipairs(unified_inventory.items_list) do
if matches_spec(name) then
ingredient_items[name] = true
end
-- Get items that fit into this spec (group or item name)
local specname = ItemStack(spec):get_name()
for item_name, _ in pairs(get_matching_spec_items(specname)) do
ingredient_items[item_name] = true
end
end
for name, _ in pairs(ingredient_items) do
if unified_inventory.crafts_for.usage[name] == nil then
unified_inventory.crafts_for.usage[name] = {}
if not ui.crafts_for.usage[name] then
ui.crafts_for.usage[name] = {}
end
table.insert(unified_inventory.crafts_for.usage[name], recipe)
table.insert(ui.crafts_for.usage[name], recipe)
end
if next(ingredient_items) then
-- There's at least one known ingredient: mark as good recipe
-- PS: What whatll be done about partially incomplete recipes?
table.insert(new_recipe_list, recipe)
end
end
ui.crafts_for.recipe[outputitemname] = new_recipe_list
end
for _, callback in ipairs(ui.initialized_callbacks) do
callback()
end
end)
---------------- Home API ----------------
-- 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
unified_inventory.home_pos = {}
ui.home_pos = {}
return
end
while true do
@ -167,32 +202,42 @@ local function load_home()
local y = input:read("*n")
local z = input:read("*n")
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
io.close(input)
end
load_home()
function unified_inventory.set_home(player, pos)
function ui.set_home(player, pos)
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
local output = io.open(unified_inventory.home_filename, "w")
for k, v in pairs(unified_inventory.home_pos) do
local output = io.open(ui.home_filename, "w")
if not output then
minetest.log("warning", "[unified_inventory] Failed to save file: "
.. ui.home_filename)
return
end
for k, v in pairs(ui.home_pos) do
output:write(v.x.." "..v.y.." "..v.z.." "..k.."\n")
end
io.close(output)
end
function unified_inventory.go_home(player)
local pos = unified_inventory.home_pos[player:get_player_name()]
function ui.go_home(player)
local pos = ui.home_pos[player:get_player_name()]
if pos then
player:set_pos(pos)
return true
end
return false
end
-- register_craft
function unified_inventory.register_craft(options)
---------------- Crafting API ----------------
function ui.register_craft(options)
if not options.output then
return
end
@ -203,12 +248,16 @@ function unified_inventory.register_craft(options)
if options.type == "normal" and options.width == 0 then
options = { type = "shapeless", items = options.items, output = options.output, width = 0 }
end
if not unified_inventory.crafts_for.recipe[itemstack:get_name()] then
unified_inventory.crafts_for.recipe[itemstack:get_name()] = {}
local item_name = itemstack:get_name()
if not ui.crafts_for.recipe[item_name] then
ui.crafts_for.recipe[item_name] = {}
end
table.insert(unified_inventory.crafts_for.recipe[itemstack:get_name()],options)
end
table.insert(ui.crafts_for.recipe[item_name],options)
for _, callback in ipairs(ui.craft_registered_callbacks) do
callback(item_name, options)
end
end
local craft_type_defaults = {
width = 3,
@ -216,8 +265,7 @@ local craft_type_defaults = {
uses_crafting_grid = false,
}
function unified_inventory.craft_type_defaults(name, options)
function ui.craft_type_defaults(name, options)
if not options.description then
options.description = name
end
@ -226,13 +274,12 @@ function unified_inventory.craft_type_defaults(name, options)
end
function unified_inventory.register_craft_type(name, options)
unified_inventory.registered_craft_types[name] =
unified_inventory.craft_type_defaults(name, options)
function ui.register_craft_type(name, options)
ui.registered_craft_types[name] = ui.craft_type_defaults(name, options)
end
unified_inventory.register_craft_type("normal", {
ui.register_craft_type("normal", {
description = F(S("Crafting")),
icon = "ui_craftgrid_icon.png",
width = 3,
@ -248,7 +295,7 @@ unified_inventory.register_craft_type("normal", {
})
unified_inventory.register_craft_type("shapeless", {
ui.register_craft_type("shapeless", {
description = F(S("Mixing")),
icon = "ui_craftgrid_icon.png",
width = 3,
@ -263,7 +310,7 @@ unified_inventory.register_craft_type("shapeless", {
})
unified_inventory.register_craft_type("cooking", {
ui.register_craft_type("cooking", {
description = F(S("Cooking")),
icon = "default_furnace_front.png",
width = 1,
@ -271,37 +318,96 @@ unified_inventory.register_craft_type("cooking", {
})
unified_inventory.register_craft_type("digging", {
ui.register_craft_type("digging", {
description = F(S("Digging")),
icon = "default_tool_steelpick.png",
width = 1,
height = 1,
})
unified_inventory.register_craft_type("digging_chance", {
ui.register_craft_type("digging_chance", {
description = "Digging (by chance)",
icon = "default_tool_steelpick.png^[transformFY.png",
width = 1,
height = 1,
})
function unified_inventory.register_page(name, def)
unified_inventory.pages[name] = def
---------------- GUI registrations ----------------
function ui.register_page(name, def)
ui.pages[name] = def
end
function unified_inventory.register_button(name, def)
function ui.register_button(name, def)
if not def.action then
def.action = function(player)
unified_inventory.set_inventory_formspec(player, name)
ui.set_inventory_formspec(player, name)
end
end
def.name = name
table.insert(unified_inventory.buttons, def)
table.insert(ui.buttons, def)
end
---------------- Callback registrations ----------------
function unified_inventory.is_creative(playername)
function ui.register_on_initialized(callback)
if type(callback) ~= "function" then
error(("Initialized callback must be a function, %s given."):format(type(callback)))
end
table.insert(ui.initialized_callbacks, callback)
end
function ui.register_on_craft_registered(callback)
if type(callback) ~= "function" then
error(("Craft registered callback must be a function, %s given."):format(type(callback)))
end
table.insert(ui.craft_registered_callbacks, callback)
end
---------------- List getters ----------------
function ui.get_recipe_list(output)
return ui.crafts_for.recipe[output]
end
function ui.get_registered_outputs()
local outputs = {}
for item_name, _ in pairs(ui.crafts_for.recipe) do
table.insert(outputs, item_name)
end
return outputs
end
---------------- Player utilities ----------------
function ui.is_creative(playername)
return minetest.check_player_privs(playername, {creative=true})
or minetest.settings:get_bool("creative_mode")
end
---------------- Formspec helpers ----------------
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

180
bags.lua
View File

@ -7,31 +7,36 @@ License: GPLv3
local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape
local ui = unified_inventory
unified_inventory.register_page("bags", {
get_formspec = function(player)
ui.register_page("bags", {
get_formspec = function(player, perplayer_formspec)
local player_name = player:get_player_name()
return { formspec = table.concat({
"background[0.06,0.99;7.92,7.52;ui_bags_main_form.png]",
"label[0,0;" .. F(S("Bags")) .. "]",
"button[0,2;2,0.5;bag1;" .. F(S("Bag @1", 1)) .. "]",
"button[2,2;2,0.5;bag2;" .. F(S("Bag @1", 2)) .. "]",
"button[4,2;2,0.5;bag3;" .. F(S("Bag @1", 3)) .. "]",
"button[6,2;2,0.5;bag4;" .. F(S("Bag @1", 4)) .. "]",
local std_inv_x = perplayer_formspec.std_inv_x
local formspec = {
perplayer_formspec.standard_inv_bg,
"label[", perplayer_formspec.form_header_x, ",",
perplayer_formspec.form_header_y, ";", F(S("Bags")), "]",
"listcolors[#00000000;#00000000]",
"list[detached:" .. F(player_name) .. "_bags;bag1;0.5,1;1,1;]",
"list[detached:" .. F(player_name) .. "_bags;bag2;2.5,1;1,1;]",
"list[detached:" .. F(player_name) .. "_bags;bag3;4.5,1;1,1;]",
"list[detached:" .. F(player_name) .. "_bags;bag4;6.5,1;1,1;]"
}) }
}
for i = 1, 4 do
local x = std_inv_x + i * 2.5
formspec[#formspec + 1] = ui.single_slot(x - 1.875, 1.5)
formspec[#formspec + 1] = string.format("list[detached:%s_bags;bag%i;%.3f,1.65;1,1;]",
F(player_name), i, x - 1.725)
formspec[#formspec + 1] = string.format("button[%.4f,2.75;1.875,0.75;bag%i;%s]",
x - 2.1875, i, F(S("Bag @1", i)))
end
return { formspec = table.concat(formspec) }
end,
})
unified_inventory.register_button("bags", {
ui.register_button("bags", {
type = "image",
image = "ui_bags_icon.png",
tooltip = S("Bags"),
hide_lite=true
})
local function get_player_bag_stack(player, i)
@ -42,32 +47,46 @@ local function get_player_bag_stack(player, i)
end
for bag_i = 1, 4 do
unified_inventory.register_page("bag" .. bag_i, {
get_formspec = function(player)
ui.register_page("bag" .. bag_i, {
get_formspec = function(player, perplayer_formspec)
local stack = get_player_bag_stack(player, bag_i)
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
if slots == 8 then
fs[#fs + 1] = "background[0.06,0.99;7.92,7.52;ui_bags_sm_form.png]"
elseif slots == 16 then
fs[#fs + 1] = "background[0.06,0.99;7.92,7.52;ui_bags_med_form.png]"
elseif slots == 24 then
fs[#fs + 1] = "background[0.06,0.99;7.92,7.52;ui_bags_lg_form.png]"
local std_inv_x = perplayer_formspec.std_inv_x
local lite_mode = perplayer_formspec.is_lite_mode
local bag_inv_y, header_x, header_y = 1.5, 0.3, 0.65
if lite_mode then
bag_inv_y = 0.5
header_x = perplayer_formspec.form_header_x
header_y = perplayer_formspec.form_header_y
end
local formspec = {
perplayer_formspec.standard_inv_bg,
ui.make_inv_img_grid(std_inv_x, bag_inv_y, 8, slots/8),
"label[", header_x, ",", header_y, ";", F(S("Bag @1", bag_i)), "]",
"listcolors[#00000000;#00000000]",
"listring[current_player;main]",
string.format("list[current_player;bag%icontents;%f,%f;8,3;]",
bag_i, std_inv_x + ui.list_img_offset, bag_inv_y + ui.list_img_offset),
"listring[current_name;bag", bag_i, "contents]",
}
if lite_mode then
return { formspec = table.concat(formspec) }
end
local n = #formspec + 1
formspec[n] = "image[" .. std_inv_x + 8.9 .. ",0.4;1,1;" .. image .. "]"
n = n + 1
local player_name = player:get_player_name() -- For if statement.
if unified_inventory.trash_enabled
or unified_inventory.is_creative(player_name)
or minetest.get_player_privs(player_name).give then
fs[#fs + 1] = "background[6.06,0;0.92,0.92;ui_bags_trash.png]"
.. "list[detached:trash;main;6,0.1;1,1;]"
if ui.trash_enabled
or ui.is_creative(player_name)
or minetest.get_player_privs(player_name).give then
formspec[n] = ui.make_trash_slot(7.8, 0.25)
n = n + 1
end
local inv = player:get_inventory()
for i = 1, 4 do
@ -84,11 +103,12 @@ for bag_i = 1, 4 do
end
local img = def.inventory_image
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]",
i + 1, img, i, label)
formspec[n] = string.format("image_button[%f,0.4;1,1;%s;bag%i;%s]",
(i + 1.35)*1.25, img, i, label)
n = n + 1
end
end
return { formspec = table.concat(fs) }
return { formspec = table.concat(formspec) }
end,
})
end
@ -103,12 +123,14 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if not stack:get_definition().groups.bagslots then
return
end
unified_inventory.set_inventory_formspec(player, "bag" .. i)
ui.set_inventory_formspec(player, "bag" .. i)
return
end
end
end)
-- Player slots are preserved when unified_inventory is disabled. Do not allow modification.
-- Fix: use a detached inventory and store the data separately.
local function save_bags_metadata(player, bags_inv)
local is_empty = true
local bags = {}
@ -132,7 +154,7 @@ end
local function load_bags_metadata(player, bags_inv)
local player_inv = player:get_inventory()
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 dirty_meta = false
if not bags_meta then
@ -158,7 +180,7 @@ local function load_bags_metadata(player, bags_inv)
save_bags_metadata(player, bags_inv)
end
-- Clean up deprecated garbage after saving
-- Legacy: Clean up old player lists
for i = 1, 4 do
local bag = "bag" .. i
player_inv:set_size(bag, 0)
@ -167,46 +189,29 @@ end
minetest.register_on_joinplayer(function(player)
local player_name = player:get_player_name()
local bags_inv = minetest.create_detached_inventory(player_name .. "_bags",{
local bags_inv = minetest.create_detached_inventory(player_name .. "_bags", {
allow_put = function(inv, listname, index, stack, player)
local new_slots = stack:get_definition().groups.bagslots
if not new_slots then
return 0 -- ItemStack is not a bag.
end
-- The execution order of `allow_put`/`allow_take` is not defined.
-- We do not know the replacement ItemStack if the items are swapped.
-- Hence, bag slot upgrades and downgrades are not possible with the
-- current API.
if not player:get_inventory():is_empty(listname .. "contents") then
-- Legacy: in case `allow_take` is not executed on old Minetest versions.
return 0
end
return 1
end,
on_put = function(inv, listname, index, stack, player)
player:get_inventory():set_size(listname .. "contents",
stack:get_definition().groups.bagslots)
save_bags_metadata(player, inv)
end,
allow_put = function(inv, listname, index, stack, player)
local new_slots = stack:get_definition().groups.bagslots
if not new_slots then
return 0
end
local player_inv = player:get_inventory()
local old_slots = player_inv:get_size(listname .. "contents")
if new_slots >= old_slots then
return 1
end
-- using a smaller bag, make sure it fits
local old_list = player_inv:get_list(listname .. "contents")
local new_list = {}
local slots_used = 0
local use_new_list = false
for i, v in ipairs(old_list) do
if v and not v:is_empty() then
slots_used = slots_used + 1
use_new_list = i > new_slots
new_list[slots_used] = v
end
end
if new_slots >= slots_used then
if use_new_list then
player_inv:set_list(listname .. "contents", new_list)
end
return 1
end
-- New bag is smaller: Disallow inserting
return 0
end,
allow_take = function(inv, listname, index, stack, player)
if player:get_inventory():is_empty(listname .. "contents") then
return stack:get_count()
@ -216,6 +221,11 @@ minetest.register_on_joinplayer(function(player)
on_take = function(inv, listname, index, stack, player)
player:get_inventory():set_size(listname .. "contents", 0)
save_bags_metadata(player, inv)
if listname == ui.current_page[player:get_player_name()] then
-- Bag is currently open: avoid follow-up issues by navigating back
-- Trick: the list name is the same as the registered page name
ui.set_inventory_formspec(player, "bags")
end
end,
allow_move = function()
return 0
@ -225,6 +235,20 @@ minetest.register_on_joinplayer(function(player)
load_bags_metadata(player, bags_inv)
end)
minetest.register_allow_player_inventory_action(function(player, action, inventory, info)
-- From detached inventory -> player inventory: put & take callbacks
if action ~= "put" or not info.listname:find("bag%dcontents") then
return
end
if info.stack:get_definition().groups.bagslots then
-- Problem 1: empty bags could be moved into their own slots
-- Problem 2: cannot reliably keep track of ItemStack ownership due to
--> Disallow all external bag movements into this list
return 0
end
end)
-- register bag tools
minetest.register_tool("unified_inventory:bag_small", {
description = S("Small Bag"),

View File

@ -1,3 +1,5 @@
local ui = unified_inventory
local function default_refill(stack)
stack:set_count(stack:get_stack_max())
local itemdef = minetest.registered_items[stack:get_name()]
@ -12,18 +14,17 @@ end
minetest.register_on_joinplayer(function(player)
local player_name = player:get_player_name()
unified_inventory.players[player_name] = {}
unified_inventory.current_index[player_name] = 1
unified_inventory.current_index[player_name] = 1 -- Item (~page) index
unified_inventory.filtered_items_list[player_name] =
unified_inventory.items_list
unified_inventory.items_list
unified_inventory.activefilter[player_name] = ""
unified_inventory.active_search_direction[player_name] = "nochange"
unified_inventory.apply_filter(player, "", "nochange")
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.current_item[player_name] = nil
unified_inventory.current_craft_direction[player_name] = "recipe"
unified_inventory.set_inventory_formspec(player,
unified_inventory.default)
-- Refill slot
local refill = minetest.create_detached_inventory(player_name.."refill", {
@ -45,34 +46,92 @@ minetest.register_on_joinplayer(function(player)
refill:set_size("main", 1)
end)
minetest.register_on_mods_loaded(function()
minetest.register_on_joinplayer(function(player)
-- After everything is initialized, set up the formspec
ui.apply_filter(player, "", "nochange")
ui.set_inventory_formspec(player, unified_inventory.default)
end)
end)
local function apply_new_filter(player, search_text, new_dir)
local player_name = player:get_player_name()
minetest.sound_play("click", {to_player=player_name, gain = 0.1})
unified_inventory.apply_filter(player, search_text, new_dir)
unified_inventory.current_searchbox[player_name] = search_text
unified_inventory.set_inventory_formspec(player,
unified_inventory.current_page[player_name])
minetest.sound_play("ui_click", {to_player=player_name, gain = 0.1})
ui.apply_filter(player, search_text, new_dir)
ui.current_searchbox[player_name] = search_text
ui.set_inventory_formspec(player, ui.current_page[player_name])
end
-- Search box handling
local function receive_fields_searchbox(player, formname, fields)
local player_name = player:get_player_name()
-- always take new search text, even if not searching on it yet
if fields.searchbox and fields.searchbox ~= ui.current_searchbox[player_name] then
ui.current_searchbox[player_name] = fields.searchbox
end
if fields.searchbutton
or fields.key_enter_field == "searchbox" then
if ui.current_searchbox[player_name] ~= ui.activefilter[player_name] then
ui.apply_filter(player, ui.current_searchbox[player_name], "nochange")
ui.set_inventory_formspec(player, ui.current_page[player_name])
minetest.sound_play("paperflip2",
{to_player=player_name, gain = 1.0})
end
elseif fields.searchresetbutton then
if ui.activefilter[player_name] ~= "" then
apply_new_filter(player, "", "nochange")
end
end
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
local player_name = player:get_player_name()
local ui_peruser,draw_lite_mode = unified_inventory.get_per_player_formspec(player_name)
if formname ~= "" then
return
end
-- always take new search text, even if not searching on it yet
if fields.searchbox
and fields.searchbox ~= unified_inventory.current_searchbox[player_name] then
unified_inventory.current_searchbox[player_name] = fields.searchbox
receive_fields_searchbox(player, formname, fields)
local player_name = player:get_player_name()
local ui_peruser,draw_lite_mode = unified_inventory.get_per_player_formspec(player_name)
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 or fields.prev_category then
local step = fields.next_category and 1 or -1
local scroll_old = ui.current_category_scroll[player_name]
local scroll_new = math.max(0, math.min(#ui.category_list - ui_peruser.pagecols, scroll_old + step))
if scroll_old ~= scroll_new then
ui.current_category_scroll[player_name] = scroll_new
ui.set_inventory_formspec(player,
unified_inventory.current_page[player_name])
end
end
for i, def in pairs(unified_inventory.buttons) do
if fields[def.name] then
def.action(player)
minetest.sound_play("click",
minetest.sound_play("ui_click",
{to_player=player_name, gain = 0.1})
return
end
@ -121,11 +180,12 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
-- Check clicked item image button
local clicked_item
for name, value in pairs(fields) do
local new_dir, mangled_item = string.match(name, "^item_button_([a-z]+)_(.*)$")
local new_dir, mangled_item = string.match(name, "^[0-9]*_?item_button_([a-z]+)_(.*)$")
if new_dir and mangled_item then
clicked_item = unified_inventory.demangle_for_formspec(mangled_item)
if string.sub(clicked_item, 1, 6) == "group:" then
-- Change search filter to this group
unified_inventory.current_category[player_name] = "all"
apply_new_filter(player, clicked_item, new_dir)
return
end
@ -136,7 +196,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
end
if clicked_item then
minetest.sound_play("click",
minetest.sound_play("ui_click",
{to_player=player_name, gain = 0.1})
local page = unified_inventory.current_page[player_name]
local player_creative = unified_inventory.is_creative(player_name)
@ -158,22 +218,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
end
if fields.searchbutton
or fields.key_enter_field == "searchbox" then
unified_inventory.apply_filter(player, unified_inventory.current_searchbox[player_name], "nochange")
unified_inventory.set_inventory_formspec(player,
unified_inventory.current_page[player_name])
minetest.sound_play("paperflip2",
{to_player=player_name, gain = 1.0})
elseif fields.searchresetbutton then
apply_new_filter(player, "", "nochange")
end
-- alternate buttons
if not (fields.alternate or fields.alternate_prev) then
return
end
minetest.sound_play("click",
minetest.sound_play("ui_click",
{to_player=player_name, gain = 0.1})
local item_name = unified_inventory.current_item[player_name]
if not item_name then
@ -204,11 +253,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
unified_inventory.current_page[player_name])
end)
if minetest.delete_detached_inventory then
minetest.register_on_leaveplayer(function(player)
local player_name = player:get_player_name()
minetest.delete_detached_inventory(player_name.."_bags")
minetest.delete_detached_inventory(player_name.."craftrecipe")
minetest.delete_detached_inventory(player_name.."refill")
end)
end
minetest.register_on_leaveplayer(function(player)
local player_name = player:get_player_name()
minetest.remove_detached_inventory(player_name.."_bags")
minetest.remove_detached_inventory(player_name.."refill")
end)

153
category.lua Normal file
View File

@ -0,0 +1,153 @@
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 = "unknown_item.png",
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)
config = config or {}
if config.symbol then
unified_inventory.set_category_symbol(category_name, config.symbol)
end
if config.label then
unified_inventory.set_category_label(category_name, config.label)
end
if config.index then
unified_inventory.set_category_index(category_name, config.index)
end
if config.items then
unified_inventory.add_category_items(category_name, config.items)
end
update_category_list()
end
-- TODO: Mark these for removal. They are pretty much useless
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

@ -1,8 +1,17 @@
unified_inventory API
=====================
This file provides information about the API of unified_inventory.
This file provides information about the API of unified_inventory
and can be viewed in Markdown readers.
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
--------------
@ -12,6 +21,66 @@ Grouped by use-case, afterwards sorted alphabetically.
* Checks whether creative is enabled or the player has `creative`
Callbacks
---------
Register a callback that will be run whenever a craft is registered via unified_inventory.register_craft.
This callback is run before any recipe ingredients checks, hence it is also executed on recipes that are
purged after all mods finished loading.
unified_inventory.register_on_craft_registered(
function (item_name, options)
-- item_name (string): name of the output item, equivalent to `ItemStack:get_name()`
-- options (table): definition table of crafts registered by `unified_inventory.register_craft`
end
)
Register a callback that will be run after all mods have loaded and after the unified_inventory mod has initialised all its internal structures:
unified_inventory.register_on_initialized(callback)
-- The callback is passed no arguments
Accessing Data
--------------
These methods should be used instead of accessing the unified_inventory data structures directly - this will ensure your code survives any potential restructuring of the mod.
Get a list of recipes for a particular output item:
unified_inventory.get_recipe_list(output_item)
Returns a list of tables, each holding a recipe definition, like:
{
{
type = "normal",
items = { "default:stick", "default:stick", "default:stick", "default:stick" },
output = "default:wood",
width = 2
},
{
type = "shapeless",
items = { "default:tree" },
output = "default:wood 4",
width = 0
},
...
}
Get a list of all the output items crafts have been registered for:
unified_inventory.get_registered_outputs()
Returns a list of item names, like:
{
"default:stone",
"default:chest",
"default:brick",
"doors:door_wood",
...
}
Pages
-----
@ -93,3 +162,61 @@ Register a non-standard craft recipe:
-- ^ Same as `minetest.register_recipe`
})
Categories
----------
* `unified_inventory.register_category(name, def)`
* Registers a new category
* `name` (string): internal category name
* `def` (optional, table): also its fields are optional
unified_inventory.register_category("category_name", {
symbol = source,
-- ^ Can be in the format "mod_name:item_name" or "texture.png",
label = "Human Readable Label",
index = 5,
-- ^ Categories are sorted by index. Lower numbers appear before higher ones.
-- By default, the name is translated to a number: AA -> 0.0101, ZZ -> 0.2626
--- Predefined category indices: "all" = -2, "uncategorized" = -1
items = {
"mod_name:item_name",
"another_mod:different_item"
}
-- ^ List of items within this category
})
* `unified_inventory.remove_category(name)`
* Removes an entire category
Modifier functions (to be removed)
* `unified_inventory.set_category_symbol(name, source)`
* Changes the symbol of the category. The category does not need to exist yet.
* `name` (string): internal category name
* `source` (string, optional): `"mod_name:item_name"` or `"texture.png"`.
Defaults to `"default:stick"` if not specified.
* `unified_inventory.set_category_label(name, label)`
* Changes the human readable label of the category.
* `name` (string): internal category name
* `label` (string): human readable label. Defaults to the category name.
* `unified_inventory.set_category_index(name, index)`
* Changes the sorting index of the category.
* `name` (string): internal category name
* `index` (numeric): any real number
Item management
* ` unified_inventory.add_category_item(name, itemname)`
* Adds a single item to the category
* `itemname` (string): self-explanatory
* `unified_inventory.add_category_items(name, { itemname1, itemname2, ... }`
* Same as above but with multiple items
* `unified_inventory.remove_category_item(name, itemname)`
* Removes an item from the category
* `unified_inventory.find_category(itemname)`
* Looks up the first category containing this item
* Returns: category name (string) or nil
* `unified_inventory.find_categories(itemname)`
* Looks up the item name within all registered categories
* Returns: array of category names (table)

101
group.lua
View File

@ -1,29 +1,5 @@
local S = minetest.get_translator("unified_inventory")
function unified_inventory.canonical_item_spec_matcher(spec)
local specname = ItemStack(spec):get_name()
if specname:sub(1, 6) ~= "group:" then
return function (itemname)
return itemname == specname
end
end
local group_names = specname:sub(7):split(",")
return function (itemname)
local itemdef = minetest.registered_items[itemname]
for _, group_name in ipairs(group_names) do
if (itemdef.groups[group_name] or 0) == 0 then
return false
end
end
return true
end
end
function unified_inventory.item_matches_spec(item, spec)
local itemname = ItemStack(item):get_name()
return unified_inventory.canonical_item_spec_matcher(spec)(itemname)
end
local ui = unified_inventory
function unified_inventory.extract_groupnames(groupname)
local specname = ItemStack(groupname):get_name()
@ -34,22 +10,6 @@ function unified_inventory.extract_groupnames(groupname)
return table.concat(group_names, S(" and ")), #group_names
end
unified_inventory.registered_group_items = {
mesecon_conductor_craftable = "mesecons:wire_00000000_off",
stone = "default:cobble",
wood = "default:wood",
book = "default:book",
sand = "default:sand",
leaves = "default:leaves",
tree = "default:tree",
vessel = "vessels:glass_bottle",
wool = "wool:white",
}
function unified_inventory.register_group_item(groupname, itemname)
unified_inventory.registered_group_items[groupname] = itemname
end
-- This is used when displaying craft recipes, where an ingredient is
-- specified by group rather than as a specific item. A single-item group
@ -67,6 +27,7 @@ end
-- It may be a comma-separated list of group names. This is really a
-- "group:..." ingredient specification, minus the "group:" prefix.
-- TODO Replace this with the more efficient spec matcher (below)
local function compute_group_item(group_name_list)
local group_names = group_name_list:split(",")
local candidate_items = {}
@ -125,3 +86,61 @@ function unified_inventory.get_group_item(group_name)
return group_item_cache[group_name]
end
--[[
This is for filtering known items by groups
e.g. find all items that match "group:flower,yellow" (flower AND yellow groups)
]]
local spec_matcher = {}
function unified_inventory.init_matching_cache()
for _, name in ipairs(ui.items_list) do
-- we only need to care about groups, exact items are handled separately
for group, value in pairs(minetest.registered_items[name].groups) do
if value and value ~= 0 then
if not spec_matcher[group] then
spec_matcher[group] = {}
end
spec_matcher[group][name] = true
end
end
end
end
--[[
Retrieves all matching items
Arguments:
specname (string): Item name or group(s) to filter
Output:
{
matchingitem1 = true,
...
}
]]
function unified_inventory.get_matching_items(specname)
if specname:sub(1,6) ~= "group:" then
return { [specname] = true }
end
local accepted = {}
for i, group in ipairs(specname:sub(7):split(",")) do
if i == 1 then
-- First step: Copy all possible item names in this group
for name, _ in pairs(spec_matcher[group] or {}) do
accepted[name] = true
end
else
-- Perform filtering
if spec_matcher[group] then
for name, _ in pairs(accepted) do
accepted[name] = spec_matcher[group][name]
end
else
-- No matching items
return {}
end
end
end
return accepted
end

151
init.lua
View File

@ -1,4 +1,10 @@
-- Unified Inventory for Minetest >= 0.4.16
-- Unified Inventory
if not minetest.features.formspec_version_element then
-- At least formspec_version[] is the minimal feature requirement
error("Unified Inventory requires Minetest version 5.4.0 or newer.\n" ..
" Please update Minetest or use an older version of Unified Inventory.")
end
local modpath = minetest.get_modpath(minetest.get_current_modname())
local worldpath = minetest.get_worldpath()
@ -10,6 +16,8 @@ unified_inventory = {
alternate = {},
current_page = {},
current_searchbox = {},
current_category = {},
current_category_scroll = {},
current_index = {},
current_item = {},
current_craft_direction = {},
@ -22,6 +30,8 @@ unified_inventory = {
filtered_items_list = {},
pages = {},
buttons = {},
initialized_callbacks = {},
craft_registered_callbacks = {},
-- Homepos stuff
home_pos = {},
@ -33,20 +43,129 @@ unified_inventory = {
-- "Lite" mode
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 = (minetest.settings:get_bool("unified_inventory_trash") ~= false),
imgscale = 1.25,
list_img_offset = 0.13,
standard_background = "bgcolor[#0000]background9[0,0;1,1;ui_formbg_9_sliced.png;true;16]",
pagecols = 8,
pagerows = 10,
page_y = 0,
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
hide_disabled_buttons = minetest.settings:get_bool("unified_inventory_hide_disabled_buttons", false),
version = 4
}
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,
-- Item browser size, pos
pagecols = 8,
pagerows = 9,
page_x = 10.75,
page_y = 2.30,
-- Item browser controls
page_buttons_x = 11.60,
page_buttons_y = 10.15,
searchwidth = 3.4,
-- Crafting grid positions
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,
-- Tab switching buttons
main_button_x = 0.4,
main_button_y = 11.0,
main_button_cols = 12,
main_button_rows = 1,
-- Tab title position
form_header_x = 0.4,
form_header_y = 0.4,
-- Generic sizes
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,
-- Item browser size, pos
pagecols = 4,
pagerows = 5,
page_x = 10.5,
page_y = 2.15,
-- Item browser controls
page_buttons_x = 10.5,
page_buttons_y = 6.15,
searchwidth = 1.6,
-- Crafting grid positions
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,
-- Tab switching buttons
main_button_x = 10.5,
main_button_y = 8.15,
main_button_cols = 4,
main_button_rows = 2,
-- Tab title position
form_header_x = 0.2,
form_header_y = 0.2,
-- Generic sizes
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
local creative = rawget(_G, "creative") or rawget(_G, "creative_inventory")
if creative then
@ -62,7 +181,8 @@ if sfinv then
end
dofile(modpath.."/group.lua")
dofile(modpath.."/api.lua")
dofile(modpath.."/category.lua")
dofile(modpath.."/default-categories.lua")
dofile(modpath.."/internal.lua")
dofile(modpath.."/callbacks.lua")
dofile(modpath.."/match_craft.lua")
@ -71,11 +191,12 @@ dofile(modpath.."/register.lua")
if minetest.settings:get_bool("unified_inventory_bags") ~= false then
dofile(modpath.."/bags.lua")
end
dofile(modpath.."/item_names.lua")
if minetest.get_modpath("datastorage") then
if minetest.settings:get_bool("unified_inventory_item_names") ~= false then
dofile(modpath.."/item_names.lua")
end
if minetest.settings:get_bool("unified_inventory_waypoints") ~= false then
dofile(modpath.."/waypoints.lua")
end
dofile(modpath.."/legacy.lua") -- mod compatibility
minetest.log("action", "[unified_inventory] loaded.")

View File

@ -1,5 +1,6 @@
local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape
local ui = unified_inventory
-- This pair of encoding functions is used where variable text must go in
-- button names, where the text might contain formspec metacharacters.
@ -9,281 +10,349 @@ local F = minetest.formspec_escape
-- 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
-- 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)
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)
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})
-- Get the player-specific unified_inventory style
function ui.get_per_player_formspec(player_name)
local draw_lite_mode = ui.lite_mode and not minetest.check_player_privs(player_name, {ui_full=true})
local ui = {}
ui.pagecols = unified_inventory.pagecols
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
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
local style = table.copy(draw_lite_mode and ui.style_lite or ui.style_full)
style.is_lite_mode = draw_lite_mode
return style
end
function unified_inventory.get_formspec(player, page)
-- Creates an item image or regular image button with a tooltip
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'
elseif image:find(":", 1, true) then
image = "unknown_item.png"
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
-- Add registered buttons (tabs)
local function formspec_tab_buttons(player, formspec, style)
local n = #formspec + 1
-- Main buttons
local filtered_inv_buttons = {}
for _, def in pairs(ui.buttons) do
if not (style.is_lite_mode and def.hide_lite) then
if def.condition == nil or def.condition(player) or not ui.hide_disabled_buttons then
table.insert(filtered_inv_buttons, def)
end
end
end
local needs_scrollbar = #filtered_inv_buttons > style.main_button_cols * style.main_button_rows
formspec[n] = ("scroll_container[%g,%g;%g,%g;tabbtnscroll;vertical]"):format(
style.main_button_x, style.main_button_y, -- position
style.main_button_cols * style.btn_spc, style.main_button_rows -- size
)
n = n + 1
for i, def in pairs(filtered_inv_buttons) do
local pos_x = ((i - 1) % style.main_button_cols) * style.btn_spc
local pos_y = math.floor((i - 1) / style.main_button_cols) * style.btn_spc
if def.type == "image" then
if (def.condition == nil or def.condition(player)) then
formspec[n] = string.format("image_button[%g,%g;%g,%g;%s;%s;]",
pos_x, pos_y, style.btn_size, style.btn_size,
F(def.image),
F(def.name))
formspec[n+1] = "tooltip["..F(def.name)..";"..(def.tooltip or "").."]"
n = n+2
else
formspec[n] = string.format("image[%g,%g;%g,%g;%s^[colorize:#808080:alpha]",
pos_x, pos_y, style.btn_size, style.btn_size,
def.image)
n = n+1
end
end
end
formspec[n] = "scroll_container_end[]"
if needs_scrollbar then
local total_rows = math.ceil(#filtered_inv_buttons / style.main_button_cols)
formspec[n+1] = ("scrollbaroptions[max=%i;arrows=hide]"):format(
-- This calculation is not 100% accurate but "good enough"
(total_rows - style.main_button_rows) * style.btn_spc * 10
)
formspec[n+2] = ("scrollbar[%g,%g;0.4,%g;vertical;tabbtnscroll;0]"):format(
style.main_button_x + style.main_button_cols * style.btn_spc - 0.1, -- x pos
style.main_button_y, -- y pos
style.main_button_rows * style.btn_spc -- height
)
formspec[n+3] = "scrollbaroptions[max=1000;arrows=default]"
end
end
-- Add category GUI elements (top right)
local function formspec_add_categories(player, formspec, ui_peruser)
local player_name = player:get_player_name()
local n = #formspec + 1
local categories_pos = {
ui_peruser.page_x,
ui_peruser.page_y-ui_peruser.btn_spc-0.5
}
local categories_scroll_pos = {
ui_peruser.page_x,
ui_peruser.form_header_y - (ui_peruser.is_lite_mode and 0 or 0.2)
}
formspec[n] = string.format("background9[%f,%f;%f,%f;%s;false;16]",
ui_peruser.page_x-0.15, categories_scroll_pos[2],
(ui_peruser.btn_spc * ui_peruser.pagecols) + 0.2, 1.4 + (ui_peruser.is_lite_mode and 0 or 0.2),
"ui_smallbg_9_sliced.png")
n = n + 1
formspec[n] = string.format("label[%f,%f;%s]",
ui_peruser.page_x,
ui_peruser.form_header_y + (ui_peruser.is_lite_mode and 0.3 or 0.2), F(S("Category:")))
n = n + 1
local scroll_offset = 0
local category_count = #ui.category_list
if category_count > ui_peruser.pagecols then
scroll_offset = ui.current_category_scroll[player_name]
end
for index, category in ipairs(ui.category_list) do
local column = index - scroll_offset
if column > 0 and column <= ui_peruser.pagecols then
local scale = 0.8
if ui.current_category[player_name] == category.name then
scale = 1
end
formspec[n] = formspec_button(ui_peruser, "category_"..category.name, category.symbol, categories_pos, {column-1, 0}, scale, category.label)
n = n + 1
end
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"))
end
end
local function formspec_add_search_box(player, formspec, ui_peruser)
local player_name = player:get_player_name()
local n = #formspec + 1
formspec[n] = "field_close_on_enter[searchbox;false]"
formspec[n+1] = string.format("field[%f,%f;%f,%f;searchbox;;%s]",
ui_peruser.page_buttons_x, ui_peruser.page_buttons_y,
ui_peruser.searchwidth - 0.1, ui_peruser.btn_size,
F(ui.current_searchbox[player_name]))
formspec[n+2] = string.format("image_button[%f,%f;%f,%f;ui_search_icon.png;searchbutton;]",
ui_peruser.page_buttons_x + ui_peruser.searchwidth, ui_peruser.page_buttons_y,
ui_peruser.btn_size,ui_peruser.btn_size)
formspec[n+3] = "tooltip[searchbutton;" ..F(S("Search")) .. "]"
formspec[n+4] = string.format("image_button[%f,%f;%f,%f;ui_reset_icon.png;searchresetbutton;]",
ui_peruser.page_buttons_x + ui_peruser.searchwidth + ui_peruser.btn_spc,
ui_peruser.page_buttons_y,
ui_peruser.btn_size, ui_peruser.btn_size)
formspec[n+5] = "tooltip[searchresetbutton;"..F(S("Reset search and display everything")).."]"
if ui.activefilter[player_name] ~= "" then
formspec[n+6] = string.format("label[%f,%f;%s: %s]",
ui_peruser.page_x, ui_peruser.page_y - 0.25,
F(S("Filter")), F(ui.activefilter[player_name]))
end
end
local function formspec_add_item_browser(player, formspec, ui_peruser)
local player_name = player:get_player_name()
local n = #formspec + 1
-- 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 ui_peruser.is_lite_mode then
btnlist[2] = nil
btnlist[5] = 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
-- Items list
if #ui.filtered_items_list[player_name] == 0 then
local no_matches = S("No matching items")
if ui_peruser.is_lite_mode then
no_matches = S("No matches.")
end
formspec[n] = "label["..ui_peruser.page_x..","..(ui_peruser.page_y+0.15)..";" .. F(no_matches) .. "]"
return
end
local dir = ui.active_search_direction[player_name]
local list_index = ui.current_index[player_name]
local page2 = math.floor(list_index / (ui_peruser.items_per_page) + 1)
local pagemax = math.floor(
(#ui.filtered_items_list[player_name] - 1)
/ (ui_peruser.items_per_page) + 1)
for y = 0, ui_peruser.pagerows - 1 do
for x = 0, ui_peruser.pagecols - 1 do
local name = ui.filtered_items_list[player_name][list_index]
local item = minetest.registered_items[name]
if item then
-- Clicked on current item: Flip crafting direction
if name == ui.current_item[player_name] then
local cdir = ui.current_craft_direction[player_name]
if cdir == "recipe" then
dir = "usage"
elseif cdir == "usage" then
dir = "recipe"
end
else
-- Default: use active search direction by default
dir = ui.active_search_direction[player_name]
end
local button_name = "item_button_" .. dir .. "_"
.. ui.mangle_for_formspec(name)
formspec[n] = ("item_image_button[%f,%f;%f,%f;%s;%s;]"):format(
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
)
local tooltip = item.description
if item.mod_origin then
-- "mod_origin" may not be specified for items that were
-- registered in a callback (during or before ServerEnv init)
tooltip = tooltip .. " [" .. item.mod_origin .. "]"
end
formspec[n + 1] = ("tooltip[%s;%s]"):format(
button_name, minetest.formspec_escape(tooltip)
)
n = n + 2
list_index = list_index + 1
end
end
end
formspec[n] = "style[page_number;content_offset=0]"
formspec[n + 1] = string.format("image_button[%f,%f;%f,0.4;;page_number;%s: %s;false;false;]",
ui_peruser.page_buttons_x,
ui_peruser.page_buttons_y + ui_peruser.btn_spc * 2 - 0.1,
ui_peruser.btn_spc * (bn - 1) + ui_peruser.btn_size,
F(S("Page")), S("@1 of @2",page2,pagemax))
end
function ui.get_formspec(player, page)
if not player then
return ""
end
local player_name = player:get_player_name()
local ui_peruser,draw_lite_mode = unified_inventory.get_per_player_formspec(player_name)
local ui_peruser = ui.get_per_player_formspec(player_name)
unified_inventory.current_page[player_name] = page
local pagedef = unified_inventory.pages[page]
ui.current_page[player_name] = page
local pagedef = ui.pages[page]
if not pagedef then
return "" -- Invalid page name
end
local formspec = {
"size[14,10]",
local fs = {
"formspec_version[4]",
"size["..ui_peruser.formw..","..ui_peruser.formh.."]",
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
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)
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 perplayer_formspec = ui.get_per_player_formspec(player_name)
local fsdata = pagedef.get_formspec(player, perplayer_formspec)
formspec[n] = fsdata.formspec
n = n+1
fs[#fs + 1] = fsdata.formspec
local button_row = 0
local button_col = 0
-- Main buttons
local filtered_inv_buttons = {}
for i, def in pairs(unified_inventory.buttons) do
if not (draw_lite_mode and def.hide_lite) then
table.insert(filtered_inv_buttons, def)
end
end
local j = 1 --Modif NALC (sys4 20/11/2018) 12 buttons max by row
for i, def in pairs(filtered_inv_buttons) do
if draw_lite_mode and i > 4 then
button_row = 1
button_col = 1
elseif not draw_lite_mode and j > 12 then
button_row = 1
j = 1
end
if def.type == "image" then
if (def.condition == nil or def.condition(player) == true) then
formspec[n] = "image_button["
formspec[n+1] = ( ui_peruser.main_button_x + 0.65 * (j - 1) - button_col * 0.65 * 4) -- Modif NALC
formspec[n+2] = ","..(ui_peruser.main_button_y + button_row * 0.7)..";0.8,0.8;"
formspec[n+3] = F(def.image)..";"
formspec[n+4] = F(def.name)..";]"
formspec[n+5] = "tooltip["..F(def.name)
formspec[n+6] = ";"..(def.tooltip or "").."]"
n = n+7
else
formspec[n] = "image["
formspec[n+1] = ( ui_peruser.main_button_x + 0.65 * (j - 1) - button_col * 0.65 * 4) -- Modif NALC
formspec[n+2] = ","..(ui_peruser.main_button_y + button_row * 0.7)..";0.8,0.8;"
formspec[n+3] = F(def.image).."^[colorize:#808080:alpha]"
n = n+4
end
end
j = j + 1 -- Modif NALC
end
formspec_tab_buttons(player, fs, ui_peruser)
if fsdata.draw_inventory ~= false then
-- Player inventory
formspec[n] = "listcolors[#00000000;#00000000]"
formspec[n+1] = "list[current_player;main;0,"..(ui_peruser.formspec_y + 3.5)..";8,4;]"
n = n+2
fs[#fs + 1] = "listcolors[#00000000;#00000000]"
fs[#fs + 1] = ui_peruser.standard_inv
end
if fsdata.draw_item_list == false then
return table.concat(formspec, "")
return table.concat(fs, "")
end
-- Controls to flip items pages
local start_x = 9.2
formspec_add_categories(player, fs, ui_peruser)
formspec_add_search_box(player, fs, ui_peruser)
formspec_add_item_browser(player, fs, ui_peruser)
if not draw_lite_mode then
formspec[n] =
"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)
.. ",9;.8,.8;ui_doubleleft_icon.png;rewind3;]"
.. "tooltip[rewind3;" .. F(S("Back three pages")) .. "]"
.. "image_button[" .. (start_x + 0.6 * 2)
.. ",9;.8,.8;ui_left_icon.png;rewind1;]"
.. "tooltip[rewind1;" .. F(S("Back one page")) .. "]"
.. "image_button[" .. (start_x + 0.6 * 3)
.. ",9;.8,.8;ui_right_icon.png;forward1;]"
.. "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)
.. ",9;.8,.8;ui_skip_forward_icon.png;end_list;]"
.. "tooltip[end_list;" .. F(S("Last page")) .. "]"
else
formspec[n] =
"image_button[" .. (8.2 + 0.65 * 0)
.. ",5.8;.8,.8;ui_skip_backward_icon.png;start_list;]"
.. "tooltip[start_list;" .. F(S("First page")) .. "]"
.. "image_button[" .. (8.2 + 0.65 * 1)
.. ",5.8;.8,.8;ui_left_icon.png;rewind1;]"
.. "tooltip[rewind1;" .. F(S("Back one page")) .. "]"
.. "image_button[" .. (8.2 + 0.65 * 2)
.. ",5.8;.8,.8;ui_right_icon.png;forward1;]"
.. "tooltip[forward1;" .. F(S("Forward one page")) .. "]"
.. "image_button[" .. (8.2 + 0.65 * 3)
.. ",5.8;.8,.8;ui_skip_forward_icon.png;end_list;]"
.. "tooltip[end_list;" .. F(S("Last page")) .. "]"
end
n = n+1
-- Search box
formspec[n] = "field_close_on_enter[searchbox;false]"
n = n+1
if not draw_lite_mode then
formspec[n] = "field[9.5,8.325;3,1;searchbox;;"
.. F(unified_inventory.current_searchbox[player_name]) .. "]"
formspec[n+1] = "image_button[12.2,8.1;.8,.8;ui_search_icon.png;searchbutton;]"
.. "tooltip[searchbutton;" ..F(S("Search")) .. "]"
formspec[n+2] = "image_button[12.9,8.1;.8,.8;ui_reset_icon.png;searchresetbutton;]"
.. "tooltip[searchbutton;" ..F(S("Search")) .. "]"
.. "tooltip[searchresetbutton;" ..F(S("Reset search and display everything")) .. "]"
else
formspec[n] = "field[8.5,5.225;2.2,1;searchbox;;"
.. F(unified_inventory.current_searchbox[player_name]) .. "]"
formspec[n+1] = "image_button[10.3,5;.8,.8;ui_search_icon.png;searchbutton;]"
.. "tooltip[searchbutton;" ..F(S("Search")) .. "]"
formspec[n+2] = "image_button[11,5;.8,.8;ui_reset_icon.png;searchresetbutton;]"
.. "tooltip[searchbutton;" ..F(S("Search")) .. "]"
.. "tooltip[searchresetbutton;" ..F(S("Reset search and display everything")) .. "]"
end
n = n+3
local no_matches = S("No matching items")
if draw_lite_mode then
no_matches = S("No matches.")
end
-- Items list
if #unified_inventory.filtered_items_list[player_name] == 0 then
formspec[n] = "label[8.2,"..ui_peruser.form_header_y..";" .. F(no_matches) .. "]"
else
local dir = unified_inventory.active_search_direction[player_name]
local list_index = unified_inventory.current_index[player_name]
local page2 = math.floor(list_index / (ui_peruser.items_per_page) + 1)
local pagemax = math.floor(
(#unified_inventory.filtered_items_list[player_name] - 1)
/ (ui_peruser.items_per_page) + 1)
for y = 0, ui_peruser.pagerows - 1 do
for x = 0, ui_peruser.pagecols - 1 do
local name = unified_inventory.filtered_items_list[player_name][list_index]
local item = minetest.registered_items[name]
if item then
-- Clicked on current item: Flip crafting direction
if name == unified_inventory.current_item[player_name] then
local cdir = unified_inventory.current_craft_direction[player_name]
if cdir == "recipe" then
dir = "usage"
elseif cdir == "usage" then
dir = "recipe"
end
else
-- Default: use active search direction by default
dir = unified_inventory.active_search_direction[player_name]
end
local button_name = "item_button_" .. dir .. "_"
.. unified_inventory.mangle_for_formspec(name)
formspec[n] = ("item_image_button[%f,%f;.81,.81;%s;%s;]"):format(
8.2 + x * 0.7, ui_peruser.formspec_y + ui_peruser.page_y + y * 0.7,
name, button_name
)
formspec[n + 1] = ("tooltip[%s;%s \\[%s\\]]"):format(
button_name, minetest.formspec_escape(item.description),
item.mod_origin or "??"
)
n = n + 2
list_index = list_index + 1
end
end
end
formspec[n] = "label[8.2,"..ui_peruser.form_header_y..";"..F(S("Page")) .. ": "
.. S("@1 of @2",page2,pagemax).."]"
end
n= n+1
if unified_inventory.activefilter[player_name] ~= "" then
formspec[n] = "label[8.2,"..(ui_peruser.form_header_y + 0.4)..";" .. F(S("Filter")) .. ":]"
formspec[n+1] = "label[9.1,"..(ui_peruser.form_header_y + 0.4)..";"..F(unified_inventory.activefilter[player_name]).."]"
end
return table.concat(formspec, "")
return table.concat(fs)
end
function unified_inventory.set_inventory_formspec(player, page)
function ui.set_inventory_formspec(player, page)
if player then
player:set_inventory_formspec(unified_inventory.get_formspec(player, page))
player:set_inventory_formspec(ui.get_formspec(player, page))
end
end
function ui.is_itemdef_listable(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)
function unified_inventory.apply_filter(player, filter, search_dir)
function ui.apply_filter(player, filter, search_dir)
if not player then
return false
end
local player_name = player:get_player_name()
local lfilter = string.lower(filter)
local ffilter
if lfilter:sub(1, 6) == "group:" then
-- Group filter: all groups of the item must match
local groups = lfilter:sub(7):split(",")
ffilter = function(name, def)
for _, group in ipairs(groups) do
@ -295,84 +364,66 @@ function unified_inventory.apply_filter(player, filter, search_dir)
return true
end
else
-- Name filter: fuzzy match item names and descriptions
local player_info = minetest.get_player_information(player_name)
local lang = player_info and player_info.lang_code or ""
ffilter = function(name, def)
local lname = string.lower(name)
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)
or llocaldesc and string.find(llocaldesc, lfilter, 1, true)
end
end
unified_inventory.filtered_items_list[player_name]={}
for name, def in pairs(minetest.registered_items) do
if (not def.groups.not_in_creative_inventory
or def.groups.not_in_creative_inventory == 0)
and def.description
and def.description ~= ""
and ffilter(name, def) then
table.insert(unified_inventory.filtered_items_list[player_name], name)
end
end
table.sort(unified_inventory.filtered_items_list[player_name])
unified_inventory.filtered_items_list_size[player_name] = #unified_inventory.filtered_items_list[player_name]
unified_inventory.current_index[player_name] = 1
unified_inventory.activefilter[player_name] = filter
unified_inventory.active_search_direction[player_name] = search_dir
unified_inventory.set_inventory_formspec(player,
unified_inventory.current_page[player_name])
end
function unified_inventory.items_in_group(groups)
local items = {}
for name, item in pairs(minetest.registered_items) do
for _, group in pairs(groups:split(',')) do
if item.groups[group] then
table.insert(items, name)
local is_itemdef_listable = ui.is_itemdef_listable
local filtered_items = {}
local category = ui.current_category[player_name] or 'all'
if category == 'all' then
for name, def in pairs(minetest.registered_items) do
if is_itemdef_listable(def)
and ffilter(name, def) then
table.insert(filtered_items, name)
end
end
elseif category == 'uncategorized' then
for name, def in pairs(minetest.registered_items) do
if is_itemdef_listable(def)
and not ui.find_category(name)
and ffilter(name, def) then
table.insert(filtered_items, name)
end
end
else
-- Any other category is selected
for name, exists in pairs(ui.registered_category_items[category]) do
local def = minetest.registered_items[name]
if exists and def
and is_itemdef_listable(def)
and ffilter(name, def) then
table.insert(filtered_items, name)
end
end
end
return items
table.sort(filtered_items)
ui.filtered_items_list_size[player_name] = #filtered_items
ui.filtered_items_list[player_name] = filtered_items
ui.current_index[player_name] = 1
ui.activefilter[player_name] = filter
ui.active_search_direction[player_name] = search_dir
ui.set_inventory_formspec(player, ui.current_page[player_name])
end
function unified_inventory.sort_inventory(inv)
local inlist = inv:get_list("main")
local typecnt = {}
local typekeys = {}
for _, st in ipairs(inlist) do
if not st:is_empty() then
local n = st:get_name()
local w = st:get_wear()
local m = st:get_metadata()
local k = string.format("%s %05d %s", n, w, m)
if not typecnt[k] then
typecnt[k] = {
name = n,
wear = w,
metadata = m,
stack_max = st:get_stack_max(),
count = 0,
}
table.insert(typekeys, k)
end
typecnt[k].count = typecnt[k].count + st:get_count()
end
-- Inform players about potential visual issues
minetest.register_on_joinplayer(function(player)
local player_name = player:get_player_name()
local info = minetest.get_player_information(player_name)
if info and (info.formspec_version or 0) < 4 then
minetest.chat_send_player(player_name, S("Unified Inventory: Your game version is too old"
.. " and does not support the GUI requirements. You might experience visual issues."))
end
table.sort(typekeys)
local outlist = {}
for _, k in ipairs(typekeys) do
local tc = typecnt[k]
while tc.count > 0 do
local c = math.min(tc.count, tc.stack_max)
table.insert(outlist, ItemStack({
name = tc.name,
wear = tc.wear,
metadata = tc.metadata,
count = c,
}))
tc.count = tc.count - c
end
end
if #outlist > #inlist then return end
while #outlist < #inlist do
table.insert(outlist, ItemStack(nil))
end
inv:set_list("main", outlist)
end
end)

View File

@ -3,6 +3,8 @@
local item_names = {} -- [player_name] = { hud, dtime, itemname }
local dlimit = 3 -- HUD element will be hidden after this many seconds
local hudbars_mod = minetest.get_modpath("hudbars")
local only_names = minetest.settings:get_bool("unified_inventory_only_names", true)
local max_length = tonumber(minetest.settings:get("unified_inventory_max_item_name_length")) or 80
local function set_hud(player)
local player_name = player:get_player_name()
@ -60,6 +62,7 @@ minetest.register_globalstep(function(dtime)
data.itemname = itemname
data.index = index
data.dtime = 0
local lang_code = minetest.get_player_information(player:get_player_name()).lang_code
local desc = stack.get_meta
and stack:get_meta():get_string("description")
@ -69,6 +72,14 @@ minetest.register_globalstep(function(dtime)
local def = minetest.registered_items[itemname]
desc = def and def.description or ""
end
if only_names and desc and string.find(desc, "\n") then
desc = string.match(desc, "([^\n]*)")
end
desc = minetest.get_translated_string(lang_code, desc)
desc = minetest.strip_colors(desc)
if string.len(desc) > max_length and max_length > 0 then
desc = string.sub(desc, 1, max_length) .. " [...]"
end
player:hud_change(data.hud, 'text', desc)
end
end

55
legacy.lua Normal file
View File

@ -0,0 +1,55 @@
-- Inefficient pattern matching
local warned_funcs = {}
local function LOG_ONCE(funcname)
if warned_funcs[funcname] then return end
warned_funcs[funcname] = true
minetest.log("error", "Call to undocumented, deprecated API '" .. funcname .. "'."
.. " In a future version of Unified Inventory this will result in a real error.")
end
function unified_inventory.canonical_item_spec_matcher(spec)
LOG_ONCE("canonical_item_spec_matcher")
local specname = ItemStack(spec):get_name()
if specname:sub(1, 6) ~= "group:" then
return function (itemname)
return itemname == specname
end
end
local group_names = specname:sub(7):split(",")
return function (itemname)
local itemdef = minetest.registered_items[itemname]
for _, group_name in ipairs(group_names) do
if (itemdef.groups[group_name] or 0) == 0 then
return false
end
end
return true
end
end
function unified_inventory.item_matches_spec(item, spec)
LOG_ONCE("item_matches_spec")
local itemname = ItemStack(item):get_name()
return unified_inventory.canonical_item_spec_matcher(spec)(itemname)
end
unified_inventory.registered_group_items = {
mesecon_conductor_craftable = "mesecons:wire_00000000_off",
stone = "default:cobble",
wood = "default:wood",
book = "default:book",
sand = "default:sand",
leaves = "default:leaves",
tree = "default:tree",
vessel = "vessels:glass_bottle",
wool = "wool:white",
}
function unified_inventory.register_group_item(groupname, itemname)
LOG_ONCE("register_group_item")
unified_inventory.registered_group_items[groupname] = itemname
end

View File

@ -1,54 +1,52 @@
# textdomain: unified_inventory
# waypoints.lua
White=
Yellow=
Red=
Green=
Blue=
Waypoints=
Select Waypoint #@1=
Waypoint @1=
Set waypoint to current location=
Make waypoint @1=
invisible=
visible=
@1 display of waypoint coordinates=
Disable=
Enable=
Change color of waypoint display=
Edit waypoint name=
Waypoint active=
Waypoint inactive=
Finish editing=
World position=
Name=
HUD text color=
# group.lua
Mixing=
Cooking=
Digging=
Bags=
Bag @1=
Small Bag=
Medium Bag=
Large Bag=
All Items=
Misc. Items=
Plant Life=
Building Materials=
Tools=
Minerals and Metals=
Environment and Worldgen=
Lighting=
and =
# register.lua
Scroll categories left=
Scroll categories right=
Search=
Reset search and display everything=
First page=
Back three pages=
Back one page=
Forward one page=
Forward three pages=
Last page=
No matching items=
No matches.=
Page=
@1 of @2=
Filter=
Can use the creative inventory=
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=
Crafting Guide=
Set home position=
Home position set to: @1=
You don't have the \"home\" privilege!=
You don't have the "home" privilege!=
Go home=
Set time to day=
Set time to night=
Time of day set to 6am=
Time of day set to 9pm=
You don't have the settime privilege!=
Set time to night=
Time of day set to 9pm=
Clear inventory=
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=
This button has been disabled outside=
Crafting=
Trash:=
Refill:=
Any item belonging to the @1 group=
@ -65,36 +63,28 @@ Show previous recipe=
Show previous usage=
@1 (@2)=
Give me:=
This recipe is too@nlarge to be displayed.=
This recipe is too@@large to be displayed.=
To craft grid:=
All=
# api.lua
Mixing=
Cooking=
Digging=
# internal.lua
First page=
Back three pages=
Back one page=
Forward one page=
Forward three pages=
Last page=
Search=
Reset search and display everything=
No matching items=
No matches.=
Page=
@1 of @2=
Filter=
# bags.lua
Bags=
Bag @1=
Small Bag=
Medium Bag=
Large Bag=
Crafting=
White=
Yellow=
Red=
Green=
Blue=
Waypoints=
Select Waypoint #@1=
Waypoint @1=
Set waypoint to current location=
Hide waypoint=
Show waypoint=
Hide coordinates=
Show coordinates=
Change color of waypoint display=
Edit waypoint name=
Waypoint active=
Waypoint inactive=
Finish editing=
World position=
Name=
HUD text color=

View File

@ -1,5 +1,4 @@
# textdomain: unified_inventory
Crafting=Fertigung
Mixing=Mischen
Cooking=Kochen
Digging=Graben
@ -8,21 +7,32 @@ Bag @1=Tasche @1
Small Bag=Kleine Tasche
Medium Bag=Mittelgroße Tasche
Large Bag=Große Tasche
All Items=Alle Gegenstände
Misc. Items=Sonstige Gegenstände
Plant Life=Pfanzenwelt
Building Materials=Baumaterialien
Tools=Werkzeuge
Minerals and Metals=Minerale und Metalle
Environment and Worldgen=Umwelt und Welterstellung
Lighting=Beleuchtung
and = und
Scroll categories left=Kategorien nach links blättern
Scroll categories right=Kategorien nach rechts blättern
Search=Suchen
Reset search and display everything=Suche zurücksetzen und alles anzeigen
First page=Erste Seite
Back three pages=3 Seiten zurückblättern
Back one page=1 Seite zurückblättern
Forward one page=1 Seite vorblättern
Forward three pages=3 Seiten vorblättern
Last page=Letzte Seite
Search=Suchen
Reset search and display everything=Suche zurücksetzen und alles anzeigen
No matching items=Keine passenden Gegenstände
No matches.=Keine Treffer
Page=Seite
@1 of @2=@1 von @2
Filter=Filter
Can use the creative inventory=Kann das Kreativinventar nutzen
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=Zwingt Unified Inventory, im Vollmodus angezeigt zu werden, wenn der Minimalmodus global eingestellt ist
Crafting Grid=Fertigungsraster
Crafting Guide=Fertigungsführer
Set home position=Heimatposition setzen
@ -35,6 +45,7 @@ You don't have the settime privilege!=Du hast das „settime“-Privileg nicht!
Set time to night=Zur Nachtzeit wechseln
Time of day set to 9pm=Tageszeit auf 21 Uhr gesetzt
Clear inventory=Inventar leeren
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Inventar geleert!
Trash:=Müll:
Refill:=Nachfüllen:
@ -50,9 +61,12 @@ Show next recipe=Nächstes Rezept zeigen
Show next usage=Nächste Verwendung zeigen
Show previous recipe=Vorheriges Rezept zeigen
Show previous usage=Vorherige Verwendung zeigen
@1 (@2)=
Give me:=Gib mir:
This recipe is too@@large to be displayed.=
To craft grid:=Ins Fertigungsraster:
All=Alles
Crafting=Fertigung
White=Weiß
Yellow=Gelb
Red=Rot
@ -62,12 +76,10 @@ Waypoints=Wegpunkte
Select Waypoint #@1=Wegpunkt Nr. @1 auswählen
Waypoint @1=Wegpunkt Nr. @1
Set waypoint to current location=Setze Wegpunkt zur derzeitigen Position
invisible=unsichtbar
visible=sichtbar
Make waypoint @1=Wegpunkt @1 machen
Disable=ausschalten
Enable=einschalten
@1 display of waypoint coordinates=Anzeige der Wegpunktkoordinaten @1
Hide waypoint=Wegpunkt verstecken
Show waypoint=Wegpunkt zeigen
Hide coordinates=Koordinaten verstecken
Show coordinates=Koordinaten zeigen
Change color of waypoint display=Farbe der Darstellung der Wegpunkte ändern
Edit waypoint name=Name des Wegpunkts ändern
Waypoint active=Wegpunkt aktiv
@ -76,4 +88,13 @@ Finish editing=Bearbeitung abschließen
World position=Weltposition
Name=Name
HUD text color=HUD-Textfarbe
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=Zwingt Unified Inventory, im Vollmodus angezeigt zu werden, wenn der Minimalmodus global eingestellt ist
##### not used anymore #####
invisible=unsichtbar
visible=sichtbar
Make waypoint @1=Wegpunkt @1 machen
Disable=ausschalten
Enable=einschalten
@1 display of waypoint coordinates=Anzeige der Wegpunktkoordinaten @1

View File

@ -1,54 +1,57 @@
# textdomain: unified_inventory
# waypoints.lua
White=Blanco
Yellow=Amarillo
Red=Rojo
Green=Verde
Blue=Azul
Waypoints=Puntos
Select Waypoint #@1=Seleccionar Punto #@1
Waypoint @1=Punto @1
Set waypoint to current location=Establecer el punto a la ubicación actual
Make waypoint @1=Hacer punto @1
invisible=invisible
visible=visible
@1 display of waypoint coordinates=Visualizar coordenadas del punto @1
Disable=Deshabilitado
Enable=Habilitado
Change color of waypoint display=Cambiar el color del punto
Edit waypoint name=Editar nombre del punto
Waypoint active=Punto activo
Waypoint inactive=Punto inactivo
Finish editing=Terminar edición
World position=Posición en el mundo
Name=Nombre
HUD text color=Color del texto de la Interfaz
# api.lua
Mixing=Mezclar
Cooking=Hornear
Digging=Recoger
# bags.lua
Bags=Bolsos
Bag @1=Bolso @1
Small Bag=Bolso Pequeño
Medium Bag=Bolso Mediano
Large Bag=Bolso Grande
All Items=
Misc. Items=
Plant Life=
Building Materials=
Tools=
Minerals and Metals=
Environment and Worldgen=
Lighting=
# group.lua
and = y
Scroll categories left=
Scroll categories right=
Search=Buscar
Reset search and display everything=Limpiar la busqueda y mostrar todo
# internal.lua
First page=Primera página
Back three pages=Volver tres páginas
Back one page=Volver una página
Forward one page=Avanzar una página
Forward three pages=Avanzar tres páginas
Last page=Ultima Pagina
No matching items=No se encontraron elementos
No matches.=No hay resultados.
Page=Página
@1 of @2=@1 de @2
Filter=Filtro
# register.lua
Can use the creative inventory=Puede usar el inventario creativo
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=Obliga al Inventario Unificado a mostrarse en modo Completo si el modo Simple está configurado globalmente
Crafting Grid=Cuadricula de Elaboración
Crafting Guide=Guía de Elaboración
Set home position=Establecer posición de la casa
Home position set to: @1=Posición de la casa cambiada a: @1
You don't have the \"home\" privilege!=¡No tienes el privilegio \"home\"!
You don't have the "home" privilege!=
Go home=Ir a casa
Set time to day=Cambiar a dia
Set time to night=Cambiar a noche
Time of day set to 6am=Hora del día cambiada a 6 AM
Time of day set to 9pm=Hora del día cambiada a 9 PM
You don't have the settime privilege!=¡No tienes el privilegio "settime"!
Set time to night=Cambiar a noche
Time of day set to 9pm=Hora del día cambiada a 9 PM
Clear inventory=Limpiar inventario
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=¡Inventario limpio!
This button has been disabled outside=Este botón ha sido deshabilitado
Crafting=Elaboración
Trash:=Basura:
Refill:=Rellenar:
Any item belonging to the @1 group=Cualquier elemento que pertenezca al grupo @1
@ -65,36 +68,41 @@ Show previous recipe=Mostrar la receta anterior
Show previous usage=Mostrar el uso anterior
@1 (@2)=@1 (@2)
Give me:=Dame:
This recipe is too@nlarge to be displayed.=Esta receta es demasiado@ngrande para ser mostrada.
This recipe is too@@large to be displayed.=
To craft grid:=Construir:
All=Todos
Crafting=Elaboración
White=Blanco
Yellow=Amarillo
Red=Rojo
Green=Verde
Blue=Azul
Waypoints=Puntos
Select Waypoint #@1=Seleccionar Punto #@1
Waypoint @1=Punto @1
Set waypoint to current location=Establecer el punto a la ubicación actual
Hide waypoint=
Show waypoint=
Hide coordinates=
Show coordinates=
Change color of waypoint display=Cambiar el color del punto
Edit waypoint name=Editar nombre del punto
Waypoint active=Punto activo
Waypoint inactive=Punto inactivo
Finish editing=Terminar edición
World position=Posición en el mundo
Name=Nombre
HUD text color=Color del texto de la Interfaz
# api.lua
Mixing=Mezclar
Cooking=Hornear
Digging=Recoger
##### not used anymore #####
# internal.lua
First page=Primera página
Back three pages=Volver tres páginas
Back one page=Volver una página
Forward one page=Avanzar una página
Forward three pages=Avanzar tres páginas
Last page=Ultima Pagina
Search=Buscar
Reset search and display everything=Limpiar la busqueda y mostrar todo
No matching items=No se encontraron elementos
No matches.=No hay resultados.
Page=Página
@1 of @2=@1 de @2
Filter=Filtro
# bags.lua
Bags=Bolsos
Bag @1=Bolso @1
Small Bag=Bolso Pequeño
Medium Bag=Bolso Mediano
Large Bag=Bolso Grande
Make waypoint @1=Hacer punto @1
invisible=invisible
visible=visible
@1 display of waypoint coordinates=Visualizar coordenadas del punto @1
Disable=Deshabilitado
Enable=Habilitado
You don't have the \"home\" privilege!=¡No tienes el privilegio \"home\"!
This button has been disabled outside=Este botón ha sido deshabilitado
This recipe is too@nlarge to be displayed.=Esta receta es demasiado@ngrande para ser mostrada.

View File

@ -1,5 +1,5 @@
# textdomain: unified_inventory
Crafting=Création
Mixing=
Cooking=Cuisson
Digging=Creuser
Bags=Sacs
@ -7,35 +7,66 @@ Bag @1=Sac @1
Small Bag=Petit sac
Medium Bag=Sac moyen
Large Bag=Grand sac
All Items=
Misc. Items=
Plant Life=
Building Materials=
Tools=
Minerals and Metals=
Environment and Worldgen=
Lighting=
and = et
Scroll categories left=
Scroll categories right=
Search=Rechercher
Reset search and display everything=
First page=1ère page
Back three pages=3 pages en arrière
Back one page=Page précédente
Forward one page=Page suivante
Forward three pages=3 pages en avant
Last page=Dernière page
Search=Rechercher
No matching items=Aucun élément correspondant
No matches.=Aucun match
Page=Page
@1 of @2=@1 de @2
Filter=Filtre
Can use the creative inventory=Vous pouvez utiliser l'inventaire créatif
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=Grille de création
Crafting Guide=Guide de création
Set home position=Position dans le monde
Home position set to: @1=Position de votre base fixée à: @1
You don't have the "home" privilege!=Vous n'avez pas le privilège "home"!
Go home=
Set time to day=
Time of day set to 6am=Heure fixée à 6h
You don't have the settime privilege!=Vous n'avez pas le privilège "settime"!
Set time to night=
Time of day set to 9pm=Heure fixée à 21h
Clear inventory=
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Inventaire vidé !
Trash:=Poubelle :
Refill:=Remplir :
Any item belonging to the @1 group=
Any item belonging to the groups @1=
Recipe @1 of @2=Recette @1 de @2
Usage @1 of @2=
No recipes=
No usages=
Result=Résultat
Ingredient=
Show next recipe=
Show next usage=
Show previous recipe=
Show previous usage=
@1 (@2)=
Give me:=
This recipe is too@@large to be displayed.=
To craft grid:=Sur de création:
All=Tout
Crafting=Création
White=Blanc
Yellow=Jaune
Red=Rouge
@ -45,8 +76,10 @@ Waypoints=Point de passage
Select Waypoint #@1=Choisir un point de passage #@1
Waypoint @1=Point de passage @1
Set waypoint to current location=Marquer un point de passage à la position actuelle
Make waypoint @1=Rendre @1 le point de passage
@1 display of waypoint coordinates=@1 montrer les coordonnées des points de passages
Hide waypoint=
Show waypoint=
Hide coordinates=
Show coordinates=
Change color of waypoint display=Changer la couleur du point de passage
Edit waypoint name=Editer le nom du point de passage
Waypoint active=Point de passage actif
@ -55,3 +88,9 @@ Finish editing=Terminer l'édition
World position=Position dans le monde
Name=Nom
HUD text color=Couleur de texte du HUD
##### not used anymore #####
Make waypoint @1=Rendre @1 le point de passage
@1 display of waypoint coordinates=@1 montrer les coordonnées des points de passages

View File

@ -1,5 +1,4 @@
# textdomain: unified_inventory
Crafting=Assemblaggio
Mixing=Unione
Cooking=Cottura
Digging=Scavo
@ -8,21 +7,32 @@ Bag @1=Borsa @1
Small Bag=Borsa piccola
Medium Bag=Borsa media
Large Bag=Borsa grande
All Items=
Misc. Items=
Plant Life=
Building Materials=
Tools=
Minerals and Metals=
Environment and Worldgen=
Lighting=
and = e
Scroll categories left=
Scroll categories right=
Search=Cerca
Reset search and display everything=Azzera la ricerca e mostra tutto
First page=Prima pagina
Back three pages=Indietro di tre pagine
Back one page=Indietro di una pagina
Forward one page=Avanti di una pagina
Forward three pages=Avanti di tre pagine
Last page=Ultima pagina
Search=Cerca
Reset search and display everything=Azzera la ricerca e mostra tutto
No matching items=Nessun oggetto corrispondente
No matches.=Nessuna corrispondenza.
Page=Pagina
@1 of @2=@1 di @2
Filter=Filtro
Can use the creative inventory=Può usare l'inventario creativo
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=Forza la visualizzazione di Unified Inventory in modalità completa se è configurata globalmente la visualizzazione semplice
Crafting Grid=Griglia di assemblaggio
Crafting Guide=Guida di assemblaggio
Set home position=Imposta la residenza
@ -35,6 +45,7 @@ You don't have the settime privilege!=Non hai il privilegio "time"!
Set time to night=Imposta l'orario sulla notte
Time of day set to 9pm=Orario impostato sulle 9am
Clear inventory=Ripulisci l'inventario
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Inventario ripulito!
Trash:=Butta:
Refill:=Riempi:
@ -50,9 +61,12 @@ Show next recipe=Mostra la prossima ricetta
Show next usage=Mostra il prossimo utilizzo
Show previous recipe=Mostra la ricetta precedente
Show previous usage=Mostra l'utilizzo precedente
@1 (@2)=
Give me:=Dammi:
This recipe is too@@large to be displayed.=
To craft grid:=Alla griglia di assemblaggio:
All=Tutto
Crafting=Assemblaggio
White=Bianco
Yellow=Giallo
Red=Rosso
@ -62,12 +76,10 @@ Waypoints=Tappe
Select Waypoint #@1=Seleziona tappa n°@1
Waypoint @1=Tappa @1
Set waypoint to current location=Imposta tappa alla posizione attuale
invisible=invisibile
visible=visibile
Make waypoint @1=Crea tappa @1
Disable=Disabilita
Enable=Abilita
@1 display of waypoint coordinates=@1 la visualizzazione delle coordinate della tappa
Hide waypoint=
Show waypoint=
Hide coordinates=
Show coordinates=
Change color of waypoint display=Modifica il colore della visualizzazione della tappa
Edit waypoint name=Modifica il nome della tappa
Waypoint active=Tappa attiva
@ -76,4 +88,13 @@ Finish editing=Termina la modifica
World position=Posizione del mondo
Name=Nome
HUD text color=Colore del testo del visore
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=Forza la visualizzazione di Unified Inventory in modalità completa se è configurata globalmente la visualizzazione semplice
##### not used anymore #####
invisible=invisibile
visible=visibile
Make waypoint @1=Crea tappa @1
Disable=Disabilita
Enable=Abilita
@1 display of waypoint coordinates=@1 la visualizzazione delle coordinate della tappa

View File

@ -1,5 +1,4 @@
# textdomain: unified_inventory
Crafting=Pertukangan
Mixing=Pencampuran
Cooking=Pemasakan
Digging=Penggalian
@ -8,21 +7,32 @@ Bag @1=Beg @1
Small Bag=Beg Kecil
Medium Bag=Beg Sederhana
Large Bag=Beg Besar
All Items=
Misc. Items=
Plant Life=
Building Materials=
Tools=
Minerals and Metals=
Environment and Worldgen=
Lighting=
and = dan
Scroll categories left=
Scroll categories right=
Search=Cari
Reset search and display everything=Set semula carian dan tunjukkan semua benda
First page=Halaman pertama
Back three pages=Tiga halaman sebelumnya
Back one page=Halaman sebelumnya
Forward one page=Halaman seterusnya
Forward three pages=Tiga halaman seterusnya
Last page=Halaman terakhir
Search=Cari
Reset search and display everything=Set semula carian dan tunjukkan semua benda
No matching items=Tiada item sepadan
No matches.=Tiada padanan.
Page=Halaman
@1 of @2=@1 drpd @2
Filter=Tapis
Can use the creative inventory=Boleh guna inventori kreatif
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=Grid Pertukangan
Crafting Guide=Panduan Pertukangan
Set home position=Tetapkan kedudukan rumah
@ -35,6 +45,7 @@ You don't have the settime privilege!=Anda tidak ada keistimewaan settime!
Set time to night=Tetapkan masa jadi malam
Time of day set to 9pm=Masa ditetapkan ke 9 malam
Clear inventory=Kosongkan inventori
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Inventori dikosongkan!
Trash:=Buang:
Refill:=Isi balik:
@ -52,7 +63,10 @@ Show previous recipe=Tunjuk resipi sebelumnya
Show previous usage=Tunjuk kegunaan sebelumnya
@1 (@2)=@1 (@2)
Give me:=Beri saya:
This recipe is too@@large to be displayed.=
To craft grid:=Ke grid pertukangan:
All=
Crafting=Pertukangan
White=Putih
Yellow=Kuning
Red=Merah
@ -62,12 +76,10 @@ Waypoints=Titik Arah
Select Waypoint #@1=Pilih Titik Arah #@1
Waypoint @1=Titik Arah @1
Set waypoint to current location=Tetapkan titik arah ke lokasi semasa
invisible=Sembunyikan
visible=Paparkan
Make waypoint @1=@1 titik arah
Disable=Sembunyikan
Enable=Paparkan
@1 display of waypoint coordinates=@1 koordinat untuk titik arah
Hide waypoint=
Show waypoint=
Hide coordinates=
Show coordinates=
Change color of waypoint display=Tukar warna paparan titik arah
Edit waypoint name=Edit nama titik arah
Waypoint active=Titik arah aktif
@ -76,3 +88,13 @@ Finish editing=Selesai edit
World position=Kedudukan dunia
Name=Nama
HUD text color=Warna tulisan HUD
##### not used anymore #####
invisible=Sembunyikan
visible=Paparkan
Make waypoint @1=@1 titik arah
Disable=Sembunyikan
Enable=Paparkan
@1 display of waypoint coordinates=@1 koordinat untuk titik arah

View File

@ -1,61 +1,91 @@
# textdomain: unified_inventory
Category:=Kategorie:
Mixing=Miksowanie
Cooking=Gotowanie
Digging=Kopanie
Bags=Plecaki
Bag @1=Plecak @1
Small Bag=Maly plecak
Medium Bag=Sredni plecak
Large Bag=Duzy plecak
Small Bag=Mały plecak
Medium Bag=Średni plecak
Large Bag=Duży plecak
All Items=Wszystkie przedmioty
Misc. Items=Różne przedmioty
Plant Life=Życie roślin
Building Materials=Materiały budowlane
Tools=Narzędzia
Minerals and Metals=Minerały i metale
Environment and Worldgen=Otoczenie i generowanie świata
Lighting=Oświetlenie
and = i
First page=Pierwsza strona
Back three pages=3 strony w tyl
Back one page=1 strona w tyl
Forward one page=1 strona do przodu
Forward three pages=3 strony do przodu
Last page=Ostatnia strona
Scroll categories left=Przewiń kategorię w lewo
Scroll categories right=Przewiń kategorię w prawo
Search=Szukaj
No matching items=Brak pasujacych przedmiotow
Reset search and display everything=Zresetuj wyszukiwanie i pokaż wszystko
First page=Pierwsza strona
Back three pages=Trzy strony do tyłu
Back one page=Stronę do tyłu
Forward one page=Stronę do przodu
Forward three pages=Trzy strony do przodu
Last page=Ostatnia strona
No matching items=Brak pasujących przedmiotów
No matches.=Brak wyników
Page=Strona
@1 of @2=@1 z @2
Filter=Filtr
Set home position=Ustaw pozycję wyjściową
Home position set to: @1=Pozycja domowa ustawiona na: @1
You don't have the "home" privilege!=Nie masz uprawnien do zmiany czasu "home"!
Can use the creative inventory=Może używać kreatywnego ekwipunku
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=Wymusza wyświetlanie Unified Inventory w trybie Full jeżeli tryb Lite jest skonfigurowany globalnie
Crafting Grid=Siatka craftingu
Crafting Guide=Przewodnik craftingu
Set home position=Ustaw pozycję domu
Home position set to: @1=Pozycja domu ustawiona na: @1
You don't have the "home" privilege!=Brak uprawnień "home"!
Go home=Idź do domu
Set time to day=Ustaw czas na dzień
Time of day set to 6am=Czas ustawiony na 6:00
You don't have the settime privilege!=Nie masz uprawnien do zmiany czasu "settime"!
You don't have the settime privilege!=Brak uprawnień "settime"!
Set time to night=Ustaw czas na noc
Time of day set to 9pm=Czas ustawiony na 21:00
Clear inventory=Wyczyść zapasy
Inventory cleared!=Zapasy zostały wyczyszczone!
Trash:=Smietnik:
Refill:=Uzupelnianie:
Clear inventory=Wyczyść ekwipunek
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=Aby zapobiec przypadkowemu skasowaniu ekwipunku, ten przycisk został wyłączony poza trybem kreatywnym.@nUżyj zamiast tego ikony śmietnika.
Inventory cleared!=Ekwipunek został wyczyszczony!
Trash:=Śmietnik:
Refill:=Uzupełnianie:
Any item belonging to the @1 group=Każdy przedmiot należący do @1 grupy
Any item belonging to the groups @1=Każdy przedmiot należacy do grup @1
Recipe @1 of @2=Recepta @1 z @2
Usage @1 of @2=Użycie @1 z @2
No recipes=Brak recepty
No usages=Bez użycia
Result=Wynik
Ingredient=Składnik
Show next recipe=Pokaż nastepną recepturę
Show next usage=Pokaż następne użycie
Show previous recipe=Pokaż poprzednią recepturę
Show previous usage=Pokaż poprzednie użycie
@1 (@2)=@1 (@2)
Give me:=Daj mi:
This recipe is too@@large to be displayed.=Receptura jest zbyt@@duża aby ją wyświetlić.
To craft grid:=Do siatki craftingu.
All=Wszystko
White=Bialy
Yellow=Zolty
Crafting=Crafting
White=Biały
Yellow=Zółty
Red=Czerwony
Green=Zielony
Blue=Niebieski
Waypoints=Punkty orientacyjne
Select Waypoint #@1=Wybierz punkt #@1
Waypoint @1=Punkty orientacyjne @1
Set waypoint to current location=Ustaw punkt orientacyjny na biezacej pozycji
invisible=niewidzialny
visible=widomy
Make waypoint @1=Robić punkt @1
@1 display of waypoint coordinates=@1 koordynatow punktu
Change color of waypoint display=Zmien kolor punktu
Edit waypoint name=Edytuj nazwe punktu
Waypoint active=Punkt wlaczony
Waypoint inactive=Punkt wylaczony
Finish editing=Zakoncz edycje
Set waypoint to current location=Ustaw punkt orientacyjny na bieżacej pozycji
Hide waypoint=Ukryj punkt orientacyjny
Show waypoint=Pokaż punkt orientacyjny
Hide coordinates=Ukryj koordynaty
Show coordinates=Pokaż koordynaty
Change color of waypoint display=Zmień kolor punktu
Edit waypoint name=Edytuj nazwę punktu
Waypoint active=Punkt włączony
Waypoint inactive=Punkt wyłączony
Finish editing=Zakończ edycję
World position=Pozycja
Name=Nazwa
HUD text color=Kolor tekstu HUD
HUD text color=Kolor tekstu HUD

View File

@ -1,5 +1,4 @@
# textdomain: unified_inventory
Crafting=Artesanato
Mixing=Muistura
Cooking=Cozimento
Digging=Escavação
@ -8,21 +7,32 @@ Bag @1=Bolsa @1
Small Bag=Bolsa Pequena
Medium Bag=Bolsa Média
Large Bag=Bolsa Grande
All Items=
Misc. Items=
Plant Life=
Building Materials=
Tools=
Minerals and Metals=
Environment and Worldgen=
Lighting=
and = e
Scroll categories left=
Scroll categories right=
Search=Pesquisar
Reset search and display everything=Redefinir pesquisa e exibir tudo
First page=Primeira Página
Back three pages=Voltar 3 Páginas
Back one page=Voltar 1 Página
Forward one page=Avançar 1 Página
Forward three pages=Avançar 3 Páginas
Last page=Ultima Página
Search=Pesquisar
Reset search and display everything=Redefinir pesquisa e exibir tudo
No matching items=Nenhum item correspondente
No matches.=Sem correspondências
Page=Página
@1 of @2=@1 de @2
Filter=Filtro
Can use the creative inventory=Pode usar o inventário do criativo
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=Grade de Artesanato
Crafting Guide=Guia de Artesanato
Set home position=Definir posição de casa
@ -35,6 +45,7 @@ You don't have the settime privilege!=Você não tem o privilégio de "settime"!
Set time to night=Definir turno para noite
Time of day set to 9pm=Hora do dia ajustada para 21h
Clear inventory=Limpar Inventário
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Inventário Apagado!
Trash:=Lixo:
Refill:=Recarga:
@ -50,9 +61,12 @@ Show next recipe=Exibir Próxima Receita
Show next usage=Mostrar Próxima Utilização
Show previous recipe=Exibir Receita Anterior
Show previous usage=Exibir Utilização Anterior
@1 (@2)=
Give me:=Gerado:
This recipe is too@@large to be displayed.=
To craft grid:=Para Grade de Artesanato
All=MAX
Crafting=Artesanato
White=Branco
Yellow=Amarelo
Red=Vermelho
@ -62,10 +76,10 @@ Waypoints=Apontador de Direção
Select Waypoint #@1=Seleção de Apontador de Direção #@1
Waypoint @1=Apontador de Direção @1
Set waypoint to current location=Configurar localização atual do Apontador de Direção
invisible=invisível
visible=visível
Make waypoint @1=Fazer Apontador de Direção @1
@1 display of waypoint coordinates=@1 exibição de coordenadas de Fazer Apontador de Direção
Hide waypoint=
Show waypoint=
Hide coordinates=
Show coordinates=
Change color of waypoint display=Mudar cor exibida do Apontador de Direção
Edit waypoint name=Editar Nome de Apontador de Direção
Waypoint active=Apontador de Direção Ativo
@ -74,3 +88,11 @@ Finish editing=Edição Finalizada
World position=Posição Mundial
Name=Nome
HUD text color=Cor de HUD
##### not used anymore #####
invisible=invisível
visible=visível
Make waypoint @1=Fazer Apontador de Direção @1
@1 display of waypoint coordinates=@1 exibição de coordenadas de Fazer Apontador de Direção

View File

@ -1,5 +1,4 @@
# textdomain: unified_inventory
Crafting=Крафт
Mixing=Мешать
Cooking=Варить
Digging=Копать
@ -8,21 +7,32 @@ Bag @1=Сумка @1
Small Bag=Малая сумка
Medium Bag=Средняя сумка
Large Bag=Большая сумка
All Items=
Misc. Items=
Plant Life=
Building Materials=
Tools=
Minerals and Metals=
Environment and Worldgen=
Lighting=
and = и
Scroll categories left=
Scroll categories right=
Search=Поиск
Reset search and display everything=Сброс поиска, показать всё
First page=Первая страница
Back three pages=3 страницы назад
Back one page=1 страницу назад
Forward one page=1 страницу вперёд
Forward three pages=3 страницы вперёд
Last page=Последняя страница
Search=Поиск
Reset search and display everything=Сброс поиска, показать всё
No matching items=Нет подходящих элементов
No matches.=Ничего не найдено
Page=Страница
@1 of @2=@1 из @2
Filter=Фильтр
Can use the creative inventory=Можно использовать инвентарь творческого режима
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=Решетка крафта
Crafting Guide=Книга рецептов
Set home position=Установить позицию дома
@ -35,6 +45,7 @@ You don't have the settime privilege!=Вам не разрешено устан
Set time to night=Ночь
Time of day set to 9pm=Установлено время 9 вечера
Clear inventory=Очистить инвентарь
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Инвентарь очищен!
Trash:=Мусор:
Refill:=Наполнить:
@ -50,9 +61,12 @@ Show next recipe=Следующий рецепт
Show next usage=Следующее использование
Show previous recipe=Прошлый рецепт
Show previous usage=Прошлая страница
@1 (@2)=
Give me:=Дай мне:
This recipe is too@@large to be displayed.=
To craft grid:=На решeтку крафта:
All=Все
Crafting=Крафт
White=Белый
Yellow=Желтый
Red=Красный
@ -62,12 +76,10 @@ Waypoints=Путевые точки
Select Waypoint #@1=Выбрать путевую точку №@1
Waypoint @1=Путевая точка @1
Set waypoint to current location=Установить путевую точку по текущей позиции
invisible=невидимой
visible=видимой
Make waypoint @1=Сделать путевую точку @1
Disable=Выключить
Enable=Включить
@1 display of waypoint coordinates=@1 показ координат путевых точек
Hide waypoint=
Show waypoint=
Hide coordinates=
Show coordinates=
Change color of waypoint display=Поменять цвет путевой точки
Edit waypoint name=Переименовать путевую точку
Waypoint active=Путевая точка включена
@ -76,3 +88,13 @@ Finish editing=Закончить редакцию
World position=Позиция мира
Name=Имя
HUD text color=Цвет текста HUDа
##### not used anymore #####
invisible=невидимой
visible=видимой
Make waypoint @1=Сделать путевую точку @1
Disable=Выключить
Enable=Включить
@1 display of waypoint coordinates=@1 показ координат путевых точек

View File

@ -1,5 +1,4 @@
# textdomain: unified_inventory
Crafting=Üretim
Mixing=Karıştırma
Cooking=Pişirme
Digging=Kazma
@ -8,20 +7,32 @@ Bag @1=@1. Çanta
Small Bag=Küçük Çanta
Medium Bag=Çanta
Large Bag=Büyük Çanta
All Items=
Misc. Items=
Plant Life=
Building Materials=
Tools=
Minerals and Metals=
Environment and Worldgen=
Lighting=
and = ve
Scroll categories left=
Scroll categories right=
Search=Ara
Reset search and display everything=
First page=İlk Sayfa
Back three pages=3 Sayfa Gerile
Back one page=Geri
Forward one page=İleri
Forward three pages=3 Sayfa İlerile
Last page=Son Sayfa
Search=Ara
No matching items=Eşleşme yok
No matches.=Eşleşme yok
Page=Sayfa
@1 of @2=@1 dan @2
Filter=Süzgeç
Can use the creative inventory=Yaratıcı envanteri kullanabilir
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=Üretim tablosu
Crafting Guide=Kılavuz
Set home position=Set ev pozisyon
@ -33,19 +44,29 @@ Time of day set to 6am=Saat 06:00 olarak ayarlandı
You don't have the settime privilege!="settime" yetkiniz yok!
Set time to night=Geceye zaman ayarla
Time of day set to 9pm=Saat 19:00 olarak ayarlandı
msgid ""=Yaratıcı modu dışında iken bu tuş kullanılamaz.
Clear inventory=
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Envanter temizlendi!
Trash:=Çöp
Refill:=Doldur
Any item belonging to the @1 group=
Any item belonging to the groups @1=
Recipe @1 of @2=@1 dan @2 tarifi
Usage @1 of @2=Kullanım @1/@2
No recipes=Tarifi yok
No usages=Kullanım yok
Result=Çıktı
Ingredient=Bileşen
Show next recipe=
Show next usage=
Show previous recipe=
Show previous usage=
@1 (@2)=
Give me:=Ver bana:
This recipe is too@@large to be displayed.=
To craft grid:=Üretim tablosuna kopyala
All=Tümü
Crafting=Üretim
White=Beyaz
Yellow=Sarı
Red=Kırmızı
@ -55,10 +76,10 @@ Waypoints=Konum Noktaları
Select Waypoint #@1=#@1 konum noktası seç
Waypoint @1=@1 Konum Noktaları
Set waypoint to current location=Bulunduğun noktayı işaretle
invisible=görünmez
visible=görünür
Make waypoint @1=Yol noktası @1
@1 display of waypoint coordinates=Yol noktası koordinatlarının görüntülenmesini @1
Hide waypoint=
Show waypoint=
Hide coordinates=
Show coordinates=
Change color of waypoint display=Konum Gösterge Rengi
Edit waypoint name=Konum Noktasını Düzenle
Waypoint active=Konum Etkin
@ -67,3 +88,12 @@ Finish editing=Düzenleme bitti
World position=Dünya konumu
Name=İsim
HUD text color=Metin rengi
##### not used anymore #####
msgid ""=Yaratıcı modu dışında iken bu tuş kullanılamaz.
invisible=görünmez
visible=görünür
Make waypoint @1=Yol noktası @1
@1 display of waypoint coordinates=Yol noktası koordinatlarının görüntülenmesini @1

View File

@ -1,8 +1,4 @@
# textdomain: unified_inventory
# traslation by: IFRFSX(BingFengFSX)
#Email: IFRFSX@Protonmail.com
Crafting=合成
Mixing=混合
Cooking=烹饪
Digging=挖出
@ -11,20 +7,32 @@ Bag @1=背包@1
Small Bag=小背包
Medium Bag=中背包
Large Bag=大背包
All Items=所有物品
Misc. Items=杂项
Plant Life=植物
Building Materials=建材
Tools=工具
Minerals and Metals=矿物与金属
Environment and Worldgen=自然环境
Lighting=光源
and = 和
Scroll categories left=向左滚动分类栏
Scroll categories right=向右滚动分类栏
Search=搜索
Reset search and display everything=重置搜索并显示所有物品
First page=第一页
Back three pages=后退三页
Back one page=后退一页
Forward one page=前进一页
Forward three pages=前进三页
Last page=最后一页
Search=搜索
No matching items=没有匹配物品
No matches.=没有匹配
Page=页面
@1 of @2=第@1页共@2页
Filter=过滤器
Can use the creative inventory=可以使用创造背包
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=如果轻量模式被全局配置强迫Unified Inventory以完全模式展现。
Crafting Grid=合成表
Crafting Guide=合成指南
Set home position=设置家的位置
@ -36,21 +44,29 @@ Time of day set to 6am=时间设置到早晨6点
You don't have the settime privilege!=你没有“settime”权限
Set time to night=设置时间到晚上
Time of day set to 9pm=时间设置到晚上9点
Inventory cleared!=清空背包
Clear inventory=清空背包
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=此按钮已在非创造模式中禁用以防止意外的背包清空。@n请使用垃圾桶栏。
Inventory cleared!=清空背包
Trash:=丢弃:
Refill:=填满:
Any item belonging to the @1 group=属于@1组的任何项目
Any item belonging to the groups @1=属于组@1的任何项目
Recipe @1 of @2=第@1配方共@2个
Usage @1 of @2=第@1用法共@2个
No recipes=没有配方
No usages=没有用法
Result=结果
Ingredient=原料
Show next recipe=显示下一个配方
Show next usage=显示下一个用法
Show previous recipe=显示前一个配方
Show previous usage=显示前一个用法
@1 (@2)=@1 (@2)
Give me:=给予:
This recipe is too@@large to be displayed.=该配方太@@大,不能显示。
To craft grid:=填充物品到合成表
All=全部
Crafting=合成
White=白
Yellow=黄
Red=红
@ -60,10 +76,10 @@ Waypoints=航路点
Select Waypoint #@1=查询航路点 #@1
Waypoint @1=航路点 @1
Set waypoint to current location=将航路点设置到当前位置
invisible=不可见的
visible=可见的
Make waypoint @1=设置航路点 @1
@1 display of waypoint coordinates=显示航路点@1坐标
Hide waypoint=隐藏航路点
Show waypoint=显示航路点
Hide coordinates=隐藏坐标
Show coordinates=显示坐标
Change color of waypoint display=改变航路点显示的颜色
Edit waypoint name=编辑航路点名称
Waypoint active=航路点已激活
@ -73,6 +89,10 @@ World position=世界位置
Name=名称
HUD text color=HUD文本颜色
#new
Reset search and display everything=重置搜索并显示所有物品
##### not used anymore #####
invisible=不可见的
visible=可见的
Make waypoint @1=设置航路点 @1
@1 display of waypoint coordinates=显示航路点@1坐标

View File

@ -1,8 +1,4 @@
# textdomain: unified_inventory
# traslation by: IFRFSX(BingFengFSX)
#Email: IFRFSX@Protonmail.com
Crafting=合成
Mixing=混合
Cooking=烹飪
Digging=挖出
@ -11,20 +7,32 @@ Bag @1=揹包@1
Small Bag=小揹包
Medium Bag=中揹包
Large Bag=大揹包
All Items=所有物品
Misc. Items=雜項
Plant Life=植物
Building Materials=建材
Tools=工具
Minerals and Metals=礦物與金屬
Environment and Worldgen=自然環境
Lighting=光源
and = 和
Scroll categories left=向左滾動分類欄
Scroll categories right=向右滾動分類欄
Search=搜索
Reset search and display everything=重置搜索並顯示所有物品
First page=第一頁
Back three pages=後退三頁
Back one page=後退一頁
Forward one page=前進一頁
Forward three pages=前進三頁
Last page=最後一頁
Search=搜索
No matching items=沒有匹配物品
No matches.=沒有匹配
Page=頁面
@1 of @2=第@1頁共@2頁
Filter=過濾器
Can use the creative inventory=可以使用創造揹包
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=如果輕量模式被全局配置強迫Unified Inventory以完全模式展現。
Crafting Grid=合成表
Crafting Guide=合成指南
Set home position=設置家的位置
@ -36,21 +44,29 @@ Time of day set to 6am=時間設置到早晨6點
You don't have the settime privilege!=你沒有“settime”權限
Set time to night=設置時間到晚上
Time of day set to 9pm=時間設置到晚上9點
Inventory cleared!=清空揹包
Clear inventory=清空揹包
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=此按鈕已在非創造模式中禁用以防止意外的背包清空。@n請使用垃圾桶欄。
Inventory cleared!=清空揹包
Trash:=丟棄:
Refill:=填滿:
Any item belonging to the @1 group=屬於@1組的任何項目
Any item belonging to the groups @1=屬於組@1的任何項目
Recipe @1 of @2=第@1配方共@2個
Usage @1 of @2=第@1用法共@2個
No recipes=沒有配方
No usages=沒有用法
Result=結果
Ingredient=原料
Show next recipe=顯示下一個配方
Show next usage=顯示下一個用法
Show previous recipe=顯示上一個配方
Show previous usage=顯示上一個用法
@1 (@2)=@1 (@2)
Give me:=給予:
This recipe is too@@large to be displayed.=該配方太@@大,不能顯示。
To craft grid:=填充物品到合成表
All=全部
Crafting=合成
White=白
Yellow=黃
Red=紅
@ -60,10 +76,10 @@ Waypoints=航路點
Select Waypoint #@1=查詢航路點 #@1
Waypoint @1=航路點 @1
Set waypoint to current location=將航路點設置到當前位置
invisible=不可見的
visible=可見的
Make waypoint @1=設置航路點 @1
@1 display of waypoint coordinates=顯示航路點@1座
Hide waypoint=隱藏航路點
Show waypoint=顯示航路點
Hide coordinates=隱藏坐標
Show coordinates=顯示坐
Change color of waypoint display=改變航路點顯示的顏色
Edit waypoint name=編輯航路點名稱
Waypoint active=航路點已激活
@ -73,6 +89,10 @@ World position=世界位置
Name=名稱
HUD text color=HUD文本顏色
#new
Reset search and display everything=重置搜索並顯示所有物品
##### not used anymore #####
invisible=不可見的
visible=可見的
Make waypoint @1=設置航路點 @1
@1 display of waypoint coordinates=顯示航路點@1座標

View File

@ -126,25 +126,18 @@ Example output:
}
--]]
function unified_inventory.find_usable_items(inv_items, craft_items)
local get_group = minetest.get_item_group
local result = {}
for craft_item in pairs(craft_items) do
local group = craft_item:match("^group:(.+)")
local found = {}
-- may specify group:type1,type2
local items = unified_inventory.get_matching_items(craft_item)
if group ~= nil then
for inv_item in pairs(inv_items) do
if get_group(inv_item, group) > 0 then
found[inv_item] = true
end
end
else
if inv_items[craft_item] ~= nil then
found[craft_item] = true
local found = {}
for itemname, _ in pairs(items) do
if inv_items[itemname] then
found[itemname] = true
end
end
result[craft_item] = found
end

View File

@ -1,4 +1,8 @@
name = unified_inventory
depends = default
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.
optional_depends = default, creative, sfinv, datastorage
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 NS = function(s) return s end
local F = minetest.formspec_escape
local ui = unified_inventory
minetest.register_privilege("creative", {
description = S("Can use the creative inventory"),
@ -12,10 +13,9 @@ minetest.register_privilege("ui_full", {
give_to_singleplayer = false,
})
local trash = minetest.create_detached_inventory("trash", {
--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()
-- else
-- return 0
@ -29,19 +29,19 @@ local trash = minetest.create_detached_inventory("trash", {
})
trash:set_size("main", 1)
unified_inventory.register_button("craft", {
ui.register_button("craft", {
type = "image",
image = "ui_craft_icon.png",
tooltip = S("Crafting Grid")
})
unified_inventory.register_button("craftguide", {
ui.register_button("craftguide", {
type = "image",
image = "ui_craftguide_icon.png",
tooltip = S("Crafting Guide")
})
unified_inventory.register_button("misc_set_day", {
ui.register_button("misc_set_day", {
type = "image",
image = "ui_sun_icon.png",
tooltip = S("Set time to day"),
@ -49,7 +49,7 @@ unified_inventory.register_button("misc_set_day", {
action = function(player)
local player_name = player:get_player_name()
if minetest.check_player_privs(player_name, {settime=true}) then
minetest.sound_play("birds",
minetest.sound_play("ui_morning",
{to_player=player_name, gain = 1.0})
minetest.set_timeofday((6000 % 24000) / 24000)
minetest.chat_send_player(player_name,
@ -57,7 +57,7 @@ unified_inventory.register_button("misc_set_day", {
else
minetest.chat_send_player(player_name,
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,
condition = function(player)
@ -65,7 +65,7 @@ unified_inventory.register_button("misc_set_day", {
end,
})
unified_inventory.register_button("misc_set_night", {
ui.register_button("misc_set_night", {
type = "image",
image = "ui_moon_icon.png",
tooltip = S("Set time to night"),
@ -73,7 +73,7 @@ unified_inventory.register_button("misc_set_night", {
action = function(player)
local player_name = player:get_player_name()
if minetest.check_player_privs(player_name, {settime=true}) then
minetest.sound_play("owl",
minetest.sound_play("ui_owl",
{to_player=player_name, gain = 1.0})
minetest.set_timeofday((21000 % 24000) / 24000)
minetest.chat_send_player(player_name,
@ -81,7 +81,7 @@ unified_inventory.register_button("misc_set_night", {
else
minetest.chat_send_player(player_name,
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,
condition = function(player)
@ -89,19 +89,19 @@ unified_inventory.register_button("misc_set_night", {
end,
})
unified_inventory.register_button("clear_inv", {
ui.register_button("clear_inv", {
type = "image",
image = "ui_trash_icon.png",
tooltip = S("Clear inventory"),
action = function(player)
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,
S("This button has been disabled outside"
.." of creative mode to prevent"
.." accidental inventory trashing."
.."\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
end
player:get_inventory():set_list("main", {})
@ -110,35 +110,42 @@ unified_inventory.register_button("clear_inv", {
{to_player=player_name, gain = 1.0})
end,
condition = function(player)
return unified_inventory.is_creative(player:get_player_name())
return ui.is_creative(player:get_player_name())
end,
})
unified_inventory.register_page("craft", {
ui.register_page("craft", {
get_formspec = function(player, perplayer_formspec)
local formspecy = perplayer_formspec.formspec_y
local formheadery = perplayer_formspec.form_header_y
local formheaderx = perplayer_formspec.form_header_x
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 formspec = "background[2,"..formspecy..";6,3;ui_crafting_form.png]"
formspec = formspec.."background[0,"..(formspecy + 3.5)..";8,4;ui_main_inventory.png]"
formspec = formspec.."label[0,"..formheadery..";" ..F(S("Crafting")).."]"
formspec = formspec.."listcolors[#00000000;#00000000]"
formspec = formspec.."list[current_player;craftpreview;6,"..formspecy..";1,1;]"
formspec = formspec.."list[current_player;craft;2,"..formspecy..";3,3;]"
if unified_inventory.trash_enabled or unified_inventory.is_creative(player_name) or minetest.get_player_privs(player_name).give then
formspec = formspec.."label[7,"..(formspecy + 1.5)..";" .. F(S("Trash:")) .. "]"
formspec = formspec.."background[7,"..(formspecy + 2)..";1,1;ui_single_slot.png]"
formspec = formspec.."list[detached:trash;main;7,"..(formspecy + 2)..";1,1;]"
local formspec = {
perplayer_formspec.standard_inv_bg,
perplayer_formspec.craft_grid,
"label["..formheaderx..","..formheadery..";" ..F(S("Crafting")).."]",
"listcolors[#00000000;#00000000]",
"listring[current_name;craft]",
"listring[current_player;main]"
}
local n=#formspec+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.35, crafty + 2.3, F(S("Trash:")))
formspec[n+1] = ui.make_trash_slot(craftx + 6.25, crafty + 2.5)
n=n + 2
end
formspec = formspec.."listring[current_name;craft]"
formspec = formspec.."listring[current_player;main]"
if unified_inventory.is_creative(player_name) then
formspec = formspec.."label[0,"..(formspecy + 1.5)..";" .. F(S("Refill:")) .. "]"
formspec = formspec.."list[detached:"..F(player_name).."refill;main;0,"..(formspecy +2)..";1,1;]"
if ui.is_creative(player_name) then
formspec[n] = ui.single_slot(craftx - 2.5, crafty + 2.5)
formspec[n+1] = string.format("label[%f,%f;%s]", craftx - 2.4, crafty + 2.3, F(S("Refill:")))
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
return {formspec=formspec}
return {formspec=table.concat(formspec)}
end,
})
@ -151,24 +158,26 @@ unified_inventory.register_page("craft", {
local function stack_image_button(x, y, w, h, buttonname_prefix, item)
local name = item:get_name()
local count = item:get_count()
local description = item:get_meta():get_string("description")
local show_is_group = false
local displayitem = name.." "..count
local displayitem = item:to_string()
local selectitem = name
if name:sub(1, 6) == "group:" then
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
displayitem = group_item.item or "unknown"
selectitem = group_item.sole and displayitem or name
end
local label = show_is_group and "G" or ""
local buttonname = F(buttonname_prefix..unified_inventory.mangle_for_formspec(selectitem))
-- Unique id to prevent tooltip being overridden
local id = string.format("%i%i_", x*10, y*10)
local buttonname = F(id..buttonname_prefix..ui.mangle_for_formspec(selectitem))
local button = string.format("item_image_button[%f,%f;%f,%f;%s;%s;%s]",
x, y, w, h,
F(displayitem), buttonname, label)
if show_is_group then
local groupstring, andcount = unified_inventory.extract_groupnames(name)
local groupstring, andcount = ui.extract_groupnames(name)
local grouptip
if andcount == 1 then
grouptip = S("Any item belonging to the @1 group", groupstring)
@ -179,10 +188,15 @@ local function stack_image_button(x, y, w, h, buttonname_prefix, item)
if andcount >= 1 then
button = button .. string.format("tooltip[%s;%s]", buttonname, grouptip)
end
elseif description ~= "" then
button = button .. string.format("tooltip[%s;%s]", buttonname, F(description))
end
return button
end
-- The recipe text contains parameters, hence they can yet not be translated.
-- Instead, use a dummy translation call so that it can be picked up by the
-- static parsing of the translation string update script
local recipe_text = {
recipe = NS("Recipe @1 of @2"),
usage = NS("Usage @1 of @2"),
@ -208,26 +222,33 @@ local other_dir = {
usage = "recipe",
}
unified_inventory.register_page("craftguide", {
ui.register_page("craftguide", {
get_formspec = function(player, perplayer_formspec)
local formspecy = perplayer_formspec.formspec_y
local formheadery = perplayer_formspec.form_header_y
local craftresultx = perplayer_formspec.craft_result_x
local craftresulty = perplayer_formspec.craft_result_y
local craftguidex = perplayer_formspec.craft_guide_x
local craftguidey = perplayer_formspec.craft_guide_y
local craftguidearrowx = perplayer_formspec.craft_guide_arrow_x
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_privs = minetest.get_player_privs(player_name)
local fs = {
"background[0,"..(formspecy + 3.5)..";8,4;ui_main_inventory.png]",
"label[0,"..formheadery..";" .. F(S("Crafting Guide")) .. "]",
local formspec = {
perplayer_formspec.standard_inv_bg,
"label["..formheaderx..","..formheadery..";" .. F(S("Crafting Guide")) .. "]",
"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
return { formspec = table.concat(fs) }
return { formspec = table.concat(formspec) }
end
local n = 4
local item_name_shown
if minetest.registered_items[item_name]
and minetest.registered_items[item_name].description then
@ -237,51 +258,60 @@ unified_inventory.register_page("craftguide", {
item_name_shown = item_name
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 crafts = unified_inventory.crafts_for[dir][item_name]
local alternate = unified_inventory.alternate[player_name]
local crafts = ui.crafts_for[dir][item_name]
local alternate = ui.alternate[player_name]
local alternates, craft
if crafts and #crafts > 0 then
alternates = #crafts
craft = crafts[alternate]
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]"
fs[#fs + 1] = string.format("textarea[%f,%f;10,1;;%s: %s;]",
craftresultx, craftresulty, F(role_text[dir]), item_name_shown)
fs[#fs + 1] = stack_image_button(0, formspecy, 1.1, 1.1,
"item_button_" .. rdir .. "_", ItemStack(item_name))
formspec[n] = string.format("image[%f,%f;%f,%f;ui_crafting_arrow.png]",
craftguidearrowx, craftguidey, ui.imgscale, ui.imgscale)
formspec[n+1] = string.format("textarea[%f,%f;10,1;;%s: %s;]",
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
-- No craft recipes available for this item.
fs[#fs + 1] = "label[5.5,"..(formspecy + 2.35)..";"
.. F(no_recipe_text[dir]) .. "]"
local no_pos = dir == "recipe" and 4.5 or 6.5
local item_pos = dir == "recipe" and 6.5 or 4.5
fs[#fs + 1] = "image["..no_pos..","..formspecy..";1.1,1.1;ui_no.png]"
fs[#fs + 1] = stack_image_button(item_pos, formspecy, 1.1, 1.1,
formspec[n] = string.format("label[%f,%f;%s]", craftguidex+2.5, craftguidey+1.5, F(no_recipe_text[dir]))
local no_pos = dir == "recipe" and (craftguidex+2.5) or craftguideresultx
local item_pos = dir == "recipe" and craftguideresultx or (craftguidex+2.5)
formspec[n+1] = "image["..no_pos..","..craftguidey..";1.2,1.2;ui_no.png]"
formspec[n+2] = stack_image_button(item_pos, craftguidey, 1.2, 1.2,
"item_button_" .. other_dir[dir] .. "_", ItemStack(item_name))
if has_give then
fs[#fs + 1] = "label[0," .. (formspecy + 2.10) .. ";" .. F(S("Give me:")) .. "]"
.. "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]"
formspec[n+3] = giveme_form
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
local craft_type = unified_inventory.registered_craft_types[craft.type] or
unified_inventory.craft_type_defaults(craft.type, {})
local craft_type = ui.registered_craft_types[craft.type] or
ui.craft_type_defaults(craft.type, {})
if craft_type.icon then
fs[#fs + 1] = string.format("image[%f,%f;%f,%f;%s]",
5.7, (formspecy + 0.05), 0.5, 0.5, craft_type.icon)
formspec[n] = string.format("image[%f,%f;%f,%f;%s]",
craftguidearrowx+0.35, craftguidey, 0.5, 0.5, craft_type.icon)
n = n + 1
end
fs[#fs + 1] = "label[5.5,"..(formspecy + 1)..";" .. F(craft_type.description).."]"
fs[#fs + 1] = stack_image_button(6.5, formspecy, 1.1, 1.1,
"item_button_usage_", ItemStack(craft.output))
formspec[n] = string.format("label[%f,%f;%s]", craftguidearrowx + 0.15, craftguidey + 1.4, F(craft_type.description))
n = n + 1
local display_size = craft_type.dynamic_display_size
and craft_type.dynamic_display_size(craft)
@ -292,11 +322,12 @@ unified_inventory.register_page("craftguide", {
-- This keeps recipes aligned to the right,
-- 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
local of = (3/math.max(3, math.max(display_size.width, display_size.height)))
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
if display_size.width >= mini_craft_size then
od = math.max(1, display_size.width - 2)
@ -305,12 +336,12 @@ unified_inventory.register_page("craftguide", {
-- Size modifier factor
local sf = math.min(1, of * (1.05 + 0.05*od))
-- Button size
local bsize_h = 1.1 * sf
local bsize_w = bsize_h
if display_size.width >= mini_craft_size then
bsize_w = 1.175 * sf
local bsize = 1.2 * sf
if display_size.width >= mini_craft_size then -- it's not a normal 3x3 grid
bsize = 0.8 * sf
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 x = 1, display_size.width do
local item
@ -320,48 +351,53 @@ unified_inventory.register_page("craftguide", {
-- Flipped x, used to build formspec buttons from right to left
local fx = display_size.width - (x-1)
-- x offset, y offset
local xof = (fx-1) * of + of
local yof = (y-1) * of + 1
local xof = ((fx-1) * of + of) * bspc
local yof = ((y-1) * of + 1) * bspc
if item then
fs[#fs + 1] = stack_image_button(
xoffset - xof, formspecy - 1 + yof, bsize_w, bsize_h,
formspec[n] = stack_image_button(
xoffset - xof, craftguidey - 1.25 + yof, bsize, bsize,
"item_button_recipe_",
ItemStack(item))
else
-- Fake buttons just to make grid
fs[#fs + 1] = string.format("image_button[%f,%f;%f,%f;ui_blank_image.png;;]",
xoffset - xof, formspecy - 1 + yof, bsize_w, bsize_h)
formspec[n] = string.format("image_button[%f,%f;%f,%f;ui_blank_image.png;;]",
xoffset - xof, craftguidey - 1.25 + yof, bsize, bsize)
end
n = n + 1
end
end
else
-- Error
fs[#fs + 1] = string.format("label[2,%f;%s]",
formspecy, F(S("This recipe is too@nlarge to be displayed.")))
formspec[n] = string.format("label[2,%f;%s]",
craftguidey, F(S("This recipe is too@nlarge to be displayed.")))
n = n + 1
end
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:")) .. "]"
.. "button[0, " .. (formspecy + 1.5) .. ";0.6,0.5;craftguide_craft_1;1]"
.. "button[0.6," .. (formspecy + 1.5) .. ";0.7,0.5;craftguide_craft_10;10]"
.. "button[1.3," .. (formspecy + 1.5) .. ";0.8,0.5;craftguide_craft_max;" .. F(S("All")) .. "]"
formspec[n] = "label["..(give_x+0.1)..",".. (craftguidey + 1.7) .. ";" .. F(S("To craft grid:")) .. "]"
formspec[n+1] = "button[".. (give_x)..",".. (craftguidey + 1.9) .. ";0.75,0.5;craftguide_craft_1;1]"
formspec[n+2] = "button[".. (give_x+0.8)..",".. (craftguidey + 1.9) .. ";0.75,0.5;craftguide_craft_10;10]"
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
if has_give then
fs[#fs + 1] = "label[0," .. (formspecy + 2.1) .. ";" .. F(S("Give me:")) .. "]"
.. "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]"
formspec[n] = giveme_form
n = n + 1
end
if alternates and alternates > 1 then
fs[#fs + 1] = "label[5.5," .. (formspecy + 1.6) .. ";"
.. F(S(recipe_text[dir], alternate, alternates)) .. "]"
.. "image_button[5.5," .. (formspecy + 2) .. ";1,1;ui_left_icon.png;alternate_prev;]"
.. "image_button[6.5," .. (formspecy + 2) .. ";1,1;ui_right_icon.png;alternate;]"
.. "tooltip[alternate_prev;" .. F(prev_alt_text[dir]) .. "]"
.. "tooltip[alternate;" .. F(next_alt_text[dir]) .. "]"
formspec[n] = string.format("label[%f,%f;%s]",
craftguidex+4, craftguidey + 2.3, F(S(recipe_text[dir], alternate, alternates)))
formspec[n+1] = string.format("image_button[%f,%f;1.1,1.1;ui_left_icon.png;alternate_prev;]",
craftguidearrowx+0.2, craftguidey + 2.6)
formspec[n+2] = string.format("image_button[%f,%f;1.1,1.1;ui_right_icon.png;alternate;]",
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
return { formspec = table.concat(fs) }
return { formspec = table.concat(formspec) }
end,
})
@ -369,7 +405,7 @@ local function craftguide_giveme(player, formname, fields)
local player_name = player:get_player_name()
local player_privs = minetest.get_player_privs(player_name)
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 " ..
player_name)
return
@ -384,7 +420,7 @@ local function craftguide_giveme(player, formname, fields)
amount = tonumber(amount) or 0
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
local player_inv = player:get_inventory()
@ -405,21 +441,29 @@ local function craftguide_craft(player, formname, fields)
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
local crafts = unified_inventory.crafts_for[
unified_inventory.current_craft_direction[player_name]][output] or {}
local crafts = ui.crafts_for[
ui.current_craft_direction[player_name]][output] or {}
if #crafts == 0 then return end
local alternate = unified_inventory.alternate[player_name]
local alternate = ui.alternate[player_name]
local craft = crafts[alternate]
if not craft.width then
if not craft.output then
minetest.log("warning", "[unified_inventory] Craft has no output.")
else
minetest.log("warning", ("[unified_inventory] Craft for '%s' has no width."):format(craft.output))
end
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
minetest.register_on_player_receive_fields(function(player, formname, fields)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 220 KiB

View File

@ -1,11 +1,32 @@
#Enabling lite mode enables a smaller and simpler version of the Unified
#Inventory, optimized for small displays.
# Reduced formspec layout, optimized for smaller displays.
# Note: This may also disable some features to free up visual space.
unified_inventory_lite (Lite mode) bool false
#If enabled, bags will be made available which can be used to extend
#inventory storage size.
# Provides craftable bag items to extend the inventory space.
unified_inventory_bags (Enable bags) bool true
#If enabled, the trash slot can be used by those without both creative
#and the give privilege.
# Shows the trash slot to everyone.
# When disabled, only players with the privilege "creative" or "give" will
# have this slot shown in their inventory.
unified_inventory_trash (Enable trash) bool true
# Provides waypoints on a per-player basis to remember positions on the map.
unified_inventory_waypoints (Enable waypoints) bool true
# If enabled, disabled buttons will be hidden instead of grayed out.
unified_inventory_hide_disabled_buttons (Hide disabled buttons) bool false
# Automatically categorizes registered items based on their
# groups. This is based on a fuzzy match, thus is not 100% accurate.
unified_inventory_automatic_categorization (Categories: add items automatically) bool true
# Shows the selected wielded item description in the HUD for a few seconds.
unified_inventory_item_names (Enable HUD item names) bool true
# Trims the shown wielded item description to the first line.
unified_inventory_only_names (HUD item name: first line only) bool true
# Hard character limit of the wielded item description.
# Crops the shown description to the specified length.
# 0 disables this functionality.
unified_inventory_max_item_name_length (HUD item names: character limit) int 80

Binary file not shown.

Binary file not shown.

BIN
sounds/ui_click.ogg Normal file

Binary file not shown.

BIN
sounds/ui_morning.ogg Normal file

Binary file not shown.

BIN
sounds/ui_owl.ogg Normal file

Binary file not shown.

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: 510 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: 551 B

BIN
textures/ui_teleport.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

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,7 @@
local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape
local ui = unified_inventory
local COUNT = 5
local hud_colors = {
{"#FFFFFF", 0xFFFFFF, S("White")},
@ -9,107 +11,212 @@ local hud_colors = {
{"#2c4df1", 0x2c4df1, S("Blue")},
}
local hud_colors_max = #hud_colors
-- Storage compatibility code
-- Stores temporary player data (persists until player leaves)
--[[
Stores temporary player data (persists until player leaves)
[player_name] = {
[<waypoint index>] = {
edit = <edit current waypoint?>,
hud = <hud ID>,
},
[<waypoint index>] = { ... },
...
}
]]
local waypoints_temp = {}
unified_inventory.register_page("waypoints", {
--[[
Datastorage format (per-player):
{
selected = <waypoint index>,
[<waypoint index>] = {
name = <name or nil>
world_pos = <coordinates vector>,
color = <"hud_colors" index>,
active = <hud show waypoint?>,
display_pos = <hud display coorinates?>,
},
[<waypoint index>] = { ... },
...
}
Player metadata format:
{
selected = <selected number>,
-- Cannot mix integer/string keys in JSON
data = {
[<waypoint index>] = { same as above },
...
}
}
]]
local function set_waypoint_data(player, waypoints)
local meta = player:get_meta()
if not next(waypoints.data or {}) then
-- Empty data. Do not save anything, or delete
meta:set_string("ui_waypoints", "")
else
meta:set_string("ui_waypoints", minetest.write_json(waypoints))
end
end
local function migrate_datastorage(player, waypoints)
-- Copy values from old table
local new_data = {
selected = waypoints.selected,
data = {}
}
for i = 1, COUNT do
new_data.data[i] = waypoints[i]
end
set_waypoint_data(player, new_data)
-- Delete values, but keep one entry so that it's saved by datastorage
for k, _ in pairs(waypoints) do
waypoints[k] = nil
end
waypoints[1] = 1
end
local have_datastorage = minetest.get_modpath("datastorage") ~= nil
local function get_waypoint_data(player)
local player_name = player:get_player_name()
-- Migration step
if have_datastorage then
local waypoints = datastorage.get(player_name, "waypoints")
if waypoints.selected then
migrate_datastorage(player, waypoints)
minetest.log("action", "[unified_inventory] " ..
"Migrated waypoints of player: " .. player_name)
end
end
-- Get directly from metadata
local waypoints = player:get_meta():get("ui_waypoints")
waypoints = waypoints and minetest.parse_json(waypoints) or {}
waypoints.data = waypoints.data or {}
return waypoints
end
ui.register_page("waypoints", {
get_formspec = function(player)
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
-- during sign-on and returned an empty entry
if not waypoints_temp[player_name] then waypoints_temp[player_name] = {hud = 1} end
local waypoints = get_waypoint_data(player)
local sel = waypoints.selected or 1
local waypoints = datastorage.get(player_name, "waypoints")
local formspec = "background[0,4.5;8,4;ui_main_inventory.png]" ..
"image[0,0;1,1;ui_waypoints_icon.png]" ..
"label[1,0;" .. F(S("Waypoints")) .. "]"
local formspec = {
ui.style_full.standard_inv_bg,
string.format("label[%f,%f;%s]",
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:
for i = 1, 5, 1 do
formspec = formspec ..
"image_button[0.0," .. 0.2 + i * 0.7 .. ";.8,.8;" ..
(i == waypoints.selected and "ui_blue_icon_background.png^" or "") ..
"ui_" .. i .. "_icon.png;" ..
"select_waypoint" .. i .. ";]" ..
"tooltip[select_waypoint" .. i .. ";"
.. S("Select Waypoint #@1", i).."]"
for i = 1, COUNT do
local sw="select_waypoint"..i
formspec[n] = string.format("image_button[%f,%f;%f,%f;%sui_%i_icon.png;%s;]",
ui.style_full.main_button_x, wp_bottom_row - (5-i) * ui.style_full.btn_spc,
ui.style_full.btn_size, ui.style_full.btn_size,
(i == sel) and "ui_blue_icon_background.png^" or "",
i, sw)
formspec[n+1] = "tooltip["..sw..";"..S("Select Waypoint #@1", i).."]"
n = n + 2
end
local i = waypoints.selected or 1
local waypoint = waypoints[i] or {}
local temp = waypoints_temp[player_name][i] or {}
local default_name = S("Waypoint @1", i)
local waypoint = waypoints.data[sel] or {}
local temp = waypoints_temp[player_name][sel] or {}
local default_name = S("Waypoint @1", sel)
-- Main buttons:
formspec = formspec ..
"image_button[4.5,3.7;.8,.8;"..
"ui_waypoint_set_icon.png;"..
"set_waypoint"..i..";]"..
"tooltip[set_waypoint" .. i .. ";"
.. F(S("Set waypoint to current location")).."]"
local btnlist = {
-- 1. formspec name
-- 2. button image
-- 3. translation text
{
"toggle_waypoint",
waypoint.active and "ui_on_icon.png" or "ui_off_icon.png",
waypoint.active and S("Hide waypoint") or S("Show waypoint")
},
{
"rename_waypoint",
"ui_pencil_icon.png",
S("Edit waypoint name")
},
{
"set_waypoint",
"ui_waypoint_set_icon.png",
S("Set waypoint to current location")
},
{
"toggle_display_pos",
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)",
waypoint.display_pos and S("Hide coordinates") or S("Show coordinates")
},
{
"toggle_color",
"ui_circular_arrows_icon.png",
S("Change color of waypoint display")
},
}
if minetest.get_player_privs(player_name).teleport then
table.insert(btnlist, {
"teleport_waypoint",
"ui_teleport.png",
S("Teleport to waypoint")
})
end
formspec = formspec ..
"image_button[5.2,3.7;.8,.8;"..
(waypoint.active and "ui_on_icon.png" or "ui_off_icon.png")..";"..
"toggle_waypoint"..i..";]"..
"tooltip[toggle_waypoint" .. i .. ";"
.. F(S("Make waypoint @1",
waypoint.active and S("invisible") or S("visible"))).."]"
formspec = formspec ..
"image_button[5.9,3.7;.8,.8;"..
(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")).."]"
for i, def in pairs(btnlist) do
formspec[n] = string.format("image_button[%f,%f;%f,%f;%s;%s%i;]",
wp_buttons_rj + ui.style_full.btn_spc * (i - #btnlist), wp_bottom_row,
ui.style_full.btn_size, ui.style_full.btn_size,
def[2], def[1], sel)
formspec[n+1] = "tooltip["..def[1]..sel..";"..F(def[3]).."]"
n = n + 2
end
-- Waypoint's info:
if waypoint.active then
formspec = formspec .. "label[1,0.8;"..F(S("Waypoint active")).."]"
else
formspec = formspec .. "label[1,0.8;"..F(S("Waypoint inactive")).."]"
end
formspec[n] = ("label[%f,%f;%s]"):format(
wp_info_x, wp_info_y + 1.1,
F(waypoint.active and S("Waypoint active") or S("Waypoint inactive"))
)
n = n + 1
if temp.edit then
formspec = formspec ..
"field[1.3,3.2;6,.8;rename_box" .. i .. ";;"
..(waypoint.name or default_name).."]" ..
"image_button[7.3,2.9;.8,.8;"..
"ui_ok_icon.png;"..
"confirm_rename"..i.. ";]"..
"tooltip[confirm_rename" .. i .. ";"
.. F(S("Finish editing")).."]"
formspec[n] = string.format("field[%f,%f;%f,%f;rename_box%i;;%s]",
wp_buttons_rj - wp_edit_w - 0.1, wp_bottom_row - ui.style_full.btn_spc,
wp_edit_w, ui.style_full.btn_size, sel, (waypoint.name or default_name))
formspec[n+1] = string.format("image_button[%f,%f;%f,%f;ui_ok_icon.png;confirm_rename%i;]",
wp_buttons_rj, wp_bottom_row - ui.style_full.btn_spc,
ui.style_full.btn_size, ui.style_full.btn_size, sel)
formspec[n+2] = "tooltip[confirm_rename"..sel..";"..F(S("Finish editing")).."]"
n = n + 3
end
formspec = formspec .. "label[1,1.3;"..F(S("World position"))..": " ..
minetest.pos_to_string(waypoint.world_pos or vector.new()) .. "]" ..
"label[1,1.8;"..F(S("Name"))..": ".. (waypoint.name or default_name) .. "]" ..
"label[1,2.3;"..F(S("HUD text color"))..": " ..
hud_colors[waypoint.color or 1][3] .. "]"
formspec[n] = string.format("label[%f,%f;%s: %s]",
wp_info_x, wp_info_y+1.6, F(S("World position")),
minetest.pos_to_string(waypoint.world_pos or vector.new()))
formspec[n+1] = string.format("label[%f,%f;%s: %s]",
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,
})
unified_inventory.register_button("waypoints", {
ui.register_button("waypoints", {
type = "image",
image = "ui_waypoints_icon.png",
tooltip = S("Waypoints"),
@ -117,10 +224,12 @@ unified_inventory.register_button("waypoints", {
})
local function update_hud(player, waypoints, temp, i)
local waypoint = waypoints[i]
local waypoint = waypoints.data[i]
if not waypoint then return end
temp[i] = temp[i] or {}
temp = temp[i]
local pos = waypoint.world_pos or vector.new()
local name
if waypoint.display_pos then
@ -129,10 +238,13 @@ local function update_hud(player, waypoints, temp, i)
name = name..", "..waypoint.name
end
else
name = waypoint.name or "Waypoint "..i
name = waypoint.name or S("Waypoint @1", i)
end
-- Perform HUD updates
if temp.hud then
player:hud_remove(temp.hud)
temp.hud = nil
end
if waypoint.active then
temp.hud = player:hud_add({
@ -142,8 +254,6 @@ local function update_hud(player, waypoints, temp, i)
text = "m",
world_pos = pos
})
else
temp.hud = nil
end
end
@ -155,9 +265,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local need_update_hud = false
local hit = false
local waypoints = datastorage.get(player_name, "waypoints")
local waypoints = get_waypoint_data(player)
local temp = waypoints_temp[player_name]
for i = 1, 5, 1 do
for i = 1, COUNT do
local waypoint = waypoints.data[i] or {}
if fields["select_waypoint"..i] then
hit = true
waypoints.selected = i
@ -166,20 +278,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields["toggle_waypoint"..i] then
hit = true
waypoints[i] = waypoints[i] or {}
waypoints[i].active = not (waypoints[i].active)
waypoint.active = not (waypoint.active)
need_update_hud = true
update_formspec = true
end
if fields["set_waypoint"..i] then
hit = true
local pos = player:get_pos()
pos.x = math.floor(pos.x)
pos.y = math.floor(pos.y)
pos.z = math.floor(pos.z)
waypoints[i] = waypoints[i] or {}
waypoints[i].world_pos = pos
local pos = vector.round(player:get_pos())
waypoint.world_pos = pos
need_update_hud = true
update_formspec = true
end
@ -193,51 +300,66 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields["toggle_display_pos"..i] then
hit = true
waypoints[i] = waypoints[i] or {}
waypoints[i].display_pos = not waypoints[i].display_pos
waypoint.display_pos = not waypoint.display_pos
need_update_hud = true
update_formspec = true
end
if fields["toggle_color"..i] then
hit = true
waypoints[i] = waypoints[i] or {}
local color = waypoints[i].color or 1
local color = waypoint.color or 0
color = color + 1
if color > hud_colors_max then
if color > #hud_colors then
color = 1
end
waypoints[i].color = color
waypoint.color = color
need_update_hud = true
update_formspec = true
end
if fields["confirm_rename"..i] then
hit = true
waypoints[i] = waypoints[i] or {}
temp[i] = temp[i] or {}
temp[i].edit = false
waypoints[i].name = fields["rename_box"..i]
waypoint.name = fields["rename_box"..i]
need_update_hud = true
update_formspec = true
end
if fields["teleport_waypoint" .. i] and waypoint.world_pos then
if minetest.get_player_privs(player_name).teleport then
minetest.sound_play("teleport", {to_player = player_name})
player:set_pos(waypoint.world_pos)
end
end
if hit then
-- Save first
waypoints.data[i] = waypoint
set_waypoint_data(player, waypoints)
end
-- Update after
if need_update_hud then
update_hud(player, waypoints, temp, i)
end
if update_formspec then
unified_inventory.set_inventory_formspec(player, "waypoints")
minetest.sound_play("ui_click", {to_player=player_name, gain = 0.1})
ui.set_inventory_formspec(player, "waypoints")
end
if hit then return end
end
end)
minetest.register_on_joinplayer(function(player)
-- waypoints_temp must be initialized before the general unified_inventory
-- joinplayer callback is run for updating the inventory
table.insert(minetest.registered_on_joinplayers, 1, function(player)
local player_name = player:get_player_name()
local waypoints = datastorage.get(player_name, "waypoints")
local temp = {}
waypoints_temp[player_name] = temp
for i = 1, 5 do
update_hud(player, waypoints, temp, i)
local waypoints = get_waypoint_data(player)
waypoints_temp[player_name] = {}
for i = 1, COUNT do
update_hud(player, waypoints, waypoints_temp[player_name], i)
end
end)