diff --git a/basic_materials/.github/workflows/luacheck.yml b/basic_materials/.github/workflows/luacheck.yml
new file mode 100644
index 0000000..a13efa9
--- /dev/null
+++ b/basic_materials/.github/workflows/luacheck.yml
@@ -0,0 +1,13 @@
+name: luacheck
+on: [push, pull_request]
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - name: apt
+ run: sudo apt-get install -y luarocks
+ - name: luacheck install
+ run: luarocks install --local luacheck
+ - name: luacheck run
+ run: $HOME/.luarocks/bin/luacheck ./
diff --git a/basic_materials/.luacheckrc b/basic_materials/.luacheckrc
new file mode 100644
index 0000000..55879b0
--- /dev/null
+++ b/basic_materials/.luacheckrc
@@ -0,0 +1,30 @@
+std = "lua51+minetest"
+unused_args = false
+allow_defined_top = true
+max_line_length = 999
+
+stds.minetest = {
+ read_globals = {
+ "DIR_DELIM",
+ "minetest",
+ "core",
+ "dump",
+ "vector",
+ "nodeupdate",
+ "VoxelManip",
+ "VoxelArea",
+ "PseudoRandom",
+ "ItemStack",
+ "default",
+ table = {
+ fields = {
+ "copy",
+ },
+ },
+ }
+}
+
+read_globals = {
+ "default",
+ "moreores",
+}
diff --git a/basic_materials/LICENSE b/basic_materials/LICENSE
new file mode 100644
index 0000000..c5885ae
--- /dev/null
+++ b/basic_materials/LICENSE
@@ -0,0 +1,600 @@
+License for code: LGPL 3.0
+License for media and all other assets: CC-by-SA 4.0
+
+###############################################################################
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ 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.
+
+###############################################################################
+
+Attribution-ShareAlike 4.0 International
+
+=======================================================================
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and
+does not provide legal services or legal advice. Distribution of
+Creative Commons public licenses does not create a lawyer-client or
+other relationship. Creative Commons makes its licenses and related
+information available on an "as-is" basis. Creative Commons gives no
+warranties regarding its licenses, any material licensed under their
+terms and conditions, or any related information. Creative Commons
+disclaims all liability for damages resulting from their use to the
+fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and
+conditions that creators and other rights holders may use to share
+original works of authorship and other material subject to copyright
+and certain other rights specified in the public license below. The
+following considerations are for informational purposes only, are not
+exhaustive, and do not form part of our licenses.
+
+ Considerations for licensors: Our public licenses are
+ intended for use by those authorized to give the public
+ permission to use material in ways otherwise restricted by
+ copyright and certain other rights. Our licenses are
+ irrevocable. Licensors should read and understand the terms
+ and conditions of the license they choose before applying it.
+ Licensors should also secure all rights necessary before
+ applying our licenses so that the public can reuse the
+ material as expected. Licensors should clearly mark any
+ material not subject to the license. This includes other CC-
+ licensed material, or material used under an exception or
+ limitation to copyright. More considerations for licensors:
+ wiki.creativecommons.org/Considerations_for_licensors
+
+ Considerations for the public: By using one of our public
+ licenses, a licensor grants the public permission to use the
+ licensed material under specified terms and conditions. If
+ the licensor's permission is not necessary for any reason--for
+ example, because of any applicable exception or limitation to
+ copyright--then that use is not regulated by the license. Our
+ licenses grant only permissions under copyright and certain
+ other rights that a licensor has authority to grant. Use of
+ the licensed material may still be restricted for other
+ reasons, including because others have copyright or other
+ rights in the material. A licensor may make special requests,
+ such as asking that all changes be marked or described.
+ Although not required by our licenses, you are encouraged to
+ respect those requests where reasonable. More considerations
+ for the public:
+ wiki.creativecommons.org/Considerations_for_licensees
+
+=======================================================================
+
+Creative Commons Attribution-ShareAlike 4.0 International Public
+License
+
+By exercising the Licensed Rights (defined below), You accept and agree
+to be bound by the terms and conditions of this Creative Commons
+Attribution-ShareAlike 4.0 International Public License ("Public
+License"). To the extent this Public License may be interpreted as a
+contract, You are granted the Licensed Rights in consideration of Your
+acceptance of these terms and conditions, and the Licensor grants You
+such rights in consideration of benefits the Licensor receives from
+making the Licensed Material available under these terms and
+conditions.
+
+
+Section 1 -- Definitions.
+
+ a. Adapted Material means material subject to Copyright and Similar
+ Rights that is derived from or based upon the Licensed Material
+ and in which the Licensed Material is translated, altered,
+ arranged, transformed, or otherwise modified in a manner requiring
+ permission under the Copyright and Similar Rights held by the
+ Licensor. For purposes of this Public License, where the Licensed
+ Material is a musical work, performance, or sound recording,
+ Adapted Material is always produced where the Licensed Material is
+ synched in timed relation with a moving image.
+
+ b. Adapter's License means the license You apply to Your Copyright
+ and Similar Rights in Your contributions to Adapted Material in
+ accordance with the terms and conditions of this Public License.
+
+ c. BY-SA Compatible License means a license listed at
+ creativecommons.org/compatiblelicenses, approved by Creative
+ Commons as essentially the equivalent of this Public License.
+
+ d. Copyright and Similar Rights means copyright and/or similar rights
+ closely related to copyright including, without limitation,
+ performance, broadcast, sound recording, and Sui Generis Database
+ Rights, without regard to how the rights are labeled or
+ categorized. For purposes of this Public License, the rights
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
+ Rights.
+
+ e. Effective Technological Measures means those measures that, in the
+ absence of proper authority, may not be circumvented under laws
+ fulfilling obligations under Article 11 of the WIPO Copyright
+ Treaty adopted on December 20, 1996, and/or similar international
+ agreements.
+
+ f. Exceptions and Limitations means fair use, fair dealing, and/or
+ any other exception or limitation to Copyright and Similar Rights
+ that applies to Your use of the Licensed Material.
+
+ g. License Elements means the license attributes listed in the name
+ of a Creative Commons Public License. The License Elements of this
+ Public License are Attribution and ShareAlike.
+
+ h. Licensed Material means the artistic or literary work, database,
+ or other material to which the Licensor applied this Public
+ License.
+
+ i. Licensed Rights means the rights granted to You subject to the
+ terms and conditions of this Public License, which are limited to
+ all Copyright and Similar Rights that apply to Your use of the
+ Licensed Material and that the Licensor has authority to license.
+
+ j. Licensor means the individual(s) or entity(ies) granting rights
+ under this Public License.
+
+ k. Share means to provide material to the public by any means or
+ process that requires permission under the Licensed Rights, such
+ as reproduction, public display, public performance, distribution,
+ dissemination, communication, or importation, and to make material
+ available to the public including in ways that members of the
+ public may access the material from a place and at a time
+ individually chosen by them.
+
+ l. Sui Generis Database Rights means rights other than copyright
+ resulting from Directive 96/9/EC of the European Parliament and of
+ the Council of 11 March 1996 on the legal protection of databases,
+ as amended and/or succeeded, as well as other essentially
+ equivalent rights anywhere in the world.
+
+ m. You means the individual or entity exercising the Licensed Rights
+ under this Public License. Your has a corresponding meaning.
+
+
+Section 2 -- Scope.
+
+ a. License grant.
+
+ 1. Subject to the terms and conditions of this Public License,
+ the Licensor hereby grants You a worldwide, royalty-free,
+ non-sublicensable, non-exclusive, irrevocable license to
+ exercise the Licensed Rights in the Licensed Material to:
+
+ a. reproduce and Share the Licensed Material, in whole or
+ in part; and
+
+ b. produce, reproduce, and Share Adapted Material.
+
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
+ Exceptions and Limitations apply to Your use, this Public
+ License does not apply, and You do not need to comply with
+ its terms and conditions.
+
+ 3. Term. The term of this Public License is specified in Section
+ 6(a).
+
+ 4. Media and formats; technical modifications allowed. The
+ Licensor authorizes You to exercise the Licensed Rights in
+ all media and formats whether now known or hereafter created,
+ and to make technical modifications necessary to do so. The
+ Licensor waives and/or agrees not to assert any right or
+ authority to forbid You from making technical modifications
+ necessary to exercise the Licensed Rights, including
+ technical modifications necessary to circumvent Effective
+ Technological Measures. For purposes of this Public License,
+ simply making modifications authorized by this Section 2(a)
+ (4) never produces Adapted Material.
+
+ 5. Downstream recipients.
+
+ a. Offer from the Licensor -- Licensed Material. Every
+ recipient of the Licensed Material automatically
+ receives an offer from the Licensor to exercise the
+ Licensed Rights under the terms and conditions of this
+ Public License.
+
+ b. Additional offer from the Licensor -- Adapted Material.
+ Every recipient of Adapted Material from You
+ automatically receives an offer from the Licensor to
+ exercise the Licensed Rights in the Adapted Material
+ under the conditions of the Adapter's License You apply.
+
+ c. No downstream restrictions. You may not offer or impose
+ any additional or different terms or conditions on, or
+ apply any Effective Technological Measures to, the
+ Licensed Material if doing so restricts exercise of the
+ Licensed Rights by any recipient of the Licensed
+ Material.
+
+ 6. No endorsement. Nothing in this Public License constitutes or
+ may be construed as permission to assert or imply that You
+ are, or that Your use of the Licensed Material is, connected
+ with, or sponsored, endorsed, or granted official status by,
+ the Licensor or others designated to receive attribution as
+ provided in Section 3(a)(1)(A)(i).
+
+ b. Other rights.
+
+ 1. Moral rights, such as the right of integrity, are not
+ licensed under this Public License, nor are publicity,
+ privacy, and/or other similar personality rights; however, to
+ the extent possible, the Licensor waives and/or agrees not to
+ assert any such rights held by the Licensor to the limited
+ extent necessary to allow You to exercise the Licensed
+ Rights, but not otherwise.
+
+ 2. Patent and trademark rights are not licensed under this
+ Public License.
+
+ 3. To the extent possible, the Licensor waives any right to
+ collect royalties from You for the exercise of the Licensed
+ Rights, whether directly or through a collecting society
+ under any voluntary or waivable statutory or compulsory
+ licensing scheme. In all other cases the Licensor expressly
+ reserves any right to collect such royalties.
+
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the
+following conditions.
+
+ a. Attribution.
+
+ 1. If You Share the Licensed Material (including in modified
+ form), You must:
+
+ a. retain the following if it is supplied by the Licensor
+ with the Licensed Material:
+
+ i. identification of the creator(s) of the Licensed
+ Material and any others designated to receive
+ attribution, in any reasonable manner requested by
+ the Licensor (including by pseudonym if
+ designated);
+
+ ii. a copyright notice;
+
+ iii. a notice that refers to this Public License;
+
+ iv. a notice that refers to the disclaimer of
+ warranties;
+
+ v. a URI or hyperlink to the Licensed Material to the
+ extent reasonably practicable;
+
+ b. indicate if You modified the Licensed Material and
+ retain an indication of any previous modifications; and
+
+ c. indicate the Licensed Material is licensed under this
+ Public License, and include the text of, or the URI or
+ hyperlink to, this Public License.
+
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
+ reasonable manner based on the medium, means, and context in
+ which You Share the Licensed Material. For example, it may be
+ reasonable to satisfy the conditions by providing a URI or
+ hyperlink to a resource that includes the required
+ information.
+
+ 3. If requested by the Licensor, You must remove any of the
+ information required by Section 3(a)(1)(A) to the extent
+ reasonably practicable.
+
+ b. ShareAlike.
+
+ In addition to the conditions in Section 3(a), if You Share
+ Adapted Material You produce, the following conditions also apply.
+
+ 1. The Adapter's License You apply must be a Creative Commons
+ license with the same License Elements, this version or
+ later, or a BY-SA Compatible License.
+
+ 2. You must include the text of, or the URI or hyperlink to, the
+ Adapter's License You apply. You may satisfy this condition
+ in any reasonable manner based on the medium, means, and
+ context in which You Share Adapted Material.
+
+ 3. You may not offer or impose any additional or different terms
+ or conditions on, or apply any Effective Technological
+ Measures to, Adapted Material that restrict exercise of the
+ rights granted under the Adapter's License You apply.
+
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that
+apply to Your use of the Licensed Material:
+
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+ to extract, reuse, reproduce, and Share all or a substantial
+ portion of the contents of the database;
+
+ b. if You include all or a substantial portion of the database
+ contents in a database in which You have Sui Generis Database
+ Rights, then the database in which You have Sui Generis Database
+ Rights (but not its individual contents) is Adapted Material,
+
+ including for purposes of Section 3(b); and
+ c. You must comply with the conditions in Section 3(a) if You Share
+ all or a substantial portion of the contents of the database.
+
+For the avoidance of doubt, this Section 4 supplements and does not
+replace Your obligations under this Public License where the Licensed
+Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+
+ c. The disclaimer of warranties and limitation of liability provided
+ above shall be interpreted in a manner that, to the extent
+ possible, most closely approximates an absolute disclaimer and
+ waiver of all liability.
+
+
+Section 6 -- Term and Termination.
+
+ a. This Public License applies for the term of the Copyright and
+ Similar Rights licensed here. However, if You fail to comply with
+ this Public License, then Your rights under this Public License
+ terminate automatically.
+
+ b. Where Your right to use the Licensed Material has terminated under
+ Section 6(a), it reinstates:
+
+ 1. automatically as of the date the violation is cured, provided
+ it is cured within 30 days of Your discovery of the
+ violation; or
+
+ 2. upon express reinstatement by the Licensor.
+
+ For the avoidance of doubt, this Section 6(b) does not affect any
+ right the Licensor may have to seek remedies for Your violations
+ of this Public License.
+
+ c. For the avoidance of doubt, the Licensor may also offer the
+ Licensed Material under separate terms or conditions or stop
+ distributing the Licensed Material at any time; however, doing so
+ will not terminate this Public License.
+
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+ License.
+
+
+Section 7 -- Other Terms and Conditions.
+
+ a. The Licensor shall not be bound by any additional or different
+ terms or conditions communicated by You unless expressly agreed.
+
+ b. Any arrangements, understandings, or agreements regarding the
+ Licensed Material not stated herein are separate from and
+ independent of the terms and conditions of this Public License.
+
+
+Section 8 -- Interpretation.
+
+ a. For the avoidance of doubt, this Public License does not, and
+ shall not be interpreted to, reduce, limit, restrict, or impose
+ conditions on any use of the Licensed Material that could lawfully
+ be made without permission under this Public License.
+
+ b. To the extent possible, if any provision of this Public License is
+ deemed unenforceable, it shall be automatically reformed to the
+ minimum extent necessary to make it enforceable. If the provision
+ cannot be reformed, it shall be severed from this Public License
+ without affecting the enforceability of the remaining terms and
+ conditions.
+
+ c. No term or condition of this Public License will be waived and no
+ failure to comply consented to unless expressly agreed to by the
+ Licensor.
+
+ d. Nothing in this Public License constitutes or may be interpreted
+ as a limitation upon, or waiver of, any privileges and immunities
+ that apply to the Licensor or You, including from the legal
+ processes of any jurisdiction or authority.
+
+
+=======================================================================
+
+Creative Commons is not a party to its public
+licenses. Notwithstanding, Creative Commons may elect to apply one of
+its public licenses to material it publishes and in those instances
+will be considered the “Licensor.” The text of the Creative Commons
+public licenses is dedicated to the public domain under the CC0 Public
+Domain Dedication. Except for the limited purpose of indicating that
+material is shared under a Creative Commons public license or as
+otherwise permitted by the Creative Commons policies published at
+creativecommons.org/policies, Creative Commons does not authorize the
+use of the trademark "Creative Commons" or any other trademark or logo
+of Creative Commons without its prior written consent including,
+without limitation, in connection with any unauthorized modifications
+to any of its public licenses or any other arrangements,
+understandings, or agreements concerning use of licensed material. For
+the avoidance of doubt, this paragraph does not form part of the
+public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
diff --git a/basic_materials/electrical-electronic.lua b/basic_materials/electrical-electronic.lua
new file mode 100644
index 0000000..91fac4e
--- /dev/null
+++ b/basic_materials/electrical-electronic.lua
@@ -0,0 +1,86 @@
+-- Translation support
+local S = minetest.get_translator("basic_materials")
+
+-- items
+
+minetest.register_craftitem("basic_materials:silicon", {
+ description = S("Silicon lump"),
+ inventory_image = "basic_materials_silicon.png",
+})
+
+minetest.register_craftitem("basic_materials:ic", {
+ description = S("Simple Integrated Circuit"),
+ inventory_image = "basic_materials_ic.png",
+})
+
+minetest.register_craftitem("basic_materials:motor", {
+ description = S("Simple Motor"),
+ inventory_image = "basic_materials_motor.png",
+})
+
+minetest.register_craftitem("basic_materials:heating_element", {
+ description = S("Heating element"),
+ inventory_image = "basic_materials_heating_element.png",
+})
+
+minetest.register_craftitem("basic_materials:energy_crystal_simple", {
+ description = S("Simple energy crystal"),
+ inventory_image = "basic_materials_energy_crystal.png",
+})
+
+-- crafts
+
+minetest.register_craft( {
+ output = "mesecons_materials:silicon 4",
+ recipe = {
+ { "default:sand", "default:sand" },
+ { "default:sand", "default:steel_ingot" },
+ },
+})
+
+minetest.register_craft( {
+ output = "basic_materials:ic 4",
+ recipe = {
+ { "mesecons_materials:silicon", "mesecons_materials:silicon" },
+ { "mesecons_materials:silicon", "default:copper_ingot" },
+ },
+})
+
+minetest.register_craft( {
+ output = "basic_materials:motor 2",
+ recipe = {
+ { "default:mese_crystal_fragment", "basic_materials:copper_wire", "basic_materials:plastic_sheet" },
+ { "default:copper_ingot", "default:steel_ingot", "default:steel_ingot" },
+ { "default:mese_crystal_fragment", "basic_materials:copper_wire", "basic_materials:plastic_sheet" }
+ },
+ replacements = {
+ { "basic_materials:copper_wire", "basic_materials:empty_spool" },
+ { "basic_materials:copper_wire", "basic_materials:empty_spool" },
+ }
+})
+
+minetest.register_craft( {
+ output = "basic_materials:heating_element 2",
+ recipe = {
+ { "default:copper_ingot", "default:mese_crystal_fragment", "default:copper_ingot" }
+ },
+})
+
+minetest.register_craft({
+ --type = "shapeless",
+ output = "basic_materials:energy_crystal_simple 2",
+ recipe = {
+ { "default:mese_crystal_fragment", "default:torch", "default:mese_crystal_fragment" },
+ { "default:diamond", "default:gold_ingot", "default:diamond" }
+ },
+})
+
+-- aliases
+
+minetest.register_alias("homedecor:ic", "basic_materials:ic")
+minetest.register_alias("homedecor:motor", "basic_materials:motor")
+minetest.register_alias("technic:motor", "basic_materials:motor")
+minetest.register_alias("homedecor:heating_element", "basic_materials:heating_element")
+minetest.register_alias("homedecor:power_crystal", "basic_materials:energy_crystal_simple")
+
+minetest.register_alias_force("mesecons_materials:silicon", "basic_materials:silicon")
diff --git a/basic_materials/init.lua b/basic_materials/init.lua
new file mode 100644
index 0000000..348c059
--- /dev/null
+++ b/basic_materials/init.lua
@@ -0,0 +1,15 @@
+-- Basic materials mod
+-- by Vanessa Dannenberg
+
+-- This mod supplies all those little random craft items that everyone always
+-- seems to need, such as metal bars (ala rebar), plastic, wire, and so on.
+
+local modpath = minetest.get_modpath("basic_materials")
+
+basic_materials = {}
+basic_materials.mod = { author = "Vanessa Dannenberg" }
+
+dofile(modpath.."/metals.lua")
+dofile(modpath.."/plastics.lua")
+dofile(modpath.."/electrical-electronic.lua")
+dofile(modpath.."/misc.lua")
diff --git a/basic_materials/locale/basic_materials.de.tr b/basic_materials/locale/basic_materials.de.tr
new file mode 100644
index 0000000..8fddd8a
--- /dev/null
+++ b/basic_materials/locale/basic_materials.de.tr
@@ -0,0 +1,33 @@
+# textdomain: basic_materials
+Silicon lump=Siliziumklumpen
+Simple Integrated Circuit=Einfacher Integrierter Schaltkreis
+Simple Motor=Einfacher Motor
+Heating element=Heizelement
+Simple energy crystal=Einfacher Energiekristall
+
+Spool of steel wire=Spule mit Stahldraht
+Spool of copper wire=Spule mit Kupferdraht
+Spool of silver wire=Spule mit Silberdraht
+Spool of gold wire=Spule mit Golddraht
+Steel Strip=Stahlstreifen
+Copper Strip=Kupferstreifen
+Steel Bar=Stahlstab
+Chainlinks (brass)=Messingkettenglieder
+Chainlinks (steel)=Stahlkettenglieder
+Brass Ingot=Messingbarren
+Steel gear=Stahlzahnrad
+Padlock=Vorhängeschloss
+Chain (steel, hanging)=Hängende Stahlkette
+Chain (brass, hanging)=Hängende Messingkette
+Brass Block=Messingblock
+
+Oil extract=Ölextrakt
+Unprocessed paraffin=Unverarbeitetes Paraffin
+Uncooked Terracotta Base=Ungebranntes Terrakotta
+Wet Cement=Nasser Zement
+Cement=Zement
+Concrete Block=Betonblock
+
+Plastic sheet=Kunststoffplatte
+Plastic strips=Kunststoffstreifen
+Empty wire spool=Leere Drahtspule
diff --git a/basic_materials/locale/basic_materials.fr.tr b/basic_materials/locale/basic_materials.fr.tr
new file mode 100644
index 0000000..0bebf79
--- /dev/null
+++ b/basic_materials/locale/basic_materials.fr.tr
@@ -0,0 +1,33 @@
+# textdomain: basic_materials
+Silicon lump=Morceau de silicium
+Simple Integrated Circuit=Circuit intégré simple
+Simple Motor=Moteur simple
+Heating element=Élément chauffant
+Simple energy crystal=Cristal d’énergie simple
+
+Spool of steel wire=Bobine de fil d’acier
+Spool of copper wire=Bobine de fil de cuivre
+Spool of silver wire=Bobine de fil d’argent
+Spool of gold wire=Bobine de fil d’or
+Steel Strip=Bande de acier
+Copper Strip=Bande de cuivre
+Steel Bar=Barre d’acier
+Chainlinks (brass)=Maillon en laiton
+Chainlinks (steel)=Maillon en acier
+Brass Ingot=Lingot de laiton
+Steel gear=Rouage en acier
+Padlock=Cadenas
+Chain (steel, hanging)=Chaine en acier
+Chain (brass, hanging)=Chaine en laiton
+Brass Block=Bloc de laiton
+
+Oil extract=Extrait d’huile
+Unprocessed paraffin=Paraffine non transformée
+Uncooked Terracotta Base=Argile crue
+Wet Cement=Ciment humide
+Cement=Ciment
+Concrete Block=Bloc de béton
+
+Plastic sheet=Morceau de plastique
+Plastic strips=Bande de plastique
+Empty wire spool=Bobine de fil vide
diff --git a/basic_materials/locale/basic_materials.it.tr b/basic_materials/locale/basic_materials.it.tr
new file mode 100644
index 0000000..aae0b3b
--- /dev/null
+++ b/basic_materials/locale/basic_materials.it.tr
@@ -0,0 +1,34 @@
+# textdomain: basic_materials
+# Author: Salvo 'LtWorf' Tomaselli
+Silicon lump=Grumo di silicio
+Simple Integrated Circuit=Circuito integrato semplice
+Simple Motor=Motore semplice
+Heating element=Elemento riscaldante
+Simple energy crystal=Cristallo di energia semplice
+
+Spool of steel wire=Bobina di filo d'acciaio
+Spool of copper wire=Bobina di filo di rame
+Spool of silver wire=Bobina di filo d'argento
+Spool of gold wire=Bobina di filo d'oro
+Steel Strip=Striscia d'acciaio
+Copper Strip=Striscia di rame
+Steel Bar=Barra d'acciaio
+Chainlinks (brass)=Catena (ottone)
+Chainlinks (steel)=Catena (acciaio)
+Brass Ingot=Lingotto di ottone
+Steel gear=Ingranaggio d'acciaio
+Padlock=Catenaccio
+Chain (steel, hanging)=Catena (acciaio, pendente)
+Chain (brass, hanging)=Catena (ottone, pendente)
+Brass Block=Blocco di ottone
+
+Oil extract=Estratto d'olio
+Unprocessed paraffin=Paraffina grezza
+Uncooked Terracotta Base=Argilla cruda
+Wet Cement=Cemento umido
+Cement=Cemento
+Concrete Block=Blocco di calcestruzzo
+
+Plastic sheet=Foglio di plastica
+Plastic strips=Striscia di plastica
+Empty wire spool=Rocchetto vuoto
diff --git a/basic_materials/locale/basic_materials.ru.tr b/basic_materials/locale/basic_materials.ru.tr
new file mode 100644
index 0000000..85e9c0c
--- /dev/null
+++ b/basic_materials/locale/basic_materials.ru.tr
@@ -0,0 +1,33 @@
+# textdomain: basic_materials
+Silicon lump=Кусок Кремния
+Simple Integrated Circuit=Микросхема
+Simple Motor=Мотор
+Heating element=Нить Накала
+Simple energy crystal=Энергетический Кристалл
+
+Spool of steel wire=Катушка Стальной Проволоки
+Spool of copper wire=Катушка Медной Проволоки
+Spool of silver wire=Катушка Серебрянной Проволоки
+Spool of gold wire=Катушка Золотой Проволоки
+Steel Strip=Стальная Полоса
+Copper Strip=Медная Полоса
+Steel Bar=Стальной Прут
+Chainlinks (brass)=Латунные Звенья
+Chainlinks (steel)=Стальные Звенья
+Brass Ingot=Латунный Брусок
+Steel gear=Стальная Шестерня
+Padlock=Навесной Замок
+Chain (steel, hanging)=Стальная Цепь
+Chain (brass, hanging)=Латунная Цепь
+Brass Block=Латунный Блок
+
+Oil extract=Масляный Экстракт
+Unprocessed paraffin=Необработанный Парафин
+Uncooked Terracotta Base=Ком Мокрого Терракота
+Wet Cement=Ком Мокрого Цемента
+Cement=Цемент
+Concrete Block=Железобетон
+
+Plastic sheet=Пластиковый Лист
+Plastic strips=Пластиковая Полоса
+Empty wire spool=Пустая Катушка
diff --git a/basic_materials/metals.lua b/basic_materials/metals.lua
new file mode 100644
index 0000000..0a3243b
--- /dev/null
+++ b/basic_materials/metals.lua
@@ -0,0 +1,300 @@
+-- Translation support
+local S = minetest.get_translator("basic_materials")
+
+-- items
+
+minetest.register_craftitem("basic_materials:steel_wire", {
+ description = S("Spool of steel wire"),
+ groups = { wire = 1 },
+ inventory_image = "basic_materials_steel_wire.png"
+})
+
+minetest.register_craftitem("basic_materials:copper_wire", {
+ description = S("Spool of copper wire"),
+ groups = { wire = 1 },
+ inventory_image = "basic_materials_copper_wire.png"
+})
+
+minetest.register_craftitem("basic_materials:silver_wire", {
+ description = S("Spool of silver wire"),
+ groups = { wire = 1 },
+ inventory_image = "basic_materials_silver_wire.png"
+})
+
+minetest.register_craftitem("basic_materials:gold_wire", {
+ description = S("Spool of gold wire"),
+ groups = { wire = 1 },
+ inventory_image = "basic_materials_gold_wire.png"
+})
+
+minetest.register_craftitem("basic_materials:steel_strip", {
+ description = S("Steel Strip"),
+ groups = { strip = 1 },
+ inventory_image = "basic_materials_steel_strip.png"
+})
+
+minetest.register_craftitem("basic_materials:copper_strip", {
+ description = S("Copper Strip"),
+ groups = { strip = 1 },
+ inventory_image = "basic_materials_copper_strip.png"
+})
+
+minetest.register_craftitem("basic_materials:steel_bar", {
+ description = S("Steel Bar"),
+ inventory_image = "basic_materials_steel_bar.png",
+})
+
+minetest.register_craftitem("basic_materials:chainlink_brass", {
+ description = S("Chainlinks (brass)"),
+ groups = { chainlinks = 1 },
+ inventory_image = "basic_materials_chainlink_brass.png"
+})
+
+minetest.register_craftitem("basic_materials:chainlink_steel", {
+ description = S("Chainlinks (steel)"),
+ groups = { chainlinks = 1 },
+ inventory_image = "basic_materials_chainlink_steel.png"
+})
+
+minetest.register_craftitem("basic_materials:brass_ingot", {
+ description = S("Brass Ingot"),
+ inventory_image = "basic_materials_brass_ingot.png",
+})
+
+minetest.register_craftitem("basic_materials:gear_steel", {
+ description = S("Steel gear"),
+ inventory_image = "basic_materials_gear_steel.png"
+})
+
+minetest.register_craftitem("basic_materials:padlock", {
+ description = S("Padlock"),
+ inventory_image = "basic_materials_padlock.png"
+})
+
+-- nodes
+
+local chains_sbox = {
+ type = "fixed",
+ fixed = { -0.1, -0.5, -0.1, 0.1, 0.5, 0.1 }
+}
+
+minetest.register_node("basic_materials:chain_steel", {
+ description = S("Chain (steel, hanging)"),
+ drawtype = "mesh",
+ mesh = "basic_materials_chains.obj",
+ tiles = {"basic_materials_chain_steel.png"},
+ walkable = false,
+ climbable = true,
+ sunlight_propagates = true,
+ paramtype = "light",
+ inventory_image = "basic_materials_chain_steel_inv.png",
+ groups = {cracky=3},
+ selection_box = chains_sbox,
+})
+
+minetest.register_node("basic_materials:chain_brass", {
+ description = S("Chain (brass, hanging)"),
+ drawtype = "mesh",
+ mesh = "basic_materials_chains.obj",
+ tiles = {"basic_materials_chain_brass.png"},
+ walkable = false,
+ climbable = true,
+ sunlight_propagates = true,
+ paramtype = "light",
+ inventory_image = "basic_materials_chain_brass_inv.png",
+ groups = {cracky=3},
+ selection_box = chains_sbox,
+})
+
+minetest.register_node("basic_materials:brass_block", {
+ description = S("Brass Block"),
+ tiles = { "basic_materials_brass_block.png" },
+ is_ground_content = false,
+ groups = {cracky=1, level=2},
+ sounds = default.node_sound_metal_defaults()
+})
+
+-- crafts
+
+minetest.register_craft( {
+ output = "basic_materials:copper_wire 2",
+ type = "shapeless",
+ recipe = {
+ "default:copper_ingot",
+ "basic_materials:empty_spool",
+ "basic_materials:empty_spool",
+ },
+})
+
+minetest.register_craft( {
+ output = "basic_materials:silver_wire 2",
+ type = "shapeless",
+ recipe = {
+ "moreores:silver_ingot",
+ "basic_materials:empty_spool",
+ "basic_materials:empty_spool",
+ },
+})
+
+minetest.register_craft( {
+ output = "basic_materials:gold_wire 2",
+ type = "shapeless",
+ recipe = {
+ "default:gold_ingot",
+ "basic_materials:empty_spool",
+ "basic_materials:empty_spool",
+ },
+})
+
+minetest.register_craft( {
+ output = "basic_materials:steel_wire 2",
+ type = "shapeless",
+ recipe = {
+ "default:steel_ingot",
+ "basic_materials:empty_spool",
+ "basic_materials:empty_spool",
+ },
+})
+
+minetest.register_craft( {
+ output = "basic_materials:steel_strip 12",
+ recipe = {
+ { "", "default:steel_ingot", "" },
+ { "default:steel_ingot", "", "" },
+ },
+})
+
+minetest.register_craft( {
+ output = "basic_materials:copper_strip 12",
+ recipe = {
+ { "", "default:copper_ingot", "" },
+ { "default:copper_ingot", "", "" },
+ },
+})
+
+minetest.register_craft( {
+ output = "basic_materials:steel_bar 6",
+ recipe = {
+ { "", "", "default:steel_ingot" },
+ { "", "default:steel_ingot", "" },
+ { "default:steel_ingot", "", "" },
+ },
+})
+
+minetest.register_craft( {
+ output = "basic_materials:padlock 2",
+ recipe = {
+ { "basic_materials:steel_bar" },
+ { "default:steel_ingot" },
+ { "default:steel_ingot" },
+ },
+})
+
+minetest.register_craft({
+ output = "basic_materials:chainlink_steel 12",
+ recipe = {
+ {"", "default:steel_ingot", "default:steel_ingot"},
+ { "default:steel_ingot", "", "default:steel_ingot" },
+ { "default:steel_ingot", "default:steel_ingot", "" },
+ },
+})
+
+minetest.register_craft({
+ output = "basic_materials:chainlink_brass 12",
+ recipe = {
+ {"", "basic_materials:brass_ingot", "basic_materials:brass_ingot"},
+ { "basic_materials:brass_ingot", "", "basic_materials:brass_ingot" },
+ { "basic_materials:brass_ingot", "basic_materials:brass_ingot", "" },
+ },
+})
+
+minetest.register_craft({
+ output = 'basic_materials:chain_steel 2',
+ recipe = {
+ {"basic_materials:chainlink_steel"},
+ {"basic_materials:chainlink_steel"},
+ {"basic_materials:chainlink_steel"}
+ }
+})
+
+minetest.register_craft({
+ output = 'basic_materials:chain_brass 2',
+ recipe = {
+ {"basic_materials:chainlink_brass"},
+ {"basic_materials:chainlink_brass"},
+ {"basic_materials:chainlink_brass"}
+ }
+})
+
+minetest.register_craft( {
+ output = "basic_materials:gear_steel 6",
+ recipe = {
+ { "", "default:steel_ingot", "" },
+ { "default:steel_ingot","basic_materials:chainlink_steel", "default:steel_ingot" },
+ { "", "default:steel_ingot", "" }
+ },
+})
+
+minetest.register_craft( {
+ type = "shapeless",
+ output = "basic_materials:brass_ingot 3",
+ recipe = {
+ "default:copper_ingot",
+ "default:copper_ingot",
+ "moreores:silver_ingot",
+ },
+})
+
+if not minetest.get_modpath("moreores") then
+ -- Without moreores, there still should be a way to create brass.
+ minetest.register_craft( {
+ output = "basic_materials:brass_ingot 9",
+ recipe = {
+ {"default:copper_ingot", "default:tin_ingot", "default:copper_ingot"},
+ {"default:gold_ingot", "default:copper_ingot", "default:gold_ingot"},
+ {"default:copper_ingot", "default:tin_ingot", "default:copper_ingot"},
+ },
+ })
+end
+
+minetest.register_craft( {
+ type = "shapeless",
+ output = "basic_materials:brass_ingot 9",
+ recipe = { "basic_materials:brass_block" },
+})
+
+minetest.register_craft( {
+ output = "basic_materials:brass_block",
+ recipe = {
+ { "basic_materials:brass_ingot", "basic_materials:brass_ingot", "basic_materials:brass_ingot" },
+ { "basic_materials:brass_ingot", "basic_materials:brass_ingot", "basic_materials:brass_ingot" },
+ { "basic_materials:brass_ingot", "basic_materials:brass_ingot", "basic_materials:brass_ingot" },
+ },
+})
+
+-- aliases
+
+minetest.register_alias("homedecor:copper_wire", "basic_materials:copper_wire")
+minetest.register_alias("technic:fine_copper_wire", "basic_materials:copper_wire")
+minetest.register_alias("technic:fine_silver_wire", "basic_materials:silver_wire")
+minetest.register_alias("technic:fine_gold_wire", "basic_materials:gold_wire")
+
+minetest.register_alias("homedecor:steel_wire", "basic_materials:steel_wire")
+
+minetest.register_alias("homedecor:brass_ingot", "basic_materials:brass_ingot")
+minetest.register_alias("technic:brass_ingot", "basic_materials:brass_ingot")
+minetest.register_alias("technic:brass_block", "basic_materials:brass_block")
+
+minetest.register_alias("homedecor:copper_strip", "basic_materials:copper_strip")
+minetest.register_alias("homedecor:steel_strip", "basic_materials:steel_strip")
+
+minetest.register_alias_force("glooptest:chainlink", "basic_materials:chainlink_steel")
+minetest.register_alias_force("homedecor:chainlink_steel", "basic_materials:chainlink_steel")
+minetest.register_alias("homedecor:chainlink_brass", "basic_materials:chainlink_brass")
+minetest.register_alias("chains:chain", "basic_materials:chain_steel")
+minetest.register_alias("chains:chain_brass", "basic_materials:chain_brass")
+
+minetest.register_alias("pipeworks:gear", "basic_materials:gear_steel")
+
+minetest.register_alias("technic:rebar", "basic_materials:steel_bar")
+
diff --git a/basic_materials/misc.lua b/basic_materials/misc.lua
new file mode 100644
index 0000000..0012897
--- /dev/null
+++ b/basic_materials/misc.lua
@@ -0,0 +1,126 @@
+-- Translation support
+local S = minetest.get_translator("basic_materials")
+
+-- items
+
+minetest.register_craftitem("basic_materials:oil_extract", {
+ description = S("Oil extract"),
+ inventory_image = "basic_materials_oil_extract.png",
+})
+
+minetest.register_craftitem("basic_materials:paraffin", {
+ description = S("Unprocessed paraffin"),
+ inventory_image = "basic_materials_paraffin.png",
+})
+
+minetest.register_craftitem("basic_materials:terracotta_base", {
+ description = S("Uncooked Terracotta Base"),
+ inventory_image = "basic_materials_terracotta_base.png",
+})
+
+minetest.register_craftitem("basic_materials:wet_cement", {
+ description = S("Wet Cement"),
+ inventory_image = "basic_materials_wet_cement.png",
+})
+
+-- nodes
+
+minetest.register_node("basic_materials:cement_block", {
+ description = S("Cement"),
+ tiles = {"basic_materials_cement_block.png"},
+ is_ground_content = true,
+ groups = {cracky=2},
+ sounds = default.node_sound_stone_defaults(),
+})
+
+minetest.register_node("basic_materials:concrete_block", {
+ description = S("Concrete Block"),
+ tiles = {"basic_materials_concrete_block.png",},
+ groups = {cracky=1, level=2, concrete=1},
+ sounds = default.node_sound_stone_defaults(),
+})
+
+-- crafts
+
+minetest.register_craft({
+ type = "shapeless",
+ output = "basic_materials:oil_extract 2",
+ recipe = {
+ "group:leaves",
+ "group:leaves",
+ "group:leaves",
+ "group:leaves",
+ "group:leaves",
+ "group:leaves"
+ }
+})
+
+minetest.register_craft({
+ type = "cooking",
+ output = "basic_materials:paraffin",
+ recipe = "basic_materials:oil_extract",
+})
+
+minetest.register_craft({
+ type = "fuel",
+ recipe = "basic_materials:oil_extract",
+ burntime = 30,
+})
+
+minetest.register_craft({
+ type = "fuel",
+ recipe = "basic_materials:paraffin",
+ burntime = 30,
+})
+
+minetest.register_craft( {
+ type = "shapeless",
+ output = "basic_materials:terracotta_base 8",
+ recipe = {
+ "bucket:bucket_water",
+ "default:clay_lump",
+ "default:gravel",
+ },
+ replacements = { {"bucket:bucket_water", "bucket:bucket_empty"}, },
+})
+
+minetest.register_craft({
+ type = "shapeless",
+ output = "basic_materials:wet_cement 3",
+ recipe = {
+ "default:dirt",
+ "dye:dark_grey",
+ "dye:dark_grey",
+ "dye:dark_grey",
+ "bucket:bucket_water"
+ },
+ replacements = {{'bucket:bucket_water', 'bucket:bucket_empty'},},
+})
+
+minetest.register_craft({
+ type = "cooking",
+ output = "basic_materials:cement_block",
+ recipe = "basic_materials:wet_cement",
+ cooktime = 8
+})
+
+minetest.register_craft({
+ output = 'basic_materials:concrete_block 6',
+ recipe = {
+ {'group:sand', 'basic_materials:wet_cement', 'default:gravel'},
+ {'basic_materials:steel_bar', 'basic_materials:wet_cement', 'basic_materials:steel_bar'},
+ {'default:gravel', 'basic_materials:wet_cement', 'group:sand'},
+ }
+})
+
+-- aliases
+
+minetest.register_alias("homedecor:oil_extract", "basic_materials:oil_extract")
+minetest.register_alias("homedecor:paraffin", "basic_materials:paraffin")
+minetest.register_alias("homedecor:plastic_base", "basic_materials:paraffin")
+minetest.register_alias("homedecor:terracotta_base", "basic_materials:terracotta_base")
+
+minetest.register_alias("gloopblocks:wet_cement", "basic_materials:wet_cement")
+minetest.register_alias("gloopblocks:cement", "basic_materials:cement_block")
+
+minetest.register_alias("technic:concrete", "basic_materials:concrete_block")
diff --git a/basic_materials/mod.conf b/basic_materials/mod.conf
new file mode 100644
index 0000000..7234bfe
--- /dev/null
+++ b/basic_materials/mod.conf
@@ -0,0 +1,4 @@
+name = basic_materials
+depends = default
+optional_depends = moreores
+min_minetest_version = 5.2.0
diff --git a/basic_materials/models/basic_materials_chains.obj b/basic_materials/models/basic_materials_chains.obj
new file mode 100644
index 0000000..78724c9
--- /dev/null
+++ b/basic_materials/models/basic_materials_chains.obj
@@ -0,0 +1,881 @@
+# Blender v2.73 (sub 0) OBJ File: 'chains.blend'
+# www.blender.org
+o Torus.016_Torus
+v 0.000000 -0.429978 0.000002
+v 0.000000 -0.401109 0.055211
+v -0.014044 -0.391975 0.048870
+v -0.014044 -0.423304 0.000002
+v -0.009826 -0.379748 0.040970
+v -0.009826 -0.406012 0.000002
+v 0.009826 -0.379748 0.040970
+v 0.009826 -0.406012 0.000002
+v 0.014044 -0.391975 0.048870
+v 0.014044 -0.423304 0.000002
+v 0.000000 -0.316336 0.080195
+v -0.014044 -0.316336 0.069112
+v -0.009826 -0.316336 0.057941
+v 0.009826 -0.316336 0.057941
+v 0.014044 -0.316336 0.069112
+v 0.000000 -0.231564 0.055211
+v -0.014044 -0.240700 0.048870
+v -0.009826 -0.252925 0.040970
+v 0.009826 -0.252925 0.040970
+v 0.014044 -0.240700 0.048870
+v 0.000000 -0.202695 0.000002
+v -0.014044 -0.209368 0.000002
+v -0.009826 -0.226661 0.000002
+v 0.009826 -0.226661 0.000002
+v 0.014044 -0.209368 0.000002
+v 0.000000 -0.231564 -0.055206
+v -0.014044 -0.240700 -0.048868
+v -0.009826 -0.252925 -0.040967
+v 0.009826 -0.252925 -0.040967
+v 0.014044 -0.240700 -0.048865
+v 0.000000 -0.316336 -0.080190
+v -0.014044 -0.316336 -0.069108
+v -0.009826 -0.316336 -0.057936
+v 0.009826 -0.316336 -0.057936
+v 0.014044 -0.316336 -0.069108
+v 0.000000 -0.400361 -0.055206
+v -0.014044 -0.391975 -0.048868
+v -0.009826 -0.379748 -0.040967
+v 0.009826 -0.379748 -0.040967
+v 0.014044 -0.391975 -0.048868
+v 0.000000 -0.262249 0.000002
+v -0.061672 -0.233381 0.000002
+v -0.054590 -0.224245 -0.012569
+v 0.000000 -0.255577 -0.012569
+v -0.045765 -0.212018 -0.008794
+v 0.000000 -0.238285 -0.008794
+v -0.045765 -0.212018 0.008798
+v 0.000000 -0.238285 0.008798
+v -0.054590 -0.224245 0.012574
+v 0.000000 -0.255577 0.012574
+v -0.089582 -0.148609 0.000002
+v -0.077200 -0.148609 -0.012569
+v -0.064722 -0.148609 -0.008794
+v -0.064722 -0.148609 0.008799
+v -0.077200 -0.148609 0.012574
+v -0.061672 -0.063837 0.000002
+v -0.054590 -0.072971 -0.012569
+v -0.045765 -0.085198 -0.008794
+v -0.045765 -0.085198 0.008799
+v -0.054590 -0.072971 0.012574
+v 0.000000 -0.034967 0.000002
+v 0.000000 -0.041641 -0.012569
+v 0.000000 -0.058933 -0.008794
+v 0.000000 -0.058933 0.008799
+v 0.000000 -0.041641 0.012574
+v 0.061672 -0.063837 0.000002
+v 0.054590 -0.072971 -0.012569
+v 0.045765 -0.085198 -0.008794
+v 0.045765 -0.085198 0.008799
+v 0.054590 -0.072971 0.012574
+v 0.089582 -0.148609 0.000002
+v 0.077200 -0.148609 -0.012569
+v 0.064722 -0.148609 -0.008794
+v 0.064722 -0.148609 0.008799
+v 0.077200 -0.148609 0.012574
+v 0.061672 -0.232631 0.000002
+v 0.054590 -0.224245 -0.012569
+v 0.045765 -0.212018 -0.008794
+v 0.045765 -0.212018 0.008798
+v 0.054590 -0.224245 0.012574
+v 0.000000 0.073316 0.000002
+v 0.061672 0.102183 0.000002
+v 0.054590 0.111319 0.012574
+v 0.000000 0.079988 0.012574
+v 0.045765 0.123546 0.008799
+v 0.000000 0.097280 0.008799
+v 0.045765 0.123546 -0.008794
+v 0.000000 0.097280 -0.008794
+v 0.054590 0.111319 -0.012569
+v 0.000000 0.079988 -0.012569
+v 0.089582 0.186956 0.000002
+v 0.077200 0.186956 0.012574
+v 0.064722 0.186956 0.008799
+v 0.064722 0.186956 -0.008794
+v 0.077200 0.186956 -0.012569
+v 0.061672 0.271728 0.000002
+v 0.054590 0.262594 0.012574
+v 0.045765 0.250367 0.008799
+v 0.045765 0.250367 -0.008794
+v 0.054590 0.262594 -0.012569
+v 0.000000 0.300597 0.000002
+v 0.000000 0.293923 0.012574
+v 0.000000 0.276631 0.008799
+v 0.000000 0.276631 -0.008794
+v 0.000000 0.293923 -0.012569
+v -0.061672 0.271728 0.000002
+v -0.054590 0.262594 0.012574
+v -0.045765 0.250367 0.008799
+v -0.045765 0.250367 -0.008794
+v -0.054590 0.262594 -0.012569
+v -0.089582 0.186956 0.000002
+v -0.077200 0.186956 0.012574
+v -0.064722 0.186956 0.008799
+v -0.064722 0.186956 -0.008794
+v -0.077200 0.186956 -0.012569
+v -0.061672 0.102931 0.000002
+v -0.054590 0.111319 0.012574
+v -0.045765 0.123546 0.008799
+v -0.045765 0.123546 -0.008794
+v -0.054590 0.111319 -0.012569
+v 0.000000 -0.095037 0.000002
+v 0.000000 -0.066168 -0.055206
+v 0.014044 -0.057034 -0.048868
+v 0.014044 -0.088363 0.000002
+v 0.009826 -0.044807 -0.040967
+v 0.009826 -0.071071 0.000002
+v -0.009826 -0.044807 -0.040967
+v -0.009826 -0.071071 0.000002
+v -0.014044 -0.057034 -0.048868
+v -0.014044 -0.088363 0.000002
+v 0.000000 0.018605 -0.080190
+v 0.014044 0.018605 -0.069108
+v 0.009826 0.018605 -0.057936
+v -0.009826 0.018605 -0.057936
+v -0.014044 0.018605 -0.069108
+v 0.000000 0.103377 -0.055206
+v 0.014044 0.094243 -0.048868
+v 0.009826 0.082016 -0.040967
+v -0.009826 0.082016 -0.040967
+v -0.014044 0.094243 -0.048868
+v 0.000000 0.132246 0.000002
+v 0.014044 0.125572 0.000002
+v 0.009826 0.108280 0.000002
+v -0.009826 0.108280 0.000002
+v -0.014044 0.125572 0.000002
+v 0.000000 0.103377 0.055211
+v 0.014044 0.094243 0.048870
+v 0.009826 0.082016 0.040970
+v -0.009826 0.082016 0.040970
+v -0.014044 0.094243 0.048870
+v 0.000000 0.018605 0.080195
+v 0.014044 0.018605 0.069112
+v 0.009826 0.018605 0.057941
+v -0.009826 0.018605 0.057941
+v -0.014044 0.018605 0.069112
+v 0.000000 -0.065420 0.055211
+v 0.014044 -0.057032 0.048870
+v 0.009826 -0.044807 0.040970
+v -0.009826 -0.044807 0.040970
+v -0.014044 -0.057032 0.048870
+v 0.000000 -0.598329 0.000002
+v 0.061672 -0.569460 0.000002
+v 0.054590 -0.560326 0.012574
+v 0.000000 -0.591655 0.012574
+v 0.045765 -0.548099 0.008798
+v 0.000000 -0.574363 0.008798
+v 0.045765 -0.548099 -0.008794
+v 0.000000 -0.574363 -0.008794
+v 0.054590 -0.560326 -0.012569
+v 0.000000 -0.591655 -0.012569
+v 0.089582 -0.484687 0.000002
+v 0.077200 -0.484687 0.012574
+v 0.064722 -0.484687 0.008798
+v 0.064722 -0.484687 -0.008794
+v 0.077200 -0.484687 -0.012569
+v 0.061672 -0.399915 0.000002
+v 0.054590 -0.409051 0.012574
+v 0.045765 -0.421278 0.008798
+v 0.045765 -0.421278 -0.008794
+v 0.054590 -0.409051 -0.012569
+v 0.000000 -0.371048 0.000002
+v 0.000000 -0.377719 0.012574
+v 0.000000 -0.395012 0.008798
+v 0.000000 -0.395012 -0.008794
+v 0.000000 -0.377719 -0.012569
+v -0.061672 -0.399915 0.000002
+v -0.054590 -0.409051 0.012574
+v -0.045765 -0.421278 0.008798
+v -0.045765 -0.421278 -0.008794
+v -0.054590 -0.409051 -0.012569
+v -0.089582 -0.484687 0.000002
+v -0.077200 -0.484687 0.012574
+v -0.064722 -0.484687 0.008798
+v -0.064722 -0.484687 -0.008794
+v -0.077200 -0.484687 -0.012569
+v -0.061672 -0.568712 0.000002
+v -0.054590 -0.560326 0.012574
+v -0.045765 -0.548099 0.008798
+v -0.045765 -0.548099 -0.008794
+v -0.054590 -0.560326 -0.012569
+v 0.000000 0.241043 0.000002
+v 0.000000 0.269910 0.055211
+v -0.014044 0.279047 0.048870
+v -0.014044 0.247717 0.000002
+v -0.009826 0.291274 0.040970
+v -0.009826 0.265007 0.000002
+v 0.009826 0.291274 0.040970
+v 0.009826 0.265007 0.000002
+v 0.014044 0.279047 0.048870
+v 0.014044 0.247717 0.000002
+v 0.000000 0.354683 0.080195
+v -0.014044 0.354683 0.069112
+v -0.009826 0.354683 0.057941
+v 0.009826 0.354683 0.057941
+v 0.014044 0.354683 0.069112
+v 0.000000 0.439455 0.055211
+v -0.014044 0.430321 0.048870
+v -0.009826 0.418094 0.040970
+v 0.009826 0.418094 0.040970
+v 0.014044 0.430321 0.048870
+v 0.000000 0.468325 0.000002
+v -0.014044 0.461651 0.000002
+v -0.009826 0.444361 0.000002
+v 0.009826 0.444361 0.000002
+v 0.014044 0.461651 0.000002
+v 0.000000 0.439455 -0.055206
+v -0.014044 0.430321 -0.048868
+v -0.009826 0.418094 -0.040967
+v 0.009826 0.418094 -0.040967
+v 0.014044 0.430321 -0.048868
+v 0.000000 0.354683 -0.080190
+v -0.014044 0.354683 -0.069108
+v -0.009826 0.354683 -0.057936
+v 0.009826 0.354683 -0.057936
+v 0.014044 0.354683 -0.069108
+v 0.000000 0.270661 -0.055206
+v -0.014044 0.279047 -0.048868
+v -0.009826 0.291274 -0.040967
+v 0.009826 0.291274 -0.040967
+v 0.014044 0.279047 -0.048868
+vt 0.187500 0.125000
+vt 0.250000 0.125000
+vt 0.250000 0.187500
+vt 0.187500 0.187500
+vt 0.250000 0.250000
+vt 0.187500 0.250000
+vt 0.250000 0.312500
+vt 0.187500 0.312500
+vt 0.250000 0.375000
+vt 0.187500 0.375000
+vt 0.187500 0.062500
+vt 0.250000 0.062500
+vt 0.312500 0.125000
+vt 0.312500 0.187500
+vt 0.312500 0.250000
+vt 0.312500 0.312500
+vt 0.312500 0.375000
+vt 0.312500 0.062500
+vt 0.375000 0.125000
+vt 0.375000 0.187500
+vt 0.375000 0.250000
+vt 0.375000 0.312500
+vt 0.375000 0.375000
+vt 0.375000 0.062500
+vt 0.437500 0.125000
+vt 0.437500 0.187500
+vt 0.437500 0.250000
+vt 0.437500 0.312500
+vt 0.437500 0.375000
+vt 0.437500 0.062500
+vt 0.500000 0.125000
+vt 0.500000 0.187500
+vt 0.500000 0.250000
+vt 0.500000 0.312500
+vt 0.500000 0.375000
+vt 0.500000 0.062500
+vt -0.000000 0.125000
+vt 0.062500 0.125000
+vt 0.062500 0.187500
+vt -0.000000 0.187500
+vt 0.062500 0.250000
+vt -0.000000 0.250000
+vt 0.062500 0.312500
+vt -0.000000 0.312500
+vt 0.062500 0.375000
+vt -0.000000 0.375000
+vt -0.000000 0.062500
+vt 0.062500 0.062500
+vt 0.125000 0.125000
+vt 0.125000 0.187500
+vt 0.125000 0.250000
+vt 0.125000 0.312500
+vt 0.125000 0.375000
+vt 0.125000 0.062500
+vt 0.750000 0.625000
+vt 0.812500 0.625000
+vt 0.812500 0.687500
+vt 0.750000 0.687500
+vt 0.750000 0.375000
+vt 0.812500 0.375000
+vt 0.812500 0.437500
+vt 0.750000 0.437500
+vt 0.812500 0.500000
+vt 0.750000 0.500000
+vt 0.812500 0.562500
+vt 0.750000 0.562500
+vt 0.875000 0.625000
+vt 0.875000 0.687500
+vt 0.875000 0.375000
+vt 0.875000 0.437500
+vt 0.875000 0.500000
+vt 0.875000 0.562500
+vt 0.937500 0.625000
+vt 0.937500 0.687500
+vt 0.937500 0.375000
+vt 0.937500 0.437500
+vt 0.937500 0.500000
+vt 0.937500 0.562500
+vt 1.000000 0.625000
+vt 1.000000 0.687500
+vt 1.000000 0.375000
+vt 1.000000 0.437500
+vt 1.000000 0.500000
+vt 1.000000 0.562500
+vt 0.500000 0.625000
+vt 0.562500 0.625000
+vt 0.562500 0.687500
+vt 0.500000 0.687500
+vt 0.562500 0.375000
+vt 0.562500 0.437500
+vt 0.500000 0.437500
+vt 0.562500 0.500000
+vt 0.500000 0.500000
+vt 0.562500 0.562500
+vt 0.500000 0.562500
+vt 0.625000 0.625000
+vt 0.625000 0.687500
+vt 0.625000 0.375000
+vt 0.625000 0.437500
+vt 0.625000 0.500000
+vt 0.625000 0.562500
+vt 0.687500 0.625000
+vt 0.687500 0.687500
+vt 0.687500 0.375000
+vt 0.687500 0.437500
+vt 0.687500 0.500000
+vt 0.687500 0.562500
+vt 0.250000 0.625000
+vt 0.312500 0.625000
+vt 0.312500 0.687500
+vt 0.250000 0.687500
+vt 0.312500 0.437500
+vt 0.250000 0.437500
+vt 0.312500 0.500000
+vt 0.250000 0.500000
+vt 0.312500 0.562500
+vt 0.250000 0.562500
+vt 0.375000 0.625000
+vt 0.375000 0.687500
+vt 0.375000 0.437500
+vt 0.375000 0.500000
+vt 0.375000 0.562500
+vt 0.437500 0.625000
+vt 0.437500 0.687500
+vt 0.437500 0.437500
+vt 0.437500 0.500000
+vt 0.437500 0.562500
+vt -0.000000 0.625000
+vt 0.062500 0.625000
+vt 0.062500 0.687500
+vt -0.000000 0.687500
+vt 0.062500 0.437500
+vt -0.000000 0.437500
+vt 0.062500 0.500000
+vt -0.000000 0.500000
+vt 0.062500 0.562500
+vt -0.000000 0.562500
+vt 0.125000 0.625000
+vt 0.125000 0.687500
+vt 0.125000 0.437500
+vt 0.125000 0.500000
+vt 0.125000 0.562500
+vt 0.187500 0.625000
+vt 0.187500 0.687500
+vt 0.187500 0.437500
+vt 0.187500 0.500000
+vt 0.187500 0.562500
+vt 0.687500 0.750000
+vt 0.750000 0.750000
+vt 0.750000 0.812500
+vt 0.687500 0.812500
+vt 0.750000 0.875000
+vt 0.687500 0.875000
+vt 0.750000 0.937500
+vt 0.687500 0.937500
+vt 0.750000 1.000000
+vt 0.687500 1.000000
+vt 0.812500 0.750000
+vt 0.812500 0.812500
+vt 0.812500 0.875000
+vt 0.812500 0.937500
+vt 0.812500 1.000000
+vt 0.875000 0.750000
+vt 0.875000 0.812500
+vt 0.875000 0.875000
+vt 0.875000 0.937500
+vt 0.875000 1.000000
+vt 0.937500 0.750000
+vt 0.937500 0.812500
+vt 0.937500 0.875000
+vt 0.937500 0.937500
+vt 0.937500 1.000000
+vt 1.000000 0.750000
+vt 1.000000 0.812500
+vt 1.000000 0.875000
+vt 1.000000 0.937500
+vt 1.000000 1.000000
+vt 0.500000 0.750000
+vt 0.562500 0.750000
+vt 0.562500 0.812500
+vt 0.500000 0.812500
+vt 0.562500 0.875000
+vt 0.500000 0.875000
+vt 0.562500 0.937500
+vt 0.500000 0.937500
+vt 0.562500 1.000000
+vt 0.500000 1.000000
+vt 0.625000 0.750000
+vt 0.625000 0.812500
+vt 0.625000 0.875000
+vt 0.625000 0.937500
+vt 0.625000 1.000000
+vt 0.750000 0.312500
+vt 0.812500 0.312500
+vt 0.750000 0.062500
+vt 0.812500 0.062500
+vt 0.812500 0.125000
+vt 0.750000 0.125000
+vt 0.812500 0.187500
+vt 0.750000 0.187500
+vt 0.812500 0.250000
+vt 0.750000 0.250000
+vt 0.875000 0.312500
+vt 0.875000 0.062500
+vt 0.875000 0.125000
+vt 0.875000 0.187500
+vt 0.875000 0.250000
+vt 0.937500 0.312500
+vt 0.937500 0.062500
+vt 0.937500 0.125000
+vt 0.937500 0.187500
+vt 0.937500 0.250000
+vt 1.000000 0.312500
+vt 1.000000 0.062500
+vt 1.000000 0.125000
+vt 1.000000 0.187500
+vt 1.000000 0.250000
+vt 0.562500 0.312500
+vt 0.562500 0.062500
+vt 0.562500 0.125000
+vt 0.562500 0.187500
+vt 0.562500 0.250000
+vt 0.625000 0.312500
+vt 0.625000 0.062500
+vt 0.625000 0.125000
+vt 0.625000 0.187500
+vt 0.625000 0.250000
+vt 0.687500 0.312500
+vt 0.687500 0.062500
+vt 0.687500 0.125000
+vt 0.687500 0.187500
+vt 0.687500 0.250000
+vt 0.250000 0.937500
+vt 0.312500 0.937500
+vt 0.312500 1.000000
+vt 0.250000 1.000000
+vt 0.312500 0.750000
+vt 0.250000 0.750000
+vt 0.312500 0.812500
+vt 0.250000 0.812500
+vt 0.312500 0.875000
+vt 0.250000 0.875000
+vt 0.375000 0.937500
+vt 0.375000 1.000000
+vt 0.375000 0.750000
+vt 0.375000 0.812500
+vt 0.375000 0.875000
+vt 0.437500 0.937500
+vt 0.437500 1.000000
+vt 0.437500 0.750000
+vt 0.437500 0.812500
+vt 0.437500 0.875000
+vt 0.000000 0.937500
+vt 0.062500 0.937500
+vt 0.062500 1.000000
+vt 0.000000 1.000000
+vt 0.062500 0.750000
+vt 0.000000 0.750000
+vt 0.062500 0.812500
+vt 0.000000 0.812500
+vt 0.062500 0.875000
+vt 0.000000 0.875000
+vt 0.125000 0.937500
+vt 0.125000 1.000000
+vt 0.125000 0.750000
+vt 0.125000 0.812500
+vt 0.125000 0.875000
+vt 0.187500 0.937500
+vt 0.187500 1.000000
+vt 0.187500 0.750000
+vt 0.187500 0.812500
+vt 0.187500 0.875000
+vn 0.000000 -1.000000 -0.004800
+vn 0.000000 -0.657400 0.753500
+vn -0.898300 -0.248500 0.362300
+vn -0.863600 -0.504100 -0.003400
+vn -0.661500 0.421500 -0.620200
+vn -0.746000 0.665900 0.000000
+vn 0.661500 0.421500 -0.620200
+vn 0.746000 0.665900 0.000000
+vn 0.898300 -0.248500 0.362300
+vn 0.863600 -0.504100 -0.003400
+vn 0.000000 0.000000 1.000000
+vn -0.925200 0.000000 0.379500
+vn -0.617100 0.000000 -0.786900
+vn 0.617100 0.000000 -0.786900
+vn 0.925200 0.000000 0.379500
+vn 0.000000 0.657400 0.753500
+vn -0.898300 0.248400 0.362300
+vn -0.661500 -0.421500 -0.620200
+vn 0.661500 -0.421500 -0.620200
+vn 0.898300 0.248400 0.362300
+vn 0.000000 1.000000 0.000000
+vn -0.866100 0.499800 0.000000
+vn -0.746000 -0.665900 0.000000
+vn 0.746000 -0.665900 0.000000
+vn 0.866100 0.499800 0.000000
+vn 0.000000 0.657400 -0.753500
+vn -0.898300 0.248400 -0.362400
+vn -0.661600 -0.421500 0.620200
+vn 0.661500 -0.421500 0.620200
+vn 0.898300 0.248400 -0.362300
+vn 0.000000 -0.000900 -1.000000
+vn -0.924600 -0.000600 -0.380700
+vn -0.617100 0.000000 0.786900
+vn 0.617100 0.000000 0.786900
+vn 0.924700 -0.000600 -0.380700
+vn 0.000000 -0.650300 -0.759600
+vn -0.895600 -0.254600 -0.364800
+vn -0.661600 0.421500 0.620200
+vn 0.661600 0.421500 0.620200
+vn 0.895600 -0.254600 -0.364800
+vn 0.004900 -1.000000 0.000000
+vn -0.729700 -0.683800 0.000000
+vn -0.324500 -0.256300 -0.910500
+vn 0.003300 -0.475500 -0.879700
+vn 0.578700 0.436200 -0.689100
+vn 0.000000 0.666600 -0.745400
+vn 0.578700 0.436200 0.689100
+vn 0.000000 0.666600 0.745400
+vn -0.324500 -0.256300 0.910500
+vn 0.003300 -0.475500 0.879700
+vn -1.000000 0.000000 0.000000
+vn -0.359600 0.000000 -0.933100
+vn 0.756400 0.000000 -0.654100
+vn 0.756400 0.000000 0.654100
+vn -0.359600 0.000000 0.933100
+vn -0.729700 0.683700 0.000000
+vn -0.324500 0.256300 -0.910500
+vn 0.578700 -0.436200 -0.689100
+vn 0.578700 -0.436200 0.689100
+vn -0.324500 0.256300 0.910500
+vn 0.000000 0.470900 -0.882200
+vn 0.000000 -0.666600 -0.745400
+vn 0.000000 -0.666600 0.745400
+vn 0.000000 0.470900 0.882200
+vn 0.729700 0.683700 0.000000
+vn 0.324500 0.256300 -0.910500
+vn -0.578700 -0.436200 -0.689100
+vn -0.578700 -0.436200 0.689100
+vn 0.324500 0.256300 0.910500
+vn 1.000000 -0.001100 0.000000
+vn 0.361000 -0.000700 -0.932600
+vn -0.756400 0.000000 -0.654100
+vn -0.756400 0.000000 0.654100
+vn 0.361000 -0.000700 0.932600
+vn 0.736100 -0.676800 0.000000
+vn 0.327100 -0.263100 -0.907600
+vn -0.578700 0.436200 -0.689100
+vn -0.578700 0.436200 0.689100
+vn 0.327100 -0.263100 0.907600
+vn -0.004900 -1.000000 0.000000
+vn 0.729700 -0.683800 0.000000
+vn 0.324500 -0.256300 0.910500
+vn -0.003300 -0.475400 0.879700
+vn 0.324500 -0.256300 -0.910500
+vn -0.003300 -0.475400 -0.879700
+vn 1.000000 0.000000 0.000000
+vn 0.359600 0.000000 0.933100
+vn 0.359600 0.000000 -0.933100
+vn -1.000000 -0.001100 0.000000
+vn -0.361000 -0.000700 0.932600
+vn -0.361000 -0.000700 -0.932600
+vn -0.736100 -0.676800 0.000000
+vn -0.327100 -0.263100 0.907600
+vn -0.327100 -0.263100 -0.907600
+vn 0.000000 -1.000000 0.004800
+vn 0.000000 -0.657400 -0.753500
+vn 0.898300 -0.248500 -0.362400
+vn 0.863600 -0.504100 0.003400
+vn -0.898300 -0.248500 -0.362400
+vn -0.863600 -0.504100 0.003400
+vn 0.000000 0.000000 -1.000000
+vn 0.925200 0.000000 -0.379500
+vn -0.925200 0.000000 -0.379500
+vn 0.898300 0.248500 -0.362400
+vn 0.661600 -0.421500 0.620200
+vn -0.898300 0.248500 -0.362400
+vn 0.898300 0.248500 0.362300
+vn -0.898300 0.248500 0.362300
+vn 0.000000 -0.000900 1.000000
+vn 0.924700 -0.000600 0.380700
+vn -0.924700 -0.000600 0.380700
+vn 0.000000 -0.650300 0.759600
+vn 0.895600 -0.254600 0.364700
+vn -0.895600 -0.254600 0.364700
+vn 0.729700 -0.683700 0.000000
+vn 0.729700 0.683800 0.000000
+vn -0.729700 0.683800 0.000000
+vn -0.898300 -0.248400 0.362300
+vn -0.863600 -0.504100 -0.003500
+vn 0.898300 -0.248400 0.362300
+vn 0.863600 -0.504100 -0.003500
+vn -0.661500 -0.421500 0.620200
+vn 0.924600 -0.000600 -0.380700
+vn -0.661500 0.421500 0.620200
+vn 0.661500 0.421500 0.620200
+s 1
+f 1/1/1 2/2/2 3/3/3 4/4/4
+f 4/4/4 3/3/3 5/5/5 6/6/6
+f 6/6/6 5/5/5 7/7/7 8/8/8
+f 8/8/8 7/7/7 9/9/9 10/10/10
+f 1/1/1 10/11/10 9/12/9 2/2/2
+f 2/2/2 11/13/11 12/14/12 3/3/3
+f 3/3/3 12/14/12 13/15/13 5/5/5
+f 5/5/5 13/15/13 14/16/14 7/7/7
+f 7/7/7 14/16/14 15/17/15 9/9/9
+f 9/12/9 15/18/15 11/13/11 2/2/2
+f 11/13/11 16/19/16 17/20/17 12/14/12
+f 12/14/12 17/20/17 18/21/18 13/15/13
+f 13/15/13 18/21/18 19/22/19 14/16/14
+f 14/16/14 19/22/19 20/23/20 15/17/15
+f 15/18/15 20/24/20 16/19/16 11/13/11
+f 16/19/16 21/25/21 22/26/22 17/20/17
+f 17/20/17 22/26/22 23/27/23 18/21/18
+f 18/21/18 23/27/23 24/28/24 19/22/19
+f 19/22/19 24/28/24 25/29/25 20/23/20
+f 20/24/20 25/30/25 21/25/21 16/19/16
+f 21/25/21 26/31/26 27/32/27 22/26/22
+f 22/26/22 27/32/27 28/33/28 23/27/23
+f 23/27/23 28/33/28 29/34/29 24/28/24
+f 24/28/24 29/34/29 30/35/30 25/29/25
+f 25/30/25 30/36/30 26/31/26 21/25/21
+f 26/37/26 31/38/31 32/39/32 27/40/27
+f 27/40/27 32/39/32 33/41/33 28/42/28
+f 28/42/28 33/41/33 34/43/34 29/44/29
+f 29/44/29 34/43/34 35/45/35 30/46/30
+f 30/47/30 35/48/35 31/38/31 26/37/26
+f 31/38/31 36/49/36 37/50/37 32/39/32
+f 32/39/32 37/50/37 38/51/38 33/41/33
+f 33/41/33 38/51/38 39/52/39 34/43/34
+f 34/43/34 39/52/39 40/53/40 35/45/35
+f 35/48/35 40/54/40 36/49/36 31/38/31
+f 36/49/36 1/1/1 4/4/4 37/50/37
+f 37/50/37 4/4/4 6/6/6 38/51/38
+f 38/51/38 6/6/6 8/8/8 39/52/39
+f 39/52/39 8/8/8 10/10/10 40/53/40
+f 1/1/1 36/49/36 40/54/40 10/11/10
+f 41/55/41 42/56/42 43/57/43 44/58/44
+f 44/59/44 43/60/43 45/61/45 46/62/46
+f 46/62/46 45/61/45 47/63/47 48/64/48
+f 48/64/48 47/63/47 49/65/49 50/66/50
+f 41/55/41 50/66/50 49/65/49 42/56/42
+f 42/56/42 51/67/51 52/68/52 43/57/43
+f 43/60/43 52/69/52 53/70/53 45/61/45
+f 45/61/45 53/70/53 54/71/54 47/63/47
+f 47/63/47 54/71/54 55/72/55 49/65/49
+f 49/65/49 55/72/55 51/67/51 42/56/42
+f 51/67/51 56/73/56 57/74/57 52/68/52
+f 52/69/52 57/75/57 58/76/58 53/70/53
+f 53/70/53 58/76/58 59/77/59 54/71/54
+f 54/71/54 59/77/59 60/78/60 55/72/55
+f 55/72/55 60/78/60 56/73/56 51/67/51
+f 56/73/56 61/79/21 62/80/61 57/74/57
+f 57/75/57 62/81/61 63/82/62 58/76/58
+f 58/76/58 63/82/62 64/83/63 59/77/59
+f 59/77/59 64/83/63 65/84/64 60/78/60
+f 60/78/60 65/84/64 61/79/21 56/73/56
+f 61/85/21 66/86/65 67/87/66 62/88/61
+f 62/35/61 67/89/66 68/90/67 63/91/62
+f 63/91/62 68/90/67 69/92/68 64/93/63
+f 64/93/63 69/92/68 70/94/69 65/95/64
+f 65/95/64 70/94/69 66/86/65 61/85/21
+f 66/86/65 71/96/70 72/97/71 67/87/66
+f 67/89/66 72/98/71 73/99/72 68/90/67
+f 68/90/67 73/99/72 74/100/73 69/92/68
+f 69/92/68 74/100/73 75/101/74 70/94/69
+f 70/94/69 75/101/74 71/96/70 66/86/65
+f 71/96/70 76/102/75 77/103/76 72/97/71
+f 72/98/71 77/104/76 78/105/77 73/99/72
+f 73/99/72 78/105/77 79/106/78 74/100/73
+f 74/100/73 79/106/78 80/107/79 75/101/74
+f 75/101/74 80/107/79 76/102/75 71/96/70
+f 76/102/75 41/55/41 44/58/44 77/103/76
+f 77/104/76 44/59/44 46/62/46 78/105/77
+f 78/105/77 46/62/46 48/64/48 79/106/78
+f 79/106/78 48/64/48 50/66/50 80/107/79
+f 41/55/41 76/102/75 80/107/79 50/66/50
+f 81/108/80 82/109/81 83/110/82 84/111/83
+f 84/9/83 83/17/82 85/112/78 86/113/48
+f 86/113/48 85/112/78 87/114/77 88/115/46
+f 88/115/46 87/114/77 89/116/84 90/117/85
+f 81/108/80 90/117/85 89/116/84 82/109/81
+f 82/109/81 91/118/86 92/119/87 83/110/82
+f 83/17/82 92/23/87 93/120/73 85/112/78
+f 85/112/78 93/120/73 94/121/72 87/114/77
+f 87/114/77 94/121/72 95/122/88 89/116/84
+f 89/116/84 95/122/88 91/118/86 82/109/81
+f 91/118/86 96/123/65 97/124/69 92/119/87
+f 92/23/87 97/29/69 98/125/68 93/120/73
+f 93/120/73 98/125/68 99/126/67 94/121/72
+f 94/121/72 99/126/67 100/127/66 95/122/88
+f 95/122/88 100/127/66 96/123/65 91/118/86
+f 96/123/65 101/85/21 102/88/64 97/124/69
+f 97/29/69 102/35/64 103/91/63 98/125/68
+f 98/125/68 103/91/63 104/93/62 99/126/67
+f 99/126/67 104/93/62 105/95/61 100/127/66
+f 100/127/66 105/95/61 101/85/21 96/123/65
+f 101/128/21 106/129/56 107/130/60 102/131/64
+f 102/46/64 107/45/60 108/132/59 103/133/63
+f 103/133/63 108/132/59 109/134/58 104/135/62
+f 104/135/62 109/134/58 110/136/57 105/137/61
+f 105/137/61 110/136/57 106/129/56 101/128/21
+f 106/129/56 111/138/89 112/139/90 107/130/60
+f 107/45/60 112/53/90 113/140/54 108/132/59
+f 108/132/59 113/140/54 114/141/53 109/134/58
+f 109/134/58 114/141/53 115/142/91 110/136/57
+f 110/136/57 115/142/91 111/138/89 106/129/56
+f 111/138/89 116/143/92 117/144/93 112/139/90
+f 112/53/90 117/10/93 118/145/47 113/140/54
+f 113/140/54 118/145/47 119/146/45 114/141/53
+f 114/141/53 119/146/45 120/147/94 115/142/91
+f 115/142/91 120/147/94 116/143/92 111/138/89
+f 116/143/92 81/108/80 84/111/83 117/144/93
+f 117/10/93 84/9/83 86/113/48 118/145/47
+f 118/145/47 86/113/48 88/115/46 119/146/45
+f 119/146/45 88/115/46 90/117/85 120/147/94
+f 81/108/80 116/143/92 120/147/94 90/117/85
+f 121/148/95 122/149/96 123/150/97 124/151/98
+f 124/151/98 123/150/97 125/152/39 126/153/8
+f 126/153/8 125/152/39 127/154/38 128/155/6
+f 128/155/6 127/154/38 129/156/99 130/157/100
+f 121/148/95 130/103/100 129/58/99 122/149/96
+f 122/149/96 131/158/101 132/159/102 123/150/97
+f 123/150/97 132/159/102 133/160/34 125/152/39
+f 125/152/39 133/160/34 134/161/33 127/154/38
+f 127/154/38 134/161/33 135/162/103 129/156/99
+f 129/58/99 135/57/103 131/158/101 122/149/96
+f 131/158/101 136/163/26 137/164/104 132/159/102
+f 132/159/102 137/164/104 138/165/105 133/160/34
+f 133/160/34 138/165/105 139/166/28 134/161/33
+f 134/161/33 139/166/28 140/167/106 135/162/103
+f 135/57/103 140/68/106 136/163/26 131/158/101
+f 136/163/26 141/168/21 142/169/25 137/164/104
+f 137/164/104 142/169/25 143/170/24 138/165/105
+f 138/165/105 143/170/24 144/171/23 139/166/28
+f 139/166/28 144/171/23 145/172/22 140/167/106
+f 140/68/106 145/74/22 141/168/21 136/163/26
+f 141/168/21 146/173/16 147/174/107 142/169/25
+f 142/169/25 147/174/107 148/175/19 143/170/24
+f 143/170/24 148/175/19 149/176/18 144/171/23
+f 144/171/23 149/176/18 150/177/108 145/172/22
+f 145/74/22 150/80/108 146/173/16 141/168/21
+f 146/178/16 151/179/109 152/180/110 147/181/107
+f 147/181/107 152/180/110 153/182/14 148/183/19
+f 148/183/19 153/182/14 154/184/13 149/185/18
+f 149/185/18 154/184/13 155/186/111 150/187/108
+f 150/88/108 155/87/111 151/179/109 146/178/16
+f 151/179/109 156/188/112 157/189/113 152/180/110
+f 152/180/110 157/189/113 158/190/7 153/182/14
+f 153/182/14 158/190/7 159/191/5 154/184/13
+f 154/184/13 159/191/5 160/192/114 155/186/111
+f 155/87/111 160/97/114 156/188/112 151/179/109
+f 156/188/112 121/148/95 124/151/98 157/189/113
+f 157/189/113 124/151/98 126/153/8 158/190/7
+f 158/190/7 126/153/8 128/155/6 159/191/5
+f 159/191/5 128/155/6 130/157/100 160/192/114
+f 121/148/95 156/188/112 160/97/114 130/103/100
+f 161/193/80 162/194/115 163/60/82 164/59/83
+f 164/195/83 163/196/82 165/197/78 166/198/48
+f 166/198/48 165/197/78 167/199/77 168/200/46
+f 168/200/46 167/199/77 169/201/84 170/202/85
+f 161/193/80 170/202/85 169/201/84 162/194/115
+f 162/194/115 171/203/86 172/69/87 163/60/82
+f 163/196/82 172/204/87 173/205/73 165/197/78
+f 165/197/78 173/205/73 174/206/72 167/199/77
+f 167/199/77 174/206/72 175/207/88 169/201/84
+f 169/201/84 175/207/88 171/203/86 162/194/115
+f 171/203/86 176/208/116 177/75/69 172/69/87
+f 172/204/87 177/209/69 178/210/68 173/205/73
+f 173/205/73 178/210/68 179/211/67 174/206/72
+f 174/206/72 179/211/67 180/212/66 175/207/88
+f 175/207/88 180/212/66 176/208/116 171/203/86
+f 176/208/116 181/213/21 182/81/64 177/75/69
+f 177/209/69 182/214/64 183/215/63 178/210/68
+f 178/210/68 183/215/63 184/216/62 179/211/67
+f 179/211/67 184/216/62 185/217/61 180/212/66
+f 180/212/66 185/217/61 181/213/21 176/208/116
+f 181/34/21 186/218/117 187/89/60 182/35/64
+f 182/36/64 187/219/60 188/220/59 183/31/63
+f 183/31/63 188/220/59 189/221/58 184/32/62
+f 184/32/62 189/221/58 190/222/57 185/33/61
+f 185/33/61 190/222/57 186/218/117 181/34/21
+f 186/218/117 191/223/89 192/98/90 187/89/60
+f 187/219/60 192/224/90 193/225/54 188/220/59
+f 188/220/59 193/225/54 194/226/53 189/221/58
+f 189/221/58 194/226/53 195/227/91 190/222/57
+f 190/222/57 195/227/91 191/223/89 186/218/117
+f 191/223/89 196/228/92 197/104/93 192/98/90
+f 192/224/90 197/229/93 198/230/47 193/225/54
+f 193/225/54 198/230/47 199/231/45 194/226/53
+f 194/226/53 199/231/45 200/232/94 195/227/91
+f 195/227/91 200/232/94 196/228/92 191/223/89
+f 196/228/92 161/193/80 164/59/83 197/104/93
+f 197/229/93 164/195/83 166/198/48 198/230/47
+f 198/230/47 166/198/48 168/200/46 199/231/45
+f 199/231/45 168/200/46 170/202/85 200/232/94
+f 161/193/80 196/228/92 200/232/94 170/202/85
+f 201/233/1 202/234/2 203/235/118 204/236/119
+f 204/111/119 203/110/118 205/237/5 206/238/6
+f 206/238/6 205/237/5 207/239/7 208/240/8
+f 208/240/8 207/239/7 209/241/120 210/242/121
+f 201/233/1 210/242/121 209/241/120 202/234/2
+f 202/234/2 211/243/11 212/244/12 203/235/118
+f 203/110/118 212/119/12 213/245/13 205/237/5
+f 205/237/5 213/245/13 214/246/14 207/239/7
+f 207/239/7 214/246/14 215/247/15 209/241/120
+f 209/241/120 215/247/15 211/243/11 202/234/2
+f 211/243/11 216/248/16 217/249/108 212/244/12
+f 212/119/12 217/124/108 218/250/18 213/245/13
+f 213/245/13 218/250/18 219/251/19 214/246/14
+f 214/246/14 219/251/19 220/252/107 215/247/15
+f 215/247/15 220/252/107 216/248/16 211/243/11
+f 216/248/16 221/185/21 222/187/22 217/249/108
+f 217/124/108 222/88/22 223/178/23 218/250/18
+f 218/250/18 223/178/23 224/181/24 219/251/19
+f 219/251/19 224/181/24 225/183/25 220/252/107
+f 220/252/107 225/183/25 221/185/21 216/248/16
+f 221/253/21 226/254/26 227/255/106 222/256/22
+f 222/131/22 227/130/106 228/257/122 223/258/23
+f 223/258/23 228/257/122 229/259/29 224/260/24
+f 224/260/24 229/259/29 230/261/104 225/262/25
+f 225/262/25 230/261/104 226/254/26 221/253/21
+f 226/254/26 231/263/31 232/264/32 227/255/106
+f 227/130/106 232/139/32 233/265/33 228/257/122
+f 228/257/122 233/265/33 234/266/34 229/259/29
+f 229/259/29 234/266/34 235/267/123 230/261/104
+f 230/261/104 235/267/123 231/263/31 226/254/26
+f 231/263/31 236/268/36 237/269/37 232/264/32
+f 232/139/32 237/144/37 238/270/124 233/265/33
+f 233/265/33 238/270/124 239/271/125 234/266/34
+f 234/266/34 239/271/125 240/272/40 235/267/123
+f 235/267/123 240/272/40 236/268/36 231/263/31
+f 236/268/36 201/233/1 204/236/119 237/269/37
+f 237/144/37 204/111/119 206/238/6 238/270/124
+f 238/270/124 206/238/6 208/240/8 239/271/125
+f 239/271/125 208/240/8 210/242/121 240/272/40
+f 201/233/1 236/268/36 240/272/40 210/242/121
diff --git a/basic_materials/plastics.lua b/basic_materials/plastics.lua
new file mode 100644
index 0000000..e29af53
--- /dev/null
+++ b/basic_materials/plastics.lua
@@ -0,0 +1,56 @@
+-- Translation support
+local S = minetest.get_translator("basic_materials")
+
+-- items
+
+minetest.register_craftitem("basic_materials:plastic_sheet", {
+ description = S("Plastic sheet"),
+ inventory_image = "basic_materials_plastic_sheet.png",
+})
+
+minetest.register_craftitem("basic_materials:plastic_strip", {
+ description = S("Plastic strips"),
+ groups = { strip = 1 },
+ inventory_image = "basic_materials_plastic_strip.png",
+})
+
+minetest.register_craftitem("basic_materials:empty_spool", {
+ description = S("Empty wire spool"),
+ inventory_image = "basic_materials_empty_spool.png"
+})
+
+-- crafts
+
+minetest.register_craft({
+ type = "cooking",
+ output = "basic_materials:plastic_sheet",
+ recipe = "basic_materials:paraffin",
+})
+
+minetest.register_craft({
+ type = "fuel",
+ recipe = "basic_materials:plastic_sheet",
+ burntime = 30,
+})
+
+minetest.register_craft( {
+ output = "basic_materials:plastic_strip 9",
+ recipe = {
+ { "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
+ },
+})
+
+minetest.register_craft( {
+ output = "basic_materials:empty_spool 3",
+ recipe = {
+ { "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
+ { "", "basic_materials:plastic_sheet", "" },
+ { "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
+ },
+})
+
+-- aliases
+
+minetest.register_alias("homedecor:plastic_sheeting", "basic_materials:plastic_sheet")
+minetest.register_alias("homedecor:plastic_strips", "basic_materials:plastic_strip")
+minetest.register_alias("homedecor:empty_spool", "basic_materials:empty_spool")
diff --git a/basic_materials/textures/basic_materials_brass_block.png b/basic_materials/textures/basic_materials_brass_block.png
new file mode 100644
index 0000000..c937800
Binary files /dev/null and b/basic_materials/textures/basic_materials_brass_block.png differ
diff --git a/basic_materials/textures/basic_materials_brass_ingot.png b/basic_materials/textures/basic_materials_brass_ingot.png
new file mode 100644
index 0000000..0bd030a
Binary files /dev/null and b/basic_materials/textures/basic_materials_brass_ingot.png differ
diff --git a/basic_materials/textures/basic_materials_cement_block.png b/basic_materials/textures/basic_materials_cement_block.png
new file mode 100644
index 0000000..6d30f47
Binary files /dev/null and b/basic_materials/textures/basic_materials_cement_block.png differ
diff --git a/basic_materials/textures/basic_materials_chain_brass.png b/basic_materials/textures/basic_materials_chain_brass.png
new file mode 100644
index 0000000..e2fb20d
Binary files /dev/null and b/basic_materials/textures/basic_materials_chain_brass.png differ
diff --git a/basic_materials/textures/basic_materials_chain_brass_inv.png b/basic_materials/textures/basic_materials_chain_brass_inv.png
new file mode 100644
index 0000000..8c2d554
Binary files /dev/null and b/basic_materials/textures/basic_materials_chain_brass_inv.png differ
diff --git a/basic_materials/textures/basic_materials_chain_steel.png b/basic_materials/textures/basic_materials_chain_steel.png
new file mode 100644
index 0000000..29af8db
Binary files /dev/null and b/basic_materials/textures/basic_materials_chain_steel.png differ
diff --git a/basic_materials/textures/basic_materials_chain_steel_inv.png b/basic_materials/textures/basic_materials_chain_steel_inv.png
new file mode 100644
index 0000000..c552f7b
Binary files /dev/null and b/basic_materials/textures/basic_materials_chain_steel_inv.png differ
diff --git a/basic_materials/textures/basic_materials_chainlink_brass.png b/basic_materials/textures/basic_materials_chainlink_brass.png
new file mode 100644
index 0000000..9a1ad87
Binary files /dev/null and b/basic_materials/textures/basic_materials_chainlink_brass.png differ
diff --git a/basic_materials/textures/basic_materials_chainlink_steel.png b/basic_materials/textures/basic_materials_chainlink_steel.png
new file mode 100644
index 0000000..d7132c3
Binary files /dev/null and b/basic_materials/textures/basic_materials_chainlink_steel.png differ
diff --git a/basic_materials/textures/basic_materials_concrete_block.png b/basic_materials/textures/basic_materials_concrete_block.png
new file mode 100644
index 0000000..5dd0d66
Binary files /dev/null and b/basic_materials/textures/basic_materials_concrete_block.png differ
diff --git a/basic_materials/textures/basic_materials_copper_strip.png b/basic_materials/textures/basic_materials_copper_strip.png
new file mode 100644
index 0000000..22e572a
Binary files /dev/null and b/basic_materials/textures/basic_materials_copper_strip.png differ
diff --git a/basic_materials/textures/basic_materials_copper_wire.png b/basic_materials/textures/basic_materials_copper_wire.png
new file mode 100644
index 0000000..9df9f36
Binary files /dev/null and b/basic_materials/textures/basic_materials_copper_wire.png differ
diff --git a/basic_materials/textures/basic_materials_empty_spool.png b/basic_materials/textures/basic_materials_empty_spool.png
new file mode 100644
index 0000000..017a94f
Binary files /dev/null and b/basic_materials/textures/basic_materials_empty_spool.png differ
diff --git a/basic_materials/textures/basic_materials_energy_crystal.png b/basic_materials/textures/basic_materials_energy_crystal.png
new file mode 100644
index 0000000..f1c28e8
Binary files /dev/null and b/basic_materials/textures/basic_materials_energy_crystal.png differ
diff --git a/basic_materials/textures/basic_materials_gear_steel.png b/basic_materials/textures/basic_materials_gear_steel.png
new file mode 100644
index 0000000..584f9a5
Binary files /dev/null and b/basic_materials/textures/basic_materials_gear_steel.png differ
diff --git a/basic_materials/textures/basic_materials_gold_wire.png b/basic_materials/textures/basic_materials_gold_wire.png
new file mode 100644
index 0000000..781de7b
Binary files /dev/null and b/basic_materials/textures/basic_materials_gold_wire.png differ
diff --git a/basic_materials/textures/basic_materials_heating_element.png b/basic_materials/textures/basic_materials_heating_element.png
new file mode 100644
index 0000000..42e00b7
Binary files /dev/null and b/basic_materials/textures/basic_materials_heating_element.png differ
diff --git a/basic_materials/textures/basic_materials_ic.png b/basic_materials/textures/basic_materials_ic.png
new file mode 100644
index 0000000..4c88894
Binary files /dev/null and b/basic_materials/textures/basic_materials_ic.png differ
diff --git a/basic_materials/textures/basic_materials_motor.png b/basic_materials/textures/basic_materials_motor.png
new file mode 100644
index 0000000..f19ec0a
Binary files /dev/null and b/basic_materials/textures/basic_materials_motor.png differ
diff --git a/basic_materials/textures/basic_materials_oil_extract.png b/basic_materials/textures/basic_materials_oil_extract.png
new file mode 100644
index 0000000..e34623d
Binary files /dev/null and b/basic_materials/textures/basic_materials_oil_extract.png differ
diff --git a/basic_materials/textures/basic_materials_padlock.png b/basic_materials/textures/basic_materials_padlock.png
new file mode 100644
index 0000000..b05b7ef
Binary files /dev/null and b/basic_materials/textures/basic_materials_padlock.png differ
diff --git a/basic_materials/textures/basic_materials_paraffin.png b/basic_materials/textures/basic_materials_paraffin.png
new file mode 100644
index 0000000..77d2bbd
Binary files /dev/null and b/basic_materials/textures/basic_materials_paraffin.png differ
diff --git a/basic_materials/textures/basic_materials_plastic_sheet.png b/basic_materials/textures/basic_materials_plastic_sheet.png
new file mode 100644
index 0000000..034dcc2
Binary files /dev/null and b/basic_materials/textures/basic_materials_plastic_sheet.png differ
diff --git a/basic_materials/textures/basic_materials_plastic_strip.png b/basic_materials/textures/basic_materials_plastic_strip.png
new file mode 100644
index 0000000..1318dfc
Binary files /dev/null and b/basic_materials/textures/basic_materials_plastic_strip.png differ
diff --git a/basic_materials/textures/basic_materials_silicon.png b/basic_materials/textures/basic_materials_silicon.png
new file mode 100644
index 0000000..847b366
Binary files /dev/null and b/basic_materials/textures/basic_materials_silicon.png differ
diff --git a/basic_materials/textures/basic_materials_silver_wire.png b/basic_materials/textures/basic_materials_silver_wire.png
new file mode 100644
index 0000000..a38a45e
Binary files /dev/null and b/basic_materials/textures/basic_materials_silver_wire.png differ
diff --git a/basic_materials/textures/basic_materials_steel_bar.png b/basic_materials/textures/basic_materials_steel_bar.png
new file mode 100644
index 0000000..0673b6e
Binary files /dev/null and b/basic_materials/textures/basic_materials_steel_bar.png differ
diff --git a/basic_materials/textures/basic_materials_steel_strip.png b/basic_materials/textures/basic_materials_steel_strip.png
new file mode 100644
index 0000000..6384dc8
Binary files /dev/null and b/basic_materials/textures/basic_materials_steel_strip.png differ
diff --git a/basic_materials/textures/basic_materials_steel_wire.png b/basic_materials/textures/basic_materials_steel_wire.png
new file mode 100644
index 0000000..0c96c8f
Binary files /dev/null and b/basic_materials/textures/basic_materials_steel_wire.png differ
diff --git a/basic_materials/textures/basic_materials_terracotta_base.png b/basic_materials/textures/basic_materials_terracotta_base.png
new file mode 100644
index 0000000..9f04aad
Binary files /dev/null and b/basic_materials/textures/basic_materials_terracotta_base.png differ
diff --git a/basic_materials/textures/basic_materials_wet_cement.png b/basic_materials/textures/basic_materials_wet_cement.png
new file mode 100644
index 0000000..6a7fbf1
Binary files /dev/null and b/basic_materials/textures/basic_materials_wet_cement.png differ
diff --git a/ta4_addons/README.md b/ta4_addons/README.md
index 87db92d..6a89f98 100644
--- a/ta4_addons/README.md
+++ b/ta4_addons/README.md
@@ -8,8 +8,29 @@ Currently, the following devices are implemented:
## License
-Copyright (C) 2020 Joachim Stolberg
-Copyright (C) 2020 Thomas-S
+Copyright (C) 2020-2021 Joachim Stolberg
+Copyright (C) 2020-2021 Thomas-S
+
+### Code
+Licensed under the GNU AGPL version 3 or later. See `LICENSE.txt`.
+
+The only exception is the file `markdown2lua.py` (by Joachim Stolberg), which is licensed under the GNU GPL version 3 or later.
+See `LICENSE_GPL.txt`.
+It is taken from the [ta4_jetpack](https://github.com/joe7575/ta4_jetpack) mod.
+
+### Textures
+
+`ta4_addons_touchscreen.png`:
+Based on [techage_display.png](https://github.com/joe7575/techage/blob/master/textures/techage_display.png) by Joachim Stolberg, published under the CC BY-SA 3.0 license.
+Modifications were made by Thomas-S.
+
+`ta4_addons_touchscreen_inventory.png`, `ta4_addons_matrix_screen_inventory.png`, `ta4_addons_appl_matrix_screen.png`:
+Based on [techage_display_inventory.png](https://github.com/joe7575/techage/blob/master/textures/techage_display_inventory.png) by Joachim Stolberg, published under the CC BY-SA 3.0 license.
+Modifications were made by Thomas-S.
+
+Everything else:
+CC BY-SA 3.0 by Thomas-S
+
## Example Program for the Lua Controller
@@ -55,23 +76,3 @@ if num == tostring(TOUCHSCREEN_NUM) and msg.next then
end
```
-### Code
-Licensed under the GNU AGPL version 3 or later. See `LICENSE.txt`.
-
-The only exception is the file `markdown2lua.py` (by Joachim Stolberg), which is licensed under the GNU GPL version 3 or later.
-See `LICENSE_GPL.txt`.
-It is taken from the [ta4_jetpack](https://github.com/joe7575/ta4_jetpack) mod.
-
-### Textures
-
-`ta4_addons_touchscreen.png`:
-Based on [techage_display.png](https://github.com/joe7575/techage/blob/master/textures/techage_display.png) by Joachim Stolberg, published under the CC BY-SA 3.0 license.
-Modifications were made by Thomas-S.
-
-`ta4_addons_touchscreen_inventory.png`:
-Based on [techage_display_inventory.png](https://github.com/joe7575/techage/blob/master/textures/techage_display_inventory.png) by Joachim Stolberg, published under the CC BY-SA 3.0 license.
-Modifications were made by Thomas-S.
-
-Everything else:
-CC BY-SA 3.0 by Thomas-S
-
diff --git a/ta4_addons/generate_pixels.py b/ta4_addons/generate_pixels.py
new file mode 100644
index 0000000..76af5fc
--- /dev/null
+++ b/ta4_addons/generate_pixels.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from PIL import Image
+
+colors = [
+ "000000", "000055", "0000aa", "0000ff", "550000", "550055", "5500aa", "5500ff",
+ "aa0000", "aa0055", "aa00aa", "aa00ff", "ff0000", "ff0055", "ff00aa", "ff00ff",
+ "005500", "005555", "0055aa", "0055ff", "555500", "555555", "5555aa", "5555ff",
+ "aa5500", "aa5555", "aa55aa", "aa55ff", "ff5500", "ff5555", "ff55aa", "ff55ff",
+ "00aa00", "00aa55", "00aaaa", "00aaff", "55aa00", "55aa55", "55aaaa", "55aaff",
+ "aaaa00", "aaaa55", "aaaaaa", "aaaaff", "ffaa00", "ffaa55", "ffaaaa", "ffaaff",
+ "00ff00", "00ff55", "00ffaa", "00ffff", "55ff00", "55ff55", "55ffaa", "55ffff",
+ "aaff00", "aaff55", "aaffaa", "aaffff", "ffff00", "ffff55", "ffffaa", "ffffff",
+]
+
+for idx,color in enumerate(colors):
+ img = Image.new('RGB', (1,1), color="#"+color)
+ img.save("textures/px"+str(idx+1)+".png")
+
diff --git a/ta4_addons/init.lua b/ta4_addons/init.lua
index b47936c..8e3c2b9 100644
--- a/ta4_addons/init.lua
+++ b/ta4_addons/init.lua
@@ -3,8 +3,8 @@
TA4 Addons
==========
- Copyright (C) 2020 Joachim Stolberg
- Copyright (C) 2020 Thomas S.
+ Copyright (C) 2020-2021 Joachim Stolberg
+ Copyright (C) 2020-2021 Thomas S.
GPL v3
See LICENSE.txt for more information
@@ -22,9 +22,11 @@ ta4_addons.S = minetest.get_translator("ta4_addons")
local MP = minetest.get_modpath("ta4_addons")
dofile(MP.."/touchscreen/main.lua") -- Touchscreen
+dofile(MP.."/matrix_screen/main.lua") -- Matrix Screen
dofile(MP.."/manual_DE.lua") -- Techage Manual DE
dofile(MP.."/manual_EN.lua") -- Techage Manual EN
techage.add_manual_items({ta4_addons_touchscreen = "ta4_addons_touchscreen_inventory.png"})
+techage.add_manual_items({ta4_addons_matrix_screen = "ta4_addons_matrix_screen_inventory.png"})
diff --git a/ta4_addons/manual_DE.lua b/ta4_addons/manual_DE.lua
index 4373bed..2e861ed 100644
--- a/ta4_addons/manual_DE.lua
+++ b/ta4_addons/manual_DE.lua
@@ -2,6 +2,7 @@ techage.add_to_manual('DE', {
"1,TA4 Addons",
"2,Touchscreen",
"3,Unterstützte Elemente und ihre Eigenschaften",
+ "2,Matrix Screen",
}, {
"Aktuell sind folgende Erweiterungen für TA4 verfügbar:\n"..
"\n"..
@@ -56,12 +57,26 @@ techage.add_to_manual('DE', {
"\n"..
"Für weitere Informationen über die Bedeutung dieser Elemente sei die Datei lua_api.txt des Minetest-Projekts empfohlen.\n"..
"\n",
+ "\n"..
+ "\n"..
+ "Der Matrix Screen ist eine 16x16px-Anzeige.\n"..
+ "Es stehen verschiedene Paletten mit je 64 Farben zur Verfügung.\n"..
+ "\n"..
+ "Zum Programmieren der Anzeige wird ein Base64-codierter String als Payload des Befehls \"pixels\" gesendet.\n"..
+ "Dieser String muss 256 Zeichen umfassen\\, wobei jedes Zeichen einem Pixel entspricht (zeilenweise von links oben nach rechts unten).\n"..
+ "\n"..
+ "Zum einfachen Erstellen solcher Strings sei der TA4 Matrix Screen Programmer empfohlen.\n"..
+ "\n"..
+ "Die verwendete Farbpalette kann über den Befehl \"palette\" geändert werden.\n"..
+ "\n",
}, {
"",
"ta4_addons_touchscreen",
"ta4_addons_touchscreen",
+ "ta4_addons_matrix_screen",
}, {
"",
"",
"",
+ "",
})
diff --git a/ta4_addons/manual_DE.md b/ta4_addons/manual_DE.md
index b70613a..aed800f 100644
--- a/ta4_addons/manual_DE.md
+++ b/ta4_addons/manual_DE.md
@@ -54,4 +54,18 @@ image_button_exit: x, y, w, h, texture_name, name, label
box: x, y, w, h, color
checkbox: x, y, name, label, selected
-Für weitere Informationen über die Bedeutung dieser Elemente sei die Datei lua_api.txt des Minetest-Projekts empfohlen.
\ No newline at end of file
+Für weitere Informationen über die Bedeutung dieser Elemente sei die Datei lua_api.txt des Minetest-Projekts empfohlen.
+
+## Matrix Screen
+
+[ta4_addons_matrix_screen|image]
+
+Der Matrix Screen ist eine 16x16px-Anzeige.
+Es stehen verschiedene Paletten mit je 64 Farben zur Verfügung.
+
+Zum Programmieren der Anzeige wird ein Base64-codierter String als Payload des Befehls "pixels" gesendet.
+Dieser String muss 256 Zeichen umfassen, wobei jedes Zeichen einem Pixel entspricht (zeilenweise von links oben nach rechts unten).
+
+Zum einfachen Erstellen solcher Strings sei der TA4 Matrix Screen Programmer empfohlen.
+
+Die verwendete Farbpalette kann über den Befehl "palette" geändert werden.
diff --git a/ta4_addons/manual_EN.lua b/ta4_addons/manual_EN.lua
index 5c8a7b1..1f343d3 100644
--- a/ta4_addons/manual_EN.lua
+++ b/ta4_addons/manual_EN.lua
@@ -2,6 +2,7 @@ techage.add_to_manual('EN', {
"1,TA4 Addons",
"2,Touchscreen",
"3,Supported Elements and their properties",
+ "2,Matrix Screen",
}, {
"Currently\\, the following extensions for TA4 are available:\n"..
"\n"..
@@ -56,12 +57,26 @@ techage.add_to_manual('EN', {
"\n"..
"For further information of the meaning of these elements\\, please consult Minetest's lua_api.txt.\n"..
"\n",
+ "\n"..
+ "\n"..
+ "The matrix screen is a 16x16px display.\n"..
+ "Different palettes with 64 colors each are available.\n"..
+ "\n"..
+ "To program the display\\, you can send a base64 encoded string as a payload for the \"pixels\" command.\n"..
+ "This string has to be 256 characters long. Each character corresponds to a pixel\\, line by line from the upper left-hand corner to the lower right-hand corner. \n"..
+ "\n"..
+ "It is recommended to use the TA4 Matrix Screen Programmer in order to create such strings easily.\n"..
+ "\n"..
+ "The color palette can be changed with the \"palette\" command.\n"..
+ "\n",
}, {
"",
"ta4_addons_touchscreen",
"ta4_addons_touchscreen",
+ "ta4_addons_matrix_screen",
}, {
"",
"",
"",
+ "",
})
diff --git a/ta4_addons/manual_EN.md b/ta4_addons/manual_EN.md
index b4d6c71..6bd656c 100644
--- a/ta4_addons/manual_EN.md
+++ b/ta4_addons/manual_EN.md
@@ -54,4 +54,18 @@ image_button_exit: x, y, w, h, texture_name, name, label
box: x, y, w, h, color
checkbox: x, y, name, label, selected
-For further information of the meaning of these elements, please consult Minetest's lua_api.txt.
\ No newline at end of file
+For further information of the meaning of these elements, please consult Minetest's lua_api.txt.
+
+## Matrix Screen
+
+[ta4_addons_matrix_screen|image]
+
+The matrix screen is a 16x16px display.
+Different palettes with 64 colors each are available.
+
+To program the display, you can send a base64 encoded string as a payload for the "pixels" command.
+This string has to be 256 characters long. Each character corresponds to a pixel, line by line from the upper left-hand corner to the lower right-hand corner.
+
+It is recommended to use the TA4 Matrix Screen Programmer in order to create such strings easily.
+
+The color palette can be changed with the "palette" command.
diff --git a/ta4_addons/matrix_screen/main.lua b/ta4_addons/matrix_screen/main.lua
new file mode 100644
index 0000000..b25fdc7
--- /dev/null
+++ b/ta4_addons/matrix_screen/main.lua
@@ -0,0 +1,462 @@
+--[[
+
+ TA4 Addons
+ ==========
+
+ Copyright (C) 2020-2021 Joachim Stolberg
+ Copyright (C) 2020-2021 Thomas S.
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ Matrix Screen
+
+]]--
+
+local S = ta4_addons.S
+local M = minetest.get_meta
+local N = techage.get_nvm
+
+local letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+local letters_to_idx = {}
+for idx = 1,64 do
+ letters_to_idx[letters:sub(idx, idx)] = idx
+end
+
+local function letter_to_idx(letter)
+ return letters_to_idx[letter] or 1
+end
+
+local palettes = {
+ "rgb6bit",-- "resurrect64", "aap64", "sweet_canyon_extended", "endesga64"
+}
+
+local palettes_to_idx = {}
+
+for k,v in ipairs(palettes) do
+ palettes_to_idx[v] = k
+end
+
+local rgb6bit_palette = {
+ "000000", "000055", "0000aa", "0000ff", "550000", "550055", "5500aa", "5500ff",
+ "aa0000", "aa0055", "aa00aa", "aa00ff", "ff0000", "ff0055", "ff00aa", "ff00ff",
+ "005500", "005555", "0055aa", "0055ff", "555500", "555555", "5555aa", "5555ff",
+ "aa5500", "aa5555", "aa55aa", "aa55ff", "ff5500", "ff5555", "ff55aa", "ff55ff",
+ "00aa00", "00aa55", "00aaaa", "00aaff", "55aa00", "55aa55", "55aaaa", "55aaff",
+ "aaaa00", "aaaa55", "aaaaaa", "aaaaff", "ffaa00", "ffaa55", "ffaaaa", "ffaaff",
+ "00ff00", "00ff55", "00ffaa", "00ffff", "55ff00", "55ff55", "55ffaa", "55ffff",
+ "aaff00", "aaff55", "aaffaa", "aaffff", "ffff00", "ffff55", "ffffaa", "ffffff",
+}
+
+-- Source: https://lospec.com/palette-list/resurrect-64
+local resurrect64_palette = {
+ "2e222f", "3e3546", "625565", "966c6c", "ab947a", "694f62", "7f708a", "9babb2",
+ "c7dcd0", "ffffff", "6e2727", "b33831", "ea4f36", "f57d4a", "ae2334", "e83b3b",
+ "fb6b1d", "f79617", "f9c22b", "7a3045", "9e4539", "cd683d", "e6904e", "fbb954",
+ "4c3e24", "676633", "a2a947", "d5e04b", "fbff86", "165a4c", "239063", "1ebc73",
+ "91db69", "cddf6c", "313638", "374e4a", "547e64", "92a984", "b2ba90", "0b5e65",
+ "0b8a8f", "0eaf9b", "30e1b9", "8ff8e2", "323353", "484a77", "4d65b4", "4d9be6",
+ "8fd3ff", "45293f", "6b3e75", "905ea9", "a884f3", "eaaded", "753c54", "a24b6f",
+ "cf657f", "ed8099", "831c5d", "c32454", "f04f78", "f68181", "fca790", "fdcbb0",
+}
+
+-- Source: https://lospec.com/palette-list/aap-64
+local aap64_palette = {
+ "060608", "141013", "3b1725", "73172d", "b4202a", "df3e23", "fa6a0a", "f9a31b",
+ "ffd541", "fffc40", "d6f264", "9cdb43", "59c135", "14a02e", "1a7a3e", "24523b",
+ "122020", "143464", "285cc4", "249fde", "20d6c7", "a6fcdb", "ffffff", "fef3c0",
+ "fad6b8", "f5a097", "e86a73", "bc4a9b", "793a80", "403353", "242234", "221c1a",
+ "322b28", "71413b", "bb7547", "dba463", "f4d29c", "dae0ea", "b3b9d1", "8b93af",
+ "6d758d", "4a5462", "333941", "422433", "5b3138", "8e5252", "ba756a", "e9b5a3",
+ "e3e6ff", "b9bffb", "849be4", "588dbe", "477d85", "23674e", "328464", "5daf8d",
+ "92dcba", "cdf7e2", "e4d2aa", "c7b08b", "a08662", "796755", "5a4e44", "423934",
+}
+
+-- Source: https://lospec.com/palette-list/sweet-canyon-extended-64
+local sweet_canyon_extended_palette = {
+ "0f0e11", "2d2c33", "40404a", "51545c", "6b7179", "7c8389", "a8b2b6", "d5d5d5",
+ "eeebe0", "f1dbb1", "eec99f", "e1a17e", "cc9562", "ab7b49", "9a643a", "86482f",
+ "783a29", "6a3328", "541d29", "42192c", "512240", "782349", "8b2e5d", "a93e89",
+ "d062c8", "ec94ea", "f2bdfc", "eaebff", "a2fafa", "64e7e7", "54cfd8", "2fb6c3",
+ "2c89af", "25739d", "2a5684", "214574", "1f2966", "101445", "3c0d3b", "66164c",
+ "901f3d", "bb3030", "dc473c", "ec6a45", "fb9b41", "f0c04c", "f4d66e", "fffb76",
+ "ccf17a", "97d948", "6fba3b", "229443", "1d7e45", "116548", "0c4f3f", "0a3639",
+ "251746", "48246d", "69189c", "9f20c0", "e527d2", "ff51cf", "ff7ada", "ff9edb",
+}
+
+-- Source: https://lospec.com/palette-list/endesga-64
+local endesga64_palette = {
+ "ff0040", "131313", "1b1b1b", "272727", "3d3d3d", "5d5d5d", "858585", "b4b4b4",
+ "ffffff", "c7cfdd", "92a1b9", "657392", "424c6e", "2a2f4e", "1a1932", "0e071b",
+ "1c121c", "391f21", "5d2c28", "8a4836", "bf6f4a", "e69c69", "f6ca9f", "f9e6cf",
+ "edab50", "e07438", "c64524", "8e251d", "ff5000", "ed7614", "ffa214", "ffc825",
+ "ffeb57", "d3fc7e", "99e65f", "5ac54f", "33984b", "1e6f50", "134c4c", "0c2e44",
+ "00396d", "0069aa", "0098dc", "00cdf9", "0cf1ff", "94fdff", "fdd2ed", "f389f5",
+ "db3ffd", "7a09fa", "3003d9", "0c0293", "03193f", "3b1443", "622461", "93388f",
+ "ca52c9", "c85086", "f68187", "f5555d", "ea323c", "c42430", "891e2b", "571c27",
+}
+
+local function rgb6bit(idx)
+ return rgb6bit_palette[idx]
+end
+
+local function resurrect64(idx)
+ return resurrect64_palette[idx]
+end
+
+local function aap64(idx)
+ return aap64_palette[idx]
+end
+
+local function sweet_canyon_extended(idx)
+ return sweet_canyon_extended_palette[idx]
+end
+
+local function endesga64(idx)
+ return endesga64_palette[idx]
+end
+
+local function get_palette(palette_name)
+ --if palette_name == "resurrect64" then
+ -- return resurrect64
+ --elseif palette_name == "aap64" then
+ -- return aap64
+ --elseif palette_name == "sweet_canyon_extended" then
+ -- return sweet_canyon_extended
+ --elseif palette_name == "endesga64" then
+ -- return endesga64
+ --end
+ return rgb6bit
+end
+
+local function string_to_indices(input_string)
+ input_string = input_string:gsub("%s", "") -- Ignore space characters
+ input_string = input_string:sub(1, 256) -- Limit to 256 chars at max
+ input_string = input_string..string.rep("A", 256-#input_string) -- Fill up to reach 256 chars
+ local result = {}
+ for i = 1,#input_string do
+ result[i] = letter_to_idx(input_string:sub(i, i))
+ end
+ return result
+end
+
+local function string_to_colors(input_string, palette_name)
+ local palette_func = get_palette(palette_name)
+ local indices = string_to_indices(input_string)
+ local result = {}
+ for i = 1,#indices do
+ result[i] = palette_func(indices[i])
+ end
+ return result
+end
+
+local function generate_texture_from_color_list(colors)
+ local texture = {"[combine:16x16"}
+ local x, y = 0, 0
+ for _,color in ipairs(colors) do
+ texture[#texture+1] = ":"
+ texture[#texture+1] = x
+ texture[#texture+1] = ","
+ texture[#texture+1] = y
+ texture[#texture+1] = "=px.png\\^[colorize\\:#"
+ texture[#texture+1] = color
+ x = x + 1
+ if x >= 16 then
+ x = 0
+ y = y + 1
+ end
+ end
+ texture[#texture+1] = "^[resize:128x128^ta4_addons_matrix_screen_overlay.png"
+ return table.concat(texture, "")
+end
+
+local function generate_texture_from_indices(indices)
+ local texture = {"[combine:16x16:0,0=px_bg.png"}
+ local x, y = 0, 0
+ for _,index in ipairs(indices) do
+ if index ~=1 then
+ texture[#texture+1] = ":"
+ texture[#texture+1] = x
+ texture[#texture+1] = ","
+ texture[#texture+1] = y
+ texture[#texture+1] = "=px"
+ texture[#texture+1] = index
+ texture[#texture+1] = ".png"
+ end
+ x = x + 1
+ if x >= 16 then
+ x = 0
+ y = y + 1
+ end
+ end
+ texture[#texture+1] = "^[resize:128x128^ta4_addons_matrix_screen_overlay.png"
+ return table.concat(texture, "")
+end
+
+local function string_to_table(input_string)
+ local indices = string_to_indices(input_string)
+ local t = {}
+ local x, y = 0, 0
+ for i = 1,#indices do
+ t[y] = t[y] or {}
+ t[y][x] = indices[i]
+ x = x + 1
+ if x >= 16 then
+ x = 0
+ y = y + 1
+ end
+ end
+ return t
+end
+
+ta4_addons.base64_to_texture = function(color_string, palette)
+ --return generate_texture_from_color_list(string_to_colors(color_string, palette))
+ return generate_texture_from_indices(string_to_indices(color_string))
+end
+
+local function update_matrix_display(pos, objref)
+ pos = vector.round(pos)
+ local nvm = N(pos)
+ objref:set_properties({
+ textures = { ta4_addons.base64_to_texture(nvm.color_string or "", nvm.palette) },
+ })
+end
+
+minetest.register_node("ta4_addons:matrix_screen", {
+ description = S("TA4 Matrix Screen"),
+ inventory_image = "ta4_addons_matrix_screen_inventory.png",
+ tiles = {"ta4_addons_matrix_screen.png"},
+ drawtype = "nodebox",
+ paramtype = "light",
+ sunlight_propagates = true,
+ paramtype2 = "wallmounted",
+ node_box = techage.display.lcd_box,
+ selection_box = techage.display.lcd_box,
+ light_source = 6,
+
+ display_entities = {
+ ["techage:display_entity"] = {
+ depth = 0.42,
+ on_display_update = update_matrix_display
+ },
+ },
+
+ after_place_node = function(pos, placer)
+ local number = techage.add_node(pos, "ta4_addons:matrix_screen")
+ local meta = M(pos)
+ meta:set_string("node_number", number)
+ meta:set_string("infotext", S("Matrix Screen no: ")..number)
+ local nvm = techage.get_nvm(pos)
+ nvm.color_string = "AABBCCDDEEFFGGHHAABBCCDDEEFFGGHH"
+ .. "IIJJKKLLMMNNOOPPIIJJKKLLMMNNOOPP"
+ .. "QQRRSSTTUUVVWWXXQQRRSSTTUUVVWWXX"
+ .. "YYZZaabbccddeeffYYZZaabbccddeeff"
+ .. "gghhiijjkkllmmnngghhiijjkkllmmnn"
+ .. "ooppqqrrssttuuvvooppqqrrssttuuvv"
+ .. "wwxxyyzz00112233wwxxyyzz00112233"
+ .. "445566778899++//445566778899++//"
+ lcdlib.update_entities(pos)
+ minetest.get_node_timer(pos):start(2)
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ end,
+
+ on_timer = techage.display.on_timer,
+ on_place = lcdlib.on_place,
+ on_construct = lcdlib.on_construct,
+ on_destruct = lcdlib.on_destruct,
+ on_rotate = lcdlib.on_rotate,
+ groups = {cracky=2, crumbly=2},
+ is_ground_content = false,
+ sounds = default.node_sound_glass_defaults(),
+})
+
+minetest.register_craft({
+ output = "ta4_addons:matrix_screen",
+ recipe = {
+ {"dye:red", "dye:green", "dye:blue"},
+ {"default:copper_ingot", "techage:ta4_display", "default:copper_ingot"},
+ {"", "default:mese_crystal_fragment", ""},
+ },
+})
+
+techage.register_node({"ta4_addons:matrix_screen"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ local mem = techage.get_mem(pos)
+ mem.ticks = mem.ticks or 0
+
+ if mem.ticks == 0 then
+ mem.ticks = 1
+ end
+
+ if topic == "pixels" then
+ N(pos).color_string = tostring(payload)
+ elseif topic == "palette" then
+ N(pos).palette = tostring(payload)
+ end
+ end,
+})
+
+local function generate_px_button(x, y, i, palette_func, name)
+ return "image_button["..x..","..y..";.5,.5;px.png^[colorize:#"..palette_func(i)..";"..name..";"..letters:sub(i,i).."]"
+end
+
+local function get_px_val(nvm, x, y)
+ return ((nvm.px or {})[y] or {})[x] or 1
+end
+
+local function generate_base64(nvm)
+ local result = ""
+ for y=0,15 do
+ for x=0,15 do
+ local i = get_px_val(nvm, x, y)
+ result = result..letters:sub(i,i)
+ end
+ result = result.." "
+ end
+ return result:sub(1,-2)
+end
+
+local function update_fs(pos)
+ local nvm = N(pos)
+ local palette = nvm.palette or "rgb6bit"
+ local palette_func = get_palette(palette)
+ local current_idx = nvm.current_idx or 1
+ local fs = "formspec_version[4]size[18,12]"
+ fs = fs.."label[0.5,.75;Palette:]"
+ fs = fs.."dropdown[2,.5;3,.5;palette;"..table.concat(palettes, ",")..";"..(palettes_to_idx[palette] or 1).."]"
+ local x = .5
+ local y = 1.5
+ for i = 1,64 do
+ fs = fs..generate_px_button(x, y, i, palette_func, "color_idx_"..i)
+ x = x + .6
+ if x > 2.5 then
+ x = .5
+ y = y + .6
+ end
+ end
+ for y_px = 0,15 do
+ for x_px = 0,15 do
+ fs = fs..generate_px_button(3.5+x_px*.6, 1.5+y_px*.6, get_px_val(nvm, x_px, y_px), palette_func, "px_"..x_px.."_"..y_px)
+ end
+ end
+ fs = fs.."label[13.5,.75;Current Color:]"
+ fs = fs..generate_px_button(17, .5, current_idx, palette_func, "current_color")
+ fs = fs.."style_type[textarea;font=mono]"
+ fs = fs.."textarea[13.5,4.5;4,5;base64;Base64 string:;"..generate_base64(nvm).."]"
+ fs = fs.."button[16.5,9.5;1,.5;read_base64;Read]"
+ fs = fs.."field[13.5,10.5;3,1;target;Target Techage Number:;"..minetest.formspec_escape(nvm.target or "").."]"
+ fs = fs.."button[16.5,10.5;1,1;send_cmnd;Send]"
+ M(pos):set_string("formspec", fs)
+end
+
+minetest.register_node("ta4_addons:matrix_screen_programmer", {
+ description = S("TA4 Matrix Screen Programmer"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_filling_ta4.png^techage_frame_ta4_top.png",
+ "techage_filling_ta4.png^techage_frame_ta4.png",
+ "techage_filling_ta4.png^techage_frame_ta4.png",
+ "techage_filling_ta4.png^techage_frame_ta4.png",
+ "techage_filling_ta4.png^techage_frame_ta4.png",
+ "techage_filling_ta4.png^techage_frame_ta4.png^ta4_addons_appl_matrix_screen.png",
+ },
+ drawtype = "normal",
+ paramtype = "light",
+ paramtype2 = "facedir",
+ on_construct = function(pos)
+ update_fs(pos)
+ M(pos):set_string("infotext", S("TA4 Matrix Screen Programmer"))
+ end,
+ after_place_node = function(pos, placer)
+ local number = techage.add_node(pos, "ta4_addons:matrix_screen_programmer")
+ local meta = M(pos)
+ meta:set_string("node_number", number)
+ meta:set_string("infotext", S("Matrix Screen Programmer ")..number)
+ end,
+ after_dig_node = function(pos, oldnode, oldmetadata)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ end,
+ groups = {cracky=2, crumbly=2},
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+ on_receive_fields = function (pos, formname, fields, sender)
+ local player_name = sender:get_player_name()
+ if minetest.is_protected(pos, player_name) then
+ return
+ end
+ local nvm = N(pos)
+ for i=1,64 do
+ if fields["color_idx_"..i] then
+ nvm.current_idx = i
+ end
+ end
+ for y=0,15 do
+ for x=0,15 do
+ if fields["px_"..x.."_"..y] then
+ nvm.px = nvm.px or {}
+ nvm.px[y] = nvm.px[y] or {}
+ nvm.px[y][x] = nvm.current_idx
+ end
+ end
+ end
+ if fields.read_base64 and fields.base64 then
+ nvm.px = string_to_table(fields.base64)
+ end
+ if fields.send_cmnd and fields.target and techage.check_numbers(fields.target, player_name) then
+ nvm.target = fields.target
+ local own_number = M(pos):get_string("node_number")
+ if not own_number or own_number == "" then
+ own_number = "0"
+ end
+ techage.send_multi(own_number, fields.target, "palette", nvm.palette or "rgb6bit")
+ techage.send_multi(own_number, fields.target, "pixels", generate_base64(nvm))
+ end
+ if fields.palette then
+ nvm.palette = fields.palette
+ end
+ update_fs(pos)
+ end
+})
+
+techage.register_node({"ta4_addons:matrix_screen_programmer"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ local nvm = N(pos)
+ if topic == "on" then
+ local own_number = M(pos):get_string("node_number")
+ techage.send_multi(own_number, nvm.target, "pixels", generate_base64(nvm))
+ techage.send_multi(own_number, nvm.target, "palette", nvm.palette or "rgb6bit")
+ end
+ end,
+})
+
+minetest.register_craft({
+ output = "ta4_addons:matrix_screen_programmer",
+ recipe = {
+ {"default:steel_ingot", "techage:ta4_ramchip", "default:steel_ingot"},
+ {"", "ta4_addons:matrix_screen", ""},
+ {"default:steel_ingot", "techage:ta4_wlanchip", "default:steel_ingot"},
+ },
+})
+
+if techage.repair_number then
+ minetest.register_lbm({
+ label = "Fix lost techage numbers for matrix screens",
+ name = "ta4_addons:repair_matrix_screen_numbers",
+ nodenames = {"ta4_addons:matrix_screen", "ta4_addons:matrix_screen_programmer"},
+ action = function(pos, node)
+ techage.repair_number(pos)
+ end
+ })
+end
+
+minetest.register_lbm({
+ label = "Fix lost timer for matrix screens",
+ name = "ta4_addons:repair_matrix_screen_timer",
+ nodenames = {"ta4_addons:matrix_screen"},
+ action = function(pos, node)
+ minetest.get_node_timer(pos):start(2)
+ end
+})
\ No newline at end of file
diff --git a/ta4_addons/textures/px.png b/ta4_addons/textures/px.png
new file mode 100644
index 0000000..d057ee3
Binary files /dev/null and b/ta4_addons/textures/px.png differ
diff --git a/ta4_addons/textures/px1.png b/ta4_addons/textures/px1.png
new file mode 100644
index 0000000..19b3f6a
Binary files /dev/null and b/ta4_addons/textures/px1.png differ
diff --git a/ta4_addons/textures/px10.png b/ta4_addons/textures/px10.png
new file mode 100644
index 0000000..836752a
Binary files /dev/null and b/ta4_addons/textures/px10.png differ
diff --git a/ta4_addons/textures/px11.png b/ta4_addons/textures/px11.png
new file mode 100644
index 0000000..25b2325
Binary files /dev/null and b/ta4_addons/textures/px11.png differ
diff --git a/ta4_addons/textures/px12.png b/ta4_addons/textures/px12.png
new file mode 100644
index 0000000..83a1832
Binary files /dev/null and b/ta4_addons/textures/px12.png differ
diff --git a/ta4_addons/textures/px13.png b/ta4_addons/textures/px13.png
new file mode 100644
index 0000000..62a5f8f
Binary files /dev/null and b/ta4_addons/textures/px13.png differ
diff --git a/ta4_addons/textures/px14.png b/ta4_addons/textures/px14.png
new file mode 100644
index 0000000..8ac3712
Binary files /dev/null and b/ta4_addons/textures/px14.png differ
diff --git a/ta4_addons/textures/px15.png b/ta4_addons/textures/px15.png
new file mode 100644
index 0000000..6570303
Binary files /dev/null and b/ta4_addons/textures/px15.png differ
diff --git a/ta4_addons/textures/px16.png b/ta4_addons/textures/px16.png
new file mode 100644
index 0000000..f6cb70b
Binary files /dev/null and b/ta4_addons/textures/px16.png differ
diff --git a/ta4_addons/textures/px17.png b/ta4_addons/textures/px17.png
new file mode 100644
index 0000000..9235ae3
Binary files /dev/null and b/ta4_addons/textures/px17.png differ
diff --git a/ta4_addons/textures/px18.png b/ta4_addons/textures/px18.png
new file mode 100644
index 0000000..5983ad2
Binary files /dev/null and b/ta4_addons/textures/px18.png differ
diff --git a/ta4_addons/textures/px19.png b/ta4_addons/textures/px19.png
new file mode 100644
index 0000000..4e301f8
Binary files /dev/null and b/ta4_addons/textures/px19.png differ
diff --git a/ta4_addons/textures/px2.png b/ta4_addons/textures/px2.png
new file mode 100644
index 0000000..c6ea63b
Binary files /dev/null and b/ta4_addons/textures/px2.png differ
diff --git a/ta4_addons/textures/px20.png b/ta4_addons/textures/px20.png
new file mode 100644
index 0000000..91b10ac
Binary files /dev/null and b/ta4_addons/textures/px20.png differ
diff --git a/ta4_addons/textures/px21.png b/ta4_addons/textures/px21.png
new file mode 100644
index 0000000..f8cd875
Binary files /dev/null and b/ta4_addons/textures/px21.png differ
diff --git a/ta4_addons/textures/px22.png b/ta4_addons/textures/px22.png
new file mode 100644
index 0000000..74e7365
Binary files /dev/null and b/ta4_addons/textures/px22.png differ
diff --git a/ta4_addons/textures/px23.png b/ta4_addons/textures/px23.png
new file mode 100644
index 0000000..697cfa4
Binary files /dev/null and b/ta4_addons/textures/px23.png differ
diff --git a/ta4_addons/textures/px24.png b/ta4_addons/textures/px24.png
new file mode 100644
index 0000000..482d299
Binary files /dev/null and b/ta4_addons/textures/px24.png differ
diff --git a/ta4_addons/textures/px25.png b/ta4_addons/textures/px25.png
new file mode 100644
index 0000000..583c769
Binary files /dev/null and b/ta4_addons/textures/px25.png differ
diff --git a/ta4_addons/textures/px26.png b/ta4_addons/textures/px26.png
new file mode 100644
index 0000000..14801a6
Binary files /dev/null and b/ta4_addons/textures/px26.png differ
diff --git a/ta4_addons/textures/px27.png b/ta4_addons/textures/px27.png
new file mode 100644
index 0000000..7e39815
Binary files /dev/null and b/ta4_addons/textures/px27.png differ
diff --git a/ta4_addons/textures/px28.png b/ta4_addons/textures/px28.png
new file mode 100644
index 0000000..6ecb893
Binary files /dev/null and b/ta4_addons/textures/px28.png differ
diff --git a/ta4_addons/textures/px29.png b/ta4_addons/textures/px29.png
new file mode 100644
index 0000000..f841b9b
Binary files /dev/null and b/ta4_addons/textures/px29.png differ
diff --git a/ta4_addons/textures/px3.png b/ta4_addons/textures/px3.png
new file mode 100644
index 0000000..d325ef7
Binary files /dev/null and b/ta4_addons/textures/px3.png differ
diff --git a/ta4_addons/textures/px30.png b/ta4_addons/textures/px30.png
new file mode 100644
index 0000000..461394c
Binary files /dev/null and b/ta4_addons/textures/px30.png differ
diff --git a/ta4_addons/textures/px31.png b/ta4_addons/textures/px31.png
new file mode 100644
index 0000000..7976a07
Binary files /dev/null and b/ta4_addons/textures/px31.png differ
diff --git a/ta4_addons/textures/px32.png b/ta4_addons/textures/px32.png
new file mode 100644
index 0000000..3d279b7
Binary files /dev/null and b/ta4_addons/textures/px32.png differ
diff --git a/ta4_addons/textures/px33.png b/ta4_addons/textures/px33.png
new file mode 100644
index 0000000..c31f012
Binary files /dev/null and b/ta4_addons/textures/px33.png differ
diff --git a/ta4_addons/textures/px34.png b/ta4_addons/textures/px34.png
new file mode 100644
index 0000000..bd6e4b8
Binary files /dev/null and b/ta4_addons/textures/px34.png differ
diff --git a/ta4_addons/textures/px35.png b/ta4_addons/textures/px35.png
new file mode 100644
index 0000000..2a34105
Binary files /dev/null and b/ta4_addons/textures/px35.png differ
diff --git a/ta4_addons/textures/px36.png b/ta4_addons/textures/px36.png
new file mode 100644
index 0000000..4a1ebbc
Binary files /dev/null and b/ta4_addons/textures/px36.png differ
diff --git a/ta4_addons/textures/px37.png b/ta4_addons/textures/px37.png
new file mode 100644
index 0000000..934016e
Binary files /dev/null and b/ta4_addons/textures/px37.png differ
diff --git a/ta4_addons/textures/px38.png b/ta4_addons/textures/px38.png
new file mode 100644
index 0000000..64ec437
Binary files /dev/null and b/ta4_addons/textures/px38.png differ
diff --git a/ta4_addons/textures/px39.png b/ta4_addons/textures/px39.png
new file mode 100644
index 0000000..3f319ec
Binary files /dev/null and b/ta4_addons/textures/px39.png differ
diff --git a/ta4_addons/textures/px4.png b/ta4_addons/textures/px4.png
new file mode 100644
index 0000000..548a5b9
Binary files /dev/null and b/ta4_addons/textures/px4.png differ
diff --git a/ta4_addons/textures/px40.png b/ta4_addons/textures/px40.png
new file mode 100644
index 0000000..dad0224
Binary files /dev/null and b/ta4_addons/textures/px40.png differ
diff --git a/ta4_addons/textures/px41.png b/ta4_addons/textures/px41.png
new file mode 100644
index 0000000..cff5622
Binary files /dev/null and b/ta4_addons/textures/px41.png differ
diff --git a/ta4_addons/textures/px42.png b/ta4_addons/textures/px42.png
new file mode 100644
index 0000000..aadd5a5
Binary files /dev/null and b/ta4_addons/textures/px42.png differ
diff --git a/ta4_addons/textures/px43.png b/ta4_addons/textures/px43.png
new file mode 100644
index 0000000..bc6e629
Binary files /dev/null and b/ta4_addons/textures/px43.png differ
diff --git a/ta4_addons/textures/px44.png b/ta4_addons/textures/px44.png
new file mode 100644
index 0000000..a81e8b2
Binary files /dev/null and b/ta4_addons/textures/px44.png differ
diff --git a/ta4_addons/textures/px45.png b/ta4_addons/textures/px45.png
new file mode 100644
index 0000000..f3aee2f
Binary files /dev/null and b/ta4_addons/textures/px45.png differ
diff --git a/ta4_addons/textures/px46.png b/ta4_addons/textures/px46.png
new file mode 100644
index 0000000..a3c53ac
Binary files /dev/null and b/ta4_addons/textures/px46.png differ
diff --git a/ta4_addons/textures/px47.png b/ta4_addons/textures/px47.png
new file mode 100644
index 0000000..2880e98
Binary files /dev/null and b/ta4_addons/textures/px47.png differ
diff --git a/ta4_addons/textures/px48.png b/ta4_addons/textures/px48.png
new file mode 100644
index 0000000..835ec73
Binary files /dev/null and b/ta4_addons/textures/px48.png differ
diff --git a/ta4_addons/textures/px49.png b/ta4_addons/textures/px49.png
new file mode 100644
index 0000000..e970424
Binary files /dev/null and b/ta4_addons/textures/px49.png differ
diff --git a/ta4_addons/textures/px5.png b/ta4_addons/textures/px5.png
new file mode 100644
index 0000000..46d8f34
Binary files /dev/null and b/ta4_addons/textures/px5.png differ
diff --git a/ta4_addons/textures/px50.png b/ta4_addons/textures/px50.png
new file mode 100644
index 0000000..2a385f9
Binary files /dev/null and b/ta4_addons/textures/px50.png differ
diff --git a/ta4_addons/textures/px51.png b/ta4_addons/textures/px51.png
new file mode 100644
index 0000000..72d70d1
Binary files /dev/null and b/ta4_addons/textures/px51.png differ
diff --git a/ta4_addons/textures/px52.png b/ta4_addons/textures/px52.png
new file mode 100644
index 0000000..f2bf6d6
Binary files /dev/null and b/ta4_addons/textures/px52.png differ
diff --git a/ta4_addons/textures/px53.png b/ta4_addons/textures/px53.png
new file mode 100644
index 0000000..bfc0e1c
Binary files /dev/null and b/ta4_addons/textures/px53.png differ
diff --git a/ta4_addons/textures/px54.png b/ta4_addons/textures/px54.png
new file mode 100644
index 0000000..7ecb742
Binary files /dev/null and b/ta4_addons/textures/px54.png differ
diff --git a/ta4_addons/textures/px55.png b/ta4_addons/textures/px55.png
new file mode 100644
index 0000000..164d9e2
Binary files /dev/null and b/ta4_addons/textures/px55.png differ
diff --git a/ta4_addons/textures/px56.png b/ta4_addons/textures/px56.png
new file mode 100644
index 0000000..8fc4b14
Binary files /dev/null and b/ta4_addons/textures/px56.png differ
diff --git a/ta4_addons/textures/px57.png b/ta4_addons/textures/px57.png
new file mode 100644
index 0000000..a0c2abb
Binary files /dev/null and b/ta4_addons/textures/px57.png differ
diff --git a/ta4_addons/textures/px58.png b/ta4_addons/textures/px58.png
new file mode 100644
index 0000000..c7c55b1
Binary files /dev/null and b/ta4_addons/textures/px58.png differ
diff --git a/ta4_addons/textures/px59.png b/ta4_addons/textures/px59.png
new file mode 100644
index 0000000..ae66950
Binary files /dev/null and b/ta4_addons/textures/px59.png differ
diff --git a/ta4_addons/textures/px6.png b/ta4_addons/textures/px6.png
new file mode 100644
index 0000000..fa55860
Binary files /dev/null and b/ta4_addons/textures/px6.png differ
diff --git a/ta4_addons/textures/px60.png b/ta4_addons/textures/px60.png
new file mode 100644
index 0000000..726b328
Binary files /dev/null and b/ta4_addons/textures/px60.png differ
diff --git a/ta4_addons/textures/px61.png b/ta4_addons/textures/px61.png
new file mode 100644
index 0000000..bab6c7f
Binary files /dev/null and b/ta4_addons/textures/px61.png differ
diff --git a/ta4_addons/textures/px62.png b/ta4_addons/textures/px62.png
new file mode 100644
index 0000000..0a0a7b5
Binary files /dev/null and b/ta4_addons/textures/px62.png differ
diff --git a/ta4_addons/textures/px63.png b/ta4_addons/textures/px63.png
new file mode 100644
index 0000000..0cc7701
Binary files /dev/null and b/ta4_addons/textures/px63.png differ
diff --git a/ta4_addons/textures/px64.png b/ta4_addons/textures/px64.png
new file mode 100644
index 0000000..94381b4
Binary files /dev/null and b/ta4_addons/textures/px64.png differ
diff --git a/ta4_addons/textures/px7.png b/ta4_addons/textures/px7.png
new file mode 100644
index 0000000..495f997
Binary files /dev/null and b/ta4_addons/textures/px7.png differ
diff --git a/ta4_addons/textures/px8.png b/ta4_addons/textures/px8.png
new file mode 100644
index 0000000..543e9bb
Binary files /dev/null and b/ta4_addons/textures/px8.png differ
diff --git a/ta4_addons/textures/px9.png b/ta4_addons/textures/px9.png
new file mode 100644
index 0000000..fd908c1
Binary files /dev/null and b/ta4_addons/textures/px9.png differ
diff --git a/ta4_addons/textures/px_bg.png b/ta4_addons/textures/px_bg.png
new file mode 100644
index 0000000..1a80c40
Binary files /dev/null and b/ta4_addons/textures/px_bg.png differ
diff --git a/ta4_addons/textures/ta4_addons_appl_matrix_screen.png b/ta4_addons/textures/ta4_addons_appl_matrix_screen.png
new file mode 100644
index 0000000..6f2fc3d
Binary files /dev/null and b/ta4_addons/textures/ta4_addons_appl_matrix_screen.png differ
diff --git a/ta4_addons/textures/ta4_addons_matrix_screen.png b/ta4_addons/textures/ta4_addons_matrix_screen.png
new file mode 100644
index 0000000..e5575cc
Binary files /dev/null and b/ta4_addons/textures/ta4_addons_matrix_screen.png differ
diff --git a/ta4_addons/textures/ta4_addons_matrix_screen_inventory.png b/ta4_addons/textures/ta4_addons_matrix_screen_inventory.png
new file mode 100644
index 0000000..6010178
Binary files /dev/null and b/ta4_addons/textures/ta4_addons_matrix_screen_inventory.png differ
diff --git a/ta4_addons/textures/ta4_addons_matrix_screen_overlay.png b/ta4_addons/textures/ta4_addons_matrix_screen_overlay.png
new file mode 100644
index 0000000..11752c2
Binary files /dev/null and b/ta4_addons/textures/ta4_addons_matrix_screen_overlay.png differ
diff --git a/ta4_addons/touchscreen/main.lua b/ta4_addons/touchscreen/main.lua
index 6674d8a..5524c49 100644
--- a/ta4_addons/touchscreen/main.lua
+++ b/ta4_addons/touchscreen/main.lua
@@ -3,8 +3,8 @@
TA4 Addons
==========
- Copyright (C) 2020 Joachim Stolberg
- Copyright (C) 2020 Thomas S.
+ Copyright (C) 2020-2021 Joachim Stolberg
+ Copyright (C) 2020-2021 Thomas S.
AGPL v3
See LICENSE.txt for more information
@@ -18,329 +18,329 @@ local M = minetest.get_meta
local N = techage.get_nvm
local function get_value(element, key, default)
- return minetest.formspec_escape(element.get(key) or default)
+ return minetest.formspec_escape(element.get(key) or default)
end
local function parse_payload(payload)
- local element_type = payload.get("type")
- if type(element_type) ~= "string" then
- return
- end
- element_type = string.lower(element_type)
- if element_type == "button" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local w = get_value(payload, "w", 2)
- local h = get_value(payload, "h", 1)
- local name = get_value(payload, "name", "button")
- local label = get_value(payload, "label", "Button")
- return "button["..x..","..y..";"..w..","..h..";"..name..";"..label.."]"
- elseif element_type == "label" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local label = get_value(payload, "label", "Label")
- return "label["..x..","..y..";"..label.."]"
- elseif element_type == "image" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local w = get_value(payload, "w", 1)
- local h = get_value(payload, "h", 1)
- local texture_name = get_value(payload, "texture_name", "default_apple.png")
- return "image["..x..","..y..";"..w..","..h..";"..texture_name.."]"
- elseif element_type == "animated_image" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local w = get_value(payload, "w", 1)
- local h = get_value(payload, "h", 1)
- local name = get_value(payload, "name", "animated_image")
- local texture_name = get_value(payload, "texture_name", "default_apple.png")
- local frame_count = get_value(payload, "frame_count", 1)
- local frame_duration = get_value(payload, "frame_duration", 1000)
- local frame_start = get_value(payload, "frame_start", 1)
- return "animated_image["..x..","..y..";"..w..","..h..";"..name..";"..texture_name..";"..frame_count..";"..frame_duration..";"..frame_start.."]"
- elseif element_type == "item_image" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local w = get_value(payload, "w", 1)
- local h = get_value(payload, "h", 1)
- local item_name = get_value(payload, "item_name", "default:apple")
- return "item_image["..x..","..y..";"..w..","..h..";"..item_name.."]"
- elseif element_type == "pwdfield" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local w = get_value(payload, "w", 2)
- local h = get_value(payload, "h", 1)
- local name = get_value(payload, "name", "pwdfield")
- local label = get_value(payload, "label", "Password")
- return "pwdfield["..x..","..y..";"..w..","..h..";"..name..";"..label.."]"
- elseif element_type == "field" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local w = get_value(payload, "w", 2)
- local h = get_value(payload, "h", 1)
- local name = get_value(payload, "name", "field")
- local label = get_value(payload, "label", "Input")
- local default = get_value(payload, "default", ""):gsub("%${", "$ {") -- To prevent reading metadata
- return "field["..x..","..y..";"..w..","..h..";"..name..";"..label..";"..default.."]"
- elseif element_type == "field_close_on_enter" then
- local name = get_value(payload, "name", "field")
- local close_on_enter = get_value(payload, "close_on_enter", "false")
- return "field_close_on_enter["..name..";"..close_on_enter"]"
- elseif element_type == "textarea" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local w = get_value(payload, "w", 2)
- local h = get_value(payload, "h", 1)
- local name = get_value(payload, "name", "")
- local label = get_value(payload, "label", "Textarea")
- local default = get_value(payload, "default", ""):gsub("%${", "$ {") -- To prevent reading metadata
- return "textarea["..x..","..y..";"..w..","..h..";"..name..";"..label..";"..default.."]"
- elseif element_type == "image_button" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local w = get_value(payload, "w", 1)
- local h = get_value(payload, "h", 1)
- local texture_name = get_value(payload, "texture_name", "default_apple.png")
- local name = get_value(payload, "name", "image_button")
- local label = get_value(payload, "label", "")
- return "image_button["..x..","..y..";"..w..","..h..";"..texture_name..";"..name..";"..label.."]"
- elseif element_type == "item_image_button" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local w = get_value(payload, "w", 1)
- local h = get_value(payload, "h", 1)
- local item_name = get_value(payload, "item_name", "default:apple")
- local name = get_value(payload, "name", "item_image_button")
- local label = get_value(payload, "label", "")
- return "item_image_button["..x..","..y..";"..w..","..h..";"..item_name..";"..name..";"..label.."]"
- elseif element_type == "button_exit" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local w = get_value(payload, "w", 2)
- local h = get_value(payload, "h", 1)
- local name = get_value(payload, "name", "button_exit")
- local label = get_value(payload, "label", "Exit Button")
- return "button_exit["..x..","..y..";"..w..","..h..";"..name..";"..label.."]"
- elseif element_type == "image_button_exit" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local w = get_value(payload, "w", 1)
- local h = get_value(payload, "h", 1)
- local texture_name = get_value(payload, "texture_name", "creative_clear_icon.png")
- local name = get_value(payload, "name", "image_button")
- local label = get_value(payload, "label", "")
- return "image_button_exit["..x..","..y..";"..w..","..h..";"..texture_name..";"..name..";"..label.."]"
- elseif element_type == "box" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local w = get_value(payload, "w", 2)
- local h = get_value(payload, "h", 1)
- local color = get_value(payload, "color", "")
- return "box["..x..","..y..";"..w..","..h..";"..color.."]"
- elseif element_type == "checkbox" then
- local x = get_value(payload, "x", 1)
- local y = get_value(payload, "y", 1)
- local name = get_value(payload, "name", "checkbox")
- local label = get_value(payload, "label", "")
- local selected = get_value(payload, "selected", "false")
- return "checkbox["..x..","..y..";"..name..";"..label..";"..selected.."]"
- end
+ local element_type = payload.get("type")
+ if type(element_type) ~= "string" then
+ return
+ end
+ element_type = string.lower(element_type)
+ if element_type == "button" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local w = get_value(payload, "w", 2)
+ local h = get_value(payload, "h", 1)
+ local name = get_value(payload, "name", "button")
+ local label = get_value(payload, "label", "Button")
+ return "button["..x..","..y..";"..w..","..h..";"..name..";"..label.."]"
+ elseif element_type == "label" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local label = get_value(payload, "label", "Label")
+ return "label["..x..","..y..";"..label.."]"
+ elseif element_type == "image" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local w = get_value(payload, "w", 1)
+ local h = get_value(payload, "h", 1)
+ local texture_name = get_value(payload, "texture_name", "default_apple.png")
+ return "image["..x..","..y..";"..w..","..h..";"..texture_name.."]"
+ elseif element_type == "animated_image" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local w = get_value(payload, "w", 1)
+ local h = get_value(payload, "h", 1)
+ local name = get_value(payload, "name", "animated_image")
+ local texture_name = get_value(payload, "texture_name", "default_apple.png")
+ local frame_count = get_value(payload, "frame_count", 1)
+ local frame_duration = get_value(payload, "frame_duration", 1000)
+ local frame_start = get_value(payload, "frame_start", 1)
+ return "animated_image["..x..","..y..";"..w..","..h..";"..name..";"..texture_name..";"..frame_count..";"..frame_duration..";"..frame_start.."]"
+ elseif element_type == "item_image" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local w = get_value(payload, "w", 1)
+ local h = get_value(payload, "h", 1)
+ local item_name = get_value(payload, "item_name", "default:apple")
+ return "item_image["..x..","..y..";"..w..","..h..";"..item_name.."]"
+ elseif element_type == "pwdfield" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local w = get_value(payload, "w", 2)
+ local h = get_value(payload, "h", 1)
+ local name = get_value(payload, "name", "pwdfield")
+ local label = get_value(payload, "label", "Password")
+ return "pwdfield["..x..","..y..";"..w..","..h..";"..name..";"..label.."]"
+ elseif element_type == "field" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local w = get_value(payload, "w", 2)
+ local h = get_value(payload, "h", 1)
+ local name = get_value(payload, "name", "field")
+ local label = get_value(payload, "label", "Input")
+ local default = get_value(payload, "default", ""):gsub("%${", "$ {") -- To prevent reading metadata
+ return "field["..x..","..y..";"..w..","..h..";"..name..";"..label..";"..default.."]"
+ elseif element_type == "field_close_on_enter" then
+ local name = get_value(payload, "name", "field")
+ local close_on_enter = get_value(payload, "close_on_enter", "false")
+ return "field_close_on_enter["..name..";"..close_on_enter"]"
+ elseif element_type == "textarea" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local w = get_value(payload, "w", 2)
+ local h = get_value(payload, "h", 1)
+ local name = get_value(payload, "name", "")
+ local label = get_value(payload, "label", "Textarea")
+ local default = get_value(payload, "default", ""):gsub("%${", "$ {") -- To prevent reading metadata
+ return "textarea["..x..","..y..";"..w..","..h..";"..name..";"..label..";"..default.."]"
+ elseif element_type == "image_button" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local w = get_value(payload, "w", 1)
+ local h = get_value(payload, "h", 1)
+ local texture_name = get_value(payload, "texture_name", "default_apple.png")
+ local name = get_value(payload, "name", "image_button")
+ local label = get_value(payload, "label", "")
+ return "image_button["..x..","..y..";"..w..","..h..";"..texture_name..";"..name..";"..label.."]"
+ elseif element_type == "item_image_button" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local w = get_value(payload, "w", 1)
+ local h = get_value(payload, "h", 1)
+ local item_name = get_value(payload, "item_name", "default:apple")
+ local name = get_value(payload, "name", "item_image_button")
+ local label = get_value(payload, "label", "")
+ return "item_image_button["..x..","..y..";"..w..","..h..";"..item_name..";"..name..";"..label.."]"
+ elseif element_type == "button_exit" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local w = get_value(payload, "w", 2)
+ local h = get_value(payload, "h", 1)
+ local name = get_value(payload, "name", "button_exit")
+ local label = get_value(payload, "label", "Exit Button")
+ return "button_exit["..x..","..y..";"..w..","..h..";"..name..";"..label.."]"
+ elseif element_type == "image_button_exit" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local w = get_value(payload, "w", 1)
+ local h = get_value(payload, "h", 1)
+ local texture_name = get_value(payload, "texture_name", "creative_clear_icon.png")
+ local name = get_value(payload, "name", "image_button")
+ local label = get_value(payload, "label", "")
+ return "image_button_exit["..x..","..y..";"..w..","..h..";"..texture_name..";"..name..";"..label.."]"
+ elseif element_type == "box" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local w = get_value(payload, "w", 2)
+ local h = get_value(payload, "h", 1)
+ local color = get_value(payload, "color", "")
+ return "box["..x..","..y..";"..w..","..h..";"..color.."]"
+ elseif element_type == "checkbox" then
+ local x = get_value(payload, "x", 1)
+ local y = get_value(payload, "y", 1)
+ local name = get_value(payload, "name", "checkbox")
+ local label = get_value(payload, "label", "")
+ local selected = get_value(payload, "selected", "false")
+ return "checkbox["..x..","..y..";"..name..";"..label..";"..selected.."]"
+ end
end
local function next_id(pos)
- local nvm = N(pos)
- local id = (nvm.element_id or 0) + 1
- nvm.element_id = id
- return id
+ local nvm = N(pos)
+ local id = (nvm.element_id or 0) + 1
+ nvm.element_id = id
+ return id
end
local function reset_id(pos)
- N(pos).element_id = 0
+ N(pos).element_id = 0
end
local function get_elements(pos)
- local nvm = N(pos)
- nvm.elements = nvm.elements or {}
- return nvm.elements
+ local nvm = N(pos)
+ nvm.elements = nvm.elements or {}
+ return nvm.elements
end
local function valid_payload(payload)
- if not payload then return false end
- if not type(payload) == "table" then return false end
- if not payload.get then return false end
- if not payload.next then return false end
- return true
+ if not payload then return false end
+ if not type(payload) == "table" then return false end
+ if not payload.get then return false end
+ if not payload.next then return false end
+ return true
end
local function update_fs(pos)
- local meta = M(pos)
- local fs = "formspec_version[3]"
- fs = fs .. "size[10,10]"
- local elements = get_elements(pos)
- for _,ele in ipairs(elements) do
- fs = fs .. ele
- end
- meta:set_string("formspec", fs)
+ local meta = M(pos)
+ local fs = "formspec_version[3]"
+ fs = fs .. "size[10,10]"
+ local elements = get_elements(pos)
+ for _,ele in ipairs(elements) do
+ fs = fs .. ele
+ end
+ meta:set_string("formspec", fs)
end
local function add_content(pos, payload)
- if not valid_payload(payload) then
- return
- end
- local element = parse_payload(payload)
- if not element then
- return
- end
- local elements = get_elements(pos)
- local id = next_id(pos)
- elements[id] = element
- update_fs(pos)
- return id
+ if not valid_payload(payload) then
+ return
+ end
+ local element = parse_payload(payload)
+ if not element then
+ return
+ end
+ local elements = get_elements(pos)
+ local id = next_id(pos)
+ elements[id] = element
+ update_fs(pos)
+ return id
end
local function update_content(pos, payload)
- if not valid_payload(payload) then
- return false
- end
- local id = payload.get("id")
- local elements = get_elements(pos)
- if not id or not elements[id] then
- return false
- end
- local element = parse_payload(payload)
- if not element then
- return false
- end
- elements[id] = element
- update_fs(pos)
- return true
+ if not valid_payload(payload) then
+ return false
+ end
+ local id = payload.get("id")
+ local elements = get_elements(pos)
+ if not id or not elements[id] then
+ return false
+ end
+ local element = parse_payload(payload)
+ if not element then
+ return false
+ end
+ elements[id] = element
+ update_fs(pos)
+ return true
end
local function remove_content(pos, payload)
- if valid_payload(payload) then
- local id = payload.get("id")
- if id then
- local elements = get_elements(pos)
- if not elements[id] then
- return false
- end
- elements[id] = nil
- update_fs(pos)
- return true
- else
- return false
- end
- end
- local nvm = techage.get_nvm(pos)
- nvm.elements = {}
- nvm.element_id = nil
- update_fs(pos)
- return true
+ if valid_payload(payload) then
+ local id = payload.get("id")
+ if id then
+ local elements = get_elements(pos)
+ if not elements[id] then
+ return false
+ end
+ elements[id] = nil
+ update_fs(pos)
+ return true
+ else
+ return false
+ end
+ end
+ local nvm = techage.get_nvm(pos)
+ nvm.elements = {}
+ nvm.element_id = nil
+ update_fs(pos)
+ return true
end
minetest.register_node("ta4_addons:touchscreen", {
- description = S("TA4 Display"),
- inventory_image = "ta4_addons_touchscreen_inventory.png",
- tiles = {"ta4_addons_touchscreen.png"},
- drawtype = "nodebox",
- paramtype = "light",
- sunlight_propagates = true,
- paramtype2 = "wallmounted",
- node_box = techage.display.lcd_box,
- selection_box = techage.display.lcd_box,
- light_source = 6,
+ description = S("TA4 Display"),
+ inventory_image = "ta4_addons_touchscreen_inventory.png",
+ tiles = {"ta4_addons_touchscreen.png"},
+ drawtype = "nodebox",
+ paramtype = "light",
+ sunlight_propagates = true,
+ paramtype2 = "wallmounted",
+ node_box = techage.display.lcd_box,
+ selection_box = techage.display.lcd_box,
+ light_source = 6,
- display_entities = {
- ["techage:display_entity"] = {
- depth = 0.42,
- on_display_update = techage.display.display_update
- },
- },
+ display_entities = {
+ ["techage:display_entity"] = {
+ depth = 0.42,
+ on_display_update = techage.display.display_update
+ },
+ },
- after_place_node = function(pos, placer)
- local number = techage.add_node(pos, "ta4_addons:touchscreen")
- local meta = M(pos)
- meta:set_string("node_number", number)
- meta:set_string("infotext", S("Touchscreen no: ")..number)
- update_fs(pos)
- local nvm = techage.get_nvm(pos)
- nvm.text = {"My", "Techage","TA4", "Touchscreen", "No: "..number}
- lcdlib.update_entities(pos)
- minetest.get_node_timer(pos):start(1)
- end,
+ after_place_node = function(pos, placer)
+ local number = techage.add_node(pos, "ta4_addons:touchscreen")
+ local meta = M(pos)
+ meta:set_string("node_number", number)
+ meta:set_string("infotext", S("Touchscreen no: ")..number)
+ update_fs(pos)
+ local nvm = techage.get_nvm(pos)
+ nvm.text = {"My", "Techage","TA4", "Touchscreen", "No: "..number}
+ lcdlib.update_entities(pos)
+ minetest.get_node_timer(pos):start(1)
+ end,
- after_dig_node = function(pos, oldnode, oldmetadata)
- remove_content(pos)
- techage.remove_node(pos, oldnode, oldmetadata)
- end,
-
- on_rightclick = function(pos, node, clicker)
- local meta = M(pos)
- local ctrl = meta:get_string("ctrl")
- if ctrl then
- local own_num = meta:get_string("node_number") or ""
- techage.send_single(own_num, ctrl, "msg", safer_lua.Store("_touchscreen_opened_by", clicker:get_player_name()))
- end
- end,
+ after_dig_node = function(pos, oldnode, oldmetadata)
+ remove_content(pos)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ end,
- on_receive_fields = function(pos, formname, fields, sender)
- local meta = M(pos)
- local player_name = sender:get_player_name()
- if meta:get_string("public") ~= "true" and minetest.is_protected(pos, player_name) then
- return
- end
- local fields_store = safer_lua.Store()
- for k,v in pairs(fields) do
- fields_store.set(k, v)
- end
- fields_store.set("_sent_by", player_name)
- local ctrl = meta:get_string("ctrl")
- if ctrl then
- local own_num = meta:get_string("node_number") or ""
- techage.send_single(own_num, ctrl, "msg", fields_store)
- end
- end,
+ on_rightclick = function(pos, node, clicker)
+ local meta = M(pos)
+ local ctrl = meta:get_string("ctrl")
+ if ctrl then
+ local own_num = meta:get_string("node_number") or ""
+ techage.send_single(own_num, ctrl, "msg", safer_lua.Store("_touchscreen_opened_by", clicker:get_player_name()))
+ end
+ end,
- on_timer = techage.display.on_timer,
- on_place = lcdlib.on_place,
- on_construct = lcdlib.on_construct,
- on_destruct = lcdlib.on_destruct,
- on_rotate = lcdlib.on_rotate,
- groups = {cracky=2, crumbly=2},
- is_ground_content = false,
- sounds = default.node_sound_glass_defaults(),
+ on_receive_fields = function(pos, formname, fields, sender)
+ local meta = M(pos)
+ local player_name = sender:get_player_name()
+ if meta:get_string("public") ~= "true" and minetest.is_protected(pos, player_name) then
+ return
+ end
+ local fields_store = safer_lua.Store()
+ for k,v in pairs(fields) do
+ fields_store.set(k, v)
+ end
+ fields_store.set("_sent_by", player_name)
+ local ctrl = meta:get_string("ctrl")
+ if ctrl then
+ local own_num = meta:get_string("node_number") or ""
+ techage.send_single(own_num, ctrl, "msg", fields_store)
+ end
+ end,
+
+ on_timer = techage.display.on_timer,
+ on_place = lcdlib.on_place,
+ on_construct = lcdlib.on_construct,
+ on_destruct = lcdlib.on_destruct,
+ on_rotate = lcdlib.on_rotate,
+ groups = {cracky=2, crumbly=2},
+ is_ground_content = false,
+ sounds = default.node_sound_glass_defaults(),
})
minetest.register_craft({
- output = "ta4_addons:touchscreen",
- recipe = {
- {"", "dye:blue", ""},
- {"default:copper_ingot", "techage:ta4_display", "default:copper_ingot"},
- {"", "default:mese_crystal_fragment", ""},
- },
+ output = "ta4_addons:touchscreen",
+ recipe = {
+ {"", "dye:blue", ""},
+ {"default:copper_ingot", "techage:ta4_display", "default:copper_ingot"},
+ {"", "default:mese_crystal_fragment", ""},
+ },
})
techage.register_node({"ta4_addons:touchscreen"}, {
- on_recv_message = function(pos, src, topic, payload)
- if topic == "add" then -- add one line and scroll if necessary
- techage.display.add_line(pos, payload, 1)
- elseif topic == "set" then -- overwrite the given row
- techage.display.write_row(pos, payload, 1)
- elseif topic == "clear" then -- clear the screen
- techage.display.clear_screen(pos, 1)
- elseif topic == "add_content" then
- M(pos):set_string("ctrl", src)
- return add_content(pos, payload)
- elseif topic == "update_content" then
- M(pos):set_string("ctrl", src)
- return update_content(pos, payload)
- elseif topic == "remove_content" then
- M(pos):set_string("ctrl", src)
- return remove_content(pos, payload)
- elseif topic == "private" then
- M(pos):set_string("public", "false")
- elseif topic == "public" then
- M(pos):set_string("public", "true")
- end
- end,
+ on_recv_message = function(pos, src, topic, payload)
+ if topic == "add" then -- add one line and scroll if necessary
+ techage.display.add_line(pos, payload, 1)
+ elseif topic == "set" then -- overwrite the given row
+ techage.display.write_row(pos, payload, 1)
+ elseif topic == "clear" then -- clear the screen
+ techage.display.clear_screen(pos, 1)
+ elseif topic == "add_content" then
+ M(pos):set_string("ctrl", src)
+ return add_content(pos, payload)
+ elseif topic == "update_content" then
+ M(pos):set_string("ctrl", src)
+ return update_content(pos, payload)
+ elseif topic == "remove_content" then
+ M(pos):set_string("ctrl", src)
+ return remove_content(pos, payload)
+ elseif topic == "private" then
+ M(pos):set_string("public", "false")
+ elseif topic == "public" then
+ M(pos):set_string("public", "true")
+ end
+ end,
})
\ No newline at end of file
diff --git a/unified_inventory/.github/workflows/check-release.yml b/unified_inventory/.github/workflows/check-release.yml
new file mode 100644
index 0000000..47313ff
--- /dev/null
+++ b/unified_inventory/.github/workflows/check-release.yml
@@ -0,0 +1,11 @@
+on: [push, pull_request]
+name: Check & Release
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - name: lint
+ uses: Roang-zero1/factorio-mod-luacheck@master
+ with:
+ luacheckrc_url: https://raw.githubusercontent.com/minetest-mods/unified_inventory/master/.luacheckrc
diff --git a/unified_inventory/.luacheckrc b/unified_inventory/.luacheckrc
index 9fb6a7c..e6fec97 100644
--- a/unified_inventory/.luacheckrc
+++ b/unified_inventory/.luacheckrc
@@ -14,6 +14,7 @@ read_globals = {
"ItemStack", "datastorage",
"hb",
+ "doors",
}
files["callbacks.lua"].ignore = { "player", "draw_lite_mode" }
diff --git a/unified_inventory/README.md b/unified_inventory/README.md
index 8c917ec..5d23f79 100644
--- a/unified_inventory/README.md
+++ b/unified_inventory/README.md
@@ -15,7 +15,8 @@ Unified Inventory replaces the default survival and creative inventory.
* Recipe search function by ingredients
* Up to four bags with up to 24 slots each
* Home function to teleport
- * Trash slot
+ * Trash slot and refill slot for creative
+ * Waypoints to keep track of important locations
* Lite mode: reduces the item browser width
* `minetest.conf` setting `unified_inventory_lite = true`
* Mod API for modders: see [mod_api.txt](doc/mod_api.txt)
@@ -24,7 +25,11 @@ Unified Inventory replaces the default survival and creative inventory.
## Requirements
- * Minetest 5.0.0+
+ * Minetest 5.4.0+
+ * Mod `default` for category filters (contained in Minetest Game)
+ * Mod `farming` for craftable bags (contained in Minetest Game)
+ * For waypoint migration: `datastorage`
+
# Licenses
@@ -96,4 +101,4 @@ Other files from Wikimedia Commons:
RealBadAngel: (CC-BY-4.0)
- * Everything else.
\ No newline at end of file
+ * Everything else.
diff --git a/unified_inventory/api.lua b/unified_inventory/api.lua
index 81dd8f3..8cc5532 100644
--- a/unified_inventory/api.lua
+++ b/unified_inventory/api.lua
@@ -1,5 +1,6 @@
local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape
+local ui = unified_inventory
-- Create detached creative inventory after loading all mods
minetest.after(0.01, function()
@@ -8,12 +9,12 @@ minetest.after(0.01, function()
if not rev_aliases[target] then rev_aliases[target] = {} end
table.insert(rev_aliases[target], source)
end
- unified_inventory.items_list = {}
+ ui.items_list = {}
for name, def in pairs(minetest.registered_items) do
if (not def.groups.not_in_creative_inventory or
def.groups.not_in_creative_inventory == 0) and
def.description and def.description ~= "" then
- table.insert(unified_inventory.items_list, name)
+ table.insert(ui.items_list, name)
local all_names = rev_aliases[name] or {}
table.insert(all_names, name)
for _, player_name in ipairs(all_names) do
@@ -26,30 +27,30 @@ minetest.after(0.01, function()
for _,chk in pairs(recipe.items) do
local groupchk = string.find(chk, "group:")
if (not groupchk and not minetest.registered_items[chk])
- or (groupchk and not unified_inventory.get_group_item(string.gsub(chk, "group:", "")).item)
+ or (groupchk and not ui.get_group_item(string.gsub(chk, "group:", "")).item)
or minetest.get_item_group(chk, "not_in_craft_guide") ~= 0 then
unknowns = true
end
end
if not unknowns then
- unified_inventory.register_craft(recipe)
+ ui.register_craft(recipe)
end
end
end
end
end
end
- table.sort(unified_inventory.items_list)
- unified_inventory.items_list_size = #unified_inventory.items_list
- print("Unified Inventory. inventory size: "..unified_inventory.items_list_size)
- for _, name in ipairs(unified_inventory.items_list) do
+ table.sort(ui.items_list)
+ ui.items_list_size = #ui.items_list
+ print("Unified Inventory. inventory size: "..ui.items_list_size)
+ for _, name in ipairs(ui.items_list) do
local def = minetest.registered_items[name]
-- Simple drops
if type(def.drop) == "string" then
local dstack = ItemStack(def.drop)
if not dstack:is_empty() and dstack:get_name() ~= name then
- unified_inventory.register_craft({
+ ui.register_craft({
type = "digging",
items = {name},
output = def.drop,
@@ -115,7 +116,7 @@ minetest.after(0.01, function()
end
end
for itemstring, count in pairs(drop_guaranteed) do
- unified_inventory.register_craft({
+ ui.register_craft({
type = "digging",
items = {name},
output = itemstring .. " " .. count,
@@ -123,7 +124,7 @@ minetest.after(0.01, function()
})
end
for itemstring, count in pairs(drop_maybe) do
- unified_inventory.register_craft({
+ ui.register_craft({
type = "digging_chance",
items = {name},
output = itemstring .. " " .. count,
@@ -132,33 +133,37 @@ minetest.after(0.01, function()
end
end
end
- for _, recipes in pairs(unified_inventory.crafts_for.recipe) do
+ for _, recipes in pairs(ui.crafts_for.recipe) do
for _, recipe in ipairs(recipes) do
local ingredient_items = {}
for _, spec in pairs(recipe.items) do
- local matches_spec = unified_inventory.canonical_item_spec_matcher(spec)
- for _, name in ipairs(unified_inventory.items_list) do
+ local matches_spec = ui.canonical_item_spec_matcher(spec)
+ for _, name in ipairs(ui.items_list) do
if matches_spec(name) then
ingredient_items[name] = true
end
end
end
for name, _ in pairs(ingredient_items) do
- if unified_inventory.crafts_for.usage[name] == nil then
- unified_inventory.crafts_for.usage[name] = {}
+ if ui.crafts_for.usage[name] == nil then
+ ui.crafts_for.usage[name] = {}
end
- table.insert(unified_inventory.crafts_for.usage[name], recipe)
+ table.insert(ui.crafts_for.usage[name], recipe)
end
end
end
+
+ for _, callback in ipairs(ui.initialized_callbacks) do
+ callback()
+ end
end)
-- load_home
local function load_home()
- local input = io.open(unified_inventory.home_filename, "r")
+ local input = io.open(ui.home_filename, "r")
if not input then
- unified_inventory.home_pos = {}
+ ui.home_pos = {}
return
end
while true do
@@ -167,25 +172,31 @@ local function load_home()
local y = input:read("*n")
local z = input:read("*n")
local name = input:read("*l")
- unified_inventory.home_pos[name:sub(2)] = {x = x, y = y, z = z}
+ ui.home_pos[name:sub(2)] = {x = x, y = y, z = z}
end
io.close(input)
end
load_home()
-function unified_inventory.set_home(player, pos)
+function ui.set_home(player, pos)
local player_name = player:get_player_name()
- unified_inventory.home_pos[player_name] = vector.round(pos)
+ ui.home_pos[player_name] = vector.round(pos)
+
-- save the home data from the table to the file
- local output = io.open(unified_inventory.home_filename, "w")
- for k, v in pairs(unified_inventory.home_pos) do
+ local output = io.open(ui.home_filename, "w")
+ if not output then
+ minetest.log("warning", "[unified_inventory] Failed to save file: "
+ .. ui.home_filename)
+ return
+ end
+ for k, v in pairs(ui.home_pos) do
output:write(v.x.." "..v.y.." "..v.z.." "..k.."\n")
end
io.close(output)
end
-function unified_inventory.go_home(player)
- local pos = unified_inventory.home_pos[player:get_player_name()]
+function ui.go_home(player)
+ local pos = ui.home_pos[player:get_player_name()]
if pos then
player:set_pos(pos)
return true
@@ -194,7 +205,7 @@ function unified_inventory.go_home(player)
end
-- register_craft
-function unified_inventory.register_craft(options)
+function ui.register_craft(options)
if not options.output then
return
end
@@ -205,10 +216,15 @@ function unified_inventory.register_craft(options)
if options.type == "normal" and options.width == 0 then
options = { type = "shapeless", items = options.items, output = options.output, width = 0 }
end
- if not unified_inventory.crafts_for.recipe[itemstack:get_name()] then
- unified_inventory.crafts_for.recipe[itemstack:get_name()] = {}
+ local item_name = itemstack:get_name()
+ if not ui.crafts_for.recipe[item_name] then
+ ui.crafts_for.recipe[item_name] = {}
+ end
+ table.insert(ui.crafts_for.recipe[item_name],options)
+
+ for _, callback in ipairs(ui.craft_registered_callbacks) do
+ callback(item_name, options)
end
- table.insert(unified_inventory.crafts_for.recipe[itemstack:get_name()],options)
end
@@ -219,7 +235,7 @@ local craft_type_defaults = {
}
-function unified_inventory.craft_type_defaults(name, options)
+function ui.craft_type_defaults(name, options)
if not options.description then
options.description = name
end
@@ -228,13 +244,13 @@ function unified_inventory.craft_type_defaults(name, options)
end
-function unified_inventory.register_craft_type(name, options)
- unified_inventory.registered_craft_types[name] =
- unified_inventory.craft_type_defaults(name, options)
+function ui.register_craft_type(name, options)
+ ui.registered_craft_types[name] =
+ ui.craft_type_defaults(name, options)
end
-unified_inventory.register_craft_type("normal", {
+ui.register_craft_type("normal", {
description = F(S("Crafting")),
icon = "ui_craftgrid_icon.png",
width = 3,
@@ -250,7 +266,7 @@ unified_inventory.register_craft_type("normal", {
})
-unified_inventory.register_craft_type("shapeless", {
+ui.register_craft_type("shapeless", {
description = F(S("Mixing")),
icon = "ui_craftgrid_icon.png",
width = 3,
@@ -265,7 +281,7 @@ unified_inventory.register_craft_type("shapeless", {
})
-unified_inventory.register_craft_type("cooking", {
+ui.register_craft_type("cooking", {
description = F(S("Cooking")),
icon = "default_furnace_front.png",
width = 1,
@@ -273,37 +289,86 @@ unified_inventory.register_craft_type("cooking", {
})
-unified_inventory.register_craft_type("digging", {
+ui.register_craft_type("digging", {
description = F(S("Digging")),
icon = "default_tool_steelpick.png",
width = 1,
height = 1,
})
-unified_inventory.register_craft_type("digging_chance", {
+ui.register_craft_type("digging_chance", {
description = "Digging (by chance)",
icon = "default_tool_steelpick.png^[transformFY.png",
width = 1,
height = 1,
})
-function unified_inventory.register_page(name, def)
- unified_inventory.pages[name] = def
+function ui.register_page(name, def)
+ ui.pages[name] = def
end
-function unified_inventory.register_button(name, def)
+function ui.register_button(name, def)
if not def.action then
def.action = function(player)
- unified_inventory.set_inventory_formspec(player, name)
+ ui.set_inventory_formspec(player, name)
end
end
def.name = name
- table.insert(unified_inventory.buttons, def)
+ table.insert(ui.buttons, def)
end
+function ui.register_on_initialized(callback)
+ if type(callback) ~= "function" then
+ error(("Initialized callback must be a function, %s given."):format(type(callback)))
+ end
+ table.insert(ui.initialized_callbacks, callback)
+end
-function unified_inventory.is_creative(playername)
+function ui.register_on_craft_registered(callback)
+ if type(callback) ~= "function" then
+ error(("Craft registered callback must be a function, %s given."):format(type(callback)))
+ end
+ table.insert(ui.craft_registered_callbacks, callback)
+end
+
+function ui.get_recipe_list(output)
+ return ui.crafts_for.recipe[output]
+end
+
+function ui.get_registered_outputs()
+ local outputs = {}
+ for item_name, _ in pairs(ui.crafts_for.recipe) do
+ table.insert(outputs, item_name)
+ end
+ return outputs
+end
+
+function ui.is_creative(playername)
return minetest.check_player_privs(playername, {creative=true})
or minetest.settings:get_bool("creative_mode")
end
+
+function ui.single_slot(xpos, ypos, bright)
+ return string.format("background9[%f,%f;%f,%f;ui_single_slot%s.png;false;16]",
+ xpos, ypos, ui.imgscale, ui.imgscale, (bright and "_bright" or "") )
+end
+
+function ui.make_trash_slot(xpos, ypos)
+ return
+ ui.single_slot(xpos, ypos)..
+ "image["..xpos..","..ypos..";1.25,1.25;ui_trash_slot_icon.png]"..
+ "list[detached:trash;main;"..(xpos + ui.list_img_offset)..","..(ypos + ui.list_img_offset)..";1,1;]"
+end
+
+function ui.make_inv_img_grid(xpos, ypos, width, height, bright)
+ local tiled = {}
+ local n=1
+ for y = 0, (height - 1) do
+ for x = 0, (width -1) do
+ tiled[n] = ui.single_slot(xpos + (ui.imgscale * x), ypos + (ui.imgscale * y), bright)
+ n = n + 1
+ end
+ end
+ return table.concat(tiled)
+end
diff --git a/unified_inventory/bags.lua b/unified_inventory/bags.lua
index 1bb2b5c..14ac875 100644
--- a/unified_inventory/bags.lua
+++ b/unified_inventory/bags.lua
@@ -7,29 +7,32 @@ License: GPLv3
local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape
-local bags_inv_bg_prefix = "image[-0.1,1.0;10.05,"
+local ui = unified_inventory
-unified_inventory.register_page("bags", {
+ui.register_page("bags", {
get_formspec = function(player)
local player_name = player:get_player_name()
return { formspec = table.concat({
- string.gsub(unified_inventory.standard_inv_bg, "YYY", "4.4"),
- bags_inv_bg_prefix.."1.175;ui_bags_header.png]",
- "label[0,0;" .. F(S("Bags")) .. "]",
- "button[0,2.2;2,0.5;bag1;" .. F(S("Bag @1", 1)) .. "]",
- "button[2,2.2;2,0.5;bag2;" .. F(S("Bag @1", 2)) .. "]",
- "button[4,2.2;2,0.5;bag3;" .. F(S("Bag @1", 3)) .. "]",
- "button[6,2.2;2,0.5;bag4;" .. F(S("Bag @1", 4)) .. "]",
+ ui.style_full.standard_inv_bg,
+ ui.single_slot(0.925, 1.5),
+ ui.single_slot(3.425, 1.5),
+ ui.single_slot(5.925, 1.5),
+ ui.single_slot(8.425, 1.5),
+ "label["..ui.style_full.form_header_x..","..ui.style_full.form_header_y..";" .. F(S("Bags")) .. "]",
+ "button[0.6125,2.75;1.875,0.75;bag1;" .. F(S("Bag @1", 1)) .. "]",
+ "button[3.1125,2.75;1.875,0.75;bag2;" .. F(S("Bag @1", 2)) .. "]",
+ "button[5.6125,2.75;1.875,0.75;bag3;" .. F(S("Bag @1", 3)) .. "]",
+ "button[8.1125,2.75;1.875,0.75;bag4;" .. F(S("Bag @1", 4)) .. "]",
"listcolors[#00000000;#00000000]",
- "list[detached:" .. F(player_name) .. "_bags;bag1;0.5,1.1;1,1;]",
- "list[detached:" .. F(player_name) .. "_bags;bag2;2.5,1.1;1,1;]",
- "list[detached:" .. F(player_name) .. "_bags;bag3;4.5,1.1;1,1;]",
- "list[detached:" .. F(player_name) .. "_bags;bag4;6.5,1.1;1,1;]"
+ "list[detached:" .. F(player_name) .. "_bags;bag1;1.075,1.65;1,1;]",
+ "list[detached:" .. F(player_name) .. "_bags;bag2;3.575,1.65;1,1;]",
+ "list[detached:" .. F(player_name) .. "_bags;bag3;6.075,1.65;1,1;]",
+ "list[detached:" .. F(player_name) .. "_bags;bag4;8.575,1.65;1,1;]"
}) }
end,
})
-unified_inventory.register_button("bags", {
+ui.register_button("bags", {
type = "image",
image = "ui_bags_icon.png",
tooltip = S("Bags"),
@@ -44,33 +47,31 @@ local function get_player_bag_stack(player, i)
end
for bag_i = 1, 4 do
- unified_inventory.register_page("bag" .. bag_i, {
+ ui.register_page("bag" .. bag_i, {
get_formspec = function(player)
local stack = get_player_bag_stack(player, bag_i)
local image = stack:get_definition().inventory_image
- local fs = {
- string.gsub(unified_inventory.standard_inv_bg, "YYY", "4.4"),
- "image[7,0;1,1;" .. image .. "]",
- "label[0,0;" .. F(S("Bag @1", bag_i)) .. "]",
- "listcolors[#00000000;#00000000]",
- "list[current_player;bag" .. bag_i .. "contents;0,1.1;8,3;]",
- "listring[current_name;bag" .. bag_i .. "contents]",
- "listring[current_player;main]",
- }
local slots = stack:get_definition().groups.bagslots
- if slots == 8 then
- fs[#fs + 1] = bags_inv_bg_prefix.."1.175;ui_bags_inv_small.png]"
- elseif slots == 16 then
- fs[#fs + 1] = bags_inv_bg_prefix.."2.35;ui_bags_inv_medium.png]"
- elseif slots == 24 then
- fs[#fs + 1] = bags_inv_bg_prefix.."3.525;ui_bags_inv_large.png]"
- end
+
+ local formspec = {
+ ui.style_full.standard_inv_bg,
+ ui.make_inv_img_grid(0.3, 1.5, 8, slots/8),
+ "image[9.2,0.4;1,1;" .. image .. "]",
+ "label[0.3,0.65;" .. F(S("Bag @1", bag_i)) .. "]",
+ "listcolors[#00000000;#00000000]",
+ "listring[current_player;main]",
+ string.format("list[current_player;bag%icontents;%f,%f;8,3;]",
+ bag_i, 0.3 + ui.list_img_offset, 1.5 + ui.list_img_offset),
+ "listring[current_name;bag" .. bag_i .. "contents]",
+ }
+ local n = #formspec + 1
+
local player_name = player:get_player_name() -- For if statement.
- if unified_inventory.trash_enabled
- or unified_inventory.is_creative(player_name)
- or minetest.get_player_privs(player_name).give then
- fs[#fs + 1] = "image[5.91,-0.06;1.21,1.15;ui_bags_trash.png]"
- .. "list[detached:trash;main;6,0.1;1,1;]"
+ if ui.trash_enabled
+ or ui.is_creative(player_name)
+ or minetest.get_player_privs(player_name).give then
+ formspec[n] = ui.make_trash_slot(7.8, 0.25)
+ n = n + 1
end
local inv = player:get_inventory()
for i = 1, 4 do
@@ -87,11 +88,12 @@ for bag_i = 1, 4 do
end
local img = def.inventory_image
local label = F(S("Bag @1", i)) .. "\n" .. used .. "/" .. size
- fs[#fs + 1] = string.format("image_button[%i,0;1,1;%s;bag%i;%s]",
- i + 1, img, i, label)
+ formspec[n] = string.format("image_button[%f,0.4;1,1;%s;bag%i;%s]",
+ (i + 1.35)*1.25, img, i, label)
+ n = n + 1
end
end
- return { formspec = table.concat(fs) }
+ return { formspec = table.concat(formspec) }
end,
})
end
@@ -106,7 +108,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if not stack:get_definition().groups.bagslots then
return
end
- unified_inventory.set_inventory_formspec(player, "bag" .. i)
+ ui.set_inventory_formspec(player, "bag" .. i)
return
end
end
diff --git a/unified_inventory/callbacks.lua b/unified_inventory/callbacks.lua
index bc90237..5874a0f 100644
--- a/unified_inventory/callbacks.lua
+++ b/unified_inventory/callbacks.lua
@@ -19,11 +19,12 @@ minetest.register_on_joinplayer(function(player)
unified_inventory.active_search_direction[player_name] = "nochange"
unified_inventory.apply_filter(player, "", "nochange")
unified_inventory.current_searchbox[player_name] = ""
+ unified_inventory.current_category[player_name] = "all"
+ unified_inventory.current_category_scroll[player_name] = 0
unified_inventory.alternate[player_name] = 1
unified_inventory.current_item[player_name] = nil
unified_inventory.current_craft_direction[player_name] = "recipe"
- unified_inventory.set_inventory_formspec(player,
- unified_inventory.default)
+ unified_inventory.set_inventory_formspec(player, unified_inventory.default)
-- Refill slot
local refill = minetest.create_detached_inventory(player_name.."refill", {
@@ -69,6 +70,41 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
unified_inventory.current_searchbox[player_name] = fields.searchbox
end
+
+ local clicked_category
+ for name, value in pairs(fields) do
+ local category_name = string.match(name, "^category_(.+)$")
+ if category_name then
+ clicked_category = category_name
+ break
+ end
+ end
+
+ if clicked_category
+ and clicked_category ~= unified_inventory.current_category[player_name] then
+ unified_inventory.current_category[player_name] = clicked_category
+ unified_inventory.apply_filter(player, unified_inventory.current_searchbox[player_name], "nochange")
+ unified_inventory.set_inventory_formspec(player,
+ unified_inventory.current_page[player_name])
+ end
+
+ if fields.next_category then
+ local scroll = math.min(#unified_inventory.category_list-ui_peruser.pagecols, unified_inventory.current_category_scroll[player_name] + 1)
+ if scroll ~= unified_inventory.current_category_scroll[player_name] then
+ unified_inventory.current_category_scroll[player_name] = scroll
+ unified_inventory.set_inventory_formspec(player,
+ unified_inventory.current_page[player_name])
+ end
+ end
+ if fields.prev_category then
+ local scroll = math.max(0, unified_inventory.current_category_scroll[player_name] - 1)
+ if scroll ~= unified_inventory.current_category_scroll[player_name] then
+ unified_inventory.current_category_scroll[player_name] = scroll
+ unified_inventory.set_inventory_formspec(player,
+ unified_inventory.current_page[player_name])
+ end
+ end
+
for i, def in pairs(unified_inventory.buttons) do
if fields[def.name] then
def.action(player)
@@ -121,11 +157,12 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
-- Check clicked item image button
local clicked_item
for name, value in pairs(fields) do
- local new_dir, mangled_item = string.match(name, "^item_button_([a-z]+)_(.*)$")
+ local new_dir, mangled_item = string.match(name, "^[0-9]*_?item_button_([a-z]+)_(.*)$")
if new_dir and mangled_item then
clicked_item = unified_inventory.demangle_for_formspec(mangled_item)
if string.sub(clicked_item, 1, 6) == "group:" then
-- Change search filter to this group
+ unified_inventory.current_category[player_name] = "all"
apply_new_filter(player, clicked_item, new_dir)
return
end
diff --git a/unified_inventory/category.lua b/unified_inventory/category.lua
new file mode 100644
index 0000000..d0fee5e
--- /dev/null
+++ b/unified_inventory/category.lua
@@ -0,0 +1,150 @@
+local S = minetest.get_translator("unified_inventory")
+
+unified_inventory.registered_categories = {}
+unified_inventory.registered_category_items = {}
+unified_inventory.category_list = {}
+
+local function char_to_sort_index(char_code)
+ if char_code <= 32 then
+ -- Command codes, no thanks
+ return 0
+ end
+ if char_code <= 64 then
+ -- Sorts numbers, and some punctuation, after letters
+ return char_code
+ end
+ if char_code >= 158 then
+ -- Out of sortable range
+ return 0
+ end
+ if char_code > 122 then
+ -- Avoids overlap with {, |, } and ~
+ return char_code - 58
+ end
+ if char_code > 96 then
+ -- Normalises lowercase with uppercase
+ return char_code - 96
+ end
+ return char_code - 64
+end
+
+local function string_to_sort_index(str)
+ local max_chars = 5
+ local power = 100
+ local index = 0
+ for i=1,math.min(#str, max_chars) do
+ index = index + (char_to_sort_index(string.byte(str, i))/(power^i))
+ end
+ return index
+end
+
+function update_category_list()
+ local category_list = {}
+ table.insert(category_list, {
+ name = "all",
+ label = S("All Items"),
+ symbol = "ui_category_all.png",
+ index = -2,
+ })
+ table.insert(category_list, {
+ name = "uncategorized",
+ label = S("Misc. Items"),
+ symbol = "ui_category_none.png",
+ index = -1,
+ })
+ for category, def in pairs(unified_inventory.registered_categories) do
+ table.insert(category_list, {
+ name = category,
+ label = def.label or category,
+ symbol = def.symbol,
+ index = def.index or -- sortby defined order
+ string_to_sort_index(category) -- or do a rudimentary alphabetical sort
+ })
+ end
+ table.sort(category_list, function (a,b)
+ return a.index < b.index
+ end)
+ unified_inventory.category_list = category_list
+end
+
+local function ensure_category_exists(category_name)
+ if not unified_inventory.registered_categories[category_name] then
+ unified_inventory.registered_categories[category_name] = {
+ symbol = "unknown_item.png",
+ label = category_name
+ }
+ end
+ if not unified_inventory.registered_category_items[category_name] then
+ unified_inventory.registered_category_items[category_name] = {}
+ end
+end
+
+function unified_inventory.register_category(category_name, config)
+ ensure_category_exists(category_name)
+ config = config or {}
+ if config.symbol then
+ unified_inventory.set_category_symbol(category_name, config.symbol)
+ end
+ if config.label then
+ unified_inventory.set_category_label(category_name, config.label)
+ end
+ if config.index then
+ unified_inventory.set_category_index(category_name, config.index)
+ end
+ if config.items then
+ unified_inventory.add_category_items(category_name, config.items)
+ end
+ update_category_list()
+end
+function unified_inventory.set_category_symbol(category_name, symbol)
+ ensure_category_exists(category_name)
+ unified_inventory.registered_categories[category_name].symbol = symbol
+ update_category_list()
+end
+function unified_inventory.set_category_label(category_name, label)
+ ensure_category_exists(category_name)
+ unified_inventory.registered_categories[category_name].label = label
+ update_category_list()
+end
+function unified_inventory.set_category_index(category_name, index)
+ ensure_category_exists(category_name)
+ unified_inventory.registered_categories[category_name].index = index
+ update_category_list()
+end
+function unified_inventory.add_category_item(category_name, item)
+ ensure_category_exists(category_name)
+ unified_inventory.registered_category_items[category_name][item] = true
+end
+function unified_inventory.add_category_items(category_name, items)
+ for _,item in ipairs(items) do
+ unified_inventory.add_category_item(category_name, item)
+ end
+end
+
+function unified_inventory.remove_category_item(category_name, item)
+ unified_inventory.registered_category_items[category_name][item] = nil
+end
+function unified_inventory.remove_category(category_name)
+ unified_inventory.registered_categories[category_name] = nil
+ unified_inventory.registered_category_items[category_name] = nil
+ update_category_list()
+end
+
+function unified_inventory.find_category(item)
+ -- Returns the first category the item exists in
+ -- Best for checking if an item has any category at all
+ for category, items in pairs(unified_inventory.registered_category_items) do
+ if items[item] then return category end
+ end
+end
+function unified_inventory.find_categories(item)
+ -- Returns all the categories the item exists in
+ -- Best for listing all categories
+ local categories = {}
+ for category, items in pairs(unified_inventory.registered_category_items) do
+ if items[item] then
+ table.insert(categories, category)
+ end
+ end
+ return categories
+end
diff --git a/unified_inventory/default-categories.lua b/unified_inventory/default-categories.lua
new file mode 100644
index 0000000..57d3e88
--- /dev/null
+++ b/unified_inventory/default-categories.lua
@@ -0,0 +1,704 @@
+local S = minetest.get_translator("unified_inventory")
+
+unified_inventory.register_category('plants', {
+ symbol = "flowers:tulip",
+ label = S("Plant Life")
+})
+unified_inventory.register_category('building', {
+ symbol = "default:brick",
+ label = S("Building Materials")
+})
+unified_inventory.register_category('tools', {
+ symbol = "default:pick_diamond",
+ label = S("Tools")
+})
+unified_inventory.register_category('minerals', {
+ symbol = "default:iron_lump",
+ label = S("Minerals and Metals")
+})
+unified_inventory.register_category('environment', {
+ symbol = "default:dirt_with_grass",
+ label = S("Environment and Worldgen")
+})
+unified_inventory.register_category('lighting', {
+ symbol = "default:torch",
+ label = S("Lighting")
+})
+
+
+if unified_inventory.automatic_categorization then
+ minetest.register_on_mods_loaded(function()
+
+ -- Add biome nodes to environment category
+ for _,def in pairs(minetest.registered_biomes) do
+ local env_nodes = {
+ def.node_riverbed, def.node_top, def.node_filler, def.node_dust,
+ }
+ for i,node in pairs(env_nodes) do
+ if node then
+ unified_inventory.add_category_item('environment', node)
+ end
+ end
+ end
+
+ -- Add minable ores to minerals and everything else (pockets of stone & sand variations) to environment
+ for _,item in pairs(minetest.registered_ores) do
+ if item.ore_type == "scatter" then
+ local drop = minetest.registered_nodes[item.ore].drop
+ if drop and drop ~= "" then
+ unified_inventory.add_category_item('minerals', item.ore)
+ unified_inventory.add_category_item('minerals', drop)
+ else
+ unified_inventory.add_category_item('environment', item.ore)
+ end
+ else
+ unified_inventory.add_category_item('environment', item.ore)
+ end
+ end
+
+ -- Add items by item definition
+ for name, def in pairs(minetest.registered_items) do
+ local group = def.groups or {}
+ if not group.not_in_creative_inventory then
+ if group.stair or
+ group.slab or
+ group.wall or
+ group.fence then
+ unified_inventory.add_category_item('building', name)
+ elseif group.flora or
+ group.flower or
+ group.seed or
+ group.leaves or
+ group.sapling or
+ group.tree then
+ unified_inventory.add_category_item('plants', name)
+ elseif def.type == 'tool' then
+ unified_inventory.add_category_item('tools', name)
+ elseif def.liquidtype == 'source' then
+ unified_inventory.add_category_item('environment', name)
+ elseif def.light_source and def.light_source > 0 then
+ unified_inventory.add_category_item('lighting', name)
+ elseif group.door or
+ minetest.global_exists("doors") and (
+ doors.registered_doors and doors.registered_doors[name..'_a'] or
+ doors.registered_trapdoors and doors.registered_trapdoors[name]
+ ) then
+ unified_inventory.add_category_item('building', name)
+ end
+ end
+ end
+ end)
+end
+
+-- [[
+unified_inventory.add_category_items('plants', {
+ "default:dry_grass_5",
+ "default:acacia_sapling",
+ "default:blueberry_bush_sapling",
+ "default:grass_2",
+ "default:pine_bush_stem",
+ "default:leaves",
+ "default:pine_needles",
+ "default:cactus",
+ "default:junglegrass",
+ "default:pine_sapling",
+ "default:sapling",
+ "default:bush_stem",
+ "default:dry_grass_2",
+ "default:fern_1",
+ "default:grass_3",
+ "default:marram_grass_1",
+ "default:pine_tree",
+ "default:dry_grass_3",
+ "default:dry_shrub",
+ "default:grass_4",
+ "default:marram_grass_2",
+ "default:jungleleaves",
+ "default:apple",
+ "default:tree",
+ "default:aspen_tree",
+ "default:bush_sapling",
+ "default:grass_5",
+ "default:blueberry_bush_leaves_with_berries",
+ "default:acacia_bush_sapling",
+ "default:grass_1",
+ "default:aspen_leaves",
+ "default:marram_grass_3",
+ "default:large_cactus_seedling",
+ "default:junglesapling",
+ "default:dry_grass_4",
+ "default:acacia_bush_stem",
+ "default:papyrus",
+ "default:pine_bush_needles",
+ "default:bush_leaves",
+ "default:fern_3",
+ "default:aspen_sapling",
+ "default:acacia_tree",
+ "default:apple_mark",
+ "default:acacia_leaves",
+ "default:jungletree",
+ "default:dry_grass_1",
+ "default:acacia_bush_leaves",
+ "default:emergent_jungle_sapling",
+ "default:fern_2",
+ "default:blueberries",
+ "default:sand_with_kelp",
+ "default:blueberry_bush_leaves",
+ "default:pine_bush_sapling",
+
+ "farming:cotton",
+ "farming:cotton_1",
+ "farming:cotton_2",
+ "farming:cotton_3",
+ "farming:cotton_4",
+ "farming:cotton_5",
+ "farming:cotton_6",
+ "farming:cotton_7",
+ "farming:cotton_8",
+ "farming:cotton_wild",
+ "farming:seed_cotton",
+ "farming:seed_wheat",
+ "farming:straw",
+ "farming:wheat",
+ "farming:wheat_1",
+ "farming:wheat_2",
+ "farming:wheat_3",
+ "farming:wheat_4",
+ "farming:wheat_5",
+ "farming:wheat_6",
+ "farming:wheat_7",
+ "farming:wheat_8",
+
+ "flowers:chrysanthemum_green",
+ "flowers:dandelion_white",
+ "flowers:dandelion_yellow",
+ "flowers:geranium",
+ "flowers:mushroom_brown",
+ "flowers:mushroom_red",
+ "flowers:rose",
+ "flowers:tulip",
+ "flowers:tulip_black",
+ "flowers:viola",
+ "flowers:waterlily",
+ "flowers:waterlily_waving",
+})
+
+unified_inventory.add_category_items('tools', {
+ "default:sword_diamond",
+ "default:axe_diamond",
+ "default:shovel_diamond",
+ "default:axe_steel",
+ "default:shovel_mese",
+ "default:sword_wood",
+ "default:pick_bronze",
+ "default:axe_stone",
+ "default:sword_stone",
+ "default:pick_stone",
+ "default:shovel_stone",
+ "default:sword_mese",
+ "default:shovel_bronze",
+ "default:sword_bronze",
+ "default:axe_bronze",
+ "default:shovel_steel",
+ "default:sword_steel",
+ "default:axe_mese",
+ "default:shovel_wood",
+ "default:pick_mese",
+ "default:axe_wood",
+ "default:pick_diamond",
+ "default:pick_wood",
+ "default:pick_steel",
+
+ "farming:hoe_bronze",
+ "farming:hoe_diamond",
+ "farming:hoe_mese",
+ "farming:hoe_steel",
+ "farming:hoe_stone",
+ "farming:hoe_wood",
+
+ "fire:flint_and_steel",
+ "map:mapping_kit",
+ "screwdriver:screwdriver",
+
+ "fireflies:bug_net",
+ "bucket:bucket_empty",
+
+ "binoculars:binoculars",
+ "default:skeleton_key",
+})
+
+unified_inventory.add_category_items('minerals', {
+ "default:stone_with_copper",
+ "default:stone_with_gold",
+ "default:stone_with_iron",
+ "default:copper_ingot",
+ "default:copper_lump",
+ "default:gold_lump",
+ "default:diamondblock",
+ "default:stone_with_diamond",
+ "default:stone_with_mese",
+ "default:steel_ingot",
+ "default:gold_ingot",
+ "default:iron_lump",
+ "default:tinblock",
+ "default:tin_lump",
+ "default:stone_with_tin",
+ "default:mese_crystal",
+ "default:diamond",
+ "default:bronze_ingot",
+ "default:mese",
+ "default:mese_crystal_fragment",
+ "default:copperblock",
+ "default:stone_with_coal",
+ "default:steelblock",
+ "default:tin_ingot",
+ "default:coalblock",
+ "default:coal_lump",
+ "default:bronzeblock",
+ "default:goldblock",
+
+ "stairs:slab_bronzeblock",
+ "stairs:slab_copperblock",
+ "stairs:slab_steelblock",
+ "stairs:slab_tinblock",
+ "stairs:stair_bronzeblock",
+ "stairs:stair_copperblock",
+ "stairs:stair_inner_bronzeblock",
+ "stairs:stair_inner_copperblock",
+ "stairs:stair_inner_steelblock",
+ "stairs:stair_inner_tinblock",
+ "stairs:stair_outer_bronzeblock",
+ "stairs:stair_outer_copperblock",
+ "stairs:stair_outer_steelblock",
+ "stairs:stair_outer_tinblock",
+ "stairs:stair_steelblock",
+ "stairs:stair_tinblock",
+})
+
+unified_inventory.add_category_items('building', {
+ "default:fence_rail_aspen_wood",
+ "default:fence_rail_acacia_wood",
+ "default:fence_junglewood",
+ "default:fence_rail_junglewood",
+ "default:fence_aspen_wood",
+ "default:fence_pine_wood",
+ "default:fence_rail_wood",
+ "default:fence_rail_pine_wood",
+ "default:fence_acacia_wood",
+ "default:junglewood",
+ "default:acacia_wood",
+ "default:aspen_wood",
+ "default:fence_wood",
+ "default:pine_wood",
+ "default:silver_sandstone",
+ "default:desert_sandstone",
+ "default:sandstone_block",
+ "default:desert_sandstone_brick",
+ "default:stone_block",
+ "default:stonebrick",
+ "default:obsidian_glass",
+ "default:desert_sandstone_block",
+ "default:silver_sandstone_brick",
+ "default:brick",
+ "default:obsidianbrick",
+ "default:sandstonebrick",
+ "default:sandstone",
+ "default:desert_stone_block",
+ "default:silver_sandstone_block",
+ "default:wood",
+ "default:obsidian_block",
+ "default:glass",
+ "default:clay_brick",
+ "default:desert_stonebrick",
+ "default:desert_cobble",
+ "default:cobble",
+ "default:mossycobble",
+
+ "doors:door_glass",
+ "doors:door_glass_a",
+ "doors:door_glass_b",
+ "doors:door_glass_c",
+ "doors:door_glass_d",
+ "doors:door_obsidian_glass",
+ "doors:door_obsidian_glass_a",
+ "doors:door_obsidian_glass_b",
+ "doors:door_obsidian_glass_c",
+ "doors:door_obsidian_glass_d",
+ "doors:door_steel",
+ "doors:door_steel_a",
+ "doors:door_steel_b",
+ "doors:door_steel_c",
+ "doors:door_steel_d",
+ "doors:door_wood",
+ "doors:door_wood_a",
+ "doors:door_wood_b",
+ "doors:door_wood_c",
+ "doors:door_wood_d",
+ "doors:gate_acacia_wood_closed",
+ "doors:gate_acacia_wood_open",
+ "doors:gate_aspen_wood_closed",
+ "doors:gate_aspen_wood_open",
+ "doors:gate_junglewood_closed",
+ "doors:gate_junglewood_open",
+ "doors:gate_pine_wood_closed",
+ "doors:gate_pine_wood_open",
+ "doors:gate_wood_closed",
+ "doors:gate_wood_open",
+ "doors:hidden",
+ "doors:trapdoor",
+ "doors:trapdoor_open",
+ "doors:trapdoor_steel",
+ "doors:trapdoor_steel_open",
+
+ "stairs:slab_bronzeblock",
+ "stairs:slab_copperblock",
+ "stairs:slab_steelblock",
+ "stairs:slab_tinblock",
+ "stairs:stair_bronzeblock",
+ "stairs:stair_copperblock",
+ "stairs:stair_inner_bronzeblock",
+ "stairs:stair_inner_copperblock",
+ "stairs:stair_inner_steelblock",
+ "stairs:stair_inner_tinblock",
+ "stairs:stair_outer_bronzeblock",
+ "stairs:stair_outer_copperblock",
+ "stairs:stair_outer_steelblock",
+ "stairs:stair_outer_tinblock",
+ "stairs:stair_steelblock",
+ "stairs:stair_tinblock",
+
+ "stairs:slab_acacia_wood",
+ "stairs:slab_aspen_wood",
+ "stairs:slab_brick",
+ "stairs:slab_cobble",
+ "stairs:slab_desert_cobble",
+ "stairs:slab_desert_sandstone",
+ "stairs:slab_desert_sandstone_block",
+ "stairs:slab_desert_sandstone_brick",
+ "stairs:slab_desert_stone",
+ "stairs:slab_desert_stone_block",
+ "stairs:slab_desert_stonebrick",
+ "stairs:slab_glass",
+ "stairs:slab_goldblock",
+ "stairs:slab_ice",
+ "stairs:slab_junglewood",
+ "stairs:slab_mossycobble",
+ "stairs:slab_obsidian",
+ "stairs:slab_obsidian_block",
+ "stairs:slab_obsidian_glass",
+ "stairs:slab_obsidianbrick",
+ "stairs:slab_pine_wood",
+ "stairs:slab_sandstone",
+ "stairs:slab_sandstone_block",
+ "stairs:slab_sandstonebrick",
+ "stairs:slab_silver_sandstone",
+ "stairs:slab_silver_sandstone_block",
+ "stairs:slab_silver_sandstone_brick",
+ "stairs:slab_snowblock",
+ "stairs:slab_stone",
+ "stairs:slab_stone_block",
+ "stairs:slab_stonebrick",
+ "stairs:slab_straw",
+ "stairs:slab_wood",
+ "stairs:stair_acacia_wood",
+ "stairs:stair_aspen_wood",
+ "stairs:stair_brick",
+ "stairs:stair_cobble",
+ "stairs:stair_desert_cobble",
+ "stairs:stair_desert_sandstone",
+ "stairs:stair_desert_sandstone_block",
+ "stairs:stair_desert_sandstone_brick",
+ "stairs:stair_desert_stone",
+ "stairs:stair_desert_stone_block",
+ "stairs:stair_desert_stonebrick",
+ "stairs:stair_glass",
+ "stairs:stair_goldblock",
+ "stairs:stair_ice",
+ "stairs:stair_inner_acacia_wood",
+ "stairs:stair_inner_aspen_wood",
+ "stairs:stair_inner_brick",
+ "stairs:stair_inner_cobble",
+ "stairs:stair_inner_desert_cobble",
+ "stairs:stair_inner_desert_sandstone",
+ "stairs:stair_inner_desert_sandstone_block",
+ "stairs:stair_inner_desert_sandstone_brick",
+ "stairs:stair_inner_desert_stone",
+ "stairs:stair_inner_desert_stone_block",
+ "stairs:stair_inner_desert_stonebrick",
+ "stairs:stair_inner_glass",
+ "stairs:stair_inner_goldblock",
+ "stairs:stair_inner_ice",
+ "stairs:stair_inner_junglewood",
+ "stairs:stair_inner_mossycobble",
+ "stairs:stair_inner_obsidian",
+ "stairs:stair_inner_obsidian_block",
+ "stairs:stair_inner_obsidian_glass",
+ "stairs:stair_inner_obsidianbrick",
+ "stairs:stair_inner_pine_wood",
+ "stairs:stair_inner_sandstone",
+ "stairs:stair_inner_sandstone_block",
+ "stairs:stair_inner_sandstonebrick",
+ "stairs:stair_inner_silver_sandstone",
+ "stairs:stair_inner_silver_sandstone_block",
+ "stairs:stair_inner_silver_sandstone_brick",
+ "stairs:stair_inner_snowblock",
+ "stairs:stair_inner_stone",
+ "stairs:stair_inner_stone_block",
+ "stairs:stair_inner_stonebrick",
+ "stairs:stair_inner_straw",
+ "stairs:stair_inner_wood",
+ "stairs:stair_junglewood",
+ "stairs:stair_mossycobble",
+ "stairs:stair_obsidian",
+ "stairs:stair_obsidian_block",
+ "stairs:stair_obsidian_glass",
+ "stairs:stair_obsidianbrick",
+ "stairs:stair_outer_acacia_wood",
+ "stairs:stair_outer_aspen_wood",
+ "stairs:stair_outer_brick",
+ "stairs:stair_outer_cobble",
+ "stairs:stair_outer_desert_cobble",
+ "stairs:stair_outer_desert_sandstone",
+ "stairs:stair_outer_desert_sandstone_block",
+ "stairs:stair_outer_desert_sandstone_brick",
+ "stairs:stair_outer_desert_stone",
+ "stairs:stair_outer_desert_stone_block",
+ "stairs:stair_outer_desert_stonebrick",
+ "stairs:stair_outer_glass",
+ "stairs:stair_outer_goldblock",
+ "stairs:stair_outer_ice",
+ "stairs:stair_outer_junglewood",
+ "stairs:stair_outer_mossycobble",
+ "stairs:stair_outer_obsidian",
+ "stairs:stair_outer_obsidian_block",
+ "stairs:stair_outer_obsidian_glass",
+ "stairs:stair_outer_obsidianbrick",
+ "stairs:stair_outer_pine_wood",
+ "stairs:stair_outer_sandstone",
+ "stairs:stair_outer_sandstone_block",
+ "stairs:stair_outer_sandstonebrick",
+ "stairs:stair_outer_silver_sandstone",
+ "stairs:stair_outer_silver_sandstone_block",
+ "stairs:stair_outer_silver_sandstone_brick",
+ "stairs:stair_outer_snowblock",
+ "stairs:stair_outer_stone",
+ "stairs:stair_outer_stone_block",
+ "stairs:stair_outer_stonebrick",
+ "stairs:stair_outer_straw",
+ "stairs:stair_outer_wood",
+ "stairs:stair_pine_wood",
+ "stairs:stair_sandstone",
+ "stairs:stair_sandstone_block",
+ "stairs:stair_sandstonebrick",
+ "stairs:stair_silver_sandstone",
+ "stairs:stair_silver_sandstone_block",
+ "stairs:stair_silver_sandstone_brick",
+ "stairs:stair_snowblock",
+ "stairs:stair_stone",
+ "stairs:stair_stone_block",
+ "stairs:stair_stonebrick",
+ "stairs:stair_straw",
+ "stairs:stair_wood",
+
+ "xpanes:bar",
+ "xpanes:bar_flat",
+ "xpanes:door_steel_bar",
+ "xpanes:door_steel_bar_a",
+ "xpanes:door_steel_bar_b",
+ "xpanes:door_steel_bar_c",
+ "xpanes:door_steel_bar_d",
+ "xpanes:obsidian_pane",
+ "xpanes:obsidian_pane_flat",
+ "xpanes:pane",
+ "xpanes:pane_flat",
+ "xpanes:trapdoor_steel_bar",
+ "xpanes:trapdoor_steel_bar_open",
+
+ "walls:cobble",
+ "walls:desertcobble",
+ "walls:mossycobble",
+})
+
+unified_inventory.add_category_items('environment', {
+ "air",
+ "default:cave_ice",
+ "default:dirt_with_rainforest_litter",
+ "default:gravel",
+ "default:dry_dirt_with_dry_grass",
+ "default:permafrost",
+ "default:desert_stone",
+ "default:ice",
+ "default:dry_dirt",
+ "default:obsidian",
+ "default:sand",
+ "default:river_water_source",
+ "default:dirt_with_snow",
+ "default:dirt_with_grass",
+ "default:water_flowing",
+ "default:dirt",
+ "default:desert_sand",
+ "default:permafrost_with_moss",
+ "default:dirt_with_coniferous_litter",
+ "default:water_source",
+ "default:dirt_with_dry_grass",
+ "default:river_water_flowing",
+ "default:stone",
+ "default:snow",
+ "default:lava_flowing",
+ "default:lava_source",
+ "default:permafrost_with_stones",
+ "default:dirt_with_grass_footsteps",
+ "default:silver_sand",
+ "default:snowblock",
+ "default:clay",
+
+ "farming:desert_sand_soil",
+ "farming:desert_sand_soil_wet",
+ "farming:dry_soil",
+ "farming:dry_soil_wet",
+ "farming:soil",
+ "farming:soil_wet",
+})
+
+unified_inventory.add_category_items('lighting', {
+ "default:mese_post_light_junglewood",
+ "default:torch_ceiling",
+ "default:meselamp",
+ "default:torch",
+ "default:mese_post_light_acacia_wood",
+ "default:mese_post_light",
+ "default:torch_wall",
+ "default:mese_post_light_pine_wood",
+ "default:mese_post_light_aspen_wood"
+})
+--]]
+
+
+--[[ UNCATEGORISED
+
+ "farming:string",
+
+ "beds:bed_bottom",
+ "beds:bed_top",
+ "beds:fancy_bed_bottom",
+ "beds:fancy_bed_top",
+ "boats:boat",
+ "bones:bones",
+
+ "bucket:bucket_lava",
+ "bucket:bucket_river_water",
+ "bucket:bucket_water",
+
+ "butterflies:butterfly_red",
+ "butterflies:butterfly_violet",
+ "butterflies:butterfly_white",
+ "butterflies:hidden_butterfly_red",
+ "butterflies:hidden_butterfly_violet",
+ "butterflies:hidden_butterfly_white",
+
+ "carts:brakerail",
+ "carts:cart",
+ "carts:powerrail",
+ "carts:rail",
+
+ "default:book",
+ "default:book_written",
+ "default:bookshelf",
+ "default:chest",
+ "default:chest_locked",
+ "default:chest_locked_open",
+ "default:chest_open",
+ "default:clay_lump",
+ "default:cloud",
+ "default:coral_brown",
+ "default:coral_cyan",
+ "default:coral_green",
+ "default:coral_orange",
+ "default:coral_pink",
+ "default:coral_skeleton",
+ "default:flint",
+ "default:furnace",
+ "default:furnace_active",
+ "default:key",
+ "default:ladder_steel",
+ "default:ladder_wood",
+ "default:obsidian_shard",
+ "default:paper",
+ "default:sign_wall_steel",
+ "default:sign_wall_wood",
+ "default:stick",
+
+ "fire:basic_flame",
+ "fire:permanent_flame",
+ "fireflies:firefly",
+ "fireflies:firefly_bottle",
+ "fireflies:hidden_firefly",
+
+ "ignore",
+ "unknown",
+
+ "tnt:boom",
+ "tnt:gunpowder",
+ "tnt:gunpowder_burning",
+ "tnt:tnt",
+ "tnt:tnt_burning",
+ "tnt:tnt_stick",
+
+ "vessels:drinking_glass",
+ "vessels:glass_bottle",
+ "vessels:glass_fragments",
+ "vessels:shelf",
+ "vessels:steel_bottle",
+
+ "dye:black",
+ "dye:blue",
+ "dye:brown",
+ "dye:cyan",
+ "dye:dark_green",
+ "dye:dark_grey",
+ "dye:green",
+ "dye:grey",
+ "dye:magenta",
+ "dye:orange",
+ "dye:pink",
+ "dye:red",
+ "dye:violet",
+ "dye:white",
+ "dye:yellow",
+
+ "wool:black",
+ "wool:blue",
+ "wool:brown",
+ "wool:cyan",
+ "wool:dark_green",
+ "wool:dark_grey",
+ "wool:green",
+ "wool:grey",
+ "wool:magenta",
+ "wool:orange",
+ "wool:pink",
+ "wool:red",
+ "wool:violet",
+ "wool:white",
+ "wool:yellow",
+
+ "unified_inventory:bag_large",
+ "unified_inventory:bag_medium",
+ "unified_inventory:bag_small",
+--]]
+
+--[[ LIST UNCATEGORIZED AFTER LOAD
+minetest.register_on_mods_loaded(function()
+ minetest.after(1, function ( )
+ local l = {}
+ for name,_ in pairs(minetest.registered_items) do
+ if not unified_inventory.find_category(name) then
+ -- minetest.log("error", minetest.serialize(minetest.registered_items[name]))
+ table.insert(l, name)
+ end
+ end
+ table.sort(l)
+ minetest.log(table.concat(l, '",'.."\n"..'"'))
+ end)
+end)
+--]]
\ No newline at end of file
diff --git a/unified_inventory/doc/mod_api.txt b/unified_inventory/doc/mod_api.txt
index c0be129..ef87697 100644
--- a/unified_inventory/doc/mod_api.txt
+++ b/unified_inventory/doc/mod_api.txt
@@ -3,6 +3,14 @@ unified_inventory API
This file provides information about the API of unified_inventory.
+API revisions within unified_inventory can be checked using:
+
+ (unified_inventory.version or 1)
+
+**Revision history**
+
+* Version `1`: Classic formspec layout (no real_coordinates)
+* Version `2`: Force formspec version 4 (includes real_coordinates)
Misc functions
--------------
@@ -12,6 +20,64 @@ Grouped by use-case, afterwards sorted alphabetically.
* Checks whether creative is enabled or the player has `creative`
+Callbacks
+---------
+
+Register a callback that will be run whenever a craft is registered via unified_inventory.register_craft:
+
+ unified_inventory.register_on_craft_registered(
+ function (item_name, options)
+ -- item_name (string): name of the output item, equivalent to `ItemStack:get_name()`
+ -- options (table): definition table of crafts registered by `unified_inventory.register_craft`
+ end
+ )
+
+Register a callback that will be run after all mods have loaded and after the unified_inventory mod has initialised all its internal structures:
+
+ unified_inventory.register_on_initialized(callback)
+ -- The callback is passed no arguments
+
+
+Accessing Data
+--------------
+
+These methods should be used instead of accessing the unified_inventory data structures directly - this will ensure your code survives any potential restructuring of the mod.
+
+Get a list of recipes for a particular output item:
+
+ unified_inventory.get_recipe_list(output_item)
+
+ Returns a list of tables, each holding a recipe definition, like:
+ {
+ {
+ type = "normal",
+ items = { "default:stick", "default:stick", "default:stick", "default:stick" },
+ output = "default:wood",
+ width = 2
+ },
+ {
+ type = "shapeless",
+ items = { "default:tree" },
+ output = "default:wood 4",
+ width = 0
+ },
+ ...
+ }
+
+Get a list of all the output items crafts have been registered for:
+
+ unified_inventory.get_registered_outputs()
+
+ Returns a list of item names, like:
+ {
+ "default:stone",
+ "default:chest",
+ "default:brick",
+ "doors:door_wood",
+ ...
+ }
+
+
Pages
-----
@@ -93,3 +159,72 @@ Register a non-standard craft recipe:
-- ^ Same as `minetest.register_recipe`
})
+
+Categories
+----------
+
+Register a new category:
+ The config table (second argument) is optional, and all its members are optional
+ See the unified_inventory.set_category_* functions for more details on the members of the config table
+
+ unified_inventory.register_category("category_name", {
+ symbol = "mod_name:item_name" or "texture.png",
+ label = "Human Readable Label",
+ index = 5,
+ items = {
+ "mod_name:item_name",
+ "another_mod:different_item"
+ }
+ })
+
+Add / override the symbol for a category:
+ The category does not need to exist first
+ The symbol can be an item name or a texture image
+ If unset this will default to "default:stick"
+
+ unified_inventory.set_category_symbol("category_name", "mod_name:item_name" or "texture.png")
+
+Add / override the human readable label for a category:
+ If unset this will default to the category name
+
+ unified_inventory.set_category_label("category_name", "Human Readable Label")
+
+Add / override the sorting index of the category:
+ Must be a number, can also be negative (-5) or fractional (2.345)
+ This determines the position the category appears in the list of categories
+ The "all" meta-category has index -2, the "misc"/"uncategorized" meta-category has index -1, use a negative number smaller than these to make a category appear before these in the list
+ By default categories are sorted alphabetically with an index between 0.0101(AA) and 0.2626(ZZ)
+
+ unified_inventory.set_category_index("category_name", 5)
+
+Add a single item to a category:
+
+ unified_inventory.add_category_item("category_name", "mod_name:item_name")
+
+Add multiple items to a category:
+
+ unified_inventory.add_category_items("category_name", {
+ "mod_name:item_name",
+ "another_mod:different_item"
+ })
+
+Remove an item from a category:
+
+ unified_inventory.remove_category_item("category_name", "mod_name:item_name")
+
+Remove a category entirely:
+
+ unified_inventory.remove_category("category_name")
+
+Finding existing items in categories:
+ This will find the first category an item exists in
+ It should be used for checking if an item is catgorised
+ Returns "category_name" or nil
+
+ unified_inventory.find_category("mod_name:item_name")
+
+
+ This will find all the categories an item exists in
+ Returns a number indexed table (list) of category names
+
+ unified_inventory.find_categories("mod_name:item_name")
diff --git a/unified_inventory/init.lua b/unified_inventory/init.lua
index 7be101c..98ee2e5 100644
--- a/unified_inventory/init.lua
+++ b/unified_inventory/init.lua
@@ -1,4 +1,4 @@
--- Unified Inventory for Minetest >= 0.4.16
+-- Unified Inventory
local modpath = minetest.get_modpath(minetest.get_current_modname())
local worldpath = minetest.get_worldpath()
@@ -10,6 +10,8 @@ unified_inventory = {
alternate = {},
current_page = {},
current_searchbox = {},
+ current_category = {},
+ current_category_scroll = {},
current_index = {},
current_item = {},
current_craft_direction = {},
@@ -22,6 +24,8 @@ unified_inventory = {
filtered_items_list = {},
pages = {},
buttons = {},
+ initialized_callbacks = {},
+ craft_registered_callbacks = {},
-- Homepos stuff
home_pos = {},
@@ -33,23 +37,111 @@ unified_inventory = {
-- "Lite" mode
lite_mode = minetest.settings:get_bool("unified_inventory_lite"),
+ -- Items automatically added to categories based on item definitions
+ automatic_categorization = (minetest.settings:get_bool("unified_inventory_automatic_categorization") ~= false),
+
-- Trash enabled
trash_enabled = (minetest.settings:get_bool("unified_inventory_trash") ~= false),
+ imgscale = 1.25,
+ list_img_offset = 0.13,
+ standard_background = "background9[0,0;1,1;ui_formbg_9_sliced.png;true;16]",
- pagecols = 8,
- pagerows = 10,
- page_y = 0,
- formspec_y = 1,
- main_button_x = 0,
- main_button_y = 9,
- craft_result_x = 0.3,
- craft_result_y = 0.5,
- form_header_y = 0,
- standard_background = "background[-0.2,-0.2;1,1;ui_form_bg.png;true]", -- the 'true' scales to fill, overrides the 1,1
- standard_inv = "list[current_player;main;0,YYY;8,4;]", -- the YYY's are placeholders which get
- standard_inv_bg = "image[-0.1,YYY;10.05,4.70;ui_main_inventory.png]", -- replaced later by string.gsub()
+ version = 3
}
+local ui = unified_inventory
+
+-- These tables establish position and layout for the two UI styles.
+-- UI doesn't use formspec_[xy] anymore, but other mods may need them.
+
+ui.style_full = {
+ formspec_x = 1,
+ formspec_y = 1,
+ formw = 17.75,
+ formh = 12.25,
+ pagecols = 8,
+ pagerows = 9,
+ page_x = 10.75,
+ page_y = 2.30,
+ craft_x = 2.8,
+ craft_y = 1.15,
+ craftresult_x = 7.8,
+ craft_arrow_x = 6.55,
+ craft_guide_x = 3.3,
+ craft_guide_y = 1.15,
+ craft_guide_arrow_x = 7.05,
+ craft_guide_result_x = 8.3,
+ craft_guide_resultstr_x = 0.3,
+ craft_guide_resultstr_y = 0.6,
+ give_btn_x = 0.25,
+ main_button_x = 0.4,
+ main_button_y = 11.0,
+ page_buttons_x = 11.60,
+ page_buttons_y = 10.15,
+ searchwidth = 3.4,
+ form_header_x = 0.4,
+ form_header_y = 0.4,
+ btn_spc = 0.85,
+ btn_size = 0.75,
+ std_inv_x = 0.3,
+ std_inv_y = 5.75,
+}
+
+ui.style_lite = {
+ formspec_x = 0.6,
+ formspec_y = 0.6,
+ formw = 14,
+ formh = 9.75,
+ pagecols = 4,
+ pagerows = 5,
+ page_x = 10.5,
+ page_y = 2.15,
+ craft_x = 2.6,
+ craft_y = 0.75,
+ craftresult_x = 5.75,
+ craft_arrow_x = 6.35,
+ craft_guide_x = 3.1,
+ craft_guide_y = 0.75,
+ craft_guide_arrow_x = 7.05,
+ craft_guide_result_x = 8.3,
+ craft_guide_resultstr_x = 0.15,
+ craft_guide_resultstr_y = 0.35,
+ give_btn_x = 0.15,
+ main_button_x = 10.5,
+ main_button_y = 8.15,
+ page_buttons_x = 10.5,
+ page_buttons_y = 6.15,
+ searchwidth = 1.6,
+ form_header_x = 0.2,
+ form_header_y = 0.2,
+ btn_spc = 0.8,
+ btn_size = 0.7,
+ std_inv_x = 0.1,
+ std_inv_y = 4.6,
+}
+
+dofile(modpath.."/api.lua")
+
+for _, style in ipairs({ui.style_full, ui.style_lite}) do
+ style.items_per_page = style.pagecols * style.pagerows
+ style.standard_inv = string.format("list[current_player;main;%f,%f;8,4;]",
+ style.std_inv_x + ui.list_img_offset, style.std_inv_y + ui.list_img_offset)
+
+ style.standard_inv_bg = ui.make_inv_img_grid(style.std_inv_x, style.std_inv_y, 8, 1, true)..
+ ui.make_inv_img_grid(style.std_inv_x, style.std_inv_y + ui.imgscale, 8, 3)
+
+ style.craft_grid = table.concat({
+ ui.make_inv_img_grid(style.craft_x, style.craft_y, 3, 3),
+ ui.single_slot(style.craft_x + ui.imgscale*4, style.craft_y), -- the craft result slot
+ string.format("image[%f,%f;%f,%f;ui_crafting_arrow.png]",
+ style.craft_arrow_x, style.craft_y, ui.imgscale, ui.imgscale),
+ string.format("list[current_player;craft;%f,%f;3,3;]",
+ style.craft_x + ui.list_img_offset, style.craft_y + ui.list_img_offset),
+ string.format("list[current_player;craftpreview;%f,%f;1,1;]",
+ style.craftresult_x + ui.list_img_offset, style.craft_y + ui.list_img_offset)
+ })
+end
+
-- Disable default creative inventory
local creative = rawget(_G, "creative") or rawget(_G, "creative_inventory")
if creative then
@@ -65,7 +157,8 @@ if sfinv then
end
dofile(modpath.."/group.lua")
-dofile(modpath.."/api.lua")
+dofile(modpath.."/category.lua")
+dofile(modpath.."/default-categories.lua")
dofile(modpath.."/internal.lua")
dofile(modpath.."/callbacks.lua")
dofile(modpath.."/match_craft.lua")
@@ -76,7 +169,4 @@ if minetest.settings:get_bool("unified_inventory_bags") ~= false then
end
dofile(modpath.."/item_names.lua")
-
-if minetest.get_modpath("datastorage") then
- dofile(modpath.."/waypoints.lua")
-end
+dofile(modpath.."/waypoints.lua")
diff --git a/unified_inventory/internal.lua b/unified_inventory/internal.lua
index 78cba2a..b49906e 100644
--- a/unified_inventory/internal.lua
+++ b/unified_inventory/internal.lua
@@ -1,5 +1,6 @@
local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape
+local ui = unified_inventory
-- This pair of encoding functions is used where variable text must go in
-- button names, where the text might contain formspec metacharacters.
@@ -9,269 +10,310 @@ local F = minetest.formspec_escape
-- This is a game engine bug, and in the anticipation that it might be
-- fixed some day we don't want to rely on it. So for safety we apply
-- an encoding that avoids all formspec metacharacters.
-function unified_inventory.mangle_for_formspec(str)
+
+function ui.mangle_for_formspec(str)
return string.gsub(str, "([^A-Za-z0-9])", function (c) return string.format("_%d_", string.byte(c)) end)
end
-function unified_inventory.demangle_for_formspec(str)
+function ui.demangle_for_formspec(str)
return string.gsub(str, "_([0-9]+)_", function (v) return string.char(v) end)
end
-function unified_inventory.get_per_player_formspec(player_name)
- local lite = unified_inventory.lite_mode and not minetest.check_player_privs(player_name, {ui_full=true})
- local ui = {}
- ui.pagecols = unified_inventory.pagecols
- ui.pagerows = unified_inventory.pagerows
- ui.page_y = unified_inventory.page_y
- ui.formspec_y = unified_inventory.formspec_y
- ui.main_button_x = unified_inventory.main_button_x
- ui.main_button_y = unified_inventory.main_button_y
- ui.craft_result_x = unified_inventory.craft_result_x
- ui.craft_result_y = unified_inventory.craft_result_y
- ui.form_header_y = unified_inventory.form_header_y
+function ui.get_per_player_formspec(player_name)
+ local draw_lite_mode = ui.lite_mode and not minetest.check_player_privs(player_name, {ui_full=true})
- if lite then
- ui.pagecols = 4
- ui.pagerows = 6
- ui.page_y = 0.25
- ui.formspec_y = 0.47
- ui.main_button_x = 8.2
- ui.main_button_y = 6.5
- ui.craft_result_x = 2.8
- ui.craft_result_y = 3.4
- ui.form_header_y = -0.1
- end
-
- ui.items_per_page = ui.pagecols * ui.pagerows
- return ui, lite
+ local style = table.copy(draw_lite_mode and ui.style_lite or ui.style_full)
+ style.is_lite_mode = draw_lite_mode
+ return style
end
-function unified_inventory.get_formspec(player, page)
+local function formspec_button(ui_peruser, name, image, offset, pos, scale, label)
+ local element = 'image_button'
+ if minetest.registered_items[image] then
+ element = 'item_image_button'
+ elseif image:find(":", 1, true) then
+ image = "unknown_item.png"
+ end
+ local spc = (1-scale)*ui_peruser.btn_size/2
+ local size = ui_peruser.btn_size*scale
+ return string.format("%s[%f,%f;%f,%f;%s;%s;]", element,
+ (offset.x or offset[1]) + ( ui_peruser.btn_spc * (pos.x or pos[1]) ) + spc,
+ (offset.y or offset[2]) + ( ui_peruser.btn_spc * (pos.y or pos[2]) ) + spc,
+ size, size, image, name) ..
+ string.format("tooltip[%s;%s]", name, F(label or name))
+end
+
+local function formspec_add_filters(player, formspec, style)
+ local button_row = 0
+ local button_col = 0
+ local n = #formspec + 1
+
+ -- Main buttons
+
+ local filtered_inv_buttons = {}
+
+ for i, def in pairs(ui.buttons) do
+ if not (style.is_lite_mode and def.hide_lite) then
+ table.insert(filtered_inv_buttons, def)
+ end
+ end
+
+ for i, def in pairs(filtered_inv_buttons) do
+ if style.is_lite_mode and i > 4 then
+ button_row = 1
+ button_col = 1
+ end
+
+ if def.type == "image" then
+ local pos_x = style.main_button_x + style.btn_spc * (i - 1) - button_col * style.btn_spc * 4
+ local pos_y = style.main_button_y + button_row * style.btn_spc
+ if (def.condition == nil or def.condition(player) == true) then
+ formspec[n] = string.format("image_button[%f,%f;%f,%f;%s;%s;]",
+ pos_x, pos_y, style.btn_size, style.btn_size,
+ F(def.image),
+ F(def.name))
+ formspec[n+1] = "tooltip["..F(def.name)..";"..(def.tooltip or "").."]"
+ n = n+2
+ else
+ formspec[n] = string.format("image[%f,%f;%f,%f;%s^[colorize:#808080:alpha]",
+ pos_x, pos_y, style.btn_size, style.btn_size,
+ def.image)
+ n = n+1
+ end
+ end
+ end
+end
+
+local function formspec_add_categories(player, formspec, ui_peruser)
+ local player_name = player:get_player_name()
+ local n = #formspec + 1
+
+ local categories_pos = {
+ ui_peruser.page_x,
+ ui_peruser.page_y-ui_peruser.btn_spc-0.5
+ }
+ local categories_scroll_pos = {
+ ui_peruser.page_x,
+ ui_peruser.form_header_y - (ui_peruser.is_lite_mode and 0 or 0.2)
+ }
+
+ formspec[n] = string.format("background9[%f,%f;%f,%f;%s;false;3]",
+ ui_peruser.page_x-0.1, categories_scroll_pos[2],
+ (ui_peruser.btn_spc * ui_peruser.pagecols) + 0.13, 1.4 + (ui_peruser.is_lite_mode and 0 or 0.2),
+ "ui_smallbg_9_sliced.png")
+ n = n + 1
+
+ formspec[n] = string.format("label[%f,%f;%s]",
+ ui_peruser.page_x,
+ ui_peruser.form_header_y + (ui_peruser.is_lite_mode and 0.3 or 0.2), F(S("Category:")))
+ n = n + 1
+
+ local scroll_offset = 0
+ local category_count = #ui.category_list
+ if category_count > ui_peruser.pagecols then
+ scroll_offset = ui.current_category_scroll[player_name]
+ end
+
+ for index, category in ipairs(ui.category_list) do
+ local column = index - scroll_offset
+ if column > 0 and column <= ui_peruser.pagecols then
+ local scale = 0.8
+ if ui.current_category[player_name] == category.name then
+ scale = 1
+ end
+ formspec[n] = formspec_button(ui_peruser, "category_"..category.name, category.symbol, categories_pos, {column-1, 0}, scale, category.label)
+ n = n + 1
+ end
+ end
+ if category_count > ui_peruser.pagecols and scroll_offset > 0 then
+ -- prev
+ formspec[n] = formspec_button(ui_peruser, "prev_category", "ui_left_icon.png", categories_scroll_pos, {ui_peruser.pagecols - 2, 0}, 0.8, S("Scroll categories left"))
+ n = n + 1
+ end
+ if category_count > ui_peruser.pagecols and category_count - scroll_offset > ui_peruser.pagecols then
+ -- next
+ formspec[n] = formspec_button(ui_peruser, "next_category", "ui_right_icon.png", categories_scroll_pos, {ui_peruser.pagecols - 1, 0}, 0.8, S("Scroll categories right"))
+ end
+end
+
+local function formspec_add_search_box(player, formspec, ui_peruser)
+ local player_name = player:get_player_name()
+ local n = #formspec + 1
+
+ formspec[n] = "field_close_on_enter[searchbox;false]"
+
+ formspec[n+1] = string.format("field[%f,%f;%f,%f;searchbox;;%s]",
+ ui_peruser.page_buttons_x, ui_peruser.page_buttons_y,
+ ui_peruser.searchwidth - 0.1, ui_peruser.btn_size,
+ F(ui.current_searchbox[player_name]))
+ formspec[n+2] = string.format("image_button[%f,%f;%f,%f;ui_search_icon.png;searchbutton;]",
+ ui_peruser.page_buttons_x + ui_peruser.searchwidth, ui_peruser.page_buttons_y,
+ ui_peruser.btn_size,ui_peruser.btn_size)
+ formspec[n+3] = "tooltip[searchbutton;" ..F(S("Search")) .. "]"
+ formspec[n+4] = string.format("image_button[%f,%f;%f,%f;ui_reset_icon.png;searchresetbutton;]",
+ ui_peruser.page_buttons_x + ui_peruser.searchwidth + ui_peruser.btn_spc,
+ ui_peruser.page_buttons_y,
+ ui_peruser.btn_size, ui_peruser.btn_size)
+ formspec[n+5] = "tooltip[searchresetbutton;"..F(S("Reset search and display everything")).."]"
+
+ if ui.activefilter[player_name] ~= "" then
+ formspec[n+6] = string.format("label[%f,%f;%s: %s]",
+ ui_peruser.page_x, ui_peruser.page_y - 0.25,
+ F(S("Filter")), F(ui.activefilter[player_name]))
+ end
+end
+
+local function formspec_add_item_browser(player, formspec, ui_peruser)
+ local player_name = player:get_player_name()
+ local n = #formspec + 1
+
+ -- Controls to flip items pages
+
+ local btnlist = {
+ { "ui_skip_backward_icon.png", "start_list", S("First page") },
+ { "ui_doubleleft_icon.png", "rewind3", S("Back three pages") },
+ { "ui_left_icon.png", "rewind1", S("Back one page") },
+ { "ui_right_icon.png", "forward1", S("Forward one page") },
+ { "ui_doubleright_icon.png", "forward3", S("Forward three pages") },
+ { "ui_skip_forward_icon.png", "end_list", S("Last page") },
+ }
+
+ if ui_peruser.is_lite_mode then
+ btnlist[2] = nil
+ btnlist[5] = nil
+ end
+
+ local bn = 0
+ for _, b in pairs(btnlist) do
+ formspec[n] = string.format("image_button[%f,%f;%f,%f;%s;%s;]",
+ ui_peruser.page_buttons_x + ui_peruser.btn_spc*bn,
+ ui_peruser.page_buttons_y + ui_peruser.btn_spc,
+ ui_peruser.btn_size, ui_peruser.btn_size,
+ b[1],b[2])
+ formspec[n+1] = "tooltip["..b[2]..";"..F(b[3]).."]"
+ bn = bn + 1
+ n = n + 2
+ end
+
+ -- Items list
+ if #ui.filtered_items_list[player_name] == 0 then
+ local no_matches = S("No matching items")
+ if ui_peruser.is_lite_mode then
+ no_matches = S("No matches.")
+ end
+
+ formspec[n] = "label["..ui_peruser.page_x..","..(ui_peruser.page_y+0.15)..";" .. F(no_matches) .. "]"
+ return
+ end
+
+ local dir = ui.active_search_direction[player_name]
+ local list_index = ui.current_index[player_name]
+ local page2 = math.floor(list_index / (ui_peruser.items_per_page) + 1)
+ local pagemax = math.floor(
+ (#ui.filtered_items_list[player_name] - 1)
+ / (ui_peruser.items_per_page) + 1)
+ for y = 0, ui_peruser.pagerows - 1 do
+ for x = 0, ui_peruser.pagecols - 1 do
+ local name = ui.filtered_items_list[player_name][list_index]
+ local item = minetest.registered_items[name]
+ if item then
+ -- Clicked on current item: Flip crafting direction
+ if name == ui.current_item[player_name] then
+ local cdir = ui.current_craft_direction[player_name]
+ if cdir == "recipe" then
+ dir = "usage"
+ elseif cdir == "usage" then
+ dir = "recipe"
+ end
+ else
+ -- Default: use active search direction by default
+ dir = ui.active_search_direction[player_name]
+ end
+
+ local button_name = "item_button_" .. dir .. "_"
+ .. ui.mangle_for_formspec(name)
+ formspec[n] = ("item_image_button[%f,%f;%f,%f;%s;%s;]"):format(
+ ui_peruser.page_x + x * ui_peruser.btn_spc,
+ ui_peruser.page_y + y * ui_peruser.btn_spc,
+ ui_peruser.btn_size, ui_peruser.btn_size,
+ name, button_name
+ )
+ formspec[n + 1] = ("tooltip[%s;%s]"):format(
+ button_name, minetest.formspec_escape(item.description)
+ )
+ n = n + 2
+ list_index = list_index + 1
+ end
+ end
+ end
+ formspec[n] = string.format("label[%f,%f;%s: %s]",
+ ui_peruser.page_buttons_x + ui_peruser.btn_spc * (ui_peruser.is_lite_mode and 1 or 2),
+ ui_peruser.page_buttons_y + 0.1 + ui_peruser.btn_spc * 2,
+ F(S("Page")), S("@1 of @2",page2,pagemax))
+end
+
+function ui.get_formspec(player, page)
if not player then
return ""
end
local player_name = player:get_player_name()
- local ui_peruser,draw_lite_mode = unified_inventory.get_per_player_formspec(player_name)
+ local ui_peruser = ui.get_per_player_formspec(player_name)
- unified_inventory.current_page[player_name] = page
- local pagedef = unified_inventory.pages[page]
+ ui.current_page[player_name] = page
+ local pagedef = ui.pages[page]
if not pagedef then
return "" -- Invalid page name
end
- local formspec = {
- "size[14,10]",
+ local fs = {
+ "formspec_version[4]",
+ "size["..ui_peruser.formw..","..ui_peruser.formh.."]",
pagedef.formspec_prepend and "" or "no_prepend[]",
- unified_inventory.standard_background -- Background
+ ui.standard_background
}
- local n = 4
- if draw_lite_mode then
- formspec[1] = "size[11,7.7]"
- formspec[3] = unified_inventory.standard_background
- end
-
- if unified_inventory.is_creative(player_name)
- and page == "craft" then
- formspec[n] = "background[0,"..(ui_peruser.formspec_y + 2)..";1,1;ui_single_slot.png]"
- n = n+1
- end
-
- local perplayer_formspec = unified_inventory.get_per_player_formspec(player_name)
+ local perplayer_formspec = ui.get_per_player_formspec(player_name)
local fsdata = pagedef.get_formspec(player, perplayer_formspec)
- formspec[n] = fsdata.formspec
- n = n+1
+ fs[#fs + 1] = fsdata.formspec
- local button_row = 0
- local button_col = 0
-
- -- Main buttons
-
- local filtered_inv_buttons = {}
-
- for i, def in pairs(unified_inventory.buttons) do
- if not (draw_lite_mode and def.hide_lite) then
- table.insert(filtered_inv_buttons, def)
- end
- end
-
- for i, def in pairs(filtered_inv_buttons) do
-
- if draw_lite_mode and i > 4 then
- button_row = 1
- button_col = 1
- end
-
- if def.type == "image" then
- if (def.condition == nil or def.condition(player) == true) then
- formspec[n] = "image_button["
- formspec[n+1] = ( ui_peruser.main_button_x + 0.65 * (i - 1) - button_col * 0.65 * 4)
- formspec[n+2] = ","..(ui_peruser.main_button_y + button_row * 0.7)..";0.8,0.8;"
- formspec[n+3] = F(def.image)..";"
- formspec[n+4] = F(def.name)..";]"
- formspec[n+5] = "tooltip["..F(def.name)
- formspec[n+6] = ";"..(def.tooltip or "").."]"
- n = n+7
- else
- formspec[n] = "image["
- formspec[n+1] = ( ui_peruser.main_button_x + 0.65 * (i - 1) - button_col * 0.65 * 4)
- formspec[n+2] = ","..(ui_peruser.main_button_y + button_row * 0.7)..";0.8,0.8;"
- formspec[n+3] = F(def.image).."^[colorize:#808080:alpha]"
- n = n+4
-
- end
- end
- end
+ formspec_add_filters(player, fs, ui_peruser)
if fsdata.draw_inventory ~= false then
-- Player inventory
- formspec[n] = "listcolors[#00000000;#00000000]"
- formspec[n+1] = string.gsub(unified_inventory.standard_inv, "YYY", ui_peruser.formspec_y + 3.5)
- n = n+2
+ fs[#fs + 1] = "listcolors[#00000000;#00000000]"
+ fs[#fs + 1] = ui_peruser.standard_inv
end
if fsdata.draw_item_list == false then
- return table.concat(formspec, "")
+ return table.concat(fs, "")
end
- -- Controls to flip items pages
- local start_x = 9.2
+ formspec_add_categories(player, fs, ui_peruser)
+ formspec_add_search_box(player, fs, ui_peruser)
+ formspec_add_item_browser(player, fs, ui_peruser)
- if not draw_lite_mode then
- formspec[n] =
- "image_button[" .. (start_x + 0.6 * 0)
- .. ",9;.8,.8;ui_skip_backward_icon.png;start_list;]"
- .. "tooltip[start_list;" .. F(S("First page")) .. "]"
-
- .. "image_button[" .. (start_x + 0.6 * 1)
- .. ",9;.8,.8;ui_doubleleft_icon.png;rewind3;]"
- .. "tooltip[rewind3;" .. F(S("Back three pages")) .. "]"
- .. "image_button[" .. (start_x + 0.6 * 2)
- .. ",9;.8,.8;ui_left_icon.png;rewind1;]"
- .. "tooltip[rewind1;" .. F(S("Back one page")) .. "]"
-
- .. "image_button[" .. (start_x + 0.6 * 3)
- .. ",9;.8,.8;ui_right_icon.png;forward1;]"
- .. "tooltip[forward1;" .. F(S("Forward one page")) .. "]"
- .. "image_button[" .. (start_x + 0.6 * 4)
- .. ",9;.8,.8;ui_doubleright_icon.png;forward3;]"
- .. "tooltip[forward3;" .. F(S("Forward three pages")) .. "]"
-
- .. "image_button[" .. (start_x + 0.6 * 5)
- .. ",9;.8,.8;ui_skip_forward_icon.png;end_list;]"
- .. "tooltip[end_list;" .. F(S("Last page")) .. "]"
- else
- formspec[n] =
- "image_button[" .. (8.2 + 0.65 * 0)
- .. ",5.8;.8,.8;ui_skip_backward_icon.png;start_list;]"
- .. "tooltip[start_list;" .. F(S("First page")) .. "]"
- .. "image_button[" .. (8.2 + 0.65 * 1)
- .. ",5.8;.8,.8;ui_left_icon.png;rewind1;]"
- .. "tooltip[rewind1;" .. F(S("Back one page")) .. "]"
- .. "image_button[" .. (8.2 + 0.65 * 2)
- .. ",5.8;.8,.8;ui_right_icon.png;forward1;]"
- .. "tooltip[forward1;" .. F(S("Forward one page")) .. "]"
- .. "image_button[" .. (8.2 + 0.65 * 3)
- .. ",5.8;.8,.8;ui_skip_forward_icon.png;end_list;]"
- .. "tooltip[end_list;" .. F(S("Last page")) .. "]"
- end
- n = n+1
-
- -- Search box
- formspec[n] = "field_close_on_enter[searchbox;false]"
- n = n+1
-
- if not draw_lite_mode then
- formspec[n] = "field[9.5,8.325;3,1;searchbox;;"
- .. F(unified_inventory.current_searchbox[player_name]) .. "]"
- formspec[n+1] = "image_button[12.2,8.1;.8,.8;ui_search_icon.png;searchbutton;]"
- .. "tooltip[searchbutton;" ..F(S("Search")) .. "]"
- formspec[n+2] = "image_button[12.9,8.1;.8,.8;ui_reset_icon.png;searchresetbutton;]"
- .. "tooltip[searchbutton;" ..F(S("Search")) .. "]"
- .. "tooltip[searchresetbutton;" ..F(S("Reset search and display everything")) .. "]"
- else
- formspec[n] = "field[8.5,5.225;2.2,1;searchbox;;"
- .. F(unified_inventory.current_searchbox[player_name]) .. "]"
- formspec[n+1] = "image_button[10.3,5;.8,.8;ui_search_icon.png;searchbutton;]"
- .. "tooltip[searchbutton;" ..F(S("Search")) .. "]"
- formspec[n+2] = "image_button[11,5;.8,.8;ui_reset_icon.png;searchresetbutton;]"
- .. "tooltip[searchbutton;" ..F(S("Search")) .. "]"
- .. "tooltip[searchresetbutton;" ..F(S("Reset search and display everything")) .. "]"
- end
- n = n+3
-
- local no_matches = S("No matching items")
- if draw_lite_mode then
- no_matches = S("No matches.")
- end
-
- -- Items list
- if #unified_inventory.filtered_items_list[player_name] == 0 then
- formspec[n] = "label[8.2,"..ui_peruser.form_header_y..";" .. F(no_matches) .. "]"
- else
- local dir = unified_inventory.active_search_direction[player_name]
- local list_index = unified_inventory.current_index[player_name]
- local page2 = math.floor(list_index / (ui_peruser.items_per_page) + 1)
- local pagemax = math.floor(
- (#unified_inventory.filtered_items_list[player_name] - 1)
- / (ui_peruser.items_per_page) + 1)
- for y = 0, ui_peruser.pagerows - 1 do
- for x = 0, ui_peruser.pagecols - 1 do
- local name = unified_inventory.filtered_items_list[player_name][list_index]
- local item = minetest.registered_items[name]
- if item then
- -- Clicked on current item: Flip crafting direction
- if name == unified_inventory.current_item[player_name] then
- local cdir = unified_inventory.current_craft_direction[player_name]
- if cdir == "recipe" then
- dir = "usage"
- elseif cdir == "usage" then
- dir = "recipe"
- end
- else
- -- Default: use active search direction by default
- dir = unified_inventory.active_search_direction[player_name]
- end
-
- local button_name = "item_button_" .. dir .. "_"
- .. unified_inventory.mangle_for_formspec(name)
- formspec[n] = ("item_image_button[%f,%f;.81,.81;%s;%s;]"):format(
- 8.2 + x * 0.7, ui_peruser.formspec_y + ui_peruser.page_y + y * 0.7,
- name, button_name
- )
- formspec[n + 1] = ("tooltip[%s;%s \\[%s\\]]"):format(
- button_name, minetest.formspec_escape(item.description),
- item.mod_origin or "??"
- )
- n = n + 2
- list_index = list_index + 1
- end
- end
- end
- formspec[n] = "label[8.2,"..ui_peruser.form_header_y..";"..F(S("Page")) .. ": "
- .. S("@1 of @2",page2,pagemax).."]"
- end
- n= n+1
-
- if unified_inventory.activefilter[player_name] ~= "" then
- formspec[n] = "label[8.2,"..(ui_peruser.form_header_y + 0.4)..";" .. F(S("Filter")) .. ":]"
- formspec[n+1] = "label[9.1,"..(ui_peruser.form_header_y + 0.4)..";"..F(unified_inventory.activefilter[player_name]).."]"
- end
- return table.concat(formspec, "")
+ return table.concat(fs)
end
-function unified_inventory.set_inventory_formspec(player, page)
+function ui.set_inventory_formspec(player, page)
if player then
- player:set_inventory_formspec(unified_inventory.get_formspec(player, page))
+ player:set_inventory_formspec(ui.get_formspec(player, page))
end
end
+local function valid_def(def)
+ return (not def.groups.not_in_creative_inventory
+ or def.groups.not_in_creative_inventory == 0)
+ and def.description
+ and def.description ~= ""
+end
+
--apply filter to the inventory list (create filtered copy of full one)
-function unified_inventory.apply_filter(player, filter, search_dir)
+function ui.apply_filter(player, filter, search_dir)
if not player then
return false
end
@@ -290,7 +332,9 @@ function unified_inventory.apply_filter(player, filter, search_dir)
return true
end
else
- local lang = minetest.get_player_information(player_name).lang_code
+ local player_info = minetest.get_player_information(player_name)
+ local lang = player_info and player_info.lang_code or ""
+
ffilter = function(name, def)
local lname = string.lower(name)
local ldesc = string.lower(def.description)
@@ -300,78 +344,37 @@ function unified_inventory.apply_filter(player, filter, search_dir)
or llocaldesc and string.find(llocaldesc, lfilter, 1, true)
end
end
- unified_inventory.filtered_items_list[player_name]={}
- for name, def in pairs(minetest.registered_items) do
- if (not def.groups.not_in_creative_inventory
- or def.groups.not_in_creative_inventory == 0)
- and def.description
- and def.description ~= ""
- and ffilter(name, def) then
- table.insert(unified_inventory.filtered_items_list[player_name], name)
+ ui.filtered_items_list[player_name]={}
+ local category = ui.current_category[player_name] or 'all'
+ if category == 'all' then
+ for name, def in pairs(minetest.registered_items) do
+ if valid_def(def)
+ and ffilter(name, def) then
+ table.insert(ui.filtered_items_list[player_name], name)
+ end
end
- end
- table.sort(unified_inventory.filtered_items_list[player_name])
- unified_inventory.filtered_items_list_size[player_name] = #unified_inventory.filtered_items_list[player_name]
- unified_inventory.current_index[player_name] = 1
- unified_inventory.activefilter[player_name] = filter
- unified_inventory.active_search_direction[player_name] = search_dir
- unified_inventory.set_inventory_formspec(player,
- unified_inventory.current_page[player_name])
-end
-
-function unified_inventory.items_in_group(groups)
- local items = {}
- for name, item in pairs(minetest.registered_items) do
- for _, group in pairs(groups:split(',')) do
- if item.groups[group] then
- table.insert(items, name)
+ elseif category == 'uncategorized' then
+ for name, def in pairs(minetest.registered_items) do
+ if (not ui.find_category(name))
+ and valid_def(def)
+ and ffilter(name, def) then
+ table.insert(ui.filtered_items_list[player_name], name)
+ end
+ end
+ else
+ for name,exists in pairs(ui.registered_category_items[category]) do
+ local def = minetest.registered_items[name]
+ if exists and def
+ and valid_def(def)
+ and ffilter(name, def) then
+ table.insert(ui.filtered_items_list[player_name], name)
end
end
end
- return items
-end
-
-function unified_inventory.sort_inventory(inv)
- local inlist = inv:get_list("main")
- local typecnt = {}
- local typekeys = {}
- for _, st in ipairs(inlist) do
- if not st:is_empty() then
- local n = st:get_name()
- local w = st:get_wear()
- local m = st:get_metadata()
- local k = string.format("%s %05d %s", n, w, m)
- if not typecnt[k] then
- typecnt[k] = {
- name = n,
- wear = w,
- metadata = m,
- stack_max = st:get_stack_max(),
- count = 0,
- }
- table.insert(typekeys, k)
- end
- typecnt[k].count = typecnt[k].count + st:get_count()
- end
- end
- table.sort(typekeys)
- local outlist = {}
- for _, k in ipairs(typekeys) do
- local tc = typecnt[k]
- while tc.count > 0 do
- local c = math.min(tc.count, tc.stack_max)
- table.insert(outlist, ItemStack({
- name = tc.name,
- wear = tc.wear,
- metadata = tc.metadata,
- count = c,
- }))
- tc.count = tc.count - c
- end
- end
- if #outlist > #inlist then return end
- while #outlist < #inlist do
- table.insert(outlist, ItemStack(nil))
- end
- inv:set_list("main", outlist)
+ table.sort(ui.filtered_items_list[player_name])
+ ui.filtered_items_list_size[player_name] = #ui.filtered_items_list[player_name]
+ ui.current_index[player_name] = 1
+ ui.activefilter[player_name] = filter
+ ui.active_search_direction[player_name] = search_dir
+ ui.set_inventory_formspec(player, ui.current_page[player_name])
end
diff --git a/unified_inventory/locale/unified_inventory.template.tr b/unified_inventory/locale/template.txt
similarity index 73%
rename from unified_inventory/locale/unified_inventory.template.tr
rename to unified_inventory/locale/template.txt
index 2ea4fca..fd931d8 100644
--- a/unified_inventory/locale/unified_inventory.template.tr
+++ b/unified_inventory/locale/template.txt
@@ -1,54 +1,52 @@
# textdomain: unified_inventory
-
-# waypoints.lua
-
-White=
-Yellow=
-Red=
-Green=
-Blue=
-Waypoints=
-Select Waypoint #@1=
-Waypoint @1=
-Set waypoint to current location=
-Make waypoint @1=
-invisible=
-visible=
-@1 display of waypoint coordinates=
-Disable=
-Enable=
-Change color of waypoint display=
-Edit waypoint name=
-Waypoint active=
-Waypoint inactive=
-Finish editing=
-World position=
-Name=
-HUD text color=
-
-# group.lua
-
+Mixing=
+Cooking=
+Digging=
+Bags=
+Bag @1=
+Small Bag=
+Medium Bag=
+Large Bag=
+All Items=
+Misc. Items=
+Plant Life=
+Building Materials=
+Tools=
+Minerals and Metals=
+Environment and Worldgen=
+Lighting=
and =
-
-# register.lua
-
+Scroll categories left=
+Scroll categories right=
+Search=
+Reset search and display everything=
+First page=
+Back three pages=
+Back one page=
+Forward one page=
+Forward three pages=
+Last page=
+No matching items=
+No matches.=
+Page=
+@1 of @2=
+Filter=
Can use the creative inventory=
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=
Crafting Guide=
Set home position=
Home position set to: @1=
-You don't have the \"home\" privilege!=
+You don't have the "home" privilege!=
Go home=
Set time to day=
-Set time to night=
Time of day set to 6am=
-Time of day set to 9pm=
You don't have the settime privilege!=
+Set time to night=
+Time of day set to 9pm=
Clear inventory=
+This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=
-This button has been disabled outside=
-Crafting=
Trash:=
Refill:=
Any item belonging to the @1 group=
@@ -65,36 +63,28 @@ Show previous recipe=
Show previous usage=
@1 (@2)=
Give me:=
-This recipe is too@nlarge to be displayed.=
+This recipe is too@@large to be displayed.=
To craft grid:=
All=
-
-# api.lua
-
-Mixing=
-Cooking=
-Digging=
-
-# internal.lua
-
-First page=
-Back three pages=
-Back one page=
-Forward one page=
-Forward three pages=
-Last page=
-Search=
-Reset search and display everything=
-No matching items=
-No matches.=
-Page=
-@1 of @2=
-Filter=
-
-# bags.lua
-
-Bags=
-Bag @1=
-Small Bag=
-Medium Bag=
-Large Bag=
+Crafting=
+White=
+Yellow=
+Red=
+Green=
+Blue=
+Waypoints=
+Select Waypoint #@1=
+Waypoint @1=
+Set waypoint to current location=
+Hide waypoint=
+Show waypoint=
+Hide coordinates=
+Show coordinates=
+Change color of waypoint display=
+Edit waypoint name=
+Waypoint active=
+Waypoint inactive=
+Finish editing=
+World position=
+Name=
+HUD text color=
diff --git a/unified_inventory/locale/unified_inventory.de.tr b/unified_inventory/locale/unified_inventory.de.tr
index e2a05be..474049c 100644
--- a/unified_inventory/locale/unified_inventory.de.tr
+++ b/unified_inventory/locale/unified_inventory.de.tr
@@ -1,5 +1,4 @@
# textdomain: unified_inventory
-Crafting=Fertigung
Mixing=Mischen
Cooking=Kochen
Digging=Graben
@@ -8,21 +7,32 @@ Bag @1=Tasche @1
Small Bag=Kleine Tasche
Medium Bag=Mittelgroße Tasche
Large Bag=Große Tasche
+All Items=
+Misc. Items=
+Plant Life=
+Building Materials=
+Tools=
+Minerals and Metals=
+Environment and Worldgen=
+Lighting=
and = und
+Scroll categories left=
+Scroll categories right=
+Search=Suchen
+Reset search and display everything=Suche zurücksetzen und alles anzeigen
First page=Erste Seite
Back three pages=3 Seiten zurückblättern
Back one page=1 Seite zurückblättern
Forward one page=1 Seite vorblättern
Forward three pages=3 Seiten vorblättern
Last page=Letzte Seite
-Search=Suchen
-Reset search and display everything=Suche zurücksetzen und alles anzeigen
No matching items=Keine passenden Gegenstände
No matches.=Keine Treffer
Page=Seite
@1 of @2=@1 von @2
Filter=Filter
Can use the creative inventory=Kann das Kreativinventar nutzen
+Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=Zwingt Unified Inventory, im Vollmodus angezeigt zu werden, wenn der Minimalmodus global eingestellt ist
Crafting Grid=Fertigungsraster
Crafting Guide=Fertigungsführer
Set home position=Heimatposition setzen
@@ -35,6 +45,7 @@ You don't have the settime privilege!=Du hast das „settime“-Privileg nicht!
Set time to night=Zur Nachtzeit wechseln
Time of day set to 9pm=Tageszeit auf 21 Uhr gesetzt
Clear inventory=Inventar leeren
+This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Inventar geleert!
Trash:=Müll:
Refill:=Nachfüllen:
@@ -50,9 +61,12 @@ Show next recipe=Nächstes Rezept zeigen
Show next usage=Nächste Verwendung zeigen
Show previous recipe=Vorheriges Rezept zeigen
Show previous usage=Vorherige Verwendung zeigen
+@1 (@2)=
Give me:=Gib mir:
+This recipe is too@@large to be displayed.=
To craft grid:=Ins Fertigungsraster:
All=Alles
+Crafting=Fertigung
White=Weiß
Yellow=Gelb
Red=Rot
@@ -62,12 +76,10 @@ Waypoints=Wegpunkte
Select Waypoint #@1=Wegpunkt Nr. @1 auswählen
Waypoint @1=Wegpunkt Nr. @1
Set waypoint to current location=Setze Wegpunkt zur derzeitigen Position
-invisible=unsichtbar
-visible=sichtbar
-Make waypoint @1=Wegpunkt @1 machen
-Disable=ausschalten
-Enable=einschalten
-@1 display of waypoint coordinates=Anzeige der Wegpunktkoordinaten @1
+Hide waypoint=
+Show waypoint=
+Hide coordinates=
+Show coordinates=
Change color of waypoint display=Farbe der Darstellung der Wegpunkte ändern
Edit waypoint name=Name des Wegpunkts ändern
Waypoint active=Wegpunkt aktiv
@@ -76,4 +88,13 @@ Finish editing=Bearbeitung abschließen
World position=Weltposition
Name=Name
HUD text color=HUD-Textfarbe
-Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=Zwingt Unified Inventory, im Vollmodus angezeigt zu werden, wenn der Minimalmodus global eingestellt ist
+
+
+##### not used anymore #####
+
+invisible=unsichtbar
+visible=sichtbar
+Make waypoint @1=Wegpunkt @1 machen
+Disable=ausschalten
+Enable=einschalten
+@1 display of waypoint coordinates=Anzeige der Wegpunktkoordinaten @1
diff --git a/unified_inventory/locale/unified_inventory.es.tr b/unified_inventory/locale/unified_inventory.es.tr
index 18b6c77..85a794e 100644
--- a/unified_inventory/locale/unified_inventory.es.tr
+++ b/unified_inventory/locale/unified_inventory.es.tr
@@ -1,54 +1,57 @@
# textdomain: unified_inventory
-
-# waypoints.lua
-
-White=Blanco
-Yellow=Amarillo
-Red=Rojo
-Green=Verde
-Blue=Azul
-Waypoints=Puntos
-Select Waypoint #@1=Seleccionar Punto #@1
-Waypoint @1=Punto @1
-Set waypoint to current location=Establecer el punto a la ubicación actual
-Make waypoint @1=Hacer punto @1
-invisible=invisible
-visible=visible
-@1 display of waypoint coordinates=Visualizar coordenadas del punto @1
-Disable=Deshabilitado
-Enable=Habilitado
-Change color of waypoint display=Cambiar el color del punto
-Edit waypoint name=Editar nombre del punto
-Waypoint active=Punto activo
-Waypoint inactive=Punto inactivo
-Finish editing=Terminar edición
-World position=Posición en el mundo
-Name=Nombre
-HUD text color=Color del texto de la Interfaz
-
+# api.lua
+Mixing=Mezclar
+Cooking=Hornear
+Digging=Recoger
+# bags.lua
+Bags=Bolsos
+Bag @1=Bolso @1
+Small Bag=Bolso Pequeño
+Medium Bag=Bolso Mediano
+Large Bag=Bolso Grande
+All Items=
+Misc. Items=
+Plant Life=
+Building Materials=
+Tools=
+Minerals and Metals=
+Environment and Worldgen=
+Lighting=
# group.lua
-
and = y
-
+Scroll categories left=
+Scroll categories right=
+Search=Buscar
+Reset search and display everything=Limpiar la busqueda y mostrar todo
+# internal.lua
+First page=Primera página
+Back three pages=Volver tres páginas
+Back one page=Volver una página
+Forward one page=Avanzar una página
+Forward three pages=Avanzar tres páginas
+Last page=Ultima Pagina
+No matching items=No se encontraron elementos
+No matches.=No hay resultados.
+Page=Página
+@1 of @2=@1 de @2
+Filter=Filtro
# register.lua
-
Can use the creative inventory=Puede usar el inventario creativo
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=Obliga al Inventario Unificado a mostrarse en modo Completo si el modo Simple está configurado globalmente
Crafting Grid=Cuadricula de Elaboración
Crafting Guide=Guía de Elaboración
Set home position=Establecer posición de la casa
Home position set to: @1=Posición de la casa cambiada a: @1
-You don't have the \"home\" privilege!=¡No tienes el privilegio \"home\"!
+You don't have the "home" privilege!=
Go home=Ir a casa
Set time to day=Cambiar a dia
-Set time to night=Cambiar a noche
Time of day set to 6am=Hora del día cambiada a 6 AM
-Time of day set to 9pm=Hora del día cambiada a 9 PM
You don't have the settime privilege!=¡No tienes el privilegio "settime"!
+Set time to night=Cambiar a noche
+Time of day set to 9pm=Hora del día cambiada a 9 PM
Clear inventory=Limpiar inventario
+This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=¡Inventario limpio!
-This button has been disabled outside=Este botón ha sido deshabilitado
-Crafting=Elaboración
Trash:=Basura:
Refill:=Rellenar:
Any item belonging to the @1 group=Cualquier elemento que pertenezca al grupo @1
@@ -65,36 +68,41 @@ Show previous recipe=Mostrar la receta anterior
Show previous usage=Mostrar el uso anterior
@1 (@2)=@1 (@2)
Give me:=Dame:
-This recipe is too@nlarge to be displayed.=Esta receta es demasiado@ngrande para ser mostrada.
+This recipe is too@@large to be displayed.=
To craft grid:=Construir:
All=Todos
+Crafting=Elaboración
+White=Blanco
+Yellow=Amarillo
+Red=Rojo
+Green=Verde
+Blue=Azul
+Waypoints=Puntos
+Select Waypoint #@1=Seleccionar Punto #@1
+Waypoint @1=Punto @1
+Set waypoint to current location=Establecer el punto a la ubicación actual
+Hide waypoint=
+Show waypoint=
+Hide coordinates=
+Show coordinates=
+Change color of waypoint display=Cambiar el color del punto
+Edit waypoint name=Editar nombre del punto
+Waypoint active=Punto activo
+Waypoint inactive=Punto inactivo
+Finish editing=Terminar edición
+World position=Posición en el mundo
+Name=Nombre
+HUD text color=Color del texto de la Interfaz
-# api.lua
-Mixing=Mezclar
-Cooking=Hornear
-Digging=Recoger
+##### not used anymore #####
-# internal.lua
-
-First page=Primera página
-Back three pages=Volver tres páginas
-Back one page=Volver una página
-Forward one page=Avanzar una página
-Forward three pages=Avanzar tres páginas
-Last page=Ultima Pagina
-Search=Buscar
-Reset search and display everything=Limpiar la busqueda y mostrar todo
-No matching items=No se encontraron elementos
-No matches.=No hay resultados.
-Page=Página
-@1 of @2=@1 de @2
-Filter=Filtro
-
-# bags.lua
-
-Bags=Bolsos
-Bag @1=Bolso @1
-Small Bag=Bolso Pequeño
-Medium Bag=Bolso Mediano
-Large Bag=Bolso Grande
+Make waypoint @1=Hacer punto @1
+invisible=invisible
+visible=visible
+@1 display of waypoint coordinates=Visualizar coordenadas del punto @1
+Disable=Deshabilitado
+Enable=Habilitado
+You don't have the \"home\" privilege!=¡No tienes el privilegio \"home\"!
+This button has been disabled outside=Este botón ha sido deshabilitado
+This recipe is too@nlarge to be displayed.=Esta receta es demasiado@ngrande para ser mostrada.
diff --git a/unified_inventory/locale/unified_inventory.fr.tr b/unified_inventory/locale/unified_inventory.fr.tr
index 5367ddb..96d8c3f 100644
--- a/unified_inventory/locale/unified_inventory.fr.tr
+++ b/unified_inventory/locale/unified_inventory.fr.tr
@@ -1,5 +1,5 @@
# textdomain: unified_inventory
-Crafting=Création
+Mixing=
Cooking=Cuisson
Digging=Creuser
Bags=Sacs
@@ -7,35 +7,66 @@ Bag @1=Sac @1
Small Bag=Petit sac
Medium Bag=Sac moyen
Large Bag=Grand sac
+All Items=
+Misc. Items=
+Plant Life=
+Building Materials=
+Tools=
+Minerals and Metals=
+Environment and Worldgen=
+Lighting=
and = et
+Scroll categories left=
+Scroll categories right=
+Search=Rechercher
+Reset search and display everything=
First page=1ère page
Back three pages=3 pages en arrière
Back one page=Page précédente
Forward one page=Page suivante
Forward three pages=3 pages en avant
Last page=Dernière page
-Search=Rechercher
No matching items=Aucun élément correspondant
No matches.=Aucun match
Page=Page
@1 of @2=@1 de @2
Filter=Filtre
Can use the creative inventory=Vous pouvez utiliser l'inventaire créatif
+Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=Grille de création
Crafting Guide=Guide de création
Set home position=Position dans le monde
Home position set to: @1=Position de votre base fixée à: @1
You don't have the "home" privilege!=Vous n'avez pas le privilège "home"!
+Go home=
+Set time to day=
Time of day set to 6am=Heure fixée à 6h
You don't have the settime privilege!=Vous n'avez pas le privilège "settime"!
+Set time to night=
Time of day set to 9pm=Heure fixée à 21h
+Clear inventory=
+This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Inventaire vidé !
Trash:=Poubelle :
Refill:=Remplir :
+Any item belonging to the @1 group=
+Any item belonging to the groups @1=
Recipe @1 of @2=Recette @1 de @2
+Usage @1 of @2=
+No recipes=
+No usages=
Result=Résultat
+Ingredient=
+Show next recipe=
+Show next usage=
+Show previous recipe=
+Show previous usage=
+@1 (@2)=
+Give me:=
+This recipe is too@@large to be displayed.=
To craft grid:=Sur de création:
All=Tout
+Crafting=Création
White=Blanc
Yellow=Jaune
Red=Rouge
@@ -45,8 +76,10 @@ Waypoints=Point de passage
Select Waypoint #@1=Choisir un point de passage #@1
Waypoint @1=Point de passage @1
Set waypoint to current location=Marquer un point de passage à la position actuelle
-Make waypoint @1=Rendre @1 le point de passage
-@1 display of waypoint coordinates=@1 montrer les coordonnées des points de passages
+Hide waypoint=
+Show waypoint=
+Hide coordinates=
+Show coordinates=
Change color of waypoint display=Changer la couleur du point de passage
Edit waypoint name=Editer le nom du point de passage
Waypoint active=Point de passage actif
@@ -55,3 +88,9 @@ Finish editing=Terminer l'édition
World position=Position dans le monde
Name=Nom
HUD text color=Couleur de texte du HUD
+
+
+##### not used anymore #####
+
+Make waypoint @1=Rendre @1 le point de passage
+@1 display of waypoint coordinates=@1 montrer les coordonnées des points de passages
diff --git a/unified_inventory/locale/unified_inventory.it.tr b/unified_inventory/locale/unified_inventory.it.tr
index 1bf7660..c30d9e0 100644
--- a/unified_inventory/locale/unified_inventory.it.tr
+++ b/unified_inventory/locale/unified_inventory.it.tr
@@ -1,5 +1,4 @@
# textdomain: unified_inventory
-Crafting=Assemblaggio
Mixing=Unione
Cooking=Cottura
Digging=Scavo
@@ -8,21 +7,32 @@ Bag @1=Borsa @1
Small Bag=Borsa piccola
Medium Bag=Borsa media
Large Bag=Borsa grande
+All Items=
+Misc. Items=
+Plant Life=
+Building Materials=
+Tools=
+Minerals and Metals=
+Environment and Worldgen=
+Lighting=
and = e
+Scroll categories left=
+Scroll categories right=
+Search=Cerca
+Reset search and display everything=Azzera la ricerca e mostra tutto
First page=Prima pagina
Back three pages=Indietro di tre pagine
Back one page=Indietro di una pagina
Forward one page=Avanti di una pagina
Forward three pages=Avanti di tre pagine
Last page=Ultima pagina
-Search=Cerca
-Reset search and display everything=Azzera la ricerca e mostra tutto
No matching items=Nessun oggetto corrispondente
No matches.=Nessuna corrispondenza.
Page=Pagina
@1 of @2=@1 di @2
Filter=Filtro
Can use the creative inventory=Può usare l'inventario creativo
+Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=Forza la visualizzazione di Unified Inventory in modalità completa se è configurata globalmente la visualizzazione semplice
Crafting Grid=Griglia di assemblaggio
Crafting Guide=Guida di assemblaggio
Set home position=Imposta la residenza
@@ -35,6 +45,7 @@ You don't have the settime privilege!=Non hai il privilegio "time"!
Set time to night=Imposta l'orario sulla notte
Time of day set to 9pm=Orario impostato sulle 9am
Clear inventory=Ripulisci l'inventario
+This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Inventario ripulito!
Trash:=Butta:
Refill:=Riempi:
@@ -50,9 +61,12 @@ Show next recipe=Mostra la prossima ricetta
Show next usage=Mostra il prossimo utilizzo
Show previous recipe=Mostra la ricetta precedente
Show previous usage=Mostra l'utilizzo precedente
+@1 (@2)=
Give me:=Dammi:
+This recipe is too@@large to be displayed.=
To craft grid:=Alla griglia di assemblaggio:
All=Tutto
+Crafting=Assemblaggio
White=Bianco
Yellow=Giallo
Red=Rosso
@@ -62,12 +76,10 @@ Waypoints=Tappe
Select Waypoint #@1=Seleziona tappa n°@1
Waypoint @1=Tappa @1
Set waypoint to current location=Imposta tappa alla posizione attuale
-invisible=invisibile
-visible=visibile
-Make waypoint @1=Crea tappa @1
-Disable=Disabilita
-Enable=Abilita
-@1 display of waypoint coordinates=@1 la visualizzazione delle coordinate della tappa
+Hide waypoint=
+Show waypoint=
+Hide coordinates=
+Show coordinates=
Change color of waypoint display=Modifica il colore della visualizzazione della tappa
Edit waypoint name=Modifica il nome della tappa
Waypoint active=Tappa attiva
@@ -76,4 +88,13 @@ Finish editing=Termina la modifica
World position=Posizione del mondo
Name=Nome
HUD text color=Colore del testo del visore
-Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=Forza la visualizzazione di Unified Inventory in modalità completa se è configurata globalmente la visualizzazione semplice
+
+
+##### not used anymore #####
+
+invisible=invisibile
+visible=visibile
+Make waypoint @1=Crea tappa @1
+Disable=Disabilita
+Enable=Abilita
+@1 display of waypoint coordinates=@1 la visualizzazione delle coordinate della tappa
diff --git a/unified_inventory/locale/unified_inventory.ms.tr b/unified_inventory/locale/unified_inventory.ms.tr
index 25fc853..be4eb5e 100644
--- a/unified_inventory/locale/unified_inventory.ms.tr
+++ b/unified_inventory/locale/unified_inventory.ms.tr
@@ -1,5 +1,4 @@
# textdomain: unified_inventory
-Crafting=Pertukangan
Mixing=Pencampuran
Cooking=Pemasakan
Digging=Penggalian
@@ -8,21 +7,32 @@ Bag @1=Beg @1
Small Bag=Beg Kecil
Medium Bag=Beg Sederhana
Large Bag=Beg Besar
+All Items=
+Misc. Items=
+Plant Life=
+Building Materials=
+Tools=
+Minerals and Metals=
+Environment and Worldgen=
+Lighting=
and = dan
+Scroll categories left=
+Scroll categories right=
+Search=Cari
+Reset search and display everything=Set semula carian dan tunjukkan semua benda
First page=Halaman pertama
Back three pages=Tiga halaman sebelumnya
Back one page=Halaman sebelumnya
Forward one page=Halaman seterusnya
Forward three pages=Tiga halaman seterusnya
Last page=Halaman terakhir
-Search=Cari
-Reset search and display everything=Set semula carian dan tunjukkan semua benda
No matching items=Tiada item sepadan
No matches.=Tiada padanan.
Page=Halaman
@1 of @2=@1 drpd @2
Filter=Tapis
Can use the creative inventory=Boleh guna inventori kreatif
+Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=Grid Pertukangan
Crafting Guide=Panduan Pertukangan
Set home position=Tetapkan kedudukan rumah
@@ -35,6 +45,7 @@ You don't have the settime privilege!=Anda tidak ada keistimewaan settime!
Set time to night=Tetapkan masa jadi malam
Time of day set to 9pm=Masa ditetapkan ke 9 malam
Clear inventory=Kosongkan inventori
+This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Inventori dikosongkan!
Trash:=Buang:
Refill:=Isi balik:
@@ -52,7 +63,10 @@ Show previous recipe=Tunjuk resipi sebelumnya
Show previous usage=Tunjuk kegunaan sebelumnya
@1 (@2)=@1 (@2)
Give me:=Beri saya:
+This recipe is too@@large to be displayed.=
To craft grid:=Ke grid pertukangan:
+All=
+Crafting=Pertukangan
White=Putih
Yellow=Kuning
Red=Merah
@@ -62,12 +76,10 @@ Waypoints=Titik Arah
Select Waypoint #@1=Pilih Titik Arah #@1
Waypoint @1=Titik Arah @1
Set waypoint to current location=Tetapkan titik arah ke lokasi semasa
-invisible=Sembunyikan
-visible=Paparkan
-Make waypoint @1=@1 titik arah
-Disable=Sembunyikan
-Enable=Paparkan
-@1 display of waypoint coordinates=@1 koordinat untuk titik arah
+Hide waypoint=
+Show waypoint=
+Hide coordinates=
+Show coordinates=
Change color of waypoint display=Tukar warna paparan titik arah
Edit waypoint name=Edit nama titik arah
Waypoint active=Titik arah aktif
@@ -76,3 +88,13 @@ Finish editing=Selesai edit
World position=Kedudukan dunia
Name=Nama
HUD text color=Warna tulisan HUD
+
+
+##### not used anymore #####
+
+invisible=Sembunyikan
+visible=Paparkan
+Make waypoint @1=@1 titik arah
+Disable=Sembunyikan
+Enable=Paparkan
+@1 display of waypoint coordinates=@1 koordinat untuk titik arah
diff --git a/unified_inventory/locale/unified_inventory.pl.tr b/unified_inventory/locale/unified_inventory.pl.tr
index 19121d8..69d39e3 100644
--- a/unified_inventory/locale/unified_inventory.pl.tr
+++ b/unified_inventory/locale/unified_inventory.pl.tr
@@ -1,22 +1,40 @@
# textdomain: unified_inventory
+Mixing=
+Cooking=
+Digging=
Bags=Plecaki
Bag @1=Plecak @1
Small Bag=Maly plecak
Medium Bag=Sredni plecak
Large Bag=Duzy plecak
+All Items=
+Misc. Items=
+Plant Life=
+Building Materials=
+Tools=
+Minerals and Metals=
+Environment and Worldgen=
+Lighting=
and = i
+Scroll categories left=
+Scroll categories right=
+Search=Szukaj
+Reset search and display everything=
First page=Pierwsza strona
Back three pages=3 strony w tyl
Back one page=1 strona w tyl
Forward one page=1 strona do przodu
Forward three pages=3 strony do przodu
Last page=Ostatnia strona
-Search=Szukaj
No matching items=Brak pasujacych przedmiotow
No matches.=Brak wyników
Page=Strona
@1 of @2=@1 z @2
Filter=Filtr
+Can use the creative inventory=
+Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
+Crafting Grid=
+Crafting Guide=
Set home position=Ustaw pozycję wyjściową
Home position set to: @1=Pozycja domowa ustawiona na: @1
You don't have the "home" privilege!=Nie masz uprawnien do zmiany czasu "home"!
@@ -27,17 +45,28 @@ You don't have the settime privilege!=Nie masz uprawnien do zmiany czasu "settim
Set time to night=Ustaw czas na noc
Time of day set to 9pm=Czas ustawiony na 21:00
Clear inventory=Wyczyść zapasy
+This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Zapasy zostały wyczyszczone!
Trash:=Smietnik:
Refill:=Uzupelnianie:
+Any item belonging to the @1 group=
+Any item belonging to the groups @1=
Recipe @1 of @2=Recepta @1 z @2
Usage @1 of @2=Użycie @1 z @2
No recipes=Brak recepty
No usages=Bez użycia
Result=Wynik
Ingredient=Składnik
+Show next recipe=
+Show next usage=
+Show previous recipe=
+Show previous usage=
+@1 (@2)=
Give me:=Daj mi:
+This recipe is too@@large to be displayed.=
+To craft grid:=
All=Wszystko
+Crafting=
White=Bialy
Yellow=Zolty
Red=Czerwony
@@ -47,10 +76,10 @@ Waypoints=Punkty orientacyjne
Select Waypoint #@1=Wybierz punkt #@1
Waypoint @1=Punkty orientacyjne @1
Set waypoint to current location=Ustaw punkt orientacyjny na biezacej pozycji
-invisible=niewidzialny
-visible=widomy
-Make waypoint @1=Robić punkt @1
-@1 display of waypoint coordinates=@1 koordynatow punktu
+Hide waypoint=
+Show waypoint=
+Hide coordinates=
+Show coordinates=
Change color of waypoint display=Zmien kolor punktu
Edit waypoint name=Edytuj nazwe punktu
Waypoint active=Punkt wlaczony
@@ -59,3 +88,11 @@ Finish editing=Zakoncz edycje
World position=Pozycja
Name=Nazwa
HUD text color=Kolor tekstu HUD
+
+
+##### not used anymore #####
+
+invisible=niewidzialny
+visible=widomy
+Make waypoint @1=Robić punkt @1
+@1 display of waypoint coordinates=@1 koordynatow punktu
diff --git a/unified_inventory/locale/unified_inventory.pt.tr b/unified_inventory/locale/unified_inventory.pt.tr
index 3b0b902..5fedbc0 100644
--- a/unified_inventory/locale/unified_inventory.pt.tr
+++ b/unified_inventory/locale/unified_inventory.pt.tr
@@ -1,5 +1,4 @@
# textdomain: unified_inventory
-Crafting=Artesanato
Mixing=Muistura
Cooking=Cozimento
Digging=Escavação
@@ -8,21 +7,32 @@ Bag @1=Bolsa @1
Small Bag=Bolsa Pequena
Medium Bag=Bolsa Média
Large Bag=Bolsa Grande
+All Items=
+Misc. Items=
+Plant Life=
+Building Materials=
+Tools=
+Minerals and Metals=
+Environment and Worldgen=
+Lighting=
and = e
+Scroll categories left=
+Scroll categories right=
+Search=Pesquisar
+Reset search and display everything=Redefinir pesquisa e exibir tudo
First page=Primeira Página
Back three pages=Voltar 3 Páginas
Back one page=Voltar 1 Página
Forward one page=Avançar 1 Página
Forward three pages=Avançar 3 Páginas
Last page=Ultima Página
-Search=Pesquisar
-Reset search and display everything=Redefinir pesquisa e exibir tudo
No matching items=Nenhum item correspondente
No matches.=Sem correspondências
Page=Página
@1 of @2=@1 de @2
Filter=Filtro
Can use the creative inventory=Pode usar o inventário do criativo
+Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=Grade de Artesanato
Crafting Guide=Guia de Artesanato
Set home position=Definir posição de casa
@@ -35,6 +45,7 @@ You don't have the settime privilege!=Você não tem o privilégio de "settime"!
Set time to night=Definir turno para noite
Time of day set to 9pm=Hora do dia ajustada para 21h
Clear inventory=Limpar Inventário
+This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Inventário Apagado!
Trash:=Lixo:
Refill:=Recarga:
@@ -50,9 +61,12 @@ Show next recipe=Exibir Próxima Receita
Show next usage=Mostrar Próxima Utilização
Show previous recipe=Exibir Receita Anterior
Show previous usage=Exibir Utilização Anterior
+@1 (@2)=
Give me:=Gerado:
+This recipe is too@@large to be displayed.=
To craft grid:=Para Grade de Artesanato
All=MAX
+Crafting=Artesanato
White=Branco
Yellow=Amarelo
Red=Vermelho
@@ -62,10 +76,10 @@ Waypoints=Apontador de Direção
Select Waypoint #@1=Seleção de Apontador de Direção #@1
Waypoint @1=Apontador de Direção @1
Set waypoint to current location=Configurar localização atual do Apontador de Direção
-invisible=invisível
-visible=visível
-Make waypoint @1=Fazer Apontador de Direção @1
-@1 display of waypoint coordinates=@1 exibição de coordenadas de Fazer Apontador de Direção
+Hide waypoint=
+Show waypoint=
+Hide coordinates=
+Show coordinates=
Change color of waypoint display=Mudar cor exibida do Apontador de Direção
Edit waypoint name=Editar Nome de Apontador de Direção
Waypoint active=Apontador de Direção Ativo
@@ -74,3 +88,11 @@ Finish editing=Edição Finalizada
World position=Posição Mundial
Name=Nome
HUD text color=Cor de HUD
+
+
+##### not used anymore #####
+
+invisible=invisível
+visible=visível
+Make waypoint @1=Fazer Apontador de Direção @1
+@1 display of waypoint coordinates=@1 exibição de coordenadas de Fazer Apontador de Direção
diff --git a/unified_inventory/locale/unified_inventory.ru.tr b/unified_inventory/locale/unified_inventory.ru.tr
index f2a2300..2e3489c 100644
--- a/unified_inventory/locale/unified_inventory.ru.tr
+++ b/unified_inventory/locale/unified_inventory.ru.tr
@@ -1,5 +1,4 @@
# textdomain: unified_inventory
-Crafting=Крафт
Mixing=Мешать
Cooking=Варить
Digging=Копать
@@ -8,21 +7,32 @@ Bag @1=Сумка @1
Small Bag=Малая сумка
Medium Bag=Средняя сумка
Large Bag=Большая сумка
+All Items=
+Misc. Items=
+Plant Life=
+Building Materials=
+Tools=
+Minerals and Metals=
+Environment and Worldgen=
+Lighting=
and = и
+Scroll categories left=
+Scroll categories right=
+Search=Поиск
+Reset search and display everything=Сброс поиска, показать всё
First page=Первая страница
Back three pages=3 страницы назад
Back one page=1 страницу назад
Forward one page=1 страницу вперёд
Forward three pages=3 страницы вперёд
Last page=Последняя страница
-Search=Поиск
-Reset search and display everything=Сброс поиска, показать всё
No matching items=Нет подходящих элементов
No matches.=Ничего не найдено
Page=Страница
@1 of @2=@1 из @2
Filter=Фильтр
Can use the creative inventory=Можно использовать инвентарь творческого режима
+Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=Решетка крафта
Crafting Guide=Книга рецептов
Set home position=Установить позицию дома
@@ -35,6 +45,7 @@ You don't have the settime privilege!=Вам не разрешено устан
Set time to night=Ночь
Time of day set to 9pm=Установлено время 9 вечера
Clear inventory=Очистить инвентарь
+This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Инвентарь очищен!
Trash:=Мусор:
Refill:=Наполнить:
@@ -50,9 +61,12 @@ Show next recipe=Следующий рецепт
Show next usage=Следующее использование
Show previous recipe=Прошлый рецепт
Show previous usage=Прошлая страница
+@1 (@2)=
Give me:=Дай мне:
+This recipe is too@@large to be displayed.=
To craft grid:=На решeтку крафта:
All=Все
+Crafting=Крафт
White=Белый
Yellow=Желтый
Red=Красный
@@ -62,12 +76,10 @@ Waypoints=Путевые точки
Select Waypoint #@1=Выбрать путевую точку №@1
Waypoint @1=Путевая точка @1
Set waypoint to current location=Установить путевую точку по текущей позиции
-invisible=невидимой
-visible=видимой
-Make waypoint @1=Сделать путевую точку @1
-Disable=Выключить
-Enable=Включить
-@1 display of waypoint coordinates=@1 показ координат путевых точек
+Hide waypoint=
+Show waypoint=
+Hide coordinates=
+Show coordinates=
Change color of waypoint display=Поменять цвет путевой точки
Edit waypoint name=Переименовать путевую точку
Waypoint active=Путевая точка включена
@@ -76,3 +88,13 @@ Finish editing=Закончить редакцию
World position=Позиция мира
Name=Имя
HUD text color=Цвет текста HUDа
+
+
+##### not used anymore #####
+
+invisible=невидимой
+visible=видимой
+Make waypoint @1=Сделать путевую точку @1
+Disable=Выключить
+Enable=Включить
+@1 display of waypoint coordinates=@1 показ координат путевых точек
diff --git a/unified_inventory/locale/unified_inventory.tr.tr b/unified_inventory/locale/unified_inventory.tr.tr
index 93246cc..b4e15b8 100644
--- a/unified_inventory/locale/unified_inventory.tr.tr
+++ b/unified_inventory/locale/unified_inventory.tr.tr
@@ -1,5 +1,4 @@
# textdomain: unified_inventory
-Crafting=Üretim
Mixing=Karıştırma
Cooking=Pişirme
Digging=Kazma
@@ -8,20 +7,32 @@ Bag @1=@1. Çanta
Small Bag=Küçük Çanta
Medium Bag=Çanta
Large Bag=Büyük Çanta
+All Items=
+Misc. Items=
+Plant Life=
+Building Materials=
+Tools=
+Minerals and Metals=
+Environment and Worldgen=
+Lighting=
and = ve
+Scroll categories left=
+Scroll categories right=
+Search=Ara
+Reset search and display everything=
First page=İlk Sayfa
Back three pages=3 Sayfa Gerile
Back one page=Geri
Forward one page=İleri
Forward three pages=3 Sayfa İlerile
Last page=Son Sayfa
-Search=Ara
No matching items=Eşleşme yok
No matches.=Eşleşme yok
Page=Sayfa
@1 of @2=@1 dan @2
Filter=Süzgeç
Can use the creative inventory=Yaratıcı envanteri kullanabilir
+Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=Üretim tablosu
Crafting Guide=Kılavuz
Set home position=Set ev pozisyon
@@ -33,19 +44,29 @@ Time of day set to 6am=Saat 06:00 olarak ayarlandı
You don't have the settime privilege!="settime" yetkiniz yok!
Set time to night=Geceye zaman ayarla
Time of day set to 9pm=Saat 19:00 olarak ayarlandı
-msgid ""=Yaratıcı modu dışında iken bu tuş kullanılamaz.
+Clear inventory=
+This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
Inventory cleared!=Envanter temizlendi!
Trash:=Çöp
Refill:=Doldur
+Any item belonging to the @1 group=
+Any item belonging to the groups @1=
Recipe @1 of @2=@1 dan @2 tarifi
Usage @1 of @2=Kullanım @1/@2
No recipes=Tarifi yok
No usages=Kullanım yok
Result=Çıktı
Ingredient=Bileşen
+Show next recipe=
+Show next usage=
+Show previous recipe=
+Show previous usage=
+@1 (@2)=
Give me:=Ver bana:
+This recipe is too@@large to be displayed.=
To craft grid:=Üretim tablosuna kopyala
All=Tümü
+Crafting=Üretim
White=Beyaz
Yellow=Sarı
Red=Kırmızı
@@ -55,10 +76,10 @@ Waypoints=Konum Noktaları
Select Waypoint #@1=#@1 konum noktası seç
Waypoint @1=@1 Konum Noktaları
Set waypoint to current location=Bulunduğun noktayı işaretle
-invisible=görünmez
-visible=görünür
-Make waypoint @1=Yol noktası @1
-@1 display of waypoint coordinates=Yol noktası koordinatlarının görüntülenmesini @1
+Hide waypoint=
+Show waypoint=
+Hide coordinates=
+Show coordinates=
Change color of waypoint display=Konum Gösterge Rengi
Edit waypoint name=Konum Noktasını Düzenle
Waypoint active=Konum Etkin
@@ -67,3 +88,12 @@ Finish editing=Düzenleme bitti
World position=Dünya konumu
Name=İsim
HUD text color=Metin rengi
+
+
+##### not used anymore #####
+
+msgid ""=Yaratıcı modu dışında iken bu tuş kullanılamaz.
+invisible=görünmez
+visible=görünür
+Make waypoint @1=Yol noktası @1
+@1 display of waypoint coordinates=Yol noktası koordinatlarının görüntülenmesini @1
diff --git a/unified_inventory/locale/unified_inventory.zh_CN.tr b/unified_inventory/locale/unified_inventory.zh_CN.tr
index 30e15e3..595a492 100644
--- a/unified_inventory/locale/unified_inventory.zh_CN.tr
+++ b/unified_inventory/locale/unified_inventory.zh_CN.tr
@@ -1,8 +1,4 @@
# textdomain: unified_inventory
-# traslation by: IFRFSX(BingFengFSX)
-#Email: IFRFSX@Protonmail.com
-
-Crafting=合成
Mixing=混合
Cooking=烹饪
Digging=挖出
@@ -11,20 +7,32 @@ Bag @1=背包@1
Small Bag=小背包
Medium Bag=中背包
Large Bag=大背包
+All Items=
+Misc. Items=
+Plant Life=
+Building Materials=
+Tools=
+Minerals and Metals=
+Environment and Worldgen=
+Lighting=
and = 和
+Scroll categories left=
+Scroll categories right=
+Search=搜索
+Reset search and display everything=重置搜索并显示所有物品
First page=第一页
Back three pages=后退三页
Back one page=后退一页
Forward one page=前进一页
Forward three pages=前进三页
Last page=最后一页
-Search=搜索
No matching items=没有匹配物品
No matches.=没有匹配
Page=页面
@1 of @2=第@1页,共@2页
Filter=过滤器
Can use the creative inventory=可以使用创造背包
+Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=合成表
Crafting Guide=合成指南
Set home position=设置家的位置
@@ -36,21 +44,29 @@ Time of day set to 6am=时间设置到早晨6点
You don't have the settime privilege!=你没有“settime”权限!
Set time to night=设置时间到晚上
Time of day set to 9pm=时间设置到晚上9点
-
-Inventory cleared!=清空背包
Clear inventory=清空背包
-
+This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
+Inventory cleared!=清空背包
Trash:=丢弃:
Refill:=填满:
+Any item belonging to the @1 group=属于@1组的任何项目
+Any item belonging to the groups @1=属于组@1的任何项目
Recipe @1 of @2=第@1配方,共@2个
Usage @1 of @2=第@1用法,共@2个
No recipes=没有配方
No usages=没有用法
Result=结果
Ingredient=原料
+Show next recipe=
+Show next usage=
+Show previous recipe=
+Show previous usage=
+@1 (@2)=
Give me:=给予:
+This recipe is too@@large to be displayed.=
To craft grid:=填充物品到合成表
All=全部
+Crafting=合成
White=白
Yellow=黄
Red=红
@@ -60,10 +76,10 @@ Waypoints=航路点
Select Waypoint #@1=查询航路点 #@1
Waypoint @1=航路点 @1
Set waypoint to current location=将航路点设置到当前位置
-invisible=不可见的
-visible=可见的
-Make waypoint @1=设置航路点 @1
-@1 display of waypoint coordinates=显示航路点@1坐标
+Hide waypoint=
+Show waypoint=
+Hide coordinates=
+Show coordinates=
Change color of waypoint display=改变航路点显示的颜色
Edit waypoint name=编辑航路点名称
Waypoint active=航路点已激活
@@ -73,7 +89,10 @@ World position=世界位置
Name=名称
HUD text color=HUD文本颜色
-Reset search and display everything=重置搜索并显示所有物品
-Any item belonging to the @1 group=属于@1组的任何项目
-Any item belonging to the groups @1=属于组@1的任何项目
+##### not used anymore #####
+
+invisible=不可见的
+visible=可见的
+Make waypoint @1=设置航路点 @1
+@1 display of waypoint coordinates=显示航路点@1坐标
diff --git a/unified_inventory/locale/unified_inventory.zh_TW.tr b/unified_inventory/locale/unified_inventory.zh_TW.tr
index 3e8d1a1..f41190c 100644
--- a/unified_inventory/locale/unified_inventory.zh_TW.tr
+++ b/unified_inventory/locale/unified_inventory.zh_TW.tr
@@ -1,8 +1,4 @@
# textdomain: unified_inventory
-# traslation by: IFRFSX(BingFengFSX)
-#Email: IFRFSX@Protonmail.com
-
-Crafting=合成
Mixing=混合
Cooking=烹飪
Digging=挖出
@@ -11,20 +7,32 @@ Bag @1=揹包@1
Small Bag=小揹包
Medium Bag=中揹包
Large Bag=大揹包
+All Items=
+Misc. Items=
+Plant Life=
+Building Materials=
+Tools=
+Minerals and Metals=
+Environment and Worldgen=
+Lighting=
and = 和
+Scroll categories left=
+Scroll categories right=
+Search=搜索
+Reset search and display everything=重置搜索並顯示所有物品
First page=第一頁
Back three pages=後退三頁
Back one page=後退一頁
Forward one page=前進一頁
Forward three pages=前進三頁
Last page=最後一頁
-Search=搜索
No matching items=沒有匹配物品
No matches.=沒有匹配
Page=頁面
@1 of @2=第@1頁,共@2頁
Filter=過濾器
Can use the creative inventory=可以使用創造揹包
+Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=
Crafting Grid=合成表
Crafting Guide=合成指南
Set home position=設置家的位置
@@ -36,21 +44,29 @@ Time of day set to 6am=時間設置到早晨6點
You don't have the settime privilege!=你沒有“settime”權限!
Set time to night=設置時間到晚上
Time of day set to 9pm=時間設置到晚上9點
-
-Inventory cleared!=清空揹包
Clear inventory=清空揹包
-
+This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=
+Inventory cleared!=清空揹包
Trash:=丟棄:
Refill:=填滿:
+Any item belonging to the @1 group=屬於@1組的任何項目
+Any item belonging to the groups @1=屬於組@1的任何項目
Recipe @1 of @2=第@1配方,共@2個
Usage @1 of @2=第@1用法,共@2個
No recipes=沒有配方
No usages=沒有用法
Result=結果
Ingredient=原料
+Show next recipe=
+Show next usage=
+Show previous recipe=
+Show previous usage=
+@1 (@2)=
Give me:=給予:
+This recipe is too@@large to be displayed.=
To craft grid:=填充物品到合成表
All=全部
+Crafting=合成
White=白
Yellow=黃
Red=紅
@@ -60,10 +76,10 @@ Waypoints=航路點
Select Waypoint #@1=查詢航路點 #@1
Waypoint @1=航路點 @1
Set waypoint to current location=將航路點設置到當前位置
-invisible=不可見的
-visible=可見的
-Make waypoint @1=設置航路點 @1
-@1 display of waypoint coordinates=顯示航路點@1座標
+Hide waypoint=
+Show waypoint=
+Hide coordinates=
+Show coordinates=
Change color of waypoint display=改變航路點顯示的顏色
Edit waypoint name=編輯航路點名稱
Waypoint active=航路點已激活
@@ -73,7 +89,10 @@ World position=世界位置
Name=名稱
HUD text color=HUD文本顏色
-Reset search and display everything=重置搜索並顯示所有物品
-Any item belonging to the @1 group=屬於@1組的任何項目
-Any item belonging to the groups @1=屬於組@1的任何項目
+##### not used anymore #####
+
+invisible=不可見的
+visible=可見的
+Make waypoint @1=設置航路點 @1
+@1 display of waypoint coordinates=顯示航路點@1座標
diff --git a/unified_inventory/mod.conf b/unified_inventory/mod.conf
index bca70ca..3d27d29 100644
--- a/unified_inventory/mod.conf
+++ b/unified_inventory/mod.conf
@@ -1,7 +1,8 @@
name = unified_inventory
-depends = default
-optional_depends = creative, sfinv, datastorage, farming
+
+optional_depends = default, creative, sfinv, datastorage, farming
description = """
Unified Inventory replaces the default survival and creative inventory.
It adds a nicer interface and a number of features, such as a crafting guide.
"""
+min_minetest_version = 5.4.0
diff --git a/unified_inventory/register.lua b/unified_inventory/register.lua
index cfc1d7d..8dc20f0 100644
--- a/unified_inventory/register.lua
+++ b/unified_inventory/register.lua
@@ -1,6 +1,7 @@
local S = minetest.get_translator("unified_inventory")
local NS = function(s) return s end
local F = minetest.formspec_escape
+local ui = unified_inventory
minetest.register_privilege("creative", {
description = S("Can use the creative inventory"),
@@ -12,10 +13,9 @@ minetest.register_privilege("ui_full", {
give_to_singleplayer = false,
})
-
local trash = minetest.create_detached_inventory("trash", {
--allow_put = function(inv, listname, index, stack, player)
- -- if unified_inventory.is_creative(player:get_player_name()) then
+ -- if ui.is_creative(player:get_player_name()) then
-- return stack:get_count()
-- else
-- return 0
@@ -29,19 +29,19 @@ local trash = minetest.create_detached_inventory("trash", {
})
trash:set_size("main", 1)
-unified_inventory.register_button("craft", {
+ui.register_button("craft", {
type = "image",
image = "ui_craft_icon.png",
tooltip = S("Crafting Grid")
})
-unified_inventory.register_button("craftguide", {
+ui.register_button("craftguide", {
type = "image",
image = "ui_craftguide_icon.png",
tooltip = S("Crafting Guide")
})
-unified_inventory.register_button("home_gui_set", {
+ui.register_button("home_gui_set", {
type = "image",
image = "ui_sethome_icon.png",
tooltip = S("Set home position"),
@@ -49,8 +49,8 @@ unified_inventory.register_button("home_gui_set", {
action = function(player)
local player_name = player:get_player_name()
if minetest.check_player_privs(player_name, {home=true}) then
- unified_inventory.set_home(player, player:get_pos())
- local home = unified_inventory.home_pos[player_name]
+ ui.set_home(player, player:get_pos())
+ local home = ui.home_pos[player_name]
if home ~= nil then
minetest.sound_play("dingdong",
{to_player=player_name, gain = 1.0})
@@ -60,7 +60,7 @@ unified_inventory.register_button("home_gui_set", {
else
minetest.chat_send_player(player_name,
S("You don't have the \"home\" privilege!"))
- unified_inventory.set_inventory_formspec(player, unified_inventory.current_page[player_name])
+ ui.set_inventory_formspec(player, ui.current_page[player_name])
end
end,
condition = function(player)
@@ -68,7 +68,7 @@ unified_inventory.register_button("home_gui_set", {
end,
})
-unified_inventory.register_button("home_gui_go", {
+ui.register_button("home_gui_go", {
type = "image",
image = "ui_gohome_icon.png",
tooltip = S("Go home"),
@@ -76,13 +76,13 @@ unified_inventory.register_button("home_gui_go", {
action = function(player)
local player_name = player:get_player_name()
if minetest.check_player_privs(player_name, {home=true}) then
- if unified_inventory.go_home(player) then
+ if ui.go_home(player) then
minetest.sound_play("teleport", {to_player = player_name})
end
else
minetest.chat_send_player(player_name,
S("You don't have the \"home\" privilege!"))
- unified_inventory.set_inventory_formspec(player, unified_inventory.current_page[player_name])
+ ui.set_inventory_formspec(player, ui.current_page[player_name])
end
end,
condition = function(player)
@@ -90,7 +90,7 @@ unified_inventory.register_button("home_gui_go", {
end,
})
-unified_inventory.register_button("misc_set_day", {
+ui.register_button("misc_set_day", {
type = "image",
image = "ui_sun_icon.png",
tooltip = S("Set time to day"),
@@ -106,7 +106,7 @@ unified_inventory.register_button("misc_set_day", {
else
minetest.chat_send_player(player_name,
S("You don't have the settime privilege!"))
- unified_inventory.set_inventory_formspec(player, unified_inventory.current_page[player_name])
+ ui.set_inventory_formspec(player, ui.current_page[player_name])
end
end,
condition = function(player)
@@ -114,7 +114,7 @@ unified_inventory.register_button("misc_set_day", {
end,
})
-unified_inventory.register_button("misc_set_night", {
+ui.register_button("misc_set_night", {
type = "image",
image = "ui_moon_icon.png",
tooltip = S("Set time to night"),
@@ -130,7 +130,7 @@ unified_inventory.register_button("misc_set_night", {
else
minetest.chat_send_player(player_name,
S("You don't have the settime privilege!"))
- unified_inventory.set_inventory_formspec(player, unified_inventory.current_page[player_name])
+ ui.set_inventory_formspec(player, ui.current_page[player_name])
end
end,
condition = function(player)
@@ -138,19 +138,19 @@ unified_inventory.register_button("misc_set_night", {
end,
})
-unified_inventory.register_button("clear_inv", {
+ui.register_button("clear_inv", {
type = "image",
image = "ui_trash_icon.png",
tooltip = S("Clear inventory"),
action = function(player)
local player_name = player:get_player_name()
- if not unified_inventory.is_creative(player_name) then
+ if not ui.is_creative(player_name) then
minetest.chat_send_player(player_name,
S("This button has been disabled outside"
.." of creative mode to prevent"
.." accidental inventory trashing."
.."\nUse the trash slot instead."))
- unified_inventory.set_inventory_formspec(player, unified_inventory.current_page[player_name])
+ ui.set_inventory_formspec(player, ui.current_page[player_name])
return
end
player:get_inventory():set_list("main", {})
@@ -159,35 +159,42 @@ unified_inventory.register_button("clear_inv", {
{to_player=player_name, gain = 1.0})
end,
condition = function(player)
- return unified_inventory.is_creative(player:get_player_name())
+ return ui.is_creative(player:get_player_name())
end,
})
-unified_inventory.register_page("craft", {
+ui.register_page("craft", {
get_formspec = function(player, perplayer_formspec)
- local formspecy = perplayer_formspec.formspec_y
- local formheadery = perplayer_formspec.form_header_y
+ local formheaderx = perplayer_formspec.form_header_x
+ local formheadery = perplayer_formspec.form_header_y
+ local craftx = perplayer_formspec.craft_x
+ local crafty = perplayer_formspec.craft_y
local player_name = player:get_player_name()
- local formspec = "background[2,"..formspecy..";6,3;ui_crafting_form.png]"
- formspec = formspec..string.gsub(unified_inventory.standard_inv_bg, "YYY", (formspecy + 3.4))
- formspec = formspec.."label[0,"..formheadery..";" ..F(S("Crafting")).."]"
- formspec = formspec.."listcolors[#00000000;#00000000]"
- formspec = formspec.."list[current_player;craftpreview;6,"..formspecy..";1,1;]"
- formspec = formspec.."list[current_player;craft;2,"..formspecy..";3,3;]"
- if unified_inventory.trash_enabled or unified_inventory.is_creative(player_name) or minetest.get_player_privs(player_name).give then
- formspec = formspec.."label[7,"..(formspecy + 1.5)..";" .. F(S("Trash:")) .. "]"
- formspec = formspec.."background[7,"..(formspecy + 2)..";1,1;ui_single_slot.png]"
- formspec = formspec.."list[detached:trash;main;7,"..(formspecy + 2)..";1,1;]"
+ local formspec = {
+ perplayer_formspec.standard_inv_bg,
+ perplayer_formspec.craft_grid,
+ "label["..formheaderx..","..formheadery..";" ..F(S("Crafting")).."]",
+ "listcolors[#00000000;#00000000]",
+ "listring[current_name;craft]",
+ "listring[current_player;main]"
+ }
+ local n=#formspec+1
+
+ if ui.trash_enabled or ui.is_creative(player_name) or minetest.get_player_privs(player_name).give then
+ formspec[n] = string.format("label[%f,%f;%s]", craftx + 6.45, crafty + 2.4, F(S("Trash:")))
+ formspec[n+1] = ui.make_trash_slot(craftx + 6.25, crafty + 2.5)
+ n=n + 2
end
- formspec = formspec.."listring[current_name;craft]"
- formspec = formspec.."listring[current_player;main]"
- if unified_inventory.is_creative(player_name) then
- formspec = formspec.."label[0,"..(formspecy + 1.5)..";" .. F(S("Refill:")) .. "]"
- formspec = formspec.."list[detached:"..F(player_name).."refill;main;0,"..(formspecy +2)..";1,1;]"
+
+ if ui.is_creative(player_name) then
+ formspec[n] = ui.single_slot(craftx - 2.5, crafty + 2.5)
+ formspec[n+1] = string.format("label[%f,%f;%s]", craftx - 2.3, crafty + 2.4,F(S("Refill:")))
+ formspec[n+2] = string.format("list[detached:%srefill;main;%f,%f;1,1;]",
+ F(player_name), craftx - 2.5 + ui.list_img_offset, crafty + 2.5 + ui.list_img_offset)
end
- return {formspec=formspec}
+ return {formspec=table.concat(formspec)}
end,
})
@@ -201,23 +208,27 @@ unified_inventory.register_page("craft", {
local function stack_image_button(x, y, w, h, buttonname_prefix, item)
local name = item:get_name()
local count = item:get_count()
+ local wear = item:get_wear()
+ local description = item:get_meta():get_string("description")
local show_is_group = false
- local displayitem = name.." "..count
+ local displayitem = name.." "..count.." "..wear
local selectitem = name
if name:sub(1, 6) == "group:" then
local group_name = name:sub(7)
- local group_item = unified_inventory.get_group_item(group_name)
+ local group_item = ui.get_group_item(group_name)
show_is_group = not group_item.sole
displayitem = group_item.item or "unknown"
selectitem = group_item.sole and displayitem or name
end
local label = show_is_group and "G" or ""
- local buttonname = F(buttonname_prefix..unified_inventory.mangle_for_formspec(selectitem))
+ -- Unique id to prevent tooltip being overridden
+ local id = string.format("%i%i_", x*10, y*10)
+ local buttonname = F(id..buttonname_prefix..ui.mangle_for_formspec(selectitem))
local button = string.format("item_image_button[%f,%f;%f,%f;%s;%s;%s]",
x, y, w, h,
F(displayitem), buttonname, label)
if show_is_group then
- local groupstring, andcount = unified_inventory.extract_groupnames(name)
+ local groupstring, andcount = ui.extract_groupnames(name)
local grouptip
if andcount == 1 then
grouptip = S("Any item belonging to the @1 group", groupstring)
@@ -228,6 +239,8 @@ local function stack_image_button(x, y, w, h, buttonname_prefix, item)
if andcount >= 1 then
button = button .. string.format("tooltip[%s;%s]", buttonname, grouptip)
end
+ elseif description ~= "" then
+ button = button .. string.format("tooltip[%s;%s]", buttonname, F(description))
end
return button
end
@@ -257,26 +270,33 @@ local other_dir = {
usage = "recipe",
}
-unified_inventory.register_page("craftguide", {
+ui.register_page("craftguide", {
get_formspec = function(player, perplayer_formspec)
- local formspecy = perplayer_formspec.formspec_y
- local formheadery = perplayer_formspec.form_header_y
- local craftresultx = perplayer_formspec.craft_result_x
- local craftresulty = perplayer_formspec.craft_result_y
+ local craftguidex = perplayer_formspec.craft_guide_x
+ local craftguidey = perplayer_formspec.craft_guide_y
+ local craftguidearrowx = perplayer_formspec.craft_guide_arrow_x
+ local craftguideresultx = perplayer_formspec.craft_guide_result_x
+ local formheaderx = perplayer_formspec.form_header_x
+ local formheadery = perplayer_formspec.form_header_y
+ local give_x = perplayer_formspec.give_btn_x
local player_name = player:get_player_name()
local player_privs = minetest.get_player_privs(player_name)
- local fs = {
- string.gsub(unified_inventory.standard_inv_bg, "YYY", (formspecy + 3.4)),
- "label[0,"..formheadery..";" .. F(S("Crafting Guide")) .. "]",
+
+ local formspec = {
+ perplayer_formspec.standard_inv_bg,
+ "label["..formheaderx..","..formheadery..";" .. F(S("Crafting Guide")) .. "]",
"listcolors[#00000000;#00000000]"
}
- local item_name = unified_inventory.current_item[player_name]
+
+ local item_name = ui.current_item[player_name]
if not item_name then
- return { formspec = table.concat(fs) }
+ return { formspec = table.concat(formspec) }
end
+ local n = 4
+
local item_name_shown
if minetest.registered_items[item_name]
and minetest.registered_items[item_name].description then
@@ -286,51 +306,60 @@ unified_inventory.register_page("craftguide", {
item_name_shown = item_name
end
- local dir = unified_inventory.current_craft_direction[player_name]
+ local dir = ui.current_craft_direction[player_name]
local rdir = dir == "recipe" and "usage" or "recipe"
- local crafts = unified_inventory.crafts_for[dir][item_name]
- local alternate = unified_inventory.alternate[player_name]
+ local crafts = ui.crafts_for[dir][item_name]
+ local alternate = ui.alternate[player_name]
local alternates, craft
if crafts and #crafts > 0 then
alternates = #crafts
craft = crafts[alternate]
end
- local has_give = player_privs.give or unified_inventory.is_creative(player_name)
+ local has_give = player_privs.give or ui.is_creative(player_name)
- fs[#fs + 1] = "background[0.5,"..(formspecy + 0.2)..";8,3;ui_craftguide_form.png]"
- fs[#fs + 1] = string.format("textarea[%f,%f;10,1;;%s: %s;]",
- craftresultx, craftresulty, F(role_text[dir]), item_name_shown)
- fs[#fs + 1] = stack_image_button(0, formspecy, 1.1, 1.1,
- "item_button_" .. rdir .. "_", ItemStack(item_name))
+ formspec[n] = string.format("image[%f,%f;%f,%f;ui_crafting_arrow.png]",
+ craftguidearrowx, craftguidey, ui.imgscale, ui.imgscale)
+
+ formspec[n+1] = string.format("textarea[%f,%f;10,1;;%s: %s;]",
+ perplayer_formspec.craft_guide_resultstr_x, perplayer_formspec.craft_guide_resultstr_y,
+ F(role_text[dir]), item_name_shown)
+ n = n + 2
+
+ local giveme_form = table.concat({
+ "label[".. (give_x+0.1)..",".. (craftguidey + 2.7) .. ";" .. F(S("Give me:")) .. "]",
+ "button["..(give_x)..",".. (craftguidey + 2.9) .. ";0.75,0.5;craftguide_giveme_1;1]",
+ "button["..(give_x+0.8)..",".. (craftguidey + 2.9) .. ";0.75,0.5;craftguide_giveme_10;10]",
+ "button["..(give_x+1.6)..",".. (craftguidey + 2.9) .. ";0.75,0.5;craftguide_giveme_99;99]"
+ })
if not craft then
-- No craft recipes available for this item.
- fs[#fs + 1] = "label[5.5,"..(formspecy + 2.35)..";"
- .. F(no_recipe_text[dir]) .. "]"
- local no_pos = dir == "recipe" and 4.5 or 6.5
- local item_pos = dir == "recipe" and 6.5 or 4.5
- fs[#fs + 1] = "image["..no_pos..","..formspecy..";1.1,1.1;ui_no.png]"
- fs[#fs + 1] = stack_image_button(item_pos, formspecy, 1.1, 1.1,
+ formspec[n] = string.format("label[%f,%f;%s]", craftguidex+2.5, craftguidey+1.5, F(no_recipe_text[dir]))
+ local no_pos = dir == "recipe" and (craftguidex+2.5) or craftguideresultx
+ local item_pos = dir == "recipe" and craftguideresultx or (craftguidex+2.5)
+ formspec[n+1] = "image["..no_pos..","..craftguidey..";1.2,1.2;ui_no.png]"
+ formspec[n+2] = stack_image_button(item_pos, craftguidey, 1.2, 1.2,
"item_button_" .. other_dir[dir] .. "_", ItemStack(item_name))
if has_give then
- fs[#fs + 1] = "label[0," .. (formspecy + 2.10) .. ";" .. F(S("Give me:")) .. "]"
- .. "button[0, " .. (formspecy + 2.7) .. ";0.6,0.5;craftguide_giveme_1;1]"
- .. "button[0.6," .. (formspecy + 2.7) .. ";0.7,0.5;craftguide_giveme_10;10]"
- .. "button[1.3," .. (formspecy + 2.7) .. ";0.8,0.5;craftguide_giveme_99;99]"
+ formspec[n+3] = giveme_form
end
- return { formspec = table.concat(fs) }
+ return { formspec = table.concat(formspec) }
+ else
+ formspec[n] = stack_image_button(craftguideresultx, craftguidey, 1.2, 1.2,
+ "item_button_" .. rdir .. "_", ItemStack(craft.output))
+ n = n + 1
end
- local craft_type = unified_inventory.registered_craft_types[craft.type] or
- unified_inventory.craft_type_defaults(craft.type, {})
+ local craft_type = ui.registered_craft_types[craft.type] or
+ ui.craft_type_defaults(craft.type, {})
if craft_type.icon then
- fs[#fs + 1] = string.format("image[%f,%f;%f,%f;%s]",
- 5.7, (formspecy + 0.05), 0.5, 0.5, craft_type.icon)
+ formspec[n] = string.format("image[%f,%f;%f,%f;%s]",
+ craftguidearrowx+0.35, craftguidey, 0.5, 0.5, craft_type.icon)
+ n = n + 1
end
- fs[#fs + 1] = "label[5.5,"..(formspecy + 1)..";" .. F(craft_type.description).."]"
- fs[#fs + 1] = stack_image_button(6.5, formspecy, 1.1, 1.1,
- "item_button_usage_", ItemStack(craft.output))
+ formspec[n] = string.format("label[%f,%f;%s]", craftguidearrowx + 0.15, craftguidey + 1.4, F(craft_type.description))
+ n = n + 1
local display_size = craft_type.dynamic_display_size
and craft_type.dynamic_display_size(craft)
@@ -341,11 +370,12 @@ unified_inventory.register_page("craftguide", {
-- This keeps recipes aligned to the right,
-- so that they're close to the arrow.
- local xoffset = 5.5
+ local xoffset = craftguidex+3.75
+ local bspc = 1.25
-- Offset factor for crafting grids with side length > 4
local of = (3/math.max(3, math.max(display_size.width, display_size.height)))
local od = 0
- -- Minimum grid size at which size optimazation measures kick in
+ -- Minimum grid size at which size optimization measures kick in
local mini_craft_size = 6
if display_size.width >= mini_craft_size then
od = math.max(1, display_size.width - 2)
@@ -354,12 +384,12 @@ unified_inventory.register_page("craftguide", {
-- Size modifier factor
local sf = math.min(1, of * (1.05 + 0.05*od))
-- Button size
- local bsize_h = 1.1 * sf
- local bsize_w = bsize_h
- if display_size.width >= mini_craft_size then
- bsize_w = 1.175 * sf
+ local bsize = 1.2 * sf
+
+ if display_size.width >= mini_craft_size then -- it's not a normal 3x3 grid
+ bsize = 0.8 * sf
end
- if (bsize_h > 0.35 and display_size.width) then
+ if (bsize > 0.35 and display_size.width) then
for y = 1, display_size.height do
for x = 1, display_size.width do
local item
@@ -369,48 +399,53 @@ unified_inventory.register_page("craftguide", {
-- Flipped x, used to build formspec buttons from right to left
local fx = display_size.width - (x-1)
-- x offset, y offset
- local xof = (fx-1) * of + of
- local yof = (y-1) * of + 1
+ local xof = ((fx-1) * of + of) * bspc
+ local yof = ((y-1) * of + 1) * bspc
if item then
- fs[#fs + 1] = stack_image_button(
- xoffset - xof, formspecy - 1 + yof, bsize_w, bsize_h,
+ formspec[n] = stack_image_button(
+ xoffset - xof, craftguidey - 1.25 + yof, bsize, bsize,
"item_button_recipe_",
ItemStack(item))
else
-- Fake buttons just to make grid
- fs[#fs + 1] = string.format("image_button[%f,%f;%f,%f;ui_blank_image.png;;]",
- xoffset - xof, formspecy - 1 + yof, bsize_w, bsize_h)
+ formspec[n] = string.format("image_button[%f,%f;%f,%f;ui_blank_image.png;;]",
+ xoffset - xof, craftguidey - 1.25 + yof, bsize, bsize)
end
+ n = n + 1
end
end
else
-- Error
- fs[#fs + 1] = string.format("label[2,%f;%s]",
- formspecy, F(S("This recipe is too@nlarge to be displayed.")))
+ formspec[n] = string.format("label[2,%f;%s]",
+ craftguidey, F(S("This recipe is too@nlarge to be displayed.")))
+ n = n + 1
end
if craft_type.uses_crafting_grid and display_size.width <= 3 then
- fs[#fs + 1] = "label[0," .. (formspecy + 0.9) .. ";" .. F(S("To craft grid:")) .. "]"
- .. "button[0, " .. (formspecy + 1.5) .. ";0.6,0.5;craftguide_craft_1;1]"
- .. "button[0.6," .. (formspecy + 1.5) .. ";0.7,0.5;craftguide_craft_10;10]"
- .. "button[1.3," .. (formspecy + 1.5) .. ";0.8,0.5;craftguide_craft_max;" .. F(S("All")) .. "]"
+ formspec[n] = "label["..(give_x+0.1)..",".. (craftguidey + 1.7) .. ";" .. F(S("To craft grid:")) .. "]"
+ formspec[n+1] = "button[".. (give_x)..",".. (craftguidey + 1.9) .. ";0.75,0.5;craftguide_craft_1;1]"
+ formspec[n+2] = "button[".. (give_x+0.8)..",".. (craftguidey + 1.9) .. ";0.75,0.5;craftguide_craft_10;10]"
+ formspec[n+3] = "button[".. (give_x+1.6)..",".. (craftguidey + 1.9) .. ";0.75,0.5;craftguide_craft_max;" .. F(S("All")) .. "]"
+ n = n + 4
end
+
if has_give then
- fs[#fs + 1] = "label[0," .. (formspecy + 2.1) .. ";" .. F(S("Give me:")) .. "]"
- .. "button[0, " .. (formspecy + 2.7) .. ";0.6,0.5;craftguide_giveme_1;1]"
- .. "button[0.6," .. (formspecy + 2.7) .. ";0.7,0.5;craftguide_giveme_10;10]"
- .. "button[1.3," .. (formspecy + 2.7) .. ";0.8,0.5;craftguide_giveme_99;99]"
+ formspec[n] = giveme_form
+ n = n + 1
end
if alternates and alternates > 1 then
- fs[#fs + 1] = "label[5.5," .. (formspecy + 1.6) .. ";"
- .. F(S(recipe_text[dir], alternate, alternates)) .. "]"
- .. "image_button[5.5," .. (formspecy + 2) .. ";1,1;ui_left_icon.png;alternate_prev;]"
- .. "image_button[6.5," .. (formspecy + 2) .. ";1,1;ui_right_icon.png;alternate;]"
- .. "tooltip[alternate_prev;" .. F(prev_alt_text[dir]) .. "]"
- .. "tooltip[alternate;" .. F(next_alt_text[dir]) .. "]"
+ formspec[n] = string.format("label[%f,%f;%s]",
+ craftguidex+4, craftguidey + 2.3, F(S(recipe_text[dir], alternate, alternates)))
+ formspec[n+1] = string.format("image_button[%f,%f;1.1,1.1;ui_left_icon.png;alternate_prev;]",
+ craftguidearrowx+0.2, craftguidey + 2.6)
+ formspec[n+2] = string.format("image_button[%f,%f;1.1,1.1;ui_right_icon.png;alternate;]",
+ craftguidearrowx+1.35, craftguidey + 2.6)
+ formspec[n+3] = "tooltip[alternate_prev;" .. F(prev_alt_text[dir]) .. "]"
+ formspec[n+4] = "tooltip[alternate;" .. F(next_alt_text[dir]) .. "]"
end
- return { formspec = table.concat(fs) }
+
+ return { formspec = table.concat(formspec) }
end,
})
@@ -418,7 +453,7 @@ local function craftguide_giveme(player, formname, fields)
local player_name = player:get_player_name()
local player_privs = minetest.get_player_privs(player_name)
if not player_privs.give and
- not unified_inventory.is_creative(player_name) then
+ not ui.is_creative(player_name) then
minetest.log("action", "[unified_inventory] Denied give action to player " ..
player_name)
return
@@ -433,7 +468,7 @@ local function craftguide_giveme(player, formname, fields)
amount = tonumber(amount) or 0
if amount == 0 then return end
- local output = unified_inventory.current_item[player_name]
+ local output = ui.current_item[player_name]
if (not output) or (output == "") then return end
local player_inv = player:get_inventory()
@@ -454,21 +489,29 @@ local function craftguide_craft(player, formname, fields)
local player_name = player:get_player_name()
- local output = unified_inventory.current_item[player_name] or ""
+ local output = ui.current_item[player_name] or ""
if output == "" then return end
- local crafts = unified_inventory.crafts_for[
- unified_inventory.current_craft_direction[player_name]][output] or {}
+ local crafts = ui.crafts_for[
+ ui.current_craft_direction[player_name]][output] or {}
if #crafts == 0 then return end
- local alternate = unified_inventory.alternate[player_name]
+ local alternate = ui.alternate[player_name]
local craft = crafts[alternate]
+ if not craft.width then
+ if not craft.output then
+ minetest.log("warning", "[unified_inventory] Craft has no output.")
+ else
+ minetest.log("warning", ("[unified_inventory] Craft for '%s' has no width."):format(craft.output))
+ end
+ return
+ end
if craft.width > 3 then return end
- unified_inventory.craftguide_match_craft(player, "main", "craft", craft, amount)
+ ui.craftguide_match_craft(player, "main", "craft", craft, amount)
- unified_inventory.set_inventory_formspec(player, "craft")
+ ui.set_inventory_formspec(player, "craft")
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
diff --git a/unified_inventory/settingtypes.txt b/unified_inventory/settingtypes.txt
index 910989f..27768ac 100644
--- a/unified_inventory/settingtypes.txt
+++ b/unified_inventory/settingtypes.txt
@@ -9,3 +9,6 @@ unified_inventory_bags (Enable bags) bool true
#If enabled, the trash slot can be used by those without both creative
#and the give privilege.
unified_inventory_trash (Enable trash) bool true
+
+
+unified_inventory_automatic_categorization (Items automatically added to categories) bool true
\ No newline at end of file
diff --git a/unified_inventory/textures/ui_bags_header.png b/unified_inventory/textures/ui_bags_header.png
deleted file mode 100644
index f9bf1dd..0000000
Binary files a/unified_inventory/textures/ui_bags_header.png and /dev/null differ
diff --git a/unified_inventory/textures/ui_bags_inv_large.png b/unified_inventory/textures/ui_bags_inv_large.png
deleted file mode 100644
index a3725ee..0000000
Binary files a/unified_inventory/textures/ui_bags_inv_large.png and /dev/null differ
diff --git a/unified_inventory/textures/ui_bags_inv_medium.png b/unified_inventory/textures/ui_bags_inv_medium.png
deleted file mode 100644
index 5924f54..0000000
Binary files a/unified_inventory/textures/ui_bags_inv_medium.png and /dev/null differ
diff --git a/unified_inventory/textures/ui_bags_inv_small.png b/unified_inventory/textures/ui_bags_inv_small.png
deleted file mode 100644
index 6776754..0000000
Binary files a/unified_inventory/textures/ui_bags_inv_small.png and /dev/null differ
diff --git a/unified_inventory/textures/ui_bags_trash.png b/unified_inventory/textures/ui_bags_trash.png
deleted file mode 100644
index 8247130..0000000
Binary files a/unified_inventory/textures/ui_bags_trash.png and /dev/null differ
diff --git a/unified_inventory/textures/ui_category_all.png b/unified_inventory/textures/ui_category_all.png
new file mode 100644
index 0000000..0af7a53
Binary files /dev/null and b/unified_inventory/textures/ui_category_all.png differ
diff --git a/unified_inventory/textures/ui_category_none.png b/unified_inventory/textures/ui_category_none.png
new file mode 100644
index 0000000..8976fb0
Binary files /dev/null and b/unified_inventory/textures/ui_category_none.png differ
diff --git a/unified_inventory/textures/ui_craftguide_form.png b/unified_inventory/textures/ui_craftguide_form.png
deleted file mode 100644
index d9be53f..0000000
Binary files a/unified_inventory/textures/ui_craftguide_form.png and /dev/null differ
diff --git a/unified_inventory/textures/ui_crafting_arrow.png b/unified_inventory/textures/ui_crafting_arrow.png
new file mode 100644
index 0000000..6901c58
Binary files /dev/null and b/unified_inventory/textures/ui_crafting_arrow.png differ
diff --git a/unified_inventory/textures/ui_crafting_form.png b/unified_inventory/textures/ui_crafting_form.png
deleted file mode 100644
index 9043287..0000000
Binary files a/unified_inventory/textures/ui_crafting_form.png and /dev/null differ
diff --git a/unified_inventory/textures/ui_form_bg.png b/unified_inventory/textures/ui_form_bg.png
deleted file mode 100644
index 7111fac..0000000
Binary files a/unified_inventory/textures/ui_form_bg.png and /dev/null differ
diff --git a/unified_inventory/textures/ui_formbg_9_sliced.png b/unified_inventory/textures/ui_formbg_9_sliced.png
new file mode 100644
index 0000000..0b8463c
Binary files /dev/null and b/unified_inventory/textures/ui_formbg_9_sliced.png differ
diff --git a/unified_inventory/textures/ui_main_inventory.png b/unified_inventory/textures/ui_main_inventory.png
deleted file mode 100644
index b9a0545..0000000
Binary files a/unified_inventory/textures/ui_main_inventory.png and /dev/null differ
diff --git a/unified_inventory/textures/ui_misc_form.png b/unified_inventory/textures/ui_misc_form.png
deleted file mode 100644
index c6a6057..0000000
Binary files a/unified_inventory/textures/ui_misc_form.png and /dev/null differ
diff --git a/unified_inventory/textures/ui_single_slot.png b/unified_inventory/textures/ui_single_slot.png
index 63da98d..2451623 100644
Binary files a/unified_inventory/textures/ui_single_slot.png and b/unified_inventory/textures/ui_single_slot.png differ
diff --git a/unified_inventory/textures/ui_single_slot_bright.png b/unified_inventory/textures/ui_single_slot_bright.png
new file mode 100644
index 0000000..c66365c
Binary files /dev/null and b/unified_inventory/textures/ui_single_slot_bright.png differ
diff --git a/unified_inventory/textures/ui_smallbg_9_sliced.png b/unified_inventory/textures/ui_smallbg_9_sliced.png
new file mode 100644
index 0000000..865e0c9
Binary files /dev/null and b/unified_inventory/textures/ui_smallbg_9_sliced.png differ
diff --git a/unified_inventory/textures/ui_trash_slot_icon.png b/unified_inventory/textures/ui_trash_slot_icon.png
new file mode 100644
index 0000000..5fc4de1
Binary files /dev/null and b/unified_inventory/textures/ui_trash_slot_icon.png differ
diff --git a/unified_inventory/textures/ui_xyz_off_icon.png b/unified_inventory/textures/ui_xyz_off_icon.png
deleted file mode 100644
index 3c1836e..0000000
Binary files a/unified_inventory/textures/ui_xyz_off_icon.png and /dev/null differ
diff --git a/unified_inventory/textures/ui_xyz_on_icon.png b/unified_inventory/textures/ui_xyz_on_icon.png
deleted file mode 100644
index 003ea63..0000000
Binary files a/unified_inventory/textures/ui_xyz_on_icon.png and /dev/null differ
diff --git a/unified_inventory/waypoints.lua b/unified_inventory/waypoints.lua
index 97712b7..1496cdd 100644
--- a/unified_inventory/waypoints.lua
+++ b/unified_inventory/waypoints.lua
@@ -1,5 +1,7 @@
local S = minetest.get_translator("unified_inventory")
local F = minetest.formspec_escape
+local ui = unified_inventory
+local COUNT = 5
local hud_colors = {
{"#FFFFFF", 0xFFFFFF, S("White")},
@@ -9,107 +11,199 @@ local hud_colors = {
{"#2c4df1", 0x2c4df1, S("Blue")},
}
-local hud_colors_max = #hud_colors
+-- Storage compatibility code
--- Stores temporary player data (persists until player leaves)
+--[[
+Stores temporary player data (persists until player leaves)
+ [player_name] = {
+ [] = {
+ edit = ,
+ hud = ,
+ },
+ [] = { ... },
+ ...
+ }
+]]
local waypoints_temp = {}
-unified_inventory.register_page("waypoints", {
+--[[
+Datastorage format (per-player):
+ {
+ selected = ,
+ [] = {
+ name =
+ world_pos = ,
+ color = <"hud_colors" index>,
+ active = ,
+ display_pos = ,
+ },
+ [] = { ... },
+ ...
+ }
+Player metadata format:
+ {
+ selected = ,
+ -- Cannot mix integer/string keys in JSON
+ data = {
+ [] = { same as above },
+ ...
+ }
+ }
+]]
+
+local function set_waypoint_data(player, waypoints)
+ local meta = player:get_meta()
+ if not next(waypoints.data or {}) then
+ -- Empty data. Do not save anything, or delete
+ meta:set_string("ui_waypoints", "")
+ else
+ meta:set_string("ui_waypoints", minetest.write_json(waypoints))
+ end
+end
+
+local function migrate_datastorage(player, waypoints)
+ -- Copy values from old table
+ local new_data = {
+ selected = waypoints.selected,
+ data = {}
+ }
+ for i = 1, COUNT do
+ new_data.data[i] = waypoints[i]
+ end
+
+ set_waypoint_data(player, new_data)
+
+ -- Delete values, but keep one entry so that it's saved by datastorage
+ for k, _ in pairs(waypoints) do
+ waypoints[k] = nil
+ end
+ waypoints[1] = 1
+end
+
+local have_datastorage = minetest.get_modpath("datastorage") ~= nil
+local function get_waypoint_data(player)
+ local player_name = player:get_player_name()
+
+ -- Migration step
+ if have_datastorage then
+ local waypoints = datastorage.get(player_name, "waypoints")
+ if waypoints.selected then
+ migrate_datastorage(player, waypoints)
+ minetest.log("action", "[unified_inventory] " ..
+ "Migrated waypoints of player: " .. player_name)
+ end
+ end
+
+ -- Get directly from metadata
+ local waypoints = player:get_meta():get("ui_waypoints")
+ waypoints = waypoints and minetest.parse_json(waypoints) or {}
+ waypoints.data = waypoints.data or {}
+
+ return waypoints
+end
+
+ui.register_page("waypoints", {
get_formspec = function(player)
local player_name = player:get_player_name()
+ local wp_info_x = ui.style_full.form_header_x + 1.25
+ local wp_info_y = ui.style_full.form_header_y + 0.5
+ local wp_bottom_row = ui.style_full.std_inv_y - 1
+ local wp_buttons_rj = ui.style_full.std_inv_x + 10.1 - ui.style_full.btn_spc
+ local wp_edit_w = ui.style_full.btn_spc * 4 - 0.1
- -- build a "fake" temp entry if the server took too long
- -- during sign-on and returned an empty entry
- if not waypoints_temp[player_name] then waypoints_temp[player_name] = {hud = 1} end
+ local waypoints = get_waypoint_data(player)
+ local sel = waypoints.selected or 1
- local waypoints = datastorage.get(player_name, "waypoints")
- local formspec = string.gsub(unified_inventory.standard_inv_bg, "YYY", "4.4") ..
- "image[0,0;1,1;ui_waypoints_icon.png]" ..
- "label[1,0;" .. F(S("Waypoints")) .. "]"
+ local formspec = {
+ ui.style_full.standard_inv_bg,
+ string.format("label[%f,%f;%s]",
+ ui.style_full.form_header_x, ui.style_full.form_header_y, F(S("Waypoints"))),
+ "image["..wp_info_x..","..wp_info_y..";1,1;ui_waypoints_icon.png]"
+ }
+ local n=4
-- Tabs buttons:
- for i = 1, 5, 1 do
- formspec = formspec ..
- "image_button[0.0," .. 0.2 + i * 0.7 .. ";.8,.8;" ..
- (i == waypoints.selected and "ui_blue_icon_background.png^" or "") ..
- "ui_" .. i .. "_icon.png;" ..
- "select_waypoint" .. i .. ";]" ..
- "tooltip[select_waypoint" .. i .. ";"
- .. S("Select Waypoint #@1", i).."]"
+ for i = 1, COUNT do
+ local sw="select_waypoint"..i
+ formspec[n] = string.format("image_button[%f,%f;%f,%f;%sui_%i_icon.png;%s;]",
+ ui.style_full.main_button_x, wp_bottom_row - (5-i) * ui.style_full.btn_spc,
+ ui.style_full.btn_size, ui.style_full.btn_size,
+ (i == sel) and "ui_blue_icon_background.png^" or "",
+ i, sw)
+ formspec[n+1] = "tooltip["..sw..";"..S("Select Waypoint #@1", i).."]"
+ n = n + 2
end
- local i = waypoints.selected or 1
- local waypoint = waypoints[i] or {}
- local temp = waypoints_temp[player_name][i] or {}
- local default_name = S("Waypoint @1", i)
+ local waypoint = waypoints.data[sel] or {}
+ local temp = waypoints_temp[player_name][sel] or {}
+ local default_name = S("Waypoint @1", sel)
-- Main buttons:
- formspec = formspec ..
- "image_button[4.5,3.7;.8,.8;"..
- "ui_waypoint_set_icon.png;"..
- "set_waypoint"..i..";]"..
- "tooltip[set_waypoint" .. i .. ";"
- .. F(S("Set waypoint to current location")).."]"
+ local btnlist = {
+ set_waypoint = {
+ "ui_waypoint_set_icon.png",
+ S("Set waypoint to current location")
+ },
+ toggle_waypoint = {
+ waypoint.active and "ui_on_icon.png" or "ui_off_icon.png",
+ waypoint.active and S("Hide waypoint") or S("Show waypoint")
+ },
+ toggle_display_pos = {
+ waypoint.display_pos and "ui_green_icon_background.png^ui_xyz_icon.png" or "ui_red_icon_background.png^ui_xyz_icon.png^(ui_no.png^[transformR90)",
+ waypoint.display_pos and S("Hide coordinates") or S("Show coordinates")
+ },
+ toggle_color = {
+ "ui_circular_arrows_icon.png",
+ S("Change color of waypoint display")
+ },
+ rename_waypoint = {
+ "ui_pencil_icon.png",
+ S("Edit waypoint name")
+ }
+ }
- formspec = formspec ..
- "image_button[5.2,3.7;.8,.8;"..
- (waypoint.active and "ui_on_icon.png" or "ui_off_icon.png")..";"..
- "toggle_waypoint"..i..";]"..
- "tooltip[toggle_waypoint" .. i .. ";"
- .. F(S("Make waypoint @1",
- waypoint.active and S("invisible") or S("visible"))).."]"
-
- formspec = formspec ..
- "image_button[5.9,3.7;.8,.8;"..
- (waypoint.display_pos and "ui_green_icon_background.png" or "ui_red_icon_background.png").."^ui_xyz_icon.png;"..
- "toggle_display_pos" .. i .. ";]"..
- "tooltip[toggle_display_pos" .. i .. ";"
- .. F(S("@1 display of waypoint coordinates",
- waypoint.display_pos and S("Disable") or S("Enable"))) .."]"
-
- formspec = formspec ..
- "image_button[6.6,3.7;.8,.8;"..
- "ui_circular_arrows_icon.png;"..
- "toggle_color"..i..";]"..
- "tooltip[toggle_color" .. i .. ";"
- .. F(S("Change color of waypoint display")).."]"
-
- formspec = formspec ..
- "image_button[7.3,3.7;.8,.8;"..
- "ui_pencil_icon.png;"..
- "rename_waypoint"..i..";]"..
- "tooltip[rename_waypoint" .. i .. ";"
- .. F(S("Edit waypoint name")).."]"
+ local x = 4
+ for name, def in pairs(btnlist) do
+ formspec[n] = string.format("image_button[%f,%f;%f,%f;%s;%s%i;]",
+ wp_buttons_rj - ui.style_full.btn_spc * x, wp_bottom_row,
+ ui.style_full.btn_size, ui.style_full.btn_size,
+ def[1], name, sel)
+ formspec[n+1] = "tooltip["..name..sel..";"..F(def[2]).."]"
+ x = x - 1
+ n = n + 2
+ end
-- Waypoint's info:
- if waypoint.active then
- formspec = formspec .. "label[1,0.8;"..F(S("Waypoint active")).."]"
- else
- formspec = formspec .. "label[1,0.8;"..F(S("Waypoint inactive")).."]"
- end
+ formspec[n] = ("label[%f,%f;%s]"):format(
+ wp_info_x, wp_info_y + 1.1,
+ F(waypoint.active and S("Waypoint active") or S("Waypoint inactive"))
+ )
+ n = n + 1
if temp.edit then
- formspec = formspec ..
- "field[1.3,3.2;6,.8;rename_box" .. i .. ";;"
- ..(waypoint.name or default_name).."]" ..
- "image_button[7.3,2.9;.8,.8;"..
- "ui_ok_icon.png;"..
- "confirm_rename"..i.. ";]"..
- "tooltip[confirm_rename" .. i .. ";"
- .. F(S("Finish editing")).."]"
+ formspec[n] = string.format("field[%f,%f;%f,%f;rename_box%i;;%s]",
+ wp_buttons_rj - wp_edit_w - 0.1, wp_bottom_row - ui.style_full.btn_spc,
+ wp_edit_w, ui.style_full.btn_size, sel, (waypoint.name or default_name))
+ formspec[n+1] = string.format("image_button[%f,%f;%f,%f;ui_ok_icon.png;confirm_rename%i;]",
+ wp_buttons_rj, wp_bottom_row - ui.style_full.btn_spc,
+ ui.style_full.btn_size, ui.style_full.btn_size, sel)
+ formspec[n+2] = "tooltip[confirm_rename"..sel..";"..F(S("Finish editing")).."]"
+ n = n + 3
end
- formspec = formspec .. "label[1,1.3;"..F(S("World position"))..": " ..
- minetest.pos_to_string(waypoint.world_pos or vector.new()) .. "]" ..
- "label[1,1.8;"..F(S("Name"))..": ".. (waypoint.name or default_name) .. "]" ..
- "label[1,2.3;"..F(S("HUD text color"))..": " ..
- hud_colors[waypoint.color or 1][3] .. "]"
+ formspec[n] = string.format("label[%f,%f;%s: %s]",
+ wp_info_x, wp_info_y+1.6, F(S("World position")),
+ minetest.pos_to_string(waypoint.world_pos or vector.new()))
+ formspec[n+1] = string.format("label[%f,%f;%s: %s]",
+ wp_info_x, wp_info_y+2.10, F(S("Name")), (waypoint.name or default_name))
+ formspec[n+2] = string.format("label[%f,%f;%s: %s]",
+ wp_info_x, wp_info_y+2.60, F(S("HUD text color")), hud_colors[waypoint.color or 1][3])
- return {formspec=formspec}
+ return {formspec=table.concat(formspec)}
end,
})
-unified_inventory.register_button("waypoints", {
+ui.register_button("waypoints", {
type = "image",
image = "ui_waypoints_icon.png",
tooltip = S("Waypoints"),
@@ -117,10 +211,12 @@ unified_inventory.register_button("waypoints", {
})
local function update_hud(player, waypoints, temp, i)
- local waypoint = waypoints[i]
+ local waypoint = waypoints.data[i]
if not waypoint then return end
+
temp[i] = temp[i] or {}
temp = temp[i]
+
local pos = waypoint.world_pos or vector.new()
local name
if waypoint.display_pos then
@@ -129,10 +225,13 @@ local function update_hud(player, waypoints, temp, i)
name = name..", "..waypoint.name
end
else
- name = waypoint.name or "Waypoint "..i
+ name = waypoint.name or S("Waypoint @1", i)
end
+
+ -- Perform HUD updates
if temp.hud then
player:hud_remove(temp.hud)
+ temp.hud = nil
end
if waypoint.active then
temp.hud = player:hud_add({
@@ -142,8 +241,6 @@ local function update_hud(player, waypoints, temp, i)
text = "m",
world_pos = pos
})
- else
- temp.hud = nil
end
end
@@ -155,9 +252,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local need_update_hud = false
local hit = false
- local waypoints = datastorage.get(player_name, "waypoints")
+ local waypoints = get_waypoint_data(player)
local temp = waypoints_temp[player_name]
- for i = 1, 5, 1 do
+ for i = 1, COUNT do
+ local waypoint = waypoints.data[i] or {}
+
if fields["select_waypoint"..i] then
hit = true
waypoints.selected = i
@@ -166,20 +265,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields["toggle_waypoint"..i] then
hit = true
- waypoints[i] = waypoints[i] or {}
- waypoints[i].active = not (waypoints[i].active)
+ waypoint.active = not (waypoint.active)
need_update_hud = true
update_formspec = true
end
if fields["set_waypoint"..i] then
hit = true
- local pos = player:get_pos()
- pos.x = math.floor(pos.x)
- pos.y = math.floor(pos.y)
- pos.z = math.floor(pos.z)
- waypoints[i] = waypoints[i] or {}
- waypoints[i].world_pos = pos
+ local pos = vector.round(player:get_pos())
+ waypoint.world_pos = pos
need_update_hud = true
update_formspec = true
end
@@ -193,51 +287,58 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields["toggle_display_pos"..i] then
hit = true
- waypoints[i] = waypoints[i] or {}
- waypoints[i].display_pos = not waypoints[i].display_pos
+ waypoint.display_pos = not waypoint.display_pos
need_update_hud = true
update_formspec = true
end
if fields["toggle_color"..i] then
hit = true
- waypoints[i] = waypoints[i] or {}
- local color = waypoints[i].color or 1
+ local color = waypoint.color or 0
color = color + 1
- if color > hud_colors_max then
+ if color > #hud_colors then
color = 1
end
- waypoints[i].color = color
+ waypoint.color = color
need_update_hud = true
update_formspec = true
end
if fields["confirm_rename"..i] then
hit = true
- waypoints[i] = waypoints[i] or {}
+ temp[i] = temp[i] or {}
temp[i].edit = false
- waypoints[i].name = fields["rename_box"..i]
+ waypoint.name = fields["rename_box"..i]
need_update_hud = true
update_formspec = true
end
+
+ if hit then
+ -- Save first
+ waypoints.data[i] = waypoint
+ set_waypoint_data(player, waypoints)
+ end
+ -- Update after
if need_update_hud then
update_hud(player, waypoints, temp, i)
end
if update_formspec then
- unified_inventory.set_inventory_formspec(player, "waypoints")
+ ui.set_inventory_formspec(player, "waypoints")
end
+
if hit then return end
end
end)
-
-minetest.register_on_joinplayer(function(player)
+-- waypoints_temp must be initialized before the general unified_inventory
+-- joinplayer callback is run for updating the inventory
+table.insert(minetest.registered_on_joinplayers, 1, function(player)
local player_name = player:get_player_name()
- local waypoints = datastorage.get(player_name, "waypoints")
- local temp = {}
- waypoints_temp[player_name] = temp
- for i = 1, 5 do
- update_hud(player, waypoints, temp, i)
+ local waypoints = get_waypoint_data(player)
+
+ waypoints_temp[player_name] = {}
+ for i = 1, COUNT do
+ update_hud(player, waypoints, waypoints_temp[player_name], i)
end
end)