diff --git a/basic_materials/.gitlab-ci.yml b/basic_materials/.gitlab-ci.yml
deleted file mode 100644
index ff51e7e..0000000
--- a/basic_materials/.gitlab-ci.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-stages:
- - test
-
-luacheck:
- stage: test
- image: pipelinecomponents/luacheck:latest
- script:
- - luacheck .
diff --git a/basic_materials/.luacheckrc b/basic_materials/.luacheckrc
deleted file mode 100644
index 55879b0..0000000
--- a/basic_materials/.luacheckrc
+++ /dev/null
@@ -1,30 +0,0 @@
-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
deleted file mode 100644
index c5885ae..0000000
--- a/basic_materials/LICENSE
+++ /dev/null
@@ -1,600 +0,0 @@
-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
deleted file mode 100644
index 91fac4e..0000000
--- a/basic_materials/electrical-electronic.lua
+++ /dev/null
@@ -1,86 +0,0 @@
--- 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
deleted file mode 100644
index 348c059..0000000
--- a/basic_materials/init.lua
+++ /dev/null
@@ -1,15 +0,0 @@
--- 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
deleted file mode 100644
index 8fddd8a..0000000
--- a/basic_materials/locale/basic_materials.de.tr
+++ /dev/null
@@ -1,33 +0,0 @@
-# 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
deleted file mode 100644
index 0bebf79..0000000
--- a/basic_materials/locale/basic_materials.fr.tr
+++ /dev/null
@@ -1,33 +0,0 @@
-# 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
deleted file mode 100644
index aae0b3b..0000000
--- a/basic_materials/locale/basic_materials.it.tr
+++ /dev/null
@@ -1,34 +0,0 @@
-# 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
deleted file mode 100644
index 85e9c0c..0000000
--- a/basic_materials/locale/basic_materials.ru.tr
+++ /dev/null
@@ -1,33 +0,0 @@
-# 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
deleted file mode 100644
index 0a3243b..0000000
--- a/basic_materials/metals.lua
+++ /dev/null
@@ -1,300 +0,0 @@
--- 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
deleted file mode 100644
index 0012897..0000000
--- a/basic_materials/misc.lua
+++ /dev/null
@@ -1,126 +0,0 @@
--- 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
deleted file mode 100644
index 7234bfe..0000000
--- a/basic_materials/mod.conf
+++ /dev/null
@@ -1,4 +0,0 @@
-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
deleted file mode 100644
index 78724c9..0000000
--- a/basic_materials/models/basic_materials_chains.obj
+++ /dev/null
@@ -1,881 +0,0 @@
-# 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
deleted file mode 100644
index e29af53..0000000
--- a/basic_materials/plastics.lua
+++ /dev/null
@@ -1,56 +0,0 @@
--- 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
deleted file mode 100644
index c937800..0000000
Binary files a/basic_materials/textures/basic_materials_brass_block.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_brass_ingot.png b/basic_materials/textures/basic_materials_brass_ingot.png
deleted file mode 100644
index 0bd030a..0000000
Binary files a/basic_materials/textures/basic_materials_brass_ingot.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_cement_block.png b/basic_materials/textures/basic_materials_cement_block.png
deleted file mode 100644
index 6d30f47..0000000
Binary files a/basic_materials/textures/basic_materials_cement_block.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_chain_brass.png b/basic_materials/textures/basic_materials_chain_brass.png
deleted file mode 100644
index e2fb20d..0000000
Binary files a/basic_materials/textures/basic_materials_chain_brass.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_chain_brass_inv.png b/basic_materials/textures/basic_materials_chain_brass_inv.png
deleted file mode 100644
index 8c2d554..0000000
Binary files a/basic_materials/textures/basic_materials_chain_brass_inv.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_chain_steel.png b/basic_materials/textures/basic_materials_chain_steel.png
deleted file mode 100644
index 29af8db..0000000
Binary files a/basic_materials/textures/basic_materials_chain_steel.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_chain_steel_inv.png b/basic_materials/textures/basic_materials_chain_steel_inv.png
deleted file mode 100644
index c552f7b..0000000
Binary files a/basic_materials/textures/basic_materials_chain_steel_inv.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_chainlink_brass.png b/basic_materials/textures/basic_materials_chainlink_brass.png
deleted file mode 100644
index 9a1ad87..0000000
Binary files a/basic_materials/textures/basic_materials_chainlink_brass.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_chainlink_steel.png b/basic_materials/textures/basic_materials_chainlink_steel.png
deleted file mode 100644
index d7132c3..0000000
Binary files a/basic_materials/textures/basic_materials_chainlink_steel.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_concrete_block.png b/basic_materials/textures/basic_materials_concrete_block.png
deleted file mode 100644
index 5dd0d66..0000000
Binary files a/basic_materials/textures/basic_materials_concrete_block.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_copper_strip.png b/basic_materials/textures/basic_materials_copper_strip.png
deleted file mode 100644
index 22e572a..0000000
Binary files a/basic_materials/textures/basic_materials_copper_strip.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_copper_wire.png b/basic_materials/textures/basic_materials_copper_wire.png
deleted file mode 100644
index 9df9f36..0000000
Binary files a/basic_materials/textures/basic_materials_copper_wire.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_empty_spool.png b/basic_materials/textures/basic_materials_empty_spool.png
deleted file mode 100644
index 017a94f..0000000
Binary files a/basic_materials/textures/basic_materials_empty_spool.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_energy_crystal.png b/basic_materials/textures/basic_materials_energy_crystal.png
deleted file mode 100644
index f1c28e8..0000000
Binary files a/basic_materials/textures/basic_materials_energy_crystal.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_gear_steel.png b/basic_materials/textures/basic_materials_gear_steel.png
deleted file mode 100644
index 584f9a5..0000000
Binary files a/basic_materials/textures/basic_materials_gear_steel.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_gold_wire.png b/basic_materials/textures/basic_materials_gold_wire.png
deleted file mode 100644
index 781de7b..0000000
Binary files a/basic_materials/textures/basic_materials_gold_wire.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_heating_element.png b/basic_materials/textures/basic_materials_heating_element.png
deleted file mode 100644
index 42e00b7..0000000
Binary files a/basic_materials/textures/basic_materials_heating_element.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_ic.png b/basic_materials/textures/basic_materials_ic.png
deleted file mode 100644
index 4c88894..0000000
Binary files a/basic_materials/textures/basic_materials_ic.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_motor.png b/basic_materials/textures/basic_materials_motor.png
deleted file mode 100644
index f19ec0a..0000000
Binary files a/basic_materials/textures/basic_materials_motor.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_oil_extract.png b/basic_materials/textures/basic_materials_oil_extract.png
deleted file mode 100644
index e34623d..0000000
Binary files a/basic_materials/textures/basic_materials_oil_extract.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_padlock.png b/basic_materials/textures/basic_materials_padlock.png
deleted file mode 100644
index b05b7ef..0000000
Binary files a/basic_materials/textures/basic_materials_padlock.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_paraffin.png b/basic_materials/textures/basic_materials_paraffin.png
deleted file mode 100644
index 77d2bbd..0000000
Binary files a/basic_materials/textures/basic_materials_paraffin.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_plastic_sheet.png b/basic_materials/textures/basic_materials_plastic_sheet.png
deleted file mode 100644
index 034dcc2..0000000
Binary files a/basic_materials/textures/basic_materials_plastic_sheet.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_plastic_strip.png b/basic_materials/textures/basic_materials_plastic_strip.png
deleted file mode 100644
index 1318dfc..0000000
Binary files a/basic_materials/textures/basic_materials_plastic_strip.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_silicon.png b/basic_materials/textures/basic_materials_silicon.png
deleted file mode 100644
index 847b366..0000000
Binary files a/basic_materials/textures/basic_materials_silicon.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_silver_wire.png b/basic_materials/textures/basic_materials_silver_wire.png
deleted file mode 100644
index a38a45e..0000000
Binary files a/basic_materials/textures/basic_materials_silver_wire.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_steel_bar.png b/basic_materials/textures/basic_materials_steel_bar.png
deleted file mode 100644
index 0673b6e..0000000
Binary files a/basic_materials/textures/basic_materials_steel_bar.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_steel_strip.png b/basic_materials/textures/basic_materials_steel_strip.png
deleted file mode 100644
index 6384dc8..0000000
Binary files a/basic_materials/textures/basic_materials_steel_strip.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_steel_wire.png b/basic_materials/textures/basic_materials_steel_wire.png
deleted file mode 100644
index 0c96c8f..0000000
Binary files a/basic_materials/textures/basic_materials_steel_wire.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_terracotta_base.png b/basic_materials/textures/basic_materials_terracotta_base.png
deleted file mode 100644
index 9f04aad..0000000
Binary files a/basic_materials/textures/basic_materials_terracotta_base.png and /dev/null differ
diff --git a/basic_materials/textures/basic_materials_wet_cement.png b/basic_materials/textures/basic_materials_wet_cement.png
deleted file mode 100644
index 6a7fbf1..0000000
Binary files a/basic_materials/textures/basic_materials_wet_cement.png and /dev/null differ
diff --git a/hyperloop/data_base.lua b/hyperloop/data_base.lua
index 0c7f1f4..ba8e202 100644
--- a/hyperloop/data_base.lua
+++ b/hyperloop/data_base.lua
@@ -54,7 +54,7 @@ minetest.register_on_shutdown(function()
end)
-- delete data base entries without corresponding nodes
-minetest.after(5, check_data_base)
+--minetest.after(5, check_data_base)
-- store data after one hour
minetest.after(60*60, update_mod_storage)
diff --git a/hyperloop/init.lua b/hyperloop/init.lua
index 0b39088..6caafdd 100644
--- a/hyperloop/init.lua
+++ b/hyperloop/init.lua
@@ -35,13 +35,14 @@
2020-03-12 v2.05 minetest translator added (thanks to acmgit/Clyde)
2020-06-14 v2.06 The default value for `hyperloop_free_tube_placement_enabled` is now true
2021-02-07 v2.07 tube_crowbar: Add tube length check
+ 2021-11-01 v2.08 Enable the use of hyperloop networks for other mods
]]--
hyperloop = {}
-- Version for compatibility checks, see history
-hyperloop.version = 2.06
+hyperloop.version = 2.08
if minetest.global_exists("techage") and techage.version < 0.06 then
error("[hyperloop] Hyperloop requires techage version 0.06 or newer!")
@@ -71,7 +72,7 @@ else
hyperloop.wifi_enabled = minetest.settings:get_bool("hyperloop_wifi_enabled")
hyperloop.wifi_crafting_enabled = minetest.settings:get_bool("hyperloop_wifi_crafting_enabled")
hyperloop.free_tube_placement_enabled = minetest.settings:get_bool("hyperloop_free_tube_placement_enabled", true)
- hyperloop.subnet_enabled = minetest.settings:get_bool("hyperloop_subnet_enabled")
+ hyperloop.subnet_enabled = minetest.settings:get_bool("hyperloop_subnet_enabled", true)
dofile(minetest.get_modpath("hyperloop") .. "/network.lua")
dofile(minetest.get_modpath("hyperloop") .. "/data_base.lua")
diff --git a/hyperloop/junction.lua b/hyperloop/junction.lua
index 47be4b6..f504521 100644
--- a/hyperloop/junction.lua
+++ b/hyperloop/junction.lua
@@ -28,12 +28,18 @@ Tube:register_on_tube_update(function(node, pos, out_dir, peer_pos, peer_in_dir)
if out_dir <= 5 then
Stations:update_connections(pos, out_dir, peer_pos)
local s = hyperloop.get_connection_string(pos)
- M(pos):set_string("infotext", S("Station connected with ")..s)
+ M(pos):set_string("infotext", S("Station connected to ")..s)
end
elseif node.name == "hyperloop:junction" then
Stations:update_connections(pos, out_dir, peer_pos)
local s = hyperloop.get_connection_string(pos)
- M(pos):set_string("infotext", S("Junction connected with ")..s)
+ M(pos):set_string("infotext", S("Junction connected to ")..s)
+ elseif Tube.secondary_node_names[node.name] then
+ if out_dir == 5 then
+ Stations:update_connections(pos, out_dir, peer_pos)
+ local s = hyperloop.get_connection_string(pos)
+ M(pos):set_string("conn_to", s)
+ end
end
end)
diff --git a/hyperloop/locale/hyperloop.de.tr b/hyperloop/locale/hyperloop.de.tr
index fc27f03..26d842d 100644
--- a/hyperloop/locale/hyperloop.de.tr
+++ b/hyperloop/locale/hyperloop.de.tr
@@ -57,8 +57,8 @@ Save=Speichern
### junction.lua ###
-Station connected with =Station verbunden mit
-Junction connected with =Anschlussstelle verbunden mit
+Station connected to =Station verbunden mit
+Junction connected to =Anschlussstelle verbunden mit
Hyperloop Junction Block=Hyperloop Anschlussstelle
Hyperloop Pillar=Hyperloop Stütze
@@ -77,7 +77,7 @@ Dist.=Entf.
Station/Junction=Station/Anschlussstelle
Position=Position
Owner=Besitzer
-Conn. with=Verb. mit
+Conn. to=Verb. mit
Close=Schließen
Hyperloop Station Book=Hyperloop Stationsbuch
diff --git a/hyperloop/map.lua b/hyperloop/map.lua
index c875268..9c292e6 100644
--- a/hyperloop/map.lua
+++ b/hyperloop/map.lua
@@ -37,7 +37,7 @@ local function generate_string(sortedList)
"label[1.8,0;"..S("Station/Junction").."]"..
"label[5.4,0;"..S("Position").."]"..
"label[7.9,0;"..S("Owner").."]"..
- "label[10,0;"..S("Conn. with").."]"}
+ "label[10,0;"..S("Conn. to").."]"}
for idx,dataSet in ipairs(sortedList) do
if idx == 23 then
break
diff --git a/hyperloop/network.lua b/hyperloop/network.lua
index ae08c19..aaa9659 100644
--- a/hyperloop/network.lua
+++ b/hyperloop/network.lua
@@ -278,3 +278,11 @@ function Network:serialize()
return minetest.serialize(self)
end
+-- Return a pos/item table with all network nodes, the node at pos is connected with
+function Network:get_node_table(pos)
+ local tRes = {}
+ local key = S(pos)
+ get_stations(self.tStations, key, tRes)
+ tRes[key] = nil
+ return tRes
+end
diff --git a/hyperloop/settingtypes.txt b/hyperloop/settingtypes.txt
index 2c2e90e..771bf66 100644
--- a/hyperloop/settingtypes.txt
+++ b/hyperloop/settingtypes.txt
@@ -12,4 +12,4 @@ hyperloop_free_tube_placement_enabled (free tube placement enabled) bool false
# The ticket block has an additional field for specifying a subnet name.
# Stations with the same subnet name (optional) represent an isolated
# subnet within the Hyperloop network.
-hyperloop_subnet_enabled (enable building of subnets) bool false
\ No newline at end of file
+hyperloop_subnet_enabled (enable building of subnets) bool true
\ No newline at end of file
diff --git a/minecart/baselib.lua b/minecart/baselib.lua
index 06b96b6..53bd7ad 100644
--- a/minecart/baselib.lua
+++ b/minecart/baselib.lua
@@ -256,7 +256,12 @@ function minecart.add_nodecart(pos, node_name, param2, cargo, owner, userID)
if not minecart.is_rail(pos) then
pos2 = minetest.find_node_near(pos, 1, minecart.lRails)
if not pos2 or not minecart.is_rail(pos2) then
- pos2 = minetest.find_node_near(pos, 2, minecart.lRails)
+ -- If no rail is around, use an available cart as new search center
+ pos2 = minetest.find_node_near(pos, 1, minecart.lRailsExt)
+ -- ...and search again.
+ if pos2 then
+ pos2 = minetest.find_node_near(pos2, 1, minecart.lRails)
+ end
end
else
pos2 = vector.new(pos)
diff --git a/minecart/entitylib.lua b/minecart/entitylib.lua
index 94c99c1..5c1cbd2 100644
--- a/minecart/entitylib.lua
+++ b/minecart/entitylib.lua
@@ -217,9 +217,20 @@ local function on_step(self, dtime)
recording_waypoints(self)
self.rec_time = self.rec_time + 2.0
end
- recording_junctions(self)
+ if recording_junctions(self) then
+ local pos = vector.round(self.object:get_pos())
+ minecart.stop_recording(self, pos, true)
+ local player = minetest.get_player_by_name(self.driver)
+ minecart.manage_attachment(player, self, false)
+ minecart.entity_to_node(pos, self)
+ end
else
- player_ctrl(self)
+ if player_ctrl(self) then
+ local pos = vector.round(self.object:get_pos())
+ local player = minetest.get_player_by_name(self.driver)
+ minecart.manage_attachment(player, self, false)
+ minecart.entity_to_node(pos, self)
+ end
end
end
end
@@ -241,7 +252,7 @@ local function on_entitycard_punch(self, puncher, time_from_last_punch, tool_cap
-- Dig cart
if self.driver then
-- remove cart as driver
- minecart.stop_recording(self, pos)
+ minecart.stop_recording(self, pos, true)
minecart.monitoring_remove_cart(self.owner, self.userID)
minecart.remove_entity(self, pos, puncher)
minecart.manage_attachment(puncher, self, false)
@@ -273,12 +284,13 @@ local function on_entitycard_rightclick(self, clicker)
if self.driver then
-- get off
local pos = vector.round(self.object:get_pos())
+ minecart.stop_recording(self, pos, true)
minecart.manage_attachment(clicker, self, false)
minecart.entity_to_node(pos, self)
else
-- get on
local pos = vector.round(self.object:get_pos())
- minecart.stop_recording(self, pos)
+ minecart.stop_recording(self, pos, true)
minecart.manage_attachment(clicker, self, true)
end
end
diff --git a/minecart/monitoring.lua b/minecart/monitoring.lua
index 2956f88..82e3b03 100644
--- a/minecart/monitoring.lua
+++ b/minecart/monitoring.lua
@@ -213,7 +213,9 @@ function minecart.monitoring_remove_cart(owner, userID)
if tCartsOnRail[owner] and tCartsOnRail[owner][userID] then
-- Cart stopped?
if tCartsOnRail[owner][userID].objID == 0 then
- -- Can directly be deleted
+ -- Mark as "to be deleted" by monitoring (if part of monitoring)
+ tCartsOnRail[owner][userID].objID = nil
+ -- And delete directly in addition
tCartsOnRail[owner][userID] = nil
else -- Cart running
-- Mark as "to be deleted" by monitoring
@@ -292,7 +294,7 @@ minetest.register_chatcommand("stopcart", {
minecart.remove_entity(entity, data.pos)
else
-- Cart as zombie/invalid/corrupted
- -- nothing to do
+ minetest.log("warning", "[Minecart] data.objID ~= 0, but no entity available!")
end
minetest.add_item(player_pos, ItemStack({name = data.node_name}))
minecart.monitoring_remove_cart(owner, userID)
diff --git a/minecart/recording.lua b/minecart/recording.lua
index d55e30a..5b93fee 100644
--- a/minecart/recording.lua
+++ b/minecart/recording.lua
@@ -103,12 +103,14 @@ function minecart.start_recording(self, pos)
end
end
-function minecart.stop_recording(self, pos)
+function minecart.stop_recording(self, pos, force_exit)
--print("stop_recording")
if self.driver and self.is_recording then
local dest_pos = minecart.get_buffer_pos(pos, self.driver)
local player = minetest.get_player_by_name(self.driver)
- if dest_pos and player and #self.checkpoints > 3 then
+ if force_exit then
+ minetest.chat_send_player(self.driver, S("[minecart] Recording canceled!"))
+ elseif dest_pos and player and #self.checkpoints > 3 then
-- Remove last checkpoint, because it is potentially too close to the dest_pos
table.remove(self.checkpoints)
if self.start_pos then
@@ -163,6 +165,8 @@ function minecart.recording_junctions(self)
self.ctrl = {right = true}
elseif ctrl.up or ctrl.down then
self.ctrl = nil
+ elseif ctrl.jump then
+ return true
end
end
if self.hud_time <= self.timebase then
@@ -186,6 +190,8 @@ function minecart.player_ctrl(self)
self.ctrl = {left = true}
elseif ctrl.right then
self.ctrl = {right = true}
+ elseif ctrl.jump then
+ return true
end
end
end
diff --git a/minecart/storage.lua b/minecart/storage.lua
index 54f7a48..1ac383f 100644
--- a/minecart/storage.lua
+++ b/minecart/storage.lua
@@ -57,8 +57,8 @@ minetest.register_on_mods_loaded(function()
-- mark all entity carts as zombified
if cart.objID ~= 0 then
cart.objID = -1
- minecart.push(1, cart)
end
+ minecart.push(1, cart)
end
end
end
diff --git a/safer_lua/environ.lua b/safer_lua/environ.lua
index f038f4f..09edbb6 100644
--- a/safer_lua/environ.lua
+++ b/safer_lua/environ.lua
@@ -61,11 +61,14 @@ local BASE_ENV = {
if separator == "" then separator = " " end
return safer_lua.Array(unpack(string.split(str, separator, include_empty, max_splits, sep_is_pattern)))
end,
+ split2 = function(str, separator, include_empty, max_splits, sep_is_pattern)
+ if separator == "" then separator = " " end
+ return unpack(string.split(str, separator, include_empty, max_splits, sep_is_pattern))
+ end,
trim = string.trim,
},
tonumber = tonumber,
tostring = tostring,
- unpack = unpack,
type = type,
ticks = 0,
}
diff --git a/safer_lua/init.lua b/safer_lua/init.lua
index 0dde11d..e607168 100644
--- a/safer_lua/init.lua
+++ b/safer_lua/init.lua
@@ -15,7 +15,7 @@
safer_lua = {}
-- Version for compatibility checks, see readme.md/history
-safer_lua.version = 1.0
+safer_lua.version = 1.01
dofile(minetest.get_modpath("safer_lua") .. "/data_struct.lua")
dofile(minetest.get_modpath("safer_lua") .. "/scanner.lua")
diff --git a/safer_lua/readme.md b/safer_lua/readme.md
index e157656..eb6bde8 100644
--- a/safer_lua/readme.md
+++ b/safer_lua/readme.md
@@ -8,7 +8,7 @@ A subset of the language Lua for safe and secure Lua sandboxes with:
- limited posibilities to call functions
### License
-Copyright (C) 2018-2020 Joachim Stolberg
+Copyright (C) 2018-2021 Joachim Stolberg
Code: Licensed under the GNU LGPL version 2.1 or later. See LICENSE.txt
@@ -18,3 +18,4 @@ none
### History
- 2018-06-24 v0.01 * first draft
- 2020-03-14 v1.00 * extracted from TechPack and released
+- 2021-11-28 v1.01 * function `string.split2` added, `unpack` removed
diff --git a/signs_bot/basis.lua b/signs_bot/basis.lua
index 893d413..ef5e1c3 100644
--- a/signs_bot/basis.lua
+++ b/signs_bot/basis.lua
@@ -199,6 +199,12 @@ function signs_bot.infotext(pos, state)
meta:set_string("infotext", S("Robot Box").." "..number..": "..state)
end
+local function free_start_pos(pos, mem)
+ local param2 = (minetest.get_node(pos).param2 + 1) % 4
+ local robot_pos = lib.next_pos(pos, param2, 1)
+ return signs_bot.lib.is_air_like(robot_pos)
+end
+
local function reset_robot(pos, mem)
mem.robot_param2 = (minetest.get_node(pos).param2 + 1) % 4
mem.robot_pos = lib.next_pos(pos, mem.robot_param2, 1)
@@ -208,24 +214,26 @@ end
function signs_bot.start_robot(base_pos)
local mem = tubelib2.get_mem(base_pos)
- mem.steps = nil
- mem.script = "cond_move"
- local meta = M(base_pos)
- signs_bot.reset(base_pos, mem)
- mem.running = true
- mem.charging = false
- mem.error = false
- mem.stored_node = nil
- if minetest.global_exists("techage") then
- mem.capa = mem.capa or 0 -- enable power consumption
- else
- mem.capa = nil
+ if free_start_pos(base_pos, mem) then
+ mem.steps = nil
+ mem.script = "cond_move"
+ local meta = M(base_pos)
+ signs_bot.reset(base_pos, mem)
+ mem.running = true
+ mem.charging = false
+ mem.error = false
+ mem.stored_node = nil
+ if minetest.global_exists("techage") then
+ mem.capa = mem.capa or 0 -- enable power consumption
+ else
+ mem.capa = nil
+ end
+ meta:set_string("formspec", formspec(base_pos, mem))
+ signs_bot.infotext(base_pos, S("running"))
+ reset_robot(base_pos, mem)
+ minetest.get_node_timer(base_pos):start(CYCLE_TIME)
+ return true
end
- meta:set_string("formspec", formspec(base_pos, mem))
- signs_bot.infotext(base_pos, S("running"))
- reset_robot(base_pos, mem)
- minetest.get_node_timer(base_pos):start(CYCLE_TIME)
- return true
end
function signs_bot.stop_robot(base_pos, mem)
diff --git a/signs_bot/cmd_item.lua b/signs_bot/cmd_item.lua
index 4ed7d70..61dde86 100644
--- a/signs_bot/cmd_item.lua
+++ b/signs_bot/cmd_item.lua
@@ -239,17 +239,19 @@ signs_bot.register_botcommand("drop_items", {
end,
})
-signs_bot.register_botcommand("punch_cart", {
- mod = "item",
- params = "",
- num_param = 0,
- description = S("Punch a rail cart to start it"),
- cmnd = function(base_pos, mem)
- local punch_dir = minetest.facedir_to_dir(mem.robot_param2)
- minecart.punch_cart(mem.robot_pos, mem.robot_param2, 1, punch_dir)
- return signs_bot.DONE
- end,
-})
+if minetest.global_exists("minecart") then
+ signs_bot.register_botcommand("punch_cart", {
+ mod = "item",
+ params = "",
+ num_param = 0,
+ description = S("Punch a rail cart to start it"),
+ cmnd = function(base_pos, mem)
+ local punch_dir = minetest.facedir_to_dir(mem.robot_param2)
+ minecart.punch_cart(mem.robot_pos, mem.robot_param2, 1, punch_dir)
+ return signs_bot.DONE
+ end,
+ })
+end
-- def is a table with following data:
-- {
diff --git a/signs_bot/init.lua b/signs_bot/init.lua
index 30e9c7c..e02652c 100644
--- a/signs_bot/init.lua
+++ b/signs_bot/init.lua
@@ -65,7 +65,9 @@ dofile(MP.."/nodes.lua")
dofile(MP.."/bot_sensor.lua")
dofile(MP.."/node_sensor.lua")
dofile(MP.."/crop_sensor.lua")
-dofile(MP.."/cart_sensor.lua")
+if minetest.global_exists("minecart") then
+ dofile(MP.."/cart_sensor.lua")
+end
dofile(MP.."/chest.lua")
dofile(MP.."/legacy.lua")
dofile(MP.."/techage.lua")
diff --git a/signs_bot/signs.lua b/signs_bot/signs.lua
index aa20777..2818dd9 100644
--- a/signs_bot/signs.lua
+++ b/signs_bot/signs.lua
@@ -195,7 +195,7 @@ minetest.register_craft({
}
})
-if minetest.get_modpath("minecart") then
+if minetest.global_exists("minecart") then
register_sign({
name = "sign_add_cart",
description = S('Sign "add to cart"'),
@@ -273,7 +273,7 @@ if minetest.get_modpath("doc") then
})
end
-if minetest.get_modpath("doc") and minetest.get_modpath("minecart") then
+if minetest.get_modpath("doc") and minetest.global_exists("minecart") then
doc.add_entry("signs_bot", "sign_add_cart", {
name = S('Sign "add to cart"'),
data = {
diff --git a/techage/README.md b/techage/README.md
index 024dba7..69914bd 100644
--- a/techage/README.md
+++ b/techage/README.md
@@ -1,6 +1,6 @@
-# Tech Age [techage] (Minetest 5.3+)
+# Tech Age [techage] (Minetest 5.4+)
-Tech Age, a mod to go through 4 tech ages in search of wealth and power.
+Tech Age, a mod to go through 5 tech ages in search of wealth and power.
**Tech Age (techage) is the successor to TechPack V2, at first glance similar and yet completely different!**
@@ -11,13 +11,12 @@ Tech Age, a mod to go through 4 tech ages in search of wealth and power.
Important facts:
- techage is not backwards compatible and cannot be installed on a server together with TechPack
- techage is significantly more extensive, since additional mods are integrated
-- techage represents 4 technological ages:
+- techage represents 5 technological ages:
- Iron Age (TA1) - simple tools like coal pile, coal burner, gravel sieve, hammer for getting ores and making goods
- Steam Age (TA2) - Simple machines that are powered by steam engines and drive axles
- Oil Age (TA3) - More modern machines that are powered by electricity.
- The electricity is generated by coal & oil power plants. The oil must be explored, extracted and transported.
- - Future Age (TA4) - Electricity from renewable energy sources such as sun and wind.
- Environmentally friendly electricity storage, intelligent machines and means of transport of the future
+ - Present (TA4) - Electricity from renewable energy sources such as sun and wind.
+ - Future (TA5) - Machines to overcome space and time, new sources of energy and other achievements.
- Since the levels build on each other, all ages have to be run through one after the other
In contrast to TechPack, the resources are more limited and it is much more difficult to pass all levels.
@@ -81,6 +80,20 @@ Available worlds will be converted to 'lsqlite3', but there is no way back, so:
### History
+**2022-01-03 V1.06**
+- TA5 teleport blocks added
+- Many improvements
+
+**2021-12-25 V1.05**
+- Support for the mod i3 added (thanks to ghaydn)
+- TA5 enabled
+- Many improvements
+
+**2021-12-12 V1.04**
+- TA4 Collider added (experimental)
+- move, turn, sound, and fly blocks added
+- TA5 (future) introduced (TA4 is now the "present")
+
**2021-10-24 V1.03**
- Add TA4 Sequencer for time controlled command sequences
- Add TA4 Move Controller for moving blocks
diff --git a/techage/basic_machines/autocrafter.lua b/techage/basic_machines/autocrafter.lua
index 4f6fd85..5a0e733 100644
--- a/techage/basic_machines/autocrafter.lua
+++ b/techage/basic_machines/autocrafter.lua
@@ -189,6 +189,17 @@ local function normalize(item_list)
return item_list
end
+local function get_input_from_recipeblock(pos, number, idx)
+ local own_num = M(pos):get_string("node_number")
+ local owner = M(pos):get_string("owner")
+ if techage.check_numbers(number, owner) then
+ local input = techage.send_single(own_num, number, "input", idx)
+ if input and type(input) == "string" then
+ return input
+ end
+ end
+end
+
local function on_output_change(pos, inventory, stack)
if not stack then
inventory:set_list("output", {})
@@ -212,6 +223,47 @@ local function on_output_change(pos, inventory, stack)
after_recipe_change(pos, inventory)
end
+local function determine_recipe_items(pos, input)
+ if input and type(input) == "string" then
+ -- Test if "." input
+ local num, idx = unpack(string.split(input, ".", false, 1))
+ if num and idx then
+ input = get_input_from_recipeblock(pos, num, idx)
+ end
+
+ if input then
+ -- "- ,
- ,..." input
+ local items = string.split(input, ",", true, 8)
+ if items and type(items) == "table" and next(items) then
+ return items
+ end
+ end
+ end
+end
+
+local function on_new_recipe(pos, input)
+ local items = determine_recipe_items(pos, input)
+ if items then
+ input = {
+ method = "normal",
+ width = 3,
+ items = items,
+ }
+ local output, _ = minetest.get_craft_result(input)
+ if output.item:get_name() ~= "" then
+ local inv = M(pos):get_inventory()
+ for i = 1, 9 do
+ inv:set_stack("recipe", i, input.items[i])
+ end
+ after_recipe_change(pos, inv)
+ end
+ else
+ local inv = M(pos):get_inventory()
+ inv:set_list("recipe", {})
+ after_recipe_change(pos, inv)
+ end
+end
+
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
@@ -346,6 +398,8 @@ tiles.act = {
},
}
+local INFO = [[Commands: 'state', 'recipe']]
+
local tubing = {
on_inv_request = function(pos, in_dir, access_type)
if access_type == "push" then
@@ -378,7 +432,20 @@ local tubing = {
end
end,
on_recv_message = function(pos, src, topic, payload)
- return CRD(pos).State:on_receive_message(pos, topic, payload)
+ if topic == "recipe" and CRD(pos).stage == 4 then
+ if payload and payload ~= "" then
+ local inv = M(pos):get_inventory()
+ on_new_recipe(pos, payload)
+ return true
+ else
+ local inv = M(pos):get_inventory()
+ return inv:get_stack("output", 1):get_name()
+ end
+ elseif topic == "info" and CRD(pos).stage == 4 then
+ return INFO
+ else
+ return CRD(pos).State:on_receive_message(pos, topic, payload)
+ end
end,
on_node_load = function(pos)
CRD(pos).State:on_node_load(pos)
@@ -410,7 +477,7 @@ local node_name_ta2, node_name_ta3, node_name_ta4 =
num_items = {0,1,2,4},
power_consumption = {0,4,6,9},
},
- {false, true, true, false}) -- TA2/TA3
+ {false, true, true, true}) -- TA2/TA3/TA4
minetest.register_craft({
output = node_name_ta2,
@@ -430,9 +497,18 @@ minetest.register_craft({
},
})
+minetest.register_craft({
+ output = node_name_ta4,
+ recipe = {
+ {"", "default:diamond", ""},
+ {"", node_name_ta3, ""},
+ {"", "techage:ta4_wlanchip", ""},
+ },
+})
+
local Cable = techage.ElectricCable
local power = networks.power
-techage.register_node_for_v1_transition({"techage:ta3_autocrafter_pas"}, function(pos, node)
+techage.register_node_for_v1_transition({"techage:ta3_autocrafter_pas", "techage:ta4_autocrafter_pas"}, function(pos, node)
power.update_network(pos, nil, Cable)
-end)
\ No newline at end of file
+end)
diff --git a/techage/basic_machines/chest.lua b/techage/basic_machines/chest.lua
index 36312cc..5d66ffa 100644
--- a/techage/basic_machines/chest.lua
+++ b/techage/basic_machines/chest.lua
@@ -45,6 +45,7 @@ end
local function after_dig_node(pos, oldnode, oldmetadata, digger)
techage.remove_node(pos, oldnode, oldmetadata)
+ techage.del_mem(pos)
end
local function formspec2()
diff --git a/techage/basic_machines/consumer.lua b/techage/basic_machines/consumer.lua
index d132ce5..f745a59 100644
--- a/techage/basic_machines/consumer.lua
+++ b/techage/basic_machines/consumer.lua
@@ -3,14 +3,14 @@
TechAge
=======
- Copyright (C) 2019-2020 Joachim Stolberg
+ Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
Consumer node basis functionality.
It handles:
- - up to 3 stages of nodes (TA2/TA3/TA4)
+ - up to 4 stages of nodes (TA2/TA3/TA4/TA5)
- power consumption
- node state handling
- registration of passive and active nodes
@@ -119,7 +119,7 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
if not node_name_prefix then
node_name_prefix = "techage:ta"
end
- for stage = 2,4 do
+ for stage = 2,5 do
local name_pas = node_name_prefix..stage.."_"..base_name.."_pas"
local name_act = node_name_prefix..stage.."_"..base_name.."_act"
local name_inv = "TA"..stage.." "..inv_name
@@ -178,6 +178,7 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
local node = minetest.get_node(pos)
meta:set_int("push_dir", techage.side_to_indir("L", node.param2))
meta:set_int("pull_dir", techage.side_to_indir("R", node.param2))
+ meta:set_string("owner", placer:get_player_name())
-- Delete existing node number. Needed for Digtron compatibility.
if (meta:contains("node_number")) then
meta:set_string("node_number", "")
@@ -298,5 +299,5 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
end
end
end
- return names[1], names[2], names[3]
+ return names[1], names[2], names[3], names[4]
end
diff --git a/techage/basic_machines/electronic_fab.lua b/techage/basic_machines/electronic_fab.lua
index b73318f..96a875b 100644
--- a/techage/basic_machines/electronic_fab.lua
+++ b/techage/basic_machines/electronic_fab.lua
@@ -32,21 +32,19 @@ local RecipeType = {
local function formspec(self, pos, nvm)
local rtype = RecipeType[CRD(pos).stage]
+ local owner = M(pos):get_string("owner")
return "size[8.4,8.4]"..
- default.gui_bg..
- default.gui_bg_img..
- default.gui_slots..
- "list[context;src;0,0;2,4;]"..
- recipes.formspec(2.2, 0, rtype, nvm)..
- "list[context;dst;6.4,0;2,4;]"..
- "image_button[3.7,3.3;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
- "tooltip[3.7,3.3;1,1;"..self:get_state_tooltip(nvm).."]"..
- "list[current_player;main;0.2,4.5;8,4;]"..
- "listring[context;dst]"..
- "listring[current_player;main]"..
- "listring[context;src]"..
- "listring[current_player;main]"..
- default.get_hotbar_bg(0.2, 4.5)
+ "list[context;src;0,0;2,4;]"..
+ recipes.formspec(2.2, 0, rtype, nvm, owner)..
+ "list[context;dst;6.4,0;2,4;]"..
+ "image_button[3.7,3.3;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
+ "tooltip[3.7,3.3;1,1;"..self:get_state_tooltip(nvm).."]"..
+ "list[current_player;main;0.2,4.5;8,4;]"..
+ "listring[context;dst]"..
+ "listring[current_player;main]"..
+ "listring[context;src]"..
+ "listring[current_player;main]"..
+ default.get_hotbar_bg(0.2, 4.5)
end
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
@@ -261,24 +259,22 @@ minetest.register_craft({
},
})
-if minetest.global_exists("unified_inventory") then
- unified_inventory.register_craft_type("ta2_electronic_fab", {
- description = S("TA2 Ele Fab"),
- icon = 'techage_filling_ta2.png^techage_appl_electronic_fab.png^techage_frame_ta2.png',
- width = 2,
- height = 2,
- })
- unified_inventory.register_craft_type("ta3_electronic_fab", {
- description = S("TA3 Ele Fab"),
- icon = 'techage_filling_ta3.png^techage_appl_electronic_fab.png^techage_frame_ta3.png',
- width = 2,
- height = 2,
- })
- unified_inventory.register_craft_type("ta4_electronic_fab", {
- description = S("TA4 Ele Fab"),
- icon = 'techage_filling_ta4.png^techage_appl_electronic_fab.png^techage_frame_ta4.png',
- width = 2,
- height = 2,
- })
-end
+techage.recipes.register_craft_type("ta2_electronic_fab", {
+ description = S("TA2 Ele Fab"),
+ icon = 'techage_filling_ta2.png^techage_appl_electronic_fab.png^techage_frame_ta2.png',
+ width = 2,
+ height = 2,
+})
+techage.recipes.register_craft_type("ta3_electronic_fab", {
+ description = S("TA3 Ele Fab"),
+ icon = 'techage_filling_ta3.png^techage_appl_electronic_fab.png^techage_frame_ta3.png',
+ width = 2,
+ height = 2,
+})
+techage.recipes.register_craft_type("ta4_electronic_fab", {
+ description = S("TA4 Ele Fab"),
+ icon = 'techage_filling_ta4.png^techage_appl_electronic_fab.png^techage_frame_ta4.png',
+ width = 2,
+ height = 2,
+})
diff --git a/techage/basic_machines/gravelrinser.lua b/techage/basic_machines/gravelrinser.lua
index 1d91dd9..3df776f 100644
--- a/techage/basic_machines/gravelrinser.lua
+++ b/techage/basic_machines/gravelrinser.lua
@@ -317,22 +317,18 @@ minetest.register_craft({
})
-if minetest.global_exists("unified_inventory") then
- unified_inventory.register_craft_type("rinsing", {
- description = S("Rinsing"),
- icon = "techage_appl_rinser_top.png^techage_frame_ta2_top.png",
- width = 2,
- height = 2,
- })
-end
+techage.recipes.register_craft_type("rinsing", {
+ description = S("Rinsing"),
+ icon = "techage_appl_rinser_top.png^techage_frame_ta2_top.png",
+ width = 2,
+ height = 2,
+})
function techage.add_rinser_recipe(recipe)
Probability[recipe.output] = recipe.probability
- if minetest.global_exists("unified_inventory") then
- recipe.items = {recipe.input}
- recipe.type = "rinsing"
- unified_inventory.register_craft(recipe)
- end
+ recipe.items = {recipe.input}
+ recipe.type = "rinsing"
+ techage.recipes.register_craft(recipe)
end
techage.add_rinser_recipe({input="techage:sieved_gravel", output="techage:usmium_nuggets", probability=30})
diff --git a/techage/basic_machines/gravelsieve.lua b/techage/basic_machines/gravelsieve.lua
index 0bd9aa4..3152d3c 100644
--- a/techage/basic_machines/gravelsieve.lua
+++ b/techage/basic_machines/gravelsieve.lua
@@ -246,38 +246,36 @@ minetest.register_craft({
},
})
-if minetest.global_exists("unified_inventory") then
- unified_inventory.register_craft_type("ta2_gravelsieve", {
- description = S("TA2 Gravel Sieve"),
- icon = 'techage_sieve_sieve_ta1.png',
- width = 1,
- height = 1,
- })
- unified_inventory.register_craft_type("ta3_gravelsieve", {
- description = S("TA3 Gravel Sieve"),
- icon = 'techage_filling_ta3.png^techage_appl_sieve.png^techage_frame_ta3.png',
- width = 1,
- height = 1,
- })
- unified_inventory.register_craft_type("ta4_gravelsieve", {
- description = S("TA4 Gravel Sieve"),
- icon = 'techage_filling_ta4.png^techage_appl_sieve.png^techage_frame_ta4.png',
- width = 1,
- height = 1,
- })
- unified_inventory.register_craft({
- output = "techage:sieved_basalt_gravel",
- items = {"techage:basalt_gravel"},
- type = "ta2_gravelsieve",
- })
- unified_inventory.register_craft({
- output = "techage:sieved_basalt_gravel",
- items = {"techage:basalt_gravel"},
- type = "ta3_gravelsieve",
- })
- unified_inventory.register_craft({
- output = "techage:sieved_basalt_gravel",
- items = {"techage:basalt_gravel"},
- type = "ta4_gravelsieve",
- })
-end
+techage.recipes.register_craft_type("ta2_gravelsieve", {
+ description = S("TA2 Gravel Sieve"),
+ icon = 'techage_sieve_sieve_ta1.png',
+ width = 1,
+ height = 1,
+})
+techage.recipes.register_craft_type("ta3_gravelsieve", {
+ description = S("TA3 Gravel Sieve"),
+ icon = 'techage_filling_ta3.png^techage_appl_sieve.png^techage_frame_ta3.png',
+ width = 1,
+ height = 1,
+})
+techage.recipes.register_craft_type("ta4_gravelsieve", {
+ description = S("TA4 Gravel Sieve"),
+ icon = 'techage_filling_ta4.png^techage_appl_sieve.png^techage_frame_ta4.png',
+ width = 1,
+ height = 1,
+})
+techage.recipes.register_craft({
+ output = "techage:sieved_basalt_gravel",
+ items = {"techage:basalt_gravel"},
+ type = "ta2_gravelsieve",
+})
+techage.recipes.register_craft({
+ output = "techage:sieved_basalt_gravel",
+ items = {"techage:basalt_gravel"},
+ type = "ta3_gravelsieve",
+})
+techage.recipes.register_craft({
+ output = "techage:sieved_basalt_gravel",
+ items = {"techage:basalt_gravel"},
+ type = "ta4_gravelsieve",
+})
diff --git a/techage/basic_machines/grinder.lua b/techage/basic_machines/grinder.lua
index 9cf8dcd..ec20d1a 100644
--- a/techage/basic_machines/grinder.lua
+++ b/techage/basic_machines/grinder.lua
@@ -351,20 +351,18 @@ minetest.register_craft({
},
})
-if minetest.global_exists("unified_inventory") then
- unified_inventory.register_craft_type("grinding", {
- description = S("Grinding"),
- icon = 'techage_appl_grinder.png',
- width = 2,
- height = 2,
- })
- unified_inventory.register_craft_type("milling", {
- description = S("Milling"),
- icon = 'techage_mill_inv.png',
- width = 2,
- height = 2,
- })
-end
+techage.recipes.register_craft_type("grinding", {
+ description = S("Grinding"),
+ icon = 'techage_appl_grinder.png',
+ width = 2,
+ height = 2,
+})
+techage.recipes.register_craft_type("milling", {
+ description = S("Milling"),
+ icon = 'techage_mill_inv.png',
+ width = 2,
+ height = 2,
+})
function techage.add_grinder_recipe(recipe, ta1_permitted)
local name, num = unpack(string.split(recipe.input, " ", false, 1))
@@ -372,20 +370,16 @@ function techage.add_grinder_recipe(recipe, ta1_permitted)
if ta1_permitted then
RecipesTa1[name] = {input = name,inp_num = tonumber(num) or 1, output = recipe.output}
- if minetest.global_exists("unified_inventory") then
- recipe.items = {recipe.input}
- recipe.type = "milling"
- unified_inventory.register_craft(table.copy(recipe))
- end
+ recipe.items = {recipe.input}
+ recipe.type = "milling"
+ techage.recipes.register_craft(table.copy(recipe))
end
Recipes[name] = {input = name,inp_num = tonumber(num) or 1, output = recipe.output}
- if minetest.global_exists("unified_inventory") then
- recipe.items = {recipe.input}
- recipe.type = "grinding"
- unified_inventory.register_craft(recipe)
- end
+ recipe.items = {recipe.input}
+ recipe.type = "grinding"
+ techage.recipes.register_craft(recipe)
end
end
diff --git a/techage/basic_machines/recipeblock.lua b/techage/basic_machines/recipeblock.lua
new file mode 100644
index 0000000..3e34cc5
--- /dev/null
+++ b/techage/basic_machines/recipeblock.lua
@@ -0,0 +1,244 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2019-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Recipe Block for the TA4 Autocrafter
+]]--
+
+-- for lazy programmers
+local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
+local S2P = minetest.string_to_pos
+local M = minetest.get_meta
+local S = techage.S
+
+local MAX_RECIPE = 10
+
+local function recipes_formspec(x, y, idx)
+ return "container[" .. x .. "," .. y .. "]" ..
+ "background[0,0;8,3.2;techage_form_grey.png]" ..
+ "list[context;input;0.1,0.1;3,3;]" ..
+ "image[3,1.1;1,1;techage_form_arrow.png]" ..
+ "list[context;output;3.9,1.1;1,1;]" ..
+ "button[5.5,1.1;1,1;priv;<<]" ..
+ "button[6.5,1.1;1,1;next;>>]" ..
+ "label[5.5,0.5;"..S("Recipe") .. ": " .. idx .. "/" .. MAX_RECIPE .. "]" ..
+ "container_end[]"
+end
+
+local function formspec(pos, nvm)
+ return "size[8,7.4]"..
+ recipes_formspec(0, 0, nvm.recipe_idx or 1) ..
+ "list[current_player;main;0,3.6;8,4;]" ..
+ "listring[current_player;main]"..
+ "listring[context;src]" ..
+ "listring[current_player;main]"..
+ "listring[context;dst]" ..
+ "listring[current_player;main]"
+end
+
+local function determine_new_input(pos, inv)
+ local output = inv:get_stack("output", 1):get_name()
+ if output and output ~= "" then
+ local recipe = minetest.get_craft_recipe(output)
+ if recipe.items and recipe.type == "normal" then
+ for i = 1, 9 do
+ local name = recipe.items[i]
+ if name then
+ if minetest.registered_items[name] then
+ inv:set_stack("input", i, name)
+ end
+ end
+ end
+ inv:set_stack("output", 1, recipe.output)
+ end
+ else
+ for i = 1, 9 do
+ inv:set_stack("input", i, nil)
+ end
+ end
+end
+
+local function determine_new_output(pos, inv)
+ local items = {}
+ for i = 1, 9 do
+ items[i] = inv:get_stack("input", i):get_name()
+ end
+ local input = {
+ method = "normal",
+ width = 3,
+ items = items,
+ }
+ local output, _ = minetest.get_craft_result(input)
+ inv:set_stack("output", 1, output.item)
+end
+
+local function get_recipe(inv)
+ local items = {}
+ local last_idx = 0
+ for i = 1, 9 do
+ local name = inv:get_stack("input", i):get_name()
+ if name ~= "" then
+ last_idx = i
+ end
+ items[i] = name
+ end
+ local input = table.concat(items, ",", 1, last_idx)
+ local stack = inv:get_stack("output", 1)
+ return {
+ input = input,
+ output = stack:get_name() .. " " .. stack:get_count()
+ }
+end
+
+local function after_recipe_change(pos, inv, listname)
+ if listname == "input" then
+ determine_new_output(pos, inv)
+ else
+ determine_new_input(pos, inv)
+ end
+ local nvm = techage.get_nvm(pos)
+ nvm.recipes = nvm.recipes or {}
+ nvm.recipes[nvm.recipe_idx or 1] = get_recipe(inv)
+end
+
+local function update_inventor(pos, inv, idx)
+ local nvm = techage.get_nvm(pos)
+ nvm.recipes = nvm.recipes or {}
+ local recipe = nvm.recipes[idx]
+ if recipe then
+ local items = string.split(recipe.input, ",", true)
+ for i = 1, 9 do
+ inv:set_stack("input", i, items[i] or "")
+ end
+ inv:set_stack("output", 1, recipe.output)
+ else
+ for i = 1, 9 do
+ inv:set_stack("input", i, nil)
+ end
+ inv:set_stack("output", 1, nil)
+ end
+end
+
+local function allow_metadata_inventory_put(pos, listname, index, stack, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return 0
+ end
+
+ local inv = M(pos):get_inventory()
+ local list = inv:get_list(listname)
+ stack:set_count(1)
+ inv:set_stack(listname, index, stack)
+ after_recipe_change(pos, inv, listname)
+ return 0
+end
+
+local function allow_metadata_inventory_take(pos, listname, index, stack, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return 0
+ end
+
+ local inv = M(pos):get_inventory()
+ inv:set_stack(listname, index, nil)
+ after_recipe_change(pos, inv, listname)
+ return 0
+end
+
+local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return 0
+ end
+
+ local inv = M(pos):get_inventory()
+ if from_list == to_list then
+ minetest.after(0.1, after_recipe_change, pos, inv, from_list)
+ return 1
+ end
+ return 0
+end
+
+minetest.register_node("techage:ta4_recipeblock", {
+ description = S("TA4 Recipe Block"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_filling_ta4.png^techage_frame_ta4_top.png",
+ "techage_filling_ta4.png^techage_frame_ta4_top.png",
+ "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_recipeblock.png",
+ },
+
+ on_construct = function(pos)
+ local inv = M(pos):get_inventory()
+ inv:set_size('input', 9)
+ inv:set_size('output', 1)
+ end,
+
+ after_place_node = function(pos, placer, itemstack)
+ local nvm = techage.get_nvm(pos)
+ local number = techage.add_node(pos, "techage:ta4_chest")
+ M(pos):set_string("owner", placer:get_player_name())
+ M(pos):set_string("node_number", number)
+ M(pos):set_string("formspec", formspec(pos, nvm))
+ M(pos):set_string("infotext", S("TA4 Recipe Block") .. " " .. number)
+ end,
+
+ on_receive_fields = function(pos, formname, fields, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return
+ end
+
+ local nvm = techage.get_nvm(pos)
+ nvm.recipe_idx = nvm.recipe_idx or 1
+ if fields.next == ">>" then
+ nvm.recipe_idx = techage.in_range(nvm.recipe_idx + 1, 1, MAX_RECIPE)
+ elseif fields.priv == "<<" then
+ nvm.recipe_idx = techage.in_range(nvm.recipe_idx - 1, 1, MAX_RECIPE)
+ end
+ local inv = M(pos):get_inventory()
+ update_inventor(pos, inv, nvm.recipe_idx or 1)
+ M(pos):set_string("formspec", formspec(pos, nvm))
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata, digger)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ techage.del_mem(pos)
+ end,
+
+ allow_metadata_inventory_put = allow_metadata_inventory_put,
+ allow_metadata_inventory_take = allow_metadata_inventory_take,
+ allow_metadata_inventory_move = allow_metadata_inventory_move,
+
+ paramtype2 = "facedir",
+ groups = {choppy=2, cracky=2, crumbly=2},
+ is_ground_content = false,
+ sounds = default.node_sound_wood_defaults(),
+})
+
+techage.register_node({"techage:ta4_recipeblock"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ local nvm = techage.get_nvm(pos)
+ if topic == "input" and payload and payload ~= "" then
+ nvm.recipes = nvm.recipes or {}
+ local recipe = nvm.recipes[tonumber(payload) or 1]
+ if recipe then
+ return recipe.input
+ end
+ else
+ return "unsupported"
+ end
+ end,
+})
+
+minetest.register_craft({
+ output = "techage:ta4_recipeblock",
+ recipe = {
+ {"techage:ta4_carbon_fiber", "dye:blue", "techage:aluminum"},
+ {"", "basic_materials:ic", ""},
+ {"default:steel_ingot", "techage:ta4_wlanchip", "default:steel_ingot"},
+ },
+})
+
diff --git a/techage/basic_machines/recycler.lua b/techage/basic_machines/recycler.lua
index ce85b3f..f2adfc2 100644
--- a/techage/basic_machines/recycler.lua
+++ b/techage/basic_machines/recycler.lua
@@ -26,40 +26,44 @@ local CYCLE_TIME = 8
local Recipes = {}
local SpecialItems = {
- ["techage:sieved_gravel"] = "default:sand",
- ["basic_materials:heating_element"] = "default:copper_ingot",
- ["techage:ta4_wlanchip"] = "",
- ["techage:basalt_cobble"] = "default:sand",
- ["default:stone"] = "techage:sieved_gravel",
- ["default:wood"] = "default:stick 5",
- ["basic_materials:concrete_block"] = "techage:sieved_gravel",
- ["dye:green"] = "",
- ["dye:red"] = "",
- ["dye:white"] = "",
- ["dye:blue"] = "",
- ["dye:brown"] = "",
+ ["techage:sieved_gravel"] = "default:sand",
+ ["basic_materials:heating_element"] = "default:copper_ingot",
+ ["techage:ta4_wlanchip"] = "",
+ ["techage:basalt_cobble"] = "default:sand",
+ ["default:stone"] = "techage:sieved_gravel",
+ ["default:wood"] = "default:stick 5",
+ ["basic_materials:concrete_block"] = "techage:sieved_gravel",
+ ["dye:green"] = "",
+ ["dye:red"] = "",
+ ["dye:white"] = "",
+ ["dye:blue"] = "",
+ ["dye:brown"] = "",
["dye:cyan"] = "",
["dye:yellow"] = "",
["dye:grey"] = "",
["dye:orange"] = "",
- ["dye:black"] = "",
- ["techage:basalt_glass_thin"] = "",
- ["group:stone"] = "techage:sieved_gravel",
- ["basic_materials:plastic_sheet"] = "",
- ["group:wood"] = "default:stick 5",
- ["techage:basalt_glass"] = "",
- ["default:junglewood"] = "default:stick 5",
- ["techage:ta4_silicon_wafer"] = "",
- ["default:cobble"] = "techage:sieved_gravel",
- ["default:pick_diamond"] = "default:stick",
- ["techage:hammer_steel"] = "default:stick",
- ["default:paper"] = "",
- ["stairs:slab_basalt_glass2"] = "",
- ["techage:basalt_stone"] = "techage:sieved_gravel",
- ["techage:ta4_ramchip"] = "",
+ ["dye:black"] = "",
+ ["techage:basalt_glass_thin"] = "",
+ ["group:stone"] = "techage:sieved_gravel",
+ ["basic_materials:plastic_sheet"] = "",
+ ["group:wood"] = "default:stick 5",
+ ["techage:basalt_glass"] = "",
+ ["default:junglewood"] = "default:stick 5",
+ ["techage:ta4_silicon_wafer"] = "",
+ ["default:cobble"] = "techage:sieved_gravel",
+ ["default:pick_diamond"] = "default:stick",
+ ["techage:hammer_steel"] = "default:stick",
+ ["default:paper"] = "",
+ ["stairs:slab_basalt_glass2"] = "",
+ ["techage:basalt_stone"] = "techage:sieved_gravel",
+ ["techage:ta4_ramchip"] = "",
["protector:chest"] = "default:chest",
["techage:ta4_rotor_blade"] = "",
["techage:ta4_carbon_fiber"] = "",
+ ["techage:ta4_round_ceramic"] = "",
+ ["techage:ta4_furnace_ceramic"] = "",
+ ["techage:ta5_aichip"] = "",
+ ["techage:ta4_leds"] = "",
}
local function formspec(self, pos, nvm)
diff --git a/techage/basic_machines/ta5_chest.lua b/techage/basic_machines/ta5_chest.lua
new file mode 100644
index 0000000..222525d
--- /dev/null
+++ b/techage/basic_machines/ta5_chest.lua
@@ -0,0 +1,185 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2019-2022 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA5 Hyperloop Chest
+
+]]--
+
+-- for lazy programmers
+local S2P = minetest.string_to_pos
+local P2S = minetest.pos_to_string
+local M = minetest.get_meta
+local S = techage.S
+
+local TA4_INV_SIZE = 32
+local EX_POINTS = 20
+
+local hyperloop = techage.hyperloop
+local remote_pos = techage.hyperloop.remote_pos
+local shared_inv = techage.shared_inv
+local menu = techage.menu
+
+local function formspec(pos)
+ local ndef = minetest.registered_nodes["techage:ta5_hl_chest"]
+ local status = M(pos):get_string("conn_status")
+ if hyperloop.is_client(pos) or hyperloop.is_server(pos) then
+ local title = ndef.description .. " " .. status
+ return "size[8,9]"..
+ "box[0,-0.1;7.8,0.5;#c6e8ff]" ..
+ "label[0.2,-0.1;" .. minetest.colorize( "#000000", title) .. "]" ..
+ "list[context;main;0,1;8,4;]"..
+ "list[current_player;main;0,5.3;8,4;]"..
+ "listring[context;main]"..
+ "listring[current_player;main]"
+ else
+ return menu.generate_formspec(pos, ndef, hyperloop.SUBMENU)
+ end
+end
+
+local function allow_metadata_inventory_put(pos, listname, index, stack, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return 0
+ end
+ shared_inv.before_inv_access(pos, listname)
+ local inv = minetest.get_inventory({type="node", pos=pos})
+ if inv:room_for_item(listname, stack) then
+ return stack:get_count()
+ end
+ return 0
+end
+
+local function allow_metadata_inventory_take(pos, listname, index, stack, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return 0
+ end
+ shared_inv.before_inv_access(pos, listname)
+ local inv = minetest.get_inventory({type="node", pos=pos})
+ if inv:contains_item(listname, stack) then
+ return stack:get_count()
+ end
+ return 0
+end
+
+local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
+ if shared_inv.before_inv_access(pos, "main") then
+ return 0
+ end
+ return count
+end
+
+minetest.register_node("techage:ta5_hl_chest", {
+ description = S("TA5 Hyperloop Chest"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_filling_ta4.png^techage_frame_ta5_top.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_chest_back_ta4.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_chest_back_ta4.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_chest_back_ta4.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_chest_front_ta4.png",
+ },
+ after_place_node = function(pos, placer)
+ local meta = minetest.get_meta(pos)
+ local inv = meta:get_inventory()
+ inv:set_size('main', 32)
+ local number = techage.add_node(pos, "techage:ta5_hl_chest")
+ meta:set_string("node_number", number)
+ meta:set_string("owner", placer:get_player_name())
+ meta:set_string("formspec", formspec(pos))
+ meta:set_string("infotext", S("TA5 Hyperloop Chest").." "..number)
+ hyperloop.after_place_node(pos, placer, "chest")
+ end,
+ on_receive_fields = function(pos, formname, fields, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return
+ end
+ if techage.get_expoints(player) >= EX_POINTS then
+ if techage.menu.eval_input(pos, hyperloop.SUBMENU, fields) then
+ hyperloop.after_formspec(pos, fields)
+ shared_inv.on_rightclick(pos, player, "main")
+ M(pos):set_string("formspec", formspec(pos))
+ end
+ end
+ end,
+ on_timer = shared_inv.node_timer,
+ on_rightclick = function(pos, node, clicker)
+ shared_inv.on_rightclick(pos, clicker, "main")
+ M(pos):set_string("formspec", formspec(pos))
+ end,
+ can_dig = function(pos, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return false
+ end
+ shared_inv.before_inv_access(pos, "main")
+ local inv = minetest.get_meta(pos):get_inventory()
+ return inv:is_empty("main")
+ end,
+ after_dig_node = function(pos, oldnode, oldmetadata, digger)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ hyperloop.after_dig_node(pos, oldnode, oldmetadata, digger)
+ techage.del_mem(pos)
+ end,
+ allow_metadata_inventory_put = allow_metadata_inventory_put,
+ allow_metadata_inventory_take = allow_metadata_inventory_take,
+ allow_metadata_inventory_move = allow_metadata_inventory_move,
+ on_metadata_inventory_put = shared_inv.after_inv_access,
+ on_metadata_inventory_take = shared_inv.after_inv_access,
+ paramtype2 = "facedir",
+ groups = {choppy=2, cracky=2, crumbly=2},
+ is_ground_content = false,
+ sounds = default.node_sound_wood_defaults(),
+})
+
+
+techage.register_node({"techage:ta5_hl_chest"}, {
+ on_inv_request = function(pos, in_dir, access_type)
+ pos = remote_pos(pos)
+ local meta = minetest.get_meta(pos)
+ return meta:get_inventory(), "main"
+ end,
+ on_pull_item = function(pos, in_dir, num, item_name)
+ pos = remote_pos(pos)
+ local meta = minetest.get_meta(pos)
+ local inv = meta:get_inventory()
+ return techage.get_items(pos, inv, "main", num)
+ end,
+ on_push_item = function(pos, in_dir, stack)
+ if techage.hyperloop.is_paired(pos) then
+ pos = remote_pos(pos)
+ local meta = minetest.get_meta(pos)
+ local inv = meta:get_inventory()
+ return techage.put_items(inv, "main", stack)
+ end
+ return false
+ end,
+ on_unpull_item = function(pos, in_dir, stack)
+ pos = remote_pos(pos)
+ local meta = minetest.get_meta(pos)
+ local inv = meta:get_inventory()
+ return techage.put_items(inv, "main", stack)
+ end,
+ on_recv_message = function(pos, src, topic, payload)
+ if topic == "state" then
+ pos = remote_pos(pos)
+ local meta = minetest.get_meta(pos)
+ local inv = meta:get_inventory()
+ return techage.get_inv_state(inv, "main")
+ else
+ return "unsupported"
+ end
+ end,
+})
+
+
+minetest.register_craft({
+ type = "shapeless",
+ output = "techage:ta5_hl_chest",
+ recipe = {"techage:chest_ta4", "techage:ta5_aichip"}
+})
diff --git a/techage/basis/assemble.lua b/techage/basis/assemble.lua
index 8437c1f..b176495 100644
--- a/techage/basis/assemble.lua
+++ b/techage/basis/assemble.lua
@@ -124,3 +124,118 @@ function techage.assemble.remove(pos, AssemblyPlan, player_name)
remove(pos, node.param2, AssemblyPlan, #AssemblyPlan)
nvm.assemble_build = false
end
+
+--------------------------------------------------------------------------------
+-- Assembly functions based on nodes from node inventory
+--------------------------------------------------------------------------------
+local function play_sound(pos, sound)
+ minetest.sound_play(sound, {
+ pos = pos,
+ gain = 1,
+ max_hear_distance = 10,
+ })
+end
+
+local function build_inv(pos, inv, param2, AssemblyPlan, player_name, idx)
+ local item = AssemblyPlan[idx]
+ if item ~= nil then
+ local y, path, fd_offs, node_name = item[1], item[2], item[3], item[4]
+ local pos1 = dest_pos(pos, param2, path, y)
+ if not minetest.is_protected(pos1, player_name) then
+ local node = minetest.get_node(pos1)
+ if techage.is_air_like(node.name) then
+ local stack = inv:remove_item("src", ItemStack(node_name))
+ if stack:get_count() == 1 then
+ minetest.add_node(pos1, {name=node_name, param2=(param2 + fd_offs) % 4})
+ play_sound(pos, "default_place_node_hard")
+ local ndef = minetest.registered_nodes[node_name]
+ if ndef and ndef.after_place_node then
+ local placer = minetest.get_player_by_name(player_name)
+ ndef.after_place_node(pos1, placer, ItemStack(node_name))
+ end
+ end
+ end
+ end
+ minetest.after(0.5, build_inv, pos, inv, param2, AssemblyPlan, player_name, idx + 1)
+ else
+ local nvm = techage.get_nvm(pos)
+ nvm.assemble_locked = false
+ end
+end
+
+local function remove_inv(pos, inv, param2, AssemblyPlan, player_name, idx)
+ local item = AssemblyPlan[idx]
+ if item ~= nil then
+ local y, path, fd_offs, node_name = item[1], item[2], item[3], item[4]
+ local pos1 = dest_pos(pos, param2, path, y)
+ if not minetest.is_protected(pos1, player_name) then
+ local stack = ItemStack(node_name)
+ if inv:room_for_item("src", stack) then
+ local node = minetest.get_node(pos1)
+ if node.name == node_name then
+ minetest.remove_node(pos1)
+ inv:add_item("src", stack)
+ play_sound(pos, "default_dig_cracky")
+ local ndef = minetest.registered_nodes[node_name]
+ if ndef and ndef.after_dig_node then
+ local digger = minetest.get_player_by_name(player_name)
+ ndef.after_dig_node(pos1, pos, ItemStack(node_name), {}, digger)
+ end
+ end
+ end
+ end
+ minetest.after(0.5, remove_inv, pos, inv, param2, AssemblyPlan, player_name, idx - 1)
+ else
+ local nvm = techage.get_nvm(pos)
+ nvm.assemble_locked = false
+ end
+end
+
+function techage.assemble.build_inv(pos, inv, AssemblyPlan, player_name)
+ -- check protection
+ if minetest.is_protected(pos, player_name) then
+ return
+ end
+ local nvm = techage.get_nvm(pos)
+ if nvm.assemble_locked then
+ return
+ end
+ local node = minetest.get_node(pos)
+ nvm.assemble_locked = true
+ build_inv(pos, inv, node.param2, AssemblyPlan, player_name, 1)
+end
+
+function techage.assemble.remove_inv(pos, inv, AssemblyPlan, player_name)
+ -- check protection
+ if minetest.is_protected(pos, player_name) then
+ return
+ end
+ local nvm = techage.get_nvm(pos)
+ if nvm.assemble_locked then
+ return
+ end
+ local node = minetest.get_node(pos)
+ nvm.assemble_locked = true
+ remove_inv(pos, inv, node.param2, AssemblyPlan, player_name, #AssemblyPlan)
+end
+
+function techage.assemble.count_items(AssemblyPlan)
+ local t = {}
+ for _, item in ipairs(AssemblyPlan) do
+ local node_name = item[4]
+ local ndef = minetest.registered_nodes[node_name]
+ local name = ndef.description
+ if not t[name] then
+ t[name] = 1
+ else
+ t[name] = t[name] + 1
+ end
+ end
+ return t
+end
+
+-- Determine the destination position based on the given route
+-- param2, and a route table like : {0,3}
+-- 0 = forward, 1 = right, 2 = backward, 3 = left
+-- techage.assemble.get_pos(pos, param2, route, y_offs)
+techage.assemble.get_pos = dest_pos
diff --git a/techage/basis/command.lua b/techage/basis/command.lua
index f09fe94..1cd93fb 100644
--- a/techage/basis/command.lua
+++ b/techage/basis/command.lua
@@ -262,6 +262,28 @@ function techage.repair_number(pos)
end
end
+-- Like techage.add_node, but use the old number again
+function techage.unpack_node(pos, name, number)
+ if item_handling_node(name) then
+ Tube:after_place_node(pos)
+ end
+ local key = minetest.hash_node_position(pos)
+ NumbersToBeRecycled[key] = nil
+ if number then
+ backend.set_nodepos(number, pos)
+ end
+end
+
+-- Like techage.remove_node but don't store the number for this position
+function techage.pack_node(pos, oldnode, number)
+ if number then
+ NodeInfoCache[number] = nil
+ end
+ if oldnode and item_handling_node(oldnode.name) then
+ Tube:after_dig_node(pos)
+ end
+end
+
-------------------------------------------------------------------
-- Node register function
@@ -544,3 +566,62 @@ function techage.get_inv_state(inv, listname)
end
return state
end
+
+minetest.register_chatcommand("ta_send", {
+ description = minetest.formspec_escape(
+ "Send a techage command to the block with the number given: /ta_send []"),
+ func = function(name, param)
+ local num, cmnd, payload = param:match('^([0-9]+)%s+(%w+)%s*(.*)$')
+
+ if num and cmnd then
+ if techage.not_protected(num, name) then
+ local resp = techage.send_single("0", num, cmnd, payload)
+ if type(resp) == "string" then
+ return true, resp
+ else
+ return true, dump(resp)
+ end
+ else
+ return false, "Destination block is protected"
+ end
+ end
+ return false, "Syntax: /ta_send []"
+ end
+})
+
+minetest.register_chatcommand("expoints", {
+ privs = {
+ server = true
+ },
+ func = function(name, param)
+ local player_name, points = param:match("^(%S+)%s*(%d*)$")
+ if player_name then
+ local player = minetest.get_player_by_name(player_name)
+ if player then
+ if points and points ~= "" then
+ if techage.set_expoints(player, tonumber(points)) then
+ return true, "The player "..player_name.." now has "..points.." experience points."
+ end
+ else
+ points = techage.get_expoints(player)
+ return true, "The player "..player_name.." has "..points.." experience points."
+ end
+ else
+ return false, "Unknown player "..player_name
+ end
+ end
+ return false, "Syntax error! Syntax: /expoints []"
+ end
+})
+
+minetest.register_chatcommand("my_expoints", {
+ func = function(name, param)
+ local player = minetest.get_player_by_name(name)
+ if player then
+ local points = techage.get_expoints(player)
+ if points then
+ return true, "You have "..points.." experience points."
+ end
+ end
+ end
+})
diff --git a/techage/basis/counting.lua b/techage/basis/counting.lua
index 265b048..33db84d 100644
--- a/techage/basis/counting.lua
+++ b/techage/basis/counting.lua
@@ -34,6 +34,10 @@ function techage.counting_hit()
end
end
+function techage.counting_add(player_name, points)
+ PlayerPoints[player_name] = (PlayerPoints[player_name] or 0) + points
+end
+
local function output()
for name, val in pairs(PlayerPoints) do
if val > MAX_POINTS then
diff --git a/techage/basis/fly_lib.lua b/techage/basis/fly_lib.lua
new file mode 100644
index 0000000..8cc8d19
--- /dev/null
+++ b/techage/basis/fly_lib.lua
@@ -0,0 +1,733 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2020-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ Block fly/move library
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
+local S2P = minetest.string_to_pos
+local S = techage.S
+
+local flylib = {}
+
+local function lvect_add_vec(lvect1, offs)
+ if not lvect1 or not offs then return end
+
+ local lvect2 = {}
+ for _, v in ipairs(lvect1) do
+ lvect2[#lvect2 + 1] = vector.add(v, offs)
+ end
+ return lvect2
+end
+
+local function lvect_add(lvect1, lvect2)
+ if not lvect1 or not lvect2 then return end
+
+ local lvect3 = {}
+ for i, v in ipairs(lvect1) do
+ lvect3[#lvect3 + 1] = vector.add(v, lvect2[i])
+ end
+ return lvect3
+end
+
+local function lvect_subtract(lvect1, lvect2)
+ if not lvect1 or not lvect2 then return end
+
+ local lvect3 = {}
+ for i, v in ipairs(lvect1) do
+ lvect3[#lvect3 + 1] = vector.subtract(v, lvect2[i])
+ end
+ return lvect3
+end
+
+-- yaw in radiant
+local function rotate(v, yaw)
+ local sinyaw = math.sin(yaw)
+ local cosyaw = math.cos(yaw)
+ return {x = v.x * cosyaw - v.z * sinyaw, y = v.y, z = v.x * sinyaw + v.z * cosyaw}
+end
+
+-------------------------------------------------------------------------------
+-- to_path function for the fly/move path
+-------------------------------------------------------------------------------
+
+local function strsplit(text)
+ text = text:gsub("\r\n", "\n")
+ text = text:gsub("\r", "\n")
+ return string.split(text, "\n", true)
+end
+
+local function trim(s)
+ return (s:gsub("^%s*(.-)%s*$", "%1"))
+end
+
+function flylib.distance(v)
+ return math.abs(v.x) + math.abs(v.y) + math.abs(v.z)
+end
+
+function flylib.to_vector(s)
+ local x,y,z = unpack(string.split(s, ","))
+ if x and y and z then
+ return {
+ x=tonumber(x) or 0,
+ y=tonumber(y) or 0,
+ z=tonumber(z) or 0,
+ }
+ end
+end
+
+function flylib.to_path(s, max_dist)
+ local tPath
+ local dist = 0
+
+ for _, line in ipairs(strsplit(s)) do
+ line = trim(line)
+ line = string.split(line, "--", true, 1)[1] or ""
+ if line ~= "" then
+ local v = flylib.to_vector(line)
+ if v then
+ dist = dist + flylib.distance(v)
+ if not max_dist or dist <= max_dist then
+ tPath = tPath or {}
+ tPath[#tPath + 1] = v
+ else
+ return tPath, S("Error: Max. length of the flight route exceeded !!")
+ end
+ else
+ return tPath, S("Error: Invalid path !!")
+ end
+ end
+ end
+ return tPath
+end
+
+local function next_path_pos(pos, lpath, idx)
+ local offs = lpath[idx]
+ if offs then
+ return vector.add(pos, offs)
+ end
+end
+
+local function reverse_path(lpath)
+ local lres = {}
+ for i = #lpath, 1, -1 do
+ lres[#lres + 1] = vector.multiply(lpath[i], -1)
+ end
+ return lres
+end
+
+local function dest_offset(lpath)
+ local offs = {x=0, y=0, z=0}
+ for i = 1,#lpath do
+ offs = vector.add(offs, lpath[i])
+ end
+ return offs
+end
+
+-------------------------------------------------------------------------------
+-- Entity / Move / Attach / Detach
+-------------------------------------------------------------------------------
+local MIN_SPEED = 0.4
+local MAX_SPEED = 8
+local CORNER_SPEED = 4
+local SimpleNodes = techage.logic.SimpleNodes
+
+local function calc_speed(v)
+ return math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z)
+end
+
+-- Only the ID ist stored, not the object
+local function get_object_id(object)
+ for id, entity in pairs(minetest.luaentities) do
+ if entity.object == object then
+ return id
+ end
+ end
+end
+
+-- determine exact position of attached entities
+local function obj_pos(obj)
+ local _, _, pos = obj:get_attach()
+ if pos then
+ pos = vector.divide(pos, 29)
+ return vector.add(obj:get_pos(), pos)
+ end
+end
+
+-- Check access conflicts with other mods
+local function lock_player(player)
+ local meta = player:get_meta()
+ if meta:get_int("player_physics_locked") == 0 then
+ meta:set_int("player_physics_locked", 1)
+ meta:set_string("player_physics_locked_by", "ta_flylib")
+ return true
+ end
+ return false
+end
+
+local function unlock_player(player)
+ local meta = player:get_meta()
+ if meta:get_int("player_physics_locked") == 1 then
+ if meta:get_string("player_physics_locked_by") == "ta_flylib" then
+ meta:set_int("player_physics_locked", 0)
+ meta:set_string("player_physics_locked_by", "")
+ return true
+ end
+ end
+ return false
+end
+
+local function detach_player(player)
+ local pos = obj_pos(player)
+ if pos then
+ player:set_detach()
+ player:set_properties({visual_size = {x=1, y=1}})
+ player:set_pos(pos)
+ end
+ -- TODO: move to save position
+end
+
+-- Attach player/mob to given parent object (block)
+local function attach_single_object(parent, obj, dir)
+ local self = parent:get_luaentity()
+ local res = obj:get_attach()
+ if not res then -- not already attached
+ local yaw
+ if obj:is_player() then
+ yaw = obj:get_look_horizontal()
+ else
+ yaw = obj:get_rotation().y
+ end
+ -- store for later use
+ local offs = table.copy(dir)
+ -- Calc entity rotation, which is relative to the parent's rotation
+ local rot = parent:get_rotation()
+ if self.param2 >= 20 then
+ dir = rotate(dir, 2 * math.pi - rot.y)
+ dir.y = -dir.y
+ dir.x = -dir.x
+ rot.y = rot.y - yaw
+ elseif self.param2 < 4 then
+ dir = rotate(dir, 2 * math.pi - rot.y)
+ rot.y = rot.y - yaw
+ end
+ dir = vector.multiply(dir, 29)
+ obj:set_attach(parent, "", dir, vector.multiply(rot, 180 / math.pi))
+ obj:set_properties({visual_size = {x=2.9, y=2.9}})
+ if obj:is_player() then
+ if lock_player(obj) then
+ table.insert(self.players, {name = obj:get_player_name(), offs = offs})
+ end
+ else
+ table.insert(self.entities, {objID = get_object_id(obj), offs = offs})
+ end
+ end
+end
+
+-- Attach all objects around to the parent object
+-- offs is the search/attach position offset
+local function attach_objects(pos, offs, parent, yoffs)
+ local pos1 = vector.add(pos, offs)
+ for _, obj in pairs(minetest.get_objects_inside_radius(pos1, 0.9)) do
+ local dir = vector.subtract(obj:get_pos(), pos)
+ local entity = obj:get_luaentity()
+ if entity then
+ if entity.name == "__builtin:item" then -- dropped items
+ --obj:set_attach(objref, "", {x=0, y=0, z=0}, {x=0, y=0, z=0}, true) -- hier kracht es
+ elseif entity.name ~= "techage:move_item" then
+ dir.y = dir.y + yoffs
+ attach_single_object(parent, obj, dir)
+ end
+ elseif obj:is_player() then
+ attach_single_object(parent, obj, dir)
+ end
+ end
+end
+
+-- Detach all attached objects from the parent object
+local function detach_objects(pos, self)
+ for _, item in ipairs(self.entities or {}) do
+ local entity = minetest.luaentities[item.objID]
+ if entity then
+ local obj = entity.object
+ obj:set_detach()
+ obj:set_properties({visual_size = {x=1, y=1}})
+ local pos1 = vector.add(pos, item.offs)
+ pos1.y = pos1.y - (self.yoffs or 0)
+ obj:set_pos(pos1)
+ end
+ end
+ for _, item in ipairs(self.players or {}) do
+ local obj = minetest.get_player_by_name(item.name)
+ if obj then
+ obj:set_detach()
+ obj:set_properties({visual_size = {x=1, y=1}})
+ local pos1 = vector.add(pos, item.offs)
+ pos1.y = pos1.y + 0.1
+ obj:set_pos(pos1)
+ unlock_player(obj)
+ end
+ end
+ self.entities = {}
+ self.players = {}
+end
+
+local function entity_to_node(pos, obj)
+ local self = obj:get_luaentity()
+ if self then
+ local name = self.item_name or "air"
+ local param2 = self.param2 or 0
+ local metadata = self.metadata or {}
+ detach_objects(pos, self)
+ if self.base_pos then
+ local nvm = techage.get_nvm(self.base_pos)
+ nvm.running = nil
+ end
+ obj:remove()
+
+ local node = minetest.get_node(pos)
+ local ndef1 = minetest.registered_nodes[name]
+ local ndef2 = minetest.registered_nodes[node.name]
+ if ndef1 and ndef2 then
+ if ndef2.buildable_to then
+ local meta = M(pos)
+ minetest.set_node(pos, {name=name, param2=param2})
+ meta:from_table(metadata)
+ meta:set_string("ta_move_block", "")
+ return
+ end
+ local meta = M(pos)
+ if not meta:contains("ta_move_block") then
+ meta:set_string("ta_move_block", minetest.serialize({name=name, param2=param2}))
+ return
+ end
+ minetest.add_item(pos, ItemStack(name))
+ elseif ndef1 then
+ minetest.add_item(pos, ItemStack(name))
+ end
+ end
+end
+
+local function node_to_entity(start_pos)
+ local meta = M(start_pos)
+ local node, metadata
+
+ if meta:contains("ta_move_block") then
+ -- Move-block stored as metadata
+ node = minetest.deserialize(meta:get_string("ta_move_block"))
+ metadata = {}
+ meta:set_string("ta_move_block", "")
+ else
+ -- Block with other metadata
+ node = minetest.get_node(start_pos)
+ metadata = meta:to_table()
+ minetest.remove_node(start_pos)
+ end
+ local obj = minetest.add_entity(start_pos, "techage:move_item")
+ if obj then
+ local self = obj:get_luaentity()
+ local rot = techage.facedir_to_rotation(node.param2)
+ obj:set_rotation(rot)
+ obj:set_properties({wield_item=node.name})
+ obj:set_armor_groups({immortal=1})
+
+ -- To be able to revert to node
+ self.item_name = node.name
+ self.param2 = node.param2
+ self.metadata = metadata or {}
+
+ -- Prepare for attachments
+ self.players = {}
+ self.entities = {}
+ -- Prepare for path walk
+ self.path_idx = 1
+ return obj
+ end
+end
+
+-- move block direction
+local function determine_dir(pos1, pos2)
+ local vdist = vector.subtract(pos2, pos1)
+ local ndist = vector.length(vdist)
+ if ndist > 0 then
+ return vector.divide(vdist, ndist)
+ end
+ return {x=0, y=0, z=0}
+end
+
+local function move_entity(obj, dest_pos, dir, is_corner)
+ local self = obj:get_luaentity()
+ self.dest_pos = dest_pos
+ self.dir = dir
+ if is_corner then
+ local vel = vector.multiply(dir, math.min(CORNER_SPEED, self.max_speed))
+ obj:set_velocity(vel)
+ end
+ local acc = vector.multiply(dir, self.max_speed / 2)
+ obj:set_acceleration(acc)
+end
+
+local function moveon_entity(obj, self, pos1)
+ local pos2 = next_path_pos(pos1, self.lpath, self.path_idx)
+ if pos2 then
+ self.path_idx = self.path_idx + 1
+ local dir = determine_dir(pos1, pos2)
+ move_entity(obj, pos2, dir, true)
+ return true
+ end
+end
+
+-- Handover the entity to the next movecontroller
+local function handover_to(obj, self, pos1)
+ local info = techage.get_node_info(self.handover)
+ if info and info.name == "techage:ta4_movecontroller" then
+ local meta = M(info.pos)
+ if self.move2to1 then
+ self.handover = meta:contains("handoverA") and meta:get_string("handoverA")
+ else
+ self.handover = meta:contains("handoverB") and meta:get_string("handoverB")
+ end
+
+ self.lpath = flylib.to_path(meta:get_string("path"))
+ if pos1 and self.lpath then
+ self.path_idx = 2
+ if self.move2to1 then
+ self.lpath[1] = vector.multiply(self.lpath[1], - 1)
+ end
+ local pos2 = next_path_pos(pos1, self.lpath, 1)
+ local dir = determine_dir(pos1, pos2)
+ --print("handover_to", P2S(pos1), P2S(pos2), P2S(dir), P2S(info.pos), meta:get_string("path"))
+ if not self.handover then
+ local nvm = techage.get_nvm(info.pos)
+ nvm.lpos1 = nvm.lpos1 or {}
+ if self.move2to1 then
+ nvm.lpos1[self.pos1_idx] = pos2
+
+ else
+ nvm.lpos1[self.pos1_idx] = pos1
+ end
+ end
+ move_entity(obj, pos2, dir)
+ return true
+ end
+ end
+end
+
+minetest.register_entity("techage:move_item", {
+ initial_properties = {
+ pointable = true,
+ makes_footstep_sound = true,
+ static_save = true,
+ collide_with_objects = false,
+ physical = false,
+ visual = "wielditem",
+ wield_item = "default:dirt",
+ visual_size = {x=0.67, y=0.67, z=0.67},
+ selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
+ },
+
+ get_staticdata = function(self)
+ return minetest.serialize({
+ item_name = self.item_name,
+ param2 = self.param2,
+ metadata = self.metadata,
+ move2to1 = self.move2to1,
+ handover = self.handover,
+ path_idx = self.path_idx,
+ pos1_idx = self.pos1_idx,
+ lpath = self.lpath,
+ start_pos = self.start_pos,
+ base_pos = self.base_pos,
+ max_speed = self.max_speed,
+ dest_pos = self.dest_pos,
+ dir = self.dir,
+ respawn = true,
+ })
+ end,
+
+ on_activate = function(self, staticdata)
+ if staticdata then
+ local tbl = minetest.deserialize(staticdata) or {}
+ self.item_name = tbl.item_name or "air"
+ self.param2 = tbl.param2 or 0
+ self.metadata = tbl.metadata or {}
+ self.move2to1 = tbl.move2to1 or false
+ self.handover = tbl.handover
+ self.path_idx = tbl.path_idx or 1
+ self.pos1_idx = tbl.pos1_idx or 1
+ self.lpath = tbl.lpath or {}
+ self.max_speed = tbl.max_speed or MAX_SPEED
+ self.dest_pos = tbl.dest_pos or self.object:get_pos()
+ self.start_pos = tbl.start_pos or self.object:get_pos()
+ self.base_pos = tbl.base_pos
+ self.dir = tbl.dir or {x=0, y=0, z=0}
+ self.object:set_properties({wield_item = self.item})
+ --print("tbl.respawn", tbl.respawn)
+ if tbl.respawn then
+ entity_to_node(self.start_pos, self.object)
+ end
+ end
+ end,
+
+ on_step = function(self, dtime, moveresult)
+ local stop_obj = function(obj, self)
+ local dest_pos = self.dest_pos
+ obj:move_to(self.dest_pos, true)
+ obj:set_acceleration({x=0, y=0, z=0})
+ obj:set_velocity({x=0, y=0, z=0})
+ self.dest_pos = nil
+ self.old_dist = nil
+ self.ttl = 2
+ return dest_pos
+ end
+
+ if self.dest_pos then
+ local obj = self.object
+ local pos = obj:get_pos()
+ local dist = vector.distance(pos, self.dest_pos)
+ local speed = calc_speed(obj:get_velocity())
+ self.old_dist = self.old_dist or dist
+
+ -- Landing
+ if self.lpath and self.lpath[self.path_idx] then
+ if dist < 1 or dist > self.old_dist then
+ local dest_pos = stop_obj(obj, self)
+ if not moveon_entity(obj, self, dest_pos) then
+ minetest.after(0.5, entity_to_node, dest_pos, obj)
+ end
+ return
+ end
+ elseif self.handover and dist < 0.2 or dist > self.old_dist then
+ local dest_pos = stop_obj(obj, self)
+ if not handover_to(obj, self, dest_pos) then
+ minetest.after(0.5, entity_to_node, dest_pos, obj)
+ end
+ return
+ else
+ if dist < 0.05 or dist > self.old_dist then
+ local dest_pos = stop_obj(obj, self)
+ minetest.after(0.5, entity_to_node, dest_pos, obj)
+ return
+ end
+ end
+
+ self.old_dist = dist
+
+ -- Braking or limit max speed
+ if self.handover then
+ if speed > (dist * 4) or speed > self.max_speed then
+ speed = math.min(speed, math.max(dist * 4, MIN_SPEED))
+ local vel = vector.multiply(self.dir,speed)
+ obj:set_velocity(vel)
+ obj:set_acceleration({x=0, y=0, z=0})
+ end
+ else
+ if speed > (dist * 2) or speed > self.max_speed then
+ speed = math.min(speed, math.max(dist * 2, MIN_SPEED))
+ local vel = vector.multiply(self.dir,speed)
+ obj:set_velocity(vel)
+ obj:set_acceleration({x=0, y=0, z=0})
+ end
+ end
+
+ elseif self.ttl then
+ self.ttl = self.ttl - dtime
+ if self.ttl < 0 then
+ local obj = self.object
+ local pos = obj:get_pos()
+ entity_to_node(pos, obj)
+ end
+ end
+ end,
+})
+
+local function is_valid_dest(pos)
+ local node = minetest.get_node(pos)
+ local ndef = minetest.registered_nodes[node.name]
+ if ndef and ndef.buildable_to then
+ return true
+ end
+ if not M(pos):contains("ta_move_block") then
+ return true
+ end
+ return false
+end
+
+local function is_simple_node(pos)
+ -- special handling
+ local name = minetest.get_node(pos).name
+ if SimpleNodes[name] ~= nil then
+ return SimpleNodes[name]
+ end
+
+ local ndef = minetest.registered_nodes[name]
+ if not ndef or name == "air" or name == "ignore" then return false end
+ -- don't remove nodes with some intelligence or undiggable nodes
+ if ndef.drop == "" then return false end
+ if ndef.diggable == false then return false end
+ if ndef.after_dig_node then return false end
+
+ return true
+end
+
+local function move_node(pos, pos1_idx, start_pos, lpath, max_speed, height, move2to1, handover, cpos)
+ local pos2 = next_path_pos(start_pos, lpath, 1)
+ --print("move_node", P2S(pos), P2S(start_pos), lpath, max_speed, height, move2to1, P2S(pos2))
+ -- optional for non-player objects
+ local yoffs = M(pos):get_float("offset")
+
+ if pos2 then
+ local dir = determine_dir(start_pos, pos2)
+ local obj = node_to_entity(start_pos)
+
+ if obj then
+ local offs = {x=0, y=height or 1, z=0}
+ attach_objects(start_pos, offs, obj, yoffs)
+ if dir.y == 0 then
+ if (dir.x ~= 0 and dir.z == 0) or (dir.x == 0 and dir.z ~= 0) then
+ attach_objects(start_pos, dir, obj, yoffs)
+ end
+ end
+ local self = obj:get_luaentity()
+ self.path_idx = 2
+ self.pos1_idx = pos1_idx
+ self.lpath = lpath
+ self.max_speed = max_speed
+ self.start_pos = start_pos
+ self.base_pos = pos
+ self.move2to1 = move2to1
+ self.handover = handover
+ self.yoffs = yoffs
+ --print("move_node", P2S(start_pos), P2S(pos2), P2S(dir), P2S(pos))
+ move_entity(obj, pos2, dir)
+ end
+ end
+end
+
+local function move_nodes(pos, meta, nvm, lpath, max_speed, height, move2to1, handover)
+ --print("move_nodes", dump(nvm), dump(lpath), max_speed, height, move2to1, handover)
+ local owner = meta:get_string("owner")
+ techage.counting_add(owner, #nvm.lpos1 * #lpath)
+
+ for idx = 1, #nvm.lpos1 do
+ local pos1 = nvm.lpos1[idx]
+ local pos2 = nvm.lpos2[idx]
+
+ if move2to1 then
+ pos1, pos2 = pos2, pos1
+ end
+
+ --print("move_nodes", P2S(pos1), P2S(pos2))
+ if not minetest.is_protected(pos1, owner) and not minetest.is_protected(pos2, owner) then
+ if is_simple_node(pos1) and is_valid_dest(pos2) then
+ move_node(pos, idx, pos1, lpath, max_speed, height, move2to1, handover)
+ else
+ if not is_simple_node(pos1) then
+ meta:set_string("status", S("No valid node at the start position"))
+ else
+ meta:set_string("status", S("No valid destination position"))
+ end
+ end
+ else
+ if minetest.is_protected(pos1, owner) then
+ meta:set_string("status", S("Start position is protected"))
+ else
+ meta:set_string("status", S("Destination position is protected"))
+ end
+ return false
+ end
+ end
+ return true
+end
+
+function flylib.move_to_other_pos(pos, move2to1)
+ local meta = M(pos)
+ local nvm = techage.get_nvm(pos)
+ local lpath, err = flylib.to_path(meta:get_string("path")) or {}
+ local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED
+ local height = meta:contains("height") and meta:get_float("height") or 1
+ local handover
+
+ if err then return false end
+
+ height = techage.in_range(height, 0, 1)
+ max_speed = techage.in_range(max_speed, MIN_SPEED, MAX_SPEED)
+ nvm.lpos1 = nvm.lpos1 or {}
+
+ local offs = dest_offset(lpath)
+ if move2to1 then
+ lpath = reverse_path(lpath)
+ end
+ -- calc destination positions
+ nvm.lpos2 = lvect_add_vec(nvm.lpos1, offs)
+
+ if move2to1 then
+ handover = meta:contains("handoverA") and meta:get_string("handoverA")
+ else
+ handover = meta:contains("handoverB") and meta:get_string("handoverB")
+ end
+ return move_nodes(pos, meta, nvm, lpath, max_speed, height, move2to1, handover)
+end
+
+-- rot is one of "l", "r", "2l", "2r"
+-- cpos is the center pos (optional)
+function flylib.rotate_nodes(pos, posses1, rot)
+ local meta = M(pos)
+ local owner = meta:get_string("owner")
+ local cpos = meta:contains("center") and flylib.to_vector(meta:get_string("center"))
+ local posses2 = techage.rotate_around_center(posses1, rot, cpos)
+ local param2
+ local nodes2 = {}
+
+ techage.counting_add(owner, #posses1 * 2)
+
+ for i, pos1 in ipairs(posses1) do
+ local node = techage.get_node_lvm(pos1)
+ if rot == "l" then
+ param2 = techage.param2_turn_left(node.param2)
+ elseif rot == "r" then
+ param2 = techage.param2_turn_right(node.param2)
+ else
+ param2 = techage.param2_turn_left(techage.param2_turn_left(node.param2))
+ end
+ if not minetest.is_protected(pos1, owner) and is_simple_node(pos1) then
+ minetest.remove_node(pos1)
+ nodes2[#nodes2 + 1] = {pos = posses2[i], name = node.name, param2 = param2}
+ end
+ end
+ for _,item in ipairs(nodes2) do
+ if not minetest.is_protected(item.pos, owner) and is_valid_dest(item.pos) then
+ minetest.add_node(item.pos, {name = item.name, param2 = item.param2})
+ end
+ end
+ return posses2
+end
+
+
+minetest.register_on_joinplayer(function(player)
+ unlock_player(player)
+end)
+
+minetest.register_on_leaveplayer(function(player)
+ if unlock_player(player) then
+ detach_player(player)
+ end
+end)
+
+minetest.register_on_dieplayer(function(player)
+ if unlock_player(player) then
+ detach_player(player)
+ end
+end)
+
+return flylib
diff --git a/techage/basis/hyperloop.lua b/techage/basis/hyperloop.lua
new file mode 100644
index 0000000..d5e1c64
--- /dev/null
+++ b/techage/basis/hyperloop.lua
@@ -0,0 +1,235 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2019-2022 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ For chests and tanks with hyperloop support
+
+]]--
+
+-- for lazy programmers
+local S2P = minetest.string_to_pos
+local P2S = minetest.pos_to_string
+local M = minetest.get_meta
+local N = techage.get_node_lvm
+local S = techage.S
+
+-- Will be initialized when mods are loaded
+local Stations = nil
+local Tube = nil
+local HYPERLOOP = nil
+
+techage.hyperloop = {}
+
+--[[
+
+ tStations["(x,y,z)"] = {
+ conn = {dir = "(200,0,20)", ...},
+ name = , -- chest/tank
+ owner = "singleplayer",
+ conn_name = ,
+ single = true/nil,
+ }
+
+]]--
+
+minetest.register_on_mods_loaded(function()
+ if minetest.global_exists("hyperloop") then
+ Stations = hyperloop.Stations
+ Tube = hyperloop.Tube
+ HYPERLOOP = true
+ Tube:add_secondary_node_names({"techage:ta5_hl_chest", "techage:ta5_hl_tank"})
+ end
+end)
+
+local function get_remote_pos(pos, rmt_name)
+ local owner = M(pos):get_string("owner")
+ for key,item in pairs(Stations:get_node_table(pos)) do
+ if item.owner == owner and item.conn_name == rmt_name then
+ return S2P(key)
+ end
+ end
+end
+
+local function get_free_server_list(pos, owner)
+ local tbl = {M(pos):get_string("remote_name")}
+ for key,item in pairs(Stations:get_node_table(pos)) do
+ if item.single and item.owner == owner then
+ if M(pos):get_string("node_type") == M(S2P(key)):get_string("node_type") then
+ tbl[#tbl+1] = item.conn_name
+ end
+ end
+ end
+ tbl[#tbl+1] = ""
+ return tbl
+end
+
+local function on_lose_connection(pos, node_type)
+ local name = techage.get_node_lvm(pos).name
+ local ndef = minetest.registered_nodes[name]
+ if ndef and ndef.on_lose_connection then
+ ndef.on_lose_connection(pos, node_type)
+ end
+end
+
+local function on_dropdown(pos)
+ local owner = M(pos):get_string("owner")
+ return table.concat(get_free_server_list(pos, owner), ",")
+end
+
+local function update_node_data(pos, state, conn_name, remote_name, rmt_pos)
+ local meta = M(pos)
+ local nvm = techage.get_nvm(pos)
+
+ if state == "server_connected" then
+ Stations:update(pos, {conn_name=conn_name, single="nil"})
+ meta:set_string("status", "server")
+ meta:set_string("conn_name", conn_name)
+ meta:set_string("remote_name", "")
+ meta:set_string("conn_status", S("connected to") .. " " .. P2S(rmt_pos))
+ nvm.rmt_pos = rmt_pos
+ elseif state == "client_connected" then
+ Stations:update(pos, {conn_name="nil", single="nil"})
+ meta:set_string("status", "client")
+ meta:set_string("conn_name", "")
+ meta:set_string("remote_name", remote_name)
+ meta:set_string("conn_status", S("connected to") .. " " .. P2S(rmt_pos))
+ nvm.rmt_pos = rmt_pos
+ elseif state == "server_not_connected" then
+ Stations:update(pos, {conn_name=conn_name, single=true})
+ meta:set_string("status", "server")
+ meta:set_string("conn_name", conn_name)
+ meta:set_string("remote_name", "")
+ meta:set_string("conn_status", S("not connected"))
+ nvm.rmt_pos = nil
+ on_lose_connection(pos, "server")
+ elseif state == "client_not_connected" then
+ Stations:update(pos, {conn_name="nil", single=nil})
+ meta:set_string("status", "not connected")
+ meta:set_string("conn_name", "")
+ meta:set_string("remote_name", "")
+ meta:set_string("conn_status", S("not connected"))
+ nvm.rmt_pos = nil
+ on_lose_connection(pos, "client")
+ end
+end
+
+techage.hyperloop.SUBMENU = {
+ {
+ type = "label",
+ label = S("Enter a block name or select an existing one"),
+ tooltip = "",
+ name = "l1",
+ },
+ {
+ type = "ascii",
+ name = "conn_name",
+ label = S("Block name"),
+ tooltip = S("Connection name for this block"),
+ default = "",
+ },
+ {
+ type = "dropdown",
+ choices = "",
+ on_dropdown = on_dropdown,
+ name = "remote_name",
+ label = S("Remote name"),
+ tooltip = S("Connection name of the remote block"),
+ },
+}
+
+function techage.hyperloop.is_client(pos)
+ if HYPERLOOP then
+ local nvm = techage.get_nvm(pos)
+ if Stations:get(nvm.rmt_pos) then
+ if M(pos):get_string("status") == "client" then
+ return true
+ end
+ end
+ end
+end
+
+function techage.hyperloop.is_server(pos)
+ if HYPERLOOP then
+ if M(pos):get_string("status") == "server" then
+ return true
+ end
+ end
+end
+
+function techage.hyperloop.is_paired(pos)
+ if HYPERLOOP then
+ local nvm = techage.get_nvm(pos)
+ if Stations:get(nvm.rmt_pos) then
+ if M(pos):get_string("status") ~= "not connected" then
+ return true
+ end
+ end
+ end
+end
+
+function techage.hyperloop.remote_pos(pos)
+ if HYPERLOOP then
+ local nvm = techage.get_nvm(pos)
+ if Stations:get(nvm.rmt_pos) then
+ if M(pos):contains("remote_name") then
+ return nvm.rmt_pos
+ end
+ end
+ end
+ return pos
+end
+
+function techage.hyperloop.after_place_node(pos, placer, node_type)
+ if HYPERLOOP then
+ Stations:set(pos, node_type, {owner=placer:get_player_name()})
+ M(pos):set_string("node_type", node_type)
+ Tube:after_place_node(pos)
+ end
+end
+
+function techage.hyperloop.after_dig_node(pos, oldnode, oldmetadata, digger)
+ if HYPERLOOP then
+ local conn_name = oldmetadata.fields.conn_name
+ local remote_name = oldmetadata.fields.remote_name
+ local loc_pos, rmt_pos = pos, techage.get_nvm(pos).rmt_pos
+
+ -- Close connections
+ if remote_name and rmt_pos then -- Connected client
+ update_node_data(rmt_pos, "server_not_connected", remote_name, "")
+ elseif conn_name and rmt_pos then -- Connected server
+ update_node_data(rmt_pos, "client_not_connected", "", conn_name)
+ end
+
+ Tube:after_dig_node(pos)
+ Stations:delete(pos)
+ end
+end
+
+function techage.hyperloop.after_formspec(pos, fields)
+ if HYPERLOOP and fields.save or fields.key_enter_field then
+ local meta = M(pos)
+ local conn_name = meta:get_string("conn_name")
+ local remote_name = meta:get_string("remote_name")
+ local status = meta:contains("status") and meta:get_string("status") or "not connected"
+ local loc_pos, rmt_pos = pos, techage.get_nvm(pos).rmt_pos
+
+ if status == "not connected" then
+ if fields.remote_name ~= "" then -- Client
+ local rmt_pos = get_remote_pos(pos, fields.remote_name)
+ if rmt_pos then
+ update_node_data(loc_pos, "client_connected", "", fields.remote_name, rmt_pos)
+ update_node_data(rmt_pos, "server_connected", fields.remote_name, "", loc_pos)
+ end
+ elseif fields.conn_name ~= "" then -- Server
+ update_node_data(loc_pos, "server_not_connected", fields.conn_name, "")
+ end
+ end
+ end
+end
+
diff --git a/techage/basis/laser_lib.lua b/techage/basis/laser_lib.lua
index 802b3c3..135fe61 100644
--- a/techage/basis/laser_lib.lua
+++ b/techage/basis/laser_lib.lua
@@ -42,7 +42,7 @@ local function get_positions(pos, mem, dir)
return true -- no new values
end
--- return both both laser entities the pos and length
+-- return for both laser entities the pos and length
local function get_laser_length_and_pos(pos1, pos2, dir)
local dist = vector.distance(pos1, pos2)
@@ -133,5 +133,14 @@ function techage.renew_laser(pos, force)
return res
end
+function techage.add_laser(pos, pos1, pos2)
+ local dir = vector.direction(pos1, pos2)
+ local param2 = minetest.dir_to_facedir(dir)
+ local size, pos3, pos4 = get_laser_length_and_pos(pos1, pos2, dir)
+ if size then
+ add_laser(pos, pos3, pos4, size, param2)
+ end
+end
+
-- techage.del_laser(pos)
techage.del_laser = del_laser
diff --git a/techage/basis/lib.lua b/techage/basis/lib.lua
index fda1525..6b83c27 100644
--- a/techage/basis/lib.lua
+++ b/techage/basis/lib.lua
@@ -3,7 +3,7 @@
TechAge
=======
- Copyright (C) 2019 Joachim Stolberg
+ Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@@ -27,6 +27,117 @@ local Input = {
20,21,22,23, -- 6
}
+-- Input data to turn a "facedir" block to the right/left
+local ROTATION = {
+ {5,14,11,16}, -- x+
+ {7,12,9,18}, -- x-
+ {0,1,2,3}, -- y+
+ {22,21,20,23}, -- y-
+ {6,15,8,17}, -- z+
+ {4,13,10,19}, -- z-
+}
+
+local FACEDIR_TO_ROT = {[0] =
+ {x=0.000000, y=0.000000, z=0.000000},
+ {x=0.000000, y=4.712389, z=0.000000},
+ {x=0.000000, y=3.141593, z=0.000000},
+ {x=0.000000, y=1.570796, z=0.000000},
+ {x=4.712389, y=0.000000, z=0.000000},
+ {x=3.141593, y=1.570796, z=1.570796},
+ {x=1.570796, y=4.712389, z=4.712389},
+ {x=3.141593, y=4.712389, z=4.712389},
+ {x=1.570796, y=0.000000, z=0.000000},
+ {x=0.000000, y=4.712389, z=1.570796},
+ {x=4.712389, y=1.570796, z=4.712389},
+ {x=0.000000, y=1.570796, z=4.712389},
+ {x=0.000000, y=0.000000, z=1.570796},
+ {x=4.712389, y=0.000000, z=1.570796},
+ {x=0.000000, y=3.141593, z=4.712389},
+ {x=1.570796, y=3.141593, z=4.712389},
+ {x=0.000000, y=0.000000, z=4.712389},
+ {x=1.570796, y=0.000000, z=4.712389},
+ {x=0.000000, y=3.141593, z=1.570796},
+ {x=4.712389, y=0.000000, z=4.712389},
+ {x=0.000000, y=0.000000, z=3.141593},
+ {x=0.000000, y=1.570796, z=3.141593},
+ {x=0.000000, y=3.141593, z=3.141593},
+ {x=0.000000, y=4.712389, z=3.141593},
+}
+
+local RotationViaYAxis = {}
+
+for _,row in ipairs(ROTATION) do
+ for i = 1,4 do
+ local val = row[i]
+ local left = row[i == 1 and 4 or i - 1]
+ local right = row[i == 4 and 1 or i + 1]
+ RotationViaYAxis[val] = {left, right}
+ end
+end
+
+function techage.facedir_to_rotation(facedir)
+ return FACEDIR_TO_ROT[facedir]
+end
+
+function techage.param2_turn_left(param2)
+ return (RotationViaYAxis[param2] or RotationViaYAxis[0])[1]
+end
+
+function techage.param2_turn_right(param2)
+ return (RotationViaYAxis[param2] or RotationViaYAxis[0])[2]
+end
+
+-------------------------------------------------------------------------------
+-- Rotate nodes around the center
+-------------------------------------------------------------------------------
+function techage.positions_center(lpos)
+ local c = {x=0, y=0, z=0}
+ for _,v in ipairs(lpos) do
+ c = vector.add(c, v)
+ end
+ c = vector.divide(c, #lpos)
+ c = vector.round(c)
+ c.y = 0
+ return c
+end
+
+function techage.rotate_around_axis(v, c, turn)
+ local dx, dz = v.x - c.x, v.z - c.z
+ if turn == "l" then
+ return {
+ x = c.x - dz,
+ y = v.y,
+ z = c.z + dx,
+ }
+ elseif turn == "r" then
+ return {
+ x = c.x + dz,
+ y = v.y,
+ z = c.z - dx,
+ }
+ elseif turn == "" then
+ return v
+ else -- turn 180 degree
+ return {
+ x = c.x - dx,
+ y = v.y,
+ z = c.z - dz,
+ }
+ end
+end
+
+-- Function returns a list ẃith the new node positions
+-- turn is one of "l", "r", "2l", "2r"
+-- cpos is the center pos (optional)
+function techage.rotate_around_center(nodes1, turn, cpos)
+ cpos = cpos or techage.positions_center(nodes1)
+ local nodes2 = {}
+ for _,pos in ipairs(nodes1) do
+ nodes2[#nodes2 + 1] = techage.rotate_around_axis(pos, cpos, turn)
+ end
+ return nodes2
+end
+
-- allowed for digging
local RegisteredNodesToBeDug = {}
@@ -330,6 +441,14 @@ function techage.mydump(o, indent, nested, level)
return "{"..table.concat(t, ", ").."}"
end
+function techage.vector_dump(posses)
+ local t = {}
+ for _,pos in ipairs(posses) do
+ t[#t + 1] = minetest.pos_to_string(pos)
+ end
+ return table.concat(t, " ")
+end
+
-- title bar help (width is the fornmspec width)
function techage.question_mark_help(width, tooltip)
local x = width- 0.6
@@ -343,3 +462,88 @@ function techage.wrench_tooltip(x, y)
"tooltip["..x..","..y..";0.5,0.5;"..tooltip..";#0C3D32;#FFFFFF]"
end
+-------------------------------------------------------------------------------
+-- Terminal history buffer
+-------------------------------------------------------------------------------
+local BUFFER_DEPTH = 10
+
+function techage.historybuffer_add(pos, s)
+ local mem = techage.get_mem(pos)
+ mem.hisbuf = mem.hisbuf or {}
+
+ if #s > 2 then
+ table.insert(mem.hisbuf, s)
+ if #mem.hisbuf > BUFFER_DEPTH then
+ table.remove(mem.hisbuf, 1)
+ end
+ mem.hisbuf_idx = #mem.hisbuf + 1
+ end
+end
+
+function techage.historybuffer_priv(pos)
+ local mem = techage.get_mem(pos)
+ mem.hisbuf = mem.hisbuf or {}
+ mem.hisbuf_idx = mem.hisbuf_idx or 1
+
+ mem.hisbuf_idx = math.max(1, mem.hisbuf_idx - 1)
+ return mem.hisbuf[mem.hisbuf_idx]
+end
+
+function techage.historybuffer_next(pos)
+ local mem = techage.get_mem(pos)
+ mem.hisbuf = mem.hisbuf or {}
+ mem.hisbuf_idx = mem.hisbuf_idx or 1
+
+ mem.hisbuf_idx = math.min(#mem.hisbuf, mem.hisbuf_idx + 1)
+ return mem.hisbuf[mem.hisbuf_idx]
+end
+
+-------------------------------------------------------------------------------
+-- Player TA5 Experience Points
+-------------------------------------------------------------------------------
+function techage.get_expoints(player)
+ if player and player.get_meta then
+ local meta = player:get_meta()
+ if meta then
+ return meta:get_int("techage_ex_points")
+ end
+ end
+end
+
+-- Can only be used from one collider
+function techage.add_expoint(player, number)
+ if player and player.get_meta then
+ local meta = player:get_meta()
+ if meta then
+ if not meta:contains("techage_collider_number") then
+ meta:set_string("techage_collider_number", number)
+ end
+ if meta:get_string("techage_collider_number") == number then
+ meta:set_int("techage_ex_points", meta:get_int("techage_ex_points") + 1)
+ return true
+ else
+ minetest.chat_send_player(player:get_player_name(), "[techage] More than one collider is not allowed!")
+ return false
+ end
+ end
+ end
+end
+
+function techage.on_remove_collider(player)
+ if player and player.get_meta then
+ local meta = player:get_meta()
+ if meta then
+ meta:set_string("techage_collider_number", "")
+ end
+ end
+end
+
+function techage.set_expoints(player, ex_points)
+ if player and player.get_meta then
+ local meta = player:get_meta()
+ if meta then
+ meta:set_int("techage_ex_points", ex_points)
+ return true
+ end
+ end
+end
diff --git a/techage/basis/liquid_lib.lua b/techage/basis/liquid_lib.lua
index bf1c395..967f560 100644
--- a/techage/basis/liquid_lib.lua
+++ b/techage/basis/liquid_lib.lua
@@ -30,8 +30,8 @@ local function help(x, y)
"tooltip["..x..","..y..";0.5,0.5;"..tooltip..";#0C3D32;#FFFFFF]"
end
-function techage.liquid.formspec(pos, nvm)
- local title = S("Liquid Tank")
+function techage.liquid.formspec(pos, nvm, title)
+ title = title or S("Liquid Tank")
local itemname = "techage:liquid"
if nvm.liquid and nvm.liquid.amount and nvm.liquid.amount > 0 and nvm.liquid.name then
itemname = nvm.liquid.name.." "..nvm.liquid.amount
@@ -41,19 +41,19 @@ function techage.liquid.formspec(pos, nvm)
local meta = M(pos)
local public = dump((meta:get_int("public") or 0) == 1)
local keep_assignment = dump((meta:get_int("keep_assignment") or 0) == 1)
- return "size[5,3.5]"..
- "box[0,-0.1;4.8,0.5;#c6e8ff]"..
- "label[1.5,-0.1;"..minetest.colorize("#000000", title).."]"..
- help(4.4, -0.1)..
- techage.item_image(2, 1, itemname)..
+ return "size[8,3.5]"..
+ "box[0,-0.1;7.8,0.5;#c6e8ff]"..
+ "label[0.2,-0.1;"..minetest.colorize("#000000", title).."]"..
+ help(7.4, -0.1)..
+ techage.item_image(3.5, 1, itemname)..
"checkbox[0.1,2.5;public;"..S("Allow public access to the tank")..";"..public.."]"..
"checkbox[0.1,3;keep_assignment;"..S("keep assignment")..";"..keep_assignment.."]"
else
- return "size[4,2]"..
- "box[0,-0.1;3.8,0.5;#c6e8ff]"..
- "label[1,-0.1;"..minetest.colorize("#000000", title).."]"..
- help(3.4, -0.1)..
- techage.item_image(1.5, 1, itemname)
+ return "size[8,2]"..
+ "box[0,-0.1;7.8,0.5;#c6e8ff]"..
+ "label[0.2,-0.1;"..minetest.colorize("#000000", title).."]"..
+ help(7.4, -0.1)..
+ techage.item_image(3.5, 1, itemname)
end
end
diff --git a/techage/basis/mark_lib.lua b/techage/basis/mark_lib.lua
new file mode 100644
index 0000000..8cc52ce
--- /dev/null
+++ b/techage/basis/mark_lib.lua
@@ -0,0 +1,122 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2020-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ Block marker lib for door/move/fly controller
+
+]]--
+
+local marker = {}
+
+local MarkedNodes = {} -- t[player] = {{entity, pos},...}
+local MaxNumber = {}
+local CurrentPos -- to mark punched entities
+
+local function unmark_position(name, pos)
+ pos = vector.round(pos)
+ for idx,item in ipairs(MarkedNodes[name] or {}) do
+ if vector.equals(pos, item.pos) then
+ item.entity:remove()
+ table.remove(MarkedNodes[name], idx)
+ CurrentPos = pos
+ return
+ end
+ end
+end
+
+function marker.unmark_all(name)
+ for _,item in ipairs(MarkedNodes[name] or {}) do
+ item.entity:remove()
+ end
+ MarkedNodes[name] = nil
+end
+
+local function mark_position(name, pos)
+ pos = vector.round(pos)
+ if not CurrentPos or not vector.equals(pos, CurrentPos) then -- entity not punched?
+ if #MarkedNodes[name] < MaxNumber[name] then
+ local entity = minetest.add_entity(pos, "techage:block_marker")
+ if entity ~= nil then
+ entity:get_luaentity().player_name = name
+ table.insert(MarkedNodes[name], {pos = pos, entity = entity})
+ end
+ CurrentPos = nil
+ return true
+ end
+ end
+ CurrentPos = nil
+end
+
+function marker.get_poslist(name)
+ local idx = 0
+ local lst = {}
+ for _,item in ipairs(MarkedNodes[name] or {}) do
+ table.insert(lst, item.pos)
+ idx = idx + 1
+ if idx >= 16 then break end
+ end
+ return lst
+end
+
+minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing)
+ if puncher and puncher:is_player() then
+ local name = puncher:get_player_name()
+
+ if not MarkedNodes[name] then
+ return
+ end
+
+ mark_position(name, pointed_thing.under)
+ end
+end)
+
+function marker.start(name, max_num)
+ MaxNumber[name] = max_num or 99
+ MarkedNodes[name] = {}
+end
+
+function marker.stop(name)
+ MarkedNodes[name] = nil
+ MaxNumber[name] = nil
+end
+
+minetest.register_entity(":techage:block_marker", {
+ initial_properties = {
+ visual = "cube",
+ textures = {
+ "techage_cube_mark.png",
+ "techage_cube_mark.png",
+ "techage_cube_mark.png",
+ "techage_cube_mark.png",
+ "techage_cube_mark.png",
+ "techage_cube_mark.png",
+ },
+ --use_texture_alpha = true,
+ physical = false,
+ visual_size = {x=1.1, y=1.1},
+ collisionbox = {-0.55,-0.55,-0.55, 0.55,0.55,0.55},
+ glow = 8,
+ },
+ on_step = function(self, dtime)
+ self.ttl = (self.ttl or 2400) - 1
+ if self.ttl <= 0 then
+ local pos = self.object:get_pos()
+ unmark_position(self.player_name, pos)
+ end
+ end,
+ on_punch = function(self, hitter)
+ local pos = self.object:get_pos()
+ local name = hitter:get_player_name()
+ if name == self.player_name then
+ unmark_position(name, pos)
+ end
+ end,
+})
+
+return marker
\ No newline at end of file
diff --git a/techage/basis/node_states.lua b/techage/basis/node_states.lua
index 9e76c89..ea4a29d 100644
--- a/techage/basis/node_states.lua
+++ b/techage/basis/node_states.lua
@@ -174,6 +174,7 @@ function NodeStates:new(attr)
cycle_time = attr.cycle_time, -- for running state
standby_ticks = attr.standby_ticks, -- for standby state
-- optional
+ countdown_ticks = attr.countdown_ticks or 1,
node_name_passive = attr.node_name_passive,
node_name_active = attr.node_name_active,
infotext_name = attr.infotext_name,
@@ -254,7 +255,7 @@ function NodeStates:start(pos, nvm)
if self.start_node then
self.start_node(pos, nvm, state)
end
- nvm.techage_countdown = 1
+ nvm.techage_countdown = self.countdown_ticks
if self.node_name_active then
swap_node(pos, self.node_name_active)
end
diff --git a/techage/basis/oggfiles.lua b/techage/basis/oggfiles.lua
new file mode 100644
index 0000000..ffe7c82
--- /dev/null
+++ b/techage/basis/oggfiles.lua
@@ -0,0 +1,103 @@
+techage.OggFileList = {
+ "autobahn_motor", -- ./mods/autobahn/sounds
+ "signs_bot_ping", -- ./mods/signs_bot/sounds
+ "signs_bot_go_away", -- ./mods/signs_bot/sounds
+ "signs_bot_step", -- ./mods/signs_bot/sounds
+ "signs_bot_pong", -- ./mods/signs_bot/sounds
+ "signs_bot_error", -- ./mods/signs_bot/sounds
+ "normal2", -- ./mods/hyperloop/sounds
+ "up2", -- ./mods/hyperloop/sounds
+ "down2", -- ./mods/hyperloop/sounds
+ "ele_norm", -- ./mods/hyperloop/sounds
+ "door", -- ./mods/hyperloop/sounds
+ "hyperloop_crowbar", -- ./mods/hyperloop/sounds
+ "ele_door", -- ./mods/hyperloop/sounds
+ "techage_watermill", -- ./mods/techage/sounds
+ "techage_button", -- ./mods/techage/sounds
+ "techage_steamengine", -- ./mods/techage/sounds
+ "techage_generator", -- ./mods/techage/sounds
+ "techage_gasflare", -- ./mods/techage/sounds
+ "techage_explore", -- ./mods/techage/sounds
+ "techage_mill", -- ./mods/techage/sounds
+ "techage_reactor", -- ./mods/techage/sounds
+ "techage_valve", -- ./mods/techage/sounds
+ "techage_oildrill", -- ./mods/techage/sounds
+ "techage_turbine", -- ./mods/techage/sounds
+ "techage_booster", -- ./mods/techage/sounds
+ "techage_quarry", -- ./mods/techage/sounds
+ "techage_reboiler", -- ./mods/techage/sounds
+ "jetpack_loop", -- ./mods/jetpack/sounds
+ "paperflip1", -- ./mods/unified_inventory/sounds
+ "teleport", -- ./mods/unified_inventory/sounds
+ "electricity", -- ./mods/unified_inventory/sounds
+ "owl", -- ./mods/unified_inventory/sounds
+ "click", -- ./mods/unified_inventory/sounds
+ "birds", -- ./mods/unified_inventory/sounds
+ "paperflip2", -- ./mods/unified_inventory/sounds
+ "dingdong", -- ./mods/unified_inventory/sounds
+ "trash", -- ./mods/unified_inventory/sounds
+ "trash_all", -- ./mods/unified_inventory/sounds
+ "ta4_jetpack", -- ./mods/ta4_jetpack/sounds
+ "ta4_jetpack_alarm", -- ./mods/ta4_jetpack/sounds
+ "ta4_jetpack_on", -- ./mods/ta4_jetpack/sounds
+ "player_damage", -- ./games/minetest_game/mods/player_api/sounds
+ "env_sounds_water", -- ./games/minetest_game/mods/env_sounds/sounds
+ "env_sounds_lava", -- ./games/minetest_game/mods/env_sounds/sounds
+ "doors_door_close", -- ./games/minetest_game/mods/doors/sounds
+ "doors_steel_door_close", -- ./games/minetest_game/mods/doors/sounds
+ "doors_door_open", -- ./games/minetest_game/mods/doors/sounds
+ "doors_fencegate_close", -- ./games/minetest_game/mods/doors/sounds
+ "doors_glass_door_close", -- ./games/minetest_game/mods/doors/sounds
+ "doors_fencegate_open", -- ./games/minetest_game/mods/doors/sounds
+ "doors_glass_door_open", -- ./games/minetest_game/mods/doors/sounds
+ "doors_steel_door_open", -- ./games/minetest_game/mods/doors/sounds
+ "fire_flint_and_steel", -- ./games/minetest_game/mods/fire/sounds
+ "fire_large", -- ./games/minetest_game/mods/fire/sounds
+ "fire_fire", -- ./games/minetest_game/mods/fire/sounds
+ "fire_extinguish_flame", -- ./games/minetest_game/mods/fire/sounds
+ "fire_small", -- ./games/minetest_game/mods/fire/sounds
+ "tnt_ignite", -- ./games/minetest_game/mods/tnt/sounds
+ "tnt_gunpowder_burning", -- ./games/minetest_game/mods/tnt/sounds
+ "tnt_explode", -- ./games/minetest_game/mods/tnt/sounds
+ "carts_cart_new", -- ./games/minetest_game/mods/carts/sounds
+ "carts_cart_moving", -- ./games/minetest_game/mods/carts/sounds
+ "xpanes_steel_bar_door_open", -- ./games/minetest_game/mods/xpanes/sounds
+ "xpanes_steel_bar_door_close", -- ./games/minetest_game/mods/xpanes/sounds
+ "default_break_glass", -- ./games/minetest_game/mods/default/sounds
+ "default_dig_dig_immediate", -- ./games/minetest_game/mods/default/sounds
+ "default_dig_cracky", -- ./games/minetest_game/mods/default/sounds
+ "default_dig_choppy", -- ./games/minetest_game/mods/default/sounds
+ "default_water_footstep", -- ./games/minetest_game/mods/default/sounds
+ "player_damage", -- ./games/minetest_game/mods/default/sounds
+ "default_gravel_footstep", -- ./games/minetest_game/mods/default/sounds
+ "default_dig_metal", -- ./games/minetest_game/mods/default/sounds
+ "default_gravel_dug", -- ./games/minetest_game/mods/default/sounds
+ "default_hard_footstep", -- ./games/minetest_game/mods/default/sounds
+ "default_sand_footstep", -- ./games/minetest_game/mods/default/sounds
+ "default_grass_footstep", -- ./games/minetest_game/mods/default/sounds
+ "default_chest_close", -- ./games/minetest_game/mods/default/sounds
+ "default_cool_lava", -- ./games/minetest_game/mods/default/sounds
+ "default_place_node_hard", -- ./games/minetest_game/mods/default/sounds
+ "default_ice_dug", -- ./games/minetest_game/mods/default/sounds
+ "default_dig_crumbly", -- ./games/minetest_game/mods/default/sounds
+ "default_tool_breaks", -- ./games/minetest_game/mods/default/sounds
+ "default_ice_footstep", -- ./games/minetest_game/mods/default/sounds
+ "default_dig_cracky", -- ./games/minetest_game/mods/default/sounds
+ "default_chest_open", -- ./games/minetest_game/mods/default/sounds
+ "default_gravel_dig", -- ./games/minetest_game/mods/default/sounds
+ "default_dig_oddly_breakable_by_hand", -- ./games/minetest_game/mods/default/sounds
+ "default_dug_metal", -- ./games/minetest_game/mods/default/sounds
+ "default_dirt_footstep", -- ./games/minetest_game/mods/default/sounds
+ "default_dig_choppy", -- ./games/minetest_game/mods/default/sounds
+ "default_glass_footstep", -- ./games/minetest_game/mods/default/sounds
+ "default_snow_footstep", -- ./games/minetest_game/mods/default/sounds
+ "default_place_node", -- ./games/minetest_game/mods/default/sounds
+ "default_dig_snappy", -- ./games/minetest_game/mods/default/sounds
+ "default_dug_node", -- ./games/minetest_game/mods/default/sounds
+ "default_metal_footstep", -- ./games/minetest_game/mods/default/sounds
+ "default_ice_dig", -- ./games/minetest_game/mods/default/sounds
+ "default_place_node_metal", -- ./games/minetest_game/mods/default/sounds
+ "default_wood_footstep", -- ./games/minetest_game/mods/default/sounds
+ "default_furnace_active", -- ./games/minetest_game/mods/default/sounds
+ "default_item_smoke", -- ./games/minetest_game/mods/default/sounds
+}
diff --git a/techage/basis/recipe_lib.lua b/techage/basis/recipe_lib.lua
index 95ecddc..76306d3 100644
--- a/techage/basis/recipe_lib.lua
+++ b/techage/basis/recipe_lib.lua
@@ -22,6 +22,19 @@ local range = techage.in_range
techage.recipes = {}
+local GROUP_ITEMS = {
+ stone = "default:cobble",
+ wood = "default:wood",
+ book = "default:book",
+ sand = "default:sand",
+ leaves = "default:leaves",
+ stick = "default:stick",
+ tree = "default:tree",
+ vessel = "vessels:glass_bottle",
+ wool = "wool:white",
+}
+
+
local RECIPE = {
output = {name = "", num = 0},
waste = {name = "", num = 0},
@@ -33,6 +46,22 @@ local RECIPE = {
},
}
+local function filter_recipes_based_on_points(recipes, owner)
+ local ex_points = 0
+ if owner then
+ local player = minetest.get_player_by_name(owner)
+ ex_points = techage.get_expoints(player) or 0
+ end
+
+ local tbl = {}
+ for _,item in ipairs(recipes) do
+ if ex_points >= (item.ex_points or 0) then
+ tbl[#tbl + 1] = item
+ end
+ end
+ return tbl
+end
+
-- Formspec
local function input_string(recipe)
@@ -80,24 +109,24 @@ function techage.recipes.add(rtype, recipe)
name, num = unpack(string.split(recipe.output, " "))
item.output = {name = name or "", num = tonumber(num) or 0}
item.catalyst = recipe.catalyst
+ item.ex_points = recipe.ex_points or 0
Recipes[rtype][#Recipes[rtype]+1] = item
output = name
- if minetest.global_exists("unified_inventory") then
- unified_inventory.register_craft({
- output = recipe.output,
- items = recipe.input,
- type = rtype,
- })
- end
+ techage.recipes.register_craft({
+ output = recipe.output,
+ items = recipe.input,
+ type = rtype,
+ })
NormalizedRecipes[output] = {
output = recipe.output,
items = recipe.input,
}
end
-function techage.recipes.formspec(x, y, rtype, nvm)
+function techage.recipes.formspec(x, y, rtype, nvm, owner)
local recipes = Recipes[rtype] or {}
+ recipes = filter_recipes_based_on_points(recipes, owner)
nvm.recipe_idx = range(nvm.recipe_idx or 1, 1, #recipes)
local idx = nvm.recipe_idx
local recipe = recipes[idx] or RECIPE
@@ -137,3 +166,114 @@ function techage.recipes.get_recipe(name)
return NormalizedRecipes[name]
end
+
+function techage.recipes.get_default_group_item_name(item_name)
+ if item_name and item_name:sub(1, 6) == "group:" then
+ local default_name = GROUP_ITEMS[item_name:sub(7)]
+ if default_name then
+ return default_name
+ end
+ end
+ return item_name
+end
+
+function techage.recipes.add_group_item(group, default_item_name)
+ GROUP_ITEMS[group] = default_item_name
+end
+
+-------------------------------------------------------------------------------
+-- Borrowed from ghaydn
+-------------------------------------------------------------------------------
+local has_i3 = minetest.get_modpath("i3")
+local has_ui = minetest.get_modpath("unified_inventory")
+local has_cg = minetest.get_modpath("craftguide")
+
+local function format_i3(input)
+ local output = {}
+ for _, entry in ipairs(input) do
+ local secondput = ""
+ if type(entry) == "table" then
+ for _, secondtry in ipairs(entry) do
+ secondput = secondput..secondtry..","
+ end
+ table.insert(output, secondput)
+ else
+ table.insert(output, entry)
+ end
+ end
+ return output
+end
+
+techage.recipes.register_craft_type = function(name, def)
+ if has_cg then
+ local cg_def = {
+ description = def.description,
+ icon = def.icon,
+ }
+ craftguide.register_craft_type(name, cg_def)
+ end
+ if has_i3 then
+ local i3_def = {
+ description = def.description,
+ icon = def.icon,
+ width = def.width or 3,
+ height = def.height or 3,
+ dynamic_display_size = def.dynamic_display_size or nil,
+ uses_crafting_grid = def.uses_crafting_grid,
+ }
+ i3.register_craft_type(name, i3_def)
+ end
+ if has_ui then
+ local ui_def = {
+ description = def.description,
+ icon = def.icon,
+ width = def.width or 3,
+ height = def.height or 3,
+ dynamic_display_size = def.dynamic_display_size or nil,
+ uses_crafting_grid = def.uses_crafting_grid,
+ }
+ unified_inventory.register_craft_type(name, ui_def)
+ end
+end
+
+techage.recipes.register_craft = function(def)
+ if not def.items then
+ if def.input then
+ def.items = table.copy(def.input)
+ elseif def.recipe then
+ def.items = table.copy(def.recipe)
+ end
+ end
+ if not def.result then
+ if def.output then def.result = def.output end
+ end
+
+ if has_cg then
+ local cg_def = {
+ result = def.result,
+ type = def.type,
+ items = def.items,
+ }
+ craftguide.register_craft(cg_def)
+ end
+ if has_i3 then
+
+ local i3_def = {
+ result = def.result,
+ type = def.type,
+ items = format_i3(def.items),
+ width = def.width or 3,
+ }
+ i3.register_craft(i3_def)
+ end
+ if has_ui then
+ local ui_def = {
+ output = def.result,
+ type = def.type,
+ items = def.items,
+ width = def.width or 3,
+ height = def.height or 3,
+ }
+ unified_inventory.register_craft(ui_def)
+ end
+end
diff --git a/techage/basis/shared_inv.lua b/techage/basis/shared_inv.lua
new file mode 100644
index 0000000..3f375af
--- /dev/null
+++ b/techage/basis/shared_inv.lua
@@ -0,0 +1,69 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2019-2022 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ Library for shared inventories
+
+]]--
+
+-- for lazy programmers
+local S2P = minetest.string_to_pos
+local P2S = minetest.pos_to_string
+local M = minetest.get_meta
+local S = techage.S
+
+techage.shared_inv = {}
+
+local hyperloop = techage.hyperloop
+local remote_pos = techage.hyperloop.remote_pos
+
+local function copy_inventory_list(from_pos, to_pos, listname)
+ local inv1 = minetest.get_inventory({type="node", pos=from_pos})
+ local inv2 = minetest.get_inventory({type="node", pos=to_pos})
+ inv2:set_list(listname, inv1:get_list(listname))
+end
+
+function techage.shared_inv.node_timer(pos, elapsed)
+ local rmt_pos = remote_pos(pos)
+ if techage.is_activeformspec(pos) then
+ copy_inventory_list(rmt_pos, pos, "main")
+ return true
+ end
+ return false
+end
+
+-- Synchronize the client inventory with the server one
+function techage.shared_inv.before_inv_access(pos, listname)
+ if hyperloop.is_client(pos) then
+ local rmt_pos = remote_pos(pos)
+ copy_inventory_list(rmt_pos, pos, listname)
+ return true
+ end
+ return false
+end
+
+-- Synchronize the client inventory with the server one
+function techage.shared_inv.after_inv_access(pos, listname)
+ if hyperloop.is_client(pos) then
+ local rmt_pos = remote_pos(pos)
+ copy_inventory_list(pos, rmt_pos, listname)
+ return true
+ end
+ return false
+end
+
+function techage.shared_inv.on_rightclick(pos, clicker, listname)
+ if hyperloop.is_client(pos) then
+ local rmt_pos = remote_pos(pos)
+ copy_inventory_list(rmt_pos, pos, listname)
+ techage.set_activeformspec(pos, clicker)
+ minetest.get_node_timer(pos):start(2)
+ end
+end
+
diff --git a/techage/basis/shared_tank.lua b/techage/basis/shared_tank.lua
new file mode 100644
index 0000000..5d0b1fe
--- /dev/null
+++ b/techage/basis/shared_tank.lua
@@ -0,0 +1,105 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2019-2022 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ Library for shared inventories
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local NDEF = function(pos) return minetest.registered_nodes[techage.get_node_lvm(pos).name] or {} end
+
+techage.shared_tank = {}
+
+local liquid = networks.liquid
+local hyperloop = techage.hyperloop
+local remote_pos = techage.hyperloop.remote_pos
+local menu = techage.menu
+
+local function formspec(pos)
+ local ndef = NDEF(pos)
+ local status = M(pos):get_string("conn_status")
+ if hyperloop.is_client(pos) or hyperloop.is_server(pos) then
+ local title = ndef.description .. " " .. status
+ local nvm = techage.get_nvm(remote_pos(pos))
+ return techage.liquid.formspec(pos, nvm, title)
+ else
+ return menu.generate_formspec(pos, ndef, hyperloop.SUBMENU)
+ end
+end
+
+function techage.shared_tank.node_timer(pos)
+ if techage.is_activeformspec(pos) then
+ M(pos):set_string("formspec", formspec(pos))
+ return true
+ end
+ return false
+end
+
+function techage.shared_tank.on_rightclick(pos, node, clicker)
+ --if hyperloop.is_client(pos) then
+ techage.set_activeformspec(pos, clicker)
+ minetest.get_node_timer(pos):start(2)
+ --end
+ M(pos):set_string("formspec", formspec(pos))
+end
+
+function techage.shared_tank.can_dig(pos, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return false
+ end
+ pos = remote_pos(pos)
+ return techage.liquid.is_empty(pos)
+end
+
+function techage.shared_tank.peek_liquid(pos, indir)
+ pos = remote_pos(pos)
+ local nvm = techage.get_nvm(pos)
+ return liquid.srv_peek(nvm)
+end
+
+function techage.shared_tank.take_liquid(pos, indir, name, amount)
+ pos = remote_pos(pos)
+ local nvm = techage.get_nvm(pos)
+ amount, name = liquid.srv_take(nvm, name, amount)
+ if techage.is_activeformspec(pos) then
+ M(pos):set_string("formspec", formspec(pos))
+ end
+ return amount, name
+end
+
+function techage.shared_tank.put_liquid(pos, indir, name, amount)
+ pos = remote_pos(pos)
+ -- check if it is not powder
+ local ndef = minetest.registered_craftitems[name] or {}
+ if not ndef.groups or ndef.groups.powder ~= 1 then
+ local nvm = techage.get_nvm(pos)
+ local ndef = NDEF(pos)
+ local leftover = liquid.srv_put(nvm, name, amount, ndef.liquid.capa)
+ if techage.is_activeformspec(pos) then
+ M(pos):set_string("formspec", formspec(pos))
+ end
+ return leftover
+ end
+ return amount
+end
+
+function techage.shared_tank.untake_liquid(pos, indir, name, amount)
+ pos = remote_pos(pos)
+ local nvm = techage.get_nvm(pos)
+ local ndef = NDEF(pos)
+ local leftover = liquid.srv_put(nvm, name, amount, ndef.liquid.capa)
+ if techage.is_activeformspec(pos) then
+ M(pos):set_string("formspec", formspec(pos))
+ end
+ return leftover
+end
+
+techage.shared_tank.formspec = formspec
\ No newline at end of file
diff --git a/techage/tools/submenu.lua b/techage/basis/submenu.lua
similarity index 84%
rename from techage/tools/submenu.lua
rename to techage/basis/submenu.lua
index a06ad7d..f7011db 100644
--- a/techage/tools/submenu.lua
+++ b/techage/basis/submenu.lua
@@ -3,7 +3,7 @@
TechAge
=======
- Copyright (C) 2019-2021 Joachim Stolberg
+ Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@@ -13,7 +13,7 @@
local S = techage.S
-local menu = {}
+techage.menu = {}
local function index(list, x)
for idx, v in ipairs(list) do
@@ -48,7 +48,9 @@ local function generate_formspec_substring(pos, meta, form_def, player_name)
local offs = (i - 1) * 0.9 - 0.2
tbl[#tbl+1] = "label[0," .. offs .. ";" .. minetest.formspec_escape(elem.label) .. ":]"
tbl[#tbl+1] = "tooltip[0," .. offs .. ";4,1;" .. elem.tooltip .. "]"
- if elem.type == "number" then
+ if elem.type == "label" then
+ -- none
+ elseif elem.type == "number" then
local val = elem.default
if meta:contains(elem.name) then
val = meta:get_int(elem.name)
@@ -91,7 +93,7 @@ local function generate_formspec_substring(pos, meta, form_def, player_name)
elseif elem.type == "const" then
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. elem.value .. "]"
elseif elem.type == "output" then
- local val = nvm[elem.name] or ""
+ local val = nvm[elem.name] or meta:get_string(elem.name) or ""
if tonumber(val) then
val = techage.round(val)
end
@@ -104,6 +106,15 @@ local function generate_formspec_substring(pos, meta, form_def, player_name)
val = meta:get_string(elem.name) or ""
end
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. val .. "]"
+ elseif elem.on_dropdown then -- block provides a specific list of choice elements
+ local val = elem.default
+ if meta:contains(elem.name) then
+ val = meta:get_string(elem.name) or ""
+ end
+ local choices = elem.on_dropdown(pos)
+ local l = choices:split(",")
+ local idx = index(l, val) or 1
+ tbl[#tbl+1] = "dropdown[4.72," .. (offs) .. ";5.5,1.4;" .. elem.name .. ";" .. choices .. ";" .. idx .. "]"
else
local val = elem.default
if meta:contains(elem.name) then
@@ -112,7 +123,7 @@ local function generate_formspec_substring(pos, meta, form_def, player_name)
local idx = index(l, val) or 1
tbl[#tbl+1] = "dropdown[4.72," .. (offs) .. ";5.5,1.4;" .. elem.name .. ";" .. elem.choices .. ";" .. idx .. "]"
end
- elseif elem.type == "items" then
+ elseif elem.type == "items" then -- inventory
tbl[#tbl+1] = "list[detached:" .. minetest.formspec_escape(player_name) .. "_techage_wrench_menu;cfg;4.75," .. offs .. ";" .. elem.size .. ",1;]"
player_inv_needed = true
end
@@ -193,7 +204,7 @@ local function evaluate_data(pos, meta, form_def, fields, player_name)
if fields[elem.name] ~= nil then
meta:set_string(elem.name, fields[elem.name])
end
- elseif elem.type == "items" then
+ elseif elem.type == "items" and player_name then
local inv_name = minetest.formspec_escape(player_name) .. "_techage_wrench_menu"
local dinv = minetest.get_inventory({type = "detached", name = inv_name})
local ninv = minetest.get_inventory({type = "node", pos = pos})
@@ -208,25 +219,26 @@ local function evaluate_data(pos, meta, form_def, fields, player_name)
return res
end
-function menu.generate_formspec(pos, ndef, form_def, player_name)
+function techage.menu.generate_formspec(pos, ndef, form_def, player_name)
local meta = minetest.get_meta(pos)
local number = techage.get_node_number(pos)
local mem = techage.get_mem(pos)
mem.star = ((mem.star or 0) + 1) % 2
local star = mem.star == 1 and "*" or ""
- local inv_name = minetest.formspec_escape(player_name) .. "_techage_wrench_menu"
- minetest.create_detached_inventory(inv_name, {
- allow_put = allow_put,
- allow_take = allow_take})
- local dinv = minetest.get_inventory({type = "detached", name = inv_name})
- local ninv = minetest.get_inventory({type = "node", pos = pos})
- if dinv and ninv then
- dinv:set_size('cfg', ninv:get_size("cfg"))
- for i = 1, ninv:get_size("cfg") do
- dinv:set_stack("cfg", i, ninv:get_stack("cfg", i))
+ if player_name then
+ local inv_name = minetest.formspec_escape(player_name) .. "_techage_wrench_menu"
+ minetest.create_detached_inventory(inv_name, {
+ allow_put = allow_put,
+ allow_take = allow_take})
+ local dinv = minetest.get_inventory({type = "detached", name = inv_name})
+ local ninv = minetest.get_inventory({type = "node", pos = pos})
+ if dinv and ninv then
+ dinv:set_size('cfg', ninv:get_size("cfg"))
+ for i = 1, ninv:get_size("cfg") do
+ dinv:set_stack("cfg", i, ninv:get_stack("cfg", i))
+ end
end
end
-
if meta and number and ndef and form_def then
local title = ndef.description .. " (" .. number .. ")"
local player_inv_needed, text = generate_formspec_substring(pos, meta, form_def, player_name)
@@ -275,13 +287,10 @@ function menu.generate_formspec(pos, ndef, form_def, player_name)
return ""
end
-function menu.eval_input(pos, form_def, fields, player_name)
- --print(dump(fields))
- if fields.save then
+function techage.menu.eval_input(pos, form_def, fields, player_name)
+ if fields.save or fields.key_enter_field then
local meta = minetest.get_meta(pos)
evaluate_data(pos, meta, form_def, fields, player_name)
end
- return fields.refresh or fields.save
+ return fields.refresh or fields.save or fields.key_enter_field
end
-
-return menu
diff --git a/techage/basis/teleport.lua b/techage/basis/teleport.lua
new file mode 100644
index 0000000..4184c33
--- /dev/null
+++ b/techage/basis/teleport.lua
@@ -0,0 +1,167 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2019-2022 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ For tupe/pipe blocks with teleport support
+
+]]--
+
+-- for lazy programmers
+local S2P = minetest.string_to_pos
+local P2S = minetest.pos_to_string
+local NDEF = function(pos) return minetest.registered_nodes[techage.get_node_lvm(pos).name] or {} end
+local M = minetest.get_meta
+local S = techage.S
+local menu = techage.menu
+
+techage.teleport = {}
+
+local PairingList = {} -- {owner = {node_type = {channel = pos}}}
+
+local function get_pairing_table1(meta)
+ local owner = meta:get_string("owner")
+ local node_type = meta:get_string("tele_node_type")
+ PairingList[owner] = PairingList[owner] or {}
+ PairingList[owner][node_type] = PairingList[owner][node_type] or {}
+ return PairingList[owner][node_type]
+end
+
+local function get_pairing_table2(oldmetadata)
+ local owner = oldmetadata.fields.owner
+ local node_type = oldmetadata.fields.tele_node_type
+ PairingList[owner] = PairingList[owner] or {}
+ PairingList[owner][node_type] = PairingList[owner][node_type] or {}
+ return PairingList[owner][node_type]
+end
+
+local function get_free_server_list(pos)
+ local tbl = {""}
+ for name, pos in pairs(get_pairing_table1(M(pos))) do
+ table.insert(tbl, name)
+ end
+ return table.concat(tbl, ",")
+end
+
+local TELE_MENU = {
+ {
+ type = "label",
+ label = S("Enter a block name or select an existing one"),
+ tooltip = "",
+ name = "l1",
+ },
+ {
+ type = "ascii",
+ name = "conn_name",
+ label = S("Block name"),
+ tooltip = S("Connection name for this block"),
+ default = "",
+ },
+ {
+ type = "dropdown",
+ choices = "",
+ on_dropdown = get_free_server_list,
+ name = "remote_name",
+ label = S("Remote name"),
+ tooltip = S("Connection name of the remote block"),
+ },
+ {
+ type = "output",
+ label = S("Status"),
+ tooltip = S("Connection status"),
+ name = "status",
+ default = "",
+ },
+}
+
+function techage.teleport.formspec(pos)
+ local ndef = NDEF(pos)
+ return menu.generate_formspec(pos, ndef, TELE_MENU)
+end
+
+local function store_connection(pos, peer_pos)
+ local meta = M(pos)
+ local status = S("connected to") .. " " .. P2S(peer_pos)
+ meta:set_string("tele_status", status)
+ meta:set_string("tele_peer_pos", P2S(peer_pos))
+ meta:set_string("formspec", "")
+end
+
+function techage.teleport.prepare_pairing(pos, node_type, status)
+ local meta = M(pos)
+ if node_type then
+ meta:set_string("tele_node_type", node_type)
+ end
+ status = status or S("not connected")
+ meta:set_string("tele_status", status)
+ meta:set_string("tele_peer_pos", "")
+ meta:set_string("formspec", techage.teleport.formspec(pos))
+end
+
+function techage.teleport.stop_pairing(pos, oldmetadata)
+ -- disconnect peer node
+ if oldmetadata and oldmetadata.fields then
+ if oldmetadata.fields.tele_peer_pos then
+ local peer_pos = S2P(oldmetadata.fields.tele_peer_pos)
+ local meta = M(peer_pos)
+ if meta:get_string("conn_name") ~= "" then -- Server
+ local tbl = get_pairing_table1(meta)
+ tbl[meta:get_string("conn_name")] = peer_pos
+ techage.teleport.prepare_pairing(peer_pos, nil, S("server not connected"))
+ else
+ techage.teleport.prepare_pairing(peer_pos)
+ end
+ elseif oldmetadata.fields.conn_name then
+ local tbl = get_pairing_table2(oldmetadata)
+ tbl[oldmetadata.fields.conn_name] = nil
+ end
+ end
+end
+
+function techage.teleport.is_connected(pos)
+ return M(pos):get_string("tele_peer_pos") ~= ""
+end
+
+function techage.teleport.get_remote_pos(pos)
+ local s = M(pos):get_string("tele_peer_pos")
+ if s ~= "" then
+ return S2P(s)
+ end
+end
+
+function techage.teleport.after_formspec(pos, player, fields, max_dist, ex_points)
+ if techage.get_expoints(player) >= ex_points then
+ if techage.menu.eval_input(pos, TELE_MENU, fields) then
+ if not techage.teleport.is_connected(pos) then
+ local meta = M(pos)
+ if fields.remote_name ~= "" then -- Client
+ local tbl = get_pairing_table1(meta)
+ local peer_pos = tbl[fields.remote_name]
+ if peer_pos then
+ if vector.distance(pos, peer_pos) <= max_dist then
+ tbl[fields.remote_name] = nil
+ store_connection(pos, peer_pos)
+ store_connection(peer_pos, pos)
+ M(pos):set_string("status", S("Connected"))
+ else
+ M(pos):set_string("status", S("Distance > @1 blocks", max_dist))
+ meta:set_string("formspec", techage.teleport.formspec(pos))
+ end
+ end
+ elseif fields.conn_name ~= "" then -- Server
+ local tbl = get_pairing_table1(meta)
+ tbl[fields.conn_name] = pos
+ techage.teleport.prepare_pairing(pos, nil, S("server not connected"))
+ end
+ end
+ end
+ else
+ M(pos):set_string("status", S("Ex-points missing (@1 < @2)", techage.get_expoints(player), ex_points))
+ M(pos):set_string("formspec", techage.teleport.formspec(pos))
+ end
+end
diff --git a/techage/chemistry/ta4_doser.lua b/techage/chemistry/ta4_doser.lua
index eafdda8..886e8b3 100644
--- a/techage/chemistry/ta4_doser.lua
+++ b/techage/chemistry/ta4_doser.lua
@@ -362,14 +362,12 @@ techage.register_node({"techage:ta4_doser", "techage:ta4_doser_on"}, {
end,
})
-if minetest.global_exists("unified_inventory") then
- unified_inventory.register_craft_type("ta4_doser", {
- description = S("TA4 Reactor"),
- icon = 'techage_reactor_filler_plan.png',
- width = 2,
- height = 2,
- })
-end
+techage.recipes.register_craft_type("ta4_doser", {
+ description = S("TA4 Reactor"),
+ icon = 'techage_reactor_filler_plan.png',
+ width = 2,
+ height = 2,
+})
minetest.register_craft({
output = "techage:ta4_doser",
diff --git a/techage/collider/cooler.lua b/techage/collider/cooler.lua
new file mode 100644
index 0000000..4161b08
--- /dev/null
+++ b/techage/collider/cooler.lua
@@ -0,0 +1,91 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2019-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Cooler as part of the Collider
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local S = techage.S
+
+local Pipe = techage.LiquidPipe
+
+minetest.register_node("techage:ta4_collider_cooler", {
+ description = S("TA4 Collider Cooler"),
+ tiles = {
+ -- up, down, right, left, back, front
+ {
+ image = "techage_appl_cooler4.png^techage_frame4_ta4_top.png",
+ backface_culling = false,
+ animation = {
+ type = "vertical_frames",
+ aspect_w = 32,
+ aspect_h = 32,
+ length = 0.4,
+ },
+ },
+ {
+ image = "techage_appl_cooler4.png^techage_frame4_ta4_top.png",
+ backface_culling = false,
+ animation = {
+ type = "vertical_frames",
+ aspect_w = 32,
+ aspect_h = 32,
+ length = 0.4,
+ },
+ },
+ "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_hole_pipe.png",
+ "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_hole_pipe.png",
+ "techage_filling_ta4.png^techage_frame_ta4.png^techage_cooler.png",
+ "techage_filling_ta4.png^techage_frame_ta4.png^techage_cooler.png",
+ },
+ drawtype = "nodebox",
+ paramtype2 = "facedir",
+ groups = {cracky = 1},
+ on_rotate = screwdriver.disallow,
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+ networks = {
+ pipe2 = {},
+ },
+
+ after_place_node = function(pos, placer, itemstack)
+ Pipe:after_place_node(pos)
+ end,
+
+ after_dig_node = function(pos, oldnode)
+ Pipe:after_dig_node(pos)
+ techage.del_mem(pos)
+ end,
+})
+
+Pipe:add_secondary_node_names({"techage:ta4_collider_cooler"})
+Pipe:set_valid_sides("techage:ta4_collider_cooler", {"R", "L"})
+
+techage.register_node({"techage:ta4_collider_cooler"}, {
+ on_transfer = function(pos, in_dir, topic, payload)
+ if topic == "cooler" then
+ return true
+ else
+ return false
+ end
+ end,
+})
+
+minetest.register_craft({
+ output = "techage:ta4_collider_cooler",
+ recipe = {
+ {'', 'dye:blue', ''},
+ {'', 'techage:cooler', ''},
+ {'', 'techage:aluminum', ''},
+ },
+})
+
diff --git a/techage/collider/detector.lua b/techage/collider/detector.lua
new file mode 100644
index 0000000..6a38a27
--- /dev/null
+++ b/techage/collider/detector.lua
@@ -0,0 +1,414 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2019-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Detector as part of the Collider
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local S = techage.S
+local S2P = minetest.string_to_pos
+local P2S = minetest.pos_to_string
+local getpos = techage.assemble.get_pos
+
+local CYCLE_TIME = 2
+local TNO_MAGNETS = 22
+local PROBABILITY = 180 -- check every 20 s => 20 * 180 * 50% = 30 min
+
+local TIME_SLOTS = 10
+local Schedule = {[0] =
+ -- Route: 0 = forward, 1 = right, 2 = backward, 3 = left
+ -- Gas left/right
+ {name = "techage:ta4_collider_pipe_inlet", yoffs = 1, route = {3,3,3,2}, check = techage.gas_inlet_check},
+ {name = "techage:ta4_collider_pipe_inlet", yoffs = 1, route = {1,1,1,2}, check = techage.gas_inlet_check},
+ -- Power left/right
+ {name = "techage:ta4_collider_cable_inlet", yoffs = 2, route = {3,3,3}, check = techage.power_inlet_check},
+ {name = "techage:ta4_collider_cable_inlet", yoffs = 2, route = {1,1,1}, check = techage.power_inlet_check},
+ -- Cooler
+ {name = "techage:ta4_collider_pipe_inlet", yoffs = 0, route = {0}, check = techage.cooler_check},
+ {name = "techage:ta4_collider_pipe_inlet", yoffs = 2, route = {0}, check = techage.cooler_check},
+ -- Air outlet
+ {name = "techage:ta4_collider_pipe_outlet", yoffs = 2, route = {}, check = techage.air_outlet_check},
+ -- All nodes
+ {name = "shell", yoffs = 0, route = {}, check = nil},
+}
+
+local function play_sound(pos)
+ minetest.sound_play("techage_hum", {
+ pos = pos,
+ gain = 0.5,
+ max_hear_distance = 10,
+ })
+end
+
+local function terminal_message(pos, msg)
+ local term_num = M(pos):contains("term_num") and M(pos):get_string("term_num")
+ local own_num = M(pos):get_string("node_number")
+
+ if term_num and own_num then
+ techage.send_single(own_num, term_num, "text", msg)
+ end
+end
+
+local function experience_points(pos)
+ if math.random(PROBABILITY) == 1 then
+ local owner = M(pos):get_string("owner")
+ local own_num = M(pos):get_string("node_number")
+ local player = minetest.get_player_by_name(owner)
+ if player then
+ if techage.add_expoint(player, own_num) then
+ terminal_message(pos, "Experience point reached!")
+ end
+ end
+ end
+end
+
+local function check_shell(pos, param2)
+ local pos1 = getpos(pos, param2, {3,3,3,2}, 0)
+ local pos2 = getpos(pos, param2, {1,1,1,0}, 2)
+ local _, tbl = minetest.find_nodes_in_area(pos1, pos2, {"techage:ta4_detector_magnet", "techage:ta4_colliderblock", "default:obsidian_glass"})
+ if tbl["techage:ta4_detector_magnet"] < 16 then
+ return false, "Magnet missing"
+ elseif tbl["techage:ta4_colliderblock"] < 31 then
+ return false, "Steel block missing"
+ elseif tbl["default:obsidian_glass"] < 1 then
+ return false, "Obsidian glass missing"
+ end
+ return true
+end
+
+local function check_state(pos)
+ -- Cyclically check all connections
+ local param2 = minetest.get_node(pos).param2
+ local nvm = techage.get_nvm(pos)
+ nvm.ticks = (nvm.ticks or 0) + 1
+ local idx = nvm.ticks % TIME_SLOTS
+ local item = Schedule[idx]
+
+ if idx == 1 then
+ nvm.result = true
+ end
+
+ if item then
+ if item.name == "shell" then
+ local res, err = check_shell(pos, param2)
+ if not res then
+ nvm.result = false
+ nvm.runnning = false
+ terminal_message(pos, (err or "unknown") .. "!!!")
+ return nvm.result
+ end
+ else
+ local pos2 = getpos(pos, param2, item.route, item.yoffs)
+ local nvm2 = techage.get_nvm(pos2)
+ local meta2 = M(pos2)
+ local node2 = minetest.get_node(pos2)
+ if item.name == node2.name then
+ local res, err = item.check(pos2, node2, meta2, nvm2)
+ --print("check_state", idx, res, err)
+ if not res then
+ nvm.result = false
+ nvm.runnning = false
+ terminal_message(pos, (err or "unknown") .. "!!!")
+ return nvm.result
+ end
+ else
+ nvm.result = false
+ nvm.runnning = false
+ terminal_message(pos, "Detector defect!!!")
+ end
+ end
+ elseif idx == #Schedule + 1 then
+ return nvm.result
+ end
+end
+
+local function add_laser(pos)
+ local param2 = minetest.get_node(pos).param2
+ local pos1 = getpos(pos, param2, {3,3}, 1)
+ local pos2 = getpos(pos, param2, {1,1,1}, 1)
+ techage.del_laser(pos)
+ techage.add_laser(pos, pos1, pos2)
+end
+
+local function create_task(pos, task)
+ local mem = techage.get_mem(pos)
+ if not mem.co then
+ mem.co = coroutine.create(task)
+ end
+
+ local _, err = coroutine.resume(mem.co, pos)
+ if err then
+ mem.co = nil
+ --print(err)
+ return
+ end
+ minetest.after(0.4, create_task, pos)
+end
+
+-- Call on_cyclic_check of all magents so that the magnets don't need a FLB.
+local function magnet_on_cyclic_check(pos, nvm)
+ local ndef = minetest.registered_nodes["techage:ta4_magnet"]
+ for idx,pos2 in ipairs(nvm.magnet_positions or {}) do
+ local res = ndef.on_cyclic_check(pos2)
+ if res == -2 then
+ terminal_message(pos, "Magnet #" .. idx .. " defect!!!")
+ return false
+ elseif res == -1 then
+ terminal_message(pos, "Vacuum defect!!!")
+ techage.air_outlet_reset({x=pos.x, y=pos.y + 2, z=pos.z})
+ return false
+ end
+ end
+ return true
+end
+
+minetest.register_node("techage:ta4_detector_core", {
+ description = S("TA4 Collider Detector Core"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png^techage_collider_detector_core.png",
+ "default_steel_block.png^techage_collider_detector_core.png",
+ "default_steel_block.png^techage_collider_detector_core.png",
+ "default_steel_block.png^techage_collider_detector_core.png",
+ },
+ drawtype = "nodebox",
+ paramtype2 = "facedir",
+ groups = {cracky = 1},
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+
+ after_place_node = function(pos, placer, itemstack)
+ local nvm = techage.get_nvm(pos)
+ local meta = M(pos)
+ local own_num = techage.add_node(pos, "techage:ta4_detector_core")
+ meta:set_string("node_number", own_num)
+ meta:set_string("owner", placer:get_player_name())
+ M({x=pos.x, y=pos.y - 1, z=pos.z}):set_string("infotext", S("TA4 Collider Detector") .. " " .. own_num)
+ minetest.get_node_timer(pos):start(CYCLE_TIME)
+ end,
+
+ on_timer = function(pos, elapsed)
+ local nvm = techage.get_nvm(pos)
+ if not magnet_on_cyclic_check(pos, nvm) then
+ techage.del_laser(pos)
+ if nvm.running then
+ terminal_message(pos, "Detector stopped.")
+ nvm.running = false
+ end
+ nvm.magnet_positions = nil
+ elseif nvm.running then
+ local res = check_state(pos)
+ if res == true then
+ experience_points(pos)
+ add_laser(pos)
+ if nvm.ticks <= TIME_SLOTS then -- only once
+ terminal_message(pos, "Detector running.")
+ end
+ elseif res == false then
+ techage.del_laser(pos)
+ nvm.running = false
+ nvm.magnet_positions = nil
+ terminal_message(pos, "Detector stopped.")
+ end
+ if nvm.running then
+ play_sound(pos)
+ end
+ end
+ return true
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata, digger)
+ techage.on_remove_collider(digger)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ techage.del_mem(pos)
+ end,
+})
+
+local function check_expr(own_num, term_num, text, expr)
+ techage.send_single(own_num, term_num, "text", text .. "..." .. (expr and "ok" or "error!!!"))
+ return expr
+end
+
+local function start_task(pos)
+ local term_num = M(pos):contains("term_num") and M(pos):get_string("term_num")
+ local param2 = minetest.get_node(pos).param2
+ local pos2 = getpos(pos, param2, {3,3,3}, 1)
+ local own_num = M(pos):get_string("node_number")
+ local nvm = techage.get_nvm(pos)
+ nvm.magnet_positions = {}
+
+ if term_num and param2 and pos2 then
+ techage.send_single(own_num, term_num, "text", "#### Start ####")
+
+ coroutine.yield()
+ local resp = techage.tube_inlet_command(pos2, "enumerate", 1)
+ if not check_expr(own_num, term_num, "- Check number of magnets", resp == TNO_MAGNETS) then
+ nvm.locked = false
+ return
+ end
+
+ coroutine.yield()
+ techage.send_single(own_num, term_num, "text", "- Check position of magnets...")
+ resp = techage.tube_inlet_command(pos2, "distance")
+ if resp ~= true then
+ techage.send_single(own_num, term_num, "append", "#" .. resp .. " defect!!!")
+ nvm.locked = false
+ return
+ end
+ techage.send_single(own_num, term_num, "append", "ok")
+
+ coroutine.yield()
+ techage.send_single(own_num, term_num, "text", "- Start magnets...")
+ local t = {}
+ for num = 1, TNO_MAGNETS do
+ local resp = techage.tube_inlet_command(pos2, "pos", num)
+ if not resp or type(resp) ~= "table" then
+ techage.send_single(own_num, term_num, "append", "#" .. num .. " defect!!!")
+ nvm.magnet_positions = nil
+ nvm.locked = false
+ return
+ else
+ t[#t + 1] = resp
+ end
+ coroutine.yield()
+ end
+ nvm.magnet_positions = t
+ techage.send_single(own_num, term_num, "append", "ok")
+
+ coroutine.yield()
+ techage.send_single(own_num, term_num, "text", "- Check magnets...")
+ -- The check will be performed by the timer, so wait 5 sec.
+ for i = 1,14 do
+ coroutine.yield()
+ end
+ if nvm.magnet_positions then
+ techage.send_single(own_num, term_num, "append", "ok")
+ else
+ nvm.locked = false
+ return
+ end
+
+ coroutine.yield()
+ techage.send_single(own_num, term_num, "text", "- Check detector...")
+ for _,item in ipairs(Schedule)do
+ if item.name == "shell" then
+ local res, err = check_shell(pos, param2)
+ if not res then
+ techage.send_single(own_num, term_num, "append", err .. "!!!")
+ nvm.magnet_positions = nil
+ nvm.locked = false
+ return
+ end
+ else
+ local pos2 = getpos(pos, param2, item.route, item.yoffs)
+ local nvm2 = techage.get_nvm(pos2)
+ local meta2 = M(pos2)
+ local node2 = minetest.get_node(pos2)
+ if item.name == node2.name then
+ local res, err = item.check(pos2, node2, meta2, nvm2)
+ if not res then
+ techage.send_single(own_num, term_num, "append", err .. "!!!")
+ nvm.magnet_positions = nil
+ nvm.locked = false
+ return
+ end
+ else
+ techage.send_single(own_num, term_num, "append", "defect!!!")
+ nvm.magnet_positions = nil
+ nvm.locked = false
+ return
+ end
+ coroutine.yield()
+ end
+ end
+ techage.send_single(own_num, term_num, "append", "ok")
+
+ coroutine.yield()
+ techage.send_single(own_num, term_num, "text", "Collider started.")
+ nvm.ticks = 0
+ nvm.running = true
+ end
+end
+
+local function test_magnet(pos, payload)
+ local term_num = M(pos):contains("term_num") and M(pos):get_string("term_num")
+ local param2 = minetest.get_node(pos).param2
+ local pos2 = getpos(pos, param2, {3,3,3}, 1)
+ local own_num = M(pos):get_string("node_number")
+ local magnet_num = tonumber(payload)
+ local res, err = techage.tube_inlet_command(pos2, "test", magnet_num)
+ if res then
+ techage.send_single(own_num, term_num, "text", "magnet #" .. magnet_num .. ": ok")
+ else
+ techage.send_single(own_num, term_num, "text", "magnet #" .. magnet_num .. ": " .. (err or "unknown error") .. "!!!")
+ end
+end
+
+techage.register_node({"techage:ta4_detector_core"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ local nvm = techage.get_nvm(pos)
+ if topic == "connect" then
+ M(pos):set_string("term_num", src)
+ return true
+ elseif topic == "start" then
+ -- Worker block
+ nvm.locked = true
+ create_task(pos, start_task)
+ return true
+ elseif topic == "stop" then
+ nvm.running = false
+ techage.del_laser(pos)
+ nvm.locked = false
+ return "Detector stopped."
+ elseif topic == "status" then
+ if nvm.running == true then
+ return "running"
+ elseif nvm.result == false then
+ return "fault"
+ else
+ return "stopped"
+ end
+ elseif topic == "test"then
+ if payload and tonumber(payload) then
+ test_magnet(pos, payload)
+ return true
+ else
+ return "Invalid magnet number"
+ end
+ elseif topic == "points" then
+ local owner = M(pos):get_string("owner")
+ local player = minetest.get_player_by_name(owner)
+ if player then
+ local points = techage.get_expoints(player)
+ return "Ex. Points = " .. points
+ end
+ else
+ return "unsupported"
+ end
+ end,
+ on_node_load = function(pos)
+ minetest.get_node_timer(pos):start(CYCLE_TIME)
+ end,
+})
+
+
+minetest.register_craft({
+ output = "techage:ta4_detector_core",
+ recipe = {
+ {'techage:aluminum', 'basic_materials:heating_element', 'default:steel_ingot'},
+ {'default:diamond', 'techage:ta4_wlanchip', 'techage:electric_cableS'},
+ {'default:steel_ingot', '', 'techage:aluminum'},
+ },
+})
+
diff --git a/techage/collider/inlets.lua b/techage/collider/inlets.lua
new file mode 100644
index 0000000..10bd185
--- /dev/null
+++ b/techage/collider/inlets.lua
@@ -0,0 +1,364 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2019-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Tube/Pipe Inputs/Outputs as part of the Collider
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local S = techage.S
+
+local PWR_NEEDED = 15
+local CYCLE_TIME = 2
+local GAS_CAPA = 20
+local AIR_CAPA = 1000
+
+local VTube = techage.VTube
+local Pipe = techage.LiquidPipe
+local Cable = techage.ElectricCable
+local power = networks.power
+local liquid = networks.liquid
+
+--------------------------------------------------------------------------------
+-- Tube Input
+--------------------------------------------------------------------------------
+minetest.register_node("techage:ta4_collider_tube_inlet", {
+ description = S("TA4 Collider Tube Input"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png^techage_collider_tube_open.png",
+ },
+ drawtype = "nodebox",
+ node_box = {
+ type = "fixed",
+ fixed = {
+ {-4/8, -4/8, -4/8, -1/8, 4/8, 4/8},
+ { 1/8, -4/8, -4/8, 4/8, 4/8, 4/8},
+ {-4/8, 1/8, -4/8, 4/8, 4/8, 4/8},
+ {-4/8, -4/8, -4/8, 4/8, -1/8, 4/8},
+ },
+ },
+ selection_box = {
+ type = "fixed",
+ fixed = {-4/8, -4/8, -4/8, 4/8, 4/8, 4/8},
+ },
+ paramtype2 = "facedir",
+ groups = {cracky = 1},
+ on_rotate = screwdriver.disallow,
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+
+ after_place_node = function(pos, placer, itemstack)
+ VTube:after_place_node(pos)
+ end,
+
+ after_dig_node = function(pos, oldnode)
+ VTube:after_dig_node(pos)
+ techage.del_mem(pos)
+ end,
+})
+
+VTube:add_secondary_node_names({"techage:ta4_collider_tube_inlet"})
+VTube:set_valid_sides("techage:ta4_collider_tube_inlet", {"F"})
+
+-- Called from the detector via tube ring
+techage.register_node({"techage:ta4_collider_tube_inlet"}, {
+ on_transfer = function(pos, in_dir, topic, payload)
+ if topic == "distance" then
+ return pos
+ elseif topic == "enumerate" and payload then
+ return payload - 1
+ elseif topic == "check" then
+ local nvm = techage.get_nvm(pos)
+ nvm.check_received = true
+ return true
+ end
+ end,
+})
+
+-- Used by the detector to check the tube connection
+function techage.tube_inlet_command(pos, command, payload)
+ if command == "distance" then
+ local pos2 = techage.transfer(pos, "F", command, payload, VTube, {"techage:ta4_magnet"})
+ if type(pos2) == "table" then
+ local dist = math.abs(pos.x - pos2.x) + math.abs(pos.z - pos2.z)
+ if pos.y == pos2.y and dist == VTube.max_tube_length + 1 then
+ return true
+ end
+ return 0
+ else
+ return pos2
+ end
+ end
+ return techage.transfer(pos, "F", command, payload, VTube, {"techage:ta4_magnet"})
+end
+
+minetest.register_craft({
+ output = "techage:ta4_collider_tube_inlet",
+ recipe = {
+ {'', '', ''},
+ {'techage:ta4_vtubeS', 'techage:ta4_colliderblock', ''},
+ {'', '', ''},
+ },
+})
+
+--------------------------------------------------------------------------------
+-- Pipe Input (gas)
+--------------------------------------------------------------------------------
+minetest.register_node("techage:ta4_collider_pipe_inlet", {
+ description = S("TA4 Collider Pipe Input"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png^techage_appl_hole_pipe.png",
+ },
+ drawtype = "nodebox",
+ paramtype2 = "facedir",
+ groups = {cracky = 1},
+ on_rotate = screwdriver.disallow,
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+ networks = {
+ pipe2 = {},
+ },
+
+ after_place_node = function(pos, placer, itemstack)
+ local nvm = techage.get_nvm(pos)
+ Pipe:after_place_node(pos)
+ nvm.liquid = {}
+ end,
+
+ after_dig_node = function(pos, oldnode)
+ Pipe:after_dig_node(pos)
+ techage.del_mem(pos)
+ end,
+})
+
+liquid.register_nodes({"techage:ta4_collider_pipe_inlet"}, Pipe, "tank", {"F"}, {
+ capa = GAS_CAPA,
+ peek = function(pos, indir)
+ local nvm = techage.get_nvm(pos)
+ return liquid.srv_peek(nvm)
+ end,
+ put = function(pos, indir, name, amount)
+ local nvm = techage.get_nvm(pos)
+ return liquid.srv_put(nvm, name, amount, GAS_CAPA)
+ end,
+ take = function(pos, indir, name, amount)
+ local nvm = techage.get_nvm(pos)
+ return liquid.srv_take(nvm, name, amount)
+ end,
+ untake = function(pos, indir, name, amount)
+ local nvm = techage.get_nvm(pos)
+ liquid.srv_put(nvm, name, amount, GAS_CAPA)
+ end,
+})
+
+techage.register_node({"techage:ta4_collider_pipe_inlet"}, {
+ on_transfer = function(pos, in_dir, topic, payload)
+ -- called from heatexchanger
+ if topic == "detector" then
+ local nvm = techage.get_nvm(pos)
+ nvm.detector_received = true
+ return true
+ end
+ end,
+})
+
+-- Used by the detector to check for gas pressure
+function techage.gas_inlet_check(pos, node, meta, nvm)
+ nvm.liquid = nvm.liquid or {}
+ if nvm.liquid.amount == GAS_CAPA and nvm.liquid.name == "techage:isobutane" then
+ return true
+ end
+ return false, "no gas"
+end
+
+-- Used by the detector to check for cooler connection
+function techage.cooler_check(pos, node, meta, nvm)
+ if nvm.detector_received then
+ nvm.detector_received = nil
+ return true
+ end
+ return false, "Cooler defect"
+end
+
+minetest.register_craft({
+ output = "techage:ta4_collider_pipe_inlet",
+ recipe = {
+ {'', '', ''},
+ {'techage:ta3_pipeS', 'techage:ta4_colliderblock', ''},
+ {'', '', ''},
+ },
+})
+
+
+--------------------------------------------------------------------------------
+-- Pipe Output (air)
+--------------------------------------------------------------------------------
+local function init_air(nvm)
+ nvm.liquid = {
+ amount = AIR_CAPA,
+ name = "air",
+ }
+ return nvm.liquid
+end
+
+minetest.register_node("techage:ta4_collider_pipe_outlet", {
+ description = S("TA4 Collider Pipe Output"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "default_steel_block.png^techage_appl_hole_pipe.png",
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png",
+ },
+ drawtype = "nodebox",
+ paramtype2 = "facedir",
+ groups = {cracky = 1},
+ on_rotate = screwdriver.disallow,
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+ networks = {
+ pipe2 = {},
+ },
+
+ after_place_node = function(pos, placer, itemstack)
+ local nvm = techage.get_nvm(pos)
+ init_air(nvm)
+ Pipe:after_place_node(pos)
+ end,
+
+ after_dig_node = function(pos, oldnode)
+ Pipe:after_dig_node(pos)
+ techage.del_mem(pos)
+ end,
+})
+
+liquid.register_nodes({"techage:ta4_collider_pipe_outlet"}, Pipe, "tank", {"U"}, {
+ capa = AIR_CAPA,
+ peek = function(pos, indir)
+ local nvm = techage.get_nvm(pos)
+ return liquid.srv_peek(nvm)
+ end,
+ put = function(pos, indir, name, amount)
+ local nvm = techage.get_nvm(pos)
+ return liquid.srv_put(nvm, name, amount, AIR_CAPA)
+ end,
+ take = function(pos, indir, name, amount)
+ local nvm = techage.get_nvm(pos)
+ return liquid.srv_take(nvm, name, amount)
+ end,
+ untake = function(pos, indir, name, amount)
+ local nvm = techage.get_nvm(pos)
+ liquid.srv_put(nvm, name, amount, AIR_CAPA)
+ end,
+})
+
+-- Used by the detector to check the vacuum
+function techage.air_outlet_check(pos, node, meta, nvm)
+ nvm.liquid = nvm.liquid or {}
+ if nvm.liquid.amount == 0 then
+ return true
+ end
+ return false, "no vacuum"
+end
+
+function techage.air_outlet_reset(pos)
+ local nvm = techage.get_nvm(pos)
+ init_air(nvm)
+end
+
+minetest.register_craft({
+ output = "techage:ta4_collider_pipe_outlet",
+ recipe = {
+ {'', 'techage:ta3_pipeS', ''},
+ {'', 'techage:ta4_colliderblock', ''},
+ {'', '', ''},
+ },
+})
+
+--------------------------------------------------------------------------------
+-- Cable Input (power)
+--------------------------------------------------------------------------------
+minetest.register_node("techage:ta4_collider_cable_inlet", {
+ description = S("TA4 Collider Cable Input"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png",
+ "default_steel_block.png^techage_appl_hole_electric.png",
+ },
+ drawtype = "nodebox",
+ paramtype2 = "facedir",
+ groups = {cracky = 1},
+ on_rotate = screwdriver.disallow,
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+ networks = {
+ pipe2 = {},
+ },
+
+ after_place_node = function(pos, placer, itemstack)
+ Cable:after_place_node(pos)
+ minetest.get_node_timer(pos):start(CYCLE_TIME)
+ end,
+
+ on_timer = function(pos, elapsed)
+ local nvm = techage.get_nvm(pos)
+ nvm.consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
+ return true
+ end,
+
+ after_dig_node = function(pos, oldnode)
+ Cable:after_dig_node(pos)
+ techage.del_mem(pos)
+ end,
+})
+
+-- Used by the detector to check for power
+function techage.power_inlet_check(pos, node, meta, nvm)
+ if nvm.consumed == PWR_NEEDED then
+ return true
+ end
+ return false, "no power"
+end
+
+power.register_nodes({"techage:ta4_collider_cable_inlet"}, Cable, "con", {"F"})
+
+techage.register_node({"techage:ta4_collider_cable_inlet"}, {
+ on_node_load = function(pos)
+ minetest.get_node_timer(pos):start(CYCLE_TIME)
+ end,
+})
+
+minetest.register_craft({
+ output = "techage:ta4_collider_cable_inlet",
+ recipe = {
+ {'', '', ''},
+ {'techage:electric_cableS', 'techage:ta4_colliderblock', ''},
+ {'', '', ''},
+ },
+})
diff --git a/techage/collider/magnet.lua b/techage/collider/magnet.lua
new file mode 100644
index 0000000..b7314f3
--- /dev/null
+++ b/techage/collider/magnet.lua
@@ -0,0 +1,305 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2019-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Magnet as part of the Collider
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local S = techage.S
+local S2P = minetest.string_to_pos
+local P2S = minetest.pos_to_string
+
+local PWR_NEEDED = 5
+local CYCLE_TIME = 2
+local CAPACITY = 10
+
+local Cable = techage.ElectricCable
+local Pipe = techage.LiquidPipe
+local VTube = techage.VTube
+local power = networks.power
+local liquid = networks.liquid
+
+minetest.register_node("techage:ta4_colliderblock", {
+ description = S("TA4 Collider Steel Block"),
+ tiles = {
+ "default_steel_block.png",
+ },
+ paramtype2 = "facedir",
+ groups = {cracky = 1},
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+})
+
+minetest.register_node("techage:ta4_detector_magnet", {
+ description = S("TA4 Collider Detector Magnet"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_collider_magnet.png^techage_collider_magnet_appl.png",
+ "techage_collider_magnet.png^techage_collider_magnet_appl.png",
+ "techage_collider_magnet.png",
+ "techage_collider_magnet.png",
+ "techage_collider_magnet.png^techage_collider_magnet_appl.png",
+ "techage_collider_magnet.png^techage_collider_magnet_appl.png",
+ },
+ drawtype = "nodebox",
+ paramtype2 = "facedir",
+ groups = {cracky = 1},
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+})
+
+minetest.register_node("techage:ta4_magnet", {
+ description = S("TA4 Collider Magnet"),
+ inventory_image = minetest.inventorycube(
+ "techage_collider_magnet.png^techage_appl_hole_electric.png",
+ "techage_collider_magnet.png^techage_appl_hole_pipe.png",
+ "techage_collider_magnet.png^techage_collider_magnet_tube.png"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_collider_magnet.png^techage_appl_hole_electric.png",
+ "techage_collider_magnet.png",
+ "techage_collider_magnet.png^techage_collider_magnet_tube.png",
+ "techage_collider_magnet.png^techage_collider_magnet_tube.png",
+ "techage_collider_magnet.png^techage_collider_magnet_appl.png^techage_appl_hole_pipe.png^techage_collider_magnet_sign.png",
+ "techage_collider_magnet.png^techage_collider_magnet_appl.png^techage_appl_hole_pipe.png^techage_collider_magnet_sign.png",
+ },
+ drawtype = "nodebox",
+ use_texture_alpha = techage.CLIP,
+ node_box = {
+ type = "fixed",
+ fixed = {
+ {-11/16, -11/16, -11/16, 11/16, 11/16, -2/16},
+ {-11/16, -11/16, 2/16, 11/16, 11/16, 11/16},
+ {-11/16, 2/16, -11/16, 11/16, 11/16, 11/16},
+ {-11/16, -11/16, -11/16, 11/16, -2/16, 11/16},
+ },
+ },
+ selection_box = {
+ type = "fixed",
+ fixed = {-4/8, -4/8, -4/8, 4/8, 4/8, 4/8},
+ },
+ collision_box = {
+ type = "fixed",
+ fixed = {-11/16, -11/16, -11/16, 11/16, 11/16, 11/16},
+ },
+ wield_scale = {x = 0.8, y = 0.8, z = 0.8},
+ paramtype2 = "facedir",
+ groups = {cracky = 1},
+ on_rotate = screwdriver.disallow,
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+
+ after_place_node = function(pos, placer, itemstack)
+ if pos.y > techage.collider_min_depth then
+ minetest.remove_node(pos)
+ minetest.add_item(pos, ItemStack("techage:ta4_magnet"))
+ return
+ end
+ local nvm = techage.get_nvm(pos)
+ nvm.liquid = {}
+ Pipe:after_place_node(pos)
+ Cable:after_place_node(pos)
+ VTube:after_place_node(pos)
+ M(pos):set_string("infotext", S("TA4 Collider Magnet") .. " #0")
+ end,
+
+ -- To be called by the detector
+ on_cyclic_check = function(pos)
+ local nvm = techage.get_nvm(pos)
+ nvm.liquid = nvm.liquid or {}
+ nvm.consumed = power.consume_power(pos, Cable, 6, PWR_NEEDED)
+ if nvm.tube_damage then
+ nvm.tube_damage = nil
+ return -1
+ elseif nvm.liquid.amount == CAPACITY and
+ nvm.liquid.name == "techage:isobutane" and
+ nvm.consumed == PWR_NEEDED then
+ return 0
+ end
+ return -2
+ end,
+
+ tubelib2_on_update2 = function(pos, outdir, tlib2, node)
+ if tlib2.tube_type == "vtube" then
+ local nvm = techage.get_nvm(pos)
+ nvm.tube_damage = true
+ elseif tlib2.tube_type == "pipe2" then
+ local nvm = techage.get_nvm(pos)
+ nvm.liquid = nvm.liquid or {}
+ nvm.liquid.amount = 0
+ end
+ end,
+
+ after_dig_node = function(pos, oldnode)
+ Pipe:after_dig_node(pos)
+ Cable:after_dig_node(pos)
+ VTube:after_dig_node(pos)
+ techage.del_mem(pos)
+ end,
+})
+
+power.register_nodes({"techage:ta4_magnet"}, Cable, "con", {"U"})
+liquid.register_nodes({"techage:ta4_magnet"}, Pipe, "tank", {"F", "B"}, {
+ capa = CAPACITY,
+ peek = function(pos, indir)
+ local nvm = techage.get_nvm(pos)
+ return liquid.srv_peek(nvm)
+ end,
+ put = function(pos, indir, name, amount)
+ local nvm = techage.get_nvm(pos)
+ return liquid.srv_put(nvm, name, amount, CAPACITY)
+ end,
+ take = function(pos, indir, name, amount)
+ local nvm = techage.get_nvm(pos)
+ return liquid.srv_take(nvm, name, amount)
+ end,
+ untake = function(pos, indir, name, amount)
+ local nvm = techage.get_nvm(pos)
+ liquid.srv_put(nvm, name, amount, CAPACITY)
+ end,
+})
+
+VTube:add_secondary_node_names({"techage:ta4_magnet"})
+VTube:set_valid_sides("techage:ta4_magnet", {"R", "L"})
+
+local function send_to_next(pos, in_dir, topic, payload)
+ return techage.transfer(pos, in_dir, topic, payload, VTube,
+ {"techage:ta4_magnet", "techage:ta4_collider_tube_inlet"})
+end
+
+--[[
+Commands
+--------
+
+distance : Check distance between all magnets.
+ Returns pos of next magnet or the number of the defect magnet.
+enumerate : Give each magnet a unique number (1...n)
+pos : Read the position
+test : Test all magnet attributs.
+ Returns true or false, err
+]]--
+techage.register_node({"techage:ta4_magnet"}, {
+ on_transfer = function(pos, in_dir, topic, payload)
+ local nvm = techage.get_nvm(pos)
+ if topic == "distance" then
+ local pos2 = send_to_next(pos, in_dir, topic, payload)
+ if type(pos2) == "table" then
+ local dist = math.abs(pos.x - pos2.x) + math.abs(pos.z - pos2.z)
+ if pos.y == pos2.y and dist == VTube.max_tube_length + 1 then
+ return pos
+ end
+ return nvm.number or 0
+ else
+ return pos2
+ end
+ elseif topic == "enumerate" and payload then
+ payload = tonumber(payload) or 1
+ nvm.number = payload
+ M(pos):set_string("infotext", S("TA4 Collider Magnet") .. " #" .. payload)
+ return send_to_next(pos, in_dir, topic, payload + 1)
+ elseif topic == "pos" then
+ if payload and tonumber(payload) == nvm.number then
+ nvm.tube_damage = nil
+ return pos
+ else
+ return send_to_next(pos, in_dir, topic, payload)
+ end
+ elseif topic == "test" then
+ if payload and tonumber(payload) == nvm.number then
+ if not nvm.liquid or not nvm.liquid.amount or nvm.liquid.amount < CAPACITY then
+ return false, "no gas"
+ elseif nvm.liquid.name ~= "techage:isobutane" then
+ return false, "wrong gas"
+ elseif nvm.consumed ~= PWR_NEEDED then
+ return false, "no power"
+ elseif nvm.tube_damage then
+ nvm.tube_damage = nil
+ return false, "no vacuum"
+ end
+ return true
+ else
+ return send_to_next(pos, in_dir, topic, payload)
+ end
+ end
+ end,
+})
+
+minetest.register_node("techage:ta4_magnet_base", {
+ description = S("TA4 Collider Magnet Base"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "default_steel_block.png",
+ },
+ drawtype = "nodebox",
+ node_box = {
+ type = "fixed",
+ fixed = {
+ {-6/16, -8/16, -6/16, 6/16, 5/16, 6/16},
+ },
+ },
+ paramtype2 = "facedir",
+ groups = {cracky = 1},
+ is_ground_content = false,
+ paramtype = "light",
+ use_texture_alpha = techage.CLIP,
+ sounds = default.node_sound_metal_defaults(),
+})
+
+minetest.register_craft({
+ output = "techage:ta4_colliderblock",
+ recipe = {
+ {'techage:aluminum', '', 'default:steel_ingot'},
+ {'', '', ''},
+ {'default:steel_ingot', '', 'techage:aluminum'},
+ },
+})
+
+
+minetest.register_craft({
+ output = "techage:ta4_detector_magnet 2",
+ recipe = {
+ {'default:steel_ingot', '', 'techage:aluminum'},
+ {'dye:red', 'basic_materials:gold_wire', 'dye:brown'},
+ {'techage:aluminum', '', 'default:steel_ingot'},
+ },
+})
+
+minetest.register_craft({
+ output = "techage:ta4_magnet",
+ recipe = {
+ {'techage:ta3_pipeS', '', 'techage:electric_cableS'},
+ {'techage:ta4_round_ceramic', 'techage:ta4_detector_magnet', 'techage:ta4_round_ceramic'},
+ {'', '', ''},
+ },
+})
+
+minetest.register_craft({
+ output = "techage:ta4_magnet_base 4",
+ recipe = {
+ {'techage:aluminum', 'default:steel_ingot', ''},
+ {'techage:aluminum', 'default:steel_ingot', ''},
+ {'techage:aluminum', 'default:steel_ingot', ''},
+ },
+})
+
+minetest.register_lbm({
+ label = "Repair Magnets",
+ name = "techage:magnets",
+ nodenames = {"techage:ta4_magnet", "techage:ta4_collider_pipe_inlet"},
+ run_at_every_load = false,
+ action = function(pos, node)
+ local nvm = techage.get_nvm(pos)
+ if nvm.liquid and nvm.liquid.name == "techage:hydrogen" then
+ nvm.liquid.name = "techage:isobutane"
+ end
+ end,
+})
\ No newline at end of file
diff --git a/techage/collider/terminal.lua b/techage/collider/terminal.lua
new file mode 100644
index 0000000..3d1c7ea
--- /dev/null
+++ b/techage/collider/terminal.lua
@@ -0,0 +1,208 @@
+--[[
+
+ Techage
+ =======
+
+ Copyright (C) 2020-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Terminal
+
+]]--
+
+local M = minetest.get_meta
+local S = techage.S
+
+local STR_LEN = 80
+local HELP = [[#### TA4 Terminal ####
+
+Send commands to the connected machine
+and output text messages from the
+machine.
+
+Commands can have up to 80 characters.
+Local commands:
+- clear = clear screen
+- help = this message
+- pub = switch to public use
+- priv = switch to private use
+- connect = connect the machine
+
+All other commands are machine dependent.
+]]
+
+local function get_string(meta, num, default)
+ local s = meta:get_string("bttn_text"..num)
+ if not s or s == "" then
+ return default
+ end
+ return s
+end
+
+local function formspec2(mem)
+ mem.command = mem.command or ""
+ mem.output = mem.output or ""
+ local output = minetest.formspec_escape(mem.output)
+ output = output:gsub("\n", ",")
+ local command = minetest.formspec_escape(mem.command)
+ local bttn_text1 = get_string(meta, 1, "User1")
+ local bttn_text2 = get_string(meta, 2, "User2")
+ local bttn_text3 = get_string(meta, 3, "User3")
+ local bttn_text4 = get_string(meta, 4, "User4")
+ local bttn_text5 = get_string(meta, 5, "User5")
+ local bttn_text6 = get_string(meta, 6, "User6")
+ local bttn_text7 = get_string(meta, 7, "User7")
+ local bttn_text8 = get_string(meta, 8, "User8")
+ local bttn_text9 = get_string(meta, 9, "User9")
+ return "size[10,8]"..
+ "style_type[table,field;font=mono]"..
+ "button[0,0;3.3,1;bttn1;"..bttn_text1.."]button[3.3,0;3.3,1;bttn2;"..bttn_text2.."]button[6.6,0;3.3,1;bttn3;"..bttn_text3.."]"..
+ "button[0,0.8;3.3,1;bttn4;"..bttn_text4.."]button[3.3,0.8;3.3,1;bttn5;"..bttn_text5.."]button[6.6,0.8;3.3,1;bttn6;"..bttn_text6.."]"..
+ "button[0,1.6;3.3,1;bttn7;"..bttn_text7.."]button[3.3,1.6;3.3,1;bttn8;"..bttn_text8.."]button[6.6,1.6;3.3,1;bttn9;"..bttn_text9.."]"..
+ "table[0,2.5;9.8,4.7;output;"..output..";200]"..
+ "field[0.4,7.7;7.6,1;cmnd;;"..mem.command.."]" ..
+ "field_close_on_enter[cmnd;false]"..
+ "button[7.9,7.4;2,1;enter;"..S("Enter").."]"
+end
+
+local function output(pos, text)
+ local mem = techage.get_mem(pos)
+ mem.output = mem.output .. "\n" .. (text or "")
+ mem.output = mem.output:sub(-500,-1)
+ M(pos):set_string("formspec", formspec2(mem))
+end
+
+local function command(pos, mem, player)
+ local meta = minetest.get_meta(pos)
+ local owner = meta:get_string("owner")
+
+ if mem.command == "clear" then
+ mem.output = ""
+ mem.command = ""
+ meta:set_string("formspec", formspec2(mem))
+ elseif mem.command == "" then
+ output(pos, ">")
+ mem.command = ""
+ meta:set_string("formspec", formspec2(mem))
+ elseif mem.command == "help" then
+ local meta = minetest.get_meta(pos)
+ mem.output = HELP
+ mem.command = ""
+ meta:set_string("formspec", formspec2(mem))
+ elseif mem.command == "pub" and owner == player then
+ meta:set_int("public", 1)
+ output(pos, "> "..mem.command)
+ mem.command = ""
+ output(pos, "Switched to public use!")
+ elseif mem.command == "priv" and owner == player then
+ meta:set_int("public", 0)
+ output(pos, "> "..mem.command)
+ mem.command = ""
+ output(pos, "Switched to private use!")
+ elseif meta:get_int("public") == 1 or owner == player then
+ if mem.command == "clear" then
+ mem.output =
+ mem.command = ""
+ meta:set_string("formspec", formspec2(mem))
+ end
+ end
+end
+
+minetest.register_node("techage:ta4_terminal", {
+ description = "TA4 Collider Terminal",
+ tiles = {
+ -- up, down, right, left, back, front
+ 'techage_terminal1_top.png',
+ 'techage_terminal1_bottom.png',
+ 'techage_terminal1_side.png',
+ 'techage_terminal1_side.png',
+ 'techage_terminal1_bottom.png',
+ "techage_terminal1_front.png",
+ },
+ drawtype = "nodebox",
+ node_box = {
+ type = "fixed",
+ fixed = {
+ {-12/32, -16/32, -8/32, 12/32, -14/32, 12/32},
+ {-12/32, -14/32, 12/32, 12/32, 6/32, 14/32},
+ },
+ },
+ selection_box = {
+ type = "fixed",
+ fixed = {
+ {-12/32, -16/32, -8/32, 12/32, -14/32, 12/32},
+ {-12/32, -14/32, 12/32, 12/32, 6/32, 14/32},
+ },
+ },
+
+ after_place_node = function(pos, placer)
+ local number = techage.add_node(pos, minetest.get_node(pos).name)
+ local meta = minetest.get_meta(pos)
+ meta:set_string("formspec", formspec1())
+ meta:set_string("owner", placer:get_player_name())
+ meta:set_string("infotext", S("TA4 Collider Terminal") .. ": " .. S("not connected")
+ end,
+
+ on_receive_fields = function(pos, formname, fields, player)
+ local meta = minetest.get_meta(pos)
+ local mem = techage.get_mem(pos)
+ if fields.number and fields.number ~= "" then
+ local owner = meta:get_string("owner")
+ if techage.check_numbers(fields.number, owner) then
+ local own_number = meta:get_string("own_number")
+ if techage.send_single(own_number, fields.number, "connect") == true then
+ meta:set_string("number", fields.number)
+ meta:set_string("infotext", S("TA4 Collider Terminal") .. ": " .. S("connected with") .. " " .. fields.number)
+ meta:set_string("formspec", formspec2(mem))
+ end
+ end
+ elseif (fields.enter or fields.key_enter_field) and fields.cmnd then
+ mem.command = string.sub(fields.cmnd, 1, STR_LEN)
+ command(pos, mem, player:get_player_name())
+ elseif fields.key_up then
+ mem.command = pdp13.historybuffer_priv(pos)
+ meta:set_string("formspec", formspec2(mem))
+ elseif fields.key_down then
+ mem.command = pdp13.historybuffer_next(pos)
+ meta:set_string("formspec", formspec2(mem))
+ end
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ end,
+
+ paramtype = "light",
+ use_texture_alpha = techage.CLIP,
+ sunlight_propagates = true,
+ paramtype2 = "facedir",
+ groups = {choppy=2, cracky=2, crumbly=2},
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+})
+
+minetest.register_craft({
+ output = "techage:ta4_terminal",
+ recipe = {
+ {"", "techage:ta4_display", ""},
+ {"dye:black", "techage:ta4_wlanchip", "default:copper_ingot"},
+ {"", "techage:aluminum", ""},
+ },
+})
+
+techage.register_node({"techage:ta4_terminal"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ if topic == "term" then
+ output(pos, payload)
+ return true
+ elseif topic == "clear" then
+ local mem = techage.get_mem(pos)
+ mem.output = ""
+ mem.command = ""
+ M(pos):set_string("formspec", formspec2(mem))
+ return true
+ end
+ end,
+})
diff --git a/techage/collider/vacuumtube.lua b/techage/collider/vacuumtube.lua
new file mode 100644
index 0000000..ad5b2be
--- /dev/null
+++ b/techage/collider/vacuumtube.lua
@@ -0,0 +1,130 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2019-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Vacuum Tube as part of the Collider
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local S = techage.S
+
+local VTube = tubelib2.Tube:new({
+ dirs_to_check = {1,2,3,4},
+ max_tube_length = 5,
+ tube_type = "vtube",
+ show_infotext = false,
+ primary_node_names = {"techage:ta4_vtubeS", "techage:ta4_vtubeA"},
+ secondary_node_names = {"techage:ta4_magnet"},
+ after_place_tube = function(pos, param2, tube_type, num_tubes)
+ minetest.swap_node(pos, {name = "techage:ta4_vtube"..tube_type, param2 = param2})
+ end,
+})
+
+techage.VTube = VTube
+
+minetest.register_node("techage:ta4_vtubeS", {
+ description = S("TA4 Vacuum Tube"),
+ drawtype = "nodebox",
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_collider_tube.png^[transformR90",
+ "techage_collider_tube.png^[transformR90",
+ "techage_collider_tube.png",
+ "techage_collider_tube.png",
+ 'techage_collider_tube_open.png',
+ 'techage_collider_tube_open.png',
+ },
+ node_box = {
+ type = "fixed",
+ fixed = {
+ {-8/16, -8/16, -8/16, -6/16, 8/16, 8/16},
+ { 6/16, -8/16, -8/16, 8/16, 8/16, 8/16},
+ {-8/16, 6/16, -8/16, 8/16, 8/16, 8/16},
+ {-8/16, -8/16, -8/16, 8/16, -6/16, 8/16},
+ },
+ },
+ selection_box = {
+ type = "fixed",
+ fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
+ },
+
+ after_place_node = function(pos, placer, itemstack, pointed_thing)
+ if not VTube:after_place_tube(pos, placer, pointed_thing) then
+ minetest.remove_node(pos)
+ return true
+ end
+ return false
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata, digger)
+ VTube:after_dig_tube(pos, oldnode, oldmetadata)
+ end,
+
+ paramtype2 = "facedir", -- important!
+ on_rotate = screwdriver.disallow, -- important!
+ paramtype = "light",
+ use_texture_alpha = techage.CLIP,
+ sunlight_propagates = true,
+ is_ground_content = false,
+ groups = {cracky = 2},
+ sounds = default.node_sound_metal_defaults(),
+})
+
+minetest.register_node("techage:ta4_vtubeA", {
+ description = S("TA4 Vacuum Tube"),
+ drawtype = "nodebox",
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_collider_tube.png^[transformR90",
+ 'techage_collider_tube.png^techage_collider_tube_open.png',
+ "techage_collider_tube.png",
+ "techage_collider_tube.png",
+ "techage_collider_tube.png^[transformR90",
+ 'techage_collider_tube.png^techage_collider_tube_open.png',
+ },
+ node_box = {
+ type = "fixed",
+ fixed = {
+ {-8/16, -8/16, -8/16, -6/16, 8/16, 8/16},
+ { 6/16, -8/16, -8/16, 8/16, 8/16, 8/16},
+ {-8/16, 6/16, -8/16, 8/16, 8/16, 8/16},
+ {-8/16, -8/16, 6/16, 8/16, 8/16, 8/16},
+ {-8/16, -8/16, -8/16, 8/16, -6/16, -6/16},
+ },
+ },
+ selection_box = {
+ type = "fixed",
+ fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
+ },
+
+ after_dig_node = function(pos, oldnode, oldmetadata, digger)
+ VTube:after_dig_tube(pos, oldnode, oldmetadata)
+ end,
+
+ paramtype2 = "facedir", -- important!
+ on_rotate = screwdriver.disallow, -- important!
+ paramtype = "light",
+ use_texture_alpha = techage.CLIP,
+ sunlight_propagates = true,
+ is_ground_content = false,
+ groups = {cracky = 1, not_in_creative_inventory=1},
+ drop = "techage:ta4_vtubeS",
+ sounds = default.node_sound_metal_defaults(),
+})
+
+minetest.register_craft({
+ output = "techage:ta4_vtubeS 4",
+ recipe = {
+ {'', 'default:steel_ingot', ''},
+ {'techage:aluminum', 'dye:blue', 'techage:aluminum'},
+ {'', 'default:steel_ingot', ''},
+ },
+})
diff --git a/techage/collider/worker.lua b/techage/collider/worker.lua
new file mode 100644
index 0000000..dba2139
--- /dev/null
+++ b/techage/collider/worker.lua
@@ -0,0 +1,210 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2019-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Detector Worlker as part of the Collider
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local S = techage.S
+
+local AssemblyPlan = {
+ -- y-offs, path, facedir-offs, name
+ -- 0 = forward, 1 = right, 2 = backward, 3 = left
+
+ -- level 1
+ -- left/right
+ { 1, {3,3,3,2}, 0, "techage:ta4_colliderblock"},
+ { 1, {3,3,3}, 0, "techage:ta4_colliderblock"},
+ { 1, {3,3,3,0}, 0, "techage:ta4_colliderblock"},
+ { 1, {1,1,1,2}, 0, "techage:ta4_colliderblock"},
+ { 1, {1,1,1}, 0, "techage:ta4_colliderblock"},
+ { 1, {1,1,1,0}, 0, "techage:ta4_colliderblock"},
+ -- front
+ { 1, {3,3,2}, 0, "techage:ta4_colliderblock"},
+ { 1, {3,2}, 0, "techage:ta4_colliderblock"},
+ { 1, {2}, 0, "techage:ta4_colliderblock"},
+ { 1, {1,2}, 0, "techage:ta4_colliderblock"},
+ { 1, {1,1,2}, 0, "techage:ta4_colliderblock"},
+ -- back
+ { 1, {3,3,0}, 0, "techage:ta4_colliderblock"},
+ { 1, {3,0}, 0, "techage:ta4_colliderblock"},
+ { 1, {0}, 2, "techage:ta4_collider_pipe_inlet"},
+ { 1, {1,0}, 0, "techage:ta4_colliderblock"},
+ { 1, {1,1,0}, 0, "techage:ta4_colliderblock"},
+ -- middle
+ { 1, {3,3}, 0, "techage:ta4_detector_magnet"},
+ { 1, {3}, 0, "techage:ta4_detector_magnet"},
+ { 1, {1}, 0, "techage:ta4_detector_magnet"},
+ { 1, {1,1}, 0, "techage:ta4_detector_magnet"},
+
+ -- level 2
+ -- left/right
+ { 2, {3,3,3,2}, 1, "techage:ta4_collider_pipe_inlet"},
+ { 2, {3,3,3}, 1, "techage:ta4_collider_tube_inlet"},
+ { 2, {3,3,3,0}, 0, "techage:ta4_colliderblock"},
+ { 2, {1,1,1,2}, 3, "techage:ta4_collider_pipe_inlet"},
+ { 2, {1,1,1}, 3, "techage:ta4_collider_tube_inlet"},
+ { 2, {1,1,1,0}, 0, "techage:ta4_colliderblock"},
+ -- front
+ { 2, {3,3,2}, 0, "techage:ta4_detector_magnet"},
+ { 2, {3,2}, 0, "techage:ta4_detector_magnet"},
+ { 2, {2}, 0, "default:obsidian_glass"},
+ { 2, {1,2}, 0, "techage:ta4_detector_magnet"},
+ { 2, {1,1,2}, 0, "techage:ta4_detector_magnet"},
+ -- back
+ { 2, {3,3,0}, 0, "techage:ta4_detector_magnet"},
+ { 2, {3,0}, 0, "techage:ta4_detector_magnet"},
+ { 2, {0}, 0, "techage:ta4_colliderblock"},
+ { 2, {1,0}, 0, "techage:ta4_detector_magnet"},
+ { 2, {1,1,0}, 0, "techage:ta4_detector_magnet"},
+
+ -- level 3
+ -- left/right
+ { 3, {3,3,3,2}, 0, "techage:ta4_colliderblock"},
+ { 3, {3,3,3}, 1, "techage:ta4_collider_cable_inlet"},
+ { 3, {3,3,3,0}, 0, "techage:ta4_colliderblock"},
+ { 3, {1,1,1,2}, 0, "techage:ta4_colliderblock"},
+ { 3, {1,1,1}, 3, "techage:ta4_collider_cable_inlet"},
+ { 3, {1,1,1,0}, 0, "techage:ta4_colliderblock"},
+ -- front
+ { 3, {3,3,2}, 0, "techage:ta4_colliderblock"},
+ { 3, {3,2}, 0, "techage:ta4_colliderblock"},
+ { 3, {2}, 0, "techage:ta4_colliderblock"},
+ { 3, {1,2}, 0, "techage:ta4_colliderblock"},
+ { 3, {1,1,2}, 0, "techage:ta4_colliderblock"},
+ -- back
+ { 3, {3,3,0}, 0, "techage:ta4_colliderblock"},
+ { 3, {3,0}, 0, "techage:ta4_colliderblock"},
+ { 3, {0}, 2, "techage:ta4_collider_pipe_inlet"},
+ { 3, {1,0}, 0, "techage:ta4_colliderblock"},
+ { 3, {1,1,0}, 0, "techage:ta4_colliderblock"},
+ -- middle
+ { 3, {3,3}, 0, "techage:ta4_detector_magnet"},
+ { 3, {3}, 0, "techage:ta4_detector_magnet"},
+ { 3, {}, 0, "techage:ta4_collider_pipe_outlet"},
+ { 3, {1}, 0, "techage:ta4_detector_magnet"},
+ { 3, {1,1}, 0, "techage:ta4_detector_magnet"},
+
+ -- Core block
+ { 1, {}, 0, "techage:ta4_detector_core"},
+}
+
+local t = {}
+for name, cnt in pairs(techage.assemble.count_items(AssemblyPlan)) do
+ t[#t + 1] = " - " .. cnt .. " " .. name
+end
+local LABEL = table.concat(t, "\n")
+
+local function build(pos, player_name)
+ minetest.chat_send_player(player_name, S("[TA4] Detector is being built!"))
+ local inv = M(pos):get_inventory()
+ techage.assemble.build_inv(pos, inv, AssemblyPlan, player_name)
+end
+
+local function remove(pos, player_name)
+ minetest.chat_send_player(player_name, S("[TA4] Detector is being removed!"))
+ local inv = M(pos):get_inventory()
+ techage.assemble.remove_inv(pos, inv, AssemblyPlan, player_name)
+end
+
+
+local function formspec()
+ return "size[8,8.2]"..
+ "list[context;src;5,0;3,3;]"..
+ "label[0.2,-0.2;" .. S("Item list") .. ":\n" .. LABEL .. "]" ..
+ "button_exit[0,3.5;4,1;build;" .. S("Build detector") .. "]" ..
+ "button_exit[4,3.5;4,1;remove;" .. S("Remove detector") .. "]" ..
+ "list[current_player;main;0,4.5;8,4;]"..
+ "listring[context;src]"..
+ "listring[current_player;main]"
+end
+
+minetest.register_node("techage:ta4_collider_detector_worker", {
+ description = S("TA4 Collider Detector Worker"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "default_steel_block.png^techage_collider_detector_appl.png^techage_collider_detector_banner.png",
+ "default_steel_block.png^techage_collider_detector_banner.png",
+ "default_steel_block.png^techage_collider_detector_banner.png",
+ "default_steel_block.png^techage_collider_detector_banner.png",
+ "default_steel_block.png^techage_collider_detector_banner.png",
+ "default_steel_block.png^techage_collider_detector_appl.png^techage_collider_detector_banner.png",
+ },
+ drawtype = "nodebox",
+ paramtype2 = "facedir",
+ groups = {cracky = 1},
+ on_rotate = screwdriver.disallow,
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+
+ after_place_node = function(pos, placer, itemstack)
+ if pos.y > (techage.collider_min_depth - 2) then
+ minetest.remove_node(pos)
+ minetest.add_item(pos, ItemStack("techage:ta4_collider_detector_worker"))
+ return
+ end
+ local inv = M(pos):get_inventory()
+ inv:set_size("src", 9)
+ M(pos):set_string("formspec", formspec())
+ end,
+
+ on_receive_fields = function(pos, formname, fields, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return
+ end
+
+ local nvm = techage.get_nvm(pos)
+ if fields.build then
+ if not nvm.assemble_locked then
+ build(pos, player:get_player_name())
+ end
+ elseif fields.remove then
+ if not nvm.assemble_locked then
+ local nvm = techage.get_nvm({x=pos.x, y=pos.y + 1, z=pos.z})
+ if not nvm.locked then
+ remove(pos, player:get_player_name())
+ end
+ end
+ end
+ end,
+
+ after_dig_node = function(pos, oldnode)
+ techage.del_mem(pos)
+ end,
+
+ can_dig = function(pos, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return false
+ end
+ local nvm = techage.get_nvm(pos)
+ if nvm.assemble_locked or nvm.assemble_build then
+ minetest.after(30, function(pos)
+ local nvm = techage.get_nvm(pos)
+ nvm.assemble_locked = false
+ end, pos)
+ return false
+ end
+ local inv = M(pos):get_inventory()
+ return inv:is_empty("src")
+ end,
+})
+
+
+minetest.register_craft({
+ output = "techage:ta4_collider_detector_worker",
+ recipe = {
+ {'techage:aluminum', 'default:chest', 'default:steel_ingot'},
+ {'', 'basic_materials:gear_steel', ''},
+ {'default:steel_ingot', 'default:mese_crystal', 'techage:aluminum'},
+ },
+})
+
diff --git a/techage/doc/guide.lua b/techage/doc/guide.lua
index c409678..b65e121 100644
--- a/techage/doc/guide.lua
+++ b/techage/doc/guide.lua
@@ -13,6 +13,8 @@ local function tooltip(item)
local img, name = item[1], item[2]
if img == "" then -- larger image for the plan?
return "", name
+ elseif img == "10x10" then -- huge image for the plan?
+ return "10x10", name
end
local ndef = minetest.registered_nodes[name]
if ndef and ndef.description then
@@ -41,6 +43,9 @@ local function plan(images)
elseif img == "" then
img = tooltip -- use tooltip for bigger image
tbl[#tbl+1] = "image["..x_offs..","..y_offs..";2.2,2.2;"..img.."]"
+ elseif img == "10x10" then
+ img = tooltip -- use tooltip for bigger image
+ tbl[#tbl+1] = "image["..x_offs..","..y_offs..";10,10;"..img.."]"
elseif string.find(img, ":") then
tbl[#tbl+1] = "item_image["..x_offs..","..y_offs..";1,1;"..img.."]"
else
diff --git a/techage/doc/items.lua b/techage/doc/items.lua
index bf4dc37..a2e822e 100644
--- a/techage/doc/items.lua
+++ b/techage/doc/items.lua
@@ -54,8 +54,8 @@ techage.Items = {
ta2_forceload = "techage:forceload",
ta2_driveaxle = "techage:axle",
ta2_generator = "techage:ta2_generator_off",
- ta2_winch = "techage:ta2_winch",
- ta2_weight_chest = "techage:ta2_weight_chest",
+ ta2_winch = "techage:ta2_winch",
+ ta2_weight_chest = "techage:ta2_weight_chest",
---------------------
techage_ta3 = "techage_ta3.png",
techage_ta31 = "techage_ta3b.png",
@@ -126,6 +126,7 @@ techage.Items = {
ta3_injector = "techage:ta3_injector_pas",
----------------------------
techage_ta4 = "techage_ta4.png",
+ techage_ta4c = "techage_ta4c.png",
ta4_windturbine = "techage:ta4_wind_turbine",
ta4_pillar = "techage:pillar",
ta4_blinklamp = "techage:rotor_signal_lamp_off",
@@ -191,11 +192,22 @@ techage.Items = {
ta4_electricmeter = "techage:ta4_electricmeter",
ta4_transformer = "techage:ta4_transformer",
power_reduction = "techage_power_reduction.png",
+ ta4_button_2x = "techage:ta4_button_2x",
ta4_button_4x = "techage:ta4_button_4x",
ta4_sequencer = "techage:ta4_sequencer",
ta4_movecontroller = "techage:ta4_movecontroller",
+ ta4_turncontroller = "techage:ta4_turncontroller",
+ ta4_signallamp_2x = "techage:ta4_signallamp_2x",
+ ta4_signallamp_4x = "techage:ta4_signallamp_4x",
+ ta4_terminal = "techage:terminal3",
+ ta4_autocrafter = "techage:ta4_autocrafter_pas",
+ ta4_recipeblock = "techage:ta4_recipeblock",
+ ----------------------------
+ ta5_flycontroller = "techage:ta5_flycontroller",
+ ta5_aichip = "techage:ta5_aichip",
+ ta5_tele_pipe = "techage:ta5_tele_pipe",
+ ta5_tele_tube = "techage:ta5_tele_tube",
- --ta4_ "",
}
function techage.add_manual_items(table_with_items)
diff --git a/techage/doc/manual_DE.lua b/techage/doc/manual_DE.lua
index 4fc8946..78d1df5 100644
--- a/techage/doc/manual_DE.lua
+++ b/techage/doc/manual_DE.lua
@@ -117,6 +117,7 @@ techage.manual_DE.aTitel = {
"3,Tür/Tor Blöcke / Door/Gate Blocks",
"3,TA3 Tür Controller / Door Controller",
"3,TA3 Tür Controller II / Door Controller II",
+ "3,TA3 Sound Block",
"3,TA3 Mesecons Umsetzer / TA3 Mesecons Converter",
"2,Detektoren",
"3,TA3 Detektor / Detector",
@@ -138,7 +139,7 @@ techage.manual_DE.aTitel = {
"3,TechAge Programmer",
"3,TechAge Kelle / Trowel",
"3,TA3 Bohrgestängezange / TA3 Drill Pipe Wrench",
- "1,TA4: Zukunft",
+ "1,TA4: Gegenwart",
"2,Windkraftanlage",
"3,TA4 Windkraftanlage / Wind Turbine",
"3,TA4 Windkraftanlagengondel / Wind Turbine Nacelle",
@@ -183,12 +184,17 @@ techage.manual_DE.aTitel = {
"3,TA4 Lua Controller Terminal",
"2,TA4 Logik-/Schalt-Module",
"3,TA4 Taster/Schalter / Button/Switch",
+ "3,TA4 2x Taster / 2x Button",
"3,TA4 4x Taster / 4x Button",
+ "3,TA4 2x Signallampe / 2x Signal Lamp",
+ "3,TA4 4x Signallampe / 4x Signal Lamp",
"3,TA4 Spieler Detektor / Player Detector",
"3,TA4 Zustandssammler / State Collector",
"3,TA4 Detektor / Detector",
- "3,TA4 Move Controller",
"3,TA4 Sequenzer",
+ "2,Move/Dreh-Controller",
+ "3,TA4 Move Controller",
+ "3,TA4 Drehcontroller / Turn Controller",
"2,TA4 Lampen",
"3,TA4 LED Pflanzenlampe / TA4 LED Grow Light",
"3,TA4 LED Straßenlampe / TA4 LED Street Lamp",
@@ -197,7 +203,13 @@ techage.manual_DE.aTitel = {
"3,Fundament-Ebene",
"3,Schotter-Ebene",
"3,Einfüll-Ebene",
+ "2,TA4 Teilchenbeschleuniger / Collider",
+ "3,Detektor",
+ "3,Steuerung / TA4 Terminal",
+ "3,Aufbau",
"2,Weitere TA4 Blöcke",
+ "3,TA4 Rezept Block",
+ "3,TA4 Autocrafter",
"3,TA4 Tank / TA4 Tank",
"3,TA4 Pumpe / TA4 Pump",
"3,TA4 Ofenheizung / furnace heater",
@@ -215,10 +227,27 @@ techage.manual_DE.aTitel = {
"3,TA4 Elektronikfabrik / Electronic Fab",
"3,TA4 Injektor / Injector",
"3,TA4 Recycler",
+ "1,TA5: Zukunft",
+ "2,Energiequellen",
+ "3,TA5 Fusionsreaktor (geplant)",
+ "2,Energiespeicher",
+ "3,TA5 Hybrid-Speicher (geplant)",
+ "2,Logik Blöcke",
+ "2,Transport und Verkehr",
+ "3,TA5 Flug Controller",
+ "3,TA5 Hyperloop Kiste / TA5 Hyperloop Chest",
+ "3,TA5 Hyperloop Tank / TA5 Hyperloop Tank",
+ "3,Hyperloop Teleport Blöcke (geplant)",
+ "3,TA5 Container (geplant)",
+ "3,TA5 Teleport Block Gegenstände / TA5 Teleport Block Items",
+ "3,TA5 Teleport Block Flüssigkeiten / TA5 Teleport Block Liquids",
+ "3,TA5-Raumgleiter (geplant)",
+ "2,Weitere TA5 Blöcke/Items",
+ "3,TA5 KI Chip / TA5 AI Chip",
}
techage.manual_DE.aText = {
- "Tech Age ist eine Technik-Mod mit 4 Entwicklungsstufen:\n"..
+ "Tech Age ist eine Technik-Mod mit 5 Entwicklungsstufen:\n"..
"\n"..
"TA1: Eisenzeitalter (Iron Age) \n"..
"Benutze Werkzeuge und Hilfsmittel wie Köhler\\, Kohlebrenner\\, Kiessieb\\, Hammer\\, Hopper um notwendige Erze und Metalle zu schürfen und zu verarbeiten.\n"..
@@ -229,9 +258,12 @@ techage.manual_DE.aText = {
"TA3: Ölzeitalter (Oil Age)\n"..
"Suche und fördere Öl\\, baute Schienenwege zur Ölbeförderung. Ein Kraftwerk liefert den notwendigen Strom für deine Maschinen. Elektrisches Licht erhellt deine Industrieanlagen.\n"..
"\n"..
- "TA4: Zukunft (Future Age)\n"..
+ "TA4: Gegenwart (Present)\n"..
"Regenerative Energiequellen wie Wind\\, Sonne und Biokraft helfen dir\\, das Ölzeitalter zu verlassen. Mit modernen Technologien und intelligenten Maschinen machst du dich auf in die Zukunft.\n"..
"\n"..
+ "TA5: Zukunft (Future)\n"..
+ "Maschinen zur Überwindung von Raum und Zeit\\, neue Energiequellen und andere Errungenschaften prägen dein Leben.\n"..
+ "\n"..
"Hinweis: Mit Klicken auf die Pluszeichen kommst du in die Unterkapitel dieser Anleitung.\n"..
"\n"..
"\n"..
@@ -1113,6 +1145,16 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
+ "Mir dem Sound Block können veschiedene Sounds/Laute abgespielt werden. Es sind alle Sounds der Mods Techage\\, Signs Bot\\, Hyperloop\\, Unified Inventory\\, TA4 Jetpack und Minetest Game verfügbar.\n"..
+ "\n"..
+ "Die Sounds können über das Menü und über ein Kommando ausgewählt und abgespielt werden.\n"..
+ "\n"..
+ " - Kommando 'on' zum Abspielen eines Sounds\n"..
+ " - Kommando 'sound ' zur Auswahl eines Sounds über den Index\n"..
+ " - Kommando 'gain ' zum Einstellen der Lautstärke über den '' Wert (0 bis 1.0).\n"..
+ "\n"..
+ "\n"..
+ "\n",
"Der Mesecons Umsetzer dient zur Umwandlung von Techage on/off Kommandos in Mesecons Signale und umgekehrt.\n"..
"Dazu müssen eine oder mehrere Knotennummern eingegeben und der Konverter mit Mesecons Blöcken \n"..
"über Mesecons Leitungen verbunden werden. Den Mesecons Umsetzer kann man auch mit dem Programmer konfigurieren.\n"..
@@ -1436,7 +1478,8 @@ techage.manual_DE.aText = {
"Beim Cracken werden lange Kette von Kohlenwasserstoffen unter Verwendung eines Katalysator in kurze Ketten gebrochen.\n"..
"Als Katalysator dient Gibbsitpulver (wird nicht verbraucht). Damit kann Bitumen in Schweröl\\, Schweröl in Naphtha und Naphtha in Benzin umgewandelt werden.\n"..
"\n"..
- "Bei der Hydrierung werden einem Molekül Paare von Wasserstoffatomen hinzugefügt\\, um kurzkettige Kohlenwasserstoffe in lange umzuwandeln. Hier wird Eisenpulver als Katalysator benötigt (wird nicht verbraucht). Damit kann Benzin in Naphtha\\, \n"..
+ "Bei der Hydrierung werden einem Molekül Paare von Wasserstoffatomen hinzugefügt\\, um kurzkettige Kohlenwasserstoffe in lange umzuwandeln.\n"..
+ "Hier wird Eisenpulver als Katalysator benötigt (wird nicht verbraucht). Damit kann Propangas in Isobutan\\, Isobutan in Benzin\\, Benzin in Naphtha\\,\n"..
"Naphtha in Schweröl und Schweröl in Bitumen umgewandelt werden.\n"..
"\n"..
"\n"..
@@ -1562,10 +1605,32 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
+ "Dieser Block hat zwei Taster\\, die über das Schraubenschlüssel-Menü individuell konfiguriert werden können. Für beide Taster kann die Beschriftung und die Zielblockadresse konfiguriert werden. Zusätzlich kann für beide Taster das Kommando konfiguriert werden\\, welches gesendet werden soll.\n"..
+ "\n"..
+ "\n"..
+ "\n",
"Dieser Block hat vier Taster\\, die über das Schraubenschlüssel-Menü individuell konfiguriert werden können. Für jeden Taster kann die Beschriftung und die Zielblockadresse konfiguriert werden. Zusätzlich kann für jeden Taster das Kommando konfiguriert werden\\, welches gesendet werden soll.\n"..
"\n"..
"\n"..
"\n",
+ "Dieser Block hat zwei Lampen\\, die individuell angesteuert werden können. Jede Lampe kann die Farben \"rot\"\\, \"grün\" und \"orange\" anzeigen. Über das Schraubenschlüssel-Menü kann für beide Lampen die Beschriftung konfiguriert werden. Die Lampen können über folgende Kommandos angesteuert werden:\n"..
+ "\n"..
+ " - Lampe 1 auf rot schalten: '$send_cmnd(1234\\, \"red\"\\, 1)'\n"..
+ " - Lampe 2 auf grün schalten: '$send_cmnd(1234\\, \"green\"\\, 2)'\n"..
+ " - Lampe 1 auf orange schalten: '$send_cmnd(1234\\, \"amber\"\\, 1)'\n"..
+ " - Lampe 2 aus schalten: '$send_cmnd(1234\\, \"off\"\\, 2)'\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "Dieser Block hat vier Lampen\\, die individuell angesteuert werden können. Jede Lampe kann die Farben \"rot\"\\, \"grün\" und \"orange\" anzeigen. Über das Schraubenschlüssel-Menü kann für alle Lampen die Beschriftung konfiguriert werden. Die Lampen können über folgende Kommandos angesteuert werden:\n"..
+ "\n"..
+ " - Lampe 1 auf rot schalten: '$send_cmnd(1234\\, \"red\"\\, 1)'\n"..
+ " - Lampe 2 auf grün schalten: '$send_cmnd(1234\\, \"green\"\\, 2)'\n"..
+ " - Lampe 3 auf orange schalten: '$send_cmnd(1234\\, \"amber\"\\, 3)'\n"..
+ " - Lampe 4 aus schalten: '$send_cmnd(1234\\, \"off\"\\, 4)'\n"..
+ "\n"..
+ "\n"..
+ "\n",
"Beim TA4 Spieler Detektor hat sich nur das Aussehen geändert. Die Funktionalität ist gleich wie beim TA3 Spieler Detektor.\n"..
"\n"..
"\n"..
@@ -1579,26 +1644,6 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
- "Der TA4 Move Controller ist ähnlich zum \"Door Controller 2\"\\, aber die ausgewählten Blöcke werden nicht entfernt\\, sondern können bewegt werden.\n"..
- "Da die bewegten Blöcke Spieler und Mobs mitnehmen können\\, die auf dem Block stehen\\, können damit Fahrstühle und ähnliche Transportsysteme gebaut werden.\n"..
- "\n"..
- "Anleitung:\n"..
- "\n"..
- " - Controller setzen und die Blöcke\\, die bewegt werden sollen\\, über das Menü an-trainieren (Es können bis zu 16 Blöcke an-trainiert werden)\n"..
- " - die \"Flugstrecke\" muss über eine x\\,y\\,z Angabe (relativ) eingegeben werden (die maximale Distanz beträgt 100 m)\n"..
- " - mit den Menü-Tasten \"Bewege A-B\" sowie \"Bewege B-A\" kann die Bewegung getestet werden\n"..
- " - man kann auch durch Wände oder andere Blöcke fliegen\n"..
- " - auch die Zielposition für die Blöcke kann belegt sein. Die Blöcke werden in diesem Falle \"unsichtbar\" gespeichert. Dies ist für Schiebetüren und ähnliches gedacht\n"..
- " - Über das Gabelschlüssel-Menü kann im Controller auch ein \"handover\" programmiert werden. Durch Eingabe einer Blocknummer werden die Blöcke dann an den nächsten Move Controller übergeben. So lassen sich auch zusammenhängende Bewegungen über mehrere Move Controller realisieren.\n"..
- "\n"..
- "Der Move Controller unterstützt folgende techage Kommandos:\n"..
- "\n"..
- " - 'a2b' Bewege Block von A nach B\n"..
- " - 'b2a' Bewege Block von B nach A\n"..
- " - 'move' Bewege Block auf die andere Seite\n"..
- "\n"..
- "\n"..
- "\n",
"über den TA4 Sequenzer können ganze Abläufe programmiert werden. Hier ein Beispiel:\n"..
"\n"..
" -- this is a comment\n"..
@@ -1623,6 +1668,47 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
+ "",
+ "Der TA4 Move Controller ist ähnlich zum \"Door Controller 2\"\\, aber die ausgewählten Blöcke werden nicht entfernt\\, sondern können bewegt werden.\n"..
+ "Da die bewegten Blöcke Spieler und Mobs mitnehmen können\\, die auf dem Block stehen\\, können damit Fahrstühle und ähnliche Transportsysteme gebaut werden.\n"..
+ "\n"..
+ "Anleitung:\n"..
+ "\n"..
+ " - Controller setzen und die Blöcke\\, die bewegt werden sollen\\, über das Menü an-trainieren (Es können bis zu 16 Blöcke an-trainiert werden)\n"..
+ " - die \"Flugstrecke\" muss über eine x\\,y\\,z Angabe (relativ) eingegeben werden (die maximale Distanz beträgt 100 m)\n"..
+ " - mit den Menü-Tasten \"Bewege A-B\" sowie \"Bewege B-A\" kann die Bewegung getestet werden\n"..
+ " - man kann auch durch Wände oder andere Blöcke fliegen\n"..
+ " - auch die Zielposition für die Blöcke kann belegt sein. Die Blöcke werden in diesem Falle \"unsichtbar\" gespeichert. Dies ist für Schiebetüren und ähnliches gedacht\n"..
+ " - Über das Gabelschlüssel-Menü kann im Controller auch ein \"handover\" programmiert werden. Durch Eingabe einer Blocknummer werden die Blöcke dann an den nächsten Move Controller übergeben. So lassen sich auch zusammenhängende Bewegungen über mehrere Move Controller realisieren.\n"..
+ "\n"..
+ "Der Move Controller unterstützt folgende techage Kommandos:\n"..
+ "\n"..
+ " - 'a2b' Bewege Block von A nach B\n"..
+ " - 'b2a' Bewege Block von B nach A\n"..
+ " - 'move' Bewege Block auf die andere Seite\n"..
+ "\n"..
+ "*Wichtige Hinweise:*\n"..
+ "\n"..
+ " - Sofern mehrere Blöcke bewegt werden sollen\\, muss der Block\\, der die Spieler/Mobs mitnehmen soll\\, beim Antrainieren als erstes angeklickt werden.\n"..
+ " - Hat der Block\\, der die Spieler/Mobs mitnehmen soll\\, eine reduzierte Höhe\\, so muss die Höhe im Controller über das Schraubenschlüsselmenü eingestellt werden (bspw. Höhe = 0.5). Ansonsten wird der Spieler/Mob nicht \"gefunden\" und damit nicht mitgenommen.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "Der TA4 Drehcontroller ist ähnlich zum Move Controller\"\\, aber die ausgewählten Blöcke werden nicht bewegt\\, sondern um ihr Zentrum nach rechts oder links gedreht.\n"..
+ "\n"..
+ "Anleitung:\n"..
+ "\n"..
+ " - Controller setzen und die Blöcke\\, die bewegt werden sollen\\, über das Menü an-trainieren (Es können bis zu 16 Blöcke an-trainiert werden)\n"..
+ " - mit den Menü-Tasten \"Drehe links\" sowie \"Drehe rechts\" kann die Bewegung getestet werden\n"..
+ "\n"..
+ "Der Drehcontroller unterstützt folgende techage Kommandos:\n"..
+ "\n"..
+ " - 'left' Drehe nach links\n"..
+ " - 'right' Drehe nach rechts\n"..
+ " - 'uturn' Drehe um 180 Grad\n"..
+ "\n"..
+ "\n"..
+ "\n",
"TA4 beinhaltet eine Reihe von leistungsstarken Lampen\\, die eine bessere Ausleuchtung ermöglichen oder Spezialaufgaben übernehmen.\n"..
"\n",
"Die TA4 LED Pflanzenlampe ermöglicht ein schnelles und kräftiges Wachstum aller Pflanzen aus der 'farming' Mod. Die Lampe beleuchtet ein 3x3 großes Feld\\, so dass sich damit auch Pflanzen unter Tage anbauen lassen.\n"..
@@ -1675,7 +1761,99 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
+ "Der Teilchenbeschleuniger ist eine Forschungsanlage\\, bei der Grundlagenforschung betrieben wird. Hier können Erfahrungspunkte (experience points) gesammelt werden\\, welche für TA5 (Future Age) benötigt werden.\n"..
+ "\n"..
+ "Der Teilchenbeschleuniger muss wie sein Original am CERN in Genf unterirdisch aufgebaut werden. Die Standardeinstellung ist hier Y <= -28. Der Wert kann aber per Konfiguration vom Server Personal geändert werden. Ab besten nachfragen\\, oder mit dem \"TA4 Collider Detector Worker\" Block ausprobieren.\n"..
+ "\n"..
+ "Pro Spieler kann nur ein Teilchenbeschleuniger betrieben werden. Es macht also keinen Sinn\\, zwei oder mehrere Teilchenbeschleuniger aufzubauen. Erfahrungspunkte werden dem Spieler gutgeschrieben\\, dem der Teilchenbeschleuniger gehört. Die Erfahrungspunkte können nicht übertragen werden.\n"..
+ "\n"..
+ "Ein Teilchenbeschleuniger besteht aus einem \"Ring\" aus Röhren und Magneten sowie dem Detektor mit Kühlanlage. \n"..
+ "\n"..
+ " - Der Detektor ist das Herz der Anlage. Hier finden die wissenschaftlichen Experimente statt. Der Detektor ist 3x3x7 Blöcke groß.\n"..
+ " - Die TA4 Collider Detector Magnete (22 Stück) müssen über jeweils 5 Blöcken der TA4 Vakuumröhre miteinander verbunden werden. Jeder Magnet benötigt zusätzlich Strom und einen Gasanschluss für die Kühlung. Das ganze bildet (wie rechts im Plan abgebildet) ein Quadrat mit einer Kantenlänge von 37 Metern.\n"..
+ " - Zusätzlich wird eine Kühlung benötigt\\, welche zusätzlich beim Detektor aufgebaut werden muss. Für die Kühlung wird Isobutan benötigt.\n"..
+ " - Die Anlage benötigt einiges an Strom. Daher ist eine eigene Stromversorgung sinnvoll.\n"..
+ "\n"..
+ "Der Plan zeigt die Anlage von oben:\n"..
+ "\n"..
+ " - der graue Block ist der Detektor mit dem Worker-Block in der Mitte\n"..
+ " - die roten Blöcke sind die Magnete\\, das blaue die Vakuumröhren\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "Der Detektor wird mit Hilfe des \"TA4 Collider Detector Worker\" Blocks automatisch aufgebaut (ähnlich wie beim Bohrturm). Alle dazu notwendigen Materialien müssen zuvor in den Worker-Block gelegt werden. Auf dem Worker-Block ist der Detektor symbolisch dargestellt. Der Detektor wird über dem Worker-Block in Querrichtung errichtet.\n"..
+ "\n"..
+ "Der Detektor kann mit Hilfe des Worker-Blocks auch wieder abgebaut werden.\n"..
+ "\n"..
+ "Auf den beiden Stirnseiten des Detektors befinden sich die Anschlüsse für Strom\\, Gas und Vakuumröhre. Oben muss eine TA4 Pumpe angeschlossen werden\\, um die Röhre leer zu saugen / das Vakuum zu erzeugen.\n"..
+ "\n"..
+ "Auf der Rückseite des Detektors muss das Kühlsystem angeschlossen werden. Im Plan rechts ist das Kühlsystem abgebildet. Hier wird neben dem TA4 Wärmetauscher des Energiespeichers (welcher hier zur Kühlung genutzt wird)\\, auch ein TA4 Kühlerblock benötigt. \n"..
+ "\n"..
+ "Hinweis: Der Pfeil des Wärmetauschers muss vom Detektor weg zeigen. Auch der Wärmetauscher muss mit Strom versorgt werden.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "Der Teilchenbeschleuniger wird über ein TA4 Terminal gesteuert (nicht über das TA4 Lua Controller Terminal).\n"..
+ "\n"..
+ "Dieses Terminal muss mit dem Detektor verbunden werden. Die Nummer des Detektors wird als Infotext am Worker-Block angezeigt.\n"..
+ "\n"..
+ "Das Terminal unterstützt folgende Kommandos:\n"..
+ "\n"..
+ " - 'connect ' (verbinden mit dem Detektor)\n"..
+ " - 'start' (starten des Detektors)\n"..
+ " - 'stop' (stoppen des Detektors)\n"..
+ " - 'test ' (überprüfen eines Magneten)\n"..
+ " - 'points' (abfragen der bereits erreichten Erfahrungspunkte)\n"..
+ "\n"..
+ "Tritt beim 'start' an einem Magneten ein Fehler auf\\, so wird die Nummer des Magneten ausgegeben. Über das 'test' Kommando können weitere Informationen zum Fehler des Magneten angefordert werden.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "Für den Teilchenbeschleunigers wird außer den Blöcken für den Bau folgendes benötigt:\n"..
+ "\n"..
+ " - Strom (145 ku)\n"..
+ " - TA4 Tank mit mindestens 250 Einheiten Isobutan\n"..
+ "\n"..
+ "Beim Aufbau des Teilchenbeschleunigers empfiehlt sich folgende Reihenfolge:\n"..
+ "\n"..
+ " - Einen Forceload Block setzen. Nur der Detektor mit der Kühlanlage muss sich im Bereich des Forceload Blockes befinden.\n"..
+ " - Den Worker-Block setzen\\, mit Items füllen und den Detektor über das Menü aufbauen\n"..
+ " - Den Ring mit Röhren und Magneten aufbauen\n"..
+ " - Alle Magnete und den Detektor mit Stromkabel verbinden\n"..
+ " - Alle Magnete und den Detektor mit den gelben Röhren verbinden und das Isobutan mit einer Pumpe in das Röhrensystem pumpen.\n"..
+ " - Eine TA4 Pumpe als Vakuumpumpe auf dem Detektor installieren und einschalten (es wird kein zusätzlicher Tank benötigt). Geht die Pumpe in den \"standby\"\\, ist das Vakuum hergestellt. Dies dauert einige Sekunden\n"..
+ " - den Kühler (Wärmetauscher) aufbauen und mit dem Stromkabel verbinden\n"..
+ " - Das TA4 Terminal vor den Detektor setzen und über 'connect ' mit dem Detektor verbinden\n"..
+ " - Die Stromversorgung einschalten/herstellen\n"..
+ " - den Kühler (Wärmetauscher) einschalten\n"..
+ " - den Detektor über 'start' am TA4 Terminal einschalten. Der Detektor geht nach einigen Prüfschritten in den Normalbetrieb oder gibt einen Fehler aus.\n"..
+ " - Der Teilchenbeschleunigers muss im Dauerbetrieb laufen und liefert dann nach und nach Erfahrungspunkte. Für 10 Punkte muss der Teilchenbeschleuniger schon einige Stunden laufen.\n"..
+ "\n"..
+ "\n"..
+ "\n",
"",
+ "Im Rezept Block können bis zu 10 Rezepte gespeichert werden. Diese Rezepte können dann über ein TA4 Autocrafter Kommando abgerufen werden. Dies ermöglicht eine Rezept-Konfiguration des Autocrafters über ein Kommando. Die Rezepte des Rezept Blocks können auch direkt per Kommando abgefragt werden.\n"..
+ "\n"..
+ "'input ' liest ein Rezept aus dem TA4 Rezeptblock. '' ist die Nummer des Rezepts. Der Block gibt eine Liste von Rezept-Zutaten zurück. \n"..
+ "\n"..
+ "Beispiel: '$send_cmnd(1234\\, \"input\"\\, 1)'\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "Die Funktion entspricht der von TA3. \n"..
+ "\n"..
+ "Die Verarbeitungsleistung beträgt 4 Items alle 4 s. Der Autocrafter benötigt hierfür 9 ku Strom.\n"..
+ "\n"..
+ "Zusätzlich unterstützt der TA4 Autocrafter die Auswahl unterschiedlicher Rezepte über folgende Kommandos:\n"..
+ "\n"..
+ "'recipe .' schaltet den Autocrafter auf ein Rezept des TA4 Rezept Blocks um. '' ist die Nummer des Rezept Blocks\\, '' die Rezept-Nummer. Beispiel: '$send_cmnd(1234\\, \"recipe\"\\, 5467.1)'\n"..
+ "\n"..
+ "Alternativ kann ein Rezept auch über die Zutatenliste ausgewählt werden\\, wie bspw.:\n"..
+ "'$send_cmnd(1234\\, \"recipe\"\\, \"default:coal_lump\\,\\,\\,default:stick\")'\n"..
+ "Hier müssen alle technische Namen eines Rezeptes durch Kommas getrennt angegeben werden. Siehe auch das Kommando 'input' beim TA4 Rezept Block.\n"..
+ "\n"..
+ "\n"..
+ "\n",
"Siehe TA3 Tank.\n"..
"\n"..
"In einen TA4 Tank passen 2000 Einheiten oder 200 Fässer einer Flüssigkeit.\n"..
@@ -1684,7 +1862,7 @@ techage.manual_DE.aText = {
"\n",
"Siehe TA3 Pumpe.\n"..
"\n"..
- "Die TA4 Pumpe pumpt 8 Einheiten Flüssigkeit alle zwei Sekunden.\n"..
+ "Die TA4 Pumpe pumpt 8 Einheiten Flüssigkeit alle zwei Sekunden. Zusätzlich unterstützt die Pumpe das Kommando 'flowrate'. Damit kann die Gesamtdurchflussmenge durch die Pumpe abgefragt werden.\n"..
"\n"..
"\n"..
"\n",
@@ -1799,6 +1977,81 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
+ "Maschinen zur Überwindung von Raum und Zeit\\, neue Energiequellen und andere Errungenschaften prägen dein Leben. \n"..
+ "\n"..
+ "Für die Herstellung und Nutzung von TA5 Maschinen und Blöcken sind Erfahrungspunkte (experience points) notwendig. Diese können nur über den Teilchenbeschleuniger aus TA4 erarbeitet werden.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "Der TA5 Flug Controller ist ähnlich zum TA4 Move Controller. Im Gegensatz zum TA4 Move Controller können hier mehrere Bewegungen zu einer Flugstrecke kombiniert werden. Diese Flugstrecke kann im Eingabefeld über mehrere x\\,y\\,z Angaben definiert werden (eine Bewegung pro Zeile). Über \"Speichern\" wird die Flugstrecke geprüft und gespeichert. Bei einem Fehler wird eine Fehlermeldung ausgegeben.\n"..
+ "\n"..
+ "Mit der Taste \"Test\" wird die Flugstrecke mit den absoluten Koordinaten zur Überprüfung im Chat ausgegeben.\n"..
+ "\n"..
+ "Die maximale Distanz für die gesammte Flugstrecke beträgt 500 m.\n"..
+ "\n"..
+ "Die Nutzung des TA5 Flug Controllers benötigt 40 Erfahrungspunkte.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "Die TA5 Hyperloop Kiste erlaubt den Transport von Gegenständen über ein Hyperloop Netzwerk.\n"..
+ "\n"..
+ "Die TA5 Hyperloop Kiste muss man dazu auf eine Hyperloop Junction stellen. Die Kiste besitzt ein spezielles Menü\\, mit dem man das Pairing von zwei Kisten durchführen kann. Dinge\\, die in der Kiste sind\\, werden zur Gegenstelle teleportiert. Die Kiste kann auch mit einem Schieber gefüllt/geleert werden.\n"..
+ "\n"..
+ "Für das Pairing musst du zuerst auf der einen Seite einen Namen für die Kiste eingeben\\, dann kannst du bei der anderen Kiste diesen Namen auswählen und so die beiden Blöcke verbinden.\n"..
+ "\n"..
+ "Die Nutzung der TA5 Hyperloop Kiste benötigt 20 Erfahrungspunkte.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "Der TA5 Hyperloop Tank erlaubt den Transport von Flüssigkeiten über ein Hyperloop Netzwerk.\n"..
+ "\n"..
+ "Den TA5 Hyperloop Tank muss man dazu auf eine Hyperloop Junction stellen. Der Tank besitzt ein spezielles Menü\\, mit dem man das Pairing von zwei Tanks durchführen kann. Flüssigkeiten\\, die in dem Tank sind\\, werden zur Gegenstelle teleportiert. Der Tank kann auch mit einer Pumpe gefüllt/geleert werden.\n"..
+ "\n"..
+ "Für das Pairing musst du zuerst auf der einen Seite einen Namen für den Tank eingeben\\, dann kannst du bei dem anderen Tank diesen Namen auswählen und so die beiden Blöcke verbinden.\n"..
+ "\n"..
+ "Die Nutzung des TA5 Hyperloop Tanks benötigt 20 Erfahrungspunkte.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "Die Hyperloop Teleport Blöcke erlauben den Aufbau von Hyperloop Netzwerk ohne Hyperloop-Röhren.\n"..
+ "\n"..
+ "Die Nutzung der Hyperloop Teleport Blöcke benötigt 120 Erfahrungspunkte.\n"..
+ "\n",
+ "Der TA5 Container erlaubt Techage Anlagen ein- und an einer anderen Stelle wieder auszupacken.\n"..
+ "\n"..
+ "Für die Nutzung des TA5 Containers werden 80 Erfahrungspunkte benötigt.\n"..
+ "\n",
+ "Teleportblöcke erlauben den Item-Transport ohne Röhren bis zu einer Entfernung von 200 Blöcken.\n"..
+ "Für das Pairing musst du zuerst auf der einen Seite einen Namen für den Block eingeben\\, dann kannst du bei dem anderen Block diesen Namen auswählen und so die beiden Blöcke verbinden.\n"..
+ "\n"..
+ "Teleportblöcke benötigen jeweils 12 ku Strom.\n"..
+ "\n"..
+ "Für die Nutzung der Teleportblöcke werden 60 Erfahrungspunkte benötigt.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "Teleportblöcke erlauben den Flüssigkeiten-Transport ohne Leitungen bis zu einer Entfernung von 200 Blöcken.\n"..
+ "Für das Pairing musst du zuerst auf der einen Seite einen Namen für den Block eingeben\\, dann kannst du bei dem anderen Block diesen Namen auswählen und so die beiden Blöcke verbinden.\n"..
+ "\n"..
+ "Teleportblöcke benötigen jeweils 12 ku Strom.\n"..
+ "\n"..
+ "Für die Nutzung der Teleportblöcke werden 60 Erfahrungspunkte benötigt.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "Dank einem Spezialantrieb für Lichtgeschwindigkeit können mit dem Raumgleiter auch große Entfernungen sehr schnell überwunden werden.\n"..
+ "\n",
+ "",
+ "Der TA5 KI Chip wird teilweise zur Herstellung von TA5 Blöcken benötigt. Der TA5 KI Chip kann nur auf der TA4 Elektronik Fab hergestellt werden. Dazu werden 10 Erfahrungspunkte benötigt.\n"..
+ "\n"..
+ "\n"..
+ "\n",
}
techage.manual_DE.aItemName = {
@@ -1918,6 +2171,7 @@ techage.manual_DE.aItemName = {
"ta3_doorblock",
"ta3_doorcontroller",
"ta3_doorcontroller",
+ "ta3_soundblock",
"ta3_mesecons_converter",
"ta3_nodedetector",
"ta3_detector",
@@ -1984,13 +2238,18 @@ techage.manual_DE.aItemName = {
"ta4_terminal",
"",
"ta4_button",
+ "ta4_button_2x",
"ta4_button_4x",
+ "ta4_signallamp_2x",
+ "ta4_signallamp_4x",
"ta4_playerdetector",
"ta4_collector",
"ta4_detector",
- "ta4_movecontroller",
"ta4_sequencer",
"",
+ "ta4_movecontroller",
+ "ta4_turncontroller",
+ "",
"ta4_growlight",
"ta4_streetlamp",
"ta4_industriallamp",
@@ -1999,6 +2258,12 @@ techage.manual_DE.aItemName = {
"",
"",
"",
+ "",
+ "ta4_terminal",
+ "techage_ta4c",
+ "",
+ "ta4_recipeblock",
+ "ta4_autocrafter",
"ta4_tank",
"ta4_pump",
"ta4_furnaceheater",
@@ -2016,6 +2281,23 @@ techage.manual_DE.aItemName = {
"ta4_electronicfab",
"ta4_injector",
"ta4_recycler",
+ "techage_ta5",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "ta5_flycontroller",
+ "ta4_chest",
+ "ta4_tank",
+ "",
+ "",
+ "ta5_tele_tube",
+ "ta5_tele_pipe",
+ "",
+ "",
+ "ta5_aichip",
}
techage.manual_DE.aPlanTable = {
@@ -2157,6 +2439,7 @@ techage.manual_DE.aPlanTable = {
"",
"",
"",
+ "",
"ta4_windturbine",
"",
"",
@@ -2212,9 +2495,37 @@ techage.manual_DE.aPlanTable = {
"",
"",
"",
+ "",
+ "",
+ "",
+ "",
+ "",
"ta4_liquid_filter_base",
"ta4_liquid_filter_gravel",
"ta4_liquid_filter_top",
+ "techage_collider_plan",
+ "ta4_cooler",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
"",
"",
"",
diff --git a/techage/doc/manual_EN.lua b/techage/doc/manual_EN.lua
index 9a8d062..37b4a12 100644
--- a/techage/doc/manual_EN.lua
+++ b/techage/doc/manual_EN.lua
@@ -117,6 +117,7 @@ techage.manual_EN.aTitel = {
"3,Door/Gate Blocks",
"3,TA3 Door Controller",
"3,TA3 Door Controller II",
+ "3,TA3 Sound Block",
"3,TA3 Mesecons Converter",
"2,Detectors",
"3,TA3 Detector",
@@ -138,7 +139,7 @@ techage.manual_EN.aTitel = {
"3,TechAge Programmer",
"3,TechAge Trowel / Trowel",
"3,TA3 drill pipe wrench",
- "1,TA4: Future",
+ "1,TA4: Present",
"2,Wind Turbine",
"3,TA4 Wind Turbine",
"3,TA4 Wind Turbine Nacelle",
@@ -183,12 +184,17 @@ techage.manual_EN.aTitel = {
"3,TA4 Lua Controller Terminal",
"2,TA4 Logic/Switching Modules",
"3,TA4 Button/Switch",
+ "3,TA4 2x Button",
"3,TA4 4x Button",
+ "3,TA4 2x Signal Lamp",
+ "3,TA4 4x Signal Lamp",
"3,TA4 Player Detector",
"3,TA4 State Collector",
"3,TA4 Detector",
- "3,TA4 Move Controller",
"3,TA4 Sequencer",
+ "2,Move/Turn Controller",
+ "3,TA4 Move Controller",
+ "3,TA4 Turn Controller",
"2,TA4 Lamps",
"3,TA4 LED Grow Light",
"3,TA4 Street Lamp",
@@ -197,7 +203,13 @@ techage.manual_EN.aTitel = {
"3,Base Layer",
"3,Gravel Layer",
"3,Filling Layer",
+ "2,TA4 Collider (Particle Accelerator)",
+ "3,Detector",
+ "3,Control / TA4 Terminal",
+ "3,Construction",
"2,More TA4 Blocks",
+ "3,TA4 Recipe Block",
+ "3,TA4 Autocrafter",
"3,TA4 Tank",
"3,TA4 Pump",
"3,TA4 Furnace Heater",
@@ -215,10 +227,26 @@ techage.manual_EN.aTitel = {
"3,TA4 Electronic Fab",
"3,TA4 Injector",
"3,TA4 Recycler",
+ "1,TA5: Future",
+ "2,Energy Sources",
+ "3,TA5 Fusion Reactor (planned)",
+ "2,Energy Storage",
+ "3,TA5 Hybrid Storage (planned)",
+ "2,Logic blocks",
+ "2,Transport and Traffic",
+ "3,TA5 Flight Controller",
+ "3,TA5 Hyperloop Chest",
+ "3,TA5 Hyperloop Tank",
+ "3,Hyperloop Teleport Blocks (planned)",
+ "3,TA5 Container (planned)",
+ "3,TA5 Teleport Block Items",
+ "3,TA5 Teleport Block Liquids",
+ "2,More TA5 Blocks / Items",
+ "3,TA5 AI Chip",
}
techage.manual_EN.aText = {
- "Tech Age is a technology mod with 4 development stages:\n"..
+ "Tech Age is a technology mod with 5 development stages:\n"..
"\n"..
"TA1: Iron Age\n"..
"Use tools and aids such as coal burners\\, coal burners\\, gravel sieves\\, hammers and hoppers to mine and process the necessary ores and metals.\n"..
@@ -229,9 +257,12 @@ techage.manual_EN.aText = {
"TA3: Oil Age\n"..
"Find and extract oil\\, built railways for oil transportation. A power plant provides the necessary electricity for your machines. Electric light illuminates your industrial plants.\n"..
"\n"..
- "TA4: Future Age\n"..
+ "TA4: Present\n"..
"Renewable energy sources such as wind\\, sun and biofuels help you to leave the oil age. With modern technologies and intelligent machines you set out into the future.\n"..
"\n"..
+ "TA5: Future\n"..
+ "Machines to overcome space and time\\, new sources of energy and other achievements shape your life.\n"..
+ "\n"..
"Note: With a click on the plus sign you get into the subchapters of this manual.\n"..
"\n"..
"\n"..
@@ -1112,6 +1143,16 @@ techage.manual_EN.aText = {
"\n"..
"\n"..
"\n",
+ "Different sounds can be played with the sound block. All sounds of the Mods Techage\\, Signs Bot\\, Hyperloop\\, Unified Inventory\\, TA4 Jetpack and Minetest Game are available.\n"..
+ "\n"..
+ "The sounds can be selected and played via the menu and via command.\n"..
+ "\n"..
+ " - Command 'on' to play a sound\n"..
+ " - Command 'sound ' to select a sound via the index\n"..
+ " - Command 'gain ' to adjust the volume via the '' value (0 to 1.0).\n"..
+ "\n"..
+ "\n"..
+ "\n",
"The Mesecons converter is used to convert Techage on/off commands into Mesecons signals and vice versa.\n"..
"To do this\\, one or more node numbers must be entered and the converter with Mesecons blocks\n"..
"has to be connected via Mesecons cables. The Mesecons converter can also be configured with the programmer.\n"..
@@ -1434,9 +1475,9 @@ techage.manual_EN.aText = {
"Cracking breaks long chains of hydrocarbons into short chains using a catalyst.\n"..
"Gibbsite powder serves as a catalyst (is not consumed). It can be used to convert bitumen into fueloil\\, fueloil into naphtha and naphtha into gasoline.\n"..
"\n"..
- "In hydrogenation\\, pairs of hydrogen atoms are added to a molecule to convert short-chain hydrocarbons into long ones. \n"..
- "Here iron powder is required as a catalyst (is not consumed). It can be used to convert gasoline into naphtha\\,\n"..
- "naphtha into fueloil\\, and fueloil into bitumen.\n"..
+ "In hydrogenation\\, pairs of hydrogen atoms are added to a molecule to convert short-chain hydrocarbons into long ones.\n"..
+ "Here iron powder is required as a catalyst (is not consumed). It can be used to convert gas (propane) into isobutane\\,\n"..
+ "isobutane into gasoline\\, gasoline into naphtha\\, naphtha into fueloil\\, and fueloil into bitumen.\n"..
"\n"..
"\n"..
"\n",
@@ -1560,10 +1601,32 @@ techage.manual_EN.aText = {
"\n"..
"\n"..
"\n",
+ "This block has two buttons that can be individually configured using the wrench menu. The labeling and the target block address can be configured for each button. In addition\\, the command that is to be sent can be configured for each button. \n"..
+ "\n"..
+ "\n"..
+ "\n",
"This block has four buttons that can be individually configured using the wrench menu. The labeling and the target block address can be configured for each button. In addition\\, the command that is to be sent can be configured for each button. \n"..
"\n"..
"\n"..
"\n",
+ "This block has two lamps that can be controlled individually. Each lamp can display the colors \"red\"\\, \"green\" and \"amber\". The labeling for both lamps can be configured via the wrench menu. The lamps can be controlled using the following commands:\n"..
+ "\n"..
+ " - Switch lamp 1 to red: '$send_cmnd(1234\\, \"red\"\\, 1)'\n"..
+ " - Switch lamp 2 to green: '$send_cmnd(1234\\, \"green \"\\, 2)'\n"..
+ " - Switch lamp 1 to orange: '$send_cmnd(1234\\, \"amber\"\\, 1)'\n"..
+ " - Switch lamp 2 off: '$send_cmnd(1234\\, \"off\"\\, 2)'\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "This block has four lamps that can be controlled individually. Each lamp can display the colors \"red\"\\, \"green\" and \"amber\". The labeling for all lamps can be configured via the wrench menu. The lamps can be controlled using the following commands:\n"..
+ "\n"..
+ " - Switch lamp 1 to red: '$send_cmnd(1234\\, \"red\"\\, 1)'\n"..
+ " - Switch lamp 2 to green: '$send_cmnd(1234\\, \"green \"\\, 2)'\n"..
+ " - Switch lamp 3 to orange: '$send_cmnd(1234\\, \"amber\"\\, 3)'\n"..
+ " - Switch lamp 4 off: '$send_cmnd(1234\\, \"off\"\\, 4)'\n"..
+ "\n"..
+ "\n"..
+ "\n",
"Only the appearance of the TA4 player detector has changed. The functionality is the same as with the TA3 player detector.\n"..
"\n"..
"\n"..
@@ -1577,26 +1640,6 @@ techage.manual_EN.aText = {
"\n"..
"\n"..
"\n",
- "The TA4 Move Controller is similar to \"Door Controller 2\"\\, but the selected blocks are not removed\\, but can be moved.\n"..
- "Since the moving blocks can take players and mobs standing on the block with them\\, elevators and similar transport systems can be built with them.\n"..
- "\n"..
- "Instructions:\n"..
- "\n"..
- " - Set the controller and train the blocks to be moved via the menu (up to 16 blocks can be trained)\n"..
- " - the \"flight route\" must be entered via an x\\, y\\, z specification (relative) (the maximum distance is 100 m)\n"..
- " - The movement can be tested with the menu buttons \"Move A-B\" and \"Move B-A\"\n"..
- " - you can also fly through walls or other blocks\n"..
- " - The target position for the blocks can also be occupied. In this case\\, the blocks are saved \"invisibly\". This is intended for sliding doors and the like\n"..
- " - A \"handover\" can also be programmed in the controller via the open-ended wrench menu. By entering a block number\\, the blocks are then transferred to the next move controller. In this way\\, connected movements can also be implemented using several Move Controllers.\n"..
- "\n"..
- "The Move Controller supports the following techage commands:\n"..
- "\n"..
- " - 'a2b' Move block from A to B.\n"..
- " - 'b2a' Move block from B to A.\n"..
- " - 'move' Move block to the other side\n"..
- "\n"..
- "\n"..
- "\n",
"Entire processes can be programmed using the TA4 sequencer. Here's an example:\n"..
"\n"..
" -- this is a comment\n"..
@@ -1621,6 +1664,47 @@ techage.manual_EN.aText = {
"\n"..
"\n"..
"\n",
+ "",
+ "The TA4 Move Controller is similar to \"Door Controller 2\"\\, but the selected blocks are not removed\\, but can be moved.\n"..
+ "Since the moving blocks can take players and mobs standing on the block with them\\, elevators and similar transport systems can be built with them.\n"..
+ "\n"..
+ "Instructions:\n"..
+ "\n"..
+ " - Set the controller and train the blocks to be moved via the menu (up to 16 blocks can be trained)\n"..
+ " - the \"flight route\" must be entered via an x\\, y\\, z specification (relative) (the maximum distance is 100 m)\n"..
+ " - The movement can be tested with the menu buttons \"Move A-B\" and \"Move B-A\"\n"..
+ " - you can also fly through walls or other blocks\n"..
+ " - The target position for the blocks can also be occupied. In this case\\, the blocks are saved \"invisibly\". This is intended for sliding doors and the like\n"..
+ " - A \"handover\" can also be programmed in the controller via the open-ended wrench menu. By entering a block number\\, the blocks are then transferred to the next move controller. In this way\\, connected movements can also be implemented using several Move Controllers.\n"..
+ "\n"..
+ "The Move Controller supports the following techage commands:\n"..
+ "\n"..
+ " - 'a2b' Move block from A to B.\n"..
+ " - 'b2a' Move block from B to A.\n"..
+ " - 'move' Move block to the other side\n"..
+ "\n"..
+ "*Important instructions:*\n"..
+ "\n"..
+ " - If several blocks are to be moved\\, the block that is to take the players/mobs must be clicked first when training.\n"..
+ " - If the block that is supposed to take the players/mobs has a reduced height\\, the height must be set in the controller using the open-ended wrench menu (e.g. height = 0.5). Otherwise the player/mob will not be \"found\" and will not be taken away.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "The TA4 turn controller is similar to the \"Move Controller\"\\, but the selected blocks are not moved\\, but rotated around their center to the right or left.\n"..
+ "\n"..
+ "Instructions:\n"..
+ "\n"..
+ " - Set the controller and train the blocks to be moved via the menu (up to 16 blocks can be trained)\n"..
+ " - The movement can be tested with the menu buttons \"Turn left\" and \"Turn right\"\n"..
+ "\n"..
+ "The turn controller supports the following techage commands:\n"..
+ "\n"..
+ " - 'left' Turn left\n"..
+ " - 'right' Turn right\n"..
+ " - 'uturn' Turn 180 degrees\n"..
+ "\n"..
+ "\n"..
+ "\n",
"TA4 contains a series of powerful lamps that enable better illumination or take on special tasks.\n"..
"\n",
"The TA4 LED grow light enables fast and vigorous growth of all plants from the 'farming' mod. The lamp illuminates a 3x3 field\\, so that plants can also be grown underground.\n"..
@@ -1673,7 +1757,99 @@ techage.manual_EN.aText = {
"\n"..
"\n"..
"\n",
+ "The Collider is a research facility that conducts basic research. Experience points can be collected here\\, which are required for TA5 (Future Age).\n"..
+ "\n"..
+ "Like its original at CERN in Geneva\\, the collider must be built underground. The standard setting here is Y <= -28. The value can\\, however\\, be changed by the server personnel via configuration. Please ask or try the \"TA4 Collider Detector Worker\" block.\n"..
+ "\n"..
+ "Only one collider can be operated per player. So it makes no sense to set up two or more colliders. Experience points are credited to the player who owns the collider. The experience points cannot be transferred.\n"..
+ "\n"..
+ "A collider consists of a \"ring\" made of tubes and magnets as well as a detector with a cooling system.\n"..
+ "\n"..
+ " - The detector is the heart of the system. This is where the scientific experiments take place. The detector is 3x3x7 blocks in size.\n"..
+ " - The TA4 Collider Detector magnets (22 pieces) must be connected to each other via 5 blocks of the TA4 vacuum tube. Each magnet also requires electricity and a gas connection for cooling. The whole thing forms (as shown in the plan on the right) a square with an edge length of 37 meters.\n"..
+ " - In addition\\, cooling is required\\, which must also be installed at the detector. Isobutane is required for cooling.\n"..
+ " - The system requires quite a bit of electricity. Therefore\\, it makes sense to have your own power supply.\n"..
+ "\n"..
+ "The plan shows the facility from above:\n"..
+ "\n"..
+ " - the gray block is the detector with the worker block in the middle\n"..
+ " - the red blocks are the magnets\\, the blue the vacuum tubes\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "The detector is set up automatically with the help of the \"TA4 Collider Detector Worker\" block (similar to the derrick). All of the materials required for this must first be placed in the worker block. The detector is shown symbolically on the worker block. The detector is set up across the worker block.\n"..
+ "\n"..
+ "The detector can also be dismantled again with the help of the worker block.\n"..
+ "\n"..
+ "The connections for electricity\\, gas and vacuum tubes are located on the two front sides of the detector. A TA4 pump must be connected at the top in order to suck the tube empty / to create the vacuum.\n"..
+ "\n"..
+ "The cooling system must be connected to the rear of the detector. The cooling system is shown in the plan on the right. In addition to the TA4 heat exchanger of the energy storage unit (which is used here for cooling)\\, a TA4 cooler block is also required.\n"..
+ "\n"..
+ "Note: The arrow on the heat exchanger must point away from the detector. The heat exchanger must also be supplied with electricity.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "The collider is controlled via a TA4 terminal (not via the TA4 Lua controller terminal).\n"..
+ "\n"..
+ "This terminal must be connected to the detector. The number of the detector is displayed as info text on the worker block.\n"..
+ "\n"..
+ "The terminal supports the following commands:\n"..
+ "\n"..
+ " - 'connect ' (connect to the detector)\n"..
+ " - 'start' (starting the detector)\n"..
+ " - 'stop' (stop the detector)\n"..
+ " - 'test ' (checking a magnet)\n"..
+ " - 'points' (query of the experience points already achieved)\n"..
+ "\n"..
+ "If an error occurs on a magnet during the 'start'\\, the number of the magnet is output. The 'test' command can be used to request further information on the magnet error.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "In addition to the building blocks\\, the following is required for the collider:\n"..
+ "\n"..
+ " - electricity (145 ku)\n"..
+ " - TA4 tank with at least 250 units of isobutane\n"..
+ "\n"..
+ "The following sequence is recommended when setting up the collider:\n"..
+ "\n"..
+ " - Put a forceload block. Only the detector with the cooling system has to be in the area of the forceload block.\n"..
+ " - Set the worker block\\, fill it with items and set up the detector via the menu\n"..
+ " - Build the ring with tubes and magnets\n"..
+ " - Connect all magnets and the detector with power cables\n"..
+ " - Connect all magnets and the detector with the yellow tubes and pump the isobutane into the tube system with a pump\n"..
+ " - Install a TA4 pump as a vacuum pump on the detector and switch it on (no additional tank is required). If the pump goes into \"standby\"\\, the vacuum is established. This will take a few seconds\n"..
+ " - assemble the cooler (heat exchanger) and connect it to the power cable\n"..
+ " - Place the TA4 terminal in front of the detector and connect it to the detector via 'connect '\n"..
+ " - Switch on / connect the power supply\n"..
+ " - switch on the cooler (heat exchanger)\n"..
+ " - Switch on the detector via 'start' on the TA4 terminal. After a few test steps\\, the detector goes into normal operation or outputs an error.\n"..
+ " - The collider has to run continuously and then gradually delivers experience points. For 10 points\\, the collider has to run for a few hours\n"..
+ "\n"..
+ "\n"..
+ "\n",
"",
+ "Up to 10 recipes can be saved in the recipe block. These recipes can then be called up via a TA4 Autocrafter command. This enables the autocrafter's recipe to be configured using a command. The recipes in the recipe block can also be queried directly using a command.\n"..
+ "\n"..
+ "'input ' reads a recipe from the TA4 recipe block. '' is the number of the recipe. The block returns a list of recipe ingredients.\n"..
+ "\n"..
+ "Example: '$send_cmnd(1234\\, \"input\"\\, 1)'\n"..
+ "\n"..
+ " \n"..
+ "\n",
+ "The function corresponds to that of TA3.\n"..
+ "\n"..
+ "The processing power is 4 items every 4 s. The autocrafter requires 9 ku of electricity for this.\n"..
+ "\n"..
+ "In addition\\, the TA4 Autocrafter supports the selection of different recipes using the following commands:\n"..
+ "\n"..
+ "'recipe .' switches the autocrafter to a recipe from the TA4 Recipe Block. '' is the number of the recipe block\\, '' the recipe number. Example: '$send_cmnd(1234\\, \"recipe\"\\, 5467.1)'\n"..
+ "\n"..
+ "Alternatively\\, a recipe can also be selected via the list of ingredients\\, such as:\n"..
+ "'$send_cmnd(1234\\, \"recipe\"\\, \"default:coal_lump\\,\\,\\,default:stick\")'\n"..
+ "All technical names of a recipe must be specified here\\, separated by commas. See also the command 'input' in the TA4 recipe block.\n"..
+ "\n"..
+ " \n"..
+ "\n",
"See TA3 tank.\n"..
"\n"..
"A TA4 tank can hold 2000 units or 200 barrels of liquid.\n"..
@@ -1682,7 +1858,7 @@ techage.manual_EN.aText = {
"\n",
"See TA3 pump.\n"..
"\n"..
- "The TA4 pump pumps 8 units of liquid every two seconds.\n"..
+ "The TA4 pump pumps 8 units of liquid every two seconds. The pump also supports the 'flowrate' command. This means that the total flow rate through the pump can be queried. \n"..
"\n"..
"\n"..
"\n",
@@ -1798,6 +1974,79 @@ techage.manual_EN.aText = {
"\n"..
" \n"..
"\n",
+ "Machines to overcome space and time\\, new sources of energy and other achievements shape your life.\n"..
+ "\n"..
+ "Experience points are required for the manufacture and use of TA5 machines and blocks. These can only be worked out using the collider from TA4.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "The TA5 Flight Controller is similar to the TA4 Move Controller. In contrast to the TA4 Move Controller\\, several movements can be combined into one flight route. This flight route can be defined in the input field using several x\\,y\\,z entries (one movement per line). The flight route is checked and saved via \"Save\". In the event of an error\\, an error message is issued.\n"..
+ "\n"..
+ "With the \"Test\" button\\, the flight route with the absolute coordinates is output for checking in the chat.\n"..
+ "\n"..
+ "The maximum distance for the entire flight distance is 500 m.\n"..
+ "\n"..
+ "The use of the TA5 Flight Controller requires 40 experience points.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "The TA5 Hyperloop Chest allows objects to be transported over a Hyperloop network.\n"..
+ "\n"..
+ "The TA5 Hyperloop Chest has to be placed on a Hyperloop Junction. The chest has a special menu\\, with which you can pair two chests. Things that are in the chest are teleported to the remote station. The chest can also be filled/emptied with a pusher.\n"..
+ "\n"..
+ "For pairing you first have to enter a name for the chest on one side\\, then you can select this name for the other chest and thus connect the two blocks.\n"..
+ "\n"..
+ "The use of the TA5 Hyperloop Chest requires 20 experience points.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "The TA5 Hyperloop Tank allows liquids to be transported over a Hyperloop network.\n"..
+ "\n"..
+ "The TA5 Hyperloop Tank has to be placed on a Hyperloop Junction.The tank has a special menu\\, with which you can pair two tanks. Liquids in the tank will be teleported to the remote station. The tank can also be filled/emptied with a pump.\n"..
+ "\n"..
+ "For pairing you first have to enter a name for the tank on one side\\, then you can select this name for the other tank and thus connect the two blocks.\n"..
+ "\n"..
+ "The use of the TA5 Hyperloop Tank requires 20 experience points.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "The Hyperloop Teleport Blocks allow the construction of a Hyperloop network without Hyperloop tubes.\n"..
+ "\n"..
+ "The use of the Hyperloop Teleport Blocks requires 120 experience points.\n"..
+ "\n",
+ "The TA5 container allows Techage systems to be packed and unpacked at another location.\n"..
+ "\n"..
+ "80 experience points are required to use the TA5 container.\n"..
+ "\n",
+ "Teleport blocks allow items to be transported without tubes up to a distance of 200 blocks.\n"..
+ "For pairing you first have to enter a name for the block on one side\\, then you can select this name for the other block and thus connect the two blocks.\n"..
+ "\n"..
+ "Teleport blocks each require 12 ku of electricity.\n"..
+ "\n"..
+ "60 experience points are required to use the Teleport blocks.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "Teleport blocks allow liquids to be transported without pipes up to a distance of 200 blocks.\n"..
+ "For pairing you first have to enter a name for the block on one side\\, then you can select this name for the other block and thus connect the two blocks.\n"..
+ "\n"..
+ "Teleport blocks each require 12 ku of electricity.\n"..
+ "\n"..
+ "60 experience points are required to use the Teleport blocks.\n"..
+ "\n"..
+ "\n"..
+ "\n",
+ "",
+ "The TA5 AI Chip is partly required for the production of TA5 blocks. The TA5 AI Chip can only be manufactured at the TA4 Electronics Fab. This requires 10 experience points.\n"..
+ "\n"..
+ "\n"..
+ "\n",
}
techage.manual_EN.aItemName = {
@@ -1917,6 +2166,7 @@ techage.manual_EN.aItemName = {
"ta3_doorblock",
"ta3_doorcontroller",
"ta3_doorcontroller",
+ "ta3_soundblock",
"ta3_mesecons_converter",
"ta3_nodedetector",
"ta3_detector",
@@ -1983,13 +2233,18 @@ techage.manual_EN.aItemName = {
"ta4_terminal",
"",
"ta4_button",
+ "ta4_button_2x",
"ta4_button_4x",
+ "ta4_signallamp_2x",
+ "ta4_signallamp_4x",
"ta4_playerdetector",
"ta4_collector",
"ta4_detector",
- "ta4_movecontroller",
"ta4_sequencer",
"",
+ "ta4_movecontroller",
+ "ta4_turncontroller",
+ "",
"ta4_growlight",
"ta4_streetlamp",
"ta4_industriallamp",
@@ -1998,6 +2253,12 @@ techage.manual_EN.aItemName = {
"",
"",
"",
+ "",
+ "ta4_terminal",
+ "techage_ta4c",
+ "",
+ "ta4_recipeblock",
+ "ta4_autocrafter",
"ta4_tank",
"ta4_pump",
"ta4_furnaceheater",
@@ -2015,6 +2276,22 @@ techage.manual_EN.aItemName = {
"ta4_electronicfab",
"ta4_injector",
"ta4_recycler",
+ "techage_ta5",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "ta5_flycontroller",
+ "ta4_chest",
+ "ta4_tank",
+ "",
+ "",
+ "ta5_tele_tube",
+ "ta5_tele_pipe",
+ "",
+ "ta5_aichip",
}
techage.manual_EN.aPlanTable = {
@@ -2156,6 +2433,7 @@ techage.manual_EN.aPlanTable = {
"",
"",
"",
+ "",
"ta4_windturbine",
"",
"",
@@ -2211,9 +2489,36 @@ techage.manual_EN.aPlanTable = {
"",
"",
"",
+ "",
+ "",
+ "",
+ "",
+ "",
"ta4_liquid_filter_base",
"ta4_liquid_filter_gravel",
"ta4_liquid_filter_top",
+ "techage_collider_plan",
+ "ta4_cooler",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
"",
"",
"",
diff --git a/techage/doc/plans.lua b/techage/doc/plans.lua
index 4eb7b64..b2c50f4 100644
--- a/techage/doc/plans.lua
+++ b/techage/doc/plans.lua
@@ -24,6 +24,7 @@ local IMG41 = {"", "techage_ta4_tes.png"}
local IMG42 = {"", "techage_ta4_solar.png"}
local IMG43 = {"", "techage_reactor_inv.png"}
local IMG44 = {"", "techage_ta4_filter.png"}
+local IMG45 = {"10x10", "techage_collider_plan.png"}
local TOP_V = {"top_view", ""}
local SIDEV = {"side_view", ""}
@@ -462,6 +463,36 @@ techage.ConstructionPlans["ta4_liquid_filter_top"] = {
{false, CONCR, CONCR, CONCR, CONCR, CONCR},
}
+--
+-- TA4 Collider
+--
+local STEEL = {"default_steel_block.png", "techage:ta4_colliderblock"}
+local COOL4 = {"techage_filling_ta4.png^techage_frame_ta4.png^techage_cooler.png", "techage:ta4_collider_cooler"}
+
+techage.ConstructionPlans["techage_collider_plan"] = {
+ {IMG45, false, false, false},
+ {false, false, false, false},
+ {false, false, false, false},
+ {false, false, false, false},
+ {false, false, false, false},
+ {false, false, false, false},
+}
+
+--
+-- TA4 Detector Cooler
+--
+local STEEL = {"default_steel_block.png", "techage:ta4_colliderblock"}
+local COOL4 = {"techage_filling_ta4.png^techage_frame_ta4.png^techage_cooler.png", "techage:ta4_collider_cooler"}
+
+techage.ConstructionPlans["ta4_cooler"] = {
+ {false, false, false, SIDEV, false, false, false, false, false},
+ {false, false, false, false, false, false, false, false, false},
+ {false, STEEL, PIPEH, HEXR1, PIPEH, COOL4, PN270, false, false},
+ {false, STEEL, false, HEXR2, false, false, PIPEV, false, false},
+ {false, STEEL, PIPEH, HEXR3, PIPEH, PIPEH, PN180, false, false},
+ {false, false, false, false, false, false, false, false, false},
+}
+
function techage.add_manual_plans(table_with_plans)
for name, tbl in pairs(table_with_plans) do
techage.ConstructionPlans[name] = tbl
diff --git a/techage/energy_storage/heatexchanger1.lua b/techage/energy_storage/heatexchanger1.lua
index 78f562b..198f587 100644
--- a/techage/energy_storage/heatexchanger1.lua
+++ b/techage/energy_storage/heatexchanger1.lua
@@ -25,12 +25,12 @@ local power = networks.power
local function turbine_cmnd(pos, topic, payload)
return techage.transfer(pos, "R", topic, payload, Pipe,
- {"techage:ta4_turbine", "techage:ta4_turbine_on"})
+ {"techage:ta4_turbine", "techage:ta4_turbine_on", "techage:ta4_collider_cooler"})
end
local function inlet_cmnd(pos, topic, payload)
return techage.transfer(pos, "L", topic, payload, Pipe,
- {"techage:ta4_pipe_inlet"})
+ {"techage:ta4_pipe_inlet", "techage:ta4_collider_pipe_inlet"})
end
minetest.register_node("techage:heatexchanger1", {
@@ -83,7 +83,7 @@ techage.register_node({"techage:heatexchanger1"}, {
on_transfer = function(pos, indir, topic, payload)
local nvm = techage.get_nvm(pos)
-- used by heatexchanger2
- if topic == "diameter" or topic == "volume" or topic == "window" then
+ if topic == "diameter" or topic == "volume" or topic == "window" or topic == "detector" then
return inlet_cmnd(pos, topic, payload)
else
return turbine_cmnd(pos, topic, payload)
diff --git a/techage/energy_storage/heatexchanger2.lua b/techage/energy_storage/heatexchanger2.lua
index 591acc8..d914355 100644
--- a/techage/energy_storage/heatexchanger2.lua
+++ b/techage/energy_storage/heatexchanger2.lua
@@ -9,6 +9,7 @@
See LICENSE.txt for more information
TA4 Heat Exchanger2 (middle part)
+ (alternatively used as cooler for the TA4 collider)
]]--
@@ -31,6 +32,7 @@ local PWR_CAPA = {
[9] = GRVL_CAPA * 7 * 7 * 7, -- 286 kuh
}
local DOWN = 5
+local PWR_NEEDED = 5
local function heatexchanger1_cmnd(pos, topic, payload)
return techage.transfer({x = pos.x, y = pos.y - 1, z = pos.z},
@@ -75,7 +77,25 @@ local function stop_sound(pos)
end
end
+local function cooler_formspec(self, pos, nvm)
+ return "size[4,2]"..
+ "box[0,-0.1;3.8,0.5;#c6e8ff]" ..
+ "label[0.2,-0.1;" .. minetest.colorize( "#000000", S("TA4 Heat Exchanger")) .. "]" ..
+ "image_button[1.5,1;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
+ "tooltip[1.5,1;1,1;"..self:get_state_tooltip(nvm).."]"
+end
+
local function can_start(pos, nvm)
+ -- Used as cooler for the collider?
+ if heatexchanger1_cmnd(pos, "detector") then
+ if power.power_available(pos, Cable, DOWN) then
+ nvm.used_as_cooler = true
+ return true
+ else
+ return S("No power")
+ end
+ end
+ -- Used as heat exchanger
local netID = networks.determine_netID(pos, Cable, DOWN)
if heatexchanger1_cmnd(pos, "netID") ~= netID then
return S("Power network connection error")
@@ -97,21 +117,32 @@ local function can_start(pos, nvm)
end
local function start_node(pos, nvm)
- nvm.win_pos = heatexchanger1_cmnd(pos, "window")
- power.start_storage_calc(pos, Cable, DOWN)
- play_sound(pos)
- heatexchanger1_cmnd(pos, "start")
+ if nvm.used_as_cooler then
+ play_sound(pos)
+ else
+ nvm.win_pos = heatexchanger1_cmnd(pos, "window")
+ power.start_storage_calc(pos, Cable, DOWN)
+ play_sound(pos)
+ heatexchanger1_cmnd(pos, "start")
+ end
end
local function stop_node(pos, nvm)
- power.start_storage_calc(pos, Cable, DOWN)
- stop_sound(pos)
- heatexchanger1_cmnd(pos, "stop")
+ if nvm.used_as_cooler then
+ stop_sound(pos)
+ else
+ power.start_storage_calc(pos, Cable, DOWN)
+ stop_sound(pos)
+ heatexchanger1_cmnd(pos, "stop")
+ end
end
local function formspec(self, pos, nvm)
local data
+ if nvm.used_as_cooler then
+ return cooler_formspec(self, pos, nvm)
+ end
if techage.is_running(nvm) then
data = power.get_network_data(pos, Cable, DOWN)
end
@@ -135,11 +166,9 @@ local function check_TES_integrity(pos, nvm)
end
if (nvm.ticks % 30) == 0 then -- every minute
return heatexchanger1_cmnd(pos, "volume")
- end
- if (nvm.ticks % 30) == 10 then -- every minute
- return heatexchanger3_cmnd(pos, "diameter") ~= nil or S("inlet/pipe error")
- end
- if (nvm.ticks % 30) == 20 then -- every minute
+ elseif (nvm.ticks % 30) == 10 then -- every minute
+ return heatexchanger1_cmnd(pos, "diameter") ~= nil or S("inlet/pipe error")
+ elseif (nvm.ticks % 30) == 20 then -- every minute
return heatexchanger3_cmnd(pos, "diameter") ~= nil or S("inlet/pipe error")
end
local netID = networks.determine_netID(pos, Cable, DOWN)
@@ -166,8 +195,38 @@ local State = techage.NodeStates:new({
formspec_func = formspec,
})
+local function cooler_timer(pos, nvm)
+ local err = false
+ if power.consume_power(pos, Cable, DOWN, PWR_NEEDED) ~= PWR_NEEDED then
+ State:fault(pos, nvm, "No power")
+ stop_sound(pos)
+ return true
+ end
+
+ -- Cyclically check pipe connections
+ nvm.ticks = (nvm.ticks or 0) + 1
+ if (nvm.ticks % 5) == 0 then -- every 10 s
+ err = heatexchanger1_cmnd(pos, "detector") ~= true
+ elseif (nvm.ticks % 5) == 1 then -- every 10 s
+ err = heatexchanger3_cmnd(pos, "detector") ~= true
+ elseif (nvm.ticks % 5) == 2 then -- every 10 s
+ err = heatexchanger1_cmnd(pos, "cooler") ~= true
+ elseif (nvm.ticks % 5) == 3 then -- every 10 s
+ err = heatexchanger3_cmnd(pos, "cooler") ~= true
+ end
+ if err then
+ State:fault(pos, nvm, "Pipe connection error")
+ stop_sound(pos)
+ end
+ return true
+end
+
local function node_timer(pos, elapsed)
local nvm = techage.get_nvm(pos)
+ if nvm.used_as_cooler then
+ cooler_timer(pos, nvm)
+ return true
+ end
local res = check_TES_integrity(pos, nvm)
if res ~= true then
State:fault(pos, nvm, res)
@@ -304,26 +363,10 @@ techage.register_node({"techage:heatexchanger2"}, {
else
stop_sound(pos)
end
- -- convert to v1
- if not nvm.capa_max then
- local pos1 = {x = pos.x, y = pos.y - 1, z = pos.z}
- local nvm1 = techage.get_nvm(pos1)
- nvm.capa_max = nvm1.capa_max or 1
- nvm.capa = nvm1.capa or 0
-
- local own_num = techage.add_node(pos, "techage:heatexchanger2")
- State:node_init(pos, nvm, own_num)
- if nvm1.running then
- State:start(pos, nvm)
- end
- M(pos):set_string("owner", M(pos1):get_string("owner"))
- M(pos):set_string("infotext", S("TA4 Heat Exchanger")..": "..own_num)
-
- M(pos1):set_string("node_number", "")
- M(pos1):set_string("infotext", "")
- techage.del_mem(pos1)
- Cable:after_place_node(pos)
- Cable:after_place_node(pos1)
+ -- Attempt to restart the system as the heat exchanger goes into error state
+ -- when parts of the storage block are unloaded.
+ if nvm.techage_state == techage.FAULT then
+ start_node(pos, nvm)
end
end,
})
diff --git a/techage/energy_storage/heatexchanger3.lua b/techage/energy_storage/heatexchanger3.lua
index 0fa9688..70f3713 100644
--- a/techage/energy_storage/heatexchanger3.lua
+++ b/techage/energy_storage/heatexchanger3.lua
@@ -42,9 +42,14 @@ local function after_dig_node(pos, oldnode)
Pipe:after_dig_node(pos)
end
+local function cooler_cmnd(pos, topic, payload)
+ return techage.transfer(pos, "R", topic, payload, Pipe,
+ {"techage:ta4_collider_cooler"})
+end
+
local function inlet_cmnd(pos, topic, payload)
return techage.transfer(pos, "L", topic, payload, Pipe,
- {"techage:ta4_pipe_inlet"})
+ {"techage:ta4_pipe_inlet", "techage:ta4_collider_pipe_inlet"})
end
minetest.register_node("techage:heatexchanger3", {
@@ -77,7 +82,11 @@ Pipe:add_secondary_node_names({"techage:heatexchanger3"})
-- command interface, used by heatexchanger2
techage.register_node({"techage:heatexchanger3"}, {
on_transfer = function(pos, indir, topic, payload)
- return inlet_cmnd(pos, topic, payload)
+ if topic == "cooler" then
+ return cooler_cmnd(pos, topic, payload)
+ else
+ return inlet_cmnd(pos, topic, payload)
+ end
end,
})
diff --git a/techage/furnace/cooking.lua b/techage/furnace/cooking.lua
index 4583407..8e07c09 100644
--- a/techage/furnace/cooking.lua
+++ b/techage/furnace/cooking.lua
@@ -192,14 +192,12 @@ function techage.furnace.reset_cooking(nvm)
end
-if minetest.global_exists("unified_inventory") then
- unified_inventory.register_craft_type("ta3_melting", {
- description = S("TA3 Melting"),
- icon = "techage_concrete.png^techage_appl_furnace.png^techage_frame_ta3.png",
- width = 2,
- height = 2,
- })
-end
+techage.recipes.register_craft_type("ta3_melting", {
+ description = S("TA3 Melting"),
+ icon = "techage_concrete.png^techage_appl_furnace.png^techage_frame_ta3.png",
+ width = 2,
+ height = 2,
+})
function techage.furnace.register_recipe(recipe)
local words = string.split(recipe.output, " ")
@@ -224,9 +222,7 @@ function techage.furnace.register_recipe(recipe)
end
end
- if minetest.global_exists("unified_inventory") then
- recipe.items = recipe.recipe
- recipe.type = "ta3_melting"
- unified_inventory.register_craft(recipe)
- end
+ recipe.items = recipe.recipe
+ recipe.type = "ta3_melting"
+ techage.recipes.register_craft(recipe)
end
\ No newline at end of file
diff --git a/techage/icta_controller/commands.lua b/techage/icta_controller/commands.lua
index d5b5522..74354c6 100644
--- a/techage/icta_controller/commands.lua
+++ b/techage/icta_controller/commands.lua
@@ -456,7 +456,7 @@ techage.icta_register_condition("signaltower", {
})
techage.icta_register_action("signaltower", {
- title = "send Signal Tower command",
+ title = "TA4 Signal Tower",
formspec = {
{
type = "numbers",
@@ -487,6 +487,45 @@ techage.icta_register_action("signaltower", {
end,
})
+techage.icta_register_action("signallamp", {
+ title = "TA4 Signal Lamp",
+ formspec = {
+ {
+ type = "numbers",
+ name = "number",
+ label = "Signal Tower number",
+ default = "",
+ },
+ {
+ type = "textlist",
+ name = "payload",
+ label = "lamp number",
+ choices = "1,2,3,4",
+ default = "1",
+ },
+ {
+ type = "textlist",
+ name = "value",
+ label = "lamp color",
+ choices = "off,green,amber,red",
+ default = "red",
+ },
+ {
+ type = "label",
+ name = "lbl",
+ label = "Turn on/off a Signal Tower lamp.",
+ },
+ },
+ button = function(data, environ)
+ return 'tower('..techage.fmt_number(data.number)..","..data.payload..","..data.value..')'
+ end,
+ code = function(data, environ)
+ return function(env, output, idx)
+ techage.send_multi(environ.number, data.number, data.value, tonumber(data.payload))
+ end
+ end,
+})
+
techage.icta_register_action("switch", {
title = "turn block on/off",
formspec = {
@@ -657,6 +696,98 @@ techage.icta_register_action("door", {
end,
})
+techage.icta_register_action("move", {
+ title = "TA4 Move Controller",
+ formspec = {
+ {
+ type = "number",
+ name = "number",
+ label = "block number",
+ default = "",
+ },
+ {
+ type = "textlist",
+ name = "cmnd",
+ label = "command",
+ choices = "a2b,b2a,move",
+ default = "a2b",
+ },
+ },
+ button = function(data, environ) -- default button label
+ return 'move('..techage.fmt_number(data.number)..","..data.cmnd..')'
+ end,
+ code = function(data, environ)
+ return function(env, output, idx)
+ return techage.send_single(environ.number, data.number, data.cmnd)
+ end
+ end,
+})
+
+techage.icta_register_action("turn", {
+ title = "TA4 Turn Controller",
+ formspec = {
+ {
+ type = "number",
+ name = "number",
+ label = "block number",
+ default = "",
+ },
+ {
+ type = "textlist",
+ name = "cmnd",
+ label = "command",
+ choices = "left,right,uturn",
+ default = "left",
+ },
+ },
+ button = function(data, environ) -- default button label
+ return 'move('..techage.fmt_number(data.number)..","..data.cmnd..')'
+ end,
+ code = function(data, environ)
+ return function(env, output, idx)
+ return techage.send_single(environ.number, data.number, data.cmnd)
+ end
+ end,
+})
+
+techage.icta_register_action("goto", {
+ title = "TA4 Sequencer",
+ formspec = {
+ {
+ type = "number",
+ name = "number",
+ label = "block number",
+ default = "",
+ },
+ {
+ type = "textlist",
+ name = "cmnd",
+ label = "command",
+ choices = "goto,stop",
+ default = "left",
+ },
+ {
+ type = "number",
+ name = "slot",
+ label = "time slot",
+ default = "1",
+ },
+ {
+ type = "label",
+ name = "lbl",
+ label = "The 'stop' command needs no time slot.",
+ },
+ },
+ button = function(data, environ) -- default button label
+ return data.cmnd..'('..techage.fmt_number(data.number)..","..data.slot..')'
+ end,
+ code = function(data, environ)
+ return function(env, output, idx)
+ return techage.send_single(environ.number, data.number, data.cmnd, tonumber(data.slot or "1") or 1)
+ end
+ end,
+})
+
function techage.icta_player_detect(own_num, number, name)
local state = techage.send_single(own_num, number, "name", nil)
if state ~= "" then
diff --git a/techage/init.lua b/techage/init.lua
index a53ea37..61dfbd1 100644
--- a/techage/init.lua
+++ b/techage/init.lua
@@ -13,7 +13,7 @@
techage = {}
-- Version for compatibility checks, see readme.md/history
-techage.version = 1.03
+techage.version = 1.06
if minetest.global_exists("tubelib") then
minetest.log("error", "[techage] Techage can't be used together with the mod tubelib!")
@@ -33,12 +33,15 @@ elseif minetest.global_exists("minecart") and minecart.version < 1.08 then
elseif minetest.global_exists("lcdlib") and lcdlib.version < 1.01 then
minetest.log("error", "[techage] Techage requires lcdlib version 1.01 or newer!")
return
-elseif minetest.global_exists("safer_lua") and safer_lua.version < 1.0 then
- minetest.log("error", "[techage] Techage requires safer_lua version 1.0 or newer!")
+elseif minetest.global_exists("safer_lua") and safer_lua.version < 1.01 then
+ minetest.log("error", "[techage] Techage requires safer_lua version 1.01 or newer!")
return
elseif minetest.global_exists("networks") and networks.version < 0.10 then
minetest.log("error", "[techage] Techage requires networks version 0.10 or newer!")
return
+elseif minetest.global_exists("hyperloop") and hyperloop.version < 2.07 then
+ minetest.log("error", "[techage] Techage requires hyperloop version 2.07 or newer!")
+ return
end
-- Test MT 5.4 new string mode
@@ -52,6 +55,7 @@ techage.max_num_forceload_blocks = tonumber(minetest.settings:get("techage_max_n
techage.basalt_stone_enabled = minetest.settings:get_bool("techage_basalt_stone_enabled") ~= false
techage.ore_rarity = tonumber(minetest.settings:get("techage_ore_rarity")) or 1
techage.modified_recipes_enabled = minetest.settings:get_bool("techage_modified_recipes_enabled") ~= false
+techage.collider_min_depth = tonumber(minetest.settings:get("techage_collider_min_depth")) or -28
-- allow to load marshal and sqlite3
techage.IE = minetest.request_insecure_environment()
@@ -94,6 +98,12 @@ dofile(MP.."/basis/formspec_update.lua")
dofile(MP.."/basis/windturbine_lib.lua")
dofile(MP.."/basis/laser_lib.lua")
dofile(MP.."/basis/legacy.lua")
+dofile(MP.."/basis/hyperloop.lua")
+dofile(MP.."/basis/oggfiles.lua")
+dofile(MP.."/basis/submenu.lua")
+dofile(MP.."/basis/shared_inv.lua")
+dofile(MP.."/basis/shared_tank.lua")
+dofile(MP.."/basis/teleport.lua")
-- Main doc
dofile(MP.."/doc/manual_DE.lua")
@@ -183,6 +193,8 @@ dofile(MP.."/basic_machines/ta4_injector.lua")
dofile(MP.."/basic_machines/itemsource.lua")
dofile(MP.."/basic_machines/recycler.lua")
dofile(MP.."/basic_machines/concentrator.lua")
+dofile(MP.."/basic_machines/recipeblock.lua")
+dofile(MP.."/basic_machines/ta5_chest.lua")
-- Liquids II
dofile(MP.."/liquids/tank.lua")
@@ -191,6 +203,7 @@ dofile(MP.."/liquids/silo.lua")
dofile(MP.."/liquids/pump.lua")
dofile(MP.."/liquids/waterpump.lua")
dofile(MP.."/liquids/waterinlet.lua")
+dofile(MP.."/liquids/ta5_tank.lua")
-- Coal power station
dofile(MP.."/coal_power_station/firebox.lua")
@@ -270,18 +283,28 @@ dofile(MP.."/logic/lua_logic.lua") -- old
dofile(MP.."/logic/logic_block.lua") -- new
dofile(MP.."/logic/node_detector.lua")
dofile(MP.."/logic/player_detector.lua")
+dofile(MP.."/logic/mba_detector.lua")
dofile(MP.."/logic/cart_detector.lua")
-dofile(MP.."/logic/gateblock.lua")
-dofile(MP.."/logic/doorblock.lua")
-dofile(MP.."/logic/doorcontroller.lua") -- old
-dofile(MP.."/logic/doorcontroller2.lua") -- new
dofile(MP.."/logic/collector.lua")
+dofile(MP.."/logic/button_2x.lua")
dofile(MP.."/logic/button_4x.lua")
-dofile(MP.."/logic/movecontroller.lua")
+dofile(MP.."/logic/signallamp_2x.lua")
+dofile(MP.."/logic/signallamp_4x.lua")
if minetest.global_exists("mesecon") then
dofile(MP.."/logic/mesecons_converter.lua")
end
+-- move_controller
+dofile(MP.."/move_controller/gateblock.lua")
+dofile(MP.."/move_controller/doorblock.lua")
+dofile(MP.."/move_controller/doorcontroller.lua") -- old
+dofile(MP.."/move_controller/doorcontroller2.lua") -- new
+dofile(MP.."/move_controller/movecontroller.lua")
+dofile(MP.."/move_controller/turncontroller.lua")
+dofile(MP.."/move_controller/flycontroller.lua")
+dofile(MP.."/move_controller/soundblock.lua")
+
+
-- Test
dofile(MP.."/recipe_checker.lua")
dofile(MP.."/.test/sink.lua")
@@ -363,6 +386,17 @@ dofile(MP.."/items/moreblocks.lua")
dofile(MP.."/carts/tank_cart.lua")
dofile(MP.."/carts/chest_cart.lua")
+-- Collider
+dofile(MP.."/collider/vacuumtube.lua")
+dofile(MP.."/collider/magnet.lua")
+dofile(MP.."/collider/inlets.lua")
+dofile(MP.."/collider/cooler.lua")
+dofile(MP.."/collider/detector.lua")
+dofile(MP.."/collider/worker.lua")
+
+dofile(MP.."/teleport/teleport_tube.lua")
+dofile(MP.."/teleport/teleport_pipe.lua")
+
-- Prevent other mods from using IE
techage.IE = nil
diff --git a/techage/iron_age/meltingpot.lua b/techage/iron_age/meltingpot.lua
index 9ae4bac..5a286e6 100644
--- a/techage/iron_age/meltingpot.lua
+++ b/techage/iron_age/meltingpot.lua
@@ -475,25 +475,23 @@ minetest.register_craft({
},
})
-if minetest.global_exists("unified_inventory") then
- unified_inventory.register_craft_type("melting", {
- description = S("TA1 Melting"),
- icon = "default_cobble.png^techage_meltingpot.png",
- width = 2,
- height = 2,
- })
- unified_inventory.register_craft_type("burning", {
- description = S("TA1 Burning"),
- icon = "techage_smoke.png",
- width = 1,
- height = 1,
- })
- unified_inventory.register_craft({
- output = "techage:charcoal",
- items = {"group:wood"},
- type = "burning",
- })
-end
+techage.recipes.register_craft_type("melting", {
+ description = S("TA1 Melting"),
+ icon = "default_cobble.png^techage_meltingpot.png",
+ width = 2,
+ height = 2,
+})
+techage.recipes.register_craft_type("burning", {
+ description = S("TA1 Burning"),
+ icon = "techage_smoke.png",
+ width = 1,
+ height = 1,
+})
+techage.recipes.register_craft({
+ output = "techage:charcoal",
+ items = {"group:wood"},
+ type = "burning",
+})
function techage.ironage_register_recipe(recipe)
local key = recipe_key(recipe.recipe)
@@ -509,10 +507,8 @@ function techage.ironage_register_recipe(recipe)
}
NumRecipes = NumRecipes + 1
- if minetest.global_exists("unified_inventory") then
- recipe.items = recipe.recipe
- recipe.type = "melting"
- unified_inventory.register_craft(recipe)
- end
+ recipe.items = recipe.recipe
+ recipe.type = "melting"
+ techage.recipes.register_craft(recipe)
end
diff --git a/techage/items/ceramic.lua b/techage/items/ceramic.lua
index 62aa79b..357fb00 100644
--- a/techage/items/ceramic.lua
+++ b/techage/items/ceramic.lua
@@ -52,4 +52,18 @@ techage.furnace.register_recipe({
"techage:ta4_ceramic_material",
},
time = 16,
+})
+
+minetest.register_craftitem("techage:ta4_round_ceramic", {
+ description = S("TA4 Round Ceramic"),
+ inventory_image = "techage_round_ceramic.png",
+})
+
+techage.furnace.register_recipe({
+ output = "techage:ta4_round_ceramic 2",
+ recipe = {
+ "techage:ta4_ceramic_material", "techage:ta4_ceramic_material",
+ "techage:ta4_ceramic_material", "techage:ta4_ceramic_material",
+ },
+ time = 16,
})
\ No newline at end of file
diff --git a/techage/items/cracking.lua b/techage/items/cracking.lua
index 0773d3f..3555de7 100644
--- a/techage/items/cracking.lua
+++ b/techage/items/cracking.lua
@@ -15,7 +15,8 @@
In hydrogenation, pairs of hydrogen atoms are added to a molecule to convert short-chain
hydrocarbons into long ones.
Here iron powder is required as a catalyst (is not consumed).
- It can be used to convert gasoline into naphtha, naphtha into fueloil, and fueloil into bitumen.
+ It can be used to convert gas (propan) into isobutane, isobutane into gasoline, gasoline into naphtha,
+ naphtha into fueloil, and fueloil into bitumen.
]]--
@@ -46,9 +47,27 @@ techage.recipes.add("ta4_doser", {
-- Hydrogenate
techage.recipes.add("ta4_doser", {
- output = "techage:bitumen 1",
+ output = "techage:isobutane 1",
input = {
- "techage:fueloil 1",
+ "techage:gas 1",
+ "techage:hydrogen 1",
+ },
+ catalyst = "techage:iron_powder",
+})
+
+techage.recipes.add("ta4_doser", {
+ output = "techage:gasoline 1",
+ input = {
+ "techage:isobutane 1",
+ "techage:hydrogen 1",
+ },
+ catalyst = "techage:iron_powder",
+})
+
+techage.recipes.add("ta4_doser", {
+ output = "techage:naphtha 1",
+ input = {
+ "techage:gasoline 1",
"techage:hydrogen 1",
},
catalyst = "techage:iron_powder",
@@ -64,9 +83,9 @@ techage.recipes.add("ta4_doser", {
})
techage.recipes.add("ta4_doser", {
- output = "techage:naphtha 1",
+ output = "techage:bitumen 1",
input = {
- "techage:gasoline 1",
+ "techage:fueloil 1",
"techage:hydrogen 1",
},
catalyst = "techage:iron_powder",
diff --git a/techage/items/electronic.lua b/techage/items/electronic.lua
index 7c4000e..49f7a33 100644
--- a/techage/items/electronic.lua
+++ b/techage/items/electronic.lua
@@ -39,6 +39,10 @@ minetest.register_craftitem("techage:ta4_leds", {
inventory_image = "techage_leds.png",
})
+minetest.register_craftitem("techage:ta5_aichip", {
+ description = S("TA5 AI Chip"),
+ inventory_image = "techage_aichip.png",
+})
techage.recipes.add("ta2_electronic_fab", {
output = "techage:vacuum_tube 2",
@@ -74,3 +78,9 @@ techage.recipes.add("ta4_electronic_fab", {
output = "techage:ta4_leds 8",
input = {"basic_materials:plastic_sheet 4", "basic_materials:copper_wire 1", "techage:ta4_silicon_wafer 1"}
})
+
+techage.recipes.add("ta4_electronic_fab", {
+ output = "techage:ta5_aichip 2",
+ input = {"techage:ta4_leds 8", "basic_materials:copper_wire 1", "basic_materials:gold_wire 1", "techage:ta4_silicon_wafer 1"},
+ ex_points = 10,
+})
diff --git a/techage/items/petroleum.lua b/techage/items/petroleum.lua
index a0e8753..ba82b95 100644
--- a/techage/items/petroleum.lua
+++ b/techage/items/petroleum.lua
@@ -8,7 +8,7 @@
AGPL v3
See LICENSE.txt for more information
- TA3 Petroleum types: bitumen, fueloil, naphtha, gasoline, gas
+ TA3 Petroleum types: bitumen, fueloil, naphtha, gasoline, isobutane, gas (propan)
]]--
@@ -39,6 +39,12 @@ minetest.register_craftitem("techage:gasoline", {
groups = {ta_liquid = 1},
})
+minetest.register_craftitem("techage:isobutane", {
+ description = S("TA4 Isobutane"),
+ inventory_image = "techage_isobutane_inv.png",
+ groups = {ta_liquid = 1},
+})
+
minetest.register_craftitem("techage:gas", {
description = S("TA3 Propane"),
inventory_image = "techage_gas_inv.png",
@@ -57,6 +63,18 @@ minetest.register_craftitem("techage:ta3_cylinder_large_gas", {
stack_max = 1,
})
+minetest.register_craftitem("techage:ta4_cylinder_small_isobutane", {
+ description = S("Isobutane Cylinder Small"),
+ inventory_image = "techage_gas_cylinder_small.png^[colorize:#18d618:120",
+ stack_max = 1,
+})
+
+minetest.register_craftitem("techage:ta4_cylinder_large_isobutane", {
+ description = S("Isobutane Cylinder Large"),
+ inventory_image = "techage_gas_cylinder_large.png^[colorize:#18d618:120",
+ stack_max = 1,
+})
+
minetest.register_craftitem("techage:ta3_barrel_bitumen", {
description = S("TA3 Bitumen Barrel"),
inventory_image = "techage_barrel_inv.png^[colorize:#000000:120",
@@ -113,6 +131,12 @@ minetest.register_craft({
burntime = 30,
})
+minetest.register_craft({
+ type = "fuel",
+ recipe = "techage:isobutane",
+ burntime = 40,
+})
+
minetest.register_craft({
type = "fuel",
recipe = "techage:gasoline",
@@ -138,6 +162,7 @@ techage.register_liquid("techage:ta3_barrel_fueloil", "techage:ta3_barrel_empty"
techage.register_liquid("techage:ta3_barrel_naphtha", "techage:ta3_barrel_empty", 10, "techage:naphtha")
techage.register_liquid("techage:ta3_barrel_gasoline", "techage:ta3_barrel_empty", 10, "techage:gasoline")
techage.register_liquid("techage:ta3_cylinder_large_gas", "techage:ta3_cylinder_large", 6, "techage:gas")
+techage.register_liquid("techage:ta4_cylinder_large_isobutane", "techage:ta3_cylinder_large", 6, "techage:isobutane")
techage.register_liquid("techage:ta3_canister_oil", "techage:ta3_canister_empty", 1, "techage:oil_source")
techage.register_liquid("techage:ta3_canister_bitumen", "techage:ta3_canister_empty", 1, "techage:bitumen")
@@ -145,4 +170,5 @@ techage.register_liquid("techage:ta3_canister_fueloil", "techage:ta3_canister_em
techage.register_liquid("techage:ta3_canister_naphtha", "techage:ta3_canister_empty", 1, "techage:naphtha")
techage.register_liquid("techage:ta3_canister_gasoline", "techage:ta3_canister_empty", 1, "techage:gasoline")
techage.register_liquid("techage:ta3_cylinder_small_gas", "techage:ta3_cylinder_small", 1, "techage:gas")
+techage.register_liquid("techage:ta4_cylinder_small_isobutane", "techage:ta3_cylinder_small", 1, "techage:isobutane")
diff --git a/techage/liquids/pump.lua b/techage/liquids/pump.lua
index 54dc680..9f25800 100644
--- a/techage/liquids/pump.lua
+++ b/techage/liquids/pump.lua
@@ -25,6 +25,13 @@ local COUNTDOWN_TICKS = 4
local CYCLE_TIME = 2
local CAPA = 4
+local WRENCH_MENU = {{
+ type = "output",
+ name = "flowrate",
+ label = S("Total flow rate"),
+ tooltip = S("Total flow rate in liquid units"),
+}}
+
local State3 = techage.NodeStates:new({
node_name_passive = "techage:t3_pump",
node_name_active = "techage:t3_pump_on",
@@ -49,16 +56,24 @@ local function pumping(pos, nvm, state, capa)
if taken > 0 then
local leftover = liquid.put(pos, Pipe, outdir, name, taken, mem.dbg_cycles > 0)
if leftover and leftover > 0 then
+ -- air needs no tank
+ if name == "air" then
+ state:keep_running(pos, nvm, COUNTDOWN_TICKS)
+ return 0
+ end
liquid.untake(pos, Pipe, Flip[outdir], name, leftover)
if leftover == taken then
state:blocked(pos, nvm)
- return
+ return 0
end
+ state:keep_running(pos, nvm, COUNTDOWN_TICKS)
+ return taken - leftover
end
state:keep_running(pos, nvm, COUNTDOWN_TICKS)
- return
+ return taken
end
state:idle(pos, nvm)
+ return 0
end
local function after_place_node3(pos, placer)
@@ -85,7 +100,7 @@ end
local function node_timer4(pos, elapsed)
local nvm = techage.get_nvm(pos)
- pumping(pos, nvm, State4, CAPA * 2)
+ nvm.flowrate = (nvm.flowrate or 0) + pumping(pos, nvm, State4, CAPA * 2)
return State4:is_active(nvm)
end
@@ -235,6 +250,7 @@ minetest.register_node("techage:t4_pump", {
groups = {cracky=2},
is_ground_content = false,
sounds = default.node_sound_metal_defaults(),
+ ta4_formspec = WRENCH_MENU,
})
minetest.register_node("techage:t4_pump_on", {
@@ -261,7 +277,12 @@ techage.register_node({"techage:t3_pump", "techage:t3_pump_on"}, {
techage.register_node({"techage:t4_pump", "techage:t4_pump_on"}, {
on_recv_message = function(pos, src, topic, payload)
- return State4:on_receive_message(pos, topic, payload)
+ if topic == "flowrate" then
+ local nvm = techage.get_nvm(pos)
+ return nvm.flowrate or 0
+ else
+ return State4:on_receive_message(pos, topic, payload)
+ end
end,
})
diff --git a/techage/liquids/ta5_tank.lua b/techage/liquids/ta5_tank.lua
new file mode 100644
index 0000000..6f64416
--- /dev/null
+++ b/techage/liquids/ta5_tank.lua
@@ -0,0 +1,105 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2019-2022 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA5 Hyperloop Tank
+
+]]--
+
+-- for lazy programmers
+local S2P = minetest.string_to_pos
+local P2S = minetest.pos_to_string
+local M = minetest.get_meta
+local S = techage.S
+
+local Pipe = techage.LiquidPipe
+local liquid = networks.liquid
+local hyperloop = techage.hyperloop
+local remote_pos = techage.hyperloop.remote_pos
+local shared_tank = techage.shared_tank
+local menu = techage.menu
+
+local CAPACITY = 1000
+local EX_POINTS = 20
+
+minetest.register_node("techage:ta5_hl_tank", {
+ description = S("TA5 Hyperloop Tank"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_filling_ta4.png^techage_frame_ta5_top.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_tank.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_tank.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_tank.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_tank.png",
+ },
+
+ after_place_node = function(pos, placer)
+ local meta = M(pos)
+ local nvm = techage.get_nvm(pos)
+ nvm.liquid = {}
+ local number = techage.add_node(pos, "techage:ta5_hl_tank")
+ meta:set_string("node_number", number)
+ meta:set_string("owner", placer:get_player_name())
+ meta:set_string("formspec", shared_tank.formspec(pos))
+ meta:set_string("infotext", S("TA5 Hyperloop Tank").." "..number)
+ Pipe:after_place_node(pos)
+ hyperloop.after_place_node(pos, placer, "tank")
+ end,
+ on_receive_fields = function(pos, formname, fields, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return
+ end
+ if techage.get_expoints(player) >= EX_POINTS then
+ if techage.menu.eval_input(pos, hyperloop.SUBMENU, fields) then
+ hyperloop.after_formspec(pos, fields)
+ shared_tank.on_rightclick(pos, nil, player)
+ M(pos):set_string("formspec", shared_tank.formspec(pos))
+ end
+ end
+ end,
+ on_timer = shared_tank.node_timer,
+ on_rightclick = shared_tank.on_rightclick,
+ on_punch = function(pos, node, puncher)
+ return techage.liquid.on_punch(remote_pos(pos), node, puncher)
+ end,
+ can_dig = shared_tank.can_dig,
+ after_dig_node = function(pos, oldnode, oldmetadata, digger)
+ Pipe:after_dig_node(pos)
+ hyperloop.after_dig_node(pos, oldnode, oldmetadata, digger)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ techage.del_mem(pos)
+ end,
+ paramtype2 = "facedir",
+ on_rotate = screwdriver.disallow,
+ groups = {cracky=2},
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+})
+
+liquid.register_nodes({"techage:ta5_hl_tank"},
+ Pipe, "tank", nil, {
+ capa = CAPACITY,
+ peek = shared_tank.peek_liquid,
+ put = shared_tank.put_liquid,
+ take = shared_tank.take_liquid,
+ untake = shared_tank.untake_liquid,
+ }
+)
+
+techage.register_node({"techage:ta5_hl_tank"}, techage.liquid.recv_message)
+
+minetest.register_craft({
+ output = "techage:ta5_hl_tank",
+ recipe = {
+ {"", "techage:ta5_aichip", ""},
+ {"", "techage:ta4_tank", ""},
+ {"", "", ""},
+ },
+})
diff --git a/techage/liquids/tank.lua b/techage/liquids/tank.lua
index 51dc523..fbd149b 100644
--- a/techage/liquids/tank.lua
+++ b/techage/liquids/tank.lua
@@ -295,4 +295,4 @@ minetest.register_lbm({
--tubelib2.del_mem(pos)
end
end,
-})
\ No newline at end of file
+})
diff --git a/techage/locale/techage.de.tr b/techage/locale/techage.de.tr
index b81fdd3..fda454e 100644
--- a/techage/locale/techage.de.tr
+++ b/techage/locale/techage.de.tr
@@ -110,12 +110,13 @@ TA3 Booster=TA3 Gebläse
### button.lua ###
Access:=Zugriff:
+Command to be sent=Zu sendender Befehl
TA3 Button/Switch=TA3 Taster/Schalter
TA4 Button/Switch=TA4 Schalter/Taster
### button.lua ###
+### button_2x.lua ###
### button_4x.lua ###
-### signallamp_4x.lua ###
Command=Kommando
@@ -141,27 +142,32 @@ Insert destination node number(s)=Gebe Zielnummer(n) ein
Save=Speichern
-### button.lua ###
-### signallamp_4x.lua ###
+### button_2x.lua ###
-Command to be sent=Zu sendender Befehl
+TA4 2x Button=TA4 2x Taster
+### button_2x.lua ###
### button_4x.lua ###
-Command to be sent (ignored for switches)=Zu sendender Befehl (wird für Schalter ignoriert)
-Label=Beschriftung
-Label for the button=Beschriftung für die Taste
-Momentary button or on/off switch=Taster oder Ein-/Ausschalter
-TA4 4x Button=TA4 4x Taster
-Type=Typ
-
-### button_4x.lua ###
-### signallamp_4x.lua ###
-
Access=Zugriff
Button protection=Tastenschutz
+Command to be sent (ignored for switches)=Zu sendender Befehl (wird für Schalter ignoriert)
Destination block number=Zielblocknummer
+Label for the button=Beschriftung für die Taste
+Momentary button or on/off switch=Taster oder Ein-/Ausschalter
Number=Nummer
+Type=Typ
+
+### button_2x.lua ###
+### button_4x.lua ###
+### signallamp_2x.lua ###
+### signallamp_4x.lua ###
+
+Label=Beschriftung
+
+### button_4x.lua ###
+
+TA4 4x Button=TA4 4x Taster
### cart_detector.lua ###
@@ -190,6 +196,7 @@ Cement Powder=Zement Pulver
TA4 Ceramic Material=TA4 Keramik Material
TA4 Furnace Ceramic=TA4 Ofen Keramik
+TA4 Round Ceramic=TA4 Rund-Keramik
### charcoalpile.lua ###
@@ -232,6 +239,7 @@ TA3 Melting=TA3 Schmelzen
### cooler.lua ###
TA3 Cooler=TA3 Kühler
+TA4 Collider Cooler=TA4 Collider Kühler
### counting.lua ###
@@ -247,19 +255,26 @@ TA2 Cylinder=TA2 Zylinder
### detector.lua ###
+TA4 Collider Detector=TA4 Collider Detektor
+TA4 Collider Detector Core=TA4 Collider Detektorkern
+TA4 Detector=TA4 Detektor
+
+### detector.lua ###
+### logic_block.lua ###
+### tele.lua ###
+
+Blocking Time=Sperrzeit
+
+### detector.lua ###
+### tele.lua ###
+
Configured Items=Konfigurierte Gegenstände
Items which generate an 'on' command.@nIf empty, all passed items generate an 'on' command.=Items, die einen 'on'-Kommando generieren.@nWenn leer, generieren alle übergebenen Items einen 'on'-Befehl.
On Time=ON Zeit
TA3 Detector=TA3 Detektor
-TA4 Detector=TA4 Detektor
The time after the 'off' command@nuntil the next 'on' command is accepted.=Die Zeit nach dem 'off' Kommando,@nbis das nächste 'on' Kommando akzeptiert wird.
The time between the 'on' and 'off' commands.=Die Zeit zwischen den 'on' und 'off' Kommandos.
-### detector.lua ###
-### logic_block.lua ###
-
-Blocking Time=Sperrzeit
-
### display.lua ###
Display no: =Display Nr.
@@ -303,7 +318,9 @@ TA3 Door Controller II=TA3 Tür Controller II
with door sound=mit Türgeräusch
### doorcontroller2.lua ###
+### flycontroller.lua ###
### movecontroller.lua ###
+### turncontroller.lua ###
Done=Fertig
Record=Aufzeichnen
@@ -365,6 +382,7 @@ TA3 Vacuum Tube=TA3 Vakuumröhre
TA4 LEDs=TA4 LEDs
TA4 RAM Chip=RAM Chip
TA4 WLAN Chip=TA4 WLAN Chip
+TA5 AI Chip=TA5 KI Chip
WLAN Chip=WLAN Chip
### electronic_fab.lua ###
@@ -403,6 +421,49 @@ TA3 Power Station Firebox=TA3 Kraftwerks-Feuerbox
Firebox=Feuerkasten
+### fly_lib.lua ###
+
+Destination position is protected=Zielposition ist geschützt
+Error: Max. length of the flight route exceeded !!=Fehler: Max. Flugstreckenlänge überschritten !!
+No valid destination position=Keine gültige Zielposition
+No valid node at the start position=Kein gültiger Block an der Startposition
+Start position is protected=Startposition ist geschützt
+
+### fly_lib.lua ###
+### flycontroller.lua ###
+
+Error: Invalid path !!=Fehler: Ungültiger Pfad !!
+
+### flycontroller.lua ###
+
+Error: Recording is missing !!=Fehler: Aufzeichnung fehlt !!
+Flight route (A to B)=Flug Route (A nach B)
+Move=Bewege
+See chat output=Siehe chat Ausgabe
+TA5 Fly Controller=TA5 Flug Controller
+Test=Test
+[TA4 Fly Controller] Invalid path!=[TA5 Flug Controller] Ungültiger Pfad!
+[TA4 Fly Controller] Recording is missing!=[TA5 Flug Controller] Aufzeichnung fehlt!
+
+### flycontroller.lua ###
+### logic_block.lua ###
+### lua_logic.lua ###
+### movecontroller.lua ###
+
+Store=Speichern
+
+### flycontroller.lua ###
+### movecontroller.lua ###
+
+Click on all blocks that shall be moved=Klicke auf alle Blöcke, die verschoben werden sollen
+Maximum Speed=Maximalgeschwindigkeit
+Maximum speed for moving blocks=Maximale Geschwindigkeit für bewegliche Blöcke
+Move A-B=Bewege A-B
+Move B-A=Bewege B-A
+Move block height=Move Block Höhe
+Stored=Gespeichert
+Value in the range of 0.0 to 1.0=Wert im Bereich von 0.0 bis 1.0
+
### flywheel.lua ###
Flywheel=Schwungrad
@@ -532,11 +593,12 @@ TA4 Heat Exchanger 1=TA4 Wärmetauscher 1
### heatexchanger2.lua ###
+No power=Kein Strom
Power network connection error=Stromnetz Verbindungsfehler
TA4 Heat Exchanger=TA4 Wärmetauscher
TA4 Heat Exchanger 2=TA4 Wärmetauscher 2
did you check the plan?=hast du den Plan geprüft?
-inlet/pipe error=Einlass/Röhrenfehler
+inlet/pipe error=Einlass/Leitungsfehler
wrong storage diameter=Falscher Wärmespeicher-Durchmesser
### heatexchanger3.lua ###
@@ -549,6 +611,23 @@ Hydrogen Cylinder Large=Wasserstoffflasche groß
Hydrogen Cylinder Small=Wasserstoffflasche klein
TA4 Hydrogen=TA4 Wasserstoff
+### hyperloop.lua ###
+### sensorchest.lua ###
+### teleport.lua ###
+### terminal.lua ###
+
+not connected=nicht verbunden
+
+### hyperloop.lua ###
+### teleport.lua ###
+
+Block name=Blockname
+Connection name for this block=Verbindungsname für diesen Block
+Connection name of the remote block=Verbindungsname des entfernten Blocks
+Enter a block name or select an existing one=Gebe einen Blocknamen ein oder wähle einen vorhandenen aus
+Remote name=Name entfernter Block
+connected to=verbunden mit
+
### industriallamp1.lua ###
TA Industrial Lamp 1=TA Industrielampe 1
@@ -567,12 +646,19 @@ TA4 LED Industrial Lamp=TA4 LED Industrielampe
### inlet.lua ###
-TA4 Pipe Inlet=TA4 Rohrzulauf
+TA4 Pipe Inlet=TA4 Leitungszulauf
one window maximum=maximal ein Fenster
wrong diameter (should be 5, 7, or 9)=falscher Durchmesser (sollte 5, 7, oder 9 sein)
wrong number of gravel nodes=falsche Anzahl von Kiesblöcken
wrong number of shell nodes=falsche Anzahl von Blöcken bei der Hülle
+### inlets.lua ###
+
+TA4 Collider Cable Input=TA4 Collider Kabelausgang
+TA4 Collider Pipe Input=TA4 Collider Leitungseingang
+TA4 Collider Pipe Output=TA4 Collider Leitungsausgang
+TA4 Collider Tube Input=TA4 Collider Rohreneingang
+
### inverter.lua ###
Inverter=Wechselrichter
@@ -609,6 +695,7 @@ Block has an@nadditional wrench menu=Block besitzt ein@nzusätzliches@nSchrauben
### lib.lua ###
### sensorchest.lua ###
+### terminal.lua ###
connected with=verbunden mit
@@ -666,12 +753,6 @@ Syntax=Syntax
TA3 Logic Block=TA3 Logikblock
Update=Update
-### logic_block.lua ###
-### lua_logic.lua ###
-### movecontroller.lua ###
-
-Store=Speichern
-
### logic_block.lua ###
### sequencer2.lua ###
@@ -683,6 +764,17 @@ Lye=Lauge
Lye Barrel=Lauge Fass
Lye Canister=Lauge Kanister
+### magnet.lua ###
+
+TA4 Collider Detector Magnet=TA4 Collider Detektormagnet
+TA4 Collider Magnet=TA4 Collider Magnet
+TA4 Collider Magnet Base=TA4 Collider Magnetfuß
+TA4 Collider Steel Block=TA4 Collider Stahlblock
+
+### mba_detector.lua ###
+
+TA4 Mapblock Active Detector=TA4 Aktiver Mapblock Detektor
+
### meltingpot.lua ###
Heat=Hitze
@@ -736,25 +828,15 @@ TA4 Streetlamp Solar Cell=TA4 Straßenlampen-Solarzelle
### movecontroller.lua ###
-Click on all blocks that shall be moved=Klicke auf alle Blöcke, die verschoben werden sollen
-Destination position is protected=Zielposition ist geschützt
-Error: Distance > 100 m !!=Fehler: Distanz > 100 m !!
+Error: Invalid distance !!=Fehler: Ungültige Entfernung !!
Handover to A=Übergabe an A
Handover to B=Übergabe an B
-Maximum Speed=Maximalgeschwindigkeit
-Maximum speed for the moving block.=Maximale Geschwindigkeit für den beweglichen Block.
-Move A-B=Bewege A-B
-Move B-A=Bewege B-A
-Move block height=Move Block Höhe
Move distance (A to B)=Entfernung (A nach B)
-No valid destination position=Keine gültige Zielposition
-No valid node at the start position=Kein gültiger Block an der Startposition
-Number of the next movecontroller.=Nummer des nächsten Move Controllers.
-Number of the previous movecontroller.=Nummer des vorherigen Move Controllers.
-Position list error=Positionslistenfehler
-Start position is protected=Startposition ist geschützt
+Number of the next movecontroller=Nummer des nächsten Move Controllers
+Number of the previous movecontroller=Nummer des vorhergehenden Move Controllers
+Object offset=Objekt Offset
TA4 Move Controller=TA4 Move Controller
-Value in the range of 0.0 to 1.0=Wert im Bereich von 0.0 bis 1.0
+Y-offset for non-player objects like vehicles (-0.5 to 0.5)=Y-Offset für Nicht-Spieler Objekte wie Fahrzeuge (-0.5 bis 0.5)
### node_detector.lua ###
@@ -781,6 +863,8 @@ TA3 Power Station Oil Burner=TA3 Kraftwerks-Ölbrenner
### petroleum.lua ###
+Isobutane Cylinder Large=Isobutangasflasche groß
+Isobutane Cylinder Small=Isobutangasflasche klein
Propane Cylinder Large=Propangasflasche groß
Propane Cylinder Small=Propangasflasche klein
TA3 Bitumen=TA3 Bitumen
@@ -796,6 +880,7 @@ TA3 Naphtha=TA3 Naphtha
TA3 Naphtha Barrel=TA3 Naphtha-Fass
TA3 Naphtha Canister=TA3 Naphtha-Kanister
TA3 Propane=TA3 Propan
+TA4 Isobutane=TA4 Isobutan
### pillar.lua ###
@@ -803,7 +888,7 @@ TA4 Pillar=TA4 Säule
### pipe_wall_entry.lua ###
-TA3 Pipe Wall Entry=TA3 Rohr/Wanddurchbruch
+TA3 Pipe Wall Entry=TA3 Leitungs/Wanddurchbruch
### pipe_wrench.lua ###
@@ -882,6 +967,8 @@ Allow to dig/place Techage power lines nearby power poles=Erlaubt TODO
TA3 Pump=TA3 Pumpe
TA4 Pump=TA4 Pumpe
+Total flow rate=Gesamtdurchfluss
+Total flow rate in liquid units=Gesamtdurchfluss in Flüssigkeitseinheiten
### pumpjack.lua ###
@@ -912,6 +999,7 @@ inventory full=Inventar ist voll
TA3 Oil Reboiler=TA3 Aufkocher
### recipe_lib.lua ###
+### recipeblock.lua ###
Recipe=Rezept
@@ -920,6 +1008,10 @@ Recipe=Rezept
Catalyst=Katalysator
+### recipeblock.lua ###
+
+TA4 Recipe Block=TA4 Rezept Block
+
### recipes.lua ###
Flint and Iron=Flint and Iron
@@ -961,7 +1053,6 @@ TA4 Wind Turbine Nacelle=TA4 Windkraftanlagengondel
Allow public chest access=Erlaube öffentlichen Zugriff
TA4 Sensor Chest=Sensorkiste
-not connected=nicht verbunden
### sequencer.lua ###
@@ -1004,9 +1095,18 @@ TA4 Wind Turbine Signal Lamp=TA4 Windkraftanlagenlampe
TechAge Signal Lamp=TechAge Signallampe
TechAge Signal Lamp (can be colored)=TechAge Signallampe (kann gefärbt werden)
+### signallamp_2x.lua ###
+
+TA4 2x Signal Lamp=TA4 2x Signallampe
+
+### signallamp_2x.lua ###
### signallamp_4x.lua ###
-TA4 4x Signal Lamp=
+Label for the lamp=Bezeichner der Lampe
+
+### signallamp_4x.lua ###
+
+TA4 4x Signal Lamp=TA4 4x Signallampe
### silicon.lua ###
@@ -1039,6 +1139,11 @@ light=Licht
power=Strom
+### soundblock.lua ###
+
+Play=Abspielen
+TA3 Sound Block=TA3 Sound Block
+
### source.lua ###
Axle Power Source=Achsenkraftquelle
@@ -1148,6 +1253,14 @@ on=an
no power=kein Strom
+### ta5_chest.lua ###
+
+TA5 Hyperloop Chest=TA5 Hyperloop Kiste
+
+### ta5_tank.lua ###
+
+TA5 Hyperloop Tank=TA5 Hyperloop Tank
+
### tank.lua ###
Oil Tank=Öltank
@@ -1158,12 +1271,34 @@ TA4 Tank=TA4 Tank
TA Tank Cart=TA Tankwagen
+### teleport.lua ###
+
+Connected=Verbunden
+Connection status=Verbindungsstatus
+Distance > @1 blocks=Abstand > @1 Blöcke
+Ex-points missing (@1 < @2)=Erf.-Punkte fehlen (@1 < @2)
+Status=Status
+server not connected=Server nicht verbunden
+
+### teleport_pipe.lua ###
+
+TA5 Teleport Block Liquids=TA5 Teleport Block Flüssigkeiten
+
+### teleport_pipe.lua ###
+### teleport_tube.lua ###
+
+Remote block error=Fehler entfernter Block
+
+### teleport_tube.lua ###
+
+TA5 Teleport Block Items=TA5 Teleport Block Gegenstände
+
### terminal.lua ###
-Switched to private use!=Zur privaten Nutzung umgeschaltet
-Switched to public use!=Zur öffentlichen Nutzung umgeschaltet
Syntax error, try help=Syntax Fehler, nutze help
TA3 Terminal=TA3 Terminal
+TA4 Collider Terminal=TA4 Collider Terminal
+TA4 Terminal=TA4 Terminal
commands like: help=Kommandos wie: help
### timer.lua ###
@@ -1194,7 +1329,7 @@ TechAge Trowel=TechAge Kelle
### tube_wall_entry.lua ###
-Tube Wall Entry=Tube Wanddurchbruch
+Tube Wall Entry=Röhrenwanddurchbruch
### tubes.lua ###
@@ -1209,11 +1344,22 @@ TA4 Tube=TA4 Röhre
TA3 Turbine=TA3 Turbine
TA4 Turbine=TA4 Turbine
+### turncontroller.lua ###
+
+Click on all blocks that shall be turned=Klicke auf all Blöcke, die gedreht werden sollen
+TA4 Turn Controller=TA4 Dreh Controller
+Turn left=Drehe links
+Turn right=Drehe rechts
+
### usmium.lua ###
Usmium Nuggets=Usmium Nuggets
Usmium Powder=Usmium Pulver
+### vacuumtube.lua ###
+
+TA4 Vacuum Tube=TA4 Vakuumröhre
+
### valve.lua ###
TA Valve=TA Ventil
@@ -1248,7 +1394,11 @@ This is not the surface of the ocean!=Das ist nicht die Meeresoberfläche!
biome and no ocean!=Biom und keine Meer (ocean)!
is a suitable place for a wind turbine!=ist ein geeigneter Ort für eine Windkraftanlage!
+### worker.lua ###
-##### not used anymore #####
-
-[techage] The limit for commands per minute has been exceeded.=[techage] Das Limit für Befehle pro Minute wurde überschritten.
+Build detector=Baue Detektor
+Item list=Teileliste
+Remove detector=Entferne Detektor
+TA4 Collider Detector Worker=TA4 Collider Detektor Worker
+[TA4] Detector is being built!=[TA4] Detektor wird gebaut!
+[TA4] Detector is being removed!=[TA4] Detektor wird entfernt!
diff --git a/techage/locale/template.txt b/techage/locale/template.txt
index ead7e30..6a51b06 100644
--- a/techage/locale/template.txt
+++ b/techage/locale/template.txt
@@ -110,12 +110,13 @@ TA3 Booster=
### button.lua ###
Access:=
+Command to be sent=
TA3 Button/Switch=
TA4 Button/Switch=
### button.lua ###
+### button_2x.lua ###
### button_4x.lua ###
-### signallamp_4x.lua ###
Command=
@@ -141,27 +142,32 @@ Insert destination node number(s)=
Save=
-### button.lua ###
-### signallamp_4x.lua ###
+### button_2x.lua ###
-Command to be sent=
+TA4 2x Button=
+### button_2x.lua ###
### button_4x.lua ###
-Command to be sent (ignored for switches)=
-Label=
-Label for the button=
-Momentary button or on/off switch=
-TA4 4x Button=
-Type=
-
-### button_4x.lua ###
-### signallamp_4x.lua ###
-
Access=
Button protection=
+Command to be sent (ignored for switches)=
Destination block number=
+Label for the button=
+Momentary button or on/off switch=
Number=
+Type=
+
+### button_2x.lua ###
+### button_4x.lua ###
+### signallamp_2x.lua ###
+### signallamp_4x.lua ###
+
+Label=
+
+### button_4x.lua ###
+
+TA4 4x Button=
### cart_detector.lua ###
@@ -190,6 +196,7 @@ Cement Powder=
TA4 Ceramic Material=
TA4 Furnace Ceramic=
+TA4 Round Ceramic=
### charcoalpile.lua ###
@@ -232,6 +239,7 @@ TA3 Melting=
### cooler.lua ###
TA3 Cooler=
+TA4 Collider Cooler=
### counting.lua ###
@@ -247,19 +255,26 @@ TA2 Cylinder=
### detector.lua ###
+TA4 Collider Detector=
+TA4 Collider Detector Core=
+TA4 Detector=
+
+### detector.lua ###
+### logic_block.lua ###
+### tele.lua ###
+
+Blocking Time=
+
+### detector.lua ###
+### tele.lua ###
+
Configured Items=
Items which generate an 'on' command.@nIf empty, all passed items generate an 'on' command.=
On Time=
TA3 Detector=
-TA4 Detector=
The time after the 'off' command@nuntil the next 'on' command is accepted.=
The time between the 'on' and 'off' commands.=
-### detector.lua ###
-### logic_block.lua ###
-
-Blocking Time=
-
### display.lua ###
Display no: =
@@ -303,7 +318,9 @@ TA3 Door Controller II=
with door sound=
### doorcontroller2.lua ###
+### flycontroller.lua ###
### movecontroller.lua ###
+### turncontroller.lua ###
Done=
Record=
@@ -365,6 +382,7 @@ TA3 Vacuum Tube=
TA4 LEDs=
TA4 RAM Chip=
TA4 WLAN Chip=
+TA5 AI Chip=
WLAN Chip=
### electronic_fab.lua ###
@@ -403,6 +421,49 @@ TA3 Power Station Firebox=
Firebox=
+### fly_lib.lua ###
+
+Destination position is protected=
+Error: Max. length of the flight route exceeded !!=
+No valid destination position=
+No valid node at the start position=
+Start position is protected=
+
+### fly_lib.lua ###
+### flycontroller.lua ###
+
+Error: Invalid path !!=
+
+### flycontroller.lua ###
+
+Error: Recording is missing !!=
+Flight route (A to B)=
+Move=
+See chat output=
+TA5 Fly Controller=
+Test=
+[TA4 Fly Controller] Invalid path!=
+[TA4 Fly Controller] Recording is missing!=
+
+### flycontroller.lua ###
+### logic_block.lua ###
+### lua_logic.lua ###
+### movecontroller.lua ###
+
+Store=
+
+### flycontroller.lua ###
+### movecontroller.lua ###
+
+Click on all blocks that shall be moved=
+Maximum Speed=
+Maximum speed for moving blocks=
+Move A-B=
+Move B-A=
+Move block height=
+Stored=
+Value in the range of 0.0 to 1.0=
+
### flywheel.lua ###
Flywheel=
@@ -532,6 +593,7 @@ TA4 Heat Exchanger 1=
### heatexchanger2.lua ###
+No power=
Power network connection error=
TA4 Heat Exchanger=
TA4 Heat Exchanger 2=
@@ -549,6 +611,23 @@ Hydrogen Cylinder Large=
Hydrogen Cylinder Small=
TA4 Hydrogen=
+### hyperloop.lua ###
+### sensorchest.lua ###
+### teleport.lua ###
+### terminal.lua ###
+
+not connected=
+
+### hyperloop.lua ###
+### teleport.lua ###
+
+Block name=
+Connection name for this block=
+Connection name of the remote block=
+Enter a block name or select an existing one=
+Remote name=
+connected to=
+
### industriallamp1.lua ###
TA Industrial Lamp 1=
@@ -573,6 +652,13 @@ wrong diameter (should be 5, 7, or 9)=
wrong number of gravel nodes=
wrong number of shell nodes=
+### inlets.lua ###
+
+TA4 Collider Cable Input=
+TA4 Collider Pipe Input=
+TA4 Collider Pipe Output=
+TA4 Collider Tube Input=
+
### inverter.lua ###
Inverter=
@@ -609,6 +695,7 @@ Block has an@nadditional wrench menu=
### lib.lua ###
### sensorchest.lua ###
+### terminal.lua ###
connected with=
@@ -666,12 +753,6 @@ Syntax=
TA3 Logic Block=
Update=
-### logic_block.lua ###
-### lua_logic.lua ###
-### movecontroller.lua ###
-
-Store=
-
### logic_block.lua ###
### sequencer2.lua ###
@@ -683,6 +764,17 @@ Lye=
Lye Barrel=
Lye Canister=
+### magnet.lua ###
+
+TA4 Collider Detector Magnet=
+TA4 Collider Magnet=
+TA4 Collider Magnet Base=
+TA4 Collider Steel Block=
+
+### mba_detector.lua ###
+
+TA4 Mapblock Active Detector=
+
### meltingpot.lua ###
Heat=
@@ -736,25 +828,15 @@ TA4 Streetlamp Solar Cell=
### movecontroller.lua ###
-Click on all blocks that shall be moved=
-Destination position is protected=
-Error: Distance > 100 m !!=
+Error: Invalid distance !!=
Handover to A=
Handover to B=
-Maximum Speed=
-Maximum speed for the moving block.=
-Move A-B=
-Move B-A=
-Move block height=
Move distance (A to B)=
-No valid destination position=
-No valid node at the start position=
-Number of the next movecontroller.=
-Number of the previous movecontroller.=
-Position list error=
-Start position is protected=
+Number of the next movecontroller=
+Number of the previous movecontroller=
+Object offset=
TA4 Move Controller=
-Value in the range of 0.0 to 1.0=
+Y-offset for non-player objects like vehicles (-0.5 to 0.5)=
### node_detector.lua ###
@@ -781,6 +863,8 @@ TA3 Power Station Oil Burner=
### petroleum.lua ###
+Isobutane Cylinder Large=
+Isobutane Cylinder Small=
Propane Cylinder Large=
Propane Cylinder Small=
TA3 Bitumen=
@@ -796,6 +880,7 @@ TA3 Naphtha=
TA3 Naphtha Barrel=
TA3 Naphtha Canister=
TA3 Propane=
+TA4 Isobutane=
### pillar.lua ###
@@ -882,6 +967,8 @@ Allow to dig/place Techage power lines nearby power poles=
TA3 Pump=
TA4 Pump=
+Total flow rate=
+Total flow rate in liquid units=
### pumpjack.lua ###
@@ -912,6 +999,7 @@ inventory full=
TA3 Oil Reboiler=
### recipe_lib.lua ###
+### recipeblock.lua ###
Recipe=
@@ -920,6 +1008,10 @@ Recipe=
Catalyst=
+### recipeblock.lua ###
+
+TA4 Recipe Block=
+
### recipes.lua ###
Flint and Iron=
@@ -961,7 +1053,6 @@ TA4 Wind Turbine Nacelle=
Allow public chest access=
TA4 Sensor Chest=
-not connected=
### sequencer.lua ###
@@ -1004,6 +1095,15 @@ TA4 Wind Turbine Signal Lamp=
TechAge Signal Lamp=
TechAge Signal Lamp (can be colored)=
+### signallamp_2x.lua ###
+
+TA4 2x Signal Lamp=
+
+### signallamp_2x.lua ###
+### signallamp_4x.lua ###
+
+Label for the lamp=
+
### signallamp_4x.lua ###
TA4 4x Signal Lamp=
@@ -1039,6 +1139,11 @@ light=
power=
+### soundblock.lua ###
+
+Play=
+TA3 Sound Block=
+
### source.lua ###
Axle Power Source=
@@ -1148,6 +1253,14 @@ on=
no power=
+### ta5_chest.lua ###
+
+TA5 Hyperloop Chest=
+
+### ta5_tank.lua ###
+
+TA5 Hyperloop Tank=
+
### tank.lua ###
Oil Tank=
@@ -1158,12 +1271,34 @@ TA4 Tank=
TA Tank Cart=
+### teleport.lua ###
+
+Connected=
+Connection status=
+Distance > @1 blocks=
+Ex-points missing (@1 < @2)=
+Status=
+server not connected=
+
+### teleport_pipe.lua ###
+
+TA5 Teleport Block Liquids=
+
+### teleport_pipe.lua ###
+### teleport_tube.lua ###
+
+Remote block error=
+
+### teleport_tube.lua ###
+
+TA5 Teleport Block Items=
+
### terminal.lua ###
-Switched to private use!=
-Switched to public use!=
Syntax error, try help=
TA3 Terminal=
+TA4 Collider Terminal=
+TA4 Terminal=
commands like: help=
### timer.lua ###
@@ -1209,11 +1344,22 @@ TA4 Tube=
TA3 Turbine=
TA4 Turbine=
+### turncontroller.lua ###
+
+Click on all blocks that shall be turned=
+TA4 Turn Controller=
+Turn left=
+Turn right=
+
### usmium.lua ###
Usmium Nuggets=
Usmium Powder=
+### vacuumtube.lua ###
+
+TA4 Vacuum Tube=
+
### valve.lua ###
TA Valve=
@@ -1247,3 +1393,12 @@ This is not the surface of the ocean!=
[TA4 Wind Turbine]=
biome and no ocean!=
is a suitable place for a wind turbine!=
+
+### worker.lua ###
+
+Build detector=
+Item list=
+Remove detector=
+TA4 Collider Detector Worker=
+[TA4] Detector is being built!=
+[TA4] Detector is being removed!=
diff --git a/techage/logic/button_2x.lua b/techage/logic/button_2x.lua
new file mode 100644
index 0000000..3d46904
--- /dev/null
+++ b/techage/logic/button_2x.lua
@@ -0,0 +1,252 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2017-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Logic twofold button
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local S = techage.S
+
+local function get_button_num(pos, clicker, pointed_thing)
+ -- use the node behind the button to get better results
+ if clicker and pointed_thing then
+ local offs = vector.subtract(pointed_thing.under, pointed_thing.above)
+ pointed_thing.under = vector.add(pointed_thing.under, offs)
+ pointed_thing.above = vector.add(pointed_thing.above, offs)
+ local pos1 = minetest.pointed_thing_to_face_pos(clicker, pointed_thing)
+ local y = pos1.y - pos.y
+
+ if y > 0.03 then
+ return 1
+ elseif y < -0.03 then
+ return 2
+ end
+ end
+end
+
+local WRENCH_MENU = {
+ {
+ type = "dropdown",
+ choices = "button,switch",
+ name = "type",
+ label = S("Type"),
+ tooltip = S("Momentary button or on/off switch"),
+ default = "1",
+ },
+ {
+ type = "ascii",
+ name = "label1",
+ label = S("Label") .. " 1",
+ tooltip = S("Label for the button"),
+ default = "1",
+ },
+ {
+ type = "numbers",
+ name = "dest_number1",
+ label = S("Number") .. " 1",
+ tooltip = S("Destination block number"),
+ default = "",
+ },
+ {
+ type = "ascii",
+ name = "command1",
+ label = S("Command") .. " 1",
+ tooltip = S("Command to be sent (ignored for switches)"),
+ default = "1",
+ },
+ {
+ type = "ascii",
+ name = "label2",
+ label = S("Label") .. " 2",
+ tooltip = S("Label for the button"),
+ default = "1",
+ },
+ {
+ type = "numbers",
+ name = "dest_number2",
+ label = S("Number") .. " 2",
+ tooltip = S("Destination block number"),
+ default = "",
+ },
+ {
+ type = "ascii",
+ name = "command2",
+ label = S("Command") .. " 2",
+ tooltip = S("Command to be sent (ignored for switches)"),
+ default = "2",
+ },
+ {
+ type = "dropdown",
+ choices = "private,protected,public",
+ name = "access",
+ label = S("Access"),
+ tooltip = S("Button protection"),
+ default = "8",
+ },
+}
+
+local function send_cmnd(pos, num, cmd)
+ local meta = M(pos)
+ local own_num = meta:get_string("node_number")
+ local dest = meta:get_string("dest_number" .. num)
+ local command, payload = cmd, nil
+ if not cmd then
+ local s = meta:get_string("command" .. num)
+ command, payload = unpack(string.split(s, " ", false, 1))
+ end
+ local owner = meta:get_string("owner")
+ if techage.check_numbers(dest, owner) then
+ techage.send_multi(own_num, dest, command, payload)
+ end
+end
+
+local function button_update(pos, objref)
+ local meta = M(pos)
+ pos = vector.round(pos)
+ local nvm = techage.get_nvm(pos)
+ nvm.button = nvm.button or {}
+ local tbl = {" ", " ", meta:get_string("label1"), " ", meta:get_string("label2")}
+ local text = "< " .. table.concat(tbl, "\n< ")
+ local texture = lcdlib.make_multiline_texture("default", text, 96, 96, 7, "top", "#000", 6)
+
+ if nvm.button[1] then
+ texture = texture .. "^techage_smartline_button_4x_on2.png"
+ end
+ if nvm.button[2] then
+ texture = texture .. "^techage_smartline_button_4x_on3.png"
+ end
+ objref:set_properties({ textures = {texture}, visual_size = {x=1, y=1} })
+end
+
+local function switch_off(pos, num)
+ local nvm = techage.get_nvm(pos)
+ nvm.button = nvm.button or {}
+ nvm.button[num] = nil
+ lcdlib.update_entities(pos)
+end
+
+local function switch_on(pos, num)
+ local nvm = techage.get_nvm(pos)
+ nvm.button = nvm.button or {}
+ nvm.button[num] = true
+ lcdlib.update_entities(pos)
+end
+
+local lcd_box = {-8/16, -4/16, 7.75/16, 8/16, 4/16, 8/16}
+
+local function can_access(pos, player)
+ local meta = M(pos)
+ local playername = player:get_player_name()
+ local access = meta:get_string("access")
+ local owner = meta:get_string("owner")
+ local protected = minetest.is_protected(pos, playername)
+
+ if access == "private" and playername ~= owner then
+ return false
+ elseif access == "protected" and protected then
+ return false
+ end
+ return true
+end
+
+minetest.register_node("techage:ta4_button_2x", {
+ description = S("TA4 2x Button"),
+ inventory_image = 'techage_smartline_button_2x.png',
+ tiles = {'techage_smartline_button_2x.png'},
+ drawtype = "nodebox",
+ paramtype = "light",
+ use_texture_alpha = "clip",
+ sunlight_propagates = true,
+ paramtype2 = "facedir",
+ node_box = {
+ type = "fixed",
+ fixed = lcd_box,
+ },
+ light_source = 6,
+
+ display_entities = {
+ ["techage:display_entity"] = { depth = 0.48,
+ on_display_update = button_update},
+ },
+
+ after_place_node = function(pos, placer)
+ local number = techage.add_node(pos, "techage:ta4_button_2x")
+ local meta = minetest.get_meta(pos)
+ meta:set_string("node_number", number)
+ meta:set_string("owner", placer:get_player_name())
+ meta:set_string("infotext", "TA4 2x Button " .. number)
+ meta:set_string("type", "button")
+ meta:set_string("label1", "B1")
+ meta:set_string("label2", "B2")
+ lcdlib.update_entities(pos)
+ end,
+
+ on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
+ if clicker and clicker:is_player() then
+ -- Check access settings
+ if not can_access(pos, clicker) then
+ return
+ end
+
+ local num = get_button_num(pos, clicker, pointed_thing)
+ if num then
+ local typ = M(pos):get_string("type")
+ if typ == "switch" then
+ local nvm = techage.get_nvm(pos)
+ nvm.button = nvm.button or {}
+ if nvm.button[num] then
+ switch_off(pos, num)
+ send_cmnd(pos, num, "off")
+ else
+ switch_on(pos, num)
+ send_cmnd(pos, num, "on")
+ end
+ else
+ switch_on(pos, num)
+ send_cmnd(pos, num)
+ minetest.after(0.5, switch_off, pos, num)
+ end
+ minetest.sound_play("techage_button", {
+ pos = pos,
+ gain = 0.5,
+ max_hear_distance = 5,
+ })
+ end
+ end
+ end,
+
+ ta_after_formspec = function(pos, fields, playername)
+ lcdlib.update_entities(pos)
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ end,
+
+ ta3_formspec = WRENCH_MENU,
+ 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 = "techage:ta4_button_2x",
+ recipe = {
+ {"", "", ""},
+ {"", "techage:ta4_button_off", "techage:ta4_button_off"},
+ {"", "", ""},
+ },
+})
diff --git a/techage/logic/button_4x.lua b/techage/logic/button_4x.lua
index 56ef4ea..7377265 100644
--- a/techage/logic/button_4x.lua
+++ b/techage/logic/button_4x.lua
@@ -195,6 +195,21 @@ end
local lcd_box = {-8/16, -8/16, 7.75/16, 8/16, 8/16, 8/16}
+local function can_access(pos, player)
+ local meta = M(pos)
+ local playername = player:get_player_name()
+ local access = meta:get_string("access")
+ local owner = meta:get_string("owner")
+ local protected = minetest.is_protected(pos, playername)
+
+ if access == "private" and playername ~= owner then
+ return false
+ elseif access == "protected" and protected then
+ return false
+ end
+ return true
+end
+
minetest.register_node("techage:ta4_button_4x", {
description = S("TA4 4x Button"),
inventory_image = 'techage_smartline_button_4x.png',
@@ -231,17 +246,11 @@ minetest.register_node("techage:ta4_button_4x", {
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
if clicker and clicker:is_player() then
- local playername = clicker:get_player_name()
- if minetest.is_protected(pos, playername) then
+ -- Check access settings
+ if not can_access(pos, clicker) then
return
end
- -- Check node settings in addition
- local access = M(pos):get_string("access")
- local owner = M(pos):get_string("owner")
- if access == "private" and playername ~= owner then
- return
- end
-
+
local num = get_button_num(pos, clicker, pointed_thing)
if num then
local typ = M(pos):get_string("type")
diff --git a/techage/logic/lib.lua b/techage/logic/lib.lua
index 86a99fe..1d21911 100644
--- a/techage/logic/lib.lua
+++ b/techage/logic/lib.lua
@@ -102,4 +102,4 @@ function techage.logic.set_numbers(pos, numbers, player_name, descr)
return true
end
return false
-end
\ No newline at end of file
+end
diff --git a/techage/logic/mba_detector.lua b/techage/logic/mba_detector.lua
new file mode 100644
index 0000000..8947676
--- /dev/null
+++ b/techage/logic/mba_detector.lua
@@ -0,0 +1,100 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2017-2020 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Mapblock Active Detector
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local S = techage.S
+
+local logic = techage.logic
+
+minetest.register_node("techage:ta4_mbadetector", {
+ description = "TA4 Mapblock Active Detector",
+ inventory_image = 'techage_smartline_mba_detector_inv.png',
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_smartline.png",
+ "techage_smartline.png",
+ "techage_smartline.png",
+ "techage_smartline.png",
+ "techage_smartline.png",
+ "techage_smartline.png^techage_smartline_mba_detector.png",
+ },
+
+ drawtype = "nodebox",
+ node_box = {
+ type = "fixed",
+ fixed = {
+ { -6/32, -6/32, 14/32, 6/32, 6/32, 16/32},
+ },
+ },
+
+ after_place_node = function(pos, placer)
+ local meta = M(pos)
+ logic.after_place_node(pos, placer, "techage:ta4_mbadetector", S("TA4 Mapblock Active Detector"))
+ logic.infotext(meta, S("TA4 Mapblock Active Detector"))
+ minetest.get_node_timer(pos):start(1)
+ end,
+
+ on_timer = function(pos, elapsed)
+ local mem = techage.get_mem(pos)
+ mem.gametime = minetest.get_gametime()
+ return true
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata, digger)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ techage.del_mem(pos)
+ end,
+
+ paramtype = "light",
+ sunlight_propagates = true,
+ paramtype2 = "facedir",
+ groups = {choppy=2, cracky=2, crumbly=2},
+ is_ground_content = false,
+ sounds = default.node_sound_metal_defaults(),
+})
+
+minetest.register_craft({
+ output = "techage:ta4_mbadetector",
+ recipe = {
+ {"", "group:wood", "default:mese_crystal"},
+ {"", "techage:vacuum_tube", "default:copper_ingot"},
+ {"", "group:wood", ""},
+ },
+})
+
+techage.register_node({"techage:ta4_mbadetector"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ if topic == "state" then
+ if minetest.compare_block_status then
+ if minetest.compare_block_status(pos, "active") then
+ return "on"
+ else
+ return "off"
+ end
+ else
+ local mem = techage.get_mem(pos)
+ local res = mem.gametime and mem.gametime > (minetest.get_gametime() - 2)
+ return res and "on" or "off"
+ end
+ else
+ return "unsupported"
+ end
+ end,
+ on_node_load = function(pos)
+ minetest.get_node_timer(pos):start(1)
+ end,
+ }
+)
+
diff --git a/techage/logic/movecontroller.lua b/techage/logic/movecontroller.lua
deleted file mode 100644
index 55939ee..0000000
--- a/techage/logic/movecontroller.lua
+++ /dev/null
@@ -1,812 +0,0 @@
---[[
-
- TechAge
- =======
-
- Copyright (C) 2020-2021 Joachim Stolberg
-
- AGPL v3
- See LICENSE.txt for more information
-
- TA4 Move Controller
-
-]]--
-
--- for lazy programmers
-local M = minetest.get_meta
-local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
-local S2P = minetest.string_to_pos
-local S = techage.S
-
--------------------------------------------------------------------------------
--- Entity / Move / Attach / Detach
--------------------------------------------------------------------------------
-local MIN_SPEED = 0.4
-local MAX_SPEED = 8
-
-local function to_vector(s)
- local x,y,z = unpack(string.split(s, ","))
- if x and y and z then
- return {
- x=tonumber(x) or 0,
- y=tonumber(y) or 0,
- z=tonumber(z) or 0,
- }
- end
- return {x=0, y=0, z=0}
-end
-
--- Only the ID ist stored, not the object
-local function get_object_id(object)
- for id, entity in pairs(minetest.luaentities) do
- if entity.object == object then
- return id
- end
- end
-end
-
--- determine exact position of attached entities
-local function obj_pos(obj)
- local _, _, pos = obj:get_attach()
- pos = vector.divide(pos, 29)
- return vector.add(obj:get_pos(), pos)
-end
-
--- Check access conflicts with other mods
-local function lock_player(player)
- local meta = player:get_meta()
- if meta:get_int("player_physics_locked") == 0 then
- meta:set_int("player_physics_locked", 1)
- meta:set_string("player_physics_locked_by", "ta_movecontroller")
- return true
- end
- return false
-end
-
-local function unlock_player(player)
- local meta = player:get_meta()
- if meta:get_int("player_physics_locked") == 1 then
- if meta:get_string("player_physics_locked_by") == "ta_movecontroller" then
- meta:set_int("player_physics_locked", 0)
- meta:set_string("player_physics_locked_by", "")
- return true
- end
- end
- return false
-end
-
-local function detach_player(player)
- local pos = obj_pos(player)
- player:set_detach()
- player:set_properties({visual_size = {x=1, y=1}})
- player:set_pos(pos)
- -- TODO: move to save position
-end
-
-
--- Attach player/mob to given parent object (block)
-local function attach_single_object(parent, obj, dir)
- local self = parent:get_luaentity()
- local rot = obj:get_rotation()
- local res = obj:get_attach()
- if not res then
- local offs = table.copy(dir)
- dir = vector.multiply(dir, 29)
- obj:set_attach(parent, "", dir, rot, true)
- obj:set_properties({visual_size = {x=2.9, y=2.9}})
- if obj:is_player() then
- if lock_player(obj) then
- table.insert(self.players, {name = obj:get_player_name(), offs = offs})
- end
- else
- table.insert(self.entities, {objID = get_object_id(obj), offs = offs})
- end
- end
-end
-
--- Attach all objects around to the parent object
--- offs is the search/attach position offset
-local function attach_objects(pos, offs, parent)
- local pos1 = vector.add(pos, offs)
- for _, obj in pairs(minetest.get_objects_inside_radius(pos1, 0.9)) do
- local dir = vector.subtract(obj:get_pos(), pos)
- local entity = obj:get_luaentity()
- if entity then
- if entity.name == "__builtin:item" then -- dropped items
- --obj:set_attach(objref, "", {x=0, y=0, z=0}, {x=0, y=0, z=0}, true) -- hier kracht es
- elseif entity.name ~= "techage:move_item" then
- attach_single_object(parent, obj, dir)
- end
- elseif obj:is_player() then
- attach_single_object(parent, obj, dir)
- end
- end
-end
-
--- Detach all attached objects from the parent object
-local function detach_objects(pos, self)
- for _, item in ipairs(self.entities or {}) do
- local entity = minetest.luaentities[item.objID]
- if entity then
- local obj = entity.object
- obj:set_detach()
- obj:set_properties({visual_size = {x=1, y=1}})
- local pos1 = vector.add(pos, item.offs)
- obj:set_pos(pos1)
- end
- end
- for _, item in ipairs(self.players or {}) do
- local obj = minetest.get_player_by_name(item.name)
- if obj then
- obj:set_detach()
- obj:set_properties({visual_size = {x=1, y=1}})
- local pos1 = vector.add(pos, item.offs)
- obj:set_pos(pos1)
- unlock_player(obj)
- end
- end
- self.entities = {}
- self.players = {}
-end
-
-local function entity_to_node(pos, obj)
- local self = obj:get_luaentity()
- if self then
- local name = self.item or "air"
- local metadata = self.metadata or {}
- local rot = obj:get_rotation()
- detach_objects(pos, self)
- obj:remove()
-
- pos = vector.round(pos)
- local dir = minetest.yaw_to_dir(rot.y or 0)
- local param2 = minetest.dir_to_facedir(dir) or 0
- local node = minetest.get_node(pos)
- local ndef1 = minetest.registered_nodes[name]
- local ndef2 = minetest.registered_nodes[node.name]
- if ndef1 and ndef2 then
- if ndef2.buildable_to then
- local meta = M(pos)
- minetest.set_node(pos, {name=name, param2=param2})
- meta:from_table(metadata)
- meta:set_string("ta_move_block", "")
- return
- end
- local meta = M(pos)
- if not meta:contains("ta_move_block") then
- meta:set_string("ta_move_block", minetest.serialize({name=name, param2=param2}))
- return
- end
- minetest.add_item(pos, ItemStack(name))
- elseif ndef1 then
- minetest.add_item(pos, ItemStack(name))
- end
- end
-end
-
-local function node_to_entity(pos, handover)
- local meta = M(pos)
- local node, metadata
-
- if meta:contains("ta_move_block") then
- node = minetest.deserialize(meta:get_string("ta_move_block"))
- metadata = {}
- meta:set_string("ta_move_block", "")
- else
- node = minetest.get_node(pos)
- meta:set_string("ta_move_block", "")
- metadata = meta:to_table()
- minetest.remove_node(pos)
- end
- local dir = minetest.facedir_to_dir(node.param2)
- local yaw = minetest.dir_to_yaw(dir)
- local obj = minetest.add_entity(pos, "techage:move_item")
- if obj then
- local self = obj:get_luaentity()
- obj:set_rotation({x=0, y=yaw, z=0})
- obj:set_properties({wield_item=node.name})
- obj:set_armor_groups({immortal=1})
- self.item = node.name
- self.metadata = metadata or {}
- self.handover = handover
- self.start_pos = table.copy(pos)
- return obj
- end
-end
-
-local function capture_entity(pos)
- local l = minetest.get_objects_in_area(pos, pos)
- for _, obj in ipairs(l) do
- local self = obj:get_luaentity()
- if self and self.name == "techage:move_item" then
- return obj
- end
- end
-end
-
--- move block direction
-local function determine_dir(pos1, pos2)
- local vdist = vector.subtract(pos2, pos1)
- local ndist = vector.length(vdist)
- return vector.divide(vdist, ndist)
-end
-
-local function move_entity(obj, pos2, dir, max_speed)
- local self = obj:get_luaentity()
- self.max_speed = max_speed
- self.dest_pos = table.copy(pos2)
- self.dir = dir
- local acc = vector.multiply(dir, max_speed / 2)
- obj:set_acceleration(acc)
-end
-
--- Handover the entity to the next movecontroller
-local function handover_to(pos, self)
- local info = techage.get_node_info(self.handover)
- if info and info.name == "techage:ta4_movecontroller" then
- local mem = techage.get_mem(info.pos)
- if not mem.entities_are_there then
- mem.entities_are_there = true
- -- copy move direction
- --print("techage.get_nvm(pos).pos_2to1", techage.get_nvm(pos).pos_2to1)
- techage.get_nvm(info.pos).pos_2to1 = techage.get_nvm(pos).pos_2to1
- minetest.after(0.2, techage.send_single, "0", self.handover, "handover")
- end
- return true
- end
-end
-
-minetest.register_entity("techage:move_item", {
- initial_properties = {
- pointable = true,
- makes_footstep_sound = true,
- static_save = true,
- collide_with_objects = false,
- physical = false,
- visual = "wielditem",
- wield_item = "default:dirt",
- visual_size = {x=0.67, y=0.67, z=0.67},
- selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
- },
-
- get_staticdata = function(self)
- return minetest.serialize({
- item = self.item,
- max_speed = self.max_speed,
- dest_pos = self.dest_pos,
- start_pos = self.start_pos,
- dir = self.dir,
- metadata = self.metadata,
- respawn = true,
- })
- end,
-
- on_activate = function(self, staticdata)
- if staticdata then
- local tbl = minetest.deserialize(staticdata) or {}
- self.item = tbl.item or "air"
- self.max_speed = tbl.max_speed or MAX_SPEED
- self.dest_pos = tbl.dest_pos or self.object:get_pos()
- self.start_pos = tbl.start_pos or self.object:get_pos()
- self.dir = tbl.dir or {x=0, y=0, z=0}
- self.metadata = tbl.metadata or {}
- self.object:set_properties({wield_item = self.item})
- if tbl.respawn then
- entity_to_node(self.start_pos, self.object)
- end
- end
- end,
-
- on_step = function(self, dtime, moveresult)
- if self.dest_pos then
- local obj = self.object
- local pos = obj:get_pos()
- local dist = vector.distance(pos, self.dest_pos)
- local speed = vector.length(obj:get_velocity())
-
- -- Landing
- if dist < 0.05 then
- obj:move_to(self.dest_pos, true)
- obj:set_acceleration({x=0, y=0, z=0})
- obj:set_velocity({x=0, y=0, z=0})
- self.dest_pos = nil
- if not self.handover or not handover_to(pos, self) then
- minetest.after(0.5, entity_to_node, pos, obj)
- end
- self.ttl = 2
- return
- end
-
- -- Braking or limit max speed
- if speed > (dist * 2) or speed > self.max_speed then
- local speed = math.min(speed, math.max(dist * 2, MIN_SPEED))
- local vel = vector.multiply(self.dir,speed)
- obj:set_velocity(vel)
- obj:set_acceleration({x=0, y=0, z=0})
- end
- elseif self.ttl then
- self.ttl = self.ttl - dtime
- if self.ttl < 0 then
- local obj = self.object
- local pos = obj:get_pos()
- entity_to_node(pos, obj)
- end
- end
- end,
-
-})
-
--------------------------------------------------------------------------------
--- Marker / Record
--------------------------------------------------------------------------------
-local MarkedNodes = {} -- t[player] = {{entity, pos},...}
-local CurrentPos -- to mark punched entities
-local SimpleNodes = techage.logic.SimpleNodes
-
-local function is_valid_dest(pos)
- local node = minetest.get_node(pos)
- local ndef = minetest.registered_nodes[node.name]
- if ndef and ndef.buildable_to then
- return true
- end
- if not M(pos):contains("ta_move_block") then
- return true
- end
- return false
-end
-
-local function is_simple_node(pos)
- -- special handling
- local name = minetest.get_node(pos).name
- if SimpleNodes[name] ~= nil then
- return SimpleNodes[name]
- end
-
- local ndef = minetest.registered_nodes[name]
- if not ndef or name == "air" or name == "ignore" then return false end
- -- don't remove nodes with some intelligence or undiggable nodes
- if ndef.drop == "" then return false end
- if ndef.diggable == false then return false end
- if ndef.after_dig_node then return false end
-
- return true
-end
-
-local function table_add(tbl, offs)
- if not tbl or not offs then return end
-
- local tbl2 = {}
- for _, v in ipairs(tbl) do
- tbl2[#tbl2 + 1] = vector.add(v, offs)
- end
- return tbl2
-end
-
-local function unmark_position(name, pos)
- pos = vector.round(pos)
- for idx,item in ipairs(MarkedNodes[name] or {}) do
- if vector.equals(pos, item.pos) then
- item.entity:remove()
- table.remove(MarkedNodes[name], idx)
- CurrentPos = pos
- return
- end
- end
-end
-
-local function unmark_all(name)
- for _,item in ipairs(MarkedNodes[name] or {}) do
- item.entity:remove()
- end
- MarkedNodes[name] = nil
-end
-
-local function mark_position(name, pos)
- MarkedNodes[name] = MarkedNodes[name] or {}
- pos = vector.round(pos)
- if not CurrentPos or not vector.equals(pos, CurrentPos) then -- entity not punched?
- local entity = minetest.add_entity(pos, "techage:moveblock_marker")
- if entity ~= nil then
- entity:get_luaentity().player_name = name
- table.insert(MarkedNodes[name], {pos = pos, entity = entity})
- end
- CurrentPos = nil
- return true
- end
- CurrentPos = nil
-end
-
-local function get_poslist(name)
- local idx = 0
- local lst = {}
- for _,item in ipairs(MarkedNodes[name] or {}) do
- table.insert(lst, item.pos)
- idx = idx + 1
- if idx >= 16 then break end
- end
- return lst
-end
-
-minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing)
- if puncher and puncher:is_player() then
- local name = puncher:get_player_name()
-
- if not MarkedNodes[name] then
- return
- end
-
- mark_position(name, pointed_thing.under)
- end
-end)
-
-
-minetest.register_entity(":techage:moveblock_marker", {
- initial_properties = {
- visual = "cube",
- textures = {
- "techage_cube_mark.png",
- "techage_cube_mark.png",
- "techage_cube_mark.png",
- "techage_cube_mark.png",
- "techage_cube_mark.png",
- "techage_cube_mark.png",
- },
- --use_texture_alpha = true,
- physical = false,
- visual_size = {x=1.1, y=1.1},
- collisionbox = {-0.55,-0.55,-0.55, 0.55,0.55,0.55},
- glow = 8,
- },
- on_step = function(self, dtime)
- self.ttl = (self.ttl or 2400) - 1
- if self.ttl <= 0 then
- local pos = self.object:get_pos()
- unmark_position(self.player_name, pos)
- end
- end,
- on_punch = function(self, hitter)
- local pos = self.object:get_pos()
- local name = hitter:get_player_name()
- if name == self.player_name then
- unmark_position(name, pos)
- end
- end,
-})
-
--------------------------------------------------------------------------------
--- TA4 Move Controller
--------------------------------------------------------------------------------
-local WRENCH_MENU = {
- {
- type = "dropdown",
- choices = "0.5,1,2,4,6,8",
- name = "max_speed",
- label = S("Maximum Speed"),
- tooltip = S("Maximum speed for the moving block."),
- default = "8",
- },
- {
- type = "number",
- name = "handoverB",
- label = S("Handover to B"),
- tooltip = S("Number of the next movecontroller."),
- default = "",
- },
- {
- type = "number",
- name = "handoverA",
- label = S("Handover to A"),
- tooltip = S("Number of the previous movecontroller."),
- default = "",
- },
- {
- type = "float",
- name = "height",
- label = S("Move block height"),
- tooltip = S("Value in the range of 0.0 to 1.0"),
- default = "1.0",
- },
-}
-
-local function formspec(nvm, meta)
- local status = meta:get_string("status")
- local distance = meta:contains("distance") and meta:get_string("distance") or "0,3,0"
- return "size[8,5]" ..
- default.gui_bg ..
- default.gui_bg_img ..
- default.gui_slots ..
- "box[0,-0.1;7.2,0.5;#c6e8ff]" ..
- "label[0.2,-0.1;" .. minetest.colorize( "#000000", S("TA4 Move Controller")) .. "]" ..
- techage.wrench_image(7.4, -0.05) ..
- "button[0.1,0.8;3.8,1;record;" .. S("Record") .. "]" ..
- "button[4.1,0.8;3.8,1;ready;" .. S("Done") .. "]" ..
- "field[0.4,2.5;3.8,1;distance;" .. S("Move distance (A to B)") .. ";" .. distance .. "]" ..
- "button[4.1,2.2;3.8,1;store;" .. S("Store") .. "]" ..
- "button[0.1,3.3;3.8,1;moveAB;" .. S("Move A-B") .. "]" ..
- "button[4.1,3.3;3.8,1;moveBA;" .. S("Move B-A") .. "]" ..
- "label[0.3,4.3;" .. status .. "]"
-end
-
-local function move_node(pos, pos1, pos2, max_speed, handover, height)
- local meta = M(pos)
- local dir = determine_dir(pos1, pos2)
- local obj = node_to_entity(pos1, handover)
- local self = obj:get_luaentity()
- self.players = {}
- self.entities = {}
-
- if obj then
- local offs = {x=0, y=height or 1, z=0}
- attach_objects(pos1, offs, obj)
- if dir.y == 0 then
- if (dir.x ~= 0 and dir.z == 0) or (dir.x == 0 and dir.z ~= 0) then
- attach_objects(pos1, dir, obj)
- end
- end
- move_entity(obj, pos2, dir, max_speed)
- end
-end
-
-local function move_nodes(pos, lpos1, lpos2, handover)
- local meta = M(pos)
- local owner = meta:get_string("owner")
- local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED
- local height = meta:contains("height") and meta:get_float("height") or 1
- height = techage.in_range(height, 0, 1)
-
- if #lpos1 == #lpos2 then
- for idx = 1, #lpos1 do
- local pos1 = lpos1[idx]
- local pos2 = lpos2[idx]
- if not minetest.is_protected(pos1, owner) and not minetest.is_protected(pos2, owner) then
- if is_simple_node(pos1) and is_valid_dest(pos2) then
- move_node(pos, pos1, pos2, max_speed, handover, height)
- else
- if not is_simple_node(pos1) then
- meta:set_string("status", S("No valid node at the start position"))
- else
- meta:set_string("status", S("No valid destination position"))
- end
- end
- else
- if minetest.is_protected(pos1, owner) then
- meta:set_string("status", S("Start position is protected"))
- else
- meta:set_string("status", S("Destination position is protected"))
- end
- return false
- end
- end
- else
- meta:set_string("status", S("Position list error"))
- return false
- end
- local info = techage.get_node_info(handover)
- if info and info.name == "techage:ta4_movecontroller" then
- local mem = techage.get_mem(info.pos)
- mem.num_entities = #lpos1
- end
- return true
-end
-
-local function moveon_nodes(pos, lpos1, lpos2, handover)
- local meta = M(pos)
- local owner = meta:get_string("owner")
- local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED
-
- if #lpos1 == #lpos2 then
- for idx = 1, #lpos1 do
- local pos1 = lpos1[idx]
- local pos2 = lpos2[idx]
- if not minetest.is_protected(pos1, owner) and not minetest.is_protected(pos2, owner) then
- if is_valid_dest(pos2) then
- local dir = determine_dir(pos1, pos2)
- local obj = capture_entity(pos1)
- if obj then
- obj:get_luaentity().handover = handover
- move_entity(obj, pos2, dir, max_speed)
- end
- else
- if not is_simple_node(pos1) then
- meta:set_string("status", S("No valid node at the start position"))
- else
- meta:set_string("status", S("No valid destination position"))
- end
- end
- else
- if minetest.is_protected(pos1, owner) then
- meta:set_string("status", S("Start position is protected"))
- else
- meta:set_string("status", S("Destination position is protected"))
- end
- return false
- end
- end
- else
- meta:set_string("status", S("Position list error"))
- return false
- end
- local info = techage.get_node_info(handover)
- if info and info.name == "techage:ta4_movecontroller" then
- local mem = techage.get_mem(info.pos)
- mem.num_entities = #lpos1
- end
- return true
-end
-
-local function move_to_other_pos(pos)
- local meta = M(pos)
- local nvm = techage.get_nvm(pos)
-
- if nvm.pos_2to1 then
- local lpos1 = nvm.lpos1 or {}
- local lpos2 = nvm.lpos2 or {}
- nvm.pos_2to1 = false
- local handover = meta:contains("handoverA") and meta:get_string("handoverA")
- return move_nodes(pos, lpos2, lpos1, handover)
- else
- local lpos1 = nvm.lpos1 or {}
- local lpos2 = nvm.lpos2 or {}
- nvm.pos_2to1 = true
- local handover = meta:contains("handoverB") and meta:get_string("handoverB")
- return move_nodes(pos, lpos1, lpos2, handover)
- end
-end
-
-local function takeover(pos)
- local meta = M(pos)
- local nvm = techage.get_nvm(pos)
- local mem = techage.get_mem(pos)
- mem.entities_are_there = nil
-
- if nvm.pos_2to1 then
- local lpos1 = nvm.lpos1 or {}
- local lpos2 = nvm.lpos2 or {}
- nvm.pos_2to1 = false
- local handover = meta:contains("handoverA") and meta:get_string("handoverA")
- return moveon_nodes(pos, lpos2, lpos1, handover)
- else
- local lpos1 = nvm.lpos1 or {}
- local lpos2 = nvm.lpos2 or {}
- nvm.pos_2to1 = true
- local handover = meta:contains("handoverB") and meta:get_string("handoverB")
- return moveon_nodes(pos, lpos1, lpos2, handover)
- end
-end
-
-minetest.register_node("techage:ta4_movecontroller", {
- description = S("TA4 Move Controller"),
- tiles = {
- -- up, down, right, left, back, front
- "techage_filling_ta4.png^techage_frame_ta4_top.png",
- "techage_filling_ta4.png^techage_frame_ta4_top.png",
- "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_movecontroller.png",
- },
-
- after_place_node = function(pos, placer, itemstack)
- local meta = M(pos)
- techage.logic.after_place_node(pos, placer, "techage:ta4_movecontroller", S("TA4 Move Controller"))
- techage.logic.infotext(meta, S("TA4 Move Controller"))
- local nvm = techage.get_nvm(pos)
- meta:set_string("formspec", formspec(nvm, meta))
- end,
-
- on_receive_fields = function(pos, formname, fields, player)
- if minetest.is_protected(pos, player:get_player_name()) then
- return
- end
-
- local meta = M(pos)
- local nvm = techage.get_nvm(pos)
-
- if fields.record then
- nvm.lpos1 = nil
- nvm.lpos2 = nil
- nvm.pos_2to1 = false
- meta:set_string("status", S("Recording..."))
- local name = player:get_player_name()
- minetest.chat_send_player(name, S("Click on all blocks that shall be moved"))
- MarkedNodes[name] = {}
- meta:set_string("formspec", formspec(nvm, meta))
- elseif fields.ready then
- local name = player:get_player_name()
- local pos_list = get_poslist(name)
- local text = #pos_list.." "..S("block positions are stored.")
- meta:set_string("status", text)
- meta:set_string("distance", fields.distance)
- nvm.lpos1 = pos_list
- nvm.lpos2 = table_add(pos_list, to_vector(fields.distance))
- nvm.pos_2to1 = false
- unmark_all(name)
- meta:set_string("formspec", formspec(nvm, meta))
- elseif fields.store then
- local dist = to_vector(fields.distance)
- local l = math.hypot(dist.x, math.hypot(dist.y, dist.z))
- if l <= 100 then
- meta:set_string("distance", fields.distance)
- nvm.lpos2 = table_add(nvm.lpos1, to_vector(fields.distance))
- nvm.pos_2to1 = false
- else
- meta:set_string("status", S("Error: Distance > 100 m !!"))
- end
- meta:set_string("formspec", formspec(nvm, meta))
- elseif fields.moveAB then
- meta:set_string("status", "")
- nvm.pos_2to1 = false
- if move_to_other_pos(pos) then
- meta:set_string("formspec", formspec(nvm, meta))
- local name = player:get_player_name()
- MarkedNodes[name] = nil
- end
- elseif fields.moveBA then
- meta:set_string("status", "")
- nvm.pos_2to1 = true
- if move_to_other_pos(pos) then
- meta:set_string("formspec", formspec(nvm, meta))
- local name = player:get_player_name()
- MarkedNodes[name] = nil
- end
- end
- end,
-
-
- after_dig_node = function(pos, oldnode, oldmetadata, digger)
- local name = digger:get_player_name()
- unmark_all(name)
- techage.remove_node(pos, oldnode, oldmetadata)
- end,
-
- ta4_formspec = WRENCH_MENU,
- paramtype2 = "facedir",
- groups = {choppy=2, cracky=2, crumbly=2},
- is_ground_content = false,
- sounds = default.node_sound_wood_defaults(),
-})
-
-local INFO = [[Commands: 'a2b', 'b2a', 'move']]
-
-techage.register_node({"techage:ta4_movecontroller"}, {
- on_recv_message = function(pos, src, topic, payload)
- if topic == "info" then
- return INFO
- elseif topic == "a2b" then
- local nvm = techage.get_nvm(pos)
- nvm.pos_2to1 = false
- return move_to_other_pos(pos)
- elseif topic == "b2a" then
- local nvm = techage.get_nvm(pos)
- nvm.pos_2to1 = true
- return move_to_other_pos(pos)
- elseif topic == "move" then
- return move_to_other_pos(pos)
- elseif topic == "handover" then
- return takeover(pos)
- end
- return false
- end,
-})
-
-minetest.register_craft({
- output = "techage:ta4_movecontroller",
- recipe = {
- {"default:steel_ingot", "dye:blue", "default:steel_ingot"},
- {"default:mese_crystal_fragment", "techage:ta4_wlanchip", "default:mese_crystal_fragment"},
- {"group:wood", "basic_materials:gear_steel", "group:wood"},
- },
-})
-
-minetest.register_on_joinplayer(function(player)
- unlock_player(player)
-end)
-
-minetest.register_on_leaveplayer(function(player)
- if unlock_player(player) then
- detach_player(player)
- end
-end)
-
-minetest.register_on_dieplayer(function(player)
- if unlock_player(player) then
- detach_player(player)
- end
-end)
diff --git a/techage/logic/sequencer2.lua b/techage/logic/sequencer2.lua
index 0b717c7..fe407fe 100644
--- a/techage/logic/sequencer2.lua
+++ b/techage/logic/sequencer2.lua
@@ -95,7 +95,7 @@ local function compile(s, tRes)
return exception(tRes, i, "Order error!")
end
start_idx = start_idx or idx
- if old_idx ~= 0 and not tCode[old_idx].next_idx then
+ if old_idx ~= 0 and tCode[old_idx] and not tCode[old_idx].next_idx then
tCode[old_idx].next_idx = idx
end
if cmnd1 == "send" then
@@ -215,15 +215,12 @@ local function on_receive_fields(pos, formname, fields, player)
local mem = techage.get_mem(pos)
nvm.running = nvm.running or false
- print(1, dump(fields))
if fields.stop then
nvm.running = false
minetest.get_node_timer(pos):stop()
logic.infotext(meta, S("TA4 Sequencer"), S("stopped"))
elseif not nvm.running then
- print(2)
if fields.tab == "2" then
- print(3)
meta:set_string("formspec", formspec_help(meta))
return
elseif fields.tab == "1" then
diff --git a/techage/logic/signallamp_2x.lua b/techage/logic/signallamp_2x.lua
new file mode 100644
index 0000000..58ef893
--- /dev/null
+++ b/techage/logic/signallamp_2x.lua
@@ -0,0 +1,151 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2017-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Logic twofold signal lamp
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local S = techage.S
+
+local OFF = 0
+local RED = 1
+local GREEN = 2
+local AMBER = 3
+
+local WRENCH_MENU = {
+ {
+ type = "ascii",
+ name = "label1",
+ label = S("Label") .. " 1",
+ tooltip = S("Label for the lamp"),
+ default = "1",
+ },
+ {
+ type = "ascii",
+ name = "label2",
+ label = S("Label") .. " 2",
+ tooltip = S("Label for the lamp"),
+ default = "2",
+ },
+}
+
+local function lamp_update(pos, objref)
+ local meta = M(pos)
+ pos = vector.round(pos)
+ local nvm = techage.get_nvm(pos)
+ nvm.lamp = nvm.lamp or {}
+ local tbl = {" ", " ", meta:get_string("label1"), " ", meta:get_string("label2")}
+ local text = "< " .. table.concat(tbl, "\n< ")
+ local texture = lcdlib.make_multiline_texture("default", text, 96, 96, 7, "top", "#000", 6)
+
+ if nvm.lamp[1] == RED then
+ texture = texture .. "^techage_smartline_signal_red2.png"
+ elseif nvm.lamp[1] == GREEN then
+ texture = texture .. "^techage_smartline_signal_green2.png"
+ elseif nvm.lamp[1] == AMBER then
+ texture = texture .. "^techage_smartline_signal_amber2.png"
+ end
+
+ if nvm.lamp[2] == RED then
+ texture = texture .. "^techage_smartline_signal_red3.png"
+ elseif nvm.lamp[2] == GREEN then
+ texture = texture .. "^techage_smartline_signal_green3.png"
+ elseif nvm.lamp[2] == AMBER then
+ texture = texture .. "^techage_smartline_signal_amber3.png"
+ end
+
+ objref:set_properties({ textures = {texture}, visual_size = {x=1, y=1} })
+end
+
+local lcd_box = {-8/16, -4/16, 7.75/16, 8/16, 4/16, 8/16}
+
+minetest.register_node("techage:ta4_signallamp_2x", {
+ description = S("TA4 2x Signal Lamp"),
+ inventory_image = 'techage_smartline_signal_2x.png^techage_smartline_signal_green2.png^techage_smartline_signal_amber3.png',
+ tiles = {'techage_smartline_signal_2x.png'},
+ drawtype = "nodebox",
+ paramtype = "light",
+ use_texture_alpha = "clip",
+ sunlight_propagates = true,
+ paramtype2 = "facedir",
+ node_box = {
+ type = "fixed",
+ fixed = lcd_box,
+ },
+ light_source = 6,
+
+ display_entities = {
+ ["techage:display_entity"] = { depth = 0.48,
+ on_display_update = lamp_update},
+ },
+
+ after_place_node = function(pos, placer)
+ local number = techage.add_node(pos, "techage:ta4_signallamp_2x")
+ local meta = minetest.get_meta(pos)
+ meta:set_string("node_number", number)
+ meta:set_string("owner", placer:get_player_name())
+ meta:set_string("infotext", S("TA4 2x Signal Lamp") .. " " .. number)
+ local nvm = techage.get_nvm(pos)
+ nvm.lamp = {}
+ lcdlib.update_entities(pos)
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ end,
+
+ ta_after_formspec = function(pos, fields, playername)
+ lcdlib.update_entities(pos)
+ end,
+
+ ta3_formspec = WRENCH_MENU,
+ 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(),
+})
+
+techage.register_node({"techage:ta4_signallamp_2x"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ local nvm = techage.get_nvm(pos)
+ nvm.lamp = nvm.lamp or {}
+ if topic == "green" then
+ local num = math.min(tonumber(payload) or 0, 2)
+ nvm.lamp[num] = GREEN
+ lcdlib.update_entities(pos)
+ elseif topic == "amber" then
+ local num = math.min(tonumber(payload) or 0, 2)
+ nvm.lamp[num] = AMBER
+ lcdlib.update_entities(pos)
+ elseif topic == "red" then
+ local num = math.min(tonumber(payload) or 0, 2)
+ nvm.lamp[num] = RED
+ lcdlib.update_entities(pos)
+ elseif topic == "off" then
+ local num = math.min(tonumber(payload) or 0, 2)
+ nvm.lamp[num] = OFF
+ lcdlib.update_entities(pos)
+ end
+ end,
+})
+
+minetest.register_craft({
+ output = "techage:ta4_signallamp_2x",
+ recipe = {
+ {"", "techage:aluminum", "dye:blue"},
+ {"", "default:glass", "techage:ta4_wlanchip"},
+ {"", "techage:ta4_leds", "techage:ta4_leds"},
+ },
+})
diff --git a/techage/logic/signallamp_4x.lua b/techage/logic/signallamp_4x.lua
new file mode 100644
index 0000000..8edf379
--- /dev/null
+++ b/techage/logic/signallamp_4x.lua
@@ -0,0 +1,182 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2017-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Logic fourfold signal lamp
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local S = techage.S
+
+local OFF = 0
+local RED = 1
+local GREEN = 2
+local AMBER = 3
+
+local WRENCH_MENU = {
+ {
+ type = "ascii",
+ name = "label1",
+ label = S("Label") .. " 1",
+ tooltip = S("Label for the lamp"),
+ default = "1",
+ },
+ {
+ type = "ascii",
+ name = "label2",
+ label = S("Label") .. " 2",
+ tooltip = S("Label for the lamp"),
+ default = "2",
+ },
+ {
+ type = "ascii",
+ name = "label3",
+ label = S("Label") .. " 3",
+ tooltip = S("Label for the lamp"),
+ default = "3",
+ },
+ {
+ type = "ascii",
+ name = "label4",
+ label = S("Label") .. " 4",
+ tooltip = S("Label for the lamp"),
+ default = "4",
+ },
+}
+
+local function lamp_update(pos, objref)
+ local meta = M(pos)
+ pos = vector.round(pos)
+ local nvm = techage.get_nvm(pos)
+ nvm.lamp = nvm.lamp or {}
+ local tbl = {meta:get_string("label1"), " ", meta:get_string("label2"), " ", meta:get_string("label3"), " ", meta:get_string("label4")}
+ local text = "< " .. table.concat(tbl, "\n< ")
+ local texture = lcdlib.make_multiline_texture("default", text, 96, 96, 7, "top", "#000", 6)
+
+ if nvm.lamp[1] == RED then
+ texture = texture .. "^techage_smartline_signal_red1.png"
+ elseif nvm.lamp[1] == GREEN then
+ texture = texture .. "^techage_smartline_signal_green1.png"
+ elseif nvm.lamp[1] == AMBER then
+ texture = texture .. "^techage_smartline_signal_amber1.png"
+ end
+
+ if nvm.lamp[2] == RED then
+ texture = texture .. "^techage_smartline_signal_red2.png"
+ elseif nvm.lamp[2] == GREEN then
+ texture = texture .. "^techage_smartline_signal_green2.png"
+ elseif nvm.lamp[2] == AMBER then
+ texture = texture .. "^techage_smartline_signal_amber2.png"
+ end
+
+ if nvm.lamp[3] == RED then
+ texture = texture .. "^techage_smartline_signal_red3.png"
+ elseif nvm.lamp[3] == GREEN then
+ texture = texture .. "^techage_smartline_signal_green3.png"
+ elseif nvm.lamp[3] == AMBER then
+ texture = texture .. "^techage_smartline_signal_amber3.png"
+ end
+
+ if nvm.lamp[4] == RED then
+ texture = texture .. "^techage_smartline_signal_red4.png"
+ elseif nvm.lamp[4] == GREEN then
+ texture = texture .. "^techage_smartline_signal_green4.png"
+ elseif nvm.lamp[4] == AMBER then
+ texture = texture .. "^techage_smartline_signal_amber4.png"
+ end
+
+ objref:set_properties({ textures = {texture}, visual_size = {x=1, y=1} })
+end
+
+local lcd_box = {-8/16, -8/16, 7.75/16, 8/16, 8/16, 8/16}
+
+minetest.register_node("techage:ta4_signallamp_4x", {
+ description = S("TA4 4x Signal Lamp"),
+ inventory_image = 'techage_smartline_signal_4x.png^techage_smartline_signal_off1.png^techage_smartline_signal_green2.png^techage_smartline_signal_amber3.png^techage_smartline_signal_red4.png',
+ tiles = {'techage_smartline_signal_4x.png'},
+ drawtype = "nodebox",
+ paramtype = "light",
+ use_texture_alpha = "clip",
+ sunlight_propagates = true,
+ paramtype2 = "facedir",
+ node_box = {
+ type = "fixed",
+ fixed = lcd_box,
+ },
+ light_source = 6,
+
+ display_entities = {
+ ["techage:display_entity"] = { depth = 0.48,
+ on_display_update = lamp_update},
+ },
+
+ after_place_node = function(pos, placer)
+ local number = techage.add_node(pos, "techage:ta4_signallamp_4x")
+ local meta = minetest.get_meta(pos)
+ meta:set_string("node_number", number)
+ meta:set_string("owner", placer:get_player_name())
+ meta:set_string("infotext", S("TA4 4x Signal Lamp") .. " " .. number)
+ local nvm = techage.get_nvm(pos)
+ nvm.text = {"1", "", "2", "", "3", "", "4"}
+ nvm.lamp = {}
+ lcdlib.update_entities(pos)
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ end,
+
+ ta_after_formspec = function(pos, fields, playername)
+ lcdlib.update_entities(pos)
+ end,
+
+ ta3_formspec = WRENCH_MENU,
+ 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(),
+})
+
+techage.register_node({"techage:ta4_signallamp_4x"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ local nvm = techage.get_nvm(pos)
+ nvm.lamp = nvm.lamp or {}
+ if topic == "green" then
+ local num = math.min(tonumber(payload) or 0, 4)
+ nvm.lamp[num] = GREEN
+ lcdlib.update_entities(pos)
+ elseif topic == "amber" then
+ local num = math.min(tonumber(payload) or 0, 4)
+ nvm.lamp[num] = AMBER
+ lcdlib.update_entities(pos)
+ elseif topic == "red" then
+ local num = math.min(tonumber(payload) or 0, 4)
+ nvm.lamp[num] = RED
+ lcdlib.update_entities(pos)
+ elseif topic == "off" then
+ local num = math.min(tonumber(payload) or 0, 4)
+ nvm.lamp[num] = OFF
+ lcdlib.update_entities(pos)
+ end
+ end,
+})
+
+minetest.register_craft({
+ output = "techage:ta4_signallamp_4x",
+ recipe = {
+ {"", "techage:ta4_signallamp_2x", ""},
+ {"", "techage:ta4_signallamp_2x", ""},
+ {"", "", ""},
+ },
+})
diff --git a/techage/logic/terminal.lua b/techage/logic/terminal.lua
index 7bf483f..cf63084 100644
--- a/techage/logic/terminal.lua
+++ b/techage/logic/terminal.lua
@@ -3,7 +3,7 @@
Terminal
========
- Copyright (C) 2018-2020 Joachim Stolberg
+ Copyright (C) 2018-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@@ -15,22 +15,36 @@
local M = minetest.get_meta
local S = techage.S
-local HELP_TA3 = "Syntax:\n"..
-" cmd \n"..
-"\n"..
-"like: cmd 181 on\n"..
-"or: cmd 4573 state\n"..
-"\n"..
-"Local commands:\n"..
-"- clear = clear screen\n"..
-"- help = this message\n"..
-"- pub = switch to public use of buttons\n"..
-"- priv = switch to private use of buttons\n"..
-"To program a user button with a command:\n"..
-" set \n"..
-"e.g.: set 1 ON cmd 123 on"
+local HELP_TA3 = [[ #### TA3 Terminal ####
+Send commands to machines and output the results.
+Local commands:
+- Clear screen with 'clear'
+- Output this message with 'help'
+- Switch to public use of buttons with 'pub'
+- Switch to private use of buttons with 'priv'
+- Program a user button with
+ 'set '
+ Example: 'set 1 ON cmd 1234 on'
+- send a command with 'cmd '
+ Example: 'cmd 1234 on']]
-local CMNDS_TA3 = S("Syntax error, try help")
+local HELP_TA4 = [[ #### TA4 Terminal ####
+Send commands to machines and output the results.
+Local commands:
+- Clear screen with 'clear'
+- Output this message with 'help'
+- Switch to public use of buttons with 'pub'
+- Switch to private use of buttons with 'priv'
+- Program a user button with
+ 'set '
+ Example: 'set 1 ON cmd 1234 on'
+- send a command with 'cmd '
+ Example: 'cmd 1234 on'
+- Connect to a machine with 'connect '
+If connected, compact commands like 'status'
+are possible.]]
+
+local SYNTAX_ERR = S("Syntax error, try help")
local function get_string(meta, num, default)
local s = meta:get_string("bttn_text"..num)
@@ -54,24 +68,28 @@ local function formspec2(meta)
local bttn_text7 = get_string(meta, 7, "User7")
local bttn_text8 = get_string(meta, 8, "User8")
local bttn_text9 = get_string(meta, 9, "User9")
- return "size[10,8]"..
- default.gui_bg..
- default.gui_bg_img..
- default.gui_slots..
- "style_type[table,field;font=mono]"..
- "button[0,0;3.3,1;bttn1;"..bttn_text1.."]button[3.3,0;3.3,1;bttn2;"..bttn_text2.."]button[6.6,0;3.3,1;bttn3;"..bttn_text3.."]"..
- "button[0,0.8;3.3,1;bttn4;"..bttn_text4.."]button[3.3,0.8;3.3,1;bttn5;"..bttn_text5.."]button[6.6,0.8;3.3,1;bttn6;"..bttn_text6.."]"..
- "button[0,1.6;3.3,1;bttn7;"..bttn_text7.."]button[3.3,1.6;3.3,1;bttn8;"..bttn_text8.."]button[6.6,1.6;3.3,1;bttn9;"..bttn_text9.."]"..
- "table[0,2.5;9.8,4.7;output;"..output..";200]"..
- "field[0.4,7.7;7.6,1;cmnd;;"..command.."]" ..
+ return "size[10,8.5]"..
+ --"style_type[table,field;font=mono]"..
+ "button[0,-0.2;3.3,1;bttn1;"..bttn_text1.."]button[3.3,-0.2;3.3,1;bttn2;"..bttn_text2.."]button[6.6,-0.2;3.3,1;bttn3;"..bttn_text3.."]"..
+ "button[0,0.6;3.3,1;bttn4;"..bttn_text4.."]button[3.3,0.6;3.3,1;bttn5;"..bttn_text5.."]button[6.6,0.6;3.3,1;bttn6;"..bttn_text6.."]"..
+ "button[0,1.4;3.3,1;bttn7;"..bttn_text7.."]button[3.3,1.4;3.3,1;bttn8;"..bttn_text8.."]button[6.6,1.4;3.3,1;bttn9;"..bttn_text9.."]"..
+ "table[0,2.3;9.8,5.6;output;"..output..";200]"..
+ "field[0.4,8.2;7.6,1;cmnd;;"..command.."]" ..
"field_close_on_enter[cmnd;false]"..
- "button[7.9,7.4;2,1;ok;"..S("Enter").."]"
+ "button[7.9,7.9;2,1;ok;"..S("Enter").."]"
end
local function output(pos, text)
local meta = minetest.get_meta(pos)
text = meta:get_string("output") .. "\n" .. (text or "")
- text = text:sub(-500,-1)
+ text = text:sub(-1000,-1)
+ meta:set_string("output", text)
+ meta:set_string("formspec", formspec2(meta))
+end
+
+local function append(pos, text)
+ local meta = minetest.get_meta(pos)
+ text = meta:get_string("output") .. (text or "")
meta:set_string("output", text)
meta:set_string("formspec", formspec2(meta))
end
@@ -84,37 +102,146 @@ local function get_line_text(pos, num)
return line:gsub("^[%s$]*(.-)%s*$", "%1")
end
+local function server_debug(pos, command, player)
+ local cmnd, payload = command:match('^pipe%s+([%w_]+)%s*(.*)$')
+ if cmnd then
+ if not minetest.check_player_privs(player, "server") then
+ output(pos, "server privs missing")
+ return
+ end
+ local resp = techage.transfer(
+ pos,
+ "B", -- outdir
+ cmnd, -- topic
+ payload, -- payload
+ techage.LiquidPipe, -- network
+ nil) -- valid nodes
+ output(pos, dump(resp))
+ return true
+ end
+
+ cmnd, payload = command:match('^axle%s+([%w_]+)%s*(.*)$')
+ if cmnd then
+ if not minetest.check_player_privs(player, "server") then
+ output(pos, "server privs missing")
+ return
+ end
+ local resp = techage.transfer(
+ pos,
+ "B", -- outdir
+ cmnd, -- topic
+ payload, -- payload
+ techage.TA1Axle, -- network
+ nil) -- valid nodes
+ output(pos, dump(resp))
+ return true
+ end
+
+ cmnd, payload = command:match('^vtube%s+([%w_]+)%s*(.*)$')
+ if cmnd then
+ if not minetest.check_player_privs(player, "server") then
+ output(pos, "server privs missing")
+ return
+ end
+ local resp = techage.transfer(
+ pos,
+ "B", -- outdir
+ cmnd, -- topic
+ payload, -- payload
+ techage.VTube, -- network
+ nil) -- valid nodes
+ output(pos, dump(resp))
+ return true
+ end
+end
-local function command(pos, command, player)
+local function command(pos, command, player, is_ta4)
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner") or ""
- if command then
- command = command:sub(1,80)
- command = string.trim(command)
-
- if command == "clear" then
- meta:set_string("output", "")
- meta:set_string("formspec", formspec2(meta))
- elseif command == "help" then
- local meta = minetest.get_meta(pos)
- meta:set_string("output", HELP_TA3)
- meta:set_string("formspec", formspec2(meta))
- elseif command == "pub" then
- meta:set_int("public", 1)
- output(pos, player..":$ "..command)
- output(pos, S("Switched to public use!"))
- elseif command == "priv" then
- meta:set_int("public", 0)
- output(pos, player..":$ "..command)
- output(pos, S("Switched to private use!"))
+ command = command:sub(1,80)
+ command = string.trim(command)
+ local cmnd, data = command:match('^(%w+)%s*(.*)$')
+
+ if cmnd == "clear" then
+ meta:set_string("output", "")
+ meta:set_string("formspec", formspec2(meta))
+ elseif cmnd == "" then
+ output(pos, "$")
+ elseif cmnd == "help" then
+ if is_ta4 then
+ output(pos, HELP_TA4)
else
- output(pos, "$ "..command)
+ output(pos, HELP_TA3)
+ end
+ elseif cmnd == "pub" then
+ meta:set_int("public", 1)
+ output(pos, "$ "..command)
+ output(pos, "Switched to public buttons!")
+ elseif cmnd == "priv" then
+ meta:set_int("public", 0)
+ output(pos, "$ "..command)
+ output(pos, "Switched to private buttons!")
+ elseif cmnd == "connect" and data then
+ output(pos, "$ "..command)
+ if techage.not_protected(data, owner, owner) then
local own_num = meta:get_string("node_number")
- local num, cmnd, payload = command:match('^cmd%s+([0-9]+)%s+(%w+)%s*(.*)$')
- if num and cmnd then
- if techage.not_protected(num, owner, owner) then
- local resp = techage.send_single(own_num, num, cmnd, payload)
+ local resp = techage.send_single(own_num, data, cmnd)
+ if resp then
+ meta:set_string("connected_to", data)
+ output(pos, "Connected.")
+ else
+ meta:set_string("connected_to", "")
+ output(pos, "Not connected!")
+ end
+ else
+ output(pos, "Protection error!")
+ end
+ else
+ output(pos, "$ "..command)
+ local own_num = meta:get_string("node_number")
+ local connected_to = meta:contains("connected_to") and meta:get_string("connected_to")
+ local bttn_num, label, num, cmnd, payload
+
+ num, cmnd, payload = command:match('^cmd%s+([0-9]+)%s+(%w+)%s*(.*)$')
+ if num and cmnd then
+ if techage.not_protected(num, owner, owner) then
+ local resp = techage.send_single(own_num, num, cmnd, payload)
+ if type(resp) == "string" then
+ output(pos, resp)
+ else
+ output(pos, dump(resp))
+ end
+ end
+ return
+ end
+
+ num, cmnd = command:match('^turn%s+([0-9]+)%s+([onf]+)$')
+ if num and (cmnd == "on" or cmnd == "off") then
+ if techage.not_protected(num, owner, owner) then
+ local resp = techage.send_single(own_num, num, cmnd)
+ output(pos, dump(resp))
+ end
+ return
+ end
+
+ bttn_num, label, cmnd = command:match('^set%s+([1-9])%s+([%w_]+)%s+(.+)$')
+ if bttn_num and label and cmnd then
+ meta:set_string("bttn_text"..bttn_num, label)
+ meta:set_string("bttn_cmnd"..bttn_num, cmnd)
+ meta:set_string("formspec", formspec2(meta))
+ return
+ end
+
+ if server_debug(pos, command, player) then
+ return
+ end
+
+ if connected_to then
+ local cmnd, payload = command:match('^(%w+)%s*(.*)$')
+ if cmnd then
+ local resp = techage.send_single(own_num, connected_to, cmnd, payload)
+ if resp ~= true then
if type(resp) == "string" then
output(pos, resp)
else
@@ -123,59 +250,10 @@ local function command(pos, command, player)
end
return
end
- num, cmnd = command:match('^turn%s+([0-9]+)%s+([onf]+)$')
- if num and (cmnd == "on" or cmnd == "off") then
- if techage.not_protected(num, owner, owner) then
- local resp = techage.send_single(own_num, num, cmnd)
- output(pos, dump(resp))
- end
- return
- end
- local bttn_num, label, cmnd = command:match('^set%s+([1-9])%s+([%w_]+)%s+(.+)$')
- if bttn_num and label and cmnd then
- meta:set_string("bttn_text"..bttn_num, label)
- meta:set_string("bttn_cmnd"..bttn_num, cmnd)
- meta:set_string("formspec", formspec2(meta))
- return
- end
-
- local cmnd, payload = command:match('^pipe%s+([%w_]+)%s*(.*)$')
- if cmnd then
- if not minetest.check_player_privs(player, "server") then
- output(pos, "server privs missing")
- return
- end
- local resp = techage.transfer(
- pos,
- "B", -- outdir
- cmnd, -- topic
- payload, -- payload
- techage.LiquidPipe, -- network
- nil) -- valid nodes
- output(pos, dump(resp))
- return
- end
-
- local cmnd, payload = command:match('^axle%s+([%w_]+)%s*(.*)$')
- if cmnd then
- if not minetest.check_player_privs(player, "server") then
- output(pos, "server privs missing")
- return
- end
- local resp = techage.transfer(
- pos,
- "B", -- outdir
- cmnd, -- topic
- payload, -- payload
- techage.TA1Axle, -- network
- nil) -- valid nodes
- output(pos, dump(resp))
- return
- end
-
- if command ~= "" then
- output(pos, CMNDS_TA3)
- end
+ end
+
+ if command ~= "" then
+ output(pos, SYNTAX_ERR)
end
end
end
@@ -186,9 +264,9 @@ local function send_cmnd(pos, meta, num)
command(pos, cmnd, owner)
end
-local function register_terminal(num, tiles, node_box, selection_box)
- minetest.register_node("techage:terminal"..num, {
- description = S("TA3 Terminal"),
+local function register_terminal(name, description, tiles, node_box, selection_box)
+ minetest.register_node("techage:"..name, {
+ description = description,
tiles = tiles,
drawtype = "nodebox",
node_box = node_box,
@@ -201,7 +279,7 @@ local function register_terminal(num, tiles, node_box, selection_box)
meta:set_string("command", S("commands like: help"))
meta:set_string("formspec", formspec2(meta))
meta:set_string("owner", placer:get_player_name())
- meta:set_string("infotext", S("TA3 Terminal") .. " " .. number)
+ meta:set_string("infotext", description .. " " .. number)
end,
on_receive_fields = function(pos, formname, fields, player)
@@ -216,11 +294,21 @@ local function register_terminal(num, tiles, node_box, selection_box)
meta:set_string("command", s)
meta:set_string("formspec", formspec2(meta))
return
- elseif (fields.key_enter == "true" or fields.ok) and fields.cmnd ~= "" then
- command(pos, fields.cmnd, player:get_player_name())
+ elseif (fields.ok or fields.key_enter_field) and fields.cmnd then
+ local is_ta4 = string.find(description, "TA4")
+ command(pos, fields.cmnd, player:get_player_name(), is_ta4)
+ techage.historybuffer_add(pos, fields.cmnd)
meta:set_string("command", "")
meta:set_string("formspec", formspec2(meta))
return
+ elseif fields.key_up then
+ meta:set_string("command", techage.historybuffer_priv(pos))
+ meta:set_string("formspec", formspec2(meta))
+ return
+ elseif fields.key_down then
+ meta:set_string("command", techage.historybuffer_next(pos))
+ meta:set_string("formspec", formspec2(meta))
+ return
end
end
if public or not protected then
@@ -251,7 +339,7 @@ local function register_terminal(num, tiles, node_box, selection_box)
})
end
-register_terminal("2", {
+register_terminal("terminal2", S("TA3 Terminal"), {
-- up, down, right, left, back, front
'techage_terminal2_top.png',
'techage_terminal2_side.png',
@@ -277,7 +365,33 @@ register_terminal("2", {
fixed = {
{-12/32, -16/32, -4/32, 12/32, 6/32, 16/32},
},
- })
+ }
+)
+
+register_terminal("terminal3", S("TA4 Terminal"), {
+ -- up, down, right, left, back, front
+ 'techage_terminal1_top.png',
+ 'techage_terminal1_bottom.png',
+ 'techage_terminal1_side.png',
+ 'techage_terminal1_side.png',
+ 'techage_terminal1_bottom.png',
+ "techage_terminal1_front.png",
+ },
+ {
+ type = "fixed",
+ fixed = {
+ {-12/32, -16/32, -8/32, 12/32, -14/32, 12/32},
+ {-12/32, -14/32, 12/32, 12/32, 6/32, 14/32},
+ },
+ },
+ {
+ type = "fixed",
+ fixed = {
+ {-12/32, -16/32, -8/32, 12/32, -14/32, 12/32},
+ {-12/32, -14/32, 12/32, 12/32, 6/32, 14/32},
+ },
+ }
+)
minetest.register_craft({
output = "techage:terminal2",
@@ -288,6 +402,15 @@ minetest.register_craft({
},
})
+minetest.register_craft({
+ output = "techage:terminal3",
+ recipe = {
+ {"techage:basalt_glass_thin", "", ""},
+ {"techage:ta4_leds", "", ""},
+ {"techage:aluminum", "techage:ta4_wlanchip", "techage:ta4_ramchip"},
+ },
+})
+
techage.register_node({"techage:terminal2"}, {
on_recv_message = function(pos, src, topic, payload)
output(pos, "src="..src..", cmd="..dump(topic)..", data="..dump(payload))
@@ -302,3 +425,16 @@ techage.register_node({"techage:terminal2"}, {
end
end,
})
+
+techage.register_node({"techage:terminal3"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ if topic == "text" then
+ output(pos, payload)
+ elseif topic == "append" then
+ append(pos, payload)
+ else
+ output(pos, "src="..src..", cmd="..dump(topic)..", data="..dump(payload))
+ end
+ return true
+ end,
+})
diff --git a/techage/manuals/QSG.md b/techage/manuals/QSG.md
index 445ae89..d2933aa 100644
--- a/techage/manuals/QSG.md
+++ b/techage/manuals/QSG.md
@@ -3,12 +3,13 @@
The Techage Modpack is an extensive collection of technical mods with many machines and systems, which unfortunately cannot be set up intuitively. Therefore, there is this Quick Start Guide and further manuals for the different mods.
-Techage represents four technological ages:
+Techage represents five technological ages:
- Iron Age (TA1) - Simple tools like coal pile, coal burner, gravel sieve, hammer for getting ores and making goods
- Steam Age (TA2) - Simple machines that are powered by steam engines and drive axles
- Oil Age (TA3) - More modern machines that are powered by electricity
-- Future Age (TA4) - Electricity from renewable energy sources such as sun and wind
+- Present (TA4) - Electricity from renewable energy sources such as sun and wind
+- Future (TA5) - Machines to overcome space and time, new sources of energy and other achievements shape your life
Since the levels build on each other, all ages have to be run through one after the other.
@@ -61,7 +62,7 @@ Since the levels build on each other, all ages have to be run through one after
-## Future Age (TA4)
+## Present (TA4)
1. Build solar and wind plants to get renewable energy
2. Build a Thermal Energy Storage to store the energy
@@ -72,9 +73,14 @@ Since the levels build on each other, all ages have to be run through one after
+## Future (TA5)
+
+tbd.
+
+
## Power Consumption
-t| TechAge Machine | TA2 [ku] | TA3 [ku] | TA4 [ku] |
+| TechAge Machine | TA2 [ku] | TA3 [ku] | TA4 [ku] |
| ------------------------------ | -------- | -------- | --------- |
| Autocrafter | 4 | 6 | (9) |
| Electronic Fab | 8 | 12 | 12 |
diff --git a/techage/manuals/manual_DE.md b/techage/manuals/manual_DE.md
index 6a4995a..97cf0e0 100644
--- a/techage/manuals/manual_DE.md
+++ b/techage/manuals/manual_DE.md
@@ -1,6 +1,6 @@
# Tech Age Mod
-Tech Age ist eine Technik-Mod mit 4 Entwicklungsstufen:
+Tech Age ist eine Technik-Mod mit 5 Entwicklungsstufen:
TA1: Eisenzeitalter (Iron Age)
Benutze Werkzeuge und Hilfsmittel wie Köhler, Kohlebrenner, Kiessieb, Hammer, Hopper um notwendige Erze und Metalle zu schürfen und zu verarbeiten.
@@ -11,9 +11,13 @@ Baue eine Dampfmaschine mit Antriebsachsen und betreibe damit deine ersten Masch
TA3: Ölzeitalter (Oil Age)
Suche und fördere Öl, baute Schienenwege zur Ölbeförderung. Ein Kraftwerk liefert den notwendigen Strom für deine Maschinen. Elektrisches Licht erhellt deine Industrieanlagen.
-TA4: Zukunft (Future Age)
+TA4: Gegenwart (Present)
Regenerative Energiequellen wie Wind, Sonne und Biokraft helfen dir, das Ölzeitalter zu verlassen. Mit modernen Technologien und intelligenten Maschinen machst du dich auf in die Zukunft.
+TA5: Zukunft (Future)
+Maschinen zur Überwindung von Raum und Zeit, neue Energiequellen und andere Errungenschaften prägen dein Leben.
+
+
Hinweis: Mit Klicken auf die Pluszeichen kommst du in die Unterkapitel dieser Anleitung.
[techage_ta4|image]
diff --git a/techage/manuals/manual_EN.md b/techage/manuals/manual_EN.md
index e346d95..3dd5743 100644
--- a/techage/manuals/manual_EN.md
+++ b/techage/manuals/manual_EN.md
@@ -1,6 +1,6 @@
# Tech Age Mod
-Tech Age is a technology mod with 4 development stages:
+Tech Age is a technology mod with 5 development stages:
TA1: Iron Age
Use tools and aids such as coal burners, coal burners, gravel sieves, hammers and hoppers to mine and process the necessary ores and metals.
@@ -11,9 +11,13 @@ Build a steam engine with drive axles and use it to operate your first ore proce
TA3: Oil Age
Find and extract oil, built railways for oil transportation. A power plant provides the necessary electricity for your machines. Electric light illuminates your industrial plants.
-TA4: Future Age
+TA4: Present
Renewable energy sources such as wind, sun and biofuels help you to leave the oil age. With modern technologies and intelligent machines you set out into the future.
+TA5: Future
+Machines to overcome space and time, new sources of energy and other achievements shape your life.
+
+
Note: With a click on the plus sign you get into the subchapters of this manual.
[techage_ta4|image]
diff --git a/techage/manuals/manual_ta3_DE.md b/techage/manuals/manual_ta3_DE.md
index 1f49a38..6916f56 100644
--- a/techage/manuals/manual_ta3_DE.md
+++ b/techage/manuals/manual_ta3_DE.md
@@ -671,6 +671,18 @@ Damit lassen sich auch ausfahrbare Treppen und ähnliches simulieren.
[ta3_doorcontroller|image]
+### TA3 Sound Block
+
+Mir dem Sound Block können veschiedene Sounds/Laute abgespielt werden. Es sind alle Sounds der Mods Techage, Signs Bot, Hyperloop, Unified Inventory, TA4 Jetpack und Minetest Game verfügbar.
+
+Die Sounds können über das Menü und über ein Kommando ausgewählt und abgespielt werden.
+
+- Kommando `on` zum Abspielen eines Sounds
+- Kommando `sound ` zur Auswahl eines Sounds über den Index
+- Kommando `gain ` zum Einstellen der Lautstärke über den `` Wert (0 bis 1.0).
+
+[ta3_soundblock|image]
+
### TA3 Mesecons Umsetzer / TA3 Mesecons Converter
Der Mesecons Umsetzer dient zur Umwandlung von Techage on/off Kommandos in Mesecons Signale und umgekehrt.
diff --git a/techage/manuals/manual_ta3_EN.md b/techage/manuals/manual_ta3_EN.md
index 983fa7b..82b6f81 100644
--- a/techage/manuals/manual_ta3_EN.md
+++ b/techage/manuals/manual_ta3_EN.md
@@ -664,6 +664,17 @@ This can also be used to simulate extendable stairs and the like.
[ta3_doorcontroller|image]
+### TA3 Sound Block
+
+Different sounds can be played with the sound block. All sounds of the Mods Techage, Signs Bot, Hyperloop, Unified Inventory, TA4 Jetpack and Minetest Game are available.
+
+The sounds can be selected and played via the menu and via command.
+
+- Command `on` to play a sound
+- Command `sound ` to select a sound via the index
+- Command `gain ` to adjust the volume via the `` value (0 to 1.0).
+
+[ta3_soundblock|image]
### TA3 Mesecons Converter
diff --git a/techage/manuals/manual_ta4_DE.md b/techage/manuals/manual_ta4_DE.md
index 6ee4f31..15e33cf 100644
--- a/techage/manuals/manual_ta4_DE.md
+++ b/techage/manuals/manual_ta4_DE.md
@@ -1,4 +1,4 @@
-# TA4: Zukunft
+# TA4: Gegenwart
Regenerative Energiequellen wie Wind, Sonne und Biokraft helfen dir, das Ölzeitalter zu verlassen. Mit modernen Technologien und intelligenten Maschinen machst du dich auf in die Zukunft.
@@ -294,7 +294,8 @@ Hinweis 2: Tanks oder Silos mit verschiedenen Inhalten dürfen nicht zu einem Le
Beim Cracken werden lange Kette von Kohlenwasserstoffen unter Verwendung eines Katalysator in kurze Ketten gebrochen.
Als Katalysator dient Gibbsitpulver (wird nicht verbraucht). Damit kann Bitumen in Schweröl, Schweröl in Naphtha und Naphtha in Benzin umgewandelt werden.
-Bei der Hydrierung werden einem Molekül Paare von Wasserstoffatomen hinzugefügt, um kurzkettige Kohlenwasserstoffe in lange umzuwandeln. Hier wird Eisenpulver als Katalysator benötigt (wird nicht verbraucht). Damit kann Benzin in Naphtha,
+Bei der Hydrierung werden einem Molekül Paare von Wasserstoffatomen hinzugefügt, um kurzkettige Kohlenwasserstoffe in lange umzuwandeln.
+Hier wird Eisenpulver als Katalysator benötigt (wird nicht verbraucht). Damit kann Propangas in Isobutan, Isobutan in Benzin, Benzin in Naphtha,
Naphtha in Schweröl und Schweröl in Bitumen umgewandelt werden.
[ta4_reactor|plan]
@@ -470,12 +471,40 @@ Beim TA4 Taster/Schalter hat sich nur das Aussehen geändert. Die Funktionalitä
[ta4_button|image]
+### TA4 2x Taster / 2x Button
+
+Dieser Block hat zwei Taster, die über das Schraubenschlüssel-Menü individuell konfiguriert werden können. Für beide Taster kann die Beschriftung und die Zielblockadresse konfiguriert werden. Zusätzlich kann für beide Taster das Kommando konfiguriert werden, welches gesendet werden soll.
+
+[ta4_button_2x|image]
+
### TA4 4x Taster / 4x Button
Dieser Block hat vier Taster, die über das Schraubenschlüssel-Menü individuell konfiguriert werden können. Für jeden Taster kann die Beschriftung und die Zielblockadresse konfiguriert werden. Zusätzlich kann für jeden Taster das Kommando konfiguriert werden, welches gesendet werden soll.
[ta4_button_4x|image]
+### TA4 2x Signallampe / 2x Signal Lamp
+
+Dieser Block hat zwei Lampen, die individuell angesteuert werden können. Jede Lampe kann die Farben "rot", "grün" und "orange" anzeigen. Über das Schraubenschlüssel-Menü kann für beide Lampen die Beschriftung konfiguriert werden. Die Lampen können über folgende Kommandos angesteuert werden:
+
+- Lampe 1 auf rot schalten: `$send_cmnd(1234, "red", 1)`
+- Lampe 2 auf grün schalten: `$send_cmnd(1234, "green", 2)`
+- Lampe 1 auf orange schalten: `$send_cmnd(1234, "amber", 1)`
+- Lampe 2 aus schalten: `$send_cmnd(1234, "off", 2)`
+
+[ta4_signallamp_2x|image]
+
+### TA4 4x Signallampe / 4x Signal Lamp
+
+Dieser Block hat vier Lampen, die individuell angesteuert werden können. Jede Lampe kann die Farben "rot", "grün" und "orange" anzeigen. Über das Schraubenschlüssel-Menü kann für alle Lampen die Beschriftung konfiguriert werden. Die Lampen können über folgende Kommandos angesteuert werden:
+
+- Lampe 1 auf rot schalten: `$send_cmnd(1234, "red", 1)`
+- Lampe 2 auf grün schalten: `$send_cmnd(1234, "green", 2)`
+- Lampe 3 auf orange schalten: `$send_cmnd(1234, "amber", 3)`
+- Lampe 4 aus schalten: `$send_cmnd(1234, "off", 4)`
+
+[ta4_signallamp_4x|image]
+
### TA4 Spieler Detektor / Player Detector
Beim TA4 Spieler Detektor hat sich nur das Aussehen geändert. Die Funktionalität ist gleich wie beim TA3 Spieler Detektor.
@@ -495,28 +524,6 @@ Diesen Zähler kann man über das Kommando 'count' abfragen und über 'reset' zu
[ta4_detector|image]
-### TA4 Move Controller
-
-Der TA4 Move Controller ist ähnlich zum "Door Controller 2", aber die ausgewählten Blöcke werden nicht entfernt, sondern können bewegt werden.
-Da die bewegten Blöcke Spieler und Mobs mitnehmen können, die auf dem Block stehen, können damit Fahrstühle und ähnliche Transportsysteme gebaut werden.
-
-Anleitung:
-
-- Controller setzen und die Blöcke, die bewegt werden sollen, über das Menü an-trainieren (Es können bis zu 16 Blöcke an-trainiert werden)
-- die "Flugstrecke" muss über eine x,y,z Angabe (relativ) eingegeben werden (die maximale Distanz beträgt 100 m)
-- mit den Menü-Tasten "Bewege A-B" sowie "Bewege B-A" kann die Bewegung getestet werden
-- man kann auch durch Wände oder andere Blöcke fliegen
-- auch die Zielposition für die Blöcke kann belegt sein. Die Blöcke werden in diesem Falle "unsichtbar" gespeichert. Dies ist für Schiebetüren und ähnliches gedacht
-- Über das Gabelschlüssel-Menü kann im Controller auch ein "handover" programmiert werden. Durch Eingabe einer Blocknummer werden die Blöcke dann an den nächsten Move Controller übergeben. So lassen sich auch zusammenhängende Bewegungen über mehrere Move Controller realisieren.
-
-Der Move Controller unterstützt folgende techage Kommandos:
-
-- `a2b` Bewege Block von A nach B
-- `b2a` Bewege Block von B nach A
-- `move` Bewege Block auf die andere Seite
-
-[ta4_movecontroller|image]
-
### TA4 Sequenzer
@@ -550,6 +557,56 @@ Das `goto` Kommando wird nur angenommen, wenn der Sequenzer gestoppt ist.
+
+## Move/Dreh-Controller
+
+### TA4 Move Controller
+
+Der TA4 Move Controller ist ähnlich zum "Door Controller 2", aber die ausgewählten Blöcke werden nicht entfernt, sondern können bewegt werden.
+Da die bewegten Blöcke Spieler und Mobs mitnehmen können, die auf dem Block stehen, können damit Fahrstühle und ähnliche Transportsysteme gebaut werden.
+
+Anleitung:
+
+- Controller setzen und die Blöcke, die bewegt werden sollen, über das Menü an-trainieren (Es können bis zu 16 Blöcke an-trainiert werden)
+- die "Flugstrecke" muss über eine x,y,z Angabe (relativ) eingegeben werden (die maximale Distanz beträgt 100 m)
+- mit den Menü-Tasten "Bewege A-B" sowie "Bewege B-A" kann die Bewegung getestet werden
+- man kann auch durch Wände oder andere Blöcke fliegen
+- auch die Zielposition für die Blöcke kann belegt sein. Die Blöcke werden in diesem Falle "unsichtbar" gespeichert. Dies ist für Schiebetüren und ähnliches gedacht
+- Über das Gabelschlüssel-Menü kann im Controller auch ein "handover" programmiert werden. Durch Eingabe einer Blocknummer werden die Blöcke dann an den nächsten Move Controller übergeben. So lassen sich auch zusammenhängende Bewegungen über mehrere Move Controller realisieren.
+
+Der Move Controller unterstützt folgende techage Kommandos:
+
+- `a2b` Bewege Block von A nach B
+- `b2a` Bewege Block von B nach A
+- `move` Bewege Block auf die andere Seite
+
+**Wichtige Hinweise:**
+
+- Sofern mehrere Blöcke bewegt werden sollen, muss der Block, der die Spieler/Mobs mitnehmen soll, beim Antrainieren als erstes angeklickt werden.
+- Hat der Block, der die Spieler/Mobs mitnehmen soll, eine reduzierte Höhe, so muss die Höhe im Controller über das Schraubenschlüsselmenü eingestellt werden (bspw. Höhe = 0.5). Ansonsten wird der Spieler/Mob nicht "gefunden" und damit nicht mitgenommen.
+
+[ta4_movecontroller|image]
+
+### TA4 Drehcontroller / Turn Controller
+
+Der TA4 Drehcontroller ist ähnlich zum Move Controller", aber die ausgewählten Blöcke werden nicht bewegt, sondern um ihr Zentrum nach rechts oder links gedreht.
+
+Anleitung:
+
+- Controller setzen und die Blöcke, die bewegt werden sollen, über das Menü an-trainieren (Es können bis zu 16 Blöcke an-trainiert werden)
+- mit den Menü-Tasten "Drehe links" sowie "Drehe rechts" kann die Bewegung getestet werden
+
+Der Drehcontroller unterstützt folgende techage Kommandos:
+
+- `left` Drehe nach links
+- `right` Drehe nach rechts
+- `uturn` Drehe um 180 Grad
+
+[ta4_turncontroller|image]
+
+
+
+
## TA4 Lampen
TA4 beinhaltet eine Reihe von leistungsstarken Lampen, die eine bessere Ausleuchtung ermöglichen oder Spezialaufgaben übernehmen.
@@ -623,9 +680,117 @@ In den Einfüllstutzen muss Rotschlamm mittels einer Pumpe geleitet werden.
+## TA4 Teilchenbeschleuniger / Collider
+
+Der Teilchenbeschleuniger ist eine Forschungsanlage, bei der Grundlagenforschung betrieben wird. Hier können Erfahrungspunkte (experience points) gesammelt werden, welche für TA5 (Future Age) benötigt werden.
+
+Der Teilchenbeschleuniger muss wie sein Original am CERN in Genf unterirdisch aufgebaut werden. Die Standardeinstellung ist hier Y <= -28. Der Wert kann aber per Konfiguration vom Server Personal geändert werden. Ab besten nachfragen, oder mit dem "TA4 Collider Detector Worker" Block ausprobieren.
+
+Pro Spieler kann nur ein Teilchenbeschleuniger betrieben werden. Es macht also keinen Sinn, zwei oder mehrere Teilchenbeschleuniger aufzubauen. Erfahrungspunkte werden dem Spieler gutgeschrieben, dem der Teilchenbeschleuniger gehört. Die Erfahrungspunkte können nicht übertragen werden.
+
+Ein Teilchenbeschleuniger besteht aus einem "Ring" aus Röhren und Magneten sowie dem Detektor mit Kühlanlage.
+
+- Der Detektor ist das Herz der Anlage. Hier finden die wissenschaftlichen Experimente statt. Der Detektor ist 3x3x7 Blöcke groß.
+- Die TA4 Collider Detector Magnete (22 Stück) müssen über jeweils 5 Blöcken der TA4 Vakuumröhre miteinander verbunden werden. Jeder Magnet benötigt zusätzlich Strom und einen Gasanschluss für die Kühlung. Das ganze bildet (wie rechts im Plan abgebildet) ein Quadrat mit einer Kantenlänge von 37 Metern.
+- Zusätzlich wird eine Kühlung benötigt, welche zusätzlich beim Detektor aufgebaut werden muss. Für die Kühlung wird Isobutan benötigt.
+- Die Anlage benötigt einiges an Strom. Daher ist eine eigene Stromversorgung sinnvoll.
+
+Der Plan zeigt die Anlage von oben:
+
+- der graue Block ist der Detektor mit dem Worker-Block in der Mitte
+- die roten Blöcke sind die Magnete, das blaue die Vakuumröhren
+
+[techage_collider_plan|plan]
+
+### Detektor
+
+Der Detektor wird mit Hilfe des "TA4 Collider Detector Worker" Blocks automatisch aufgebaut (ähnlich wie beim Bohrturm). Alle dazu notwendigen Materialien müssen zuvor in den Worker-Block gelegt werden. Auf dem Worker-Block ist der Detektor symbolisch dargestellt. Der Detektor wird über dem Worker-Block in Querrichtung errichtet.
+
+Der Detektor kann mit Hilfe des Worker-Blocks auch wieder abgebaut werden.
+
+Auf den beiden Stirnseiten des Detektors befinden sich die Anschlüsse für Strom, Gas und Vakuumröhre. Oben muss eine TA4 Pumpe angeschlossen werden, um die Röhre leer zu saugen / das Vakuum zu erzeugen.
+
+Auf der Rückseite des Detektors muss das Kühlsystem angeschlossen werden. Im Plan rechts ist das Kühlsystem abgebildet. Hier wird neben dem TA4 Wärmetauscher des Energiespeichers (welcher hier zur Kühlung genutzt wird), auch ein TA4 Kühlerblock benötigt.
+
+Hinweis: Der Pfeil des Wärmetauschers muss vom Detektor weg zeigen. Auch der Wärmetauscher muss mit Strom versorgt werden.
+
+[ta4_cooler|plan]
+
+### Steuerung / TA4 Terminal
+
+Der Teilchenbeschleuniger wird über ein TA4 Terminal gesteuert (nicht über das TA4 Lua Controller Terminal).
+
+Dieses Terminal muss mit dem Detektor verbunden werden. Die Nummer des Detektors wird als Infotext am Worker-Block angezeigt.
+
+Das Terminal unterstützt folgende Kommandos:
+
+- `connect ` (verbinden mit dem Detektor)
+- `start` (starten des Detektors)
+- `stop` (stoppen des Detektors)
+- `test ` (überprüfen eines Magneten)
+- `points` (abfragen der bereits erreichten Erfahrungspunkte)
+
+Tritt beim `start` an einem Magneten ein Fehler auf, so wird die Nummer des Magneten ausgegeben. Über das `test` Kommando können weitere Informationen zum Fehler des Magneten angefordert werden.
+
+[ta4_terminal|image]
+
+
+
+### Aufbau
+
+Für den Teilchenbeschleunigers wird außer den Blöcken für den Bau folgendes benötigt:
+
+- Strom (145 ku)
+- TA4 Tank mit mindestens 250 Einheiten Isobutan
+
+Beim Aufbau des Teilchenbeschleunigers empfiehlt sich folgende Reihenfolge:
+
+- Einen Forceload Block setzen. Nur der Detektor mit der Kühlanlage muss sich im Bereich des Forceload Blockes befinden.
+- Den Worker-Block setzen, mit Items füllen und den Detektor über das Menü aufbauen
+- Den Ring mit Röhren und Magneten aufbauen
+- Alle Magnete und den Detektor mit Stromkabel verbinden
+- Alle Magnete und den Detektor mit den gelben Röhren verbinden und das Isobutan mit einer Pumpe in das Röhrensystem pumpen.
+- Eine TA4 Pumpe als Vakuumpumpe auf dem Detektor installieren und einschalten (es wird kein zusätzlicher Tank benötigt). Geht die Pumpe in den "standby", ist das Vakuum hergestellt. Dies dauert einige Sekunden
+- den Kühler (Wärmetauscher) aufbauen und mit dem Stromkabel verbinden
+- Das TA4 Terminal vor den Detektor setzen und über `connect ` mit dem Detektor verbinden
+- Die Stromversorgung einschalten/herstellen
+- den Kühler (Wärmetauscher) einschalten
+- den Detektor über `start` am TA4 Terminal einschalten. Der Detektor geht nach einigen Prüfschritten in den Normalbetrieb oder gibt einen Fehler aus.
+- Der Teilchenbeschleunigers muss im Dauerbetrieb laufen und liefert dann nach und nach Erfahrungspunkte. Für 10 Punkte muss der Teilchenbeschleuniger schon einige Stunden laufen.
+
+[techage_ta4c|image]
+
+
+
## Weitere TA4 Blöcke
+### TA4 Rezept Block
+
+Im Rezept Block können bis zu 10 Rezepte gespeichert werden. Diese Rezepte können dann über ein TA4 Autocrafter Kommando abgerufen werden. Dies ermöglicht eine Rezept-Konfiguration des Autocrafters über ein Kommando. Die Rezepte des Rezept Blocks können auch direkt per Kommando abgefragt werden.
+
+`input ` liest ein Rezept aus dem TA4 Rezeptblock. `` ist die Nummer des Rezepts. Der Block gibt eine Liste von Rezept-Zutaten zurück.
+
+Beispiel: `$send_cmnd(1234, "input", 1)`
+
+[ta4_recipeblock|image]
+
+### TA4 Autocrafter
+
+Die Funktion entspricht der von TA3.
+
+Die Verarbeitungsleistung beträgt 4 Items alle 4 s. Der Autocrafter benötigt hierfür 9 ku Strom.
+
+Zusätzlich unterstützt der TA4 Autocrafter die Auswahl unterschiedlicher Rezepte über folgende Kommandos:
+
+`recipe .` schaltet den Autocrafter auf ein Rezept des TA4 Rezept Blocks um. `` ist die Nummer des Rezept Blocks, `` die Rezept-Nummer. Beispiel: `$send_cmnd(1234, "recipe", 5467.1)`
+
+Alternativ kann ein Rezept auch über die Zutatenliste ausgewählt werden, wie bspw.:
+`$send_cmnd(1234, "recipe", "default:coal_lump,,,default:stick")`
+Hier müssen alle technische Namen eines Rezeptes durch Kommas getrennt angegeben werden. Siehe auch das Kommando `input` beim TA4 Rezept Block.
+
+[ta4_autocrafter|image]
+
### TA4 Tank / TA4 Tank
Siehe TA3 Tank.
@@ -638,7 +803,7 @@ In einen TA4 Tank passen 2000 Einheiten oder 200 Fässer einer Flüssigkeit.
Siehe TA3 Pumpe.
-Die TA4 Pumpe pumpt 8 Einheiten Flüssigkeit alle zwei Sekunden.
+Die TA4 Pumpe pumpt 8 Einheiten Flüssigkeit alle zwei Sekunden. Zusätzlich unterstützt die Pumpe das Kommando `flowrate`. Damit kann die Gesamtdurchflussmenge durch die Pumpe abgefragt werden.
[ta4_pump|image]
diff --git a/techage/manuals/manual_ta4_EN.md b/techage/manuals/manual_ta4_EN.md
index 388cd30..d242b3c 100644
--- a/techage/manuals/manual_ta4_EN.md
+++ b/techage/manuals/manual_ta4_EN.md
@@ -1,4 +1,4 @@
-# TA4: Future
+# TA4: Present
Renewable energy sources such as wind, sun and biofuels help you to leave the oil age. With modern technologies and intelligent machines you set out into the future.
@@ -287,9 +287,9 @@ Note 2: Tanks or silos with different contents must not be connected to a pipe s
Cracking breaks long chains of hydrocarbons into short chains using a catalyst.
Gibbsite powder serves as a catalyst (is not consumed). It can be used to convert bitumen into fueloil, fueloil into naphtha and naphtha into gasoline.
-In hydrogenation, pairs of hydrogen atoms are added to a molecule to convert short-chain hydrocarbons into long ones.
-Here iron powder is required as a catalyst (is not consumed). It can be used to convert gasoline into naphtha,
-naphtha into fueloil, and fueloil into bitumen.
+In hydrogenation, pairs of hydrogen atoms are added to a molecule to convert short-chain hydrocarbons into long ones.
+Here iron powder is required as a catalyst (is not consumed). It can be used to convert gas (propane) into isobutane,
+isobutane into gasoline, gasoline into naphtha, naphtha into fueloil, and fueloil into bitumen.
[ta4_reactor|plan]
@@ -463,12 +463,41 @@ Only the appearance of the TA4 button/switch has changed. The functionality is t
[ta4_button|image]
+### TA4 2x Button
+
+This block has two buttons that can be individually configured using the wrench menu. The labeling and the target block address can be configured for each button. In addition, the command that is to be sent can be configured for each button.
+
+[ta4_button_2x|image]
+
+
### TA4 4x Button
This block has four buttons that can be individually configured using the wrench menu. The labeling and the target block address can be configured for each button. In addition, the command that is to be sent can be configured for each button.
[ta4_button_4x|image]
+### TA4 2x Signal Lamp
+
+This block has two lamps that can be controlled individually. Each lamp can display the colors "red", "green" and "amber". The labeling for both lamps can be configured via the wrench menu. The lamps can be controlled using the following commands:
+
+- Switch lamp 1 to red: `$send_cmnd(1234, "red", 1)`
+- Switch lamp 2 to green: `$send_cmnd(1234, "green ", 2)`
+- Switch lamp 1 to orange: `$send_cmnd(1234, "amber", 1)`
+- Switch lamp 2 off: `$send_cmnd(1234, "off", 2)`
+
+[ta4_signallamp_2x|image]
+
+### TA4 4x Signal Lamp
+
+This block has four lamps that can be controlled individually. Each lamp can display the colors "red", "green" and "amber". The labeling for all lamps can be configured via the wrench menu. The lamps can be controlled using the following commands:
+
+- Switch lamp 1 to red: `$send_cmnd(1234, "red", 1)`
+- Switch lamp 2 to green: `$send_cmnd(1234, "green ", 2)`
+- Switch lamp 3 to orange: `$send_cmnd(1234, "amber", 3)`
+- Switch lamp 4 off: `$send_cmnd(1234, "off", 4)`
+
+[ta4_signallamp_4x|image]
+
### TA4 Player Detector
Only the appearance of the TA4 player detector has changed. The functionality is the same as with the TA3 player detector.
@@ -488,28 +517,6 @@ This counter can be queried with the 'count' command and reset with 'reset'.
[ta4_detector|image]
-### TA4 Move Controller
-
-The TA4 Move Controller is similar to "Door Controller 2", but the selected blocks are not removed, but can be moved.
-Since the moving blocks can take players and mobs standing on the block with them, elevators and similar transport systems can be built with them.
-
-Instructions:
-
-- Set the controller and train the blocks to be moved via the menu (up to 16 blocks can be trained)
-- the "flight route" must be entered via an x, y, z specification (relative) (the maximum distance is 100 m)
-- The movement can be tested with the menu buttons "Move A-B" and "Move B-A"
-- you can also fly through walls or other blocks
-- The target position for the blocks can also be occupied. In this case, the blocks are saved "invisibly". This is intended for sliding doors and the like
-- A "handover" can also be programmed in the controller via the open-ended wrench menu. By entering a block number, the blocks are then transferred to the next move controller. In this way, connected movements can also be implemented using several Move Controllers.
-
-The Move Controller supports the following techage commands:
-
-- `a2b` Move block from A to B.
-- `b2a` Move block from B to A.
-- `move` Move block to the other side
-
-[ta4_movecontroller|image]
-
### TA4 Sequencer
Entire processes can be programmed using the TA4 sequencer. Here's an example:
@@ -542,6 +549,54 @@ The `goto` command is only accepted when the sequencer is stopped.
+## Move/Turn Controller
+
+### TA4 Move Controller
+
+The TA4 Move Controller is similar to "Door Controller 2", but the selected blocks are not removed, but can be moved.
+Since the moving blocks can take players and mobs standing on the block with them, elevators and similar transport systems can be built with them.
+
+Instructions:
+
+- Set the controller and train the blocks to be moved via the menu (up to 16 blocks can be trained)
+- the "flight route" must be entered via an x, y, z specification (relative) (the maximum distance is 100 m)
+- The movement can be tested with the menu buttons "Move A-B" and "Move B-A"
+- you can also fly through walls or other blocks
+- The target position for the blocks can also be occupied. In this case, the blocks are saved "invisibly". This is intended for sliding doors and the like
+- A "handover" can also be programmed in the controller via the open-ended wrench menu. By entering a block number, the blocks are then transferred to the next move controller. In this way, connected movements can also be implemented using several Move Controllers.
+
+The Move Controller supports the following techage commands:
+
+- `a2b` Move block from A to B.
+- `b2a` Move block from B to A.
+- `move` Move block to the other side
+
+**Important instructions:**
+
+- If several blocks are to be moved, the block that is to take the players/mobs must be clicked first when training.
+- If the block that is supposed to take the players/mobs has a reduced height, the height must be set in the controller using the open-ended wrench menu (e.g. height = 0.5). Otherwise the player/mob will not be "found" and will not be taken away.
+
+[ta4_movecontroller|image]
+
+### TA4 Turn Controller
+
+The TA4 turn controller is similar to the "Move Controller", but the selected blocks are not moved, but rotated around their center to the right or left.
+
+Instructions:
+
+- Set the controller and train the blocks to be moved via the menu (up to 16 blocks can be trained)
+- The movement can be tested with the menu buttons "Turn left" and "Turn right"
+
+The turn controller supports the following techage commands:
+
+- `left` Turn left
+- `right` Turn right
+- `uturn` Turn 180 degrees
+
+[ta4_turncontroller|image]
+
+
+
## TA4 Lamps
@@ -617,8 +672,117 @@ The red mud must be pumped into the filler pipe.
+## TA4 Collider (Particle Accelerator)
+
+The Collider is a research facility that conducts basic research. Experience points can be collected here, which are required for TA5 (Future Age).
+
+Like its original at CERN in Geneva, the collider must be built underground. The standard setting here is Y <= -28. The value can, however, be changed by the server personnel via configuration. Please ask or try the "TA4 Collider Detector Worker" block.
+
+Only one collider can be operated per player. So it makes no sense to set up two or more colliders. Experience points are credited to the player who owns the collider. The experience points cannot be transferred.
+
+A collider consists of a "ring" made of tubes and magnets as well as a detector with a cooling system.
+
+- The detector is the heart of the system. This is where the scientific experiments take place. The detector is 3x3x7 blocks in size.
+- The TA4 Collider Detector magnets (22 pieces) must be connected to each other via 5 blocks of the TA4 vacuum tube. Each magnet also requires electricity and a gas connection for cooling. The whole thing forms (as shown in the plan on the right) a square with an edge length of 37 meters.
+- In addition, cooling is required, which must also be installed at the detector. Isobutane is required for cooling.
+- The system requires quite a bit of electricity. Therefore, it makes sense to have your own power supply.
+
+The plan shows the facility from above:
+
+- the gray block is the detector with the worker block in the middle
+- the red blocks are the magnets, the blue the vacuum tubes
+
+[techage_collider_plan|plan]
+
+### Detector
+
+The detector is set up automatically with the help of the "TA4 Collider Detector Worker" block (similar to the derrick). All of the materials required for this must first be placed in the worker block. The detector is shown symbolically on the worker block. The detector is set up across the worker block.
+
+The detector can also be dismantled again with the help of the worker block.
+
+The connections for electricity, gas and vacuum tubes are located on the two front sides of the detector. A TA4 pump must be connected at the top in order to suck the tube empty / to create the vacuum.
+
+The cooling system must be connected to the rear of the detector. The cooling system is shown in the plan on the right. In addition to the TA4 heat exchanger of the energy storage unit (which is used here for cooling), a TA4 cooler block is also required.
+
+Note: The arrow on the heat exchanger must point away from the detector. The heat exchanger must also be supplied with electricity.
+
+[ta4_cooler|plan]
+
+### Control / TA4 Terminal
+
+The collider is controlled via a TA4 terminal (not via the TA4 Lua controller terminal).
+
+This terminal must be connected to the detector. The number of the detector is displayed as info text on the worker block.
+
+The terminal supports the following commands:
+
+- `connect ` (connect to the detector)
+- `start` (starting the detector)
+- `stop` (stop the detector)
+- `test ` (checking a magnet)
+- `points` (query of the experience points already achieved)
+
+If an error occurs on a magnet during the `start`, the number of the magnet is output. The `test` command can be used to request further information on the magnet error.
+
+[ta4_terminal|image]
+
+
+
+### Construction
+
+In addition to the building blocks, the following is required for the collider:
+
+- electricity (145 ku)
+- TA4 tank with at least 250 units of isobutane
+
+The following sequence is recommended when setting up the collider:
+
+- Put a forceload block. Only the detector with the cooling system has to be in the area of the forceload block.
+- Set the worker block, fill it with items and set up the detector via the menu
+- Build the ring with tubes and magnets
+- Connect all magnets and the detector with power cables
+- Connect all magnets and the detector with the yellow tubes and pump the isobutane into the tube system with a pump
+- Install a TA4 pump as a vacuum pump on the detector and switch it on (no additional tank is required). If the pump goes into "standby", the vacuum is established. This will take a few seconds
+- assemble the cooler (heat exchanger) and connect it to the power cable
+- Place the TA4 terminal in front of the detector and connect it to the detector via `connect `
+- Switch on / connect the power supply
+- switch on the cooler (heat exchanger)
+- Switch on the detector via `start` on the TA4 terminal. After a few test steps, the detector goes into normal operation or outputs an error.
+- The collider has to run continuously and then gradually delivers experience points. For 10 points, the collider has to run for a few hours
+
+[techage_ta4c|image]
+
+
+
+
## More TA4 Blocks
+### TA4 Recipe Block
+
+Up to 10 recipes can be saved in the recipe block. These recipes can then be called up via a TA4 Autocrafter command. This enables the autocrafter's recipe to be configured using a command. The recipes in the recipe block can also be queried directly using a command.
+
+`input ` reads a recipe from the TA4 recipe block. `` is the number of the recipe. The block returns a list of recipe ingredients.
+
+Example: `$send_cmnd(1234, "input", 1)`
+
+[ta4_recipeblock|image]
+
+### TA4 Autocrafter
+
+The function corresponds to that of TA3.
+
+The processing power is 4 items every 4 s. The autocrafter requires 9 ku of electricity for this.
+
+In addition, the TA4 Autocrafter supports the selection of different recipes using the following commands:
+
+`recipe .` switches the autocrafter to a recipe from the TA4 Recipe Block. `` is the number of the recipe block, `` the recipe number. Example: `$send_cmnd(1234, "recipe", 5467.1)`
+
+Alternatively, a recipe can also be selected via the list of ingredients, such as:
+`$send_cmnd(1234, "recipe", "default:coal_lump,,,default:stick")`
+All technical names of a recipe must be specified here, separated by commas. See also the command `input` in the TA4 recipe block.
+
+[ta4_autocrafter|image]
+
### TA4 Tank
See TA3 tank.
@@ -631,7 +795,7 @@ A TA4 tank can hold 2000 units or 200 barrels of liquid.
See TA3 pump.
-The TA4 pump pumps 8 units of liquid every two seconds.
+The TA4 pump pumps 8 units of liquid every two seconds. The pump also supports the `flowrate` command. This means that the total flow rate through the pump can be queried.
[ta4_pump|image]
diff --git a/techage/manuals/manual_ta5_DE.md b/techage/manuals/manual_ta5_DE.md
new file mode 100644
index 0000000..8fe44f1
--- /dev/null
+++ b/techage/manuals/manual_ta5_DE.md
@@ -0,0 +1,101 @@
+# TA5: Zukunft
+
+Maschinen zur Überwindung von Raum und Zeit, neue Energiequellen und andere Errungenschaften prägen dein Leben.
+
+Für die Herstellung und Nutzung von TA5 Maschinen und Blöcken sind Erfahrungspunkte (experience points) notwendig. Diese können nur über den Teilchenbeschleuniger aus TA4 erarbeitet werden.
+
+[techage_ta5|image]
+
+## Energiequellen
+
+### TA5 Fusionsreaktor (geplant)
+
+## Energiespeicher
+
+### TA5 Hybrid-Speicher (geplant)
+
+## Logik Blöcke
+
+## Transport und Verkehr
+
+### TA5 Flug Controller
+
+Der TA5 Flug Controller ist ähnlich zum TA4 Move Controller. Im Gegensatz zum TA4 Move Controller können hier mehrere Bewegungen zu einer Flugstrecke kombiniert werden. Diese Flugstrecke kann im Eingabefeld über mehrere x,y,z Angaben definiert werden (eine Bewegung pro Zeile). Über "Speichern" wird die Flugstrecke geprüft und gespeichert. Bei einem Fehler wird eine Fehlermeldung ausgegeben.
+
+Mit der Taste "Test" wird die Flugstrecke mit den absoluten Koordinaten zur Überprüfung im Chat ausgegeben.
+
+Die maximale Distanz für die gesammte Flugstrecke beträgt 500 m.
+
+Die Nutzung des TA5 Flug Controllers benötigt 40 Erfahrungspunkte.
+
+[ta5_flycontroller|image]
+
+### TA5 Hyperloop Kiste / TA5 Hyperloop Chest
+
+Die TA5 Hyperloop Kiste erlaubt den Transport von Gegenständen über ein Hyperloop Netzwerk.
+
+Die TA5 Hyperloop Kiste muss man dazu auf eine Hyperloop Junction stellen. Die Kiste besitzt ein spezielles Menü, mit dem man das Pairing von zwei Kisten durchführen kann. Dinge, die in der Kiste sind, werden zur Gegenstelle teleportiert. Die Kiste kann auch mit einem Schieber gefüllt/geleert werden.
+
+Für das Pairing musst du zuerst auf der einen Seite einen Namen für die Kiste eingeben, dann kannst du bei der anderen Kiste diesen Namen auswählen und so die beiden Blöcke verbinden.
+
+Die Nutzung der TA5 Hyperloop Kiste benötigt 20 Erfahrungspunkte.
+
+[ta4_chest|image]
+
+### TA5 Hyperloop Tank / TA5 Hyperloop Tank
+
+Der TA5 Hyperloop Tank erlaubt den Transport von Flüssigkeiten über ein Hyperloop Netzwerk.
+
+Den TA5 Hyperloop Tank muss man dazu auf eine Hyperloop Junction stellen. Der Tank besitzt ein spezielles Menü, mit dem man das Pairing von zwei Tanks durchführen kann. Flüssigkeiten, die in dem Tank sind, werden zur Gegenstelle teleportiert. Der Tank kann auch mit einer Pumpe gefüllt/geleert werden.
+
+Für das Pairing musst du zuerst auf der einen Seite einen Namen für den Tank eingeben, dann kannst du bei dem anderen Tank diesen Namen auswählen und so die beiden Blöcke verbinden.
+
+Die Nutzung des TA5 Hyperloop Tanks benötigt 20 Erfahrungspunkte.
+
+[ta4_tank|image]
+
+### Hyperloop Teleport Blöcke (geplant)
+
+Die Hyperloop Teleport Blöcke erlauben den Aufbau von Hyperloop Netzwerk ohne Hyperloop-Röhren.
+
+Die Nutzung der Hyperloop Teleport Blöcke benötigt 120 Erfahrungspunkte.
+
+### TA5 Container (geplant)
+
+Der TA5 Container erlaubt Techage Anlagen ein- und an einer anderen Stelle wieder auszupacken.
+
+Für die Nutzung des TA5 Containers werden 80 Erfahrungspunkte benötigt.
+
+### TA5 Teleport Block Gegenstände / TA5 Teleport Block Items
+
+Teleportblöcke erlauben den Item-Transport ohne Röhren bis zu einer Entfernung von 200 Blöcken.
+Für das Pairing musst du zuerst auf der einen Seite einen Namen für den Block eingeben, dann kannst du bei dem anderen Block diesen Namen auswählen und so die beiden Blöcke verbinden.
+
+Teleportblöcke benötigen jeweils 12 ku Strom.
+
+Für die Nutzung der Teleportblöcke werden 60 Erfahrungspunkte benötigt.
+
+[ta5_tele_tube|image]
+
+### TA5 Teleport Block Flüssigkeiten / TA5 Teleport Block Liquids
+
+Teleportblöcke erlauben den Flüssigkeiten-Transport ohne Leitungen bis zu einer Entfernung von 200 Blöcken.
+Für das Pairing musst du zuerst auf der einen Seite einen Namen für den Block eingeben, dann kannst du bei dem anderen Block diesen Namen auswählen und so die beiden Blöcke verbinden.
+
+Teleportblöcke benötigen jeweils 12 ku Strom.
+
+Für die Nutzung der Teleportblöcke werden 60 Erfahrungspunkte benötigt.
+
+[ta5_tele_pipe|image]
+
+### TA5-Raumgleiter (geplant)
+
+Dank einem Spezialantrieb für Lichtgeschwindigkeit können mit dem Raumgleiter auch große Entfernungen sehr schnell überwunden werden.
+
+## Weitere TA5 Blöcke/Items
+
+### TA5 KI Chip / TA5 AI Chip
+
+Der TA5 KI Chip wird teilweise zur Herstellung von TA5 Blöcken benötigt. Der TA5 KI Chip kann nur auf der TA4 Elektronik Fab hergestellt werden. Dazu werden 10 Erfahrungspunkte benötigt.
+
+[ta5_aichip|image]
\ No newline at end of file
diff --git a/techage/manuals/manual_ta5_EN.md b/techage/manuals/manual_ta5_EN.md
new file mode 100644
index 0000000..5877f5b
--- /dev/null
+++ b/techage/manuals/manual_ta5_EN.md
@@ -0,0 +1,97 @@
+# TA5: Future
+
+Machines to overcome space and time, new sources of energy and other achievements shape your life.
+
+Experience points are required for the manufacture and use of TA5 machines and blocks. These can only be worked out using the collider from TA4.
+
+[techage_ta5|image]
+
+## Energy Sources
+
+### TA5 Fusion Reactor (planned)
+
+## Energy Storage
+
+### TA5 Hybrid Storage (planned)
+
+## Logic blocks
+
+## Transport and Traffic
+
+### TA5 Flight Controller
+
+The TA5 Flight Controller is similar to the TA4 Move Controller. In contrast to the TA4 Move Controller, several movements can be combined into one flight route. This flight route can be defined in the input field using several x,y,z entries (one movement per line). The flight route is checked and saved via "Save". In the event of an error, an error message is issued.
+
+With the "Test" button, the flight route with the absolute coordinates is output for checking in the chat.
+
+The maximum distance for the entire flight distance is 500 m.
+
+The use of the TA5 Flight Controller requires 40 experience points.
+
+[ta5_flycontroller|image]
+
+### TA5 Hyperloop Chest
+
+The TA5 Hyperloop Chest allows objects to be transported over a Hyperloop network.
+
+The TA5 Hyperloop Chest has to be placed on a Hyperloop Junction. The chest has a special menu, with which you can pair two chests. Things that are in the chest are teleported to the remote station. The chest can also be filled/emptied with a pusher.
+
+For pairing you first have to enter a name for the chest on one side, then you can select this name for the other chest and thus connect the two blocks.
+
+The use of the TA5 Hyperloop Chest requires 20 experience points.
+
+[ta4_chest|image]
+
+### TA5 Hyperloop Tank
+
+The TA5 Hyperloop Tank allows liquids to be transported over a Hyperloop network.
+
+The TA5 Hyperloop Tank has to be placed on a Hyperloop Junction.The tank has a special menu, with which you can pair two tanks. Liquids in the tank will be teleported to the remote station. The tank can also be filled/emptied with a pump.
+
+For pairing you first have to enter a name for the tank on one side, then you can select this name for the other tank and thus connect the two blocks.
+
+The use of the TA5 Hyperloop Tank requires 20 experience points.
+
+[ta4_tank|image]
+
+### Hyperloop Teleport Blocks (planned)
+
+The Hyperloop Teleport Blocks allow the construction of a Hyperloop network without Hyperloop tubes.
+
+The use of the Hyperloop Teleport Blocks requires 120 experience points.
+
+### TA5 Container (planned)
+
+The TA5 container allows Techage systems to be packed and unpacked at another location.
+
+80 experience points are required to use the TA5 container.
+
+### TA5 Teleport Block Items
+
+Teleport blocks allow items to be transported without tubes up to a distance of 200 blocks.
+For pairing you first have to enter a name for the block on one side, then you can select this name for the other block and thus connect the two blocks.
+
+Teleport blocks each require 12 ku of electricity.
+
+60 experience points are required to use the Teleport blocks.
+
+[ta5_tele_tube|image]
+
+### TA5 Teleport Block Liquids
+
+Teleport blocks allow liquids to be transported without pipes up to a distance of 200 blocks.
+For pairing you first have to enter a name for the block on one side, then you can select this name for the other block and thus connect the two blocks.
+
+Teleport blocks each require 12 ku of electricity.
+
+60 experience points are required to use the Teleport blocks.
+
+[ta5_tele_pipe|image]
+
+## More TA5 Blocks / Items
+
+### TA5 AI Chip
+
+The TA5 AI Chip is partly required for the production of TA5 blocks. The TA5 AI Chip can only be manufactured at the TA4 Electronics Fab. This requires 10 experience points.
+
+[ta5_aichip|image]
\ No newline at end of file
diff --git a/techage/manuals/markdown2formspec.py b/techage/manuals/markdown2formspec.py
index 76c7cb4..86bb605 100644
--- a/techage/manuals/markdown2formspec.py
+++ b/techage/manuals/markdown2formspec.py
@@ -247,6 +247,7 @@ parse_md_file("./manual_ta1_DE.md", mod, manual)
parse_md_file("./manual_ta2_DE.md", mod, manual)
parse_md_file("./manual_ta3_DE.md", mod, manual)
parse_md_file("./manual_ta4_DE.md", mod, manual)
+parse_md_file("./manual_ta5_DE.md", mod, manual)
gen_lua_file("../doc/manual_DE.lua")
gen_toc_md_file("./toc_DE.md", "Inhaltsverzeichnis")
@@ -259,6 +260,7 @@ parse_md_file("./manual_ta1_EN.md", mod, manual)
parse_md_file("./manual_ta2_EN.md", mod, manual)
parse_md_file("./manual_ta3_EN.md", mod, manual)
parse_md_file("./manual_ta4_EN.md", mod, manual)
+parse_md_file("./manual_ta5_EN.md", mod, manual)
gen_lua_file("../doc/manual_EN.lua")
gen_toc_md_file("./toc_EN.md", "Table of Contents")
diff --git a/techage/manuals/ta4_lua_controller_EN.md b/techage/manuals/ta4_lua_controller_EN.md
index b50b953..51bf2a7 100644
--- a/techage/manuals/ta4_lua_controller_EN.md
+++ b/techage/manuals/ta4_lua_controller_EN.md
@@ -134,7 +134,8 @@ SaferLua directly supports the following standard functions:
- string.rep
- string.sub
- string.upper
-- string.split
+- string.split (result is an Array)
+- string.split2 (result are multiple returns like the Lua function unpack)
- string.trim
For own function definitions, the menu tab 'func' can be used. Here you write your functions like:
@@ -366,12 +367,14 @@ Please note, that this is not a technical distinction, only a logical.
| "depth" | number | Read the current depth value of a quarry block (1..80) |
| "load" | number | Read the load value in percent (0..100) of a tank, silo, accu, or battery block, or from the Signs Bot Box. Silo and tank return two values: The percentage value and the absolute value in units.
Example: percent, absolute = $send_cmnd("223", "load") |
| "delivered" | number | Read the current delivered power value of a generator block. A power consuming block (accu) provides a negative value |
+| "flowrate" | Total flow rate in liquid units | Only for TA4 Pumps |
| "action" | player-name, action-string | Only for Sensor Chests |
| "stacks" | Array with up to 4 Stores with the inventory content (see example) | Only for Sensor Chests |
| "count" | number | Read the item counter of the TA4 Item Detector block |
| "count" | number of items | Read the total amount of TA4 chest items. An optional number as `add_data` is used to address only one inventory slot (1..8, from left to right). |
| "itemstring" | item string of the given slot | Specific command for the TA4 8x2000 Chest to read the item type (technical name) of one chest slot, specified via `add_data` (1..8).
Example: s = $send_cmnd("223", "itemstring", 1) |
| "output" | recipe output string,
e.g.: "default:glass" | Only for the Industrial Furnace. If no recipe is active, the command returns "unknown" |
+| "input" | `` | Read a recipe from the TA4 Recipe Block. `` is the number of the recipe. The block return a list of recipe items. |
@@ -385,19 +388,25 @@ Please note, that this is not a technical distinction, only a logical.
| -------------------------------- | ------------ | ------------------------------------------------------------ |
| "on", "off" | nil | turn a node on/off (machine, lamp,...) |
| "red, "amber", "green", "off" | nil | set Signal Tower color |
-| "port" | `=on/off` | Enable/disable a Distributor filter slot..
Example: `yellow=on`
colors: "red", "green", "blue", "yellow" |
+| "red, "amber", "green", "off" | lamp number (1..4) | Set the signal lamp color. Valid for "TA4 2x Signal Lamp" and "TA4 4x Signal Lamp" |
+| "port" | string
`=on/off` | Enable/disable a Distributor filter slot..
Example: `"yellow=on"`
colors: red, green, blue, yellow |
| "text" | text string | Text to be used for the Sensor Chest menu |
| "reset" | nil | Reset the item counter of the TA4 Item Detector block |
| "pull" | item string | Start the TA4 pusher to pull/push items.
Example: `default:dirt 8` |
| "config" | item string | Configure the TA4 pusher.
Example: `wool:blue` |
| "exchange" | inventory slot number | place/remove/exchange an block by means of the TA3 Door Controller II (techage:ta3_doorcontroller2) |
-
-
-
-* `$display(num, row, text)` Send a text string to the display with number _num_. _row_ is the display row, a value from 1 to 5, or 0 to add the text string at the bottom (scroll screen mode). _text_ is the string to be displayed. If the first char of the string is a blank, the text will be horizontally centered.
-* `$clear_screen(num)` Clear the screen of the display with number _num_.
-* `$position(num)` Returns the position as string "'(x,y,z)" of the device with the given _num_.
-
+| "a2b" | nil | TA4 Move Controller command to move the block(s) from position A to B |
+| "b2a" | nil | TA4 Move Controller command to move the block(s) from position B to A |
+| "move" | nil | TA4 Move Controller command to move the block(s) to the opposite position |
+| "left" | nil | TA4 Turn Controller command to turn the block(s) to the left |
+| "right" | nil | TA4 Turn Controller command to turn the block(s) to the right |
+| "uturn" | nil | TA4 Turn Controller command to turn the block(s) 180 degrees |
+| "recipe" | `,,...` | Set the TA4 Autocrafter recipe.
Example for the torch recipe: `default:coal_lump,,,default:stick`
Hint: Empty fields may only be left out at the end of the item list! |
+| "recipe" | `.` | Set the TA4 Autocrafter recipe with a recipe from a TA4 Recipe Block.
`` is the TA4 Recipe Block number
`` is the number of the recipe in the TA4 Recipe Block |
+| "goto" | `` | Start command for the TA4 Sequencer. `` is the time slot like `[1]` where the execution starts. |
+| "stop" | nil | Stop command for the TA4 Sequencer. |
+| "gain" | volume | Set volume of the sound block (`volume` is a value between 0 and 1.0) |
+| "sound" | index | Select sound sample of the sound block |
### Server and Terminal Functions
@@ -414,25 +423,27 @@ In contrast the Controller can send text strings to the terminal.
- `$get_term()` - Read a text command received from the Terminal
- `$put_term(num, text)` - Send a text string to the Terminal. _num_ is the number of the Terminal.
-
-### Further Functions
+### Communication between Lua Controllers
Messages are used to transport data between Controllers. Messages can contain arbitrary data. Incoming messages are stored in order (up to 10) and can be read one after the other.
+
* `$get_msg([raw])` - Read a received message. The function returns the sender number and the message. (see example "Emails"). If the _raw_ parameter is not set or false, the message is guaranteed to be a string.
* `$send_msg(num, msg)` - Send a message to another Controller. _num_ is the destination number. (see example "Emails")
-* `$chat(text)` - Send yourself a chat message. _text_ is a text string.
+### Further Functions
+* `$chat(text)` - Send yourself a chat message. _text_ is a text string.
* `$door(pos, text)` - Open/Close a door at position "pos".
Example: `$door("123,7,-1200", "close")`.
Hint: Use the Techage Info Tool to determine the door position.
-
* `$item_description("default:apple")`
Get the description (item name) for a specified itemstring, e. g. determined via the TA4 8x2000 Chest command `itemstring`:
`str = $send_cmnd("223", "itemstring", 1)`
`descr = $item_description(str)`
-
+* `$display(num, row, text)` Send a text string to the display with number _num_. _row_ is the display row, a value from 1 to 5, or 0 to add the text string at the bottom (scroll screen mode). _text_ is the string to be displayed. If the first char of the string is a blank, the text will be horizontally centered.
+* `$clear_screen(num)` Clear the screen of the display with number _num_.
+* `$position(num)` Returns the position as string "'(x,y,z)" of the device with the given _num_.
## Example Scripts
@@ -662,7 +673,7 @@ loop() code:
-- read from Terminal and send the message
s = $get_term()
if s then
- name,text = unpack(string.split(s, ":", false, 1))
+ name,text = string.split2(s, ":", false, 1)
num = $server_read(SERVER, name)
if num then
$send_msg(num, text)
diff --git a/techage/manuals/ta4_lua_controller_EN.pdf b/techage/manuals/ta4_lua_controller_EN.pdf
index 73fca67..c030a4b 100644
Binary files a/techage/manuals/ta4_lua_controller_EN.pdf and b/techage/manuals/ta4_lua_controller_EN.pdf differ
diff --git a/techage/manuals/toc_DE.md b/techage/manuals/toc_DE.md
index 2f0702c..e1c7aa8 100644
--- a/techage/manuals/toc_DE.md
+++ b/techage/manuals/toc_DE.md
@@ -116,6 +116,7 @@
- [Tür/Tor Blöcke / Door/Gate Blocks](./manual_ta3_DE.md#türtor-blöcke--doorgate-blocks)
- [TA3 Tür Controller / Door Controller](./manual_ta3_DE.md#ta3-tür-controller--door-controller)
- [TA3 Tür Controller II / Door Controller II](./manual_ta3_DE.md#ta3-tür-controller-ii--door-controller-ii)
+ - [TA3 Sound Block](./manual_ta3_DE.md#ta3-sound-block)
- [TA3 Mesecons Umsetzer / TA3 Mesecons Converter](./manual_ta3_DE.md#ta3-mesecons-umsetzer--ta3-mesecons-converter)
- [Detektoren](./manual_ta3_DE.md#detektoren)
- [TA3 Detektor / Detector](./manual_ta3_DE.md#ta3-detektor--detector)
@@ -137,7 +138,7 @@
- [TechAge Programmer](./manual_ta3_DE.md#techage-programmer)
- [TechAge Kelle / Trowel](./manual_ta3_DE.md#techage-kelle--trowel)
- [TA3 Bohrgestängezange / TA3 Drill Pipe Wrench](./manual_ta3_DE.md#ta3-bohrgestängezange--ta3-drill-pipe-wrench)
-- [TA4: Zukunft](./manual_ta4_DE.md#ta4:-zukunft)
+- [TA4: Gegenwart](./manual_ta4_DE.md#ta4:-gegenwart)
- [Windkraftanlage](./manual_ta4_DE.md#windkraftanlage)
- [TA4 Windkraftanlage / Wind Turbine](./manual_ta4_DE.md#ta4-windkraftanlage--wind-turbine)
- [TA4 Windkraftanlagengondel / Wind Turbine Nacelle](./manual_ta4_DE.md#ta4-windkraftanlagengondel--wind-turbine-nacelle)
@@ -182,12 +183,17 @@
- [TA4 Lua Controller Terminal](./manual_ta4_DE.md#ta4-lua-controller-terminal)
- [TA4 Logik-/Schalt-Module](./manual_ta4_DE.md#ta4-logik-schalt-module)
- [TA4 Taster/Schalter / Button/Switch](./manual_ta4_DE.md#ta4-tasterschalter--buttonswitch)
+ - [TA4 2x Taster / 2x Button](./manual_ta4_DE.md#ta4-2x-taster--2x-button)
- [TA4 4x Taster / 4x Button](./manual_ta4_DE.md#ta4-4x-taster--4x-button)
+ - [TA4 2x Signallampe / 2x Signal Lamp](./manual_ta4_DE.md#ta4-2x-signallampe--2x-signal-lamp)
+ - [TA4 4x Signallampe / 4x Signal Lamp](./manual_ta4_DE.md#ta4-4x-signallampe--4x-signal-lamp)
- [TA4 Spieler Detektor / Player Detector](./manual_ta4_DE.md#ta4-spieler-detektor--player-detector)
- [TA4 Zustandssammler / State Collector](./manual_ta4_DE.md#ta4-zustandssammler--state-collector)
- [TA4 Detektor / Detector](./manual_ta4_DE.md#ta4-detektor--detector)
- - [TA4 Move Controller](./manual_ta4_DE.md#ta4-move-controller)
- [TA4 Sequenzer](./manual_ta4_DE.md#ta4-sequenzer)
+ - [Move/Dreh-Controller](./manual_ta4_DE.md#movedreh-controller)
+ - [TA4 Move Controller](./manual_ta4_DE.md#ta4-move-controller)
+ - [TA4 Drehcontroller / Turn Controller](./manual_ta4_DE.md#ta4-drehcontroller--turn-controller)
- [TA4 Lampen](./manual_ta4_DE.md#ta4-lampen)
- [TA4 LED Pflanzenlampe / TA4 LED Grow Light](./manual_ta4_DE.md#ta4-led-pflanzenlampe--ta4-led-grow-light)
- [TA4 LED Straßenlampe / TA4 LED Street Lamp](./manual_ta4_DE.md#ta4-led-straßenlampe--ta4-led-street-lamp)
@@ -196,7 +202,13 @@
- [Fundament-Ebene](./manual_ta4_DE.md#fundament-ebene)
- [Schotter-Ebene](./manual_ta4_DE.md#schotter-ebene)
- [Einfüll-Ebene](./manual_ta4_DE.md#einfüll-ebene)
+ - [TA4 Teilchenbeschleuniger / Collider](./manual_ta4_DE.md#ta4-teilchenbeschleuniger--collider)
+ - [Detektor](./manual_ta4_DE.md#detektor)
+ - [Steuerung / TA4 Terminal](./manual_ta4_DE.md#steuerung--ta4-terminal)
+ - [Aufbau](./manual_ta4_DE.md#aufbau)
- [Weitere TA4 Blöcke](./manual_ta4_DE.md#weitere-ta4-blöcke)
+ - [TA4 Rezept Block](./manual_ta4_DE.md#ta4-rezept-block)
+ - [TA4 Autocrafter](./manual_ta4_DE.md#ta4-autocrafter)
- [TA4 Tank / TA4 Tank](./manual_ta4_DE.md#ta4-tank--ta4-tank)
- [TA4 Pumpe / TA4 Pump](./manual_ta4_DE.md#ta4-pumpe--ta4-pump)
- [TA4 Ofenheizung / furnace heater](./manual_ta4_DE.md#ta4-ofenheizung--furnace-heater)
@@ -213,4 +225,21 @@
- [TA4 Steinbrecher / Quarry](./manual_ta4_DE.md#ta4-steinbrecher--quarry)
- [TA4 Elektronikfabrik / Electronic Fab](./manual_ta4_DE.md#ta4-elektronikfabrik--electronic-fab)
- [TA4 Injektor / Injector](./manual_ta4_DE.md#ta4-injektor--injector)
- - [TA4 Recycler](./manual_ta4_DE.md#ta4-recycler)
\ No newline at end of file
+ - [TA4 Recycler](./manual_ta4_DE.md#ta4-recycler)
+- [TA5: Zukunft](./manual_ta5_DE.md#ta5:-zukunft)
+ - [Energiequellen](./manual_ta5_DE.md#energiequellen)
+ - [TA5 Fusionsreaktor (geplant)](./manual_ta5_DE.md#ta5-fusionsreaktor-(geplant))
+ - [Energiespeicher](./manual_ta5_DE.md#energiespeicher)
+ - [TA5 Hybrid-Speicher (geplant)](./manual_ta5_DE.md#ta5-hybrid-speicher-(geplant))
+ - [Logik Blöcke](./manual_ta5_DE.md#logik-blöcke)
+ - [Transport und Verkehr](./manual_ta5_DE.md#transport-und-verkehr)
+ - [TA5 Flug Controller](./manual_ta5_DE.md#ta5-flug-controller)
+ - [TA5 Hyperloop Kiste / TA5 Hyperloop Chest](./manual_ta5_DE.md#ta5-hyperloop-kiste--ta5-hyperloop-chest)
+ - [TA5 Hyperloop Tank / TA5 Hyperloop Tank](./manual_ta5_DE.md#ta5-hyperloop-tank--ta5-hyperloop-tank)
+ - [Hyperloop Teleport Blöcke (geplant)](./manual_ta5_DE.md#hyperloop-teleport-blöcke-(geplant))
+ - [TA5 Container (geplant)](./manual_ta5_DE.md#ta5-container-(geplant))
+ - [TA5 Teleport Block Gegenstände / TA5 Teleport Block Items](./manual_ta5_DE.md#ta5-teleport-block-gegenstände--ta5-teleport-block-items)
+ - [TA5 Teleport Block Flüssigkeiten / TA5 Teleport Block Liquids](./manual_ta5_DE.md#ta5-teleport-block-flüssigkeiten--ta5-teleport-block-liquids)
+ - [TA5-Raumgleiter (geplant)](./manual_ta5_DE.md#ta5-raumgleiter-(geplant))
+ - [Weitere TA5 Blöcke/Items](./manual_ta5_DE.md#weitere-ta5-blöckeitems)
+ - [TA5 KI Chip / TA5 AI Chip](./manual_ta5_DE.md#ta5-ki-chip--ta5-ai-chip)
\ No newline at end of file
diff --git a/techage/manuals/toc_EN.md b/techage/manuals/toc_EN.md
index be1c999..d2e59e5 100644
--- a/techage/manuals/toc_EN.md
+++ b/techage/manuals/toc_EN.md
@@ -116,6 +116,7 @@
- [Door/Gate Blocks](./manual_ta3_EN.md#doorgate-blocks)
- [TA3 Door Controller](./manual_ta3_EN.md#ta3-door-controller)
- [TA3 Door Controller II](./manual_ta3_EN.md#ta3-door-controller-ii)
+ - [TA3 Sound Block](./manual_ta3_EN.md#ta3-sound-block)
- [TA3 Mesecons Converter](./manual_ta3_EN.md#ta3-mesecons-converter)
- [Detectors](./manual_ta3_EN.md#detectors)
- [TA3 Detector](./manual_ta3_EN.md#ta3-detector)
@@ -137,7 +138,7 @@
- [TechAge Programmer](./manual_ta3_EN.md#techage-programmer)
- [TechAge Trowel / Trowel](./manual_ta3_EN.md#techage-trowel--trowel)
- [TA3 drill pipe wrench](./manual_ta3_EN.md#ta3-drill-pipe-wrench)
-- [TA4: Future](./manual_ta4_EN.md#ta4:-future)
+- [TA4: Present](./manual_ta4_EN.md#ta4:-present)
- [Wind Turbine](./manual_ta4_EN.md#wind-turbine)
- [TA4 Wind Turbine](./manual_ta4_EN.md#ta4-wind-turbine)
- [TA4 Wind Turbine Nacelle](./manual_ta4_EN.md#ta4-wind-turbine-nacelle)
@@ -182,12 +183,17 @@
- [TA4 Lua Controller Terminal](./manual_ta4_EN.md#ta4-lua-controller-terminal)
- [TA4 Logic/Switching Modules](./manual_ta4_EN.md#ta4-logicswitching-modules)
- [TA4 Button/Switch](./manual_ta4_EN.md#ta4-buttonswitch)
+ - [TA4 2x Button](./manual_ta4_EN.md#ta4-2x-button)
- [TA4 4x Button](./manual_ta4_EN.md#ta4-4x-button)
+ - [TA4 2x Signal Lamp](./manual_ta4_EN.md#ta4-2x-signal-lamp)
+ - [TA4 4x Signal Lamp](./manual_ta4_EN.md#ta4-4x-signal-lamp)
- [TA4 Player Detector](./manual_ta4_EN.md#ta4-player-detector)
- [TA4 State Collector](./manual_ta4_EN.md#ta4-state-collector)
- [TA4 Detector](./manual_ta4_EN.md#ta4-detector)
- - [TA4 Move Controller](./manual_ta4_EN.md#ta4-move-controller)
- [TA4 Sequencer](./manual_ta4_EN.md#ta4-sequencer)
+ - [Move/Turn Controller](./manual_ta4_EN.md#moveturn-controller)
+ - [TA4 Move Controller](./manual_ta4_EN.md#ta4-move-controller)
+ - [TA4 Turn Controller](./manual_ta4_EN.md#ta4-turn-controller)
- [TA4 Lamps](./manual_ta4_EN.md#ta4-lamps)
- [TA4 LED Grow Light](./manual_ta4_EN.md#ta4-led-grow-light)
- [TA4 Street Lamp](./manual_ta4_EN.md#ta4-street-lamp)
@@ -196,7 +202,13 @@
- [Base Layer](./manual_ta4_EN.md#base-layer)
- [Gravel Layer](./manual_ta4_EN.md#gravel-layer)
- [Filling Layer](./manual_ta4_EN.md#filling-layer)
+ - [TA4 Collider (Particle Accelerator)](./manual_ta4_EN.md#ta4-collider-(particle-accelerator))
+ - [Detector](./manual_ta4_EN.md#detector)
+ - [Control / TA4 Terminal](./manual_ta4_EN.md#control--ta4-terminal)
+ - [Construction](./manual_ta4_EN.md#construction)
- [More TA4 Blocks](./manual_ta4_EN.md#more-ta4-blocks)
+ - [TA4 Recipe Block](./manual_ta4_EN.md#ta4-recipe-block)
+ - [TA4 Autocrafter](./manual_ta4_EN.md#ta4-autocrafter)
- [TA4 Tank](./manual_ta4_EN.md#ta4-tank)
- [TA4 Pump](./manual_ta4_EN.md#ta4-pump)
- [TA4 Furnace Heater](./manual_ta4_EN.md#ta4-furnace-heater)
@@ -213,4 +225,20 @@
- [TA4 Quarry](./manual_ta4_EN.md#ta4-quarry)
- [TA4 Electronic Fab](./manual_ta4_EN.md#ta4-electronic-fab)
- [TA4 Injector](./manual_ta4_EN.md#ta4-injector)
- - [TA4 Recycler](./manual_ta4_EN.md#ta4-recycler)
\ No newline at end of file
+ - [TA4 Recycler](./manual_ta4_EN.md#ta4-recycler)
+- [TA5: Future](./manual_ta5_EN.md#ta5:-future)
+ - [Energy Sources](./manual_ta5_EN.md#energy-sources)
+ - [TA5 Fusion Reactor (planned)](./manual_ta5_EN.md#ta5-fusion-reactor-(planned))
+ - [Energy Storage](./manual_ta5_EN.md#energy-storage)
+ - [TA5 Hybrid Storage (planned)](./manual_ta5_EN.md#ta5-hybrid-storage-(planned))
+ - [Logic blocks](./manual_ta5_EN.md#logic-blocks)
+ - [Transport and Traffic](./manual_ta5_EN.md#transport-and-traffic)
+ - [TA5 Flight Controller](./manual_ta5_EN.md#ta5-flight-controller)
+ - [TA5 Hyperloop Chest](./manual_ta5_EN.md#ta5-hyperloop-chest)
+ - [TA5 Hyperloop Tank](./manual_ta5_EN.md#ta5-hyperloop-tank)
+ - [Hyperloop Teleport Blocks (planned)](./manual_ta5_EN.md#hyperloop-teleport-blocks-(planned))
+ - [TA5 Container (planned)](./manual_ta5_EN.md#ta5-container-(planned))
+ - [TA5 Teleport Block Items](./manual_ta5_EN.md#ta5-teleport-block-items)
+ - [TA5 Teleport Block Liquids](./manual_ta5_EN.md#ta5-teleport-block-liquids)
+ - [More TA5 Blocks / Items](./manual_ta5_EN.md#more-ta5-blocks--items)
+ - [TA5 AI Chip](./manual_ta5_EN.md#ta5-ai-chip)
\ No newline at end of file
diff --git a/techage/mod.conf b/techage/mod.conf
index fde06d4..4fae9d8 100644
--- a/techage/mod.conf
+++ b/techage/mod.conf
@@ -1,4 +1,4 @@
name = techage
depends = default,doors,flowers,tubelib2,networks,basic_materials,bucket,stairs,screwdriver,minecart,lcdlib,safer_lua
-optional_depends = unified_inventory,wielded_light,unifieddyes,moreores,ethereal,mesecon,digtron,bakedclay,moreblocks
-description = Techage, go through 4 tech ages in search of wealth and power!
+optional_depends = unified_inventory,wielded_light,unifieddyes,moreores,ethereal,mesecon,digtron,bakedclay,moreblocks,i3
+description = Techage, go through 5 tech ages in search of wealth and power!
diff --git a/techage/logic/doorblock.lua b/techage/move_controller/doorblock.lua
similarity index 100%
rename from techage/logic/doorblock.lua
rename to techage/move_controller/doorblock.lua
diff --git a/techage/logic/doorcontroller.lua b/techage/move_controller/doorcontroller.lua
similarity index 100%
rename from techage/logic/doorcontroller.lua
rename to techage/move_controller/doorcontroller.lua
diff --git a/techage/logic/doorcontroller2.lua b/techage/move_controller/doorcontroller2.lua
similarity index 98%
rename from techage/logic/doorcontroller2.lua
rename to techage/move_controller/doorcontroller2.lua
index 9b3e916..2ab46ef 100644
--- a/techage/logic/doorcontroller2.lua
+++ b/techage/move_controller/doorcontroller2.lua
@@ -179,7 +179,7 @@ local function exchange_nodes(pos, nvm, slot)
for idx = (slot or 1), (slot or 16) do
local pos = nvm.pos_list[idx]
- if pos and not minetest.is_protected(pos, owner) then
+ if pos then
item_list[idx], nvm.param2_list[idx] = exchange_node(pos, item_list[idx], nvm.param2_list[idx])
res = true
end
@@ -381,7 +381,9 @@ minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing)
return
end
- mark_position(name, pointed_thing.under)
+ if not minetest.is_protected(pointed_thing.under, name) then
+ mark_position(name, pointed_thing.under)
+ end
end
end)
diff --git a/techage/move_controller/flycontroller.lua b/techage/move_controller/flycontroller.lua
new file mode 100644
index 0000000..a1db0fd
--- /dev/null
+++ b/techage/move_controller/flycontroller.lua
@@ -0,0 +1,241 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2020-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Move Controller
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
+local S2P = minetest.string_to_pos
+local S = techage.S
+
+local MP = minetest.get_modpath("techage")
+local fly = dofile(MP .. "/basis/fly_lib.lua")
+local mark = dofile(MP .. "/basis/mark_lib.lua")
+
+local MAX_DIST = 500
+local MAX_BLOCKS = 16
+local EX_POINTS = 40
+
+local WRENCH_MENU = {
+ {
+ type = "dropdown",
+ choices = "0.5,1,2,4,6,8",
+ name = "max_speed",
+ label = S("Maximum Speed"),
+ tooltip = S("Maximum speed for moving blocks"),
+ default = "8",
+ },
+ {
+ type = "float",
+ name = "height",
+ label = S("Move block height"),
+ tooltip = S("Value in the range of 0.0 to 1.0"),
+ default = "1.0",
+ },
+}
+
+local function formspec(nvm, meta)
+ local status = meta:get_string("status")
+ local path = meta:contains("path") and meta:get_string("path") or "0,3,0"
+ return "size[8,6.7]" ..
+ "style_type[textarea;font=mono;textcolor=#FFFFFF;border=true]" ..
+ "box[0,-0.1;7.2,0.5;#c6e8ff]" ..
+ "label[0.2,-0.1;" .. minetest.colorize( "#000000", S("TA5 Fly Controller")) .. "]" ..
+ techage.wrench_image(7.4, -0.05) ..
+ "button[0.1,0.7;3.8,1;record;" .. S("Record") .. "]" ..
+ "button[4.1,0.7;3.8,1;done;" .. S("Done") .. "]" ..
+ "textarea[0.4,2.1;3.8,4.4;path;" .. S("Flight route (A to B)") .. ";"..path.."]" ..
+ "button[4.1,1.8;3.8,1;store;" .. S("Store") .. "]" ..
+ "button[4.1,2.6;3.8,1;test;" .. S("Test") .. "]" ..
+ "button[4.1,3.4;3.8,1;moveAB;" .. S("Move A-B") .. "]" ..
+ "button[4.1,4.2;3.8,1;moveBA;" .. S("Move B-A") .. "]" ..
+ "button[4.1,5.0;3.8,1;move;" .. S("Move") .. "]" ..
+ "label[0.3,6.3;" .. status .. "]"
+end
+
+
+minetest.register_node("techage:ta5_flycontroller", {
+ description = S("TA5 Fly Controller"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_filling_ta4.png^techage_frame_ta5_top.png",
+ "techage_filling_ta4.png^techage_frame_ta5_top.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_movecontroller.png",
+ },
+
+ after_place_node = function(pos, placer, itemstack)
+ local meta = M(pos)
+ techage.logic.after_place_node(pos, placer, "techage:ta5_flycontroller", S("TA5 Fly Controller"))
+ techage.logic.infotext(meta, S("TA5 Fly Controller"))
+ local nvm = techage.get_nvm(pos)
+ meta:set_string("formspec", formspec(nvm, meta))
+ end,
+
+ on_receive_fields = function(pos, formname, fields, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return
+ end
+ if techage.get_expoints(player) < EX_POINTS then
+ return
+ end
+
+ local meta = M(pos)
+ local nvm = techage.get_nvm(pos)
+
+ if fields.record then
+ nvm.lpos1 = {}
+ nvm.lpos2 = {}
+ nvm.moveBA = false
+ nvm.running = true
+ meta:set_string("status", S("Recording..."))
+ local name = player:get_player_name()
+ minetest.chat_send_player(name, S("Click on all blocks that shall be moved"))
+ mark.start(name, MAX_BLOCKS)
+ meta:set_string("formspec", formspec(nvm, meta))
+ elseif fields.done then
+ local name = player:get_player_name()
+ local pos_list = mark.get_poslist(name)
+ local _, err = fly.to_path(fields.path, MAX_DIST)
+ if not err then
+ meta:set_string("path", fields.path)
+ end
+ nvm.running = false
+ local text = #pos_list.." "..S("block positions are stored.")
+ meta:set_string("status", text)
+ nvm.lpos1 = pos_list
+ mark.unmark_all(name)
+ mark.stop(name)
+ meta:set_string("formspec", formspec(nvm, meta))
+ elseif fields.store then
+ local _, err = fly.to_path(fields.path, MAX_DIST)
+ if not err then
+ meta:set_string("path", fields.path)
+ meta:set_string("status", S("Stored"))
+ else
+ meta:set_string("status", err)
+ end
+ meta:set_string("formspec", formspec(nvm, meta))
+ local name = player:get_player_name()
+ mark.stop(name)
+ nvm.moveBA = false
+ nvm.running = true
+ elseif fields.test then
+ local path, err = fly.to_path(fields.path, MAX_DIST)
+ if err then
+ meta:set_string("status", err)
+ elseif path and nvm.lpos1 then
+ local pos = table.copy(nvm.lpos1[1])
+ if pos then
+ for _, offs in ipairs(path) do
+ local pos2 = vector.add(pos, offs)
+ local s = string.format("[TA4 Fly Controller] %s + %s = %s", P2S(pos), P2S(offs), P2S(pos2))
+ minetest.chat_send_player(player:get_player_name(), s)
+ pos = pos2
+ end
+ meta:set_string("status", S("See chat output"))
+ else
+ minetest.chat_send_player(player:get_player_name(), S("[TA4 Fly Controller] Recording is missing!"))
+ meta:set_string("status", S("Error: Recording is missing !!"))
+ end
+ else
+ if nvm.lpos1 then
+ minetest.chat_send_player(player:get_player_name(), S("[TA4 Fly Controller] Invalid path!"))
+ meta:set_string("status", S("Error: Invalid path !!"))
+ else
+ minetest.chat_send_player(player:get_player_name(), S("[TA4 Fly Controller] Recording is missing!"))
+ meta:set_string("status", S("Error: Recording is missing !!"))
+ end
+ end
+ meta:set_string("formspec", formspec(nvm, meta))
+ elseif fields.moveAB then
+ meta:set_string("status", "")
+ if fly.move_to_other_pos(pos, false) then
+ nvm.moveBA = true
+ nvm.running = true
+ meta:set_string("formspec", formspec(nvm, meta))
+ local name = player:get_player_name()
+ mark.stop(name)
+ end
+ meta:set_string("formspec", formspec(nvm, meta))
+ elseif fields.moveBA then
+ meta:set_string("status", "")
+ if fly.move_to_other_pos(pos, true) then
+ nvm.moveBA = false
+ nvm.running = true
+ meta:set_string("formspec", formspec(nvm, meta))
+ local name = player:get_player_name()
+ mark.stop(name)
+ end
+ meta:set_string("formspec", formspec(nvm, meta))
+ elseif fields.move then
+ meta:set_string("status", "")
+ nvm.moveBA = nvm.moveBA == false
+ if fly.move_to_other_pos(pos, nvm.moveBA == false) then
+ nvm.moveBA = nvm.moveBA == false
+ nvm.running = true
+ meta:set_string("formspec", formspec(nvm, meta))
+ local name = player:get_player_name()
+ mark.stop(name)
+ end
+ meta:set_string("formspec", formspec(nvm, meta))
+ end
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata, digger)
+ local name = digger:get_player_name()
+ mark.unmark_all(name)
+ mark.stop(name)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ end,
+
+ ta5_formspec = {menu=WRENCH_MENU, ex_points=EX_POINTS},
+ paramtype2 = "facedir",
+ groups = {choppy=2, cracky=2, crumbly=2},
+ is_ground_content = false,
+ sounds = default.node_sound_wood_defaults(),
+})
+
+local INFO = [[Commands: 'state', 'a2b', 'b2a', 'move']]
+
+techage.register_node({"techage:ta5_flycontroller"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ local nvm = techage.get_nvm(pos)
+ if topic == "info" then
+ return INFO
+ elseif topic == "state" then
+ return nvm.running and "running" or "stopped"
+ elseif topic == "a2b" then
+ nvm.moveBA = true
+ nvm.running = true
+ return fly.move_to_other_pos(pos, false)
+ elseif topic == "b2a" then
+ nvm.moveBA = false
+ nvm.running = true
+ return fly.move_to_other_pos(pos, true)
+ elseif topic == "move" then
+ nvm.moveBA = nvm.moveBA == false
+ nvm.running = true
+ return fly.move_to_other_pos(pos, nvm.moveBA == false)
+ end
+ return false
+ end,
+})
+
+minetest.register_craft({
+ output = "techage:ta5_flycontroller",
+ recipe = {
+ {"default:steel_ingot", "dye:red", "default:steel_ingot"},
+ {"techage:aluminum", "techage:ta5_aichip", "techage:aluminum"},
+ {"group:wood", "basic_materials:gear_steel", "group:wood"},
+ },
+})
diff --git a/techage/logic/gateblock.lua b/techage/move_controller/gateblock.lua
similarity index 100%
rename from techage/logic/gateblock.lua
rename to techage/move_controller/gateblock.lua
diff --git a/techage/move_controller/movecontroller.lua b/techage/move_controller/movecontroller.lua
new file mode 100644
index 0000000..e72d918
--- /dev/null
+++ b/techage/move_controller/movecontroller.lua
@@ -0,0 +1,216 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2020-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Move Controller
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
+local S2P = minetest.string_to_pos
+local S = techage.S
+
+local MP = minetest.get_modpath("techage")
+local fly = dofile(MP .. "/basis/fly_lib.lua")
+local mark = dofile(MP .. "/basis/mark_lib.lua")
+
+local MAX_DIST = 100
+local MAX_BLOCKS = 16
+
+local WRENCH_MENU = {
+ {
+ type = "dropdown",
+ choices = "0.5,1,2,4,6,8",
+ name = "max_speed",
+ label = S("Maximum Speed"),
+ tooltip = S("Maximum speed for moving blocks"),
+ default = "8",
+ },
+ {
+ type = "number",
+ name = "handoverB",
+ label = S("Handover to B"),
+ tooltip = S("Number of the next movecontroller"),
+ default = "",
+ },
+ {
+ type = "number",
+ name = "handoverA",
+ label = S("Handover to A"),
+ tooltip = S("Number of the previous movecontroller"),
+ default = "",
+ },
+ {
+ type = "float",
+ name = "height",
+ label = S("Move block height"),
+ tooltip = S("Value in the range of 0.0 to 1.0"),
+ default = "1.0",
+ },
+ {
+ type = "float",
+ name = "offset",
+ label = S("Object offset"),
+ tooltip = S("Y-offset for non-player objects like vehicles (-0.5 to 0.5)"),
+ default = "0.0",
+ },
+}
+
+local function formspec(nvm, meta)
+ local status = meta:get_string("status")
+ local path = meta:contains("path") and meta:get_string("path") or "0,3,0"
+ return "size[8,5]" ..
+ default.gui_bg ..
+ default.gui_bg_img ..
+ default.gui_slots ..
+ "box[0,-0.1;7.2,0.5;#c6e8ff]" ..
+ "label[0.2,-0.1;" .. minetest.colorize( "#000000", S("TA4 Move Controller")) .. "]" ..
+ techage.wrench_image(7.4, -0.05) ..
+ "button[0.1,0.8;3.8,1;record;" .. S("Record") .. "]" ..
+ "button[4.1,0.8;3.8,1;done;" .. S("Done") .. "]" ..
+ "field[0.4,2.5;3.8,1;path;" .. S("Move distance (A to B)") .. ";" .. path .. "]" ..
+ "button[4.1,2.2;3.8,1;store;" .. S("Store") .. "]" ..
+ "button_exit[0.1,3.3;3.8,1;moveAB;" .. S("Move A-B") .. "]" ..
+ "button_exit[4.1,3.3;3.8,1;moveBA;" .. S("Move B-A") .. "]" ..
+ "label[0.3,4.3;" .. status .. "]"
+end
+
+minetest.register_node("techage:ta4_movecontroller", {
+ description = S("TA4 Move Controller"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_filling_ta4.png^techage_frame_ta4_top.png",
+ "techage_filling_ta4.png^techage_frame_ta4_top.png",
+ "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_movecontroller.png",
+ },
+
+ after_place_node = function(pos, placer, itemstack)
+ local meta = M(pos)
+ techage.logic.after_place_node(pos, placer, "techage:ta4_movecontroller", S("TA4 Move Controller"))
+ techage.logic.infotext(meta, S("TA4 Move Controller"))
+ local nvm = techage.get_nvm(pos)
+ meta:set_string("formspec", formspec(nvm, meta))
+ end,
+
+ on_receive_fields = function(pos, formname, fields, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return
+ end
+
+ local meta = M(pos)
+ local nvm = techage.get_nvm(pos)
+
+ if fields.record then
+ nvm.lpos1 = {}
+ nvm.lpos2 = {}
+ nvm.moveBA = false
+ nvm.running = true
+ meta:set_string("status", S("Recording..."))
+ local name = player:get_player_name()
+ minetest.chat_send_player(name, S("Click on all blocks that shall be moved"))
+ mark.start(name, MAX_BLOCKS)
+ meta:set_string("formspec", formspec(nvm, meta))
+ elseif fields.done then
+ local name = player:get_player_name()
+ local pos_list = mark.get_poslist(name)
+ if fly.to_vector(fields.path or "", MAX_DIST) then
+ meta:set_string("path", fields.path)
+ end
+ local text = #pos_list.." "..S("block positions are stored.")
+ nvm.running = false
+ meta:set_string("status", text)
+ nvm.lpos1 = pos_list
+ mark.unmark_all(name)
+ mark.stop(name)
+ meta:set_string("formspec", formspec(nvm, meta))
+ elseif fields.store then
+ if fly.to_vector(fields.path or "", MAX_DIST) then
+ meta:set_string("path", fields.path)
+ meta:set_string("status", S("Stored"))
+ else
+ meta:set_string("status", S("Error: Invalid distance !!"))
+ end
+ meta:set_string("formspec", formspec(nvm, meta))
+ local name = player:get_player_name()
+ mark.stop(name)
+ nvm.moveBA = false
+ nvm.running = true
+ elseif fields.moveAB then
+ meta:set_string("status", "")
+ if fly.move_to_other_pos(pos, false) then
+ nvm.moveBA = true
+ nvm.running = true
+ meta:set_string("formspec", formspec(nvm, meta))
+ local name = player:get_player_name()
+ mark.stop(name)
+ end
+ meta:set_string("formspec", formspec(nvm, meta))
+ elseif fields.moveBA then
+ meta:set_string("status", "")
+ if fly.move_to_other_pos(pos, true) then
+ nvm.moveBA = false
+ nvm.running = true
+ meta:set_string("formspec", formspec(nvm, meta))
+ local name = player:get_player_name()
+ mark.stop(name)
+ end
+ meta:set_string("formspec", formspec(nvm, meta))
+ end
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata, digger)
+ local name = digger:get_player_name()
+ mark.unmark_all(name)
+ mark.stop(name)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ end,
+
+ ta4_formspec = WRENCH_MENU,
+ paramtype2 = "facedir",
+ groups = {choppy=2, cracky=2, crumbly=2},
+ is_ground_content = false,
+ sounds = default.node_sound_wood_defaults(),
+})
+
+local INFO = [[Commands: 'state', 'a2b', 'b2a', 'move']]
+
+techage.register_node({"techage:ta4_movecontroller"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ local nvm = techage.get_nvm(pos)
+ if topic == "info" then
+ return INFO
+ elseif topic == "state" then
+ return nvm.running and "running" or "stopped"
+ elseif topic == "a2b" then
+ nvm.moveBA = true
+ nvm.running = true
+ return fly.move_to_other_pos(pos, false)
+ elseif topic == "b2a" then
+ nvm.moveBA = false
+ nvm.running = true
+ return fly.move_to_other_pos(pos, true)
+ elseif topic == "move" then
+ nvm.moveBA = nvm.moveBA == false
+ nvm.running = true
+ return fly.move_to_other_pos(pos, nvm.moveBA == false)
+ end
+ return false
+ end,
+})
+
+minetest.register_craft({
+ output = "techage:ta4_movecontroller",
+ recipe = {
+ {"default:steel_ingot", "dye:blue", "default:steel_ingot"},
+ {"default:mese_crystal_fragment", "techage:ta4_wlanchip", "default:mese_crystal_fragment"},
+ {"group:wood", "basic_materials:gear_steel", "group:wood"},
+ },
+})
diff --git a/techage/move_controller/soundblock.lua b/techage/move_controller/soundblock.lua
new file mode 100644
index 0000000..87982bc
--- /dev/null
+++ b/techage/move_controller/soundblock.lua
@@ -0,0 +1,128 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ Sound Block
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local S = techage.S
+
+local t = {}
+for idx, ogg in ipairs(techage.OggFileList) do
+ t[idx] = idx .. "," .. ogg
+end
+local OGG_FILES = table.concat(t, ",")
+
+local logic = techage.logic
+
+local GAIN = {0.05 ,0.1, 0.2, 0.5, 1.0}
+
+
+local function play_sound(pos, ogg, gain)
+ minetest.sound_play(ogg, {
+ pos = pos,
+ gain = GAIN[gain or 1] or 1,
+ max_hear_distance = 15})
+end
+
+local function formspec(meta)
+ local idx = meta:contains("idx") and meta:get_int("idx") or 1
+ local gain = meta:contains("gain") and meta:get_int("gain") or 1
+ return "size[8,8]"..
+ "tablecolumns[text,width=5;text]"..
+ "table[0,0;8,6;oggfiles;" .. OGG_FILES .. ";" .. idx .. "]" ..
+ "dropdown[0,6.5;5.5,1.4;gain;1,2,3,4,5;" .. gain .. "]" ..
+ "button[2.5,7.2;3,1;play;" .. S("Play") .. "]"
+end
+
+minetest.register_node("techage:ta3_soundblock", {
+ description = S("TA3 Sound Block"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_filling_ta3.png^techage_frame_ta3_top.png",
+ "techage_filling_ta3.png^techage_frame_ta3_top.png",
+ "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_sound.png",
+ },
+
+ after_place_node = function(pos, placer)
+ local meta = M(pos)
+ logic.after_place_node(pos, placer, "techage:ta3_soundblock", S("TA3 Sound Block"))
+ logic.infotext(meta, S("TA3 Sound Block"))
+ meta:set_string("formspec", formspec(meta))
+ end,
+
+ on_receive_fields = function(pos, formname, fields, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return
+ end
+
+ if fields.oggfiles then
+ local mem = techage.get_mem(pos)
+ local t = minetest.explode_table_event(fields.oggfiles)
+ mem.idx = t.row
+ end
+ if fields.gain then
+ M(pos):set_int("gain", tonumber(fields.gain) or 1)
+ end
+ if fields.play then
+ local mem = techage.get_mem(pos)
+ M(pos):set_int("idx", mem.idx or 1)
+ local ogg = techage.OggFileList[mem.idx or 1] or techage.OggFileList[1]
+ play_sound(pos, ogg, M(pos):get_int("gain"))
+ end
+ end,
+
+ paramtype2 = "facedir",
+ groups = {choppy=2, cracky=2, crumbly=2},
+ is_ground_content = false,
+ sounds = default.node_sound_wood_defaults(),
+})
+
+local INFO = [[Commands: 'on', 'sound', 'gain']]
+
+techage.register_node({"techage:ta3_soundblock"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ if topic == "info" then
+ return INFO
+ elseif topic == "on" then
+ local mem = techage.get_mem(pos)
+ if not mem.blocking_time or (mem.blocking_time < minetest.get_gametime()) then
+ local idx = M(pos):get_int("idx")
+ local ogg = techage.OggFileList[idx or 1] or techage.OggFileList[1]
+ local gain = M(pos):get_float("gain")
+ play_sound(pos, ogg, gain)
+ mem.blocking_time = minetest.get_gametime() + 2
+ return true
+ end
+ elseif topic == "sound" then
+ M(pos):get_int("idx", tonumber(payload or 1) or 1)
+ elseif topic == "gain" then
+ M(pos):get_int("gain", tonumber(payload or 1) or 1)
+ else
+ return "unsupported"
+ end
+ end,
+ on_node_load = function(pos)
+ local meta = M(pos)
+ meta:set_string("formspec", formspec(meta))
+ end
+})
+
+minetest.register_craft({
+ output = "techage:ta3_soundblock",
+ recipe = {
+ {"", "group:wood",""},
+ {"techage:vacuum_tube", "basic_materials:gold_wire", "techage:usmium_nuggets"},
+ {"", "group:wood", ""},
+ },
+})
+
diff --git a/techage/move_controller/turncontroller.lua b/techage/move_controller/turncontroller.lua
new file mode 100644
index 0000000..fa89f07
--- /dev/null
+++ b/techage/move_controller/turncontroller.lua
@@ -0,0 +1,164 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2020-2021 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA4 Turn Controller
+
+]]--
+
+-- for lazy programmers
+local M = minetest.get_meta
+local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
+local S2P = minetest.string_to_pos
+local S = techage.S
+
+local MP = minetest.get_modpath("techage")
+local fly = dofile(MP .. "/basis/fly_lib.lua")
+local mark = dofile(MP .. "/basis/mark_lib.lua")
+
+local MAX_BLOCKS = 16
+
+local function formspec(nvm, meta)
+ local status = meta:get_string("status")
+ local path = meta:contains("path") and meta:get_string("path") or "0,3,0"
+ return "size[8,3]" ..
+ "box[0,-0.1;7.8,0.5;#c6e8ff]" ..
+ "label[0.2,-0.1;" .. minetest.colorize( "#000000", S("TA4 Turn Controller")) .. "]" ..
+ --techage.wrench_image(7.4, -0.05) ..
+ "button[0.1,0.7;3.8,1;record;" .. S("Record") .. "]" ..
+ "button[4.1,0.7;3.8,1;done;" .. S("Done") .. "]" ..
+ "button[0.1,1.5;3.8,1;left;" .. S("Turn left") .. "]" ..
+ "button[4.1,1.5;3.8,1;right;" .. S("Turn right") .. "]" ..
+ "label[0.3,2.5;" .. status .. "]"
+end
+
+
+minetest.register_node("techage:ta4_turncontroller", {
+ description = S("TA4 Turn Controller"),
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_filling_ta4.png^techage_frame_ta4_top.png",
+ "techage_filling_ta4.png^techage_frame_ta4_top.png",
+ "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_turn.png",
+ },
+
+ after_place_node = function(pos, placer, itemstack)
+ local meta = M(pos)
+ techage.logic.after_place_node(pos, placer, "techage:ta4_turncontroller", S("TA4 Turn Controller"))
+ techage.logic.infotext(meta, S("TA4 Turn Controller"))
+ local nvm = techage.get_nvm(pos)
+ meta:set_string("formspec", formspec(nvm, meta))
+ end,
+
+ on_receive_fields = function(pos, formname, fields, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return
+ end
+
+ local meta = M(pos)
+ local nvm = techage.get_nvm(pos)
+
+ if fields.record then
+ nvm.lpos1 = {}
+ nvm.lpos2 = {}
+ meta:set_string("status", S("Recording..."))
+ local name = player:get_player_name()
+ minetest.chat_send_player(name, S("Click on all blocks that shall be turned"))
+ mark.start(name, MAX_BLOCKS)
+ meta:set_string("formspec", formspec(nvm, meta))
+ elseif fields.done then
+ local name = player:get_player_name()
+ local pos_list = mark.get_poslist(name)
+ local text = #pos_list.." "..S("block positions are stored.")
+ meta:set_string("status", text)
+ nvm.lpos = pos_list
+ mark.unmark_all(name)
+ mark.stop(name)
+ meta:set_string("formspec", formspec(nvm, meta))
+ elseif fields.left then
+ meta:set_string("status", "")
+ local new_posses = fly.rotate_nodes(pos, nvm.lpos, "l")
+ if new_posses then
+ nvm.lpos = new_posses
+ local name = player:get_player_name()
+ mark.stop(name)
+ end
+ meta:set_string("formspec", formspec(nvm, meta))
+ elseif fields.right then
+ meta:set_string("status", "")
+ local new_posses = fly.rotate_nodes(pos, nvm.lpos, "r")
+ if new_posses then
+ nvm.lpos = new_posses
+ local name = player:get_player_name()
+ mark.stop(name)
+ end
+ meta:set_string("formspec", formspec(nvm, meta))
+ end
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata, digger)
+ local name = digger:get_player_name()
+ mark.unmark_all(name)
+ mark.stop(name)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ end,
+
+ paramtype2 = "facedir",
+ groups = {choppy=2, cracky=2, crumbly=2},
+ is_ground_content = false,
+ sounds = default.node_sound_wood_defaults(),
+})
+
+local INFO = [[Commands: 'left', 'right', 'uturn']]
+
+techage.register_node({"techage:ta4_turncontroller"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ if topic == "info" then
+ return INFO
+ elseif topic == "left" then
+ local nvm = techage.get_nvm(pos)
+ local new_posses = fly.rotate_nodes(pos, nvm.lpos, "l")
+ if new_posses then
+ nvm.lpos = new_posses
+ return true
+ end
+ return false
+ elseif topic == "right" then
+ local nvm = techage.get_nvm(pos)
+ local new_posses = fly.rotate_nodes(pos, nvm.lpos, "r")
+ if new_posses then
+ nvm.lpos = new_posses
+ return true
+ end
+ return false
+ elseif topic == "uturn" then
+ local nvm = techage.get_nvm(pos)
+ local new_posses = fly.rotate_nodes(pos, nvm.lpos, "r")
+ if new_posses then
+ nvm.lpos = new_posses
+ new_posses = fly.rotate_nodes(pos, nvm.lpos, "r")
+ if new_posses then
+ nvm.lpos = new_posses
+ return true
+ end
+ end
+ return false
+ end
+ return false
+ end,
+})
+
+minetest.register_craft({
+ output = "techage:ta4_turncontroller",
+ recipe = {
+ {"default:steel_ingot", "dye:blue", "default:steel_ingot"},
+ {"techage:aluminum", "techage:baborium_ingot", "techage:aluminum"},
+ {"group:wood", "basic_materials:gear_steel", "group:wood"},
+ },
+})
diff --git a/techage/settingtypes.txt b/techage/settingtypes.txt
index ac0117b..377539a 100644
--- a/techage/settingtypes.txt
+++ b/techage/settingtypes.txt
@@ -29,4 +29,8 @@ techage_use_sqlite (use sqlite database) bool false
# To reduce the server CPU load, the number of sent techage commands
# per player and minute can be limited.
-techage_command_limit (Max. number of commands sent per minute) int 1200
\ No newline at end of file
+techage_command_limit (Max. number of commands sent per minute) int 1200
+
+# Colliders are huge systems and should not be built on the surface.
+# 'techage_collider_min_depth specifies' the min. depth (Y) to build a TA4 Collider
+techage_collider_min_depth (Min. depth to build a TA4 Collider) int -30
\ No newline at end of file
diff --git a/techage/sounds/techage_hum.ogg b/techage/sounds/techage_hum.ogg
new file mode 100644
index 0000000..b90b66d
Binary files /dev/null and b/techage/sounds/techage_hum.ogg differ
diff --git a/techage/sounds/techage_watermill.ogg b/techage/sounds/techage_watermill.ogg
index 3e6486a..246479b 100644
Binary files a/techage/sounds/techage_watermill.ogg and b/techage/sounds/techage_watermill.ogg differ
diff --git a/techage/ta1_watermill/watermill.lua b/techage/ta1_watermill/watermill.lua
index d9b04a3..b029ae9 100644
--- a/techage/ta1_watermill/watermill.lua
+++ b/techage/ta1_watermill/watermill.lua
@@ -271,7 +271,7 @@ minetest.register_entity("techage:ta1_watermill_entity", {
stop_wheel(pos, self)
end
trigger_consumer(pos, self.facedir)
- minetest.sound_play("techage_watermill", {gain = 0.3, pos = pos,
+ minetest.sound_play("techage_watermill", {gain = 0.5, pos = pos,
max_hear_distance = 10}, true)
end
end,
diff --git a/techage/ta4_power/laser.lua b/techage/ta4_power/laser.lua
index 58c89b4..779c768 100644
--- a/techage/ta4_power/laser.lua
+++ b/techage/ta4_power/laser.lua
@@ -37,7 +37,8 @@ minetest.register_node("techage:ta4_laser_emitter", {
local tube_dir = networks.side_to_outdir(pos, "F")
Cable:prepare_pairing(pos, tube_dir, "")
Cable:after_place_node(pos, {tube_dir})
-
+ local number = techage.add_node(pos, "techage:ta4_laser_emitter")
+ M(pos):set_string("node_number", number)
local res, pos1, pos2 = techage.renew_laser(pos, true)
if pos1 then
local node = techage.get_node_lvm(pos2)
@@ -56,17 +57,20 @@ minetest.register_node("techage:ta4_laser_emitter", {
end,
on_timer = function(pos, elapsed)
+ local nvm = techage.get_nvm(pos)
local res, pos1, pos2 = techage.renew_laser(pos)
if pos1 then
local node = techage.get_node_lvm(pos2)
if node.name == "techage:ta4_laser_receiver" then
Cable:pairing(pos2, "laser")
Cable:pairing(pos, "laser")
+ nvm.running = true
else
local metadata = M(pos):to_table()
Cable:stop_pairing(pos, metadata, "")
local tube_dir = tonumber(metadata.fields.tube_dir or 0)
Cable:after_dig_node(pos, {tube_dir})
+ nvm.running = false
end
elseif not res then
techage.del_laser(pos)
@@ -74,6 +78,7 @@ minetest.register_node("techage:ta4_laser_emitter", {
Cable:stop_pairing(pos, metadata, "")
local tube_dir = tonumber(metadata.fields.tube_dir or 0)
Cable:after_dig_node(pos, {tube_dir})
+ nvm.running = false
end
return true
end,
@@ -121,6 +126,17 @@ minetest.register_node("techage:ta4_laser_receiver", {
sounds = default.node_sound_wood_defaults(),
})
+techage.register_node({"techage:ta4_laser_emitter"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ if topic == "state" then
+ local nvm = techage.get_nvm(pos)
+ return nvm.running and "running" or "stopped"
+ else
+ return "unsupported"
+ end
+ end,
+})
+
power.register_nodes({"techage:ta4_laser_emitter", "techage:ta4_laser_receiver"}, Cable, "special", {"F"})
minetest.register_craft({
diff --git a/techage/teleport/teleport_pipe.lua b/techage/teleport/teleport_pipe.lua
new file mode 100644
index 0000000..0fd5aa7
--- /dev/null
+++ b/techage/teleport/teleport_pipe.lua
@@ -0,0 +1,191 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2017-2022 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA5 teleport pipe
+
+]]--
+
+-- for lazy programmers
+local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
+local S2P = minetest.string_to_pos
+local M = minetest.get_meta
+local S = techage.S
+
+local Pipe = techage.LiquidPipe
+local teleport = techage.teleport
+local Cable = techage.ElectricCable
+local power = networks.power
+local liquid = networks.liquid
+
+local STANDBY_TICKS = 4
+local COUNTDOWN_TICKS = 4
+local CYCLE_TIME = 2
+local PWR_NEEDED = 12
+local EX_POINTS = 60
+local MAX_DIST = 200
+local DESCRIPTION = S("TA5 Teleport Block Liquids")
+
+local function formspec(self, pos, nvm)
+ local title = DESCRIPTION .. " " .. M(pos):get_string("tele_status")
+ return "size[8,2]"..
+ "box[0,-0.1;7.8,0.5;#c6e8ff]" ..
+ "label[0.5,-0.1;" .. minetest.colorize( "#000000", title) .. "]" ..
+ "image_button[3.5,1;1,1;" .. self:get_state_button_image(nvm) .. ";state_button;]" ..
+ "tooltip[3.5,1;1,1;" .. self:get_state_tooltip(nvm) .. "]"
+end
+
+local function can_start(pos, nvm, state)
+ return teleport.is_connected(pos)
+end
+
+local State = techage.NodeStates:new({
+ node_name_passive = "techage:ta5_tele_pipe",
+ infotext_name = DESCRIPTION,
+ cycle_time = CYCLE_TIME,
+ standby_ticks = STANDBY_TICKS,
+ countdown_ticks = COUNTDOWN_TICKS,
+ formspec_func = formspec,
+ can_start = can_start,
+})
+
+local function consume_power(pos, nvm)
+ if techage.needs_power(nvm) then
+ local taken = power.consume_power(pos, Cable, nil, PWR_NEEDED)
+ if techage.is_running(nvm) then
+ if taken < PWR_NEEDED then
+ State:nopower(pos, nvm)
+ else
+ return true -- keep running
+ end
+ elseif taken == PWR_NEEDED then
+ State:start(pos, nvm)
+ end
+ end
+end
+
+minetest.register_node("techage:ta5_tele_pipe", {
+ description = DESCRIPTION,
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_filling_ta4.png^techage_frame_ta5_top.png^techage_appl_tele_pipe.png",
+ "techage_filling_ta4.png^techage_frame_ta5_top.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_teleport.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_hole_pipe.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_teleport.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_teleport.png",
+ },
+
+ after_place_node = function(pos, placer)
+ local meta = M(pos)
+ local nvm = techage.get_nvm(pos)
+ local node = minetest.get_node(pos)
+ local pipe_dir = techage.side_to_outdir("L", node.param2)
+ local number = techage.add_node(pos, "techage:ta5_tele_pipe")
+ State:node_init(pos, nvm, number)
+ meta:set_int("pipe_dir", pipe_dir)
+ meta:set_string("owner", placer:get_player_name())
+ Pipe:after_place_node(pos, {pipe_dir})
+ Cable:after_place_node(pos)
+ teleport.prepare_pairing(pos, "ta5_tele_pipe")
+ end,
+
+ on_receive_fields = function(pos, formname, fields, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return
+ end
+ if teleport.is_connected(pos) then
+ local nvm = techage.get_nvm(pos)
+ State:state_button_event(pos, nvm, fields)
+ M(pos):set_string("formspec", formspec(State, pos, nvm))
+ else
+ teleport.after_formspec(pos, player, fields, MAX_DIST, EX_POINTS)
+ end
+ end,
+
+ on_rightclick = function(pos, clicker, listname)
+ if teleport.is_connected(pos) then
+ local nvm = techage.get_nvm(pos)
+ M(pos):set_string("formspec", formspec(State, pos, nvm))
+ else
+ M(pos):set_string("formspec", teleport.formspec(pos))
+ end
+ end,
+
+ on_timer = function(pos, elapsed)
+ local nvm = techage.get_nvm(pos)
+ consume_power(pos, nvm)
+ -- the state has to be triggered by on_push_item
+ State:idle(pos, nvm)
+ return State:is_active(nvm)
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata, digger)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ teleport.stop_pairing(pos, oldmetadata)
+ Pipe:after_dig_node(pos)
+ Cable:after_dig_node(pos)
+ techage.del_mem(pos)
+ end,
+
+ paramtype2 = "facedir", -- important!
+ on_rotate = screwdriver.disallow, -- important!
+ is_ground_content = false,
+ groups = {choppy=2, cracky=2, crumbly=2},
+ sounds = default.node_sound_wood_defaults(),
+})
+
+minetest.register_craft({
+ output = "techage:ta5_tele_pipe",
+ recipe = {
+ {"techage:aluminum", "dye:red", "techage:aluminum"},
+ {"techage:ta3_pipeS", "techage:usmium_nuggets", "techage:ta5_aichip"},
+ {"techage:ta4_carbon_fiber", "", "techage:ta4_carbon_fiber"},
+ },
+})
+
+local blocked = false -- flag to prevent stack overruns (not to pump into the own "tank")
+liquid.register_nodes({"techage:ta5_tele_pipe"}, Pipe, "tank", {"L"}, {
+ peek = function(pos)
+ local nvm = techage.get_nvm(pos)
+ return liquid.srv_peek(nvm)
+ end,
+ put = function(pos, indir, name, amount)
+ local nvm = techage.get_nvm(pos)
+ nvm.oil_amount = nvm.oil_amount or 0
+ if not blocked and techage.is_operational(nvm) then
+ local rmt_pos = teleport.get_remote_pos(pos)
+ local rmt_nvm = techage.get_nvm(rmt_pos)
+ if techage.is_operational(rmt_nvm) then
+ local pipe_dir = M(rmt_pos):get_int("pipe_dir")
+ blocked = true
+ local leftover = liquid.put(rmt_pos, Pipe, pipe_dir, name, amount)
+ blocked = false
+ if leftover < amount then
+ State:keep_running(pos, nvm, COUNTDOWN_TICKS)
+ State:keep_running(rmt_pos, rmt_nvm, COUNTDOWN_TICKS)
+ end
+ return leftover
+ else
+ State:blocked(pos, nvm, S("Remote block error"))
+ end
+ end
+ return amount
+ end
+})
+
+techage.register_node({"techage:ta5_tele_pipe"}, {
+ on_recv_message = function(pos, src, topic, payload)
+ return State:on_receive_message(pos, topic, payload)
+ end,
+})
+
+power.register_nodes({"techage:ta5_tele_pipe"}, Cable, "con", {"B", "R", "F", "D", "U"})
+Pipe:set_valid_sides("techage:ta5_tele_pipe", {"L"})
+
diff --git a/techage/teleport/teleport_tube.lua b/techage/teleport/teleport_tube.lua
new file mode 100644
index 0000000..ce6d0c9
--- /dev/null
+++ b/techage/teleport/teleport_tube.lua
@@ -0,0 +1,180 @@
+--[[
+
+ TechAge
+ =======
+
+ Copyright (C) 2017-2022 Joachim Stolberg
+
+ AGPL v3
+ See LICENSE.txt for more information
+
+ TA5 teleport tube
+
+]]--
+
+-- for lazy programmers
+local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
+local S2P = minetest.string_to_pos
+local M = minetest.get_meta
+local S = techage.S
+
+local Tube = techage.Tube
+local teleport = techage.teleport
+local Cable = techage.ElectricCable
+local power = networks.power
+
+local STANDBY_TICKS = 4
+local COUNTDOWN_TICKS = 4
+local CYCLE_TIME = 2
+local PWR_NEEDED = 12
+local EX_POINTS = 60
+local MAX_DIST = 200
+local DESCRIPTION = S("TA5 Teleport Block Items")
+
+local function formspec(self, pos, nvm)
+ local title = DESCRIPTION .. " " .. M(pos):get_string("tele_status")
+ return "size[8,2]"..
+ "box[0,-0.1;7.8,0.5;#c6e8ff]" ..
+ "label[0.5,-0.1;" .. minetest.colorize( "#000000", title) .. "]" ..
+ "image_button[3.5,1;1,1;" .. self:get_state_button_image(nvm) .. ";state_button;]" ..
+ "tooltip[3.5,1;1,1;" .. self:get_state_tooltip(nvm) .. "]"
+end
+
+local function can_start(pos, nvm, state)
+ return teleport.is_connected(pos)
+end
+
+local State = techage.NodeStates:new({
+ node_name_passive = "techage:ta5_tele_tube",
+ infotext_name = DESCRIPTION,
+ cycle_time = CYCLE_TIME,
+ standby_ticks = STANDBY_TICKS,
+ countdown_ticks = COUNTDOWN_TICKS,
+ formspec_func = formspec,
+ can_start = can_start,
+})
+
+local function consume_power(pos, nvm)
+ if techage.needs_power(nvm) then
+ local taken = power.consume_power(pos, Cable, nil, PWR_NEEDED)
+ if techage.is_running(nvm) then
+ if taken < PWR_NEEDED then
+ State:nopower(pos, nvm)
+ else
+ return true -- keep running
+ end
+ elseif taken == PWR_NEEDED then
+ State:start(pos, nvm)
+ end
+ end
+end
+
+minetest.register_node("techage:ta5_tele_tube", {
+ description = DESCRIPTION,
+ tiles = {
+ -- up, down, right, left, back, front
+ "techage_filling_ta4.png^techage_frame_ta5_top.png^techage_appl_tele_tube.png",
+ "techage_filling_ta4.png^techage_frame_ta5_top.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_teleport.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_hole_tube.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_teleport.png",
+ "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_teleport.png",
+ },
+
+ after_place_node = function(pos, placer)
+ local meta = M(pos)
+ local nvm = techage.get_nvm(pos)
+ local node = minetest.get_node(pos)
+ local tube_dir = techage.side_to_outdir("L", node.param2)
+ local number = techage.add_node(pos, "techage:ta5_tele_tube")
+ State:node_init(pos, nvm, number)
+ meta:set_int("tube_dir", tube_dir)
+ meta:set_string("owner", placer:get_player_name())
+ Tube:after_place_node(pos, {tube_dir})
+ Cable:after_place_node(pos)
+ teleport.prepare_pairing(pos, "ta5_tele_tube")
+ end,
+
+ on_receive_fields = function(pos, formname, fields, player)
+ if minetest.is_protected(pos, player:get_player_name()) then
+ return
+ end
+ if teleport.is_connected(pos) then
+ local nvm = techage.get_nvm(pos)
+ State:state_button_event(pos, nvm, fields)
+ M(pos):set_string("formspec", formspec(State, pos, nvm))
+ else
+ teleport.after_formspec(pos, player, fields, MAX_DIST, EX_POINTS)
+ end
+ end,
+
+ on_rightclick = function(pos, clicker, listname)
+ if teleport.is_connected(pos) then
+ local nvm = techage.get_nvm(pos)
+ M(pos):set_string("formspec", formspec(State, pos, nvm))
+ else
+ M(pos):set_string("formspec", teleport.formspec(pos))
+ end
+ end,
+
+ on_timer = function(pos, elapsed)
+ local nvm = techage.get_nvm(pos)
+ consume_power(pos, nvm)
+ -- the state has to be triggered by on_push_item
+ State:idle(pos, nvm)
+ return State:is_active(nvm)
+ end,
+
+ after_dig_node = function(pos, oldnode, oldmetadata, digger)
+ techage.remove_node(pos, oldnode, oldmetadata)
+ teleport.stop_pairing(pos, oldmetadata)
+ Tube:after_dig_node(pos)
+ Cable:after_dig_node(pos)
+ techage.del_mem(pos)
+ end,
+
+ paramtype2 = "facedir", -- important!
+ on_rotate = screwdriver.disallow, -- important!
+ is_ground_content = false,
+ groups = {choppy=2, cracky=2, crumbly=2},
+ sounds = default.node_sound_wood_defaults(),
+})
+
+minetest.register_craft({
+ output = "techage:ta5_tele_tube",
+ recipe = {
+ {"techage:aluminum", "dye:red", "techage:aluminum"},
+ {"techage:ta4_tubeS", "techage:usmium_nuggets", "techage:ta5_aichip"},
+ {"techage:ta4_carbon_fiber", "", "techage:ta4_carbon_fiber"},
+ },
+})
+
+techage.register_node({"techage:ta5_tele_tube"}, {
+ on_push_item = function(pos, in_dir, stack)
+ local nvm = techage.get_nvm(pos)
+ if techage.is_operational(nvm) then
+ local rmt_pos = teleport.get_remote_pos(pos)
+ local rmt_nvm = techage.get_nvm(rmt_pos)
+ if techage.is_operational(rmt_nvm) then
+ local tube_dir = M(rmt_pos):get_int("tube_dir")
+ if techage.push_items(rmt_pos, tube_dir, stack) then
+ State:keep_running(pos, nvm, COUNTDOWN_TICKS)
+ State:keep_running(rmt_pos, rmt_nvm, COUNTDOWN_TICKS)
+ return true
+ end
+ else
+ State:blocked(pos, nvm, S("Remote block error"))
+ end
+ end
+ return false
+ end,
+ is_pusher = true, -- is a pulling/pushing node
+
+ on_recv_message = function(pos, src, topic, payload)
+ return State:on_receive_message(pos, topic, payload)
+ end,
+})
+
+power.register_nodes({"techage:ta5_tele_tube"}, Cable, "con", {"B", "R", "F", "D", "U"})
+Tube:set_valid_sides("techage:ta5_tele_tube", {"L"})
+
diff --git a/techage/textures/techage_aichip.png b/techage/textures/techage_aichip.png
new file mode 100644
index 0000000..58dfd32
Binary files /dev/null and b/techage/textures/techage_aichip.png differ
diff --git a/techage/textures/techage_appl_movecontroller.png b/techage/textures/techage_appl_movecontroller.png
index 4938ab1..36c22b8 100644
Binary files a/techage/textures/techage_appl_movecontroller.png and b/techage/textures/techage_appl_movecontroller.png differ
diff --git a/techage/textures/techage_appl_recipeblock.png b/techage/textures/techage_appl_recipeblock.png
new file mode 100644
index 0000000..ae14cc9
Binary files /dev/null and b/techage/textures/techage_appl_recipeblock.png differ
diff --git a/techage/textures/techage_appl_sound.png b/techage/textures/techage_appl_sound.png
new file mode 100644
index 0000000..4efea64
Binary files /dev/null and b/techage/textures/techage_appl_sound.png differ
diff --git a/techage/textures/techage_appl_tele_pipe.png b/techage/textures/techage_appl_tele_pipe.png
new file mode 100644
index 0000000..4cd509b
Binary files /dev/null and b/techage/textures/techage_appl_tele_pipe.png differ
diff --git a/techage/textures/techage_appl_tele_tube.png b/techage/textures/techage_appl_tele_tube.png
new file mode 100644
index 0000000..aaffc3d
Binary files /dev/null and b/techage/textures/techage_appl_tele_tube.png differ
diff --git a/techage/textures/techage_appl_teleport.png b/techage/textures/techage_appl_teleport.png
new file mode 100644
index 0000000..1a18d59
Binary files /dev/null and b/techage/textures/techage_appl_teleport.png differ
diff --git a/techage/textures/techage_appl_turn.png b/techage/textures/techage_appl_turn.png
new file mode 100644
index 0000000..fbc8b33
Binary files /dev/null and b/techage/textures/techage_appl_turn.png differ
diff --git a/techage/textures/techage_collider_detector_appl.png b/techage/textures/techage_collider_detector_appl.png
new file mode 100644
index 0000000..fa8776b
Binary files /dev/null and b/techage/textures/techage_collider_detector_appl.png differ
diff --git a/techage/textures/techage_collider_detector_banner.png b/techage/textures/techage_collider_detector_banner.png
new file mode 100644
index 0000000..1718dba
Binary files /dev/null and b/techage/textures/techage_collider_detector_banner.png differ
diff --git a/techage/textures/techage_collider_detector_core.png b/techage/textures/techage_collider_detector_core.png
new file mode 100644
index 0000000..b0edd8d
Binary files /dev/null and b/techage/textures/techage_collider_detector_core.png differ
diff --git a/techage/textures/techage_collider_magnet.png b/techage/textures/techage_collider_magnet.png
new file mode 100644
index 0000000..7a81fd5
Binary files /dev/null and b/techage/textures/techage_collider_magnet.png differ
diff --git a/techage/textures/techage_collider_magnet_appl.png b/techage/textures/techage_collider_magnet_appl.png
new file mode 100644
index 0000000..2f748e1
Binary files /dev/null and b/techage/textures/techage_collider_magnet_appl.png differ
diff --git a/techage/textures/techage_collider_magnet_sign.png b/techage/textures/techage_collider_magnet_sign.png
new file mode 100644
index 0000000..5493297
Binary files /dev/null and b/techage/textures/techage_collider_magnet_sign.png differ
diff --git a/techage/textures/techage_collider_magnet_tube.png b/techage/textures/techage_collider_magnet_tube.png
new file mode 100644
index 0000000..040c3e5
Binary files /dev/null and b/techage/textures/techage_collider_magnet_tube.png differ
diff --git a/techage/textures/techage_collider_plan.png b/techage/textures/techage_collider_plan.png
new file mode 100644
index 0000000..3cdc09d
Binary files /dev/null and b/techage/textures/techage_collider_plan.png differ
diff --git a/techage/textures/techage_collider_tube.png b/techage/textures/techage_collider_tube.png
new file mode 100644
index 0000000..2ef480b
Binary files /dev/null and b/techage/textures/techage_collider_tube.png differ
diff --git a/techage/textures/techage_collider_tube_open.png b/techage/textures/techage_collider_tube_open.png
new file mode 100644
index 0000000..21af706
Binary files /dev/null and b/techage/textures/techage_collider_tube_open.png differ
diff --git a/techage/textures/techage_frame_ta5.png b/techage/textures/techage_frame_ta5.png
new file mode 100644
index 0000000..6609d1f
Binary files /dev/null and b/techage/textures/techage_frame_ta5.png differ
diff --git a/techage/textures/techage_frame_ta5_top.png b/techage/textures/techage_frame_ta5_top.png
new file mode 100644
index 0000000..85b4276
Binary files /dev/null and b/techage/textures/techage_frame_ta5_top.png differ
diff --git a/techage/textures/techage_isobutane_inv.png b/techage/textures/techage_isobutane_inv.png
new file mode 100644
index 0000000..2189b67
Binary files /dev/null and b/techage/textures/techage_isobutane_inv.png differ
diff --git a/techage/textures/techage_round_ceramic.png b/techage/textures/techage_round_ceramic.png
new file mode 100644
index 0000000..70d5dd6
Binary files /dev/null and b/techage/textures/techage_round_ceramic.png differ
diff --git a/techage/textures/techage_smartline_button_2x.png b/techage/textures/techage_smartline_button_2x.png
new file mode 100644
index 0000000..aaa73df
Binary files /dev/null and b/techage/textures/techage_smartline_button_2x.png differ
diff --git a/techage/textures/techage_smartline_mba_detector.png b/techage/textures/techage_smartline_mba_detector.png
new file mode 100644
index 0000000..660fe10
Binary files /dev/null and b/techage/textures/techage_smartline_mba_detector.png differ
diff --git a/techage/textures/techage_smartline_mba_detector_inv.png b/techage/textures/techage_smartline_mba_detector_inv.png
new file mode 100644
index 0000000..dc681b6
Binary files /dev/null and b/techage/textures/techage_smartline_mba_detector_inv.png differ
diff --git a/techage/textures/techage_smartline_signal_2x.png b/techage/textures/techage_smartline_signal_2x.png
new file mode 100644
index 0000000..7d0e633
Binary files /dev/null and b/techage/textures/techage_smartline_signal_2x.png differ
diff --git a/techage/textures/techage_smartline_signal_4x.png b/techage/textures/techage_smartline_signal_4x.png
new file mode 100644
index 0000000..ec3e9fc
Binary files /dev/null and b/techage/textures/techage_smartline_signal_4x.png differ
diff --git a/techage/textures/techage_smartline_signal_amber1.png b/techage/textures/techage_smartline_signal_amber1.png
new file mode 100644
index 0000000..ff3d5e7
Binary files /dev/null and b/techage/textures/techage_smartline_signal_amber1.png differ
diff --git a/techage/textures/techage_smartline_signal_amber2.png b/techage/textures/techage_smartline_signal_amber2.png
new file mode 100644
index 0000000..fb9df3d
Binary files /dev/null and b/techage/textures/techage_smartline_signal_amber2.png differ
diff --git a/techage/textures/techage_smartline_signal_amber3.png b/techage/textures/techage_smartline_signal_amber3.png
new file mode 100644
index 0000000..da5f91e
Binary files /dev/null and b/techage/textures/techage_smartline_signal_amber3.png differ
diff --git a/techage/textures/techage_smartline_signal_amber4.png b/techage/textures/techage_smartline_signal_amber4.png
new file mode 100644
index 0000000..3267c8f
Binary files /dev/null and b/techage/textures/techage_smartline_signal_amber4.png differ
diff --git a/techage/textures/techage_smartline_signal_green1.png b/techage/textures/techage_smartline_signal_green1.png
new file mode 100644
index 0000000..df07eb2
Binary files /dev/null and b/techage/textures/techage_smartline_signal_green1.png differ
diff --git a/techage/textures/techage_smartline_signal_green2.png b/techage/textures/techage_smartline_signal_green2.png
new file mode 100644
index 0000000..34685ec
Binary files /dev/null and b/techage/textures/techage_smartline_signal_green2.png differ
diff --git a/techage/textures/techage_smartline_signal_green3.png b/techage/textures/techage_smartline_signal_green3.png
new file mode 100644
index 0000000..956cc49
Binary files /dev/null and b/techage/textures/techage_smartline_signal_green3.png differ
diff --git a/techage/textures/techage_smartline_signal_green4.png b/techage/textures/techage_smartline_signal_green4.png
new file mode 100644
index 0000000..08c0efe
Binary files /dev/null and b/techage/textures/techage_smartline_signal_green4.png differ
diff --git a/techage/textures/techage_smartline_signal_off1.png b/techage/textures/techage_smartline_signal_off1.png
new file mode 100644
index 0000000..edabb43
Binary files /dev/null and b/techage/textures/techage_smartline_signal_off1.png differ
diff --git a/techage/textures/techage_smartline_signal_off2.png b/techage/textures/techage_smartline_signal_off2.png
new file mode 100644
index 0000000..2065fa4
Binary files /dev/null and b/techage/textures/techage_smartline_signal_off2.png differ
diff --git a/techage/textures/techage_smartline_signal_off3.png b/techage/textures/techage_smartline_signal_off3.png
new file mode 100644
index 0000000..451bff0
Binary files /dev/null and b/techage/textures/techage_smartline_signal_off3.png differ
diff --git a/techage/textures/techage_smartline_signal_off4.png b/techage/textures/techage_smartline_signal_off4.png
new file mode 100644
index 0000000..1ffcbac
Binary files /dev/null and b/techage/textures/techage_smartline_signal_off4.png differ
diff --git a/techage/textures/techage_smartline_signal_red1.png b/techage/textures/techage_smartline_signal_red1.png
new file mode 100644
index 0000000..64bc5eb
Binary files /dev/null and b/techage/textures/techage_smartline_signal_red1.png differ
diff --git a/techage/textures/techage_smartline_signal_red2.png b/techage/textures/techage_smartline_signal_red2.png
new file mode 100644
index 0000000..714d806
Binary files /dev/null and b/techage/textures/techage_smartline_signal_red2.png differ
diff --git a/techage/textures/techage_smartline_signal_red3.png b/techage/textures/techage_smartline_signal_red3.png
new file mode 100644
index 0000000..38b8b99
Binary files /dev/null and b/techage/textures/techage_smartline_signal_red3.png differ
diff --git a/techage/textures/techage_smartline_signal_red4.png b/techage/textures/techage_smartline_signal_red4.png
new file mode 100644
index 0000000..7220fb5
Binary files /dev/null and b/techage/textures/techage_smartline_signal_red4.png differ
diff --git a/techage/textures/techage_ta4c.png b/techage/textures/techage_ta4c.png
new file mode 100644
index 0000000..6ce1a9f
Binary files /dev/null and b/techage/textures/techage_ta4c.png differ
diff --git a/techage/tools/repairkit.lua b/techage/tools/repairkit.lua
index 5ea2092..7778ac0 100644
--- a/techage/tools/repairkit.lua
+++ b/techage/tools/repairkit.lua
@@ -17,7 +17,7 @@ local S = techage.S
local Cable1 = techage.ElectricCable
local Cable2 = techage.TA4_Cable
local Pipe2 = techage.LiquidPipe
-local menu = dofile(minetest.get_modpath("techage") .. "/tools/submenu.lua")
+local menu = techage.menu
local function network_check(start_pos, Cable, player_name)
-- local ndef = techage.networks.net_def(start_pos, Cable.tube_type)
@@ -109,6 +109,11 @@ local function read_state(itemstack, user, pointed_thing)
consumption = dump(consumption)
minetest.chat_send_player(user:get_player_name(), ndef.description.." "..number..": consumption = "..consumption.." kud ")
end
+ local flowrate = techage.send_single("0", number, "flowrate", nil)
+ if flowrate and flowrate ~= "" and flowrate ~= "unsupported" then
+ flowrate = dump(flowrate)
+ minetest.chat_send_player(user:get_player_name(), ndef.description.." "..number..": flowrate = "..flowrate.." ")
+ end
local owner = M(pos):get_string("owner") or ""
if owner ~= "" then
minetest.chat_send_player(user:get_player_name(), S("Node owner")..": "..owner.." ")
@@ -149,7 +154,18 @@ local function settings_menu(pos, playername)
local number = techage.get_node_number(pos)
local node = minetest.get_node(pos)
local ndef = minetest.registered_nodes[node.name]
- local form_def = ndef and (ndef.ta3_formspec or ndef.ta4_formspec)
+ local form_def
+
+ if ndef then
+ if ndef.ta3_formspec or ndef.ta4_formspec then
+ form_def = ndef.ta3_formspec or ndef.ta4_formspec
+ elseif ndef.ta5_formspec then
+ local player = minetest.get_player_by_name(playername)
+ if techage.get_expoints(player) >= ndef.ta5_formspec.ex_points then
+ form_def = ndef.ta5_formspec.menu
+ end
+ end
+ end
context[playername] = pos
if form_def then
@@ -170,7 +186,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local number = techage.get_node_number(pos)
local node = minetest.get_node(pos)
local ndef = minetest.registered_nodes[node.name]
- local form_def = ndef and (ndef.ta3_formspec or ndef.ta4_formspec)
+ local form_def = ndef and (ndef.ta3_formspec or ndef.ta4_formspec or ndef.ta5_formspec.menu)
if form_def then
if menu.eval_input(pos, form_def, fields, playername) then
diff --git a/tubelib2/depends.txt b/tubelib2/depends.txt
index 9207dab..60f8390 100644
--- a/tubelib2/depends.txt
+++ b/tubelib2/depends.txt
@@ -1,2 +1,2 @@
-default
+default?
intllib?
diff --git a/tubelib2/init.lua b/tubelib2/init.lua
index 88d4420..509dc07 100644
--- a/tubelib2/init.lua
+++ b/tubelib2/init.lua
@@ -9,4 +9,6 @@ dofile(MP .. "/internal1.lua")
dofile(MP .. "/tube_api.lua")
dofile(MP .. "/storage.lua")
-- Only for testing/demo purposes
---dofile(MP .. "/tube_test.lua")
+if minetest.settings:get_bool("tubelib2_testingblocks_enabled") == true then
+ dofile(MP .. "/tube_test.lua")
+end
diff --git a/tubelib2/internal1.lua b/tubelib2/internal1.lua
index daa2d2b..9902053 100644
--- a/tubelib2/internal1.lua
+++ b/tubelib2/internal1.lua
@@ -132,7 +132,7 @@ end
-- pairing functions
--------------------------------------------------------------------------------------
--- Pairing helper function
+-- Pairing helper function. NOT USED (see internal2.lua)!!!
function Tube:store_teleport_data(pos, peer_pos)
local meta = M(pos)
meta:set_string("tele_pos", S(peer_pos))
diff --git a/tubelib2/settingtypes.txt b/tubelib2/settingtypes.txt
new file mode 100644
index 0000000..7386cc2
--- /dev/null
+++ b/tubelib2/settingtypes.txt
@@ -0,0 +1,3 @@
+# Maximim number of Forceload Blocks per player (default 20)
+tubelib2_testingblocks_enabled (enbale the testing blocks) bool false
+
diff --git a/tubelib2/tube_test.lua b/tubelib2/tube_test.lua
index fc92a51..0b40140 100644
--- a/tubelib2/tube_test.lua
+++ b/tubelib2/tube_test.lua
@@ -269,7 +269,7 @@ local function store_connection(pos, peer_pos)
meta:set_string("peer_pos", P2S(peer_pos))
meta:set_string("channel", "")
meta:set_string("formspec", "")
- meta:set_string("infotext", "Connected with "..P2S(peer_pos))
+ meta:set_string("infotext", "Connected to "..P2S(peer_pos))
end
local function prepare_pairing(pos)