i3 insted of smart inventory is used - forced minetest 5.4

master
daretmavi 2021-02-25 00:24:30 +01:00
parent 0650944b19
commit bd90f181c2
110 changed files with 3924 additions and 7649 deletions

View File

@ -11,7 +11,7 @@ DST="$PROJ"/mods/ # Game mods dir
#copy files
MOD_PATH=("player/skinsdb" "gui/smart_inventory" "mobs/mobs_mobkit/petz/petz") #temporary not used: "minetest_game"
MOD_PATH=("player/skinsdb" "mobs/mobs_mobkit/petz/petz") #temporary not used: "minetest_game"
for MOD_INDEX in ${!MOD_PATH[*]}
do

View File

@ -1,2 +1,2 @@
name = A Planet Alive
min_minetest_version = 5.3
min_minetest_version = 5.4

22
mods/gui/i3/.luacheckrc Normal file
View File

@ -0,0 +1,22 @@
allow_defined_top = true
ignore = {
"get_debug_grid",
}
read_globals = {
"minetest",
"default",
"armor",
"skins",
"awards",
"vector",
"string",
"table",
"ItemStack",
}
globals = {
"i3",
"core",
}

262
mods/gui/i3/API.md Normal file
View File

@ -0,0 +1,262 @@
## API
### Custom tabs
#### `i3.new_tab(def)`
Custom tabs can be added to the `i3` inventory as follow (example):
```Lua
i3.new_tab {
name = "stuff",
description = "Stuff",
image = "image.png", -- Optional, adds an image next to the tab description
-- Determine if the tab is visible by a player, `false` or `nil` hide the tab
access = function(player, data)
local name = player:get_player_name()
if name == "singleplayer" then
return false
end
end,
formspec = function(player, data, fs)
fs("label[3,1;This is just a test]")
end,
fields = function(player, data, fields)
end,
-- Determine if the recipe panels must be hidden or not (must return a boolean)
hide_panels = function(player, data)
local name = player:get_player_name()
return core.is_creative_enabled(name)
end,
}
```
- `player` is an `ObjectRef` to the user.
- `data` are the user data.
- `fs` is the formspec table which is callable with a metamethod. Each call adds a new entry.
#### `i3.set_fs(player[, extra_formspec])`
Updates the current formspec. `extra_formspec` adds an additional formspec string.
#### `i3.delete_tab(tabname)`
Deletes a tab by name.
#### `i3.set_tab(player[, tabname])`
Sets the current tab by name. `player` is an `ObjectRef` to the user.
`tabname` can be omitted to get an empty tab.
#### `i3.override_tab(tabname, def)`
Overrides a tab by name. `def` is the tab definition like seen in `i3.set_tab`.
#### `i3.get_tabs()`
Returns the list of registered tabs.
---
### Custom recipes
Custom recipes are nonconventional crafts outside the main crafting grid.
They can be registered in-game dynamically and have a size beyond 3x3 items.
**Note:** the registration format differs from the default registration format in everything.
The width is automatically calculated depending where you place the commas. Look at the examples attentively.
#### Registering a custom crafting type (example)
```Lua
i3.register_craft_type("digging", {
description = "Digging",
icon = "default_tool_steelpick.png",
})
```
#### Registering a custom crafting recipe (examples)
```Lua
i3.register_craft({
type = "digging",
result = "default:cobble 2",
items = {"default:stone"},
})
```
```Lua
i3.register_craft({
result = "default:cobble 16",
items = {
"default:stone, default:stone, default:stone",
"default:stone, , default:stone",
"default:stone, default:stone, default:stone",
}
})
```
Recipes can be registered in a Minecraft-like way:
```Lua
i3.register_craft({
grid = {
"X #",
" ## ",
"X#X#",
"X X",
},
key = {
['#'] = "default:wood",
['X'] = "default:glass",
},
result = "default:mese 3",
})
```
Multiples recipes can also be registered:
```Lua
i3.register_craft({
{
result = "default:mese",
items = {
"default:mese_crystal, default:mese_crystal",
"default:mese_crystal, default:mese_crystal",
}
},
big = {
result = "default:mese 4",
items = {
"default:mese_crystal, default:mese_crystal",
"default:mese_crystal, default:mese_crystal",
"default:mese_crystal, default:mese_crystal",
"default:mese_crystal, default:mese_crystal",
}
},
})
```
Recipes can be registered from a given URL containing a JSON file (HTTP support is required¹):
```Lua
i3.register_craft({
url = "https://raw.githubusercontent.com/minetest-mods/i3/main/test_online_recipe.json"
})
```
---
### Recipe filters
Recipe filters can be used to filter the recipes shown to players. Progressive
mode is implemented as a recipe filter.
#### `i3.add_recipe_filter(name, function(recipes, player))`
Adds a recipe filter with the given `name`. The filter function returns the
recipes to be displayed, given the available recipes and an `ObjectRef` to the
user. Each recipe is a table of the form returned by
`minetest.get_craft_recipe`.
Example function to hide recipes for items from a mod called "secretstuff":
```lua
i3.add_recipe_filter("Hide secretstuff", function(recipes)
local filtered = {}
for _, recipe in ipairs(recipes) do
if recipe.output:sub(1,12) ~= "secretstuff:" then
filtered[#filtered + 1] = recipe
end
end
return filtered
end)
```
#### `i3.set_recipe_filter(name, function(recipe, player))`
Removes all recipe filters and adds a new one.
#### `i3.delete_recipe_filter(name)`
Removes the recipe filter with the given `name`.
#### `i3.get_recipe_filters()`
Returns a map of recipe filters, indexed by name.
---
### Search filters
Search filters are used to perform specific searches inside the search field.
These filters are cumulative to perform a specific search.
They can be used like so: `<optional_name> +<filter name>=<value1>,<value2>,<...>`
Example usages:
- `+groups=cracky,crumbly`: search for groups `cracky` and `crumbly` in all items.
- `wood +groups=flammable +types=node`: search for group `flammable` amongst items which contain
`wood` in their names AND have a `node` drawtype.
Notes:
- If `optional_name` is omitted, the search filter will apply to all items, without pre-filtering.
- The `+groups` and `+types` filters are currently implemented by default.
#### `i3.add_search_filter(name, function(item, values))`
Adds a search filter with the given `name`. `values` is a table of all possible values.
The search function must return a boolean value (whether the given item should be listed or not).
Example function sorting items by drawtype:
```lua
i3.add_search_filter("types", function(item, drawtypes)
local t = {}
for i, dt in ipairs(drawtypes) do
t[i] = (dt == "node" and reg_nodes[item] and 1) or
(dt == "item" and reg_craftitems[item] and 1) or
(dt == "tool" and reg_tools[item] and 1) or nil
end
return #t > 0
end)
```
#### `i3.remove_search_filter(name)`
Removes the search filter with the given `name`.
#### `i3.get_search_filters()`
Returns a map of search filters, indexed by name.
---
### Miscellaneous
#### `i3.group_stereotypes`
This is the table indexing the item groups by stereotypes.
You can add a stereotype like so:
```Lua
i3.group_stereotypes.radioactive = "mod:item"
```
#### `i3.export_url`
If set, the mod will export all the cached recipes and usages in a JSON format
to the given URL (HTTP support is required¹).
---
**¹** Add `i3` to the `secure.http_mods` or `secure.trusted_mods` setting in `minetest.conf`.

60
mods/gui/i3/LICENSE Normal file
View File

@ -0,0 +1,60 @@
License of source code
----------------------
The MIT License (MIT)
Copyright (c) 2020-2021 Jean-Patrick Guerrero and contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Licenses of media (textures)
----------------------------
paramat (CC BY-SA 3.0):
i3_arrow.png - derived from a texture by BlockMen (CC BY-SA 3.0)
i3_hotbar.png
You are free to:
Share — copy and redistribute the material in any medium or format.
Adapt — remix, transform, and build upon the material for any purpose, even commercially.
The licensor cannot revoke these freedoms as long as you follow the license terms.
Under the following terms:
Attribution — You must give appropriate credit, provide a link to the license, and
indicate if changes were made. You may do so in any reasonable manner, but not in any way
that suggests the licensor endorses you or your use.
ShareAlike — If you remix, transform, or build upon the material, you must distribute
your contributions under the same license as the original.
No additional restrictions — You may not apply legal terms or technological measures that
legally restrict others from doing anything the license permits.
Notices:
You do not have to comply with the license for elements of the material in the public
domain or where your use is permitted by an applicable exception or limitation.
No warranties are given. The license may not give you all of the permissions necessary
for your intended use. For example, other rights such as publicity, privacy, or moral
rights may limit how you use the material.
For more details:
http://creativecommons.org/licenses/by-sa/3.0/

50
mods/gui/i3/README.md Normal file
View File

