built on 03/01/2022 11:59:31
@ -1,8 +0,0 @@
|
||||
stages:
|
||||
- test
|
||||
|
||||
luacheck:
|
||||
stage: test
|
||||
image: pipelinecomponents/luacheck:latest
|
||||
script:
|
||||
- luacheck .
|
@ -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",
|
||||
}
|
@ -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. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
|
||||
###############################################################################
|
||||
|
||||
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.
|
@ -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")
|
@ -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")
|
@ -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
|
@ -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
|
@ -1,34 +0,0 @@
|
||||
# textdomain: basic_materials
|
||||
# Author: Salvo 'LtWorf' Tomaselli <tiposchi@tiscali.it>
|
||||
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
|
@ -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=Пустая Катушка
|
@ -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")
|
||||
|
@ -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")
|
@ -1,4 +0,0 @@
|
||||
name = basic_materials
|
||||
depends = default
|
||||
optional_depends = moreores
|
||||
min_minetest_version = 5.2.0
|
@ -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
|
@ -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")
|
Before Width: | Height: | Size: 272 B |
Before Width: | Height: | Size: 223 B |
Before Width: | Height: | Size: 243 B |
Before Width: | Height: | Size: 344 B |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 386 B |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 178 B |
Before Width: | Height: | Size: 175 B |
Before Width: | Height: | Size: 252 B |
Before Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 306 B |
Before Width: | Height: | Size: 214 B |
Before Width: | Height: | Size: 817 B |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 286 B |
Before Width: | Height: | Size: 369 B |
Before Width: | Height: | Size: 293 B |
Before Width: | Height: | Size: 247 B |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 215 B |
Before Width: | Height: | Size: 345 B |
Before Width: | Height: | Size: 293 B |
Before Width: | Height: | Size: 160 B |
Before Width: | Height: | Size: 769 B |
Before Width: | Height: | Size: 251 B |
Before Width: | Height: | Size: 311 B |
Before Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 284 B |
Before Width: | Height: | Size: 775 B |
Before Width: | Height: | Size: 366 B |
@ -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)
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
hyperloop_subnet_enabled (enable building of subnets) bool true
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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,6 +214,7 @@ end
|
||||
|
||||
function signs_bot.start_robot(base_pos)
|
||||
local mem = tubelib2.get_mem(base_pos)
|
||||
if free_start_pos(base_pos, mem) then
|
||||
mem.steps = nil
|
||||
mem.script = "cond_move"
|
||||
local meta = M(base_pos)
|
||||
@ -227,6 +234,7 @@ function signs_bot.start_robot(base_pos)
|
||||
minetest.get_node_timer(base_pos):start(CYCLE_TIME)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function signs_bot.stop_robot(base_pos, mem)
|
||||
local meta = M(base_pos)
|
||||
|
@ -239,6 +239,7 @@ signs_bot.register_botcommand("drop_items", {
|
||||
end,
|
||||
})
|
||||
|
||||
if minetest.global_exists("minecart") then
|
||||
signs_bot.register_botcommand("punch_cart", {
|
||||
mod = "item",
|
||||
params = "",
|
||||
@ -250,6 +251,7 @@ signs_bot.register_botcommand("punch_cart", {
|
||||
return signs_bot.DONE
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
-- def is a table with following data:
|
||||
-- {
|
||||
|
@ -65,7 +65,9 @@ dofile(MP.."/nodes.lua")
|
||||
dofile(MP.."/bot_sensor.lua")
|
||||
dofile(MP.."/node_sensor.lua")
|
||||
dofile(MP.."/crop_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")
|
||||
|
@ -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 = {
|
||||
|
@ -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
|
||||
|
@ -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 "<node-number>.<recipe-number>" 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
|
||||
-- "<item>,<item>,..." 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)
|
||||
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)
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -32,12 +32,10 @@ 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)..
|
||||
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).."]"..
|
||||
@ -261,24 +259,22 @@ minetest.register_craft({
|
||||
},
|
||||
})
|
||||
|
||||
if minetest.global_exists("unified_inventory") then
|
||||
unified_inventory.register_craft_type("ta2_electronic_fab", {
|
||||
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,
|
||||
})
|
||||
unified_inventory.register_craft_type("ta3_electronic_fab", {
|
||||
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,
|
||||
})
|
||||
unified_inventory.register_craft_type("ta4_electronic_fab", {
|
||||
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,
|
||||
})
|
||||
end
|
||||
|
||||
|
@ -317,22 +317,18 @@ minetest.register_craft({
|
||||
})
|
||||
|
||||
|
||||
if minetest.global_exists("unified_inventory") then
|
||||
unified_inventory.register_craft_type("rinsing", {
|
||||
techage.recipes.register_craft_type("rinsing", {
|
||||
description = S("Rinsing"),
|
||||
icon = "techage_appl_rinser_top.png^techage_frame_ta2_top.png",
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
end
|
||||
|
||||
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
|
||||
techage.recipes.register_craft(recipe)
|
||||
end
|
||||
|
||||
techage.add_rinser_recipe({input="techage:sieved_gravel", output="techage:usmium_nuggets", probability=30})
|
||||
|
@ -246,38 +246,36 @@ minetest.register_craft({
|
||||
},
|
||||
})
|
||||
|
||||
if minetest.global_exists("unified_inventory") then
|
||||
unified_inventory.register_craft_type("ta2_gravelsieve", {
|
||||
techage.recipes.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", {
|
||||
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,
|
||||
})
|
||||
unified_inventory.register_craft_type("ta4_gravelsieve", {
|
||||
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,
|
||||
})
|
||||
unified_inventory.register_craft({
|
||||
techage.recipes.register_craft({
|
||||
output = "techage:sieved_basalt_gravel",
|
||||
items = {"techage:basalt_gravel"},
|
||||
type = "ta2_gravelsieve",
|
||||
})
|
||||
unified_inventory.register_craft({
|
||||
techage.recipes.register_craft({
|
||||
output = "techage:sieved_basalt_gravel",
|
||||
items = {"techage:basalt_gravel"},
|
||||
type = "ta3_gravelsieve",
|
||||
})
|
||||
unified_inventory.register_craft({
|
||||
techage.recipes.register_craft({
|
||||
output = "techage:sieved_basalt_gravel",
|
||||
items = {"techage:basalt_gravel"},
|
||||
type = "ta4_gravelsieve",
|
||||
})
|
||||
end
|
||||
|
@ -351,20 +351,18 @@ minetest.register_craft({
|
||||
},
|
||||
})
|
||||
|
||||
if minetest.global_exists("unified_inventory") then
|
||||
unified_inventory.register_craft_type("grinding", {
|
||||
techage.recipes.register_craft_type("grinding", {
|
||||
description = S("Grinding"),
|
||||
icon = 'techage_appl_grinder.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
unified_inventory.register_craft_type("milling", {
|
||||
techage.recipes.register_craft_type("milling", {
|
||||
description = S("Milling"),
|
||||
icon = 'techage_mill_inv.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
end
|
||||
|
||||
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
|
||||
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
|
||||
techage.recipes.register_craft(recipe)
|
||||
end
|
||||
end
|
||||
|
||||
|
244
techage/basic_machines/recipeblock.lua
Normal file
@ -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"},
|
||||
},
|
||||
})
|
||||
|
@ -60,6 +60,10 @@ local SpecialItems = {
|
||||
["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)
|
||||
|
185
techage/basic_machines/ta5_chest.lua
Normal file
@ -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"}
|
||||
})
|
@ -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
|
||||
|
@ -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 <number> <command> [<data>]"),
|
||||
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 <number> <command> [<data>]"
|
||||
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 <name> [<points>]"
|
||||
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
|
||||
})
|
||||
|
@ -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
|
||||
|
733
techage/basis/fly_lib.lua
Normal file
@ -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
|
235
techage/basis/hyperloop.lua
Normal file
@ -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 = <node_type>, -- chest/tank
|
||||
owner = "singleplayer",
|
||||
conn_name = <own 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
122
techage/basis/mark_lib.lua
Normal file
@ -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
|
@ -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
|
||||
|
103
techage/basis/oggfiles.lua
Normal file
@ -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
|
||||
}
|
@ -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({
|
||||
techage.recipes.register_craft({
|
||||
output = recipe.output,
|
||||
items = recipe.input,
|
||||
type = rtype,
|
||||
})
|
||||
end
|
||||
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
|
||||
|
69
techage/basis/shared_inv.lua
Normal file
@ -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
|
||||
|
105
techage/basis/shared_tank.lua
Normal file
@ -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
|
@ -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,12 +219,13 @@ 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 ""
|
||||
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,
|
||||
@ -226,7 +238,7 @@ function menu.generate_formspec(pos, ndef, form_def, player_name)
|
||||
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
|
167
techage/basis/teleport.lua
Normal file
@ -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
|
@ -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", {
|
||||
techage.recipes.register_craft_type("ta4_doser", {
|
||||
description = S("TA4 Reactor"),
|
||||
icon = 'techage_reactor_filler_plan.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:ta4_doser",
|
||||
|
91
techage/collider/cooler.lua
Normal file
@ -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', ''},
|
||||
},
|
||||
})
|
||||
|
414
techage/collider/detector.lua
Normal file
@ -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'},
|
||||
},
|
||||
})
|
||||
|
364
techage/collider/inlets.lua
Normal file
@ -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', ''},
|
||||
{'', '', ''},
|
||||
},
|
||||
})
|
305
techage/collider/magnet.lua
Normal file
@ -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,
|
||||
})
|
208
techage/collider/terminal.lua
Normal file
@ -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 <num> = 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,
|
||||
})
|
130
techage/collider/vacuumtube.lua
Normal file
@ -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', ''},
|
||||
},
|
||||
})
|
210
techage/collider/worker.lua
Normal file
@ -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'},
|
||||
},
|
||||
})
|
||||
|
@ -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
|
||||
|