@ -0,0 +1,50 @@
# i3
[![ContentDB](https://content.minetest.net/packages/jp/i3/shields/title/)](https://content.minetest.net/packages/jp/i3/) [![ContentDB](https://content.minetest.net/packages/jp/i3/shields/downloads/)](https://content.minetest.net/packages/jp/i3/)
#### **`i3`** is a next-generation inventory for Minetest.
This inventory offers a slick, modern UI made with the latest technologies of the Minetest engine.
**`i3`** provides a rich [**API**](https://github.com/minetest-mods/i3/blob/master/API.md) for mod developers who want to extend it.
This mod requires **Minetest 5.4+**
#### List of features:
- Crafting Guide (only in survival mode)
- Progressive Mode¹
- Quick Crafting
- Backpacks
- 3D Player Model Preview
- Inventory Sorting (alphabetical + item stack compression)
- Item Bookmarks
**¹** *This mode is a Terraria-like system that shows recipes you can craft from items you ever had in your inventory.
To enable it: `i3_progressive_mode = true` in `minetest.conf`.*
#### This mod officially supports the following mods:
- [**`3d_armor`**](https://content.minetest.net/packages/stu/3d_armor/)
- [**`skinsdb`**](https://content.minetest.net/packages/bell07/skinsdb/)
- [**`awards`**](https://content.minetest.net/packages/rubenwardy/awards/)
#### Recommendations
To use this mod in the best conditions, it's recommended to follow these recommendations:
- Use LuaJIT
- Use a HiDPI widescreen display
- Use the default Freetype font style
#### Notes
`i3` uses a larger inventory than the usual inventories in Minetest games.
Thus, most chests will be unadapted to this inventory size.
The `i3` inventory is 9 slots wide by default (without backpack), such as in Minecraft.
Report any bug on the [**Bug Tracker**](https://github.com/minetest-mods/i3/issues).
Love this mod? Donations are appreciated: https://www.paypal.me/jpg84240
Demo video: https://www.youtube.com/watch?v=25nCAaqeacU
![Preview](https://user-images.githubusercontent.com/7883281/109045805-4f450600-76d4-11eb-90f7-b99ab939246a.png)

3138
mods/gui/i3/init.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,85 @@
# textdomain: i3
### init.lua ###
@1 added in your inventory=@1 ajouté à votre inventaire
@1 new recipe(s) discovered!=@1 nouvelle(s) recette(s) découverte(s)!
@1 of chance to drop=@1 de chance de tomber
@1 spawned=@1 spawné
Achievements: @1 of @2 (@3)=Succès : @1 sur @2 (@3)
Any black dye=N'importe quel colorant noir
Any black flower=N'importe quelle fleur noire
Any blue dye=N'importe quel colorant bleu
Any blue flower=N'importe quelle fleur bleue
Any brown dye=N'importe quel colorant marron
Any carpet=N'importe quel tapis
Any coal=N'importe quel charbon
Any cyan dye=N'importe quel colorant bleu turquoise
Any dark green dye=N'importe quel colorant vert foncé
Any dark grey dye=N'importe quel colorant gris foncé
Any dye=N'importe quel colorant
Any flower=N'importe quelle fleur
Any glass=N'importe quel verre
Any green dye=N'importe quel colorant vert
Any green flower=N'importe quelle fleur verte
Any grey dye=N'importe quel colorant gris
Any item belonging to the groups: @1=Tout item appartenant aux groupes : @1
Any leaves=N'importe quelles feuilles d'arbre
Any magenta dye=N'importe quel colorant mauve
Any mushroom=N'importe quel champignon
Any orange dye=N'importe quel colorant orange
Any orange flower=N'importe quelle fleur orange
Any pink dye=N'importe quel colorant rose
Any red dye=N'importe quel colorant rouge
Any red flower=N'importe quelle fleur rouge
Any sand=N'importe quel sable
Any stick=N'importe quel bâton
Any stone=N'importe quelle roche
Any tree=N'importe quel tronc d'arbre
Any vessel=N'importe quel couvert
Any violet dye=N'importe quel colorant violet
Any violet flower=N'importe quelle fleur violette
Any white dye=N'importe quel colorant blanc
Any white flower=N'importe quelle fleur blanche
Any wood planks=N'importe quelles planches de bois
Any wool=N'importe quelle laine
Any yellow dye=N'importe quel colorant jaune
Any yellow flower=N'importe quelle fleur jaune
Armor=Armure
Bag=Sac
Bookmarks=Favoris
Burning time: @1=Temps de combustion : @1
Cannot mark this item. Bookmark limit reached.=
Collect items to reveal more recipes=Collecter des items pour révéler des recettes
Compress items=Compresser les items
Cooking=Cuisson
Cooking time: @1=Temps de cuisson : @1
Craft (x@1)=Fabriquer (x@1)
Digging=Minage
Digging (by chance)=Minage (par chance)
Heal=Guérison
Inventory=Inventaire
Items=Items
Level=Niveau
Mark this item=Ajouter aux favoris
No item to show=Aucun item à montrer
No recipes=Aucune recette
No usages=Aucun usage
Only drop if using one of these tools: @1=Tombe seulement en utilisant un de ces outils : @1
Only drop if using this tool: @1=Tombe seulement en utilisant cet outil : @1
Quick crafting=Fabrication rapide
Recipe @1 of @2=Recette @1 sur @2
Repairable by step of @1=Réparable par étape de @1
Replaced by @1 on burning=Remplacé par @1 à la combustion
Replaced by @1 on crafting=Remplacé par @1 à la fabrication
Replaced by @1 on smelting=Remplacé par @1 à la cuisson
Shapeless=Sans forme particulière
Skins=Skins
Sort items (A-Z)=Trier les items (A-Z)
Sort items (Z-A)=Trier les items (Z-A)
The inventory is extended by @1 slots=L'inventaire est étendu de @1 slots
Trash all items=Détruire tous les items
Unknown Item (@1)=Item inconnu (@1)
Unmark this item=Enlever des favoris
Usage @1 of @2=Usage @1 sur @2

View File

@ -0,0 +1,84 @@
# textdomain: i3
### init.lua ###
@1 added in your inventory=
@1 new recipe(s) discovered!=
@1 of chance to drop=
@1 spawned=
Achievements: @1 of @2 (@3)=
Any black dye=
Any black flower=
Any blue dye=
Any blue flower=
Any brown dye=
Any carpet=
Any coal=
Any cyan dye=
Any dark green dye=
Any dark grey dye=
Any dye=
Any flower=
Any glass=
Any green dye=
Any green flower=
Any grey dye=
Any item belonging to the groups: @1=
Any leaves=
Any magenta dye=
Any mushroom=
Any orange dye=
Any orange flower=
Any pink dye=
Any red dye=
Any red flower=
Any sand=
Any stick=
Any stone=
Any tree=
Any vessel=
Any violet dye=
Any violet flower=
Any white dye=
Any white flower=
Any wood planks=
Any wool=
Any yellow dye=
Any yellow flower=
Armor=
Bag=
Bookmarks=
Burning time: @1=
Cannot mark this item. Bookmark limit reached.=
Collect items to reveal more recipes=
Compress items=
Cooking=
Cooking time: @1=
Craft (x@1)=
Digging=
Digging (by chance)=
Heal=
Inventory=
Items=
Level=
Mark this item=
No item to show=
No recipes=
No usages=
Only drop if using one of these tools: @1=
Only drop if using this tool: @1=
Quick crafting=
Recipe @1 of @2=
Repairable by step of @1=
Replaced by @1 on burning=
Replaced by @1 on crafting=
Replaced by @1 on smelting=
Shapeless=
Skins=
Sort items (A-Z)=
Sort items (Z-A)=
The inventory is extended by @1 slots=
Trash all items=
Unknown Item (@1)=
Unmark this item=
Usage @1 of @2=

3
mods/gui/i3/mod.conf Normal file
View File

@ -0,0 +1,3 @@
name = i3
description = Tiling inventory for Minetest
optional_depends = 3d_armor, skinsdb, awards

View File

@ -0,0 +1,2 @@
# The progressive mode shows recipes you can craft from items you ever had in your inventory.
i3_progressive_mode (Learn crafting recipes progressively) bool false

BIN
mods/gui/i3/sounds/i3_click.ogg Executable file

Binary file not shown.

BIN
mods/gui/i3/sounds/i3_craft.ogg Executable file

Binary file not shown.

BIN
mods/gui/i3/sounds/i3_tab.ogg Executable file

Binary file not shown.

View File

@ -0,0 +1,159 @@
i3.register_craft({
grid = {
"X #",
" ## ",
"X#X#",
"X X",
},
key = {
['#'] = "default:wood",
['X'] = "default:glass",
},
result = "default:mese 3",
})
i3.register_craft({
grid = {
"X #",
" ## ",
"X#X#X",
"X X",
},
key = {
['#'] = "default:wood",
['X'] = "default:glass",
},
result = "default:mese 3",
})
i3.register_craft({
grid = {
"X #",
" ## ",
"X#X#",
"#X#X#",
"X X",
},
key = {
['#'] = "default:wood",
['X'] = "default:glass",
},
result = "default:mese 3",
})
i3.register_craft({
grid = {
"X #",
" ## ",
"X#X#",
"#X#X#",
"X X##",
},
key = {
['#'] = "default:wood",
['X'] = "default:glass",
},
result = "default:mese 3",
})
i3.register_craft({
grid = {
"X #",
" ## ",
"X#X#",
"#X#X#",
"X X##",
" ## ",
},
key = {
['#'] = "default:wood",
['X'] = "default:glass",
},
result = "default:mese 3",
})
i3.register_craft({
grid = {
"X #",
" ## ",
"X#X#",
"#X#X#",
"X X##X",
" ## ",
},
key = {
['#'] = "default:wood",
['X'] = "default:glass",
},
result = "default:mese 3",
})
i3.register_craft({
grid = {
"X #",
" ## ",
"X#X#",
"#X#X#",
"X X##X#",
" ## ",
},
key = {
['#'] = "default:wood",
['X'] = "default:glass",
},
result = "default:mese 3",
})
i3.register_craft({
grid = {
"X #",
" ## ",
"X#X#",
"#X#X#",
"X X##X#X",
" ## ",
},
key = {
['#'] = "default:wood",
['X'] = "default:glass",
},
result = "default:mese 3",
})
i3.register_craft({
grid = {
"X #",
" ## ",
"X#X#",
"#X#X#",
"X X##X#X",
" ## ",
"#X#X#",
"#X#X#",
},
key = {
['#'] = "default:wood",
['X'] = "default:glass",
},
result = "default:mese 3",
})
i3.register_craft({
grid = {
"X #",
" ## ",
"X#X#",
"#X#X#",
"X X##X#X",
" ## ",
"#X#X#",
"#X#X#",
"X #",
},
key = {
['#'] = "default:wood",
['X'] = "default:glass",
},
result = "default:mese 3",
})

View File

@ -0,0 +1,8 @@
{
"items": [
"default:stone, default:stone, default:stone",
"default:stone, , default:stone",
"default:stone, default:stone, default:stone"
],
"result": "default:cobble 16"
}

49
mods/gui/i3/test_tabs.lua Normal file
View File

@ -0,0 +1,49 @@
i3.new_tab {
name = "test1",
description = "Test 1 Test 1",
image = "i3_heart.png",
formspec = function(player, data, fs)
fs("label[3,1;Test 1]")
end,
}
i3.new_tab {
name = "test2",
description = "Test 2",
image = "i3_mesepick.png",
formspec = function(player, data, fs)
fs("label[3,1;Test 2]")
end,
}
i3.new_tab {
name = "test3",
description = "Test 3",
access = function(player, data)
local name = player:get_player_name()
if name == "singleplayer" then
return true
end
end,
formspec = function(player, data, fs)
fs("label[3,1;Test 3]")
end,
fields = function(player, data, fields)
i3.set_fs(player, "label[3,2;Test extra_fs]")
end,
}
i3.override_tab("test2", {
name = "test2",
description = "Test override",
image = "i3_mesepick.png",
formspec = function(player, data, fs)
fs("label[3,1;Override!]")
end,
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 950 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,99 +0,0 @@
# API definition to working together with smart_inventory
## Pages framework
### Register page
To get own page in smart_inventory the next register method should be used
```
smart_inventory.register_page({
name = string,
icon = string,
label = string,
tooltip = string,
smartfs_callback = function,
sequence = number,
on_button_click = function,
is_visible_func = function,
})
```
- name - unique short name, used for identification
- icon - Image displayed on page button. Optional
- label - Label displayed on page button. Optional
- tooltip - Text displayed at mouseover on the page button. Optional
- smartfs_callback(state) - smartfs callback function See [smartfs documentation](https://github.com/minetest-mods/smartfs/blob/master/docs) and existing pages implementations for reference.
- sequence - The buttons are sorted by this number (crafting=10, creative=15, player=20)
- on_button_click(state) - function called each page button click
- is_visible_func(state) - function for dynamic page enabelling. Should return bool value.
### Get the definition for registered smart_inventory page
```smart_inventory.get_registered_page(pagename)```
### Get smartfs state for players inventory
```smart_inventory.get_player_state(playername)```
Get the root smartfs state for players inventory. Note: In workbench mode the function return nil if the player does not have the form open
### Get smartfs state for a registered page in players inventory
```smart_inventory.get_page_state(pagename, playername)```
## Filter framework
Smart_inventory uses a filter-framework for dynamic grouping in creative and crafting page. The filter framework allow to register additional classify filters for beter dynamic grouping results.
Maybe the framework will be moved to own mod in the feature if needed. Please note the smart_inventory caches all results at init time so static groups only allowed. The groups will not be re-checked at runtime.
### Register new filter
```
smart_inventory.filter.register_filter({
name = string,
check_item_by_def = function,
get_description = function,
get_keyword = function,
is_valid = function,
})
```
- name - unique filter name
- check_item_by_def(fltobj, itemdef) - function to check the item classify by item definition. Item definition is the reference to minetest.registered_items[item] entry
next return values allowed:
- true -> direct (belongs to) assignment to the classify group named by filtername
- string -> dimension, steps splitted by ":" (`a:b:c:d results in filtername, filtername:a, filtername:a:b, filtername:a:b:c, filtername:a:b:c:d`)
- key/value table -> multiple groups assignment. Values could be dimensions as above (`{a,b} results in filtername, filtername:a, filtername:b`)
- nil -> no group assingment by this filter
- get_description(fltobj, group) - optional - get human readable description for the dimension string (`filtername:a:b:c`)
- get_keyword(fltobj, group) - get string that should be used for searches or nil if the group should not used in for searches
- is_valid(fltobj, groupname) - Check if the groupname is valid. By default all groups are valid
### Filter Object methods
smart_inventory.filter.get(name) get filter object by registered name. Returns filter object fltobj
- fltobj:check_item_by_name(itemname) classify by itemname (wrapper for check_item_by_def)
- fltobj:check_item_by_def(def) classify by item definition
- fltobj:get_description(group) get group description
- fltobj:get_keyword(group) get string that should be used for searches
## Cache framework
cache.register_on_cache_filled(function, parameter) - hook to call additional initializations after the cache is filled
## Crecipes framework
The should be used trough cache.register_on_cache_filled to be sure all items are already known
crecipes.add_recipes_from_list(recipeslist) - Add Custom-Type Recipes to the smart inventory database
## Example usage for cache and crecipe
```
if minetest.global_exists("smart_inventory") then
-- add grinder recipes to smart inventory database
local crecipes = smart_inventory.crecipes
local cache = smart_inventory.cache
local function fill_citem_recipes()
local recipelist = {}
for _, e in ipairs(crushingfurnace_receipes) do
table.insert(recipelist, {
output = e[2],
items = {e[1]},
type = "grinding"
})
end
crecipes.add_recipes_from_list(recipelist)
end
cache.register_on_cache_filled(fill_citem_recipes)
end
```

View File

@ -1,165 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@ -1,77 +0,0 @@
# smart_inventory
## Overview
A fast Minetest inventory with focus on a great number of items and big screens. The special feature of this inventory is the dynamic classification filters that allow fast searching and browsing trough available items and show relevant invormations only to the user.
The mod is organized in multiple pages, each page does have own focus and follow own vision.
## Crafting page
![Screenshot](https://github.com/bell07/minetest-smart_inventory/blob/master/screenshot_crafting.png)
The vision is to not affect the gameplay trough crafting helpers. The dynamic search helper display currently relevant craft recipes only based on inventory content by default.
- Contains the usual player-, and crafting inventory
- Additional view of "craftable items" based on players inventory content
- Dynamic grouping of craftable items for better overview
- Lookup field to get all recipes with item in it - with filter for revealed items if the doc system is used
- Search field - with filter for revealed items if the doc system is used
- Compress - use the stack max size in inventory
- Sweep - move content of crafting inventory back to the main inventory
### Optional support for other mods
doc_items - if the doc system is found the crafting page shows only items craftable by known (revealed) items.
A lookup button is available on already known items to jump to the documntation entry
## Creative page
![Screenshot](https://github.com/bell07/minetest-smart_inventory/blob/master/screenshot_creative.png)
The vision is to get items fast searchable and gettable
- 3 dynamic filters + text search field for fast items search
- Sort out "mass"-groups to a special "Shaped" group
- just click to the item to get it in inventory
- cleanup of inventory trough "Trash" field
- clean whole inventory trough "Trash all" button
- save and restore inventory content in 3x save slots
## Player page
![Screenshot](https://github.com/bell07/minetest-smart_inventory/blob/master/screenshot_player.png)
The vision is to get all skins and player customizations visual exposed.
### 3d_armor / clothing
In creative mode all useable armor and clothing items available. The players inventory is not used in this mode. In survival only the armor and clothing from players inventory
is shown.
### skins
tested only with my fork https://github.com/bell07/minetest-skinsdb
But it should be work with any fork that uses skins.skins[] and have *_preview.png files
## Doc page
![Screenshot](https://github.com/bell07/minetest-smart_inventory/blob/master/screenshot_doc.png)
The vision is to get all ingame documentation available in a fast way. So navigation from crafting page is possible directly to the doc_item entry
The doc and doc_items mods required to get the page
## Dependencies:
Screen size at least 1024x768 / big screen. On my mobile with "full HD" it does not work.
Minetest stable 0.4.15 or newer
default mod (some graphics are used from this mod)
## Settings
```
#If enabled, the mod will show alternative human readable filterstrings if available.
smart_inventory_friendly_group_names (Show “friendly” filter grouping names) bool true
#List of groups defined for special handling of "Shaped nodes" (Comma separated).
#Items in this groups ignores the "not_in_inventory" group and are moved to separate "Shaped" category
smart_inventory_shaped_groups (List of groups to be handled as separate) string carpet,door,fence,stair,slab,wall,micro,panel,slope,dye
#If enabled, the the mod does not replace other inventory mods.
#The functionality is provided in a workbench.
smart_inventory_workbench_mode (Use workbench instead of players inventory) bool false
```
License: [LGPL-3](https://github.com/bell07/minetest-smart_inventory/blob/master/LICENSE)
Textures:
- Workbench: WTFPL (credits: to xdecor project)
- Buttons: WTFPL (credits to Stix (Minetest-forum))
- Arrow buttons: WTFPL (credits to daretmavi)

View File

@ -1,6 +0,0 @@
creative?
sfinv?
3d_armor?
skinsdb?
doc_items?
unifieddyes?

View File

@ -1,73 +0,0 @@
smart_inventory.doc_items_mod = minetest.get_modpath("doc_items")
local doc_addon = {}
local doc_item_entries = {}
function doc_addon.is_revealed_item(itemname, playername)
if not smart_inventory.doc_items_mod then
return true
end
doc_addon.get_category_list()
itemname = minetest.registered_aliases[itemname] or itemname
local doc_entry = doc_item_entries[itemname]
if doc_entry then
return doc.entry_revealed(playername, doc_entry.cid, doc_entry.eid)
else
-- unknown item
return false
end
return true
end
function doc_addon.show(itemname, playername)
if not smart_inventory.doc_items_mod then
return
end
doc_addon.get_category_list()
itemname = minetest.registered_aliases[itemname] or itemname
local doc_entry = doc_item_entries[itemname]
if doc_entry then
doc.mark_entry_as_viewed(playername, doc_entry.cid, doc_entry.eid)
local state = smart_inventory.get_page_state("doc", playername)
local codebox = state:get("code")
codebox.edata = doc_entry
doc.data.players[playername].galidx = 1
codebox:submit() --update the page
state.location.parentState:get("doc_button"):submit() -- switch to the tab
end
end
-- Get sorted category list
local doc_category_list = nil
function doc_addon.get_category_list()
-- build on first usage
if not doc_category_list and smart_inventory.doc_items_mod then
doc_category_list = {}
for _, category_name in ipairs(doc.data.category_order) do
local category = doc.data.categories[category_name]
if category then
local entries_data = {}
for _, eid in ipairs(doc.get_sorted_entry_names(category_name)) do
local entry = doc.data.categories[category_name].entries[eid]
if entry.data.itemstring and
minetest.registered_items[entry.data.itemstring] and
(entry.data.def == minetest.registered_items[entry.data.itemstring] or entry.data.def.door) then
local edata = {cid = category_name, cid_data = category, eid = eid, data = entry}
table.insert(entries_data, edata)
doc_item_entries[entry.data.itemstring] = edata
end
end
table.insert(doc_category_list, {cid = category_name, data = category, entries = entries_data})
end
end
end
return doc_category_list
end
-------------------------
return doc_addon

View File

@ -1,31 +0,0 @@
smart_inventory = {}
smart_inventory.modpath = minetest.get_modpath(minetest.get_current_modname())
local modpath = smart_inventory.modpath
-- load libs
smart_inventory.txt = dofile(modpath.."/libs/simple_po_reader.lua")
smart_inventory.smartfs = dofile(modpath.."/libs/smartfs.lua")
smart_inventory.smartfs_elements = dofile(modpath.."/libs/smartfs-elements.lua")
smart_inventory.doc_addon = dofile(modpath.."/doc_addon.lua")
smart_inventory.filter = dofile(modpath.."/libs/filter.lua")
smart_inventory.cache = dofile(modpath.."/libs/cache.lua")
smart_inventory.crecipes = dofile(modpath.."/libs/crecipes.lua")
smart_inventory.maininv = dofile(modpath.."/libs/maininv.lua")
smart_inventory.ui_tools = dofile(modpath.."/ui_tools.lua")
-- register pages
dofile(modpath.."/inventory_framework.lua")
dofile(modpath.."/pages/crafting.lua")
dofile(modpath.."/pages/creative.lua")
dofile(modpath.."/pages/player.lua")
dofile(modpath.."/pages/doc.lua")
dofile(modpath.."/pages/awards.lua")
-- Cleanup inventories
minetest.register_on_leaveplayer(function(player)
local player_name = player:get_player_name()
minetest.remove_detached_inventory(player_name.."_crafting_inv")
minetest.remove_detached_inventory(player_name.."_trash_inv")
end)

View File

@ -1,139 +0,0 @@
local smartfs = smart_inventory.smartfs
local maininv = smart_inventory.maininv
local modpath = smart_inventory.modpath
-- smartfs callback
local inventory_form = smartfs.create("smart_inventory:main", function(state)
-- enhanced object to the main inventory functions
state.param.invobj = maininv.get(state.location.player)
-- Set language code
local player_info = minetest.get_player_information(state.location.player)
if player_info and player_info.lang_code ~= "" then
state.lang_code = player_info.lang_code
end
-- tabbed view controller
local tab_controller = {
_tabs = {},
active_name = nil,
set_active = function(self, tabname)
for name, def in pairs(self._tabs) do
if name == tabname then
def.button:setBackground("halo.png")
def.view:setVisible(true)
else
def.button:setBackground(nil)
def.view:setVisible(false)
end
end
self.active_name = tabname
end,
tab_add = function(self, name, def)
def.viewstate:size(20,10) --size of tab view
self._tabs[name] = def
end,
get_active_name = function(self)
return self.active_name
end,
}
--set screen size
state:size(20,12)
state:label(1,0.2,"header","Smart Inventory")
state:image(0,0,1,1,"header_logo", "logo.png")
state:image_button(19,0,1,1,"exit", "","smart_inventory_exit_button.png", true):setTooltip("Close the inventory")
local button_x = 0.1
table.sort(smart_inventory.registered_pages, function(a,b)
if not a.sequence then
return false
elseif not b.sequence then
return true
elseif a.sequence > b.sequence then
return false
else
return true
end
end)
for _, def in ipairs(smart_inventory.registered_pages) do
assert(def.smartfs_callback, "Callback function needed")
assert(def.name, "Name is needed")
if not def.is_visible_func or def.is_visible_func(state) then
local tabdef = {}
local label
if not def.label then
label = ""
else
label = def.label
end
tabdef.button = state:button(button_x,11.2,1,1,def.name.."_button",label)
if def.icon then
tabdef.button:setImage(def.icon)
end
tabdef.button:setTooltip(def.tooltip)
tabdef.button:onClick(function(self)
tab_controller:set_active(def.name)
if def.on_button_click then
def.on_button_click(tabdef.viewstate)
end
end)
tabdef.view = state:container(0,1,def.name.."_container")
tabdef.viewstate = tabdef.view:getContainerState()
def.smartfs_callback(tabdef.viewstate)
tab_controller:tab_add(def.name, tabdef)
button_x = button_x + 1
end
end
tab_controller:set_active(smart_inventory.registered_pages[1].name)
end)
if minetest.settings:get_bool("smart_inventory_workbench_mode") then
dofile(modpath.."/workbench.lua")
smart_inventory.get_player_state = function(playername)
-- check the inventory is shown
local state = smartfs.opened[playername]
if state and (not state.obsolete) and
state.location.type == "player" and
state.def.name == "smart_inventory:main" then
return state
end
end
else
smartfs.set_player_inventory(inventory_form)
smart_inventory.get_player_state = function(playername)
return smartfs.inv[playername]
end
end
-- pages list
smart_inventory.registered_pages = {}
-- add new page
function smart_inventory.register_page(def)
table.insert(smart_inventory.registered_pages, def)
end
-- smart_inventory.get_player_state(playername) defined above
-- get state of active page
function smart_inventory.get_page_state(pagename, playername)
local rootstate = smart_inventory.get_player_state(playername)
if not rootstate then
return
end
local view = rootstate:get(pagename.."_container")
if not view then
return
end
return view:getContainerState()
end
-- get definition of registered page
function smart_inventory.get_registered_page(pagename)
for _, registred_page in ipairs(smart_inventory.registered_pages) do
if registred_page.name == pagename then
return registred_page
end
end
end

View File

@ -1,139 +0,0 @@
local filter = smart_inventory.filter
local cache = {}
cache.cgroups = {} -- cache groups
cache.itemgroups = {} -- raw item groups for recipe checks
cache.citems = {}
-----------------------------------------------------
-- Add an Item to the cache
-----------------------------------------------------
function cache.add_item(item_def)
-- already in cache. Skip duplicate processing
if cache.citems[item_def.name] then
return
end
-- fill raw groups cache for recipes
for group, value in pairs(item_def.groups) do
cache.itemgroups[group] = cache.itemgroups[group] or {}
cache.itemgroups[group][item_def.name] = item_def
end
local entry = {
name = item_def.name,
in_output_recipe = {},
in_craft_recipe = {},
cgroups = {}
}
cache.citems[item_def.name] = entry
-- classify the item
for _, flt in pairs(filter.registered_filter) do
local filter_result = flt:check_item_by_def(item_def)
if filter_result then
if filter_result == true then
cache.assign_to_group(flt.name, item_def, flt)
else
if type(filter_result) ~= "table" then
if tonumber(filter_result) ~= nil then
filter_result = {[flt.name..":"..filter_result] = true}
else
filter_result = {[filter_result] = true}
end
end
for key, val in pairs(filter_result) do
local filter_entry = tostring(key)
if val ~= true then
filter_entry = filter_entry..":"..tostring(val)
end
cache.assign_to_group(filter_entry, item_def, flt)
end
end
end
end
end
-----------------------------------------------------
-- Add a item to cache group
-----------------------------------------------------
function cache.assign_to_group(group_name, itemdef, flt)
-- check and build filter chain
local abs_group
local parent_ref
local parent_stringpos
for rel_group in group_name:gmatch("[^:]+") do
-- get parent relation and absolute path
if abs_group then
parent_ref = cache.cgroups[abs_group]
parent_stringpos = string.len(abs_group)+2
abs_group = abs_group..":"..rel_group
else
abs_group = rel_group
end
if flt:is_valid(abs_group) then
-- check if group is new, create it
if not cache.cgroups[abs_group] then
if parent_ref then
parent_ref.childs[abs_group] = string.sub(group_name, parent_stringpos)
end
local group = {
name = abs_group,
items = {},
parent = parent_ref,
childs = {},
}
group.group_desc = flt:get_description(group)
group.keyword = flt:get_keyword(group)
cache.cgroups[abs_group] = group
end
-- set relation
cache.cgroups[abs_group].items[itemdef.name] = itemdef
cache.citems[itemdef.name].cgroups[abs_group] = cache.cgroups[abs_group]
end
end
end
-----------------------------------------------------
-- Hook / Event for further initializations of the cache is filled
-----------------------------------------------------
cache.registered_on_cache_filled = {}
function cache.register_on_cache_filled(func, ...)
assert(type(func) == "function", "register_on_cache_filled needs a function")
table.insert(cache.registered_on_cache_filled, { func = func, opt = {...}})
end
local function process_on_cache_filled()
for _, hook in ipairs(cache.registered_on_cache_filled) do
hook.func(unpack(hook.opt))
end
end
-----------------------------------------------------
-- Fill the cache at init
-----------------------------------------------------
local function fill_cache()
local shape_filter = filter.get("shape")
for _, def in pairs(minetest.registered_items) do
-- build groups and items cache
if def.description and def.description ~= "" and
(not def.groups.not_in_creative_inventory or shape_filter:check_item_by_def(def)) then
cache.add_item(def)
end
end
-- call hooks
minetest.after(0, process_on_cache_filled)
end
minetest.after(0, fill_cache)
-----------------------------------------------------
-- return the reference to the mod
-----------------------------------------------------
return cache

View File

@ -1,400 +0,0 @@
local doc_addon = smart_inventory.doc_addon
local cache = smart_inventory.cache
local filter = smart_inventory.filter
local crecipes = {}
crecipes.crecipes = {} --list of all recipes
-----------------------------------------------------
-- crecipe: Class
-----------------------------------------------------
local crecipe_class = {}
local crecipe_class_mt = {__index = crecipe_class}
crecipes.crecipe_class = crecipe_class
-----------------------------------------------------
-- crecipes: analyze all data. Return false if invalid recipe. true on success
-----------------------------------------------------
function crecipe_class:analyze()
-- check recipe output
if self._recipe.type == "cooking" then
return false --fuel not supported
end
if self._recipe.output == "" then
minetest.log("[smartfs_inventory] broken recipe without output "..dump(self._recipe))
return false
end
local outstack = ItemStack(self._recipe.output)
if outstack:get_meta():get_int("palette_index") > 0 then
minetest.log("verbose", "[smartfs_inventory] ignore unifieddyes recipe "..self._recipe.output)
return -- not supported
end
self.out_item = outstack:get_definition()
if not self.out_item or not self.out_item.name then
minetest.log("[smartfs_inventory] unknown recipe result "..self._recipe.output)
return false
end
-- check recipe items/groups
for _, recipe_item in pairs(self._recipe.items) do
if recipe_item ~= "" then
if self._items[recipe_item] then
self._items[recipe_item].count = self._items[recipe_item].count + 1
else
self._items[recipe_item] = {count = 1}
end
end
end
for recipe_item, iteminfo in pairs(self._items) do
if recipe_item:sub(1, 6) ~= "group:" then
local itemname = minetest.registered_aliases[recipe_item] or recipe_item
if minetest.registered_items[itemname] then
iteminfo.items = {[itemname] = minetest.registered_items[itemname]}
else
minetest.log("[smartfs_inventory] unknown item in recipe: "..itemname.." for result "..self.out_item.name)
return false
end
else
local retitems
for groupname in string.gmatch(recipe_item:sub(7), '([^,]+)') do
if not retitems then --first entry
if cache.itemgroups[groupname] then
retitems = {}
for k,v in pairs(cache.itemgroups[groupname]) do
retitems[k] = v
end
else
minetest.log("[smartfs_inventory] unknown group description in recipe: "..recipe_item.." / "..groupname.." for result "..self.out_item.name)
return false
end
else
for itemname, itemdef in pairs(retitems) do
if not minetest.registered_items[itemname].groups[groupname] then
retitems[itemname] = nil
end
end
end
if not retitems or not next(retitems) then
minetest.log("[smartfs_inventory] no items matches group: "..recipe_item.." for result "..self.out_item.name)
return false
end
end
iteminfo.items = retitems
end
end
-- invalid recipe
if not self._items then
minetest.log("[smartfs_inventory] skip recipe for: "..recipe_item)
return false
else
return true
end
end
-----------------------------------------------------
-- crecipes: Check if the recipe is revealed to the player
-----------------------------------------------------
function crecipe_class:is_revealed(playername, recursiv_checked_items)
local recipe_valid = true
for _, entry in pairs(self._items) do
recipe_valid = false
for _, itemdef in pairs(entry.items) do
if doc_addon.is_revealed_item(itemdef.name, playername) then
recipe_valid = true
break
end
if cache.citems[itemdef.name].cgroups["shape"] then -- Check shapes recursive
recursiv_checked_items = recursiv_checked_items or {}
for _, recipe in ipairs(cache.citems[itemdef.name].in_output_recipe) do
local crecipe = crecipes.crecipes[recipe]
if recursiv_checked_items[crecipe.out_item.name] == nil then
recursiv_checked_items[crecipe.out_item.name] = false --avoid re-recursion
recursiv_checked_items[crecipe.out_item.name] = crecipe:is_revealed(playername, recursiv_checked_items)
end
if recursiv_checked_items[crecipe.out_item.name] == true then
recipe_valid = true
break
end
end
if recipe_valid then
break
end
end
end
if not recipe_valid then
break
end
end
return recipe_valid
end
-----------------------------------------------------
-- crecipes: Returns recipe without groups, with replacements
-----------------------------------------------------
function crecipe_class:get_with_placeholder(playername, inventory_tab)
local recipe = {}
for k, v in pairs(self._recipe) do
recipe[k] = v
end
recipe.items = {}
for k, v in pairs(self._recipe.items) do
recipe.items[k] = v
end
local recursiv_checked_items = {}
if inventory_tab then
for k, v in pairs(inventory_tab) do
recursiv_checked_items[k] = v
end
end
self:is_revealed(playername, recursiv_checked_items) -- enhance recursiv_checked_items
for key, recipe_item in pairs(recipe.items) do
local item
-- Check for matching item in inventory and revealed cache
if inventory_tab then
local itemcount = 0
for _, item_in_list in pairs(self._items[recipe_item].items) do
local in_inventory = inventory_tab[item_in_list.name]
if in_inventory == true then
item = item_in_list.name
break
elseif in_inventory and in_inventory > itemcount then
item = item_in_list.name
itemcount = in_inventory
end
end
end
-- second try, revealed by recipe item
if not item then
for _, item_in_list in pairs(self._items[recipe_item].items) do
if recursiv_checked_items[item_in_list.name] then
item = item_in_list.name
break
end
end
end
-- third try, get any revealed item
if not item then
for _, item_in_list in pairs(self._items[recipe_item].items) do
if doc_addon.is_revealed_item(item_in_list.name, playername) then
item = item_in_list.name
break
end
end
end
-- last try, just get one item
if not item and self._items[recipe_item].items[1] then
item = self._items[recipe_item].items[1].name
end
-- set recipe item
if item then
if recipe_item ~= item then
recipe.items[key] = {
item = item,
tooltip = recipe_item,
text = 'G',
}
end
end
end
return recipe
end
-----------------------------------------------------
-- crecipes: Check if recipe contains only items provided in reference_items
-----------------------------------------------------
function crecipe_class:is_craftable_by_items(reference_items)
local item_ok = false
for _, entry in pairs(self._items) do
item_ok = false
for _, itemdef in pairs(entry.items) do
if reference_items[itemdef.name] then
item_ok = true
end
end
if item_ok == false then
break
end
end
return item_ok
end
-----------------------------------------------------
-- crecipes: Check if the items placed in grid matches the recipe
-----------------------------------------------------
function crecipe_class:check_craftable_by_grid(grid)
-- only "normal" recipes supported
if self.recipe_type ~= "normal" then
return false
end
for i = 1, 9 do
local grid_item = grid[i]:get_name()
-- check only fields filled in crafting grid
if grid_item and grid_item ~= "" then
-- check if item defined in recipe at this place
local item_ok = false
local recipe_item
-- default case - 3x3 crafting grid
local width = self._recipe.width
if not width or width == 0 or width == 3 then
recipe_item = self._recipe.items[i]
else
-- complex case - recalculate to the 3x3 crafting grid
local x = math.fmod((i-1),3)+1
if x <= width then
local y = math.floor((i-1)/3+1)
local coord = (y-1)*width+x
recipe_item = self._recipe.items[coord]
else
recipe_item = ""
end
end
if not recipe_item or recipe_item == "" then
return false
end
-- check if it is a compatible item
for _, itemdef in pairs(self._items[recipe_item].items) do
if itemdef.name == grid_item then
item_ok = true
break
end
end
if not item_ok then
return false
end
end
end
return true
end
-----------------------------------------------------
-- Recipe object Constructor
-----------------------------------------------------
function crecipes.new(recipe)
local self = setmetatable({}, crecipe_class_mt)
-- self.out_item = nil
self._recipe = recipe
self.recipe_type = recipe.type
self._items = {}
return self
end
-----------------------------------------------------
-- Get all revealed recipes with at least one item in reference_items table
-----------------------------------------------------
function crecipes.get_revealed_recipes_with_items(playername, reference_items)
local recipelist = {}
local revealed_items_cache = {}
for itemname, _ in pairs(reference_items) do
if cache.citems[itemname] and cache.citems[itemname].in_craft_recipe then
for _, recipe in ipairs(cache.citems[itemname].in_craft_recipe) do
local crecipe = crecipes.crecipes[recipe]
if crecipe and crecipe:is_revealed(playername, revealed_items_cache) then
recipelist[recipe] = crecipe
end
-- lookup one step forward for shapes
if cache.citems[crecipe.out_item.name].cgroups["shape"] then
for _, recipe2 in ipairs(cache.citems[crecipe.out_item.name].in_craft_recipe) do
local crecipe = crecipes.crecipes[recipe2]
if crecipe and crecipe:is_revealed(playername, revealed_items_cache) then
recipelist[recipe2] = crecipe
end
end
end
end
end
if cache.citems[itemname] and cache.citems[itemname].in_output_recipe then
for _, recipe in ipairs(cache.citems[itemname].in_output_recipe) do
local crecipe = crecipes.crecipes[recipe]
if crecipe and crecipe:is_revealed(playername, revealed_items_cache) then
recipelist[recipe] = crecipe
end
end
end
end
return recipelist
end
-----------------------------------------------------
-- Get all recipes with all required items in reference items
-----------------------------------------------------
function crecipes.get_recipes_craftable(playername, reference_items)
local all = crecipes.get_revealed_recipes_with_items(playername, reference_items)
local craftable = {}
for recipe, crecipe in pairs(all) do
if crecipe:is_craftable_by_items(reference_items) then
craftable[recipe] = crecipe
end
end
return craftable
end
-----------------------------------------------------
-- Get all recipes that match to already placed items on crafting grid
-----------------------------------------------------
function crecipes.get_recipes_started_craft(playername, grid, reference_items)
local all = crecipes.get_revealed_recipes_with_items(playername, reference_items)
local craftable = {}
for recipe, crecipe in pairs(all) do
if crecipe:check_craftable_by_grid(grid) then
craftable[recipe] = crecipe
end
end
return craftable
end
function crecipes.add_recipes_from_list(recipelist)
if recipelist then
for _, recipe in ipairs(recipelist) do
local recipe_obj = crecipes.new(recipe)
if recipe_obj:analyze() then
-- probably hidden therefore not indexed previous. But Items with recipe should be allways visible
cache.add_item(minetest.registered_items[recipe_obj.out_item.name])
table.insert(cache.citems[recipe_obj.out_item.name].in_output_recipe, recipe)
crecipes.crecipes[recipe] = recipe_obj
if recipe_obj.recipe_type ~= "normal" then
cache.assign_to_group("recipetype:"..recipe_obj.recipe_type, recipe_obj.out_item, filter.get("recipetype"))
end
for _, entry in pairs(recipe_obj._items) do
for itemname, itemdef in pairs(entry.items) do
cache.add_item(itemdef) -- probably hidden therefore not indexed previous. But Items with recipe should be allways visible
table.insert(cache.citems[itemdef.name].in_craft_recipe, recipe)
cache.assign_to_group("ingredient:"..itemdef.name, recipe_obj.out_item, filter.get("ingredient"))
end
end
end
end
end
end
-----------------------------------------------------
-- Fill the recipes cache at init
-----------------------------------------------------
local function fill_recipe_cache()
for itemname, _ in pairs(minetest.registered_items) do
crecipes.add_recipes_from_list(minetest.get_all_craft_recipes(itemname))
end
for itemname, _ in pairs(minetest.registered_aliases) do
crecipes.add_recipes_from_list(minetest.get_all_craft_recipes(itemname))
end
end
-- register to process after cache is filled
cache.register_on_cache_filled(fill_recipe_cache)
return crecipes

View File

@ -1,409 +0,0 @@
local txt = smart_inventory.txt
--------------------------------------------------------------
-- Filter class
--------------------------------------------------------------
local filter_class = {}
local filter_class_mt = {__index = filter_class}
function filter_class:check_item_by_name(itemname)
if minetest.registered_items[itemname] then
return self:check_item_by_def(minetest.registered_items[itemname])
end
end
function filter_class:check_item_by_def(def)
error("check_item_by_def needs redefinition:"..debug.traceback())
end
function filter_class:_get_description(group)
if txt then
if txt[group.name] then
return txt[group.name].." ("..group.name..")"
elseif group.parent and group.parent.childs[group.name] and txt[group.parent.name] then
return txt[group.parent.name].." "..group.parent.childs[group.name].." ("..group.name..")"
else
return group.name
end
else
return group.name
end
end
filter_class.get_description = filter_class._get_description
function filter_class:_get_keyword(group)
return group.group_desc
end
filter_class.get_keyword = filter_class._get_keyword
function filter_class:is_valid(group)
return true
end
local filter = {}
filter.registered_filter = {}
function filter.get(name)
return filter.registered_filter[name]
end
function filter.register_filter(def)
assert(def.name, "filter needs a name")
assert(def.check_item_by_def, "filter function check_item_by_def required")
assert(not filter.registered_filter[def.name], "filter already exists")
setmetatable(def, filter_class_mt)
filter.registered_filter[def.name] = def
end
-- rename groups for beter consistency
filter.group_rename = {
customnode_default = "customnode",
}
-- group configurations per basename
-- true means is dimension
-- 1 means replace the base only ("food_choco_powder" => food:choco_powder")
filter.base_group_config = {
armor = true,
physics = true,
basecolor = true,
excolor = true,
color = true,
unicolor = true,
food = 1,
customnode = true,
}
-- hide this groups
filter.group_hide_config = {
armor_count = true,
not_in_creative_inventory = false,
}
-- value of this group will be recalculated to %
filter.group_wear_config = {
armor_use = true,
}
-- Ususally 1 means true for group values. This is an exceptions table for this rule
filter.group_with_value_1_config = {
oddly_breakable_by_hand = true,
}
--------------------------------------------------------------
-- Filter group
--------------------------------------------------------------
filter.register_filter({
name = "group",
check_item_by_def = function(self, def)
local ret = {}
for k_orig, v in pairs(def.groups) do
local k = filter.group_rename[k_orig] or k_orig
local mk, mv
-- Check group base
local basename
for z in k:gmatch("[^_]+") do
basename = z
break
end
local basegroup_config = filter.base_group_config[basename]
if basegroup_config == true then
mk = string.gsub(k, "_", ":")
elseif basegroup_config == 1 then
mk = string.gsub(k, "^"..basename.."_", basename..":")
else
mk = k
end
-- stack wear related value
if filter.group_wear_config[k] then
mv = tostring(math.floor(v / 65535 * 10000 + 0.5)/100).." %"
-- value-expandable groups
elseif v ~= 1 or k == filter.group_with_value_1_config[k] then
mv = v
else
mv = true
end
if v ~= 0 and mk and not filter.group_hide_config[k] then
ret[mk] = mv
end
end
return ret
end,
})
filter.register_filter({
name = "type",
check_item_by_def = function(self, def)
return self.name..":"..def.type
end,
get_keyword = function(self, group)
if group.name ~= self.name then
return group.parent.childs[group.name]
end
end
})
filter.register_filter({
name = "mod",
check_item_by_def = function(self, def)
if def.mod_origin then
return self.name..":"..def.mod_origin
end
end,
get_keyword = function(self, group)
if group.name ~= self.name then
return group.parent.childs[group.name]
end
end
})
filter.register_filter({
name = "translucent",
check_item_by_def = function(self, def)
if def.sunlight_propagates ~= 0 then
return def.sunlight_propagates
end
end,
})
filter.register_filter({
name = "light",
check_item_by_def = function(self, def)
if def.light_source ~= 0 then
return def.light_source
end
end,
})
filter.register_filter({
name = "metainv",
check_item_by_def = function(self, def)
if def.allow_metadata_inventory_move or
def.allow_metadata_inventory_take or
def.allow_metadata_inventory_put or
def.on_metadata_inventory_move or
def.on_metadata_inventory_take or
def.on_metadata_inventory_put then
return true
end
end,
})
--[[ does it sense to filter them? I cannot define the human readable groups for them
filter.register_filter({
name = "drawtype",
check_item_by_def = function(self, def)
if def.drawtype ~= "normal" then
return def.drawtype
end
end,
})
]]
local shaped_groups = {}
local shaped_list = minetest.setting_get("smart_inventory_shaped_groups") or "carpet,door,fence,stair,slab,wall,micro,panel,slope"
if shaped_list then
for z in shaped_list:gmatch("[^,]+") do
shaped_groups[z] = true
end
end
filter.register_filter({
name = "shape",
check_item_by_def = function(self, def)
local door_groups
if shaped_groups["door"] then
local door_filter = filter.get("door")
door_groups = door_filter:check_item_by_def(def)
if door_groups and door_groups.door then
return true
end
end
for k, v in pairs(def.groups) do
if k ~= "door" and shaped_groups[k] then
return true
end
end
end,
})
--[[ disabled since debug.getupvalue is not usable to secure environment
filter.register_filter({
name = "food",
check_item_by_def = function(self, def)
if def.on_use then
local name,change=debug.getupvalue(def.on_use, 1)
if name~=nil and name=="hp_change" and change > 0 then
return tostring(change)
end
end
end,
})
filter.register_filter({
name = "toxic",
check_item_by_def = function(self, def)
if def.on_use then
local name,change=debug.getupvalue(def.on_use, 1)
if name~=nil and name=="hp_change" and change < 0 then
return tostring(change)
end
end
end,
})
]]
filter.register_filter({
name = "tool",
check_item_by_def = function(self, def)
if not def.tool_capabilities then
return
end
local rettab = {}
for k, v in pairs(def.tool_capabilities) do
if type(v) ~= "table" and v ~= 0 then
rettab["tool:"..k] = v
end
end
if def.tool_capabilities.damage_groups then
for k, v in pairs(def.tool_capabilities.damage_groups) do
if v ~= 0 then
rettab["damage:"..k] = v
end
end
end
--[[ disabled, I cannot find right human readable interpretation for this
if def.tool_capabilities.groupcaps then
for groupcap, gdef in pairs(def.tool_capabilities.groupcaps) do
for k, v in pairs(gdef) do
if type(v) ~= "table" then
rettab["groupcaps:"..groupcap..":"..k] = v
end
end
end
end
]]
return rettab
end,
get_keyword = function(self, group)
if group.name == "tool" or group.name == "damage" then
return nil
else
return self:_get_keyword(group)
end
end
})
filter.register_filter({
name = "armor",
check_item_by_def = function(self, def)
return def.armor_groups
end,
})
filter.register_filter({
name = 'clothing_cape',
check_item_by_def = function(self, def)
if def.groups.cape then
return 'clothing'
end
end
})
-- Burn times
filter.register_filter({
name = "fuel",
check_item_by_def = function(self, def)
local burntime = minetest.get_craft_result({method="fuel",width=1,items={def.name}}).time
if burntime > 0 then
return "fuel:"..burntime
end
end
})
-- Group assignment done in cache framework internally
filter.register_filter({
name = "recipetype",
check_item_by_def = function(self, def) end,
get_keyword = function(self, group)
if group.name ~= self.name then
return group.parent.childs[group.name]
end
end
})
-- Group assignment done in cache framework internally
filter.register_filter({
name = "ingredient",
check_item_by_def = function(self, def) end,
get_description = function(self, group)
local itemname = group.name:sub(12)
if txt and txt["ingredient"] and
minetest.registered_items[itemname] and minetest.registered_items[itemname].description then
return txt["ingredient"] .." "..minetest.registered_items[itemname].description.." ("..group.name..")"
else
return group.name
end
end,
get_keyword = function(self, group)
-- not searchable by ingedient
return nil
end,
is_valid = function(self, groupname)
local itemname = groupname:sub(12)
if itemname ~= "" and minetest.registered_items[itemname] then
return true
end
end
})
local door_groups
local function fill_door_groups()
door_groups = {}
for _, extend_def in pairs(minetest.registered_items) do
local base_def
if extend_def.groups and extend_def.groups.door then
if extend_def.door then
base_def = minetest.registered_items[extend_def.door.name]
elseif extend_def.drop and type(extend_def.drop) == "string" then
base_def = minetest.registered_items[extend_def.drop]
end
end
if base_def then
door_groups[base_def.name] = extend_def
door_groups[extend_def.name] = false
end
end
end
filter.register_filter({
name = "door",
check_item_by_def = function(self, def)
if not door_groups then
fill_door_groups()
end
if not door_groups[def.name] then
return
end
local group_filter = filter.get("group")
local ret = group_filter:check_item_by_def(door_groups[def.name])
if ret then
ret["not_in_creative_inventory"] = nil
return ret
end
end
})
----------------
return filter

View File

@ -1,160 +0,0 @@
-- Enhanced main inventory methods
local maininvClass = {}
maininvClass_mt = {__index = maininvClass}
-- Clear the inventory
function maininvClass:remove_all()
for idx = 1, self.inventory:get_size("main") do
self.inventory:set_stack("main", idx, "")
end
end
-- Save inventory content to a slot (file)
function maininvClass:save_to_slot(slot)
local savedata = {}
for idx, stack in ipairs(self.inventory:get_list("main")) do
if not stack:is_empty() then
savedata[idx] = stack:to_string()
end
end
local player = minetest.get_player_by_name(self.playername)
player:set_attribute("inv_save_slot_"..tostring(slot), minetest.serialize(savedata))
end
-- Get restore the inventory content from a slot (file)
function maininvClass:restore_from_slot(slot)
local player = minetest.get_player_by_name(self.playername)
local savedata = minetest.deserialize(player:get_attribute("inv_save_slot_"..tostring(slot)))
if savedata then
for idx = 1, self.inventory:get_size("main") do
self.inventory:set_stack("main", idx, savedata[idx])
end
end
end
-- Add a item to inventory
function maininvClass:add_item(item)
return self.inventory:add_item("main", item)
end
function maininvClass:add_sepearate_stack(item)
for idx, stack in ipairs(self.inventory:get_list("main")) do
if stack:is_empty() then
self.inventory:set_stack("main", idx, item)
item = ""
break
end
end
return item
end
-- Get inventory content as consolidated table
function maininvClass:get_items()
local items_in_inventory = {}
for _, stack in ipairs(self.inventory:get_list("main")) do
local itemname = stack:get_name()
if itemname and itemname ~= "" then
if not items_in_inventory[itemname] then
items_in_inventory[itemname] = stack:get_count()
else
items_in_inventory[itemname] = items_in_inventory[itemname] + stack:get_count()
end
end
end
-- add items in crafting field to the available items in inventory
for _, stack in ipairs(self.inventory:get_list("craft")) do
local itemname = stack:get_name()
if itemname and itemname ~= "" then
if not items_in_inventory[itemname] then
items_in_inventory[itemname] = stack:get_count()
else
items_in_inventory[itemname] = items_in_inventory[itemname] + stack:get_count()
end
end
end
return items_in_inventory
end
-- try to get empty stacks by move items to other stacky up to max_size
function maininvClass:compress()
for idx1 = self.inventory:get_size("main"), 1, -1 do
local stack1 = self.inventory:get_stack("main", idx1)
if not stack1:is_empty() then
for idx2 = 1, idx1 do
local stack2 = self.inventory:get_stack("main", idx2)
if idx1 ~= idx2 and stack1:get_name() == stack2:get_name() then
stack1 = stack2:add_item(stack1)
self.inventory:set_stack("main", idx1, stack1)
self.inventory:set_stack("main", idx2, stack2)
if stack1:is_empty() then
break
end
end
end
end
end
end
-- move items to crafting grid to craft item
function maininvClass:craft_item(grid)
for idx_main, stack_main in ipairs(self.inventory:get_list("main")) do
for x, col in pairs(grid) do
for y, item in pairs(col) do
local idx_craft = (y-1)*3+x
local stack_craft = self.inventory:get_stack("craft", idx_craft )
if not stack_main:is_empty() and stack_main:get_name() == item then --right item
local left = stack_craft:add_item(stack_main:take_item(1))
stack_main:add_item(left)
self.inventory:set_stack("craft", idx_craft, stack_craft)
self.inventory:set_stack("main", idx_main, stack_main)
end
end
end
end
end
-- move all items from crafting inventory back to main inventory
function maininvClass:sweep_crafting_inventory()
for idx = 1, self.inventory:get_size("craft") do
local stack = self.inventory:get_stack("craft", idx)
if not stack:is_empty() then
local left = self.inventory:add_item("main", stack)
self.inventory:set_stack("craft", idx, left)
end
end
end
-- Swap row to the top. Asumption the inventory is 8x4, the row number should be 2, 3 or 4
function maininvClass:swap_row_to_top(row)
local width = 8
for idx1 = 1, width do
local idx2 = (row -1) * width + idx1
local stack1 = self.inventory:get_stack("main", idx1)
local stack2 = self.inventory:get_stack("main", idx2)
self.inventory:set_stack("main", idx2, stack1)
self.inventory:set_stack("main", idx1, stack2)
end
end
-- player inventory class
local maininv = {}
function maininv.get(playername)
local self = setmetatable({}, maininvClass_mt)
self.playername = playername
self.inventory = minetest.get_player_by_name(playername):get_inventory()
self.inventory:set_width("craft", 3)
self.inventory:set_size("craft", 9)
return self
end
-- Check if player has creative privilege.
function maininvClass:get_has_creative()
return minetest.is_creative_enabled(self.playername)
end
return maininv

View File

@ -1,41 +0,0 @@
local txt_usage = minetest.setting_getbool("smart_inventory_friendly_group_names") --or true
if txt_usage == false then
return false
end
local modpath = minetest.get_modpath(minetest.get_current_modname()).."/locale"
local LANG = minetest.setting_get("language")
if not (LANG and (LANG ~= "")) then LANG = os.getenv("LANG") end
if not (LANG and (LANG ~= "")) then LANG = "en" end
local pofile = modpath.."/groups_"..LANG:sub(1,2)..".po"
local f=io.open(pofile,"r")
--fallback to en
if not f then
pofile = modpath.."/groups_en.po"
f=io.open(pofile,"r")
end
local texttab = {}
local msgid
local msgstr
for line in f:lines() do
if line:sub(1,5) == 'msgid' then -- msgid ""
msgid = line:sub(8, line:len()-1)
elseif line:sub(1,6) == 'msgstr' then -- msgstr ""
msgstr = line:sub(9, line:len()-1)
end
if msgid and msgstr then
if msgid ~= "" and msgstr ~= "" then
texttab[msgid] = msgstr
end
msgid = nil
msgstr = nil
end
end
io.close(f)
return texttab

View File

@ -1,287 +0,0 @@
local smartfs = smart_inventory.smartfs
local elements = {}
-----------------------------------------------------
--- Crafting Preview applet
-----------------------------------------------------
-- enhanced / prepared container
-- Additional methods
-- craft_preview:setCraft(craft)
-- craft_preview:onButtonClicked(function(self, itemname, player))
-- if craft=nil, the view will be initialized
local craft_preview = table.copy(smartfs._edef.container)
function craft_preview:onCreate()
self.data.relative = true
smartfs._edef.container.onCreate(self)
for x = 1, 3 do
for y = 1, 3 do
local button = self._state:image_button(
(x-1)*self.data.zoom+self.data.pos.x,
(y-1)*self.data.zoom+self.data.pos.y,
self.data.zoom, self.data.zoom,
"craft:"..x..":"..y,"")
button:setVisible(false)
button:onClick(function(self, state, player)
local parent_element = state.location.containerElement
if parent_element._button_click then
parent_element._button_click(parent_element, self.data.item, player)
end
end)
end
end
if self.data.recipe then
self:setCraft(self.data.recipe)
end
end
function craft_preview:onButtonClicked(func)
self._button_click = func
end
-- Update fields
function craft_preview:setCraft(craft)
local width
if craft then -- adjust width to 1 if the recipe contains just 1 item
width = craft.width or 3
if width == 0 then
width = 3
end
if craft.items[1] and next(craft.items, 1) == nil then
width = 1
end
end
for x = 1, 3 do
for y = 1, 3 do
local item = nil
if craft then
if width <= 1 then
if x == 2 then
item = craft.items[y]
end
elseif x <= width then
item = craft.items[(y-1)*width+x]
end
end
local btn = self._state:get("craft:"..x..":"..y)
if item then
if type(item) == "string" then
btn:setItem(item)
btn:setTooltip()
btn:setText("")
else
btn:setItem(item.item)
btn:setTooltip(item.tooltip)
btn:setText(item.text)
end
btn:setVisible(true)
else
btn:setVisible(false)
end
end
end
end
-- get the preview as table
function craft_preview:getCraft()
local grid = {}
for x = 1, 3 do
grid[x] = {}
for y = 1, 3 do
local button = self._state:get("craft:"..x..":"..y)
if button:getVisible() then
grid[x][y] = button:getItem()
end
end
end
return grid
end
smartfs.element("craft_preview", craft_preview)
function elements:craft_preview(x, y, name, zoom, recipe)
return self:element("craft_preview", {
pos = {x=x, y=y},
name = name,
recipe = recipe,
zoom = zoom or 1
})
end
-----------------------------------------------------
--- Pagable grid buttons
-----------------------------------------------------
--[[ enhanced / prepared container
Additional methods
buttons_grid:setList(craft)
buttons_grid:onClick(function(state, index, player)...end)
buttons_grid:setList(iconlist)
buttons_grid:getFirstVisible()
buttons_grid:setFirstVisible(index)
iconslist is a list of next entries:
entry = {
image | item =
tooltip=
is_button = true,
size = {w=,h=}
}
]]
local buttons_grid = table.copy(smartfs._edef.container)
function buttons_grid:onCreate()
self.data.relative = true
assert(self.data.size and self.data.size.w and self.data.size.h, "button needs valid size")
smartfs._edef.container.onCreate(self)
if not self.data.cell_size or not self.data.cell_size.w or not self.data.cell_size.h then
self.data.cell_size = {w=1, h=1}
end
self:setSize(self.data.size.w, self.data.size.h) -- view size for background
self.data.grid_size = {w = math.floor(self.data.size.w/self.data.cell_size.w), h = math.floor(self.data.size.h/self.data.cell_size.h)}
self.data.list_start = self.data.list_start or 1
self.data.list = self.data.list or {}
for x = 1, self.data.grid_size.w do
for y=1, self.data.grid_size.h do
local button = self._state:button(
self.data.pos.x + (x-1)*self.data.cell_size.w,
self.data.pos.y + (y-1)*self.data.cell_size.h,
self.data.cell_size.w,
self.data.cell_size.h,
tostring((y-1)*self.data.grid_size.w+x),
"")
button:onClick(function(self, state, player)
local rel = tonumber(self.name)
local parent_element = state.location.containerElement
local idx = rel
if parent_element.data.list_start > 1 then
idx = parent_element.data.list_start + rel - 2
end
if rel == 1 and parent_element.data.list_start > 1 then
-- page back
local full_pagesize = parent_element.data.grid_size.w * parent_element.data.grid_size.h
if parent_element.data.list_start <= full_pagesize then
parent_element.data.list_start = 1
else
--prev page use allways 2x navigation buttons at list_start > 1 and the next page (we navigate from) exists
parent_element.data.list_start = parent_element.data.list_start - (full_pagesize-2)
end
parent_element:update()
elseif rel == (parent_element.data.grid_size.w * parent_element.data.grid_size.h) and
parent_element.data.list[parent_element.data.list_start+parent_element.data.pagesize] then
-- page forward
parent_element.data.list_start = parent_element.data.list_start+parent_element.data.pagesize
parent_element:update()
else
-- pass call to the button function
if parent_element._click then
parent_element:_click(parent_element.root, idx, player)
end
end
end)
button:setVisible(false)
end
end
end
function buttons_grid:reset(x, y, w, h, col_size, row_size)
self._state = nil
self.data.pos.x = x or self.data.pos.x
self.data.pos.y = y or self.data.pos.y
self.data.size.w = w or self.data.size.w
self.data.size.h = h or self.data.size.h
self.data.cell_size.w = col_size or self.data.cell_size.w
self.data.cell_size.h = row_size or self.data.cell_size.h
self:onCreate()
self:update()
end
function buttons_grid:onClick(func)
self._click = func
end
function buttons_grid:getFirstVisible()
return self.data.list_start
end
function buttons_grid:setFirstVisible(idx)
self.data.list_start = idx
end
function buttons_grid:setList(iconlist)
self.data.list = iconlist or {}
self:update()
end
function buttons_grid:update()
--init pagesize
self.data.pagesize = self.data.grid_size.w * self.data.grid_size.h
--adjust start position
if self.data.list_start > #self.data.list then
self.data.list_start = #self.data.list - self.data.pagesize
end
if self.data.list_start < 1 then
self.data.list_start = 1
end
local itemindex = self.data.list_start
for btnid = 1, self.data.grid_size.w * self.data.grid_size.h do
local button = self._state:get(tostring(btnid))
if btnid == 1 and self.data.list_start > 1 then
-- setup back button
button:setVisible(true)
button:setImage("smart_inventory_left_arrow.png")
button:setText(tostring(self.data.list_start-1))
button:setSize(self.data.cell_size.w, self.data.cell_size.h)
self.data.pagesize = self.data.pagesize - 1
elseif btnid == self.data.grid_size.w * self.data.grid_size.h and self.data.list[itemindex+1] then
-- setup next button
button:setVisible(true)
button:setImage("smart_inventory_right_arrow.png")
self.data.pagesize = self.data.pagesize - 1
button:setText(tostring(#self.data.list-self.data.list_start-self.data.pagesize+1))
button:setSize(self.data.cell_size.w, self.data.cell_size.h)
else
-- functional button
local entry = self.data.list[itemindex]
if entry then
if entry.size then
button:setSize(entry.size.w, entry.size.h)
else
button:setSize(self.data.cell_size.w, self.data.cell_size.h)
end
if entry.item and entry.is_button == true then
button:setVisible(true)
button:setItem(entry.item)
button:setText(entry.text or "")
button:setTooltip(nil)
elseif entry.image and entry.is_button == true then
button:setVisible(true)
button:setImage(entry.image)
button:setText(entry.text or "")
button:setTooltip(entry.tooltip)
-- TODO 1: entry.image to display *.png
-- TODO 2: entry.text to display label on button
-- TODO 3,4,5: is_button == false to get just pic or label without button
end
else
button:setVisible(false)
end
itemindex = itemindex + 1
end
end
end
smartfs.element("buttons_grid", buttons_grid)
function elements:buttons_grid(x, y, w, h, name, col_size, row_size)
return self:element("buttons_grid", {
pos = {x=x, y=y},
size = {w=w, h=h},
cell_size = {w=col_size, h=row_size},
name = name
})
end
-------------------------
return elements

File diff suppressed because it is too large Load Diff

View File

@ -1,651 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.5\n"
msgid "all"
msgstr "Alles"
msgid "other"
msgstr "Weitere"
msgid "antiportal"
msgstr ""
msgid "armor"
msgstr "Rüstung"
msgid "armor:feet"
msgstr "Stiefel"
msgid "armor:fire"
msgstr "Feuerschutz"
msgid "armor:head"
msgstr "Kopfschutz"
msgid "armor:heal"
msgstr "Heilen"
msgid "armor:legs"
msgstr "Beinschutz"
msgid "armor:shield"
msgstr "Schild"
msgid "armor:torso"
msgstr "Körperschutz"
msgid "armor:use"
msgstr "Abnutzung bei Schaden"
msgid "attached_node"
msgstr "Verbundbar"
msgid "bag"
msgstr "Tasche"
msgid "basecolor"
msgstr ""
msgid "basecolor:black"
msgstr ""
msgid "basecolor:blue"
msgstr ""
msgid "basecolor:brown"
msgstr ""
msgid "basecolor:cyan"
msgstr ""
msgid "basecolor:green"
msgstr ""
msgid "basecolor:grey"
msgstr ""
msgid "basecolor:magenta"
msgstr ""
msgid "basecolor:orange"
msgstr ""
msgid "basecolor:red"
msgstr ""
msgid "basecolor:white"
msgstr ""
msgid "basecolor:yellow"
msgstr ""
msgid "bed"
msgstr "Bett"
msgid "bendy"
msgstr ""
msgid "book"
msgstr "Buch"
msgid "bouncy"
msgstr "Federnd"
msgid "cannon"
msgstr ""
msgid "cannonstand"
msgstr ""
msgid "choppy"
msgstr "Abgehackt"
msgid "coal"
msgstr "Kohle"
msgid "color"
msgstr "Farbe"
msgid "color:blue"
msgstr ""
msgid "color:orange"
msgstr ""
msgid "color:red"
msgstr ""
msgid "color:violet"
msgstr ""
msgid "color:white"
msgstr ""
msgid "color:yellow"
msgstr ""
msgid "connect_to_raillike"
msgstr "Schienenartig"
msgid "cools_lava"
msgstr ""
msgid "cracky"
msgstr "Knackig"
msgid "crossbrace_connectable"
msgstr ""
msgid "crumbly"
msgstr "Brüchig"
msgid "customnode"
msgstr "Dekorativer Block"
msgid "damage"
msgstr "Schaden"
msgid "damage:fleshy"
msgstr "Fleischverletzung"
msgid "desert"
msgstr ""
msgid "dig_immediate"
msgstr "Schnell abbaubar"
msgid "dig_immediate:3"
msgstr "Sofort abbaubar"
msgid "disable_jump"
msgstr "Klebrig"
msgid "door"
msgstr "Tür"
msgid "dry_grass"
msgstr ""
msgid "dye"
msgstr "Farbstoff"
msgid "eatable"
msgstr "Essbar"
msgid "excolor"
msgstr ""
msgid "excolor:black"
msgstr ""
msgid "excolor:blue"
msgstr ""
msgid "excolor:cyan"
msgstr ""
msgid "excolor:darkgrey"
msgstr ""
msgid "excolor:green"
msgstr ""
msgid "excolor:grey"
msgstr ""
msgid "excolor:orange"
msgstr ""
msgid "excolor:red"
msgstr ""
msgid "excolor:red:violet"
msgstr ""
msgid "excolor:violet"
msgstr ""
msgid "excolor:white"
msgstr ""
msgid "excolor:yellow"
msgstr ""
msgid "fall_damage_add_percent"
msgstr "Aufprallschaden"
msgid "falling_node"
msgstr "Fallend"
msgid "false"
msgstr ""
msgid "fence"
msgstr "Zaun"
msgid "flammable"
msgstr "Brennbar"
msgid "fleshy"
msgstr "Fleischig"
msgid "flora"
msgstr "Flora"
msgid "flower"
msgstr "Blume"
msgid "food"
msgstr "Nahrung"
msgid "food:apple"
msgstr ""
msgid "food:blueberry"
msgstr ""
msgid "food:bowl"
msgstr ""
msgid "food:butter"
msgstr ""
msgid "food:cactus"
msgstr ""
msgid "food:carrot"
msgstr ""
msgid "food:cheese"
msgstr ""
msgid "food:chicken"
msgstr ""
msgid "food:choco"
msgstr ""
msgid "food:choco:powder"
msgstr ""
msgid "food:cocoa"
msgstr ""
msgid "food:cup"
msgstr ""
msgid "food:dark"
msgstr ""
msgid "food:dark:chocolate"
msgstr ""
msgid "food:egg"
msgstr ""
msgid "food:flour"
msgstr ""
msgid "food:lemon"
msgstr ""
msgid "food:meat"
msgstr ""
msgid "food:meat:raw"
msgstr ""
msgid "food:milk"
msgstr ""
msgid "food:milk:chocolate"
msgstr ""
msgid "food:nut"
msgstr ""
msgid "food:orange"
msgstr ""
msgid "food:pasta"
msgstr ""
msgid "food:potato"
msgstr ""
msgid "food:rhubarb"
msgstr ""
msgid "food:strawberry"
msgstr ""
msgid "food:sugar"
msgstr ""
msgid "food:tomato"
msgstr ""
msgid "food:walnut"
msgstr ""
msgid "food:wheat"
msgstr ""
msgid "fuel"
msgstr "Brennstoff"
msgid "grass"
msgstr "Gras"
msgid "grassland"
msgstr ""
msgid "gunpowder"
msgstr ""
msgid "hot"
msgstr ""
msgid "igniter"
msgstr ""
msgid "ingredient"
msgstr "Erzeugt aus"
msgid "key"
msgstr "Schlüssel"
msgid "lava"
msgstr ""
msgid "leaves"
msgstr "Laub"
msgid "level"
msgstr "Wertvoll"
msgid "light"
msgstr "Lichtquelle"
msgid "liquid"
msgstr ""
msgid "marble"
msgstr ""
msgid "meat"
msgstr ""
msgid "melty"
msgstr ""
msgid "metainv"
msgstr "Mit Inventar"
msgid "mod"
msgstr "Mod"
msgid "not_cuttable"
msgstr ""
msgid "not_in_creative_inventory"
msgstr ""
msgid "oddly_breakable_by_hand"
msgstr "Ohne Werkzeug abbaubar"
msgid "pane"
msgstr ""
msgid "physics"
msgstr ""
msgid "physics:gravity"
msgstr "Erdanziehung"
msgid "physics:speed"
msgstr "Geschwindigkeit"
msgid "plant"
msgstr ""
msgid "poison"
msgstr ""
msgid "potting_soil"
msgstr ""
msgid "puts_out_fire"
msgstr ""
msgid "rail"
msgstr ""
msgid "recipetype"
msgstr ""
msgid "recipetype:cooking"
msgstr "Gekocht"
msgid "rock"
msgstr ""
msgid "sand"
msgstr "Sand"
msgid "sapling"
msgstr ""
msgid "seed"
msgstr "Samen"
msgid "shape"
msgstr "Geformt"
msgid "slab"
msgstr "Platte"
msgid "snappy"
msgstr "Schnittig"
msgid "snowy"
msgstr ""
msgid "soil"
msgstr "Erde"
msgid "soil:1"
msgstr "Ackerboden"
msgid "soil:2"
msgstr "Trockener Ackerboden"
msgid "soil:3"
msgstr "Nasser Ackerboden"
msgid "spreading_dirt_type"
msgstr ""
msgid "stair"
msgstr "Treppe"
msgid "stick"
msgstr "Stock"
msgid "stone"
msgstr "Stein"
msgid "surface_hot"
msgstr ""
msgid "tar_block"
msgstr ""
msgid "tool"
msgstr ""
msgid "tool:full_punch_interval"
msgstr "Verwendungsinterval"
msgid "tool:max_drop_level"
msgstr "Max drop Level"
msgid "torch"
msgstr ""
msgid "translucent"
msgstr "Lichtdurchläßig"
msgid "tree"
msgstr "Baum"
msgid "type"
msgstr ""
msgid "type:craft"
msgstr "Gegenstand"
msgid "type:node"
msgstr "Block"
msgid "type:tool"
msgstr "Werkzeug"
msgid "ud_param2_colorable"
msgstr "Färbbar"
msgid "unicolor"
msgstr ""
msgid "unicolor:black"
msgstr ""
msgid "unicolor:blue"
msgstr ""
msgid "unicolor:cyan"
msgstr ""
msgid "unicolor:dark"
msgstr ""
msgid "unicolor:dark:green"
msgstr ""
msgid "unicolor:dark:orange"
msgstr ""
msgid "unicolor:darkgrey"
msgstr ""
msgid "unicolor:green"
msgstr ""
msgid "unicolor:grey"
msgstr ""
msgid "unicolor:light"
msgstr ""
msgid "unicolor:light:red"
msgstr ""
msgid "unicolor:orange"
msgstr ""
msgid "unicolor:red"
msgstr ""
msgid "unicolor:red:violet"
msgstr ""
msgid "unicolor:violet"
msgstr ""
msgid "unicolor:white"
msgstr ""
msgid "unicolor:yellow"
msgstr ""
msgid "vessel"
msgstr "Behälter"
msgid "wall"
msgstr "Mauer"
msgid "water"
msgstr "Wasser"
msgid "water_bucket"
msgstr "Eimer"
msgid "wet"
msgstr "Nass"
msgid "wood"
msgstr "Holz"
msgid "wool"
msgstr "Wolle"
#~ msgid "physics:jump"
#~ msgstr "Sprunghöhe"
#~ msgid "armor:state"
#~ msgstr "Rüstungsstatus"
#~ msgid "damage:choppy"
#~ msgstr "Abgehackt"
#~ msgid "slope"
#~ msgstr "Neigung"
#~ msgid "leavedecay"
#~ msgstr "Verwelkbar"
#~ msgid "damage:snappy"
#~ msgstr "Schnittverletzung"
#~ msgid "micro"
#~ msgstr "Mikro"
#~ msgid "panel"
#~ msgstr "Paneel"
#~ msgid "armor:level"
#~ msgstr "Level der Rüstung"
#~ msgid "carpet"
#~ msgstr "Teppich"
#~ msgid "explody"
#~ msgstr "Explosiv"
#~ msgid "armor:water"
#~ msgstr "Wasserschutz"
#~ msgid "radiation"
#~ msgstr "Schutz gegen Radioaktivität"
#~ msgid "tool:damage:choppy"
#~ msgstr "Hack-Schaden"
#~ msgid "transluc"
#~ msgstr "Lichtdurchlässig"
#~ msgid "tool:damage:snappy"
#~ msgstr "Schnitt-Schaden"
#~ msgid "tool:damage:fleshy"
#~ msgstr "Wund-Schaden"

View File

@ -1,636 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.5\n"
msgid "all"
msgstr "All items"
msgid "other"
msgstr "Other items"
msgid "antiportal"
msgstr ""
msgid "armor"
msgstr "Armor"
msgid "armor:feet"
msgstr "Feet protection"
msgid "armor:fire"
msgstr "Fire protection"
msgid "armor:head"
msgstr "Head protection"
msgid "armor:heal"
msgstr "Heal"
msgid "armor:legs"
msgstr "Legs protection"
msgid "armor:shield"
msgstr "Shield"
msgid "armor:torso"
msgstr "Torso protection"
msgid "armor:use"
msgstr "Wear on damage"
msgid "attached_node"
msgstr "Attachable"
msgid "bag"
msgstr ""
msgid "basecolor"
msgstr ""
msgid "basecolor:black"
msgstr ""
msgid "basecolor:blue"
msgstr ""
msgid "basecolor:brown"
msgstr ""
msgid "basecolor:cyan"
msgstr ""
msgid "basecolor:green"
msgstr ""
msgid "basecolor:grey"
msgstr ""
msgid "basecolor:magenta"
msgstr ""
msgid "basecolor:orange"
msgstr ""
msgid "basecolor:red"
msgstr ""
msgid "basecolor:white"
msgstr ""
msgid "basecolor:yellow"
msgstr ""
msgid "bed"
msgstr "Bed"
msgid "bendy"
msgstr ""
msgid "book"
msgstr "Book"
msgid "bouncy"
msgstr "Bouncy"
msgid "cannon"
msgstr ""
msgid "cannonstand"
msgstr ""
msgid "choppy"
msgstr "Choppy"
msgid "coal"
msgstr "Coal"
msgid "color"
msgstr "Colour"
msgid "color:blue"
msgstr ""
msgid "color:orange"
msgstr ""
msgid "color:red"
msgstr ""
msgid "color:violet"
msgstr ""
msgid "color:white"
msgstr ""
msgid "color:yellow"
msgstr ""
msgid "connect_to_raillike"
msgstr "Rail-like"
msgid "cools_lava"
msgstr ""
msgid "cracky"
msgstr "Cracky"
msgid "crossbrace_connectable"
msgstr ""
msgid "crumbly"
msgstr "Crumbly"
msgid "customnode"
msgstr "Decorative node"
msgid "damage"
msgstr "Damage"
msgid "damage:fleshy"
msgstr "Fleshy damage"
msgid "desert"
msgstr "Desert"
msgid "dig_immediate"
msgstr "Fast diggable"
msgid "dig_immediate:3"
msgstr "Immediate diggable"
msgid "disable_jump"
msgstr "Sticky"
msgid "door"
msgstr "Door"
msgid "dry_grass"
msgstr "Dry grass"
msgid "dye"
msgstr "Dye"
msgid "eatable"
msgstr "Eatable"
msgid "excolor"
msgstr ""
msgid "excolor:black"
msgstr ""
msgid "excolor:blue"
msgstr ""
msgid "excolor:cyan"
msgstr ""
msgid "excolor:darkgrey"
msgstr ""
msgid "excolor:green"
msgstr ""
msgid "excolor:grey"
msgstr ""
msgid "excolor:orange"
msgstr ""
msgid "excolor:red"
msgstr ""
msgid "excolor:red:violet"
msgstr ""
msgid "excolor:violet"
msgstr ""
msgid "excolor:white"
msgstr ""
msgid "excolor:yellow"
msgstr ""
msgid "fall_damage_add_percent"
msgstr "Fall damage"
msgid "falling_node"
msgstr "Falling"
msgid "false"
msgstr ""
msgid "fence"
msgstr "Fence"
msgid "flammable"
msgstr "Flammable"
msgid "fleshy"
msgstr "Fleshy"
msgid "flora"
msgstr "Flora"
msgid "flower"
msgstr "Flower"
msgid "food"
msgstr "Food"
msgid "food:apple"
msgstr ""
msgid "food:blueberry"
msgstr ""
msgid "food:bowl"
msgstr ""
msgid "food:butter"
msgstr ""
msgid "food:cactus"
msgstr ""
msgid "food:carrot"
msgstr ""
msgid "food:cheese"
msgstr ""
msgid "food:chicken"
msgstr ""
msgid "food:choco"
msgstr ""
msgid "food:choco:powder"
msgstr ""
msgid "food:cocoa"
msgstr ""
msgid "food:cup"
msgstr ""
msgid "food:dark"
msgstr ""
msgid "food:dark:chocolate"
msgstr ""
msgid "food:egg"
msgstr ""
msgid "food:flour"
msgstr ""
msgid "food:lemon"
msgstr ""
msgid "food:meat"
msgstr ""
msgid "food:meat:raw"
msgstr ""
msgid "food:milk"
msgstr ""
msgid "food:milk:chocolate"
msgstr ""
msgid "food:nut"
msgstr ""
msgid "food:orange"
msgstr ""
msgid "food:pasta"
msgstr ""
msgid "food:potato"
msgstr ""
msgid "food:rhubarb"
msgstr ""
msgid "food:strawberry"
msgstr ""
msgid "food:sugar"
msgstr ""
msgid "food:tomato"
msgstr ""
msgid "food:walnut"
msgstr ""
msgid "food:wheat"
msgstr ""
msgid "fuel"
msgstr "Fuel"
msgid "grass"
msgstr "Grass"
msgid "grassland"
msgstr ""
msgid "gunpowder"
msgstr ""
msgid "hot"
msgstr "Hot"
msgid "igniter"
msgstr ""
msgid "ingredient"
msgstr "Crafted with"
msgid "key"
msgstr "Key"
msgid "lava"
msgstr ""
msgid "leaves"
msgstr "Leaves"
msgid "level"
msgstr "Valuable"
msgid "light"
msgstr "Light source"
msgid "liquid"
msgstr ""
msgid "marble"
msgstr ""
msgid "meat"
msgstr ""
msgid "melty"
msgstr ""
msgid "metainv"
msgstr "With inventory"
msgid "mod"
msgstr "Mod"
msgid "not_cuttable"
msgstr ""
msgid "not_in_creative_inventory"
msgstr ""
msgid "oddly_breakable_by_hand"
msgstr "Oddly breakable"
msgid "pane"
msgstr ""
msgid "physics"
msgstr ""
msgid "physics:gravity"
msgstr "Gravity"
msgid "physics:speed"
msgstr "Walking speed"
msgid "plant"
msgstr ""
msgid "poison"
msgstr ""
msgid "potting_soil"
msgstr ""
msgid "puts_out_fire"
msgstr ""
msgid "rail"
msgstr ""
msgid "recipetype"
msgstr ""
msgid "recipetype:cooking"
msgstr "Cooking result"
msgid "rock"
msgstr ""
msgid "sand"
msgstr "Sand"
msgid "sapling"
msgstr "Sapling"
msgid "seed"
msgstr "Seed"
msgid "shape"
msgstr "Shape"
msgid "slab"
msgstr "Slab"
msgid "snappy"
msgstr "Snappy"
msgid "snowy"
msgstr "Snowy"
msgid "soil"
msgstr "Soil"
msgid "soil:1"
msgstr "Basic soil"
msgid "soil:2"
msgstr "Dry farming soil"
msgid "soil:3"
msgstr "Wet farming"
msgid "spreading_dirt_type"
msgstr ""
msgid "stair"
msgstr "Stair"
msgid "stick"
msgstr "Stick"
msgid "stone"
msgstr "Stone"
msgid "surface_hot"
msgstr ""
msgid "tar_block"
msgstr ""
msgid "tool"
msgstr ""
msgid "tool:full_punch_interval"
msgstr "Punch interval"
msgid "tool:max_drop_level"
msgstr "Max drop level"
msgid "torch"
msgstr "Torch"
msgid "translucent"
msgstr "Translucent"
msgid "tree"
msgstr "Tree"
msgid "type"
msgstr ""
msgid "type:craft"
msgstr "Item"
msgid "type:node"
msgstr "Node"
msgid "type:tool"
msgstr "Tool"
msgid "ud_param2_colorable"
msgstr "Colorable by dye punch"
msgid "unicolor"
msgstr ""
msgid "unicolor:black"
msgstr ""
msgid "unicolor:blue"
msgstr ""
msgid "unicolor:cyan"
msgstr ""
msgid "unicolor:dark"
msgstr ""
msgid "unicolor:dark:green"
msgstr ""
msgid "unicolor:dark:orange"
msgstr ""
msgid "unicolor:darkgrey"
msgstr ""
msgid "unicolor:green"
msgstr ""
msgid "unicolor:grey"
msgstr ""
msgid "unicolor:light"
msgstr ""
msgid "unicolor:light:red"
msgstr ""
msgid "unicolor:orange"
msgstr ""
msgid "unicolor:red"
msgstr ""
msgid "unicolor:red:violet"
msgstr ""
msgid "unicolor:violet"
msgstr ""
msgid "unicolor:white"
msgstr ""
msgid "unicolor:yellow"
msgstr ""
msgid "vessel"
msgstr "Vessel"
msgid "wall"
msgstr "Wall"
msgid "water"
msgstr "Water"
msgid "water_bucket"
msgstr "Bucket"
msgid "wet"
msgstr ""
msgid "wood"
msgstr "Wood"
msgid "wool"
msgstr "Wool"
#~ msgid "physics:jump"
#~ msgstr "Jump high"
#~ msgid "armor:state"
#~ msgstr "Armor state"
#~ msgid "damage:choppy"
#~ msgstr "Choppy damage"
#~ msgid "slope"
#~ msgstr "Slope"
#~ msgid "leavedecay"
#~ msgstr "Decayable"
#~ msgid "damage:snappy"
#~ msgstr "Snappy damage"
#~ msgid "micro"
#~ msgstr "Micro"
#~ msgid "panel"
#~ msgstr "Panel"
#~ msgid "armor:level"
#~ msgstr "Armor level"
#~ msgid "carpet"
#~ msgstr "Carpet"
#~ msgid "explody"
#~ msgstr "Explosive"
#~ msgid "armor:water"
#~ msgstr "Water protection"

View File

@ -1,588 +0,0 @@
msgid "all"
msgstr ""
msgid "other"
msgstr ""
msgid "antiportal"
msgstr ""
msgid "armor"
msgstr ""
msgid "armor:feet"
msgstr ""
msgid "armor:fire"
msgstr ""
msgid "armor:head"
msgstr ""
msgid "armor:heal"
msgstr ""
msgid "armor:legs"
msgstr ""
msgid "armor:shield"
msgstr ""
msgid "armor:torso"
msgstr ""
msgid "armor:use"
msgstr ""
msgid "attached_node"
msgstr ""
msgid "bag"
msgstr ""
msgid "basecolor"
msgstr ""
msgid "basecolor:black"
msgstr ""
msgid "basecolor:blue"
msgstr ""
msgid "basecolor:brown"
msgstr ""
msgid "basecolor:cyan"
msgstr ""
msgid "basecolor:green"
msgstr ""
msgid "basecolor:grey"
msgstr ""
msgid "basecolor:magenta"
msgstr ""
msgid "basecolor:orange"
msgstr ""
msgid "basecolor:red"
msgstr ""
msgid "basecolor:white"
msgstr ""
msgid "basecolor:yellow"
msgstr ""
msgid "bed"
msgstr ""
msgid "bendy"
msgstr ""
msgid "book"
msgstr ""
msgid "bouncy"
msgstr ""
msgid "cannon"
msgstr ""
msgid "cannonstand"
msgstr ""
msgid "choppy"
msgstr ""
msgid "coal"
msgstr ""
msgid "color"
msgstr ""
msgid "color:blue"
msgstr ""
msgid "color:orange"
msgstr ""
msgid "color:red"
msgstr ""
msgid "color:violet"
msgstr ""
msgid "color:white"
msgstr ""
msgid "color:yellow"
msgstr ""
msgid "connect_to_raillike"
msgstr ""
msgid "cools_lava"
msgstr ""
msgid "cracky"
msgstr ""
msgid "crossbrace_connectable"
msgstr ""
msgid "crumbly"
msgstr ""
msgid "customnode"
msgstr ""
msgid "damage"
msgstr ""
msgid "damage:fleshy"
msgstr ""
msgid "desert"
msgstr ""
msgid "dig_immediate"
msgstr ""
msgid "dig_immediate:3"
msgstr ""
msgid "disable_jump"
msgstr ""
msgid "door"
msgstr ""
msgid "dry_grass"
msgstr ""
msgid "dye"
msgstr ""
msgid "eatable"
msgstr ""
msgid "excolor"
msgstr ""
msgid "excolor:black"
msgstr ""
msgid "excolor:blue"
msgstr ""
msgid "excolor:cyan"
msgstr ""
msgid "excolor:darkgrey"
msgstr ""
msgid "excolor:green"
msgstr ""
msgid "excolor:grey"
msgstr ""
msgid "excolor:orange"
msgstr ""
msgid "excolor:red"
msgstr ""
msgid "excolor:red:violet"
msgstr ""
msgid "excolor:violet"
msgstr ""
msgid "excolor:white"
msgstr ""
msgid "excolor:yellow"
msgstr ""
msgid "fall_damage_add_percent"
msgstr ""
msgid "falling_node"
msgstr ""
msgid "false"
msgstr ""
msgid "fence"
msgstr ""
msgid "flammable"
msgstr ""
msgid "fleshy"
msgstr ""
msgid "flora"
msgstr ""
msgid "flower"
msgstr ""
msgid "food"
msgstr ""
msgid "food:apple"
msgstr ""
msgid "food:blueberry"
msgstr ""
msgid "food:bowl"
msgstr ""
msgid "food:butter"
msgstr ""
msgid "food:cactus"
msgstr ""
msgid "food:carrot"
msgstr ""
msgid "food:cheese"
msgstr ""
msgid "food:chicken"
msgstr ""
msgid "food:choco"
msgstr ""
msgid "food:choco:powder"
msgstr ""
msgid "food:cocoa"
msgstr ""
msgid "food:cup"
msgstr ""
msgid "food:dark"
msgstr ""
msgid "food:dark:chocolate"
msgstr ""
msgid "food:egg"
msgstr ""
msgid "food:flour"
msgstr ""
msgid "food:lemon"
msgstr ""
msgid "food:meat"
msgstr ""
msgid "food:meat:raw"
msgstr ""
msgid "food:milk"
msgstr ""
msgid "food:milk:chocolate"
msgstr ""
msgid "food:nut"
msgstr ""
msgid "food:orange"
msgstr ""
msgid "food:pasta"
msgstr ""
msgid "food:potato"
msgstr ""
msgid "food:rhubarb"
msgstr ""
msgid "food:strawberry"
msgstr ""
msgid "food:sugar"
msgstr ""
msgid "food:tomato"
msgstr ""
msgid "food:walnut"
msgstr ""
msgid "food:wheat"
msgstr ""
msgid "fuel"
msgstr ""
msgid "grass"
msgstr ""
msgid "grassland"
msgstr ""
msgid "gunpowder"
msgstr ""
msgid "hot"
msgstr ""
msgid "igniter"
msgstr ""
msgid "ingredient"
msgstr ""
msgid "key"
msgstr ""
msgid "lava"
msgstr ""
msgid "leaves"
msgstr ""
msgid "level"
msgstr ""
msgid "light"
msgstr ""
msgid "liquid"
msgstr ""
msgid "marble"
msgstr ""
msgid "meat"
msgstr ""
msgid "melty"
msgstr ""
msgid "metainv"
msgstr ""
msgid "mod"
msgstr ""
msgid "not_cuttable"
msgstr ""
msgid "not_in_creative_inventory"
msgstr ""
msgid "oddly_breakable_by_hand"
msgstr ""
msgid "pane"
msgstr ""
msgid "physics"
msgstr ""
msgid "physics:gravity"
msgstr ""
msgid "physics:speed"
msgstr ""
msgid "plant"
msgstr ""
msgid "poison"
msgstr ""
msgid "potting_soil"
msgstr ""
msgid "puts_out_fire"
msgstr ""
msgid "rail"
msgstr ""
msgid "recipetype"
msgstr ""
msgid "recipetype:cooking"
msgstr ""
msgid "rock"
msgstr ""
msgid "sand"
msgstr ""
msgid "sapling"
msgstr ""
msgid "seed"
msgstr ""
msgid "shape"
msgstr ""
msgid "slab"
msgstr ""
msgid "snappy"
msgstr ""
msgid "snowy"
msgstr ""
msgid "soil"
msgstr ""
msgid "soil:1"
msgstr ""
msgid "soil:2"
msgstr ""
msgid "soil:3"
msgstr ""
msgid "spreading_dirt_type"
msgstr ""
msgid "stair"
msgstr ""
msgid "stick"
msgstr ""
msgid "stone"
msgstr ""
msgid "surface_hot"
msgstr ""
msgid "tar_block"
msgstr ""
msgid "tool"
msgstr ""
msgid "tool:full_punch_interval"
msgstr ""
msgid "tool:max_drop_level"
msgstr ""
msgid "torch"
msgstr ""
msgid "translucent"
msgstr ""
msgid "tree"
msgstr ""
msgid "type"
msgstr ""
msgid "type:craft"
msgstr ""
msgid "type:node"
msgstr ""
msgid "type:tool"
msgstr ""
msgid "ud_param2_colorable"
msgstr ""
msgid "unicolor"
msgstr ""
msgid "unicolor:black"
msgstr ""
msgid "unicolor:blue"
msgstr ""
msgid "unicolor:cyan"
msgstr ""
msgid "unicolor:dark"
msgstr ""
msgid "unicolor:dark:green"
msgstr ""
msgid "unicolor:dark:orange"
msgstr ""
msgid "unicolor:darkgrey"
msgstr ""
msgid "unicolor:green"
msgstr ""
msgid "unicolor:grey"
msgstr ""
msgid "unicolor:light"
msgstr ""
msgid "unicolor:light:red"
msgstr ""
msgid "unicolor:orange"
msgstr ""
msgid "unicolor:red"
msgstr ""
msgid "unicolor:red:violet"
msgstr ""
msgid "unicolor:violet"
msgstr ""
msgid "unicolor:white"
msgstr ""
msgid "unicolor:yellow"
msgstr ""
msgid "vessel"
msgstr ""
msgid "wall"
msgstr ""
msgid "water"
msgstr ""
msgid "water_bucket"
msgstr ""
msgid "wet"
msgstr ""
msgid "wood"
msgstr ""
msgid "wool"
msgstr ""

View File

@ -1,4 +0,0 @@
name = smart_inventory
title = Smart Inventory
author = bell07
license = CC0

View File

@ -1,33 +0,0 @@
if not minetest.get_modpath("awards") then
return
end
local function awards_callback(state)
local codebox = state:element("code", { name = "code", code = "", playername = state.location.rootState.location.player })
codebox:onBuild(function(self)
local formspec = awards.getFormspec(self.data.playername, self.data.playername, self.data.awards_idx or 1)
-- patch elememt sizes and positions
formspec = formspec:gsub('textarea%[0.25,3.75;3.9,4.2', 'textarea[-0.75,3.75;5.9,4.2')
formspec = formspec:gsub('box%[%-0.05,3.75;3.9,4.2', 'box[-1.05,3.75;5.9,4.2')
formspec = formspec:gsub('textlist%[4,0;3.8,8.6', 'textlist[6,0;6.8,8.6')
self.data.code = "container[3,0]".. formspec .."container_end[]"
end)
state:onInput(function(state, fields, player)
if fields.awards then
local event = minetest.explode_textlist_event(fields.awards)
if event.type == "CHG" then
state:get("code").data.awards_idx = event.index
end
end
end)
end
smart_inventory.register_page({
name = "awards",
icon = "awards_ui_icon.png",
tooltip = "Awards",
smartfs_callback = awards_callback,
sequence = 25,
})

View File

@ -1,760 +0,0 @@
local cache = smart_inventory.cache
local crecipes = smart_inventory.crecipes
local doc_addon = smart_inventory.doc_addon
local ui_tools = smart_inventory.ui_tools
-----------------------------------------------------
-- Update recipe preview item informations about the selected item
-----------------------------------------------------
local function update_crafting_preview(state)
local player = state.location.rootState.location.player
local listentry = state.param.crafting_recipes_preview_listentry
local selected = state.param.crafting_recipes_preview_selected
local itemdef = listentry.itemdef
local inf_state = state:get("inf_area"):getContainerState()
local cr_type_img = state:get("cr_type_img")
local craft_result = inf_state:get("craft_result")
local group_list = inf_state:get("item_groups")
-- get recipe to display, check paging buttons needed
local all_recipes
local valid_recipes = {}
local recipe
local revealed_items_cache = {}
if listentry.recipes then -- preselected recipes (ie. craftable)
all_recipes = listentry.recipes
elseif cache.citems[listentry.item] then -- check all available recipes (ie. search)
all_recipes = cache.citems[listentry.item].in_output_recipe or {}
else -- no recipes
all_recipes = {}
end
for _, recipe in ipairs(all_recipes) do
if crecipes.crecipes[recipe]:is_revealed(player, revealed_items_cache) then
table.insert(valid_recipes, recipe)
end
end
if valid_recipes[1] then
if not valid_recipes[selected] then
selected = 1
end
state.param.crafting_recipes_preview_selected = selected
if selected > 1 and valid_recipes[selected-1] then
state:get("preview_prev"):setVisible(true)
else
state:get("preview_prev"):setVisible(false)
end
if valid_recipes[selected+1] then
state:get("preview_next"):setVisible(true)
else
state:get("preview_next"):setVisible(false)
end
if valid_recipes[selected] then
recipe = valid_recipes[selected]
local crecipe = crecipes.crecipes[recipe]
if crecipe then
recipe = crecipe:get_with_placeholder(player, state.param.crafting_items_in_inventory)
end
end
else
state:get("preview_prev"):setVisible(false)
state:get("preview_next"):setVisible(false)
end
-- display the recipe result or selected item
if recipe then
if recipe.type == "normal" then
state:get("cr_type"):setText("")
cr_type_img:setVisible(false)
state:get("ac1"):setVisible(true)
elseif recipe.type == "cooking" then
state:get("cr_type"):setText(recipe.type)
state:get("cr_type"):setText("")
cr_type_img:setVisible(true)
cr_type_img:setImage("smart_inventory_furnace.png")
state:get("ac1"):setVisible(false)
else
state:get("cr_type"):setText(recipe.type)
cr_type_img:setVisible(false)
state:get("ac1"):setVisible(false)
end
craft_result:setImage(recipe.output)
craft_result:setVisible()
state:get("craft_preview"):setCraft(recipe)
else
state:get("cr_type"):setText("")
state:get("craft_preview"):setCraft(nil)
cr_type_img:setVisible(false)
state:get("ac1"):setVisible(false)
if itemdef then
craft_result:setVisible(true)
craft_result:setImage(itemdef.name)
else
craft_result:setVisible(false)
end
end
-- display docs icon if revealed item
if smart_inventory.doc_items_mod then
inf_state:get("doc_btn"):setVisible(false)
local outitem = craft_result:getImage()
if outitem then
for z in outitem:gmatch("[^%s]+") do
if doc_addon.is_revealed_item(z, player) then
inf_state:get("doc_btn"):setVisible(true)
end
break
end
end
end
-- update info area
if itemdef then
inf_state:get("info1"):setText(itemdef.description)
inf_state:get("info2"):setText("("..itemdef.name..")")
if itemdef._doc_items_longdesc then
inf_state:get("info3"):setText(itemdef._doc_items_longdesc)
else
inf_state:get("info3"):setText("")
end
group_list:clearItems()
cache.add_item(listentry.itemdef) -- Note: this addition does not affect the already prepared root lists
if cache.citems[itemdef.name] then
for _, groupdef in ipairs(ui_tools.get_tight_groups(cache.citems[itemdef.name].cgroups)) do
group_list:addItem(groupdef.group_desc)
end
end
elseif listentry.item then
inf_state:get("info1"):setText("")
inf_state:get("info2"):setText("("..listentry.item..")")
inf_state:get("info3"):setText("")
else
inf_state:get("info1"):setText("")
inf_state:get("info2"):setText("")
inf_state:get("info3"):setText("")
group_list:clearItems()
end
end
-----------------------------------------------------
-- Update the group selection table
-----------------------------------------------------
local function update_group_selection(state, rebuild)
local grouped = state.param.crafting_grouped_items
local groups_sel = state:get("groups_sel")
local grid = state:get("buttons_grid")
local label = state:get("inf_area"):getContainerState():get("groups_label")
if rebuild then
state.param.crafting_group_list = ui_tools.update_group_selection(grouped, groups_sel, state.param.crafting_group_list)
end
local sel_id = groups_sel:getSelected()
if state.param.crafting_group_list[sel_id] then
state.param.crafting_craftable_list = grouped[state.param.crafting_group_list[sel_id]].items
table.sort(state.param.crafting_craftable_list, function(a,b)
return a.sort_value < b.sort_value
end)
grid:setList(state.param.crafting_craftable_list)
label:setText(groups_sel:getSelectedItem())
else
label:setText("Empty List")
grid:setList({})
end
end
-----------------------------------------------------
-- Update the items list
-----------------------------------------------------
local function update_from_recipelist(state, recipelist, preview_item, replace_not_in_list)
local old_preview_entry, old_preview_item, new_preview_entry, new_preview_item
if state.param.crafting_recipes_preview_listentry then
old_preview_item = state.param.crafting_recipes_preview_listentry.item
end
if preview_item == "" then
new_preview_item = nil
else
new_preview_item = preview_item
end
local duplicate_index_tmp = {}
local craftable_itemlist = {}
for recipe, _ in pairs(recipelist) do
local def = crecipes.crecipes[recipe].out_item
local itemname = def.name
if duplicate_index_tmp[itemname] then
table.insert(duplicate_index_tmp[itemname].recipes, recipe)
else
local entry = {}
for k,v in pairs(cache.citems[itemname].ui_item) do
entry[k] = v
end
entry.recipes = {}
duplicate_index_tmp[itemname] = entry
table.insert(entry.recipes, recipe)
table.insert(craftable_itemlist, entry)
if new_preview_item and itemname == new_preview_item then
new_preview_entry = entry
end
if old_preview_item and itemname == old_preview_item then
old_preview_entry = entry
end
end
end
-- update crafting preview if the old is not in list anymore
if new_preview_item then
if not replace_not_in_list or not old_preview_entry then
if not new_preview_entry then
new_preview_entry = {
itemdef = minetest.registered_items[new_preview_item],
item = new_preview_item
}
end
state.param.crafting_recipes_preview_selected = 1
state.param.crafting_recipes_preview_listentry = new_preview_entry
update_crafting_preview(state)
if state:get("info_tog"):getId() == 1 then
state:get("info_tog"):submit()
end
end
elseif replace_not_in_list and not old_preview_entry then
state.param.crafting_recipes_preview_selected = 1
state.param.crafting_recipes_preview_listentry = {}
update_crafting_preview(state)
end
-- update the groups selection
state.param.crafting_grouped_items = ui_tools.get_list_grouped(craftable_itemlist)
update_group_selection(state, true)
end
-----------------------------------------------------
-- Build list matching the placed grid
-----------------------------------------------------
local function update_from_grid(state, craft_grid, lookup_item)
-- get all grid items for reference
local player = state.location.rootState.location.player
local reference_items = {}
local items_hash = ""
for _, stack in ipairs(craft_grid) do
local name = stack:get_name()
if name and name ~= "" then
reference_items[name] = true
items_hash=items_hash.."|"..name
else
items_hash=items_hash.."|empty"
end
end
if items_hash ~= state.param.survival_grid_items_hash then
state.param.survival_grid_items_hash = items_hash
if next(reference_items) then
-- update the grid with matched recipe items
local recipes = crecipes.get_recipes_started_craft(player, craft_grid, reference_items)
update_from_recipelist(state, recipes, lookup_item, true) -- replace_not_in_list=true
end
end
end
-----------------------------------------------------
-- Lookup for item lookup_item
-----------------------------------------------------
local function do_lookup_item(state, playername, lookup_item)
state.param.crafting_items_in_inventory = state.param.invobj:get_items()
state.param.crafting_items_in_inventory[lookup_item] = true -- prefer in recipe preview
-- get all craftable recipes with lookup-item as ingredient. Add recipes of lookup item to the list
local recipes = crecipes.get_revealed_recipes_with_items(playername, {[lookup_item] = true })
update_from_recipelist(state, recipes, lookup_item)
state.param.crafting_ui_controller:update_list_variant("lookup", lookup_item)
end
-----------------------------------------------------
-- Lookup inventory
-----------------------------------------------------
local function create_lookup_inv(name)
local player = minetest.get_player_by_name(name)
local invname = name.."_crafting_inv"
local plistname = "crafting_inv_lookup"
local listname = "lookup"
local pinv = player:get_inventory()
local inv = minetest.get_inventory({type="detached", name=invname})
if not inv then
inv = minetest.create_detached_inventory(invname, {
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
return 0
end,
allow_put = function(inv, listname, index, stack, player)
if pinv:is_empty(plistname) then
return 99
else
return 0
end
end,
allow_take = function(inv, listname, index, stack, player)
return 99
end,
on_put = function(inv, listname, index, stack, player)
pinv:set_stack(plistname, index, stack)
local name = player:get_player_name()
local state = smart_inventory.get_page_state("crafting", name)
do_lookup_item(state, name, stack:get_name())
-- we are outsite of usual smartfs processing. So trigger the formspec update byself
state.location.rootState:show()
-- put back
minetest.after(1, function()
-- Check maybe player is away from the game
local player = minetest.get_player_by_name(name)
if not player then
return
end
-- Check the player did not removed item from lookup field
local pinv = player:get_inventory()
local inv = minetest.get_inventory({type="detached", name=invname})
local stack = pinv:get_stack(plistname, 1)
-- put back
local applied = pinv:add_item("main", stack)
pinv:set_stack(plistname, 1, applied)
inv:set_stack(listname, 1, applied)
end)
end,
on_take = function(inv, listname, index, stack, player)
pinv:set_stack(plistname, index, nil)
end,
}, name)
end
-- copy the item from player:listname inventory to the detached
inv:set_size(listname, 1)
pinv:set_size(plistname, 1)
local stack = pinv:get_stack(plistname, 1)
inv:set_stack(listname, 1, stack)
end
-----------------------------------------------------
-- Page layout definition
-----------------------------------------------------
local function crafting_callback(state)
local player = state.location.rootState.location.player
-- build up UI controller
local ui_controller = {}
ui_controller.state = state
ui_controller.player = minetest.get_player_by_name(state.location.rootState.location.player)
state.param.crafting_ui_controller = ui_controller
function ui_controller:set_ui_variant(new_ui)
-- check if change needed
if new_ui == self.toggle1 or new_ui == self.toggle2 then
return
end
-- toggle show/hide elements
if new_ui == 'list_small' then
self.toggle1 = new_ui
self.state:get("craft_img2"):setVisible(true) --rahmen oben
self.state:get("lookup_icon"):setPosition(10, 4)
self.state:get("lookup"):setPosition(10, 4)
self.state:get("craftable"):setPosition(11, 4)
self.state:get("btn_all"):setPosition(11, 4.5)
self.state:get("btn_grid"):setPosition(11.5, 4.0)
if smart_inventory.doc_items_mod then
self.state:get("reveal_tipp"):setPosition(11.5, 4.5)
end
self.state:get("search"):setPosition(12.2, 4.5)
self.state:get("search_bg"):setPosition(12, 4)
self.state:get("search_btn"):setPosition(15.2, 4.2)
self.state:get("info_tog"):setPosition(16.2, 4.2)
self.state:get("buttons_grid_Bg"):setPosition(10, 5)
self.state:get("buttons_grid_Bg"):setSize(8, 4)
self.state:get("buttons_grid"):reset(10.25, 5.15, 8, 4)
elseif new_ui == 'list_big' then
self.toggle1 = new_ui
self.state:get("craft_img2"):setVisible(false) --rahmen oben
self.state:get("lookup_icon"):setPosition(10, 0)
self.state:get("lookup"):setPosition(10, 0)
self.state:get("craftable"):setPosition(11, 0)
self.state:get("btn_all"):setPosition(11, 0.5)
self.state:get("btn_grid"):setPosition(11.5, 0.0)
if smart_inventory.doc_items_mod then
self.state:get("reveal_tipp"):setPosition(11.5, 0.5)
end
self.state:get("search"):setPosition(12.2, 0.5)
self.state:get("search_bg"):setPosition(12, 0)
self.state:get("search_btn"):setPosition(15.2, 0.2)
self.state:get("info_tog"):setPosition(16.2, 0.2)
self.state:get("groups_sel"):setVisible(false)
self.state:get("inf_area"):setVisible(false)
self.state:get("buttons_grid_Bg"):setPosition(10, 1)
self.state:get("buttons_grid_Bg"):setSize(8, 8)
self.state:get("buttons_grid"):reset(10.25, 1.15, 8, 8)
self.state:get("info_tog"):setId(3)
else
self.toggle2 = new_ui
end
if self.toggle1 == 'list_small' then
if self.toggle2 == 'info' then
self.state:get("groups_sel"):setVisible(false)
self.state:get("inf_area"):setVisible(true)
self.state:get("info_tog"):setId(1)
elseif self.toggle2 == 'groups' then
self.state:get("groups_sel"):setVisible(true)
self.state:get("inf_area"):setVisible(false)
self.state:get("info_tog"):setId(2)
end
end
self:save()
end
function ui_controller:update_list_variant(list_variant, add_info)
self.add_info = add_info
-- reset group selection and search field on proposal mode change
if self.list_variant ~= list_variant then
self.list_variant = list_variant
self.state:get("groups_sel"):setSelected(1)
if list_variant ~= "search" then
self.state:get("search"):setText("")
end
end
-- auto-switch to the groups
if list_variant == "lookup" or list_variant == "reveal_tipp" then
state.param.crafting_ui_controller:set_ui_variant("info")
else
state.param.crafting_ui_controller:set_ui_variant("groups")
end
state:get("lookup_icon"):setBackground()
state:get("search_bg"):setBackground()
state:get("craftable"):setBackground()
state:get("btn_grid"):setBackground()
state:get("btn_all"):setBackground()
if smart_inventory.doc_items_mod then
state:get("reveal_tipp"):setBackground()
end
-- highlight the right button
if list_variant == "lookup" then
state:get("lookup_icon"):setBackground("halo.png")
elseif list_variant == "search" then
state:get("search_bg"):setBackground("halo.png")
elseif list_variant == "craftable" then
state:get("craftable"):setBackground("halo.png")
elseif list_variant == "grid" then
state:get("btn_grid"):setBackground("halo.png")
elseif list_variant == "btn_all" then
state:get("btn_all"):setBackground("halo.png")
elseif list_variant == "reveal_tipp" then
state:get("reveal_tipp"):setBackground("halo.png")
end
self:save()
end
function ui_controller:save()
local savedata = minetest.deserialize(self.player:get_attribute("smart_inventory_settings")) or {}
savedata.survival_list_variant = self.list_variant
savedata.survival_toggle1 = self.toggle1
savedata.survival_toggle2 = self.toggle2
savedata.survival_lookup_item = self.lookup_item
savedata.survival_add_info = self.add_info
self.player:set_attribute("smart_inventory_settings", minetest.serialize(savedata))
end
function ui_controller:restore()
local savedata = minetest.deserialize(self.player:get_attribute("smart_inventory_settings")) or {}
if savedata.survival_toggle1 then
self:set_ui_variant(savedata.survival_toggle1)
end
if savedata.survival_toggle2 then
self:set_ui_variant(savedata.survival_toggle2)
end
if savedata.survival_list_variant then
if savedata.survival_list_variant == "search" then
local ui_text = self.state:get(savedata.survival_list_variant)
ui_text:setText(savedata.survival_add_info)
ui_text:submit_key_enter("unused", self.state.location.rootState.location.player)
elseif savedata.survival_list_variant == "lookup" then
do_lookup_item(self.state, self.state.location.rootState.location.player, savedata.survival_add_info)
else
local ui_button = self.state:get(savedata.survival_list_variant)
if ui_button then
ui_button:submit("unused", self.state.location.rootState.location.player)
end
end
else
self.state:get("craftable"):submit("unused", self.state.location.rootState.location.player)
self:set_ui_variant("groups")
self:update_list_variant("craftable")
end
end
-- set inventory style
state:element("code", {name = "additional_code", code =
"listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]"..
"listring[current_player;main]listring[current_player;craft]"
})
--Inventorys / left site
state:inventory(1, 5, 8, 4,"main")
state:inventory(1.2, 0.2, 3, 3,"craft")
state:inventory(4.3, 1.2, 1, 1,"craftpreview")
state:background(1, 0, 4.5, 3.5, "img1", "menu_bg.png")
-- crafting helper buttons
local btn_ac1 = state:image_button(4.4, 0.3, 0.8, 0.8, "ac1", "", "smart_inventory_preview_to_crafting_field.png")
btn_ac1:onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "crafting", "ac1")
local grid = state:get("craft_preview"):getCraft()
state.param.invobj:craft_item(grid)
end)
btn_ac1:setVisible(false)
-- swap slots buttons
state:image_button(0, 6, 1, 1, "swap1", "", "smart_inventory_swapline_button.png"):onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "crafting", "swap1")
state.param.invobj:swap_row_to_top(2)
end)
state:image_button(0, 7, 1, 1, "swap2", "", "smart_inventory_swapline_button.png"):onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "crafting", "swap2")
state.param.invobj:swap_row_to_top(3)
end)
state:image_button(0, 8, 1, 1, "swap3", "", "smart_inventory_swapline_button.png"):onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "crafting", "swap3")
state.param.invobj:swap_row_to_top(4)
end)
ui_tools.create_trash_inv(state, player)
state:image(8,9,1,1,"trash_icon","smart_inventory_trash.png")
state:inventory(8, 9, 1, 1, "trash"):useDetached(player.."_trash_inv")
local btn_compress = state:image_button(1, 3.8, 1, 1, "compress", "","smart_inventory_compress_button.png")
btn_compress:setTooltip("Merge stacks with same items to get free place")
btn_compress:onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "crafting", "compress")
state.param.invobj:compress()
end)
local btn_sweep = state:image_button(2, 3.8, 1, 1, "clear", "", "smart_inventory_sweep_button.png")
btn_sweep:setTooltip("Move all items from crafting grid back to inventory")
btn_sweep:onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "crafting", "clear")
state.param.invobj:sweep_crafting_inventory()
end)
-- recipe preview area
smart_inventory.smartfs_elements.craft_preview(state, 6, 0, "craft_preview"):onButtonClicked(function(self, item, player)
do_lookup_item(state, player, item)
end)
state:image(7,2.8,1,1,"cr_type_img",""):setVisible(false)
state:label(7,3,"cr_type", "")
local pr_prev_btn = state:button(6, 3, 1, 0.5, "preview_prev", "<<")
pr_prev_btn:onClick(function(self, state, player)
state.param.crafting_recipes_preview_selected = state.param.crafting_recipes_preview_selected -1
update_crafting_preview(state)
end)
pr_prev_btn:setVisible(false)
local pr_next_btn = state:button(8, 3, 1, 0.5, "preview_next", ">>")
pr_next_btn:onClick(function(self, state, player)
state.param.crafting_recipes_preview_selected = state.param.crafting_recipes_preview_selected +1
update_crafting_preview(state)
end)
pr_next_btn:setVisible(false)
-- (dynamic-1) group selection
local group_sel = state:listbox(10.2, 0.15, 7.6, 3.6, "groups_sel",nil, true)
group_sel:onClick(function(self, state, player)
local selected = self:getSelectedItem()
if selected then
update_group_selection(state, false)
end
end)
-- (dynamic-2) item preview area
state:background(10.0, 0.1, 8, 3.8, "craft_img2", "minimap_overlay_square.png")
local inf_area = state:view(6.4, 0.1, "inf_area")
local inf_state = inf_area:getContainerState()
inf_state:label(11.5,0.5,"info1", "")
inf_state:label(11.5,1.0,"info2", "")
inf_state:label(11.5,1.5,"info3", "")
inf_state:item_image(10.2,0.3, 1, 1, "craft_result",nil):setVisible(false)
if smart_inventory.doc_items_mod then
local doc_btn = inf_state:image_button(10.4,2.3, 0.7, 0.7, "doc_btn","", "doc_button_icon_lores.png")
doc_btn:setTooltip("Show documentation for revealed item")
doc_btn:setVisible(false)
doc_btn:onClick(function(self, state, player)
local outitem = state:get("craft_result"):getImage()
if outitem then
for z in outitem:gmatch("[^%s]+") do
if minetest.registered_items[z] then
doc_addon.show(z, player)
end
break
end
end
end)
end
inf_state:label(10.3, 3.25, "groups_label", "All")
inf_state:listbox(12, 2, 5.7, 1.3, "item_groups",nil, true)
inf_area:setVisible(false)
-- Lookup
create_lookup_inv(player)
state:image(10, 4, 1, 1,"lookup_icon", "smart_inventory_lookup_field.png")
local inv_lookup = state:inventory(10, 4.0, 1, 1,"lookup"):useDetached(player.."_crafting_inv")
-- Get craftable by items in inventory
local btn_craftable = state:image_button(11, 4, 0.5, 0.5, "craftable", "", "smart_inventory_craftable_button.png")
btn_craftable:setTooltip("Show items crafteable by items in inventory")
btn_craftable:onClick(function(self, state, player)
state.param.crafting_items_in_inventory = state.param.invobj:get_items()
local craftable = crecipes.get_recipes_craftable(player, state.param.crafting_items_in_inventory)
update_from_recipelist(state, craftable)
ui_controller:update_list_variant("craftable")
end)
local grid_btn = state:image_button(11.5, 4, 0.5, 0.5, "btn_grid", "", "smart_inventory_craftable_button.png")
grid_btn:setTooltip("Search for recipes matching the grid")
grid_btn:onClick(function(self, state, player)
local player = state.location.rootState.location.player
state.param.crafting_ui_controller:update_list_variant("grid")
local craft_grid = state.param.invobj.inventory:get_list("craft")
local ret_item = state.param.invobj.inventory:get_list("craftpreview")[1]
update_from_grid(state, craft_grid, ret_item:get_name())
end)
-- Get craftable by items in inventory
local btn_all = state:image_button(11, 4.5, 0.5, 0.5, "btn_all", "", "smart_inventory_creative_button.png")
if smart_inventory.doc_items_mod then
btn_all:setTooltip("Show all already revealed items")
else
btn_all:setTooltip("Show all items")
end
btn_all:onClick(function(self, state, player)
local all_revealed = ui_tools.filter_by_revealed(ui_tools.root_list_all, player, true)
state.param.crafting_recipes_preview_selected = 1
state.param.crafting_recipes_preview_listentry = all_revealed[1] or {}
update_crafting_preview(state)
state.param.crafting_grouped_items = ui_tools.get_list_grouped(all_revealed)
update_group_selection(state, true)
ui_controller:update_list_variant("btn_all")
end)
-- Reveal tipps button
if smart_inventory.doc_items_mod then
local reveal_button = state:image_button(11.5, 4.5, 0.5, 0.5, "reveal_tipp", "", "smart_inventory_reveal_tips_button.png")
reveal_button:setTooltip("Show proposal what should be crafted to reveal more items")
reveal_button:onClick(function(self, state, player)
local all_revealed = ui_tools.filter_by_revealed(ui_tools.root_list_all, player)
local top_revealed = ui_tools.filter_by_top_reveal(all_revealed, player)
state.param.crafting_recipes_preview_selected = 1
state.param.crafting_recipes_preview_listentry = top_revealed[1] or {}
update_crafting_preview(state)
state.param.crafting_grouped_items = ui_tools.get_list_grouped(top_revealed)
update_group_selection(state, true)
ui_controller:update_list_variant("reveal_tipp")
end)
end
-- search
state:background(12, 4, 4, 0.9, "search_bg", nil) --field background not usable
local searchfield = state:field(12.2, 4.5, 3.4, 0.5, "search")
searchfield:setCloseOnEnter(false)
searchfield:onKeyEnter(function(self, state, player)
local search_string = self:getText()
if string.len(search_string) < 3 then
return
end
local filtered_list = ui_tools.filter_by_searchstring(ui_tools.root_list_all, search_string, state.location.rootState.lang_code)
filtered_list = ui_tools.filter_by_revealed(filtered_list, player)
state.param.crafting_grouped_items = ui_tools.get_list_grouped(filtered_list)
update_group_selection(state, true)
ui_controller:update_list_variant("search", search_string)
end)
local search_button = state:button(15.2, 4.2, 0.8, 0.5, "search_btn", "Go")
search_button:setTooltip("Perform search action")
search_button:onClick(function(self, state, player)
state:get("search"):submit_key_enter("", player)
end)
-- groups toggle
local info_tog = state:toggle(16.2,4.2,1.8,0.5, "info_tog", {"Info", "Groups", "Hide"})
info_tog:onToggle(function(self, state, player)
local id = self:getId()
if id == 1 then
state.param.crafting_ui_controller:set_ui_variant("list_small")
state.param.crafting_ui_controller:set_ui_variant("info")
elseif id == 2 then
state.param.crafting_ui_controller:set_ui_variant("list_small")
state.param.crafting_ui_controller:set_ui_variant("groups")
elseif id == 3 then
state.param.crafting_ui_controller:set_ui_variant("list_big")
end
end)
-- craftable items grid
state:background(10, 5, 8, 4, "buttons_grid_Bg", "minimap_overlay_square.png")
local grid = smart_inventory.smartfs_elements.buttons_grid(state, 10.25, 5.15, 8 , 4, "buttons_grid", 0.75,0.75)
grid:onClick(function(self, state, index, player)
local listentry = state.param.crafting_craftable_list[index]
if ui_controller.list_variant == "lookup" then
do_lookup_item(state, state.location.rootState.location.player, listentry.item)
else
state.param.crafting_recipes_preview_selected = 1
state.param.crafting_recipes_preview_listentry = listentry
update_crafting_preview(state)
end
state.param.crafting_ui_controller:set_ui_variant("info")
end)
ui_controller:restore()
end
-----------------------------------------------------
-- Register page in smart_inventory
-----------------------------------------------------
smart_inventory.register_page({
name = "crafting",
tooltip = "Craft new items",
icon = "smart_inventory_crafting_inventory_button.png",
smartfs_callback = crafting_callback,
sequence = 10
})
-----------------------------------------------------
-- Use lookup for predict item
-----------------------------------------------------
minetest.register_craft_predict(function(stack, player, old_craft_grid, craft_inv)
local name = player:get_player_name()
local state = smart_inventory.get_page_state("crafting", name)
if not state then
return
end
if state.param.crafting_ui_controller.list_variant ~= 'grid' then
return
end
update_from_grid(state, old_craft_grid, stack:get_name())
state.location.rootState:show()
end)

View File

@ -1,310 +0,0 @@
local cache = smart_inventory.cache
local ui_tools = smart_inventory.ui_tools
-----------------------------------------------------
-- Update on group selection change
-----------------------------------------------------
local function update_group_selection(state, changed_group)
local grouped = state.param.creative_grouped_items
local groups_sel1 = state:get("groups_sel1")
local groups_sel2 = state:get("groups_sel2")
local groups_sel3 = state:get("groups_sel3")
local grid = state:get("buttons_grid")
local outlist
if state.param.creative_grouped_shape_items and
next(state.param.creative_grouped_shape_items) then
local group_info = {}
group_info.name = "shape"
group_info.cgroup = cache.cgroups["shape"]
group_info.group_desc = "#01DF74> "..group_info.cgroup.group_desc
group_info.items = state.param.creative_grouped_shape_items
grouped["shape"] = group_info
end
-- update group 1
if changed_group < 1 or not state.param.creative_group_list1 then
state.param.creative_group_list1 = ui_tools.update_group_selection(grouped, groups_sel1, state.param.creative_group_list1)
end
local sel_id = groups_sel1:getSelected()
if state.param.creative_group_list1[sel_id] == "all"
or not state.param.creative_group_list1[sel_id]
or not grouped[state.param.creative_group_list1[sel_id]] then
outlist = grouped["all"].items
groups_sel2:clearItems()
groups_sel3:clearItems()
else
-- update group 2
grouped = ui_tools.get_list_grouped(grouped[state.param.creative_group_list1[sel_id]].items)
if changed_group < 2 or not state.param.creative_group_list2 then
state.param.creative_group_list2 = ui_tools.update_group_selection(grouped, groups_sel2, state.param.creative_group_list2)
end
sel_id = groups_sel2:getSelected()
if state.param.creative_group_list2[sel_id] == "all"
or not state.param.creative_group_list2[sel_id]
or not grouped[state.param.creative_group_list2[sel_id]] then
outlist = grouped["all"].items
groups_sel3:clearItems()
else
-- update group 3
grouped = ui_tools.get_list_grouped(grouped[state.param.creative_group_list2[sel_id]].items)
if changed_group < 3 or not state.param.creative_group_list3 then
state.param.creative_group_list3 = ui_tools.update_group_selection(grouped, groups_sel3, state.param.creative_group_list3)
end
sel_id = groups_sel3:getSelected()
outlist = grouped[state.param.creative_group_list3[sel_id]].items
end
end
-- update grid list
if outlist then
table.sort(outlist, function(a,b)
return a.sort_value < b.sort_value
end)
grid:setList(outlist)
state.param.creative_outlist = outlist
else
grid:setList({})
end
end
-----------------------------------------------------
-- Page layout definition
-----------------------------------------------------
local function creative_callback(state)
local player = state.location.rootState.location.player
-- build up UI controller
local ui_controller = {}
ui_controller.state = state
state.param.creative_ui_controller = ui_controller
ui_controller.player = minetest.get_player_by_name(state.location.rootState.location.player)
function ui_controller:set_ui_variant(new_ui)
-- check if change needed
if new_ui == self.ui_toggle then
return
end
-- toggle show/hide elements
if new_ui == 'list_small' then
self.ui_toggle = new_ui
self.state:get("groups_sel1"):setSize(5.6, 3)
self.state:get("groups_sel2"):setVisible(true)
self.state:get("groups_sel3"):setVisible(true)
self.state:get("buttons_grid"):reset(9.55, 3.75, 9.0 , 6.5)
self.state:get("buttons_grid_bg"):setPosition(9.2, 3.5)
self.state:get("buttons_grid_bg"):setSize(9.5, 6.5)
self.state:get("btn_tog"):setId(1)
elseif new_ui == 'list_big' then
self.ui_toggle = new_ui
self.state:get("groups_sel1"):setSize(7.8, 3)
self.state:get("groups_sel2"):setVisible(false)
self.state:get("groups_sel3"):setVisible(false)
self.state:get("buttons_grid"):reset(9.55, 0.25, 9.0 , 10)
self.state:get("buttons_grid_bg"):setPosition(9.2, 0)
self.state:get("buttons_grid_bg"):setSize(9.5, 10)
self.state:get("btn_tog"):setId(2)
end
self:save()
end
function ui_controller:save()
local savedata = minetest.deserialize(self.player:get_attribute("smart_inventory_settings")) or {}
savedata.creative_ui_toggle = self.ui_toggle
self.player:set_attribute("smart_inventory_settings", minetest.serialize(savedata))
end
function ui_controller:restore()
local savedata = minetest.deserialize(self.player:get_attribute("smart_inventory_settings")) or {}
if savedata.creative_ui_toggle then
ui_controller:set_ui_variant(savedata.creative_ui_toggle)
end
end
-- groups 1-3
local group_sel1 = state:listbox(1, 0.15, 5.6, 3, "groups_sel1",nil, false)
group_sel1:onClick(function(self, state, player)
local selected = self:getSelectedItem()
if selected then
state:get("groups_sel2"):setSelected(1)
state:get("groups_sel3"):setSelected(1)
update_group_selection(state, 1)
end
end)
local group_sel2 = state:listbox(7, 0.15, 5.6, 3, "groups_sel2",nil, false)
group_sel2:onClick(function(self, state, player)
local selected = self:getSelectedItem()
if selected then
state:get("groups_sel3"):setSelected(1)
update_group_selection(state, 2)
end
end)
local group_sel3 = state:listbox(13, 0.15, 5.6, 3, "groups_sel3",nil, false)
group_sel3:onClick(function(self, state, player)
local selected = self:getSelectedItem()
if selected then
update_group_selection(state, 3)
end
end)
-- functions
local searchfield = state:field(1.3, 4.1, 4.2, 0.5, "search")
searchfield:setCloseOnEnter(false)
searchfield:onKeyEnter(function(self, state, player)
local search_string = self:getText()
local lang_code = state.location.rootState.lang_code
local filtered_list = ui_tools.filter_by_searchstring(ui_tools.root_list, search_string, lang_code)
state.param.creative_grouped_items = ui_tools.get_list_grouped(filtered_list)
filtered_list = ui_tools.filter_by_searchstring(ui_tools.root_list_shape, search_string, lang_code)
state.param.creative_grouped_shape_items = filtered_list
update_group_selection(state, 0)
end)
local search_button = state:button(5.0, 3.8, 1, 0.5, "search_btn", "Go")
search_button:setTooltip("Perform search action")
search_button:onClick(function(self, state, player)
state:get("search"):submit_key_enter("", player)
end)
-- action mode toggle
state:toggle(6, 3.8,1.5,0.5, "btn_tog_mode", {"Give 1", "Give stack"})
-- groups toggle
local btn_toggle = state:toggle(7.5, 3.8,1.5,0.5, "btn_tog", {"Groups", "Hide"})
btn_toggle:onToggle(function(self, state, player)
local id = self:getId()
if id == 1 then
state.param.creative_ui_controller:set_ui_variant("list_small")
elseif id == 2 then
state.param.creative_ui_controller:set_ui_variant("list_big")
end
end)
-- craftable items grid
state:background(9.2, 3.5, 9.5, 6.5, "buttons_grid_bg", "minimap_overlay_square.png")
local grid = smart_inventory.smartfs_elements.buttons_grid(state, 9.55, 3.75, 9.0 , 6.5, "buttons_grid", 0.75,0.75)
grid:onClick(function(self, state, index, player)
local mode = state:get("btn_tog_mode"):getId() or 1
local selected = ItemStack(state.param.creative_outlist[index].item)
if mode == 1 then -- give 1 item
state.param.invobj:add_item(selected)
elseif mode == 2 then --give full stack
selected:set_count(selected:get_stack_max())
state.param.invobj:add_sepearate_stack(selected)
end
end)
-- inventory
state:inventory(1, 5, 8, 4,"main")
ui_tools.create_trash_inv(state, player)
state:image(8,9,1,1,"trash_icon","smart_inventory_trash.png")
state:element("code", {name = "trash_bg_code", code = "listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]"})
state:inventory(8,9,1,1, "trash"):useDetached(player.."_trash_inv")
-- swap slots buttons
state:image_button(0, 6, 1, 1, "swap1", "", "smart_inventory_swapline_button.png"):onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "creative", "swap1")
state.param.invobj:swap_row_to_top(2)
end)
state:image_button(0, 7, 1, 1, "swap2", "", "smart_inventory_swapline_button.png"):onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "creative", "swap2")
state.param.invobj:swap_row_to_top(3)
end)
state:image_button(0, 8, 1, 1, "swap3", "", "smart_inventory_swapline_button.png"):onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "creative", "swap3")
state.param.invobj:swap_row_to_top(4)
end)
-- trash button
local trash_all = state:image_button(7,9,1,1, "trash_all", "", "smart_inventory_trash_all_button.png")
trash_all:setTooltip("Trash all inventory content")
trash_all:onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "creative", "trash_all")
state.param.invobj:remove_all()
end)
-- save/restore buttons
local btn_save1 = state:image_button(1,9,1,1, "save1", "", "smart_inventory_save1_button.png")
btn_save1:setTooltip("Save inventory content to slot 1")
btn_save1:onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "creative", "save1")
state.param.invobj:save_to_slot(1)
end)
local btn_save2 = state:image_button(1.9,9,1,1, "save2", "", "smart_inventory_save2_button.png")
btn_save2:setTooltip("Save inventory content to slot 2")
btn_save2:onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "creative", "save2")
state.param.invobj:save_to_slot(2)
end)
local btn_save3 = state:image_button(2.8,9,1,1, "save3", "", "smart_inventory_save3_button.png")
btn_save3:setTooltip("Save inventory content to slot 3")
btn_save3:onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "creative", "save3")
state.param.invobj:save_to_slot(3)
end)
local btn_restore1 = state:image_button(4,9,1,1, "restore1", "", "smart_inventory_get1_button.png")
btn_restore1:setTooltip("Restore inventory content from slot 1")
btn_restore1:onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "creative", "restore1")
state.param.invobj:restore_from_slot(1)
end)
local btn_restore2 = state:image_button(4.9,9,1,1, "restore2", "", "smart_inventory_get2_button.png")
btn_restore2:setTooltip("Restore inventory content from slot 2")
btn_restore2:onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "creative", "restore2")
state.param.invobj:restore_from_slot(2)
end)
local btn_restore3 = state:image_button(5.8,9,1,1, "restore3", "", "smart_inventory_get3_button.png")
btn_restore3:setTooltip("Restore inventory content from slot 3")
btn_restore3:onClick(function(self, state, player)
ui_tools.image_button_feedback(player, "creative", "restore3")
state.param.invobj:restore_from_slot(3)
end)
-- fill with data
state.param.creative_grouped_items = ui_tools.get_list_grouped(ui_tools.root_list)
state.param.creative_grouped_shape_items = ui_tools.root_list_shape
update_group_selection(state, 0)
ui_controller:restore()
end
local function player_has_creative(state)
return state.param.invobj:get_has_creative()
end
-----------------------------------------------------
-- Register page in smart_inventory
-----------------------------------------------------
smart_inventory.register_page({
name = "creative",
tooltip = "The creative way to get items",
icon = "smart_inventory_creative_button.png",
smartfs_callback = creative_callback,
is_visible_func = player_has_creative,
sequence = 15
})
-- Redefinition for sfinv method maybe called from other mods
if minetest.global_exists("sfinv") then
function sfinv.set_player_inventory_formspec(player, context)
local playername = player:get_player_name()
local page_state = smart_inventory.get_page_state("creative", playername)
if page_state then
local state = page_state.location.parentState
local has_creative = player_has_creative(state)
state:get("creative_button"):setVisible(has_creative)
if not has_creative then
state:get("crafting_button"):submit(nil, playername)
end
state:show()
end
end
end

View File

@ -1,138 +0,0 @@
local doc_addon = smart_inventory.doc_addon
if not smart_inventory.doc_items_mod then
return
end
local COLOR_NOT_VIEWED = "#00FFFF" -- cyan
local COLOR_VIEWED = "#FFFFFF" -- white
local COLOR_HIDDEN = "#999999" -- gray
local COLOR_ERROR = "#FF0000" -- red
local function update_entry_list(state, selected_eid)
local playername = state.location.rootState.location.player
local category_id, category
category_id = state:get("category"):getSelected()
if category_id then
category = doc_addon.get_category_list()[category_id]
end
if not category then
return
end
local total = doc.get_entry_count(category.cid)
local revealed = doc.get_revealed_count(playername, category.cid)
local viewed = doc.get_viewed_count(playername, category.cid)
local hidden = total - revealed
local new = total - viewed - hidden
state:get("lbl_category"):setText(category.data.def.description)
state:get("lbl_viewed"):setText(minetest.colorize(COLOR_VIEWED,"Viewed: "..viewed.."/"..revealed))
state:get("lbl_hidden"):setText(minetest.colorize(COLOR_HIDDEN,"Hidden: "..hidden.."/"..total))
state:get("lbl_new"):setText(minetest.colorize(COLOR_NOT_VIEWED,"New: "..new))
local entries_box = state:get("entries")
entries_box:clearItems()
state.param.doc_entry_list = {}
for _, edata in ipairs(category.entries) do
local viewedprefix
if doc.entry_revealed(playername, category.cid, edata.eid) then
if doc.entry_viewed(playername, category.cid, edata.eid) then
viewedprefix = COLOR_VIEWED
else
viewedprefix = COLOR_NOT_VIEWED
end
local name = edata.data.name
if name == nil or name == "" then
name = edata.eid
end
local idx = entries_box:addItem(viewedprefix..name)
table.insert(state.param.doc_entry_list, edata)
if selected_eid == edata.eid then
entries_box:setSelected(idx)
end
end
end
end
local function doc_callback(state)
local playername = state.location.rootState.location.player
state:label(0, 0, "lbl_category", "")
state:background(0,0,20,0.5,"cat_bg", "halo.png")
-- state:label(0, 0.5, "lbl_revealed", "")
state:label(0, 0.5, "lbl_viewed", "")
state:label(3, 0.5, "lbl_new", "")
state:label(0, 1, "lbl_hidden", "")
local category_box = state:listbox(0, 1.5, 4.8, 2, "category", nil, false)
category_box:onClick(function(self, state, player)
update_entry_list(state)
end)
state:listbox(0, 4, 4.8, 6, "entries", nil, false):onDoubleClick(function(self, state, player)
local playername = state.location.rootState.location.player
local selected = self:getSelected()
local doc_entry = state.param.doc_entry_list[selected]
if doc_entry then
doc.mark_entry_as_viewed(playername, doc_entry.cid, doc_entry.eid)
state:get("code").edata = doc_entry
doc.data.players[playername].galidx = 1
update_entry_list(state)
end
end)
local codebox = state:element("code", { name = "code", code = "" })
codebox:onBuild(function(self)
if self.edata then
local state = self.root
local playername = state.location.rootState.location.player
self.data.code = "container[5.5,0]".. self.edata.cid_data.def.build_formspec(self.edata.data.data, playername).."container_end[]"
else
self.data.code = ""
end
end)
-- to trigger the page update
codebox:onSubmit(function(self, state)
-- select the right category
for idx, category in ipairs(doc_addon.get_category_list()) do
if category.cid == self.edata.cid then
state:get("category"):setSelected(idx)
break
end
end
-- update page for new category
update_entry_list(state, self.edata.eid)
end)
state:onInput(function(state, fields, player)
if fields.doc_button_gallery_prev then
if doc.data.players[playername].galidx - doc.data.players[playername].galrows > 0 then
doc.data.players[playername].galidx = doc.data.players[playername].galidx - doc.data.players[playername].galrows
end
elseif fields.doc_button_gallery_next then
if doc.data.players[playername].galidx + doc.data.players[playername].galrows <= doc.data.players[playername].maxgalidx then
doc.data.players[playername].galidx = doc.data.players[playername].galidx + doc.data.players[playername].galrows
end
end
end)
-- fill category table
for _, category in ipairs(doc_addon.get_category_list()) do
category_box:addItem(category.data.def.name)
end
end
smart_inventory.register_page({
name = "doc",
icon = "doc_awards_icon_generic.png",
tooltip = "Ingame documentation",
smartfs_callback = doc_callback,
sequence = 30,
on_button_click = update_entry_list,
})

View File

@ -1,445 +0,0 @@
smart_inventory.skins_mod = minetest.get_modpath("skinsdb")
smart_inventory.armor_mod = minetest.get_modpath("3d_armor")
smart_inventory.clothing_mod = minetest.get_modpath("clothing")
if not smart_inventory.skins_mod and
not smart_inventory.armor_mod and
not smart_inventory.clothing_mod then
return
end
local filter = smart_inventory.filter
local cache = smart_inventory.cache
local ui_tools = smart_inventory.ui_tools
local txt = smart_inventory.txt
local function update_grid(state, listname)
local player_has_creative = state.param.invobj:get_has_creative()
-- Update the users inventory grid
local list = {}
state.param["player_"..listname.."_list"] = list
local name = state.location.rootState.location.player
local player = minetest.get_player_by_name(name)
local invlist_tab = {}
if listname == "main" then
local inventory = player:get_inventory()
local invlist = inventory and inventory:get_list("main")
table.insert(invlist_tab, invlist)
else
if smart_inventory.armor_mod then
local inventory = minetest.get_inventory({type="detached", name=name.."_armor"})
local invlist = inventory and inventory:get_list("armor")
if invlist then
table.insert(invlist_tab, invlist)
end
end
if smart_inventory.clothing_mod then
local clothing_meta = player:get_attribute("clothing:inventory")
state.param.player_clothing_data = clothing_meta and minetest.deserialize(clothing_meta) or {}
local invlist = {}
for i=1,6 do
table.insert(invlist, ItemStack(state.param.player_clothing_data[i]))
end
table.insert(invlist_tab, invlist)
end
end
local list_dedup = {}
for _, invlist in ipairs(invlist_tab) do
for stack_index, stack in ipairs(invlist) do
local itemdef = stack:get_definition()
local is_armor = false
if itemdef then
cache.add_item(itemdef) -- analyze groups in case of hidden armor
if cache.citems[itemdef.name].cgroups["armor"] or cache.citems[itemdef.name].cgroups["clothing"] then
local entry = {}
for k, v in pairs(cache.citems[itemdef.name].ui_item) do
entry[k] = v
end
entry.stack_index = stack_index
local wear = stack:get_wear()
if wear > 0 then
entry.text = tostring(math.floor((1 - wear / 65535) * 100 + 0.5)).." %"
end
table.insert(list, entry)
list_dedup[itemdef.name] = itemdef
end
end
end
end
-- add all usable in creative available armor to the main list
if listname == "main" and player_has_creative == true then
if smart_inventory.armor_mod then
for _, itemdef in pairs(cache.cgroups["armor"].items) do
if not list_dedup[itemdef.name] and not itemdef.groups.not_in_creative_inventory then
list_dedup[itemdef.name] = itemdef
table.insert(list, cache.citems[itemdef.name].ui_item)
end
end
end
if smart_inventory.clothing_mod then
for _, itemdef in pairs(cache.cgroups["clothing"].items) do
if not list_dedup[itemdef.name] and not itemdef.groups.not_in_creative_inventory then
list_dedup[itemdef.name] = itemdef
table.insert(list, cache.citems[itemdef.name].ui_item)
end
end
end
end
local grid = state:get(listname.."_grid")
grid:setList(list)
end
local function update_selected_item(state, listentry)
local name = state.location.rootState.location.player
state.param.armor_selected_item = listentry or state.param.armor_selected_item
listentry = state.param.armor_selected_item
if not listentry then
return
end
local i_list = state:get("i_list")
i_list:clearItems()
for _, groupdef in ipairs(ui_tools.get_tight_groups(cache.citems[listentry.itemdef.name].cgroups)) do
i_list:addItem(groupdef.group_desc)
end
state:get("item_name"):setText(listentry.itemdef.description)
state:get("item_image"):setImage(listentry.item)
end
local function update_page(state)
local name = state.location.rootState.location.player
local player_obj = minetest.get_player_by_name(name)
local skin_obj = smart_inventory.skins_mod and skins.get_player_skin(player_obj)
-- Update grid lines
if smart_inventory.armor_mod or smart_inventory.clothing_mod then
update_grid(state, "main")
update_grid(state, "overlay")
end
-- Update preview area and armor informations list
if smart_inventory.armor_mod then
state:get("preview"):setImage(armor.textures[name].preview)
state.location.parentState:get("player_button"):setImage(armor.textures[name].preview)
local a_list = state:get("a_list")
a_list:clearItems()
for k, v in pairs(armor.def[name]) do
local grouptext
if k == "groups" then
for gn, gv in pairs(v) do
if txt and txt["armor:"..gn] then
grouptext = txt["armor:"..gn]
else
grouptext = "armor:"..gn
end
if grouptext and gv ~= 0 then
a_list:addItem(grouptext..": "..gv)
end
end
else
local is_physics = false
for _, group in ipairs(armor.physics) do
if group == k then
is_physics = true
break
end
end
if is_physics then
if txt and txt["physics:"..k] then
grouptext = txt["physics:"..k]
else
grouptext = "physics:"..k
end
if grouptext and v ~= 1 then
a_list:addItem(grouptext..": "..v)
end
else
if txt and txt["armor:"..k] then
grouptext = txt["armor:"..k]
else
grouptext = "armor:"..k
end
if grouptext and v ~= 0 then
if k == "state" then
a_list:addItem(grouptext..": "..tostring(math.floor((1 - v / armor.def[name].count / 65535) * 100 + 0.5)).." %")
else
a_list:addItem(grouptext..": "..v)
end
end
end
end
end
update_selected_item(state)
elseif skin_obj then
local skin_preview = skin_obj:get_preview()
state.location.parentState:get("player_button"):setImage(skin_preview)
state:get("preview"):setImage(skin_preview)
elseif smart_inventory.clothing_mod then
update_selected_item(state)
state.location.parentState:get("player_button"):setImage('inventory_plus_clothing.png')
state:get("preview"):setImage('blank.png') --TODO: build up clothing preview
end
-- Update skins list and skins info area
if skin_obj then
local m_name = skin_obj:get_meta_string("name")
local m_author = skin_obj:get_meta_string("author")
local m_license = skin_obj:get_meta_string("license")
if m_name then
state:get("skinname"):setText("Skin name: "..(skin_obj:get_meta_string("name")))
else
state:get("skinname"):setText("")
end
if m_author then
state:get("skinauthor"):setText("Author: "..(skin_obj:get_meta_string("author")))
else
state:get("skinauthor"):setText("")
end
if m_license then
state:get("skinlicense"):setText("License: "..(skin_obj:get_meta_string("license")))
else
state:get("skinlicense"):setText("")
end
-- set the skins list
state.param.skins_list = skins.get_skinlist_for_player(name)
local cur_skin = skins.get_player_skin(player_obj)
local skins_grid_data = {}
local grid_skins = state:get("skins_grid")
for idx, skin in ipairs(state.param.skins_list) do
table.insert(skins_grid_data, {
image = skin:get_preview(),
tooltip = skin:get_meta_string("name"),
is_button = true,
size = { w = 0.87, h = 1.30 }
})
if not state.param.skins_initial_page_adjusted and skin:get_key() == cur_skin:get_key() then
grid_skins:setFirstVisible(idx - 19) --8x5 (grid size) / 2 -1
state.param.skins_initial_page_adjusted = true
end
end
grid_skins:setList(skins_grid_data)
end
end
local function move_item_to_armor(state, item)
local player_has_creative = state.param.invobj:get_has_creative()
local name = state.location.rootState.location.player
local player = minetest.get_player_by_name(name)
local inventory = player:get_inventory()
local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"})
-- get item to be moved to armor inventory
local itemstack, itemname, itemdef
if player_has_creative == true then
itemstack = ItemStack(item.item)
itemname = item.item
else
itemstack = inventory:get_stack("main", item.stack_index)
itemname = itemstack:get_name()
end
itemdef = minetest.registered_items[itemname]
local new_groups = {}
for _, element in ipairs(armor.elements) do
if itemdef.groups["armor_"..element] then
new_groups["armor_"..element] = true
end
end
-- remove all items with the same group
local removed_items = {}
for stack_index, stack in ipairs(armor_inv:get_list("armor")) do
local old_def = stack:get_definition()
if old_def then
for groupname, groupdef in pairs(old_def.groups) do
if new_groups[groupname] then
table.insert(removed_items, stack)
armor_inv:set_stack("armor", stack_index, {}) --take old
minetest.detached_inventories[name.."_armor"].on_take(armor_inv, "armor", stack_index, stack, player)
if armor_inv:set_stack("armor", stack_index, itemstack) then --put new
minetest.detached_inventories[name.."_armor"].on_put(armor_inv, "armor", stack_index, itemstack, player)
itemstack = ItemStack("")
end
end
end
end
if stack:is_empty() and not itemstack:is_empty() then
if armor_inv:set_stack("armor", stack_index, itemstack) then
minetest.detached_inventories[name.."_armor"].on_put(armor_inv, "armor", stack_index, itemstack, player)
itemstack = ItemStack("")
end
end
end
-- handle put backs in non-creative to not lost items
if player_has_creative == false then
inventory:set_stack("main", item.stack_index, itemstack)
for _, stack in ipairs(removed_items) do
stack = inventory:add_item("main", stack)
if not stack:is_empty() then
armor_inv:add_item("armor", stack)
end
end
end
end
local function move_item_to_clothing(state, item)
local name = state.location.rootState.location.player
local player = minetest.get_player_by_name(name)
local inventory = player:get_inventory()
local clothes = state.param.player_clothing_data
local clothes_ordered = {}
for i=1, 6 do
if clothes[i] then
table.insert(clothes_ordered, clothes[i])
end
end
if #clothes_ordered < 6 then
table.insert(clothes_ordered, item.item)
player:set_attribute("clothing:inventory", minetest.serialize(clothes_ordered))
clothing:set_player_clothing(player)
state.param.player_clothing_data = clothes_ordered
-- handle put backs in non-creative to not lost items
if player_has_creative == false then
local itemstack = inventory:get_stack("main", item.stack_index)
itemstack:take_item()
inventory:set_stack("main", item.stack_index, itemstack)
end
end
end
local function move_item_to_inv(state, item)
local player_has_creative = state.param.invobj:get_has_creative()
local name = state.location.rootState.location.player
local player = minetest.get_player_by_name(name)
local inventory = player:get_inventory()
if cache.cgroups["armor"] and cache.cgroups["armor"].items[item.item] then
local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"})
local itemstack = armor_inv:get_stack("armor", item.stack_index)
if player_has_creative == true then
-- trash armor item in creative
itemstack = ItemStack("")
else
itemstack = inventory:add_item("main", itemstack)
end
armor_inv:set_stack("armor", item.stack_index, itemstack)
minetest.detached_inventories[name.."_armor"].on_take(armor_inv, "armor", item.stack_index, itemstack, player)
elseif cache.cgroups["clothing"] and cache.cgroups["clothing"].items[item.item] then
local clothes = state.param.player_clothing_data
if player_has_creative ~= true and clothes[item.stack_index] then
local itemstack = inventory:add_item("main", ItemStack(clothes[item.stack_index]))
if itemstack:is_empty() then
clothes[item.stack_index] = nil
end
else
clothes[item.stack_index] = nil
end
player:set_attribute("clothing:inventory", minetest.serialize(clothes))
clothing:set_player_clothing(player)
end
end
local function player_callback(state)
local name = state.location.rootState.location.player
state:background(0, 1.2, 6, 6.6, "it_bg", "smart_inventory_background_border.png")
state:item_image(0.8, 1.5,2,2,"item_image","")
state:label(2.5,1.2,"item_name", "")
state:listbox(0.8,3.3,5.1,4,"i_list", nil, true)
state:background(6.2, 1.2, 6, 6.6, "pl_bg", "smart_inventory_background_border.png")
state:image(6.7,1.7,2,4,"preview","")
state:listbox(8.6,1.7,3.5,3,"a_list", nil, true)
state:label(6.7,5.5,"skinname","")
state:label(6.7,6.0,"skinauthor", "")
state:label(6.7,6.5, "skinlicense", "")
state:background(0, 0, 20, 1, "top_bg", "halo.png")
state:background(0, 8, 20, 2, "bottom_bg", "halo.png")
if smart_inventory.armor_mod or smart_inventory.clothing_mod then
local grid_overlay = smart_inventory.smartfs_elements.buttons_grid(state, 0, 0, 20, 1, "overlay_grid")
grid_overlay:onClick(function(self, state, index, player)
if state.param.player_overlay_list[index] then
update_selected_item(state, state.param.player_overlay_list[index])
move_item_to_inv(state, state.param.player_overlay_list[index])
update_page(state)
end
end)
local grid_main = smart_inventory.smartfs_elements.buttons_grid(state, 0, 8, 20, 2, "main_grid")
grid_main:onClick(function(self, state, index, player)
update_selected_item(state, state.param.player_main_list[index])
local item = state.param.player_main_list[index]
if cache.citems[item.item].cgroups["armor"] then
move_item_to_armor(state, state.param.player_main_list[index])
elseif cache.citems[item.item].cgroups["clothing"] then
move_item_to_clothing(state, state.param.player_main_list[index])
end
update_page(state)
end)
end
if smart_inventory.skins_mod then
local player_obj = minetest.get_player_by_name(name)
-- Skins Grid
local grid_skins = smart_inventory.smartfs_elements.buttons_grid(state, 12.9, 1.5, 7 , 7, "skins_grid", 0.80, 1.20)
state:background(12.4, 1.2, 7.5 , 6.6, "bg_skins", "smart_inventory_background_border.png")
grid_skins:onClick(function(self, state, index, player)
local cur_skin = state.param.skins_list[index]
if state.location.rootState.location.type ~= "inventory" and cur_skin._key:sub(1,17) == "character_creator" then
state.location.rootState.obsolete = true -- other screen appears, obsolete the inventory session
end
skins.set_player_skin(player_obj, cur_skin)
if smart_inventory.armor_mod then
armor.textures[name].skin = cur_skin:get_texture()
armor:set_player_armor(player_obj)
end
update_page(state)
end)
end
-- not visible update plugin for updates from outsite (API)
state:element("code", { name = "update_hook" }):onSubmit(function(self, state)
update_page(state)
state.location.rootState:show()
end)
update_page(state)
end
smart_inventory.register_page({
name = "player",
icon = "player.png",
tooltip = "Customize yourself",
smartfs_callback = player_callback,
sequence = 20,
on_button_click = update_page
})
-- register callback in 3d_armor for updates
if smart_inventory.armor_mod and armor.register_on_update then
local function submit_update_hook(player)
local name = player:get_player_name()
local state = smart_inventory.get_page_state("player", name)
if state then
state:get("update_hook"):submit()
end
end
armor:register_on_update(submit_update_hook)
-- There is no callback in 3d_armor for wear change in on_hpchange implementation
minetest.register_on_player_hpchange(function(player, hp_change)
minetest.after(0, submit_update_hook, player)
end)
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 429 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

View File

@ -1,10 +0,0 @@
#If enabled, the mod will show alternative human readable filterstrings if available.
smart_inventory_friendly_group_names (Show “friendly” filter grouping names) bool true
#List of groups defined for special handling of "Shaped nodes" (Comma separated).
#Items in this groups ignores the "not_in_inventory" group and are moved to separate "Shaped" category
smart_inventory_shaped_groups (List of groups to be handled as separate) string carpet,door,fence,stair,slab,wall,micro,panel,slope,dye
#If enabled, the the mod does not replace other inventory mods.
#The functionality is provided in a workbench.
smart_inventory_workbench_mode (Use workbench instead of players inventory) bool false

View File

@ -1,2 +0,0 @@
The background border image goes where the skin button would normally go.
Inside the bordered area should be put the fron texture of a skins head.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 431 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 313 B

Some files were not shown because too many files have changed in this diff Show More